diff --git a/Cargo.lock b/Cargo.lock index 5696267..c7afd88 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3319,7 +3319,7 @@ dependencies = [ [[package]] name = "tauri-interop" -version = "2.1.0" +version = "2.1.1" dependencies = [ "js-sys", "leptos", @@ -3327,7 +3327,7 @@ dependencies = [ "serde", "serde-wasm-bindgen", "tauri", - "tauri-interop-macro 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tauri-interop-macro", "thiserror", "wasm-bindgen", "wasm-bindgen-futures", @@ -3335,7 +3335,7 @@ dependencies = [ [[package]] name = "tauri-interop-macro" -version = "2.1.0" +version = "2.1.1" dependencies = [ "convert_case 0.6.0", "lazy_static", @@ -3349,20 +3349,6 @@ dependencies = [ "tauri-interop", ] -[[package]] -name = "tauri-interop-macro" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6107bb6b43eaa7663d5b5e6aa4558f81fad2589f21c9a069802432b0a0a6e4e" -dependencies = [ - "convert_case 0.6.0", - "lazy_static", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.52", -] - [[package]] name = "tauri-macros" version = "1.4.3" diff --git a/Cargo.toml b/Cargo.toml index 9e22e19..46aa422 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,8 +24,8 @@ description = "Easily connect your rust frontend and backend without writing dup readme = "README.md" [dependencies] -#tauri-interop-macro = { path = "./tauri-interop-macro" } -tauri-interop-macro = "2.1.1" +tauri-interop-macro = { path = "./tauri-interop-macro" } +#tauri-interop-macro = "2.1.1" js-sys = "0.3" serde = { version = "1.0", features = ["derive"] } @@ -43,8 +43,8 @@ leptos = { version = "0.6", optional = true } tauri = { version = "1.6", default-features = false, features = ["wry"] } [target.'cfg(target_family = "wasm")'.dependencies] -#tauri-interop-macro = { path = "./tauri-interop-macro", features = ["_wasm"] } -tauri-interop-macro = { version = "2.1.1", features = [ "_wasm" ] } +tauri-interop-macro = { path = "./tauri-interop-macro", features = ["_wasm"] } +#tauri-interop-macro = { version = "2.1.1", features = [ "_wasm" ] } [target.'cfg(not(target_family = "wasm"))'.dev-dependencies] tauri = "1.6" diff --git a/README.md b/README.md index 96a0c7d..b6fbd57 100644 --- a/README.md +++ b/README.md @@ -20,3 +20,11 @@ The crates therefore provides the following features: - collect and register all defined tauri-commands - QOL-macros to exclude multiple imports in wasm or the host architecture - easier usage of [tauri's event feature](https://tauri.app/v1/guides/features/events/) + +### Note + +The library uses a resolver 2 features to allow easy inclusion without configuration. When working with virtual +workspaces the resolver defaults to 1. In that case it is required to set the resolver manually to version 2, +otherwise the [target specific compilation](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#platform-specific-dependencies) +will not resolve correctly. When the wrong resolver is used, an error should state that the `Listen` trait is missing. + diff --git a/src/event.rs b/src/event.rs index 578c196..b2e8607 100644 --- a/src/event.rs +++ b/src/event.rs @@ -8,6 +8,8 @@ pub use emit::*; #[cfg(any(target_family = "wasm", doc))] #[doc(cfg(target_family = "wasm"))] pub use listen::*; +#[cfg(doc)] +use tauri_interop_macro::{Emit, EmitField, Event, Listen, ListenField}; /// traits for event emitting in the host code #[cfg(not(target_family = "wasm"))] @@ -19,7 +21,34 @@ mod emit; #[doc(cfg(target_family = "wasm"))] mod listen; +#[allow(clippy::needless_doctest_main)] /// Trait defining a [Field] to a related struct implementing [Parent] with the related [Field::Type] +/// +/// When using [Event], [Emit] or [Listen], for each field of the struct, a struct named after the +/// field is generated. The field naming is snake_case to PascalCase, but because of the possibility +/// that the type and the field name are the same, the generated field has a "F" appended at the +/// beginning to separate each other and avoid type collision. +/// +/// ``` +/// use serde::{Deserialize, Serialize}; +/// use tauri_interop::{Event, event::ManagedEmit}; +/// +/// #[derive(Default, Clone, Serialize, Deserialize)] +/// struct Bar { +/// foo: u16 +/// } +/// +/// #[derive(Event)] +/// struct Test { +/// bar: Bar +/// } +/// +/// impl ManagedEmit for Test {} +/// +/// fn main() { +/// let _ = test::FBar; +/// } +/// ``` pub trait Field

where P: Parent, diff --git a/src/event/emit.rs b/src/event/emit.rs index 34cb1df..25c735c 100644 --- a/src/event/emit.rs +++ b/src/event/emit.rs @@ -36,7 +36,7 @@ where get_field_value: impl Fn(&Self) -> F::Type, ) -> Option where - Self: Sized + Send + Sync, + Self: Send + Sync, { use tauri::Manager; @@ -47,7 +47,7 @@ where } /// Trait that defines the available event emitting methods -pub trait Emit { +pub trait Emit: Sized { /// Emit all field events /// /// ### Example @@ -89,14 +89,14 @@ pub trait Emit { /// /// #[tauri_interop::command] /// fn emit_bar(handle: TauriAppHandle) { - /// Test::default().emit::(&handle).expect("emitting failed"); + /// Test::default().emit::(&handle).expect("emitting failed"); /// } /// /// fn main() {} /// ``` fn emit>(&self, handle: &AppHandle) -> Result<(), Error> where - Self: Sized + Parent; + Self: Parent; /// Update a single field and emit it afterward /// @@ -116,7 +116,7 @@ pub trait Emit { /// /// #[tauri_interop::command] /// fn emit_bar(handle: TauriAppHandle) { - /// Test::default().update::(&handle, true).expect("emitting failed"); + /// Test::default().update::(&handle, true).expect("emitting failed"); /// } /// /// fn main() {} @@ -127,5 +127,5 @@ pub trait Emit { field: F::Type, ) -> Result<(), Error> where - Self: Sized + Parent; + Self: Parent; } diff --git a/src/event/listen.rs b/src/event/listen.rs index aba279f..7e53a01 100644 --- a/src/event/listen.rs +++ b/src/event/listen.rs @@ -7,7 +7,7 @@ use wasm_bindgen::{closure::Closure, JsCast, JsValue}; use crate::command::bindings::listen; #[cfg(doc)] -use super::Emit; +use super::{Emit, Parent}; use super::Field; /// The trait which needs to be implemented for a [Field] @@ -95,15 +95,16 @@ impl ListenHandle { /// Registers a given event and binds a returned signal to these event changes /// - /// Providing [None] will unwrap into the default value. When feature `initial_value` + /// Providing [None] will unwrap into the default value. When feature `initial_value` /// is enabled [None] will try to get the value from tauri. - /// + /// /// Internally it stores a created [ListenHandle] for `event` in a [leptos::RwSignal] to hold it in /// scope, while it is used in a leptos [component](https://docs.rs/leptos_macro/0.5.2/leptos_macro/attr.component.html) #[cfg(feature = "leptos")] #[doc(cfg(feature = "leptos"))] pub fn use_register>(initial_value: Option) -> ReadSignal - where P: Sized + super::Parent + where + P: Parent, { use leptos::SignalSet; @@ -116,10 +117,10 @@ impl ListenHandle { if cfg!(feature = "initial_value") && acquire_initial_value { match F::get_value().await { Ok(value) => set_signal.set(value), - Err(why) => log::error!("{why}") + Err(why) => log::error!("{why}"), } } - + let listen_handle = ListenHandle::register(F::EVENT_NAME, move |value: F::Type| { log::trace!("update for {}", F::EVENT_NAME); set_signal.set(value) @@ -136,7 +137,7 @@ impl ListenHandle { } /// Trait that defines the available listen methods -pub trait Listen { +pub trait Listen: Sized { /// Registers a callback to a [Field] /// /// Default Implementation: see [ListenHandle::register] @@ -164,7 +165,7 @@ pub trait Listen { callback: impl Fn(F::Type) + 'static, ) -> impl std::future::Future where - Self: Sized + super::Parent, + Self: Parent, { ListenHandle::register(F::EVENT_NAME, callback) } @@ -194,7 +195,7 @@ pub trait Listen { #[doc(cfg(feature = "leptos"))] fn use_field>(initial: Option) -> ReadSignal where - Self: Sized + super::Parent, + Self: Parent, { ListenHandle::use_register::(initial) } diff --git a/src/lib.rs b/src/lib.rs index 0731409..585763d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,14 @@ //! //! Detail explanations and example can be found on the respected traits or macros. Some //! examples are ignored because they are only valid when compiling to wasm. +//! +//! ### Note +//! +//! The library uses resolver 2 features to allow easy inclusion without configuration. When working +//! with virtual workspaces the resolver defaults to 1 in which case it is required to set the +//! resolver manually to version 2, otherwise the [target specific compilation](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#platform-specific-dependencies) +//! will not resolve correctly. When the wrong resolver is used, an error should state that the +//! [event::Listen] trait is missing. #![feature(trait_alias)] #![feature(doc_cfg)] diff --git a/tauri-interop-macro/Cargo.toml b/tauri-interop-macro/Cargo.toml index 7a2043f..4953acd 100644 --- a/tauri-interop-macro/Cargo.toml +++ b/tauri-interop-macro/Cargo.toml @@ -27,7 +27,7 @@ proc-macro-error = "1.0.4" [dev-dependencies] tauri = { version = "^1.6", default-features = false, features = ["wry"] } log = "^0.4" -serde = "^1.0" +serde = { version = "^1.0", features = [ "derive" ] } # required because the intented usage is to use the main crate, # for testing we need the reexported macros from tauri-interop tauri-interop = { path = "..", features = ["event", "initial_value"] } diff --git a/tauri-interop-macro/src/event.rs b/tauri-interop-macro/src/event.rs index f82e4ff..6fe7fa9 100644 --- a/tauri-interop-macro/src/event.rs +++ b/tauri-interop-macro/src/event.rs @@ -57,7 +57,7 @@ fn prepare_event(derive_input: DeriveInput) -> EventStruct { .iter() .map(|field| { let field_ident = field.ident.as_ref().unwrap(); - let field_name = format_ident!("{}", field_ident.to_string().to_case(Case::Pascal)); + let field_name = format_ident!("F{}", field_ident.to_string().to_case(Case::Pascal)); EventField { field_name, diff --git a/tauri-interop-macro/src/event/emit.rs b/tauri-interop-macro/src/event/emit.rs index f4fffb5..91107af 100644 --- a/tauri-interop-macro/src/event/emit.rs +++ b/tauri-interop-macro/src/event/emit.rs @@ -41,7 +41,7 @@ pub fn derive(stream: TokenStream) -> TokenStream { let stream = quote! { #commands_attr pub mod #mod_name { - use super::#name; + use super::*; #( #emit_fields )* diff --git a/tauri-interop-macro/src/event/listen.rs b/tauri-interop-macro/src/event/listen.rs index fb38b9d..5307e4d 100644 --- a/tauri-interop-macro/src/event/listen.rs +++ b/tauri-interop-macro/src/event/listen.rs @@ -31,8 +31,7 @@ pub fn derive(stream: TokenStream) -> TokenStream { let stream = quote! { pub mod #mod_name { - use super::#name; - use ::tauri_interop::event::Field; + use super::*; #( #listen_fields )* } @@ -74,7 +73,7 @@ pub fn derive_field(stream: TokenStream) -> TokenStream { let stream = quote! { #get_cmd_fn - impl Field<#parent> for #name { + impl ::tauri_interop::event::Field<#parent> for #name { type Type = #parent_field_ty; const EVENT_NAME: &'static str = #event_name; diff --git a/tauri-interop-macro/src/lib.rs b/tauri-interop-macro/src/lib.rs index 6f97faa..79edc58 100644 --- a/tauri-interop-macro/src/lib.rs +++ b/tauri-interop-macro/src/lib.rs @@ -42,11 +42,17 @@ mod event; /// /// ``` /// use tauri_interop_macro::Event; +/// use serde::{Serialize, Deserialize}; /// +/// #[derive(Default, Clone, Serialize, Deserialize)] +/// pub struct Bar { +/// value: bool +/// } +/// /// #[derive(Event)] /// struct EventModel { /// foo: String, -/// pub bar: bool +/// pub bar: Bar /// } /// /// impl tauri_interop::event::ManagedEmit for EventModel {} diff --git a/test-project/Cargo.lock b/test-project/Cargo.lock index d51928a..418fec6 100644 --- a/test-project/Cargo.lock +++ b/test-project/Cargo.lock @@ -3483,7 +3483,7 @@ dependencies = [ [[package]] name = "tauri-interop" -version = "2.1.0" +version = "2.1.1" dependencies = [ "js-sys", "leptos", @@ -3499,9 +3499,7 @@ dependencies = [ [[package]] name = "tauri-interop-macro" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dbfaea1629f9987e8817846addaffef3b24ab5e132e584f371625e9d49b4191" +version = "2.1.1" dependencies = [ "convert_case 0.6.0", "lazy_static", diff --git a/test-project/Cargo.toml b/test-project/Cargo.toml index c96abcf..98abf5c 100644 --- a/test-project/Cargo.toml +++ b/test-project/Cargo.toml @@ -10,7 +10,7 @@ default-target = "wasm32-unknown-unknown" members = ["src-tauri", "api"] [dependencies] -api = { path = "./api", default-features = false, features = [ "wasm" ]} +api = { path = "./api" } console_error_panic_hook = "^0.1" console_log = "^1.0" diff --git a/test-project/api/Cargo.toml b/test-project/api/Cargo.toml index 92f81d7..09154ca 100644 --- a/test-project/api/Cargo.toml +++ b/test-project/api/Cargo.toml @@ -4,24 +4,21 @@ version = "0.1.0" edition = "2021" [dependencies] -tauri-interop = { path = "../..", default-features = false, features = ["event", "initial_value"] } +tauri-interop = { path = "../..", features = ["event", "initial_value"] } # common log = "0.4" serde = { version = "1", features = ["derive"] } -# host target -tauri = { version = "1.6", optional = true } +[target.'cfg(not(target_family = "wasm"))'.dependencies] +tauri = { version = "1.6" } -# wasm target -js-sys = { version = "0.3", optional = true } -serde-wasm-bindgen = { version = "0.6", optional = true } -wasm-bindgen = { version = "0.2", features = ["serde-serialize"], optional = true } -wasm-bindgen-futures = {version = "0.4", optional = true} +[target.'cfg(target_family = "wasm")'.dependencies] +js-sys = { version = "0.3" } +serde-wasm-bindgen = { version = "0.6" } +wasm-bindgen = { version = "0.2", features = ["serde-serialize"] } +wasm-bindgen-futures = { version = "0.4" } leptos = { version = "0.6", features = ["csr"], optional = true } [features] -default = [ "host" ] -host = [ "dep:tauri" ] -wasm = [ "dep:js-sys", "dep:serde-wasm-bindgen", "dep:wasm-bindgen", "dep:wasm-bindgen-futures"] -leptos = [ "dep:leptos", "tauri-interop/leptos" ] +leptos = ["dep:leptos", "tauri-interop/leptos"] diff --git a/test-project/api/src/cmd.rs b/test-project/api/src/cmd.rs index 4491ced..0c5e517 100644 --- a/test-project/api/src/cmd.rs +++ b/test-project/api/src/cmd.rs @@ -61,8 +61,8 @@ pub fn emit(state: TauriState>, handle: TauriAppHandle) { "foo" }; - state.update::(&handle, foo_value.into()).unwrap(); - state.update::(&handle, bar_value).unwrap(); + state.update::(&handle, foo_value.into()).unwrap(); + state.update::(&handle, bar_value).unwrap(); } tauri_interop::collect_commands!(); diff --git a/test-project/api/src/model.rs b/test-project/api/src/model.rs index 6e4f700..a10b2b1 100644 --- a/test-project/api/src/model.rs +++ b/test-project/api/src/model.rs @@ -32,12 +32,12 @@ pub struct NamingTestDefault { } fn test_naming() { - test_mod::Bar; - test_mod::Foo; - NamingTestEnumField::Bar; - NamingTestEnumField::Foo; - naming_test_default::Bar; - naming_test_default::Foo; + test_mod::FBar; + test_mod::FFoo; + NamingTestEnumField::FBar; + NamingTestEnumField::FFoo; + naming_test_default::FBar; + naming_test_default::FFoo; } // /// not allowed diff --git a/test-project/src-tauri/Cargo.toml b/test-project/src-tauri/Cargo.toml index 7b9002b..35e4dbf 100644 --- a/test-project/src-tauri/Cargo.toml +++ b/test-project/src-tauri/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" tauri-build = { version = "1.5", features = [] } [dependencies] -api = { path = "../api"} +api = { path = "../api" } tauri = { version = "1.5", features = ["shell-open"] } serde = { version = "1.0", features = ["derive"] } diff --git a/test-project/src/main.rs b/test-project/src/main.rs index fe1dcab..35d010b 100644 --- a/test-project/src/main.rs +++ b/test-project/src/main.rs @@ -21,7 +21,7 @@ fn main() { }); wasm_bindgen_futures::spawn_local(async move { - let handle_bar = TestState::listen_to::(|echo| log::info!("bar: {echo}")) + let handle_bar = TestState::listen_to::(|echo| log::info!("bar: {echo}")) .await .unwrap(); @@ -45,7 +45,7 @@ fn main() { fn App() -> impl IntoView { use leptos::SignalGet; - let bar = TestState::use_field::(Some(true)); + let bar = TestState::use_field::(Some(true)); let exit = move |_| api::model::other_cmd::stop_application(); @@ -71,7 +71,7 @@ fn Foo() -> impl IntoView { api::cmd::emit(); }).forget(); - let foo = TestState::use_field::(None); + let foo = TestState::use_field::(None); view! {

{foo}

} }