Skip to content

Commit

Permalink
feat: dynamically load pages when their sections are searched
Browse files Browse the repository at this point in the history
  • Loading branch information
mmstick committed Oct 24, 2024
1 parent 6463983 commit 51bd56d
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 10 deletions.
55 changes: 52 additions & 3 deletions cosmic-settings/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,14 @@ use desktop::{
#[cfg(feature = "wayland")]
use event::wayland;
use page::Entity;
use std::collections::BTreeSet;
use std::{borrow::Cow, str::FromStr};

#[allow(clippy::struct_excessive_bools)]
#[allow(clippy::module_name_repetitions)]
pub struct SettingsApp {
active_page: page::Entity,
loaded_pages: BTreeSet<page::Entity>,
config: Config,
core: Core,
nav_model: nav_bar::Model,
Expand Down Expand Up @@ -167,6 +169,7 @@ impl cosmic::Application for SettingsApp {
fn init(core: Core, flags: Self::Flags) -> (Self, Task<Self::Message>) {
let mut app = SettingsApp {
active_page: page::Entity::default(),
loaded_pages: BTreeSet::new(),
config: Config::new(),
core,
nav_model: nav_bar::Model::default(),
Expand Down Expand Up @@ -337,7 +340,7 @@ impl cosmic::Application for SettingsApp {
Message::SetWindowTitle => return self.set_title(),

Message::SearchChanged(phrase) => {
self.search_changed(phrase);
return self.search_changed(phrase);
}

Message::SearchActivate => {
Expand Down Expand Up @@ -781,6 +784,7 @@ impl SettingsApp {
let mut leave_task = iced::Task::none();

if current_page != page {
self.loaded_pages.remove(&current_page);
leave_task = self
.pages
.on_leave(current_page)
Expand All @@ -801,6 +805,8 @@ impl SettingsApp {
.clone()
.expect("sender should be available");

self.loaded_pages.insert(page);

let page_task = self
.pages
.on_enter(page, sender)
Expand Down Expand Up @@ -920,13 +926,15 @@ impl SettingsApp {
.into()
}

fn search_changed(&mut self, phrase: String) {
fn search_changed(&mut self, phrase: String) -> Task<crate::Message> {
// If the text was cleared, clear the search results too.
if phrase.is_empty() {
self.search_clear();
return;
return Task::none();
}

let mut tasks = Vec::new();

// Create a case-insensitive regular expression for the search function.
let search_expression = regex::RegexBuilder::new(&phrase)
.case_insensitive(true)
Expand All @@ -942,10 +950,51 @@ impl SettingsApp {
// Use the results if results were found.
if !results.is_empty() {
self.search_selections = results;

let mut unload = BTreeSet::new();
let mut load = BTreeSet::new();

'outer: for loaded_page in &self.loaded_pages {
for (page, _) in &self.search_selections {
if loaded_page == page {
continue 'outer;
}
}

unload.insert(*loaded_page);
}

for (page, _) in &self.search_selections {
if !self.loaded_pages.contains(page) {
load.insert(*page);
}
}

if let Some(ref sender) = self.page_sender {
for page in load {
eprintln!("loading {page:?}");
self.loaded_pages.insert(page);
tasks.push(self.pages.on_enter(page, sender.clone()));
}
}

for page in unload {
eprintln!("unloading {page:?}");
self.loaded_pages.remove(&page);
self.pages.on_leave(page);
}
}
}

self.search_input = phrase;

if tasks.is_empty() {
Task::none()
} else {
cosmic::command::batch(tasks)
.map(Message::PageMessage)
.map(Into::into)
}
}

/// Clears the search results so that the search page will not be shown.
Expand Down
12 changes: 11 additions & 1 deletion cosmic-settings/src/pages/desktop/appearance/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ enum ContextView {
}

pub struct Page {
on_enter_handle: Option<cosmic::iced::task::Handle>,
can_reset: bool,
no_custom_window_hint: bool,
context_view: Option<ContextView>,
Expand Down Expand Up @@ -152,6 +153,7 @@ impl
});

Self {
on_enter_handle: None,
can_reset: if theme_mode.is_dark {
theme_builder == ThemeBuilder::dark()
} else {
Expand Down Expand Up @@ -1431,7 +1433,7 @@ impl page::Page<crate::pages::Message> for Page {
_: page::Entity,
_sender: tokio::sync::mpsc::Sender<crate::pages::Message>,
) -> Task<crate::pages::Message> {
cosmic::command::batch(vec![
let (task, handle) = cosmic::command::batch(vec![
// Load icon themes
cosmic::command::future(icon_themes::fetch()).map(crate::pages::Message::Appearance),
// Load font families
Expand All @@ -1441,9 +1443,17 @@ impl page::Page<crate::pages::Message> for Page {
})
.map(crate::pages::Message::Appearance),
])
.abortable();

self.on_enter_handle = Some(handle);
task
}

fn on_leave(&mut self) -> Task<crate::pages::Message> {
if let Some(handle) = self.on_enter_handle.take() {
handle.abort();
}

cosmic::command::message(crate::pages::Message::Appearance(Message::Left))
}

Expand Down
24 changes: 23 additions & 1 deletion cosmic-settings/src/pages/desktop/wallpaper/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ enum ContextView {

/// The page struct for the wallpaper view.
pub struct Page {
/// Abort handle to the on_enter task.
on_enter_handle: Option<cosmic::iced::task::Handle>,

/// Whether to show a context drawer.
context_view: Option<ContextView>,

Expand Down Expand Up @@ -207,11 +210,16 @@ impl page::Page<crate::pages::Message> for Page {
_page: page::Entity,
_sender: tokio::sync::mpsc::Sender<crate::pages::Message>,
) -> Task<crate::pages::Message> {
// Check if the page is already being loaded.
if self.on_enter_handle.is_some() {
return Task::none();
}

let current_folder = self.config.current_folder().to_owned();

let recurse = self.categories.selected == Some(Category::Wallpapers);

Task::future(async move {
let (task, on_enter_handle) = Task::future(async move {
let (service_config, displays) = wallpaper::config().await;

let mut selection = change_folder(current_folder, recurse).await;
Expand Down Expand Up @@ -245,6 +253,19 @@ impl page::Page<crate::pages::Message> for Page {
selection,
})))
})
.abortable();

self.on_enter_handle = Some(on_enter_handle);
task
}

fn on_leave(&mut self) -> Task<crate::pages::Message> {
// Cancel the on_enter task if it was running.
if let Some(handle) = self.on_enter_handle.take() {
handle.abort();
}

Task::none()
}

fn context_drawer(&self) -> Option<Element<'_, crate::pages::Message>> {
Expand All @@ -265,6 +286,7 @@ impl page::AutoBind<crate::pages::Message> for Page {}
impl Default for Page {
fn default() -> Self {
let mut page = Page {
on_enter_handle: None,
context_view: None,
show_tab_bar: false,
active_output: None,
Expand Down
1 change: 0 additions & 1 deletion cosmic-settings/src/pages/networking/vpn/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,6 @@ pub struct Page {
dialog: Option<VpnDialog>,
view_more_popup: Option<ConnectionId>,
known_connections: IndexMap<UUID, ConnectionSettings>,
wireguard_connections: IndexMap<UUID, String>,
/// Withhold device update if the view more popup is shown.
withheld_devices: Option<Vec<network_manager::devices::DeviceInfo>>,
/// Withhold active connections update if the view more popup is shown.
Expand Down
16 changes: 15 additions & 1 deletion cosmic-settings/src/pages/power/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use slotmap::SlotMap;
pub struct Page {
battery: Battery,
connected_devices: Vec<ConnectedDevice>,
on_enter_handle: Option<cosmic::iced::task::Handle>,
}

impl page::Page<crate::pages::Message> for Page {
Expand Down Expand Up @@ -54,7 +55,20 @@ impl page::Page<crate::pages::Message> for Page {
}),
];

cosmic::Task::batch(futures).map(crate::pages::Message::Power)
let (task, handle) = cosmic::Task::batch(futures)
.map(crate::pages::Message::Power)
.abortable();

self.on_enter_handle = Some(handle);
task
}

fn on_leave(&mut self) -> Task<crate::pages::Message> {
if let Some(handle) = self.on_enter_handle.take() {
handle.abort();
}

Task::none()
}
}

Expand Down
19 changes: 16 additions & 3 deletions cosmic-settings/src/pages/system/about.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub enum Message {
pub struct Page {
editing_device_name: bool,
info: Info,
on_enter_handle: Option<cosmic::iced::task::Handle>,
}

impl page::AutoBind<crate::pages::Message> for Page {}
Expand Down Expand Up @@ -48,9 +49,21 @@ impl page::Page<crate::pages::Message> for Page {
_page: page::Entity,
_sender: tokio::sync::mpsc::Sender<crate::pages::Message>,
) -> Task<crate::pages::Message> {
Task::future(
async move { crate::pages::Message::About(Message::Info(Box::new(Info::load()))) },
)
let (task, handle) = Task::future(async move {
crate::pages::Message::About(Message::Info(Box::new(Info::load())))
})
.abortable();

self.on_enter_handle = Some(handle);
task
}

fn on_leave(&mut self) -> Task<crate::pages::Message> {
if let Some(handle) = self.on_enter_handle.take() {
handle.abort();
}

Task::none()
}
}

Expand Down

0 comments on commit 51bd56d

Please sign in to comment.