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