Skip to content

Instantly share code, notes, and snippets.

@cobodo
Last active December 12, 2018 17:48
Show Gist options
  • Save cobodo/afb23702bd4b72b5f329e8f8101b96f8 to your computer and use it in GitHub Desktop.
Save cobodo/afb23702bd4b72b5f329e8f8101b96f8 to your computer and use it in GitHub Desktop.
load more機能mikutter風 ~https://github.com/cobodo/mikutter-worldon/tree/load_more を添えて~
Plugin.create(:extract_load_more) do
def tl_uris
@tl_uris ||= Hash.new # timeline_slug -> datasource_slug -> URI -> time
end
tl_uris
def extract_tabs
Plugin[:extract].extract_tabs
end
on_extract_receive_message do |source, messages|
tabs = extract_tabs.values.select{ |r| r.sources && r.using?(source) }
next if tabs.empty?
tabs.each do |record|
@tl_uris[record.slug] ||= Hash.new
@tl_uris[record.slug][source] ||= Hash.new
messages.each do |m|
if m && m.uri
unless m.retweet_source && tl_uris[record.slug][source].has_key?(m.retweet_source.uri.to_s)
@tl_uris[record.slug][source][m.uri.to_s] = m.retweet_source ? m.modified : m.created
end
end
end
end
end
# n=TLあたりのメッセージ保持数、m=タブあたりの平均データソース数として、O(nm)
on_gui_timeline_message_removed do |i_timeline, message|
next unless (message && message.uri)
@tl_uris[i_timeline.slug] ||= Hash.new
@tl_uris[i_timeline.slug].keys.each do |source|
@tl_uris[i_timeline.slug][source].delete(message.uri.to_s)
end
end
# O(n)
on_load_more_timeline do |tl_slug, _|
next unless @tl_uris[tl_slug]
@tl_uris[tl_slug].keys.each do |source|
pair = @tl_uris[tl_slug][source].to_a.min{|a, b| a[1] <=> b[1] }
oldest = catch do |tag|
Plugin[:gtk].widgetof(timeline(tl_slug)).each do |m|
next unless (m && m.uri)
if m.uri == pair[0]
throw tag, m
end
end
end
Plugin.call(:extract_load_more_datasource, source, oldest)
end
end
on_extract_load_more_messages do |source, messages|
tabs = extract_tabs.values.select{ |r| r.sources && r.using?(source) }
next if tabs.empty?
tabs.each do |record|
timeline(record.slug).timeline_max += messages.size
end
Plugin.call(:extract_receive_message, source, messages)
end
end
class ::Gtk::TimeLine
alias :load_more_original_tl_model_remove :tl_model_remove
def tl_model_remove(iter)
Plugin.call(:gui_timeline_message_removed, @tl.imaginary, iter[Gtk::TimeLine::InnerTL::MESSAGE])
load_more_original_tl_model_remove(iter)
end
end
class Plugin::GUI::Timeline
def timeline_max
Plugin.filtering(:gui_timeline_get_timeline_max, self, nil)[1] || UserConfig[:timeline_max]
end
def timeline_max=(n)
Plugin.filtering(:gui_timeline_set_timeline_max, self, n)
end
end
Plugin.create(:gtk) do
filter_gui_timeline_get_timeline_max do |i_tl, _|
[i_tl, widgetof(i_tl).timeline_max]
end
filter_gui_timeline_set_timeline_max do |i_tl, n|
widgetof(i_tl).timeline_max = n
[i_tl, n]
end
end
Plugin.create(:load_more_timeline) do
def tl_uris
@tl_uris ||= Hash.new # timeline_slug -> URI -> time
end
tl_uris
on_gui_timeline_add_messages do |i_timeline, messages|
@tl_uris[i_timeline.slug] ||= Hash.new
messages.each {|m|
next unless (m && m.uri)
unless m.retweet_source && tl_uris[i_timeline.slug].has_key?(m.retweet_source.uri.to_s)
@tl_uris[i_timeline.slug][m.uri.to_s] = m.retweet_source ? m.modified : m.created
end
}
end
on_gui_timeline_message_removed do |i_timeline, message|
next unless (message && message.uri)
@tl_uris[i_timeline.slug] ||= Hash.new
@tl_uris[i_timeline.slug].delete(message.uri.to_s)
end
# 遡るコマンド
command(:load_more_timeline,
name: _('タイムラインを遡る'),
condition: lambda{ |opt| true },
visible: true,
role: :timeline) do |opt|
i_tl = opt.widget
pair = tl_uris[i_tl.slug].to_a.min{|a, b| a[1] <=> b[1] }
# pair[0](=key) がそのTLで最古のMessage ModelのURI
oldest = Enumerator.new do |y|
Plugin[:gtk].widgetof(i_tl).each do |m|
y << m
end
end.find do |m|
m && m.uri && m.uri == pair[0]
end
Plugin.call(:load_more_timeline, i_tl.slug, oldest)
end
end
Plugin.create(:twitter_load_more) do
on_load_more_timeline do |tl_slug, oldest|
world = Plugin.filtering(:worlds, []).first.find{|w| w.class.slug == :twitter }
if tl_slug == :home_timeline
params = {
count: 200,
max_id: oldest.id - 1,
tweet_mode: 'extended'.freeze
}
world.home_timeline(params).next{ |messages|
Plugin.call(:update, world, messages)
Plugin.call(:mention, world, messages.select{ |m| m.to_me? })
Plugin.call(:mypost, world, messages.select{ |m| m.from_me? })
}.terminate("twitter_load_more: home_timeline の追加取得に失敗しました")
elsif tl_slug == :mentions
params = {
count: 200,
max_id: oldest.id - 1,
tweet_mode: 'extended'.freeze
}
world.mentions(params).next{ |messages|
Plugin.call(:update, world, messages)
Plugin.call(:mention, world, messages)
Plugin.call(:mypost, world, messages.select{ |m| m.from_me? })
}.terminate("twitter_load_more: reply の追加取得に失敗しました")
elsif timeline(tl_slug).parent.is_a?(Plugin::GUI::Fragment)
fragment_slug = timeline(tl_slug).parent.slug
%r!\Ausertimeline_(.+)_[0-9]+_[0-9A-Fa-f]{8}_[0-9A-Fa-f]{8}\z!.match(fragment_slug.to_s) do |m|
params = {
# profile-http://twitter.com/username -> username
screen_name: m[1].split('/').last,
max_id: oldest.id - 1,
count: 200,
include_rts: 1,
tweet_mode: 'extended'.freeze
}
world.user_timeline(params).next { |messages|
timeline(tl_slug) << messages
}.terminate("twitter_load_more: usertimeline の追加取得に失敗しました")
end
end
end
end
@cobodo
Copy link
Author

cobodo commented Nov 26, 2018

既存の:load_moreプラグインと共存できるわけでもないので、むしろ被らせたほうがいいのかもしれない?

@cobodo
Copy link
Author

cobodo commented Nov 27, 2018

https://github.com/tsutsui/mikutter_load_more/blob/master/load_more.rb を参考に :twitter_load_more を作る。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment