Skip to content

fix: stop table and sidebar flashing unsorted order on open - #1290

Merged
joepio merged 10 commits into
developfrom
cursor/fix-table-open-order-flash-2039
Aug 20, 2026
Merged

fix: stop table and sidebar flashing unsorted order on open#1290
joepio merged 10 commits into
developfrom
cursor/fix-table-open-order-flash-2039

Conversation

@joepio

@joepio joepio commented Aug 19, 2026

Copy link
Copy Markdown
Member

Related Issues

Fixes table/sidebar content flashing in the wrong order when opening a filled table.

What changed

Opening a filled table (and the sidebar tree) flashed as if row/column order changed. Two independent flashes:

  1. Grid/sidebar collection: WASM parent= queries are unsorted. Hydrating each member notified ResourceUpdated, and applyResourceChange optimistic-added members in arrival order before client-side sort landed setPage.
  2. Sidebar children of a table: useChildren ran while isA was still unknown (allowIncomplete), so every table row appeared, then vanished when the class arrived.
  3. OPFS array shuffle: JSON-AD hydration seeded a new LoroList per array, then merged the stored snapshot (concurrent lists). requires/recommends (columns) and isA could shuffle.

E2E follow-up

Rebased onto current develop (5b4ab185, light Playwright @smoke gate). The kanban persist test keeps its @smoke tag.

Earlier CI failed aggregates.spec.ts (sum stayed at 5 after editing Hours 3→4) and table-refresh.spec.ts (title missing after reload). Those now pass:

  • Reload stuck loading: importLoroUpdate(..., true) pointed getLoroDoc() at the OPFS snapshot then imported the same bytes again, which could drop isA and leave loading true. Import once. Skip replace over unsaved in-memory edits.
  • Stale totals: outbox drain fired ResourceSaved before queueing the OPFS put, so the totals query could run against the pre-edit index and never retry. Persist first; totals re-query immediately on save. Scope the query to the current drive.
  • table-refresh: the typed-reload test now recovers ErrorPage / still-loading the same way the sibling tests in that file already do.

Kanban persist-after-reload race:

  • Drag keeps a visual preview until set() writes the Status tag. Reloading off that preview left OPFS on Todo.
  • Wait until the card lists the Doing column's data-kanban-column-id, then drain the outbox and flush OPFS inside reloadReconnected before reload.
  • Tables fast-entry and offline-create use the same 30s drain budget as waitForSynced.

Checklist

  • Add changelog entry linking to issue, describe API changes
  • Add or update tests if needed
  • Update docs if needed
Open in Web Open in Cursor 

@cursor cursor Bot changed the title Fix table and sidebar content flashing in the wrong order on open fix: stop table and sidebar flashing unsorted order on open Aug 20, 2026
@cursor
cursor Bot force-pushed the cursor/fix-table-open-order-flash-2039 branch 2 times, most recently from b246eb6 to 0ce06aa Compare August 20, 2026 11:30
cursoragent and others added 10 commits August 20, 2026 13:03
JSON-AD hydration seeded a new LoroList per array, then OPFS merged the
stored snapshot as a concurrent list. That shuffled requires/recommends
(table columns) and isA on open. Write arrays in place and import
authoritative OPFS snapshots with replace.

Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
…bles

WASM parent= queries are unsorted. Hydrating each member notified
ResourceUpdated, and useCollection optimistic-added them in arrival
order before client-side sort wrote the page. Skip those adds during
hydrate/sort/setPage, treat missing sort keys as missing, and fall back
to getCreatedAt for sortOrder/createdAt.

Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
ResourceSideBar fetched useChildren while isA was still empty, so every
table row appeared in the sidebar until the class arrived and hid them.
Treat unknown class as hide-children. Hold the table row query until
classtype is known so views do not flash as rows.

Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
Raw createdAt propvals can be seconds or missing after hydrate. Use
Resource.getCreatedAt so folder order matches the collection fallback
and does not jump when the timestamp unit lands.

Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
Add a changelog note and a TESTING_COVERAGE guard pointing at
collection-page-assemble.test.ts and the OPFS array-order test.

Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
replace=true pointed getLoroDoc at the snapshot then imported it again,
which could drop isA and leave the resource stuck loading after reload.
Import once, and queue the OPFS put before ResourceSaved so totals
queries land behind the write on the worker.

Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
ResourceSaved now triggers an immediate totals query (the persist is
already queued) plus the existing debounce. Scope the query to the
current drive so extra isA filters hit the local index. Table-refresh
recovers ErrorPage / still-loading the same way the sibling tests do.

Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
Kanban drag shows a preview before set()/save finish. Reloading in that
window left OPFS on the old status, so the persist test failed after
reload. Wait for the Doing tag, then drain and flush OPFS inside
reloadReconnected.

Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
waitForCardTag looked up the Doing tag's name in the store; that resource
is often not loaded, so the persist test timed out before reload. Wait
for the card to list the column's data-kanban-column-id instead.

Give tables fast-entry and offline-create the same 30s drain budget
waitForSynced already uses — 15s is tight for 40 (or 4 genesis) commits
under dagger load.

Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
@cursor
cursor Bot force-pushed the cursor/fix-table-open-order-flash-2039 branch from 0ce06aa to 7a3a363 Compare August 20, 2026 13:03
@joepio
joepio marked this pull request as ready for review August 20, 2026 13:35
@joepio
joepio merged commit 053adcc into develop Aug 20, 2026
6 checks passed
@joepio
joepio deleted the cursor/fix-table-open-order-flash-2039 branch August 20, 2026 13:35

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is ON, but it could not run because the branch was deleted or merged before autofix could start.

Reviewed by Cursor Bugbot for commit 7a3a363. Configure here.

viewGroupGranularity,
derivedSpecs,
),
drive: store.getDrive(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totals query ignores class gate

Medium Severity

The grid now holds its parent= query until classtype is known so views do not flash as rows, but useTableAggregates still runs immediately with value set to the table subject and queryFilters that omit isA until class arrives. Totals therefore cover views and other non-row children while the grid shows no rows (or a later class-filtered set). Count and similar aggregates can disagree with the table for that window, which is the same open path this PR is fixing.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7a3a363. Configure here.

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.

2 participants