summaryrefslogtreecommitdiffstats
path: root/src/threadlistmodel.cpp
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-14 20:06:08 +0200
committerDanilo M. <danix@danix.xyz>2026-08-14 20:06:08 +0200
commit4a4849421ddac044212cd0e17f9aee8ff2606292 (patch)
treebedfb35f370b637eedcb3cd4d24be8ac75b257b5 /src/threadlistmodel.cpp
parentbde7409ef817089298718376e46a57b2d303cf02 (diff)
downloadqtmaildir-4a4849421ddac044212cd0e17f9aee8ff2606292.tar.gz
qtmaildir-4a4849421ddac044212cd0e17f9aee8ff2606292.zip
Revert the message-scoped auto mark-read
Reverts bde7409 and 66f1159. The user hit the worst possible symptom: clicking one message marked a DIFFERENT, unrelated message read. The cause is in markCurrentThreadRead, which reads m_model->threadAt(current.row()). CLAUDE.md records this exact trap: a tree numbers rows PER PARENT, so a reply's row() indexes its siblings and threadAt() on it answers about an unrelated thread near the top of the list. The guards then compared the right ids against the wrong thread and let a write through for whatever message the timer's state named. That fault predates these commits, but they made it reachable and harmful: while the write was thread-scoped the mismatch was mostly masked, and scoping it to a single message turned it into "a random message is now read". Reverting rather than fixing forward. Marking the wrong mail read syncs out to the server and cannot be undone from here, so the safe state is the previous behaviour, which is too broad but predictable. The item 66 work in 4a4f82f stands: a thread root still renders one message. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'src/threadlistmodel.cpp')
-rw-r--r--src/threadlistmodel.cpp81
1 files changed, 0 insertions, 81 deletions
diff --git a/src/threadlistmodel.cpp b/src/threadlistmodel.cpp
index 04a5493..3e079ed 100644
--- a/src/threadlistmodel.cpp
+++ b/src/threadlistmodel.cpp
@@ -888,84 +888,3 @@ void ThreadListModel::applyTagChange(const QString &threadId,
return;
}
}
-
-void ThreadListModel::applyMessageTagChange(const QString &messageId,
- const QStringList &added,
- const QStringList &removed)
-{
- const auto retag = [&added, &removed](QStringList *tags) {
- for (const QString &tag : removed)
- tags->removeAll(tag);
- for (const QString &tag : added) {
- if (!tags->contains(tag))
- tags->append(tag);
- }
- };
-
- for (int row = 0; row < m_threads.size(); ++row) {
- ThreadNode &node = m_threads[row];
- bool touched = false;
-
- // `first` is a copy of the opening message rather than an alias into
- // children, so both have to be updated when they name the same one.
- if (node.first.messageId == messageId) {
- retag(&node.first.tags);
- touched = true;
- }
-
- for (int child = 0; child < node.children.size(); ++child) {
- if (node.children.at(child).messageId != messageId)
- continue;
- retag(&node.children[child].tags);
- touched = true;
- const QModelIndex childIndex = index(child, 0, index(row, 0));
- emit dataChanged(childIndex, childIndex);
- }
-
- // The thread has not been expanded and does not open with this
- // message, so nothing here holds it. The summary may still need to
- // follow, which the totalCount check below decides.
- if (!touched && node.summary.firstMessageId != messageId
- && node.summary.totalCount > 1) {
- continue;
- }
-
- // The thread's own tags follow only when the answer is unambiguous.
- //
- // A thread carries `unread` while ANY of its messages does, so a
- // one-message change can only clear it from the thread when there is
- // nothing else left to carry it. With one message in the thread that
- // is certain. With more, the honest answer needs every message's tags,
- // which are only loaded once the thread has been expanded; until then
- // the summary is left alone rather than guessed at, and the next query
- // corrects it.
- const bool wholeThread =
- node.summary.totalCount <= 1
- || (!node.children.isEmpty()
- && node.children.size() >= node.summary.totalCount);
- if (!wholeThread) {
- if (touched)
- emit dataChanged(index(row, 0), index(row, 0));
- continue;
- }
-
- for (const QString &tag : removed) {
- bool stillHeld = false;
- for (const MessageNode &child : node.children) {
- if (child.messageId != messageId && child.tags.contains(tag)) {
- stillHeld = true;
- break;
- }
- }
- if (!stillHeld)
- node.summary.tags.removeAll(tag);
- }
- for (const QString &tag : added) {
- if (!node.summary.tags.contains(tag))
- node.summary.tags.append(tag);
- }
-
- emit dataChanged(index(row, 0), index(row, 0));
- return;
- }
-}