sup

A curses threads-with-tags style email client

sup.git

git clone https://supmua.dev/git/sup/
commit fe9e9bab2cf3c1ced81c542a77af2c37afd0590f
parent fea4150a5e4948d4f98ba2d88ba74ee459301d30
Author: wmorgan <wmorgan@5c8cc53c-5e98-4d25-b20a-d8db53a31250>
Date:   Mon, 21 May 2007 16:24:13 +0000

autoload more threads when you go down

git-svn-id: svn://rubyforge.org/var/svn/sup/trunk@406 5c8cc53c-5e98-4d25-b20a-d8db53a31250

Diffstat:
M doc/TODO | 2 ++
M lib/sup/index.rb | 3 ++-
M lib/sup/modes/inbox-mode.rb | 2 +-
M lib/sup/modes/label-search-results-mode.rb | 2 +-
M lib/sup/modes/line-cursor-mode.rb | 42 +++++++++++++++++++++++++++++++++++++++++-
M lib/sup/modes/person-search-results-mode.rb | 2 +-
M lib/sup/modes/search-results-mode.rb | 2 +-
M lib/sup/modes/thread-index-mode.rb | 13 ++++++++++---
8 files changed, 59 insertions(+), 9 deletions(-)
diff --git a/doc/TODO b/doc/TODO
@@ -11,6 +11,8 @@ _ bugfix: readlock
 _ split out threading & message chunk parsing to a separate library
 _ decode RFC 2047 ("encoded word") headers
   - see: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/101949, http://dev.rubyonrails.org/ticket/6807
+_ refactor all the *-search-results-mode classes into one.
+x autoload more threads when you go down
 x add a sync-back tool that at least works for mboxes
 x thread by subject configurable in config.yaml
 x view as text command if the mime view command fails for an attachment
diff --git a/lib/sup/index.rb b/lib/sup/index.rb
@@ -143,8 +143,9 @@ class Index
 
   def num_results_for opts={}
     return 0 if @index.size == 0 # otherwise ferret barfs ###TODO: remove this once my ferret patch is accepted
+
     q = build_query opts
-    index.search(q).total_hits
+    index.search(q, :limit => 1).total_hits
   end
 
   ## yield all messages in the thread containing 'm' by repeatedly
diff --git a/lib/sup/modes/inbox-mode.rb b/lib/sup/modes/inbox-mode.rb
@@ -51,7 +51,7 @@ class InboxMode < ThreadIndexMode
     n = opts[:num] || ThreadIndexMode::LOAD_MORE_THREAD_NUM
     load_n_threads_background n, :label => :inbox,
                                  :when_done => (lambda do |num|
-      opts[:when_done].call if opts[:when_done]
+      opts[:when_done].call(num) if opts[:when_done]
       BufferManager.flash "Added #{num} threads."
     end)
   end
diff --git a/lib/sup/modes/label-search-results-mode.rb b/lib/sup/modes/label-search-results-mode.rb
@@ -14,7 +14,7 @@ class LabelSearchResultsMode < ThreadIndexMode
                                  :load_killed => true,
                                  :load_spam => false,
                                  :when_done =>(lambda do |num|
-      opts[:when_done].call if opts[:when_done]
+      opts[:when_done].call(num) if opts[:when_done]
       if num > 0
         BufferManager.flash "Found #{num} threads"
       else
diff --git a/lib/sup/modes/line-cursor-mode.rb b/lib/sup/modes/line-cursor-mode.rb
@@ -1,5 +1,6 @@
 module Redwood
 
+## extends ScrollMode to have a line-based cursor.
 class LineCursorMode < ScrollMode
   register_keymap do |k|
     ## overwrite scrollmode binding on arrow keys for cursor movement
@@ -14,6 +15,9 @@ class LineCursorMode < ScrollMode
   def initialize cursor_top=0, opts={}
     @cursor_top = cursor_top
     @curpos = cursor_top
+    @load_more_callbacks = []
+    @load_more_callbacks_m = Mutex.new
+    @load_more_callbacks_active = false
     super opts
   end
 
@@ -24,6 +28,11 @@ class LineCursorMode < ScrollMode
 
 protected
 
+  ## callbacks when the cursor is asked to go beyond the bottom
+  def to_load_more &b
+    @load_more_callbacks << b
+  end
+
   def draw_line ln, opts={}
     if ln == @curpos
       super ln, :highlight => true, :debug => opts[:debug]
@@ -49,6 +58,7 @@ protected
 
   def line_down # overwrite scrollmode
     super
+    call_load_more_callbacks([topline + buffer.content_height - lines, 10].max) if topline + buffer.content_height > lines
     set_cursor_pos topline if @curpos < topline
   end
 
@@ -58,7 +68,9 @@ protected
   end
 
   def cursor_down
+    call_load_more_callbacks buffer.content_height if @curpos == lines - 1
     return false unless @curpos < lines - 1
+
     if @curpos >= botline - 1
       page_down
       set_cursor_pos topline
@@ -102,9 +114,21 @@ protected
     end
   end
 
+  ## more complicated than one might think. three behaviors.
   def page_down
-    if topline >= lines - buffer.content_height
+    ## if we're on the last page, and it's not a full page, just move
+    ## the cursor down to the bottom and assume we can't load anything
+    ## else via the callbacks.
+    if topline > lines - buffer.content_height
       set_cursor_pos(lines - 1)
+
+    ## if we're on the last page, and it's a full page, try and load
+    ## more lines via the callbacks and then shift the page down
+    elsif topline == lines - buffer.content_height
+      call_load_more_callbacks buffer.content_height
+      super
+
+    ## otherwise, just move down
     else
       relpos = @curpos - topline
       super
@@ -129,6 +153,22 @@ private
     @status = l > 0 ? "line #{@curpos + 1} of #{l}" : ""
   end
 
+  def call_load_more_callbacks size
+    go = 
+      @load_more_callbacks_m.synchronize do
+        if @load_more_callbacks_active
+          false
+        else
+          @load_more_callbacks_active = true
+        end
+    end
+
+    return unless go
+
+    @load_more_callbacks.each { |c| c.call size }
+    @load_more_callbacks_active = false
+  end    
+
 end
 
 end
diff --git a/lib/sup/modes/person-search-results-mode.rb b/lib/sup/modes/person-search-results-mode.rb
@@ -14,7 +14,7 @@ class PersonSearchResultsMode < ThreadIndexMode
                                  :load_killed => true,
                                  :load_spam => false,
                                  :when_done =>(lambda do |num|
-      opts[:when_done].call if opts[:when_done]
+      opts[:when_done].call(num) if opts[:when_done]
       if num > 0
         BufferManager.flash "Found #{num} threads"
       else
diff --git a/lib/sup/modes/search-results-mode.rb b/lib/sup/modes/search-results-mode.rb
@@ -15,7 +15,7 @@ class SearchResultsMode < ThreadIndexMode
                                  :load_killed => true,
                                  :load_spam => false,
                                  :when_done =>(lambda do |num|
-      opts[:when_done].call if opts[:when_done]
+      opts[:when_done].call(num) if opts[:when_done]
       if num > 0
         BufferManager.flash "Found #{num} threads"
       else
diff --git a/lib/sup/modes/thread-index-mode.rb b/lib/sup/modes/thread-index-mode.rb
@@ -2,7 +2,6 @@ require 'thread'
 module Redwood
 
 ## subclasses should implement load_threads
-
 class ThreadIndexMode < LineCursorMode
   DATE_WIDTH = Time::TO_NICE_S_MAX_LEN
   FROM_WIDTH = 15
@@ -35,13 +34,21 @@ class ThreadIndexMode < LineCursorMode
     @date_width = DATE_WIDTH
     @from_width = FROM_WIDTH
     @size_width = nil
-
+    @last_load_more_size = nil
+    
     @tags = Tagger.new self
     
     initialize_threads
     update
 
     UpdateManager.register self
+
+    to_load_more do |size|
+      next if @last_load_more_size == 0
+      load_threads :num => size,
+                   :when_done => lambda { |num| @last_load_more_size = num }
+      sleep 1.0 # give 'em a chance to load
+    end
   end
 
   def lines; @text.length; end
@@ -361,7 +368,7 @@ class ThreadIndexMode < LineCursorMode
 
   def status
     if (l = lines) == 0
-      ""
+      "line 0 of 0"
     else
       "line #{curpos + 1} of #{l} #{dirty? ? '*modified*' : ''}"
     end