From fa0ce598e5ede3becdf6880c401357c88a54433c Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Tue, 6 Aug 2024 12:34:59 +0200 Subject: [PATCH] feat(date-time): select timezones from searchable context drawer --- Cargo.lock | 34 +++---- cosmic-settings/src/app.rs | 4 +- .../src/pages/input/keyboard/mod.rs | 24 +---- cosmic-settings/src/pages/time/date.rs | 90 +++++++++++++++++-- cosmic-settings/src/widget/mod.rs | 18 +++- 5 files changed, 125 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7506805..c9bb037 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1369,7 +1369,7 @@ dependencies = [ [[package]] name = "cosmic-config" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#756f4b6ba69d11075eb0c34ea0fc837bd27ad63a" +source = "git+https://github.com/pop-os/libcosmic#4dd0f72f155b8705a30c2d42282f0bf1e5159e10" dependencies = [ "atomicwrites", "calloop 0.14.0", @@ -1392,7 +1392,7 @@ dependencies = [ [[package]] name = "cosmic-config-derive" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#756f4b6ba69d11075eb0c34ea0fc837bd27ad63a" +source = "git+https://github.com/pop-os/libcosmic#4dd0f72f155b8705a30c2d42282f0bf1e5159e10" dependencies = [ "quote", "syn 1.0.109", @@ -1602,7 +1602,7 @@ dependencies = [ [[package]] name = "cosmic-theme" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#756f4b6ba69d11075eb0c34ea0fc837bd27ad63a" +source = "git+https://github.com/pop-os/libcosmic#4dd0f72f155b8705a30c2d42282f0bf1e5159e10" dependencies = [ "almost", "cosmic-config", @@ -2888,7 +2888,7 @@ dependencies = [ [[package]] name = "iced" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#756f4b6ba69d11075eb0c34ea0fc837bd27ad63a" +source = "git+https://github.com/pop-os/libcosmic#4dd0f72f155b8705a30c2d42282f0bf1e5159e10" dependencies = [ "dnd", "iced_accessibility", @@ -2907,7 +2907,7 @@ dependencies = [ [[package]] name = "iced_accessibility" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#756f4b6ba69d11075eb0c34ea0fc837bd27ad63a" +source = "git+https://github.com/pop-os/libcosmic#4dd0f72f155b8705a30c2d42282f0bf1e5159e10" dependencies = [ "accesskit", "accesskit_unix", @@ -2916,7 +2916,7 @@ dependencies = [ [[package]] name = "iced_core" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#756f4b6ba69d11075eb0c34ea0fc837bd27ad63a" +source = "git+https://github.com/pop-os/libcosmic#4dd0f72f155b8705a30c2d42282f0bf1e5159e10" dependencies = [ "bitflags 2.6.0", "dnd", @@ -2938,7 +2938,7 @@ dependencies = [ [[package]] name = "iced_futures" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#756f4b6ba69d11075eb0c34ea0fc837bd27ad63a" +source = "git+https://github.com/pop-os/libcosmic#4dd0f72f155b8705a30c2d42282f0bf1e5159e10" dependencies = [ "futures", "iced_core", @@ -2951,7 +2951,7 @@ dependencies = [ [[package]] name = "iced_graphics" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#756f4b6ba69d11075eb0c34ea0fc837bd27ad63a" +source = "git+https://github.com/pop-os/libcosmic#4dd0f72f155b8705a30c2d42282f0bf1e5159e10" dependencies = [ "bitflags 2.6.0", "bytemuck", @@ -2975,7 +2975,7 @@ dependencies = [ [[package]] name = "iced_renderer" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#756f4b6ba69d11075eb0c34ea0fc837bd27ad63a" +source = "git+https://github.com/pop-os/libcosmic#4dd0f72f155b8705a30c2d42282f0bf1e5159e10" dependencies = [ "iced_graphics", "iced_tiny_skia", @@ -2987,7 +2987,7 @@ dependencies = [ [[package]] name = "iced_runtime" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#756f4b6ba69d11075eb0c34ea0fc837bd27ad63a" +source = "git+https://github.com/pop-os/libcosmic#4dd0f72f155b8705a30c2d42282f0bf1e5159e10" dependencies = [ "dnd", "iced_accessibility", @@ -3001,7 +3001,7 @@ dependencies = [ [[package]] name = "iced_sctk" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#756f4b6ba69d11075eb0c34ea0fc837bd27ad63a" +source = "git+https://github.com/pop-os/libcosmic#4dd0f72f155b8705a30c2d42282f0bf1e5159e10" dependencies = [ "enum-repr", "float-cmp", @@ -3027,7 +3027,7 @@ dependencies = [ [[package]] name = "iced_style" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#756f4b6ba69d11075eb0c34ea0fc837bd27ad63a" +source = "git+https://github.com/pop-os/libcosmic#4dd0f72f155b8705a30c2d42282f0bf1e5159e10" dependencies = [ "iced_core", "once_cell", @@ -3037,7 +3037,7 @@ dependencies = [ [[package]] name = "iced_tiny_skia" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#756f4b6ba69d11075eb0c34ea0fc837bd27ad63a" +source = "git+https://github.com/pop-os/libcosmic#4dd0f72f155b8705a30c2d42282f0bf1e5159e10" dependencies = [ "bytemuck", "cosmic-text", @@ -3054,7 +3054,7 @@ dependencies = [ [[package]] name = "iced_wgpu" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#756f4b6ba69d11075eb0c34ea0fc837bd27ad63a" +source = "git+https://github.com/pop-os/libcosmic#4dd0f72f155b8705a30c2d42282f0bf1e5159e10" dependencies = [ "as-raw-xcb-connection", "bitflags 2.6.0", @@ -3083,7 +3083,7 @@ dependencies = [ [[package]] name = "iced_widget" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#756f4b6ba69d11075eb0c34ea0fc837bd27ad63a" +source = "git+https://github.com/pop-os/libcosmic#4dd0f72f155b8705a30c2d42282f0bf1e5159e10" dependencies = [ "dnd", "iced_renderer", @@ -3100,7 +3100,7 @@ dependencies = [ [[package]] name = "iced_winit" version = "0.12.0" -source = "git+https://github.com/pop-os/libcosmic#756f4b6ba69d11075eb0c34ea0fc837bd27ad63a" +source = "git+https://github.com/pop-os/libcosmic#4dd0f72f155b8705a30c2d42282f0bf1e5159e10" dependencies = [ "dnd", "iced_graphics", @@ -3907,7 +3907,7 @@ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libcosmic" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#756f4b6ba69d11075eb0c34ea0fc837bd27ad63a" +source = "git+https://github.com/pop-os/libcosmic#4dd0f72f155b8705a30c2d42282f0bf1e5159e10" dependencies = [ "apply", "ashpd 0.9.1", diff --git a/cosmic-settings/src/app.rs b/cosmic-settings/src/app.rs index 58c2f43..a228765 100644 --- a/cosmic-settings/src/app.rs +++ b/cosmic-settings/src/app.rs @@ -308,7 +308,9 @@ impl cosmic::Application for SettingsApp { } crate::pages::Message::DateAndTime(message) => { - page::update!(self.pages, message, time::date::Page); + if let Some(page) = self.pages.page_mut::() { + return page.update(message).map(Into::into); + } } crate::pages::Message::Desktop(message) => { diff --git a/cosmic-settings/src/pages/input/keyboard/mod.rs b/cosmic-settings/src/pages/input/keyboard/mod.rs index 7c53129..68a5ead 100644 --- a/cosmic-settings/src/pages/input/keyboard/mod.rs +++ b/cosmic-settings/src/pages/input/keyboard/mod.rs @@ -611,11 +611,11 @@ fn special_character_entry() -> Section { let descriptions = §ion.descriptions; settings::view_section(§ion.title) - .add(go_next_item( + .add(crate::widget::go_next_item( &*descriptions[alternate], Message::OpenSpecialCharacterContext(SpecialKey::AlternateCharacters), )) - .add(go_next_item( + .add(crate::widget::go_next_item( &*descriptions[compose], Message::OpenSpecialCharacterContext(SpecialKey::Compose), )) @@ -641,7 +641,7 @@ fn keyboard_shortcuts() -> Section { .iter() .find(|(_, v)| v.id == "keyboard-shortcuts") { - section = section.add(go_next_item( + section = section.add(crate::widget::go_next_item( &descriptions[shortcuts_desc], crate::pages::Message::Page(shortcuts_entity), )); @@ -712,21 +712,3 @@ fn keyboard_typing_assist() -> Section { .map(crate::pages::Message::Keyboard) }) } - -fn go_next_control() -> cosmic::Element<'static, Msg> { - widget::row::with_children(vec![ - widget::horizontal_space(Length::Fill).into(), - icon::from_name("go-next-symbolic").size(16).icon().into(), - ]) - .into() -} - -fn go_next_item(description: &str, msg: Msg) -> cosmic::Element<'_, Msg> { - settings::item(description, go_next_control()) - .apply(widget::container) - .style(cosmic::theme::Container::List) - .apply(button) - .style(theme::Button::Transparent) - .on_press(msg) - .into() -} diff --git a/cosmic-settings/src/pages/time/date.rs b/cosmic-settings/src/pages/time/date.rs index 02fb446..0ea0866 100644 --- a/cosmic-settings/src/pages/time/date.rs +++ b/cosmic-settings/src/pages/time/date.rs @@ -6,8 +6,10 @@ use std::str::FromStr; use chrono::{Datelike, Timelike}; use cosmic::{ cosmic_config::{self, ConfigGet, ConfigSet}, + iced::Length, + iced_core::text::Wrap, widget::{self, dropdown, settings}, - Apply, Command, + Apply, Command, Element, }; use cosmic_settings_page::Section; use cosmic_settings_page::{self as page, section}; @@ -16,6 +18,7 @@ use icu::{ datetime::DateTimeFormatter, locid::Locale, }; +use itertools::Itertools; use slab::Slab; use slotmap::SlotMap; pub use timedate_zbus::TimeDateProxy; @@ -38,9 +41,11 @@ pub struct Page { military_time: bool, ntp_enabled: bool, show_date_in_top_panel: bool, + timezone_context: bool, local_time: Option>, timezone: Option, timezone_list: Vec, + timezone_search: String, formatted_date: String, } @@ -79,7 +84,9 @@ impl Default for Page { ntp_enabled: false, show_date_in_top_panel, timezone: None, + timezone_context: false, timezone_list: Vec::new(), + timezone_search: String::new(), } } } @@ -136,6 +143,14 @@ impl page::Page for Page { }) .map(crate::pages::Message::DateAndTime) } + + fn context_drawer(&self) -> Option> { + if self.timezone_context { + return Some(self.timezone_context_view()); + } + + None + } } impl Page { @@ -165,6 +180,14 @@ impl Page { }); } + Message::TimezoneContext => { + self.timezone_search.clear(); + self.timezone_context = true; + return cosmic::command::message(crate::app::Message::OpenContextDrawer( + fl!("time-zone").into(), + )); + } + Message::MilitaryTime(enable) => { self.military_time = enable; self.update_local_time(); @@ -193,6 +216,10 @@ impl Page { } } + Message::TimezoneSearch(text) => { + self.timezone_search = text; + } + Message::Timezone(timezone_id) => { self.timezone = Some(timezone_id); @@ -242,7 +269,40 @@ impl Page { Command::none() } - pub fn update_local_time(&mut self) { + fn timezone_context_view(&self) -> Element<'_, crate::pages::Message> { + let search = widget::search_input(fl!("type-to-search"), &self.timezone_search) + .on_input(Message::TimezoneSearch) + .on_clear(Message::TimezoneSearch(String::new())); + + let mut list = widget::list_column(); + + let search_input = &self.timezone_search.trim().to_lowercase(); + + for (id, timezone) in self.timezone_list.iter().enumerate() { + if search_input.is_empty() || timezone.to_lowercase().contains(search_input) { + list = list.add(self.timezone_context_item(id, timezone)); + } + } + + widget::column() + .spacing(32) + .push(search) + .push(widget::container(list).apply(widget::container)) + .apply(Element::from) + .map(crate::pages::Message::DateAndTime) + } + + fn timezone_context_item<'a>(&self, id: usize, timezone: &'a str) -> Element<'a, Message> { + widget::button(widget::settings::item_row(vec![ + widget::text::body(timezone).wrap(Wrap::Word).into(), + widget::horizontal_space(Length::Fill).into(), + ])) + .on_press(Message::Timezone(id)) + .style(cosmic::theme::Button::Icon) + .into() + } + + fn update_local_time(&mut self) { self.local_time = Some(update_local_time()); self.formatted_date = match self.local_time { @@ -262,6 +322,8 @@ pub enum Message { Refresh(Info), ShowDate(bool), Timezone(usize), + TimezoneContext, + TimezoneSearch(String), UpdateTime, } @@ -347,12 +409,30 @@ fn timezone() -> Section { .title(fl!("time-zone")) .descriptions(descriptions) .view::(move |_binder, page, section| { + let timezone_context_button = settings::item_row(vec![ + widget::text( + page.timezone + .map(|id| &*page.timezone_list[id]) + .unwrap_or_default(), + ) + .wrap(Wrap::Word) + .into(), + widget::icon::from_name("go-next-symbolic") + .size(16) + .icon() + .into(), + ]) + .apply(widget::container) + .style(cosmic::theme::Container::List) + .apply(widget::button) + .style(cosmic::theme::Button::Transparent) + .on_press(Message::TimezoneContext); + settings::view_section(§ion.title) // Time zone select .add( - settings::item::builder(&*section.descriptions[time_zone]).control( - widget::dropdown(&page.timezone_list, page.timezone, Message::Timezone), - ), + settings::item::builder(&*section.descriptions[time_zone]) + .control(timezone_context_button), ) .apply(cosmic::Element::from) .map(crate::pages::Message::DateAndTime) diff --git a/cosmic-settings/src/widget/mod.rs b/cosmic-settings/src/widget/mod.rs index 660f59f..cbd0333 100644 --- a/cosmic-settings/src/widget/mod.rs +++ b/cosmic-settings/src/widget/mod.rs @@ -2,8 +2,10 @@ // SPDX-License-Identifier: GPL-3.0-only use cosmic::iced::Length; +use cosmic::iced_core::text::Wrap; use cosmic::widget::{ - button, column, container, divider, horizontal_space, icon, row, settings, text, vertical_space, + self, button, column, container, divider, horizontal_space, icon, row, settings, text, + vertical_space, }; use cosmic::{theme, Apply, Element}; use cosmic_settings_page as page; @@ -120,3 +122,17 @@ pub fn sub_page_header<'a, Message: 'static + Clone>( .width(Length::Shrink) .into() } + +pub fn go_next_item(description: &str, msg: Msg) -> cosmic::Element<'_, Msg> { + settings::item_row(vec![ + text(description).wrap(Wrap::Word).into(), + horizontal_space(Length::Fill).into(), + icon::from_name("go-next-symbolic").size(16).icon().into(), + ]) + .apply(widget::container) + .style(cosmic::theme::Container::List) + .apply(button) + .style(theme::Button::Transparent) + .on_press(msg) + .into() +}