You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is the follow-up to #559. The point of this pass was to catch the things users usually find first: the second quick click, the stale browser tab, the narrow screen, the shared folder after reload, and the site with enough content to make a visualization fall over.
I updated to current origin/trunk (c670170) before the final verification pass, then replayed every candidate from the older checkout. Anything already fixed upstream was removed from this issue.
The bugs below still reproduce on current trunk. The two settings problems are the most urgent because OpenStation tells the user everything is saved while silently keeping the wrong value. Screenshot evidence is attached in the first comment.
1. A quick second toggle in Extended Options is silently lost
Why this matters: The control ends in one state, the server saves the opposite state, and the user is not told anything went wrong.
To reproduce:
Open OpenStation Preferences → Features as an administrator.
Toggle Enable drag-and-drop in the Media Library off and immediately back on while the first save is still running.
The checkbox finishes enabled.
Reload or read desktop-mode/v1/extended-options; the server persisted disabled.
The save function returns early while a request is in flight, but the still-enabled control keeps accepting changes and never queues a trailing save.
Where to look:src/settings/sections/extended.ts
2. Two open sessions can overwrite each other’s unrelated settings
Why this matters: A setting that already showed as saved can be silently undone by a stale tab or another device changing something unrelated.
To reproduce:
Open OpenStation in two browser sessions for the same user.
In session A, change the wallpaper and wait for it to save.
Without reloading session B, change only the accent color and wait for it to save.
Reload. Session B’s stale full-settings snapshot restores the old wallpaper while keeping the new accent.
Each save replaces the complete server-side settings object. There is no revision check, conflict response, field merge, or patch request.
Where to look:src/settings/state.ts, includes/os-settings.php
3. Owned folder windows lose their Share button after reload
Why this matters: Folder sharing works on the server, but the owner loses the main way to manage it from the folder window.
To reproduce:
Enable folder sharing and create or share a folder.
Reload the owner’s desktop.
Open the folder from the wallpaper.
The title bar has its normal window and breadcrumb controls, but no Share folder action.
The button matcher requires folder ownership from the client folder store. Normal persisted-placement hydration does not populate that store.
Where to look:src/desktop-files/share-menu-items.ts
4. Accepted shared folders never show the shared badge
Why this matters: Neither owner nor recipient can tell from the desktop that a folder is shared, even after an invitation has been accepted.
To reproduce:
Share an owned folder with a second user.
Accept the invitation as the recipient.
Reload both desktops.
The folder tile has no shared badge for either person.
The badge reads placement.file.shareSummary, but placement responses omit that field. It exists only in the separate folder response shape.
Where to look:includes/desktop-files/rest.php, src/desktop-files/share-menu-items.ts
5. OpenStation Preferences is mostly unreachable at 390px
Why this matters: On a phone-sized viewport or under magnification, most of the window and every right-side title-bar action can sit outside the visible page with no horizontal recovery path.
To reproduce:
Set the viewport to 390×844.
Open OpenStation Preferences as a normal window.
The fresh window renders 820px wide. Its right edge lands at 849px, while the viewport ends at 390px.
Window actions, Minimize, Maximize, Fullscreen, Close, and much of the content are unreachable.
The window keeps its desktop minimum width instead of switching to a compact contract or clamping itself to the viewport.
Where to look:src/desktop.ts, src/window-manager/index.ts
6. Arrow keys do not operate tabs—and can switch desktops instead
Why this matters: Keyboard users cannot move through tab strips using the standard Left/Right Arrow behavior. In Preferences, the unhandled key can bubble to the shell shortcut and switch virtual desktops, making the entire window disappear.
To reproduce:
Open Preferences and focus the selected Appearance tab.
Press Right Arrow.
Focus and selection stay on Appearance instead of moving to Themes.
In the reproduced shell, the key also switched virtual desktops and hid Preferences.
Repeat in Posts: Right Arrow on All posts does not move to Categories.
The tab component handles clicks but has no ARIA tab-pattern keyboard behavior.
Where to look:src/ui/components/os-tabs/os-tabs.ts, src/window/dom.ts
7. Cron’s custom interval field is invisible and unusable
Why this matters: The Cron app opens and lists jobs, but users cannot finish creating a custom recurrence because the required number field never upgrades into a real control.
To reproduce:
Open Cron Jobs.
Choose Create.
Select Custom interval.
The intended <os-number-field> remains an undefined, zero-size element with no focusable input.
The component exists in source but is not present in the production component registration path used by the extension.
Where to look:extensions/desktop-mode-cron-manager/includes/window.php, src/ui/components/os-number-field/
8. Spatial desktop shortcuts ignore enabled native windows
Why this matters: A user can explicitly enable native Posts, Pages, Comments, Plugins, and Users, but clicking their Spatial-layout wallpaper shortcuts still opens the old iframe versions.
To reproduce:
Choose the Spatial desktop layout.
Enable the native Posts, Pages, Comments, Plugins, and Users features.
Click any matching wallpaper shortcut.
OpenStation opens the classic URL/iframe window instead of the enabled native app.
Opening the same app from the canonical native API or dock correctly uses the native renderer.
The synthesized shortcut carries only a URL and bypasses the native replacement registry used by the dock.
Where to look:src/settings/desktop-shortcuts-sync.ts, src/desktop-files/built-in-openers.ts, src/desktop-layout.ts
9. Plugin fallback icons render as blank gray squares
Why this matters: Bundled and locally installed plugins without working WordPress.org artwork lose their identity in the native Plugins window.
To reproduce:
Open native Plugins and wait for the remote icon fallback chain to finish.
Look at a plugin without usable WordPress.org artwork, such as a bundled extension or Hello Dolly.
Its fallback is a blank gray square instead of the intended plugin icon.
The fallback inserts a Dashicons class inside the table’s Shadow DOM, where the document-level Dashicons font and pseudo-element CSS cannot reach it.
Where to look:src/plugins-window/installed-view.ts, src/plugins-window/icon-fallback.ts
10. Firefox drops Gravatars on WordPress 6.0/local HTTP installs
Why this matters: Real user avatars are replaced with initials in the native Users window on a supported minimum environment.
To reproduce:
Run the supported WordPress 6.0/PHP 7.4 environment over local HTTP.
Open native Users in Firefox.
The REST response supplies http://*.gravatar.com URLs.
OpenStation probes them with crossOrigin=anonymous; the HTTP→HTTPS redirect fails CORS, and the UI falls back to initials.
Normalizing known Gravatar URLs to HTTPS before the probe avoids the redirect/CORS failure.
Where to look:src/ui/util/avatar-resolve.ts
11. Content Graph freezes the browser with a large site
Why this matters: A site within the lab’s stress profile can lock the entire OpenStation shell for more than ten seconds just by opening Content Graph. The completed view is also too dense to read or operate meaningfully.
To reproduce:
Use a site whose Content Graph contains roughly 8,890 nodes.
Open Content Graph.
On the final trunk replay, Chromium took 11.59 seconds to become usable and 28.64 seconds on the evidence replay. The longest single main-thread blocks were 10.85–14.12 seconds. Earlier cross-browser runs also blocked Firefox for about 16 seconds and WebKit for about 13 seconds.
The Fit overview renders thousands of tiny marks with no useful visual hierarchy.
The current path performs synchronous simulation warm-up work over the full graph and creates a Pixi object/text workload for every node before yielding.
Where to look:src/content-graph/index.ts, src/content-graph/scene.ts, src/content-graph/sim.ts
This is the follow-up to #559. The point of this pass was to catch the things users usually find first: the second quick click, the stale browser tab, the narrow screen, the shared folder after reload, and the site with enough content to make a visualization fall over.
I updated to current
origin/trunk(c670170) before the final verification pass, then replayed every candidate from the older checkout. Anything already fixed upstream was removed from this issue.The bugs below still reproduce on current trunk. The two settings problems are the most urgent because OpenStation tells the user everything is saved while silently keeping the wrong value. Screenshot evidence is attached in the first comment.
1. A quick second toggle in Extended Options is silently lost
Why this matters: The control ends in one state, the server saves the opposite state, and the user is not told anything went wrong.
To reproduce:
desktop-mode/v1/extended-options; the server persisted disabled.The save function returns early while a request is in flight, but the still-enabled control keeps accepting changes and never queues a trailing save.
Where to look:
src/settings/sections/extended.ts2. Two open sessions can overwrite each other’s unrelated settings
Why this matters: A setting that already showed as saved can be silently undone by a stale tab or another device changing something unrelated.
To reproduce:
Each save replaces the complete server-side settings object. There is no revision check, conflict response, field merge, or patch request.
Where to look:
src/settings/state.ts,includes/os-settings.php3. Owned folder windows lose their Share button after reload
Why this matters: Folder sharing works on the server, but the owner loses the main way to manage it from the folder window.
To reproduce:
The button matcher requires folder ownership from the client folder store. Normal persisted-placement hydration does not populate that store.
Where to look:
src/desktop-files/share-menu-items.ts4. Accepted shared folders never show the shared badge
Why this matters: Neither owner nor recipient can tell from the desktop that a folder is shared, even after an invitation has been accepted.
To reproduce:
The badge reads
placement.file.shareSummary, but placement responses omit that field. It exists only in the separate folder response shape.Where to look:
includes/desktop-files/rest.php,src/desktop-files/share-menu-items.ts5. OpenStation Preferences is mostly unreachable at 390px
Why this matters: On a phone-sized viewport or under magnification, most of the window and every right-side title-bar action can sit outside the visible page with no horizontal recovery path.
To reproduce:
The window keeps its desktop minimum width instead of switching to a compact contract or clamping itself to the viewport.
Where to look:
src/desktop.ts,src/window-manager/index.ts6. Arrow keys do not operate tabs—and can switch desktops instead
Why this matters: Keyboard users cannot move through tab strips using the standard Left/Right Arrow behavior. In Preferences, the unhandled key can bubble to the shell shortcut and switch virtual desktops, making the entire window disappear.
To reproduce:
The tab component handles clicks but has no ARIA tab-pattern keyboard behavior.
Where to look:
src/ui/components/os-tabs/os-tabs.ts,src/window/dom.ts7. Cron’s custom interval field is invisible and unusable
Why this matters: The Cron app opens and lists jobs, but users cannot finish creating a custom recurrence because the required number field never upgrades into a real control.
To reproduce:
<os-number-field>remains an undefined, zero-size element with no focusable input.The component exists in source but is not present in the production component registration path used by the extension.
Where to look:
extensions/desktop-mode-cron-manager/includes/window.php,src/ui/components/os-number-field/8. Spatial desktop shortcuts ignore enabled native windows
Why this matters: A user can explicitly enable native Posts, Pages, Comments, Plugins, and Users, but clicking their Spatial-layout wallpaper shortcuts still opens the old iframe versions.
To reproduce:
The synthesized shortcut carries only a URL and bypasses the native replacement registry used by the dock.
Where to look:
src/settings/desktop-shortcuts-sync.ts,src/desktop-files/built-in-openers.ts,src/desktop-layout.ts9. Plugin fallback icons render as blank gray squares
Why this matters: Bundled and locally installed plugins without working WordPress.org artwork lose their identity in the native Plugins window.
To reproduce:
The fallback inserts a Dashicons class inside the table’s Shadow DOM, where the document-level Dashicons font and pseudo-element CSS cannot reach it.
Where to look:
src/plugins-window/installed-view.ts,src/plugins-window/icon-fallback.ts10. Firefox drops Gravatars on WordPress 6.0/local HTTP installs
Why this matters: Real user avatars are replaced with initials in the native Users window on a supported minimum environment.
To reproduce:
http://*.gravatar.comURLs.crossOrigin=anonymous; the HTTP→HTTPS redirect fails CORS, and the UI falls back to initials.Normalizing known Gravatar URLs to HTTPS before the probe avoids the redirect/CORS failure.
Where to look:
src/ui/util/avatar-resolve.ts11. Content Graph freezes the browser with a large site
Why this matters: A site within the lab’s stress profile can lock the entire OpenStation shell for more than ten seconds just by opening Content Graph. The completed view is also too dense to read or operate meaningfully.
To reproduce:
The current path performs synchronous simulation warm-up work over the full graph and creates a Pixi object/text workload for every node before yielding.
Where to look:
src/content-graph/index.ts,src/content-graph/scene.ts,src/content-graph/sim.tsSuggested order of attack
npm run test:phpactually work #2).Each fix should get a focused regression test at the owning state/component layer, plus one browser replay of the user-visible flow.