add sys tray

This commit is contained in:
Ward from fusion-voyager-3 2024-10-04 17:44:42 +03:00
parent f978bb2faa
commit 712a2d1e70
4 changed files with 236 additions and 2 deletions

104
Cargo.lock generated
View File

@ -41,6 +41,15 @@ dependencies = [
"libc",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "apt-sources-lists"
version = "0.1.0"
@ -232,6 +241,21 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "clap"
version = "2.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
dependencies = [
"ansi_term",
"atty",
"bitflags 1.3.2",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "cloudabi"
version = "0.0.3"
@ -368,6 +392,37 @@ dependencies = [
"syn 2.0.70",
]
[[package]]
name = "dbus"
version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b"
dependencies = [
"libc",
"libdbus-sys",
"winapi 0.3.9",
]
[[package]]
name = "dbus-codegen"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a49da9fdfbe872d4841d56605dc42efa5e6ca3291299b87f44e1cde91a28617c"
dependencies = [
"clap",
"dbus",
"xml-rs",
]
[[package]]
name = "dbus-tree"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f456e698ae8e54575e19ddb1f9b7bce2298568524f215496b248eb9498b4f508"
dependencies = [
"dbus",
]
[[package]]
name = "deb822-lossless"
version = "0.1.23"
@ -1230,6 +1285,18 @@ dependencies = [
"winapi-build",
]
[[package]]
name = "ksni"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4934310bdd016e55725482b8d35ac0c16fd058c1b955d8959aa2d953b918c85b"
dependencies = [
"dbus",
"dbus-codegen",
"dbus-tree",
"thiserror",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
@ -1281,6 +1348,15 @@ version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "libdbus-sys"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72"
dependencies = [
"pkg-config",
]
[[package]]
name = "libflatpak"
version = "0.5.0"
@ -1671,6 +1747,7 @@ dependencies = [
"duct",
"futures 0.3.30",
"gtk4",
"ksni",
"legacy-apt-list-tools-rs",
"libadwaita",
"libflatpak",
@ -2191,6 +2268,12 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a8348af2d9fc3258c8733b8d9d8db2e56f54b2363a4b5b81585c7875ed65e65"
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "syn"
version = "1.0.109"
@ -2322,6 +2405,15 @@ version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233"
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "thiserror"
version = "1.0.61"
@ -2651,6 +2743,12 @@ version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version-compare"
version = "0.2.0"
@ -3002,6 +3100,12 @@ dependencies = [
"winapi-build",
]
[[package]]
name = "xml-rs"
version = "0.8.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26"
[[package]]
name = "yaml-rust"
version = "0.4.5"

View File

@ -44,4 +44,5 @@ duct = "0.13.7"
reqwest = { version = "0.11", features = ["blocking"] }
strfmt = "0.2.4"
configparser = "3.1.0"
ksni = "0.2.2"

View File

@ -154,5 +154,9 @@
"flatpak_ref_install_flatref_path_prefrencesgroup_title": "The File Path to The Flatpak Reference File You Want to Install",
"flatpak_ref_install_dialog_heading": "Flatpak Reference File Installer",
"flatpak_ref_install_dialog_add_label": "Install",
"flatpak_ref_install_dialog_cancel_label": "Cancel"
"flatpak_ref_install_dialog_cancel_label": "Cancel",
"pikman_indicator_apt_count_item_label": "APT Updates: {NUM}",
"pikman_indicator_flatpak_count_item_label": "Flatpak Updates: {NUM}",
"pikman_indicator_open_item_label": "Open",
"pikman_indicator_exit_item_label": "Exit"
}

View File

@ -5,14 +5,84 @@ use crate::config::{APP_GITHUB, APP_ICON, APP_ID, VERSION};
use crate::flatpak_update_page;
use adw::prelude::*;
use adw::*;
use async_channel::Sender;
use futures::task::SpawnExt;
use gtk::glib::{clone, MainContext};
use gtk::{License, WindowControls};
use std::borrow::Borrow;
use std::cell::RefCell;
use std::ops::Index;
use std::process::Command;
use std::rc::Rc;
use std::sync::atomic::AtomicBool;
use std::thread;
use std::sync::Arc;
use ksni;
#[derive(Debug)]
struct PikmanTray {
icon_name: Option<String>,
apt_item_label: Option<String>,
flatpak_item_label: Option<String>,
action_sender: &'static async_channel::Sender<String>,
}
impl ksni::Tray for PikmanTray {
fn icon_name(&self) -> String {
match &self.icon_name {
Some(t) => t.into(),
None => "help-about".into()
}
}
fn title(&self) -> String {
t!("application_name").to_string()
}
// NOTE: On some system trays, `id` is a required property to avoid unexpected behaviors
fn id(&self) -> String {
env!("CARGO_PKG_NAME").into()
}
fn menu(&self) -> Vec<ksni::MenuItem<Self>> {
use ksni::menu::*;
vec![
StandardItem {
label: match &self.apt_item_label {
Some(t) => t,
None => "?"
}.into(),
icon_name: "application-vnd.debian.binary-package".into(),
enabled: false,
..Default::default()
}
.into(),
StandardItem {
label: match &self.flatpak_item_label {
Some(t) => t,
None => "?"
}.into(),
icon_name: "application-vnd.flatpak".into(),
enabled: false,
..Default::default()
}
.into(),
MenuItem::Separator,
StandardItem {
label: t!("pikman_indicator_open_item_label").into(),
icon_name: "view-paged-symbolic".into(),
activate: Box::new(|_| {
self.action_sender.send_blocking(String::from("open")).unwrap()
}),
..Default::default()
}
.into(),
StandardItem {
label: t!("pikman_indicator_exit_item_label").into(),
icon_name: "application-exit-symbolic".into(),
activate: Box::new(|_| std::process::exit(0)),
..Default::default()
}
.into(),
]
}
}
pub fn build_ui(app: &Application) {
// setup glib
@ -24,6 +94,23 @@ pub fn build_ui(app: &Application) {
let (internet_loop_sender, internet_loop_receiver) = async_channel::unbounded();
let internet_loop_sender = internet_loop_sender.clone();
// Systray
let update_sys_tray = gio::SimpleAction::new("sys_tray", Some(glib::VariantTy::ARRAY));
let (tray_service_sender, tray_service_receiver) = async_channel::unbounded();
let tray_service_sender = tray_service_sender.clone();
let tray_service = ksni::TrayService::new(PikmanTray {
action_sender: Box::leak(Box::new(tray_service_sender)),
icon_name: None,
apt_item_label: None,
flatpak_item_label: None,
});
let tray_handle = tray_service.handle();
tray_service.spawn();
thread::spawn(move || loop {
match Command::new("ping").arg("google.com").arg("-c 1").output() {
Ok(t) if t.status.success() => internet_loop_sender
@ -318,6 +405,44 @@ pub fn build_ui(app: &Application) {
let flatpak_manage_page_toggle_button = add_content_button(&window_adw_stack, false, "flatpak_manage_page".to_string(), t!("flatpak_manage_page_title").to_string(), &null_toggle_button);
window_adw_view_switcher_sidebar_box.append(&flatpak_manage_page_toggle_button);
update_sys_tray.connect_activate(clone!(
#[strong]
tray_handle,
move |_,param| {
let array: &[i32] = param.unwrap().fixed_array().unwrap();
let vec = array.to_vec();
let apt_update_count = vec[0];
let flatpak_update_count = vec[1];
let tray_icon = if apt_update_count + flatpak_update_count > 1 {
Some("update-high".into())
} else {
Some("update-none".into())
};
tray_handle.update(|tray: &mut PikmanTray| {
tray.icon_name = tray_icon;
tray.apt_item_label = Some(strfmt::strfmt(
&t!("pikman_indicator_apt_count_item_label").to_string(),
&std::collections::HashMap::from([
(
"NUM".to_string(),
apt_update_count.to_string(),
),
]),
)
.unwrap());
tray.flatpak_item_label = Some(strfmt::strfmt(
&t!("pikman_indicator_flatpak_count_item_label").to_string(),
&std::collections::HashMap::from([
(
"NUM".to_string(),
flatpak_update_count.to_string(),
),
]),
)
.unwrap());
});
}));
app.connect_command_line(clone!(
#[strong]
apt_manage_page_toggle_button,