class LabelListMode < LineCursorMode
register_keymap do |k|
- k.add :view_results, "View messages with the selected label", :enter
- k.add :reload, "Discard results and reload", 'D'
+ k.add :select_label, "Search by label", :enter
+ k.add :reload, "Discard label list and reload", '@'
+ k.add :jump_to_next_new, "Jump to next new thread", :tab
+ k.add :toggle_show_unread_only, "Toggle between showing all labels and those with unread mail", 'u'
end
def initialize
@labels = []
@text = []
- super()
+ @unread_only = false
+ super
+ regen_text
end
- def lines; @text.length; end
- def [] i; @text[i]; end
+ def lines; @text.length end
+ def [] i; @text[i] end
- def load_in_background
- Redwood::reporting_thread do
- BufferManager.say("Counting labels...") { regen_text }
- BufferManager.draw_screen
+ def jump_to_next_new
+ n = ((curpos + 1) ... lines).find { |i| @labels[i][1] > 0 } || (0 ... curpos).find { |i| @labels[i][1] > 0 }
+ if n
+ ## jump there if necessary
+ jump_to_line n unless n >= topline && n < botline
+ set_cursor_pos n
+ else
+ BufferManager.flash "No labels messages with unread messages."
end
end
+ def focus
+ reload # make sure unread message counts are up-to-date
+ end
+
protected
+ def toggle_show_unread_only
+ @unread_only = !@unread_only
+ reload
+ end
+
def reload
- buffer.mark_dirty
- BufferManager.draw_screen
- load_in_background
+ regen_text
+ buffer.mark_dirty if buffer
end
-
+
def regen_text
@text = []
- @labels = (LabelManager::LISTABLE_LABELS + LabelManager.user_labels).sort_by { |t| t.to_s }
+ labels = LabelManager.all_labels
- counts = @labels.map do |t|
- total = Index.num_results_for :label => t
- unread = Index.num_results_for :labels => [t, :unread]
- [t, total, unread]
- end
+ counts = labels.map do |label|
+ string = LabelManager.string_for label
+ total = Index.num_results_for :label => label
+ unread = (label == :unread)? total : Index.num_results_for(:labels => [label, :unread])
+ [label, string, total, unread]
+ end.sort_by { |l, s, t, u| s.downcase }
- width = @labels.map { |t| t.to_s.length }.max
+ width = counts.max_of { |l, s, t, u| s.length }
- counts.map_with_index do |(t, total, unread), i|
- if total == 0 && !LabelManager::LISTABLE_LABELS.include?(t)
- Redwood::log "no hits for label #{t}, deleting"
- LabelManager.delete t
- @labels.delete t
+ if @unread_only
+ counts.delete_if { | l, s, t, u | u == 0 }
+ end
+
+ @labels = []
+ counts.map do |label, string, total, unread|
+ ## if we've done a search and there are no messages for this label, we can delete it from the
+ ## list. BUT if it's a brand-new label, the user may not have sync'ed it to the index yet, so
+ ## don't delete it in this case.
+ ##
+ ## this is all a hack. what should happen is:
+ ## TODO make the labelmanager responsible for label counts
+ ## and then it can listen to labeled and unlabeled events, etc.
+ if total == 0 && !LabelManager::RESERVED_LABELS.include?(label) && !LabelManager.new_label?(label)
+ debug "no hits for label #{label}, deleting"
+ LabelManager.delete label
next
end
- label =
- case t
- when *LabelManager::LISTABLE_LABELS
- t.to_s.ucfirst
- else
- t.to_s
- end
@text << [[(unread == 0 ? :labellist_old_color : :labellist_new_color),
- sprintf("%#{width + 1}s %5d %s, %5d unread", label, total, total == 1 ? " message" : "messages", unread)]]
+ sprintf("%#{width + 1}s %5d %s, %5d unread", string, total, total == 1 ? " message" : "messages", unread)]]
+ @labels << [label, unread]
yield i if block_given?
end.compact
- buffer.mark_dirty
+ BufferManager.flash "No labels with unread messages!" if counts.empty? && @unread_only
end
- def view_results
- label = @labels[curpos]
- if label == :inbox
- BufferManager.raise_to_front BufferManager["inbox"]
- else
- b = BufferManager.spawn_unless_exists(label) do
- mode = LabelSearchResultsMode.new [label]
- end
- b.mode.load_threads :num => b.content_height
- end
+ def select_label
+ label, num_unread = @labels[curpos]
+ return unless label
+ LabelSearchResultsMode.spawn_nicely label
end
end