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.
This commit is contained in:
2026-05-15 17:15:07 -04:00
parent a47fbdc09c
commit 6bacb3faa8
3 changed files with 139 additions and 22 deletions
+34 -13
View File
@@ -136,19 +136,40 @@ fn render_metric(label: &'static str, value: usize, color: u32) -> AnyElement {
fn render_reset_button(cx: &mut Context<ElyShell>) -> AnyElement {
div()
.id(SharedString::from("sync-reset"))
.px(px(12.0))
.py(px(7.0))
.rounded(px(8.0))
.bg(rgba(BUTTON_BG))
.text_size(px(12.0))
.font_weight(FontWeight(500.0))
.text_color(rgb(colors::INK_2))
.cursor_pointer()
.hover(|style| style.bg(rgba(BUTTON_BG_HOVER)))
.active(|style| style.opacity(0.85))
.on_click(cx.listener(|shell, _, _, cx| shell.reset_sync_settings(cx)))
.child("Reset to defaults")
.flex()
.gap(px(8.0))
.child(
div()
.id(SharedString::from("sync-upload"))
.px(px(12.0))
.py(px(7.0))
.rounded(px(8.0))
.bg(rgba(colors::ACCENT))
.text_size(px(12.0))
.font_weight(FontWeight(500.0))
.text_color(rgb(0xfff5e6))
.cursor_pointer()
.hover(|style| style.opacity(0.92))
.active(|style| style.opacity(0.78))
.on_click(cx.listener(|shell, _, _, cx| shell.trigger_cloud_sync_upload(cx)))
.child("Sync now"),
)
.child(
div()
.id(SharedString::from("sync-reset"))
.px(px(12.0))
.py(px(7.0))
.rounded(px(8.0))
.bg(rgba(BUTTON_BG))
.text_size(px(12.0))
.font_weight(FontWeight(500.0))
.text_color(rgb(colors::INK_2))
.cursor_pointer()
.hover(|style| style.bg(rgba(BUTTON_BG_HOVER)))
.active(|style| style.opacity(0.85))
.on_click(cx.listener(|shell, _, _, cx| shell.reset_sync_settings(cx)))
.child("Reset to defaults"),
)
.into_any_element()
}