From c72afce21deb1c3c46000cf166df7d5149d60650 Mon Sep 17 00:00:00 2001 From: wmorgan Date: Mon, 10 Dec 2007 02:50:49 +0000 Subject: [PATCH] fix (mostly!) the updates system git-svn-id: svn://rubyforge.org/var/svn/sup/trunk@756 5c8cc53c-5e98-4d25-b20a-d8db53a31250 --- lib/sup/draft.rb | 12 +-- lib/sup/modes/inbox-mode.rb | 13 ++-- lib/sup/modes/label-search-results-mode.rb | 2 +- lib/sup/modes/resume-mode.rb | 10 +-- lib/sup/modes/thread-index-mode.rb | 86 +++++++++++++--------- lib/sup/modes/thread-view-mode.rb | 8 +- lib/sup/poll.rb | 2 +- lib/sup/sent.rb | 2 +- lib/sup/thread.rb | 12 +-- lib/sup/update.rb | 13 ++++ 10 files changed, 98 insertions(+), 62 deletions(-) diff --git a/lib/sup/draft.rb b/lib/sup/draft.rb index 5db89fd..eb2b4e1 100644 --- a/lib/sup/draft.rb +++ b/lib/sup/draft.rb @@ -23,20 +23,20 @@ class DraftManager @source.each do |thisoffset, theselabels| m = Message.new :source => @source, :source_info => thisoffset, :labels => theselabels Index.sync_message m - UpdateManager.relay self, :add, m + UpdateManager.relay self, :added, m my_message = m if thisoffset == offset end my_message end - def discard mid - docid, entry = Index.load_entry_for_id mid - raise ArgumentError, "can't find entry for draft: #{mid.inspect}" unless entry - raise ArgumentError, "not a draft: source id #{entry[:source_id].inspect}, should be #{DraftManager.source_id.inspect} for #{mid.inspect} / docno #{docid}" unless entry[:source_id].to_i == DraftManager.source_id + def discard m + docid, entry = Index.load_entry_for_id m.id + raise ArgumentError, "can't find entry for draft: #{m.id.inspect}" unless entry + raise ArgumentError, "not a draft: source id #{entry[:source_id].inspect}, should be #{DraftManager.source_id.inspect} for #{m.id.inspect} / docno #{docid}" unless entry[:source_id].to_i == DraftManager.source_id Index.drop_entry docid File.delete @source.fn_for_offset(entry[:source_info]) - UpdateManager.relay self, :delete, mid + UpdateManager.relay self, :deleted, m end end diff --git a/lib/sup/modes/inbox-mode.rb b/lib/sup/modes/inbox-mode.rb index 10e8ba6..a2de13f 100644 --- a/lib/sup/modes/inbox-mode.rb +++ b/lib/sup/modes/inbox-mode.rb @@ -38,11 +38,14 @@ class InboxMode < ThreadIndexMode regen_text end - def handle_archived_update sender, t - if contains_thread? t - hide_thread t - regen_text - end + def handle_unarchived_update sender, m + add_or_unhide m + end + + def handle_archived_update sender, m + t = thread_containing(m) or return + hide_thread t + regen_text end def status diff --git a/lib/sup/modes/label-search-results-mode.rb b/lib/sup/modes/label-search-results-mode.rb index 3f4df9d..88e3595 100644 --- a/lib/sup/modes/label-search-results-mode.rb +++ b/lib/sup/modes/label-search-results-mode.rb @@ -9,7 +9,7 @@ class LabelSearchResultsMode < ThreadIndexMode super [], opts end - def is_relevant? m; @labels.all? { |l| m.has_label? l }; end + def is_relevant? m; @labels.all? { |l| m.has_label? l } end def self.spawn_nicely label label = LabelManager.label_for(label) unless label.is_a?(Symbol) diff --git a/lib/sup/modes/resume-mode.rb b/lib/sup/modes/resume-mode.rb index 3cc9992..3470975 100644 --- a/lib/sup/modes/resume-mode.rb +++ b/lib/sup/modes/resume-mode.rb @@ -2,7 +2,7 @@ module Redwood class ResumeMode < EditMessageMode def initialize m - @id = m.id + @m = m @safe = false header, body = parse_file m.draft_filename @@ -16,13 +16,13 @@ class ResumeMode < EditMessageMode case BufferManager.ask_yes_or_no "Discard draft?" when true - DraftManager.discard @id + DraftManager.discard @m BufferManager.flash "Draft discarded." true when false if edited? DraftManager.write_draft { |f| write_message f, false } - DraftManager.discard @id + DraftManager.discard @m BufferManager.flash "Draft saved." end true @@ -33,14 +33,14 @@ class ResumeMode < EditMessageMode def send_message if super - DraftManager.discard @id + DraftManager.discard @m @safe = true end end def save_as_draft @safe = true - DraftManager.discard @id if super + DraftManager.discard @m if super end end diff --git a/lib/sup/modes/thread-index-mode.rb b/lib/sup/modes/thread-index-mode.rb index 8727e24..be5fc8e 100644 --- a/lib/sup/modes/thread-index-mode.rb +++ b/lib/sup/modes/thread-index-mode.rb @@ -97,7 +97,7 @@ EOS ## are set, and the second to show the cursor having moved update_text_for_line curpos - UpdateManager.relay self, :read, t + UpdateManager.relay self, :read, t.first end end @@ -105,27 +105,31 @@ EOS threads.each { |t| select t } end - def handle_label_update sender, m - t = @ts_mutex.synchronize { @ts.thread_for(m) } or return - handle_label_thread_update sender, t + def handle_single_message_labeled_update sender, m + ## no need to do anything different here; we don't differentiate + ## messages from their containing threads + handle_labeled_update sender, m + end + + def handle_labeled_update sender, m + if(t = thread_containing(m)) + l = @lines[t] or return + update_text_for_line l + elsif is_relevant?(m) + add_or_unhide m + end end - def handle_label_thread_update sender, t + def handle_read_update sender, m + t = thread_containing(m) or return l = @lines[t] or return update_text_for_line l - BufferManager.draw_screen - end - - def handle_read_update sender, t - l = @lines[t] or return - update_text_for_line l - BufferManager.draw_screen end def handle_archived_update *a; handle_read_update(*a); end - def handle_deleted_update sender, t - handle_read_update sender, t + def handle_deleted_update sender, m + t = thread_containing(m) or return hide_thread t regen_text end @@ -133,22 +137,21 @@ EOS ## overwrite me! def is_relevant? m; false; end - def handle_add_update sender, m - @ts_mutex.synchronize do - return unless is_relevant?(m) || @ts.is_relevant?(m) - @ts.load_thread_for_message m - end - update + def handle_added_update sender, m + add_or_unhide m BufferManager.draw_screen end - def handle_delete_update sender, mid + def handle_deleted_update sender, m @ts_mutex.synchronize do - return unless @ts.contains_id? mid - @ts.remove mid + return unless @ts.contains? m + @ts.remove_id m.id end update - BufferManager.draw_screen + end + + def handle_undeleted_update sender, m + add_or_unhide m end def update @@ -176,10 +179,10 @@ EOS def actually_toggle_starred t if t.has_label? :starred # if ANY message has a star t.remove_label :starred # remove from all - UpdateManager.relay self, :unstarred, t + UpdateManager.relay self, :unstarred, t.first else t.first.add_label :starred # add only to first - UpdateManager.relay self, :starred, t + UpdateManager.relay self, :starred, t.first end end @@ -198,30 +201,30 @@ EOS def actually_toggle_archived t if t.has_label? :inbox t.remove_label :inbox - UpdateManager.relay self, :archived, t + UpdateManager.relay self, :archived, t.first else t.apply_label :inbox - UpdateManager.relay self, :unarchived, t + UpdateManager.relay self, :unarchived, t.first end end def actually_toggle_spammed t if t.has_label? :spam t.remove_label :spam - UpdateManager.relay self, :unspammed, t + UpdateManager.relay self, :unspammed, t.first else t.apply_label :spam - UpdateManager.relay self, :spammed, t + UpdateManager.relay self, :spammed, t.first end end def actually_toggle_deleted t if t.has_label? :deleted t.remove_label :deleted - UpdateManager.relay self, :undeleted, t + UpdateManager.relay self, :undeleted, t.first else t.apply_label :deleted - UpdateManager.relay self, :deleted, t + UpdateManager.relay self, :deleted, t.first end end @@ -372,7 +375,7 @@ EOS return unless user_labels thread.labels = keepl + user_labels user_labels.each { |l| LabelManager << l } - update_text_for_line curpos + UpdateManager.relay self, :labeled, thread.first end def multi_edit_labels threads @@ -474,6 +477,23 @@ EOS protected + def add_or_unhide m + if @hidden_threads[m] + @hidden_threads.delete m + ## now it will re-appear when #update is called + else + Redwood::log "#{self}: adding: #{m}" + @ts_mutex.synchronize do + return unless is_relevant?(m) || @ts.is_relevant?(m) + @ts.load_thread_for_message m + end + end + + update + end + + def thread_containing m; @ts_mutex.synchronize { @ts.thread_for m } end + ## used to tag threads by query. this can be made a lot more sophisticated, ## but for right now we'll do the obvious this. def thread_match? t, query diff --git a/lib/sup/modes/thread-view-mode.rb b/lib/sup/modes/thread-view-mode.rb index fbe6351..1f00783 100644 --- a/lib/sup/modes/thread-view-mode.rb +++ b/lib/sup/modes/thread-view-mode.rb @@ -171,7 +171,7 @@ EOS @thread.labels = (reserved_labels + new_labels).uniq new_labels.each { |l| LabelManager << l } update - UpdateManager.relay self, :label_thread, @thread + UpdateManager.relay self, :labeled, @thread.first end def toggle_starred @@ -193,7 +193,7 @@ EOS ## TODO: don't recalculate EVERYTHING just to add a stupid little ## star to the display update - UpdateManager.relay self, :label, m + UpdateManager.relay self, :single_message_labeled, m end ## called when someone presses enter when the cursor is highlighting @@ -331,13 +331,13 @@ EOS def archive_and_kill @thread.remove_label :inbox - UpdateManager.relay self, :archived, @thread + UpdateManager.relay self, :archived, @thread.first BufferManager.kill_buffer_safely buffer end def delete_and_kill @thread.apply_label :deleted - UpdateManager.relay self, :deleted, @thread + UpdateManager.relay self, :deleted, @thread.first BufferManager.kill_buffer_safely buffer end diff --git a/lib/sup/poll.rb b/lib/sup/poll.rb index 387f06e..2b9a9c5 100644 --- a/lib/sup/poll.rb +++ b/lib/sup/poll.rb @@ -157,7 +157,7 @@ EOS HookManager.run "before-add-message", :message => m m = yield(m, offset, entry) or next Index.sync_message m, docid, entry - UpdateManager.relay self, :add, m unless entry + UpdateManager.relay self, :added, m unless entry rescue MessageFormatError => e Redwood::log "ignoring erroneous message at #{source}##{offset}: #{e.message}" end diff --git a/lib/sup/sent.rb b/lib/sup/sent.rb index 05a88b9..9c802d9 100644 --- a/lib/sup/sent.rb +++ b/lib/sup/sent.rb @@ -25,7 +25,7 @@ class SentManager @source.each do |offset, labels| m = Message.new :source => @source, :source_info => offset, :labels => @source.labels Index.sync_message m - UpdateManager.relay self, :add, m + UpdateManager.relay self, :added, m end end end diff --git a/lib/sup/thread.rb b/lib/sup/thread.rb index d459303..880feb6 100644 --- a/lib/sup/thread.rb +++ b/lib/sup/thread.rb @@ -11,7 +11,7 @@ ## zero or more Threads. A Thread represents all the message related ## to a particular subject. Each Thread has one or more Containers. A ## Container is a recursive structure that holds the message tree as -## determined by the references: and in-reply-to: headers. EAch +## determined by the references: and in-reply-to: headers. Each ## Container holds zero or one messages. In the case of zero messages, ## it means we've seen a reference to the message but haven't (yet) ## seen the message itself. @@ -252,10 +252,10 @@ class ThreadSet @thread_by_subj = thread_by_subj end - def contains_id? id; @messages.member?(id) && !@messages[id].empty?; end - def thread_for m - (c = @messages[m.id]) && c.root.thread - end + def thread_for_id mid; (c = @messages[mid]) && c.root.thread end + def contains_id? id; @messages.member?(id) && !@messages[id].empty? end + def thread_for m; thread_for_id m.id end + def contains? m; contains_id? m.id end def delete_cruft @threads.each { |k, v| @threads.delete(k) if v.empty? } @@ -293,7 +293,7 @@ class ThreadSet end private :link - def remove mid + def remove_id mid return unless(c = @messages[mid]) c.parent.children.delete c if c.parent diff --git a/lib/sup/update.rb b/lib/sup/update.rb index 9c28fdb..655573e 100644 --- a/lib/sup/update.rb +++ b/lib/sup/update.rb @@ -1,5 +1,18 @@ module Redwood +## Classic listener/sender paradigm. Handles communication between various +## parts of Sup. +## +## Usage note: don't pass threads around. Neither thread nor message equality +## is defined beyond standard object equality. For Thread equality, this is +## because of computational cost. But message equality is trivial by comparing +## message ids, so to communicate something about a particular thread, just +## pass a representative message from it instead. +## +## This assumes that no message will be a part of more than one thread within +## a single "view" (otherwise a message from a thread wouldn't uniquely +## identify it). But that's true. + class UpdateManager include Singleton -- 2.45.2