tauri_plugin_matrix_svelte/
lib.rs

1use matrix_ui_serializable::{LibConfig, MobilePushNotificationConfig};
2use serde::Deserialize;
3use stronghold::init_stronghold_client;
4use tauri::{
5    AppHandle, Manager, Runtime,
6    plugin::{Builder, TauriPlugin},
7};
8
9#[cfg(desktop)]
10mod desktop;
11#[cfg(mobile)]
12mod mobile;
13
14mod commands;
15mod error;
16mod events;
17mod models;
18mod state_updaters;
19mod stronghold;
20mod utils;
21
22pub use error::{Error, Result};
23
24#[cfg(desktop)]
25use desktop::MatrixSvelte;
26#[cfg(mobile)]
27use mobile::MatrixSvelte;
28
29use crate::{
30    events::{event_forwarder, handle_incoming_events},
31    state_updaters::Updaters,
32    stronghold::get_matrix_session_option,
33    utils::fs::get_temp_dir_or_create_it,
34};
35
36/// Plugin config to be set in tauri.conf.json
37#[derive(Deserialize)]
38pub struct PluginConfig {
39    pub(crate) stronghold_password: String,
40    #[cfg(mobile)]
41    pub(crate) sygnal_gateway_url: String,
42}
43
44/// Extensions to [`tauri::App`], [`tauri::AppHandle`] and [`tauri::Window`] to access the Matrix Svelte APIs.
45pub trait MatrixSvelteExt<R: Runtime> {
46    fn matrix_svelte(&self) -> &MatrixSvelte<R>;
47}
48
49impl<R: Runtime, T: Manager<R>> crate::MatrixSvelteExt<R> for T {
50    fn matrix_svelte(&self) -> &MatrixSvelte<R> {
51        self.state::<MatrixSvelte<R>>().inner()
52    }
53}
54
55/// Initializes the plugin.
56pub fn init<R: Runtime>() -> TauriPlugin<R, PluginConfig> {
57    Builder::<R, PluginConfig>::new("matrix-svelte")
58        .invoke_handler(tauri::generate_handler![
59            commands::login_and_create_new_session,
60            commands::submit_async_request,
61            commands::fetch_media,
62            commands::fetch_user_profile,
63            commands::watch_notifications,
64            commands::get_devices,
65            commands::verify_device
66        ])
67        .setup(|app, api| {
68            let init_app_handle = app.app_handle().clone();
69            let stronghold_app_handle = app.app_handle().clone();
70
71            let temp_dir = get_temp_dir_or_create_it(&init_app_handle)?;
72
73            let stronghold_handle = tauri::async_runtime::spawn(async move {
74                init_stronghold_client(&stronghold_app_handle)
75                    .expect("Couldn't init stronghold client")
76            });
77
78            let _monitor = tauri::async_runtime::spawn(async move {
79                stronghold_handle
80                    .await
81                    .expect("Couldn't init stronghold client");
82
83                let session_option = get_matrix_session_option(&init_app_handle)
84                    .await
85                    .expect("Couldn't get session option");
86
87                let event_receivers = handle_incoming_events(&init_app_handle);
88
89                let push_config = get_push_config(&init_app_handle);
90
91                let updaters_handle = init_app_handle.clone();
92                let updaters = Updaters::new(updaters_handle);
93
94                let config = LibConfig::new(
95                    Box::new(updaters),
96                    push_config,
97                    event_receivers,
98                    session_option,
99                    temp_dir,
100                );
101                let receiver = matrix_ui_serializable::init(config);
102
103                let inner_app_handle = init_app_handle.clone();
104                tauri::async_runtime::spawn(async move {
105                    futures::executor::block_on(event_forwarder(inner_app_handle, receiver))
106                })
107            });
108
109            #[cfg(mobile)]
110            let matrix_svelte = mobile::init(app, api)?;
111            #[cfg(desktop)]
112            let matrix_svelte = desktop::init(app, api)?;
113            app.manage(matrix_svelte);
114            Ok(())
115        })
116        .build()
117}
118
119fn get_push_config<R: Runtime>(_app_handle: &AppHandle<R>) -> Option<MobilePushNotificationConfig> {
120    #[cfg(desktop)]
121    return None;
122    #[cfg(mobile)]
123    {
124        use crate::MatrixSvelteExt;
125        use crate::models::mobile::GetTokenRequest;
126        use crate::utils::config::get_plugin_config;
127        if let Ok(push_token) = _app_handle.matrix_svelte().get_token(GetTokenRequest {}) {
128            let plugin_config =
129                get_plugin_config(_app_handle).expect("The plugin config is not defined !");
130            let identifier = _app_handle.config().identifier.clone();
131            #[cfg(target_os = "android")]
132            let identifier = identifier.replace("-", "_"); // On android, - are replaced by _ in bundle names
133
134            return Some(MobilePushNotificationConfig::new(
135                push_token.token,
136                plugin_config.sygnal_gateway_url,
137                identifier,
138            ));
139        } else {
140            return None;
141        }
142    }
143}
144
145// Re-export for app
146pub use crate::state_updaters::LOGIN_STATE_STORE_ID;
147pub use matrix_ui_serializable::LOGIN_STORE_READY;