upgrade to tauri 2.0 beta
This commit is contained in:
2089
src-tauri/Cargo.lock
generated
2089
src-tauri/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "creddy"
|
||||
version = "0.4.7"
|
||||
version = "0.4.8"
|
||||
description = "A friendly AWS credentials manager"
|
||||
authors = ["Joseph Montanaro"]
|
||||
license = ""
|
||||
@ -20,13 +20,12 @@ path = "src/main.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "1.0.4", features = [] }
|
||||
tauri-build = { version = "2.0.0-beta", features = [] }
|
||||
|
||||
[dependencies]
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tauri = { version = "1.2", features = [ "app-all", "dialog", "dialog-open", "global-shortcut", "os-all", "system-tray"] }
|
||||
tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
|
||||
tauri = { version = "2.0.0-beta", features = ["tray-icon"] }
|
||||
sodiumoxide = "0.2.7"
|
||||
tokio = { version = ">=1.19", features = ["full"] }
|
||||
sqlx = { version = "0.6.2", features = ["sqlite", "runtime-tokio-rustls"] }
|
||||
@ -48,6 +47,9 @@ chacha20poly1305 = { version = "0.10.1", features = ["std"] }
|
||||
which = "4.4.0"
|
||||
windows = { version = "0.51.1", features = ["Win32_Foundation", "Win32_System_Pipes"] }
|
||||
time = "0.3.31"
|
||||
tauri-plugin-single-instance = "2.0.0-beta.9"
|
||||
tauri-plugin-global-shortcut = "2.0.0-beta.6"
|
||||
rfd = { version = "0.14", default-features = false, features = [ "tokio", "gtk3", "common-controls-v6" ] }
|
||||
|
||||
[features]
|
||||
# by default Tauri runs in production mode
|
||||
|
17
src-tauri/capabilities/migrated.json
Normal file
17
src-tauri/capabilities/migrated.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"identifier": "migrated",
|
||||
"description": "permissions that were migrated from v1",
|
||||
"local": true,
|
||||
"windows": [
|
||||
"main"
|
||||
],
|
||||
"permissions": [
|
||||
"path:default",
|
||||
"event:default",
|
||||
"window:default",
|
||||
"app:default",
|
||||
"resources:default",
|
||||
"menu:default",
|
||||
"tray:default"
|
||||
]
|
||||
}
|
1
src-tauri/gen/schemas/acl-manifests.json
Normal file
1
src-tauri/gen/schemas/acl-manifests.json
Normal file
File diff suppressed because one or more lines are too long
1
src-tauri/gen/schemas/capabilities.json
Normal file
1
src-tauri/gen/schemas/capabilities.json
Normal file
@ -0,0 +1 @@
|
||||
{"migrated":{"identifier":"migrated","description":"permissions that were migrated from v1","local":true,"windows":["main"],"permissions":["path:default","event:default","window:default","app:default","resources:default","menu:default","tray:default"]}}
|
2243
src-tauri/gen/schemas/desktop-schema.json
Normal file
2243
src-tauri/gen/schemas/desktop-schema.json
Normal file
File diff suppressed because it is too large
Load Diff
2243
src-tauri/gen/schemas/linux-schema.json
Normal file
2243
src-tauri/gen/schemas/linux-schema.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -33,10 +33,9 @@ pub fn run() -> tauri::Result<()> {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_single_instance::init(|app, _argv, _cwd| {
|
||||
show_main_window(app)
|
||||
.error_popup("Failed to show main window");
|
||||
.blocking_error_popup("Failed to show main window")
|
||||
}))
|
||||
.system_tray(tray::create())
|
||||
.on_system_tray_event(tray::handle_event)
|
||||
.plugin(tauri_plugin_global_shortcut::Builder::default().build())
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
ipc::unlock,
|
||||
ipc::respond,
|
||||
@ -77,8 +76,8 @@ pub async fn connect_db() -> Result<SqlitePool, SetupError> {
|
||||
|
||||
|
||||
async fn setup(app: &mut App) -> Result<(), Box<dyn Error>> {
|
||||
APP.set(app.handle()).unwrap();
|
||||
|
||||
APP.set(app.handle().clone()).unwrap();
|
||||
tray::setup(app)?;
|
||||
// get_or_create_db_path doesn't create the actual db file, just the directory
|
||||
let is_first_launch = !config::get_or_create_db_path()?.exists();
|
||||
let pool = connect_db().await?;
|
||||
@ -96,7 +95,7 @@ async fn setup(app: &mut App) -> Result<(), Box<dyn Error>> {
|
||||
};
|
||||
|
||||
let session = Session::load(&pool).await?;
|
||||
Server::start(app.handle())?;
|
||||
Server::start(app.handle().clone())?;
|
||||
|
||||
config::set_auto_launch(conf.start_on_login)?;
|
||||
if let Err(_e) = config::set_auto_launch(conf.start_on_login) {
|
||||
@ -123,7 +122,7 @@ async fn setup(app: &mut App) -> Result<(), Box<dyn Error>> {
|
||||
app.manage(state);
|
||||
|
||||
// make sure we do this after managing app state, so that it doesn't panic
|
||||
start_auto_locker(app.app_handle());
|
||||
start_auto_locker(app.app_handle().clone());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -138,7 +137,7 @@ fn start_auto_locker(app: AppHandle) {
|
||||
tokio::time::sleep(delay).await;
|
||||
|
||||
if state.should_auto_lock().await {
|
||||
state.lock().await.error_popup("Failed to lock Creddy");
|
||||
state.lock().await.error_popup("Failed to lock Creddy").await;
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -146,27 +145,27 @@ fn start_auto_locker(app: AppHandle) {
|
||||
|
||||
|
||||
pub fn show_main_window(app: &AppHandle) -> Result<(), WindowError> {
|
||||
let w = app.get_window("main").ok_or(WindowError::NoMainWindow)?;
|
||||
let w = app.get_webview_window("main").ok_or(WindowError::NoMainWindow)?;
|
||||
w.show()?;
|
||||
app.tray_handle()
|
||||
.get_item("show_hide")
|
||||
.set_title("Hide")?;
|
||||
// app.tray_handle()
|
||||
// .get_item("show_hide")
|
||||
// .set_title("Hide")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub fn hide_main_window(app: &AppHandle) -> Result<(), WindowError> {
|
||||
let w = app.get_window("main").ok_or(WindowError::NoMainWindow)?;
|
||||
let w = app.get_webview_window("main").ok_or(WindowError::NoMainWindow)?;
|
||||
w.hide()?;
|
||||
app.tray_handle()
|
||||
.get_item("show_hide")
|
||||
.set_title("Show")?;
|
||||
// app.tray_handle()
|
||||
// .get_item("show_hide")
|
||||
// .set_title("Show")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub fn toggle_main_window(app: &AppHandle) -> Result<(), WindowError> {
|
||||
let w = app.get_window("main").ok_or(WindowError::NoMainWindow)?;
|
||||
let w = app.get_webview_window("main").ok_or(WindowError::NoMainWindow)?;
|
||||
if w.is_visible()? {
|
||||
hide_main_window(app)
|
||||
}
|
||||
|
@ -135,9 +135,12 @@ impl LockedCredentials {
|
||||
}
|
||||
|
||||
|
||||
fn default_credentials_version() -> usize { 1 }
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct BaseCredentials {
|
||||
#[serde(default = "default_credentials_version")]
|
||||
pub version: usize,
|
||||
pub access_key_id: String,
|
||||
pub secret_access_key: String,
|
||||
@ -167,6 +170,7 @@ impl BaseCredentials {
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct SessionCredentials {
|
||||
#[serde(default = "default_credentials_version")]
|
||||
pub version: usize,
|
||||
pub access_key_id: String,
|
||||
pub secret_access_key: String,
|
||||
|
@ -1,7 +1,6 @@
|
||||
use std::error::Error;
|
||||
use std::convert::AsRef;
|
||||
use std::ffi::OsString;
|
||||
use std::sync::mpsc;
|
||||
use std::string::FromUtf8Error;
|
||||
use strum_macros::AsRefStr;
|
||||
|
||||
@ -10,14 +9,16 @@ use aws_sdk_sts::{
|
||||
types::SdkError as AwsSdkError,
|
||||
error::GetSessionTokenError,
|
||||
};
|
||||
use rfd::{
|
||||
AsyncMessageDialog,
|
||||
MessageDialog,
|
||||
MessageLevel,
|
||||
};
|
||||
use sqlx::{
|
||||
error::Error as SqlxError,
|
||||
migrate::MigrateError,
|
||||
};
|
||||
use tauri::api::dialog::{
|
||||
MessageDialogBuilder,
|
||||
MessageDialogKind,
|
||||
};
|
||||
use tauri_plugin_global_shortcut::Error as ShortcutError;
|
||||
use tokio::sync::oneshot::error::RecvError;
|
||||
use serde::{
|
||||
Serialize,
|
||||
@ -27,33 +28,66 @@ use serde::{
|
||||
};
|
||||
|
||||
|
||||
pub trait ShowError {
|
||||
fn error_popup(self, title: &str);
|
||||
fn error_popup_nowait(self, title: &str);
|
||||
#[allow(async_fn_in_trait)]
|
||||
pub trait ShowError<T>
|
||||
{
|
||||
async fn error_popup(self, title: &str);
|
||||
async fn error_popup_passthrough(self, title: &str) -> Result<T, ()>;
|
||||
fn blocking_error_popup(self, title: &str);
|
||||
fn error_print(self);
|
||||
fn error_print_prefix(self, prefix: &str);
|
||||
}
|
||||
|
||||
impl<E: std::fmt::Display> ShowError for Result<(), E> {
|
||||
fn error_popup(self, title: &str) {
|
||||
impl<T, E> ShowError<T> for Result<T, E>
|
||||
where E: std::fmt::Display
|
||||
{
|
||||
async fn error_popup(self, title: &str) {
|
||||
if let Err(e) = self {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
MessageDialogBuilder::new(title, format!("{e}"))
|
||||
.kind(MessageDialogKind::Error)
|
||||
.show(move |_| tx.send(true).unwrap());
|
||||
|
||||
rx.recv().unwrap();
|
||||
AsyncMessageDialog::new()
|
||||
.set_level(MessageLevel::Error)
|
||||
.set_title(title)
|
||||
.set_description(format!("{e}"))
|
||||
.show()
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
fn error_popup_nowait(self, title: &str) {
|
||||
fn blocking_error_popup(self, title: &str) {
|
||||
if let Err(e) = self {
|
||||
MessageDialogBuilder::new(title, format!("{e}"))
|
||||
.kind(MessageDialogKind::Error)
|
||||
.show(|_| {})
|
||||
MessageDialog::new()
|
||||
.set_level(MessageLevel::Error)
|
||||
.set_title(title)
|
||||
.set_description(format!("{e}"))
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
async fn error_popup_passthrough(self, title: &str) -> Result<T, ()> {
|
||||
match self {
|
||||
Ok(v) => Ok(v),
|
||||
Err(e) => {
|
||||
AsyncMessageDialog::new()
|
||||
.set_level(MessageLevel::Error)
|
||||
.set_title(title)
|
||||
.set_description(format!("{e}"))
|
||||
.show()
|
||||
.await;
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fn error_popup_nowait(self, title: &str) {
|
||||
// if let Err(e) = self {
|
||||
// let app = app::APP.get().expect("Error popup failed, app handle not available");
|
||||
// app.dialog()
|
||||
// .message(format!("{e}"))
|
||||
// .kind(MessageDialogKind::Error)
|
||||
// .title(title)
|
||||
// .show(|_| {})
|
||||
// }
|
||||
// }
|
||||
|
||||
fn error_print(self) {
|
||||
if let Err(e) = self {
|
||||
eprintln!("{e}");
|
||||
@ -144,7 +178,7 @@ pub enum SetupError {
|
||||
#[error("Failed to resolve data directory: {0}")]
|
||||
DataDir(#[from] DataDirError),
|
||||
#[error("Failed to register hotkeys: {0}")]
|
||||
RegisterHotkeys(#[from] tauri::Error),
|
||||
RegisterHotkeys(#[from] ShortcutError),
|
||||
}
|
||||
|
||||
|
||||
|
@ -13,7 +13,7 @@ use creddy::{
|
||||
fn main() {
|
||||
let res = match cli::parser().get_matches().subcommand() {
|
||||
None | Some(("run", _)) => {
|
||||
app::run().error_popup("Creddy failed to start");
|
||||
app::run().blocking_error_popup("Creddy failed to start");
|
||||
Ok(())
|
||||
},
|
||||
Some(("get", m)) => cli::get(m),
|
||||
|
@ -126,12 +126,12 @@ async fn get_aws_credentials(
|
||||
// so we bundle it all up in an async block and return a Result so we can handle errors
|
||||
let proceed = async {
|
||||
let notification = AwsRequestNotification {id: request_id, client, base};
|
||||
app_handle.emit_all("credentials-request", ¬ification)?;
|
||||
app_handle.emit("credentials-request", ¬ification)?;
|
||||
|
||||
let response = tokio::select! {
|
||||
r = chan_recv => r?,
|
||||
_ = waiter.wait_for_close() => {
|
||||
app_handle.emit_all("request-cancelled", request_id)?;
|
||||
app_handle.emit("request-cancelled", request_id)?;
|
||||
return Err(HandlerError::Abandoned);
|
||||
},
|
||||
};
|
||||
|
@ -2,7 +2,6 @@ use std::io::ErrorKind;
|
||||
use tokio::net::{UnixListener, UnixStream};
|
||||
use tauri::{
|
||||
AppHandle,
|
||||
Manager,
|
||||
async_runtime as rt,
|
||||
};
|
||||
|
||||
@ -41,7 +40,7 @@ impl Server {
|
||||
|
||||
async fn try_serve(&self) -> Result<(), HandlerError> {
|
||||
let (stream, _addr) = self.listener.accept().await?;
|
||||
let new_handle = self.app_handle.app_handle();
|
||||
let new_handle = self.app_handle.clone();
|
||||
let client_pid = get_client_pid(&stream)?;
|
||||
rt::spawn(async move {
|
||||
super::handle(stream, new_handle, client_pid)
|
||||
|
@ -52,7 +52,7 @@ impl Server {
|
||||
// create a new pipe instance to listen for the next client, and swap it in
|
||||
let new_listener = ServerOptions::new().create(r"\\.\pipe\creddy-requests")?;
|
||||
let stream = std::mem::replace(&mut self.listener, new_listener);
|
||||
let new_handle = self.app_handle.app_handle();
|
||||
let new_handle = self.app_handle.clone();
|
||||
let client_pid = get_client_pid(&stream)?;
|
||||
rt::spawn(async move {
|
||||
super::handle(stream, new_handle, client_pid)
|
||||
|
@ -1,11 +1,16 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
use tauri::{
|
||||
GlobalShortcutManager,
|
||||
AppHandle,
|
||||
Manager,
|
||||
async_runtime as rt,
|
||||
};
|
||||
|
||||
use tauri_plugin_global_shortcut::{
|
||||
GlobalShortcutExt,
|
||||
Error as ShortcutError,
|
||||
};
|
||||
|
||||
use crate::app::APP;
|
||||
use crate::config::HotkeysConfig;
|
||||
use crate::errors::*;
|
||||
@ -21,38 +26,62 @@ pub enum ShortcutAction {
|
||||
|
||||
pub fn exec_shortcut(action: ShortcutAction) {
|
||||
match action {
|
||||
ShortcutAction::LaunchTerminal => launch_terminal(),
|
||||
ShortcutAction::ShowWindow => {
|
||||
let app = APP.get().unwrap();
|
||||
app.get_window("main")
|
||||
.ok_or("Couldn't find application main window")
|
||||
.map(|w| w.show().error_popup("Failed to show window"))
|
||||
.error_popup("Failed to show window");
|
||||
},
|
||||
ShortcutAction::LaunchTerminal => {
|
||||
rt::spawn(async {
|
||||
terminal::launch(false).await.error_popup("Failed to launch terminal");
|
||||
});
|
||||
show_window(app);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn register_hotkeys(hotkeys: &HotkeysConfig) -> tauri::Result<()> {
|
||||
fn show_window(app: &AppHandle) {
|
||||
let handle = app.clone();
|
||||
rt::spawn(async move {
|
||||
handle.get_webview_window("main")
|
||||
.ok_or("Couldn't find application main window")
|
||||
.error_popup_passthrough("Failed to show window").await?
|
||||
.show()
|
||||
.error_popup("Failed to show window").await;
|
||||
Ok::<(), ()>(())
|
||||
});
|
||||
|
||||
// app.get_webview_window("main") // Option<Window>
|
||||
// .ok_or("Couldn't find application main window") // Result<Window, &'static str>
|
||||
// .map(|w| w.show().error_popup("Failed to show window"))
|
||||
// .error_popup("Failed to show window");
|
||||
}
|
||||
|
||||
|
||||
fn launch_terminal() {
|
||||
rt::spawn(async {
|
||||
terminal::launch(false)
|
||||
.await
|
||||
.error_popup("Failed to launch terminal")
|
||||
.await;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
pub fn register_hotkeys(hotkeys: &HotkeysConfig) -> Result<(), ShortcutError> {
|
||||
let app = APP.get().unwrap();
|
||||
let mut manager = app.global_shortcut_manager();
|
||||
manager.unregister_all()?;
|
||||
let shortcuts = app.global_shortcut();
|
||||
shortcuts.unregister_all([
|
||||
hotkeys.show_window.keys.as_str(),
|
||||
hotkeys.launch_terminal.keys.as_str(),
|
||||
])?;
|
||||
|
||||
if hotkeys.show_window.enabled {
|
||||
manager.register(
|
||||
&hotkeys.show_window.keys,
|
||||
|| exec_shortcut(ShortcutAction::ShowWindow)
|
||||
shortcuts.on_shortcut(
|
||||
hotkeys.show_window.keys.as_str(),
|
||||
|app, _shortcut, _event| show_window(app)
|
||||
)?;
|
||||
}
|
||||
|
||||
if hotkeys.launch_terminal.enabled {
|
||||
manager.register(
|
||||
&hotkeys.launch_terminal.keys,
|
||||
|| exec_shortcut(ShortcutAction::LaunchTerminal)
|
||||
shortcuts.on_shortcut(
|
||||
hotkeys.launch_terminal.keys.as_str(),
|
||||
|_app, _shortcut, _event| launch_terminal()
|
||||
)?;
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ impl Visibility {
|
||||
|
||||
fn acquire(&mut self, delay_ms: u64) -> Result<VisibilityLease, WindowError> {
|
||||
let app = crate::app::APP.get().unwrap();
|
||||
let window = app.get_window("main")
|
||||
let window = app.get_webview_window("main")
|
||||
.ok_or(WindowError::NoMainWindow)?;
|
||||
|
||||
self.leases += 1;
|
||||
@ -63,18 +63,17 @@ impl Visibility {
|
||||
let lease = VisibilityLease { notify: tx };
|
||||
|
||||
let delay = Duration::from_millis(delay_ms);
|
||||
let handle = app.app_handle();
|
||||
rt::spawn(async move {
|
||||
// We don't care if it's an error; lease being dropped should be handled identically
|
||||
let _ = rx.await;
|
||||
tokio::time::sleep(delay).await;
|
||||
// we can't use `self` here because we would have to move it into the async block
|
||||
let state = handle.state::<AppState>();
|
||||
let state = app.state::<AppState>();
|
||||
let mut visibility = state.visibility.write().await;
|
||||
visibility.leases -= 1;
|
||||
if visibility.leases == 0 {
|
||||
if let Some(false) = visibility.original {
|
||||
app::hide_main_window(&handle).error_print();
|
||||
app::hide_main_window(app).error_print();
|
||||
}
|
||||
visibility.original = None;
|
||||
}
|
||||
@ -222,7 +221,7 @@ impl AppState {
|
||||
*session = Session::load(&self.pool).await?;
|
||||
|
||||
let app_handle = app::APP.get().unwrap();
|
||||
app_handle.emit_all("locked", None::<usize>)?;
|
||||
app_handle.emit("locked", None::<usize>)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -23,16 +23,16 @@ pub async fn launch(use_base: bool) -> Result<(), LaunchTerminalError> {
|
||||
cmd
|
||||
};
|
||||
|
||||
// if session is unlocked or empty, wait for credentials from frontend
|
||||
// if session is locked or empty, wait for credentials from frontend
|
||||
if !state.is_unlocked().await {
|
||||
app.emit_all("launch-terminal-request", ())?;
|
||||
app.emit("launch-terminal-request", ())?;
|
||||
let lease = state.acquire_visibility_lease(0).await
|
||||
.map_err(|_e| LaunchTerminalError::NoMainWindow)?; // automate conversion eventually?
|
||||
|
||||
let (tx, rx) = tokio::sync::oneshot::channel();
|
||||
app.once_global("credentials-event", move |e| {
|
||||
app.once("credentials-event", move |e| {
|
||||
let success = match e.payload() {
|
||||
Some("\"unlocked\"") | Some("\"entered\"") => true,
|
||||
"\"unlocked\"" | "\"entered\"" => true,
|
||||
_ => false,
|
||||
};
|
||||
let _ = tx.send(success);
|
||||
|
@ -1,45 +1,46 @@
|
||||
use tauri::{
|
||||
App,
|
||||
AppHandle,
|
||||
CustomMenuItem,
|
||||
Manager,
|
||||
SystemTray,
|
||||
SystemTrayEvent,
|
||||
SystemTrayMenu,
|
||||
async_runtime as rt,
|
||||
};
|
||||
use tauri::menu::{
|
||||
MenuBuilder,
|
||||
MenuEvent,
|
||||
MenuItemBuilder,
|
||||
};
|
||||
|
||||
use crate::app;
|
||||
use crate::state::AppState;
|
||||
|
||||
|
||||
pub fn create() -> SystemTray {
|
||||
let show = CustomMenuItem::new("show_hide".to_string(), "Show");
|
||||
let quit = CustomMenuItem::new("exit".to_string(), "Exit");
|
||||
pub fn setup(app: &App) -> tauri::Result<()> {
|
||||
let show_hide = MenuItemBuilder::with_id("show_hide", "Show/Hide").build(app)?;
|
||||
let exit = MenuItemBuilder::with_id("exit", "Exit").build(app)?;
|
||||
|
||||
let menu = SystemTrayMenu::new()
|
||||
.add_item(show)
|
||||
.add_item(quit);
|
||||
let menu = MenuBuilder::new(app)
|
||||
.items(&[&show_hide, &exit])
|
||||
.build()?;
|
||||
|
||||
SystemTray::new().with_menu(menu)
|
||||
let tray = app.tray_by_id("main").unwrap();
|
||||
tray.set_menu(Some(menu))?;
|
||||
tray.on_menu_event(handle_event);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub fn handle_event(app_handle: &AppHandle, event: SystemTrayEvent) {
|
||||
match event {
|
||||
SystemTrayEvent::MenuItemClick{ id, .. } => {
|
||||
match id.as_str() {
|
||||
"exit" => app_handle.exit(0),
|
||||
"show_hide" => {
|
||||
let _ = app::toggle_main_window(app_handle);
|
||||
let new_handle = app_handle.app_handle();
|
||||
rt::spawn(async move {
|
||||
let state = new_handle.state::<AppState>();
|
||||
state.signal_activity().await;
|
||||
});
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
fn handle_event(app_handle: &AppHandle, event: MenuEvent) {
|
||||
match event.id.0.as_str() {
|
||||
"exit" => app_handle.exit(0),
|
||||
"show_hide" => {
|
||||
let _ = app::toggle_main_window(app_handle);
|
||||
let new_handle = app_handle.clone();
|
||||
rt::spawn(async move {
|
||||
let state = new_handle.state::<AppState>();
|
||||
state.signal_activity().await;
|
||||
});
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
@ -3,69 +3,57 @@
|
||||
"build": {
|
||||
"beforeBuildCommand": "npm run build",
|
||||
"beforeDevCommand": "npm run dev",
|
||||
"devPath": "http://localhost:5173",
|
||||
"distDir": "../dist"
|
||||
"frontendDist": "../dist",
|
||||
"devUrl": "http://localhost:5173"
|
||||
},
|
||||
"package": {
|
||||
"productName": "creddy",
|
||||
"version": "0.4.7"
|
||||
},
|
||||
"tauri": {
|
||||
"allowlist": {
|
||||
"app": {
|
||||
"all": true,
|
||||
"show": false,
|
||||
"hide": false
|
||||
},
|
||||
"os": {"all": true},
|
||||
"dialog": {"open": true}
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"category": "DeveloperTool",
|
||||
"copyright": "",
|
||||
"targets": "all",
|
||||
"externalBin": [],
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
],
|
||||
"windows": {
|
||||
"certificateThumbprint": null,
|
||||
"digestAlgorithm": "sha256",
|
||||
"timestampUrl": "",
|
||||
"wix": {
|
||||
"fragmentPaths": [
|
||||
"conf/cli.wxs"
|
||||
],
|
||||
"componentRefs": [
|
||||
"CliBinary",
|
||||
"AddToPath"
|
||||
]
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"category": "DeveloperTool",
|
||||
"copyright": "",
|
||||
"longDescription": "",
|
||||
"macOS": {
|
||||
"entitlements": null,
|
||||
"exceptionDomain": "",
|
||||
"frameworks": [],
|
||||
"providerShortName": null,
|
||||
"signingIdentity": null
|
||||
},
|
||||
"resources": [],
|
||||
"shortDescription": "",
|
||||
"linux": {
|
||||
"deb": {
|
||||
"depends": []
|
||||
},
|
||||
"externalBin": [],
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
],
|
||||
"identifier": "creddy",
|
||||
"longDescription": "",
|
||||
"macOS": {
|
||||
"entitlements": null,
|
||||
"exceptionDomain": "",
|
||||
"frameworks": [],
|
||||
"providerShortName": null,
|
||||
"signingIdentity": null
|
||||
},
|
||||
"resources": [],
|
||||
"shortDescription": "",
|
||||
"targets": "all",
|
||||
"windows": {
|
||||
"certificateThumbprint": null,
|
||||
"digestAlgorithm": "sha256",
|
||||
"timestampUrl": "",
|
||||
"wix": {
|
||||
"fragmentPaths": ["conf/cli.wxs"],
|
||||
"componentRefs": ["CliBinary", "AddToPath"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": {
|
||||
"csp": {
|
||||
"default-src": ["'self'"],
|
||||
"style-src": ["'self'", "'unsafe-inline'"]
|
||||
}
|
||||
},
|
||||
"updater": {
|
||||
"active": false
|
||||
},
|
||||
}
|
||||
},
|
||||
"productName": "creddy",
|
||||
"version": "0.4.8",
|
||||
"identifier": "creddy",
|
||||
"plugins": {},
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"fullscreen": false,
|
||||
@ -77,9 +65,24 @@
|
||||
"visible": false
|
||||
}
|
||||
],
|
||||
"systemTray": {
|
||||
"trayIcon": {
|
||||
"id": "main",
|
||||
"iconPath": "icons/icon.png",
|
||||
"iconAsTemplate": true
|
||||
},
|
||||
"security": {
|
||||
"csp": {
|
||||
"style-src": [
|
||||
"'self'",
|
||||
"'unsafe-inline'"
|
||||
],
|
||||
"default-src": [
|
||||
"'self'"
|
||||
],
|
||||
"connect-src": [
|
||||
"ipc: http://ipc.localhost"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user