Skip to content

Commit

Permalink
Fix Replay Sync Checkbox (#69)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
ryantaylor authored Feb 23, 2024
1 parent 31ef303 commit 952b56b
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 35 deletions.
2 changes: 1 addition & 1 deletion src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,17 @@ fn main() {
}

fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
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))
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/src/plugins/cohdb/auth/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ async fn authenticate<R: Runtime>(handle: AppHandle<R>) -> Result<String> {
*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())
}

Expand Down
75 changes: 43 additions & 32 deletions src-tauri/src/plugins/cohdb/sync/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,48 @@ 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<R: Runtime> {
#[derive(Debug, Default)]
pub struct State {
playback_watcher: Mutex<Option<RecommendedWatcher>>,
store: Store<R>,
}

pub fn init<R: Runtime>() -> TauriPlugin<R> {
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<R: Runtime>(handle: AppHandle<R>) {
let state = handle.state::<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<R: Runtime>(handle: AppHandle<R>) -> EventHandler {
let handle_ = handle.clone();
handle.listen_global("playback-dir-changed", move |event| {
let dir: String = serde_json::from_str(event.payload().unwrap()).unwrap();

info!("playback directory changed to {dir}");

*handle_.state::<State<R>>().playback_watcher.lock().unwrap() =
*handle_.state::<State>().playback_watcher.lock().unwrap() =
init_watcher(PathBuf::from(dir), handle_.clone());
})
}
Expand Down Expand Up @@ -81,12 +80,12 @@ async fn handle_modify_event<R: Runtime>(event: Event, handle: AppHandle<R>) {
return;
};

if let Some(enabled) = handle.state::<State<R>>().store.get("autoSyncReplays") {
if !serde_json::from_value::<bool>(enabled.clone()).unwrap() {
if let Some(enabled) = load_from_store::<R, bool>(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()) {
Expand Down Expand Up @@ -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<R: Runtime>(handle: AppHandle<R>) -> Store<R> {
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<R: Runtime, T: DeserializeOwned>(handle: AppHandle<R>, key: &str) -> Option<T> {
let stores = handle.state::<StoreCollection<R>>();
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<R: Runtime>(store: &Store<R>) -> String {
if let Some(path) = store.get("playbackPath") {
serde_json::from_value(path.clone()).unwrap()
fn load_playback_path<R: Runtime>(handle: AppHandle<R>) -> String {
if let Some(path) = load_from_store::<R, String>(handle, "playbackPath") {
path
} else {
default_playback_path()
}
Expand Down

0 comments on commit 952b56b

Please sign in to comment.