sup 0.12.1 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sup might be problematic. Click here for more details.
- data.tar.gz.sig +1 -0
- data/CONTRIBUTORS +25 -12
- data/History.txt +6 -1
- data/README.md +70 -0
- data/ReleaseNotes +5 -0
- data/bin/sup +22 -15
- data/bin/sup-add +3 -3
- data/bin/sup-config +3 -4
- data/bin/sup-import-dump +1 -1
- data/bin/sup-sync +1 -1
- data/bin/sup-sync-back +2 -2
- data/bin/sup-tweak-labels +1 -1
- data/lib/sup.rb +39 -23
- data/lib/sup/account.rb +4 -0
- data/lib/sup/buffer.rb +4 -7
- data/lib/sup/colormap.rb +10 -2
- data/lib/sup/contact.rb +11 -5
- data/lib/sup/crypto.rb +278 -101
- data/lib/sup/draft.rb +3 -2
- data/lib/sup/horizontal-selector.rb +5 -2
- data/lib/sup/index.rb +47 -42
- data/lib/sup/label.rb +1 -1
- data/lib/sup/message-chunks.rb +4 -2
- data/lib/sup/message.rb +14 -3
- data/lib/sup/modes/buffer-list-mode.rb +1 -1
- data/lib/sup/modes/compose-mode.rb +1 -1
- data/lib/sup/modes/contact-list-mode.rb +2 -2
- data/lib/sup/modes/edit-message-async-mode.rb +109 -0
- data/lib/sup/modes/edit-message-mode.rb +148 -16
- data/lib/sup/modes/file-browser-mode.rb +2 -2
- data/lib/sup/modes/forward-mode.rb +4 -4
- data/lib/sup/modes/line-cursor-mode.rb +2 -2
- data/lib/sup/modes/reply-mode.rb +34 -30
- data/lib/sup/modes/resume-mode.rb +4 -1
- data/lib/sup/modes/scroll-mode.rb +8 -6
- data/lib/sup/modes/text-mode.rb +1 -1
- data/lib/sup/modes/thread-index-mode.rb +44 -25
- data/lib/sup/modes/thread-view-mode.rb +26 -24
- data/lib/sup/person.rb +18 -7
- data/lib/sup/poll.rb +1 -1
- data/lib/sup/rfc2047.rb +1 -1
- data/lib/sup/sent.rb +2 -2
- data/lib/sup/source.rb +1 -1
- data/lib/sup/textfield.rb +38 -1
- data/lib/sup/thread.rb +1 -1
- data/lib/sup/time.rb +83 -0
- data/lib/sup/util.rb +38 -74
- data/lib/sup/version.rb +3 -0
- metadata +333 -168
- metadata.gz.sig +0 -0
- data/README.txt +0 -128
- data/bin/sup-cmd +0 -138
- data/bin/sup-server +0 -44
- data/lib/sup/client.rb +0 -92
- data/lib/sup/protocol.rb +0 -161
- data/lib/sup/server.rb +0 -116
@@ -80,6 +80,7 @@ EOS
|
|
80
80
|
k.add :edit_cc, "Edit Cc:", 'c'
|
81
81
|
k.add :edit_subject, "Edit Subject", 's'
|
82
82
|
k.add :edit_message, "Edit message", :enter
|
83
|
+
k.add :edit_message_async, "Edit message asynchronously", 'E'
|
83
84
|
k.add :save_as_draft, "Save as draft", 'P'
|
84
85
|
k.add :attach_file, "Attach a file", 'a'
|
85
86
|
k.add :delete_attachment, "Delete an attachment", 'd'
|
@@ -88,11 +89,10 @@ EOS
|
|
88
89
|
end
|
89
90
|
|
90
91
|
def initialize opts={}
|
91
|
-
@header = opts.delete(:header) || {}
|
92
|
+
@header = opts.delete(:header) || {}
|
92
93
|
@header_lines = []
|
93
94
|
|
94
95
|
@body = opts.delete(:body) || []
|
95
|
-
@body += sig_lines if $config[:edit_signature] && !opts.delete(:have_signature)
|
96
96
|
|
97
97
|
if opts[:attachments]
|
98
98
|
@attachments = opts[:attachments].values
|
@@ -111,16 +111,42 @@ EOS
|
|
111
111
|
|
112
112
|
@message_id = "<#{Time.now.to_i}-sup-#{rand 10000}@#{hostname}>"
|
113
113
|
@edited = false
|
114
|
+
@sig_edited = false
|
114
115
|
@selectors = []
|
115
116
|
@selector_label_width = 0
|
117
|
+
@async_mode = nil
|
118
|
+
|
119
|
+
HookManager.run "before-edit", :header => @header, :body => @body
|
120
|
+
|
121
|
+
@account_selector = nil
|
122
|
+
# only show account selector if there is more than one email address
|
123
|
+
if $config[:account_selector] && AccountManager.user_emails.length > 1
|
124
|
+
## Duplicate e-mail strings to prevent a "can't modify frozen
|
125
|
+
## object" crash triggered by the String::display_length()
|
126
|
+
## method in util.rb
|
127
|
+
user_emails_copy = []
|
128
|
+
AccountManager.user_emails.each { |e| user_emails_copy.push e.dup }
|
129
|
+
|
130
|
+
@account_selector =
|
131
|
+
HorizontalSelector.new "Account:", AccountManager.user_emails + [nil], user_emails_copy + ["Customized"]
|
132
|
+
|
133
|
+
if @header["From"] =~ /<?(\S+@(\S+?))>?$/
|
134
|
+
@account_selector.set_to $1
|
135
|
+
@account_user = ""
|
136
|
+
else
|
137
|
+
@account_selector.set_to nil
|
138
|
+
@account_user = @header["From"]
|
139
|
+
end
|
140
|
+
|
141
|
+
add_selector @account_selector
|
142
|
+
end
|
116
143
|
|
117
144
|
@crypto_selector =
|
118
145
|
if CryptoManager.have_crypto?
|
119
146
|
HorizontalSelector.new "Crypto:", [:none] + CryptoManager::OUTGOING_MESSAGE_OPERATIONS.keys, ["None"] + CryptoManager::OUTGOING_MESSAGE_OPERATIONS.values
|
120
147
|
end
|
121
148
|
add_selector @crypto_selector if @crypto_selector
|
122
|
-
|
123
|
-
HookManager.run "before-edit", :header => @header, :body => @body
|
149
|
+
|
124
150
|
if @crypto_selector
|
125
151
|
HookManager.run "crypto-mode", :header => @header, :body => @body, :crypto_selector => @crypto_selector
|
126
152
|
end
|
@@ -130,7 +156,7 @@ EOS
|
|
130
156
|
end
|
131
157
|
|
132
158
|
def lines; @text.length + (@selectors.empty? ? 0 : (@selectors.length + DECORATION_LINES)) end
|
133
|
-
|
159
|
+
|
134
160
|
def [] i
|
135
161
|
if @selectors.empty?
|
136
162
|
@text[i]
|
@@ -161,12 +187,41 @@ EOS
|
|
161
187
|
def edit_cc; edit_field "Cc" end
|
162
188
|
def edit_subject; edit_field "Subject" end
|
163
189
|
|
164
|
-
def
|
165
|
-
|
190
|
+
def save_message_to_file
|
191
|
+
sig = sig_lines.join("\n")
|
192
|
+
@file = Tempfile.new ["sup.#{self.class.name.gsub(/.*::/, '').camel_to_hyphy}", ".eml"]
|
166
193
|
@file.puts format_headers(@header - NON_EDITABLE_HEADERS).first
|
167
194
|
@file.puts
|
168
195
|
@file.puts @body.join("\n")
|
196
|
+
@file.puts sig if ($config[:edit_signature] and !@sig_edited)
|
169
197
|
@file.close
|
198
|
+
end
|
199
|
+
|
200
|
+
def set_sig_edit_flag
|
201
|
+
sig = sig_lines.join("\n")
|
202
|
+
if $config[:edit_signature]
|
203
|
+
pbody = @body.join("\n")
|
204
|
+
blen = pbody.length
|
205
|
+
slen = sig.length
|
206
|
+
|
207
|
+
if blen > slen and pbody[blen-slen..blen] == sig
|
208
|
+
@sig_edited = false
|
209
|
+
@body = pbody[0..blen-slen].split("\n")
|
210
|
+
else
|
211
|
+
@sig_edited = true
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def edit_message
|
217
|
+
old_from = @header["From"] if @account_selector
|
218
|
+
|
219
|
+
begin
|
220
|
+
save_message_to_file
|
221
|
+
rescue SystemCallError => e
|
222
|
+
BufferManager.flash "Can't save message to file: #{e.message}"
|
223
|
+
return
|
224
|
+
end
|
170
225
|
|
171
226
|
editor = $config[:editor] || ENV['EDITOR'] || "/usr/bin/vi"
|
172
227
|
|
@@ -178,13 +233,67 @@ EOS
|
|
178
233
|
|
179
234
|
header, @body = parse_file @file.path
|
180
235
|
@header = header - NON_EDITABLE_HEADERS
|
236
|
+
set_sig_edit_flag
|
237
|
+
|
238
|
+
if @account_selector and @header["From"] != old_from
|
239
|
+
@account_user = @header["From"]
|
240
|
+
@account_selector.set_to nil
|
241
|
+
end
|
242
|
+
|
181
243
|
handle_new_text @header, @body
|
244
|
+
rerun_crypto_selector_hook
|
182
245
|
update
|
183
246
|
|
184
247
|
@edited
|
185
248
|
end
|
186
249
|
|
250
|
+
def edit_message_async
|
251
|
+
begin
|
252
|
+
save_message_to_file
|
253
|
+
rescue SystemCallError => e
|
254
|
+
BufferManager.flash "Can't save message to file: #{e.message}"
|
255
|
+
return
|
256
|
+
end
|
257
|
+
|
258
|
+
@mtime = File.mtime @file.path
|
259
|
+
|
260
|
+
# put up buffer saying you can now edit the message in another
|
261
|
+
# terminal or app, and continue to use sup in the meantime.
|
262
|
+
subject = @header["Subject"] || ""
|
263
|
+
@async_mode = EditMessageAsyncMode.new self, @file.path, subject
|
264
|
+
BufferManager.spawn "Waiting for message \"#{subject}\" to be finished", @async_mode
|
265
|
+
|
266
|
+
# hide ourselves, and wait for signal to resume from async mode ...
|
267
|
+
buffer.hidden = true
|
268
|
+
end
|
269
|
+
|
270
|
+
def edit_message_async_resume being_killed=false
|
271
|
+
buffer.hidden = false
|
272
|
+
@async_mode = nil
|
273
|
+
BufferManager.raise_to_front buffer if !being_killed
|
274
|
+
|
275
|
+
@edited = true if File.mtime(@file.path) > @mtime
|
276
|
+
|
277
|
+
header, @body = parse_file @file.path
|
278
|
+
@header = header - NON_EDITABLE_HEADERS
|
279
|
+
set_sig_edit_flag
|
280
|
+
handle_new_text @header, @body
|
281
|
+
update
|
282
|
+
|
283
|
+
true
|
284
|
+
end
|
285
|
+
|
187
286
|
def killable?
|
287
|
+
if !@async_mode.nil?
|
288
|
+
return false if !@async_mode.killable?
|
289
|
+
if File.mtime(@file.path) > @mtime
|
290
|
+
@edited = true
|
291
|
+
header, @body = parse_file @file.path
|
292
|
+
@header = header - NON_EDITABLE_HEADERS
|
293
|
+
handle_new_text @header, @body
|
294
|
+
update
|
295
|
+
end
|
296
|
+
end
|
188
297
|
!edited? || BufferManager.ask_yes_or_no("Discard message?")
|
189
298
|
end
|
190
299
|
|
@@ -205,7 +314,7 @@ EOS
|
|
205
314
|
end
|
206
315
|
|
207
316
|
def delete_attachment
|
208
|
-
i = curpos - @attachment_lines_offset - DECORATION_LINES -
|
317
|
+
i = curpos - @attachment_lines_offset - DECORATION_LINES - 2
|
209
318
|
if i >= 0 && i < @attachments.size && BufferManager.ask_yes_or_no("Delete attachment #{@attachment_names[i]}?")
|
210
319
|
@attachments.delete_at i
|
211
320
|
@attachment_names.delete_at i
|
@@ -215,6 +324,12 @@ EOS
|
|
215
324
|
|
216
325
|
protected
|
217
326
|
|
327
|
+
def rerun_crypto_selector_hook
|
328
|
+
if @crypto_selector && !@crypto_selector.changed_by_user
|
329
|
+
HookManager.run "crypto-mode", :header => @header, :body => @body, :crypto_selector => @crypto_selector
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
218
333
|
def mime_encode string
|
219
334
|
string = [string].pack('M') # basic quoted-printable
|
220
335
|
string.gsub!(/=\n/,'') # .. remove trailing newline
|
@@ -242,6 +357,7 @@ protected
|
|
242
357
|
if curpos < @selectors.length
|
243
358
|
@selectors[curpos].roll_left
|
244
359
|
buffer.mark_dirty
|
360
|
+
update if @account_selector
|
245
361
|
else
|
246
362
|
col_left
|
247
363
|
end
|
@@ -251,6 +367,7 @@ protected
|
|
251
367
|
if curpos < @selectors.length
|
252
368
|
@selectors[curpos].roll_right
|
253
369
|
buffer.mark_dirty
|
370
|
+
update if @account_selector
|
254
371
|
else
|
255
372
|
col_right
|
256
373
|
end
|
@@ -262,6 +379,14 @@ protected
|
|
262
379
|
end
|
263
380
|
|
264
381
|
def update
|
382
|
+
if @account_selector
|
383
|
+
if @account_selector.val.nil?
|
384
|
+
@header["From"] = @account_user
|
385
|
+
else
|
386
|
+
@header["From"] = AccountManager.full_address_for @account_selector.val
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
265
390
|
regen_text
|
266
391
|
buffer.mark_dirty if buffer
|
267
392
|
end
|
@@ -269,8 +394,8 @@ protected
|
|
269
394
|
def regen_text
|
270
395
|
header, @header_lines = format_headers(@header - NON_EDITABLE_HEADERS) + [""]
|
271
396
|
@text = header + [""] + @body
|
272
|
-
@text += sig_lines unless
|
273
|
-
|
397
|
+
@text += sig_lines unless @sig_edited
|
398
|
+
|
274
399
|
@attachment_lines_offset = 0
|
275
400
|
|
276
401
|
unless @attachments.empty?
|
@@ -339,7 +464,7 @@ protected
|
|
339
464
|
return false if $config[:confirm_no_attachments] && mentions_attachments? && @attachments.size == 0 && !BufferManager.ask_yes_or_no("You haven't added any attachments. Really send?")#" stupid ruby-mode
|
340
465
|
return false if $config[:confirm_top_posting] && top_posting? && !BufferManager.ask_yes_or_no("You're top-posting. That makes you a bad person. Really send?") #" stupid ruby-mode
|
341
466
|
|
342
|
-
from_email =
|
467
|
+
from_email =
|
343
468
|
if @header["From"] =~ /<?(\S+@(\S+?))>?$/
|
344
469
|
$1
|
345
470
|
else
|
@@ -384,7 +509,7 @@ protected
|
|
384
509
|
m = RMail::Message.new
|
385
510
|
m.header["Content-Type"] = "text/plain; charset=#{$encoding}"
|
386
511
|
m.body = @body.join("\n")
|
387
|
-
m.body += sig_lines.join("\n") unless
|
512
|
+
m.body += "\n" + sig_lines.join("\n") unless @sig_edited
|
388
513
|
## body must end in a newline or GPG signatures will be WRONG!
|
389
514
|
m.body += "\n" unless m.body =~ /\n\Z/
|
390
515
|
|
@@ -393,7 +518,7 @@ protected
|
|
393
518
|
body_m = m
|
394
519
|
body_m.header["Content-Disposition"] = "inline"
|
395
520
|
m = RMail::Message.new
|
396
|
-
|
521
|
+
|
397
522
|
m.add_part body_m
|
398
523
|
@attachments.each { |a| m.add_part a }
|
399
524
|
end
|
@@ -414,7 +539,7 @@ protected
|
|
414
539
|
## finally, set the top-level headers
|
415
540
|
@header.each do |k, v|
|
416
541
|
next if v.nil? || v.empty?
|
417
|
-
m.header[k] =
|
542
|
+
m.header[k] =
|
418
543
|
case v
|
419
544
|
when String
|
420
545
|
k.match(/subject/i) ? mime_encode_subject(v) : mime_encode_address(v)
|
@@ -454,7 +579,7 @@ EOS
|
|
454
579
|
f.puts
|
455
580
|
f.puts sanitize_body(@body.join("\n"))
|
456
581
|
f.puts sig_lines if full unless $config[:edit_signature]
|
457
|
-
end
|
582
|
+
end
|
458
583
|
|
459
584
|
protected
|
460
585
|
|
@@ -479,6 +604,13 @@ protected
|
|
479
604
|
if contacts
|
480
605
|
text = contacts.map { |s| s.full_address }.join(", ")
|
481
606
|
@header[field] = parse_header field, text
|
607
|
+
|
608
|
+
if @account_selector and field == "From"
|
609
|
+
@account_user = @header["From"]
|
610
|
+
@account_selector.set_to nil
|
611
|
+
end
|
612
|
+
|
613
|
+
rerun_crypto_selector_hook
|
482
614
|
update
|
483
615
|
end
|
484
616
|
end
|
@@ -514,7 +646,7 @@ private
|
|
514
646
|
|
515
647
|
## no hook, do default signature generation based on config.yaml
|
516
648
|
return [] unless from_email
|
517
|
-
sigfn = (AccountManager.account_for(from_email) ||
|
649
|
+
sigfn = (AccountManager.account_for(from_email) ||
|
518
650
|
AccountManager.default_account).signature
|
519
651
|
|
520
652
|
if sigfn && File.exists?(sigfn)
|
@@ -29,7 +29,7 @@ class FileBrowserMode < LineCursorMode
|
|
29
29
|
def [] i; @text[i]; end
|
30
30
|
|
31
31
|
protected
|
32
|
-
|
32
|
+
|
33
33
|
def back
|
34
34
|
return if @dirs.size == 1
|
35
35
|
@dirs.pop
|
@@ -75,7 +75,7 @@ protected
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def regen_text
|
78
|
-
@files =
|
78
|
+
@files =
|
79
79
|
begin
|
80
80
|
cwd.entries.sort_by do |f|
|
81
81
|
[f.directory? ? 0 : 1, f.basename.to_s]
|
@@ -7,7 +7,7 @@ class ForwardMode < EditMessageMode
|
|
7
7
|
"From" => AccountManager.default_account.full_address,
|
8
8
|
}
|
9
9
|
|
10
|
-
header["Subject"] =
|
10
|
+
header["Subject"] =
|
11
11
|
if opts[:message]
|
12
12
|
"Fwd: " + opts[:message].subj
|
13
13
|
elsif opts[:attachments]
|
@@ -20,7 +20,7 @@ class ForwardMode < EditMessageMode
|
|
20
20
|
|
21
21
|
body =
|
22
22
|
if opts[:message]
|
23
|
-
forward_body_lines(opts[:message])
|
23
|
+
forward_body_lines(opts[:message])
|
24
24
|
elsif opts[:attachments]
|
25
25
|
["Note: #{opts[:attachments].size.pluralize 'attachment'}."]
|
26
26
|
end
|
@@ -32,7 +32,7 @@ class ForwardMode < EditMessageMode
|
|
32
32
|
to = opts[:to] || (BufferManager.ask_for_contacts(:people, "To: ") or return if ($config[:ask_for_to] != false))
|
33
33
|
cc = opts[:cc] || (BufferManager.ask_for_contacts(:people, "Cc: ") or return if $config[:ask_for_cc])
|
34
34
|
bcc = opts[:bcc] || (BufferManager.ask_for_contacts(:people, "Bcc: ") or return if $config[:ask_for_bcc])
|
35
|
-
|
35
|
+
|
36
36
|
attachment_hash = {}
|
37
37
|
attachments = opts[:attachments] || []
|
38
38
|
|
@@ -64,7 +64,7 @@ class ForwardMode < EditMessageMode
|
|
64
64
|
protected
|
65
65
|
|
66
66
|
def forward_body_lines m
|
67
|
-
["--- Begin forwarded message from #{m.from.mediumname} ---"] +
|
67
|
+
["--- Begin forwarded message from #{m.from.mediumname} ---"] +
|
68
68
|
m.quotable_header_lines + [""] + m.quotable_body_lines +
|
69
69
|
["--- End forwarded message ---"]
|
70
70
|
end
|
@@ -78,7 +78,7 @@ protected
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def search_start_line; @curpos end
|
81
|
-
|
81
|
+
|
82
82
|
def line_down # overwrite scrollmode
|
83
83
|
super
|
84
84
|
call_load_more_callbacks([topline + buffer.content_height - lines, 10].max) if topline + buffer.content_height > lines
|
@@ -177,7 +177,7 @@ private
|
|
177
177
|
end
|
178
178
|
|
179
179
|
def call_load_more_callbacks size
|
180
|
-
@load_more_q.push size
|
180
|
+
@load_more_q.push size if $config[:load_more_threads_when_scrolling]
|
181
181
|
end
|
182
182
|
end
|
183
183
|
|
data/lib/sup/modes/reply-mode.rb
CHANGED
@@ -48,6 +48,7 @@ EOS
|
|
48
48
|
## the full headers (most importantly the list-post header, if
|
49
49
|
## any)
|
50
50
|
body = reply_body_lines message
|
51
|
+
@body_orig = body
|
51
52
|
|
52
53
|
## first, determine the address at which we received this email. this will
|
53
54
|
## become our From: address in the reply.
|
@@ -93,18 +94,25 @@ EOS
|
|
93
94
|
## to. if it's a list message, then the list address is. otherwise,
|
94
95
|
## the cc contains a recipient.
|
95
96
|
useful_recipient = !(cc.empty? || @m.is_list_message?)
|
96
|
-
|
97
|
+
|
97
98
|
@headers = {}
|
98
99
|
@headers[:recipient] = {
|
99
100
|
"To" => cc.map { |p| p.full_address },
|
101
|
+
"Cc" => [],
|
100
102
|
} if useful_recipient
|
101
103
|
|
102
104
|
## typically we don't want to have a reply-to-sender option if the sender
|
103
105
|
## is a user account. however, if the cc is empty, it's a message to
|
104
106
|
## ourselves, so for the lack of any other options, we'll add it.
|
105
|
-
@headers[:sender] = {
|
107
|
+
@headers[:sender] = {
|
108
|
+
"To" => [to.full_address],
|
109
|
+
"Cc" => [],
|
110
|
+
} if !AccountManager.is_account?(to) || !useful_recipient
|
106
111
|
|
107
|
-
@headers[:user] = {
|
112
|
+
@headers[:user] = {
|
113
|
+
"To" => [],
|
114
|
+
"Cc" => [],
|
115
|
+
}
|
108
116
|
|
109
117
|
not_me_ccs = cc.select { |p| !AccountManager.is_account?(p) }
|
110
118
|
@headers[:all] = {
|
@@ -114,22 +122,11 @@ EOS
|
|
114
122
|
|
115
123
|
@headers[:list] = {
|
116
124
|
"To" => [@m.list_address.full_address],
|
125
|
+
"Cc" => [],
|
117
126
|
} if @m.is_list_message?
|
118
127
|
|
119
128
|
refs = gen_references
|
120
129
|
|
121
|
-
@headers.each do |k, v|
|
122
|
-
@headers[k] = {
|
123
|
-
"From" => from.full_address,
|
124
|
-
"To" => [],
|
125
|
-
"Cc" => [],
|
126
|
-
"Bcc" => [],
|
127
|
-
"In-reply-to" => "<#{@m.id}>",
|
128
|
-
"Subject" => Message.reify_subj(@m.subj),
|
129
|
-
"References" => refs,
|
130
|
-
}.merge v
|
131
|
-
end
|
132
|
-
|
133
130
|
types = REPLY_TYPES.select { |t| @headers.member?(t) }
|
134
131
|
@type_selector = HorizontalSelector.new "Reply to:", types, types.map { |x| TYPE_DESCRIPTIONS[x] }
|
135
132
|
|
@@ -148,13 +145,17 @@ EOS
|
|
148
145
|
:recipient
|
149
146
|
end)
|
150
147
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
148
|
+
headers_full = {
|
149
|
+
"From" => from.full_address,
|
150
|
+
"Bcc" => [],
|
151
|
+
"In-reply-to" => "<#{@m.id}>",
|
152
|
+
"Subject" => Message.reify_subj(@m.subj),
|
153
|
+
"References" => refs,
|
154
|
+
}.merge @headers[@type_selector.val]
|
155
|
+
|
156
|
+
HookManager.run "before-edit", :header => headers_full, :body => body
|
156
157
|
|
157
|
-
super :header =>
|
158
|
+
super :header => headers_full, :body => body, :twiddles => false
|
158
159
|
add_selector @type_selector
|
159
160
|
end
|
160
161
|
|
@@ -163,8 +164,8 @@ protected
|
|
163
164
|
def move_cursor_right
|
164
165
|
super
|
165
166
|
if @headers[@type_selector.val] != self.header
|
166
|
-
self.header = @headers[@type_selector.val]
|
167
|
-
|
167
|
+
self.header = self.header.merge @headers[@type_selector.val]
|
168
|
+
rerun_crypto_selector_hook
|
168
169
|
update
|
169
170
|
end
|
170
171
|
end
|
@@ -172,8 +173,8 @@ protected
|
|
172
173
|
def move_cursor_left
|
173
174
|
super
|
174
175
|
if @headers[@type_selector.val] != self.header
|
175
|
-
self.header = @headers[@type_selector.val]
|
176
|
-
|
176
|
+
self.header = self.header.merge @headers[@type_selector.val]
|
177
|
+
rerun_crypto_selector_hook
|
177
178
|
update
|
178
179
|
end
|
179
180
|
end
|
@@ -190,14 +191,15 @@ protected
|
|
190
191
|
end
|
191
192
|
|
192
193
|
def handle_new_text new_header, new_body
|
193
|
-
if new_body != @
|
194
|
-
@
|
194
|
+
if new_body != @body_orig
|
195
|
+
@body_orig = new_body
|
195
196
|
@edited = true
|
196
197
|
end
|
197
198
|
old_header = @headers[@type_selector.val]
|
198
|
-
if
|
199
|
+
if old_header.any? { |k, v| new_header[k] != v }
|
199
200
|
@type_selector.set_to :user
|
200
|
-
self.header = @headers[:user] = new_header
|
201
|
+
self.header["To"] = @headers[:user]["To"] = new_header["To"]
|
202
|
+
self.header["Cc"] = @headers[:user]["Cc"] = new_header["Cc"]
|
201
203
|
update
|
202
204
|
end
|
203
205
|
end
|
@@ -208,8 +210,10 @@ protected
|
|
208
210
|
|
209
211
|
def edit_field field
|
210
212
|
edited_field = super
|
211
|
-
if edited_field
|
213
|
+
if edited_field and (field == "To" or field == "Cc")
|
212
214
|
@type_selector.set_to :user
|
215
|
+
@headers[:user]["To"] = self.header["To"]
|
216
|
+
@headers[:user]["Cc"] = self.header["Cc"]
|
213
217
|
update
|
214
218
|
end
|
215
219
|
end
|