From 7027f671c35f4b22c6af5ff0b1a58f79a34d41d0 Mon Sep 17 00:00:00 2001 From: William Morgan Date: Wed, 16 Jan 2008 16:44:43 -0800 Subject: [PATCH] add the ability to joining threads forcefully to ThreadSet ThreadSet#join_threads now takes any number of threads (which must be part of the threadset) heuristically either picks one message to be the root (if all messages but one have a "Re:" on the subject line), or creates a fake root. It updates the message object and marks it dirty so that a subsequent save will preserve the new structure. --- lib/sup/message.rb | 17 ++++++++++++++++- lib/sup/thread.rb | 26 ++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/lib/sup/message.rb b/lib/sup/message.rb index c487ae3..651c839 100644 --- a/lib/sup/message.rb +++ b/lib/sup/message.rb @@ -55,6 +55,10 @@ class Message @encrypted = false @chunks = nil + ## we need to initialize this. see comments in parse_header as to + ## why. + @refs = [] + parse_header(opts[:header] || @source.load_header(@source_info)) end @@ -102,7 +106,13 @@ class Message @to = PersonManager.people_for header["to"] @cc = PersonManager.people_for header["cc"] @bcc = PersonManager.people_for header["bcc"] - @refs = (header["references"] || "").scan(/<(.+?)>/).map { |x| sanitize_message_id x.first } + + ## before loading our full header from the source, we can actually + ## have some extra refs set by the UI. (this happens when the user + ## joins threads manually). so we will merge the current refs values + ## in here. + refs = (header["references"] || "").scan(/<(.+?)>/).map { |x| sanitize_message_id x.first } + @refs = (@refs + refs).uniq @replytos = (header["in-reply-to"] || "").scan(/<(.+?)>/).map { |x| sanitize_message_id x.first } @replyto = PersonManager.person_for header["reply-to"] @@ -120,6 +130,11 @@ class Message end private :parse_header + def add_ref ref + @refs << ref + @dirty = true + end + def snippet; @snippet || (chunks && @snippet); end def is_list_message?; !@list_address.nil?; end def is_draft?; @source.is_a? DraftLoader; end diff --git a/lib/sup/thread.rb b/lib/sup/thread.rb index 3ade024..32002c4 100644 --- a/lib/sup/thread.rb +++ b/lib/sup/thread.rb @@ -349,6 +349,32 @@ class ThreadSet t.each { |m, *o| add_message m } end + ## merges two threads together. both must be members of this threadset. + ## does its best, heuristically, to determine which is the parent. + def join_threads threads + return if threads.size < 2 + + containers = threads.map do |t| + c = @messages[t.first.id] + raise "not in threadset: #{t.first.id}" unless c && c.message + c + end + + ## use subject headers heuristically + parent = containers.find { |c| !c.is_reply? } + + ## no thread was rooted by a non-reply, so make a fake parent + parent ||= @messages["joining-ref-" + containers.map { |c| c.id }.join("-")] + + containers.each do |c| + next if c == parent + c.message.add_ref parent.id + link parent, c + end + + true + end + def is_relevant? m m.refs.any? { |ref_id| @messages.member? ref_id } end -- 2.45.2