Initial port of notifications to an applet
This commit is contained in:
parent
25a8e8353e
commit
04ce88e4ce
17 changed files with 231 additions and 28 deletions
15
Cargo.lock
generated
15
Cargo.lock
generated
|
|
@ -363,6 +363,21 @@ dependencies = [
|
||||||
"zbus",
|
"zbus",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cosmic-applet-notifications"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"cascade",
|
||||||
|
"cosmic-panel-config",
|
||||||
|
"futures",
|
||||||
|
"gtk4",
|
||||||
|
"once_cell",
|
||||||
|
"serde",
|
||||||
|
"zbus",
|
||||||
|
"zbus_names",
|
||||||
|
"zvariant",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cosmic-applet-power"
|
name = "cosmic-applet-power"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ members = [
|
||||||
"applets/cosmic-applet-audio",
|
"applets/cosmic-applet-audio",
|
||||||
"applets/cosmic-applet-graphics",
|
"applets/cosmic-applet-graphics",
|
||||||
"applets/cosmic-applet-network",
|
"applets/cosmic-applet-network",
|
||||||
|
"applets/cosmic-applet-notifications",
|
||||||
"applets/cosmic-applet-power",
|
"applets/cosmic-applet-power",
|
||||||
"applets/cosmic-applet-workspaces",
|
"applets/cosmic-applet-workspaces",
|
||||||
"applets/cosmic-applet-status-area",
|
"applets/cosmic-applet-status-area",
|
||||||
|
|
|
||||||
16
applets/cosmic-applet-notifications/Cargo.toml
Normal file
16
applets/cosmic-applet-notifications/Cargo.toml
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
[package]
|
||||||
|
name = "cosmic-applet-notifications"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
license = "GPL-3.0-or-later"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
cascade = "1"
|
||||||
|
futures = "0.3"
|
||||||
|
gtk4 = "0.4.6"
|
||||||
|
once_cell = "1.12"
|
||||||
|
serde = "1"
|
||||||
|
zbus = "2.0.1"
|
||||||
|
zbus_names = "2"
|
||||||
|
zvariant = "3"
|
||||||
|
cosmic-panel-config = {git = "https://github.com/pop-os/cosmic-panel", features = ["gtk4"]}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Name=Cosmic Applet Notifications
|
||||||
|
Type=Application
|
||||||
|
Exec=cosmic-applet-notifications
|
||||||
|
Terminal=false
|
||||||
|
Categories=GNOME;GTK;
|
||||||
|
Keywords=Gnome;GTK;
|
||||||
|
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
|
||||||
|
Icon=com.system76.CosmicAppletNotifications
|
||||||
|
NoDisplay=true
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="128px" height="128px" viewBox="0 0 128 128" version="1.1">
|
||||||
|
<defs>
|
||||||
|
<filter id="alpha" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%">
|
||||||
|
<feColorMatrix type="matrix" in="SourceGraphic" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
|
||||||
|
</filter>
|
||||||
|
<mask id="mask0">
|
||||||
|
<g filter="url(#alpha)">
|
||||||
|
<rect x="0" y="0" width="128" height="128" style="fill:rgb(0%,0%,0%);fill-opacity:0.1;stroke:none;"/>
|
||||||
|
</g>
|
||||||
|
</mask>
|
||||||
|
<clipPath id="clip1">
|
||||||
|
<rect x="0" y="0" width="192" height="152"/>
|
||||||
|
</clipPath>
|
||||||
|
<g id="surface10632" clip-path="url(#clip1)">
|
||||||
|
<path style="fill:none;stroke-width:0.99;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.99,0.99;stroke-miterlimit:4;" d="M 123.503906 236 C 123.503906 268.863281 96.863281 295.503906 64 295.503906 C 31.136719 295.503906 4.496094 268.863281 4.496094 236 C 4.496094 203.136719 31.136719 176.496094 64 176.496094 C 96.863281 176.496094 123.503906 203.136719 123.503906 236 Z M 123.503906 236 " transform="matrix(1,0,0,1,8,-156)"/>
|
||||||
|
</g>
|
||||||
|
<mask id="mask1">
|
||||||
|
<g filter="url(#alpha)">
|
||||||
|
<rect x="0" y="0" width="128" height="128" style="fill:rgb(0%,0%,0%);fill-opacity:0.1;stroke:none;"/>
|
||||||
|
</g>
|
||||||
|
</mask>
|
||||||
|
<clipPath id="clip2">
|
||||||
|
<rect x="0" y="0" width="192" height="152"/>
|
||||||
|
</clipPath>
|
||||||
|
<g id="surface10635" clip-path="url(#clip2)">
|
||||||
|
<path style="fill:none;stroke-width:0.99;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.99,0.99;stroke-miterlimit:4;" d="M 29.195312 180.496094 L 98.804688 180.496094 C 103.609375 180.496094 107.503906 184.046875 107.503906 188.425781 L 107.503906 283.574219 C 107.503906 287.953125 103.609375 291.503906 98.804688 291.503906 L 29.195312 291.503906 C 24.390625 291.503906 20.496094 287.953125 20.496094 283.574219 L 20.496094 188.425781 C 20.496094 184.046875 24.390625 180.496094 29.195312 180.496094 Z M 29.195312 180.496094 " transform="matrix(1,0,0,1,8,-156)"/>
|
||||||
|
</g>
|
||||||
|
<mask id="mask2">
|
||||||
|
<g filter="url(#alpha)">
|
||||||
|
<rect x="0" y="0" width="128" height="128" style="fill:rgb(0%,0%,0%);fill-opacity:0.1;stroke:none;"/>
|
||||||
|
</g>
|
||||||
|
</mask>
|
||||||
|
<clipPath id="clip3">
|
||||||
|
<rect x="0" y="0" width="192" height="152"/>
|
||||||
|
</clipPath>
|
||||||
|
<g id="surface10638" clip-path="url(#clip3)">
|
||||||
|
<path style="fill:none;stroke-width:0.99;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.99,0.99;stroke-miterlimit:4;" d="M 20.417969 184.496094 L 107.582031 184.496094 C 111.957031 184.496094 115.503906 188.042969 115.503906 192.417969 L 115.503906 279.582031 C 115.503906 283.957031 111.957031 287.503906 107.582031 287.503906 L 20.417969 287.503906 C 16.042969 287.503906 12.496094 283.957031 12.496094 279.582031 L 12.496094 192.417969 C 12.496094 188.042969 16.042969 184.496094 20.417969 184.496094 Z M 20.417969 184.496094 " transform="matrix(1,0,0,1,8,-156)"/>
|
||||||
|
</g>
|
||||||
|
<mask id="mask3">
|
||||||
|
<g filter="url(#alpha)">
|
||||||
|
<rect x="0" y="0" width="128" height="128" style="fill:rgb(0%,0%,0%);fill-opacity:0.1;stroke:none;"/>
|
||||||
|
</g>
|
||||||
|
</mask>
|
||||||
|
<clipPath id="clip4">
|
||||||
|
<rect x="0" y="0" width="192" height="152"/>
|
||||||
|
</clipPath>
|
||||||
|
<g id="surface10641" clip-path="url(#clip4)">
|
||||||
|
<path style="fill:none;stroke-width:0.99;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.99,0.99;stroke-miterlimit:4;" d="M 16.425781 200.496094 L 111.574219 200.496094 C 115.953125 200.496094 119.503906 204.390625 119.503906 209.195312 L 119.503906 278.804688 C 119.503906 283.609375 115.953125 287.503906 111.574219 287.503906 L 16.425781 287.503906 C 12.046875 287.503906 8.496094 283.609375 8.496094 278.804688 L 8.496094 209.195312 C 8.496094 204.390625 12.046875 200.496094 16.425781 200.496094 Z M 16.425781 200.496094 " transform="matrix(1,0,0,1,8,-156)"/>
|
||||||
|
</g>
|
||||||
|
</defs>
|
||||||
|
<g id="surface10578">
|
||||||
|
<rect x="0" y="0" width="128" height="128" style="fill:rgb(94.117647%,94.117647%,94.117647%);fill-opacity:1;stroke:none;"/>
|
||||||
|
<use xlink:href="#surface10632" transform="matrix(1,0,0,1,-8,-16)" mask="url(#mask0)"/>
|
||||||
|
<use xlink:href="#surface10635" transform="matrix(1,0,0,1,-8,-16)" mask="url(#mask1)"/>
|
||||||
|
<use xlink:href="#surface10638" transform="matrix(1,0,0,1,-8,-16)" mask="url(#mask2)"/>
|
||||||
|
<use xlink:href="#surface10641" transform="matrix(1,0,0,1,-8,-16)" mask="url(#mask3)"/>
|
||||||
|
<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(38.431373%,62.7451%,91.764706%);stroke-opacity:1;stroke-miterlimit:4;" d="M 0 289 L 128 289 " transform="matrix(1,0,0,1,0,-172)"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.5 KiB |
31
applets/cosmic-applet-notifications/src/deref_cell.rs
Normal file
31
applets/cosmic-applet-notifications/src/deref_cell.rs
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
use once_cell::unsync::OnceCell;
|
||||||
|
|
||||||
|
/// Wrapper around `OnceCell` implementing `Deref`, and thus also panicking
|
||||||
|
/// when not set (or set twice).
|
||||||
|
///
|
||||||
|
/// To be used in place of `gtk::TemplateChild`, but without xml.
|
||||||
|
pub struct DerefCell<T>(OnceCell<T>);
|
||||||
|
|
||||||
|
impl<T> DerefCell<T> {
|
||||||
|
#[track_caller]
|
||||||
|
pub fn set(&self, value: T) {
|
||||||
|
if self.0.set(value).is_err() {
|
||||||
|
panic!("Initialized twice");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Default for DerefCell<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self(OnceCell::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> std::ops::Deref for DerefCell<T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn deref(&self) -> &T {
|
||||||
|
self.0.get().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
58
applets/cosmic-applet-notifications/src/main.rs
Normal file
58
applets/cosmic-applet-notifications/src/main.rs
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
use cascade::cascade;
|
||||||
|
use gtk4::{glib, prelude::*};
|
||||||
|
|
||||||
|
mod dbus_service;
|
||||||
|
mod deref_cell;
|
||||||
|
mod notification_popover;
|
||||||
|
use notification_popover::NotificationPopover;
|
||||||
|
mod notification_list;
|
||||||
|
mod notification_widget;
|
||||||
|
use notification_list::NotificationList;
|
||||||
|
mod notifications;
|
||||||
|
use notifications::Notifications;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
gtk4::init().unwrap();
|
||||||
|
|
||||||
|
// XXX Implement DBus service somewhere other than applet?
|
||||||
|
let notifications = Notifications::new();
|
||||||
|
|
||||||
|
let provider = gtk4::CssProvider::new();
|
||||||
|
provider.load_from_data(include_bytes!("style.css"));
|
||||||
|
gtk4::StyleContext::add_provider_for_display(
|
||||||
|
>k4::gdk::Display::default().expect("Could not connect to a display."),
|
||||||
|
&provider,
|
||||||
|
gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION,
|
||||||
|
);
|
||||||
|
|
||||||
|
let notification_list = NotificationList::new(¬ifications);
|
||||||
|
|
||||||
|
let popover = cascade! {
|
||||||
|
gtk4::Popover::new();
|
||||||
|
..set_child(Some(¬ification_list));
|
||||||
|
};
|
||||||
|
|
||||||
|
let menu_button = cascade! {
|
||||||
|
gtk4::MenuButton::new();
|
||||||
|
..set_popover(Some(&popover));
|
||||||
|
};
|
||||||
|
|
||||||
|
// XXX show in correct place
|
||||||
|
cascade! {
|
||||||
|
NotificationPopover::new(¬ifications);
|
||||||
|
..set_parent(&menu_button);
|
||||||
|
};
|
||||||
|
|
||||||
|
gtk4::Window::builder()
|
||||||
|
.decorated(false)
|
||||||
|
.child(&menu_button)
|
||||||
|
.resizable(false)
|
||||||
|
.width_request(1)
|
||||||
|
.height_request(1)
|
||||||
|
.css_classes(vec!["root_window".to_string()])
|
||||||
|
.build()
|
||||||
|
.show();
|
||||||
|
|
||||||
|
let main_loop = glib::MainLoop::new(None, false);
|
||||||
|
main_loop.run();
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
use futures::channel::mpsc;
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
use futures_channel::mpsc;
|
|
||||||
use gtk4::{
|
use gtk4::{
|
||||||
glib::{self, clone, subclass::Signal, SignalHandlerId},
|
glib::{self, clone, subclass::Signal, SignalHandlerId},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
33
applets/cosmic-applet-notifications/src/style.css
Normal file
33
applets/cosmic-applet-notifications/src/style.css
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
.loading-overlay {
|
||||||
|
background-color: #2f2f2f;
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
|
||||||
|
image.panel_icon {
|
||||||
|
padding-left: 0px;
|
||||||
|
padding-right: 0px;
|
||||||
|
padding-top: 0px;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.panel_icon {
|
||||||
|
border-radius: 12px;
|
||||||
|
transition: 100ms;
|
||||||
|
padding: 4px;
|
||||||
|
border-color: transparent;
|
||||||
|
background: transparent;
|
||||||
|
outline-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.panel_icon:hover {
|
||||||
|
border-radius: 12px;
|
||||||
|
transition: 100ms;
|
||||||
|
padding: 4px;
|
||||||
|
border-color: rgba(255, 255, 255, 0.1);
|
||||||
|
outline-color: rgba(255, 255, 255, 0.1);
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.root_window {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
6
justfile
6
justfile
|
|
@ -17,6 +17,7 @@ app_list_id := 'com.system76.CosmicAppList'
|
||||||
audio_id := 'com.system76.CosmicAppletAudio'
|
audio_id := 'com.system76.CosmicAppletAudio'
|
||||||
graphics_id := 'com.system76.CosmicAppletGraphics'
|
graphics_id := 'com.system76.CosmicAppletGraphics'
|
||||||
network_id := 'com.system76.CosmicAppletNetwork'
|
network_id := 'com.system76.CosmicAppletNetwork'
|
||||||
|
notifications_id := 'com.system76.CosmicAppletNotifications'
|
||||||
power_id := 'com.system76.CosmicAppletPower'
|
power_id := 'com.system76.CosmicAppletPower'
|
||||||
workspaces_id := 'com.system76.CosmicAppletWorkspaces'
|
workspaces_id := 'com.system76.CosmicAppletWorkspaces'
|
||||||
status_area_id := 'com.system76.CosmicAppletStatusArea'
|
status_area_id := 'com.system76.CosmicAppletStatusArea'
|
||||||
|
|
@ -50,6 +51,11 @@ install:
|
||||||
install -Dm0644 applets/cosmic-applet-network/data/{{network_id}}.desktop {{sharedir}}/applications/{{network_id}}.desktop
|
install -Dm0644 applets/cosmic-applet-network/data/{{network_id}}.desktop {{sharedir}}/applications/{{network_id}}.desktop
|
||||||
install -Dm0755 target/release/cosmic-applet-network {{bindir}}/cosmic-applet-network
|
install -Dm0755 target/release/cosmic-applet-network {{bindir}}/cosmic-applet-network
|
||||||
|
|
||||||
|
# notifications
|
||||||
|
install -Dm0644 applets/cosmic-applet-notifications/data/icons/{{notifications_id}}.svg {{iconsdir}}/{{notifications_id}}.svg
|
||||||
|
install -Dm0644 applets/cosmic-applet-notifications/data/{{notifications_id}}.desktop {{sharedir}}/applications/{{notifications_id}}.desktop
|
||||||
|
install -Dm04755 target/release/cosmic-applet-notifications {{bindir}}/cosmic-applet-notifications
|
||||||
|
|
||||||
# power
|
# power
|
||||||
install -Dm0644 applets/cosmic-applet-power/data/icons/{{power_id}}.svg {{iconsdir}}/{{power_id}}.svg
|
install -Dm0644 applets/cosmic-applet-power/data/icons/{{power_id}}.svg {{iconsdir}}/{{power_id}}.svg
|
||||||
install -Dm0644 applets/cosmic-applet-power/data/{{power_id}}.desktop {{sharedir}}/applications/{{power_id}}.desktop
|
install -Dm0644 applets/cosmic-applet-power/data/{{power_id}}.desktop {{sharedir}}/applications/{{power_id}}.desktop
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,10 @@ use gtk4::{
|
||||||
};
|
};
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
use crate::deref_cell::DerefCell;
|
|
||||||
use crate::notifications::Notifications;
|
|
||||||
use crate::window;
|
use crate::window;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct PanelAppInner {
|
pub struct PanelAppInner {
|
||||||
notifications: DerefCell<Notifications>,
|
|
||||||
activated: Cell<bool>,
|
activated: Cell<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -28,8 +25,6 @@ impl ObjectImpl for PanelAppInner {
|
||||||
obj.set_application_id(Some("com.system76.cosmicpanel"));
|
obj.set_application_id(Some("com.system76.cosmicpanel"));
|
||||||
|
|
||||||
self.parent_constructed(obj);
|
self.parent_constructed(obj);
|
||||||
|
|
||||||
self.notifications.set(Notifications::new());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,8 +78,4 @@ impl PanelApp {
|
||||||
fn add_window_for_monitor(&self, monitor: gdk::Monitor) {
|
fn add_window_for_monitor(&self, monitor: gdk::Monitor) {
|
||||||
window::create(self, monitor);
|
window::create(self, monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn notifications(&self) -> &Notifications {
|
|
||||||
&*self.inner().notifications
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,9 @@
|
||||||
use gtk4::{glib, prelude::*};
|
use gtk4::{glib, prelude::*};
|
||||||
|
|
||||||
mod application;
|
mod application;
|
||||||
mod dbus_service;
|
|
||||||
mod deref_cell;
|
mod deref_cell;
|
||||||
mod mpris;
|
mod mpris;
|
||||||
mod mpris_player;
|
mod mpris_player;
|
||||||
mod notification_list;
|
|
||||||
mod notification_popover;
|
|
||||||
mod notification_widget;
|
|
||||||
mod notifications;
|
|
||||||
mod popover_container;
|
mod popover_container;
|
||||||
mod time_button;
|
mod time_button;
|
||||||
mod window;
|
mod window;
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,6 @@ use gtk4::{
|
||||||
use crate::application::PanelApp;
|
use crate::application::PanelApp;
|
||||||
use crate::deref_cell::DerefCell;
|
use crate::deref_cell::DerefCell;
|
||||||
use crate::mpris::MprisControls;
|
use crate::mpris::MprisControls;
|
||||||
use crate::notification_list::NotificationList;
|
|
||||||
use crate::notification_popover::NotificationPopover;
|
|
||||||
use crate::popover_container::PopoverContainer;
|
use crate::popover_container::PopoverContainer;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -18,7 +16,6 @@ pub struct TimeButtonInner {
|
||||||
calendar: DerefCell<gtk4::Calendar>,
|
calendar: DerefCell<gtk4::Calendar>,
|
||||||
button: DerefCell<gtk4::ToggleButton>,
|
button: DerefCell<gtk4::ToggleButton>,
|
||||||
label: DerefCell<gtk4::Label>,
|
label: DerefCell<gtk4::Label>,
|
||||||
notification_popover: DerefCell<NotificationPopover>,
|
|
||||||
left_box: DerefCell<gtk4::Box>,
|
left_box: DerefCell<gtk4::Box>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,7 +85,6 @@ impl ObjectImpl for TimeButtonInner {
|
||||||
|
|
||||||
fn dispose(&self, _obj: &TimeButton) {
|
fn dispose(&self, _obj: &TimeButton) {
|
||||||
self.button.unparent();
|
self.button.unparent();
|
||||||
self.notification_popover.unparent();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,15 +99,6 @@ impl TimeButton {
|
||||||
pub fn new(app: &PanelApp) -> Self {
|
pub fn new(app: &PanelApp) -> Self {
|
||||||
let obj = glib::Object::new::<Self>(&[]).unwrap();
|
let obj = glib::Object::new::<Self>(&[]).unwrap();
|
||||||
|
|
||||||
let notification_list = NotificationList::new(app.notifications());
|
|
||||||
obj.inner().left_box.prepend(¬ification_list);
|
|
||||||
|
|
||||||
let notification_popover = cascade! {
|
|
||||||
NotificationPopover::new(app.notifications());
|
|
||||||
..set_parent(&obj);
|
|
||||||
};
|
|
||||||
obj.inner().notification_popover.set(notification_popover);
|
|
||||||
|
|
||||||
obj
|
obj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue