Skip to content

Instantly share code, notes, and snippets.

@but80
Last active February 23, 2020 08:29
Show Gist options
  • Save but80/947ad5b99445b5bd751f1fbe11b57f1b to your computer and use it in GitHub Desktop.
Save but80/947ad5b99445b5bd751f1fbe11b57f1b to your computer and use it in GitHub Desktop.
pawooのメディアタイムラインについて調べた

pawooのメディアタイムラインについて調べた

  • Pixivのmastodonリポジトリ
  • 調査時の master ブランチ : 164bad171f8ebfc5fb240f9c8369df34a506a0df
  • 調査時の pawoo ブランチ: 6b90b6e4228b824287862c74ef01fb155011bd39

おそらく このマージコミット が基本で、その後いくつか改善されている。

メディアTLの初回表示分トゥートを読み込む処理

pawooでページが読み込まれると、ここ↓にリクエストしている形跡があり、 media=true という独自パラメータがあるように思われる。

https://pawoo.net/api/v1/timelines/public?local=true&media=true

おそらく、このパラメータにより、メディアが添付されているトゥート限定で上位一定数を読み込んで、その結果をメディアTLの初回表示分としているはず。

このへんmedia パラメータが実装されている模様。 masterpawoo で差分を取ってみたところ、こんな感じ。

diff --git a/app/controllers/api/v1/timelines_controller.rb b/app/controllers/api/v1/timelines_controller.rb
index 27dc3d0..2b08188 100644
--- a/app/controllers/api/v1/timelines_controller.rb
+++ b/app/controllers/api/v1/timelines_controller.rb
@@ -21,13 +21,20 @@ class Api::V1::TimelinesController < ApiController
   end
 
   def public
-    @statuses = Status.as_public_timeline(current_account, params[:local]).paginate_by_max_id(limit_param(DEFAULT_STATUSES_LIMIT), params[:max_id], params[:since_id])
+    @statuses = Status.as_public_timeline(current_account, params[:local])
+                  .paginate_by_max_id(limit_param(DEFAULT_STATUSES_LIMIT), params[:max_id], params[:since_id])
+
+    # `SELECT DISTINCT id, updated_at` is too slow, so pluck ids at first, and then select id, updated_at with ids.
+    if params[:media]
+      status_ids = @statuses.joins(:media_attachments).distinct(:id).pluck(:id)
+      @statuses = @statuses.where(id: status_ids)
+    end
     @statuses = cache_collection(@statuses)
 
     set_maps(@statuses)
 
-    next_path = api_v1_public_timeline_url(pagination_params(max_id: @statuses.last.id))    unless @statuses.empty?
-    prev_path = api_v1_public_timeline_url(pagination_params(since_id: @statuses.first.id)) unless @statuses.empty?
+    next_path = api_v1_public_timeline_url(pagination_params(max_id: @statuses.last.id, media: params[:media]))    unless @statuses.empty?
+    prev_path = api_v1_public_timeline_url(pagination_params(since_id: @statuses.first.id, media: params[:media])) unless @statuses.empty?
 
     set_pagination_headers(next_path, prev_path)
 
@@ -56,6 +63,6 @@ class Api::V1::TimelinesController < ApiController
   end
 
   def pagination_params(core_params)
-    params.permit(:local, :limit).merge(core_params)
+    params.permit(:local, :limit, :media).merge(core_params)
   end
 end

コントローラ内でwhere句足してるっぽいので、モデル側には変更ないかな?

  • 調査中: API呼んでる側(UI)

UI

リアルタイムに更新する処理

ポーリングしてる感じもなく、WebSocketコネクションも特に変わったところはないので、おそらく「ふつうのローカルタイムライン用に張ってるWebSocketコネクションから飛んでくるトゥートのうち、メディア添付されているトゥートのみを拾ってメディアTLにも追加表示してる」だけと思われる。

  • 調査中: メディアTLコンポーネントに関わるディスパッチャとかデータバインディング
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment