Repository navigation
feat(clipboard): clear only the filtered entries - #3235
Conversation
With a search query or type filter active, the clear button deleted every unpinned entry regardless of what the list was showing, so pruning a subset meant deleting entries one by one from the context menu. When the recents list is filtered, the button now clears exactly the entries it shows and the modal stays open on that filter; with no filter the previous behaviour is untouched. A filter that matches nothing does nothing at all, rather than falling back to clearing everything. The tooltip says "Clear Filtered" while a filter is active, and the confirmation names the count. Deleting one id at a time would have cost a round trip and a full state broadcast per entry, so this adds clipboard.deleteEntries: one bolt transaction, one state update, and it skips pinned entries server-side so a bulk delete can never take out saved items. Fixes duxlabs-dev#3198
|
/claude review |
| iconSize: Theme.iconSize | ||
| iconColor: Theme.surfaceText | ||
| tooltipText: I18n.tr("Clear All") | ||
| tooltipText: header.clearsFilteredOnly ? I18n.tr("Clear Filtered") : I18n.tr("Clear All") |
There was a problem hiding this comment.
New user-facing strings need translator context per CONTRIBUTING (I18n.tr("...", "<context>")). Both strings this PR adds are missing it: "Clear Filtered" here, and "This will delete the %1 entries matching the current filter. Pinned entries are kept." in ClipboardHistoryContent.qml:150. Without context POEditor shows translators the bare string, and "Clear Filtered" is ambiguous out of context (verb vs. adjective).
| tooltipText: header.clearsFilteredOnly ? I18n.tr("Clear Filtered") : I18n.tr("Clear All") | |
| tooltipText: header.clearsFilteredOnly ? I18n.tr("Clear Filtered", "Clipboard history clear button tooltip when a search or type filter is active") : I18n.tr("Clear All") |
| handleGetEntry(conn, req, m) | ||
| case "clipboard.deleteEntry": | ||
| handleDeleteEntry(conn, req, m) | ||
| case "clipboard.deleteEntries": |
There was a problem hiding this comment.
The new method isn't listed in the IPC help output. core/internal/server/server.go enumerates every clipboard method (clipboard.getState … clipboard.subscribe, around line 1496-1506); clipboard.deleteEntries should be added there next to clipboard.deleteEntry, otherwise dms ipc help silently omits it.
log.Info(" clipboard.deleteEntries - Delete multiple entries by ID, skipping pinned (params: ids)")
Claude reviewSolid change — the server-side pinned skip, the empty-filter guard, and the single-transaction bulk delete are all the right calls. Two minor points.
Checked: |
…help Review follow-up. The two strings this branch adds carried no translator context: the "Clear Filtered" tooltip in ClipboardHeader and the confirmation body for a filtered clear in ClipboardHistoryContent. Both now say where they appear, and the second one names what %1 is, per CONTRIBUTING. "Clear All" on the same line is deliberately left alone. It is an existing shared term with four other call sites, so a context there would attach a clipboard-specific comment to a term the printer tab also uses. clipboard.deleteEntries was handled but absent from the IPC method listing that `dms debug-srv` prints, which left it undiscoverable right next to clipboard.deleteEntry. Catalogs untouched.
|
Both points are addressed in Translator context — added to the two strings this PR introduces, in the style CONTRIBUTING documents:
I left IPC help listing — That is the only static method listing I found; Verified: |
|
/claude review |
Claude reviewNo issues found. The two points from the previous run (translator context on the new strings, Checked: |
|
@bbedward heads up on the red What dies is
Which means whether it faults is a property of the process memory layout, not of the code under test. Two things point that way: the bogus pgid is byte-identical across runs ( This PR inserts six test functions into For what it's worth, the tests this PR adds all pass; the binary dies further down the run, after they've gone green. Happy to send a separate PR against master for it. Options as I see them:
First option is the smallest and still covers what #3232 was about. Tell me which you'd rather have and I'll open it. |
Description
The clear button in the clipboard modal deleted every unpinned entry regardless of the active search query or type filter, so pruning a subset meant deleting entries one at a time from the context menu (#3198).
Behaviour
all— the button clears exactly the entries the list is showing, and the modal stays open on that filter so the next one can be worked through.Shift+Deltakes the same path.Why a new IPC method. Deleting the filtered ids one at a time would cost a round trip and a full clipboard state broadcast per entry.
clipboard.deleteEntriesdoes it in one bolt transaction with a singleupdateState/notifySubscribers, and returns how many rows it removed. It skips pinned entries server-side: the UI never sends a pinned id, but a bulk delete should not be able to take out saved items.New strings:
Clear Filteredand the confirmation sentence. The term freeze is currently inactive (term_freeze.jsonabsent) andcheck_term_variants.pyreports no case or punctuation duplicates against the existing catalog. Catalogs are left alone per CONTRIBUTING.Type of change
Related issues
Fixes #3198
Screenshots / video
Six entries, one pinned.
Filtered to
TREFFER— two of six match:The confirmation names the count:
After confirming, the modal stays open on the filter and the other four entries survive:
With no filter the dialog is unchanged:
Checklist
I18n.tr(), reusing existing terms where possible (the dialog title reusesClear History?)make fmt, added tests,make testpasses,go mod tidyis cleandms clCLI, which this PR does not change, and the modal's clear button is not described there today. Say the word and I will add a section.How this was verified
Six new Go tests in
internal/server/clipboard: deletes the requested ids and keeps the rest, skips pinned, ignores unknown ids, empty list is a no-op, the handler reports the deleted count, and five malformedidsshapes are rejected without touching the store.go test ./...passes for the whole core.End to end: the built
dmsrunning against this working tree in a nested Hyprland session on its own XDG dirs. Populated six entries, pinned one, filtered, cleared, and checked the result withdms cl history— the two matching entries gone, the other four including the pinned one intact. Then filtered to a term that only the pinned entry matches and pressedShift+Del: no dialog, nothing deleted. Then cleared with no filter: only the pinned entry left, modal closed, as before.make lint-qmlneeds the Quickshell tooling VFS (.qmlls.ini), which this machine does not generate outside a full DMS install, so the touched QML was checked with Qt 6qmllintdirectly — no errors beyond the pre-existing unresolved-import warnings.