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