Skip to content

Fix unsaved-edit loss on tab switch, editor indentation, Resource Browser search jitter - #123

Merged
Panthevm merged 3 commits into
masterfrom
fix/query-refetch-on-focus-discards-edits
Jul 29, 2026
Merged

Fix unsaved-edit loss on tab switch, editor indentation, Resource Browser search jitter#123
Panthevm merged 3 commits into
masterfrom
fix/query-refetch-on-focus-discards-edits

Conversation

@Panthevm

@Panthevm Panthevm commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Three independent fixes found while chasing the first one.

1. Returning to the browser tab discarded unsaved editor changes (cdd1d32)

QueryClient had no defaultOptions, so refetchOnWindowFocus was on and staleTime was 0: every visibilitychange refetched the resource query. A successful fetch always bumps dataUpdatedAt — even when the response is byte-identical — and ResourceEditorPage is keyed by `type/id@dataUpdatedAt` (ResourceEditor/page.tsx:124), so the page remounted and useState(initialResource) re-initialized from the server copy.

useUnsavedChangesBlocker cannot catch this: a remount is not a navigation, so no "Unsaved changes" dialog appears and isDirty dies with the component. Hitting Save afterwards wrote the rolled-back version back to Aidbox.

Fix: refetchOnWindowFocus: false and refetchOnReconnect: false on the QueryClient. Nothing overrides them to true, so the editor now remounts only where intended — after Save invalidates its query key.

2. Enter put the caret one indent level too deep (f1141d3 → submodule 484b967)

indentUnit in CodeEditor was "\t", so getIndentUnit() resolved to tabSize (4) while every document is pretty-printed with 2 spaces — JSON.stringify(x, null, 2), YAML.dump({indent: 2}). continuedIndent() asked for 4 columns and indentString() materialized them as a literal tab:

{
  "id": "fooo",
  "resourceType": "Patient",
    |                          <- caret after Enter: 4 columns, a tab

Fix: indentUnit.of(" "). Tab had the same problem via insertTab, which always inserts "\t" — invalid indentation in YAML — so it now uses indentMore, matching Enter and the existing Shift-Tab (indentLess).

The submodule change lives in aidbox-ts-sdk on development; this PR carries it as a gitlink bump 6e75111 → 484b967. Review the actual diff here: react-components: code-editor indent.

3. Resource Browser list jumped left and right while searching (c300492)

The scroll container is overflow-y-auto and everything inside is centered with mx-auto max-w-[990px]. Typing changes the virtualizer's total size, so around ~5 results the classic 8px scrollbar (from the ::-webkit-scrollbar rules in index.css) keeps appearing and disappearing. Each toggle resizes the content box by 8px and moves the centered column by 4px.

Fix: scrollbar-gutter: stable on the scroll container.

Verification

pnpm typecheck, biome check, vite build, plus lint:check/tsc:check in react-components — all clean. Confirmed scrollbar-gutter:stable and indentUnit.of(" ") land in the production bundle. Submodule development is pushed, so the gitlink resolves. Not verified in a browser.

Panthevm added 3 commits July 29, 2026 17:56
Returning to the browser tab silently discarded unsaved editor changes.
The QueryClient had no defaultOptions, so refetchOnWindowFocus was on and
staleTime was 0: every visibilitychange refetched the resource query.
A successful fetch always bumps dataUpdatedAt, even when the response is
byte-identical, and ResourceEditorPage is keyed by `type/id@dataUpdatedAt`
— so the page remounted and useState(initialResource) re-initialized from
the server copy. useUnsavedChangesBlocker cannot catch this: a remount is
not a navigation. Hitting Save afterwards wrote the rolled-back version
back to Aidbox.

Turn both automatic refetches off globally. Nothing overrides them to
true, so the editor now remounts only where it was intended to — after
Save invalidates its query key.
Picks up react-components 484b967: the editor's indentUnit was a tab, so
auto-indent produced 4 columns against content pretty-printed with 2
spaces — Enter inside a JSON object left the caret one level too deep.
Tab now uses indentMore instead of inserting a literal "\t", which is
invalid indentation in YAML.
…he list

The scroll container is overflow-y-auto and everything inside it is
centered with `mx-auto max-w-[990px]`. Typing changes the virtualizer's
total size, so around ~5 results the classic 8px scrollbar (from the
::-webkit-scrollbar rules in index.css) keeps appearing and disappearing.
Each toggle resizes the content box by 8px and moves the centered column
by 4px, which reads as the list jumping left and right while searching.

scrollbar-gutter: stable reserves the gutter in both states.
@Panthevm
Panthevm merged commit 46b53a5 into master Jul 29, 2026
4 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant