feat: add tray icon

This commit is contained in:
2024-09-19 08:59:17 +07:00
parent d03865eeaa
commit 82500b35f4
7 changed files with 125 additions and 16 deletions

View File

@@ -15,6 +15,12 @@ pub struct EventPayload {
sender: String, sender: String,
} }
#[derive(Debug, Clone, Serialize, Deserialize, Type)]
struct Account {
password: String,
nostr_connect: Option<String>,
}
#[tauri::command] #[tauri::command]
#[specta::specta] #[specta::specta]
pub async fn get_metadata(user_id: String, state: State<'_, Nostr>) -> Result<String, String> { pub async fn get_metadata(user_id: String, state: State<'_, Nostr>) -> Result<String, String> {
@@ -37,12 +43,6 @@ pub async fn get_metadata(user_id: String, state: State<'_, Nostr>) -> Result<St
} }
} }
#[derive(Debug, Clone, Serialize, Deserialize, Type)]
struct Account {
password: String,
nostr_connect: Option<String>,
}
#[tauri::command] #[tauri::command]
#[specta::specta] #[specta::specta]
pub fn get_accounts() -> Vec<String> { pub fn get_accounts() -> Vec<String> {
@@ -55,6 +55,17 @@ pub fn get_accounts() -> Vec<String> {
accounts.into_iter().collect() accounts.into_iter().collect()
} }
#[tauri::command]
#[specta::specta]
pub async fn get_current_account(state: State<'_, Nostr>) -> Result<String, String> {
let client = &state.client;
let signer = client.signer().await.map_err(|e| e.to_string())?;
let public_key = signer.public_key().await.map_err(|e| e.to_string())?;
let bech32 = public_key.to_bech32().map_err(|e| e.to_string())?;
Ok(bech32)
}
#[tauri::command] #[tauri::command]
#[specta::specta] #[specta::specta]
pub async fn create_account( pub async fn create_account(

View File

@@ -1,3 +1,4 @@
pub mod account; pub mod account;
pub mod chat; pub mod chat;
pub mod relay; pub mod relay;
pub mod tray;

View File

@@ -0,0 +1,64 @@
#[cfg(target_os = "macos")]
use border::WebviewWindowExt as WebviewWindowExtAlt;
use tauri::{Manager, WebviewWindowBuilder};
#[cfg(not(target_os = "linux"))]
use tauri_plugin_decorum::WebviewWindowExt;
pub fn setup_tray_icon(app: &tauri::AppHandle) -> tauri::Result<()> {
let tray = app.tray_by_id("main").expect("Error: tray icon not found.");
let menu = tauri::menu::MenuBuilder::new(app)
.item(
&tauri::menu::MenuItem::with_id(app, "open", "Open Coop", true, None::<&str>).unwrap(),
)
.item(&tauri::menu::MenuItem::with_id(app, "quit", "Quit", true, None::<&str>).unwrap())
.build()
.expect("Error: cannot create menu.");
if tray.set_menu(Some(menu)).is_err() {
panic!("Error: cannot set menu for tray icon.")
}
tray.on_menu_event(move |app, event| match event.id.0.as_str() {
"open" => {
if let Some(window) = app.get_webview_window("main") {
if window.is_visible().unwrap_or_default() {
let _ = window.set_focus();
} else {
let _ = window.show();
let _ = window.set_focus();
};
} else {
let config = app.config().app.windows.first().unwrap();
let window =
WebviewWindowBuilder::from_config(app, config).unwrap().build().unwrap();
// Set custom decoration
#[cfg(target_os = "windows")]
window.create_overlay_titlebar().unwrap();
// Set traffic light inset
#[cfg(target_os = "macos")]
window.set_traffic_lights_inset(12.0, 18.0).unwrap();
// Workaround for reset traffic light when theme changed
#[cfg(target_os = "macos")]
let win_ = window.clone();
#[cfg(target_os = "macos")]
window.on_window_event(move |event| {
if let tauri::WindowEvent::ThemeChanged(_) = event {
win_.set_traffic_lights_inset(12.0, 18.0).unwrap();
}
});
// Restore native border
#[cfg(target_os = "macos")]
window.add_border(None);
}
}
"quit" => std::process::exit(0),
_ => {}
});
Ok(())
}

View File

@@ -3,12 +3,12 @@
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
use border::WebviewWindowExt as WebviewWindowExtAlt; use border::WebviewWindowExt as WebviewWindowExtAlt;
use commands::tray::setup_tray_icon;
use nostr_sdk::prelude::*; use nostr_sdk::prelude::*;
use specta_typescript::Typescript; use specta_typescript::Typescript;
use std::env;
use std::{ use std::{
collections::HashMap, collections::HashMap,
fs, env, fs,
io::{self, BufRead}, io::{self, BufRead},
str::FromStr, str::FromStr,
time::Duration, time::Duration,
@@ -47,6 +47,7 @@ fn main() {
delete_account, delete_account,
reset_password, reset_password,
get_accounts, get_accounts,
get_current_account,
get_metadata, get_metadata,
get_contact_list, get_contact_list,
get_chats, get_chats,
@@ -72,6 +73,8 @@ fn main() {
builder.mount_events(app); builder.mount_events(app);
let handle = app.handle(); let handle = app.handle();
let _ = setup_tray_icon(handle);
#[cfg(not(target_os = "linux"))] #[cfg(not(target_os = "linux"))]
let main_window = app.get_webview_window("main").unwrap(); let main_window = app.get_webview_window("main").unwrap();
@@ -129,7 +132,6 @@ fn main() {
if let Some((relay, option)) = line.split_once(',') { if let Some((relay, option)) = line.split_once(',') {
match RelayMetadata::from_str(option) { match RelayMetadata::from_str(option) {
Ok(meta) => { Ok(meta) => {
println!("Connecting to relay...: {} - {}", relay, meta);
let opts = if meta == RelayMetadata::Read { let opts = if meta == RelayMetadata::Read {
RelayOptions::new().read(true).write(false) RelayOptions::new().read(true).write(false)
} else { } else {
@@ -138,7 +140,6 @@ fn main() {
let _ = client.pool().add_relay(relay, opts).await; let _ = client.pool().add_relay(relay, opts).await;
} }
Err(_) => { Err(_) => {
println!("Connecting to relay...: {}", relay);
let _ = client.add_relay(relay).await; let _ = client.add_relay(relay).await;
} }
} }
@@ -175,8 +176,13 @@ fn main() {
.plugin(tauri_plugin_decorum::init()) .plugin(tauri_plugin_decorum::init())
.plugin(tauri_plugin_notification::init()) .plugin(tauri_plugin_notification::init())
.plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_shell::init())
.run(tauri::generate_context!()) .build(tauri::generate_context!())
.expect("error while running tauri application"); .expect("error while running tauri application")
.run(|_app_handle, event| {
if let tauri::RunEvent::ExitRequested { api, .. } = event {
api.prevent_exit();
}
});
} }
#[cfg(debug_assertions)] #[cfg(debug_assertions)]

View File

@@ -1,7 +1,7 @@
{ {
"productName": "Coop", "productName": "Coop",
"version": "0.1.7", "version": "0.1.7",
"identifier": "nu.lume.coop", "identifier": "su.reya.coop",
"build": { "build": {
"beforeDevCommand": "pnpm dev", "beforeDevCommand": "pnpm dev",
"devUrl": "http://localhost:1420", "devUrl": "http://localhost:1420",
@@ -29,12 +29,18 @@
"$RESOURCE/*" "$RESOURCE/*"
] ]
} }
},
"trayIcon": {
"id": "main",
"iconPath": "./icons/32x32.png",
"iconAsTemplate": true,
"menuOnLeftClick": true
} }
}, },
"bundle": { "bundle": {
"homepage": "https://lume.nu/coop", "homepage": "https://coop.reya.su",
"longDescription": "direct message client for desktop", "longDescription": "A direct message nostr client for desktop.",
"shortDescription": "nostr client", "shortDescription": "Nostr NIP-17 client",
"targets": "all", "targets": "all",
"active": true, "active": true,
"category": "SocialNetworking", "category": "SocialNetworking",

View File

@@ -112,6 +112,14 @@ async resetPassword(key: string, password: string) : Promise<Result<null, string
async getAccounts() : Promise<string[]> { async getAccounts() : Promise<string[]> {
return await TAURI_INVOKE("get_accounts"); return await TAURI_INVOKE("get_accounts");
}, },
async getCurrentAccount() : Promise<Result<string, string>> {
try {
return { status: "ok", data: await TAURI_INVOKE("get_current_account") };
} catch (e) {
if(e instanceof Error) throw e;
else return { status: "error", error: e as any };
}
},
async getMetadata(userId: string) : Promise<Result<string, string>> { async getMetadata(userId: string) : Promise<Result<string, string>> {
try { try {
return { status: "ok", data: await TAURI_INVOKE("get_metadata", { userId }) }; return { status: "ok", data: await TAURI_INVOKE("get_metadata", { userId }) };

View File

@@ -7,6 +7,19 @@ export const Route = createFileRoute("/")({
// Check for app updates // Check for app updates
await checkForAppUpdates(true); await checkForAppUpdates(true);
// Get current account
const checkAccount = await commands.getCurrentAccount();
if (checkAccount.status === "ok") {
const currentAccount = checkAccount.data;
throw redirect({
to: "/$account/chats/new",
params: { account: currentAccount },
replace: true,
});
}
// Get all accounts from system // Get all accounts from system
const accounts = await commands.getAccounts(); const accounts = await commands.getAccounts();