cooklang_sync_client/
context.rs1use std::sync::Arc;
2use tokio_util::sync::CancellationToken;
3
4use crate::models::SyncStatus;
5
6#[uniffi::export(with_foreign)]
10pub trait SyncStatusListener: Send + Sync {
11 fn on_status_changed(&self, status: SyncStatus);
12 fn on_complete(&self, success: bool, message: Option<String>);
13}
14
15#[derive(uniffi::Object)]
17pub struct SyncContext {
18 cancellation_token: CancellationToken,
19 status_listener: std::sync::Mutex<Option<Arc<dyn SyncStatusListener>>>,
20}
21
22#[uniffi::export]
23impl SyncContext {
24 #[uniffi::constructor]
26 pub fn new() -> Arc<Self> {
27 Arc::new(Self {
28 cancellation_token: CancellationToken::new(),
29 status_listener: std::sync::Mutex::new(None),
30 })
31 }
32
33 pub fn set_listener(&self, listener: Arc<dyn SyncStatusListener>) {
35 let mut listener_lock = self
37 .status_listener
38 .lock()
39 .unwrap_or_else(|e| e.into_inner());
40 *listener_lock = Some(listener);
41 }
42
43 pub fn cancel(&self) {
45 self.cancellation_token.cancel();
46 }
47}
48
49impl SyncContext {
50 pub fn notify_status(&self, status: SyncStatus) {
52 let listener_lock = self
54 .status_listener
55 .lock()
56 .unwrap_or_else(|e| e.into_inner());
57 if let Some(listener) = listener_lock.as_ref() {
58 listener.on_status_changed(status);
59 }
60 }
61
62 pub fn token(&self) -> CancellationToken {
71 self.cancellation_token.child_token()
72 }
73
74 pub fn listener(&self) -> Option<Arc<dyn SyncStatusListener>> {
76 let listener_lock = self
78 .status_listener
79 .lock()
80 .unwrap_or_else(|e| e.into_inner());
81 listener_lock.clone()
82 }
83}