Skip to content

fix(mobile): the phone's host list never flashes a list shaped unlike the desktop's - #31301

Merged
Jinwoo-H merged 2 commits into
sidebar-flip-afrom
phone-host-list-first-frame
Oct 21, 2026
Merged

Jinwoo-H merged 2 commits into
sidebar-flip-afrom
phone-host-list-first-frame

Conversation

@Jinwoo-H

@Jinwoo-H Jinwoo-H commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​152 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​152
Prod 4 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​55 $\color{#cf222e}{\Huge{\mathbf{−}}}$​12 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​43

ELI5

When you opened a desktop's workspace list on the phone, a different list showed for a split second: no Pinned section, no project groups, no host badges, and a different order. Then it jumped to the real list. The phone now never draws a list that is shaped differently from the desktop's.

What Changed

  • Before: with the sidebar feed switched on, the list is built from the desktop's sidebar feed. Until the first feed read finished, the phone drew the rows from its older workspace query (worktree.ps) as one flat, unsorted list. That query usually answers first, so the flat list flashed before the real one.
  • After: until the feed arrives, the list shows the existing loading spinner. If this page already received the feed for that desktop earlier, it opens straight on that last copy, in the desktop's shape, and then updates when the fresh copy lands. The flat worktree.ps list is now used only for a desktop that has no feed (an older Orca), so that desktop still gets a list.
  • Mechanism: use-host-list-sections.ts draws the flat fallback only when the feed state is reopen (no feed, or a version this page can't read), no longer while it is loading. use-host-sidebar-feed.ts keeps each paired desktop's last installed feed in memory, capped at 20 desktops. It uses that copy until the fresh read installs, and forgets it when the desktop stops serving the feed. A remembered copy in a version this page can't read is skipped, so it never flashes "Reopen to update".

Why

The flash was the fallback list, so the only way to remove it is to not draw a list the desktop wouldn't draw. Alternatives considered:

  • Keep the fallback but sort and group it like the desktop. That copies the desktop's list rules onto the phone, which is the gap the feed exists to close, and it still can't match pins, groups and badges exactly.
  • Save the feed to the phone's storage, so even the first open after a restart draws the list. That adds a storage format and stale-data rules for a small gain. A spinner on a cold open is honest, and the in-memory copy covers reopening within the same page.

Offline (desktop unreachable): before the first feed, the list shows the spinner and the header shows the connection status, which is what the list already did when it had no rows. A desktop seen earlier in this page shows its last known list.

With the switch off, the phone builds its own grouped and pinned list from worktree.ps and never draws the flat fallback. This flash is a regression introduced by turning the switch on.

Linked Issue

N/A (found by the owner on ad hoc candidate 7)

Visual Proof

N/A. The only visible change is that a one-frame wrong list is replaced by the spinner (or by the right list). Covered by the hook test below.

Testing

  • Automated tests added: mobile/src/host-screen/host-list-first-frame.test.tsx renders the feed hook and the list builder together with worktree.ps rows present.

    • Before the feed installs: nothing is drawn, then the desktop's list (Pinned first).
    • A reopen of the same desktop starts on its last installed feed.
    • One desktop's feed never opens another desktop's list.
    • An older desktop without the feed still lists worktree.ps rows.
    • A feed the desktop stopped serving is forgotten.

    On the base branch, the first-frame and other-desktop cases fail. Without the remembered feed, the reopen case fails.

  • Mobile typecheck, mobile tests, oxfmt, pnpm tc, and the static gate including both ratchets.

Review

Base: sidebar-flip-a. This leaves host-list-highlight.ts alone and changes one line in use-host-list-sections.ts, because a parallel highlight change touches that file.

Notes

Mixed versions: an older desktop without sidebarInputs.read still gets the worktree.ps list, with "Reopen to update". There is no wire change. SSH and remote-server rows come through the same feed, so they are unaffected.

… the desktop's

Before the host's sidebar feed installed, the feed-built list drew worktree.ps's rows flat:
no Pinned section, no project groups, no host badges, in another order, then snapped to the
desktop's list. It now waits for the feed (the loading spinner), or opens on the host's last
installed feed when this page has one. An older desktop without the feed still gets the
worktree.ps list.
@Jinwoo-H
Jinwoo-H merged commit e696ff6 into sidebar-flip-a Oct 21, 2026
28 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