Skip to content

Commit

Permalink
Merge pull request #22 from photovoltex/adjust-collect-commands
Browse files Browse the repository at this point in the history
Adjust collect commands
  • Loading branch information
photovoltex authored Mar 5, 2024
2 parents e31b04e + 29c986d commit d77382c
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 18 deletions.
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ Using `tauri_interop::command` does two things:
- it provides the command with two macros which are used depending on the `target_family`
- `tauri_interop::binding` is used when compiling to `wasm`
- `tauri::command` is used otherwise
- it adds an entry to `tauri_interop::collect_commands!()` so that the generated `get_handlers()` function includes the given commands for the tauri context
- it adds an entry to `tauri_interop::collect_commands!()` (see [collect commands](#collect-commands))
- the function is not generated when targeting `wasm`

The defined command above can then be used in wasm as below. Due to receiving data from
Expand Down Expand Up @@ -153,6 +153,25 @@ async fn heavy_computation() {
}
```

#### Collect commands

The `tauri_invoke::collect_commands` macro generates a `get_handlers` function in the current mod, which calls the
`tauri::generate_handler` macro with all function which are annotated with the `tauri_interop::command` macro. The
function is only generated for tauri and not for wasm.

Due to technical limitations we sadly can't combine multiple `get_handlers` functions. This limitation comes to the
underlying mechanic. The `tauri::generate_handler` macro generates a function which consumes `tauri::Invoke` as single
parameter. Because it fully consumes the given parameter we can't call multiple handlers with it. In addition, the
`Builder::invoke_handler` function, which usually consumes the generated `tauri::generate_handler` can't be called
twice without losing the previous registered commands.

Because of this limitation for splitting commands into multiple files it is recommended to create a root mod for the
command which includes other command mod's. The functions in the included mods need to be public and re-imported into
the root mod. With these prerequisites the `tauri_invoke::collect_commands` can be called at the end of the file, which
generates the usual `get_handlers` function, but with all "commands" defined inside the others mods.

For an example see the [test-project/api/src/command.rs](test-project/api/src/command.rs).

### Event (Backend => Frontend Communication)
Definition for both tauri supported triplet and wasm:
```rust
Expand Down
10 changes: 5 additions & 5 deletions tauri-interop-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ use proc_macro::TokenStream;
use std::{collections::BTreeSet, sync::Mutex};

use quote::{format_ident, quote, ToTokens};
use syn::{
parse::Parser, parse_macro_input, punctuated::Punctuated, token::Comma, Ident, ItemFn, ItemUse,
Token,
};
use syn::{parse::Parser, parse_macro_input, punctuated::Punctuated, token::Comma, Ident, ItemFn, ItemUse, Token};

mod command;
mod event;
Expand Down Expand Up @@ -98,7 +95,7 @@ pub fn command(_attributes: TokenStream, stream: TokenStream) -> TokenStream {
/// The provided function isn't available for wasm
#[proc_macro]
pub fn collect_commands(_: TokenStream) -> TokenStream {
let handler = HANDLER_LIST.lock().unwrap();
let mut handler = HANDLER_LIST.lock().unwrap();
let to_generated_handler = handler
.iter()
.map(|s| format_ident!("{s}"))
Expand All @@ -115,6 +112,9 @@ pub fn collect_commands(_: TokenStream) -> TokenStream {
}
};

// clearing the already used handlers
handler.clear();

TokenStream::from(stream.to_token_stream())
}

Expand Down
7 changes: 7 additions & 0 deletions test-project/api/src/command.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
mod cmd;
mod other_cmd;

pub use cmd::*;
pub use other_cmd::*;

tauri_interop::collect_commands!();
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub async fn await_heavy_computing() {
}

#[tauri_interop::command]
fn greet(name_to_greet: &str) -> String {
pub fn greet(name_to_greet: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name_to_greet)
}

Expand Down Expand Up @@ -86,5 +86,3 @@ pub mod broken {
Ok(())
}
}

tauri_interop::collect_commands!();
2 changes: 2 additions & 0 deletions test-project/api/src/command/other_cmd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#[tauri_interop::command]
pub fn other() {}
2 changes: 1 addition & 1 deletion test-project/api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![allow(clippy::disallowed_names)]
#![feature(iter_intersperse)]

pub mod cmd;
pub mod command;
pub mod model;

#[cfg(target_family = "wasm")]
Expand Down
2 changes: 1 addition & 1 deletion test-project/src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ fn main() {
.unwrap();

tauri::Builder::default()
.invoke_handler(api::cmd::get_handlers())
.invoke_handler(api::command::get_handlers())
.setup(move |app| {
let main_window = app.handle().get_window("main").unwrap();

Expand Down
14 changes: 7 additions & 7 deletions test-project/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ fn main() {
console_log::init_with_level(log::Level::Trace).expect("no errors during logger init");
console_error_panic_hook::set_once();

api::cmd::empty_invoke();
api::cmd::underscore_invoke(69);
api::command::empty_invoke();
api::command::underscore_invoke(69);

wasm_bindgen_futures::spawn_local(async {
log::info!("{}", api::cmd::greet("frontend").await);
log::info!("{}", api::command::greet("frontend").await);

api::cmd::await_heavy_computing().await;
api::command::await_heavy_computing().await;
log::info!("heavy computing finished")
});

Expand All @@ -33,8 +33,8 @@ fn main() {
Timeout::new(2000, move || drop(handle_bar)).forget();
});

Timeout::new(1000, api::cmd::emit).forget();
Timeout::new(3000, api::cmd::emit).forget();
Timeout::new(1000, api::command::emit).forget();
Timeout::new(3000, api::command::emit).forget();

#[cfg(feature = "leptos")]
Timeout::new(5000, || leptos::mount_to_body(|| view! { <App /> })).forget();
Expand Down Expand Up @@ -70,7 +70,7 @@ fn App() -> impl IntoView {
#[cfg(feature = "leptos")]
#[component]
fn Foo() -> impl IntoView {
Timeout::new(2000, api::cmd::emit).forget();
Timeout::new(2000, api::command::emit).forget();

let foo = TestState::use_field::<test_mod::Foo>("Test".into());

Expand Down

0 comments on commit d77382c

Please sign in to comment.