Merge remote-tracking branch 'origin/dev' into next

This commit is contained in:
FabianLars
2023-04-26 16:56:03 +02:00
76 changed files with 1846 additions and 914 deletions
+1
View File
@@ -0,0 +1 @@
node_modules
+2 -2
View File
@@ -1,7 +1,7 @@
[package]
name = "tauri-plugin-window-state"
version = "0.1.0"
description = "Save window positions and sizse and restore them when the app is reopened."
description = "Save window positions and sizes and restore them when the app is reopened."
authors.workspace = true
license.workspace = true
edition.workspace = true
@@ -16,4 +16,4 @@ tauri.workspace = true
log.workspace = true
thiserror.workspace = true
bincode = "1.3"
bitflags = "1"
bitflags = "2"
+29 -1
View File
@@ -21,6 +21,18 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh
pnpm add https://github.com/tauri-apps/tauri-plugin-window-state
# or
npm add https://github.com/tauri-apps/tauri-plugin-window-state
# or
yarn add https://github.com/tauri-apps/tauri-plugin-window-state
```
## Usage
First you need to register the core plugin with Tauri:
@@ -38,7 +50,7 @@ fn main() {
Afterwards all windows will remember their state when the app is being closed and will restore to their previous state on the next launch.
Optionally you can also tell the plugin to save the state of all open window to disk my using the `save_window_state()` method exposed by the `AppHandleExt` trait:
Optionally you can also tell the plugin to save the state of all open window to disk by using the `save_window_state()` method exposed by the `AppHandleExt` trait:
```rust
use tauri_plugin_window_state::{AppHandleExt, StateFlags};
@@ -47,6 +59,14 @@ use tauri_plugin_window_state::{AppHandleExt, StateFlags};
app.save_window_state(StateFlags::all()); // will save the state of all open windows to disk
```
or through Javascript
```javascript
import { saveWindowState, StateFlags } from "tauri-plugin-window-state-api";
saveWindowState(StateFlags.ALL);
```
To manually restore a windows state from disk you can call the `restore_state()` method exposed by the `WindowExt` trait:
```rust
@@ -56,6 +76,14 @@ use tauri_plugin_window_state::{WindowExt, StateFlags};
window.restore_state(StateFlags::all()); // will restore the windows state from disk
```
or through Javascript
```javascript
import { restoreStateCurrent, StateFlags } from "tauri-plugin-window-state-api";
restoreStateCurrent(StateFlags.ALL);
```
## Contributing
PRs accepted. Please make sure to read the Contributing Guide before making a pull request.
+35
View File
@@ -0,0 +1,35 @@
import { invoke } from "@tauri-apps/api/tauri";
import { WindowLabel, getCurrent } from "@tauri-apps/api/window";
export enum StateFlags {
SIZE = 1 << 0,
POSITION = 1 << 1,
MAXIMIZED = 1 << 2,
VISIBLE = 1 << 3,
DECORATIONS = 1 << 4,
FULLSCREEN = 1 << 5,
ALL = SIZE | POSITION | MAXIMIZED | VISIBLE | DECORATIONS | FULLSCREEN,
}
/**
* Save the state of all open windows to disk.
*/
async function saveWindowState(flags: StateFlags) {
invoke("plugin:window-state|save_window_state", { flags });
}
/**
* Restore the state for the specified window from disk.
*/
async function restoreState(label: WindowLabel, flags: StateFlags) {
invoke("plugin:window-state|restore_state", { label, flags });
}
/**
* Restore the state for the current window from disk.
*/
async function restoreStateCurrent(flags: StateFlags) {
restoreState(getCurrent().label, flags);
}
export { restoreState, restoreStateCurrent, saveWindowState };
+33
View File
@@ -0,0 +1,33 @@
{
"name": "tauri-plugin-window-state-api",
"version": "0.0.0",
"description": "Save window positions and sizes and restore them when the app is reopened.",
"license": "MIT or APACHE-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
],
"type": "module",
"browser": "dist-js/index.min.js",
"module": "dist-js/index.mjs",
"types": "dist-js/index.d.ts",
"exports": {
"import": "./dist-js/index.mjs",
"types": "./dist-js/index.d.ts",
"browser": "./dist-js/index.min.js"
},
"scripts": {
"build": "rollup -c"
},
"files": [
"dist-js",
"!dist-js/**/*.map",
"README.md",
"LICENSE"
],
"devDependencies": {
"tslib": "^2.5.0"
},
"dependencies": {
"@tauri-apps/api": "^1.2.0"
}
}
+11
View File
@@ -0,0 +1,11 @@
import { readFileSync } from "fs";
import { createConfig } from "../../shared/rollup.config.mjs";
export default createConfig({
input: "guest-js/index.ts",
pkg: JSON.parse(
readFileSync(new URL("./package.json", import.meta.url), "utf8")
),
external: [/^@tauri-apps\/api/],
});
+28
View File
@@ -0,0 +1,28 @@
use crate::{AppHandleExt, StateFlags, WindowExt};
use tauri::{command, AppHandle, Manager, Runtime};
#[command]
pub async fn save_window_state<R: Runtime>(
app: AppHandle<R>,
flags: u32,
) -> std::result::Result<(), String> {
let flags = StateFlags::from_bits(flags)
.ok_or_else(|| format!("Invalid state flags bits: {}", flags))?;
app.save_window_state(flags).map_err(|e| e.to_string())?;
Ok(())
}
#[command]
pub async fn restore_state<R: Runtime>(
app: AppHandle<R>,
label: String,
flags: u32,
) -> std::result::Result<(), String> {
let flags = StateFlags::from_bits(flags)
.ok_or_else(|| format!("Invalid state flags bits: {}", flags))?;
app.get_window(&label)
.ok_or_else(|| format!("Couldn't find window with label: {}", label))?
.restore_state(flags)
.map_err(|e| e.to_string())?;
Ok(())
}
+28 -2
View File
@@ -17,6 +17,8 @@ use std::{
sync::{Arc, Mutex},
};
mod cmd;
pub const STATE_FILENAME: &str = ".window-state";
#[derive(Debug, thiserror::Error)]
@@ -34,6 +36,7 @@ pub enum Error {
pub type Result<T> = std::result::Result<T, Error>;
bitflags! {
#[derive(Clone, Copy, Debug)]
pub struct StateFlags: u32 {
const SIZE = 1 << 0;
const POSITION = 1 << 1;
@@ -50,7 +53,7 @@ impl Default for StateFlags {
}
}
#[derive(Debug, Default, Deserialize, Serialize)]
#[derive(Debug, Default, Deserialize, Serialize, PartialEq)]
struct WindowState {
width: f64,
height: f64,
@@ -64,6 +67,7 @@ struct WindowState {
struct WindowStateCache(Arc<Mutex<HashMap<String, WindowState>>>);
pub trait AppHandleExt {
/// Saves all open windows state to disk
fn save_window_state(&self, flags: StateFlags) -> Result<()>;
}
@@ -93,6 +97,7 @@ impl<R: Runtime> AppHandleExt for tauri::AppHandle<R> {
}
pub trait WindowExt {
/// Restores this window state from disk
fn restore_state(&self, flags: StateFlags) -> tauri::Result<()>;
}
@@ -100,9 +105,15 @@ impl<R: Runtime> WindowExt for Window<R> {
fn restore_state(&self, flags: StateFlags) -> tauri::Result<()> {
let cache = self.state::<WindowStateCache>();
let mut c = cache.0.lock().unwrap();
let mut should_show = true;
if let Some(state) = c.get(self.label()) {
// avoid restoring the default zeroed state
if *state == WindowState::default() {
return Ok(());
}
if flags.contains(StateFlags::DECORATIONS) {
self.set_decorations(state.decorated)?;
}
@@ -225,7 +236,7 @@ impl<R: Runtime> WindowExtInternal for Window<R> {
}
if flags.contains(StateFlags::POSITION) {
let position = self.inner_position()?;
let position = self.outer_position()?;
if let Ok(Some(monitor)) = self.current_monitor() {
// save only window positions that are inside the current monitor
if monitor.contains(position) && !is_maximized {
@@ -269,6 +280,10 @@ impl Builder {
pub fn build<R: Runtime>(self) -> TauriPlugin<R> {
let flags = self.state_flags;
PluginBuilder::new("window-state")
.invoke_handler(tauri::generate_handler![
cmd::save_window_state,
cmd::restore_state
])
.setup(|app, _api| {
let cache: Arc<Mutex<HashMap<String, WindowState>>> = if let Ok(app_dir) =
app.path().app_config_dir()
@@ -304,6 +319,17 @@ impl Builder {
let label = window.label().to_string();
let window_clone = window.clone();
let flags = self.state_flags;
// 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())
.or_insert_with(WindowState::default);
}
window.on_window_event(move |e| {
if let WindowEvent::CloseRequested { .. } = e {
let mut c = cache.lock().unwrap();
+1
View File
@@ -0,0 +1 @@
../../shared/tsconfig.json