1use std::{future::Future, path::PathBuf};
2
3use tokio::sync::broadcast::Receiver;
4use uuid::Uuid;
5
6use crate::model::account::{Account, Username};
7use crate::model::api::{
8 AccountFilter, AccountIdentifier, AccountInfo, AdminFileInfoResponse, AdminSetUserTierInfo,
9 AdminValidateAccount, AdminValidateServer, ServerIndex, StripeAccountTier, SubscriptionInfo,
10};
11use crate::model::core_config::Config;
12use crate::model::crypto::DecryptedDocument;
13use crate::model::errors::{LbResult, Warning};
14use crate::model::file::{File, ShareMode};
15use crate::model::file_metadata::{DocumentHmac, FileType};
16use crate::model::path_ops::Filter;
17use crate::service::activity::RankingWeights;
18
19use crate::service::events::Event;
20use crate::service::import_export::{ExportFileInfo, ImportStatus};
21use crate::service::usage::UsageMetrics;
22use crate::subscribers::status::Status;
23
24#[cfg(not(target_family = "wasm"))]
25use {std::sync::Arc, tokio::runtime::Runtime};
26
27#[cfg(not(target_family = "wasm"))]
28use crate::subscribers::search::{SearchConfig, SearchResult};
29
30#[cfg(not(target_family = "wasm"))]
31use crate::service::debug::DebugInfo;
32
33#[derive(Clone)]
34pub struct Lb {
35 lb: crate::Lb,
36 #[cfg(not(target_family = "wasm"))]
37 rt: Arc<Runtime>,
38}
39
40impl Lb {
41 #[cfg(target_family = "wasm")]
42 pub fn init(config: Config) -> LbResult<Self> {
43 let lb = crate::Lb::init_dummy(config).unwrap();
44 Ok(Self { lb })
45 }
46
47 #[cfg(target_family = "wasm")]
48 fn block_on<F>(&self, future: F) -> F::Output
49 where
50 F: Future,
51 {
52 futures::executor::block_on(future)
53 }
54
55 #[cfg(not(target_family = "wasm"))]
56 fn block_on<F>(&self, future: F) -> F::Output
57 where
58 F: Future,
59 {
60 self.rt.block_on(future)
61 }
62
63 #[cfg(not(target_family = "wasm"))]
64 pub fn init(config: Config) -> LbResult<Self> {
65 let rt = Arc::new(Runtime::new().unwrap());
66 let lb = rt.block_on(crate::Lb::init(config))?;
67 Ok(Self { rt, lb })
68 }
69
70 pub fn create_account(
71 &self, username: &str, api_url: &str, welcome_doc: bool,
72 ) -> LbResult<Account> {
73 self.block_on(self.lb.create_account(username, api_url, welcome_doc))
74 }
75
76 pub fn import_account(&self, key: &str, api_url: Option<&str>) -> LbResult<Account> {
77 self.block_on(self.lb.import_account(key, api_url))
78 }
79
80 pub fn export_account_private_key(&self) -> LbResult<String> {
81 self.lb.export_account_private_key()
82 }
83
84 pub fn export_account_phrase(&self) -> LbResult<String> {
85 self.lb.export_account_phrase()
86 }
87
88 pub fn export_account_qr(&self) -> LbResult<Vec<u8>> {
89 self.lb.export_account_qr()
90 }
91
92 pub fn get_account(&self) -> LbResult<&Account> {
93 self.lb.get_account()
94 }
95
96 pub fn get_config(&self) -> Config {
97 self.lb.config.clone()
98 }
99
100 pub fn create_file(&self, name: &str, parent: &Uuid, file_type: FileType) -> LbResult<File> {
101 self.block_on(self.lb.create_file(name, parent, file_type))
102 }
103
104 pub fn safe_write(
105 &self, id: Uuid, old_hmac: Option<DocumentHmac>, content: Vec<u8>,
106 ) -> LbResult<DocumentHmac> {
107 self.block_on(self.lb.safe_write(id, old_hmac, content))
108 }
109
110 pub fn write_document(&self, id: Uuid, content: &[u8]) -> LbResult<()> {
111 self.block_on(self.lb.write_document(id, content))
112 }
113
114 pub fn get_root(&self) -> LbResult<File> {
115 self.block_on(self.lb.root())
116 }
117
118 pub fn get_children(&self, id: &Uuid) -> LbResult<Vec<File>> {
119 self.block_on(self.lb.get_children(id))
120 }
121
122 pub fn get_and_get_children_recursively(&self, id: &Uuid) -> LbResult<Vec<File>> {
123 self.block_on(self.lb.get_and_get_children_recursively(id))
124 }
125
126 pub fn get_file_by_id(&self, id: Uuid) -> LbResult<File> {
127 self.block_on(self.lb.get_file_by_id(id))
128 }
129
130 pub fn delete_file(&self, id: &Uuid) -> LbResult<()> {
131 self.block_on(self.lb.delete(id))
132 }
133
134 pub fn read_document(&self, id: Uuid, user_activity: bool) -> LbResult<DecryptedDocument> {
135 self.block_on(self.lb.read_document(id, user_activity))
136 }
137
138 pub fn read_document_with_hmac(
139 &self, id: Uuid, user_activity: bool,
140 ) -> LbResult<(Option<DocumentHmac>, DecryptedDocument)> {
141 self.block_on(self.lb.read_document_with_hmac(id, user_activity))
142 }
143
144 pub fn list_metadatas(&self) -> LbResult<Vec<File>> {
145 self.block_on(self.lb.list_metadatas())
146 }
147
148 pub fn rename_file(&self, id: &Uuid, new_name: &str) -> LbResult<()> {
149 self.block_on(self.lb.rename_file(id, new_name))
150 }
151
152 pub fn move_file(&self, id: &Uuid, new_parent: &Uuid) -> LbResult<()> {
153 self.block_on(self.lb.move_file(id, new_parent))
154 }
155
156 pub fn share_file(&self, id: Uuid, username: &str, mode: ShareMode) -> LbResult<()> {
157 self.block_on(self.lb.share_file(id, username, mode))
158 }
159
160 pub fn get_pending_shares(&self) -> LbResult<Vec<File>> {
161 self.block_on(self.lb.get_pending_shares())
162 }
163
164 pub fn get_pending_share_files(&self) -> LbResult<Vec<File>> {
165 self.block_on(self.lb.get_pending_share_files())
166 }
167
168 pub fn delete_pending_share(&self, id: &Uuid) -> LbResult<()> {
169 self.block_on(async { self.lb.reject_share(id).await })
170 }
171
172 pub fn create_link_at_path(&self, path_and_name: &str, target_id: Uuid) -> LbResult<File> {
173 self.block_on(self.lb.create_link_at_path(path_and_name, target_id))
174 }
175
176 pub fn create_at_path(&self, path_and_name: &str) -> LbResult<File> {
177 self.block_on(self.lb.create_at_path(path_and_name))
178 }
179
180 pub fn get_by_path(&self, path: &str) -> LbResult<File> {
181 self.block_on(self.lb.get_by_path(path))
182 }
183
184 pub fn get_path_by_id(&self, id: Uuid) -> LbResult<String> {
185 self.block_on(self.lb.get_path_by_id(id))
186 }
187
188 pub fn list_paths(&self, filter: Option<Filter>) -> LbResult<Vec<String>> {
189 self.block_on(self.lb.list_paths(filter))
190 }
191
192 pub fn get_local_changes(&self) -> LbResult<Vec<Uuid>> {
193 Ok(self.block_on(self.lb.local_changes()))
194 }
195
196 pub fn sync(&self) -> LbResult<()> {
197 self.block_on(self.lb.sync())
198 }
199
200 pub fn get_last_synced(&self) -> LbResult<i64> {
201 self.block_on(async {
202 let tx = self.lb.ro_tx().await;
203 let db = tx.db();
204 Ok(db.last_synced.get().copied().unwrap_or(0))
205 })
206 }
207
208 pub fn get_last_synced_human_string(&self) -> LbResult<String> {
209 self.block_on(self.lb.get_last_synced_human())
210 }
211
212 pub fn get_timestamp_human_string(&self, timestamp: i64) -> String {
213 self.lb.get_timestamp_human_string(timestamp)
214 }
215
216 pub fn suggested_docs(&self, settings: RankingWeights) -> LbResult<Vec<Uuid>> {
217 self.block_on(self.lb.suggested_docs(settings))
218 }
219
220 pub fn clear_suggested(&self) -> LbResult<()> {
221 self.block_on(self.lb.clear_suggested())
222 }
223
224 pub fn clear_suggested_id(&self, target_id: Uuid) -> LbResult<()> {
225 self.block_on(self.lb.clear_suggested_id(target_id))
226 }
227
228 pub fn get_usage(&self) -> LbResult<UsageMetrics> {
230 self.block_on(self.lb.get_usage())
231 }
232
233 pub fn import_files<F: Fn(ImportStatus)>(
234 &self, sources: &[PathBuf], dest: Uuid, update_status: &F,
235 ) -> LbResult<()> {
236 self.block_on(self.lb.import_files(sources, dest, update_status))
237 }
238
239 pub fn export_files(
240 &self, id: Uuid, dest: PathBuf, edit: bool,
241 export_progress: &Option<Box<dyn Fn(ExportFileInfo)>>,
242 ) -> LbResult<()> {
243 self.block_on(self.lb.export_file(id, dest, edit, export_progress))
244 }
245
246 #[cfg(not(target_family = "wasm"))]
247 pub fn search_file_paths(&self, input: &str) -> LbResult<Vec<SearchResult>> {
248 self.block_on(async { self.lb.search(input, SearchConfig::Paths).await })
249 }
250
251 #[cfg(not(target_family = "wasm"))]
252 pub fn search(&self, input: &str, cfg: SearchConfig) -> LbResult<Vec<SearchResult>> {
253 self.block_on(self.lb.search(input, cfg))
254 }
255
256 pub fn validate(&self) -> LbResult<Vec<Warning>> {
257 self.block_on(self.lb.test_repo_integrity(true))
258 }
259
260 pub fn upgrade_account_stripe(&self, account_tier: StripeAccountTier) -> LbResult<()> {
261 self.block_on(self.lb.upgrade_account_stripe(account_tier))
262 }
263
264 pub fn upgrade_account_google_play(
265 &self, purchase_token: &str, account_id: &str,
266 ) -> LbResult<()> {
267 self.block_on(
268 self.lb
269 .upgrade_account_google_play(purchase_token, account_id),
270 )
271 }
272
273 pub fn upgrade_account_app_store(
274 &self, original_transaction_id: String, app_account_token: String,
275 ) -> LbResult<()> {
276 self.block_on(
277 self.lb
278 .upgrade_account_app_store(original_transaction_id, app_account_token),
279 )
280 }
281
282 pub fn cancel_subscription(&self) -> LbResult<()> {
283 self.block_on(self.lb.cancel_subscription())
284 }
285
286 pub fn get_subscription_info(&self) -> LbResult<Option<SubscriptionInfo>> {
287 self.block_on(self.lb.get_subscription_info())
288 }
289
290 pub fn delete_account(&self) -> LbResult<()> {
291 self.block_on(self.lb.delete_account())
292 }
293
294 pub fn admin_disappear_account(&self, username: &str) -> LbResult<()> {
295 self.block_on(self.lb.disappear_account(username))
296 }
297
298 pub fn admin_disappear_file(&self, id: Uuid) -> LbResult<()> {
299 self.block_on(self.lb.disappear_file(id))
300 }
301
302 pub fn admin_list_users(&self, filter: Option<AccountFilter>) -> LbResult<Vec<Username>> {
303 self.block_on(self.lb.list_users(filter))
304 }
305
306 pub fn admin_get_account_info(&self, identifier: AccountIdentifier) -> LbResult<AccountInfo> {
307 self.block_on(self.lb.get_account_info(identifier))
308 }
309
310 pub fn admin_validate_account(&self, username: &str) -> LbResult<AdminValidateAccount> {
311 self.block_on(self.lb.validate_account(username))
312 }
313
314 pub fn admin_validate_server(&self) -> LbResult<AdminValidateServer> {
315 self.block_on(self.lb.validate_server())
316 }
317
318 pub fn admin_file_info(&self, id: Uuid) -> LbResult<AdminFileInfoResponse> {
319 self.block_on(self.lb.file_info(id))
320 }
321
322 pub fn admin_rebuild_index(&self, index: ServerIndex) -> LbResult<()> {
323 self.block_on(self.lb.rebuild_index(index))
324 }
325
326 pub fn admin_set_user_tier(&self, username: &str, info: AdminSetUserTierInfo) -> LbResult<()> {
327 self.block_on(self.lb.set_user_tier(username, info))
328 }
329
330 pub fn subscribe(&self) -> Receiver<Event> {
331 self.lb.subscribe()
332 }
333
334 pub fn status(&self) -> Status {
335 self.block_on(self.lb.status())
336 }
337
338 pub fn app_foregrounded(&self) {
339 #[cfg(not(target_family = "wasm"))]
340 {
341 let rt = self.rt.enter();
342 self.lb.app_foregrounded();
343 drop(rt);
344 }
345 }
346
347 #[cfg(not(target_family = "wasm"))]
348 pub fn debug_info(&self, os_info: String) -> LbResult<DebugInfo> {
349 self.rt.block_on(self.lb.debug_info(os_info, true))
350 }
351
352 pub fn recent_panic(&self) -> LbResult<bool> {
353 #[cfg(not(target_family = "wasm"))]
354 return self.block_on(self.lb.recent_panic());
355 #[cfg(target_family = "wasm")]
356 Ok(false)
357 }
358
359 #[cfg(not(target_family = "wasm"))]
360 pub fn write_panic_to_file(&self, error_header: String, bt: String) -> LbResult<String> {
361 self.block_on(self.lb.write_panic_to_file(error_header, bt))
362 }
363}