Optimized thread ID

This commit is contained in:
M66B 2022-01-08 11:33:20 +01:00
parent 67eb2e6ef3
commit 9f8626688c
3 changed files with 134 additions and 1 deletions

View File

@ -425,6 +425,11 @@ public interface DaoMessage {
" AND inreplyto = :inreplyto")
List<EntityMessage> getMessagesByInReplyTo(long account, String inreplyto);
@Query("SELECT thread, msgid, hash, inreplyto FROM message" +
" WHERE account = :account" +
" AND (msgid IN (:msgids) OR inreplyto IN (:msgids))")
List<TupleThreadInfo> getThreadInfo(long account, List<String> msgids);
@Query("SELECT * FROM message" +
" WHERE account = :account" +
" AND sender = :sender" +

View File

@ -1287,7 +1287,10 @@ public class MessageHelper {
String getThreadId(Context context, long account, long folder, long uid) throws MessagingException {
if (threadId == null)
threadId = _getThreadId(context, account, folder, uid);
if (BuildConfig.DEBUG)
threadId = _getThreadIdAlt(context, account, folder, uid);
else
threadId = _getThreadId(context, account, folder, uid);
return threadId;
}
@ -1370,6 +1373,90 @@ public class MessageHelper {
return thread;
}
private String _getThreadIdAlt(Context context, long account, long folder, long uid) throws MessagingException {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
if (imessage instanceof GmailMessage) {
// https://developers.google.com/gmail/imap/imap-extensions#access_to_the_gmail_thread_id_x-gm-thrid
boolean gmail_thread_id = prefs.getBoolean("gmail_thread_id", false);
if (gmail_thread_id) {
long thrid = ((GmailMessage) imessage).getThrId();
if (thrid > 0)
return "gmail:" + thrid;
}
}
String thread = null;
String msgid = getMessageID();
List<String> refs = new ArrayList<>();
for (String ref : getReferences())
if (!TextUtils.isEmpty(ref) && !refs.contains(ref))
refs.add(ref);
String inreplyto = getInReplyTo();
if (!TextUtils.isEmpty(inreplyto) && !refs.contains(inreplyto))
refs.add(inreplyto);
DB db = DB.getInstance(context);
List<String> all = new ArrayList<>(refs);
all.add(msgid);
List<TupleThreadInfo> infos = db.message().getThreadInfo(account, all);
// References, In-Reply-To (before)
for (TupleThreadInfo info : infos)
if (info.isReference(msgid) && !TextUtils.isEmpty(info.thread)) {
thread = info.thread;
break;
}
// Similar
if (thread == null) {
for (TupleThreadInfo info : infos)
if (info.isSelf(msgid) &&
!TextUtils.isEmpty(info.thread) && Objects.equals(info.hash, getHash())) {
thread = info.thread;
break;
}
}
if (thread == null)
thread = getHash() + ":" + uid;
// Received before
for (TupleThreadInfo info : infos)
if (info.isReference(msgid) &&
!thread.equals(info.thread)) {
Log.w("Updating before thread from " + info.thread + " to " + thread);
db.message().updateMessageThread(account, info.thread, thread, null);
}
// Received after
for (TupleThreadInfo info : infos)
if (info.isInReplyto(msgid) && !thread.equals(info.thread)) {
Log.w("Updating after thread from " + info.thread + " to " + thread);
db.message().updateMessageThread(account, info.thread, thread, null);
}
boolean subject_threading = prefs.getBoolean("subject_threading", false);
if (subject_threading && !isReport()) {
String sender = getSortKey(getFrom());
String subject = getSubject();
long since = new Date().getTime() - MAX_SUBJECT_AGE * 3600 * 1000L;
if (!TextUtils.isEmpty(sender) && !TextUtils.isEmpty(subject)) {
List<EntityMessage> subjects = db.message().getMessagesBySubject(account, sender, subject, since);
for (EntityMessage message : subjects)
if (!thread.equals(message.thread)) {
Log.w("Updating subject thread from " + message.thread + " to " + thread);
db.message().updateMessageThread(message.account, message.thread, thread, since);
}
}
}
return thread;
}
String[] getLabels() throws MessagingException {
//ensureMessage(false);

View File

@ -0,0 +1,41 @@
package eu.faircode.email;
/*
This file is part of FairEmail.
FairEmail is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
FairEmail is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FairEmail. If not, see <http://www.gnu.org/licenses/>.
Copyright 2018-2022 by Marcel Bokhorst (M66B)
*/
import java.util.Objects;
public class TupleThreadInfo {
public String thread;
public String msgid;
public String hash;
public String inreplyto;
public boolean isSelf(String msgid) {
return Objects.equals(this.msgid, msgid);
}
public boolean isInReplyto(String msgid) {
return Objects.equals(this.inreplyto, msgid);
}
public boolean isReference(String msgid) {
return !isSelf(msgid) && !isInReplyto(msgid);
}
}