mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-02-06 13:17:02 +00:00
feat!: add Listener and Emitter traits (#9640)
* feat!: add `Listener` and `Emitter` traits * keep only trait implementation * change file * fix doctests * fix build
This commit is contained in:
parent
1a88fc1a9b
commit
ba9590aa92
15
.changes/core-listener-emitter-trait.md
Normal file
15
.changes/core-listener-emitter-trait.md
Normal file
@ -0,0 +1,15 @@
|
||||
---
|
||||
"tauri": "patch:breaking"
|
||||
---
|
||||
|
||||
Added `Emitter` and `Listener` traits that defines what an emitter or a listener can do, this however comes with a few breaking changes:
|
||||
- Removed `Manager::listen_any`, use `Listener::listen_any` instead.
|
||||
- Removed `Manager::once_any`, use `Listener::once_any` instead.
|
||||
- Removed `Manager::unlisten`, use `Listener::unlisten` instead.
|
||||
- Removed `Manager::emit`, use `Emitter::emit` instead.
|
||||
- Removed `Manager::emit_to`, use `Emitter::emit_to` instead.
|
||||
- Removed `Manager::emit_filter`, use `Emitter::emit_filter` instead.
|
||||
- Removed `App/AppHandle::listen`, `WebviewWindow::listen`, `Window::listen` and `Webview::listen`, use `Listener::listen` instead.
|
||||
- Removed `App/AppHandle::once`, `WebviewWindow::once`, `Window::once` and `Webview::once`, use `Listener::once` instead.
|
||||
- Removed `App/AppHandle::unlisten`, `WebviewWindow::unlisten`, `Window::unlisten` and `Webview::unlisten`, use `Listener::unlisten` instead.
|
||||
|
||||
@ -22,8 +22,8 @@ use crate::{
|
||||
utils::config::Config,
|
||||
utils::Env,
|
||||
webview::PageLoadPayload,
|
||||
Context, DeviceEventFilter, EventLoopMessage, Manager, Monitor, Runtime, Scopes, StateManager,
|
||||
Theme, Webview, WebviewWindowBuilder, Window,
|
||||
Context, DeviceEventFilter, Emitter, EventLoopMessage, Listener, Manager, Monitor, Result,
|
||||
Runtime, Scopes, StateManager, Theme, Webview, WebviewWindowBuilder, Window,
|
||||
};
|
||||
|
||||
#[cfg(desktop)]
|
||||
@ -42,6 +42,7 @@ use tauri_runtime::{
|
||||
};
|
||||
use tauri_utils::PackageInfo;
|
||||
|
||||
use serde::Serialize;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::HashMap,
|
||||
@ -66,7 +67,7 @@ pub(crate) type GlobalWebviewEventListener<R> =
|
||||
Box<dyn Fn(&Webview<R>, &WebviewEvent) + Send + Sync>;
|
||||
/// A closure that is run when the Tauri application is setting up.
|
||||
pub type SetupHook<R> =
|
||||
Box<dyn FnOnce(&mut App<R>) -> Result<(), Box<dyn std::error::Error>> + Send>;
|
||||
Box<dyn FnOnce(&mut App<R>) -> std::result::Result<(), Box<dyn std::error::Error>> + Send>;
|
||||
/// A closure that is run every time a page starts or finishes loading.
|
||||
pub type OnPageLoad<R> = dyn Fn(&Webview<R>, &PageLoadPayload<'_>) + Send + Sync + 'static;
|
||||
|
||||
@ -328,7 +329,7 @@ impl<R: Runtime> Clone for AppHandle<R> {
|
||||
|
||||
impl<'de, R: Runtime> CommandArg<'de, R> for AppHandle<R> {
|
||||
/// Grabs the [`Window`] from the [`CommandItem`] and returns the associated [`AppHandle`]. This will never fail.
|
||||
fn from_command(command: CommandItem<'de, R>) -> Result<Self, InvokeError> {
|
||||
fn from_command(command: CommandItem<'de, R>) -> std::result::Result<Self, InvokeError> {
|
||||
Ok(command.message.webview().window().app_handle)
|
||||
}
|
||||
}
|
||||
@ -820,14 +821,13 @@ macro_rules! shared_app_impl {
|
||||
}
|
||||
}
|
||||
|
||||
/// Event system APIs.
|
||||
impl<R: Runtime> $app {
|
||||
impl<R: Runtime> Listener<R> for $app {
|
||||
/// Listen to an event on this app.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use tauri::Manager;
|
||||
/// use tauri::Listener;
|
||||
///
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
@ -838,19 +838,29 @@ macro_rules! shared_app_impl {
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
pub fn listen<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
fn listen<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
where
|
||||
F: Fn(Event) + Send + 'static,
|
||||
{
|
||||
self.manager.listen(event.into(), EventTarget::App, handler)
|
||||
}
|
||||
|
||||
/// Listen to an event on this app only once.
|
||||
///
|
||||
/// See [`Self::listen`] for more information.
|
||||
fn once<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
where
|
||||
F: FnOnce(Event) + Send + 'static,
|
||||
{
|
||||
self.manager.once(event.into(), EventTarget::App, handler)
|
||||
}
|
||||
|
||||
/// Unlisten to an event on this app.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use tauri::Manager;
|
||||
/// use tauri::Listener;
|
||||
///
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
@ -864,18 +874,82 @@ macro_rules! shared_app_impl {
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
pub fn unlisten(&self, id: EventId) {
|
||||
fn unlisten(&self, id: EventId) {
|
||||
self.manager.unlisten(id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Listen to an event on this app only once.
|
||||
impl<R: Runtime> Emitter<R> for $app {
|
||||
/// Emits an event to all [targets](EventTarget).
|
||||
///
|
||||
/// See [`Self::listen`] for more information.
|
||||
pub fn once<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use tauri::Emitter;
|
||||
///
|
||||
/// #[tauri::command]
|
||||
/// fn synchronize(app: tauri::AppHandle) {
|
||||
/// // emits the synchronized event to all webviews
|
||||
/// app.emit("synchronized", ());
|
||||
/// }
|
||||
/// ```
|
||||
fn emit<S: Serialize + Clone>(&self, event: &str, payload: S) -> Result<()> {
|
||||
self.manager.emit(event, payload)
|
||||
}
|
||||
|
||||
/// Emits an event to all [targets](EventTarget) matching the given target.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use tauri::{Emitter, EventTarget};
|
||||
///
|
||||
/// #[tauri::command]
|
||||
/// fn download(app: tauri::AppHandle) {
|
||||
/// for i in 1..100 {
|
||||
/// std::thread::sleep(std::time::Duration::from_millis(150));
|
||||
/// // emit a download progress event to all listeners
|
||||
/// app.emit_to(EventTarget::any(), "download-progress", i);
|
||||
/// // emit an event to listeners that used App::listen or AppHandle::listen
|
||||
/// app.emit_to(EventTarget::app(), "download-progress", i);
|
||||
/// // emit an event to any webview/window/webviewWindow matching the given label
|
||||
/// app.emit_to("updater", "download-progress", i); // similar to using EventTarget::labeled
|
||||
/// app.emit_to(EventTarget::labeled("updater"), "download-progress", i);
|
||||
/// // emit an event to listeners that used WebviewWindow::listen
|
||||
/// app.emit_to(EventTarget::webview_window("updater"), "download-progress", i);
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
fn emit_to<I, S>(&self, target: I, event: &str, payload: S) -> Result<()>
|
||||
where
|
||||
F: FnOnce(Event) + Send + 'static,
|
||||
I: Into<EventTarget>,
|
||||
S: Serialize + Clone,
|
||||
{
|
||||
self.manager.once(event.into(), EventTarget::App, handler)
|
||||
self.manager.emit_to(target, event, payload)
|
||||
}
|
||||
|
||||
/// Emits an event to all [targets](EventTarget) based on the given filter.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use tauri::{Emitter, EventTarget};
|
||||
///
|
||||
/// #[tauri::command]
|
||||
/// fn download(app: tauri::AppHandle) {
|
||||
/// for i in 1..100 {
|
||||
/// std::thread::sleep(std::time::Duration::from_millis(150));
|
||||
/// // emit a download progress event to the updater window
|
||||
/// app.emit_filter("download-progress", i, |t| match t {
|
||||
/// EventTarget::WebviewWindow { label } => label == "main",
|
||||
/// _ => false,
|
||||
/// });
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
fn emit_filter<S, F>(&self, event: &str, payload: S, filter: F) -> Result<()>
|
||||
where
|
||||
S: Serialize + Clone,
|
||||
F: Fn(&EventTarget) -> bool,
|
||||
{
|
||||
self.manager.emit_filter(event, payload, filter)
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -1239,7 +1313,7 @@ tauri::Builder::default()
|
||||
#[must_use]
|
||||
pub fn setup<F>(mut self, setup: F) -> Self
|
||||
where
|
||||
F: FnOnce(&mut App<R>) -> Result<(), Box<dyn std::error::Error>> + Send + 'static,
|
||||
F: FnOnce(&mut App<R>) -> std::result::Result<(), Box<dyn std::error::Error>> + Send + 'static,
|
||||
{
|
||||
self.setup = Box::new(setup);
|
||||
self
|
||||
|
||||
@ -9,8 +9,8 @@ use serde_json::Value as JsonValue;
|
||||
use tauri_runtime::window::is_label_valid;
|
||||
|
||||
use crate::plugin::{Builder, TauriPlugin};
|
||||
use crate::{command, ipc::CallbackFn, EventId, Manager, Result, Runtime};
|
||||
use crate::{AppHandle, Webview};
|
||||
use crate::{command, ipc::CallbackFn, EventId, Result, Runtime};
|
||||
use crate::{AppHandle, Emitter, Webview};
|
||||
|
||||
use super::{is_event_name_valid, EventTarget};
|
||||
|
||||
|
||||
@ -539,178 +539,6 @@ pub trait Manager<R: Runtime>: sealed::ManagerBase<R> {
|
||||
self.manager().package_info()
|
||||
}
|
||||
|
||||
/// Listen to an emitted event to any [target](EventTarget).
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use tauri::Manager;
|
||||
///
|
||||
/// #[tauri::command]
|
||||
/// fn synchronize(window: tauri::Window) {
|
||||
/// // emits the synchronized event to all windows
|
||||
/// window.emit("synchronized", ());
|
||||
/// }
|
||||
///
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// app.listen_any("synchronized", |event| {
|
||||
/// println!("app is in sync");
|
||||
/// });
|
||||
/// Ok(())
|
||||
/// })
|
||||
/// .invoke_handler(tauri::generate_handler![synchronize]);
|
||||
/// ```
|
||||
fn listen_any<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
where
|
||||
F: Fn(Event) + Send + 'static,
|
||||
{
|
||||
self
|
||||
.manager()
|
||||
.listen(event.into(), EventTarget::Any, handler)
|
||||
}
|
||||
|
||||
/// Remove an event listener.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use tauri::Manager;
|
||||
///
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// let handle = app.handle().clone();
|
||||
/// let handler = app.listen_any("ready", move |event| {
|
||||
/// println!("app is ready");
|
||||
///
|
||||
/// // we no longer need to listen to the event
|
||||
/// // we also could have used `app.once_global` instead
|
||||
/// handle.unlisten(event.id());
|
||||
/// });
|
||||
///
|
||||
/// // stop listening to the event when you do not need it anymore
|
||||
/// app.unlisten(handler);
|
||||
///
|
||||
///
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
fn unlisten(&self, id: EventId) {
|
||||
self.manager().unlisten(id)
|
||||
}
|
||||
|
||||
/// Listens once to an emitted event to any [target](EventTarget) .
|
||||
///
|
||||
/// See [`Self::listen_any`] for more information.
|
||||
fn once_any<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
where
|
||||
F: FnOnce(Event) + Send + 'static,
|
||||
{
|
||||
self.manager().once(event.into(), EventTarget::Any, handler)
|
||||
}
|
||||
|
||||
/// Emits an event to all [targets](EventTarget).
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use tauri::Manager;
|
||||
///
|
||||
/// #[tauri::command]
|
||||
/// fn synchronize(app: tauri::AppHandle) {
|
||||
/// // emits the synchronized event to all webviews
|
||||
/// app.emit("synchronized", ());
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument("app::emit", skip(self, payload))
|
||||
)]
|
||||
fn emit<S: Serialize + Clone>(&self, event: &str, payload: S) -> Result<()> {
|
||||
self.manager().emit(event, payload)
|
||||
}
|
||||
|
||||
/// Emits an event to all [targets](EventTarget) matching the given target.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use tauri::{Manager, EventTarget};
|
||||
///
|
||||
/// #[tauri::command]
|
||||
/// fn download(app: tauri::AppHandle) {
|
||||
/// for i in 1..100 {
|
||||
/// std::thread::sleep(std::time::Duration::from_millis(150));
|
||||
/// // emit a download progress event to all listeners
|
||||
/// app.emit_to(EventTarget::any(), "download-progress", i);
|
||||
/// // emit an event to listeners that used App::listen or AppHandle::listen
|
||||
/// app.emit_to(EventTarget::app(), "download-progress", i);
|
||||
/// // emit an event to any webview/window/webviewWindow matching the given label
|
||||
/// app.emit_to("updater", "download-progress", i); // similar to using EventTarget::labeled
|
||||
/// app.emit_to(EventTarget::labeled("updater"), "download-progress", i);
|
||||
/// // emit an event to listeners that used WebviewWindow::listen
|
||||
/// app.emit_to(EventTarget::webview_window("updater"), "download-progress", i);
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument("app::emit::to", skip(self, target, payload), fields(target))
|
||||
)]
|
||||
fn emit_to<I, S>(&self, target: I, event: &str, payload: S) -> Result<()>
|
||||
where
|
||||
I: Into<EventTarget>,
|
||||
S: Serialize + Clone,
|
||||
{
|
||||
let target = target.into();
|
||||
#[cfg(feature = "tracing")]
|
||||
tracing::Span::current().record("target", format!("{target:?}"));
|
||||
|
||||
match target {
|
||||
// if targeting all, emit to all using emit without filter
|
||||
EventTarget::Any => self.manager().emit(event, payload),
|
||||
|
||||
// if targeting any label, emit using emit_filter and filter labels
|
||||
EventTarget::AnyLabel {
|
||||
label: target_label,
|
||||
} => self.manager().emit_filter(event, payload, |t| match t {
|
||||
EventTarget::Window { label }
|
||||
| EventTarget::Webview { label }
|
||||
| EventTarget::WebviewWindow { label } => label == &target_label,
|
||||
_ => false,
|
||||
}),
|
||||
|
||||
// otherwise match same target
|
||||
_ => self.manager().emit_filter(event, payload, |t| t == &target),
|
||||
}
|
||||
}
|
||||
|
||||
/// Emits an event to all [targets](EventTarget) based on the given filter.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use tauri::{Manager, EventTarget};
|
||||
///
|
||||
/// #[tauri::command]
|
||||
/// fn download(app: tauri::AppHandle) {
|
||||
/// for i in 1..100 {
|
||||
/// std::thread::sleep(std::time::Duration::from_millis(150));
|
||||
/// // emit a download progress event to the updater window
|
||||
/// app.emit_filter("download-progress", i, |t| match t {
|
||||
/// EventTarget::WebviewWindow { label } => label == "main",
|
||||
/// _ => false,
|
||||
/// });
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument("app::emit::filter", skip(self, payload, filter))
|
||||
)]
|
||||
fn emit_filter<S, F>(&self, event: &str, payload: S, filter: F) -> Result<()>
|
||||
where
|
||||
S: Serialize + Clone,
|
||||
F: Fn(&EventTarget) -> bool,
|
||||
{
|
||||
self.manager().emit_filter(event, payload, filter)
|
||||
}
|
||||
|
||||
/// Fetch a single window from the manager.
|
||||
#[cfg(feature = "unstable")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
|
||||
@ -933,6 +761,174 @@ pub trait Manager<R: Runtime>: sealed::ManagerBase<R> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Listen to events.
|
||||
pub trait Listener<R: Runtime>: sealed::ManagerBase<R> {
|
||||
/// Listen to an emitted event on this manager.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use tauri::{Manager, Listener, Emitter};
|
||||
///
|
||||
/// #[tauri::command]
|
||||
/// fn synchronize(window: tauri::Window) {
|
||||
/// // emits the synchronized event to all windows
|
||||
/// window.emit("synchronized", ());
|
||||
/// }
|
||||
///
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// app.listen("synchronized", |event| {
|
||||
/// println!("app is in sync");
|
||||
/// });
|
||||
/// Ok(())
|
||||
/// })
|
||||
/// .invoke_handler(tauri::generate_handler![synchronize]);
|
||||
/// ```
|
||||
fn listen<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
where
|
||||
F: Fn(Event) + Send + 'static;
|
||||
|
||||
/// Listen to an event on this manager only once.
|
||||
///
|
||||
/// See [`Self::listen`] for more information.
|
||||
fn once<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
where
|
||||
F: FnOnce(Event) + Send + 'static;
|
||||
|
||||
/// Remove an event listener.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use tauri::{Manager, Listener};
|
||||
///
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// let handle = app.handle().clone();
|
||||
/// let handler = app.listen_any("ready", move |event| {
|
||||
/// println!("app is ready");
|
||||
///
|
||||
/// // we no longer need to listen to the event
|
||||
/// // we also could have used `app.once_global` instead
|
||||
/// handle.unlisten(event.id());
|
||||
/// });
|
||||
///
|
||||
/// // stop listening to the event when you do not need it anymore
|
||||
/// app.unlisten(handler);
|
||||
///
|
||||
///
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
fn unlisten(&self, id: EventId);
|
||||
|
||||
/// Listen to an emitted event to any [target](EventTarget).
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use tauri::{Manager, Emitter, Listener};
|
||||
///
|
||||
/// #[tauri::command]
|
||||
/// fn synchronize(window: tauri::Window) {
|
||||
/// // emits the synchronized event to all windows
|
||||
/// window.emit("synchronized", ());
|
||||
/// }
|
||||
///
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// app.listen_any("synchronized", |event| {
|
||||
/// println!("app is in sync");
|
||||
/// });
|
||||
/// Ok(())
|
||||
/// })
|
||||
/// .invoke_handler(tauri::generate_handler![synchronize]);
|
||||
/// ```
|
||||
fn listen_any<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
where
|
||||
F: Fn(Event) + Send + 'static,
|
||||
{
|
||||
self
|
||||
.manager()
|
||||
.listen(event.into(), EventTarget::Any, handler)
|
||||
}
|
||||
|
||||
/// Listens once to an emitted event to any [target](EventTarget) .
|
||||
///
|
||||
/// See [`Self::listen_any`] for more information.
|
||||
fn once_any<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
where
|
||||
F: FnOnce(Event) + Send + 'static,
|
||||
{
|
||||
self.manager().once(event.into(), EventTarget::Any, handler)
|
||||
}
|
||||
}
|
||||
|
||||
/// Emit events.
|
||||
pub trait Emitter<R: Runtime>: sealed::ManagerBase<R> {
|
||||
/// Emits an event to all [targets](EventTarget).
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use tauri::Emitter;
|
||||
///
|
||||
/// #[tauri::command]
|
||||
/// fn synchronize(app: tauri::AppHandle) {
|
||||
/// // emits the synchronized event to all webviews
|
||||
/// app.emit("synchronized", ());
|
||||
/// }
|
||||
/// ```
|
||||
fn emit<S: Serialize + Clone>(&self, event: &str, payload: S) -> Result<()>;
|
||||
|
||||
/// Emits an event to all [targets](EventTarget) matching the given target.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use tauri::{Emitter, EventTarget};
|
||||
///
|
||||
/// #[tauri::command]
|
||||
/// fn download(app: tauri::AppHandle) {
|
||||
/// for i in 1..100 {
|
||||
/// std::thread::sleep(std::time::Duration::from_millis(150));
|
||||
/// // emit a download progress event to all listeners
|
||||
/// app.emit_to(EventTarget::any(), "download-progress", i);
|
||||
/// // emit an event to listeners that used App::listen or AppHandle::listen
|
||||
/// app.emit_to(EventTarget::app(), "download-progress", i);
|
||||
/// // emit an event to any webview/window/webviewWindow matching the given label
|
||||
/// app.emit_to("updater", "download-progress", i); // similar to using EventTarget::labeled
|
||||
/// app.emit_to(EventTarget::labeled("updater"), "download-progress", i);
|
||||
/// // emit an event to listeners that used WebviewWindow::listen
|
||||
/// app.emit_to(EventTarget::webview_window("updater"), "download-progress", i);
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
fn emit_to<I, S>(&self, target: I, event: &str, payload: S) -> Result<()>
|
||||
where
|
||||
I: Into<EventTarget>,
|
||||
S: Serialize + Clone;
|
||||
|
||||
/// Emits an event to all [targets](EventTarget) based on the given filter.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use tauri::{Emitter, EventTarget};
|
||||
///
|
||||
/// #[tauri::command]
|
||||
/// fn download(app: tauri::AppHandle) {
|
||||
/// for i in 1..100 {
|
||||
/// std::thread::sleep(std::time::Duration::from_millis(150));
|
||||
/// // emit a download progress event to the updater window
|
||||
/// app.emit_filter("download-progress", i, |t| match t {
|
||||
/// EventTarget::WebviewWindow { label } => label == "main",
|
||||
/// _ => false,
|
||||
/// });
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
fn emit_filter<S, F>(&self, event: &str, payload: S, filter: F) -> Result<()>
|
||||
where
|
||||
S: Serialize + Clone,
|
||||
F: Fn(&EventTarget) -> bool;
|
||||
}
|
||||
|
||||
/// Prevent implementation details from leaking out of the [`Manager`] trait.
|
||||
pub(crate) mod sealed {
|
||||
use super::Runtime;
|
||||
|
||||
@ -472,10 +472,6 @@ impl<R: Runtime> AppManager<R> {
|
||||
self.listeners().listen(event, target, handler)
|
||||
}
|
||||
|
||||
pub fn unlisten(&self, id: EventId) {
|
||||
self.listeners().unlisten(id)
|
||||
}
|
||||
|
||||
pub fn once<F: FnOnce(Event) + Send + 'static>(
|
||||
&self,
|
||||
event: String,
|
||||
@ -486,6 +482,33 @@ impl<R: Runtime> AppManager<R> {
|
||||
self.listeners().once(event, target, handler)
|
||||
}
|
||||
|
||||
pub fn unlisten(&self, id: EventId) {
|
||||
self.listeners().unlisten(id)
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument("app::emit", skip(self, payload))
|
||||
)]
|
||||
pub fn emit<S: Serialize + Clone>(&self, event: &str, payload: S) -> crate::Result<()> {
|
||||
assert_event_name_is_valid(event);
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
let _span = tracing::debug_span!("emit::run").entered();
|
||||
let emit_args = EmitArgs::new(event, payload)?;
|
||||
|
||||
let listeners = self.listeners();
|
||||
|
||||
listeners.emit_js(self.webview.webviews_lock().values(), event, &emit_args)?;
|
||||
listeners.emit(emit_args)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument("app::emit::filter", skip(self, payload, filter))
|
||||
)]
|
||||
pub fn emit_filter<S, F>(&self, event: &str, payload: S, filter: F) -> crate::Result<()>
|
||||
where
|
||||
S: Serialize + Clone,
|
||||
@ -511,19 +534,36 @@ impl<R: Runtime> AppManager<R> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn emit<S: Serialize + Clone>(&self, event: &str, payload: S) -> crate::Result<()> {
|
||||
assert_event_name_is_valid(event);
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument("app::emit::to", skip(self, target, payload), fields(target))
|
||||
)]
|
||||
pub fn emit_to<I, S>(&self, target: I, event: &str, payload: S) -> crate::Result<()>
|
||||
where
|
||||
I: Into<EventTarget>,
|
||||
S: Serialize + Clone,
|
||||
{
|
||||
let target = target.into();
|
||||
#[cfg(feature = "tracing")]
|
||||
let _span = tracing::debug_span!("emit::run").entered();
|
||||
let emit_args = EmitArgs::new(event, payload)?;
|
||||
tracing::Span::current().record("target", format!("{target:?}"));
|
||||
|
||||
let listeners = self.listeners();
|
||||
match target {
|
||||
// if targeting all, emit to all using emit without filter
|
||||
EventTarget::Any => self.emit(event, payload),
|
||||
|
||||
listeners.emit_js(self.webview.webviews_lock().values(), event, &emit_args)?;
|
||||
listeners.emit(emit_args)?;
|
||||
// if targeting any label, emit using emit_filter and filter labels
|
||||
EventTarget::AnyLabel {
|
||||
label: target_label,
|
||||
} => self.emit_filter(event, payload, |t| match t {
|
||||
EventTarget::Window { label }
|
||||
| EventTarget::Webview { label }
|
||||
| EventTarget::WebviewWindow { label } => label == &target_label,
|
||||
_ => false,
|
||||
}),
|
||||
|
||||
Ok(())
|
||||
// otherwise match same target
|
||||
_ => self.emit_filter(event, payload, |t| t == &target),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_window(&self, label: &str) -> Option<Window<R>> {
|
||||
@ -634,7 +674,8 @@ mod test {
|
||||
test::{mock_app, MockRuntime},
|
||||
webview::WebviewBuilder,
|
||||
window::WindowBuilder,
|
||||
App, Manager, StateManager, Webview, WebviewWindow, WebviewWindowBuilder, Window, Wry,
|
||||
App, Emitter, Listener, Manager, StateManager, Webview, WebviewWindow, WebviewWindowBuilder,
|
||||
Window, Wry,
|
||||
};
|
||||
|
||||
use super::AppManager;
|
||||
@ -780,7 +821,11 @@ mod test {
|
||||
run_emit_test("emit (webview_window)", webview_window, &rx);
|
||||
}
|
||||
|
||||
fn run_emit_test<M: Manager<MockRuntime>>(kind: &str, m: M, rx: &Receiver<(&str, String)>) {
|
||||
fn run_emit_test<M: Manager<MockRuntime> + Emitter<MockRuntime>>(
|
||||
kind: &str,
|
||||
m: M,
|
||||
rx: &Receiver<(&str, String)>,
|
||||
) {
|
||||
let mut received = Vec::new();
|
||||
let payload = "global-payload";
|
||||
m.emit(TEST_EVENT_NAME, payload).unwrap();
|
||||
@ -853,7 +898,7 @@ mod test {
|
||||
);
|
||||
}
|
||||
|
||||
fn run_emit_to_test<M: Manager<MockRuntime>>(
|
||||
fn run_emit_to_test<M: Manager<MockRuntime> + Emitter<MockRuntime>>(
|
||||
kind: &str,
|
||||
m: &M,
|
||||
window: &Window<MockRuntime>,
|
||||
|
||||
@ -25,7 +25,7 @@ use crate::{
|
||||
pattern::PatternJavascript,
|
||||
sealed::ManagerBase,
|
||||
webview::PageLoadPayload,
|
||||
AppHandle, EventLoopMessage, EventTarget, Manager, Runtime, Scopes, Webview, Window,
|
||||
AppHandle, Emitter, EventLoopMessage, EventTarget, Manager, Runtime, Scopes, Webview, Window,
|
||||
};
|
||||
|
||||
use super::{
|
||||
|
||||
@ -17,8 +17,8 @@ use tauri_runtime::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
app::GlobalWindowEventListener, image::Image, sealed::ManagerBase, AppHandle, EventLoopMessage,
|
||||
EventTarget, Manager, Runtime, Scopes, Window, WindowEvent,
|
||||
app::GlobalWindowEventListener, image::Image, sealed::ManagerBase, AppHandle, Emitter,
|
||||
EventLoopMessage, EventTarget, Manager, Runtime, Scopes, Window, WindowEvent,
|
||||
};
|
||||
|
||||
const WINDOW_RESIZED_EVENT: &str = "tauri://resize";
|
||||
|
||||
@ -34,7 +34,8 @@ use crate::{
|
||||
},
|
||||
manager::{webview::WebviewLabelDef, AppManager},
|
||||
sealed::{ManagerBase, RuntimeOrDispatch},
|
||||
AppHandle, Event, EventId, EventLoopMessage, Manager, ResourceTable, Runtime, Window,
|
||||
AppHandle, Emitter, Event, EventId, EventLoopMessage, Listener, Manager, ResourceTable, Runtime,
|
||||
Window,
|
||||
};
|
||||
|
||||
use std::{
|
||||
@ -1484,8 +1485,7 @@ tauri::Builder::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Event system APIs.
|
||||
impl<R: Runtime> Webview<R> {
|
||||
impl<R: Runtime> Listener<R> for Webview<R> {
|
||||
/// Listen to an event on this webview.
|
||||
///
|
||||
/// # Examples
|
||||
@ -1493,13 +1493,13 @@ impl<R: Runtime> Webview<R> {
|
||||
feature = "unstable",
|
||||
doc = r####"
|
||||
```
|
||||
use tauri::Manager;
|
||||
use tauri::{Manager, Listener};
|
||||
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
let webview = app.get_webview("main").unwrap();
|
||||
webview.listen("component-loaded", move |event| {
|
||||
println!("window just loaded a component");
|
||||
println!("webview just loaded a component");
|
||||
});
|
||||
|
||||
Ok(())
|
||||
@ -1507,7 +1507,7 @@ tauri::Builder::default()
|
||||
```
|
||||
"####
|
||||
)]
|
||||
pub fn listen<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
fn listen<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
where
|
||||
F: Fn(Event) + Send + 'static,
|
||||
{
|
||||
@ -1520,6 +1520,22 @@ tauri::Builder::default()
|
||||
)
|
||||
}
|
||||
|
||||
/// Listen to an event on this webview only once.
|
||||
///
|
||||
/// See [`Self::listen`] for more information.
|
||||
fn once<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
where
|
||||
F: FnOnce(Event) + Send + 'static,
|
||||
{
|
||||
self.manager.once(
|
||||
event.into(),
|
||||
EventTarget::Webview {
|
||||
label: self.label().to_string(),
|
||||
},
|
||||
handler,
|
||||
)
|
||||
}
|
||||
|
||||
/// Unlisten to an event on this webview.
|
||||
///
|
||||
/// # Examples
|
||||
@ -1527,7 +1543,7 @@ tauri::Builder::default()
|
||||
feature = "unstable",
|
||||
doc = r####"
|
||||
```
|
||||
use tauri::Manager;
|
||||
use tauri::{Manager, Listener};
|
||||
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
@ -1549,24 +1565,97 @@ tauri::Builder::default()
|
||||
```
|
||||
"####
|
||||
)]
|
||||
pub fn unlisten(&self, id: EventId) {
|
||||
fn unlisten(&self, id: EventId) {
|
||||
self.manager.unlisten(id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Listen to an event on this webview only once.
|
||||
impl<R: Runtime> Emitter<R> for Webview<R> {
|
||||
/// Emits an event to all [targets](EventTarget).
|
||||
///
|
||||
/// See [`Self::listen`] for more information.
|
||||
pub fn once<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
/// # Examples
|
||||
#[cfg_attr(
|
||||
feature = "unstable",
|
||||
doc = r####"
|
||||
```
|
||||
use tauri::Emitter;
|
||||
|
||||
#[tauri::command]
|
||||
fn synchronize(webview: tauri::Webview) {
|
||||
// emits the synchronized event to all webviews
|
||||
webview.emit("synchronized", ());
|
||||
}
|
||||
```
|
||||
"####
|
||||
)]
|
||||
fn emit<S: Serialize + Clone>(&self, event: &str, payload: S) -> crate::Result<()> {
|
||||
self.manager.emit(event, payload)
|
||||
}
|
||||
|
||||
/// Emits an event to all [targets](EventTarget) matching the given target.
|
||||
///
|
||||
/// # Examples
|
||||
#[cfg_attr(
|
||||
feature = "unstable",
|
||||
doc = r####"
|
||||
```
|
||||
use tauri::{Emitter, EventTarget};
|
||||
|
||||
#[tauri::command]
|
||||
fn download(webview: tauri::Webview) {
|
||||
for i in 1..100 {
|
||||
std::thread::sleep(std::time::Duration::from_millis(150));
|
||||
// emit a download progress event to all listeners
|
||||
webview.emit_to(EventTarget::any(), "download-progress", i);
|
||||
// emit an event to listeners that used App::listen or AppHandle::listen
|
||||
webview.emit_to(EventTarget::app(), "download-progress", i);
|
||||
// emit an event to any webview/window/webviewWindow matching the given label
|
||||
webview.emit_to("updater", "download-progress", i); // similar to using EventTarget::labeled
|
||||
webview.emit_to(EventTarget::labeled("updater"), "download-progress", i);
|
||||
// emit an event to listeners that used WebviewWindow::listen
|
||||
webview.emit_to(EventTarget::webview_window("updater"), "download-progress", i);
|
||||
}
|
||||
}
|
||||
```
|
||||
"####
|
||||
)]
|
||||
fn emit_to<I, S>(&self, target: I, event: &str, payload: S) -> crate::Result<()>
|
||||
where
|
||||
F: FnOnce(Event) + Send + 'static,
|
||||
I: Into<EventTarget>,
|
||||
S: Serialize + Clone,
|
||||
{
|
||||
self.manager.once(
|
||||
event.into(),
|
||||
EventTarget::Webview {
|
||||
label: self.label().to_string(),
|
||||
},
|
||||
handler,
|
||||
)
|
||||
self.manager.emit_to(target, event, payload)
|
||||
}
|
||||
|
||||
/// Emits an event to all [targets](EventTarget) based on the given filter.
|
||||
///
|
||||
/// # Examples
|
||||
#[cfg_attr(
|
||||
feature = "unstable",
|
||||
doc = r####"
|
||||
```
|
||||
use tauri::{Emitter, EventTarget};
|
||||
|
||||
#[tauri::command]
|
||||
fn download(webview: tauri::Webview) {
|
||||
for i in 1..100 {
|
||||
std::thread::sleep(std::time::Duration::from_millis(150));
|
||||
// emit a download progress event to the updater window
|
||||
webview.emit_filter("download-progress", i, |t| match t {
|
||||
EventTarget::WebviewWindow { label } => label == "main",
|
||||
_ => false,
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
"####
|
||||
)]
|
||||
fn emit_filter<S, F>(&self, event: &str, payload: S, filter: F) -> crate::Result<()>
|
||||
where
|
||||
S: Serialize + Clone,
|
||||
F: Fn(&EventTarget) -> bool,
|
||||
{
|
||||
self.manager.emit_filter(event, payload, filter)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ use crate::{
|
||||
event::EventTarget,
|
||||
runtime::dpi::{PhysicalPosition, PhysicalSize},
|
||||
window::Monitor,
|
||||
ResourceTable,
|
||||
Emitter, Listener, ResourceTable,
|
||||
};
|
||||
#[cfg(desktop)]
|
||||
use crate::{
|
||||
@ -26,6 +26,7 @@ use crate::{
|
||||
UserAttentionType,
|
||||
},
|
||||
};
|
||||
use serde::Serialize;
|
||||
use tauri_utils::config::{WebviewUrl, WindowConfig};
|
||||
use url::Url;
|
||||
|
||||
@ -189,40 +190,34 @@ impl<'a, R: Runtime, M: Manager<R>> WebviewWindowBuilder<'a, R, M> {
|
||||
/// but it might be implemented in the future. **Always** check the request URL.
|
||||
///
|
||||
/// # Examples
|
||||
#[cfg_attr(
|
||||
feature = "unstable",
|
||||
doc = r####"
|
||||
```rust,no_run
|
||||
use tauri::{
|
||||
utils::config::{Csp, CspDirectiveSources, WebviewUrl},
|
||||
window::WindowBuilder,
|
||||
webview::WebviewWindowBuilder,
|
||||
};
|
||||
use http::header::HeaderValue;
|
||||
use std::collections::HashMap;
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
let webview_window = WebviewWindowBuilder::new(app, "core", WebviewUrl::App("index.html".into()))
|
||||
.on_web_resource_request(|request, response| {
|
||||
if request.uri().scheme_str() == Some("tauri") {
|
||||
// if we have a CSP header, Tauri is loading an HTML file
|
||||
// for this example, let's dynamically change the CSP
|
||||
if let Some(csp) = response.headers_mut().get_mut("Content-Security-Policy") {
|
||||
// use the tauri helper to parse the CSP policy to a map
|
||||
let mut csp_map: HashMap<String, CspDirectiveSources> = Csp::Policy(csp.to_str().unwrap().to_string()).into();
|
||||
csp_map.entry("script-src".to_string()).or_insert_with(Default::default).push("'unsafe-inline'");
|
||||
// use the tauri helper to get a CSP string from the map
|
||||
let csp_string = Csp::from(csp_map).to_string();
|
||||
*csp = HeaderValue::from_str(&csp_string).unwrap();
|
||||
}
|
||||
}
|
||||
})
|
||||
.build()?;
|
||||
Ok(())
|
||||
});
|
||||
```
|
||||
"####
|
||||
)]
|
||||
/// ```rust,no_run
|
||||
/// use tauri::{
|
||||
/// utils::config::{Csp, CspDirectiveSources, WebviewUrl},
|
||||
/// webview::WebviewWindowBuilder,
|
||||
/// };
|
||||
/// use http::header::HeaderValue;
|
||||
/// use std::collections::HashMap;
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// let webview_window = WebviewWindowBuilder::new(app, "core", WebviewUrl::App("index.html".into()))
|
||||
/// .on_web_resource_request(|request, response| {
|
||||
/// if request.uri().scheme_str() == Some("tauri") {
|
||||
/// // if we have a CSP header, Tauri is loading an HTML file
|
||||
/// // for this example, let's dynamically change the CSP
|
||||
/// if let Some(csp) = response.headers_mut().get_mut("Content-Security-Policy") {
|
||||
/// // use the tauri helper to parse the CSP policy to a map
|
||||
/// let mut csp_map: HashMap<String, CspDirectiveSources> = Csp::Policy(csp.to_str().unwrap().to_string()).into();
|
||||
/// csp_map.entry("script-src".to_string()).or_insert_with(Default::default).push("'unsafe-inline'");
|
||||
/// // use the tauri helper to get a CSP string from the map
|
||||
/// let csp_string = Csp::from(csp_map).to_string();
|
||||
/// *csp = HeaderValue::from_str(&csp_string).unwrap();
|
||||
/// }
|
||||
/// }
|
||||
/// })
|
||||
/// .build()?;
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
pub fn on_web_resource_request<
|
||||
F: Fn(http::Request<Vec<u8>>, &mut http::Response<Cow<'static, [u8]>>) + Send + Sync + 'static,
|
||||
>(
|
||||
@ -236,30 +231,24 @@ tauri::Builder::default()
|
||||
/// Defines a closure to be executed when the webview navigates to a URL. Returning `false` cancels the navigation.
|
||||
///
|
||||
/// # Examples
|
||||
#[cfg_attr(
|
||||
feature = "unstable",
|
||||
doc = r####"
|
||||
```rust,no_run
|
||||
use tauri::{
|
||||
utils::config::{Csp, CspDirectiveSources, WebviewUrl},
|
||||
window::WindowBuilder,
|
||||
webview::WebviewWindowBuilder,
|
||||
};
|
||||
use http::header::HeaderValue;
|
||||
use std::collections::HashMap;
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
let webview_window = WebviewWindowBuilder::new(app, "core", WebviewUrl::App("index.html".into()))
|
||||
.on_navigation(|url| {
|
||||
// allow the production URL or localhost on dev
|
||||
url.scheme() == "tauri" || (cfg!(dev) && url.host_str() == Some("localhost"))
|
||||
})
|
||||
.build()?;
|
||||
Ok(())
|
||||
});
|
||||
```
|
||||
"####
|
||||
)]
|
||||
/// ```rust,no_run
|
||||
/// use tauri::{
|
||||
/// utils::config::{Csp, CspDirectiveSources, WebviewUrl},
|
||||
/// webview::WebviewWindowBuilder,
|
||||
/// };
|
||||
/// use http::header::HeaderValue;
|
||||
/// use std::collections::HashMap;
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// let webview_window = WebviewWindowBuilder::new(app, "core", WebviewUrl::App("index.html".into()))
|
||||
/// .on_navigation(|url| {
|
||||
/// // allow the production URL or localhost on dev
|
||||
/// url.scheme() == "tauri" || (cfg!(dev) && url.host_str() == Some("localhost"))
|
||||
/// })
|
||||
/// .build()?;
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
pub fn on_navigation<F: Fn(&Url) -> bool + Send + 'static>(mut self, f: F) -> Self {
|
||||
self.webview_builder = self.webview_builder.on_navigation(f);
|
||||
self
|
||||
@ -318,36 +307,30 @@ tauri::Builder::default()
|
||||
/// or [`tauri_runtime::webview::PageLoadEvent::Finished`] when the page finishes loading.
|
||||
///
|
||||
/// # Examples
|
||||
#[cfg_attr(
|
||||
feature = "unstable",
|
||||
doc = r####"
|
||||
```rust,no_run
|
||||
use tauri::{
|
||||
utils::config::{Csp, CspDirectiveSources, WebviewUrl},
|
||||
window::WindowBuilder,
|
||||
webview::{PageLoadEvent, WebviewWindowBuilder},
|
||||
};
|
||||
use http::header::HeaderValue;
|
||||
use std::collections::HashMap;
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
let webview_window = WebviewWindowBuilder::new(app, "core", WebviewUrl::App("index.html".into()))
|
||||
.on_page_load(|window, payload| {
|
||||
match payload.event() {
|
||||
PageLoadEvent::Started => {
|
||||
println!("{} finished loading", payload.url());
|
||||
}
|
||||
PageLoadEvent::Finished => {
|
||||
println!("{} finished loading", payload.url());
|
||||
}
|
||||
}
|
||||
})
|
||||
.build()?;
|
||||
Ok(())
|
||||
});
|
||||
```
|
||||
"####
|
||||
)]
|
||||
/// ```rust,no_run
|
||||
/// use tauri::{
|
||||
/// utils::config::{Csp, CspDirectiveSources, WebviewUrl},
|
||||
/// webview::{PageLoadEvent, WebviewWindowBuilder},
|
||||
/// };
|
||||
/// use http::header::HeaderValue;
|
||||
/// use std::collections::HashMap;
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// let webview_window = WebviewWindowBuilder::new(app, "core", WebviewUrl::App("index.html".into()))
|
||||
/// .on_page_load(|window, payload| {
|
||||
/// match payload.event() {
|
||||
/// PageLoadEvent::Started => {
|
||||
/// println!("{} finished loading", payload.url());
|
||||
/// }
|
||||
/// PageLoadEvent::Finished => {
|
||||
/// println!("{} finished loading", payload.url());
|
||||
/// }
|
||||
/// }
|
||||
/// })
|
||||
/// .build()?;
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
pub fn on_page_load<F: Fn(WebviewWindow<R>, PageLoadPayload<'_>) + Send + Sync + 'static>(
|
||||
mut self,
|
||||
f: F,
|
||||
@ -776,32 +759,27 @@ impl<'a, R: Runtime, M: Manager<R>> WebviewWindowBuilder<'a, R, M> {
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(
|
||||
feature = "unstable",
|
||||
doc = r####"
|
||||
```rust
|
||||
use tauri::{WindowBuilder, Runtime};
|
||||
|
||||
const INIT_SCRIPT: &str = r#"
|
||||
if (window.location.origin === 'https://tauri.app') {
|
||||
console.log("hello world from js init script");
|
||||
|
||||
window.__MY_CUSTOM_PROPERTY__ = { foo: 'bar' };
|
||||
}
|
||||
"#;
|
||||
|
||||
fn main() {
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
let webview = tauri::WebviewWindowBuilder::new(app, "label", tauri::WebviewUrl::App("index.html".into()))
|
||||
.initialization_script(INIT_SCRIPT)
|
||||
.build()?;
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
```
|
||||
"####
|
||||
)]
|
||||
/// ```rust
|
||||
/// use tauri::{WebviewWindowBuilder, Runtime};
|
||||
///
|
||||
/// const INIT_SCRIPT: &str = r#"
|
||||
/// if (window.location.origin === 'https://tauri.app') {
|
||||
/// console.log("hello world from js init script");
|
||||
///
|
||||
/// window.__MY_CUSTOM_PROPERTY__ = { foo: 'bar' };
|
||||
/// }
|
||||
/// "#;
|
||||
///
|
||||
/// fn main() {
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// let webview = tauri::WebviewWindowBuilder::new(app, "label", tauri::WebviewUrl::App("index.html".into()))
|
||||
/// .initialization_script(INIT_SCRIPT)
|
||||
/// .build()?;
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// }
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub fn initialization_script(mut self, script: &str) -> Self {
|
||||
self.webview_builder = self.webview_builder.initialization_script(script);
|
||||
@ -1003,36 +981,33 @@ impl<R: Runtime> WebviewWindow<R> {
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(
|
||||
feature = "unstable",
|
||||
doc = r####"
|
||||
```
|
||||
use tauri::menu::{Menu, Submenu, MenuItem};
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
let handle = app.handle();
|
||||
let save_menu_item = MenuItem::new(handle, "Save", true, None::<&str>)?;
|
||||
let menu = Menu::with_items(handle, &[
|
||||
&Submenu::with_items(handle, "File", true, &[
|
||||
&save_menu_item,
|
||||
])?,
|
||||
])?;
|
||||
let webview_window = tauri::window::WindowBuilder::new(app, "editor")
|
||||
.menu(menu)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
webview_window.on_menu_event(move |window, event| {
|
||||
if event.id == save_menu_item.id() {
|
||||
// save menu item
|
||||
}
|
||||
});
|
||||
|
||||
Ok(())
|
||||
});
|
||||
```
|
||||
"####
|
||||
)]
|
||||
/// ```
|
||||
/// use tauri::menu::{Menu, Submenu, MenuItem};
|
||||
/// use tauri::{WebviewWindowBuilder, WebviewUrl};
|
||||
///
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// let handle = app.handle();
|
||||
/// let save_menu_item = MenuItem::new(handle, "Save", true, None::<&str>)?;
|
||||
/// let menu = Menu::with_items(handle, &[
|
||||
/// &Submenu::with_items(handle, "File", true, &[
|
||||
/// &save_menu_item,
|
||||
/// ])?,
|
||||
/// ])?;
|
||||
/// let webview_window = WebviewWindowBuilder::new(app, "editor", WebviewUrl::default())
|
||||
/// .menu(menu)
|
||||
/// .build()
|
||||
/// .unwrap();
|
||||
///
|
||||
/// webview_window.on_menu_event(move |window, event| {
|
||||
/// if event.id == save_menu_item.id() {
|
||||
/// // save menu item
|
||||
/// }
|
||||
/// });
|
||||
///
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
pub fn on_menu_event<F: Fn(&crate::Window<R>, crate::menu::MenuEvent) + Send + Sync + 'static>(
|
||||
&self,
|
||||
f: F,
|
||||
@ -1698,20 +1673,15 @@ impl<R: Runtime> WebviewWindow<R> {
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(
|
||||
feature = "unstable",
|
||||
doc = r####"
|
||||
```rust,no_run
|
||||
use tauri::Manager;
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
#[cfg(debug_assertions)]
|
||||
app.get_webview("main").unwrap().open_devtools();
|
||||
Ok(())
|
||||
});
|
||||
```
|
||||
"####
|
||||
)]
|
||||
/// ```rust,no_run
|
||||
/// use tauri::Manager;
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// #[cfg(debug_assertions)]
|
||||
/// app.get_webview_window("main").unwrap().open_devtools();
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
#[cfg(any(debug_assertions, feature = "devtools"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(debug_assertions, feature = "devtools"))))]
|
||||
pub fn open_devtools(&self) {
|
||||
@ -1729,27 +1699,22 @@ tauri::Builder::default()
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(
|
||||
feature = "unstable",
|
||||
doc = r####"
|
||||
```rust,no_run
|
||||
use tauri::Manager;
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
let webview = app.get_webview("main").unwrap();
|
||||
webview.open_devtools();
|
||||
std::thread::spawn(move || {
|
||||
std::thread::sleep(std::time::Duration::from_secs(10));
|
||||
webview.close_devtools();
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
```
|
||||
"####
|
||||
)]
|
||||
/// ```rust,no_run
|
||||
/// use tauri::Manager;
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// #[cfg(debug_assertions)]
|
||||
/// {
|
||||
/// let webview = app.get_webview_window("main").unwrap();
|
||||
/// webview.open_devtools();
|
||||
/// std::thread::spawn(move || {
|
||||
/// std::thread::sleep(std::time::Duration::from_secs(10));
|
||||
/// webview.close_devtools();
|
||||
/// });
|
||||
/// }
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
#[cfg(any(debug_assertions, feature = "devtools"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(debug_assertions, feature = "devtools"))))]
|
||||
pub fn close_devtools(&self) {
|
||||
@ -1767,25 +1732,20 @@ tauri::Builder::default()
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(
|
||||
feature = "unstable",
|
||||
doc = r####"
|
||||
```rust,no_run
|
||||
use tauri::Manager;
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
let webview = app.get_webview("main").unwrap();
|
||||
if !webview.is_devtools_open() {
|
||||
webview.open_devtools();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
```
|
||||
"####
|
||||
)]
|
||||
/// ```rust,no_run
|
||||
/// use tauri::Manager;
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// #[cfg(debug_assertions)]
|
||||
/// {
|
||||
/// let webview = app.get_webview_window("main").unwrap();
|
||||
/// if !webview.is_devtools_open() {
|
||||
/// webview.open_devtools();
|
||||
/// }
|
||||
/// }
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
#[cfg(any(debug_assertions, feature = "devtools"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(debug_assertions, feature = "devtools"))))]
|
||||
pub fn is_devtools_open(&self) -> bool {
|
||||
@ -1804,31 +1764,25 @@ tauri::Builder::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Event system APIs.
|
||||
impl<R: Runtime> WebviewWindow<R> {
|
||||
impl<R: Runtime> Listener<R> for WebviewWindow<R> {
|
||||
/// Listen to an event on this webview window.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(
|
||||
feature = "unstable",
|
||||
doc = r####"
|
||||
```
|
||||
use tauri::Manager;
|
||||
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
let webview = app.get_webview("main").unwrap();
|
||||
webview.listen("component-loaded", move |event| {
|
||||
println!("window just loaded a component");
|
||||
});
|
||||
|
||||
Ok(())
|
||||
});
|
||||
```
|
||||
"####
|
||||
)]
|
||||
pub fn listen<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
/// ```
|
||||
/// use tauri::{Manager, Listener};
|
||||
///
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// let webview_window = app.get_webview_window("main").unwrap();
|
||||
/// webview_window.listen("component-loaded", move |event| {
|
||||
/// println!("window just loaded a component");
|
||||
/// });
|
||||
///
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
fn listen<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
where
|
||||
F: Fn(Event) + Send + 'static,
|
||||
{
|
||||
@ -1841,43 +1795,10 @@ tauri::Builder::default()
|
||||
)
|
||||
}
|
||||
|
||||
/// Unlisten to an event on this webview window.
|
||||
///
|
||||
/// # Examples
|
||||
#[cfg_attr(
|
||||
feature = "unstable",
|
||||
doc = r####"
|
||||
```
|
||||
use tauri::Manager;
|
||||
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
let webview = app.get_webview("main").unwrap();
|
||||
let webview_ = webview.clone();
|
||||
let handler = webview.listen("component-loaded", move |event| {
|
||||
println!("webview just loaded a component");
|
||||
|
||||
// we no longer need to listen to the event
|
||||
// we also could have used `webview.once` instead
|
||||
webview_.unlisten(event.id());
|
||||
});
|
||||
|
||||
// stop listening to the event when you do not need it anymore
|
||||
webview.unlisten(handler);
|
||||
|
||||
Ok(())
|
||||
});
|
||||
```
|
||||
"####
|
||||
)]
|
||||
pub fn unlisten(&self, id: EventId) {
|
||||
self.manager().unlisten(id)
|
||||
}
|
||||
|
||||
/// Listen to an event on this window webview only once.
|
||||
///
|
||||
/// See [`Self::listen`] for more information.
|
||||
pub fn once<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
fn once<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
where
|
||||
F: FnOnce(Event) + Send + 'static,
|
||||
{
|
||||
@ -1889,6 +1810,108 @@ tauri::Builder::default()
|
||||
handler,
|
||||
)
|
||||
}
|
||||
|
||||
/// Unlisten to an event on this webview window.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use tauri::{Manager, Listener};
|
||||
///
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// let webview_window = app.get_webview_window("main").unwrap();
|
||||
/// let webview_window_ = webview_window.clone();
|
||||
/// let handler = webview_window.listen("component-loaded", move |event| {
|
||||
/// println!("webview_window just loaded a component");
|
||||
///
|
||||
/// // we no longer need to listen to the event
|
||||
/// // we also could have used `webview_window.once` instead
|
||||
/// webview_window_.unlisten(event.id());
|
||||
/// });
|
||||
///
|
||||
/// // stop listening to the event when you do not need it anymore
|
||||
/// webview_window.unlisten(handler);
|
||||
///
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
fn unlisten(&self, id: EventId) {
|
||||
self.manager().unlisten(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Runtime> Emitter<R> for WebviewWindow<R> {
|
||||
/// Emits an event to all [targets](EventTarget).
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use tauri::Emitter;
|
||||
///
|
||||
/// #[tauri::command]
|
||||
/// fn synchronize(window: tauri::WebviewWindow) {
|
||||
/// // emits the synchronized event to all webviews
|
||||
/// window.emit("synchronized", ());
|
||||
/// }
|
||||
/// ```
|
||||
fn emit<S: Serialize + Clone>(&self, event: &str, payload: S) -> crate::Result<()> {
|
||||
self.manager().emit(event, payload)
|
||||
}
|
||||
|
||||
/// Emits an event to all [targets](EventTarget) matching the given target.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use tauri::{Emitter, EventTarget};
|
||||
///
|
||||
/// #[tauri::command]
|
||||
/// fn download(window: tauri::WebviewWindow) {
|
||||
/// for i in 1..100 {
|
||||
/// std::thread::sleep(std::time::Duration::from_millis(150));
|
||||
/// // emit a download progress event to all listeners
|
||||
/// window.emit_to(EventTarget::any(), "download-progress", i);
|
||||
/// // emit an event to listeners that used App::listen or AppHandle::listen
|
||||
/// window.emit_to(EventTarget::app(), "download-progress", i);
|
||||
/// // emit an event to any webview/window/webviewWindow matching the given label
|
||||
/// window.emit_to("updater", "download-progress", i); // similar to using EventTarget::labeled
|
||||
/// window.emit_to(EventTarget::labeled("updater"), "download-progress", i);
|
||||
/// // emit an event to listeners that used WebviewWindow::listen
|
||||
/// window.emit_to(EventTarget::webview_window("updater"), "download-progress", i);
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
fn emit_to<I, S>(&self, target: I, event: &str, payload: S) -> crate::Result<()>
|
||||
where
|
||||
I: Into<EventTarget>,
|
||||
S: Serialize + Clone,
|
||||
{
|
||||
self.manager().emit_to(target, event, payload)
|
||||
}
|
||||
|
||||
/// Emits an event to all [targets](EventTarget) based on the given filter.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use tauri::{Emitter, EventTarget};
|
||||
///
|
||||
/// #[tauri::command]
|
||||
/// fn download(window: tauri::WebviewWindow) {
|
||||
/// for i in 1..100 {
|
||||
/// std::thread::sleep(std::time::Duration::from_millis(150));
|
||||
/// // emit a download progress event to the updater window
|
||||
/// window.emit_filter("download-progress", i, |t| match t {
|
||||
/// EventTarget::WebviewWindow { label } => label == "main",
|
||||
/// _ => false,
|
||||
/// });
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
fn emit_filter<S, F>(&self, event: &str, payload: S, filter: F) -> crate::Result<()>
|
||||
where
|
||||
S: Serialize + Clone,
|
||||
F: Fn(&EventTarget) -> bool,
|
||||
{
|
||||
self.manager().emit_filter(event, payload, filter)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Runtime> Manager<R> for WebviewWindow<R> {
|
||||
|
||||
@ -28,7 +28,8 @@ use crate::{
|
||||
sealed::{ManagerBase, RuntimeOrDispatch},
|
||||
utils::config::{WindowConfig, WindowEffectsConfig},
|
||||
webview::WebviewBuilder,
|
||||
EventLoopMessage, Manager, ResourceTable, Runtime, Theme, Webview, WindowEvent,
|
||||
Emitter, EventLoopMessage, Listener, Manager, ResourceTable, Runtime, Theme, Webview,
|
||||
WindowEvent,
|
||||
};
|
||||
#[cfg(desktop)]
|
||||
use crate::{
|
||||
@ -2019,8 +2020,7 @@ pub struct ProgressBarState {
|
||||
pub progress: Option<u64>,
|
||||
}
|
||||
|
||||
/// Event system APIs.
|
||||
impl<R: Runtime> Window<R> {
|
||||
impl<R: Runtime> Listener<R> for Window<R> {
|
||||
/// Listen to an event on this window.
|
||||
///
|
||||
/// # Examples
|
||||
@ -2028,7 +2028,7 @@ impl<R: Runtime> Window<R> {
|
||||
feature = "unstable",
|
||||
doc = r####"
|
||||
```
|
||||
use tauri::Manager;
|
||||
use tauri::{Manager, Listener};
|
||||
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
@ -2042,7 +2042,7 @@ tauri::Builder::default()
|
||||
```
|
||||
"####
|
||||
)]
|
||||
pub fn listen<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
fn listen<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
where
|
||||
F: Fn(Event) + Send + 'static,
|
||||
{
|
||||
@ -2055,6 +2055,22 @@ tauri::Builder::default()
|
||||
)
|
||||
}
|
||||
|
||||
/// Listen to an event on this window only once.
|
||||
///
|
||||
/// See [`Self::listen`] for more information.
|
||||
fn once<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
where
|
||||
F: FnOnce(Event) + Send + 'static,
|
||||
{
|
||||
self.manager.once(
|
||||
event.into(),
|
||||
EventTarget::Window {
|
||||
label: self.label().to_string(),
|
||||
},
|
||||
handler,
|
||||
)
|
||||
}
|
||||
|
||||
/// Unlisten to an event on this window.
|
||||
///
|
||||
/// # Examples
|
||||
@ -2062,7 +2078,7 @@ tauri::Builder::default()
|
||||
feature = "unstable",
|
||||
doc = r####"
|
||||
```
|
||||
use tauri::Manager;
|
||||
use tauri::{Manager, Listener};
|
||||
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
@ -2084,24 +2100,97 @@ tauri::Builder::default()
|
||||
```
|
||||
"####
|
||||
)]
|
||||
pub fn unlisten(&self, id: EventId) {
|
||||
fn unlisten(&self, id: EventId) {
|
||||
self.manager.unlisten(id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Listen to an event on this window only once.
|
||||
impl<R: Runtime> Emitter<R> for Window<R> {
|
||||
/// Emits an event to all [targets](EventTarget).
|
||||
///
|
||||
/// See [`Self::listen`] for more information.
|
||||
pub fn once<F>(&self, event: impl Into<String>, handler: F) -> EventId
|
||||
/// # Examples
|
||||
#[cfg_attr(
|
||||
feature = "unstable",
|
||||
doc = r####"
|
||||
```
|
||||
use tauri::Emitter;
|
||||
|
||||
#[tauri::command]
|
||||
fn synchronize(window: tauri::Window) {
|
||||
// emits the synchronized event to all webviews
|
||||
window.emit("synchronized", ());
|
||||
}
|
||||
```
|
||||
"####
|
||||
)]
|
||||
fn emit<S: Serialize + Clone>(&self, event: &str, payload: S) -> crate::Result<()> {
|
||||
self.manager.emit(event, payload)
|
||||
}
|
||||
|
||||
/// Emits an event to all [targets](EventTarget) matching the given target.
|
||||
///
|
||||
/// # Examples
|
||||
#[cfg_attr(
|
||||
feature = "unstable",
|
||||
doc = r####"
|
||||
```
|
||||
use tauri::{Emitter, EventTarget};
|
||||
|
||||
#[tauri::command]
|
||||
fn download(window: tauri::Window) {
|
||||
for i in 1..100 {
|
||||
std::thread::sleep(std::time::Duration::from_millis(150));
|
||||
// emit a download progress event to all listeners
|
||||
window.emit_to(EventTarget::any(), "download-progress", i);
|
||||
// emit an event to listeners that used App::listen or AppHandle::listen
|
||||
window.emit_to(EventTarget::app(), "download-progress", i);
|
||||
// emit an event to any webview/window/webviewWindow matching the given label
|
||||
window.emit_to("updater", "download-progress", i); // similar to using EventTarget::labeled
|
||||
window.emit_to(EventTarget::labeled("updater"), "download-progress", i);
|
||||
// emit an event to listeners that used WebviewWindow::listen
|
||||
window.emit_to(EventTarget::webview_window("updater"), "download-progress", i);
|
||||
}
|
||||
}
|
||||
```
|
||||
"####
|
||||
)]
|
||||
fn emit_to<I, S>(&self, target: I, event: &str, payload: S) -> crate::Result<()>
|
||||
where
|
||||
F: FnOnce(Event) + Send + 'static,
|
||||
I: Into<EventTarget>,
|
||||
S: Serialize + Clone,
|
||||
{
|
||||
self.manager.once(
|
||||
event.into(),
|
||||
EventTarget::Window {
|
||||
label: self.label().to_string(),
|
||||
},
|
||||
handler,
|
||||
)
|
||||
self.manager.emit_to(target, event, payload)
|
||||
}
|
||||
|
||||
/// Emits an event to all [targets](EventTarget) based on the given filter.
|
||||
///
|
||||
/// # Examples
|
||||
#[cfg_attr(
|
||||
feature = "unstable",
|
||||
doc = r####"
|
||||
```
|
||||
use tauri::{Emitter, EventTarget};
|
||||
|
||||
#[tauri::command]
|
||||
fn download(window: tauri::Window) {
|
||||
for i in 1..100 {
|
||||
std::thread::sleep(std::time::Duration::from_millis(150));
|
||||
// emit a download progress event to the updater window
|
||||
window.emit_filter("download-progress", i, |t| match t {
|
||||
EventTarget::WebviewWindow { label } => label == "main",
|
||||
_ => false,
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
"####
|
||||
)]
|
||||
fn emit_filter<S, F>(&self, event: &str, payload: S, filter: F) -> crate::Result<()>
|
||||
where
|
||||
S: Serialize + Clone,
|
||||
F: Fn(&EventTarget) -> bool,
|
||||
{
|
||||
self.manager.emit_filter(event, payload, filter)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
22
examples/api/src-tauri/Cargo.lock
generated
22
examples/api/src-tauri/Cargo.lock
generated
@ -4035,6 +4035,17 @@ dependencies = [
|
||||
"syn 2.0.63",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.56.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.52",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.57.0"
|
||||
@ -4046,6 +4057,17 @@ dependencies = [
|
||||
"syn 2.0.63",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.56.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.52",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.1.1"
|
||||
|
||||
@ -12,7 +12,7 @@ use serde::Serialize;
|
||||
use tauri::{
|
||||
ipc::Channel,
|
||||
webview::{PageLoadEvent, WebviewWindowBuilder},
|
||||
App, AppHandle, Manager, RunEvent, Runtime, WebviewUrl,
|
||||
App, AppHandle, Emitter, Listener, Manager, RunEvent, Runtime, WebviewUrl,
|
||||
};
|
||||
use tauri_plugin_sample::{PingRequest, SampleExt};
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
use tauri::{webview::PageLoadEvent, WebviewWindowBuilder};
|
||||
use tauri::{webview::PageLoadEvent, Listener, WebviewWindowBuilder};
|
||||
use tauri_utils::acl::ExecutionContext;
|
||||
|
||||
fn main() {
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
use tauri::{webview::PageLoadEvent, WebviewUrl, WebviewWindowBuilder};
|
||||
use tauri::{webview::PageLoadEvent, Listener, WebviewUrl, WebviewWindowBuilder};
|
||||
use tauri_utils::acl::ExecutionContext;
|
||||
|
||||
fn main() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user