From 9a32cb9ccdc6dd576bac567912fe1e5e51c36d06 Mon Sep 17 00:00:00 2001 From: luohy Date: Thu, 3 Aug 2023 11:38:18 +0800 Subject: [PATCH] feat(window-state): add group --- plugins/window-state/src/lib.rs | 74 ++++++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 14 deletions(-) diff --git a/plugins/window-state/src/lib.rs b/plugins/window-state/src/lib.rs index f17201ca..810b526e 100644 --- a/plugins/window-state/src/lib.rs +++ b/plugins/window-state/src/lib.rs @@ -4,11 +4,7 @@ use bitflags::bitflags; use serde::{Deserialize, Serialize}; -use tauri::{ - plugin::{Builder as PluginBuilder, TauriPlugin}, - LogicalSize, Manager, Monitor, PhysicalPosition, PhysicalSize, RunEvent, Runtime, Window, - WindowEvent, -}; +use tauri::{plugin::{Builder as PluginBuilder, TauriPlugin}, LogicalSize, Manager, Monitor, PhysicalPosition, PhysicalSize, RunEvent, Runtime, Window, WindowEvent, State, AppHandle}; use std::{ collections::{HashMap, HashSet}, @@ -80,7 +76,8 @@ impl Default for WindowState { } } -struct WindowStateCache(Arc>>); +struct WindowStateCache(Arc>>); +struct GroupStateCache(Arc>>); pub trait AppHandleExt { /// Saves all open windows state to disk fn save_window_state(&self, flags: StateFlags) -> Result<()>; @@ -92,10 +89,14 @@ impl AppHandleExt for tauri::AppHandle { let state_path = app_dir.join(STATE_FILENAME); let cache = self.state::(); let mut state = cache.0.lock().unwrap(); - for (label, s) in state.iter_mut() { - if let Some(window) = self.get_window(label) { - window.update_state(s, flags)?; - } + + let groups = self.state::(); + let binding = groups.0.clone(); + let binding = binding.lock().unwrap(); + let groups = binding.as_ref(); + + for window in self.windows().values() { + window.update_state(state.get(group_name(groups, window.label().into())), flags)?; } create_dir_all(&app_dir) @@ -111,6 +112,13 @@ impl AppHandleExt for tauri::AppHandle { } } +fn group_name_by_state(groups: State, label: String) { + let binding = groups.0.clone(); + let binding = binding.lock().unwrap(); + let groups = binding.as_ref(); + let key = group_name(groups, label); +} + pub trait WindowExt { /// Restores this window state from disk fn restore_state(&self, flags: StateFlags) -> tauri::Result<()>; @@ -121,9 +129,12 @@ impl WindowExt for Window { let cache = self.state::(); let mut c = cache.0.lock().unwrap(); + let groups = self.state::(); + let key = group_name_by_state(groups, self.label().into()); + let mut should_show = true; - if let Some(state) = c.get(self.label()) { + if let Some(state) = c.get(key) { // avoid restoring the default zeroed state if *state == WindowState::default() { return Ok(()); @@ -197,7 +208,7 @@ impl WindowExt for Window { metadata.fullscreen = self.is_fullscreen()?; } - c.insert(self.label().into(), metadata); + c.insert(key.into(), metadata); } if flags.contains(StateFlags::VISIBLE) && should_show { @@ -265,11 +276,36 @@ impl WindowExtInternal for Window { } } +pub struct Group { + name: String, + match_rule: fn(&String) -> bool, +} + +impl Group { + pub fn new(name: String, match_rule: fn(&String) -> bool) -> Group { + Group { name, match_rule } + } + + pub fn filter(&self, label: &String) -> bool { + (self.match_rule)(label) + } +} + +/// get group name which match first rule +pub fn group_name(groups: &Vec, label: String) -> String { + groups + .iter() + .filter(|g| g.filter(&label)) + .nth(0) + .map_or(label, |g| g.name.clone()) +} + #[derive(Default)] pub struct Builder { denylist: HashSet, skip_initial_state: HashSet, state_flags: StateFlags, + groups: Vec, } impl Builder { @@ -292,6 +328,12 @@ impl Builder { self } + /// add group + pub fn add_group(mut self, group: Group) -> Self { + self.groups.push(group); + self + } + pub fn build(self) -> TauriPlugin { let flags = self.state_flags; PluginBuilder::new("window-state") @@ -318,6 +360,7 @@ impl Builder { Default::default() }; app.manage(WindowStateCache(cache)); + app.manage(GroupStateCache(Arc::new(Mutex::new(self.groups)))); Ok(()) }) .on_webview_ready(move |window| { @@ -335,20 +378,23 @@ impl Builder { let window_clone = window.clone(); let flags = self.state_flags; + let groups = window.state::(); + let key = group_name_by_state(groups, label); + // insert a default state if this window should be tracked and // the disk cache doesn't have a state for it { cache .lock() .unwrap() - .entry(label.clone()) + .entry(key) .or_insert_with(WindowState::default); } window.on_window_event(move |e| { if let WindowEvent::CloseRequested { .. } = e { let mut c = cache.lock().unwrap(); - if let Some(state) = c.get_mut(&label) { + if let Some(state) = c.get_mut(&key) { let _ = window_clone.update_state(state, flags); } }