134 lines
3.5 KiB
Rust
134 lines
3.5 KiB
Rust
use ksni::menu::StandardItem;
|
|
use ksni::{Category, Icon, ToolTip, Tray, TrayMethods};
|
|
use std::sync::mpsc;
|
|
|
|
pub enum TrayCommand {
|
|
Show,
|
|
QuickAdd,
|
|
LogExpense,
|
|
LogIncome,
|
|
Quit,
|
|
}
|
|
|
|
static TRAY_ICON_32: &[u8] = include_bytes!("../data/icons/tray-icon-32x32.argb");
|
|
static TRAY_ICON_48: &[u8] = include_bytes!("../data/icons/tray-icon-48x48.argb");
|
|
|
|
struct OutlayTray {
|
|
sender: mpsc::Sender<TrayCommand>,
|
|
}
|
|
|
|
impl Tray for OutlayTray {
|
|
fn id(&self) -> String {
|
|
"outlay".into()
|
|
}
|
|
|
|
fn title(&self) -> String {
|
|
"Outlay".into()
|
|
}
|
|
|
|
fn icon_name(&self) -> String {
|
|
String::new()
|
|
}
|
|
|
|
fn icon_pixmap(&self) -> Vec<Icon> {
|
|
vec![
|
|
Icon {
|
|
width: 32,
|
|
height: 32,
|
|
data: TRAY_ICON_32.to_vec(),
|
|
},
|
|
Icon {
|
|
width: 48,
|
|
height: 48,
|
|
data: TRAY_ICON_48.to_vec(),
|
|
},
|
|
]
|
|
}
|
|
|
|
fn category(&self) -> Category {
|
|
Category::ApplicationStatus
|
|
}
|
|
|
|
fn tool_tip(&self) -> ToolTip {
|
|
ToolTip {
|
|
title: "Outlay - Personal Finance".into(),
|
|
description: String::new(),
|
|
icon_name: String::new(),
|
|
icon_pixmap: Vec::new(),
|
|
}
|
|
}
|
|
|
|
fn activate(&mut self, _x: i32, _y: i32) {
|
|
self.sender.send(TrayCommand::Show).ok();
|
|
}
|
|
|
|
fn menu(&self) -> Vec<ksni::MenuItem<Self>> {
|
|
vec![
|
|
StandardItem {
|
|
label: "Show Outlay".into(),
|
|
activate: Box::new(|tray: &mut Self| {
|
|
tray.sender.send(TrayCommand::Show).ok();
|
|
}),
|
|
..Default::default()
|
|
}
|
|
.into(),
|
|
ksni::MenuItem::Separator,
|
|
StandardItem {
|
|
label: "Quick Add".into(),
|
|
activate: Box::new(|tray: &mut Self| {
|
|
tray.sender.send(TrayCommand::QuickAdd).ok();
|
|
}),
|
|
..Default::default()
|
|
}
|
|
.into(),
|
|
StandardItem {
|
|
label: "Log Expense".into(),
|
|
activate: Box::new(|tray: &mut Self| {
|
|
tray.sender.send(TrayCommand::LogExpense).ok();
|
|
}),
|
|
..Default::default()
|
|
}
|
|
.into(),
|
|
StandardItem {
|
|
label: "Log Income".into(),
|
|
activate: Box::new(|tray: &mut Self| {
|
|
tray.sender.send(TrayCommand::LogIncome).ok();
|
|
}),
|
|
..Default::default()
|
|
}
|
|
.into(),
|
|
ksni::MenuItem::Separator,
|
|
StandardItem {
|
|
label: "Quit".into(),
|
|
activate: Box::new(|tray: &mut Self| {
|
|
tray.sender.send(TrayCommand::Quit).ok();
|
|
}),
|
|
..Default::default()
|
|
}
|
|
.into(),
|
|
]
|
|
}
|
|
}
|
|
|
|
pub fn spawn_tray(sender: mpsc::Sender<TrayCommand>) {
|
|
let tray = OutlayTray { sender };
|
|
|
|
std::thread::spawn(move || {
|
|
let rt = tokio::runtime::Builder::new_current_thread()
|
|
.enable_all()
|
|
.build()
|
|
.expect("Failed to create tokio runtime for tray");
|
|
|
|
rt.block_on(async {
|
|
match tray.spawn().await {
|
|
Ok(_handle) => {
|
|
std::future::pending::<()>().await;
|
|
}
|
|
Err(e) => {
|
|
eprintln!("[tray] Failed to register: {:?}", e);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|