Skip to content

feat(web): add toggleable confirmation before unpinning a thread - #7313

Merged
shivamhwp merged 14 commits into
pingdotgg:mainfrom
UtkarshUsername:fix/add-unpin-confirmation
Aug 28, 2026
Merged

shivamhwp merged 14 commits into
pingdotgg:mainfrom
UtkarshUsername:fix/add-unpin-confirmation

fix(web): confirm every thread unpin path

08c0935
Select commit
Loading
Failed to load commit list.
MacroscopeApp / Macroscope - UI Consistency succeeded Aug 28, 2026 in 2m 8s

UI Consistency: No issues found

All clear

Details

Note

Your check run agent prompt is: .macroscope/check-run-agents/ui-consistency.md
More information about how Check Run Agents work can be found in our Help Center.

Reviewed the in-scope web UI changes (apps/web/src/hooks/useThreadActions.ts, useThreadActionMenu.ts, components/Sidebar.tsx, components/ChatView.tsx, components/settings/SettingsPanels.tsx, components/settings/settingsSearch.ts).

Both findings from earlier runs are resolved at head 08c0935:

  • requestThreadUnpinConfirmation now degrades like confirmAndDeleteThread — it falls back to resolved?.thread.title ?? "this thread" and skips only the dialog when the local api is unavailable, so the preference can no longer produce a dead click.
  • "Unpin confirmation" is included in changedSettingLabels (and its dependency array) alongside the reset in restoreDefaults, and the unpin-confirmation catalog entry now precedes archive-confirmation/delete-confirmation, matching the rendered panel order.

Other checks: all web unpin dispatch sites (sidebar pin marker, sidebar context menu, chat header action menu, mod+shift+p shortcut) route through confirmAndUnpinThread; the new settings row composes the shared SettingsRow/Switch/SettingResetButton primitives with an aria-label consistent with its neighbors; no Tailwind/global CSS, scroll/mask, or environment-routing surfaces were touched.


🔍 Agent activity — 15 tool calls

💭 I'm checking the current PR state at commit 08c0935 to see if prior review findings were addressed, looking specifically at the settings search test ordering and the catalog entry placement, plus whether the thread unpin confirmation now degrades gracefully.

1. browse_code — apps/web/src/components/settings/settingsSearch.ts

2. browse_code — apps/web/src/hooks/useThreadActions.ts

💭 I want to confirm the row ordering matches between the catalog and settings panels, so I'm checking SettingsPanels around lines 2300-2400 to verify unpin sits above archive/delete there too.

3. browse_code — apps/web/src/components/settings/SettingsPanels.tsx

4. browse_code — apps/web/src/components/settings/SettingsPanels.tsx

💭 With both prior findings resolved, I want to compare confirmAndUnpinThread against the confirmAndDeleteThread pattern around line 600-680, and verify the ChatView keyboard shortcut path handles cancellation correctly by returning success(undefined) with no toast, matching the Sidebar's unpin behavior. I should also check whether the dialog uses a "destructive" variant and whether it relies on a shared confirmation helper like localApi.dialogs.confirm, plus whether there's a separate inline "confirmThreadArchive" pattern that uses a second-click instead of a dialog. I'll scan useThreadActions from lines 400-780 to compare these approaches.

5. browse_code — apps/web/src/hooks/useThreadActions.ts

💭 The delete pattern now matches, so I'm moving on to check other call sites for consistency—like the mod+shift+p shortcut in ChatView, which uses confirmAndUnpinThread correctly, and now I want to check the sidebar's unpin control to see if it's an inline hover action or something else, plus look for any other unpinThread call sites that might've been missed. I should grep for unpinThread across apps/web to catch any pinned section headers, drag-out gestures, or context menus that might not be migrated, which would create inconsistent confirmation behavior.

6. git_tools — unpinThread|confirmAndUnpinThread|unpin

💭 I noticed the sidebar has a pin marker button that can unpin threads when the server supports pinning, so I should check the relevant sidebar code sections around lines 700-780, 2600-2730, and 3190-3210 to trace all the unpin paths.

7. browse_code — apps/web/src/components/Sidebar.tsx

8. browse_code — apps/web/src/components/Sidebar.tsx

💭 I'm checking the pin marker button in SidebarThreadRow to see if it shows a pending state, then looking at the bulk unpin case in the multi-select actions to see how that path handles it.

9. browse_code — apps/web/src/components/Sidebar.tsx

10. browse_code — apps/web/src/hooks/useThreadActionMenu.ts

💭 I notice the unpin case now calls confirmAndUnpinThread from the native context menu, and the added braces around that case are harmless. The archive/delete confirmations still use the native dialog API separately, which seems fine. Now I'm checking consistency questions: delete uses a destructive variant while archive and unpin don't, which seems intentional given their severity. I want to verify whether there's a bulk unpin action in the sidebar's multi-select toolbar, and whether the keyboard shortcut for toggling pin interacts correctly with the new confirmation dialog. I'm also confirming the settings row order matches the catalog and checking whether the ChatView header has a separate pin button (beyond the keyboard shortcut) that might not have been migrated to use the same confirmation flow.

11. git_tools — pinThread|pinned|togglePin

💭 With all the unpin call sites migrated, I'm double-checking the confirmation logic — verifying that both confirmAndUnpinThread and the delete flow correctly call the local API before confirming, and examining an edge case where requestThreadUnpinConfirmation returns success even when confirm is null. This mirrors delete's fallthrough behavior when confirmation is skipped, so it's consistent. I'm also confirming the settings row description text, aria-label, and that the unpin/archive/delete ordering matches the searchable settings catalog for the search feature, checking if keyword matching like "confirmation" or "quit" resolves correctly against titles.

12. browse_code — apps/web/src/components/settings/settingsSearch.ts

13. browse_code — apps/web/src/components/settings/settingsSearch.ts

💭 Everything looks consistent, so I'm checking if there's anything else in scope, like the sidebar pin marker's unpin path and whether the confirmation dialog interacts oddly with thread activation clicks—nothing new there. I'm now considering drag interactions next. I'm checking whether the module-scope imports and hook dependencies for the unpin confirmation flow are all correctly wired—settlePromise, AsyncResult, and the confirmAndUnpinThread dependency array all look complete. I notice the raw unpinThread export is no longer consumed externally after migration, but that's a minor dead-API concern rather than a UI consistency issue. Having both raw and confirming variants (unpinThread/confirmAndUnpinThread) actually mirrors the existing deleteThread/confirmAndDeleteThread pattern, where deleteThread is still used raw elsewhere, so this isn't worth flagging. The new SettingsRow uses SettingsRow, Switch, and SettingResetButton consistently with its neighbors, and the documented mod+shift+p shortcut matches ChatView's actual behavior. I'm now checking whether there's a separate pin toggle button in the chat header that might call a different, inconsistent handler. I should search more broadly for "Unpin" usage across other components like ThreadHeader, CommandPalette, or the keybindings registry, since my earlier grep only surfaced the context menu.

14. git_tools — [Uu]npin

15. git_tools — threadEnvironment.unpin

💭 All web call sites are covered, and mobile is out of scope. I checked the sidebar pin marker button code and confirmed it's unchanged, so no interaction regression there. Both prior findings were addressed, so I'm confident there's nothing new to report. Since the response requires the JSON schema, I'll set the status to success and put "All clear" in the summary field with a plain title, rather than trying to make the whole response just those two words.


Agent Credits: 88 credits

Token usage: 20 uncached input · 424,848 cache-read input · 70,728 cache-write input · 7,089 output
Agent Credits may also include non-token charges from external tools such as web research.