Skip to content

Commit 10cbc2d

Browse files
committed
fix(macos): add macOS support for deep links and background sync
- Make tauri-plugin-frame conditional on Windows only - Add deep-link://new-url event listener for macOS OAuth callbacks - Register cloudreve:// URL scheme via tauri.conf.json deep-link config - Move initial sync to background so add_drive returns immediately - Add HTTP request timeout to prevent indefinite hangs during sync
1 parent 2065ccf commit 10cbc2d

7 files changed

Lines changed: 57 additions & 10 deletions

File tree

crates/cloudreve-api/src/client.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,8 @@ impl Client {
152152
/// Create a new API client
153153
pub fn new(config: ClientConfig) -> Self {
154154
let mut builder = HttpClient::builder()
155-
.connect_timeout(std::time::Duration::from_secs(config.timeout_seconds));
155+
.connect_timeout(std::time::Duration::from_secs(config.timeout_seconds))
156+
.timeout(std::time::Duration::from_secs(config.timeout_seconds));
156157

157158
if let Some(ref user_agent) = config.user_agent {
158159
builder = builder.user_agent(user_agent);

crates/cloudreve-sync/src/drive/manager/mod.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,8 @@ impl DriveManager {
167167
}
168168
}
169169

170-
let mut write_guard = self.drives.write().await;
170+
// Create and start the mount before acquiring the write lock
171+
// to avoid holding the lock during potentially long-running operations
171172
let mut mount = Mount::new(
172173
config.clone(),
173174
self.inventory.clone(),
@@ -185,6 +186,23 @@ impl DriveManager {
185186
.spawn_remote_event_processor(mount_arc.clone())
186187
.await;
187188
mount_arc.spawn_props_refresh_task().await;
189+
190+
// Spawn initial sync in the background so add_drive returns immediately
191+
let mount_for_sync = mount_arc.clone();
192+
tokio::spawn(async move {
193+
let sync_path = mount_for_sync.config.read().await.sync_path.clone();
194+
tracing::info!(target: "drive", id = %mount_for_sync.id, path = %sync_path.display(), "Starting background initial sync");
195+
if let Err(e) = mount_for_sync
196+
.sync_paths(vec![sync_path], crate::drive::sync::SyncMode::FullHierarchy)
197+
.await
198+
{
199+
tracing::error!(target: "drive", id = %mount_for_sync.id, error = ?e, "Background initial sync failed");
200+
} else {
201+
tracing::info!(target: "drive", id = %mount_for_sync.id, "Background initial sync completed");
202+
}
203+
});
204+
205+
let mut write_guard = self.drives.write().await;
188206
let id = mount_arc.id.clone();
189207
write_guard.insert(id.clone(), mount_arc);
190208
Ok(id)

crates/cloudreve-sync/src/drive/mounts.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,8 +387,6 @@ impl Mount {
387387
let sync_path = self.config.read().await.sync_path.clone();
388388
std::fs::create_dir_all(&sync_path).context("failed to create sync directory")?;
389389
self.start_fs_watcher().await?;
390-
self.sync_paths(vec![sync_path], crate::drive::sync::SyncMode::FullHierarchy)
391-
.await?;
392390
return Ok(());
393391
}
394392

src-tauri/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ urlencoding = "2.1"
3838
# Main sync service crate
3939
cloudreve-sync = { path = "../crates/cloudreve-sync" }
4040

41-
tauri-plugin-frame = "1.1.6"
4241
tauri-plugin-http = "2"
4342
tauri-plugin-opener = "2"
4443
tauri-plugin-deep-link = "2.4.9"
4544
tauri-plugin-dialog = "2.7.1"
4645
tauri-plugin-prevent-default = "4"
4746
tauri-plugin-os = "2"
47+
tauri-plugin-frame = "1.1.6"
4848

4949
[target.'cfg(windows)'.dependencies.windows]
5050
version = "0.58.0"

src-tauri/src/commands.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use tauri::{
1414
webview::{WebviewWindow, WebviewWindowBuilder},
1515
AppHandle, Manager, State, WebviewUrl,
1616
};
17+
#[cfg(windows)]
1718
use tauri_plugin_frame::WebviewWindowExt;
1819
use tauri_plugin_positioner::{Position, WindowExt};
1920
use uuid::Uuid;
@@ -630,6 +631,7 @@ fn show_drive_window_internal(app: &AppHandle, title: &str, url_path: &str) {
630631
let _ = window.set_effects(effects);
631632
}
632633
move_window_safely(&window, Position::Center, "add-drive");
634+
#[cfg(windows)]
633635
let _ = window.create_overlay_titlebar();
634636
let _ = window.show();
635637
let _ = window.set_focus();
@@ -693,6 +695,7 @@ pub fn show_settings_window_impl(app: &AppHandle) {
693695
let _ = window.set_effects(effects);
694696
}
695697
move_window_safely(&window, Position::Center, "settings");
698+
#[cfg(windows)]
696699
let _ = window.create_overlay_titlebar();
697700
let _ = window.show();
698701
let _ = window.set_focus();

src-tauri/src/lib.rs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ use tauri::{
88
async_runtime::spawn,
99
menu::{Menu, MenuItem},
1010
tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent},
11-
AppHandle, Emitter, Manager, RunEvent,
11+
AppHandle, Emitter, Listener, Manager, RunEvent,
1212
};
13+
#[cfg(not(target_os = "macos"))]
1314
use tauri_plugin_deep_link::DeepLinkExt;
1415
use tokio::sync::OnceCell;
1516

@@ -258,7 +259,8 @@ pub fn run() {
258259
// Initialize i18n (uses config language setting or falls back to system locale)
259260
init_i18n();
260261

261-
tauri::Builder::default()
262+
#[allow(unused_mut)]
263+
let mut builder = tauri::Builder::default()
262264
.plugin(tauri_plugin_single_instance::init(|app, argv, _cwd| {
263265
tracing::info!("a new app instance was opened with {argv:?} and the deep link event was already triggered");
264266
if argv.len() > 1 {
@@ -268,8 +270,14 @@ pub fn run() {
268270
// when defining deep link schemes at runtime, you must also check `argv` here
269271
}))
270272
.plugin(tauri_plugin_opener::init())
271-
.plugin(tauri_plugin_http::init())
272-
.plugin(tauri_plugin_frame::init())
273+
.plugin(tauri_plugin_http::init());
274+
275+
#[cfg(windows)]
276+
{
277+
builder = builder.plugin(tauri_plugin_frame::init());
278+
}
279+
280+
builder
273281
.plugin(tauri_plugin_deep_link::init())
274282
.plugin(tauri_plugin_dialog::init())
275283
.plugin(tauri_plugin_os::init())
@@ -281,9 +289,21 @@ pub fn run() {
281289
// Setup system tray
282290
setup_tray(app)?;
283291

284-
#[cfg(desktop)]
292+
#[cfg(not(target_os = "macos"))]
285293
app.deep_link().register("cloudreve")?;
286294

295+
// Listen for deep-link events (macOS and Linux)
296+
let app_handle = app.handle().clone();
297+
app.listen("deep-link://new-url", move |event: tauri::Event| {
298+
if let Ok(urls) = serde_json::from_str::<Vec<String>>(event.payload()) {
299+
if let Some(url) = urls.first() {
300+
tracing::info!(target: "main", "Received deep-link URL: {}", url);
301+
let _ = app_handle.emit("deeplink", url.clone());
302+
show_add_drive_window_impl(&app_handle);
303+
}
304+
}
305+
});
306+
287307
// Spawn async setup task - this runs in the background
288308
// while the app continues to start
289309
let app_handle = app.handle().clone();

src-tauri/tauri.conf.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,12 @@
4646
"icons/icon.icns",
4747
"icons/icon.ico"
4848
]
49+
},
50+
"plugins": {
51+
"deep-link": {
52+
"desktop": {
53+
"schemes": ["cloudreve"]
54+
}
55+
}
4956
}
5057
}

0 commit comments

Comments
 (0)