File: smartthread.rb

package info (click to toggle)
mikutter 5.1.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 9,780 kB
  • sloc: ruby: 22,912; sh: 186; makefile: 21
file content (104 lines) | stat: -rw-r--r-- 3,212 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# -*- coding: utf-8 -*-

require 'set'

Plugin.create :smartthread do

  counter = gen_counter 1
  @timeline_slugs = Set.new               # [Symbol]

  # messagesの中で、タイムライン _slug_ に入れるべきものがあれば入れる
  # ==== Args
  # [timeline] タイムライン
  # [messages] 入れるMessageの配列
  def scan(i_timeline, messages)
    SerialThread.new do
      messages.each{ |message|
        message.each_ancestor { |cur|
          if i_timeline.include? cur
            i_timeline << message
          end
        }
      }
    end
  end

  command(:smartthread,
          name: _('会話スレッドを表示'),
          icon: Skin[:list],
          condition: lambda{ |opt| not opt.messages.empty? and opt.messages.all? &:repliable? },
          visible: true,
          role: :timeline){ |opt|
    Plugin.call(:open_smartthread, opt.messages)
  }

  on_open_smartthread do |messages|
    serial = counter.call
    slug = "conversation#{serial}".to_sym
    tab slug, _("会話%{serial_id}") % {serial_id: serial} do
      set_deletable true
      set_icon Skin[:list]
      temporary_tab
      timeline slug do
        order do |message|
          message[:created].to_i end end end
    @timeline_slugs << slug
    i_timeline = timeline(slug)
    i_timeline << messages
    Delayer::Deferred.when(*messages.map{|m| around_message(m) }).next{ |around_all|
      i_timeline << around_all.flatten
    }
    timeline(slug).active!
  end

  onappear do |messages|
    @timeline_slugs.map{|s| timeline(s) }.each do |i_timeline|
      scan i_timeline, messages
    end
  end

  # 引用ツイートをsmartthreadに含める処理。
  # 会話に新しいMessageが登録される時点で、そのMessageの引用ツイートを取得して格納していく
  on_gui_timeline_add_messages do |widget, messages|
    if @timeline_slugs.include?(widget.slug)
      messages.deach do |message|
        message.quoting_messages_d(true).next{|quoting_messages|
          widget << widget.not_in_message(quoting_messages) unless quoting_messages.empty?
        }.terminate(_('引用ツイートが取得できませんでした'))
        widget << widget.not_in_message(message.quoted_by) if message.quoted_by?
      end
    end
  end

  on_gui_timeline_add_messages do |widget, messages|
    if widget.is_a?(Plugin::GUI::Timeline) && !@timeline_slugs.include?(widget.slug)
      Delayer::Deferred.when(
        *messages.select(&:has_receive_message?).map do |m|
          m.replyto_source_d(true).next do |parent|
            [parent, m]
          end.trap do |err|
            Delayer::Deferred.fail(err) if err
          end
        end
      ).next do |result|
        graph = result.compact.group_by { |p, _| p }.transform_values! do |v|
          v.map { |_, c| c }.freeze
        end
        if !graph.empty?
          @timeline_slugs.map { |s| timeline(s) }.each do |tl|
            tl.in_message(graph.keys).each do |parent|
              tl << graph[parent]
            end
          end
        end
      end.terminate
    end
  end

  on_gui_destroy do |widget|
    if widget.is_a? Plugin::GUI::Timeline
      @timeline_slugs.delete(widget.slug)
    end
  end

end