improv: create subscription channel for pages to send messages to
This commit is contained in:
parent
11de7cbd4a
commit
b443dd5b53
12 changed files with 104 additions and 26 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -1349,6 +1349,7 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"regex",
|
"regex",
|
||||||
"slotmap",
|
"slotmap",
|
||||||
|
"tokio",
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ resolver = "2"
|
||||||
rust-version = "1.71.0"
|
rust-version = "1.71.0"
|
||||||
sunrise_sunset = "1.0.1"
|
sunrise_sunset = "1.0.1"
|
||||||
|
|
||||||
|
[workspace.dependencies]
|
||||||
|
tokio = { version = "1.37.0", features = ["macros"] }
|
||||||
|
|
||||||
[workspace.dependencies.libcosmic]
|
[workspace.dependencies.libcosmic]
|
||||||
git = "https://github.com/pop-os/libcosmic"
|
git = "https://github.com/pop-os/libcosmic"
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ license = "GPL-3.0"
|
||||||
rust-version = "1.65.0"
|
rust-version = "1.65.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tokio = { version = "1.35.1", features = ["macros"] }
|
tokio.workspace = true
|
||||||
async-channel = "2.1.1"
|
async-channel = "2.1.1"
|
||||||
color-eyre = "0.6.2"
|
color-eyre = "0.6.2"
|
||||||
cosmic-bg-config = { workspace = true }
|
cosmic-bg-config = { workspace = true }
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,17 @@ use crate::pages::desktop::{
|
||||||
self, appearance, dock,
|
self, appearance, dock,
|
||||||
panel::{
|
panel::{
|
||||||
self,
|
self,
|
||||||
applets_inner::{self, AppletsPage, APPLET_DND_ICON_ID},
|
applets_inner::{self, APPLET_DND_ICON_ID},
|
||||||
inner as _panel,
|
inner as _panel,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use crate::pages::input::{self, keyboard};
|
use crate::pages::input::{self};
|
||||||
use crate::pages::{self, display, networking, sound, system, time};
|
use crate::pages::{self, display, sound, system, time};
|
||||||
use crate::subscription::desktop_files;
|
use crate::subscription::desktop_files;
|
||||||
use crate::widget::{page_title, search_header};
|
use crate::widget::{page_title, search_header};
|
||||||
use crate::PageCommands;
|
use crate::PageCommands;
|
||||||
use cosmic::app::DbusActivationMessage;
|
use cosmic::app::DbusActivationMessage;
|
||||||
|
use cosmic::iced::futures::SinkExt;
|
||||||
use cosmic::iced::Subscription;
|
use cosmic::iced::Subscription;
|
||||||
use cosmic::widget::{button, row, text_input};
|
use cosmic::widget::{button, row, text_input};
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
|
|
@ -42,6 +43,7 @@ pub struct SettingsApp {
|
||||||
config: Config,
|
config: Config,
|
||||||
core: Core,
|
core: Core,
|
||||||
nav_model: nav_bar::Model,
|
nav_model: nav_bar::Model,
|
||||||
|
page_sender: Option<tokio::sync::mpsc::Sender<crate::pages::Message>>,
|
||||||
pages: page::Binder<crate::pages::Message>,
|
pages: page::Binder<crate::pages::Message>,
|
||||||
search_active: bool,
|
search_active: bool,
|
||||||
search_id: cosmic::widget::Id,
|
search_id: cosmic::widget::Id,
|
||||||
|
|
@ -77,19 +79,21 @@ impl SettingsApp {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
|
CloseContextDrawer,
|
||||||
|
DelayedInit(page::Entity),
|
||||||
DesktopInfo,
|
DesktopInfo,
|
||||||
Error(String),
|
Error(String),
|
||||||
|
OpenContextDrawer(Cow<'static, str>),
|
||||||
Page(page::Entity),
|
Page(page::Entity),
|
||||||
PageMessage(crate::pages::Message),
|
PageMessage(crate::pages::Message),
|
||||||
PanelConfig(CosmicPanelConfig),
|
PanelConfig(CosmicPanelConfig),
|
||||||
|
RegisterSubscriptionSender(tokio::sync::mpsc::Sender<pages::Message>),
|
||||||
SearchActivate,
|
SearchActivate,
|
||||||
SearchChanged(String),
|
SearchChanged(String),
|
||||||
SearchClear,
|
SearchClear,
|
||||||
SearchSubmit,
|
SearchSubmit,
|
||||||
SetWindowTitle,
|
|
||||||
OpenContextDrawer(Cow<'static, str>),
|
|
||||||
CloseContextDrawer,
|
|
||||||
SetTheme(cosmic::theme::Theme),
|
SetTheme(cosmic::theme::Theme),
|
||||||
|
SetWindowTitle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl cosmic::Application for SettingsApp {
|
impl cosmic::Application for SettingsApp {
|
||||||
|
|
@ -113,6 +117,7 @@ impl cosmic::Application for SettingsApp {
|
||||||
config: Config::new(),
|
config: Config::new(),
|
||||||
core,
|
core,
|
||||||
nav_model: nav_bar::Model::default(),
|
nav_model: nav_bar::Model::default(),
|
||||||
|
page_sender: None,
|
||||||
pages: page::Binder::default(),
|
pages: page::Binder::default(),
|
||||||
search_active: false,
|
search_active: false,
|
||||||
search_id: cosmic::widget::Id::unique(),
|
search_id: cosmic::widget::Id::unique(),
|
||||||
|
|
@ -136,9 +141,10 @@ impl cosmic::Application for SettingsApp {
|
||||||
}
|
}
|
||||||
.unwrap_or(desktop_id);
|
.unwrap_or(desktop_id);
|
||||||
|
|
||||||
let command = app.activate_page(active_id);
|
(
|
||||||
|
app,
|
||||||
(app, command)
|
cosmic::command::message(cosmic::app::message::app(Message::DelayedInit(active_id))),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nav_model(&self) -> Option<&nav_bar::Model> {
|
fn nav_model(&self) -> Option<&nav_bar::Model> {
|
||||||
|
|
@ -208,6 +214,23 @@ impl cosmic::Application for SettingsApp {
|
||||||
});
|
});
|
||||||
|
|
||||||
Subscription::batch(vec![
|
Subscription::batch(vec![
|
||||||
|
// Creates a channel that listens to messages from pages.
|
||||||
|
// The sender is given back to the application so that it may pass it on.
|
||||||
|
cosmic::iced::subscription::channel(
|
||||||
|
std::any::TypeId::of::<Self>(),
|
||||||
|
4,
|
||||||
|
move |mut output| async move {
|
||||||
|
let (tx, mut rx) = tokio::sync::mpsc::channel::<pages::Message>(4);
|
||||||
|
|
||||||
|
let _res = output.send(Message::RegisterSubscriptionSender(tx)).await;
|
||||||
|
|
||||||
|
while let Some(event) = rx.recv().await {
|
||||||
|
let _res = output.send(Message::PageMessage(event)).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
futures::future::pending().await
|
||||||
|
},
|
||||||
|
),
|
||||||
crate::subscription::daytime().map(|daytime| {
|
crate::subscription::daytime().map(|daytime| {
|
||||||
Message::PageMessage(pages::Message::Appearance(appearance::Message::Daytime(
|
Message::PageMessage(pages::Message::Appearance(appearance::Message::Daytime(
|
||||||
daytime,
|
daytime,
|
||||||
|
|
@ -409,6 +432,21 @@ impl cosmic::Application for SettingsApp {
|
||||||
Message::Error(error) => {
|
Message::Error(error) => {
|
||||||
tracing::error!(error, "error occurred");
|
tracing::error!(error, "error occurred");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Message::RegisterSubscriptionSender(sender) => {
|
||||||
|
self.page_sender = Some(sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is necessary to delay init to allow time for the page sender to be initialized
|
||||||
|
Message::DelayedInit(active_id) => {
|
||||||
|
if self.page_sender.is_none() {
|
||||||
|
return cosmic::command::message(cosmic::app::message::app(
|
||||||
|
Message::DelayedInit(active_id),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.activate_page(active_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Command::none()
|
Command::none()
|
||||||
|
|
@ -438,7 +476,7 @@ impl cosmic::Application for SettingsApp {
|
||||||
} else if let Some(sub_pages) = self.pages.sub_pages(self.active_page) {
|
} else if let Some(sub_pages) = self.pages.sub_pages(self.active_page) {
|
||||||
self.sub_page_view(sub_pages)
|
self.sub_page_view(sub_pages)
|
||||||
} else {
|
} else {
|
||||||
panic!("page without sub-pages or content");
|
return row::row().into();
|
||||||
};
|
};
|
||||||
|
|
||||||
let padding = if self.core.is_condensed() {
|
let padding = if self.core.is_condensed() {
|
||||||
|
|
@ -518,9 +556,14 @@ impl SettingsApp {
|
||||||
self.search_active = false;
|
self.search_active = false;
|
||||||
self.activate_navbar(page);
|
self.activate_navbar(page);
|
||||||
|
|
||||||
|
let sender = self
|
||||||
|
.page_sender
|
||||||
|
.clone()
|
||||||
|
.expect("sender should be available");
|
||||||
|
|
||||||
let page_command = self
|
let page_command = self
|
||||||
.pages
|
.pages
|
||||||
.page_reload(page)
|
.on_enter(page, sender)
|
||||||
.map(Message::PageMessage)
|
.map(Message::PageMessage)
|
||||||
.map(cosmic::app::Message::App);
|
.map(cosmic::app::Message::App);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1087,7 +1087,11 @@ impl page::Page<crate::pages::Message> for Page {
|
||||||
.description(fl!("appearance", "desc"))
|
.description(fl!("appearance", "desc"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reload(&mut self, _: page::Entity) -> Command<crate::pages::Message> {
|
fn on_enter(
|
||||||
|
&mut self,
|
||||||
|
_: page::Entity,
|
||||||
|
sender: tokio::sync::mpsc::Sender<crate::pages::Message>,
|
||||||
|
) -> Command<crate::pages::Message> {
|
||||||
command::future(fetch_icon_themes()).map(crate::pages::Message::Appearance)
|
command::future(fetch_icon_themes()).map(crate::pages::Message::Appearance)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -207,7 +207,11 @@ impl page::Page<crate::pages::Message> for Page {
|
||||||
.description(fl!("wallpaper", "desc"))
|
.description(fl!("wallpaper", "desc"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reload(&mut self, _page: page::Entity) -> Command<crate::pages::Message> {
|
fn on_enter(
|
||||||
|
&mut self,
|
||||||
|
_page: page::Entity,
|
||||||
|
sender: tokio::sync::mpsc::Sender<crate::pages::Message>,
|
||||||
|
) -> Command<crate::pages::Message> {
|
||||||
let current_folder = self.config.current_folder().to_owned();
|
let current_folder = self.config.current_folder().to_owned();
|
||||||
|
|
||||||
let recurse = self.categories.selected == Some(Category::Wallpapers);
|
let recurse = self.categories.selected == Some(Category::Wallpapers);
|
||||||
|
|
|
||||||
|
|
@ -219,12 +219,20 @@ impl page::Page<crate::pages::Message> for Page {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "test"))]
|
#[cfg(not(feature = "test"))]
|
||||||
fn reload(&mut self, _page: page::Entity) -> Command<crate::pages::Message> {
|
fn on_enter(
|
||||||
command::future(reload())
|
&mut self,
|
||||||
|
_page: page::Entity,
|
||||||
|
sender: tokio::sync::mpsc::Sender<crate::pages::Message>,
|
||||||
|
) -> Command<crate::pages::Message> {
|
||||||
|
command::future(on_enter())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "test")]
|
#[cfg(feature = "test")]
|
||||||
fn reload(&mut self, _page: page::Entity) -> Command<crate::pages::Message> {
|
fn on_enter(
|
||||||
|
&mut self,
|
||||||
|
_page: page::Entity,
|
||||||
|
sender: tokio::sync::mpsc::Sender<crate::pages::Message>,
|
||||||
|
) -> Command<crate::pages::Message> {
|
||||||
command::future(async move {
|
command::future(async move {
|
||||||
let mut randr = List::default();
|
let mut randr = List::default();
|
||||||
|
|
||||||
|
|
@ -287,7 +295,7 @@ impl Page {
|
||||||
}
|
}
|
||||||
|
|
||||||
return cosmic::command::future(async {
|
return cosmic::command::future(async {
|
||||||
crate::Message::PageMessage(reload().await)
|
crate::Message::PageMessage(on_enter().await)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -805,7 +813,7 @@ fn cache_rates(cached_rates: &mut Vec<String>, rates: &[u32]) {
|
||||||
.collect();
|
.collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn reload() -> crate::pages::Message {
|
pub async fn on_enter() -> crate::pages::Message {
|
||||||
let graphics_fut = graphics::fetch();
|
let graphics_fut = graphics::fetch();
|
||||||
let randr_fut = cosmic_randr_shell::list();
|
let randr_fut = cosmic_randr_shell::list();
|
||||||
let (graphics, randr) = futures::future::zip(graphics_fut, randr_fut).await;
|
let (graphics, randr) = futures::future::zip(graphics_fut, randr_fut).await;
|
||||||
|
|
|
||||||
|
|
@ -250,7 +250,11 @@ impl page::Page<crate::pages::Message> for Page {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reload(&mut self, _page: page::Entity) -> Command<crate::pages::Message> {
|
fn on_enter(
|
||||||
|
&mut self,
|
||||||
|
_page: page::Entity,
|
||||||
|
sender: tokio::sync::mpsc::Sender<crate::pages::Message>,
|
||||||
|
) -> Command<crate::pages::Message> {
|
||||||
self.xkb = super::get_config(&self.config, "xkb_config");
|
self.xkb = super::get_config(&self.config, "xkb_config");
|
||||||
match xkb_data::keyboard_layouts() {
|
match xkb_data::keyboard_layouts() {
|
||||||
Ok(keyboard_layouts) => {
|
Ok(keyboard_layouts) => {
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,11 @@ impl page::Page<crate::pages::Message> for Page {
|
||||||
.description(fl!("about", "desc"))
|
.description(fl!("about", "desc"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reload(&mut self, _page: page::Entity) -> Command<crate::pages::Message> {
|
fn on_enter(
|
||||||
|
&mut self,
|
||||||
|
_page: page::Entity,
|
||||||
|
sender: tokio::sync::mpsc::Sender<crate::pages::Message>,
|
||||||
|
) -> Command<crate::pages::Message> {
|
||||||
command::future(async move {
|
command::future(async move {
|
||||||
crate::pages::Message::About(Message::Info(Box::new(Info::load())))
|
crate::pages::Message::About(Message::Info(Box::new(Info::load())))
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -11,4 +11,5 @@ libcosmic = { workspace = true }
|
||||||
generator = "0.7.5"
|
generator = "0.7.5"
|
||||||
downcast-rs = "1.2.0"
|
downcast-rs = "1.2.0"
|
||||||
once_cell = "1.19.0"
|
once_cell = "1.19.0"
|
||||||
url = "2.5.0"
|
tokio.workspace = true
|
||||||
|
url = "2.5.0"
|
||||||
|
|
@ -166,9 +166,13 @@ impl<Message: 'static> Binder<Message> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calls a page's load function to refresh its data.
|
/// Calls a page's load function to refresh its data.
|
||||||
pub fn page_reload(&mut self, id: crate::Entity) -> Command<Message> {
|
pub fn on_enter(
|
||||||
|
&mut self,
|
||||||
|
id: crate::Entity,
|
||||||
|
sender: tokio::sync::mpsc::Sender<Message>,
|
||||||
|
) -> Command<Message> {
|
||||||
if let Some(page) = self.page.get_mut(id) {
|
if let Some(page) = self.page.get_mut(id) {
|
||||||
return page.reload(id);
|
return page.on_enter(id, sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
Command::none()
|
Command::none()
|
||||||
|
|
|
||||||
|
|
@ -59,9 +59,12 @@ pub trait Page<Message: 'static>: Downcast {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reload page metadata via a Command.
|
/// Reload page metadata via a Command.
|
||||||
#[must_use]
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
fn reload(&mut self, page: crate::Entity) -> Command<Message> {
|
fn on_enter(
|
||||||
|
&mut self,
|
||||||
|
page: crate::Entity,
|
||||||
|
sender: tokio::sync::mpsc::Sender<Message>,
|
||||||
|
) -> Command<Message> {
|
||||||
Command::none()
|
Command::none()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue