From 1be352849159ff8f8dd9cce7c5c8d8462c90eaa8 Mon Sep 17 00:00:00 2001 From: pacholoamit Date: Wed, 9 Oct 2024 06:42:25 +0800 Subject: [PATCH] refactor: Update Tauri CLI to version 2.0.2 and simplify macOS window code --- package.json | 2 +- src-tauri/gen/schemas/macOS-schema.json | 10 + src-tauri/src/lib.rs | 18 +- src-tauri/src/mac/mod.rs | 1 - src-tauri/src/mac/window.rs | 396 ------------------------ src-tauri/src/win/mod.rs | 1 - src-tauri/src/win/window.rs | 92 ------ src-tauri/tauri.conf.json | 4 +- yarn.lock | 4 +- 9 files changed, 17 insertions(+), 511 deletions(-) delete mode 100644 src-tauri/src/mac/mod.rs delete mode 100644 src-tauri/src/mac/window.rs delete mode 100644 src-tauri/src/win/mod.rs delete mode 100644 src-tauri/src/win/window.rs diff --git a/package.json b/package.json index 83345f19..87f4c969 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ }, "devDependencies": { "@eslint/js": "^9.7.0", - "@tauri-apps/cli": "latest", + "@tauri-apps/cli": "2.0.2", "@types/lodash.sortby": "^4.7.9", "@types/node": "^20.16.11", "@types/react": "^18.3.11", diff --git a/src-tauri/gen/schemas/macOS-schema.json b/src-tauri/gen/schemas/macOS-schema.json index e9eda5eb..dd57391b 100644 --- a/src-tauri/gen/schemas/macOS-schema.json +++ b/src-tauri/gen/schemas/macOS-schema.json @@ -3392,6 +3392,16 @@ "type": "string", "const": "core:window:deny-unminimize" }, + { + "description": "Enables the show_snap_overlay command without any pre-configured scope.", + "type": "string", + "const": "decorum:allow-show-snap-overlay" + }, + { + "description": "Denies the show_snap_overlay command without any pre-configured scope.", + "type": "string", + "const": "decorum:deny-show-snap-overlay" + }, { "description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n", "type": "string", diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 37821f73..2436241a 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -6,12 +6,6 @@ extern crate cocoa; #[macro_use] extern crate objc; -#[cfg(target_os = "macos")] -mod mac; - -#[cfg(target_os = "windows")] -mod win; - mod app; mod commands; mod dirstat; @@ -74,17 +68,7 @@ fn build_and_run_app(app: AppState) { // Some macOS-specific helpers #[cfg(target_os = "macos")] - { - // Set a custom inset to the traffic lights - main_window.set_traffic_lights_inset(12.0, 16.0).unwrap(); - - // Make window transparent without privateApi - main_window.make_transparent().unwrap(); - - // Set window level - // NSWindowLevel: https://developer.apple.com/documentation/appkit/nswindowlevel - main_window.set_window_level(25).unwrap() - } + main_window.set_traffic_lights_inset(12.0, 16.0).unwrap(); // BUILD TRAY - TODO MOVE TO DIFFERENT FILE diff --git a/src-tauri/src/mac/mod.rs b/src-tauri/src/mac/mod.rs deleted file mode 100644 index 61b63f17..00000000 --- a/src-tauri/src/mac/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod window; diff --git a/src-tauri/src/mac/window.rs b/src-tauri/src/mac/window.rs deleted file mode 100644 index 51a0fc8a..00000000 --- a/src-tauri/src/mac/window.rs +++ /dev/null @@ -1,396 +0,0 @@ -use hex_color::HexColor; -use tauri::{App, Emitter, Listener, Manager, Runtime, WebviewWindow}; - -// If anything breaks on macOS, this should be the place which is broken -// We have to override Tauri (Tao) 's built-in NSWindowDelegate implementation with a -// custom implementation so we can emit events on full screen mode changes. -// Our custom implementation tries to mock the Tauri implementation. So please do refer to the relevant parts - -// Apple's NSWindowDelegate reference: https://developer.apple.com/documentation/appkit/nswindowdelegate?language=objc -// Tao's Window Delegate Implementation: https://github.com/tauri-apps/tao/blob/dev/src/platform_impl/macos/window_delegate.rs - -#[allow(dead_code)] -pub enum ToolbarThickness { - Thick, - Medium, - Thin, -} - -const WINDOW_CONTROL_PAD_X: f64 = 15.0; -const WINDOW_CONTROL_PAD_Y: f64 = 23.0; - -pub trait WindowExt { - #[cfg(target_os = "macos")] - fn set_transparent_titlebar(&self); -} - -#[cfg(target_os = "macos")] -unsafe fn set_transparent_titlebar(id: cocoa::base::id) { - use cocoa::appkit::NSWindow; - - id.setTitlebarAppearsTransparent_(cocoa::base::YES); - id.setTitleVisibility_(cocoa::appkit::NSWindowTitleVisibility::NSWindowTitleHidden); -} - -struct UnsafeWindowHandle(*mut std::ffi::c_void); -unsafe impl Send for UnsafeWindowHandle {} -unsafe impl Sync for UnsafeWindowHandle {} - -#[cfg(target_os = "macos")] -fn update_window_theme(window: &tauri::WebviewWindow, color: HexColor) { - use cocoa::appkit::{ - NSAppearance, NSAppearanceNameVibrantDark, NSAppearanceNameVibrantLight, NSWindow, - }; - - let brightness = (color.r as u64 + color.g as u64 + color.b as u64) / 3; - - unsafe { - let window_handle = UnsafeWindowHandle(window.ns_window().unwrap()); - - let _ = window.run_on_main_thread(move || { - let handle = window_handle; - - let selected_appearance = if brightness >= 128 { - NSAppearance(NSAppearanceNameVibrantLight) - } else { - NSAppearance(NSAppearanceNameVibrantDark) - }; - - NSWindow::setAppearance(handle.0 as cocoa::base::id, selected_appearance); - set_window_controls_pos( - handle.0 as cocoa::base::id, - WINDOW_CONTROL_PAD_X, - WINDOW_CONTROL_PAD_Y, - ); - }); - } -} - -#[cfg(target_os = "macos")] -fn set_window_controls_pos(window: cocoa::base::id, x: f64, y: f64) { - use cocoa::{ - appkit::{NSView, NSWindow, NSWindowButton}, - foundation::NSRect, - }; - - unsafe { - let close = window.standardWindowButton_(NSWindowButton::NSWindowCloseButton); - let miniaturize = window.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton); - let zoom = window.standardWindowButton_(NSWindowButton::NSWindowZoomButton); - - let title_bar_container_view = close.superview().superview(); - - let close_rect: NSRect = msg_send![close, frame]; - let button_height = close_rect.size.height; - - let title_bar_frame_height = button_height + y; - let mut title_bar_rect = NSView::frame(title_bar_container_view); - title_bar_rect.size.height = title_bar_frame_height; - title_bar_rect.origin.y = NSView::frame(window).size.height - title_bar_frame_height; - let _: () = msg_send![title_bar_container_view, setFrame: title_bar_rect]; - - let window_buttons = vec![close, miniaturize, zoom]; - let space_between = NSView::frame(miniaturize).origin.x - NSView::frame(close).origin.x; - - for (i, button) in window_buttons.into_iter().enumerate() { - let mut rect: NSRect = NSView::frame(button); - rect.origin.x = x + (i as f64 * space_between); - button.setFrameOrigin(rect.origin); - } - } -} - -impl WindowExt for WebviewWindow { - #[cfg(target_os = "macos")] - fn set_transparent_titlebar(&self) { - unsafe { - let id = self.ns_window().unwrap() as cocoa::base::id; - - set_transparent_titlebar(id); - - set_window_controls_pos(id, WINDOW_CONTROL_PAD_X, WINDOW_CONTROL_PAD_Y); - } - } -} - -#[cfg(target_os = "macos")] -#[derive(Debug)] -struct PachtopAppstate { - window: WebviewWindow, -} - -#[cfg(target_os = "macos")] -pub fn setup_mac_window(app: &mut App) { - use cocoa::appkit::NSWindow; - use cocoa::base::{id, BOOL}; - use cocoa::foundation::NSUInteger; - use objc::runtime::{Object, Sel}; - use std::ffi::c_void; - - fn with_pachtop_app T, T>(this: &Object, func: F) { - let ptr = unsafe { - let x: *mut c_void = *this.get_ivar("pachtopApp"); - &mut *(x as *mut PachtopAppstate) - }; - func(ptr); - } - - let window = app.get_webview_window("main").unwrap(); - - unsafe { - let ns_win = window.ns_window().unwrap() as id; - - let current_delegate: id = ns_win.delegate(); - - extern "C" fn on_window_should_close(this: &Object, _cmd: Sel, sender: id) -> BOOL { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - msg_send![super_del, windowShouldClose: sender] - } - } - extern "C" fn on_window_will_close(this: &Object, _cmd: Sel, notification: id) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowWillClose: notification]; - } - } - extern "C" fn on_window_did_resize(this: &Object, _cmd: Sel, notification: id) { - unsafe { - with_pachtop_app(&*this, |state| { - let id = state.window.ns_window().unwrap() as id; - - set_window_controls_pos(id, WINDOW_CONTROL_PAD_X, WINDOW_CONTROL_PAD_Y); - }); - - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidResize: notification]; - } - } - extern "C" fn on_window_did_move(this: &Object, _cmd: Sel, notification: id) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidMove: notification]; - } - } - extern "C" fn on_window_did_change_backing_properties( - this: &Object, - _cmd: Sel, - notification: id, - ) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidChangeBackingProperties: notification]; - } - } - extern "C" fn on_window_did_become_key(this: &Object, _cmd: Sel, notification: id) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidBecomeKey: notification]; - } - } - extern "C" fn on_window_did_resign_key(this: &Object, _cmd: Sel, notification: id) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidResignKey: notification]; - } - } - extern "C" fn on_dragging_entered(this: &Object, _cmd: Sel, notification: id) -> BOOL { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - msg_send![super_del, draggingEntered: notification] - } - } - extern "C" fn on_prepare_for_drag_operation( - this: &Object, - _cmd: Sel, - notification: id, - ) -> BOOL { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - msg_send![super_del, prepareForDragOperation: notification] - } - } - extern "C" fn on_perform_drag_operation(this: &Object, _cmd: Sel, sender: id) -> BOOL { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - msg_send![super_del, performDragOperation: sender] - } - } - extern "C" fn on_conclude_drag_operation(this: &Object, _cmd: Sel, notification: id) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, concludeDragOperation: notification]; - } - } - extern "C" fn on_dragging_exited(this: &Object, _cmd: Sel, notification: id) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, draggingExited: notification]; - } - } - extern "C" fn on_window_will_use_full_screen_presentation_options( - this: &Object, - _cmd: Sel, - window: id, - proposed_options: NSUInteger, - ) -> NSUInteger { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - msg_send![super_del, window: window willUseFullScreenPresentationOptions: proposed_options] - } - } - extern "C" fn on_window_did_enter_full_screen(this: &Object, _cmd: Sel, notification: id) { - unsafe { - with_pachtop_app(&*this, |state| { - state.window.emit("did-enter-fullscreen", ()).unwrap(); - }); - - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidEnterFullScreen: notification]; - } - } - extern "C" fn on_window_will_enter_full_screen(this: &Object, _cmd: Sel, notification: id) { - unsafe { - with_pachtop_app(&*this, |state| { - state.window.emit("will-enter-fullscreen", ()).unwrap(); - }); - - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowWillEnterFullScreen: notification]; - } - } - extern "C" fn on_window_did_exit_full_screen(this: &Object, _cmd: Sel, notification: id) { - unsafe { - with_pachtop_app(&*this, |state| { - state.window.emit("did-exit-fullscreen", ()).unwrap(); - - let id = state.window.ns_window().unwrap() as id; - set_window_controls_pos(id, WINDOW_CONTROL_PAD_X, WINDOW_CONTROL_PAD_Y); - }); - - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidExitFullScreen: notification]; - } - } - extern "C" fn on_window_will_exit_full_screen(this: &Object, _cmd: Sel, notification: id) { - unsafe { - with_pachtop_app(&*this, |state| { - state.window.emit("will-exit-fullscreen", ()).unwrap(); - }); - - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowWillExitFullScreen: notification]; - } - } - extern "C" fn on_window_did_fail_to_enter_full_screen( - this: &Object, - _cmd: Sel, - window: id, - ) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, windowDidFailToEnterFullScreen: window]; - } - } - extern "C" fn on_effective_appearance_did_change( - this: &Object, - _cmd: Sel, - notification: id, - ) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![super_del, effectiveAppearanceDidChange: notification]; - } - } - extern "C" fn on_effective_appearance_did_changed_on_main_thread( - this: &Object, - _cmd: Sel, - notification: id, - ) { - unsafe { - let super_del: id = *this.get_ivar("super_delegate"); - let _: () = msg_send![ - super_del, - effectiveAppearanceDidChangedOnMainThread: notification - ]; - } - } - - // extern fn on_dealloc(this: &Object, cmd: Sel) { - // unsafe { - // let super_del: id = *this.get_ivar("super_delegate"); - // let _: () = msg_send![super_del, dealloc]; - // } - // } - - // extern fn on_mark_is_checking_zoomed_in(this: &Object, cmd: Sel) { - // unsafe { - // let super_del: id = *this.get_ivar("super_delegate"); - // let _: () = msg_send![super_del, markIsCheckingZoomedIn]; - // } - // } - - // extern fn on_clear_is_checking_zoomed_in(this: &Object, cmd: Sel) { - // unsafe { - // let super_del: id = *this.get_ivar("super_delegate"); - // let _: () = msg_send![super_del, clearIsCheckingZoomedIn]; - // } - // } - - // Are we deallocing this properly ? (I miss safe Rust :( ) - let app_state = PachtopAppstate { window }; - let app_box = Box::into_raw(Box::new(app_state)) as *mut c_void; - - ns_win.setDelegate_(delegate!("MainWindowDelegate", { - window: id = ns_win, - pachtopApp: *mut c_void = app_box, - toolbar: id = cocoa::base::nil, - super_delegate: id = current_delegate, - // (dealloc) => on_dealloc as extern fn(&Object, Sel), - // (markIsCheckingZoomedIn) => on_mark_is_checking_zoomed_in as extern fn(&Object, Sel), - // (clearIsCheckingZoomedIn) => on_clear_is_checking_zoomed_in as extern fn(&Object, Sel), - (windowShouldClose:) => on_window_should_close as extern fn(&Object, Sel, id) -> BOOL, - (windowWillClose:) => on_window_will_close as extern fn(&Object, Sel, id), - (windowDidResize:) => on_window_did_resize as extern fn(&Object, Sel, id), - (windowDidMove:) => on_window_did_move as extern fn(&Object, Sel, id), - (windowDidChangeBackingProperties:) => on_window_did_change_backing_properties as extern fn(&Object, Sel, id), - (windowDidBecomeKey:) => on_window_did_become_key as extern fn(&Object, Sel, id), - (windowDidResignKey:) => on_window_did_resign_key as extern fn(&Object, Sel, id), - (draggingEntered:) => on_dragging_entered as extern fn(&Object, Sel, id) -> BOOL, - (prepareForDragOperation:) => on_prepare_for_drag_operation as extern fn(&Object, Sel, id) -> BOOL, - (performDragOperation:) => on_perform_drag_operation as extern fn(&Object, Sel, id) -> BOOL, - (concludeDragOperation:) => on_conclude_drag_operation as extern fn(&Object, Sel, id), - (draggingExited:) => on_dragging_exited as extern fn(&Object, Sel, id), - (window:willUseFullScreenPresentationOptions:) => on_window_will_use_full_screen_presentation_options as extern fn(&Object, Sel, id, NSUInteger) -> NSUInteger, - (windowDidEnterFullScreen:) => on_window_did_enter_full_screen as extern fn(&Object, Sel, id), - (windowWillEnterFullScreen:) => on_window_will_enter_full_screen as extern fn(&Object, Sel, id), - (windowDidExitFullScreen:) => on_window_did_exit_full_screen as extern fn(&Object, Sel, id), - (windowWillExitFullScreen:) => on_window_will_exit_full_screen as extern fn(&Object, Sel, id), - (windowDidFailToEnterFullScreen:) => on_window_did_fail_to_enter_full_screen as extern fn(&Object, Sel, id), - (effectiveAppearanceDidChange:) => on_effective_appearance_did_change as extern fn(&Object, Sel, id), - (effectiveAppearanceDidChangedOnMainThread:) => on_effective_appearance_did_changed_on_main_thread as extern fn(&Object, Sel, id) - })) - } - - // TODO: Check if this works on macos - app.get_webview_window("main") - .unwrap() - .set_transparent_titlebar(); - - let window_handle = app.get_webview_window("main").unwrap(); - - update_window_theme(&window_handle, HexColor::rgb(9, 9, 11)); - - let window = app.get_webview_window("main").unwrap(); - let handle = window.app_handle(); - - // Control window theme based on app update_window - - handle.listen("theme_changed", move |ev| { - let payload = serde_json::from_str::<&str>(ev.payload()).unwrap().trim(); - - let color = HexColor::parse_rgb(payload).unwrap(); - - update_window_theme(&window_handle, color); - }); -} diff --git a/src-tauri/src/win/mod.rs b/src-tauri/src/win/mod.rs deleted file mode 100644 index 61b63f17..00000000 --- a/src-tauri/src/win/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod window; diff --git a/src-tauri/src/win/window.rs b/src-tauri/src/win/window.rs deleted file mode 100644 index 5f6def43..00000000 --- a/src-tauri/src/win/window.rs +++ /dev/null @@ -1,92 +0,0 @@ -// use hex_color::HexColor; -// use tauri::{App, Manager}; - -// use std::mem::transmute; -// use std::{ffi::c_void, mem::size_of, ptr}; -// use tauri::Listener; -// use windows::Win32::UI::Controls::{ -// WTA_NONCLIENT, WTNCA_NODRAWICON, WTNCA_NOMIRRORHELP, WTNCA_NOSYSMENU, -// }; - -// use windows::Win32::Foundation::BOOL; -// use windows::Win32::Foundation::COLORREF; -// use windows::Win32::Foundation::HWND; -// use windows::Win32::Graphics::Dwm::DwmSetWindowAttribute; -// use windows::Win32::Graphics::Dwm::DWMWA_CAPTION_COLOR; -// use windows::Win32::Graphics::Dwm::DWMWA_USE_IMMERSIVE_DARK_MODE; -// use windows::Win32::UI::Controls::SetWindowThemeAttribute; -// use windows::Win32::UI::Controls::WTNCA_NODRAWCAPTION; - -// use winver::WindowsVersion; - -// fn hex_color_to_colorref(color: HexColor) -> COLORREF { -// // TODO: Remove this unsafe, This operation doesn't need to be unsafe! -// unsafe { COLORREF(transmute::<[u8; 4], u32>([color.r, color.g, color.b, 0])) } -// } -// #[allow(dead_code)] -// struct WinThemeAttribute { -// flag: u32, -// mask: u32, -// } - -// #[cfg(target_os = "windows")] -// fn update_bg_color(hwnd: &HWND, bg_color: HexColor) { -// let use_dark_mode = BOOL::from(true); - -// let final_color = hex_color_to_colorref(bg_color); - -// unsafe { -// DwmSetWindowAttribute( -// HWND(hwnd.0), -// DWMWA_USE_IMMERSIVE_DARK_MODE, -// ptr::addr_of!(use_dark_mode) as *const c_void, -// size_of::().try_into().unwrap(), -// ) -// .unwrap(); -// } - -// let version = WindowsVersion::detect().unwrap(); -// if version >= WindowsVersion::new(10, 0, 22000) { -// unsafe { -// DwmSetWindowAttribute( -// HWND(hwnd.0), -// DWMWA_CAPTION_COLOR, -// ptr::addr_of!(final_color) as *const c_void, -// size_of::().try_into().unwrap(), -// ) -// .unwrap(); -// } -// } - -// let flags = WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON; -// let mask = WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON | WTNCA_NOSYSMENU | WTNCA_NOMIRRORHELP; -// let options = WinThemeAttribute { flag: flags, mask }; - -// unsafe { -// SetWindowThemeAttribute( -// HWND(hwnd.0), -// WTA_NONCLIENT, -// ptr::addr_of!(options) as *const c_void, -// size_of::().try_into().unwrap(), -// ) -// .unwrap(); -// } -// } - -// #[cfg(target_os = "windows")] -// pub fn setup_win_window(app: &mut App) { -// let window = app.get_webview_window("main").unwrap(); -// let handle = window.app_handle(); - -// let win_handle = window.hwnd().unwrap(); - -// handle.listen("theme_changed", move |ev| { -// let payload = serde_json::from_str::<&str>(ev.payload()).unwrap().trim(); - -// let color = HexColor::parse_rgb(payload).unwrap(); - -// update_bg_color(&HWND(win_handle.0), color); -// }); - -// update_bg_color(&HWND(win_handle.0), HexColor::rgb(9, 9, 11)); -// } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 98b802d3..12e2342c 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -62,7 +62,9 @@ "title": "pachtop", "alwaysOnTop": false, "width": 800, - "decorations": true + "decorations": true, + "hiddenTitle": true, + "titleBarStyle": "Overlay" } ], "security": { diff --git a/yarn.lock b/yarn.lock index 88751fc5..de7deb67 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3172,7 +3172,7 @@ __metadata: languageName: node linkType: hard -"@tauri-apps/cli@npm:latest": +"@tauri-apps/cli@npm:2.0.2": version: 2.0.2 resolution: "@tauri-apps/cli@npm:2.0.2" dependencies: @@ -6794,7 +6794,7 @@ __metadata: "@mantine/notifications": ^6.0.22 "@tabler/icons-react": ^2.47.0 "@tauri-apps/api": ^2.0.2 - "@tauri-apps/cli": latest + "@tauri-apps/cli": 2.0.2 "@tauri-apps/plugin-fs": ^2.0.0 "@tauri-apps/plugin-log": ^2.0.0 "@tauri-apps/plugin-os": ^2.0.0