refactor(window-state): simply some code (#2578)

pull/2581/head
Tony 2 months ago committed by GitHub
parent 6fa388d0b2
commit a77b1353e9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -14,13 +14,14 @@ use bitflags::bitflags;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tauri::{ use tauri::{
plugin::{Builder as PluginBuilder, TauriPlugin}, plugin::{Builder as PluginBuilder, TauriPlugin},
Manager, Monitor, PhysicalPosition, PhysicalSize, RunEvent, Runtime, WebviewWindow, Window, AppHandle, Manager, Monitor, PhysicalPosition, PhysicalSize, RunEvent, Runtime, WebviewWindow,
WindowEvent, Window, WindowEvent,
}; };
use std::{ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
fs::{create_dir_all, File}, fs::create_dir_all,
io::BufReader,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
@ -106,6 +107,7 @@ impl Default for WindowState {
struct WindowStateCache(Arc<Mutex<HashMap<String, WindowState>>>); struct WindowStateCache(Arc<Mutex<HashMap<String, WindowState>>>);
/// Used to prevent deadlocks from resize and position event listeners setting the cached state on restoring states /// Used to prevent deadlocks from resize and position event listeners setting the cached state on restoring states
struct RestoringWindowState(Mutex<()>); struct RestoringWindowState(Mutex<()>);
pub trait AppHandleExt { pub trait AppHandleExt {
/// Saves all open windows state to disk /// Saves all open windows state to disk
fn save_window_state(&self, flags: StateFlags) -> Result<()>; fn save_window_state(&self, flags: StateFlags) -> Result<()>;
@ -115,33 +117,31 @@ pub trait AppHandleExt {
impl<R: Runtime> AppHandleExt for tauri::AppHandle<R> { impl<R: Runtime> AppHandleExt for tauri::AppHandle<R> {
fn save_window_state(&self, flags: StateFlags) -> Result<()> { fn save_window_state(&self, flags: StateFlags) -> Result<()> {
if let Ok(app_dir) = self.path().app_config_dir() { let app_dir = self.path().app_config_dir()?;
let plugin_state = self.state::<PluginState>(); let plugin_state = self.state::<PluginState>();
let state_path = app_dir.join(&plugin_state.filename); let state_path = app_dir.join(&plugin_state.filename);
let windows = self.webview_windows(); let windows = self.webview_windows();
let cache = self.state::<WindowStateCache>(); let cache = self.state::<WindowStateCache>();
let mut state = cache.0.lock().unwrap(); let mut state = cache.0.lock().unwrap();
for (label, s) in state.iter_mut() { for (label, s) in state.iter_mut() {
let window = match &plugin_state.map_label { let window = if let Some(map) = &plugin_state.map_label {
Some(map) => windows windows
.iter() .iter()
.find_map(|(l, window)| (map(l) == label).then_some(window)), .find_map(|(l, window)| (map(l) == label).then_some(window))
None => windows.get(label), } else {
}; windows.get(label)
};
if let Some(window) = window {
window.update_state(s, flags)?; if let Some(window) = window {
} window.update_state(s, flags)?;
} }
create_dir_all(&app_dir)
.map_err(Error::Io)
.and_then(|_| File::create(state_path).map_err(Into::into))
.and_then(|mut f| serde_json::to_writer_pretty(&mut f, &*state).map_err(Into::into))
} else {
Ok(())
} }
create_dir_all(app_dir)?;
std::fs::write(state_path, serde_json::to_vec_pretty(&*state)?)?;
Ok(())
} }
fn filename(&self) -> String { fn filename(&self) -> String {
@ -159,6 +159,7 @@ impl<R: Runtime> WindowExt for WebviewWindow<R> {
self.as_ref().window().restore_state(flags) self.as_ref().window().restore_state(flags)
} }
} }
impl<R: Runtime> WindowExt for Window<R> { impl<R: Runtime> WindowExt for Window<R> {
fn restore_state(&self, flags: StateFlags) -> tauri::Result<()> { fn restore_state(&self, flags: StateFlags) -> tauri::Result<()> {
let plugin_state = self.app_handle().state::<PluginState>(); let plugin_state = self.app_handle().state::<PluginState>();
@ -352,7 +353,7 @@ impl Builder {
self self
} }
/// Sets a filter callback to exclude specific windows from being tracked. /// Sets a filter callback to exclude specific windows from being tracked.
/// Return `true` to save the state, or `false` to skip and not save it. /// Return `true` to save the state, or `false` to skip and not save it.
pub fn with_filter<F>(mut self, filter_callback: F) -> Self pub fn with_filter<F>(mut self, filter_callback: F) -> Self
where where
@ -391,25 +392,8 @@ impl Builder {
cmd::filename cmd::filename
]) ])
.setup(|app, _api| { .setup(|app, _api| {
let cache: Arc<Mutex<HashMap<String, WindowState>>> = let cache = load_saved_window_states(app, &filename).unwrap_or_default();
if let Ok(app_dir) = app.path().app_config_dir() { app.manage(WindowStateCache(Arc::new(Mutex::new(cache))));
let state_path = app_dir.join(&filename);
if state_path.exists() {
Arc::new(Mutex::new(
std::fs::read(state_path)
.map_err(Error::from)
.and_then(|state| {
serde_json::from_slice(&state).map_err(Into::into)
})
.unwrap_or_default(),
))
} else {
Default::default()
}
} else {
Default::default()
};
app.manage(WindowStateCache(cache));
app.manage(RestoringWindowState(Mutex::new(()))); app.manage(RestoringWindowState(Mutex::new(())));
app.manage(PluginState { app.manage(PluginState {
filename, filename,
@ -522,6 +506,18 @@ impl Builder {
} }
} }
fn load_saved_window_states<R: Runtime>(
app: &AppHandle<R>,
filename: &String,
) -> Result<HashMap<String, WindowState>> {
let app_dir = app.path().app_config_dir()?;
let state_path = app_dir.join(filename);
let file = std::fs::File::open(state_path)?;
let reader = BufReader::new(file);
let states = serde_json::from_reader(reader)?;
Ok(states)
}
trait MonitorExt { trait MonitorExt {
fn intersects(&self, position: PhysicalPosition<i32>, size: PhysicalSize<u32>) -> bool; fn intersects(&self, position: PhysicalPosition<i32>, size: PhysicalSize<u32>) -> bool;
} }

Loading…
Cancel
Save