//! GoingsOn's [`SyncObserver`]: maps the engine scheduler's callbacks onto the //! Tauri events the frontend already listens for. The frontend (`js/app.js`) //! consumes: //! - `sync:status-changed`: payload `"syncing"` / `"error"` / anything else = idle //! - `sync:changes-applied`: payload = the list of DB tables the pull touched //! (drives selective cache invalidation) //! - `sync:subscription-required`: no payload (shows the subscribe toast) use std::collections::HashSet; use synckit_client::{SyncObserver, SyncState}; use tauri::{AppHandle, Emitter}; /// Emits GoingsOn's sync events from engine scheduler callbacks. pub(crate) struct GoSyncObserver { app: AppHandle, } impl GoSyncObserver { pub(crate) fn new(app: AppHandle) -> Self { Self { app } } } impl SyncObserver for GoSyncObserver { fn on_status(&self, state: SyncState) { // The frontend's dot only distinguishes syncing / error / idle. Idle, // LoggedOut, and SubscriptionRequired all rest it to connected; the last // additionally surfaces through on_subscription_required below. let payload = match state { SyncState::Syncing => "syncing", SyncState::Error(_) => "error", _ => "idle", }; let _ = self.app.emit("sync:status-changed", payload); } fn on_changes_applied(&self, tables: &HashSet) { let tables: Vec<&String> = tables.iter().collect(); let _ = self.app.emit("sync:changes-applied", tables); } fn on_subscription_required(&self) { let _ = self.app.emit("sync:subscription-required", ()); } }