tabs.rs had grown to 538 lines — past the 500-line ceiling — and was
mixing four unrelated concerns:
- `tab_navigation` (URL changes + history back/forward)
- `tab_metadata` (title, favicon, zoom, favorite/pin, sort, sync flag)
- `tab_archive_restore` (un-archive entry points + query matching)
- core CRUD (open / close / move-to-space + private helpers)
Each split file lives below 250 lines and only pulls the `ely_domain`
types and crate helpers it actually uses. `active_tab_mut` and the
`TabUrlUpdate` enum get `pub(super)` so siblings can reach them; no
behaviour change.
`SyncConnectionState` was a one-variant enum (`SignedOut`), so the
Sync page rendered "Local-only · sign-in coming soon" even after the
bearer token landed on disk and the upload thread completed. The
state machine now mirrors the actual lifecycle.
What lands:
- `SyncConnectionState` gains `SignedIn`, `AwaitingDeviceApproval`,
`SyncReady { last_synced_at_secs }`, `SyncError { message }`.
`SyncObjectState::Synced` joins the per-object enum so individual
rows can advertise "Synced" once a successful upload lands.
- `BrowserCore` stores the current `SyncConnectionState` and exposes
`set_sync_connection_state`. `sync_status` now propagates the live
state into the snapshot the UI reads.
- `ElyShell::probe_initial_sync_state` inspects
`<profile_data>/sync/bearer.token` synchronously at construction
so the first render of the sync page is honest about whether the
user is signed in.
- A `std::sync::mpsc` channel ferries upload outcomes from the
off-thread worker back to the shell; the existing 8 ms tick
drains it and stamps `core.set_sync_connection_state` with the
freshest result. The UI now shows "Signed in · awaiting first
sync", "Synced · last upload Xm ago", "Sync error · …", and the
worker-special "Signed in · waiting for device approval" when the
server returns `device_not_approved`.
Cursor-reach reveal now fulfils the "Slide in on cursor reach"
description on the design's Hidden-on-hover layout card.
- BrowserCore::active_space_sidebar_width() returns the current
sidebar tier without cloning a full BrowserSnapshot, so the
mouse_move hot path stays cheap.
- on_window_mouse_move on the shell root hits-tests the cursor x
against REVEAL_THRESHOLD_PX (24 px from the left edge). Outside
the reveal/collapse zones it returns immediately, so 99 % of
mouse moves never even read the snapshot.
- When in HIDDEN mode and the cursor crosses the reveal threshold,
expand_hidden_sidebar fires (its early-return on already-expanded
state prevents notify spam). When the cursor passes
COLLAPSE_THRESHOLD_PX (shell inset + default sidebar width + 24 px
buffer), collapse_hidden_sidebar fires.
- Click-to-expand on the rail and click-on-backdrop-to-collapse
remain as predictable fallbacks.
Domain:
- AppearanceSettings gains translucency_pct (u8, 0..=100, default 40)
with a clamping setter and serde round-trip coverage.
- DEFAULT_TRANSLUCENCY_PCT and MAX_TRANSLUCENCY_PCT exported for the
shell.
Core:
- BrowserCore::set_translucency_pct delegates to the appearance struct;
the existing reset_appearance covers the reset path.
- Integration test covers persistence into snapshot.appearance.
Render:
- chrome::sidebar::panel_bg(snapshot) replaces the static PANEL_BG
constant, mapping the user's translucency_pct linearly into the alpha
byte 0xff..0xb3. Sidebar (expanded + compact) and main pane consume
the helper so changing the setting at runtime updates every glass
surface in lock-step.
Form:
- Translucency row in chrome::appearance_form mirrors the design's
static track + thumb visual driven by the persisted percentage, plus
three preset chips (Solid 0 / Default 40 / Glassy 75) that mutate the
setting through shell.set_translucency_pct.
Strict UX rule preserved: alpha never drops below 0xb3 so panels stay
readable without backdrop blur (which GPUI 0.2.2 doesn't expose).
BrowserCore now owns an AppearanceSettings, exposes it through
BrowserSnapshot.appearance, and offers set_wallpaper_theme,
set_theme_mode, set_reduce_motion, reset_appearance mutators. Defaults
match the domain defaults (Dawn / System / motion-on) so existing
behaviour is unchanged for callers who don't touch appearance.
Integration tests cover initial snapshot defaults, mutation persistence
across snapshots, and reset behaviour.