From 978c9b51935f8597ce307166bfba29368bd4fc23 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Fri, 28 Aug 2026 12:33:52 +0200 Subject: feat: scope an action to the row it was invoked on The five *_thread actions and their submenu are gone: the row's identity is what decides the scope, so a second set of actions was a second answer to a settled question. mark_thread_unread went with them, being the sixth entry in the same submenu. tagSelected() loses its TagScope parameter, and everySelectedRowHasTag() its own, so the direction and the write ask the same question of the same object. ThreadListModel::scopeFor() and messageScopeFor() are deleted; scopeForSelection() is the one resolver. Labels name the scope. Archive, Delete, Restore, Spam, Important and the unread toggle all say "thread" on a conversation row, and Delete, Restore and Archive are ABSENT on a reply: a single reply cannot be removed from a conversation. Compose follows the same rule. Forward, Save, Reply-all and Reply without quoting disappear on a conversation row, which shows no message to act on, and Reply becomes "Reply to this thread": reply-all, quoting nothing, threaded off the conversation's NEWEST message so the answer lands at its end rather than forking the discussion at its opening post. That id is not in the model, since an unexpanded conversation holds no nodes for its replies, so it comes from resolveThreadMessages(); resolveQuery() states its newest-first sort rather than inheriting notmuch's default. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012iDeN6C7y97nHYPvP6ST4L --- src/notmuchworker.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/notmuchworker.cpp') diff --git a/src/notmuchworker.cpp b/src/notmuchworker.cpp index 1f28973..9fb3e4d 100644 --- a/src/notmuchworker.cpp +++ b/src/notmuchworker.cpp @@ -1326,6 +1326,13 @@ void NotmuchWorker::resolveQuery(const QString &query, return; } + // Stated rather than inherited. notmuch's default already is newest-first, + // and the move and restore callers do not care about the order at all, but + // "reply to this thread" reads the FIRST id as the conversation's newest + // message: an unstated default is not something a reply's threading + // headers should rest on. + notmuch_query_set_sort(nmQuery.get(), NOTMUCH_SORT_NEWEST_FIRST); + notmuch_messages_t *raw = nullptr; if (notmuch_query_search_messages(nmQuery.get(), &raw) != NOTMUCH_STATUS_SUCCESS) { -- cgit v1.2.3