lib/sup/modes/thread-view-mode.rb in sup-0.0.4 vs lib/sup/modes/thread-view-mode.rb in sup-0.0.5

- old
+ new

@@ -23,30 +23,24 @@ super() @thread = thread @state = {} @hidden_labels = hidden_labels - earliest = nil - latest = nil + earliest, latest = nil, nil latest_date = nil @thread.each do |m, d, p| next unless m earliest ||= m - @state[m] = - if m.has_label?(:unread) && m == earliest - :detailed - elsif m.has_label?(:starred) || m.has_label?(:unread) - :open - else - :closed - end + @state[m] = initial_state_for m if latest_date.nil? || m.date > latest_date latest_date = m.date latest = m end end + @state[latest] = :open if @state[latest] == :closed + @state[earliest] = :detailed if earliest.has_label?(:unread) || @thread.size == 1 BufferManager.say "Loading message bodies..." do regen_chunks regen_text end @@ -104,10 +98,11 @@ def toggle_expanded return unless(chunk = @chunk_lines[curpos]) case chunk when Message, Message::Quote, Message::Signature @state[chunk] = (@state[chunk] != :closed ? :closed : :open) + cursor_down if @state[chunk] == :closed when Message::Attachment view_attachment chunk end update end @@ -162,24 +157,25 @@ return unless(m = @message_lines[curpos]) ## jump to the top of the current message if we're in the body; ## otherwise, to the previous message top = @messages[m][0] if curpos == top - while prevm = @messages[m][2] - break if @state[prevm] == :open + while(prevm = @messages[m][2]) + break if @state[prevm] != :closed m = prevm end jump_to_message prevm if prevm else jump_to_message m end end def jump_to_message m - top, bot, prevm, nextm = @messages[m] + top, bot, prevm, nextm, depth = @messages[m] jump_to_line top unless top >= topline && top <= botline && bot >= topline && bot <= botline + jump_to_col depth * 2 # sorry!!!! TODO: make this a constant set_cursor_pos top end def expand_all_messages @global_message_state ||= :closed @@ -197,29 +193,38 @@ def expand_all_quotes if(m = @message_lines[curpos]) quotes = @chunks[m].select { |c| c.is_a?(Message::Quote) || c.is_a?(Message::Signature) } open, closed = quotes.partition { |c| @state[c] == :open } newstate = open.length > closed.length ? :closed : :open - Redwood::log "#{open.length} opened, #{closed.length} closed, new state is thus #{newstate}" quotes.each { |c| @state[c] = newstate } update end end - ## not sure if this is really necessary but we might as well... + ## kinda slow for large threads. TODO: fasterify def cleanup - @thread.each do |m, d, p| - if m && m.has_label?(:unread) - m.remove_label :unread - UpdateManager.relay :read, m + BufferManager.say "Marking messages as read..." do + @thread.each do |m, d, p| + if m && m.has_label?(:unread) + m.remove_label :unread + UpdateManager.relay :read, m + end end end @messages = @chunks = @text = nil end private + def initial_state_for m + if m.has_label?(:starred) || m.has_label?(:unread) + :open + else + :closed + end + end + def update regen_text buffer.mark_dirty if buffer end @@ -234,19 +239,31 @@ @message_lines = [] @messages = {} prev_m = nil @thread.each do |m, depth, parent| + ## we're occasionally called on @threads that have had messages + ## added to them since initialization. luckily we regen_text on + ## the entire thread every time the user does anything besides + ## scrolling (basically), so we can just slap this on here. + ## + ## to pick nits, the niceness that i do in the constructor with + ## 'latest' might not be valid, but i don't see that as a huge + ## issue. + @state[m] ||= initial_state_for m if m + text = chunk_to_lines m, @state[m], @text.length, depth, parent (0 ... text.length).each do |i| @chunk_lines[@text.length + i] = m @message_lines[@text.length + i] = m end - @messages[m] = [@text.length, @text.length + text.length, prev_m, nil] + ## sorry i store all this shit in an array. very, very sorry. + ## also sorry about the * 2. very, very sorry. + @messages[m] = [@text.length, @text.length + text.length, prev_m, nil, depth] @messages[prev_m][3] = m if prev_m - prev_m = m + prev_m = m if m.is_a? Message @text += text if @state[m] != :closed && @chunks.member?(m) @chunks[m].each do |c| @state[c] ||= :closed @@ -281,11 +298,10 @@ case state when :open [[prefix_widget, widget, imp_widget, [:message_patina_color, "#{m.from ? m.from.mediumname : '?'} to #{m.recipients.map { |l| l.shortname }.join(', ')} #{m.date.to_nice_s} (#{m.date.to_nice_distance_s})"]]] -# (m.to.empty? ? [] : [[[:message_patina_color, prefix + " To: " + m.recipients.map { |x| x.mediumname }.join(", ")]]]) + when :closed [[prefix_widget, widget, imp_widget, [:message_patina_color, "#{m.from ? m.from.mediumname : '?'}, #{m.date.to_nice_s} (#{m.date.to_nice_distance_s}) #{m.snippet}"]]] when :detailed @@ -321,16 +337,15 @@ when nil [[[:message_patina_color, "#{prefix}<an unreceived message>"]]] when Message message_patina_lines(chunk, state, parent, prefix) + (chunk.is_draft? ? [[[:draft_notification_color, prefix + " >>> This message is a draft. To edit, hit 'e'. <<<"]]] : []) - when Message::Attachment [[[:mime_color, "#{prefix}+ MIME attachment #{chunk.content_type}#{chunk.desc ? ' (' + chunk.desc + ')': ''}"]]] when Message::Text t = chunk.lines - if t.last =~ /^\s*$/ - t.pop while t[t.length - 2] =~ /^\s*$/ + if t.last =~ /^\s*$/ && t.length > 1 + t.pop while t[-2] =~ /^\s*$/ # pop until only one file empty line end t.map { |line| [[:none, "#{prefix}#{line}"]] } when Message::Quote case state when :closed