feat: refactor the settings page architecture

This commit is contained in:
Michael Aaron Murphy 2023-04-25 00:30:50 +02:00
parent efdd934e62
commit c015ad9948
No known key found for this signature in database
GPG key ID: B2732D4240C9212C
55 changed files with 2212 additions and 1635 deletions

View file

@ -0,0 +1,26 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use cosmic_settings_page::Section;
use cosmic_settings_page::{self as page, section};
use slotmap::SlotMap;
#[derive(Default)]
pub struct Page;
impl page::Page<crate::pages::Message> for Page {
fn content(
&self,
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
) -> Option<page::Content> {
Some(vec![sections.insert(Section::default())])
}
fn info(&self) -> page::Info {
page::Info::new("appearance", "preferences-pop-desktop-appearance-symbolic")
.title(fl!("appearance"))
.description(fl!("appearance", "desc"))
}
}
impl page::AutoBind<crate::pages::Message> for Page {}

View file

@ -0,0 +1,26 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use cosmic_settings_page::Section;
use cosmic_settings_page::{self as page, section};
use slotmap::SlotMap;
#[derive(Default)]
pub struct Page;
impl page::Page<crate::pages::Message> for Page {
fn content(
&self,
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
) -> Option<page::Content> {
Some(vec![sections.insert(Section::default())])
}
fn info(&self) -> page::Info {
page::Info::new("dock", "preferences-pop-desktop-dock-symbolic")
.title(fl!("dock"))
.description(fl!("dock", "desc"))
}
}
impl page::AutoBind<crate::pages::Message> for Page {}

View file

@ -0,0 +1,113 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
pub mod appearance;
pub mod dock;
pub mod notifications;
pub mod options;
pub mod wallpaper;
pub mod workspaces;
use cosmic_settings_page as page;
#[derive(Debug, Default)]
#[allow(clippy::struct_excessive_bools)]
pub struct Page {
pub top_left_hot_corner: bool,
pub show_workspaces_button: bool,
pub show_applications_button: bool,
pub show_minimize_button: bool,
pub show_maximize_button: bool,
pub slideshow: bool,
pub same_background: bool,
}
impl page::Page<crate::pages::Message> for Page {
fn info(&self) -> page::Info {
page::Info::new("desktop", "video-display-symbolic").title(fl!("desktop"))
}
}
impl page::AutoBind<crate::pages::Message> for Page {
fn sub_pages(page: page::Insert<crate::pages::Message>) -> page::Insert<crate::pages::Message> {
page.sub_page::<options::Page>()
.sub_page::<wallpaper::Page>()
.sub_page::<appearance::Page>()
.sub_page::<dock::Page>()
.sub_page::<workspaces::Page>()
.sub_page::<notifications::Page>()
}
}
#[derive(Clone, Copy, Debug)]
pub enum Message {
Slideshow(bool),
SameBackground(bool),
ShowWorkspacesButton(bool),
ShowApplicationsButton(bool),
ShowMinimizeButton(bool),
ShowMaximizeButton(bool),
TopLeftHotCorner(bool),
}
impl Page {
pub fn update(&mut self, message: Message) {
match message {
Message::SameBackground(value) => self.same_background = value,
Message::ShowApplicationsButton(value) => self.show_applications_button = value,
Message::ShowMaximizeButton(value) => self.show_maximize_button = value,
Message::ShowMinimizeButton(value) => self.show_minimize_button = value,
Message::ShowWorkspacesButton(value) => self.show_workspaces_button = value,
Message::Slideshow(value) => self.slideshow = value,
Message::TopLeftHotCorner(value) => self.top_left_hot_corner = value,
}
}
}
// impl From<page::Info> for Message {
// fn from(page: page::Info) -> Message {
// Message::page::Info(page)
// }
// }
// pub enum Output {
// page::Info(page::Info),
// }
// impl Subpage::Info for Desktoppage::Info {
// //TODO: translate
// fn title(&self) -> &'static str {
// use Desktoppage::Info::*;
// match self {
// Workspaces => "Workspaces",
// Notifications => "Notifications",
// }
// }
// //TODO: translate
// fn description(&self) -> &'static str {
// use Desktoppage::Info::*;
// match self {
// Workspaces => "Set workspace number, behavior, and placement.",
// Notifications => {
// "Do Not Disturb, lockscreen notifications, and per-application settings."
// }
// }
// }
// fn icon_name(&self) -> &'static str {
// use Desktoppage::Info::*;
// match self {
// Workspaces => "preferences-pop-desktop-workspaces-symbolic",
// Notifications => "preferences-system-notifications-symbolic",
// }
// }
// fn parent_page(&self) -> page::Info {
// page::Info::Desktop(None)
// }
// fn into_page(self) -> page::Info {
// page::Info::Desktop(Some(self))
// }
// }

View file

@ -0,0 +1,26 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use cosmic_settings_page::Section;
use cosmic_settings_page::{self as page, section};
use slotmap::SlotMap;
#[derive(Default)]
pub struct Page;
impl page::Page<crate::pages::Message> for Page {
fn content(
&self,
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
) -> Option<page::Content> {
Some(vec![sections.insert(Section::default())])
}
fn info(&self) -> page::Info {
page::Info::new("notifications", "preferences-system-notifications-symbolic")
.title(fl!("notifications"))
.description(fl!("notifications", "desc"))
}
}
impl page::AutoBind<crate::pages::Message> for Page {}

View file

@ -0,0 +1,161 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use super::Message;
use apply::Apply;
use cosmic::{
iced::widget::horizontal_space,
iced::Length,
widget::{settings, toggler},
Element,
};
use cosmic_settings_page::Section;
use cosmic_settings_page::{self as page, section};
use slotmap::SlotMap;
#[derive(Default)]
pub struct Page;
impl page::Page<crate::pages::Message> for Page {
#[allow(clippy::too_many_lines)]
fn content(
&self,
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
) -> Option<page::Content> {
Some(vec![
sections.insert(super_key_action()),
sections.insert(hot_corner()),
sections.insert(top_panel()),
sections.insert(window_controls()),
])
}
fn info(&self) -> page::Info {
page::Info::new("desktop-options", "video-display-symbolic")
.title(fl!("desktop-options"))
.description(fl!("desktop-options", "desc"))
}
}
impl page::AutoBind<crate::pages::Message> for Page {}
pub fn hot_corner() -> Section<crate::pages::Message> {
Section::default()
.title(fl!("hot-corner"))
.descriptions(vec![fl!("hot-corner", "top-left-corner")])
.view::<Page>(|binder, _page, section| {
let desktop = binder
.page::<super::Page>()
.expect("desktop page not found");
let descriptions = &section.descriptions;
settings::view_section(&section.title)
.add(settings::item(
&descriptions[0],
toggler(None, desktop.top_left_hot_corner, |value| {
Message::TopLeftHotCorner(value)
}),
))
.apply(Element::from)
.map(crate::pages::Message::Desktop)
})
}
pub fn super_key_action() -> Section<crate::pages::Message> {
Section::default()
.title(fl!("super-key-action"))
.descriptions(vec![
fl!("super-key-action", "launcher"),
fl!("super-key-action", "workspaces"),
fl!("super-key-action", "applications"),
])
.view::<Page>(|_binder, _page, section| {
let descriptions = &section.descriptions;
settings::view_section(&section.title)
.add(settings::item(
&descriptions[0],
horizontal_space(Length::Fill),
))
.add(settings::item(
&descriptions[1],
horizontal_space(Length::Fill),
))
.add(settings::item(
&descriptions[2],
horizontal_space(Length::Fill),
))
.into()
})
}
pub fn top_panel() -> Section<crate::pages::Message> {
Section::default()
.title(fl!("top-panel"))
.descriptions(vec![
fl!("top-panel", "workspaces"),
fl!("top-panel", "applications"),
])
.view::<Page>(|binder, _page, section| {
let desktop = binder
.page::<super::Page>()
.expect("desktop page not found");
let descriptions = &section.descriptions;
settings::view_section(&section.title)
.add(settings::item(
&descriptions[0],
toggler(
None,
desktop.show_workspaces_button,
Message::ShowWorkspacesButton,
),
))
.add(settings::item(
&descriptions[1],
toggler(
None,
desktop.show_applications_button,
Message::ShowApplicationsButton,
),
))
.apply(Element::from)
.map(crate::pages::Message::Desktop)
})
}
pub fn window_controls() -> Section<crate::pages::Message> {
Section::default()
.title(fl!("window-controls"))
.descriptions(vec![
fl!("window-controls", "minimize"),
fl!("window-controls", "maximize"),
])
.view::<Page>(|binder, _page, section| {
let desktop = binder
.page::<super::Page>()
.expect("desktop page not found");
let descriptions = &section.descriptions;
settings::view_section(&section.title)
.add(settings::item(
&descriptions[0],
toggler(
None,
desktop.show_minimize_button,
Message::ShowMinimizeButton,
),
))
.add(settings::item(
&descriptions[1],
toggler(
None,
desktop.show_maximize_button,
Message::ShowMaximizeButton,
),
))
.apply(Element::from)
.map(crate::pages::Message::Desktop)
})
}

View file

@ -0,0 +1,98 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use super::Message;
use apply::Apply;
use cosmic::{
iced::widget::{column, container, horizontal_space, image, row, svg, text},
iced::Length,
theme,
widget::{list_column, settings, toggler},
Element,
};
use cosmic_settings_page::Section;
use cosmic_settings_page::{self as page, section};
use slotmap::SlotMap;
#[derive(Default)]
pub struct Page;
impl page::Page<crate::pages::Message> for Page {
fn content(
&self,
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
) -> Option<page::Content> {
Some(vec![sections.insert(settings())])
}
fn info(&self) -> page::Info {
page::Info::new("wallpaper", "preferences-desktop-wallpaper-symbolic")
.title(fl!("wallpaper"))
.description(fl!("wallpaper", "desc"))
}
}
impl page::AutoBind<crate::pages::Message> for Page {}
pub fn settings() -> Section<crate::pages::Message> {
Section::default()
.descriptions(vec![
fl!("wallpaper", "same"),
fl!("wallpaper", "fit"),
fl!("wallpaper", "slide"),
fl!("wallpaper", "change"),
])
.view::<Page>(|binder, _page, section| {
let desktop = binder
.page::<super::Page>()
.expect("desktop page not found");
let descriptions = &section.descriptions;
let image_paths: Vec<std::path::PathBuf> = Vec::new();
let mut image_column = Vec::with_capacity(image_paths.len() / 4);
for chunk in image_paths.chunks(4) {
let mut image_row = Vec::with_capacity(chunk.len());
for image_path in chunk.iter() {
image_row.push(if image_path.ends_with(".svg") {
svg(svg::Handle::from_path(image_path))
.width(Length::Units(150))
.into()
} else {
image(image_path).width(Length::Units(150)).into()
});
}
image_column.push(row(image_row).spacing(16).into());
}
let children = vec![
row!(
horizontal_space(Length::Fill),
container(
image("/usr/share/backgrounds/pop/kate-hazen-COSMIC-desktop-wallpaper.png")
.width(Length::Units(300))
)
.padding(4)
.style(theme::Container::Box),
horizontal_space(Length::Fill),
)
.into(),
list_column()
.add(settings::item(
&descriptions[0],
toggler(None, desktop.same_background, Message::SameBackground),
))
.add(settings::item(&descriptions[1], text("TODO")))
.add(settings::item(
&descriptions[2],
toggler(None, desktop.slideshow, Message::Slideshow),
))
.into(),
column(image_column).spacing(16).into(),
];
settings::view_column(children)
.padding(0)
.apply(Element::from)
.map(crate::pages::Message::Desktop)
})
}

View file

@ -0,0 +1,76 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use cosmic::iced::{widget::horizontal_space, Length};
use cosmic::widget::settings;
use cosmic_settings_page::Section;
use cosmic_settings_page::{self as page, section};
use slotmap::SlotMap;
#[derive(Default)]
pub struct Page;
impl page::Page<crate::pages::Message> for Page {
fn content(
&self,
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
) -> Option<page::Content> {
Some(vec![
sections.insert(behavior()),
sections.insert(multi_behavior()),
])
}
fn info(&self) -> page::Info {
page::Info::new("workspaces", "preferences-pop-desktop-workspaces-symbolic")
.title(fl!("workspaces"))
.description(fl!("workspaces", "desc"))
}
}
impl page::AutoBind<crate::pages::Message> for Page {}
fn behavior() -> Section<crate::pages::Message> {
Section::default()
.title(fl!("workspaces-behavior"))
.descriptions(vec![
fl!("workspaces-behavior", "dynamic"),
fl!("workspaces-behavior", "fixed"),
])
.view::<Page>(|_binder, _page, section| {
let descriptions = &section.descriptions;
settings::view_section(&section.title)
.add(settings::item(
&descriptions[0],
horizontal_space(Length::Fill),
))
.add(settings::item(
&descriptions[1],
horizontal_space(Length::Fill),
))
.into()
})
}
fn multi_behavior() -> Section<crate::pages::Message> {
Section::default()
.title(fl!("workspaces-multi-behavior"))
.descriptions(vec![
fl!("workspaces-multi-behavior", "span"),
fl!("workspaces-multi-behavior", "separate"),
])
.view::<Page>(|_binder, _page, section| {
let descriptions = &section.descriptions;
settings::view_section(&section.title)
.add(settings::item(
&descriptions[0],
horizontal_space(Length::Fill),
))
.add(settings::item(
&descriptions[1],
horizontal_space(Length::Fill),
))
.into()
})
}

16
app/src/pages/mod.rs Normal file
View file

@ -0,0 +1,16 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
pub mod desktop;
pub mod networking;
pub mod sound;
pub mod system;
pub mod time;
#[derive(Clone, Debug)]
pub enum Message {
About(system::about::Message),
DateAndTime(time::date::Message),
Desktop(desktop::Message),
External { id: String, message: Vec<u8> },
}

View file

@ -0,0 +1,10 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use cosmic_settings_page as page;
pub fn info() -> page::Info {
page::Info::new("online-accounts", "goa-panel-symbolic")
.title(fl!("online-accounts"))
.description(fl!("online-accounts", "desc"))
}

View file

@ -0,0 +1,5 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
pub mod accounts;
pub mod wired;

View file

@ -0,0 +1,10 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use cosmic_settings_page as page;
pub fn info() -> page::Info {
page::Info::new("wired", "network-workgroup-symbolic")
.title(fl!("wired"))
.description(fl!("wired", "desc"))
}

124
app/src/pages/sound.rs Normal file
View file

@ -0,0 +1,124 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use cosmic::{iced, widget::settings};
use cosmic_settings_page::{self as page, section, Section};
use slotmap::SlotMap;
#[derive(Default)]
pub struct Page;
impl page::Page<crate::pages::Message> for Page {
fn content(
&self,
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
) -> Option<page::Content> {
Some(vec![
sections.insert(output()),
sections.insert(input()),
sections.insert(alerts()),
sections.insert(applications()),
])
}
fn info(&self) -> page::Info {
page::Info::new("sound", "multimedia-volume-control-symbolic")
.title(fl!("sound"))
.description(fl!("sound", "desc"))
}
}
impl page::AutoBind<crate::pages::Message> for Page {}
fn alerts() -> Section<crate::pages::Message> {
Section::default()
.title(fl!("sound-alerts"))
.descriptions(vec![
fl!("sound-alerts", "volume"),
fl!("sound-alerts", "sound"),
])
.view::<Page>(|_binder, _page, section| {
settings::view_section(&section.title)
.add(settings::item(
&section.descriptions[0],
iced::widget::text("TODO"),
))
.add(settings::item(
&section.descriptions[1],
iced::widget::text("TODO"),
))
.into()
})
}
fn applications() -> Section<crate::pages::Message> {
Section::default()
.title(fl!("sound-applications"))
.descriptions(vec![fl!("sound-applications", "desc")])
.view::<Page>(|_binder, _page, section| {
settings::view_section(&section.title)
.add(settings::item(
&section.descriptions[0],
iced::widget::text("TODO"),
))
.into()
})
}
fn input() -> Section<crate::pages::Message> {
Section::default()
.title(fl!("sound-input"))
.descriptions(vec![
fl!("sound-input", "volume"),
fl!("sound-input", "device"),
fl!("sound-input", "level"),
])
.view::<Page>(|_binder, _page, section| {
settings::view_section(&section.title)
.add(settings::item(
&section.descriptions[0],
iced::widget::text("TODO"),
))
.add(settings::item(
&section.descriptions[1],
iced::widget::text("TODO"),
))
.add(settings::item(
&section.descriptions[2],
iced::widget::text("TODO"),
))
.into()
})
}
fn output() -> Section<crate::pages::Message> {
Section::default()
.title(fl!("sound-output"))
.descriptions(vec![
fl!("sound-output", "volume"),
fl!("sound-output", "device"),
fl!("sound-output", "level"),
fl!("sound-output", "config"),
fl!("sound-output", "balance"),
])
.view::<Page>(|_binder, _page, section| {
settings::view_section(&section.title)
.add(settings::item(
&section.descriptions[0],
iced::widget::text("TODO"),
))
.add(settings::item(
&section.descriptions[1],
iced::widget::text("TODO"),
))
.add(settings::item(
&section.descriptions[2],
iced::widget::text("TODO"),
))
.add(settings::item(
&section.descriptions[3],
iced::widget::text("TODO"),
))
.into()
})
}

View file

@ -0,0 +1,158 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use cosmic_settings_page::{self as page, section, Section};
use cosmic::{
iced::{
widget::{horizontal_space, row},
Length,
},
widget::{icon, list_column, settings, text},
};
use cosmic_settings_system::about::Info;
use slotmap::SlotMap;
#[derive(Clone, Debug)]
pub enum Message {
Info(Box<Info>),
}
#[derive(Clone, Debug, Default)]
pub struct Page {
info: Info,
// support_page: page::Entity,
}
impl page::AutoBind<crate::pages::Message> for Page {}
impl page::Page<crate::pages::Message> for Page {
fn content(
&self,
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
) -> Option<page::Content> {
Some(vec![
sections.insert(distributor_logo()),
sections.insert(device()),
sections.insert(hardware()),
sections.insert(os()),
sections.insert(related()),
])
}
fn info(&self) -> page::Info {
page::Info::new("about", "help-about-symbolic")
.title(fl!("about"))
.description(fl!("about", "desc"))
}
fn load(&self, _page: page::Entity) -> Option<page::Task<crate::pages::Message>> {
Some(Box::pin(async move {
crate::pages::Message::About(Message::Info(Box::new(Info::load())))
}))
}
}
impl Page {
pub fn update(&mut self, message: Message) {
match message {
Message::Info(info) => self.info = *info,
}
}
}
fn device() -> Section<crate::pages::Message> {
Section::default()
.descriptions(vec![fl!("about-device"), fl!("about-device", "desc")])
.view::<Page>(|_binder, page, section| {
let desc = &section.descriptions;
let device_name = settings::item::builder(&desc[0])
.description(&desc[1])
.control(text(&page.info.device_name));
list_column().add(device_name).into()
})
}
fn distributor_logo() -> Section<crate::pages::Message> {
Section::default()
.search_ignore()
.view::<Page>(|_binder, _page, _section| {
row!(
horizontal_space(Length::Fill),
icon("distributor-logo", 78),
horizontal_space(Length::Fill),
)
// Add extra padding to reach 40px from the first section.
.padding([0, 16, 0, 16])
.into()
})
}
fn hardware() -> Section<crate::pages::Message> {
Section::default()
.title(fl!("about-hardware"))
.descriptions(vec![
fl!("about-hardware", "model"),
fl!("about-hardware", "memory"),
fl!("about-hardware", "processor"),
fl!("about-hardware", "graphics"),
fl!("about-hardware", "disk-capacity"),
])
.view::<Page>(|_binder, page, section| {
let desc = &section.descriptions;
let mut sections = settings::view_section(&section.title)
.add(settings::item(&desc[0], text(&page.info.hardware_model)))
.add(settings::item(&desc[1], text(&page.info.memory)))
.add(settings::item(&desc[2], text(&page.info.processor)));
for card in &page.info.graphics {
sections = sections.add(settings::item(&desc[3], text(card.as_str())));
}
sections
.add(settings::item(&desc[4], text(&page.info.disk_capacity)))
.into()
})
}
fn os() -> Section<crate::pages::Message> {
Section::default()
.title(fl!("about-os"))
.descriptions(vec![
fl!("about-os", "os"),
fl!("about-os", "os-architecture"),
fl!("about-os", "desktop-environment"),
fl!("about-os", "windowing-system"),
])
.view::<Page>(|_binder, page, section| {
let desc = &section.descriptions;
settings::view_section(&section.title)
.add(settings::item(&desc[0], text(&page.info.operating_system)))
.add(settings::item(&desc[1], text(&page.info.os_architecture)))
.add(settings::item(
&desc[2],
text(&page.info.desktop_environment),
))
.add(settings::item(&desc[3], text(&page.info.windowing_system)))
.into()
})
}
fn related() -> Section<crate::pages::Message> {
Section::default()
.title(fl!("about-related"))
.descriptions(vec![fl!("about-related", "support")])
.view::<Page>(|_binder, _page, section| {
settings::view_section(&section.title)
.add(settings::item(&section.descriptions[0], text("TODO")))
.into()
})
}
// fn page(app: &crate::SettingsApp) -> &Page {
// app.pages
// .resource::<Page>()
// .expect("missing system->about page")
// }

View file

@ -0,0 +1,26 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use cosmic_settings_page::Section;
use cosmic_settings_page::{self as page, section};
use slotmap::SlotMap;
#[derive(Default)]
pub struct Page;
impl page::Page<crate::pages::Message> for Page {
fn content(
&self,
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
) -> Option<page::Content> {
Some(vec![sections.insert(Section::default())])
}
fn info(&self) -> page::Info {
page::Info::new("firmware", "firmware-manager-symbolic")
.title(fl!("firmware"))
.description(fl!("firmware", "desc"))
}
}
impl page::AutoBind<crate::pages::Message> for Page {}

View file

@ -0,0 +1,25 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
pub mod about;
pub mod firmware;
pub mod users;
use cosmic_settings_page as page;
#[derive(Default)]
pub struct Page;
impl page::Page<crate::pages::Message> for Page {
fn info(&self) -> page::Info {
page::Info::new("system", "system-users-symbolic").title(fl!("system"))
}
}
impl page::AutoBind<crate::pages::Message> for Page {
fn sub_pages(page: page::Insert<crate::pages::Message>) -> page::Insert<crate::pages::Message> {
page.sub_page::<users::Page>()
.sub_page::<about::Page>()
.sub_page::<firmware::Page>()
}
}

View file

@ -0,0 +1,26 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use cosmic_settings_page::Section;
use cosmic_settings_page::{self as page, section};
use slotmap::SlotMap;
#[derive(Default)]
pub struct Page;
impl page::Page<crate::pages::Message> for Page {
fn content(
&self,
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
) -> Option<page::Content> {
Some(vec![sections.insert(Section::default())])
}
fn info(&self) -> page::Info {
page::Info::new("users", "system-users-symbolic")
.title(fl!("users"))
.description(fl!("users", "desc"))
}
}
impl page::AutoBind<crate::pages::Message> for Page {}

132
app/src/pages/time/date.rs Normal file
View file

@ -0,0 +1,132 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use apply::Apply;
use cosmic::{
iced::{widget::horizontal_space, Length},
widget::settings,
};
use cosmic_settings_page::Section;
use cosmic_settings_page::{self as page, section};
// use icu::calendar::{DateTime, Gregorian};
use slotmap::SlotMap;
#[derive(Default)]
pub struct Page {
auto: bool,
auto_timezone: bool,
military_time: bool,
// info: Option<cosmic_settings_time::Info>,
}
impl page::Page<crate::pages::Message> for Page {
fn content(
&self,
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
) -> Option<page::Content> {
Some(vec![
sections.insert(date()),
sections.insert(timezone()),
sections.insert(format()),
])
}
fn info(&self) -> page::Info {
page::Info::new("time-date", "preferences-system-time-symbolic")
.title(fl!("time-date"))
.description(fl!("time-date", "desc"))
}
fn load(&self, _page: page::Entity) -> Option<page::Task<crate::pages::Message>> {
None
}
}
impl Page {
pub fn update(&mut self, message: Message) {
match message {
Message::Automatic(enable) => self.auto = enable,
Message::AutomaticTimezone(enable) => self.auto_timezone = enable,
Message::MilitaryTime(enable) => self.military_time = enable,
}
}
}
#[derive(Clone, Copy, Debug)]
pub enum Message {
Automatic(bool),
AutomaticTimezone(bool),
MilitaryTime(bool),
}
impl page::AutoBind<crate::pages::Message> for Page {}
fn date() -> Section<crate::pages::Message> {
Section::default()
.title(fl!("time-date"))
.descriptions(vec![fl!("time-date", "auto"), fl!("time-date")])
.view::<Page>(|_binder, page, section| {
settings::view_section(&section.title)
.add(
settings::item::builder(&section.descriptions[0])
.toggler(page.auto, Message::Automatic),
)
.add(settings::item(
&section.descriptions[1],
horizontal_space(Length::Fill),
))
.apply(cosmic::Element::from)
.map(crate::pages::Message::DateAndTime)
})
}
fn format() -> Section<crate::pages::Message> {
Section::default()
.title(fl!("time-format"))
.descriptions(vec![
fl!("time-format", "twenty-four"),
fl!("time-format", "first"),
])
.view::<Page>(|_binder, page, section| {
settings::view_section(&section.title)
// 24-hour toggle
.add(
settings::item::builder(&section.descriptions[0])
.toggler(page.military_time, Message::MilitaryTime),
)
// First day of week
.add(settings::item(
&section.descriptions[1],
horizontal_space(Length::Fill),
))
.apply(cosmic::Element::from)
.map(crate::pages::Message::DateAndTime)
})
}
fn timezone() -> Section<crate::pages::Message> {
Section::default()
.title(fl!("time-zone"))
.descriptions(vec![
fl!("time-zone", "auto"),
fl!("time-zone", "auto-info"),
fl!("time-zone"),
])
.view::<Page>(|_binder, page, section| {
settings::view_section(&section.title)
// Automatic timezone toggle
.add(
settings::item::builder(&section.descriptions[0])
.description(&section.descriptions[1])
.toggler(page.auto_timezone, Message::AutomaticTimezone),
)
// Time zone select
.add(
settings::item::builder(&section.descriptions[2])
.control(horizontal_space(Length::Fill)),
)
.apply(cosmic::Element::from)
.map(crate::pages::Message::DateAndTime)
})
}

24
app/src/pages/time/mod.rs Normal file
View file

@ -0,0 +1,24 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use cosmic_settings_page as page;
pub mod date;
pub mod region;
#[derive(Default)]
pub struct Page;
impl page::Page<crate::pages::Message> for Page {
fn info(&self) -> page::Info {
page::Info::new("time", "preferences-system-time-symbolic")
.title(fl!("time"))
.description(fl!("time", "desc"))
}
}
impl page::AutoBind<crate::pages::Message> for Page {
fn sub_pages(page: page::Insert<crate::pages::Message>) -> page::Insert<crate::pages::Message> {
page.sub_page::<date::Page>().sub_page::<region::Page>()
}
}

View file

@ -0,0 +1,26 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use cosmic_settings_page::Section;
use cosmic_settings_page::{self as page, section};
use slotmap::SlotMap;
#[derive(Default)]
pub struct Page;
impl page::Page<crate::pages::Message> for Page {
fn content(
&self,
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
) -> Option<page::Content> {
Some(vec![sections.insert(Section::default())])
}
fn info(&self) -> page::Info {
page::Info::new("time-region", "preferences-desktop-locale-symbolic")
.title(fl!("time-region"))
.description(fl!("time-region", "desc"))
}
}
impl page::AutoBind<crate::pages::Message> for Page {}