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:
@@ -75,20 +75,17 @@ impl SyncEngine {
|
||||
self.bearer_store.load().map(|token| token.is_some())
|
||||
}
|
||||
|
||||
/// Build the JSON snapshot payload and ship it to the worker. The
|
||||
/// caller passes the BrowserCore directly so the snapshot reads
|
||||
/// the latest committed state; we don't keep a parallel copy.
|
||||
pub fn upload_now(&mut self, core: &BrowserCore) -> Result<SyncOutcome, SyncClientError> {
|
||||
/// Ship a pre-serialised snapshot payload to the worker. Callers
|
||||
/// usually pair this with `BrowserCore::build_sync_snapshot_bytes`
|
||||
/// — building the bytes on the UI thread and only crossing the
|
||||
/// thread boundary with `Vec<u8>` keeps `BrowserCore` itself
|
||||
/// single-threaded.
|
||||
pub fn upload_bytes(&mut self, bytes: Vec<u8>) -> Result<SyncOutcome, SyncClientError> {
|
||||
let Some(bearer) = self.bearer_store.load()? else {
|
||||
let outcome = SyncOutcome::SignedOut;
|
||||
self.last_outcome = Some(outcome.clone());
|
||||
return Ok(outcome);
|
||||
};
|
||||
let snapshot = SyncSnapshotBody::from_core(core);
|
||||
let bytes = serde_json::to_vec(&snapshot).map_err(|error| SyncClientError::Json {
|
||||
endpoint: "snapshot".to_string(),
|
||||
source: error,
|
||||
})?;
|
||||
let payload = SnapshotPayload::new(bytes)?;
|
||||
let logical_clock = current_logical_clock();
|
||||
let snapshot_id = snapshot_id_for_user(&self.identity);
|
||||
@@ -201,3 +198,17 @@ impl SyncEngineBuilder {
|
||||
SyncEngine::for_profile_dir(&self.profile_data_dir, self.device_name, self.platform)
|
||||
}
|
||||
}
|
||||
|
||||
impl BrowserCore {
|
||||
/// Build the JSON byte payload the sync engine expects. Lives on
|
||||
/// `BrowserCore` so the snapshot reads the live state and so the
|
||||
/// UI thread does the (synchronous, cheap) serialization before
|
||||
/// handing bytes off to the worker thread.
|
||||
pub fn build_sync_snapshot_bytes(&self) -> Result<Vec<u8>, SyncClientError> {
|
||||
let body = SyncSnapshotBody::from_core(self);
|
||||
serde_json::to_vec(&body).map_err(|error| SyncClientError::Json {
|
||||
endpoint: "snapshot".to_string(),
|
||||
source: error,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user