feat: add tray icon
This commit is contained in:
@@ -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(
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
64
src-tauri/src/commands/tray.rs
Normal file
64
src-tauri/src/commands/tray.rs
Normal 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(())
|
||||||
|
}
|
||||||
@@ -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)]
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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 }) };
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user