aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-19 10:27:02 +0200
committerDanilo M. <danix@danix.xyz>2026-08-19 10:27:02 +0200
commit2e0db925d5ca7100d8405ffc352ae435cdbdb73d (patch)
tree4d10cc671d1ed994b23263e80bdbc1c77c8df330 /src
parent6de81918dc7a9342fb532d6a5542c868ff65826c (diff)
downloadqtmaildir-2e0db925d5ca7100d8405ffc352ae435cdbdb73d.tar.gz
qtmaildir-2e0db925d5ca7100d8405ffc352ae435cdbdb73d.zip
fix(trash): refresh the list when a restore empties a rowdelete-to-trash
Reported from a hand test: Restore moved the message correctly and the row it came from sat in the trash list until the Trash filter was clicked again. The trash view is path-based, so a restored message stops matching the query the list was built from. That is a state no tag change can express, and nothing in onMessagesMoved() removes a row, deliberately: in an ordinary view a deleted message's card should stay put, since one deleted message does not doom the conversation. refreshCurrentQuery(), not runCurrentQuery(). The refresh runs immediately after the undo entry is pushed, and re-running the query outright clears the undo stack, which would make Restore the one mutation in the window with no way back. Gated on isShowingTrash() rather than on the destination, because a Delete is a move too and reaches the same slot. Three tests, each catching a different mutation: the row leaves, undo survives the refresh and still moves the file back, and a delete outside the trash view leaves its row alone. The third one was wrong on its first draft and passed against the mutation it existed to catch. It used a `tag:inbox` view, which looks ordinary but which a deleted message keeps matching, since Delete adds `deleted` and the origin tag and removes nothing. A path query on the inbox folder is the honest instrument: the file really leaves, so the row survives only because nothing refreshed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'src')
-rw-r--r--src/mainwindow.cpp23
1 files changed, 23 insertions, 0 deletions
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index a1c01c3..58c82ca 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -4982,6 +4982,29 @@ void MainWindow::onMessagesMoved(const QMap<QString, QString> &originByMessageId
}
}
+ // A restore out of the TRASH VIEW leaves the row it came from showing a
+ // message that is no longer there, and only a refresh can say so.
+ //
+ // Reported from a hand test: the move was correct and the row sat in the
+ // list until the Trash filter was clicked again. The trash view is PATH
+ // based, so a restored message stops matching the query the list was built
+ // from, which is a state no tag change can express. Nothing else here
+ // removes a row, deliberately: in an ordinary view a deleted message's
+ // card should stay put, since one deleted reply does not doom the
+ // conversation.
+ //
+ // refreshCurrentQuery() rather than runCurrentQuery(): it clears nothing,
+ // so the selection, the expanded threads, the undo stack and the message
+ // being read all survive. Re-running the query outright would destroy the
+ // undo entry this function just pushed, which is the one thing a restore
+ // must leave intact.
+ //
+ // Gated on isShowingTrash() and not on the destination: a Delete is a move
+ // too and reaches this same slot, and refreshing after every delete would
+ // make a row vanish from under the user in every other view.
+ if (isShowingTrash())
+ refreshCurrentQuery();
+
// The undo entries are pushed inside the loop above, one per origin
// group, because the placeholder resolves per origin. Nothing is pushed
// for a move the undo stack itself started: a MoveCommand is confirmed