refactor(core): return boolean on Manager::manage (#3682)

This commit is contained in:
Lucas Fernandes Nogueira 2022-03-13 11:20:35 -03:00 committed by GitHub
parent c81534ebd8
commit 263b45e1b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 140 additions and 37 deletions

View File

@ -0,0 +1,5 @@
---
"tauri": patch
---
**Breaking change:** The `Manager::manage` function now returns a bool indicating whether the type is already managed or not.

View File

@ -782,10 +782,10 @@ impl<R: Runtime> Builder<R> {
/// This method can be called any number of times as long as each call
/// refers to a different `T`.
///
/// Managed state can be retrieved by any request handler via the
/// [`State`](crate::State) request guard. In particular, if a value of type `T`
/// Managed state can be retrieved by any command handler via the
/// [`State`](crate::State) guard. In particular, if a value of type `T`
/// is managed by Tauri, adding `State<T>` to the list of arguments in a
/// request handler instructs Tauri to retrieve the managed value.
/// command handler instructs Tauri to retrieve the managed value.
///
/// # Panics
///
@ -799,25 +799,29 @@ impl<R: Runtime> Builder<R> {
/// use std::{collections::HashMap, sync::Mutex};
/// use tauri::State;
/// // here we use Mutex to achieve interior mutability
/// struct Storage(Mutex<HashMap<u64, String>>);
/// struct Storage {
/// store: Mutex<HashMap<u64, String>>,
/// }
/// struct Connection;
/// struct DbConnection(Mutex<Option<Connection>>);
/// struct DbConnection {
/// db: Mutex<Option<Connection>>,
/// }
///
/// #[tauri::command]
/// fn connect(connection: State<DbConnection>) {
/// // initialize the connection, mutating the state with interior mutability
/// *connection.0.lock().unwrap() = Some(Connection {});
/// *connection.db.lock().unwrap() = Some(Connection {});
/// }
///
/// #[tauri::command]
/// fn storage_insert(key: u64, value: String, storage: State<Storage>) {
/// // mutate the storage behind the Mutex
/// storage.0.lock().unwrap().insert(key, value);
/// storage.store.lock().unwrap().insert(key, value);
/// }
///
/// tauri::Builder::default()
/// .manage(Storage(Default::default()))
/// .manage(DbConnection(Default::default()))
/// .manage(Storage { store: Default::default() })
/// .manage(DbConnection { db: Default::default() })
/// .invoke_handler(tauri::generate_handler![connect, storage_insert])
/// // on an actual app, remove the string argument
/// .run(tauri::generate_context!("test/fixture/src-tauri/tauri.conf.json"))

View File

@ -544,15 +544,107 @@ pub trait Manager<R: Runtime>: sealed::ManagerBase<R> {
}
/// Add `state` to the state managed by the application.
/// See [`crate::Builder#manage`] for instructions.
fn manage<T>(&self, state: T)
///
/// This method can be called any number of times as long as each call
/// refers to a different `T`.
/// If a state for `T` is already managed, the function returns false and the value is ignored.
///
/// Managed state can be retrieved by any command handler via the
/// [`State`](crate::State) guard. In particular, if a value of type `T`
/// is managed by Tauri, adding `State<T>` to the list of arguments in a
/// command handler instructs Tauri to retrieve the managed value.
///
/// # Panics
///
/// Panics if state of type `T` is already being managed.
///
/// # Mutability
///
/// Since the managed state is global and must be [`Send`] + [`Sync`], mutations can only happen through interior mutability:
///
/// ```rust,no_run
/// use std::{collections::HashMap, sync::Mutex};
/// use tauri::State;
/// // here we use Mutex to achieve interior mutability
/// struct Storage {
/// store: Mutex<HashMap<u64, String>>,
/// }
/// struct Connection;
/// struct DbConnection {
/// db: Mutex<Option<Connection>>,
/// }
///
/// #[tauri::command]
/// fn connect(connection: State<DbConnection>) {
/// // initialize the connection, mutating the state with interior mutability
/// *connection.db.lock().unwrap() = Some(Connection {});
/// }
///
/// #[tauri::command]
/// fn storage_insert(key: u64, value: String, storage: State<Storage>) {
/// // mutate the storage behind the Mutex
/// storage.store.lock().unwrap().insert(key, value);
/// }
///
/// tauri::Builder::default()
/// .manage(Storage { store: Default::default() })
/// .manage(DbConnection { db: Default::default() })
/// .invoke_handler(tauri::generate_handler![connect, storage_insert])
/// // on an actual app, remove the string argument
/// .run(tauri::generate_context!("test/fixture/src-tauri/tauri.conf.json"))
/// .expect("error while running tauri application");
/// ```
///
/// # Examples
///
/// ```rust,no_run
/// use tauri::{Manager, State};
///
/// struct MyInt(isize);
/// struct MyString(String);
///
/// #[tauri::command]
/// fn int_command(state: State<MyInt>) -> String {
/// format!("The stateful int is: {}", state.0)
/// }
///
/// #[tauri::command]
/// fn string_command<'r>(state: State<'r, MyString>) {
/// println!("state: {}", state.inner().0);
/// }
///
/// tauri::Builder::default()
/// .setup(|app| {
/// app.manage(MyInt(0));
/// app.manage(MyString("tauri".into()));
/// // `MyInt` is already managed, so `manage()` returns false
/// assert!(!app.manage(MyInt(1)));
/// // read the `MyInt` managed state with the turbofish syntax
/// let int = app.state::<MyInt>();
/// assert_eq!(int.0, 0);
/// // read the `MyString` managed state with the `State` guard
/// let val: State<MyString> = app.state();
/// assert_eq!(val.0, "tauri");
/// Ok(())
/// })
/// .invoke_handler(tauri::generate_handler![int_command, string_command])
/// // on an actual app, remove the string argument
/// .run(tauri::generate_context!("test/fixture/src-tauri/tauri.conf.json"))
/// .expect("error while running tauri application");
/// ```
fn manage<T>(&self, state: T) -> bool
where
T: Send + Sync + 'static,
{
self.manager().state().set(state);
self.manager().state().set(state)
}
/// Gets the managed state for the type `T`. Panics if the type is not managed.
/// Retrieves the managed state for the type `T`.
///
/// # Panics
///
/// Panics if the state for the type `T` has not been previously [managed](Self::manage).
/// Use [try_state](Self::try_state) for a non-panicking version.
fn state<T>(&self) -> State<'_, T>
where
T: Send + Sync + 'static,
@ -565,7 +657,9 @@ pub trait Manager<R: Runtime>: sealed::ManagerBase<R> {
.expect("state() called before manage() for given type")
}
/// Tries to get the managed state for the type `T`. Returns `None` if the type is not managed.
/// Attempts to retrieve the managed state for the type `T`.
///
/// Returns `Some` if the state has previously been [managed](Self::manage). Otherwise returns `None`.
fn try_state<T>(&self) -> Option<State<'_, T>>
where
T: Send + Sync + 'static,

View File

@ -70,6 +70,7 @@ impl StateManager {
/// Gets the state associated with the specified type.
pub fn get<T: Send + Sync + 'static>(&self) -> State<'_, T> {
self.0.get::<T>();
State(
self
.0

View File

@ -515,12 +515,11 @@ dependencies = [
[[package]]
name = "deflate"
version = "0.8.6"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174"
checksum = "c86f7e25f518f4b81808a2cf1c50996a61f5c2eb394b2393bd87f2a4780a432f"
dependencies = [
"adler32",
"byteorder",
]
[[package]]
@ -1422,15 +1421,6 @@ dependencies = [
"autocfg",
]
[[package]]
name = "miniz_oxide"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
dependencies = [
"adler32",
]
[[package]]
name = "miniz_oxide"
version = "0.4.4"
@ -1441,6 +1431,15 @@ dependencies = [
"autocfg",
]
[[package]]
name = "miniz_oxide"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082"
dependencies = [
"adler",
]
[[package]]
name = "ndk"
version = "0.4.0"
@ -1802,14 +1801,14 @@ dependencies = [
[[package]]
name = "png"
version = "0.16.8"
version = "0.17.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
checksum = "dc38c0ad57efb786dd57b9864e5b18bae478c00c824dc55a38bbc9da95dde3ba"
dependencies = [
"bitflags",
"crc32fast",
"deflate 0.8.6",
"miniz_oxide 0.3.7",
"deflate 1.0.0",
"miniz_oxide 0.5.1",
]
[[package]]
@ -2509,7 +2508,7 @@ dependencies = [
[[package]]
name = "tauri"
version = "1.0.0-rc.3"
version = "1.0.0-rc.4"
dependencies = [
"anyhow",
"bincode",
@ -2550,12 +2549,12 @@ dependencies = [
[[package]]
name = "tauri-codegen"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"base64",
"blake3",
"ico",
"png 0.16.8",
"png 0.17.5",
"proc-macro2",
"quote",
"serde",
@ -2570,7 +2569,7 @@ dependencies = [
[[package]]
name = "tauri-macros"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"heck 0.4.0",
"proc-macro2",
@ -2582,7 +2581,7 @@ dependencies = [
[[package]]
name = "tauri-runtime"
version = "0.3.2"
version = "0.3.3"
dependencies = [
"gtk",
"http",
@ -2599,7 +2598,7 @@ dependencies = [
[[package]]
name = "tauri-runtime-wry"
version = "0.3.2"
version = "0.3.3"
dependencies = [
"gtk",
"tauri-runtime",
@ -2612,7 +2611,7 @@ dependencies = [
[[package]]
name = "tauri-utils"
version = "1.0.0-rc.2"
version = "1.0.0-rc.3"
dependencies = [
"ctor",
"heck 0.4.0",