From aad2d964eb4ac9c705bda48ee02f07ffbffe9f4e Mon Sep 17 00:00:00 2001 From: DecDuck Date: Sat, 26 Jul 2025 17:57:12 +1000 Subject: [PATCH] fix: app states --- app.vue | 1 + src-tauri/src/client/cleanup.rs | 7 ++-- src-tauri/src/client/commands.rs | 8 +++-- src-tauri/src/download_manager/commands.rs | 28 ++++++++------- src-tauri/src/lib.rs | 40 ++++++++++++---------- src-tauri/src/remote/commands.rs | 7 ++-- src-tauri/src/remote/utils.rs | 5 ++- 7 files changed, 53 insertions(+), 43 deletions(-) diff --git a/app.vue b/app.vue index b9011c6..d82b152 100644 --- a/app.vue +++ b/app.vue @@ -22,6 +22,7 @@ const router = useRouter(); const state = useAppState(); try { state.value = JSON.parse(await invoke("fetch_state")); + console.log(state.value) } catch (e) { console.error("failed to parse state", e); } diff --git a/src-tauri/src/client/cleanup.rs b/src-tauri/src/client/cleanup.rs index 0cd0827..c3322e4 100644 --- a/src-tauri/src/client/cleanup.rs +++ b/src-tauri/src/client/cleanup.rs @@ -1,10 +1,11 @@ use log::{debug, error}; use tauri::AppHandle; +use tokio::sync::Mutex; use crate::AppState; #[tauri::command] -pub async fn quit(app: tauri::AppHandle, state: tauri::State<'_, std::sync::Mutex>>) -> Result<(), ()> { +pub async fn quit(app: tauri::AppHandle, state: tauri::State<'_, Mutex>>) -> Result<(), ()> { cleanup_and_exit(&app, &state).await; Ok(()) @@ -12,10 +13,10 @@ pub async fn quit(app: tauri::AppHandle, state: tauri::State<'_, std::sync::Mute pub async fn cleanup_and_exit( app: &AppHandle, - state: &tauri::State<'_, std::sync::Mutex>>, + state: &tauri::State<'_, Mutex>>, ) { debug!("cleaning up and exiting application"); - let download_manager = state.lock().unwrap().download_manager.clone(); + let download_manager = state.lock().await.download_manager.clone(); match download_manager.ensure_terminated().await { Ok(res) => match res { Ok(_) => debug!("download manager terminated correctly"), diff --git a/src-tauri/src/client/commands.rs b/src-tauri/src/client/commands.rs index b47a348..635233d 100644 --- a/src-tauri/src/client/commands.rs +++ b/src-tauri/src/client/commands.rs @@ -1,10 +1,12 @@ +use tokio::sync::Mutex; + use crate::AppState; #[tauri::command] -pub fn fetch_state( - state: tauri::State<'_, std::sync::Mutex>>, +pub async fn fetch_state( + state: tauri::State<'_, Mutex>>, ) -> Result { - let guard = state.lock().unwrap(); + let guard = state.lock().await; let cloned_state = serde_json::to_string(&guard.clone()).map_err(|e| e.to_string())?; drop(guard); Ok(cloned_state) diff --git a/src-tauri/src/download_manager/commands.rs b/src-tauri/src/download_manager/commands.rs index 5156f30..8bcb350 100644 --- a/src-tauri/src/download_manager/commands.rs +++ b/src-tauri/src/download_manager/commands.rs @@ -1,31 +1,35 @@ -use std::sync::Mutex; +use tokio::sync::Mutex; use crate::{database::models::data::DownloadableMetadata, AppState}; #[tauri::command] -pub fn pause_downloads(state: tauri::State<'_, Mutex>) { - state.lock().unwrap().download_manager.pause_downloads() +pub async fn pause_downloads(state: tauri::State<'_, Mutex>>) -> Result<(), ()> { + state.lock().await.download_manager.pause_downloads(); + Ok(()) } #[tauri::command] -pub fn resume_downloads(state: tauri::State<'_, Mutex>) { - state.lock().unwrap().download_manager.resume_downloads() +pub async fn resume_downloads(state: tauri::State<'_, Mutex>>) -> Result<(), ()> { + state.lock().await.download_manager.resume_downloads(); + Ok(()) } #[tauri::command] -pub fn move_download_in_queue( - state: tauri::State<'_, Mutex>, +pub async fn move_download_in_queue( + state: tauri::State<'_, Mutex>>, old_index: usize, new_index: usize, -) { +) -> Result<(), ()> { state .lock() - .unwrap() + .await .download_manager - .rearrange(old_index, new_index) + .rearrange(old_index, new_index); + Ok(()) } #[tauri::command] -pub fn cancel_game(state: tauri::State<'_, Mutex>, meta: DownloadableMetadata) { - state.lock().unwrap().download_manager.cancel(meta) +pub async fn cancel_game(state: tauri::State<'_, Mutex>>, meta: DownloadableMetadata) -> Result<(), ()> { + state.lock().await.download_manager.cancel(meta); + Ok(()) } diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 32bb261..a7223e5 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -58,6 +58,7 @@ use remote::commands::{ use remote::fetch_object::{fetch_object, fetch_object_offline}; use remote::server_proto::{handle_server_proto, handle_server_proto_offline}; use serde::{Deserialize, Serialize}; +use std::collections::HashMap; use std::fs::File; use std::io::Write; use std::panic::PanicHookInfo; @@ -65,13 +66,13 @@ use std::path::Path; use std::str::FromStr; use std::sync::Arc; use std::time::SystemTime; -use std::collections::HashMap; use std::{env, panic}; use tauri::menu::{Menu, MenuItem, PredefinedMenuItem}; use tauri::tray::TrayIconBuilder; use tauri::{AppHandle, Manager, RunEvent, WindowEvent}; use tauri_plugin_deep_link::DeepLinkExt; use tauri_plugin_dialog::DialogExt; +use tokio::runtime::Handle; use tokio::sync::Mutex; #[derive(Clone, Copy, Serialize, Eq, PartialEq)] @@ -317,11 +318,14 @@ pub async fn run() { )) .setup(|app| { let app = app.handle().clone(); + let runtime = Handle::current(); - tauri::async_runtime::spawn(async move { + runtime.spawn(async move { let state = setup(app.clone()).await; - debug!("initialized drop client"); - app.manage(Mutex::new(state)); + info!("initialized drop client"); + if !app.manage(Mutex::new(state)) { + panic!("failed to setup drop state before Tauri does") + } { use tauri_plugin_deep_link::DeepLinkExt; @@ -329,20 +333,6 @@ pub async fn run() { debug!("registered all pre-defined deep links"); } - let _main_window = tauri::WebviewWindowBuilder::new( - &app, - "main", // BTW this is not the name of the window, just the label. Keep this 'main', there are permissions & configs that depend on it - tauri::WebviewUrl::App("index.html".into()), - ) - .title("Drop Desktop App") - .min_inner_size(1000.0, 500.0) - .inner_size(1536.0, 864.0) - .decorations(false) - .shadow(false) - .data_directory(DATA_ROOT_DIR.join(".webview")) - .build() - .unwrap(); - let deep_link_handle = app.clone(); app.deep_link().on_open_url(move |event| { @@ -413,6 +403,20 @@ pub async fn run() { .show(|_| {}); } }; + + let _main_window = tauri::WebviewWindowBuilder::new( + &app, + "main", // BTW this is not the name of the window, just the label. Keep this 'main', there are permissions & configs that depend on it + tauri::WebviewUrl::App("index.html".into()), + ) + .title("Drop Desktop App") + .min_inner_size(1000.0, 500.0) + .inner_size(1536.0, 864.0) + .decorations(false) + .shadow(false) + .data_directory(DATA_ROOT_DIR.join(".webview")) + .build() + .unwrap(); }); Ok(()) }) diff --git a/src-tauri/src/remote/commands.rs b/src-tauri/src/remote/commands.rs index 24db1a9..28bde66 100644 --- a/src-tauri/src/remote/commands.rs +++ b/src-tauri/src/remote/commands.rs @@ -1,8 +1,7 @@ -use std::sync::Mutex; - use log::debug; use reqwest::Client; use tauri::{AppHandle, Emitter, Manager}; +use tokio::sync::Mutex; use url::Url; use crate::{ @@ -72,7 +71,7 @@ pub async fn sign_out(app: AppHandle) { // Update app state { let app_state = app.state::>(); - let mut app_state_handle = app_state.lock().unwrap(); + let mut app_state_handle = app_state.lock().await; app_state_handle.status = AppStatus::SignedOut; app_state_handle.user = None; } @@ -85,7 +84,7 @@ pub async fn sign_out(app: AppHandle) { pub async fn retry_connect(state: tauri::State<'_, Mutex>>) -> Result<(), ()> { let (app_status, user) = setup().await; - let mut guard = state.lock().unwrap(); + let mut guard = state.lock().await; guard.status = app_status; guard.user = user; drop(guard); diff --git a/src-tauri/src/remote/utils.rs b/src-tauri/src/remote/utils.rs index 60b84ef..aa0acf2 100644 --- a/src-tauri/src/remote/utils.rs +++ b/src-tauri/src/remote/utils.rs @@ -1,7 +1,6 @@ -use std::sync::Mutex; - use log::{debug, warn}; use serde::Deserialize; +use tokio::sync::Mutex; use url::Url; use crate::{ @@ -34,7 +33,7 @@ pub async fn use_remote_logic( } { - let mut app_state = state.lock().unwrap(); + let mut app_state = state.lock().await; app_state.status = AppStatus::SignedOut; }