tauri_plugin_matrix_svelte/matrix/
singletons.rs

1use std::{
2    collections::BTreeMap,
3    sync::{Mutex, OnceLock},
4};
5
6use matrix_sdk::{ruma::OwnedRoomId, Client};
7use matrix_sdk_ui::sync_service::SyncService;
8use tokio::sync::{broadcast, mpsc::UnboundedSender};
9
10use super::{requests::MatrixRequest, rooms::JoinedRoomDetails};
11
12/// The sender used by [`submit_async_request`] to send requests to the async worker thread.
13/// Currently there is only one, but it can be cloned if we need more concurrent senders.
14pub static REQUEST_SENDER: OnceLock<UnboundedSender<MatrixRequest>> = OnceLock::new();
15
16/// The singleton sync service.
17pub static SYNC_SERVICE: OnceLock<SyncService> = OnceLock::new();
18
19pub fn get_sync_service() -> Option<&'static SyncService> {
20    SYNC_SERVICE.get()
21}
22
23/// Information about all joined rooms that our client currently know about.
24pub static ALL_JOINED_ROOMS: Mutex<BTreeMap<OwnedRoomId, JoinedRoomDetails>> =
25    Mutex::new(BTreeMap::new());
26
27pub static TOMBSTONED_ROOMS: Mutex<BTreeMap<OwnedRoomId, OwnedRoomId>> =
28    Mutex::new(BTreeMap::new());
29
30pub static LOG_ROOM_LIST_DIFFS: bool = true;
31
32pub static LOG_TIMELINE_DIFFS: bool = true;
33
34/// The logged-in Matrix client, which can be freely and cheaply cloned.
35pub static CLIENT: OnceLock<Client> = OnceLock::new();
36
37pub fn get_client() -> Option<Client> {
38    CLIENT.get().cloned()
39}
40
41pub static LOGIN_STORE_READY: OnceLock<bool> = OnceLock::new();
42
43#[derive(Debug, Clone)]
44pub enum UIUpdateMessage {
45    RefreshUI,
46}
47
48// Global broadcaster instance
49static GLOBAL_BROADCASTER: OnceLock<GlobalBroadcaster> = OnceLock::new();
50
51pub struct GlobalBroadcaster {
52    sender: broadcast::Sender<UIUpdateMessage>,
53}
54
55impl GlobalBroadcaster {
56    fn new(capacity: usize) -> Self {
57        let (sender, _) = broadcast::channel(capacity);
58        Self { sender }
59    }
60
61    fn broadcast(
62        &self,
63        message: UIUpdateMessage,
64    ) -> Result<usize, broadcast::error::SendError<UIUpdateMessage>> {
65        self.sender.send(message)
66    }
67
68    fn subscribe(&self) -> broadcast::Receiver<UIUpdateMessage> {
69        self.sender.subscribe()
70    }
71}
72
73// Initialize the global broadcaster (call this once at startup)
74pub fn init_broadcaster(capacity: usize) -> Result<(), &'static str> {
75    GLOBAL_BROADCASTER
76        .set(GlobalBroadcaster::new(capacity))
77        .map_err(|_| "Broadcaster already initialized")
78}
79
80// Globally available function to broadcast messages
81pub fn broadcast_event(message: UIUpdateMessage) -> Result<usize, Box<dyn std::error::Error>> {
82    let broadcaster = GLOBAL_BROADCASTER
83        .get()
84        .ok_or("Broadcaster not initialized. Call init_broadcaster() first.")?;
85
86    Ok(broadcaster.broadcast(message)?)
87}
88
89// Globally available function to create receivers
90pub fn subscribe_to_events() -> Result<broadcast::Receiver<UIUpdateMessage>, &'static str> {
91    let broadcaster = GLOBAL_BROADCASTER
92        .get()
93        .ok_or("Broadcaster not initialized. Call init_broadcaster() first.")?;
94
95    Ok(broadcaster.subscribe())
96}