Skip to content

fix(ui): roll back refused actions, own background work, unify dialogs - #191

Merged
mrsibe merged 2 commits into
mainfrom
fix/interaction-lifecycle-cleanup
Sep 30, 2026
Merged

mrsibe merged 2 commits into
mainfrom
fix/interaction-lifecycle-cleanup

Conversation

@mrsibe

@mrsibe mrsibe commented Sep 30, 2026 •

Copy link
Copy Markdown
Owner

What does this PR do?

Fixes a group of interaction/lifecycle bugs that share one shape: a UI surface
kept state that no longer matched what the main process had actually done. It
also consolidates the duplicated confirmation dialogs and replaces the last
native alert()s.

This is cleanup on top of the worker + background-ingestion work (#176), not a
change to that architecture.

Why?

  • continueMessage() marked the message pending and registered the live turn
    before the IPC. Main refuses past the continuation bound, and the invoke can
    reject as well — either left the message showing "generating" forever.
  • SettingsDialog only seeded pendingSettings / pendingConnections on
    mount, and X / Esc / overlay closed it without discarding them, so unsaved
    edits came back on reopen.
  • File imports were moved to the background queue, but refreshAfterImport
    still cleared isIndexing, so the top progress vanished while embedding was
    still running. URL / pasted text / notes still blocked their dialog for the
    whole index, which made them inconsistent with file imports.
  • Confirmation dialogs were four near-copies split across Dialog and
    AlertDialog; a few native alert()s disagreed with the global Sonner style;
    and the Quiz / Anki config dialogs disagreed on reset-on-close.

What changed?

  • chat: roll back the optimistic continue state (turn, message status,
    streaming pointer, assembler, sequence) when Main refuses or the invoke
    rejects.
  • settings: route every close path through one handleClose() that discards
    pending settings/connections; add the Radix DialogTitle /
    DialogDescription.
  • knowledge: replace isIndexing + indexProgress with indexingJobs
    keyed by documentId, fed by per-document progress broadcasts.
    refreshAfterImport no longer clears the queue, and the top bar shows
    "Indexing N sources · X%".
  • knowledge: URL, pasted text and notes now register a pending source and
    index in the background queue like file imports; the Add Source dialog only
    tracks the short isSubmitting registration.
  • dialogs: collapse ConfirmDialog, DeleteConfirmDialog,
    DeleteNoteConfirmDialog and UnsavedChangesDialog into one
    ConfirmActionDialog on AlertDialog; replace the remaining native
    alert() with Sonner; Quiz / Anki config discard input on close and reset on
    submit.
  • floating layers: dismiss the session switcher and the library Add menu on
    an outside press via a document listener. The full-viewport overlays lost to
    sibling position: relative cards, and the one inside a
    -webkit-app-region: drag header had its clicks eaten by window dragging.
  • chat: inset the bottom scroll fade by the scrollbar track so it no longer
    paints over the scrollbar.
  • scroll area: override Radix's inner display: table wrapper to block,
    so a truncate list row can no longer outgrow the viewport and cover the
    library's right padding at the panel's minimum width.

How was this tested?

  • The repo's Verify workflow runs npm run typecheck, npm run check:design,
    npm test (478/478), npm run build:unpack and npm run smoke:packaged on
    Ubuntu, macOS and Windows.
  • Manual: continue-generation refusal, Settings close/reopen with unsaved edits,
    background file-import progress, URL / text / note import, outside-click
    dismissal of the session switcher and the library menu, and the library at its
    260px minimum width.

Screenshots / recordings

Not captured in this environment; the affected surfaces are the chat panel, the
Settings dialog, the library list/menu and the session switcher.

Checklist

  • I have reviewed my own changes.
  • npm run typecheck passes.
  • npm run build passes.
  • I have tested the affected user workflow.
  • I have not included unrelated changes.
  • I have updated documentation when necessary.

Desktop / build changes

  • Not applicable

Several surfaces held state that no longer matched what the main process had
actually done, or kept it past the point where it was meaningful.

- chat: `continueMessage` set the message to `pending` and registered the live
  turn before the IPC. A `continuation-limit` refusal left it spinning forever;
  roll the optimistic state back on refusal or a rejected invoke.
- settings: X / Esc / overlay closed without discarding `pendingSettings` /
  `pendingConnections`, so unsaved edits reappeared on reopen. Route every close
  through one `handleClose`, and give the dialog the Radix title/description.
- knowledge: replace the single `isIndexing` + `indexProgress` with
  `indexingJobs` keyed by documentId and fed by per-document progress. Refreshing
  after an import no longer clears the queue, so the top progress stays up for
  the whole background index.
- knowledge: URL, pasted text and notes now register a `pending` source and index
  in the background like file imports; the Add Source dialog only tracks the
  short `isSubmitting` registration.
- dialogs: collapse `ConfirmDialog`, `DeleteConfirmDialog`,
  `DeleteNoteConfirmDialog` and `UnsavedChangesDialog` into one
  `ConfirmActionDialog` on `AlertDialog`. Replace the remaining native `alert()`
  with Sonner, and make Quiz/Anki config close-on-cancel discard temporary input.
- floating panels: dismiss the session switcher and the library add menu on an
  outside press via a document listener. The full-viewport overlays lost to
  sibling `position: relative` cards, and the one inside a
  `-webkit-app-region: drag` header had its clicks eaten by window dragging.
- chat: inset the bottom scroll fade by the scrollbar track so it no longer
  paints over the scrollbar.
Radix wraps a ScrollArea's children in an inner `min-width: 100%;
display: table` box. A table shrink-wraps to its content's min-content width,
so a `truncate` row with a fixed-width control beside it (the library's
document row and its overflow menu) makes that box wider than the viewport
once the panel reaches its 260px minimum. The row then runs past the list's
`p-2` and out to the viewport edge, so the right padding disappears under the
item and the scrollbar.

Force the wrapper back to a normal block in the shared ScrollArea, which
constrains children to the viewport again. The `!` is needed because Radix
writes both properties inline. Horizontal table scroll areas are unaffected:
a block wrapper is still 100% wide and the wider table overflows it, so the
scroll width and the horizontal bar are the same.
@mrsibe mrsibe changed the title Fix/interaction lifecycle cleanup fix: interaction lifecycle cleanup Sep 30, 2026
@github-actions github-actions Bot added the bug Something isn't working label Sep 30, 2026
@mrsibe mrsibe changed the title fix: interaction lifecycle cleanup fix(ui): roll back refused actions, own background work, unify dialogs Sep 30, 2026
@mrsibe
mrsibe merged commit 4171dbd into main Sep 30, 2026
6 checks passed
@mrsibe
mrsibe deleted the fix/interaction-lifecycle-cleanup branch September 30, 2026 08:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant