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",
|
||||
"regex",
|
||||
"slotmap",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ resolver = "2"
|
|||
rust-version = "1.71.0"
|
||||
sunrise_sunset = "1.0.1"
|
||||
|
||||
[workspace.dependencies]
|
||||
tokio = { version = "1.37.0", features = ["macros"] }
|
||||
|
||||
[workspace.dependencies.libcosmic]
|
||||
git = "https://github.com/pop-os/libcosmic"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ license = "GPL-3.0"
|
|||
rust-version = "1.65.0"
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1.35.1", features = ["macros"] }
|
||||
tokio.workspace = true
|
||||
async-channel = "2.1.1"
|
||||
color-eyre = "0.6.2"
|
||||
cosmic-bg-config = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -6,16 +6,17 @@ use crate::pages::desktop::{
|
|||
self, appearance, dock,
|
||||
panel::{
|
||||
self,
|
||||
applets_inner::{self, AppletsPage, APPLET_DND_ICON_ID},
|
||||
applets_inner::{self, APPLET_DND_ICON_ID},
|
||||
inner as _panel,
|
||||
},
|
||||
};
|
||||
use crate::pages::input::{self, keyboard};
|
||||
use crate::pages::{self, display, networking, sound, system, time};
|
||||
use crate::pages::input::{self};
|
||||
use crate::pages::{self, display, sound, system, time};
|
||||
use crate::subscription::desktop_files;
|
||||
use crate::widget::{page_title, search_header};
|
||||
use crate::PageCommands;
|
||||
use cosmic::app::DbusActivationMessage;
|
||||
use cosmic::iced::futures::SinkExt;
|
||||
use cosmic::iced::Subscription;
|
||||
use cosmic::widget::{button, row, text_input};
|
||||
use cosmic::{
|
||||
|
|
@ -42,6 +43,7 @@ pub struct SettingsApp {
|
|||
config: Config,
|
||||
core: Core,
|
||||
nav_model: nav_bar::Model,
|
||||
page_sender: Option<tokio::sync::mpsc::Sender<crate::pages::Message>>,
|
||||
pages: page::Binder<crate::pages::Message>,
|
||||
search_active: bool,
|
||||
search_id: cosmic::widget::Id,
|
||||
|
|
@ -77,19 +79,21 @@ impl SettingsApp {
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Message {
|
||||
CloseContextDrawer,
|
||||
DelayedInit(page::Entity),
|
||||
DesktopInfo,
|
||||
Error(String),
|
||||
OpenContextDrawer(Cow<'static, str>),
|
||||
Page(page::Entity),
|
||||
PageMessage(crate::pages::Message),
|
||||
PanelConfig(CosmicPanelConfig),
|
||||
RegisterSubscriptionSender(tokio::sync::mpsc::Sender<pages::Message>),
|
||||
SearchActivate,
|
||||
SearchChanged(String),
|
||||
SearchClear,
|
||||
SearchSubmit,
|
||||
SetWindowTitle,
|
||||
OpenContextDrawer(Cow<'static, str>),
|
||||
CloseContextDrawer,
|
||||
SetTheme(cosmic::theme::Theme),
|
||||
SetWindowTitle,
|
||||
}
|
||||
|
||||
impl cosmic::Application for SettingsApp {
|
||||
|
|
@ -113,6 +117,7 @@ impl cosmic::Application for SettingsApp {
|
|||
config: Config::new(),
|
||||
core,
|
||||
nav_model: nav_bar::Model::default(),
|
||||
page_sender: None,
|
||||
pages: page::Binder::default(),
|
||||
search_active: false,
|
||||
search_id: cosmic::widget::Id::unique(),
|
||||
|
|
@ -136,9 +141,10 @@ impl cosmic::Application for SettingsApp {
|
|||
}
|
||||
.unwrap_or(desktop_id);
|
||||
|
||||
let command = app.activate_page(active_id);
|
||||
|
||||
(app, command)
|
||||
(
|
||||
app,
|
||||
cosmic::command::message(cosmic::app::message::app(Message::DelayedInit(active_id))),
|
||||
)
|
||||
}
|
||||
|
||||
fn nav_model(&self) -> Option<&nav_bar::Model> {
|
||||
|
|
@ -208,6 +214,23 @@ impl cosmic::Application for SettingsApp {
|
|||
});
|
||||
|
||||
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| {
|
||||
Message::PageMessage(pages::Message::Appearance(appearance::Message::Daytime(
|
||||
daytime,
|
||||
|
|
@ -409,6 +432,21 @@ impl cosmic::Application for SettingsApp {
|
|||
Message::Error(error) => {
|
||||
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()
|
||||
|
|
@ -438,7 +476,7 @@ impl cosmic::Application for SettingsApp {
|
|||
} else if let Some(sub_pages) = self.pages.sub_pages(self.active_page) {
|
||||
self.sub_page_view(sub_pages)
|
||||
} else {
|
||||
panic!("page without sub-pages or content");
|
||||
return row::row().into();
|
||||
};
|
||||
|
||||
let padding = if self.core.is_condensed() {
|
||||
|
|
@ -518,9 +556,14 @@ impl SettingsApp {
|
|||
self.search_active = false;
|
||||
self.activate_navbar(page);
|
||||
|
||||
let sender = self
|
||||
.page_sender
|
||||
.clone()
|
||||
.expect("sender should be available");
|
||||
|
||||
let page_command = self
|
||||
.pages
|
||||
.page_reload(page)
|
||||
.on_enter(page, sender)
|
||||
.map(Message::PageMessage)
|
||||
.map(cosmic::app::Message::App);
|
||||
|
||||
|
|
|
|||
|
|
@ -1087,7 +1087,11 @@ impl page::Page<crate::pages::Message> for Page {
|
|||
.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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -207,7 +207,11 @@ impl page::Page<crate::pages::Message> for Page {
|
|||
.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 recurse = self.categories.selected == Some(Category::Wallpapers);
|
||||
|
|
|
|||
|
|
@ -219,12 +219,20 @@ impl page::Page<crate::pages::Message> for Page {
|
|||
}
|
||||
|
||||
#[cfg(not(feature = "test"))]
|
||||
fn reload(&mut self, _page: page::Entity) -> Command<crate::pages::Message> {
|
||||
command::future(reload())
|
||||
fn on_enter(
|
||||
&mut self,
|
||||
_page: page::Entity,
|
||||
sender: tokio::sync::mpsc::Sender<crate::pages::Message>,
|
||||
) -> Command<crate::pages::Message> {
|
||||
command::future(on_enter())
|
||||
}
|
||||
|
||||
#[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 {
|
||||
let mut randr = List::default();
|
||||
|
||||
|
|
@ -287,7 +295,7 @@ impl Page {
|
|||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
pub async fn reload() -> crate::pages::Message {
|
||||
pub async fn on_enter() -> crate::pages::Message {
|
||||
let graphics_fut = graphics::fetch();
|
||||
let randr_fut = cosmic_randr_shell::list();
|
||||
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");
|
||||
match xkb_data::keyboard_layouts() {
|
||||
Ok(keyboard_layouts) => {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,11 @@ impl page::Page<crate::pages::Message> for Page {
|
|||
.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 {
|
||||
crate::pages::Message::About(Message::Info(Box::new(Info::load())))
|
||||
})
|
||||
|
|
|
|||
|
|
@ -11,4 +11,5 @@ libcosmic = { workspace = true }
|
|||
generator = "0.7.5"
|
||||
downcast-rs = "1.2.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.
|
||||
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) {
|
||||
return page.reload(id);
|
||||
return page.on_enter(id, sender);
|
||||
}
|
||||
|
||||
Command::none()
|
||||
|
|
|
|||
|
|
@ -59,9 +59,12 @@ pub trait Page<Message: 'static>: Downcast {
|
|||
}
|
||||
|
||||
/// Reload page metadata via a Command.
|
||||
#[must_use]
|
||||
#[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()
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue