mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-09-26 21:41:48 +02:00
feat(window-state): add Builder::map_label method (#1497)
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"window-state": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Add `Builder::map_label` option to transform the window label when saving the window state, this could be used to group different windows to use the same state.
|
||||||
@@ -28,6 +28,8 @@ use std::{
|
|||||||
|
|
||||||
mod cmd;
|
mod cmd;
|
||||||
|
|
||||||
|
type LabelMapperFn = dyn Fn(&str) -> &str + Send + Sync;
|
||||||
|
|
||||||
/// Default filename used to store window state.
|
/// Default filename used to store window state.
|
||||||
///
|
///
|
||||||
/// If using a custom filename, you should probably use [`AppHandleExt::filename`] instead.
|
/// If using a custom filename, you should probably use [`AppHandleExt::filename`] instead.
|
||||||
@@ -65,6 +67,7 @@ impl Default for StateFlags {
|
|||||||
|
|
||||||
struct PluginState {
|
struct PluginState {
|
||||||
filename: String,
|
filename: String,
|
||||||
|
map_label: Option<Box<LabelMapperFn>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, PartialEq)]
|
#[derive(Debug, Deserialize, Serialize, PartialEq)]
|
||||||
@@ -114,10 +117,19 @@ impl<R: Runtime> AppHandleExt for tauri::AppHandle<R> {
|
|||||||
if let Ok(app_dir) = self.path().app_config_dir() {
|
if let Ok(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 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() {
|
||||||
if let Some(window) = self.get_webview_window(label) {
|
let window = match &plugin_state.map_label {
|
||||||
|
Some(map) => windows
|
||||||
|
.iter()
|
||||||
|
.find_map(|(l, window)| (map(l) == label).then_some(window)),
|
||||||
|
None => windows.get(label),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(window) = window {
|
||||||
window.update_state(s, flags)?;
|
window.update_state(s, flags)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -148,13 +160,20 @@ impl<R: Runtime> WindowExt for WebviewWindow<R> {
|
|||||||
}
|
}
|
||||||
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 label = plugin_state
|
||||||
|
.map_label
|
||||||
|
.as_ref()
|
||||||
|
.map(|map| map(self.label()))
|
||||||
|
.unwrap_or_else(|| self.label());
|
||||||
|
|
||||||
let cache = self.state::<WindowStateCache>();
|
let cache = self.state::<WindowStateCache>();
|
||||||
let mut c = cache.0.lock().unwrap();
|
let mut c = cache.0.lock().unwrap();
|
||||||
|
|
||||||
let mut should_show = true;
|
let mut should_show = true;
|
||||||
|
|
||||||
if let Some(state) = c
|
if let Some(state) = c
|
||||||
.get(self.label())
|
.get(label)
|
||||||
.filter(|state| state != &&WindowState::default())
|
.filter(|state| state != &&WindowState::default())
|
||||||
{
|
{
|
||||||
if flags.contains(StateFlags::DECORATIONS) {
|
if flags.contains(StateFlags::DECORATIONS) {
|
||||||
@@ -235,7 +254,7 @@ impl<R: Runtime> WindowExt for Window<R> {
|
|||||||
metadata.fullscreen = self.is_fullscreen()?;
|
metadata.fullscreen = self.is_fullscreen()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
c.insert(self.label().into(), metadata);
|
c.insert(label.into(), metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags.contains(StateFlags::VISIBLE) && should_show {
|
if flags.contains(StateFlags::VISIBLE) && should_show {
|
||||||
@@ -309,6 +328,7 @@ pub struct Builder {
|
|||||||
denylist: HashSet<String>,
|
denylist: HashSet<String>,
|
||||||
skip_initial_state: HashSet<String>,
|
skip_initial_state: HashSet<String>,
|
||||||
state_flags: StateFlags,
|
state_flags: StateFlags,
|
||||||
|
map_label: Option<Box<LabelMapperFn>>,
|
||||||
filename: Option<String>,
|
filename: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,9 +362,21 @@ impl Builder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Transforms the window label when saving the window state.
|
||||||
|
///
|
||||||
|
/// This can be used to group different windows to use the same state.
|
||||||
|
pub fn map_label<F>(mut self, map_fn: F) -> Self
|
||||||
|
where
|
||||||
|
F: Fn(&str) -> &str + Sync + Send + 'static,
|
||||||
|
{
|
||||||
|
self.map_label = Some(Box::new(map_fn));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build<R: Runtime>(self) -> TauriPlugin<R> {
|
pub fn build<R: Runtime>(self) -> TauriPlugin<R> {
|
||||||
let flags = self.state_flags;
|
let flags = self.state_flags;
|
||||||
let filename = self.filename.unwrap_or_else(|| DEFAULT_FILENAME.into());
|
let filename = self.filename.unwrap_or_else(|| DEFAULT_FILENAME.into());
|
||||||
|
let map_label = self.map_label;
|
||||||
|
|
||||||
PluginBuilder::new("window-state")
|
PluginBuilder::new("window-state")
|
||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
@@ -372,21 +404,31 @@ impl Builder {
|
|||||||
Default::default()
|
Default::default()
|
||||||
};
|
};
|
||||||
app.manage(WindowStateCache(cache));
|
app.manage(WindowStateCache(cache));
|
||||||
app.manage(PluginState { filename });
|
app.manage(PluginState {
|
||||||
|
filename,
|
||||||
|
map_label,
|
||||||
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.on_window_ready(move |window| {
|
.on_window_ready(move |window| {
|
||||||
if self.denylist.contains(window.label()) {
|
let plugin_state = window.app_handle().state::<PluginState>();
|
||||||
|
let label = plugin_state
|
||||||
|
.map_label
|
||||||
|
.as_ref()
|
||||||
|
.map(|map| map(window.label()))
|
||||||
|
.unwrap_or_else(|| window.label());
|
||||||
|
|
||||||
|
if self.denylist.contains(label) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.skip_initial_state.contains(window.label()) {
|
if !self.skip_initial_state.contains(label) {
|
||||||
let _ = window.restore_state(self.state_flags);
|
let _ = window.restore_state(self.state_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
let cache = window.state::<WindowStateCache>();
|
let cache = window.state::<WindowStateCache>();
|
||||||
let cache = cache.0.clone();
|
let cache = cache.0.clone();
|
||||||
let label = window.label().to_string();
|
let label = label.to_string();
|
||||||
let window_clone = window.clone();
|
let window_clone = window.clone();
|
||||||
let flags = self.state_flags;
|
let flags = self.state_flags;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user