The reconnect banner showed 'Connection lost'/'Reconnecting' instantly on every
socket close, even ones that recover in 100ms-2s (load spikes, Tailscale/relay
TCP resets). On a healthy node the drops are brief and self-healing, but each one
flashed a jarring banner, reading as constant instability.
Debounce the transient banner by 2.5s: only surface after the connection issue
persists past the grace window; hide immediately on recovery. Deliberate server
lifecycle transitions (restart/shutdown) bypass the debounce and still show at
once. A genuine persistent outage keeps isOffline true and surfaces after 2.5s.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Mobile launches use the store-driven panel (no route push) so the background
tab no longer changes and closing returns to where you launched from.
- Tab-only apps open directly (in-app WebView on companion / new tab on PWA) —
no "this app opens in a tab" interstitial.
- Shared AppLoadingScreen (app icon + progress bar) on the app session and the
legacy iframe overlay instead of a black screen.
- Pin the dashboard to 100dvh on mobile so the mesh chat/tools panes stop sliding
under the bottom tab bar in mobile browsers (no-op in the companion WebView).
- ElectrumX/electrs/electrs-ui ids now resolve to the real ElectrumX icon in My Apps.
- isMobile made reactive so overlay/footer/teleport decisions track the viewport.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
On Cloud/files (and any scrolling view), the bottom of the list could sit behind
the fixed mobile tab bar. Cause: DashboardMobileNav measured the bar's
offsetHeight and wrote it to --mobile-tab-bar-height, but when the bar was hidden
or not yet laid out the measurement was 0 — and writing "0px" defeats the
", 88px" fallback in the .mobile-scroll-pad clearance calc (an explicit 0 is
still a set value), so the clearance collapsed and the ~88px bar overlapped the
last row.
- never write 0px: only set a real measured height, else remove the var so the
88px fallback applies.
- re-measure after first paint (rAF) and after the WebView safe-area injection,
so the clearance reflects the bar's final laid-out height.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The offline/reconnecting banners were in-flow (mx-6 mt-6) and pushed the whole
dashboard down when shown. Teleport them to <body> as a fixed, top-centered
overlay with a fade/slide transition and safe-area inset, so they no longer
shift layout.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Headless containers (databases, APIs, backends without a UI) belong in a
tab labelled 'Services', not 'Websites'. The categorisation logic already
routes UI-less packages there (built under #45); this finishes the rename
of the user-facing label across Apps, Marketplace, Discover and the mobile
nav, and makes 'services' the canonical tab state/query param. Old
?tab=websites bookmarks still resolve (back-compat acceptor kept).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move CompanionIndicator from global App.vue overlay to DashboardSidebar
next to ControllerIndicator. Redesigned as inline sidebar element with
Tailwind classes — shows muted 'Relay' when idle, orange 'Companion'
with pulse dot when actively receiving input.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Frontend:
- Add remote-relay.ts: receives companion input via /ws/remote-relay,
dispatches keyboard/mouse/scroll events into browser DOM
- Add CompanionIndicator.vue: NES gamepad icon when companion connected
- Wire relay start/stop to auth state in App.vue
Kiosk:
- Move Chromium data dir to /var/lib/archipelago/chromium-kiosk (encrypted)
- Disable MetricsReporting, AutofillServerCommunication, PasswordManager
- Remove --metrics-recording-only (contradicts disable-metrics)
CSS:
- Fix Chromium ghost rectangles: only apply preserve-3d + backface-visibility
during transitions, not always-on (causes Chromium to skip painting
off-viewport cards)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add AppIconGrid: 4-column swipeable icon grid with page dots for My Apps on mobile
- Tab bar: remove text labels, square icon-only buttons (w-14 h-14), doubled padding
- Hide tab bar and top context tabs when app session is open
- App session header hidden on mobile, replaced with floating glass close button
- App sessions now render fullscreen on mobile without nav chrome
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>