193 Commits
Author SHA1 Message Date
ZacharyZhang-NY c5890058db feat(reload): reload the active tab with Cmd/Ctrl+R 2026-07-10 16:55:25 -04:00
ZacharyZhang-NY d271670906 feat(settings): persist scalar settings across launches 2026-07-10 16:08:13 -04:00
ZacharyZhang-NY 324b0f1a6e fix(profiles): scope the sidebar to the active profile 2026-07-10 16:00:30 -04:00
ZacharyZhang-NY bfab49106d fix(tabs): keep the remembered active tab when closing a background tab 2026-07-10 12:09:30 -04:00
ZacharyZhang-NY bb16ed6fb3 feat(core): persist and restore browser state across launches 2026-07-10 12:01:43 -04:00
ZacharyZhang-NY dd0f84600d feat(spaces): make the Space accent real end to end 2026-07-10 11:45:08 -04:00
ZacharyZhang-NY e95177b3e6 refactor(settings): fold the read-only Advanced page into its owning sections 2026-07-10 11:40:09 -04:00
ZacharyZhang-NY b87f9ae2d4 refactor(privacy): drop the diagnostics reporting toggle until a reporter exists 2026-07-10 11:38:47 -04:00
ZacharyZhang-NY 07cd598f75 refactor(settings): remove the Updates page until an updater exists 2026-07-10 11:34:26 -04:00
ZacharyZhang-NY 3be13ca295 fix(sync): bind browser data to one account owner 2026-07-10 10:46:52 -04:00
ZacharyZhang-NY 46eac43326 fix(auth): reconcile expired desktop sessions 2026-07-10 09:46:55 -04:00
ZacharyZhang-NY 2f346abaea fix(auth): revoke desktop sessions safely 2026-07-10 08:57:00 -04:00
ZacharyZhang-NY 94afa23a69 fix(auth): store bearer tokens in native credentials 2026-07-10 07:57:44 -04:00
ZacharyZhang-NY 540b901fd6 fix(sync): secure encrypted snapshot lifecycle 2026-07-10 06:24:53 -04:00
ZacharyZhang-NY 556c5ff624 fix(sync): enforce private profile boundaries 2026-07-10 03:02:10 -04:00
ZacharyZhang-NY 7d70db6da9 fix(sync): preserve private profile boundaries 2026-07-09 22:48:44 -04:00
ZacharyZhang-NY 31fc1acf17 fix(servo): retire sessions on internal navigation 2026-07-09 22:37:17 -04:00
ZacharyZhang-NY b422ac1631 fix(permissions): make profile snapshots authoritative 2026-07-09 21:56:36 -04:00
ZacharyZhang-NY c28ec2bee8 feat(servo): isolate profiles with hardware sidecars 2026-07-09 20:27:22 -04:00
ZacharyZhang-NYandClaude Opus 4.8 207eeaf54c style: drop stray blank lines left by the test-file splits
The `sed`-based extractions in the preceding three split commits each
left one extra blank line at the cut boundary, which `cargo fmt --all
--check` (a CI gate) rejects. Whitespace only — no code change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 13:53:41 -04:00
ZacharyZhang-NYandClaude Opus 4.8 66e5b266e9 refactor(core): split oversized integration-test files under 500-line audit
`scripts/audit_source_lines.sh` (a CI gate) flagged `tests/commands.rs`
(527) and `tests/splits.rs` (524) over the 500-line ceiling. Both are
flat lists of independent `#[test]` fns with no shared helpers, so each
splits cleanly into a sibling integration-test binary (the crate already
uses a topical file-per-concern layout under `tests/`).

- commands.rs (29 tests) -> commands.rs (20: tab/space/profile/search)
  + command_pages.rs (9: internal-page-opening commands). 527 -> 389.
- splits.rs (25 tests) -> splits.rs (13: layout/axis/detach mechanics)
  + saved_split_lifecycle.rs (12: close/archive/restore/group). 524 -> 266.

No tests added or removed; each new file carries only the imports it
uses. `cargo clippy -p ely_browser_core --tests -- -D warnings` clean;
all ely_browser_core tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 13:34:56 -04:00
ZacharyZhang-NY db7cd2f9bc refactor(core): split tabs.rs by tab concern
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.
2026-05-18 14:20:58 -04:00
ZacharyZhang-NY d076dad356 Fix shell regressions and reset Servo embedding direction 2026-05-16 11:23:41 -04:00
ZacharyZhang-NY 7823ecd0a3 feat(sync): include plugin settings in snapshots 2026-05-16 07:12:52 -04:00
ZacharyZhang-NY 80729083eb feat(sync): include history in snapshots 2026-05-16 07:03:59 -04:00
ZacharyZhang-NY b550360a47 refactor(core): split browser settings state 2026-05-16 06:48:45 -04:00
ZacharyZhang-NY 00d48a9286 feat(sync): include site permissions in snapshots 2026-05-16 06:43:04 -04:00
ZacharyZhang-NY d5e25345c5 refactor(sync): split snapshot apply coordinator 2026-05-16 06:35:31 -04:00
ZacharyZhang-NY 5409c02394 feat(sync): include profiles in snapshots 2026-05-16 06:31:52 -04:00
ZacharyZhang-NY 323271fc1f feat(sync): include reading list in snapshots 2026-05-16 06:17:38 -04:00
ZacharyZhang-NY b2b3d5deca feat(sync): include notes in snapshots 2026-05-16 06:07:44 -04:00
ZacharyZhang-NY 7d5e936ca4 refactor(sync): split snapshot records 2026-05-16 05:52:39 -04:00
ZacharyZhang-NY bfdc97d7fd feat(sync): preserve spaces in snapshots 2026-05-16 05:42:17 -04:00
ZacharyZhang-NY 0c9bfc2673 perf(sync): avoid snapshot clone when scheduling uploads 2026-05-16 05:19:54 -04:00
ZacharyZhang-NY 47eaea28a2 fix(sync): honor paused object policies 2026-05-16 03:53:42 -04:00
ZacharyZhang-NY d05d31ed22 feat(sync): include open tabs in snapshots 2026-05-16 03:44:07 -04:00
ZacharyZhang-NY bd59e74ad2 perf(shell): trim render snapshot work 2026-05-16 01:52:19 -04:00
ZacharyZhang-NY e442e6def4 perf(web-surface): avoid snapshot clones on live ticks 2026-05-16 01:41:42 -04:00
ZacharyZhang-NY 40ab6b4874 feat(sync): round trip cloud snapshots 2026-05-16 00:01:28 -04:00
ZacharyZhang-NY 225a998642 fix(tabs): refresh metadata on navigation 2026-05-15 23:31:12 -04:00
ZacharyZhang-NY 467dcb1f87 Reflect real sync state on the Sync settings page
`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`.
2026-05-15 19:58:42 -04:00
ZacharyZhang-NY 6bacb3faa8 Add Sync now button that uploads a bookmarks snapshot
Wire `SyncEngine::upload_bytes` to a Settings → Sync button:

- `BrowserCore::build_sync_snapshot_bytes` serialises the user's
  bookmarks on the UI thread (cheap, synchronous).
- `ElyShell::trigger_cloud_sync_upload` resolves the active
  profile data dir, spawns a dedicated `ely-sync-upload` thread,
  and lets the engine run the blocking HTTP round-trip there so
  the GPUI render loop never stalls on the network — the same
  invariant the Servo IPC worker enforces.
- Outcomes go through `tracing` on the `ely::sync` target. Users
  drop a Better Auth bearer token into
  `<profile_data>/sync/bearer.token` to opt in; without one, the
  engine reports `SignedOut` and the click is a no-op.

The Better Auth handshake + device-approval UX still need their
own UI passes; this lands the data-plane plumbing so those pieces
slot in without re-architecting the snapshot path.
2026-05-15 17:15:07 -04:00
ZacharyZhang-NY a47fbdc09c Wire SyncEngine into BrowserCore
Add per-profile sync orchestration to `ely_browser_core`:

- `SyncEngine::for_profile_dir` loads / generates the persistent
  device identity under `<profile_data>/sync/device.json` and reads
  the bearer token from `<profile_data>/sync/bearer.token`.
- `install_bearer` accepts (or clears) the Better Auth session
  token; everything else stays inert until a token is on disk.
- `upload_now(&BrowserCore)` serialises the user's bookmarks into a
  stable JSON snapshot, ships it via `SyncApiClient::upload_snapshot`,
  and remembers the resulting snapshot id / logical clock / device
  for the UI to surface.
- `BrowserCore::visible_bookmarks_for_sync` returns a read-only view
  the engine can iterate without touching the in-memory state.

The shell / settings-page wiring that calls `upload_now` ships
separately so this commit stays a pure model-layer change with no
runtime behaviour difference until the UI plugs in.
2026-05-15 17:10:30 -04:00
ZacharyZhang-NY 3d2c3ed1bf Propagate page title and favicon into the active tab
Servo already publishes the live page title in every `LiveFrameReport`
but the renderer was dropping it on the floor — tabs that navigated
away from `ely://new-tab` kept showing "New Tab" forever, and there
was no favicon visible anywhere in the sidebar.

Add `BrowserCore::set_tab_title` and switch `set_tab_favicon_key` to
return `Ok(true)` only when the value actually changed; both methods
mirror the new value into the matching history entry so the History
page stays in lockstep. Derive the canonical `/favicon.ico` URL from
the loaded URL on `UrlText` and store it as the tab's `favicon_key`.

In the surface layer, every Ready frame now emits a
`WebSurfacePageMetadata` change alongside any `WebSurfaceUrlChange`,
and the controller applies title + favicon URL together. Render the
sidebar tab row's favicon via GPUI's HTTP image loader (falling
through to the URL-derived glyph for `ely://` pages, file URLs, and
hosts without a /favicon.ico endpoint).
2026-05-15 16:53:32 -04:00
ZacharyZhang-NY ac84a80d9e Close Servo live sessions for removed tabs 2026-05-13 02:41:54 -04:00
ZacharyZhang-NY 05ce4afba4 Poll only visible web surfaces 2026-05-13 01:54:51 -04:00
ZacharyZhang-NY 1325f043b4 Commit Servo loaded URLs to tabs 2026-05-13 01:09:39 -04:00
ZacharyZhang-NY 4cb7ff089e Wire topbar tab history navigation 2026-05-13 00:49:52 -04:00
ZacharyZhang-NY fec5a9b475 Move idle archiving into tab lifecycle 2026-05-13 00:38:04 -04:00
ZacharyZhang-NY c95e3665c6 Omnibar Enter navigates the current tab instead of spawning a new one
`submit_command` matched every browser's "Enter to navigate" intent
to `open_tab(url)`, which always inserts a new `BrowserTab`. So
typing `google.com` and hitting Enter on a new-tab page would leave
both the new-tab and a fresh google.com tab in the sidebar.

Mirror the same in-place navigation rule the shell-level code now
uses: `navigate_active_tab(url)` for the Navigate and Search
intents, with `open_tab` as the fallback when there's no active tab
yet. Tab count only goes up when the user explicitly hits + New Tab.

cargo test --workspace: 440 passed, 0 failed.
2026-05-09 22:50:01 -04:00