refactor(core): scope JS resources to the webview (#9272)

* refactor(core): scope JS resources to the webview

* clippy

* change files

* swap args order

* more clippy

* just add them on each type

* clippy

* macro docs

* Update mod.rs

* use random rid

* revert resource table arg change

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
This commit is contained in:
Amr Bashir 2024-04-02 19:41:47 +02:00 committed by GitHub
parent 8276ab767b
commit 284eca9ef2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 357 additions and 295 deletions

View File

@ -0,0 +1,5 @@
---
'tauri': 'patch:breaking'
---
`Manager::resources_table` is now scoped so each `App/AppHandle/Window/Webview/WebviewWindow` has its own resource collection.

View File

@ -94,19 +94,19 @@ pub fn default_runtime(attributes: TokenStream, input: TokenStream) -> TokenStre
/// Accepts a closure-like syntax to call arbitrary code on a menu item /// Accepts a closure-like syntax to call arbitrary code on a menu item
/// after matching against `kind` and retrieving it from `resources_table` using `rid`. /// after matching against `kind` and retrieving it from `resources_table` using `rid`.
/// ///
/// You can optionally pass a third parameter to select which item kinds /// You can optionally pass a 5th parameter to select which item kinds
/// to match against, by providing a `|` separated list of item kinds /// to match against, by providing a `|` separated list of item kinds
/// ```ignore /// ```ignore
/// do_menu_item!(|i| i.set_text(text), Check | Submenu); /// do_menu_item!(resources_table, rid, kind, |i| i.set_text(text), Check | Submenu);
/// ``` /// ```
/// You could also provide a negated list /// You could also provide a negated list
/// ```ignore /// ```ignore
/// do_menu_item!(|i| i.set_text(text), !Check); /// do_menu_item!(resources_table, rid, kind, |i| i.set_text(text), !Check);
/// do_menu_item!(|i| i.set_text(text), !Check | !Submenu); /// do_menu_item!(resources_table, rid, kind, |i| i.set_text(text), !Check | !Submenu);
/// ``` /// ```
/// but you can't have mixed negations and positive kinds. /// but you can't have mixed negations and positive kinds.
/// ```ignore /// ```ignore
/// do_menu_item!(|i| i.set_text(text), !Check | Submeun); /// do_menu_item!(resources_table, rid, kind, |i| i.set_text(text), !Check | Submeun);
/// ``` /// ```
/// ///
/// #### Example /// #### Example
@ -115,7 +115,7 @@ pub fn default_runtime(attributes: TokenStream, input: TokenStream) -> TokenStre
/// let rid = 23; /// let rid = 23;
/// let kind = ItemKind::Check; /// let kind = ItemKind::Check;
/// let resources_table = app.resources_table(); /// let resources_table = app.resources_table();
/// do_menu_item!(|i| i.set_text(text)) /// do_menu_item!(resources_table, rid, kind, |i| i.set_text(text))
/// ``` /// ```
/// which will expand into: /// which will expand into:
/// ```ignore /// ```ignore

View File

@ -20,13 +20,32 @@ pub struct DoMenuItemInput {
} }
#[derive(Clone)] #[derive(Clone)]
struct NegatedIdent(bool, Ident); struct NegatedIdent {
negated: bool,
ident: Ident,
}
impl NegatedIdent {
fn new(ident: &str) -> Self {
Self {
negated: false,
ident: Ident::new(ident, Span::call_site()),
}
}
fn is_negated(&self) -> bool {
self.negated
}
}
impl Parse for NegatedIdent { impl Parse for NegatedIdent {
fn parse(input: ParseStream) -> syn::Result<Self> { fn parse(input: ParseStream) -> syn::Result<Self> {
let t = input.parse::<Token![!]>(); let negated_token = input.parse::<Token![!]>();
let i: Ident = input.parse()?; let ident: Ident = input.parse()?;
Ok(NegatedIdent(t.is_ok(), i)) Ok(NegatedIdent {
negated: negated_token.is_ok(),
ident,
})
} }
} }
@ -67,32 +86,31 @@ pub fn do_menu_item(input: DoMenuItemInput) -> TokenStream {
} = input; } = input;
let defaults = vec![ let defaults = vec![
NegatedIdent(false, Ident::new("Submenu", Span::call_site())), NegatedIdent::new("Submenu"),
NegatedIdent(false, Ident::new("MenuItem", Span::call_site())), NegatedIdent::new("MenuItem"),
NegatedIdent(false, Ident::new("Predefined", Span::call_site())), NegatedIdent::new("Predefined"),
NegatedIdent(false, Ident::new("Check", Span::call_site())), NegatedIdent::new("Check"),
NegatedIdent(false, Ident::new("Icon", Span::call_site())), NegatedIdent::new("Icon"),
]; ];
if kinds.is_empty() { if kinds.is_empty() {
kinds.extend(defaults.clone()); kinds.extend(defaults.clone());
} }
let has_negated = kinds.iter().any(|n| n.0); let has_negated = kinds.iter().any(|n| n.is_negated());
if has_negated { if has_negated {
kinds.extend(defaults); kinds.extend(defaults);
kinds.sort_by(|a, b| a.1.cmp(&b.1)); kinds.sort_by(|a, b| a.ident.cmp(&b.ident));
kinds.dedup_by(|a, b| a.1 == b.1); kinds.dedup_by(|a, b| a.ident == b.ident);
} }
let (kinds, types): (Vec<Ident>, Vec<Ident>) = kinds let (kinds, types): (Vec<Ident>, Vec<Ident>) = kinds
.into_iter() .into_iter()
.filter_map(|nident| { .filter_map(|nident| {
if nident.0 { if nident.is_negated() {
None None
} else { } else {
match nident.1 { match nident.ident {
i if i == "MenuItem" => Some((i, Ident::new("MenuItem", Span::call_site()))), i if i == "MenuItem" => Some((i, Ident::new("MenuItem", Span::call_site()))),
i if i == "Submenu" => Some((i, Ident::new("Submenu", Span::call_site()))), i if i == "Submenu" => Some((i, Ident::new("Submenu", Span::call_site()))),
i if i == "Predefined" => Some((i, Ident::new("PredefinedMenuItem", Span::call_site()))), i if i == "Predefined" => Some((i, Ident::new("PredefinedMenuItem", Span::call_site()))),

View File

@ -13,6 +13,7 @@ use crate::{
AppManager, Asset, AppManager, Asset,
}, },
plugin::{Plugin, PluginStore}, plugin::{Plugin, PluginStore},
resources::ResourceTable,
runtime::{ runtime::{
window::{WebviewEvent as RuntimeWebviewEvent, WindowEvent as RuntimeWindowEvent}, window::{WebviewEvent as RuntimeWebviewEvent, WindowEvent as RuntimeWindowEvent},
ExitRequestedEventAction, RunEvent as RuntimeRunEvent, ExitRequestedEventAction, RunEvent as RuntimeRunEvent,
@ -45,7 +46,7 @@ use std::{
borrow::Cow, borrow::Cow,
collections::HashMap, collections::HashMap,
fmt, fmt,
sync::{mpsc::Sender, Arc}, sync::{mpsc::Sender, Arc, MutexGuard},
}; };
use crate::{event::EventId, runtime::RuntimeHandle, Event, EventTarget}; use crate::{event::EventId, runtime::RuntimeHandle, Event, EventTarget};
@ -416,7 +417,12 @@ impl<R: Runtime> AppHandle<R> {
} }
} }
impl<R: Runtime> Manager<R> for AppHandle<R> {} impl<R: Runtime> Manager<R> for AppHandle<R> {
fn resources_table(&self) -> MutexGuard<'_, ResourceTable> {
self.manager.resources_table()
}
}
impl<R: Runtime> ManagerBase<R> for AppHandle<R> { impl<R: Runtime> ManagerBase<R> for AppHandle<R> {
fn manager(&self) -> &AppManager<R> { fn manager(&self) -> &AppManager<R> {
&self.manager &self.manager
@ -457,7 +463,12 @@ impl<R: Runtime> fmt::Debug for App<R> {
} }
} }
impl<R: Runtime> Manager<R> for App<R> {} impl<R: Runtime> Manager<R> for App<R> {
fn resources_table(&self) -> MutexGuard<'_, ResourceTable> {
self.manager.resources_table()
}
}
impl<R: Runtime> ManagerBase<R> for App<R> { impl<R: Runtime> ManagerBase<R> for App<R> {
fn manager(&self) -> &AppManager<R> { fn manager(&self) -> &AppManager<R> {
&self.manager &self.manager
@ -743,7 +754,6 @@ macro_rules! shared_app_impl {
pub fn cleanup_before_exit(&self) { pub fn cleanup_before_exit(&self) {
#[cfg(all(desktop, feature = "tray-icon"))] #[cfg(all(desktop, feature = "tray-icon"))]
self.manager.tray.icons.lock().unwrap().clear(); self.manager.tray.icons.lock().unwrap().clear();
self.resources_table().clear();
} }
} }

View File

@ -165,12 +165,9 @@ pub enum JsImage {
impl JsImage { impl JsImage {
/// Converts this intermediate image format into an actual [`Image`]. /// Converts this intermediate image format into an actual [`Image`].
pub fn into_img<R: Runtime, M: Manager<R>>(self, app: &M) -> crate::Result<Arc<Image<'_>>> { pub fn into_img<R: Runtime, M: Manager<R>>(self, manager: &M) -> crate::Result<Arc<Image<'_>>> {
match self { match self {
Self::Resource(rid) => { Self::Resource(rid) => manager.resources_table().get::<Image<'static>>(rid),
let resources_table = app.resources_table();
resources_table.get::<Image<'static>>(rid)
}
#[cfg(any(feature = "image-ico", feature = "image-png"))] #[cfg(any(feature = "image-ico", feature = "image-png"))]
Self::Path(path) => Image::from_path(path).map(Arc::new).map_err(Into::into), Self::Path(path) => Image::from_path(path).map(Arc::new).map_err(Into::into),

View File

@ -5,26 +5,27 @@
use serde::Serialize; use serde::Serialize;
use crate::plugin::{Builder, TauriPlugin}; use crate::plugin::{Builder, TauriPlugin};
use crate::{command, image::Image, AppHandle, Manager, ResourceId, Runtime}; use crate::Manager;
use crate::{command, image::Image, ResourceId, Runtime, Webview};
#[command(root = "crate")] #[command(root = "crate")]
fn new<R: Runtime>( fn new<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
rgba: Vec<u8>, rgba: Vec<u8>,
width: u32, width: u32,
height: u32, height: u32,
) -> crate::Result<ResourceId> { ) -> crate::Result<ResourceId> {
let image = Image::new_owned(rgba, width, height); let image = Image::new_owned(rgba, width, height);
let mut resources_table = app.resources_table(); let mut resources_table = webview.resources_table();
let rid = resources_table.add(image); let rid = resources_table.add(image);
Ok(rid) Ok(rid)
} }
#[cfg(any(feature = "image-ico", feature = "image-png"))] #[cfg(any(feature = "image-ico", feature = "image-png"))]
#[command(root = "crate")] #[command(root = "crate")]
fn from_bytes<R: Runtime>(app: AppHandle<R>, bytes: Vec<u8>) -> crate::Result<ResourceId> { fn from_bytes<R: Runtime>(webview: Webview<R>, bytes: Vec<u8>) -> crate::Result<ResourceId> {
let image = Image::from_bytes(&bytes)?.to_owned(); let image = Image::from_bytes(&bytes)?.to_owned();
let mut resources_table = app.resources_table(); let mut resources_table = webview.resources_table();
let rid = resources_table.add(image); let rid = resources_table.add(image);
Ok(rid) Ok(rid)
} }
@ -37,9 +38,12 @@ fn from_bytes() -> std::result::Result<(), &'static str> {
#[cfg(any(feature = "image-ico", feature = "image-png"))] #[cfg(any(feature = "image-ico", feature = "image-png"))]
#[command(root = "crate")] #[command(root = "crate")]
fn from_path<R: Runtime>(app: AppHandle<R>, path: std::path::PathBuf) -> crate::Result<ResourceId> { fn from_path<R: Runtime>(
webview: Webview<R>,
path: std::path::PathBuf,
) -> crate::Result<ResourceId> {
let image = Image::from_path(path)?.to_owned(); let image = Image::from_path(path)?.to_owned();
let mut resources_table = app.resources_table(); let mut resources_table = webview.resources_table();
let rid = resources_table.add(image); let rid = resources_table.add(image);
Ok(rid) Ok(rid)
} }
@ -51,8 +55,8 @@ fn from_path() -> std::result::Result<(), &'static str> {
} }
#[command(root = "crate")] #[command(root = "crate")]
fn rgba<R: Runtime>(app: AppHandle<R>, rid: ResourceId) -> crate::Result<Vec<u8>> { fn rgba<R: Runtime>(webview: Webview<R>, rid: ResourceId) -> crate::Result<Vec<u8>> {
let resources_table = app.resources_table(); let resources_table = webview.resources_table();
let image = resources_table.get::<Image<'_>>(rid)?; let image = resources_table.get::<Image<'_>>(rid)?;
Ok(image.rgba().to_vec()) Ok(image.rgba().to_vec())
} }
@ -64,8 +68,8 @@ struct Size {
} }
#[command(root = "crate")] #[command(root = "crate")]
fn size<R: Runtime>(app: AppHandle<R>, rid: ResourceId) -> crate::Result<Size> { fn size<R: Runtime>(webview: Webview<R>, rid: ResourceId) -> crate::Result<Size> {
let resources_table = app.resources_table(); let resources_table = webview.resources_table();
let image = resources_table.get::<Image<'_>>(rid)?; let image = resources_table.get::<Image<'_>>(rid)?;
Ok(Size { Ok(Size {
width: image.width(), width: image.width(),

View File

@ -895,10 +895,8 @@ pub trait Manager<R: Runtime>: sealed::ManagerBase<R> {
self.manager().state.try_get() self.manager().state.try_get()
} }
/// Get a reference to the resources table. /// Get a reference to the resources table of this manager.
fn resources_table(&self) -> MutexGuard<'_, ResourceTable> { fn resources_table(&self) -> MutexGuard<'_, ResourceTable>;
self.manager().resources_table()
}
/// Gets the managed [`Env`]. /// Gets the managed [`Env`].
fn env(&self) -> Env { fn env(&self) -> Env {

View File

@ -558,7 +558,6 @@ impl<R: Runtime> AppManager<R> {
self.webview.webviews_lock().clone() self.webview.webviews_lock().clone()
} }
/// Resources table managed by the application.
pub(crate) fn resources_table(&self) -> MutexGuard<'_, ResourceTable> { pub(crate) fn resources_table(&self) -> MutexGuard<'_, ResourceTable> {
self self
.resources_table .resources_table

View File

@ -2,10 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
use std::{ use std::{collections::HashMap, sync::Mutex};
collections::HashMap,
sync::{Mutex, MutexGuard},
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tauri_runtime::dpi::Position; use tauri_runtime::dpi::Position;
@ -16,9 +13,9 @@ use crate::{
image::JsImage, image::JsImage,
ipc::{channel::JavaScriptChannelId, Channel}, ipc::{channel::JavaScriptChannelId, Channel},
plugin::{Builder, TauriPlugin}, plugin::{Builder, TauriPlugin},
resources::{ResourceId, ResourceTable}, resources::ResourceId,
sealed::ManagerBase, sealed::ManagerBase,
AppHandle, Manager, RunEvent, Runtime, State, Webview, Window, Manager, RunEvent, Runtime, State, Webview, Window,
}; };
use tauri_macros::do_menu_item; use tauri_macros::do_menu_item;
@ -49,12 +46,12 @@ pub(crate) struct AboutMetadata {
} }
impl AboutMetadata { impl AboutMetadata {
pub fn into_metdata<R: Runtime, M: Manager<R>>( pub fn into_metadata<R: Runtime, M: Manager<R>>(
self, self,
app: &M, manager: &M,
) -> crate::Result<super::AboutMetadata<'_>> { ) -> crate::Result<super::AboutMetadata<'_>> {
let icon = match self.icon { let icon = match self.icon {
Some(i) => Some(i.into_img(app)?.as_ref().clone()), Some(i) => Some(i.into_img(manager)?.as_ref().clone()),
None => None, None => None,
}; };
@ -105,11 +102,7 @@ struct SubmenuPayload {
} }
impl SubmenuPayload { impl SubmenuPayload {
pub fn create_item<R: Runtime>( pub fn create_item<R: Runtime>(self, webview: &Webview<R>) -> crate::Result<Submenu<R>> {
self,
webview: &Webview<R>,
resources_table: &MutexGuard<'_, ResourceTable>,
) -> crate::Result<Submenu<R>> {
let mut builder = if let Some(id) = self.id { let mut builder = if let Some(id) = self.id {
SubmenuBuilder::with_id(webview, id, self.text) SubmenuBuilder::with_id(webview, id, self.text)
} else { } else {
@ -119,7 +112,7 @@ impl SubmenuPayload {
builder = builder.enabled(enabled); builder = builder.enabled(enabled);
} }
for item in self.items { for item in self.items {
builder = item.with_item(webview, resources_table, |i| Ok(builder.item(i)))?; builder = item.with_item(webview, |i| Ok(builder.item(i)))?;
} }
builder.build() builder.build()
@ -286,7 +279,7 @@ impl PredefinedMenuItemPayload {
Predefined::Quit => PredefinedMenuItem::quit(webview, self.text.as_deref()), Predefined::Quit => PredefinedMenuItem::quit(webview, self.text.as_deref()),
Predefined::About(metadata) => { Predefined::About(metadata) => {
let metadata = match metadata { let metadata = match metadata {
Some(m) => Some(m.into_metdata(webview)?), Some(m) => Some(m.into_metadata(webview)?),
None => None, None => None,
}; };
PredefinedMenuItem::about(webview, self.text.as_deref(), metadata) PredefinedMenuItem::about(webview, self.text.as_deref(), metadata)
@ -311,14 +304,14 @@ impl MenuItemPayloadKind {
pub fn with_item<T, R: Runtime, F: FnOnce(&dyn IsMenuItem<R>) -> crate::Result<T>>( pub fn with_item<T, R: Runtime, F: FnOnce(&dyn IsMenuItem<R>) -> crate::Result<T>>(
self, self,
webview: &Webview<R>, webview: &Webview<R>,
resources_table: &MutexGuard<'_, ResourceTable>,
f: F, f: F,
) -> crate::Result<T> { ) -> crate::Result<T> {
match self { match self {
Self::ExistingItem((rid, kind)) => { Self::ExistingItem((rid, kind)) => {
let resources_table = webview.resources_table();
do_menu_item!(resources_table, rid, kind, |i| f(&*i)) do_menu_item!(resources_table, rid, kind, |i| f(&*i))
} }
Self::Submenu(i) => f(&i.create_item(webview, resources_table)?), Self::Submenu(i) => f(&i.create_item(webview)?),
Self::Predefined(i) => f(&i.create_item(webview)?), Self::Predefined(i) => f(&i.create_item(webview)?),
Self::Check(i) => f(&i.create_item(webview)?), Self::Check(i) => f(&i.create_item(webview)?),
Self::Icon(i) => f(&i.create_item(webview)?), Self::Icon(i) => f(&i.create_item(webview)?),
@ -343,7 +336,7 @@ struct NewOptions {
#[command(root = "crate")] #[command(root = "crate")]
fn new<R: Runtime>( fn new<R: Runtime>(
app: AppHandle<R>, app: Webview<R>,
webview: Webview<R>, webview: Webview<R>,
kind: ItemKind, kind: ItemKind,
options: Option<NewOptions>, options: Option<NewOptions>,
@ -361,7 +354,7 @@ fn new<R: Runtime>(
} }
if let Some(items) = options.items { if let Some(items) = options.items {
for item in items { for item in items {
builder = item.with_item(&webview, &resources_table, |i| Ok(builder.item(i)))?; builder = item.with_item(&webview, |i| Ok(builder.item(i)))?;
} }
} }
let menu = builder.build()?; let menu = builder.build()?;
@ -378,7 +371,7 @@ fn new<R: Runtime>(
enabled: options.enabled, enabled: options.enabled,
items: options.items.unwrap_or_default(), items: options.items.unwrap_or_default(),
} }
.create_item(&webview, &resources_table)?; .create_item(&webview)?;
let id = submenu.id().clone(); let id = submenu.id().clone();
let rid = resources_table.add(submenu); let rid = resources_table.add(submenu);
@ -461,13 +454,13 @@ fn append<R: Runtime>(
ItemKind::Menu => { ItemKind::Menu => {
let menu = resources_table.get::<Menu<R>>(rid)?; let menu = resources_table.get::<Menu<R>>(rid)?;
for item in items { for item in items {
item.with_item(&webview, &resources_table, |i| menu.append(i))?; item.with_item(&webview, |i| menu.append(i))?;
} }
} }
ItemKind::Submenu => { ItemKind::Submenu => {
let submenu = resources_table.get::<Submenu<R>>(rid)?; let submenu = resources_table.get::<Submenu<R>>(rid)?;
for item in items { for item in items {
item.with_item(&webview, &resources_table, |i| submenu.append(i))?; item.with_item(&webview, |i| submenu.append(i))?;
} }
} }
_ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()),
@ -488,13 +481,13 @@ fn prepend<R: Runtime>(
ItemKind::Menu => { ItemKind::Menu => {
let menu = resources_table.get::<Menu<R>>(rid)?; let menu = resources_table.get::<Menu<R>>(rid)?;
for item in items { for item in items {
item.with_item(&webview, &resources_table, |i| menu.prepend(i))?; item.with_item(&webview, |i| menu.prepend(i))?;
} }
} }
ItemKind::Submenu => { ItemKind::Submenu => {
let submenu = resources_table.get::<Submenu<R>>(rid)?; let submenu = resources_table.get::<Submenu<R>>(rid)?;
for item in items { for item in items {
item.with_item(&webview, &resources_table, |i| submenu.prepend(i))?; item.with_item(&webview, |i| submenu.prepend(i))?;
} }
} }
_ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()),
@ -516,14 +509,14 @@ fn insert<R: Runtime>(
ItemKind::Menu => { ItemKind::Menu => {
let menu = resources_table.get::<Menu<R>>(rid)?; let menu = resources_table.get::<Menu<R>>(rid)?;
for item in items { for item in items {
item.with_item(&webview, &resources_table, |i| menu.insert(i, position))?; item.with_item(&webview, |i| menu.insert(i, position))?;
position += 1 position += 1
} }
} }
ItemKind::Submenu => { ItemKind::Submenu => {
let submenu = resources_table.get::<Submenu<R>>(rid)?; let submenu = resources_table.get::<Submenu<R>>(rid)?;
for item in items { for item in items {
item.with_item(&webview, &resources_table, |i| submenu.insert(i, position))?; item.with_item(&webview, |i| submenu.insert(i, position))?;
position += 1 position += 1
} }
} }
@ -535,12 +528,12 @@ fn insert<R: Runtime>(
#[command(root = "crate")] #[command(root = "crate")]
fn remove<R: Runtime>( fn remove<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
rid: ResourceId, rid: ResourceId,
kind: ItemKind, kind: ItemKind,
item: (ResourceId, ItemKind), item: (ResourceId, ItemKind),
) -> crate::Result<()> { ) -> crate::Result<()> {
let resources_table = app.resources_table(); let resources_table = webview.resources_table();
let (item_rid, item_kind) = item; let (item_rid, item_kind) = item;
match kind { match kind {
ItemKind::Menu => { ItemKind::Menu => {
@ -574,12 +567,12 @@ macro_rules! make_item_resource {
#[command(root = "crate")] #[command(root = "crate")]
fn remove_at<R: Runtime>( fn remove_at<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
rid: ResourceId, rid: ResourceId,
kind: ItemKind, kind: ItemKind,
position: usize, position: usize,
) -> crate::Result<Option<(ResourceId, MenuId, ItemKind)>> { ) -> crate::Result<Option<(ResourceId, MenuId, ItemKind)>> {
let mut resources_table = app.resources_table(); let mut resources_table = webview.resources_table();
match kind { match kind {
ItemKind::Menu => { ItemKind::Menu => {
let menu = resources_table.get::<Menu<R>>(rid)?; let menu = resources_table.get::<Menu<R>>(rid)?;
@ -601,11 +594,11 @@ fn remove_at<R: Runtime>(
#[command(root = "crate")] #[command(root = "crate")]
fn items<R: Runtime>( fn items<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
rid: ResourceId, rid: ResourceId,
kind: ItemKind, kind: ItemKind,
) -> crate::Result<Vec<(ResourceId, MenuId, ItemKind)>> { ) -> crate::Result<Vec<(ResourceId, MenuId, ItemKind)>> {
let mut resources_table = app.resources_table(); let mut resources_table = webview.resources_table();
let items = match kind { let items = match kind {
ItemKind::Menu => resources_table.get::<Menu<R>>(rid)?.items()?, ItemKind::Menu => resources_table.get::<Menu<R>>(rid)?.items()?,
ItemKind::Submenu => resources_table.get::<Submenu<R>>(rid)?.items()?, ItemKind::Submenu => resources_table.get::<Submenu<R>>(rid)?.items()?,
@ -622,12 +615,12 @@ fn items<R: Runtime>(
#[command(root = "crate")] #[command(root = "crate")]
fn get<R: Runtime>( fn get<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
rid: ResourceId, rid: ResourceId,
kind: ItemKind, kind: ItemKind,
id: MenuId, id: MenuId,
) -> crate::Result<Option<(ResourceId, MenuId, ItemKind)>> { ) -> crate::Result<Option<(ResourceId, MenuId, ItemKind)>> {
let mut resources_table = app.resources_table(); let mut resources_table = webview.resources_table();
match kind { match kind {
ItemKind::Menu => { ItemKind::Menu => {
let menu = resources_table.get::<Menu<R>>(rid)?; let menu = resources_table.get::<Menu<R>>(rid)?;
@ -649,7 +642,7 @@ fn get<R: Runtime>(
#[command(root = "crate")] #[command(root = "crate")]
async fn popup<R: Runtime>( async fn popup<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
current_window: Window<R>, current_window: Window<R>,
rid: ResourceId, rid: ResourceId,
kind: ItemKind, kind: ItemKind,
@ -657,11 +650,11 @@ async fn popup<R: Runtime>(
at: Option<Position>, at: Option<Position>,
) -> crate::Result<()> { ) -> crate::Result<()> {
let window = window let window = window
.map(|w| app.manager().get_window(&w)) .map(|w| webview.manager().get_window(&w))
.unwrap_or(Some(current_window)); .unwrap_or(Some(current_window));
if let Some(window) = window { if let Some(window) = window {
let resources_table = app.resources_table(); let resources_table = webview.resources_table();
match kind { match kind {
ItemKind::Menu => { ItemKind::Menu => {
let menu = resources_table.get::<Menu<R>>(rid)?; let menu = resources_table.get::<Menu<R>>(rid)?;
@ -679,8 +672,11 @@ async fn popup<R: Runtime>(
} }
#[command(root = "crate")] #[command(root = "crate")]
fn create_default<R: Runtime>(app: AppHandle<R>) -> crate::Result<(ResourceId, MenuId)> { fn create_default<R: Runtime>(
let mut resources_table = app.resources_table(); app: AppHandle<R>,
webview: Webview<R>,
) -> crate::Result<(ResourceId, MenuId)> {
let mut resources_table = webview.resources_table();
let menu = Menu::default(&app)?; let menu = Menu::default(&app)?;
let id = menu.id().clone(); let id = menu.id().clone();
let rid = resources_table.add(menu); let rid = resources_table.add(menu);
@ -689,10 +685,10 @@ fn create_default<R: Runtime>(app: AppHandle<R>) -> crate::Result<(ResourceId, M
#[command(root = "crate")] #[command(root = "crate")]
async fn set_as_app_menu<R: Runtime>( async fn set_as_app_menu<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
rid: ResourceId, rid: ResourceId,
) -> crate::Result<Option<(ResourceId, MenuId)>> { ) -> crate::Result<Option<(ResourceId, MenuId)>> {
let mut resources_table = app.resources_table(); let mut resources_table = webview.resources_table();
let menu = resources_table.get::<Menu<R>>(rid)?; let menu = resources_table.get::<Menu<R>>(rid)?;
if let Some(menu) = menu.set_as_app_menu()? { if let Some(menu) = menu.set_as_app_menu()? {
let id = menu.id().clone(); let id = menu.id().clone();
@ -704,17 +700,17 @@ async fn set_as_app_menu<R: Runtime>(
#[command(root = "crate")] #[command(root = "crate")]
async fn set_as_window_menu<R: Runtime>( async fn set_as_window_menu<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
current_window: Window<R>, current_window: Window<R>,
rid: ResourceId, rid: ResourceId,
window: Option<String>, window: Option<String>,
) -> crate::Result<Option<(ResourceId, MenuId)>> { ) -> crate::Result<Option<(ResourceId, MenuId)>> {
let window = window let window = window
.map(|w| app.manager().get_window(&w)) .map(|w| webview.manager().get_window(&w))
.unwrap_or(Some(current_window)); .unwrap_or(Some(current_window));
if let Some(window) = window { if let Some(window) = window {
let mut resources_table = app.resources_table(); let mut resources_table = webview.resources_table();
let menu = resources_table.get::<Menu<R>>(rid)?; let menu = resources_table.get::<Menu<R>>(rid)?;
if let Some(menu) = menu.set_as_window_menu(&window)? { if let Some(menu) = menu.set_as_window_menu(&window)? {
let id = menu.id().clone(); let id = menu.id().clone();
@ -726,40 +722,40 @@ async fn set_as_window_menu<R: Runtime>(
} }
#[command(root = "crate")] #[command(root = "crate")]
fn text<R: Runtime>(app: AppHandle<R>, rid: ResourceId, kind: ItemKind) -> crate::Result<String> { fn text<R: Runtime>(webview: Webview<R>, rid: ResourceId, kind: ItemKind) -> crate::Result<String> {
let resources_table = app.resources_table(); let resources_table = webview.resources_table();
do_menu_item!(resources_table, rid, kind, |i| i.text()) do_menu_item!(resources_table, rid, kind, |i| i.text())
} }
#[command(root = "crate")] #[command(root = "crate")]
fn set_text<R: Runtime>( fn set_text<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
rid: ResourceId, rid: ResourceId,
kind: ItemKind, kind: ItemKind,
text: String, text: String,
) -> crate::Result<()> { ) -> crate::Result<()> {
let resources_table = app.resources_table(); let resources_table = webview.resources_table();
do_menu_item!(resources_table, rid, kind, |i| i.set_text(text)) do_menu_item!(resources_table, rid, kind, |i| i.set_text(text))
} }
#[command(root = "crate")] #[command(root = "crate")]
fn is_enabled<R: Runtime>( fn is_enabled<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
rid: ResourceId, rid: ResourceId,
kind: ItemKind, kind: ItemKind,
) -> crate::Result<bool> { ) -> crate::Result<bool> {
let resources_table = app.resources_table(); let resources_table = webview.resources_table();
do_menu_item!(resources_table, rid, kind, |i| i.is_enabled(), !Predefined) do_menu_item!(resources_table, rid, kind, |i| i.is_enabled(), !Predefined)
} }
#[command(root = "crate")] #[command(root = "crate")]
fn set_enabled<R: Runtime>( fn set_enabled<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
rid: ResourceId, rid: ResourceId,
kind: ItemKind, kind: ItemKind,
enabled: bool, enabled: bool,
) -> crate::Result<()> { ) -> crate::Result<()> {
let resources_table = app.resources_table(); let resources_table = webview.resources_table();
do_menu_item!( do_menu_item!(
resources_table, resources_table,
rid, rid,
@ -771,12 +767,12 @@ fn set_enabled<R: Runtime>(
#[command(root = "crate")] #[command(root = "crate")]
fn set_accelerator<R: Runtime>( fn set_accelerator<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
rid: ResourceId, rid: ResourceId,
kind: ItemKind, kind: ItemKind,
accelerator: Option<String>, accelerator: Option<String>,
) -> crate::Result<()> { ) -> crate::Result<()> {
let resources_table = app.resources_table(); let resources_table = webview.resources_table();
do_menu_item!( do_menu_item!(
resources_table, resources_table,
rid, rid,
@ -788,62 +784,69 @@ fn set_accelerator<R: Runtime>(
#[command(root = "crate")] #[command(root = "crate")]
fn set_as_windows_menu_for_nsapp<R: Runtime>( fn set_as_windows_menu_for_nsapp<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
rid: ResourceId, rid: ResourceId,
) -> crate::Result<()> { ) -> crate::Result<()> {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
{ {
let resources_table = app.resources_table(); let resources_table = webview.resources_table();
let submenu = resources_table.get::<Submenu<R>>(rid)?; let submenu = resources_table.get::<Submenu<R>>(rid)?;
submenu.set_as_help_menu_for_nsapp()?; submenu.set_as_help_menu_for_nsapp()?;
} }
let _ = rid; let _ = rid;
let _ = app; let _ = webview;
Ok(()) Ok(())
} }
#[command(root = "crate")] #[command(root = "crate")]
fn set_as_help_menu_for_nsapp<R: Runtime>(app: AppHandle<R>, rid: ResourceId) -> crate::Result<()> { fn set_as_help_menu_for_nsapp<R: Runtime>(
webview: Webview<R>,
rid: ResourceId,
) -> crate::Result<()> {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
{ {
let resources_table = app.resources_table(); let resources_table = webview.resources_table();
let submenu = resources_table.get::<Submenu<R>>(rid)?; let submenu = resources_table.get::<Submenu<R>>(rid)?;
submenu.set_as_help_menu_for_nsapp()?; submenu.set_as_help_menu_for_nsapp()?;
} }
let _ = rid; let _ = rid;
let _ = app; let _ = webview;
Ok(()) Ok(())
} }
#[command(root = "crate")] #[command(root = "crate")]
fn is_checked<R: Runtime>(app: AppHandle<R>, rid: ResourceId) -> crate::Result<bool> { fn is_checked<R: Runtime>(webview: Webview<R>, rid: ResourceId) -> crate::Result<bool> {
let resources_table = app.resources_table(); let resources_table = webview.resources_table();
let check_item = resources_table.get::<CheckMenuItem<R>>(rid)?; let check_item = resources_table.get::<CheckMenuItem<R>>(rid)?;
check_item.is_checked() check_item.is_checked()
} }
#[command(root = "crate")] #[command(root = "crate")]
fn set_checked<R: Runtime>(app: AppHandle<R>, rid: ResourceId, checked: bool) -> crate::Result<()> { fn set_checked<R: Runtime>(
let resources_table = app.resources_table(); webview: Webview<R>,
rid: ResourceId,
checked: bool,
) -> crate::Result<()> {
let resources_table = webview.resources_table();
let check_item = resources_table.get::<CheckMenuItem<R>>(rid)?; let check_item = resources_table.get::<CheckMenuItem<R>>(rid)?;
check_item.set_checked(checked) check_item.set_checked(checked)
} }
#[command(root = "crate")] #[command(root = "crate")]
fn set_icon<R: Runtime>( fn set_icon<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
rid: ResourceId, rid: ResourceId,
icon: Option<Icon>, icon: Option<Icon>,
) -> crate::Result<()> { ) -> crate::Result<()> {
let resources_table = app.resources_table(); let resources_table = webview.resources_table();
let icon_item = resources_table.get::<IconMenuItem<R>>(rid)?; let icon_item = resources_table.get::<IconMenuItem<R>>(rid)?;
match icon { match icon {
Some(Icon::Native(icon)) => icon_item.set_native_icon(Some(icon)), Some(Icon::Native(icon)) => icon_item.set_native_icon(Some(icon)),
Some(Icon::Icon(icon)) => icon_item.set_icon(Some(icon.into_img(&app)?.as_ref().clone())), Some(Icon::Icon(icon)) => icon_item.set_icon(Some(icon.into_img(&webview)?.as_ref().clone())),
None => { None => {
icon_item.set_icon(None)?; icon_item.set_icon(None)?;
icon_item.set_native_icon(None)?; icon_item.set_native_icon(None)?;

View File

@ -7,7 +7,6 @@
pub(crate) mod plugin; pub(crate) mod plugin;
use crate::error::Error;
use std::{ use std::{
any::{type_name, Any, TypeId}, any::{type_name, Any, TypeId},
borrow::Cow, borrow::Cow,
@ -75,10 +74,15 @@ pub type ResourceId = u32;
#[derive(Default)] #[derive(Default)]
pub struct ResourceTable { pub struct ResourceTable {
index: BTreeMap<ResourceId, Arc<dyn Resource>>, index: BTreeMap<ResourceId, Arc<dyn Resource>>,
next_rid: ResourceId,
} }
impl ResourceTable { impl ResourceTable {
fn new_random_rid() -> u32 {
let mut bytes = [0_u8; 4];
getrandom::getrandom(&mut bytes).expect("failed to get random bytes");
u32::from_ne_bytes(bytes)
}
/// Inserts resource into the resource table, which takes ownership of it. /// Inserts resource into the resource table, which takes ownership of it.
/// ///
/// The resource type is erased at runtime and must be statically known /// The resource type is erased at runtime and must be statically known
@ -107,10 +111,9 @@ impl ResourceTable {
/// ///
/// Returns a unique resource ID, which acts as a key for this resource. /// Returns a unique resource ID, which acts as a key for this resource.
pub fn add_arc_dyn(&mut self, resource: Arc<dyn Resource>) -> ResourceId { pub fn add_arc_dyn(&mut self, resource: Arc<dyn Resource>) -> ResourceId {
let rid = self.next_rid; let rid = Self::new_random_rid();
let removed_resource = self.index.insert(rid, resource); let removed_resource = self.index.insert(rid, resource);
assert!(removed_resource.is_none()); assert!(removed_resource.is_none());
self.next_rid += 1;
rid rid
} }
@ -121,24 +124,24 @@ impl ResourceTable {
/// Returns a reference counted pointer to the resource of type `T` with the /// Returns a reference counted pointer to the resource of type `T` with the
/// given `rid`. If `rid` is not present or has a type different than `T`, /// given `rid`. If `rid` is not present or has a type different than `T`,
/// this function returns [`Error::BadResourceId`]. /// this function returns [`Error::BadResourceId`](crate::Error::BadResourceId).
pub fn get<T: Resource>(&self, rid: ResourceId) -> Result<Arc<T>, Error> { pub fn get<T: Resource>(&self, rid: ResourceId) -> crate::Result<Arc<T>> {
self self
.index .index
.get(&rid) .get(&rid)
.and_then(|rc| rc.downcast_arc::<T>()) .and_then(|rc| rc.downcast_arc::<T>())
.cloned() .cloned()
.ok_or_else(|| Error::BadResourceId(rid)) .ok_or_else(|| crate::Error::BadResourceId(rid))
} }
/// Returns a reference counted pointer to the resource of the given `rid`. /// Returns a reference counted pointer to the resource of the given `rid`.
/// If `rid` is not present, this function returns [`Error::BadResourceId`]. /// If `rid` is not present, this function returns [`Error::BadResourceId`].
pub fn get_any(&self, rid: ResourceId) -> Result<Arc<dyn Resource>, Error> { pub fn get_any(&self, rid: ResourceId) -> crate::Result<Arc<dyn Resource>> {
self self
.index .index
.get(&rid) .get(&rid)
.ok_or_else(|| crate::Error::BadResourceId(rid))
.cloned() .cloned()
.ok_or_else(|| Error::BadResourceId(rid))
} }
/// Replaces a resource with a new resource. /// Replaces a resource with a new resource.
@ -161,7 +164,7 @@ impl ResourceTable {
/// assume that `Arc::strong_count(&returned_arc)` is always equal to 1 on success. /// assume that `Arc::strong_count(&returned_arc)` is always equal to 1 on success.
/// In particular, be really careful when you want to extract the inner value of /// In particular, be really careful when you want to extract the inner value of
/// type `T` from `Arc<T>`. /// type `T` from `Arc<T>`.
pub fn take<T: Resource>(&mut self, rid: ResourceId) -> Result<Arc<T>, Error> { pub fn take<T: Resource>(&mut self, rid: ResourceId) -> crate::Result<Arc<T>> {
let resource = self.get::<T>(rid)?; let resource = self.get::<T>(rid)?;
self.index.remove(&rid); self.index.remove(&rid);
Ok(resource) Ok(resource)
@ -175,11 +178,11 @@ impl ResourceTable {
/// we cannot assume that `Arc::strong_count(&returned_arc)` is always equal to 1 /// we cannot assume that `Arc::strong_count(&returned_arc)` is always equal to 1
/// on success. In particular, be really careful when you want to extract the /// on success. In particular, be really careful when you want to extract the
/// inner value of type `T` from `Arc<T>`. /// inner value of type `T` from `Arc<T>`.
pub fn take_any(&mut self, rid: ResourceId) -> Result<Arc<dyn Resource>, Error> { pub fn take_any(&mut self, rid: ResourceId) -> crate::Result<Arc<dyn Resource>> {
self self
.index .index
.remove(&rid) .remove(&rid)
.ok_or_else(|| Error::BadResourceId(rid)) .ok_or_else(|| crate::Error::BadResourceId(rid))
} }
/// Returns an iterator that yields a `(id, name)` pair for every resource /// Returns an iterator that yields a `(id, name)` pair for every resource
@ -199,17 +202,11 @@ impl ResourceTable {
/// counted, therefore pending ops are not automatically cancelled. A resource /// counted, therefore pending ops are not automatically cancelled. A resource
/// may implement the `close()` method to perform clean-ups such as canceling /// may implement the `close()` method to perform clean-ups such as canceling
/// ops. /// ops.
pub fn close(&mut self, rid: ResourceId) -> Result<(), Error> { pub fn close(&mut self, rid: ResourceId) -> crate::Result<()> {
self self
.index .index
.remove(&rid) .remove(&rid)
.ok_or_else(|| Error::BadResourceId(rid)) .ok_or_else(|| crate::Error::BadResourceId(rid))
.map(|resource| resource.close()) .map(|resource| resource.close())
} }
/// Removes and frees all resources stored. Note that the
/// resource's `close()` method is *not* called.
pub(crate) fn clear(&mut self) {
self.index.clear()
}
} }

View File

@ -5,14 +5,14 @@
use crate::{ use crate::{
command, command,
plugin::{Builder, TauriPlugin}, plugin::{Builder, TauriPlugin},
AppHandle, Manager, Runtime, Manager, Runtime, Webview,
}; };
use super::ResourceId; use super::ResourceId;
#[command(root = "crate")] #[command(root = "crate")]
fn close<R: Runtime>(app: AppHandle<R>, rid: ResourceId) -> crate::Result<()> { fn close<R: Runtime>(webview: Webview<R>, rid: ResourceId) -> crate::Result<()> {
app.resources_table().close(rid) webview.resources_table().close(rid)
} }
pub(crate) fn init<R: Runtime>() -> TauriPlugin<R> { pub(crate) fn init<R: Runtime>() -> TauriPlugin<R> {

View File

@ -14,7 +14,7 @@ use crate::{
plugin::{Builder, TauriPlugin}, plugin::{Builder, TauriPlugin},
resources::ResourceId, resources::ResourceId,
tray::TrayIconBuilder, tray::TrayIconBuilder,
AppHandle, Manager, Runtime, AppHandle, Manager, Runtime, Webview,
}; };
use super::TrayIcon; use super::TrayIcon;
@ -34,7 +34,7 @@ struct TrayIconOptions {
#[command(root = "crate")] #[command(root = "crate")]
fn new<R: Runtime>( fn new<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
options: TrayIconOptions, options: TrayIconOptions,
handler: Channel, handler: Channel,
) -> crate::Result<(ResourceId, String)> { ) -> crate::Result<(ResourceId, String)> {
@ -48,7 +48,7 @@ fn new<R: Runtime>(
let _ = handler.send(e); let _ = handler.send(e);
}); });
let mut resources_table = app.resources_table(); let mut resources_table = webview.resources_table();
if let Some((rid, kind)) = options.menu { if let Some((rid, kind)) = options.menu {
match kind { match kind {
@ -64,7 +64,7 @@ fn new<R: Runtime>(
}; };
} }
if let Some(icon) = options.icon { if let Some(icon) = options.icon {
builder = builder.icon(icon.into_img(&app)?.as_ref().clone()); builder = builder.icon(icon.into_img(&webview)?.as_ref().clone());
} }
if let Some(tooltip) = options.tooltip { if let Some(tooltip) = options.tooltip {
builder = builder.tooltip(tooltip); builder = builder.tooltip(tooltip);
@ -82,7 +82,7 @@ fn new<R: Runtime>(
builder = builder.menu_on_left_click(menu_on_left_click); builder = builder.menu_on_left_click(menu_on_left_click);
} }
let tray = builder.build(&app)?; let tray = builder.build(&webview)?;
let id = tray.id().as_ref().to_string(); let id = tray.id().as_ref().to_string();
let rid = resources_table.add(tray); let rid = resources_table.add(tray);
@ -90,10 +90,14 @@ fn new<R: Runtime>(
} }
#[command(root = "crate")] #[command(root = "crate")]
fn get_by_id<R: Runtime>(app: AppHandle<R>, id: &str) -> crate::Result<Option<ResourceId>> { fn get_by_id<R: Runtime>(
app: AppHandle<R>,
webview: Webview<R>,
id: &str,
) -> crate::Result<Option<ResourceId>> {
let tray = app.tray_by_id(id); let tray = app.tray_by_id(id);
let maybe_rid = tray.map(|tray| { let maybe_rid = tray.map(|tray| {
let mut resources_table = app.resources_table(); let mut resources_table = webview.resources_table();
resources_table.add(tray) resources_table.add(tray)
}); });
Ok(maybe_rid) Ok(maybe_rid)
@ -110,14 +114,14 @@ fn remove_by_id<R: Runtime>(app: AppHandle<R>, id: &str) -> crate::Result<()> {
#[command(root = "crate")] #[command(root = "crate")]
fn set_icon<R: Runtime>( fn set_icon<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
rid: ResourceId, rid: ResourceId,
icon: Option<JsImage>, icon: Option<JsImage>,
) -> crate::Result<()> { ) -> crate::Result<()> {
let resources_table = app.resources_table(); let resources_table = webview.resources_table();
let tray = resources_table.get::<TrayIcon<R>>(rid)?; let tray = resources_table.get::<TrayIcon<R>>(rid)?;
let icon = match icon { let icon = match icon {
Some(i) => Some(i.into_img(&app)?.as_ref().clone()), Some(i) => Some(i.into_img(&webview)?.as_ref().clone()),
None => None, None => None,
}; };
tray.set_icon(icon) tray.set_icon(icon)
@ -125,11 +129,11 @@ fn set_icon<R: Runtime>(
#[command(root = "crate")] #[command(root = "crate")]
fn set_menu<R: Runtime>( fn set_menu<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
rid: ResourceId, rid: ResourceId,
menu: Option<(ResourceId, ItemKind)>, menu: Option<(ResourceId, ItemKind)>,
) -> crate::Result<()> { ) -> crate::Result<()> {
let resources_table = app.resources_table(); let resources_table = webview.resources_table();
let tray = resources_table.get::<TrayIcon<R>>(rid)?; let tray = resources_table.get::<TrayIcon<R>>(rid)?;
if let Some((rid, kind)) = menu { if let Some((rid, kind)) = menu {
match kind { match kind {
@ -151,62 +155,66 @@ fn set_menu<R: Runtime>(
#[command(root = "crate")] #[command(root = "crate")]
fn set_tooltip<R: Runtime>( fn set_tooltip<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
rid: ResourceId, rid: ResourceId,
tooltip: Option<String>, tooltip: Option<String>,
) -> crate::Result<()> { ) -> crate::Result<()> {
let resources_table = app.resources_table(); let resources_table = webview.resources_table();
let tray = resources_table.get::<TrayIcon<R>>(rid)?; let tray = resources_table.get::<TrayIcon<R>>(rid)?;
tray.set_tooltip(tooltip) tray.set_tooltip(tooltip)
} }
#[command(root = "crate")] #[command(root = "crate")]
fn set_title<R: Runtime>( fn set_title<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
rid: ResourceId, rid: ResourceId,
title: Option<String>, title: Option<String>,
) -> crate::Result<()> { ) -> crate::Result<()> {
let resources_table = app.resources_table(); let resources_table = webview.resources_table();
let tray = resources_table.get::<TrayIcon<R>>(rid)?; let tray = resources_table.get::<TrayIcon<R>>(rid)?;
tray.set_title(title) tray.set_title(title)
} }
#[command(root = "crate")] #[command(root = "crate")]
fn set_visible<R: Runtime>(app: AppHandle<R>, rid: ResourceId, visible: bool) -> crate::Result<()> { fn set_visible<R: Runtime>(
let resources_table = app.resources_table(); webview: Webview<R>,
rid: ResourceId,
visible: bool,
) -> crate::Result<()> {
let resources_table = webview.resources_table();
let tray = resources_table.get::<TrayIcon<R>>(rid)?; let tray = resources_table.get::<TrayIcon<R>>(rid)?;
tray.set_visible(visible) tray.set_visible(visible)
} }
#[command(root = "crate")] #[command(root = "crate")]
fn set_temp_dir_path<R: Runtime>( fn set_temp_dir_path<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
rid: ResourceId, rid: ResourceId,
path: Option<PathBuf>, path: Option<PathBuf>,
) -> crate::Result<()> { ) -> crate::Result<()> {
let resources_table = app.resources_table(); let resources_table = webview.resources_table();
let tray = resources_table.get::<TrayIcon<R>>(rid)?; let tray = resources_table.get::<TrayIcon<R>>(rid)?;
tray.set_temp_dir_path(path) tray.set_temp_dir_path(path)
} }
#[command(root = "crate")] #[command(root = "crate")]
fn set_icon_as_template<R: Runtime>( fn set_icon_as_template<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
rid: ResourceId, rid: ResourceId,
as_template: bool, as_template: bool,
) -> crate::Result<()> { ) -> crate::Result<()> {
let resources_table = app.resources_table(); let resources_table = webview.resources_table();
let tray = resources_table.get::<TrayIcon<R>>(rid)?; let tray = resources_table.get::<TrayIcon<R>>(rid)?;
tray.set_icon_as_template(as_template) tray.set_icon_as_template(as_template)
} }
#[command(root = "crate")] #[command(root = "crate")]
fn set_show_menu_on_left_click<R: Runtime>( fn set_show_menu_on_left_click<R: Runtime>(
app: AppHandle<R>, webview: Webview<R>,
rid: ResourceId, rid: ResourceId,
on_left: bool, on_left: bool,
) -> crate::Result<()> { ) -> crate::Result<()> {
let resources_table = app.resources_table(); let resources_table = webview.resources_table();
let tray = resources_table.get::<TrayIcon<R>>(rid)?; let tray = resources_table.get::<TrayIcon<R>>(rid)?;
tray.set_show_menu_on_left_click(on_left) tray.set_show_menu_on_left_click(on_left)
} }

View File

@ -34,14 +34,14 @@ use crate::{
}, },
manager::{webview::WebviewLabelDef, AppManager}, manager::{webview::WebviewLabelDef, AppManager},
sealed::{ManagerBase, RuntimeOrDispatch}, sealed::{ManagerBase, RuntimeOrDispatch},
AppHandle, Event, EventId, EventLoopMessage, Manager, Runtime, Window, AppHandle, Event, EventId, EventLoopMessage, Manager, ResourceTable, Runtime, Window,
}; };
use std::{ use std::{
borrow::Cow, borrow::Cow,
hash::{Hash, Hasher}, hash::{Hash, Hasher},
path::PathBuf, path::PathBuf,
sync::{Arc, Mutex}, sync::{Arc, Mutex, MutexGuard},
}; };
pub(crate) type WebResourceRequestHandler = pub(crate) type WebResourceRequestHandler =
@ -786,6 +786,7 @@ pub struct Webview<R: Runtime> {
pub(crate) app_handle: AppHandle<R>, pub(crate) app_handle: AppHandle<R>,
/// The webview created by the runtime. /// The webview created by the runtime.
pub(crate) webview: DetachedWebview<EventLoopMessage, R>, pub(crate) webview: DetachedWebview<EventLoopMessage, R>,
pub(crate) resources_table: Arc<Mutex<ResourceTable>>,
} }
impl<R: Runtime> std::fmt::Debug for Webview<R> { impl<R: Runtime> std::fmt::Debug for Webview<R> {
@ -804,6 +805,7 @@ impl<R: Runtime> Clone for Webview<R> {
manager: self.manager.clone(), manager: self.manager.clone(),
app_handle: self.app_handle.clone(), app_handle: self.app_handle.clone(),
webview: self.webview.clone(), webview: self.webview.clone(),
resources_table: self.resources_table.clone(),
} }
} }
} }
@ -832,6 +834,7 @@ impl<R: Runtime> Webview<R> {
manager: window.manager.clone(), manager: window.manager.clone(),
app_handle: window.app_handle.clone(), app_handle: window.app_handle.clone(),
webview, webview,
resources_table: Default::default(),
} }
} }
@ -1502,7 +1505,14 @@ tauri::Builder::default()
} }
} }
impl<R: Runtime> Manager<R> for Webview<R> {} impl<R: Runtime> Manager<R> for Webview<R> {
fn resources_table(&self) -> MutexGuard<'_, ResourceTable> {
self
.resources_table
.lock()
.expect("poisoned window resources table")
}
}
impl<R: Runtime> ManagerBase<R> for Webview<R> { impl<R: Runtime> ManagerBase<R> for Webview<R> {
fn manager(&self) -> &AppManager<R> { fn manager(&self) -> &AppManager<R> {

View File

@ -4,12 +4,17 @@
//! [`Window`] that hosts a single [`Webview`]. //! [`Window`] that hosts a single [`Webview`].
use std::{borrow::Cow, path::PathBuf, sync::Arc}; use std::{
borrow::Cow,
path::PathBuf,
sync::{Arc, MutexGuard},
};
use crate::{ use crate::{
event::EventTarget, event::EventTarget,
runtime::dpi::{PhysicalPosition, PhysicalSize}, runtime::dpi::{PhysicalPosition, PhysicalSize},
window::Monitor, window::Monitor,
ResourceTable,
}; };
#[cfg(desktop)] #[cfg(desktop)]
use crate::{ use crate::{
@ -1790,7 +1795,15 @@ tauri::Builder::default()
} }
} }
impl<R: Runtime> Manager<R> for WebviewWindow<R> {} impl<R: Runtime> Manager<R> for WebviewWindow<R> {
fn resources_table(&self) -> MutexGuard<'_, ResourceTable> {
self
.webview
.resources_table
.lock()
.expect("poisoned window resources table")
}
}
impl<R: Runtime> ManagerBase<R> for WebviewWindow<R> { impl<R: Runtime> ManagerBase<R> for WebviewWindow<R> {
fn manager(&self) -> &AppManager<R> { fn manager(&self) -> &AppManager<R> {

View File

@ -25,11 +25,10 @@ use crate::{
window::{DetachedWindow, PendingWindow, WindowBuilder as _}, window::{DetachedWindow, PendingWindow, WindowBuilder as _},
RuntimeHandle, WindowDispatch, RuntimeHandle, WindowDispatch,
}, },
sealed::ManagerBase, sealed::{ManagerBase, RuntimeOrDispatch},
sealed::RuntimeOrDispatch,
utils::config::{WindowConfig, WindowEffectsConfig}, utils::config::{WindowConfig, WindowEffectsConfig},
webview::WebviewBuilder, webview::WebviewBuilder,
EventLoopMessage, Manager, Runtime, Theme, Webview, WindowEvent, EventLoopMessage, Manager, ResourceTable, Runtime, Theme, Webview, WindowEvent,
}; };
#[cfg(desktop)] #[cfg(desktop)]
use crate::{ use crate::{
@ -51,7 +50,7 @@ use tauri_macros::default_runtime;
use std::{ use std::{
fmt, fmt,
hash::{Hash, Hasher}, hash::{Hash, Hasher},
sync::Arc, sync::{Arc, Mutex, MutexGuard},
}; };
/// Monitor descriptor. /// Monitor descriptor.
@ -876,7 +875,8 @@ pub struct Window<R: Runtime> {
pub(crate) app_handle: AppHandle<R>, pub(crate) app_handle: AppHandle<R>,
// The menu set for this window // The menu set for this window
#[cfg(desktop)] #[cfg(desktop)]
pub(crate) menu: Arc<std::sync::Mutex<Option<WindowMenu<R>>>>, pub(crate) menu: Arc<Mutex<Option<WindowMenu<R>>>>,
pub(crate) resources_table: Arc<Mutex<ResourceTable>>,
} }
impl<R: Runtime> std::fmt::Debug for Window<R> { impl<R: Runtime> std::fmt::Debug for Window<R> {
@ -913,6 +913,7 @@ impl<R: Runtime> Clone for Window<R> {
app_handle: self.app_handle.clone(), app_handle: self.app_handle.clone(),
#[cfg(desktop)] #[cfg(desktop)]
menu: self.menu.clone(), menu: self.menu.clone(),
resources_table: self.resources_table.clone(),
} }
} }
} }
@ -932,7 +933,14 @@ impl<R: Runtime> PartialEq for Window<R> {
} }
} }
impl<R: Runtime> Manager<R> for Window<R> {} impl<R: Runtime> Manager<R> for Window<R> {
fn resources_table(&self) -> MutexGuard<'_, ResourceTable> {
self
.resources_table
.lock()
.expect("poisoned window resources table")
}
}
impl<R: Runtime> ManagerBase<R> for Window<R> { impl<R: Runtime> ManagerBase<R> for Window<R> {
fn manager(&self) -> &AppManager<R> { fn manager(&self) -> &AppManager<R> {
@ -974,6 +982,7 @@ impl<R: Runtime> Window<R> {
app_handle, app_handle,
#[cfg(desktop)] #[cfg(desktop)]
menu: Arc::new(std::sync::Mutex::new(menu)), menu: Arc::new(std::sync::Mutex::new(menu)),
resources_table: Default::default(),
} }
} }

View File

@ -20,7 +20,7 @@ mod desktop_commands {
utils::config::{WindowConfig, WindowEffectsConfig}, utils::config::{WindowConfig, WindowEffectsConfig},
window::{ProgressBarState, WindowBuilder}, window::{ProgressBarState, WindowBuilder},
AppHandle, CursorIcon, Monitor, PhysicalPosition, PhysicalSize, Position, Size, Theme, AppHandle, CursorIcon, Monitor, PhysicalPosition, PhysicalSize, Position, Size, Theme,
UserAttentionType, Window, UserAttentionType, Webview, Window,
}; };
#[command(root = "crate")] #[command(root = "crate")]
@ -132,13 +132,14 @@ mod desktop_commands {
#[command(root = "crate")] #[command(root = "crate")]
pub async fn set_icon<R: Runtime>( pub async fn set_icon<R: Runtime>(
webview: Webview<R>,
window: Window<R>, window: Window<R>,
label: Option<String>, label: Option<String>,
value: crate::image::JsImage, value: crate::image::JsImage,
) -> crate::Result<()> { ) -> crate::Result<()> {
let window = get_window(window, label)?; let window = get_window(window, label)?;
window window
.set_icon(value.into_img(&window)?.as_ref().clone()) .set_icon(value.into_img(&webview)?.as_ref().clone())
.map_err(Into::into) .map_err(Into::into)
} }

View File

@ -706,6 +706,15 @@ dependencies = [
"syn 2.0.52", "syn 2.0.52",
] ]
[[package]]
name = "dpi"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "dtoa" name = "dtoa"
version = "1.0.9" version = "1.0.9"
@ -753,15 +762,6 @@ version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7"
[[package]]
name = "encoding_rs"
version = "0.8.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.1" version = "1.0.1"
@ -1239,25 +1239,6 @@ dependencies = [
"syn 2.0.52", "syn 2.0.52",
] ]
[[package]]
name = "h2"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9"
dependencies = [
"bytes",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http",
"indexmap 2.2.3",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.12.3" version = "0.12.3"
@ -1304,9 +1285,9 @@ dependencies = [
[[package]] [[package]]
name = "http" name = "http"
version = "0.2.11" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
dependencies = [ dependencies = [
"bytes", "bytes",
"fnv", "fnv",
@ -1315,12 +1296,24 @@ dependencies = [
[[package]] [[package]]
name = "http-body" name = "http-body"
version = "0.4.6" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
dependencies = [ dependencies = [
"bytes", "bytes",
"http", "http",
]
[[package]]
name = "http-body-util"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d"
dependencies = [
"bytes",
"futures-core",
"http",
"http-body",
"pin-project-lite", "pin-project-lite",
] ]
@ -1336,34 +1329,43 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
[[package]]
name = "httpdate"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "0.14.28" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-channel", "futures-channel",
"futures-core",
"futures-util", "futures-util",
"h2",
"http", "http",
"http-body", "http-body",
"httparse", "httparse",
"httpdate",
"itoa 1.0.10", "itoa 1.0.10",
"pin-project-lite", "pin-project-lite",
"smallvec",
"tokio",
"want",
]
[[package]]
name = "hyper-util"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
"http",
"http-body",
"hyper",
"pin-project-lite",
"socket2", "socket2",
"tokio", "tokio",
"tower",
"tower-service", "tower-service",
"tracing", "tracing",
"want",
] ]
[[package]] [[package]]
@ -1780,12 +1782,13 @@ dependencies = [
[[package]] [[package]]
name = "muda" name = "muda"
version = "0.12.1" version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e27c56b8cb9b3214d196556227b0eaa12db8393b4f919a0a93ffb67ed17d185" checksum = "f428b4e9db3d17e2f809dfb1ff9ddfbbf16c71790d1656d10aee320877e1392f"
dependencies = [ dependencies = [
"cocoa", "cocoa",
"crossbeam-channel", "crossbeam-channel",
"dpi",
"gtk", "gtk",
"keyboard-types", "keyboard-types",
"objc", "objc",
@ -2136,6 +2139,26 @@ dependencies = [
"siphasher", "siphasher",
] ]
[[package]]
name = "pin-project"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.52",
]
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.13" version = "0.2.13"
@ -2447,19 +2470,19 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]] [[package]]
name = "reqwest" name = "reqwest"
version = "0.11.24" version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" checksum = "2d66674f2b6fb864665eea7a3c1ac4e3dfacd2fda83cf6f935a612e01b0e3338"
dependencies = [ dependencies = [
"base64 0.21.7", "base64 0.21.7",
"bytes", "bytes",
"encoding_rs",
"futures-core", "futures-core",
"futures-util", "futures-util",
"h2",
"http", "http",
"http-body", "http-body",
"http-body-util",
"hyper", "hyper",
"hyper-util",
"ipnet", "ipnet",
"js-sys", "js-sys",
"log", "log",
@ -2471,7 +2494,6 @@ dependencies = [
"serde_json", "serde_json",
"serde_urlencoded", "serde_urlencoded",
"sync_wrapper", "sync_wrapper",
"system-configuration",
"tokio", "tokio",
"tokio-util", "tokio-util",
"tower-service", "tower-service",
@ -2925,27 +2947,6 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
[[package]]
name = "system-configuration"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
dependencies = [
"bitflags 1.3.2",
"core-foundation",
"system-configuration-sys",
]
[[package]]
name = "system-configuration-sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]] [[package]]
name = "system-deps" name = "system-deps"
version = "6.2.0" version = "6.2.0"
@ -2961,9 +2962,9 @@ dependencies = [
[[package]] [[package]]
name = "tao" name = "tao"
version = "0.26.1" version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccba570365293ca309d60f30fdac2c5271b732dc762e6154e59c85d2c762a0a1" checksum = "bd5b6ec2c43abd15155f040c765001098f50f425414b679225d471a1cd782753"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"cocoa", "cocoa",
@ -2972,10 +2973,10 @@ dependencies = [
"crossbeam-channel", "crossbeam-channel",
"dispatch", "dispatch",
"dlopen2", "dlopen2",
"dpi",
"gdkwayland-sys", "gdkwayland-sys",
"gdkx11-sys", "gdkx11-sys",
"gtk", "gtk",
"image",
"instant", "instant",
"jni", "jni",
"lazy_static", "lazy_static",
@ -2987,14 +2988,12 @@ dependencies = [
"objc", "objc",
"once_cell", "once_cell",
"parking_lot", "parking_lot",
"png",
"raw-window-handle 0.6.0", "raw-window-handle 0.6.0",
"scopeguard", "scopeguard",
"tao-macros", "tao-macros",
"unicode-segmentation", "unicode-segmentation",
"url", "url",
"windows 0.52.0", "windows 0.54.0",
"windows-implement 0.52.0",
"windows-version", "windows-version",
"x11-dl", "x11-dl",
] ]
@ -3018,7 +3017,7 @@ checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f"
[[package]] [[package]]
name = "tauri" name = "tauri"
version = "2.0.0-beta.12" version = "2.0.0-beta.13"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
@ -3154,6 +3153,7 @@ dependencies = [
name = "tauri-runtime" name = "tauri-runtime"
version = "2.0.0-beta.10" version = "2.0.0-beta.10"
dependencies = [ dependencies = [
"dpi",
"gtk", "gtk",
"http", "http",
"jni", "jni",
@ -3429,6 +3429,28 @@ dependencies = [
"winnow", "winnow",
] ]
[[package]]
name = "tower"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
dependencies = [
"futures-core",
"futures-util",
"pin-project",
"pin-project-lite",
"tokio",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower-layer"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
[[package]] [[package]]
name = "tower-service" name = "tower-service"
version = "0.3.2" version = "0.3.2"
@ -3441,6 +3463,7 @@ version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [ dependencies = [
"log",
"pin-project-lite", "pin-project-lite",
"tracing-attributes", "tracing-attributes",
"tracing-core", "tracing-core",
@ -3498,9 +3521,9 @@ dependencies = [
[[package]] [[package]]
name = "tray-icon" name = "tray-icon"
version = "0.12.0" version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "454035ff34b8430638c894e6197748578d6b4d449c6edaf8ea854d94e2dd862b" checksum = "8713f74e697917aa794800289e15bce534fc91450312ab2d3edf5b8907f7301a"
dependencies = [ dependencies = [
"cocoa", "cocoa",
"core-graphics", "core-graphics",
@ -3878,8 +3901,8 @@ dependencies = [
"webview2-com-sys", "webview2-com-sys",
"windows 0.54.0", "windows 0.54.0",
"windows-core 0.54.0", "windows-core 0.54.0",
"windows-implement 0.53.0", "windows-implement",
"windows-interface 0.53.0", "windows-interface",
] ]
[[package]] [[package]]
@ -3948,18 +3971,6 @@ dependencies = [
"windows-version", "windows-version",
] ]
[[package]]
name = "windows"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
dependencies = [
"windows-core 0.52.0",
"windows-implement 0.52.0",
"windows-interface 0.52.0",
"windows-targets 0.52.4",
]
[[package]] [[package]]
name = "windows" name = "windows"
version = "0.53.0" version = "0.53.0"
@ -3977,8 +3988,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49"
dependencies = [ dependencies = [
"windows-core 0.54.0", "windows-core 0.54.0",
"windows-implement 0.53.0", "windows-implement",
"windows-interface 0.53.0", "windows-interface",
"windows-targets 0.52.4", "windows-targets 0.52.4",
] ]
@ -4011,17 +4022,6 @@ dependencies = [
"windows-targets 0.52.4", "windows-targets 0.52.4",
] ]
[[package]]
name = "windows-implement"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12168c33176773b86799be25e2a2ba07c7aab9968b37541f1094dbd7a60c8946"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.52",
]
[[package]] [[package]]
name = "windows-implement" name = "windows-implement"
version = "0.53.0" version = "0.53.0"
@ -4033,17 +4033,6 @@ dependencies = [
"syn 2.0.52", "syn 2.0.52",
] ]
[[package]]
name = "windows-interface"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d8dc32e0095a7eeccebd0e3f09e9509365ecb3fc6ac4d6f5f14a3f6392942d1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.52",
]
[[package]] [[package]]
name = "windows-interface" name = "windows-interface"
version = "0.53.0" version = "0.53.0"
@ -4302,9 +4291,9 @@ dependencies = [
[[package]] [[package]]
name = "wry" name = "wry"
version = "0.38.2" version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "741261f2571990873d0dd5953cff8087f39a16fb37550edd0acf7221b9c8d65b" checksum = "4eca9d50437c04fc67e82c196ddd31d8e35794150713ae2d647f3a58c7f45d1a"
dependencies = [ dependencies = [
"base64 0.21.7", "base64 0.21.7",
"block", "block",
@ -4312,6 +4301,7 @@ dependencies = [
"cocoa", "cocoa",
"core-graphics", "core-graphics",
"crossbeam-channel", "crossbeam-channel",
"dpi",
"dunce", "dunce",
"gdkx11", "gdkx11",
"gtk", "gtk",