From 952b56b566dbd559f95a2ac8a8d1beb746e20a87 Mon Sep 17 00:00:00 2001 From: Ryan Taylor <2320507+ryantaylor@users.noreply.github.com> Date: Fri, 23 Feb 2024 04:34:20 -0500 Subject: [PATCH] Fix Replay Sync Checkbox (#69) * Misc cleanup. * Refactor to use proper store accessors. * Try with absolute path to store file. * Defer sync setup till after app init. * Remove test tracing. --- src-tauri/Cargo.lock | 2 +- src-tauri/src/main.rs | 7 ++- src-tauri/src/plugins/cohdb/auth/mod.rs | 2 +- src-tauri/src/plugins/cohdb/sync/mod.rs | 75 ++++++++++++++----------- 4 files changed, 51 insertions(+), 35 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 72a73ea..d69a35f 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -706,7 +706,7 @@ dependencies = [ [[package]] name = "coh3-stats-desktop-app" -version = "1.2.6" +version = "1.2.7" dependencies = [ "criterion", "keyring", diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index d6853a6..413ca5e 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -67,12 +67,17 @@ fn main() { } fn setup(app: &mut tauri::App) -> Result<(), Box> { + let handle = app.handle(); + + // Set up sync handling + // This needs to happen here because it depends on other plugins + cohdb::sync::setup(handle.clone()); + // Add window shadows let window = app.get_window("main").unwrap(); set_shadow(&window, true).expect("Unsupported platform!"); // Set up deep link - let handle = app.handle(); tauri_plugin_deep_link::register("coh3stats", move |request| { if let Err(err) = tauri::async_runtime::block_on(cohdb::auth::retrieve_token(&request, &handle)) diff --git a/src-tauri/src/plugins/cohdb/auth/mod.rs b/src-tauri/src/plugins/cohdb/auth/mod.rs index 4427506..027674b 100644 --- a/src-tauri/src/plugins/cohdb/auth/mod.rs +++ b/src-tauri/src/plugins/cohdb/auth/mod.rs @@ -96,7 +96,7 @@ async fn authenticate(handle: AppHandle) -> Result { *state.request.lock().await = Some(request); info!("redirecting to auth URL: {auth_url}"); - open(&handle.shell_scope(), auth_url.clone(), None).map_err(Shell); + open(&handle.shell_scope(), auth_url.clone(), None).map_err(Shell)?; Ok(auth_url.to_string()) } diff --git a/src-tauri/src/plugins/cohdb/sync/mod.rs b/src-tauri/src/plugins/cohdb/sync/mod.rs index 62c9576..85c3c7e 100644 --- a/src-tauri/src/plugins/cohdb/sync/mod.rs +++ b/src-tauri/src/plugins/cohdb/sync/mod.rs @@ -3,41 +3,40 @@ use std::{path::PathBuf, sync::Mutex}; use auth::responses::User; use log::{debug, error, info, warn}; use notify::{Config, Event, RecommendedWatcher, RecursiveMode, Watcher}; +use serde::de::DeserializeOwned; use tauri::{ plugin::{Builder, TauriPlugin}, AppHandle, EventHandler, Manager, Runtime, }; -use tauri_plugin_store::{Store, StoreBuilder}; +use tauri_plugin_store::{with_store, StoreCollection}; use vault::{GameType, Replay}; use super::auth; -#[derive(Debug)] -pub struct State { +#[derive(Debug, Default)] +pub struct State { playback_watcher: Mutex>, - store: Store, } pub fn init() -> TauriPlugin { Builder::new("cohdbsync") .invoke_handler(tauri::generate_handler![]) .setup(|app| { - let store = load_store(app.clone()); - let path = PathBuf::from(load_playback_path(&store)); - let watcher = init_watcher(path, app.clone()); - - app.manage(State { - playback_watcher: Mutex::new(watcher), - store, - }); - - listen_for_changes(app.clone()); - + app.manage(State::default()); Ok(()) }) .build() } +pub fn setup(handle: AppHandle) { + let state = handle.state::(); + let path = PathBuf::from(load_playback_path(handle.clone())); + let watcher = init_watcher(path, handle.clone()); + + *state.playback_watcher.lock().unwrap() = watcher; + listen_for_changes(handle.clone()); +} + pub fn listen_for_changes(handle: AppHandle) -> EventHandler { let handle_ = handle.clone(); handle.listen_global("playback-dir-changed", move |event| { @@ -45,7 +44,7 @@ pub fn listen_for_changes(handle: AppHandle) -> EventHandler { info!("playback directory changed to {dir}"); - *handle_.state::>().playback_watcher.lock().unwrap() = + *handle_.state::().playback_watcher.lock().unwrap() = init_watcher(PathBuf::from(dir), handle_.clone()); }) } @@ -81,12 +80,12 @@ async fn handle_modify_event(event: Event, handle: AppHandle) { return; }; - if let Some(enabled) = handle.state::>().store.get("autoSyncReplays") { - if !serde_json::from_value::(enabled.clone()).unwrap() { + if let Some(enabled) = load_from_store::(handle.clone(), "autoSyncReplays") { + if !enabled { info!("auto-sync disabled, skipping sync"); return; } - } + }; let path = event.paths[0].clone(); let bytes = match std::fs::read(path.clone()) { @@ -136,23 +135,35 @@ fn includes_user(replay: &Replay, user: &User) -> bool { .any(|player| player.profile_id().is_some() && player.profile_id() == user.profile_id) } -fn load_store(handle: AppHandle) -> Store { - let mut store = StoreBuilder::new(handle, PathBuf::from("config.dat")).build(); - - if let Err(err) = store.load() { - warn!("error loading store from disk: {err}"); - info!("saving store file to disk"); - if let Err(err) = store.save() { - warn!("error saving store file to disk: {err}"); +fn load_from_store(handle: AppHandle, key: &str) -> Option { + let stores = handle.state::>(); + let path = handle + .path_resolver() + .app_data_dir() + .unwrap() + .join("config.dat"); + + match with_store(handle.clone(), stores, path, |store| { + Ok(store.get(key).cloned()) + }) { + Ok(Some(value)) => match serde_json::from_value(value.clone()) { + Ok(result) => Some(result), + Err(err) => { + error!("error deserializing store value at {key}: {err}"); + None + } + }, + Ok(None) => None, + Err(err) => { + error!("error retrieving store value at {key}: {err}"); + None } } - - store } -fn load_playback_path(store: &Store) -> String { - if let Some(path) = store.get("playbackPath") { - serde_json::from_value(path.clone()).unwrap() +fn load_playback_path(handle: AppHandle) -> String { + if let Some(path) = load_from_store::(handle, "playbackPath") { + path } else { default_playback_path() }