From 7074a4c57343777fe08f5cdd3174563a46007484 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Sun, 6 Sep 2026 15:07:35 +0200 Subject: fix: give the Sent and Drafts views one row per message, in date order Both views are lists of the user's own messages and are flat, but walkThreads() emitted one ThreadSummary per THREAD and then picked a single matched message to stand for it, breaking at the first one the oldest-first walk reached. A conversation replied to twice therefore produced one row: dated by the thread, opening the OLDER of the two messages, with the newer one reachable nowhere in the view. Reported against real mail, where a message sent at 12:42 was missing while the row above it, dated 12:42, opened a message from three weeks earlier. The same wrongly chosen message supplied firstMessagePath, so Delete or Archive on such a row would have moved a file the user was not looking at, silently, and mbsync would have carried it to the server. That half was never visible. The Sent branch now emits one summary per matched message, each carrying its own id, tags, sender, path, date and subject. withRecipients still selects the branch, so Sent and Drafts both get this and no second flag can disagree with the flat-mode flag. Ordering was a second defect under the same item, found by hand once the rows appeared: notmuch_query_set_sort is a THREAD sort, so every row of a thread inherits that thread's single position and an older reply drew above a newer one. Sorting each thread's rows in place is not enough either, since a message from another thread dated between them still cannot land between them. Flat rows are collected and sorted as one list before emitting. ThreadListModel::rowKeyFor() is the second consequence and would have broken quietly: two rows now share a threadId, and reconcile() keyed its QHash on exactly that, so a sync would have dropped one of them by a different route. It answers what makes a row unique, the message id in flat mode and the thread id otherwise. Tests cover both halves over new fixture threads F and G. The cross-thread ordering assertion passed for the wrong reason at first, because the existing fixture threads happen not to interleave; thread G exists to break that and failed the moment it was added. oldestFirstReversesTheOrder is corrected rather than satisfied: OLDEST_FIRST orders threads by their oldest message while NEWEST_FIRST orders by their newest, so the two lists mirror each other only while no thread's date span contains another's, which this fixture is the first to violate. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Jq9gXquUo9W4KXDagJXMmn --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'CHANGELOG.md') diff --git a/CHANGELOG.md b/CHANGELOG.md index 73e938e..2749e0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,16 @@ point at which they are stable. ### Fixed +- **The Sent and Drafts views show every message you sent in a conversation, + not just the first.** Both views are lists of your own messages rather than + of conversations, but a thread you had replied to twice produced a single + row: it was dated by the conversation, opened the OLDER of your two + messages, and the newer one could not be reached from the view at all. Each + matched message is now its own row, carrying its own date, subject, tags and + sender, and the view is ordered by those dates rather than by the dates of + the conversations behind them. This also fixes a quieter problem on the same + rows, where Delete or Archive would have acted on the wrong message's file. + - **A background sync now clears only the accounts it actually carried.** A sync qtmaildir did not start could only be judged from the log, which cannot say which accounts a run covered, so a successful run cleared the pending -- cgit v1.2.3