Skip to content

Commit 6e8afc1

Browse files
Notifications settings page
Closes: pop-os/cosmic-notifications#97 pop-os/cosmic-notifications#83 I implemented a settings page for COSMIC Notifications so that it is easier to edit its config. COSMIC Notification already exposes a config to tweak useful options like the maximum time a notification may stay on the screen. Currently, there isn't a nice way to edit this config which can be confusing to end users.
1 parent eb8d0e3 commit 6e8afc1

6 files changed

Lines changed: 144 additions & 0 deletions

File tree

Cargo.lock

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ git = "https://github.com/pop-os/cosmic-idle"
3030
[workspace.dependencies.cosmic-panel-config]
3131
git = "https://github.com/pop-os/cosmic-panel"
3232

33+
[workspace.dependencies.cosmic-notifications-config]
34+
git = "https://github.com/pop-os/cosmic-notifications"
35+
3336
[workspace.dependencies.cosmic-randr-shell]
3437
git = "https://github.com/pop-os/cosmic-randr"
3538

cosmic-settings/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ cosmic-dbus-networkmanager = { git = "https://github.com/pop-os/dbus-settings-bi
2222
nm-secret-agent-manager = { git = "https://github.com/pop-os/dbus-settings-bindings", optional = true }
2323
cosmic-idle-config.workspace = true
2424
cosmic-panel-config = { workspace = true, optional = true }
25+
cosmic-notifications-config.workspace = true
2526
cosmic-protocols = { git = "https://github.com/pop-os/cosmic-protocols", optional = true }
2627
cosmic-randr-shell.workspace = true
2728
cosmic-randr = { workspace = true, optional = true }

cosmic-settings/src/pages/desktop/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
pub mod appearance;
55
#[cfg(feature = "wayland")]
66
pub mod dock;
7+
pub mod notifications;
78
#[cfg(feature = "wayland")]
89
pub mod panel;
910
pub mod wallpaper;
@@ -37,6 +38,7 @@ impl page::AutoBind<crate::pages::Message> for Page {
3738
) -> page::Insert<crate::pages::Message> {
3839
page = page.sub_page::<wallpaper::Page>();
3940
page = page.sub_page::<appearance::Page>();
41+
page = page.sub_page::<notifications::Page>();
4042

4143
#[cfg(feature = "wayland")]
4244
{
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// Copyright 2026 System76 <info@system76.com>
2+
// SPDX-License-Identifier: GPL-3.0-only
3+
4+
//! User configuration for `cosmic-notifications`.
5+
6+
use cosmic::{
7+
Apply, Element, Task,
8+
cosmic_config::{Config, ConfigSet, CosmicConfigEntry},
9+
widget::settings,
10+
};
11+
use cosmic_notifications_config::NotificationsConfig;
12+
use cosmic_settings_page::{self as page, AutoBind, Content, Info, Section, section};
13+
use slotmap::SlotMap;
14+
use tracing::{debug, trace, warn};
15+
16+
use crate::pages;
17+
18+
pub struct Page {
19+
entity: page::Entity,
20+
config_helper: Option<Config>,
21+
config: NotificationsConfig,
22+
}
23+
24+
impl Page {
25+
/// Reload [`NotificationsConfig`] if it exists.
26+
pub fn refresh(&mut self) {
27+
self.config = load_config(self.config_helper.as_ref());
28+
}
29+
}
30+
31+
impl Default for Page {
32+
fn default() -> Self {
33+
debug!(id = %cosmic_notifications_config::ID, "Loading Notifications config for the first time this instance");
34+
35+
let config_helper = Config::new(cosmic_notifications_config::ID, 1).ok();
36+
let config = load_config(config_helper.as_ref());
37+
38+
Self {
39+
entity: Default::default(),
40+
config_helper,
41+
config,
42+
}
43+
}
44+
}
45+
46+
impl page::Page<pages::Message> for Page {
47+
fn info(&self) -> Info {
48+
// XXX: Need icon!
49+
Info::new("notifications", "")
50+
.title(fl!("notifications"))
51+
.description(fl!("notifications", "desc"))
52+
}
53+
54+
fn content(
55+
&self,
56+
_sections: &mut SlotMap<section::Entity, Section<pages::Message>>,
57+
) -> Option<Content> {
58+
crate::slab!(descriptions {
59+
anchor = fl!("notifications", "anchor-desc");
60+
max_notif = fl!("notifications", "max-desc");
61+
max_per_app = fl!("notifications", "max-per-app-desc");
62+
max_timeout_urgent = fl!("notifications", "max-timeout-urgent-desc");
63+
max_timeout_normal = fl!("notifications", "max-timeout-normal-desc");
64+
max_timeout_low = fl!("notifications", "max-timeout-low-desc");
65+
});
66+
67+
Some(vec![
68+
Section::default()
69+
.title(fl!("notifications"))
70+
.descriptions(descriptions)
71+
.view::<Page>(move |_binder, page, section| {
72+
let descriptions = &section.descriptions;
73+
74+
settings::section()
75+
.title(&*section.title)
76+
.apply(Element::from)
77+
.map(crate::pages::Message::Appearance)
78+
}),
79+
])
80+
}
81+
82+
fn on_enter(&mut self) -> Task<pages::Message> {
83+
self.refresh();
84+
Task::none()
85+
}
86+
87+
fn set_id(&mut self, entity: page::Entity) {
88+
self.entity = entity;
89+
}
90+
}
91+
92+
impl AutoBind<pages::Message> for Page {
93+
// fn sub_pages(page: page::Insert<pages::Message>) -> page::Insert<pages::Message> {
94+
// page.sub_page::<Page>()
95+
// }
96+
}
97+
98+
/// Load [`NotificationsConfig`] or return the default settings.
99+
fn load_config(helper: Option<&Config>) -> NotificationsConfig {
100+
trace!(id = %cosmic_notifications_config::ID, "Attempting to load config");
101+
102+
let Some(helper) = helper else {
103+
debug!(id = %cosmic_notifications_config::ID, "Missing config helper; using default settings.");
104+
105+
return Default::default();
106+
};
107+
108+
NotificationsConfig::get_entry(helper).unwrap_or_else(|(errors, config)| {
109+
warn!(id = %cosmic_notifications_config::ID, "Loading config failed with: ");
110+
for error in errors.iter().filter(|e| e.is_err()) {
111+
warn!(id = %cosmic_notifications_config::ID, "\t* {error}");
112+
}
113+
114+
config
115+
})
116+
}

i18n/en/cosmic_settings.ftl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,18 @@ shadow-and-corners = Window shadow and corners
299299

300300
notifications = Notifications
301301
.desc = Do Not Disturb, lockscreen notifications, and per-application settings
302+
.anchor = Anchor
303+
.anchor-desc = Screen location to display notification
304+
.max = Maximum notifications
305+
.max-desc = Maximum number of notifications that can be displayed at once
306+
.max-per-app = Maximum notifications per app
307+
.max-per-app-desc = Maximum number of notifications that can be displayed per app if not urgent nor constrained by "maximum notifications"
308+
.max-timeout-urgent = Maximum timeout (Urgent)
309+
.max-timeout-urgent-desc = Max time in milliseconds that an urgent notification will be displayed
310+
.max-timeout-normal = Maximum timeout (Normal)
311+
.max-timeout-normal-desc = Max time in milliseconds that a normal notification will be displayed
312+
.max-timeout-low = Maximum timeout (Low)
313+
.max-timeout-low-desc = Max time in milliseconds that a low priority notification will be displayed
302314
303315
## Desktop: Panel
304316

0 commit comments

Comments
 (0)