From 047dfed247dc69906beb009c0a545c3089d780da Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Thu, 8 Aug 2024 20:01:57 +0859 Subject: [PATCH 01/35] fix: try to support a mini notification widget --- src/main.rs | 1 + src/notifications.rs | 103 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 src/notifications.rs diff --git a/src/main.rs b/src/main.rs index 3a32345..ea34f1b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,7 @@ use iced_runtime::window::Action as WindowAction; mod aximer; mod launcher; mod zbus_mpirs; +mod notifications; type LaLaShellIdAction = LayershellCustomActionsWithIdAndInfo; type LalaShellAction = LayershellCustomActionsWithInfo; diff --git a/src/notifications.rs b/src/notifications.rs new file mode 100644 index 0000000..6a2cc3c --- /dev/null +++ b/src/notifications.rs @@ -0,0 +1,103 @@ +//! # D-Bus interface proxy for: `org.freedesktop.Notifications` +//! +//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data. +//! Source: `Interface '/org/freedesktop/Notifications' from service 'org.freedesktop.Notifications' on system bus`. +//! +//! You may prefer to adapt it, instead of using it verbatim. +//! +//! More information can be found in the [Writing a client proxy] section of the zbus +//! documentation. +//! +//! This type implements the [D-Bus standard interfaces], (`org.freedesktop.DBus.*`) for which the +//! following zbus API can be used: +//! +//! * [`zbus::fdo::PeerProxy`] +//! * [`zbus::fdo::IntrospectableProxy`] +//! * [`zbus::fdo::PropertiesProxy`] +//! +//! Consequently `zbus-xmlgen` did not generate code for the above interfaces. +//! +//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html +//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, +use zbus::{interface, object_server::SignalContext, zvariant::OwnedValue}; + +const NOTIFICATION_DELTED_BY_EXPIRED: u32 = 1; +const NOTIFICATION_DELTED_BY_USER: u32 = 2; +const NOTIFICATION_CLOSED_BY_DBUS: u32 = 3; +const NOTIFICATION_COLSED_BY_UNKNOWN_REASON: u32 = 4; + +pub struct NotifyUnit { + app_name: String, + id: u32, + icon: String, + summery: String, + actions: Vec, + timeout: i32, +} + +pub struct LaLaMako { + units: Vec +} + +#[interface(name = "org.freedesktop.Notifications")] +impl LaLaMako { + // CloseNotification method + async fn close_notification(&mut self, id: u32) -> zbus::fdo::Result<()> { + Ok(()) + } + + /// GetCapabilities method + fn get_capabilities(&self) -> Vec { + vec![ + "body".to_owned(), + "body-markup".to_owned(), + "actions".to_owned(), + "icon-static".to_owned(), + "x-canonical-private-synchronous".to_owned(), + "x-dunst-stack-tag".to_owned(), + ] + } + + /// GetServerInformation method + fn get_server_information(&self) -> (String, String, String, String) { + ( + "LaLaMako".to_owned(), + "waycrate".to_owned(), + env!("CARGO_PKG_VERSION").to_owned(), + env!("CARGO_PKG_VERSION_PATCH").to_owned(), + ) + } + + // Notify method + #[allow(clippy::too_many_arguments)] + fn notify( + &mut self, + app_name: &str, + id: u32, + icon: &str, + summery: &str, + body: &str, + actions: Vec<&str>, + hints: std::collections::HashMap<&str, OwnedValue>, + timeout: i32, + ) -> zbus::fdo::Result { + Ok(0) + } + + #[zbus(signal)] + async fn action_invoked( + &self, + ctx: &SignalContext<'_>, + id: u32, + action_key: &str, + ) -> zbus::Result<()>; + + // NotificationClosed signal + #[zbus(signal)] + async fn notification_closed( + &self, + ctx: &SignalContext<'_>, + id: u32, + reason: u32, + ) -> zbus::Result<()>; +} From bade3a5dc8ff218a4118ed13f0bebf2699e63e3b Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Thu, 8 Aug 2024 20:04:12 +0859 Subject: [PATCH 02/35] chore: run fmt --- src/main.rs | 2 +- src/notifications.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index ea34f1b..d9aa395 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,8 +15,8 @@ use iced_runtime::window::Action as WindowAction; mod aximer; mod launcher; -mod zbus_mpirs; mod notifications; +mod zbus_mpirs; type LaLaShellIdAction = LayershellCustomActionsWithIdAndInfo; type LalaShellAction = LayershellCustomActionsWithInfo; diff --git a/src/notifications.rs b/src/notifications.rs index 6a2cc3c..eeeb1d0 100644 --- a/src/notifications.rs +++ b/src/notifications.rs @@ -21,10 +21,10 @@ //! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, use zbus::{interface, object_server::SignalContext, zvariant::OwnedValue}; -const NOTIFICATION_DELTED_BY_EXPIRED: u32 = 1; -const NOTIFICATION_DELTED_BY_USER: u32 = 2; +const NOTIFICATION_DELETED_BY_EXPIRED: u32 = 1; +const NOTIFICATION_DELETED_BY_USER: u32 = 2; const NOTIFICATION_CLOSED_BY_DBUS: u32 = 3; -const NOTIFICATION_COLSED_BY_UNKNOWN_REASON: u32 = 4; +const NOTIFICATION_CLOSED_BY_UNKNOWN_REASON: u32 = 4; pub struct NotifyUnit { app_name: String, @@ -36,7 +36,7 @@ pub struct NotifyUnit { } pub struct LaLaMako { - units: Vec + units: Vec, } #[interface(name = "org.freedesktop.Notifications")] From e611ae676959d51e2e905108a543cd5661e3826a Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Fri, 9 Aug 2024 21:30:54 +0859 Subject: [PATCH 03/35] feat: listen to notifications --- Cargo.lock | 1 + Cargo.toml | 1 + src/main.rs | 9 ++++++ src/notifications.rs | 75 +++++++++++++++++++++++++++++++++++++------- 4 files changed, 75 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 53a9d26..2540815 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1964,6 +1964,7 @@ dependencies = [ "alsa", "anyhow", "env_logger", + "futures", "futures-util", "gio", "iced", diff --git a/Cargo.toml b/Cargo.toml index f5f094f..4c26275 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,3 +34,4 @@ gio = "0.20.0" regex = "1.10.5" xdg = "2.5.2" url = "2.5.2" +futures = "0.3.30" diff --git a/src/main.rs b/src/main.rs index d9aa395..8614772 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ use iced_layershell::actions::{ LayershellCustomActionsWithIdAndInfo, LayershellCustomActionsWithInfo, }; use launcher::Launcher; +use notifications::{start_server, NotifyMessage}; use zbus_mpirs::ServiceInfo; use iced_layershell::reexport::{Anchor, KeyboardInteractivity, Layer, NewLayerShellSettings}; @@ -181,6 +182,7 @@ enum Message { SearchSubmit, Launch(usize), IcedEvent(Event), + Notify(NotifyMessage), } async fn get_metadata_initial() -> Option { @@ -463,6 +465,12 @@ impl MultiApplication for LalaMusicBar { ), self.launcher.as_ref().unwrap().focus_input(), ]); + } + Message::Notify(NotifyMessage::UnitAdd(notify)) => { + println!("{notify:?}"); + } + Message::Notify(NotifyMessage::UnitRemove(id)) => { + } _ => { if let Some(launcher) = self.launcher.as_mut() { @@ -494,6 +502,7 @@ impl MultiApplication for LalaMusicBar { .map(|_| Message::RequestDBusInfoUpdate), iced::time::every(std::time::Duration::from_secs(5)).map(|_| Message::UpdateBalance), iced::event::listen().map(Message::IcedEvent), + iced::subscription::channel(std::any::TypeId::of::<()>(), 100, start_server), ]) } diff --git a/src/notifications.rs b/src/notifications.rs index eeeb1d0..0a44f86 100644 --- a/src/notifications.rs +++ b/src/notifications.rs @@ -21,28 +21,55 @@ //! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, use zbus::{interface, object_server::SignalContext, zvariant::OwnedValue}; +use futures::{channel::mpsc::Sender, never::Never}; +use zbus::ConnectionBuilder; + +use super::Message; + +use std::future::pending; + +#[allow(unused)] const NOTIFICATION_DELETED_BY_EXPIRED: u32 = 1; const NOTIFICATION_DELETED_BY_USER: u32 = 2; + +#[allow(unused)] const NOTIFICATION_CLOSED_BY_DBUS: u32 = 3; +#[allow(unused)] const NOTIFICATION_CLOSED_BY_UNKNOWN_REASON: u32 = 4; -pub struct NotifyUnit { - app_name: String, - id: u32, - icon: String, - summery: String, - actions: Vec, - timeout: i32, +#[derive(Debug, Clone)] +pub enum NotifyMessage { + UnitAdd(NotifyUnit), + UnitRemove(u32), } -pub struct LaLaMako { - units: Vec, +#[derive(Debug, Clone)] +pub struct NotifyUnit { + pub app_name: String, + pub id: u32, + pub icon: String, + pub summery: String, + pub body: String, + pub actions: Vec, + pub timeout: i32, } +pub struct LaLaMako(Sender); + #[interface(name = "org.freedesktop.Notifications")] impl LaLaMako { // CloseNotification method - async fn close_notification(&mut self, id: u32) -> zbus::fdo::Result<()> { + async fn close_notification( + &mut self, + #[zbus(signal_context)] ctx: SignalContext<'_>, + id: u32, + ) -> zbus::fdo::Result<()> { + self.notification_closed(&ctx, id, NOTIFICATION_DELETED_BY_USER) + .await + .ok(); + self.0 + .try_send(Message::Notify(NotifyMessage::UnitRemove(id))) + .ok(); Ok(()) } @@ -78,9 +105,20 @@ impl LaLaMako { summery: &str, body: &str, actions: Vec<&str>, - hints: std::collections::HashMap<&str, OwnedValue>, + _hints: std::collections::HashMap<&str, OwnedValue>, timeout: i32, ) -> zbus::fdo::Result { + self.0 + .try_send(Message::Notify(NotifyMessage::UnitAdd(NotifyUnit { + app_name: app_name.to_string(), + id, + icon: icon.to_string(), + summery: summery.to_string(), + body: body.to_string(), + actions: actions.iter().map(|a| a.to_string()).collect(), + timeout, + }))) + .ok(); Ok(0) } @@ -101,3 +139,18 @@ impl LaLaMako { reason: u32, ) -> zbus::Result<()>; } + +pub async fn start_server(sender: Sender) -> Never { + let _conn = async { + ConnectionBuilder::session()? + .name("org.freedesktop.Notifications")? + .serve_at("/org/freedesktop/Notifications", LaLaMako(sender))? + .build() + .await + } + .await; + + pending::<()>().await; + + loop {} +} From e2f31af839b177e5e83bcc21a963ace6b762704c Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Fri, 9 Aug 2024 22:03:47 +0859 Subject: [PATCH 04/35] chore: little tidyup --- src/main.rs | 22 ++++++++++------------ src/notifications.rs | 1 + 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/main.rs b/src/main.rs index 8614772..5d779af 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,8 +19,8 @@ mod launcher; mod notifications; mod zbus_mpirs; -type LaLaShellIdAction = LayershellCustomActionsWithIdAndInfo; -type LalaShellAction = LayershellCustomActionsWithInfo; +type LaLaShellIdAction = LayershellCustomActionsWithIdAndInfo; +type LalaShellAction = LayershellCustomActionsWithInfo; const LAUNCHER_SVG: &[u8] = include_bytes!("../misc/launcher.svg"); @@ -42,7 +42,7 @@ pub fn main() -> Result<(), iced_layershell::Error> { } #[derive(Debug, Clone, Copy)] -struct LauncherInfo; +struct LaLaInfo; #[derive(Default)] struct LalaMusicBar { @@ -314,7 +314,7 @@ impl MultiApplication for LalaMusicBar { type Flags = (); type Executor = executor::Default; type Theme = Theme; - type WindowInfo = LauncherInfo; + type WindowInfo = LaLaInfo; fn new(_flags: Self::Flags) -> (Self, Command) { ( @@ -334,15 +334,15 @@ impl MultiApplication for LalaMusicBar { String::from("Mpirs_panel") } - fn id_info(&self, id: iced_futures::core::window::Id) -> Option<&Self::WindowInfo> { + fn id_info(&self, id: iced::window::Id) -> Option<&Self::WindowInfo> { if self.launcherid.is_some_and(|tid| tid == id) { - Some(&LauncherInfo) + Some(&LaLaInfo) } else { None } } - fn set_id_info(&mut self, id: iced_futures::core::window::Id, _info: Self::WindowInfo) { + fn set_id_info(&mut self, id: iced::window::Id, _info: Self::WindowInfo) { self.launcherid = Some(id); } @@ -458,7 +458,7 @@ impl MultiApplication for LalaMusicBar { margins: None, keyboard_interactivity: KeyboardInteractivity::Exclusive, }, - LauncherInfo, + LaLaInfo, )), ) .into(), @@ -469,9 +469,7 @@ impl MultiApplication for LalaMusicBar { Message::Notify(NotifyMessage::UnitAdd(notify)) => { println!("{notify:?}"); } - Message::Notify(NotifyMessage::UnitRemove(id)) => { - - } + Message::Notify(NotifyMessage::UnitRemove(id)) => {} _ => { if let Some(launcher) = self.launcher.as_mut() { if let Some(id) = self.launcherid { @@ -488,7 +486,7 @@ impl MultiApplication for LalaMusicBar { } fn view(&self, id: iced::window::Id) -> Element { - if let Some(LauncherInfo) = self.id_info(id) { + if let Some(LaLaInfo) = self.id_info(id) { if let Some(launcher) = &self.launcher { return launcher.view(); } diff --git a/src/notifications.rs b/src/notifications.rs index 0a44f86..e7e97db 100644 --- a/src/notifications.rs +++ b/src/notifications.rs @@ -54,6 +54,7 @@ pub struct NotifyUnit { pub timeout: i32, } +#[derive(Debug)] pub struct LaLaMako(Sender); #[interface(name = "org.freedesktop.Notifications")] From 1b220ee6290894ac6642bbc696c6fb4a458bfedb Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Fri, 9 Aug 2024 23:59:07 +0859 Subject: [PATCH 05/35] feat: split crate for iced --- Cargo.lock | 15 ++++++- Cargo.toml | 42 +++++-------------- lala_bar/Cargo.toml | 37 ++++++++++++++++ {src => lala_bar/src}/aximer.rs | 0 {src => lala_bar/src}/launcher.rs | 0 .../src}/launcher/applications.rs | 2 +- {src => lala_bar/src}/main.rs | 15 ++++--- {src => lala_bar/src}/zbus_mpirs.rs | 6 +-- notification_iced/Cargo.toml | 11 +++++ .../src/lib.rs | 33 +++++++-------- 10 files changed, 102 insertions(+), 59 deletions(-) create mode 100644 lala_bar/Cargo.toml rename {src => lala_bar/src}/aximer.rs (100%) rename {src => lala_bar/src}/launcher.rs (100%) rename {src => lala_bar/src}/launcher/applications.rs (98%) rename {src => lala_bar/src}/main.rs (97%) rename {src => lala_bar/src}/zbus_mpirs.rs (98%) create mode 100644 notification_iced/Cargo.toml rename src/notifications.rs => notification_iced/src/lib.rs (83%) diff --git a/Cargo.lock b/Cargo.lock index 2540815..be64fba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1958,7 +1958,7 @@ dependencies = [ ] [[package]] -name = "lala_musicbar" +name = "lala-bar" version = "0.2.7" dependencies = [ "alsa", @@ -1971,7 +1971,7 @@ dependencies = [ "iced_futures", "iced_layershell", "iced_runtime", - "once_cell", + "notification_iced", "regex", "serde", "tokio", @@ -2243,6 +2243,17 @@ dependencies = [ "memoffset", ] +[[package]] +name = "notification_iced" +version = "0.1.0" +dependencies = [ + "futures", + "futures-util", + "serde", + "url", + "zbus", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" diff --git a/Cargo.toml b/Cargo.toml index 4c26275..bcd4e73 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,37 +1,17 @@ -[package] -name = "lala_musicbar" -version = "0.2.7" -edition = "2021" +[workspace] +resolver = "2" +members = ["./lala_bar", "./notification_iced"] -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[workspace.package] +version = "0.1.0" -[dependencies] -iced = { version = "0.12", features = [ - "tokio", - "debug", - "image", - "advanced", - "svg", -] } -#iced_native = "0.12" -iced_runtime = "0.12" -iced_layershell = "0.4.0-rc1" -tokio = { version = "1.39", features = ["full"] } -iced_futures = "0.12.0" -env_logger = "0.11.5" -tracing = "0.1.40" -futures-util = "0.3.30" -once_cell = "1.19.0" +[workspace.dependencies] +notification_iced = { version = "0.1.0", path = "notification_iced"} +futures = "0.3.30" serde = { version = "1.0.204", features = ["derive"] } - +url = "2.5.2" zbus = { version = "4.4.0", default-features = false, features = ["tokio"] } -tracing-subscriber = "0.3.18" -anyhow = "1.0.86" -alsa = "0.9.0" +futures-util = "0.3.30" + -gio = "0.20.0" -regex = "1.10.5" -xdg = "2.5.2" -url = "2.5.2" -futures = "0.3.30" diff --git a/lala_bar/Cargo.toml b/lala_bar/Cargo.toml new file mode 100644 index 0000000..ad8d430 --- /dev/null +++ b/lala_bar/Cargo.toml @@ -0,0 +1,37 @@ +[package] +name = "lala-bar" +version = "0.2.7" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +iced = { version = "0.12", features = [ + "tokio", + "debug", + "image", + "advanced", + "svg", +] } +#iced_native = "0.12" +iced_runtime = "0.12" +iced_layershell = "0.4.0-rc1" +tokio = { version = "1.39", features = ["full"] } +iced_futures = "0.12.0" +env_logger = "0.11.5" +tracing = "0.1.40" + +futures-util.workspace = true +serde.workspace = true + +zbus.workspace = true +tracing-subscriber = "0.3.18" +anyhow = "1.0.86" +alsa = "0.9.0" + +gio = "0.20.0" +regex = "1.10.5" +xdg = "2.5.2" +url.workspace = true +futures.workspace = true +notification_iced.workspace = true diff --git a/src/aximer.rs b/lala_bar/src/aximer.rs similarity index 100% rename from src/aximer.rs rename to lala_bar/src/aximer.rs diff --git a/src/launcher.rs b/lala_bar/src/launcher.rs similarity index 100% rename from src/launcher.rs rename to lala_bar/src/launcher.rs diff --git a/src/launcher/applications.rs b/lala_bar/src/launcher/applications.rs similarity index 98% rename from src/launcher/applications.rs rename to lala_bar/src/launcher/applications.rs index 04e9869..c4233d2 100644 --- a/src/launcher/applications.rs +++ b/lala_bar/src/launcher/applications.rs @@ -10,7 +10,7 @@ use iced::{Element, Length}; use super::Message; -static DEFAULT_ICON: &[u8] = include_bytes!("../../misc/text-plain.svg"); +static DEFAULT_ICON: &[u8] = include_bytes!("../../../misc/text-plain.svg"); #[allow(unused)] #[derive(Debug, Clone)] diff --git a/src/main.rs b/lala_bar/src/main.rs similarity index 97% rename from src/main.rs rename to lala_bar/src/main.rs index 5d779af..4e0b8de 100644 --- a/src/main.rs +++ b/lala_bar/src/main.rs @@ -5,7 +5,7 @@ use iced_layershell::actions::{ LayershellCustomActionsWithIdAndInfo, LayershellCustomActionsWithInfo, }; use launcher::Launcher; -use notifications::{start_server, NotifyMessage}; +use notification_iced::{start_server, NotifyMessage}; use zbus_mpirs::ServiceInfo; use iced_layershell::reexport::{Anchor, KeyboardInteractivity, Layer, NewLayerShellSettings}; @@ -16,15 +16,14 @@ use iced_runtime::window::Action as WindowAction; mod aximer; mod launcher; -mod notifications; mod zbus_mpirs; type LaLaShellIdAction = LayershellCustomActionsWithIdAndInfo; type LalaShellAction = LayershellCustomActionsWithInfo; -const LAUNCHER_SVG: &[u8] = include_bytes!("../misc/launcher.svg"); +const LAUNCHER_SVG: &[u8] = include_bytes!("../../misc/launcher.svg"); -const RESET_SVG: &[u8] = include_bytes!("../misc/reset.svg"); +const RESET_SVG: &[u8] = include_bytes!("../../misc/reset.svg"); pub fn main() -> Result<(), iced_layershell::Error> { env_logger::builder().format_timestamp(None).init(); @@ -185,6 +184,12 @@ enum Message { Notify(NotifyMessage), } +impl From for Message { + fn from(value: NotifyMessage) -> Self { + Self::Notify(value) + } +} + async fn get_metadata_initial() -> Option { zbus_mpirs::init_mpirs().await.ok(); let infos = zbus_mpirs::MPIRS_CONNECTIONS.lock().await; @@ -469,7 +474,7 @@ impl MultiApplication for LalaMusicBar { Message::Notify(NotifyMessage::UnitAdd(notify)) => { println!("{notify:?}"); } - Message::Notify(NotifyMessage::UnitRemove(id)) => {} + Message::Notify(NotifyMessage::UnitRemove(_id)) => {} _ => { if let Some(launcher) = self.launcher.as_mut() { if let Some(id) = self.launcherid { diff --git a/src/zbus_mpirs.rs b/lala_bar/src/zbus_mpirs.rs similarity index 98% rename from src/zbus_mpirs.rs rename to lala_bar/src/zbus_mpirs.rs index 2cbb1bd..14de217 100644 --- a/src/zbus_mpirs.rs +++ b/lala_bar/src/zbus_mpirs.rs @@ -4,7 +4,7 @@ use std::{ }; use futures_util::StreamExt; -use once_cell::sync::Lazy; +use std::sync::LazyLock; use tokio::sync::Mutex; @@ -144,8 +144,8 @@ async fn get_connection() -> zbus::Result { } } -pub static MPIRS_CONNECTIONS: Lazy>>> = - Lazy::new(|| Arc::new(Mutex::new(Vec::new()))); +pub static MPIRS_CONNECTIONS: LazyLock>>> = + LazyLock::new(|| Arc::new(Mutex::new(Vec::new()))); async fn mpirs_is_ready_in(path: T) -> bool { let conns = MPIRS_CONNECTIONS.lock().await; diff --git a/notification_iced/Cargo.toml b/notification_iced/Cargo.toml new file mode 100644 index 0000000..833c5ba --- /dev/null +++ b/notification_iced/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "notification_iced" +version = "0.1.0" +edition = "2021" + +[dependencies] +futures.workspace = true +serde.workspace = true +zbus.workspace = true +futures-util.workspace = true +url.workspace = true diff --git a/src/notifications.rs b/notification_iced/src/lib.rs similarity index 83% rename from src/notifications.rs rename to notification_iced/src/lib.rs index e7e97db..a036522 100644 --- a/src/notifications.rs +++ b/notification_iced/src/lib.rs @@ -24,8 +24,6 @@ use zbus::{interface, object_server::SignalContext, zvariant::OwnedValue}; use futures::{channel::mpsc::Sender, never::Never}; use zbus::ConnectionBuilder; -use super::Message; - use std::future::pending; #[allow(unused)] @@ -55,10 +53,10 @@ pub struct NotifyUnit { } #[derive(Debug)] -pub struct LaLaMako(Sender); +pub struct LaLaMako + Send>(Sender); #[interface(name = "org.freedesktop.Notifications")] -impl LaLaMako { +impl + Send + 'static> LaLaMako { // CloseNotification method async fn close_notification( &mut self, @@ -68,9 +66,7 @@ impl LaLaMako { self.notification_closed(&ctx, id, NOTIFICATION_DELETED_BY_USER) .await .ok(); - self.0 - .try_send(Message::Notify(NotifyMessage::UnitRemove(id))) - .ok(); + self.0.try_send(NotifyMessage::UnitRemove(id).into()).ok(); Ok(()) } @@ -110,15 +106,18 @@ impl LaLaMako { timeout: i32, ) -> zbus::fdo::Result { self.0 - .try_send(Message::Notify(NotifyMessage::UnitAdd(NotifyUnit { - app_name: app_name.to_string(), - id, - icon: icon.to_string(), - summery: summery.to_string(), - body: body.to_string(), - actions: actions.iter().map(|a| a.to_string()).collect(), - timeout, - }))) + .try_send( + NotifyMessage::UnitAdd(NotifyUnit { + app_name: app_name.to_string(), + id, + icon: icon.to_string(), + summery: summery.to_string(), + body: body.to_string(), + actions: actions.iter().map(|a| a.to_string()).collect(), + timeout, + }) + .into(), + ) .ok(); Ok(0) } @@ -141,7 +140,7 @@ impl LaLaMako { ) -> zbus::Result<()>; } -pub async fn start_server(sender: Sender) -> Never { +pub async fn start_server + Send + 'static>(sender: Sender) -> Never { let _conn = async { ConnectionBuilder::session()? .name("org.freedesktop.Notifications")? From 30dda65ea9350ea3d329377f94c67deaafc5cd6e Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sat, 10 Aug 2024 00:49:50 +0859 Subject: [PATCH 06/35] chore: base notification widget --- lala_bar/src/main.rs | 92 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 77 insertions(+), 15 deletions(-) diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index 4e0b8de..fd85992 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use iced::widget::{button, container, image, row, slider, svg, text, Space}; use iced::{executor, Event, Font}; use iced::{Command, Element, Length, Theme}; @@ -5,7 +7,7 @@ use iced_layershell::actions::{ LayershellCustomActionsWithIdAndInfo, LayershellCustomActionsWithInfo, }; use launcher::Launcher; -use notification_iced::{start_server, NotifyMessage}; +use notification_iced::{start_server, NotifyMessage, NotifyUnit}; use zbus_mpirs::ServiceInfo; use iced_layershell::reexport::{Anchor, KeyboardInteractivity, Layer, NewLayerShellSettings}; @@ -40,8 +42,11 @@ pub fn main() -> Result<(), iced_layershell::Error> { }) } -#[derive(Debug, Clone, Copy)] -struct LaLaInfo; +#[derive(Debug, Clone)] +enum LaLaInfo { + Launcher, + Notify(NotifyUnit), +} #[derive(Default)] struct LalaMusicBar { @@ -51,6 +56,7 @@ struct LalaMusicBar { bar_index: SliderIndex, launcher: Option, launcherid: Option, + notifications: HashMap, } #[derive(Copy, Clone, Default)] @@ -182,6 +188,7 @@ enum Message { Launch(usize), IcedEvent(Event), Notify(NotifyMessage), + RemoveNotify(iced::window::Id), } impl From for Message { @@ -330,6 +337,7 @@ impl MultiApplication for LalaMusicBar { bar_index: SliderIndex::Balance, launcher: None, launcherid: None, + notifications: HashMap::new(), }, Command::perform(get_metadata_initial(), Message::DBusInfoUpdate), ) @@ -341,18 +349,28 @@ impl MultiApplication for LalaMusicBar { fn id_info(&self, id: iced::window::Id) -> Option<&Self::WindowInfo> { if self.launcherid.is_some_and(|tid| tid == id) { - Some(&LaLaInfo) + Some(&LaLaInfo::Launcher) } else { - None + self.notifications.get(&id) } } - fn set_id_info(&mut self, id: iced::window::Id, _info: Self::WindowInfo) { - self.launcherid = Some(id); + fn set_id_info(&mut self, id: iced::window::Id, info: Self::WindowInfo) { + match info { + LaLaInfo::Launcher => { + self.launcherid = Some(id); + } + _ => { + self.notifications.insert(id, info); + } + } } - fn remove_id(&mut self, _id: iced_futures::core::window::Id) { - self.launcherid.take(); + fn remove_id(&mut self, id: iced_futures::core::window::Id) { + if self.launcherid.is_some_and(|lid| lid == id) { + self.launcherid.take(); + } + self.notifications.remove(&id); } fn update(&mut self, message: Message) -> Command { @@ -463,7 +481,7 @@ impl MultiApplication for LalaMusicBar { margins: None, keyboard_interactivity: KeyboardInteractivity::Exclusive, }, - LaLaInfo, + LaLaInfo::Launcher, )), ) .into(), @@ -472,9 +490,42 @@ impl MultiApplication for LalaMusicBar { ]); } Message::Notify(NotifyMessage::UnitAdd(notify)) => { - println!("{notify:?}"); + return Command::single( + LaLaShellIdAction::new( + iced::window::Id::MAIN, + LalaShellAction::NewLayerShell(( + NewLayerShellSettings { + size: Some((300, 70)), + exclusize_zone: None, + anchor: Anchor::Right | Anchor::Top, + layer: Layer::Top, + margins: Some((10, 10, 10, 10)), + keyboard_interactivity: KeyboardInteractivity::None, + }, + LaLaInfo::Notify(notify), + )), + ) + .into(), + ); + } + Message::Notify(NotifyMessage::UnitRemove(removed_id)) => { + let commands: Vec<_> = self + .notifications + .iter() + .filter(|(_, info)| { + if let LaLaInfo::Notify(NotifyUnit { id, .. }) = info { + return removed_id == *id; + } + false + }) + .map(|(id, _)| Command::single(Action::Window(WindowAction::Close(*id)))) + .collect(); + + return Command::batch(commands); + } + Message::RemoveNotify(id) => { + return Command::single(Action::Window(WindowAction::Close(id))); } - Message::Notify(NotifyMessage::UnitRemove(_id)) => {} _ => { if let Some(launcher) = self.launcher.as_mut() { if let Some(id) = self.launcherid { @@ -491,9 +542,20 @@ impl MultiApplication for LalaMusicBar { } fn view(&self, id: iced::window::Id) -> Element { - if let Some(LaLaInfo) = self.id_info(id) { - if let Some(launcher) = &self.launcher { - return launcher.view(); + if let Some(info) = self.id_info(id) { + match info { + LaLaInfo::Launcher => { + if let Some(launcher) = &self.launcher { + return launcher.view(); + } + } + LaLaInfo::Notify(notify) => { + return button(text(notify.body.clone()).shaping(text::Shaping::Advanced)) + .width(Length::Fill) + .height(Length::Fill) + .on_press(Message::RemoveNotify(id)) + .into() + } } } self.main_view() From c12bb319d34789a200ec46a98d28205db39fee66 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sat, 10 Aug 2024 11:18:03 +0859 Subject: [PATCH 07/35] chore: tidy up --- Cargo.lock | 9 ++--- Cargo.toml | 2 - lala_bar/Cargo.toml | 2 +- lala_bar/src/launcher.rs | 23 +++++++---- lala_bar/src/launcher/applications.rs | 4 +- lala_bar/src/main.rs | 56 +++++++++++++++++---------- 6 files changed, 58 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index be64fba..4b47be2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1672,8 +1672,7 @@ dependencies = [ [[package]] name = "iced_layershell" version = "0.4.0-rc1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace5190b78ae4b839bcb4085aa054c44b7ac89ae80ffe86cc65768c25d12d68f" +source = "git+https://github.com/waycrate/exwlshelleventloop#1e1a79d15d73cc677d52bf6fe100320a2962c454" dependencies = [ "futures", "iced", @@ -1985,8 +1984,7 @@ dependencies = [ [[package]] name = "layershellev" version = "0.4.0-rc1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043232f79a51a9618163de3e658024992c6dab911ae71a269dc760a9da6ae205" +source = "git+https://github.com/waycrate/exwlshelleventloop#1e1a79d15d73cc677d52bf6fe100320a2962c454" dependencies = [ "bitflags 2.6.0", "log", @@ -3968,8 +3966,7 @@ dependencies = [ [[package]] name = "waycrate_xkbkeycode" version = "0.4.0-rc1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4792f051d3b0772685750b424522cf2c4ad11aa5690e670eb2e42986c4163d6" +source = "git+https://github.com/waycrate/exwlshelleventloop#1e1a79d15d73cc677d52bf6fe100320a2962c454" dependencies = [ "bitflags 2.6.0", "log", diff --git a/Cargo.toml b/Cargo.toml index bcd4e73..0e20ec8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,5 +13,3 @@ serde = { version = "1.0.204", features = ["derive"] } url = "2.5.2" zbus = { version = "4.4.0", default-features = false, features = ["tokio"] } futures-util = "0.3.30" - - diff --git a/lala_bar/Cargo.toml b/lala_bar/Cargo.toml index ad8d430..d0574f4 100644 --- a/lala_bar/Cargo.toml +++ b/lala_bar/Cargo.toml @@ -15,7 +15,7 @@ iced = { version = "0.12", features = [ ] } #iced_native = "0.12" iced_runtime = "0.12" -iced_layershell = "0.4.0-rc1" +iced_layershell = { git = "https://github.com/waycrate/exwlshelleventloop", package = "iced_layershell" } tokio = { version = "1.39", features = ["full"] } iced_futures = "0.12.0" env_logger = "0.11.5" diff --git a/lala_bar/src/launcher.rs b/lala_bar/src/launcher.rs index 8479809..cd8b320 100644 --- a/lala_bar/src/launcher.rs +++ b/lala_bar/src/launcher.rs @@ -20,6 +20,14 @@ pub struct Launcher { pub should_delete: bool, } +#[derive(Debug, Clone)] +pub enum LaunchMessage { + SearchEditChanged(String), + SearchSubmit, + Launch(usize), + IcedEvent(Event), +} + impl Launcher { pub fn new() -> Self { Self { @@ -34,11 +42,11 @@ impl Launcher { text_input::focus(INPUT_ID.clone()) } - pub fn update(&mut self, message: Message, id: iced::window::Id) -> Command { + pub fn update(&mut self, message: LaunchMessage, id: iced::window::Id) -> Command { use iced::keyboard::key::Named; use iced_runtime::keyboard; match message { - Message::SearchSubmit => { + LaunchMessage::SearchSubmit => { let re = regex::Regex::new(&self.text).ok(); let index = self .apps @@ -63,17 +71,17 @@ impl Launcher { Command::none() } } - Message::SearchEditChanged(edit) => { + LaunchMessage::SearchEditChanged(edit) => { self.scrollpos = 0; self.text = edit; Command::none() } - Message::Launch(index) => { + LaunchMessage::Launch(index) => { self.apps[index].launch(); self.should_delete = true; Command::single(Action::Window(WindowAction::Close(id))) } - Message::IcedEvent(event) => { + LaunchMessage::IcedEvent(event) => { let mut len = self.apps.len(); let re = regex::Regex::new(&self.text).ok(); @@ -112,7 +120,6 @@ impl Launcher { } text_input::focus(INPUT_ID.clone()) } - _ => Command::none(), } } @@ -120,8 +127,8 @@ impl Launcher { let re = regex::Regex::new(&self.text).ok(); let text_ip: Element = text_input("put the launcher name", &self.text) .padding(10) - .on_input(Message::SearchEditChanged) - .on_submit(Message::SearchSubmit) + .on_input(|msg| Message::LauncherInfo(LaunchMessage::SearchEditChanged(msg))) + .on_submit(Message::LauncherInfo(LaunchMessage::SearchSubmit)) .id(INPUT_ID.clone()) .into(); let bottom_vec: Vec> = self diff --git a/lala_bar/src/launcher/applications.rs b/lala_bar/src/launcher/applications.rs index c4233d2..d10da50 100644 --- a/lala_bar/src/launcher/applications.rs +++ b/lala_bar/src/launcher/applications.rs @@ -1,6 +1,8 @@ use std::path::PathBuf; use std::str::FromStr; +use super::LaunchMessage; + use gio::{AppLaunchContext, DesktopAppInfo}; use gio::prelude::*; @@ -79,7 +81,7 @@ impl App { ] .spacing(10), ) - .on_press(Message::Launch(index)) + .on_press(Message::LauncherInfo(LaunchMessage::Launch(index))) .width(Length::Fill) .height(Length::Fixed(85.)) .style(if selected { diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index fd85992..7056d18 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -1,12 +1,12 @@ use std::collections::HashMap; use iced::widget::{button, container, image, row, slider, svg, text, Space}; -use iced::{executor, Event, Font}; +use iced::{executor, Font}; use iced::{Command, Element, Length, Theme}; use iced_layershell::actions::{ LayershellCustomActionsWithIdAndInfo, LayershellCustomActionsWithInfo, }; -use launcher::Launcher; +use launcher::{LaunchMessage, Launcher}; use notification_iced::{start_server, NotifyMessage, NotifyUnit}; use zbus_mpirs::ServiceInfo; @@ -56,7 +56,7 @@ struct LalaMusicBar { bar_index: SliderIndex, launcher: Option, launcherid: Option, - notifications: HashMap, + notifications: HashMap, } #[derive(Copy, Clone, Default)] @@ -183,12 +183,10 @@ enum Message { SliderIndexNext, SliderIndexPre, ToggleLauncher, - SearchEditChanged(String), - SearchSubmit, - Launch(usize), - IcedEvent(Event), + LauncherInfo(LaunchMessage), Notify(NotifyMessage), RemoveNotify(iced::window::Id), + CheckOutput, } impl From for Message { @@ -347,11 +345,13 @@ impl MultiApplication for LalaMusicBar { String::from("Mpirs_panel") } - fn id_info(&self, id: iced::window::Id) -> Option<&Self::WindowInfo> { + fn id_info(&self, id: iced::window::Id) -> Option { if self.launcherid.is_some_and(|tid| tid == id) { - Some(&LaLaInfo::Launcher) + Some(LaLaInfo::Launcher) } else { - self.notifications.get(&id) + self.notifications + .get(&id) + .map(|noficy| LaLaInfo::Notify(noficy.clone())) } } @@ -360,8 +360,8 @@ impl MultiApplication for LalaMusicBar { LaLaInfo::Launcher => { self.launcherid = Some(id); } - _ => { - self.notifications.insert(id, info); + LaLaInfo::Notify(nofify) => { + self.notifications.insert(id, nofify); } } } @@ -480,6 +480,7 @@ impl MultiApplication for LalaMusicBar { layer: Layer::Top, margins: None, keyboard_interactivity: KeyboardInteractivity::Exclusive, + use_last_output: false, }, LaLaInfo::Launcher, )), @@ -501,6 +502,7 @@ impl MultiApplication for LalaMusicBar { layer: Layer::Top, margins: Some((10, 10, 10, 10)), keyboard_interactivity: KeyboardInteractivity::None, + use_last_output: true, }, LaLaInfo::Notify(notify), )), @@ -509,24 +511,37 @@ impl MultiApplication for LalaMusicBar { ); } Message::Notify(NotifyMessage::UnitRemove(removed_id)) => { - let commands: Vec<_> = self + let mut commands: Vec<_> = self .notifications .iter() .filter(|(_, info)| { - if let LaLaInfo::Notify(NotifyUnit { id, .. }) = info { - return removed_id == *id; - } - false + let NotifyUnit { id, .. } = info; + return removed_id == *id; }) .map(|(id, _)| Command::single(Action::Window(WindowAction::Close(*id)))) .collect(); + commands.push(Command::perform(async {}, |_| Message::CheckOutput)); return Command::batch(commands); } Message::RemoveNotify(id) => { - return Command::single(Action::Window(WindowAction::Close(id))); + return Command::batch(vec![ + Command::single(Action::Window(WindowAction::Close(id))), + Command::perform(async {}, |_| Message::CheckOutput), + ]); + } + Message::CheckOutput => { + if self.notifications.is_empty() { + return Command::single( + LaLaShellIdAction::new( + iced::window::Id::MAIN, + LalaShellAction::ForgetLastOutput, + ) + .into(), + ); + } } - _ => { + Message::LauncherInfo(message) => { if let Some(launcher) = self.launcher.as_mut() { if let Some(id) = self.launcherid { let cmd = launcher.update(message, id); @@ -566,7 +581,8 @@ impl MultiApplication for LalaMusicBar { iced::time::every(std::time::Duration::from_secs(1)) .map(|_| Message::RequestDBusInfoUpdate), iced::time::every(std::time::Duration::from_secs(5)).map(|_| Message::UpdateBalance), - iced::event::listen().map(Message::IcedEvent), + iced::event::listen() + .map(|event| Message::LauncherInfo(LaunchMessage::IcedEvent(event))), iced::subscription::channel(std::any::TypeId::of::<()>(), 100, start_server), ]) } From 3540a6afb94efc41173e3de8b250bc9ddbe017f7 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sat, 10 Aug 2024 12:00:07 +0859 Subject: [PATCH 08/35] fix: tidy --- Cargo.lock | 12 ++--- lala_bar/src/main.rs | 85 ++++++++++++++++++++++++++++-------- notification_iced/src/lib.rs | 2 +- 3 files changed, 73 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4b47be2..91d1e28 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1672,7 +1672,7 @@ dependencies = [ [[package]] name = "iced_layershell" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#1e1a79d15d73cc677d52bf6fe100320a2962c454" +source = "git+https://github.com/waycrate/exwlshelleventloop#634a487d3c3f6de142924773498e36f3c121051d" dependencies = [ "futures", "iced", @@ -1984,7 +1984,7 @@ dependencies = [ [[package]] name = "layershellev" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#1e1a79d15d73cc677d52bf6fe100320a2962c454" +source = "git+https://github.com/waycrate/exwlshelleventloop#634a487d3c3f6de142924773498e36f3c121051d" dependencies = [ "bitflags 2.6.0", "log", @@ -3966,7 +3966,7 @@ dependencies = [ [[package]] name = "waycrate_xkbkeycode" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#1e1a79d15d73cc677d52bf6fe100320a2962c454" +source = "git+https://github.com/waycrate/exwlshelleventloop#634a487d3c3f6de142924773498e36f3c121051d" dependencies = [ "bitflags 2.6.0", "log", @@ -4653,12 +4653,12 @@ checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" [[package]] name = "xdg-home" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca91dcf8f93db085f3a0a29358cd0b9d670915468f4290e8b85d118a34211ab8" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index 7056d18..73adb04 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use iced::widget::{button, container, image, row, slider, svg, text, Space}; +use iced::widget::{button, column, container, image, row, slider, svg, text, Space}; use iced::{executor, Font}; use iced::{Command, Element, Length, Theme}; use iced_layershell::actions::{ @@ -48,6 +48,12 @@ enum LaLaInfo { Notify(NotifyUnit), } +#[derive(Debug, Clone)] +struct NotifyUnitWidgetInfo { + uper: i32, + unit: NotifyUnit, +} + #[derive(Default)] struct LalaMusicBar { service_data: Option, @@ -56,7 +62,7 @@ struct LalaMusicBar { bar_index: SliderIndex, launcher: Option, launcherid: Option, - notifications: HashMap, + notifications: HashMap, } #[derive(Copy, Clone, Default)] @@ -351,7 +357,7 @@ impl MultiApplication for LalaMusicBar { } else { self.notifications .get(&id) - .map(|noficy| LaLaInfo::Notify(noficy.clone())) + .map(|NotifyUnitWidgetInfo { unit, .. }| LaLaInfo::Notify(unit.clone())) } } @@ -361,12 +367,15 @@ impl MultiApplication for LalaMusicBar { self.launcherid = Some(id); } LaLaInfo::Notify(nofify) => { - self.notifications.insert(id, nofify); + self.notifications.entry(id).or_insert(NotifyUnitWidgetInfo { + uper: 10, + unit: nofify, + }); } } } - fn remove_id(&mut self, id: iced_futures::core::window::Id) { + fn remove_id(&mut self, id: iced::window::Id) { if self.launcherid.is_some_and(|lid| lid == id) { self.launcherid.take(); } @@ -475,10 +484,10 @@ impl MultiApplication for LalaMusicBar { LalaShellAction::NewLayerShell(( NewLayerShellSettings { size: Some((500, 700)), - exclusize_zone: None, + exclusive_zone: None, anchor: Anchor::Left | Anchor::Bottom, layer: Layer::Top, - margins: None, + margin: None, keyboard_interactivity: KeyboardInteractivity::Exclusive, use_last_output: false, }, @@ -491,16 +500,28 @@ impl MultiApplication for LalaMusicBar { ]); } Message::Notify(NotifyMessage::UnitAdd(notify)) => { - return Command::single( + let mut commands = vec![]; + for (id, unit) in self.notifications.iter_mut() { + unit.uper += 75; + commands.push(Command::single( + LaLaShellIdAction::new( + *id, + LalaShellAction::MarginChange((unit.uper, 10, 10, 10)), + ) + .into(), + )); + } + + commands.push(Command::single( LaLaShellIdAction::new( iced::window::Id::MAIN, LalaShellAction::NewLayerShell(( NewLayerShellSettings { size: Some((300, 70)), - exclusize_zone: None, + exclusive_zone: None, anchor: Anchor::Right | Anchor::Top, layer: Layer::Top, - margins: Some((10, 10, 10, 10)), + margin: Some((10, 10, 10, 10)), keyboard_interactivity: KeyboardInteractivity::None, use_last_output: true, }, @@ -508,15 +529,16 @@ impl MultiApplication for LalaMusicBar { )), ) .into(), - ); + )); + return Command::batch(commands); } Message::Notify(NotifyMessage::UnitRemove(removed_id)) => { let mut commands: Vec<_> = self .notifications .iter() .filter(|(_, info)| { - let NotifyUnit { id, .. } = info; - return removed_id == *id; + let NotifyUnit { id, .. } = info.unit; + removed_id == id }) .map(|(id, _)| Command::single(Action::Window(WindowAction::Close(*id)))) .collect(); @@ -525,10 +547,32 @@ impl MultiApplication for LalaMusicBar { return Command::batch(commands); } Message::RemoveNotify(id) => { - return Command::batch(vec![ + let removed_pos = self + .notifications + .iter() + .find(|(oid, _)| **oid == id) + .map(|(_, info)| info.uper) + .unwrap_or(0); + + let mut commands = vec![]; + for (id, unit) in self.notifications.iter_mut() { + if unit.uper > removed_pos { + unit.uper -= 75; + } + commands.push(Command::single( + LaLaShellIdAction::new( + *id, + LalaShellAction::MarginChange((unit.uper, 10, 10, 10)), + ) + .into(), + )); + } + commands.append(&mut vec![ Command::single(Action::Window(WindowAction::Close(id))), Command::perform(async {}, |_| Message::CheckOutput), ]); + + return Command::batch(commands); } Message::CheckOutput => { if self.notifications.is_empty() { @@ -565,11 +609,14 @@ impl MultiApplication for LalaMusicBar { } } LaLaInfo::Notify(notify) => { - return button(text(notify.body.clone()).shaping(text::Shaping::Advanced)) - .width(Length::Fill) - .height(Length::Fill) - .on_press(Message::RemoveNotify(id)) - .into() + return button(column![ + text(notify.summery.clone()).shaping(text::Shaping::Advanced), + text(notify.body.clone()).shaping(text::Shaping::Advanced) + ]) + .width(Length::Fill) + .height(Length::Fill) + .on_press(Message::RemoveNotify(id)) + .into() } } } diff --git a/notification_iced/src/lib.rs b/notification_iced/src/lib.rs index a036522..f1e27f7 100644 --- a/notification_iced/src/lib.rs +++ b/notification_iced/src/lib.rs @@ -152,5 +152,5 @@ pub async fn start_server + Send + 'static>(sender: Sende pending::<()>().await; - loop {} + unreachable!() } From 978719e7719f592d990cbc0d3fb6399c6f5427cd Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sat, 10 Aug 2024 12:05:51 +0859 Subject: [PATCH 09/35] chore: update deps --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 91d1e28..ed393bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1672,7 +1672,7 @@ dependencies = [ [[package]] name = "iced_layershell" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#634a487d3c3f6de142924773498e36f3c121051d" +source = "git+https://github.com/waycrate/exwlshelleventloop#afa6b87c92fd4499d594e5c843ed1f8a134d9e10" dependencies = [ "futures", "iced", @@ -1984,7 +1984,7 @@ dependencies = [ [[package]] name = "layershellev" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#634a487d3c3f6de142924773498e36f3c121051d" +source = "git+https://github.com/waycrate/exwlshelleventloop#afa6b87c92fd4499d594e5c843ed1f8a134d9e10" dependencies = [ "bitflags 2.6.0", "log", @@ -3966,7 +3966,7 @@ dependencies = [ [[package]] name = "waycrate_xkbkeycode" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#634a487d3c3f6de142924773498e36f3c121051d" +source = "git+https://github.com/waycrate/exwlshelleventloop#afa6b87c92fd4499d594e5c843ed1f8a134d9e10" dependencies = [ "bitflags 2.6.0", "log", From d7cf37ea8e25c76a71cc5ea9ddf871b51ec305d0 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sat, 10 Aug 2024 12:07:52 +0859 Subject: [PATCH 10/35] chore: do fmt --- lala_bar/src/main.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index 73adb04..c7fbc9b 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -367,10 +367,12 @@ impl MultiApplication for LalaMusicBar { self.launcherid = Some(id); } LaLaInfo::Notify(nofify) => { - self.notifications.entry(id).or_insert(NotifyUnitWidgetInfo { - uper: 10, - unit: nofify, - }); + self.notifications + .entry(id) + .or_insert(NotifyUnitWidgetInfo { + uper: 10, + unit: nofify, + }); } } } From 7941421114a8c8b129356529a1893c4e1466e159 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sat, 10 Aug 2024 12:11:55 +0859 Subject: [PATCH 11/35] fix: typo with upstream --- Cargo.lock | 6 +++--- lala_bar/src/main.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ed393bd..05af74d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1672,7 +1672,7 @@ dependencies = [ [[package]] name = "iced_layershell" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#afa6b87c92fd4499d594e5c843ed1f8a134d9e10" +source = "git+https://github.com/waycrate/exwlshelleventloop#9d133283359b72fbd2102483ae7d282273dd098d" dependencies = [ "futures", "iced", @@ -1984,7 +1984,7 @@ dependencies = [ [[package]] name = "layershellev" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#afa6b87c92fd4499d594e5c843ed1f8a134d9e10" +source = "git+https://github.com/waycrate/exwlshelleventloop#9d133283359b72fbd2102483ae7d282273dd098d" dependencies = [ "bitflags 2.6.0", "log", @@ -3966,7 +3966,7 @@ dependencies = [ [[package]] name = "waycrate_xkbkeycode" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#afa6b87c92fd4499d594e5c843ed1f8a134d9e10" +source = "git+https://github.com/waycrate/exwlshelleventloop#9d133283359b72fbd2102483ae7d282273dd098d" dependencies = [ "bitflags 2.6.0", "log", diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index c7fbc9b..51e2b87 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -33,7 +33,7 @@ pub fn main() -> Result<(), iced_layershell::Error> { LalaMusicBar::run(Settings { layer_settings: LayerShellSettings { size: Some((0, 35)), - exclusize_zone: 35, + exclusive_zone: 35, anchor: Anchor::Bottom | Anchor::Left | Anchor::Right, layer: Layer::Top, ..Default::default() From 3f282ed0f3a2eb9d1ec591d693aae160be929bf8 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sat, 10 Aug 2024 18:02:13 +0859 Subject: [PATCH 12/35] chore: tidy up --- Cargo.lock | 6 ++-- lala_bar/src/main.rs | 23 ++++++++++++-- notification_iced/src/lib.rs | 58 +++++++++++++++++++++++++----------- 3 files changed, 65 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 05af74d..112c795 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1672,7 +1672,7 @@ dependencies = [ [[package]] name = "iced_layershell" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#9d133283359b72fbd2102483ae7d282273dd098d" +source = "git+https://github.com/waycrate/exwlshelleventloop#23afc29065769e335553261eab0ed88654344138" dependencies = [ "futures", "iced", @@ -1984,7 +1984,7 @@ dependencies = [ [[package]] name = "layershellev" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#9d133283359b72fbd2102483ae7d282273dd098d" +source = "git+https://github.com/waycrate/exwlshelleventloop#23afc29065769e335553261eab0ed88654344138" dependencies = [ "bitflags 2.6.0", "log", @@ -3966,7 +3966,7 @@ dependencies = [ [[package]] name = "waycrate_xkbkeycode" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#9d133283359b72fbd2102483ae7d282273dd098d" +source = "git+https://github.com/waycrate/exwlshelleventloop#23afc29065769e335553261eab0ed88654344138" dependencies = [ "bitflags 2.6.0", "log", diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index 51e2b87..32a5275 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -7,7 +7,7 @@ use iced_layershell::actions::{ LayershellCustomActionsWithIdAndInfo, LayershellCustomActionsWithInfo, }; use launcher::{LaunchMessage, Launcher}; -use notification_iced::{start_server, NotifyMessage, NotifyUnit}; +use notification_iced::{start_server, NotifyMessage, NotifyUnit, VersionInfo}; use zbus_mpirs::ServiceInfo; use iced_layershell::reexport::{Anchor, KeyboardInteractivity, Layer, NewLayerShellSettings}; @@ -632,7 +632,26 @@ impl MultiApplication for LalaMusicBar { iced::time::every(std::time::Duration::from_secs(5)).map(|_| Message::UpdateBalance), iced::event::listen() .map(|event| Message::LauncherInfo(LaunchMessage::IcedEvent(event))), - iced::subscription::channel(std::any::TypeId::of::<()>(), 100, start_server), + iced::subscription::channel(std::any::TypeId::of::<()>(), 100, |sender| async { + start_server( + sender, + vec![ + "body".to_owned(), + "body-markup".to_owned(), + "actions".to_owned(), + "icon-static".to_owned(), + "x-canonical-private-synchronous".to_owned(), + "x-dunst-stack-tag".to_owned(), + ], + VersionInfo { + name: "LaLaMako".to_owned(), + vendor: "waycrate".to_owned(), + version: env!("CARGO_PKG_VERSION").to_owned(), + spec_version: env!("CARGO_PKG_VERSION_PATCH").to_owned(), + }, + ) + .await + }), ]) } diff --git a/notification_iced/src/lib.rs b/notification_iced/src/lib.rs index f1e27f7..14ec457 100644 --- a/notification_iced/src/lib.rs +++ b/notification_iced/src/lib.rs @@ -52,8 +52,20 @@ pub struct NotifyUnit { pub timeout: i32, } +#[derive(Debug, Clone)] +pub struct VersionInfo { + pub name: String, + pub vendor: String, + pub version: String, + pub spec_version: String, +} + #[derive(Debug)] -pub struct LaLaMako + Send>(Sender); +pub struct LaLaMako + Send> { + capablities: Vec, + sender: Sender, + version: VersionInfo, +} #[interface(name = "org.freedesktop.Notifications")] impl + Send + 'static> LaLaMako { @@ -66,29 +78,30 @@ impl + Send + 'static> LaLaMako { self.notification_closed(&ctx, id, NOTIFICATION_DELETED_BY_USER) .await .ok(); - self.0.try_send(NotifyMessage::UnitRemove(id).into()).ok(); + self.sender + .try_send(NotifyMessage::UnitRemove(id).into()) + .ok(); Ok(()) } /// GetCapabilities method fn get_capabilities(&self) -> Vec { - vec![ - "body".to_owned(), - "body-markup".to_owned(), - "actions".to_owned(), - "icon-static".to_owned(), - "x-canonical-private-synchronous".to_owned(), - "x-dunst-stack-tag".to_owned(), - ] + self.capablities.clone() } /// GetServerInformation method fn get_server_information(&self) -> (String, String, String, String) { + let VersionInfo { + name, + vendor, + version, + spec_version, + } = &self.version; ( - "LaLaMako".to_owned(), - "waycrate".to_owned(), - env!("CARGO_PKG_VERSION").to_owned(), - env!("CARGO_PKG_VERSION_PATCH").to_owned(), + name.clone(), + vendor.clone(), + version.clone(), + spec_version.clone(), ) } @@ -105,7 +118,7 @@ impl + Send + 'static> LaLaMako { _hints: std::collections::HashMap<&str, OwnedValue>, timeout: i32, ) -> zbus::fdo::Result { - self.0 + self.sender .try_send( NotifyMessage::UnitAdd(NotifyUnit { app_name: app_name.to_string(), @@ -140,11 +153,22 @@ impl + Send + 'static> LaLaMako { ) -> zbus::Result<()>; } -pub async fn start_server + Send + 'static>(sender: Sender) -> Never { +pub async fn start_server + Send + 'static>( + sender: Sender, + capablities: Vec, + version: VersionInfo, +) -> Never { let _conn = async { ConnectionBuilder::session()? .name("org.freedesktop.Notifications")? - .serve_at("/org/freedesktop/Notifications", LaLaMako(sender))? + .serve_at( + "/org/freedesktop/Notifications", + LaLaMako { + sender, + capablities, + version, + }, + )? .build() .await } From f92cf61f570d7a8c0c92f38308e5e71fdec3311a Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sat, 10 Aug 2024 18:46:03 +0859 Subject: [PATCH 13/35] feat: support remove all notifications --- Cargo.lock | 6 +++--- lala_bar/src/main.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 112c795..682798d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1672,7 +1672,7 @@ dependencies = [ [[package]] name = "iced_layershell" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#23afc29065769e335553261eab0ed88654344138" +source = "git+https://github.com/waycrate/exwlshelleventloop#793515632472aee540ab7861146f0740d8dd773a" dependencies = [ "futures", "iced", @@ -1984,7 +1984,7 @@ dependencies = [ [[package]] name = "layershellev" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#23afc29065769e335553261eab0ed88654344138" +source = "git+https://github.com/waycrate/exwlshelleventloop#793515632472aee540ab7861146f0740d8dd773a" dependencies = [ "bitflags 2.6.0", "log", @@ -3966,7 +3966,7 @@ dependencies = [ [[package]] name = "waycrate_xkbkeycode" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#23afc29065769e335553261eab0ed88654344138" +source = "git+https://github.com/waycrate/exwlshelleventloop#793515632472aee540ab7861146f0740d8dd773a" dependencies = [ "bitflags 2.6.0", "log", diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index 32a5275..ae72399 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -51,6 +51,7 @@ enum LaLaInfo { #[derive(Debug, Clone)] struct NotifyUnitWidgetInfo { uper: i32, + counter: usize, unit: NotifyUnit, } @@ -325,6 +326,26 @@ impl LalaMusicBar { } } +impl LalaMusicBar { + fn counter_up(&mut self) { + for (_, unit) in self.notifications.iter_mut() { + unit.counter += 1; + } + } + fn counter_down(&mut self, ids: &Vec) { + for id in ids { + if let Some(NotifyUnitWidgetInfo { counter, .. }) = self.notifications.remove(id) { + for (_, unit) in self.notifications.iter_mut() { + if unit.counter > counter { + unit.counter -= 1; + unit.uper -= 75; + } + } + } + } + } +} + impl MultiApplication for LalaMusicBar { type Message = Message; type Flags = (); @@ -367,9 +388,11 @@ impl MultiApplication for LalaMusicBar { self.launcherid = Some(id); } LaLaInfo::Notify(nofify) => { + self.counter_up(); self.notifications .entry(id) .or_insert(NotifyUnitWidgetInfo { + counter: 0, uper: 10, unit: nofify, }); @@ -535,6 +558,15 @@ impl MultiApplication for LalaMusicBar { return Command::batch(commands); } Message::Notify(NotifyMessage::UnitRemove(removed_id)) => { + let removed_ids: Vec = self + .notifications + .iter() + .filter(|(_, info)| { + let NotifyUnit { id, .. } = info.unit; + removed_id == id + }) + .map(|(id, _)| id.clone()) + .collect(); let mut commands: Vec<_> = self .notifications .iter() @@ -544,6 +576,18 @@ impl MultiApplication for LalaMusicBar { }) .map(|(id, _)| Command::single(Action::Window(WindowAction::Close(*id)))) .collect(); + + self.counter_down(&removed_ids); + for (id, unit) in self.notifications.iter() { + commands.push(Command::single( + LaLaShellIdAction::new( + *id, + LalaShellAction::MarginChange((unit.uper, 10, 10, 10)), + ) + .into(), + )); + } + commands.push(Command::perform(async {}, |_| Message::CheckOutput)); return Command::batch(commands); From fee19a4fe5d96e66bb8bb81654fde46ea0437ecc Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sat, 10 Aug 2024 19:09:09 +0859 Subject: [PATCH 14/35] chore: typo fix --- Cargo.lock | 6 +++--- lala_bar/Cargo.toml | 2 +- lala_bar/src/main.rs | 20 ++++++++++---------- notification_iced/src/lib.rs | 8 ++++---- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 682798d..9c0d702 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1672,7 +1672,7 @@ dependencies = [ [[package]] name = "iced_layershell" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#793515632472aee540ab7861146f0740d8dd773a" +source = "git+https://github.com/waycrate/exwlshelleventloop?branch=evdirectlyremoveshell#1cb6bbca6b8815fab34ea1cc921e5a5edc386cb5" dependencies = [ "futures", "iced", @@ -1984,7 +1984,7 @@ dependencies = [ [[package]] name = "layershellev" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#793515632472aee540ab7861146f0740d8dd773a" +source = "git+https://github.com/waycrate/exwlshelleventloop?branch=evdirectlyremoveshell#1cb6bbca6b8815fab34ea1cc921e5a5edc386cb5" dependencies = [ "bitflags 2.6.0", "log", @@ -3966,7 +3966,7 @@ dependencies = [ [[package]] name = "waycrate_xkbkeycode" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#793515632472aee540ab7861146f0740d8dd773a" +source = "git+https://github.com/waycrate/exwlshelleventloop?branch=evdirectlyremoveshell#1cb6bbca6b8815fab34ea1cc921e5a5edc386cb5" dependencies = [ "bitflags 2.6.0", "log", diff --git a/lala_bar/Cargo.toml b/lala_bar/Cargo.toml index d0574f4..8f642f4 100644 --- a/lala_bar/Cargo.toml +++ b/lala_bar/Cargo.toml @@ -15,7 +15,7 @@ iced = { version = "0.12", features = [ ] } #iced_native = "0.12" iced_runtime = "0.12" -iced_layershell = { git = "https://github.com/waycrate/exwlshelleventloop", package = "iced_layershell" } +iced_layershell = { git = "https://github.com/waycrate/exwlshelleventloop", package = "iced_layershell", branch = "evdirectlyremoveshell" } tokio = { version = "1.39", features = ["full"] } iced_futures = "0.12.0" env_logger = "0.11.5" diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index ae72399..d3ac3fb 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -50,7 +50,7 @@ enum LaLaInfo { #[derive(Debug, Clone)] struct NotifyUnitWidgetInfo { - uper: i32, + upper: i32, counter: usize, unit: NotifyUnit, } @@ -338,7 +338,7 @@ impl LalaMusicBar { for (_, unit) in self.notifications.iter_mut() { if unit.counter > counter { unit.counter -= 1; - unit.uper -= 75; + unit.upper -= 75; } } } @@ -393,7 +393,7 @@ impl MultiApplication for LalaMusicBar { .entry(id) .or_insert(NotifyUnitWidgetInfo { counter: 0, - uper: 10, + upper: 10, unit: nofify, }); } @@ -527,11 +527,11 @@ impl MultiApplication for LalaMusicBar { Message::Notify(NotifyMessage::UnitAdd(notify)) => { let mut commands = vec![]; for (id, unit) in self.notifications.iter_mut() { - unit.uper += 75; + unit.upper += 75; commands.push(Command::single( LaLaShellIdAction::new( *id, - LalaShellAction::MarginChange((unit.uper, 10, 10, 10)), + LalaShellAction::MarginChange((unit.upper, 10, 10, 10)), ) .into(), )); @@ -582,7 +582,7 @@ impl MultiApplication for LalaMusicBar { commands.push(Command::single( LaLaShellIdAction::new( *id, - LalaShellAction::MarginChange((unit.uper, 10, 10, 10)), + LalaShellAction::MarginChange((unit.upper, 10, 10, 10)), ) .into(), )); @@ -597,18 +597,18 @@ impl MultiApplication for LalaMusicBar { .notifications .iter() .find(|(oid, _)| **oid == id) - .map(|(_, info)| info.uper) + .map(|(_, info)| info.upper) .unwrap_or(0); let mut commands = vec![]; for (id, unit) in self.notifications.iter_mut() { - if unit.uper > removed_pos { - unit.uper -= 75; + if unit.upper > removed_pos { + unit.upper -= 75; } commands.push(Command::single( LaLaShellIdAction::new( *id, - LalaShellAction::MarginChange((unit.uper, 10, 10, 10)), + LalaShellAction::MarginChange((unit.upper, 10, 10, 10)), ) .into(), )); diff --git a/notification_iced/src/lib.rs b/notification_iced/src/lib.rs index 14ec457..81c0e43 100644 --- a/notification_iced/src/lib.rs +++ b/notification_iced/src/lib.rs @@ -62,7 +62,7 @@ pub struct VersionInfo { #[derive(Debug)] pub struct LaLaMako + Send> { - capablities: Vec, + capabilities: Vec, sender: Sender, version: VersionInfo, } @@ -86,7 +86,7 @@ impl + Send + 'static> LaLaMako { /// GetCapabilities method fn get_capabilities(&self) -> Vec { - self.capablities.clone() + self.capabilities.clone() } /// GetServerInformation method @@ -155,7 +155,7 @@ impl + Send + 'static> LaLaMako { pub async fn start_server + Send + 'static>( sender: Sender, - capablities: Vec, + capabilities: Vec, version: VersionInfo, ) -> Never { let _conn = async { @@ -165,7 +165,7 @@ pub async fn start_server + Send + 'static>( "/org/freedesktop/Notifications", LaLaMako { sender, - capablities, + capabilities, version, }, )? From 397a4aa0be6db393d846c23216170783bd7b85a1 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sat, 10 Aug 2024 19:33:08 +0859 Subject: [PATCH 15/35] chore: update dep --- Cargo.lock | 6 +++--- lala_bar/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9c0d702..3ddfe09 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1672,7 +1672,7 @@ dependencies = [ [[package]] name = "iced_layershell" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop?branch=evdirectlyremoveshell#1cb6bbca6b8815fab34ea1cc921e5a5edc386cb5" +source = "git+https://github.com/waycrate/exwlshelleventloop#c138ea6c92ac0484133280f4f2c3476b677dfd6c" dependencies = [ "futures", "iced", @@ -1984,7 +1984,7 @@ dependencies = [ [[package]] name = "layershellev" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop?branch=evdirectlyremoveshell#1cb6bbca6b8815fab34ea1cc921e5a5edc386cb5" +source = "git+https://github.com/waycrate/exwlshelleventloop#c138ea6c92ac0484133280f4f2c3476b677dfd6c" dependencies = [ "bitflags 2.6.0", "log", @@ -3966,7 +3966,7 @@ dependencies = [ [[package]] name = "waycrate_xkbkeycode" version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop?branch=evdirectlyremoveshell#1cb6bbca6b8815fab34ea1cc921e5a5edc386cb5" +source = "git+https://github.com/waycrate/exwlshelleventloop#c138ea6c92ac0484133280f4f2c3476b677dfd6c" dependencies = [ "bitflags 2.6.0", "log", diff --git a/lala_bar/Cargo.toml b/lala_bar/Cargo.toml index 8f642f4..d0574f4 100644 --- a/lala_bar/Cargo.toml +++ b/lala_bar/Cargo.toml @@ -15,7 +15,7 @@ iced = { version = "0.12", features = [ ] } #iced_native = "0.12" iced_runtime = "0.12" -iced_layershell = { git = "https://github.com/waycrate/exwlshelleventloop", package = "iced_layershell", branch = "evdirectlyremoveshell" } +iced_layershell = { git = "https://github.com/waycrate/exwlshelleventloop", package = "iced_layershell" } tokio = { version = "1.39", features = ["full"] } iced_futures = "0.12.0" env_logger = "0.11.5" From 4f2ec3efc7fa67118ad473e5ca708b853b91b729 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sat, 10 Aug 2024 22:27:29 +0859 Subject: [PATCH 16/35] chore: finish base notifications --- Cargo.lock | 15 ++++--- lala_bar/Cargo.toml | 2 +- lala_bar/src/main.rs | 77 ++++++++++++++++++++++++++++++++++-- notification_iced/src/lib.rs | 52 ++++++++++++++---------- 4 files changed, 115 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3ddfe09..541305b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1671,8 +1671,9 @@ dependencies = [ [[package]] name = "iced_layershell" -version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#c138ea6c92ac0484133280f4f2c3476b677dfd6c" +version = "0.4.0-rc2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14e6c5f891c16ffe49e91536cfb5137e5e238ab24e1ca00a00ccc5d9b11b55f6" dependencies = [ "futures", "iced", @@ -1983,8 +1984,9 @@ dependencies = [ [[package]] name = "layershellev" -version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#c138ea6c92ac0484133280f4f2c3476b677dfd6c" +version = "0.4.0-rc2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a1a001a0e54ef546500906c620bb276f1dfcce805bfe3fd149ee6d4fffe0c77" dependencies = [ "bitflags 2.6.0", "log", @@ -3965,8 +3967,9 @@ dependencies = [ [[package]] name = "waycrate_xkbkeycode" -version = "0.4.0-rc1" -source = "git+https://github.com/waycrate/exwlshelleventloop#c138ea6c92ac0484133280f4f2c3476b677dfd6c" +version = "0.4.0-rc2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a08710583549f4417a86f39be2237cd10d2e5cd7b22e3dc519e0fee3ef7ba37" dependencies = [ "bitflags 2.6.0", "log", diff --git a/lala_bar/Cargo.toml b/lala_bar/Cargo.toml index d0574f4..ae500d5 100644 --- a/lala_bar/Cargo.toml +++ b/lala_bar/Cargo.toml @@ -15,7 +15,7 @@ iced = { version = "0.12", features = [ ] } #iced_native = "0.12" iced_runtime = "0.12" -iced_layershell = { git = "https://github.com/waycrate/exwlshelleventloop", package = "iced_layershell" } +iced_layershell = "0.4.0-rc2" tokio = { version = "1.39", features = ["full"] } iced_futures = "0.12.0" env_logger = "0.11.5" diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index d3ac3fb..8c96a1d 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -1,5 +1,7 @@ use std::collections::HashMap; +use futures::future::pending; +use futures::StreamExt; use iced::widget::{button, column, container, image, row, slider, svg, text, Space}; use iced::{executor, Font}; use iced::{Command, Element, Length, Theme}; @@ -7,7 +9,10 @@ use iced_layershell::actions::{ LayershellCustomActionsWithIdAndInfo, LayershellCustomActionsWithInfo, }; use launcher::{LaunchMessage, Launcher}; -use notification_iced::{start_server, NotifyMessage, NotifyUnit, VersionInfo}; +use notification_iced::{ + start_connection, LaLaMako, NotifyMessage, NotifyUnit, VersionInfo, DEFAULT_ACTION, + NOTIFICATION_SERVICE_PATH, +}; use zbus_mpirs::ServiceInfo; use iced_layershell::reexport::{Anchor, KeyboardInteractivity, Layer, NewLayerShellSettings}; @@ -16,6 +21,12 @@ use iced_layershell::MultiApplication; use iced_runtime::command::Action; use iced_runtime::window::Action as WindowAction; +use futures::channel::mpsc::{channel, Receiver, Sender}; + +use tokio::sync::Mutex; + +use std::sync::Arc; + mod aximer; mod launcher; mod zbus_mpirs; @@ -55,7 +66,13 @@ struct NotifyUnitWidgetInfo { unit: NotifyUnit, } -#[derive(Default)] +#[allow(unused)] +#[derive(Debug)] +enum NotifyCommand { + ActionInvoked { id: u32, action_key: String }, + NotificationClosed { id: u32, reason: u32 }, +} + struct LalaMusicBar { service_data: Option, left: i64, @@ -64,6 +81,8 @@ struct LalaMusicBar { launcher: Option, launcherid: Option, notifications: HashMap, + sender: Sender, + receiver: Arc>>, } #[derive(Copy, Clone, Default)] @@ -354,6 +373,7 @@ impl MultiApplication for LalaMusicBar { type WindowInfo = LaLaInfo; fn new(_flags: Self::Flags) -> (Self, Command) { + let (sender, receiver) = channel::(100); ( Self { service_data: None, @@ -363,6 +383,8 @@ impl MultiApplication for LalaMusicBar { launcher: None, launcherid: None, notifications: HashMap::new(), + sender, + receiver: Arc::new(Mutex::new(receiver)), }, Command::perform(get_metadata_initial(), Message::DBusInfoUpdate), ) @@ -593,6 +615,13 @@ impl MultiApplication for LalaMusicBar { return Command::batch(commands); } Message::RemoveNotify(id) => { + let NotifyUnit { id: notify_id, .. } = self.notifications.get(&id).unwrap().unit; + self.sender + .try_send(NotifyCommand::ActionInvoked { + id: notify_id, + action_key: DEFAULT_ACTION.to_string(), + }) + .ok(); let removed_pos = self .notifications .iter() @@ -670,14 +699,16 @@ impl MultiApplication for LalaMusicBar { } fn subscription(&self) -> iced::Subscription { + let rv = self.receiver.clone(); iced::subscription::Subscription::batch([ iced::time::every(std::time::Duration::from_secs(1)) .map(|_| Message::RequestDBusInfoUpdate), iced::time::every(std::time::Duration::from_secs(5)).map(|_| Message::UpdateBalance), iced::event::listen() .map(|event| Message::LauncherInfo(LaunchMessage::IcedEvent(event))), - iced::subscription::channel(std::any::TypeId::of::<()>(), 100, |sender| async { - start_server( + iced::subscription::channel(std::any::TypeId::of::<()>(), 100, |sender| async move { + let mut receiver = rv.lock().await; + let Ok(connection) = start_connection( sender, vec![ "body".to_owned(), @@ -695,6 +726,44 @@ impl MultiApplication for LalaMusicBar { }, ) .await + else { + pending::<()>().await; + unreachable!() + }; + type LaLaMakoMusic = LaLaMako; + let Ok(lalaref) = connection + .object_server() + .interface::<_, LaLaMakoMusic>(NOTIFICATION_SERVICE_PATH) + .await + else { + pending::<()>().await; + unreachable!() + }; + + while let Some(cmd) = receiver.next().await { + match cmd { + NotifyCommand::ActionInvoked { id, action_key } => { + LaLaMakoMusic::action_invoked( + lalaref.signal_context(), + id, + &action_key, + ) + .await + .ok(); + } + NotifyCommand::NotificationClosed { id, reason } => { + LaLaMakoMusic::notification_closed( + lalaref.signal_context(), + id, + reason, + ) + .await + .ok(); + } + } + } + pending::<()>().await; + unreachable!() }), ]) } diff --git a/notification_iced/src/lib.rs b/notification_iced/src/lib.rs index 81c0e43..4ef0c5f 100644 --- a/notification_iced/src/lib.rs +++ b/notification_iced/src/lib.rs @@ -75,7 +75,7 @@ impl + Send + 'static> LaLaMako { #[zbus(signal_context)] ctx: SignalContext<'_>, id: u32, ) -> zbus::fdo::Result<()> { - self.notification_closed(&ctx, id, NOTIFICATION_DELETED_BY_USER) + Self::notification_closed(&ctx, id, NOTIFICATION_DELETED_BY_USER) .await .ok(); self.sender @@ -136,8 +136,7 @@ impl + Send + 'static> LaLaMako { } #[zbus(signal)] - async fn action_invoked( - &self, + pub async fn action_invoked( ctx: &SignalContext<'_>, id: u32, action_key: &str, @@ -145,34 +144,47 @@ impl + Send + 'static> LaLaMako { // NotificationClosed signal #[zbus(signal)] - async fn notification_closed( - &self, + pub async fn notification_closed( ctx: &SignalContext<'_>, id: u32, reason: u32, ) -> zbus::Result<()>; } +pub const NOTIFICATION_SERVICE_PATH: &str = "/org/freedesktop/Notifications"; +pub const NOTIFICATION_SERVICE_NAME: &str = "/org/freedesktop/Notifications"; +pub const NOTIFICATION_SERVICE_INTERFACE: &str = "/org/freedesktop/Notifications"; + +pub const ACTION_INVOKED: &str = "action_invoked"; +pub const NOTIFICATION_CLOSED: &str = "notification_closed"; + +pub const DEFAULT_ACTION: &str = "default"; + +pub async fn start_connection + Send + 'static>( + sender: Sender, + capabilities: Vec, + version: VersionInfo, +) -> Result { + ConnectionBuilder::session()? + .name("org.freedesktop.Notifications")? + .serve_at( + "/org/freedesktop/Notifications", + LaLaMako { + sender, + capabilities, + version, + }, + )? + .build() + .await +} + pub async fn start_server + Send + 'static>( sender: Sender, capabilities: Vec, version: VersionInfo, ) -> Never { - let _conn = async { - ConnectionBuilder::session()? - .name("org.freedesktop.Notifications")? - .serve_at( - "/org/freedesktop/Notifications", - LaLaMako { - sender, - capabilities, - version, - }, - )? - .build() - .await - } - .await; + let _conn = start_connection(sender, capabilities, version).await; pending::<()>().await; From 0da36f4a6180b884fb7f2dce9d61908a2b291fc8 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sat, 10 Aug 2024 22:41:25 +0859 Subject: [PATCH 17/35] chore: use git deps --- Cargo.lock | 9 +++------ lala_bar/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 541305b..a20fc5a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1672,8 +1672,7 @@ dependencies = [ [[package]] name = "iced_layershell" version = "0.4.0-rc2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e6c5f891c16ffe49e91536cfb5137e5e238ab24e1ca00a00ccc5d9b11b55f6" +source = "git+https://github.com/waycrate/exwlshelleventloop#b6b1caf6271fba6196d11d264fee64cccc20c386" dependencies = [ "futures", "iced", @@ -1985,8 +1984,7 @@ dependencies = [ [[package]] name = "layershellev" version = "0.4.0-rc2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a1a001a0e54ef546500906c620bb276f1dfcce805bfe3fd149ee6d4fffe0c77" +source = "git+https://github.com/waycrate/exwlshelleventloop#b6b1caf6271fba6196d11d264fee64cccc20c386" dependencies = [ "bitflags 2.6.0", "log", @@ -3968,8 +3966,7 @@ dependencies = [ [[package]] name = "waycrate_xkbkeycode" version = "0.4.0-rc2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a08710583549f4417a86f39be2237cd10d2e5cd7b22e3dc519e0fee3ef7ba37" +source = "git+https://github.com/waycrate/exwlshelleventloop#b6b1caf6271fba6196d11d264fee64cccc20c386" dependencies = [ "bitflags 2.6.0", "log", diff --git a/lala_bar/Cargo.toml b/lala_bar/Cargo.toml index ae500d5..d0574f4 100644 --- a/lala_bar/Cargo.toml +++ b/lala_bar/Cargo.toml @@ -15,7 +15,7 @@ iced = { version = "0.12", features = [ ] } #iced_native = "0.12" iced_runtime = "0.12" -iced_layershell = "0.4.0-rc2" +iced_layershell = { git = "https://github.com/waycrate/exwlshelleventloop", package = "iced_layershell" } tokio = { version = "1.39", features = ["full"] } iced_futures = "0.12.0" env_logger = "0.11.5" From 64b605b3eb098c72122bc3f894f4af9c5d55dac3 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sat, 10 Aug 2024 23:35:52 +0859 Subject: [PATCH 18/35] chore: support inline-reply --- lala_bar/src/main.rs | 80 ++++++++++++++++++++++++++++++++++-- notification_iced/src/lib.rs | 20 ++++++++- 2 files changed, 95 insertions(+), 5 deletions(-) diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index 8c96a1d..1eba72f 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use futures::future::pending; use futures::StreamExt; -use iced::widget::{button, column, container, image, row, slider, svg, text, Space}; +use iced::widget::{button, column, container, image, row, slider, svg, text, text_input, Space}; use iced::{executor, Font}; use iced::{Command, Element, Length, Theme}; use iced_layershell::actions::{ @@ -63,6 +63,7 @@ enum LaLaInfo { struct NotifyUnitWidgetInfo { upper: i32, counter: usize, + inline_reply: String, unit: NotifyUnit, } @@ -70,6 +71,7 @@ struct NotifyUnitWidgetInfo { #[derive(Debug)] enum NotifyCommand { ActionInvoked { id: u32, action_key: String }, + InlineReply { id: u32, text: String }, NotificationClosed { id: u32, reason: u32 }, } @@ -212,6 +214,8 @@ enum Message { LauncherInfo(LaunchMessage), Notify(NotifyMessage), RemoveNotify(iced::window::Id), + InlineReply((iced::window::Id, u32, String)), + InlineReplyMsgUpdate((iced::window::Id, String)), CheckOutput, } @@ -416,6 +420,7 @@ impl MultiApplication for LalaMusicBar { .or_insert(NotifyUnitWidgetInfo { counter: 0, upper: 10, + inline_reply: String::new(), unit: nofify, }); } @@ -569,7 +574,7 @@ impl MultiApplication for LalaMusicBar { anchor: Anchor::Right | Anchor::Top, layer: Layer::Top, margin: Some((10, 10, 10, 10)), - keyboard_interactivity: KeyboardInteractivity::None, + keyboard_interactivity: KeyboardInteractivity::OnDemand, use_last_output: true, }, LaLaInfo::Notify(notify), @@ -671,6 +676,44 @@ impl MultiApplication for LalaMusicBar { } } } + Message::InlineReply((id, notify_id, text)) => { + self.sender + .try_send(NotifyCommand::InlineReply { + id: notify_id, + text, + }) + .ok(); + let removed_pos = self + .notifications + .iter() + .find(|(oid, _)| **oid == id) + .map(|(_, info)| info.upper) + .unwrap_or(0); + + let mut commands = vec![]; + for (id, unit) in self.notifications.iter_mut() { + if unit.upper > removed_pos { + unit.upper -= 75; + } + commands.push(Command::single( + LaLaShellIdAction::new( + *id, + LalaShellAction::MarginChange((unit.upper, 10, 10, 10)), + ) + .into(), + )); + } + commands.append(&mut vec![ + Command::single(Action::Window(WindowAction::Close(id))), + Command::perform(async {}, |_| Message::CheckOutput), + ]); + + return Command::batch(commands); + } + Message::InlineReplyMsgUpdate((id, msg)) => { + let notify = self.notifications.get_mut(&id).unwrap(); + notify.inline_reply = msg; + } } Command::none() } @@ -684,14 +727,33 @@ impl MultiApplication for LalaMusicBar { } } LaLaInfo::Notify(notify) => { - return button(column![ + let btnwidgets: Element = button(row![ text(notify.summery.clone()).shaping(text::Shaping::Advanced), text(notify.body.clone()).shaping(text::Shaping::Advanced) ]) .width(Length::Fill) .height(Length::Fill) .on_press(Message::RemoveNotify(id)) - .into() + .into(); + let notifywidget = self.notifications.get(&id).unwrap(); + if notify.inline_reply_support() { + return column![ + btnwidgets, + Space::with_height(5.), + row![ + text_input("reply something", ¬ifywidget.inline_reply).on_input( + move |msg| Message::InlineReplyMsgUpdate((id.clone(), msg)) + ), + button("send").on_press(Message::InlineReply(( + id, + notify.id, + notifywidget.inline_reply.clone() + ))), + ] + ] + .into(); + } + return btnwidgets; } } } @@ -717,6 +779,7 @@ impl MultiApplication for LalaMusicBar { "icon-static".to_owned(), "x-canonical-private-synchronous".to_owned(), "x-dunst-stack-tag".to_owned(), + "inline-reply".to_owned(), ], VersionInfo { name: "LaLaMako".to_owned(), @@ -751,6 +814,15 @@ impl MultiApplication for LalaMusicBar { .await .ok(); } + NotifyCommand::InlineReply { id, text } => { + LaLaMakoMusic::notification_replied( + lalaref.signal_context(), + id, + &text, + ) + .await + .ok(); + } NotifyCommand::NotificationClosed { id, reason } => { LaLaMakoMusic::notification_closed( lalaref.signal_context(), diff --git a/notification_iced/src/lib.rs b/notification_iced/src/lib.rs index 4ef0c5f..ffbb258 100644 --- a/notification_iced/src/lib.rs +++ b/notification_iced/src/lib.rs @@ -41,6 +41,9 @@ pub enum NotifyMessage { UnitRemove(u32), } +#[derive(Debug, Clone)] +pub struct NotifyHint {} + #[derive(Debug, Clone)] pub struct NotifyUnit { pub app_name: String, @@ -50,6 +53,13 @@ pub struct NotifyUnit { pub body: String, pub actions: Vec, pub timeout: i32, + pub hint: NotifyHint, +} + +impl NotifyUnit { + pub fn inline_reply_support(&self) -> bool { + self.actions.contains(&"inline-reply".to_owned()) + } } #[derive(Debug, Clone)] @@ -115,7 +125,7 @@ impl + Send + 'static> LaLaMako { summery: &str, body: &str, actions: Vec<&str>, - _hints: std::collections::HashMap<&str, OwnedValue>, + mut hints: std::collections::HashMap<&str, OwnedValue>, timeout: i32, ) -> zbus::fdo::Result { self.sender @@ -128,6 +138,7 @@ impl + Send + 'static> LaLaMako { body: body.to_string(), actions: actions.iter().map(|a| a.to_string()).collect(), timeout, + hint: NotifyHint {}, }) .into(), ) @@ -142,6 +153,13 @@ impl + Send + 'static> LaLaMako { action_key: &str, ) -> zbus::Result<()>; + #[zbus(signal)] + pub async fn notification_replied( + ctx: &SignalContext<'_>, + id: u32, + text: &str, + ) -> zbus::Result<()>; + // NotificationClosed signal #[zbus(signal)] pub async fn notification_closed( From 7e88e904bab7a9db2d01b5a1e4296c49bb35be93 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sat, 10 Aug 2024 23:43:45 +0859 Subject: [PATCH 19/35] feat: better inline reply --- lala_bar/src/main.rs | 25 ++++++++++++++++--------- notification_iced/src/lib.rs | 2 +- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index 1eba72f..f2de210 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -361,7 +361,7 @@ impl LalaMusicBar { for (_, unit) in self.notifications.iter_mut() { if unit.counter > counter { unit.counter -= 1; - unit.upper -= 75; + unit.upper -= 135; } } } @@ -554,7 +554,7 @@ impl MultiApplication for LalaMusicBar { Message::Notify(NotifyMessage::UnitAdd(notify)) => { let mut commands = vec![]; for (id, unit) in self.notifications.iter_mut() { - unit.upper += 75; + unit.upper += 135; commands.push(Command::single( LaLaShellIdAction::new( *id, @@ -569,7 +569,7 @@ impl MultiApplication for LalaMusicBar { iced::window::Id::MAIN, LalaShellAction::NewLayerShell(( NewLayerShellSettings { - size: Some((300, 70)), + size: Some((300, 130)), exclusive_zone: None, anchor: Anchor::Right | Anchor::Top, layer: Layer::Top, @@ -637,7 +637,7 @@ impl MultiApplication for LalaMusicBar { let mut commands = vec![]; for (id, unit) in self.notifications.iter_mut() { if unit.upper > removed_pos { - unit.upper -= 75; + unit.upper -= 135; } commands.push(Command::single( LaLaShellIdAction::new( @@ -693,7 +693,7 @@ impl MultiApplication for LalaMusicBar { let mut commands = vec![]; for (id, unit) in self.notifications.iter_mut() { if unit.upper > removed_pos { - unit.upper -= 75; + unit.upper -= 135; } commands.push(Command::single( LaLaShellIdAction::new( @@ -727,7 +727,7 @@ impl MultiApplication for LalaMusicBar { } } LaLaInfo::Notify(notify) => { - let btnwidgets: Element = button(row![ + let btnwidgets: Element = button(column![ text(notify.summery.clone()).shaping(text::Shaping::Advanced), text(notify.body.clone()).shaping(text::Shaping::Advanced) ]) @@ -741,9 +741,16 @@ impl MultiApplication for LalaMusicBar { btnwidgets, Space::with_height(5.), row![ - text_input("reply something", ¬ifywidget.inline_reply).on_input( - move |msg| Message::InlineReplyMsgUpdate((id.clone(), msg)) - ), + text_input("reply something", ¬ifywidget.inline_reply) + .on_input(move |msg| Message::InlineReplyMsgUpdate(( + id.clone(), + msg + ))) + .on_submit(Message::InlineReply(( + id, + notify.id, + notifywidget.inline_reply.clone() + ))), button("send").on_press(Message::InlineReply(( id, notify.id, diff --git a/notification_iced/src/lib.rs b/notification_iced/src/lib.rs index ffbb258..68064ec 100644 --- a/notification_iced/src/lib.rs +++ b/notification_iced/src/lib.rs @@ -125,7 +125,7 @@ impl + Send + 'static> LaLaMako { summery: &str, body: &str, actions: Vec<&str>, - mut hints: std::collections::HashMap<&str, OwnedValue>, + _hints: std::collections::HashMap<&str, OwnedValue>, timeout: i32, ) -> zbus::fdo::Result { self.sender From ee8d2ce8843b9964093d9c0ffe068e2dcf47d217 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sun, 11 Aug 2024 00:14:46 +0859 Subject: [PATCH 20/35] chore: handle image --- lala_bar/src/zbus_mpirs.rs | 1 - notification_iced/src/lib.rs | 37 +++++++++++++++++++++++++----------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/lala_bar/src/zbus_mpirs.rs b/lala_bar/src/zbus_mpirs.rs index 14de217..4b6c01e 100644 --- a/lala_bar/src/zbus_mpirs.rs +++ b/lala_bar/src/zbus_mpirs.rs @@ -376,7 +376,6 @@ pub async fn init_mpirs() -> Result<()> { .await .ok(); } - //println!("name: {:?}", get_mpirs_connections().await); } Ok::<(), anyhow::Error>(()) }); diff --git a/notification_iced/src/lib.rs b/notification_iced/src/lib.rs index 68064ec..8fc2a95 100644 --- a/notification_iced/src/lib.rs +++ b/notification_iced/src/lib.rs @@ -19,21 +19,32 @@ //! //! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html //! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, +use serde::{Deserialize, Serialize}; use zbus::{interface, object_server::SignalContext, zvariant::OwnedValue}; use futures::{channel::mpsc::Sender, never::Never}; use zbus::ConnectionBuilder; -use std::future::pending; +use zbus::zvariant::{SerializeDict, Type}; -#[allow(unused)] -const NOTIFICATION_DELETED_BY_EXPIRED: u32 = 1; -const NOTIFICATION_DELETED_BY_USER: u32 = 2; +use std::future::pending; -#[allow(unused)] -const NOTIFICATION_CLOSED_BY_DBUS: u32 = 3; -#[allow(unused)] -const NOTIFICATION_CLOSED_BY_UNKNOWN_REASON: u32 = 4; +pub const NOTIFICATION_DELETED_BY_EXPIRED: u32 = 1; +pub const NOTIFICATION_DELETED_BY_USER: u32 = 2; + +pub const NOTIFICATION_CLOSED_BY_DBUS: u32 = 3; +pub const NOTIFICATION_CLOSED_BY_UNKNOWN_REASON: u32 = 4; + +#[derive(Type, Debug, SerializeDict, OwnedValue, Clone)] +pub struct ImageData { + width: i32, + height: i32, + rowstride: i32, + has_alpha: bool, + bits_per_sample: i32, + channels: i32, + data: Vec, +} #[derive(Debug, Clone)] pub enum NotifyMessage { @@ -42,7 +53,9 @@ pub enum NotifyMessage { } #[derive(Debug, Clone)] -pub struct NotifyHint {} +pub struct NotifyHint { + pub image_data: Option, +} #[derive(Debug, Clone)] pub struct NotifyUnit { @@ -125,9 +138,11 @@ impl + Send + 'static> LaLaMako { summery: &str, body: &str, actions: Vec<&str>, - _hints: std::collections::HashMap<&str, OwnedValue>, + mut hints: std::collections::HashMap<&str, OwnedValue>, timeout: i32, ) -> zbus::fdo::Result { + let image_data: Option = + hints.remove("image-data").and_then(|v| v.try_into().ok()); self.sender .try_send( NotifyMessage::UnitAdd(NotifyUnit { @@ -138,7 +153,7 @@ impl + Send + 'static> LaLaMako { body: body.to_string(), actions: actions.iter().map(|a| a.to_string()).collect(), timeout, - hint: NotifyHint {}, + hint: NotifyHint { image_data }, }) .into(), ) From b32fb38a8c312770bebb53d8b1f92a7f7ec22393 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sun, 11 Aug 2024 00:32:58 +0859 Subject: [PATCH 21/35] chore: nearly finished --- lala_bar/src/main.rs | 37 ++++++++++++++++++++++++++++-------- notification_iced/src/lib.rs | 11 +++++++++-- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index f2de210..ca6ce14 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -727,14 +727,35 @@ impl MultiApplication for LalaMusicBar { } } LaLaInfo::Notify(notify) => { - let btnwidgets: Element = button(column![ - text(notify.summery.clone()).shaping(text::Shaping::Advanced), - text(notify.body.clone()).shaping(text::Shaping::Advanced) - ]) - .width(Length::Fill) - .height(Length::Fill) - .on_press(Message::RemoveNotify(id)) - .into(); + let btnwidgets: Element = + if let Some((width, height, pixels)) = notify.hint.image_data() { + button(row![ + image(image::Handle::from_pixels( + width as u32, + height as u32, + pixels + )), + Space::with_width(4.), + column![ + text(notify.summery.clone()).shaping(text::Shaping::Advanced), + text(notify.body.clone()).shaping(text::Shaping::Advanced) + ] + ]) + .width(Length::Fill) + .height(Length::Fill) + .on_press(Message::RemoveNotify(id)) + .into() + } else { + button(column![ + text(notify.summery.clone()).shaping(text::Shaping::Advanced), + text(notify.body.clone()).shaping(text::Shaping::Advanced) + ]) + .width(Length::Fill) + .height(Length::Fill) + .on_press(Message::RemoveNotify(id)) + .into() + }; + let notifywidget = self.notifications.get(&id).unwrap(); if notify.inline_reply_support() { return column![ diff --git a/notification_iced/src/lib.rs b/notification_iced/src/lib.rs index 8fc2a95..e531dc5 100644 --- a/notification_iced/src/lib.rs +++ b/notification_iced/src/lib.rs @@ -19,7 +19,6 @@ //! //! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html //! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, -use serde::{Deserialize, Serialize}; use zbus::{interface, object_server::SignalContext, zvariant::OwnedValue}; use futures::{channel::mpsc::Sender, never::Never}; @@ -54,7 +53,15 @@ pub enum NotifyMessage { #[derive(Debug, Clone)] pub struct NotifyHint { - pub image_data: Option, + image_data: Option, +} + +impl NotifyHint { + pub fn image_data(&self) -> Option<(i32, i32, Vec)> { + self.image_data + .as_ref() + .map(|data| (data.width, data.height, data.data.clone())) + } } #[derive(Debug, Clone)] From a5cc649a1ac77bfb1445adc23d02f904514d0d6d Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sun, 11 Aug 2024 00:53:10 +0859 Subject: [PATCH 22/35] chore: code tidy --- notification_iced/src/lib.rs | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/notification_iced/src/lib.rs b/notification_iced/src/lib.rs index e531dc5..a98eb7e 100644 --- a/notification_iced/src/lib.rs +++ b/notification_iced/src/lib.rs @@ -21,13 +21,11 @@ //! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, use zbus::{interface, object_server::SignalContext, zvariant::OwnedValue}; -use futures::{channel::mpsc::Sender, never::Never}; +use futures::channel::mpsc::Sender; use zbus::ConnectionBuilder; use zbus::zvariant::{SerializeDict, Type}; -use std::future::pending; - pub const NOTIFICATION_DELETED_BY_EXPIRED: u32 = 1; pub const NOTIFICATION_DELETED_BY_USER: u32 = 2; @@ -218,15 +216,3 @@ pub async fn start_connection + Send + 'static>( .build() .await } - -pub async fn start_server + Send + 'static>( - sender: Sender, - capabilities: Vec, - version: VersionInfo, -) -> Never { - let _conn = start_connection(sender, capabilities, version).await; - - pending::<()>().await; - - unreachable!() -} From 186012aabce9fd16cd6d99afdd950478ec75cde7 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sun, 11 Aug 2024 11:22:33 +0859 Subject: [PATCH 23/35] fix: some time also need count down --- lala_bar/src/main.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index ca6ce14..fba8736 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -620,7 +620,11 @@ impl MultiApplication for LalaMusicBar { return Command::batch(commands); } Message::RemoveNotify(id) => { - let NotifyUnit { id: notify_id, .. } = self.notifications.get(&id).unwrap().unit; + let NotifyUnitWidgetInfo { + counter, + unit: NotifyUnit { id: notify_id, .. }, + .. + } = self.notifications.get(&id).unwrap().clone(); self.sender .try_send(NotifyCommand::ActionInvoked { id: notify_id, @@ -639,6 +643,9 @@ impl MultiApplication for LalaMusicBar { if unit.upper > removed_pos { unit.upper -= 135; } + if unit.counter > counter { + unit.counter -= 1; + } commands.push(Command::single( LaLaShellIdAction::new( *id, From 4325c9033ecbed1a1c2f522f72c75f194b963e66 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sun, 11 Aug 2024 12:27:28 +0859 Subject: [PATCH 24/35] feat: only show four notifications --- lala_bar/src/main.rs | 173 ++++++++++++++++++++++++++++++++----------- 1 file changed, 129 insertions(+), 44 deletions(-) diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index fba8736..2e3f618 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -56,7 +56,7 @@ pub fn main() -> Result<(), iced_layershell::Error> { #[derive(Debug, Clone)] enum LaLaInfo { Launcher, - Notify(NotifyUnit), + Notify(NotifyUnitWidgetInfo), } #[derive(Debug, Clone)] @@ -83,6 +83,7 @@ struct LalaMusicBar { launcher: Option, launcherid: Option, notifications: HashMap, + hided_notifications: Vec, sender: Sender, receiver: Arc>>, } @@ -349,26 +350,6 @@ impl LalaMusicBar { } } -impl LalaMusicBar { - fn counter_up(&mut self) { - for (_, unit) in self.notifications.iter_mut() { - unit.counter += 1; - } - } - fn counter_down(&mut self, ids: &Vec) { - for id in ids { - if let Some(NotifyUnitWidgetInfo { counter, .. }) = self.notifications.remove(id) { - for (_, unit) in self.notifications.iter_mut() { - if unit.counter > counter { - unit.counter -= 1; - unit.upper -= 135; - } - } - } - } - } -} - impl MultiApplication for LalaMusicBar { type Message = Message; type Flags = (); @@ -387,6 +368,7 @@ impl MultiApplication for LalaMusicBar { launcher: None, launcherid: None, notifications: HashMap::new(), + hided_notifications: Vec::new(), sender, receiver: Arc::new(Mutex::new(receiver)), }, @@ -402,9 +384,7 @@ impl MultiApplication for LalaMusicBar { if self.launcherid.is_some_and(|tid| tid == id) { Some(LaLaInfo::Launcher) } else { - self.notifications - .get(&id) - .map(|NotifyUnitWidgetInfo { unit, .. }| LaLaInfo::Notify(unit.clone())) + self.notifications.get(&id).cloned().map(LaLaInfo::Notify) } } @@ -413,16 +393,8 @@ impl MultiApplication for LalaMusicBar { LaLaInfo::Launcher => { self.launcherid = Some(id); } - LaLaInfo::Notify(nofify) => { - self.counter_up(); - self.notifications - .entry(id) - .or_insert(NotifyUnitWidgetInfo { - counter: 0, - upper: 10, - inline_reply: String::new(), - unit: nofify, - }); + LaLaInfo::Notify(notify) => { + self.notifications.entry(id).or_insert(notify); } } } @@ -553,15 +525,26 @@ impl MultiApplication for LalaMusicBar { } Message::Notify(NotifyMessage::UnitAdd(notify)) => { let mut commands = vec![]; + for unit in self.hided_notifications.iter_mut() { + unit.upper += 135; + unit.counter += 1; + } + for (id, unit) in self.notifications.iter_mut() { unit.upper += 135; - commands.push(Command::single( - LaLaShellIdAction::new( - *id, - LalaShellAction::MarginChange((unit.upper, 10, 10, 10)), - ) - .into(), - )); + unit.counter += 1; + if unit.counter > 3 { + self.hided_notifications.push(unit.clone()); + commands.push(Command::single(Action::Window(WindowAction::Close(*id)))); + } else { + commands.push(Command::single( + LaLaShellIdAction::new( + *id, + LalaShellAction::MarginChange((unit.upper, 10, 10, 10)), + ) + .into(), + )); + } } commands.push(Command::single( @@ -577,7 +560,12 @@ impl MultiApplication for LalaMusicBar { keyboard_interactivity: KeyboardInteractivity::OnDemand, use_last_output: true, }, - LaLaInfo::Notify(notify), + LaLaInfo::Notify(NotifyUnitWidgetInfo { + counter: 0, + upper: 10, + inline_reply: String::new(), + unit: notify, + }), )), ) .into(), @@ -604,7 +592,18 @@ impl MultiApplication for LalaMusicBar { .map(|(id, _)| Command::single(Action::Window(WindowAction::Close(*id)))) .collect(); - self.counter_down(&removed_ids); + for id in removed_ids.iter() { + if let Some(NotifyUnitWidgetInfo { counter, .. }) = + self.notifications.remove(id) + { + for (_, unit) in self.notifications.iter_mut() { + if unit.counter > counter { + unit.counter -= 1; + unit.upper -= 135; + } + } + } + } for (id, unit) in self.notifications.iter() { commands.push(Command::single( LaLaShellIdAction::new( @@ -615,6 +614,59 @@ impl MultiApplication for LalaMusicBar { )); } + let remove_hided_notifications_count: Vec = self + .hided_notifications + .iter() + .filter( + |NotifyUnitWidgetInfo { + unit: NotifyUnit { id, .. }, + .. + }| *id == removed_id, + ) + .map(|NotifyUnitWidgetInfo { counter, .. }| *counter) + .collect(); + + self.hided_notifications.retain( + |NotifyUnitWidgetInfo { + unit: NotifyUnit { id, .. }, + .. + }| *id == removed_id, + ); + + for count in remove_hided_notifications_count { + for unit in self.hided_notifications.iter_mut() { + if unit.counter > count { + unit.counter -= 1; + unit.upper -= 135; + } + } + } + for notify in self.hided_notifications.iter() { + if notify.counter <= 4 { + commands.push(Command::single( + LaLaShellIdAction::new( + iced::window::Id::MAIN, + LalaShellAction::NewLayerShell(( + NewLayerShellSettings { + size: Some((300, 130)), + exclusive_zone: None, + anchor: Anchor::Right | Anchor::Top, + layer: Layer::Top, + margin: Some((notify.upper, 10, 10, 10)), + keyboard_interactivity: KeyboardInteractivity::OnDemand, + use_last_output: true, + }, + LaLaInfo::Notify(notify.clone()), + )), + ) + .into(), + )); + } + } + + self.hided_notifications + .retain(|NotifyUnitWidgetInfo { counter, .. }| *counter > 4); + commands.push(Command::perform(async {}, |_| Message::CheckOutput)); return Command::batch(commands); @@ -654,6 +706,38 @@ impl MultiApplication for LalaMusicBar { .into(), )); } + + let mut to_show_id = None; + for (index, notify) in self.hided_notifications.iter_mut().enumerate() { + notify.counter -= 1; + notify.upper -= 135; + if notify.counter == 3 { + to_show_id = Some(index); + commands.push(Command::single( + LaLaShellIdAction::new( + iced::window::Id::MAIN, + LalaShellAction::NewLayerShell(( + NewLayerShellSettings { + size: Some((300, 130)), + exclusive_zone: None, + anchor: Anchor::Right | Anchor::Top, + layer: Layer::Top, + margin: Some((notify.upper, 10, 10, 10)), + keyboard_interactivity: KeyboardInteractivity::OnDemand, + use_last_output: true, + }, + LaLaInfo::Notify(notify.clone()), + )), + ) + .into(), + )); + } + } + + if let Some(index) = to_show_id { + self.hided_notifications.remove(index); + } + commands.append(&mut vec![ Command::single(Action::Window(WindowAction::Close(id))), Command::perform(async {}, |_| Message::CheckOutput), @@ -701,6 +785,7 @@ impl MultiApplication for LalaMusicBar { for (id, unit) in self.notifications.iter_mut() { if unit.upper > removed_pos { unit.upper -= 135; + unit.counter -= 1; } commands.push(Command::single( LaLaShellIdAction::new( @@ -733,7 +818,7 @@ impl MultiApplication for LalaMusicBar { return launcher.view(); } } - LaLaInfo::Notify(notify) => { + LaLaInfo::Notify(NotifyUnitWidgetInfo { unit: notify, .. }) => { let btnwidgets: Element = if let Some((width, height, pixels)) = notify.hint.image_data() { button(row![ From 05b10525294fe010d64ca78a20505e50bc5e0918 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sun, 11 Aug 2024 13:10:13 +0859 Subject: [PATCH 25/35] chore: with upstream fix --- Cargo.lock | 6 ++-- lala_bar/Cargo.toml | 2 +- lala_bar/src/main.rs | 83 ++++++++++++++++++++++++++++++++++++++------ 3 files changed, 76 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a20fc5a..19856f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1672,7 +1672,7 @@ dependencies = [ [[package]] name = "iced_layershell" version = "0.4.0-rc2" -source = "git+https://github.com/waycrate/exwlshelleventloop#b6b1caf6271fba6196d11d264fee64cccc20c386" +source = "git+https://github.com/waycrate/exwlshelleventloop?branch=mutiwindowcreate#c307d7f97a826577a4026c1a53c5619618c2110d" dependencies = [ "futures", "iced", @@ -1984,7 +1984,7 @@ dependencies = [ [[package]] name = "layershellev" version = "0.4.0-rc2" -source = "git+https://github.com/waycrate/exwlshelleventloop#b6b1caf6271fba6196d11d264fee64cccc20c386" +source = "git+https://github.com/waycrate/exwlshelleventloop?branch=mutiwindowcreate#c307d7f97a826577a4026c1a53c5619618c2110d" dependencies = [ "bitflags 2.6.0", "log", @@ -3966,7 +3966,7 @@ dependencies = [ [[package]] name = "waycrate_xkbkeycode" version = "0.4.0-rc2" -source = "git+https://github.com/waycrate/exwlshelleventloop#b6b1caf6271fba6196d11d264fee64cccc20c386" +source = "git+https://github.com/waycrate/exwlshelleventloop?branch=mutiwindowcreate#c307d7f97a826577a4026c1a53c5619618c2110d" dependencies = [ "bitflags 2.6.0", "log", diff --git a/lala_bar/Cargo.toml b/lala_bar/Cargo.toml index d0574f4..21bfe95 100644 --- a/lala_bar/Cargo.toml +++ b/lala_bar/Cargo.toml @@ -15,7 +15,7 @@ iced = { version = "0.12", features = [ ] } #iced_native = "0.12" iced_runtime = "0.12" -iced_layershell = { git = "https://github.com/waycrate/exwlshelleventloop", package = "iced_layershell" } +iced_layershell = { git = "https://github.com/waycrate/exwlshelleventloop", package = "iced_layershell", branch = "mutiwindowcreate" } tokio = { version = "1.39", features = ["full"] } iced_futures = "0.12.0" env_logger = "0.11.5" diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index 2e3f618..ee05b1e 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -34,6 +34,12 @@ mod zbus_mpirs; type LaLaShellIdAction = LayershellCustomActionsWithIdAndInfo; type LalaShellAction = LayershellCustomActionsWithInfo; +const BEGINNING_UP_MARGIN: i32 = 10; + +const UNIT_MARGIN: i32 = 135; + +const EXTRAINF_MARGIN: i32 = BEGINNING_UP_MARGIN + 4 * UNIT_MARGIN; + const LAUNCHER_SVG: &[u8] = include_bytes!("../../misc/launcher.svg"); const RESET_SVG: &[u8] = include_bytes!("../../misc/reset.svg"); @@ -57,6 +63,7 @@ pub fn main() -> Result<(), iced_layershell::Error> { enum LaLaInfo { Launcher, Notify(NotifyUnitWidgetInfo), + HidenInfo, } #[derive(Debug, Clone)] @@ -82,8 +89,9 @@ struct LalaMusicBar { bar_index: SliderIndex, launcher: Option, launcherid: Option, + hidenid: Option, notifications: HashMap, - hided_notifications: Vec, + hidded_notifications: Vec, sender: Sender, receiver: Arc>>, } @@ -367,8 +375,9 @@ impl MultiApplication for LalaMusicBar { bar_index: SliderIndex::Balance, launcher: None, launcherid: None, + hidenid: None, notifications: HashMap::new(), - hided_notifications: Vec::new(), + hidded_notifications: Vec::new(), sender, receiver: Arc::new(Mutex::new(receiver)), }, @@ -383,6 +392,8 @@ impl MultiApplication for LalaMusicBar { fn id_info(&self, id: iced::window::Id) -> Option { if self.launcherid.is_some_and(|tid| tid == id) { Some(LaLaInfo::Launcher) + } else if self.hidenid.is_some_and(|tid| tid == id) { + Some(LaLaInfo::HidenInfo) } else { self.notifications.get(&id).cloned().map(LaLaInfo::Notify) } @@ -396,6 +407,9 @@ impl MultiApplication for LalaMusicBar { LaLaInfo::Notify(notify) => { self.notifications.entry(id).or_insert(notify); } + LaLaInfo::HidenInfo => { + self.hidenid = Some(id); + } } } @@ -403,6 +417,9 @@ impl MultiApplication for LalaMusicBar { if self.launcherid.is_some_and(|lid| lid == id) { self.launcherid.take(); } + if self.hidenid.is_some_and(|lid| lid == id) { + self.hidenid.take(); + } self.notifications.remove(&id); } @@ -525,7 +542,7 @@ impl MultiApplication for LalaMusicBar { } Message::Notify(NotifyMessage::UnitAdd(notify)) => { let mut commands = vec![]; - for unit in self.hided_notifications.iter_mut() { + for unit in self.hidded_notifications.iter_mut() { unit.upper += 135; unit.counter += 1; } @@ -534,7 +551,7 @@ impl MultiApplication for LalaMusicBar { unit.upper += 135; unit.counter += 1; if unit.counter > 3 { - self.hided_notifications.push(unit.clone()); + self.hidded_notifications.push(unit.clone()); commands.push(Command::single(Action::Window(WindowAction::Close(*id)))); } else { commands.push(Command::single( @@ -570,6 +587,27 @@ impl MultiApplication for LalaMusicBar { ) .into(), )); + + if !self.hidded_notifications.is_empty() && self.hidenid.is_none() { + commands.push(Command::single( + LaLaShellIdAction::new( + iced::window::Id::MAIN, + LalaShellAction::NewLayerShell(( + NewLayerShellSettings { + size: Some((300, 25)), + exclusive_zone: None, + anchor: Anchor::Right | Anchor::Top, + layer: Layer::Top, + margin: Some((EXTRAINF_MARGIN, 10, 10, 10)), + keyboard_interactivity: KeyboardInteractivity::OnDemand, + use_last_output: true, + }, + LaLaInfo::HidenInfo, + )), + ) + .into(), + )); + } return Command::batch(commands); } Message::Notify(NotifyMessage::UnitRemove(removed_id)) => { @@ -615,7 +653,7 @@ impl MultiApplication for LalaMusicBar { } let remove_hided_notifications_count: Vec = self - .hided_notifications + .hidded_notifications .iter() .filter( |NotifyUnitWidgetInfo { @@ -626,7 +664,7 @@ impl MultiApplication for LalaMusicBar { .map(|NotifyUnitWidgetInfo { counter, .. }| *counter) .collect(); - self.hided_notifications.retain( + self.hidded_notifications.retain( |NotifyUnitWidgetInfo { unit: NotifyUnit { id, .. }, .. @@ -634,14 +672,14 @@ impl MultiApplication for LalaMusicBar { ); for count in remove_hided_notifications_count { - for unit in self.hided_notifications.iter_mut() { + for unit in self.hidded_notifications.iter_mut() { if unit.counter > count { unit.counter -= 1; unit.upper -= 135; } } } - for notify in self.hided_notifications.iter() { + for notify in self.hidded_notifications.iter() { if notify.counter <= 4 { commands.push(Command::single( LaLaShellIdAction::new( @@ -664,9 +702,17 @@ impl MultiApplication for LalaMusicBar { } } - self.hided_notifications + self.hidded_notifications .retain(|NotifyUnitWidgetInfo { counter, .. }| *counter > 4); + if self.hidded_notifications.is_empty() && self.hidenid.is_some() { + let hidenid = self.hidenid.unwrap(); + + commands.push(Command::single(Action::Window(WindowAction::Close( + hidenid, + )))); + } + commands.push(Command::perform(async {}, |_| Message::CheckOutput)); return Command::batch(commands); @@ -708,7 +754,7 @@ impl MultiApplication for LalaMusicBar { } let mut to_show_id = None; - for (index, notify) in self.hided_notifications.iter_mut().enumerate() { + for (index, notify) in self.hidded_notifications.iter_mut().enumerate() { notify.counter -= 1; notify.upper -= 135; if notify.counter == 3 { @@ -735,7 +781,15 @@ impl MultiApplication for LalaMusicBar { } if let Some(index) = to_show_id { - self.hided_notifications.remove(index); + self.hidded_notifications.remove(index); + } + + if self.hidded_notifications.is_empty() && self.hidenid.is_some() { + let hidenid = self.hidenid.unwrap(); + + commands.push(Command::single(Action::Window(WindowAction::Close( + hidenid, + )))); } commands.append(&mut vec![ @@ -875,6 +929,13 @@ impl MultiApplication for LalaMusicBar { } return btnwidgets; } + LaLaInfo::HidenInfo => { + return text(format!( + "hidden notifications {}", + self.hidded_notifications.len() + )) + .into(); + } } } self.main_view() From 5687f95afbe61bdbbccf43cee090ba519a42987e Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sun, 11 Aug 2024 13:19:19 +0859 Subject: [PATCH 26/35] chore: fix typos --- Cargo.lock | 46 ++++++++++++++++++++++---------------------- lala_bar/Cargo.toml | 2 +- lala_bar/src/main.rs | 40 +++++++++++++++++++------------------- 3 files changed, 44 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 19856f3..d5f3e14 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -235,9 +235,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.3" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" +checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" dependencies = [ "async-lock", "cfg-if", @@ -249,7 +249,7 @@ dependencies = [ "rustix", "slab", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -265,9 +265,9 @@ dependencies = [ [[package]] name = "async-process" -version = "2.2.3" +version = "2.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7eda79bbd84e29c2b308d1dc099d7de8dcc7035e48f4bf5dc4a531a44ff5e2a" +checksum = "a8a07789659a4d385b79b18b9127fc27e1a59e1e89117c78c5ea3b806f016374" dependencies = [ "async-channel", "async-io", @@ -280,7 +280,7 @@ dependencies = [ "futures-lite", "rustix", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -296,9 +296,9 @@ dependencies = [ [[package]] name = "async-signal" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb3634b73397aa844481f814fad23bbf07fdb0eabec10f2eb95e58944b1ec32" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" dependencies = [ "async-io", "async-lock", @@ -309,7 +309,7 @@ dependencies = [ "rustix", "signal-hook-registry", "slab", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -549,9 +549,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.8" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504bdec147f2cc13c8b57ed9401fd8a147cc66b67ad5cb241394244f2c947549" +checksum = "e9e8aabfac534be767c909e0690571677d49f41bd8465ae876fe043d52ba5292" dependencies = [ "jobserver", "libc", @@ -714,9 +714,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core-graphics" @@ -1672,7 +1672,7 @@ dependencies = [ [[package]] name = "iced_layershell" version = "0.4.0-rc2" -source = "git+https://github.com/waycrate/exwlshelleventloop?branch=mutiwindowcreate#c307d7f97a826577a4026c1a53c5619618c2110d" +source = "git+https://github.com/waycrate/exwlshelleventloop#45eab0a77407b66e80e3effe78f17065825602b7" dependencies = [ "futures", "iced", @@ -1984,7 +1984,7 @@ dependencies = [ [[package]] name = "layershellev" version = "0.4.0-rc2" -source = "git+https://github.com/waycrate/exwlshelleventloop?branch=mutiwindowcreate#c307d7f97a826577a4026c1a53c5619618c2110d" +source = "git+https://github.com/waycrate/exwlshelleventloop#45eab0a77407b66e80e3effe78f17065825602b7" dependencies = [ "bitflags 2.6.0", "log", @@ -2658,9 +2658,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", "fastrand", @@ -2688,9 +2688,9 @@ dependencies = [ [[package]] name = "polling" -version = "3.7.2" +version = "3.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" dependencies = [ "cfg-if", "concurrent-queue", @@ -2698,7 +2698,7 @@ dependencies = [ "pin-project-lite", "rustix", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3966,7 +3966,7 @@ dependencies = [ [[package]] name = "waycrate_xkbkeycode" version = "0.4.0-rc2" -source = "git+https://github.com/waycrate/exwlshelleventloop?branch=mutiwindowcreate#c307d7f97a826577a4026c1a53c5619618c2110d" +source = "git+https://github.com/waycrate/exwlshelleventloop#45eab0a77407b66e80e3effe78f17065825602b7" dependencies = [ "bitflags 2.6.0", "log", @@ -4641,9 +4641,9 @@ checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" [[package]] name = "xcursor" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d491ee231a51ae64a5b762114c3ac2104b967aadba1de45c86ca42cf051513b7" +checksum = "f513f231f0810b04d988f0df4fb16ef0b6b25d23248f2c4b56b074e6b1b0ffe4" [[package]] name = "xdg" diff --git a/lala_bar/Cargo.toml b/lala_bar/Cargo.toml index 21bfe95..d0574f4 100644 --- a/lala_bar/Cargo.toml +++ b/lala_bar/Cargo.toml @@ -15,7 +15,7 @@ iced = { version = "0.12", features = [ ] } #iced_native = "0.12" iced_runtime = "0.12" -iced_layershell = { git = "https://github.com/waycrate/exwlshelleventloop", package = "iced_layershell", branch = "mutiwindowcreate" } +iced_layershell = { git = "https://github.com/waycrate/exwlshelleventloop", package = "iced_layershell" } tokio = { version = "1.39", features = ["full"] } iced_futures = "0.12.0" env_logger = "0.11.5" diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index ee05b1e..89a225c 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -63,7 +63,7 @@ pub fn main() -> Result<(), iced_layershell::Error> { enum LaLaInfo { Launcher, Notify(NotifyUnitWidgetInfo), - HidenInfo, + HiddenInfo, } #[derive(Debug, Clone)] @@ -91,7 +91,7 @@ struct LalaMusicBar { launcherid: Option, hidenid: Option, notifications: HashMap, - hidded_notifications: Vec, + hidden_notifications: Vec, sender: Sender, receiver: Arc>>, } @@ -377,7 +377,7 @@ impl MultiApplication for LalaMusicBar { launcherid: None, hidenid: None, notifications: HashMap::new(), - hidded_notifications: Vec::new(), + hidden_notifications: Vec::new(), sender, receiver: Arc::new(Mutex::new(receiver)), }, @@ -393,7 +393,7 @@ impl MultiApplication for LalaMusicBar { if self.launcherid.is_some_and(|tid| tid == id) { Some(LaLaInfo::Launcher) } else if self.hidenid.is_some_and(|tid| tid == id) { - Some(LaLaInfo::HidenInfo) + Some(LaLaInfo::HiddenInfo) } else { self.notifications.get(&id).cloned().map(LaLaInfo::Notify) } @@ -407,7 +407,7 @@ impl MultiApplication for LalaMusicBar { LaLaInfo::Notify(notify) => { self.notifications.entry(id).or_insert(notify); } - LaLaInfo::HidenInfo => { + LaLaInfo::HiddenInfo => { self.hidenid = Some(id); } } @@ -542,7 +542,7 @@ impl MultiApplication for LalaMusicBar { } Message::Notify(NotifyMessage::UnitAdd(notify)) => { let mut commands = vec![]; - for unit in self.hidded_notifications.iter_mut() { + for unit in self.hidden_notifications.iter_mut() { unit.upper += 135; unit.counter += 1; } @@ -551,7 +551,7 @@ impl MultiApplication for LalaMusicBar { unit.upper += 135; unit.counter += 1; if unit.counter > 3 { - self.hidded_notifications.push(unit.clone()); + self.hidden_notifications.push(unit.clone()); commands.push(Command::single(Action::Window(WindowAction::Close(*id)))); } else { commands.push(Command::single( @@ -588,7 +588,7 @@ impl MultiApplication for LalaMusicBar { .into(), )); - if !self.hidded_notifications.is_empty() && self.hidenid.is_none() { + if !self.hidden_notifications.is_empty() && self.hidenid.is_none() { commands.push(Command::single( LaLaShellIdAction::new( iced::window::Id::MAIN, @@ -602,7 +602,7 @@ impl MultiApplication for LalaMusicBar { keyboard_interactivity: KeyboardInteractivity::OnDemand, use_last_output: true, }, - LaLaInfo::HidenInfo, + LaLaInfo::HiddenInfo, )), ) .into(), @@ -653,7 +653,7 @@ impl MultiApplication for LalaMusicBar { } let remove_hided_notifications_count: Vec = self - .hidded_notifications + .hidden_notifications .iter() .filter( |NotifyUnitWidgetInfo { @@ -664,7 +664,7 @@ impl MultiApplication for LalaMusicBar { .map(|NotifyUnitWidgetInfo { counter, .. }| *counter) .collect(); - self.hidded_notifications.retain( + self.hidden_notifications.retain( |NotifyUnitWidgetInfo { unit: NotifyUnit { id, .. }, .. @@ -672,14 +672,14 @@ impl MultiApplication for LalaMusicBar { ); for count in remove_hided_notifications_count { - for unit in self.hidded_notifications.iter_mut() { + for unit in self.hidden_notifications.iter_mut() { if unit.counter > count { unit.counter -= 1; unit.upper -= 135; } } } - for notify in self.hidded_notifications.iter() { + for notify in self.hidden_notifications.iter() { if notify.counter <= 4 { commands.push(Command::single( LaLaShellIdAction::new( @@ -702,10 +702,10 @@ impl MultiApplication for LalaMusicBar { } } - self.hidded_notifications + self.hidden_notifications .retain(|NotifyUnitWidgetInfo { counter, .. }| *counter > 4); - if self.hidded_notifications.is_empty() && self.hidenid.is_some() { + if self.hidden_notifications.is_empty() && self.hidenid.is_some() { let hidenid = self.hidenid.unwrap(); commands.push(Command::single(Action::Window(WindowAction::Close( @@ -754,7 +754,7 @@ impl MultiApplication for LalaMusicBar { } let mut to_show_id = None; - for (index, notify) in self.hidded_notifications.iter_mut().enumerate() { + for (index, notify) in self.hidden_notifications.iter_mut().enumerate() { notify.counter -= 1; notify.upper -= 135; if notify.counter == 3 { @@ -781,10 +781,10 @@ impl MultiApplication for LalaMusicBar { } if let Some(index) = to_show_id { - self.hidded_notifications.remove(index); + self.hidden_notifications.remove(index); } - if self.hidded_notifications.is_empty() && self.hidenid.is_some() { + if self.hidden_notifications.is_empty() && self.hidenid.is_some() { let hidenid = self.hidenid.unwrap(); commands.push(Command::single(Action::Window(WindowAction::Close( @@ -929,10 +929,10 @@ impl MultiApplication for LalaMusicBar { } return btnwidgets; } - LaLaInfo::HidenInfo => { + LaLaInfo::HiddenInfo => { return text(format!( "hidden notifications {}", - self.hidded_notifications.len() + self.hidden_notifications.len() )) .into(); } From a45f1220326abf3b66c90c8ce9958ecca9a84b6c Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sun, 11 Aug 2024 13:23:10 +0859 Subject: [PATCH 27/35] fix: hidden id reshown --- lala_bar/src/main.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index 89a225c..564d137 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -652,7 +652,7 @@ impl MultiApplication for LalaMusicBar { )); } - let remove_hided_notifications_count: Vec = self + let mut remove_hided_notifications_count: Vec = self .hidden_notifications .iter() .filter( @@ -663,6 +663,8 @@ impl MultiApplication for LalaMusicBar { ) .map(|NotifyUnitWidgetInfo { counter, .. }| *counter) .collect(); + remove_hided_notifications_count.sort(); + remove_hided_notifications_count.reverse(); self.hidden_notifications.retain( |NotifyUnitWidgetInfo { From eed298140b706e0c8f32b94b49726153b26c1b37 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sun, 11 Aug 2024 14:01:08 +0859 Subject: [PATCH 28/35] chore: base fix --- Cargo.lock | 6 +++--- lala_bar/src/main.rs | 25 +++++++++++++++++++------ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d5f3e14..0caf2df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1672,7 +1672,7 @@ dependencies = [ [[package]] name = "iced_layershell" version = "0.4.0-rc2" -source = "git+https://github.com/waycrate/exwlshelleventloop#45eab0a77407b66e80e3effe78f17065825602b7" +source = "git+https://github.com/waycrate/exwlshelleventloop#2eaba727a44b9562747c03cfb7364ea7762ef889" dependencies = [ "futures", "iced", @@ -1984,7 +1984,7 @@ dependencies = [ [[package]] name = "layershellev" version = "0.4.0-rc2" -source = "git+https://github.com/waycrate/exwlshelleventloop#45eab0a77407b66e80e3effe78f17065825602b7" +source = "git+https://github.com/waycrate/exwlshelleventloop#2eaba727a44b9562747c03cfb7364ea7762ef889" dependencies = [ "bitflags 2.6.0", "log", @@ -3966,7 +3966,7 @@ dependencies = [ [[package]] name = "waycrate_xkbkeycode" version = "0.4.0-rc2" -source = "git+https://github.com/waycrate/exwlshelleventloop#45eab0a77407b66e80e3effe78f17065825602b7" +source = "git+https://github.com/waycrate/exwlshelleventloop#2eaba727a44b9562747c03cfb7364ea7762ef889" dependencies = [ "bitflags 2.6.0", "log", diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index 564d137..e3ba203 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -630,18 +630,25 @@ impl MultiApplication for LalaMusicBar { .map(|(id, _)| Command::single(Action::Window(WindowAction::Close(*id)))) .collect(); + let mut removed_counters = vec![]; for id in removed_ids.iter() { if let Some(NotifyUnitWidgetInfo { counter, .. }) = self.notifications.remove(id) { - for (_, unit) in self.notifications.iter_mut() { - if unit.counter > counter { - unit.counter -= 1; - unit.upper -= 135; - } + removed_counters.push(counter); + } + } + removed_counters.sort(); + removed_counters.reverse(); + for counter in removed_counters { + for (_, unit) in self.notifications.iter_mut() { + if unit.counter > counter { + unit.counter -= 1; + unit.upper -= 135; } } } + for (id, unit) in self.notifications.iter() { commands.push(Command::single( LaLaShellIdAction::new( @@ -663,6 +670,12 @@ impl MultiApplication for LalaMusicBar { ) .map(|NotifyUnitWidgetInfo { counter, .. }| *counter) .collect(); + + if self.notifications.len() < 3 { + for index in 0..self.notifications.len() { + remove_hided_notifications_count.push(index); + } + } remove_hided_notifications_count.sort(); remove_hided_notifications_count.reverse(); @@ -670,7 +683,7 @@ impl MultiApplication for LalaMusicBar { |NotifyUnitWidgetInfo { unit: NotifyUnit { id, .. }, .. - }| *id == removed_id, + }| *id != removed_id, ); for count in remove_hided_notifications_count { From 5edb401daea0466eb5455dab9ebc05650d59d0f5 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sun, 11 Aug 2024 19:19:50 +0859 Subject: [PATCH 29/35] feat: support desktop icon --- Cargo.lock | 67 ++++++++++++---------- lala_bar/src/main.rs | 100 +++++++++++++++++++++++--------- notification_iced/Cargo.toml | 1 + notification_iced/src/lib.rs | 108 +++++++++++++++++++++++++++++++++-- 4 files changed, 214 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0caf2df..91d84e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -291,7 +291,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", ] [[package]] @@ -326,7 +326,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", ] [[package]] @@ -480,7 +480,7 @@ checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", ] [[package]] @@ -951,7 +951,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", ] [[package]] @@ -1151,7 +1151,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", ] [[package]] @@ -1239,7 +1239,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", ] [[package]] @@ -1409,7 +1409,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", ] [[package]] @@ -1422,6 +1422,12 @@ dependencies = [ "system-deps", ] +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "glow" version = "0.13.1" @@ -1672,7 +1678,7 @@ dependencies = [ [[package]] name = "iced_layershell" version = "0.4.0-rc2" -source = "git+https://github.com/waycrate/exwlshelleventloop#2eaba727a44b9562747c03cfb7364ea7762ef889" +source = "git+https://github.com/waycrate/exwlshelleventloop#3b1b2743818423e9fd57ef900da637d89f157d24" dependencies = [ "futures", "iced", @@ -1984,7 +1990,7 @@ dependencies = [ [[package]] name = "layershellev" version = "0.4.0-rc2" -source = "git+https://github.com/waycrate/exwlshelleventloop#2eaba727a44b9562747c03cfb7364ea7762ef889" +source = "git+https://github.com/waycrate/exwlshelleventloop#3b1b2743818423e9fd57ef900da637d89f157d24" dependencies = [ "bitflags 2.6.0", "log", @@ -2247,6 +2253,7 @@ version = "0.1.0" dependencies = [ "futures", "futures-util", + "glob", "serde", "url", "zbus", @@ -2299,7 +2306,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", ] [[package]] @@ -2527,7 +2534,7 @@ dependencies = [ "by_address", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", ] [[package]] @@ -2626,7 +2633,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", ] [[package]] @@ -3063,22 +3070,22 @@ checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" [[package]] name = "serde" -version = "1.0.205" +version = "1.0.206" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33aedb1a7135da52b7c21791455563facbbcc43d0f0f66165b42c21b3dfb150" +checksum = "5b3e4cd94123dd520a128bcd11e34d9e9e423e7e3e50425cb1b4b1e3549d0284" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.205" +version = "1.0.206" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692d6f5ac90220161d6774db30c662202721e64aed9058d2c394f451261420c1" +checksum = "fabfb6138d2383ea8208cf98ccf69cdfb1aff4088460681d84189aa259762f97" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", ] [[package]] @@ -3089,7 +3096,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", ] [[package]] @@ -3374,9 +3381,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.72" +version = "2.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "837a7e8026c6ce912ff01cefbe8cafc2f8010ac49682e2a3d9decc3bce1ecaaf" dependencies = [ "proc-macro2", "quote", @@ -3450,7 +3457,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", ] [[package]] @@ -3555,7 +3562,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", ] [[package]] @@ -3622,7 +3629,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", ] [[package]] @@ -3903,7 +3910,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", "wasm-bindgen-shared", ] @@ -3937,7 +3944,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3966,7 +3973,7 @@ dependencies = [ [[package]] name = "waycrate_xkbkeycode" version = "0.4.0-rc2" -source = "git+https://github.com/waycrate/exwlshelleventloop#2eaba727a44b9562747c03cfb7364ea7762ef889" +source = "git+https://github.com/waycrate/exwlshelleventloop#3b1b2743818423e9fd57ef900da637d89f157d24" dependencies = [ "bitflags 2.6.0", "log", @@ -4766,7 +4773,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", "zvariant_utils", ] @@ -4805,7 +4812,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", ] [[package]] @@ -4839,7 +4846,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", "zvariant_utils", ] @@ -4851,5 +4858,5 @@ checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.73", ] diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index e3ba203..b809576 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -10,7 +10,7 @@ use iced_layershell::actions::{ }; use launcher::{LaunchMessage, Launcher}; use notification_iced::{ - start_connection, LaLaMako, NotifyMessage, NotifyUnit, VersionInfo, DEFAULT_ACTION, + start_connection, ImageInfo, LaLaMako, NotifyMessage, NotifyUnit, VersionInfo, DEFAULT_ACTION, NOTIFICATION_SERVICE_PATH, }; use zbus_mpirs::ServiceInfo; @@ -888,34 +888,78 @@ impl MultiApplication for LalaMusicBar { } } LaLaInfo::Notify(NotifyUnitWidgetInfo { unit: notify, .. }) => { - let btnwidgets: Element = - if let Some((width, height, pixels)) = notify.hint.image_data() { - button(row![ - image(image::Handle::from_pixels( - width as u32, - height as u32, - pixels - )), - Space::with_width(4.), - column![ - text(notify.summery.clone()).shaping(text::Shaping::Advanced), - text(notify.body.clone()).shaping(text::Shaping::Advanced) - ] - ]) - .width(Length::Fill) - .height(Length::Fill) - .on_press(Message::RemoveNotify(id)) - .into() - } else { - button(column![ - text(notify.summery.clone()).shaping(text::Shaping::Advanced), + let btnwidgets: Element = match notify.image() { + Some(ImageInfo::Svg(path)) => button(row![ + svg(svg::Handle::from_path(path)).height(Length::Fill), + Space::with_width(4.), + column![ + text(notify.summery.clone()) + .shaping(text::Shaping::Advanced) + .size(20) + .font(Font { + weight: iced::font::Weight::Bold, + ..Default::default() + }), + text(notify.body.clone()).shaping(text::Shaping::Advanced) + ] + ]) + .width(Length::Fill) + .height(Length::Fill) + .on_press(Message::RemoveNotify(id)) + .into(), + Some(ImageInfo::Data { + width, + height, + pixels, + }) => button(row![ + image(image::Handle::from_pixels( + width as u32, + height as u32, + pixels + )), + Space::with_width(4.), + column![ + text(notify.summery.clone()) + .shaping(text::Shaping::Advanced) + .size(20) + .font(Font { + weight: iced::font::Weight::Bold, + ..Default::default() + }), text(notify.body.clone()).shaping(text::Shaping::Advanced) - ]) - .width(Length::Fill) - .height(Length::Fill) - .on_press(Message::RemoveNotify(id)) - .into() - }; + ] + ]) + .width(Length::Fill) + .height(Length::Fill) + .on_press(Message::RemoveNotify(id)) + .into(), + Some(ImageInfo::Png(path)) | Some(ImageInfo::Jpg(path)) => button(row![ + image(image::Handle::from_path(path)).height(Length::Fill), + Space::with_width(4.), + column![ + text(notify.summery.clone()) + .shaping(text::Shaping::Advanced) + .size(20) + .font(Font { + weight: iced::font::Weight::Bold, + ..Default::default() + }), + text(notify.body.clone()).shaping(text::Shaping::Advanced) + ] + ]) + .width(Length::Fill) + .height(Length::Fill) + .on_press(Message::RemoveNotify(id)) + .into(), + _ => button(column![ + text(notify.summery.clone()).shaping(text::Shaping::Advanced), + text(notify.body.clone()).shaping(text::Shaping::Advanced) + ]) + .width(Length::Fill) + .height(Length::Fill) + .on_press(Message::RemoveNotify(id)) + .into(), + }; let notifywidget = self.notifications.get(&id).unwrap(); if notify.inline_reply_support() { diff --git a/notification_iced/Cargo.toml b/notification_iced/Cargo.toml index 833c5ba..4f094fb 100644 --- a/notification_iced/Cargo.toml +++ b/notification_iced/Cargo.toml @@ -9,3 +9,4 @@ serde.workspace = true zbus.workspace = true futures-util.workspace = true url.workspace = true +glob = "0.3.1" diff --git a/notification_iced/src/lib.rs b/notification_iced/src/lib.rs index a98eb7e..164ae49 100644 --- a/notification_iced/src/lib.rs +++ b/notification_iced/src/lib.rs @@ -19,8 +19,14 @@ //! //! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html //! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, +use std::collections::HashMap; +use std::path::{Path, PathBuf}; + +use glob::glob; use zbus::{interface, object_server::SignalContext, zvariant::OwnedValue}; +use std::sync::{Arc, LazyLock, RwLock}; + use futures::channel::mpsc::Sender; use zbus::ConnectionBuilder; @@ -32,6 +38,9 @@ pub const NOTIFICATION_DELETED_BY_USER: u32 = 2; pub const NOTIFICATION_CLOSED_BY_DBUS: u32 = 3; pub const NOTIFICATION_CLOSED_BY_UNKNOWN_REASON: u32 = 4; +static ICON_CACHE: LazyLock>>> = + LazyLock::new(|| Arc::new(RwLock::new(HashMap::new()))); + #[derive(Type, Debug, SerializeDict, OwnedValue, Clone)] pub struct ImageData { width: i32, @@ -49,16 +58,79 @@ pub enum NotifyMessage { UnitRemove(u32), } +fn lazy_get_icon(icon: &str) -> Option { + let icon_cache = ICON_CACHE.read().unwrap(); + if icon.contains(icon) { + return icon_cache.get(icon).cloned(); + } + drop(icon_cache); + let mut icon_cache = ICON_CACHE.write().unwrap(); + if let Some(path) = get_svg_icon("hicolor", icon) { + icon_cache.insert(icon.to_string(), ImageInfo::Svg(path.clone())); + return Some(ImageInfo::Svg(path)); + } + if let Some(path) = get_png_icon("hicolor", icon) { + icon_cache.insert(icon.to_string(), ImageInfo::Png(path.clone())); + return Some(ImageInfo::Png(path)); + } + if let Some(path) = get_jpeg_icon("hicolor", icon) { + icon_cache.insert(icon.to_string(), ImageInfo::Jpg(path.clone())); + return Some(ImageInfo::Jpg(path)); + } + None +} + +fn get_svg_icon(theme: &str, icon: &str) -> Option { + glob(&format!("/usr/share/icons/{theme}/**/**/{icon}.svg")) + .ok()? + .next()? + .ok() +} + +fn get_png_icon(theme: &str, icon: &str) -> Option { + glob(&format!("/usr/share/icons/{theme}/**/**/{icon}.png")) + .ok()? + .next()? + .ok() +} + +fn get_jpeg_icon(theme: &str, icon: &str) -> Option { + glob(&format!("/usr/share/icons/{theme}/**/**/{icon}.jpg")) + .ok()? + .next()? + .ok() +} + #[derive(Debug, Clone)] pub struct NotifyHint { image_data: Option, + desktop_entry: Option, +} + +#[derive(Debug, Clone)] +pub enum ImageInfo { + Data { + width: i32, + height: i32, + pixels: Vec, + }, + Svg(PathBuf), + Png(PathBuf), + Jpg(PathBuf), } impl NotifyHint { - pub fn image_data(&self) -> Option<(i32, i32, Vec)> { - self.image_data + fn desktop_image(&self) -> Option { + self.desktop_entry .as_ref() - .map(|data| (data.width, data.height, data.data.clone())) + .and_then(|icon| lazy_get_icon(icon)) + } + fn hint_image(&self) -> Option { + self.image_data.as_ref().map(|data| ImageInfo::Data { + width: data.width, + height: data.height, + pixels: data.data.clone(), + }) } } @@ -78,6 +150,28 @@ impl NotifyUnit { pub fn inline_reply_support(&self) -> bool { self.actions.contains(&"inline-reply".to_owned()) } + + pub fn image(&self) -> Option { + if let Some(hint_image) = self.hint.hint_image() { + return Some(hint_image); + } + if !self.icon.is_empty() { + let path = Path::new(&self.icon); + if path.exists() { + if self.icon.ends_with("svg") { + return Some(ImageInfo::Svg(path.into())); + } else if self.icon.ends_with("jpg") { + return Some(ImageInfo::Jpg(path.into())); + } else { + return Some(ImageInfo::Png(path.into())); + } + } + if let Some(info) = lazy_get_icon(&self.icon) { + return Some(info); + } + } + self.hint.desktop_image() + } } #[derive(Debug, Clone)] @@ -148,6 +242,9 @@ impl + Send + 'static> LaLaMako { ) -> zbus::fdo::Result { let image_data: Option = hints.remove("image-data").and_then(|v| v.try_into().ok()); + let desktop_entry: Option = hints + .remove("desktop-entry") + .and_then(|v| v.try_into().ok()); self.sender .try_send( NotifyMessage::UnitAdd(NotifyUnit { @@ -158,7 +255,10 @@ impl + Send + 'static> LaLaMako { body: body.to_string(), actions: actions.iter().map(|a| a.to_string()).collect(), timeout, - hint: NotifyHint { image_data }, + hint: NotifyHint { + image_data, + desktop_entry, + }, }) .into(), ) From 09cc9bf56ff1faa90b824ecc2b735446c3316ed6 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sun, 11 Aug 2024 20:37:02 +0859 Subject: [PATCH 30/35] feat: support full hidden panel --- Cargo.lock | 6 +- lala_bar/src/main.rs | 310 ++++++++++++++++++++++++++++--------------- 2 files changed, 207 insertions(+), 109 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 91d84e6..189d31b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1678,7 +1678,7 @@ dependencies = [ [[package]] name = "iced_layershell" version = "0.4.0-rc2" -source = "git+https://github.com/waycrate/exwlshelleventloop#3b1b2743818423e9fd57ef900da637d89f157d24" +source = "git+https://github.com/waycrate/exwlshelleventloop#f64677fd8d31103192b4ba696f14aeda447c005b" dependencies = [ "futures", "iced", @@ -1990,7 +1990,7 @@ dependencies = [ [[package]] name = "layershellev" version = "0.4.0-rc2" -source = "git+https://github.com/waycrate/exwlshelleventloop#3b1b2743818423e9fd57ef900da637d89f157d24" +source = "git+https://github.com/waycrate/exwlshelleventloop#f64677fd8d31103192b4ba696f14aeda447c005b" dependencies = [ "bitflags 2.6.0", "log", @@ -3973,7 +3973,7 @@ dependencies = [ [[package]] name = "waycrate_xkbkeycode" version = "0.4.0-rc2" -source = "git+https://github.com/waycrate/exwlshelleventloop#3b1b2743818423e9fd57ef900da637d89f157d24" +source = "git+https://github.com/waycrate/exwlshelleventloop#f64677fd8d31103192b4ba696f14aeda447c005b" dependencies = [ "bitflags 2.6.0", "log", diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index b809576..585afe3 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -2,7 +2,9 @@ use std::collections::HashMap; use futures::future::pending; use futures::StreamExt; -use iced::widget::{button, column, container, image, row, slider, svg, text, text_input, Space}; +use iced::widget::{ + button, column, container, image, row, scrollable, slider, svg, text, text_input, Space, +}; use iced::{executor, Font}; use iced::{Command, Element, Length, Theme}; use iced_layershell::actions::{ @@ -64,6 +66,7 @@ enum LaLaInfo { Launcher, Notify(NotifyUnitWidgetInfo), HiddenInfo, + RightPanel, } #[derive(Debug, Clone)] @@ -74,6 +77,85 @@ struct NotifyUnitWidgetInfo { unit: NotifyUnit, } +impl NotifyUnitWidgetInfo { + fn button<'a>(&self, id: Option, hidden: bool) -> Element<'a, Message> { + let notify = &self.unit; + let counter = self.counter; + match notify.image() { + Some(ImageInfo::Svg(path)) => button(row![ + svg(svg::Handle::from_path(path)).height(Length::Fill), + Space::with_width(4.), + column![ + text(notify.summery.clone()) + .shaping(text::Shaping::Advanced) + .size(20) + .font(Font { + weight: iced::font::Weight::Bold, + ..Default::default() + }), + text(notify.body.clone()).shaping(text::Shaping::Advanced) + ] + ]) + .width(Length::Fill) + .height(Length::Fill) + .on_press(Message::RemoveNotify(id, self.unit.id, counter, hidden)) + .into(), + Some(ImageInfo::Data { + width, + height, + pixels, + }) => button(row![ + image(image::Handle::from_pixels( + width as u32, + height as u32, + pixels + )), + Space::with_width(4.), + column![ + text(notify.summery.clone()) + .shaping(text::Shaping::Advanced) + .size(20) + .font(Font { + weight: iced::font::Weight::Bold, + ..Default::default() + }), + text(notify.body.clone()).shaping(text::Shaping::Advanced) + ] + ]) + .width(Length::Fill) + .height(Length::Fill) + .on_press(Message::RemoveNotify(id, self.unit.id, counter, hidden)) + .into(), + Some(ImageInfo::Png(path)) | Some(ImageInfo::Jpg(path)) => button(row![ + image(image::Handle::from_path(path)).height(Length::Fill), + Space::with_width(4.), + column![ + text(notify.summery.clone()) + .shaping(text::Shaping::Advanced) + .size(20) + .font(Font { + weight: iced::font::Weight::Bold, + ..Default::default() + }), + text(notify.body.clone()).shaping(text::Shaping::Advanced) + ] + ]) + .width(Length::Fill) + .height(Length::Fill) + .on_press(Message::RemoveNotify(id, self.unit.id, counter, hidden)) + .into(), + _ => button(column![ + text(notify.summery.clone()).shaping(text::Shaping::Advanced), + text(notify.body.clone()).shaping(text::Shaping::Advanced) + ]) + .width(Length::Fill) + .height(Length::Fill) + .on_press(Message::RemoveNotify(id, self.unit.id, counter, hidden)) + .into(), + } + } +} + #[allow(unused)] #[derive(Debug)] enum NotifyCommand { @@ -90,6 +172,7 @@ struct LalaMusicBar { launcher: Option, launcherid: Option, hidenid: Option, + right_panel: Option, notifications: HashMap, hidden_notifications: Vec, sender: Sender, @@ -203,6 +286,26 @@ impl LalaMusicBar { SliderIndex::Balance => self.balance_bar(), } } + + fn right_panel_view(&self) -> Element { + let btns: Vec> = self + .hidden_notifications + .iter() + .map(|wdgetinfo| { + container(wdgetinfo.button(None, true)) + .height(Length::Fixed(100.)) + .into() + }) + .collect(); + column![ + scrollable(column(btns).spacing(10.)).height(Length::Fill), + container(button(text("clear all")).on_press(Message::ClearAllNotifications)) + .width(Length::Fill) + .center_x(), + Space::with_height(10.) + ] + .into() + } } #[derive(Debug, Clone)] @@ -220,12 +323,14 @@ enum Message { SliderIndexNext, SliderIndexPre, ToggleLauncher, + ToggleRightPanel, LauncherInfo(LaunchMessage), Notify(NotifyMessage), - RemoveNotify(iced::window::Id), + RemoveNotify(Option, u32, usize, bool), InlineReply((iced::window::Id, u32, String)), InlineReplyMsgUpdate((iced::window::Id, String)), CheckOutput, + ClearAllNotifications, } impl From for Message { @@ -330,6 +435,7 @@ impl LalaMusicBar { buttons, sound_slider, Space::with_width(Length::Fixed(10.)), + button(text("N")).on_press(Message::ToggleRightPanel) ] .spacing(10) } else { @@ -345,6 +451,7 @@ impl LalaMusicBar { buttons, sound_slider, Space::with_width(Length::Fixed(10.)), + button(text("N")).on_press(Message::ToggleRightPanel) ] .spacing(10) }; @@ -375,6 +482,7 @@ impl MultiApplication for LalaMusicBar { bar_index: SliderIndex::Balance, launcher: None, launcherid: None, + right_panel: None, hidenid: None, notifications: HashMap::new(), hidden_notifications: Vec::new(), @@ -394,6 +502,8 @@ impl MultiApplication for LalaMusicBar { Some(LaLaInfo::Launcher) } else if self.hidenid.is_some_and(|tid| tid == id) { Some(LaLaInfo::HiddenInfo) + } else if self.right_panel.is_some_and(|tid| tid == id) { + Some(LaLaInfo::RightPanel) } else { self.notifications.get(&id).cloned().map(LaLaInfo::Notify) } @@ -410,6 +520,7 @@ impl MultiApplication for LalaMusicBar { LaLaInfo::HiddenInfo => { self.hidenid = Some(id); } + LaLaInfo::RightPanel => self.right_panel = Some(id), } } @@ -417,6 +528,9 @@ impl MultiApplication for LalaMusicBar { if self.launcherid.is_some_and(|lid| lid == id) { self.launcherid.take(); } + if self.right_panel.is_some_and(|lid| lid == id) { + self.right_panel.take(); + } if self.hidenid.is_some_and(|lid| lid == id) { self.hidenid.take(); } @@ -540,6 +654,33 @@ impl MultiApplication for LalaMusicBar { self.launcher.as_ref().unwrap().focus_input(), ]); } + Message::ToggleRightPanel => { + if self.right_panel.is_some() { + if let Some(id) = self.right_panel { + self.right_panel.take(); + return Command::single(Action::Window(WindowAction::Close(id))); + } + return Command::none(); + } + return Command::single( + LaLaShellIdAction::new( + iced::window::Id::MAIN, + LalaShellAction::NewLayerShell(( + NewLayerShellSettings { + size: Some((300, 0)), + exclusive_zone: Some(300), + anchor: Anchor::Right | Anchor::Bottom | Anchor::Top, + layer: Layer::Top, + margin: None, + keyboard_interactivity: KeyboardInteractivity::None, + use_last_output: false, + }, + LaLaInfo::RightPanel, + )), + ) + .into(), + ); + } Message::Notify(NotifyMessage::UnitAdd(notify)) => { let mut commands = vec![]; for unit in self.hidden_notifications.iter_mut() { @@ -732,47 +873,52 @@ impl MultiApplication for LalaMusicBar { return Command::batch(commands); } - Message::RemoveNotify(id) => { - let NotifyUnitWidgetInfo { - counter, - unit: NotifyUnit { id: notify_id, .. }, - .. - } = self.notifications.get(&id).unwrap().clone(); + Message::RemoveNotify(id, notify_id, counter, is_hidden) => { self.sender .try_send(NotifyCommand::ActionInvoked { id: notify_id, action_key: DEFAULT_ACTION.to_string(), }) .ok(); - let removed_pos = self - .notifications - .iter() - .find(|(oid, _)| **oid == id) - .map(|(_, info)| info.upper) - .unwrap_or(0); let mut commands = vec![]; - for (id, unit) in self.notifications.iter_mut() { - if unit.upper > removed_pos { - unit.upper -= 135; - } - if unit.counter > counter { - unit.counter -= 1; + + if !is_hidden { + let removed_pos = self + .notifications + .iter() + .find(|(oid, _)| id.is_some_and(|id| id == **oid)) + .map(|(_, info)| info.upper) + .unwrap_or(0); + for (id, unit) in self.notifications.iter_mut() { + if unit.upper > removed_pos { + unit.upper -= 135; + } + if unit.counter > counter { + unit.counter -= 1; + } + commands.push(Command::single( + LaLaShellIdAction::new( + *id, + LalaShellAction::MarginChange((unit.upper, 10, 10, 10)), + ) + .into(), + )); } - commands.push(Command::single( - LaLaShellIdAction::new( - *id, - LalaShellAction::MarginChange((unit.upper, 10, 10, 10)), - ) - .into(), - )); } - let mut to_show_id = None; + + let mut to_removed_index = None; for (index, notify) in self.hidden_notifications.iter_mut().enumerate() { + if counter > notify.counter { + continue; + } + if counter == notify.counter { + to_removed_index = Some(index); + } notify.counter -= 1; notify.upper -= 135; - if notify.counter == 3 { + if notify.counter == 3 && !is_hidden { to_show_id = Some(index); commands.push(Command::single( LaLaShellIdAction::new( @@ -795,6 +941,12 @@ impl MultiApplication for LalaMusicBar { } } + if is_hidden { + if let Some(index) = to_removed_index { + self.hidden_notifications.remove(index); + } + } + if let Some(index) = to_show_id { self.hidden_notifications.remove(index); } @@ -807,10 +959,10 @@ impl MultiApplication for LalaMusicBar { )))); } - commands.append(&mut vec![ - Command::single(Action::Window(WindowAction::Close(id))), - Command::perform(async {}, |_| Message::CheckOutput), - ]); + if let Some(id) = id { + commands.push(Command::single(Action::Window(WindowAction::Close(id)))); + } + commands.push(Command::perform(async {}, |_| Message::CheckOutput)); return Command::batch(commands); } @@ -875,6 +1027,19 @@ impl MultiApplication for LalaMusicBar { let notify = self.notifications.get_mut(&id).unwrap(); notify.inline_reply = msg; } + Message::ClearAllNotifications => { + self.hidden_notifications.clear(); + let mut commands = self + .notifications + .keys() + .map(|id| Command::single(Action::Window(WindowAction::Close(*id)))) + .collect::>(); + + if let Some(id) = self.hidenid { + commands.push(Command::single(Action::Window(WindowAction::Close(id)))); + } + return Command::batch(commands); + } } Command::none() } @@ -887,80 +1052,10 @@ impl MultiApplication for LalaMusicBar { return launcher.view(); } } - LaLaInfo::Notify(NotifyUnitWidgetInfo { unit: notify, .. }) => { - let btnwidgets: Element = match notify.image() { - Some(ImageInfo::Svg(path)) => button(row![ - svg(svg::Handle::from_path(path)).height(Length::Fill), - Space::with_width(4.), - column![ - text(notify.summery.clone()) - .shaping(text::Shaping::Advanced) - .size(20) - .font(Font { - weight: iced::font::Weight::Bold, - ..Default::default() - }), - text(notify.body.clone()).shaping(text::Shaping::Advanced) - ] - ]) - .width(Length::Fill) - .height(Length::Fill) - .on_press(Message::RemoveNotify(id)) - .into(), - Some(ImageInfo::Data { - width, - height, - pixels, - }) => button(row![ - image(image::Handle::from_pixels( - width as u32, - height as u32, - pixels - )), - Space::with_width(4.), - column![ - text(notify.summery.clone()) - .shaping(text::Shaping::Advanced) - .size(20) - .font(Font { - weight: iced::font::Weight::Bold, - ..Default::default() - }), - text(notify.body.clone()).shaping(text::Shaping::Advanced) - ] - ]) - .width(Length::Fill) - .height(Length::Fill) - .on_press(Message::RemoveNotify(id)) - .into(), - Some(ImageInfo::Png(path)) | Some(ImageInfo::Jpg(path)) => button(row![ - image(image::Handle::from_path(path)).height(Length::Fill), - Space::with_width(4.), - column![ - text(notify.summery.clone()) - .shaping(text::Shaping::Advanced) - .size(20) - .font(Font { - weight: iced::font::Weight::Bold, - ..Default::default() - }), - text(notify.body.clone()).shaping(text::Shaping::Advanced) - ] - ]) - .width(Length::Fill) - .height(Length::Fill) - .on_press(Message::RemoveNotify(id)) - .into(), - _ => button(column![ - text(notify.summery.clone()).shaping(text::Shaping::Advanced), - text(notify.body.clone()).shaping(text::Shaping::Advanced) - ]) - .width(Length::Fill) - .height(Length::Fill) - .on_press(Message::RemoveNotify(id)) - .into(), - }; + LaLaInfo::Notify(unitwidgetinfo) => { + let btnwidgets: Element = unitwidgetinfo.button(Some(id), false); + let notify = &unitwidgetinfo.unit; let notifywidget = self.notifications.get(&id).unwrap(); if notify.inline_reply_support() { return column![ @@ -995,6 +1090,9 @@ impl MultiApplication for LalaMusicBar { )) .into(); } + LaLaInfo::RightPanel => { + return self.right_panel_view(); + } } } self.main_view() From 7f21f6878976730edce1f6c9c19e294aea74bc2d Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sun, 11 Aug 2024 20:40:53 +0859 Subject: [PATCH 31/35] chore: make clippy happy --- lala_bar/src/main.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index 585afe3..09a0a57 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -64,7 +64,7 @@ pub fn main() -> Result<(), iced_layershell::Error> { #[derive(Debug, Clone)] enum LaLaInfo { Launcher, - Notify(NotifyUnitWidgetInfo), + Notify(Box), HiddenInfo, RightPanel, } @@ -505,7 +505,10 @@ impl MultiApplication for LalaMusicBar { } else if self.right_panel.is_some_and(|tid| tid == id) { Some(LaLaInfo::RightPanel) } else { - self.notifications.get(&id).cloned().map(LaLaInfo::Notify) + self.notifications + .get(&id) + .cloned() + .map(|notifyw| LaLaInfo::Notify(Box::new(notifyw))) } } @@ -515,7 +518,7 @@ impl MultiApplication for LalaMusicBar { self.launcherid = Some(id); } LaLaInfo::Notify(notify) => { - self.notifications.entry(id).or_insert(notify); + self.notifications.entry(id).or_insert(*notify); } LaLaInfo::HiddenInfo => { self.hidenid = Some(id); @@ -718,12 +721,12 @@ impl MultiApplication for LalaMusicBar { keyboard_interactivity: KeyboardInteractivity::OnDemand, use_last_output: true, }, - LaLaInfo::Notify(NotifyUnitWidgetInfo { + LaLaInfo::Notify(Box::new(NotifyUnitWidgetInfo { counter: 0, upper: 10, inline_reply: String::new(), unit: notify, - }), + })), )), ) .into(), @@ -759,7 +762,7 @@ impl MultiApplication for LalaMusicBar { let NotifyUnit { id, .. } = info.unit; removed_id == id }) - .map(|(id, _)| id.clone()) + .map(|(id, _)| *id) .collect(); let mut commands: Vec<_> = self .notifications @@ -850,7 +853,7 @@ impl MultiApplication for LalaMusicBar { keyboard_interactivity: KeyboardInteractivity::OnDemand, use_last_output: true, }, - LaLaInfo::Notify(notify.clone()), + LaLaInfo::Notify(Box::new(notify.clone())), )), ) .into(), @@ -933,7 +936,7 @@ impl MultiApplication for LalaMusicBar { keyboard_interactivity: KeyboardInteractivity::OnDemand, use_last_output: true, }, - LaLaInfo::Notify(notify.clone()), + LaLaInfo::Notify(Box::new(notify.clone())), )), ) .into(), @@ -1063,10 +1066,7 @@ impl MultiApplication for LalaMusicBar { Space::with_height(5.), row![ text_input("reply something", ¬ifywidget.inline_reply) - .on_input(move |msg| Message::InlineReplyMsgUpdate(( - id.clone(), - msg - ))) + .on_input(move |msg| Message::InlineReplyMsgUpdate((id, msg))) .on_submit(Message::InlineReply(( id, notify.id, From 6eccb07f5e63c2976255db0b38f927abc311b431 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sun, 11 Aug 2024 20:44:28 +0859 Subject: [PATCH 32/35] feat: toggle all actions --- lala_bar/src/main.rs | 52 +++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index 09a0a57..8f03ebb 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -12,7 +12,7 @@ use iced_layershell::actions::{ }; use launcher::{LaunchMessage, Launcher}; use notification_iced::{ - start_connection, ImageInfo, LaLaMako, NotifyMessage, NotifyUnit, VersionInfo, DEFAULT_ACTION, + start_connection, ImageInfo, LaLaMako, NotifyMessage, NotifyUnit, VersionInfo, NOTIFICATION_SERVICE_PATH, }; use zbus_mpirs::ServiceInfo; @@ -98,7 +98,13 @@ impl NotifyUnitWidgetInfo { ]) .width(Length::Fill) .height(Length::Fill) - .on_press(Message::RemoveNotify(id, self.unit.id, counter, hidden)) + .on_press(Message::RemoveNotify( + id, + self.unit.actions.clone(), + self.unit.id, + counter, + hidden, + )) .into(), Some(ImageInfo::Data { width, @@ -124,7 +130,13 @@ impl NotifyUnitWidgetInfo { ]) .width(Length::Fill) .height(Length::Fill) - .on_press(Message::RemoveNotify(id, self.unit.id, counter, hidden)) + .on_press(Message::RemoveNotify( + id, + self.unit.actions.clone(), + self.unit.id, + counter, + hidden, + )) .into(), Some(ImageInfo::Png(path)) | Some(ImageInfo::Jpg(path)) => button(row![ image(image::Handle::from_path(path)).height(Length::Fill), @@ -142,7 +154,13 @@ impl NotifyUnitWidgetInfo { ]) .width(Length::Fill) .height(Length::Fill) - .on_press(Message::RemoveNotify(id, self.unit.id, counter, hidden)) + .on_press(Message::RemoveNotify( + id, + self.unit.actions.clone(), + self.unit.id, + counter, + hidden, + )) .into(), _ => button(column![ text(notify.summery.clone()).shaping(text::Shaping::Advanced), @@ -150,7 +168,13 @@ impl NotifyUnitWidgetInfo { ]) .width(Length::Fill) .height(Length::Fill) - .on_press(Message::RemoveNotify(id, self.unit.id, counter, hidden)) + .on_press(Message::RemoveNotify( + id, + self.unit.actions.clone(), + self.unit.id, + counter, + hidden, + )) .into(), } } @@ -326,7 +350,7 @@ enum Message { ToggleRightPanel, LauncherInfo(LaunchMessage), Notify(NotifyMessage), - RemoveNotify(Option, u32, usize, bool), + RemoveNotify(Option, Vec, u32, usize, bool), InlineReply((iced::window::Id, u32, String)), InlineReplyMsgUpdate((iced::window::Id, String)), CheckOutput, @@ -876,13 +900,15 @@ impl MultiApplication for LalaMusicBar { return Command::batch(commands); } - Message::RemoveNotify(id, notify_id, counter, is_hidden) => { - self.sender - .try_send(NotifyCommand::ActionInvoked { - id: notify_id, - action_key: DEFAULT_ACTION.to_string(), - }) - .ok(); + Message::RemoveNotify(id, actions, notify_id, counter, is_hidden) => { + for action in actions { + self.sender + .try_send(NotifyCommand::ActionInvoked { + id: notify_id, + action_key: action, + }) + .ok(); + } let mut commands = vec![]; From 5682574f0451f406c1eed3b30cedd7b5cb7b78a2 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sun, 11 Aug 2024 20:45:08 +0859 Subject: [PATCH 33/35] Revert "feat: toggle all actions" only support default now This reverts commit 6eccb07f5e63c2976255db0b38f927abc311b431. --- lala_bar/src/main.rs | 52 +++++++++++--------------------------------- 1 file changed, 13 insertions(+), 39 deletions(-) diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index 8f03ebb..09a0a57 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -12,7 +12,7 @@ use iced_layershell::actions::{ }; use launcher::{LaunchMessage, Launcher}; use notification_iced::{ - start_connection, ImageInfo, LaLaMako, NotifyMessage, NotifyUnit, VersionInfo, + start_connection, ImageInfo, LaLaMako, NotifyMessage, NotifyUnit, VersionInfo, DEFAULT_ACTION, NOTIFICATION_SERVICE_PATH, }; use zbus_mpirs::ServiceInfo; @@ -98,13 +98,7 @@ impl NotifyUnitWidgetInfo { ]) .width(Length::Fill) .height(Length::Fill) - .on_press(Message::RemoveNotify( - id, - self.unit.actions.clone(), - self.unit.id, - counter, - hidden, - )) + .on_press(Message::RemoveNotify(id, self.unit.id, counter, hidden)) .into(), Some(ImageInfo::Data { width, @@ -130,13 +124,7 @@ impl NotifyUnitWidgetInfo { ]) .width(Length::Fill) .height(Length::Fill) - .on_press(Message::RemoveNotify( - id, - self.unit.actions.clone(), - self.unit.id, - counter, - hidden, - )) + .on_press(Message::RemoveNotify(id, self.unit.id, counter, hidden)) .into(), Some(ImageInfo::Png(path)) | Some(ImageInfo::Jpg(path)) => button(row![ image(image::Handle::from_path(path)).height(Length::Fill), @@ -154,13 +142,7 @@ impl NotifyUnitWidgetInfo { ]) .width(Length::Fill) .height(Length::Fill) - .on_press(Message::RemoveNotify( - id, - self.unit.actions.clone(), - self.unit.id, - counter, - hidden, - )) + .on_press(Message::RemoveNotify(id, self.unit.id, counter, hidden)) .into(), _ => button(column![ text(notify.summery.clone()).shaping(text::Shaping::Advanced), @@ -168,13 +150,7 @@ impl NotifyUnitWidgetInfo { ]) .width(Length::Fill) .height(Length::Fill) - .on_press(Message::RemoveNotify( - id, - self.unit.actions.clone(), - self.unit.id, - counter, - hidden, - )) + .on_press(Message::RemoveNotify(id, self.unit.id, counter, hidden)) .into(), } } @@ -350,7 +326,7 @@ enum Message { ToggleRightPanel, LauncherInfo(LaunchMessage), Notify(NotifyMessage), - RemoveNotify(Option, Vec, u32, usize, bool), + RemoveNotify(Option, u32, usize, bool), InlineReply((iced::window::Id, u32, String)), InlineReplyMsgUpdate((iced::window::Id, String)), CheckOutput, @@ -900,15 +876,13 @@ impl MultiApplication for LalaMusicBar { return Command::batch(commands); } - Message::RemoveNotify(id, actions, notify_id, counter, is_hidden) => { - for action in actions { - self.sender - .try_send(NotifyCommand::ActionInvoked { - id: notify_id, - action_key: action, - }) - .ok(); - } + Message::RemoveNotify(id, notify_id, counter, is_hidden) => { + self.sender + .try_send(NotifyCommand::ActionInvoked { + id: notify_id, + action_key: DEFAULT_ACTION.to_string(), + }) + .ok(); let mut commands = vec![]; From a496ad12e738ae70eb6a4e010632dac3a41fc572 Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sun, 11 Aug 2024 20:56:15 +0859 Subject: [PATCH 34/35] feat: use secondery style --- lala_bar/src/main.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index 09a0a57..94cd023 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -96,6 +96,7 @@ impl NotifyUnitWidgetInfo { text(notify.body.clone()).shaping(text::Shaping::Advanced) ] ]) + .style(iced::theme::Button::Secondary) .width(Length::Fill) .height(Length::Fill) .on_press(Message::RemoveNotify(id, self.unit.id, counter, hidden)) @@ -124,6 +125,7 @@ impl NotifyUnitWidgetInfo { ]) .width(Length::Fill) .height(Length::Fill) + .style(iced::theme::Button::Secondary) .on_press(Message::RemoveNotify(id, self.unit.id, counter, hidden)) .into(), Some(ImageInfo::Png(path)) | Some(ImageInfo::Jpg(path)) => button(row![ @@ -142,6 +144,7 @@ impl NotifyUnitWidgetInfo { ]) .width(Length::Fill) .height(Length::Fill) + .style(iced::theme::Button::Secondary) .on_press(Message::RemoveNotify(id, self.unit.id, counter, hidden)) .into(), _ => button(column![ @@ -150,6 +153,7 @@ impl NotifyUnitWidgetInfo { ]) .width(Length::Fill) .height(Length::Fill) + .style(iced::theme::Button::Secondary) .on_press(Message::RemoveNotify(id, self.unit.id, counter, hidden)) .into(), } From 9a9c5f7484a4c1f312e3906a34629db15ae25f1e Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Sun, 11 Aug 2024 21:17:10 +0859 Subject: [PATCH 35/35] feat: show music info in righpanel --- lala_bar/src/main.rs | 50 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/lala_bar/src/main.rs b/lala_bar/src/main.rs index 94cd023..2fd6d9d 100644 --- a/lala_bar/src/main.rs +++ b/lala_bar/src/main.rs @@ -301,14 +301,47 @@ impl LalaMusicBar { .into() }) .collect(); - column![ - scrollable(column(btns).spacing(10.)).height(Length::Fill), + let mut view_elements: Vec> = vec![]; + + if let Some(data) = &self.service_data { + if let Some(art_url) = url::Url::parse(&data.metadata.mpris_arturl) + .ok() + .and_then(|url| url.to_file_path().ok()) + { + view_elements.push( + container(image(image::Handle::from_path(art_url)).width(Length::Fill)) + .padding(10) + .width(Length::Fill) + .into(), + ); + view_elements.push(Space::with_height(10.).into()); + view_elements.push( + container( + text(&data.metadata.xesam_title) + .size(20) + .font(Font { + weight: iced::font::Weight::Bold, + ..Default::default() + }) + .shaping(text::Shaping::Advanced) + .style(iced::theme::Text::Color(iced::Color::WHITE)), + ) + .into(), + ); + view_elements.push(Space::with_height(10.).into()); + } + } + view_elements.append(&mut vec![ + scrollable(column(btns).spacing(10.)) + .height(Length::Fill) + .into(), container(button(text("clear all")).on_press(Message::ClearAllNotifications)) .width(Length::Fill) - .center_x(), - Space::with_height(10.) - ] - .into() + .center_x() + .into(), + Space::with_height(10.).into(), + ]); + column(view_elements).into() } } @@ -424,6 +457,7 @@ impl LalaMusicBar { .center_x(); let sound_slider = self.sound_slider(); + let panel_text = if self.right_panel.is_some() { ">" } else { "<" }; let col = if let Some(art_url) = art_url { row![ button( @@ -439,7 +473,7 @@ impl LalaMusicBar { buttons, sound_slider, Space::with_width(Length::Fixed(10.)), - button(text("N")).on_press(Message::ToggleRightPanel) + button(text(panel_text)).on_press(Message::ToggleRightPanel) ] .spacing(10) } else { @@ -455,7 +489,7 @@ impl LalaMusicBar { buttons, sound_slider, Space::with_width(Length::Fixed(10.)), - button(text("N")).on_press(Message::ToggleRightPanel) + button(text(panel_text)).on_press(Message::ToggleRightPanel) ] .spacing(10) };