tauri_store/
event.rs

1use crate::error::Result;
2use crate::store::{Store, StoreId, StoreOptions, StoreState};
3use serde::Serialize;
4use tauri::{AppHandle, Emitter as _, EventTarget, Runtime, WebviewWindow, Window};
5
6pub const STORE_CONFIG_CHANGE_EVENT: &str = "tauri-store://config-change";
7pub const STORE_STATE_CHANGE_EVENT: &str = "tauri-store://state-change";
8pub const STORE_UNLOAD_EVENT: &str = "tauri-store://unload";
9
10#[derive(Clone, Debug, Serialize)]
11#[serde(rename_all = "camelCase")]
12pub(crate) struct StatePayload<'a> {
13  id: &'a StoreId,
14  state: &'a StoreState,
15}
16
17impl<'a, R: Runtime> From<&'a Store<R>> for StatePayload<'a> {
18  fn from(store: &'a Store<R>) -> Self {
19    Self { id: &store.id, state: store.state() }
20  }
21}
22
23#[derive(Clone, Debug, Serialize)]
24#[serde(rename_all = "camelCase")]
25pub(crate) struct ConfigPayload<'a> {
26  id: &'a StoreId,
27  config: StoreOptions,
28}
29
30impl<'a, R: Runtime> From<&'a Store<R>> for ConfigPayload<'a> {
31  fn from(store: &'a Store<R>) -> Self {
32    Self { id: &store.id, config: store.into() }
33  }
34}
35
36pub(crate) fn emit<R, T, S>(app: &AppHandle<R>, event: &str, payload: &T, source: S) -> Result<()>
37where
38  R: Runtime,
39  T: Serialize + ?Sized,
40  S: Into<EventSource>,
41{
42  let source: EventSource = source.into();
43  if let Some(source) = source.0 {
44    emit_filter(app, event, payload, |it| it != source)
45  } else {
46    emit_all(app, event, payload)
47  }
48}
49
50fn emit_all<R, T>(app: &AppHandle<R>, event: &str, payload: &T) -> Result<()>
51where
52  R: Runtime,
53  T: Serialize + ?Sized,
54{
55  app.emit_filter(event, payload, |target| {
56    matches!(target, EventTarget::WebviewWindow { .. })
57  })?;
58
59  Ok(())
60}
61
62fn emit_filter<R, T, F>(app: &AppHandle<R>, event: &str, payload: &T, f: F) -> Result<()>
63where
64  R: Runtime,
65  T: Serialize + ?Sized,
66  F: Fn(&str) -> bool,
67{
68  #[rustfmt::skip]
69  app.emit_filter(event, payload, |target| {
70    matches!(target, EventTarget::WebviewWindow { label } if f(label))
71  })?;
72
73  Ok(())
74}
75
76/// Source of a store event.
77pub struct EventSource(Option<String>);
78
79impl EventSource {
80  #[inline]
81  pub const fn is_backend(&self) -> bool {
82    self.0.is_none()
83  }
84}
85
86impl From<&str> for EventSource {
87  fn from(source: &str) -> Self {
88    Self(Some(String::from(source)))
89  }
90}
91
92impl From<Option<&str>> for EventSource {
93  fn from(source: Option<&str>) -> Self {
94    Self(source.map(String::from))
95  }
96}
97
98impl From<String> for EventSource {
99  fn from(source: String) -> Self {
100    Self(Some(source))
101  }
102}
103
104impl From<&String> for EventSource {
105  fn from(source: &String) -> Self {
106    Self(Some(source.to_owned()))
107  }
108}
109
110impl From<Option<String>> for EventSource {
111  fn from(source: Option<String>) -> Self {
112    Self(source)
113  }
114}
115
116impl From<&WebviewWindow> for EventSource {
117  fn from(window: &WebviewWindow) -> Self {
118    Self(Some(window.label().to_owned()))
119  }
120}
121
122impl From<&Window> for EventSource {
123  fn from(window: &Window) -> Self {
124    Self(Some(window.label().to_owned()))
125  }
126}