feat(theme): themes as files (theme crate: toml subset + ints, contrast check, wire); whimsy dark + light; display reads themes/, serves THEME/THEME_NAME, init SET_THEME -> THEME_CHANGED to all windows, bar themed; k-ui follows; settings appearance; init keeps choice in sealed users/<id>/settings/, reapplies at sign-in + display restart
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
//! Settings: what each app may use (allow or revoke, through the
|
||||
//! permission manager), who is signed in, and signing out. A system app:
|
||||
//! permission manager), the theme (the display's list, kept per user by
|
||||
//! init), who is signed in, and signing out. A system app:
|
||||
//! `permissions` and `session` are only ever granted to apps on the system
|
||||
//! image.
|
||||
|
||||
@@ -29,6 +30,7 @@ enum Screen {
|
||||
Apps,
|
||||
/// One app, by its place in the list.
|
||||
App(usize),
|
||||
Appearance,
|
||||
About,
|
||||
}
|
||||
|
||||
@@ -37,6 +39,8 @@ enum Event {
|
||||
Show(Screen),
|
||||
/// Allow or revoke this capability of the app on screen.
|
||||
Flip(Capability),
|
||||
/// Use the display's `n`th theme.
|
||||
Theme(usize),
|
||||
SignOut,
|
||||
}
|
||||
|
||||
@@ -54,6 +58,9 @@ struct Settings {
|
||||
rows: Vec<AppRow>,
|
||||
/// Who is signed in, and how.
|
||||
who: Option<(String, Role)>,
|
||||
/// The display's themes, and which is in use.
|
||||
themes: Vec<String>,
|
||||
theme: usize,
|
||||
/// What went wrong last, shown until the next change.
|
||||
trouble: Option<String>,
|
||||
}
|
||||
@@ -99,6 +106,23 @@ impl Settings {
|
||||
self.reload();
|
||||
}
|
||||
|
||||
fn appearance(&self) -> Element<Event> {
|
||||
let rows = self.themes.iter().enumerate().map(|(i, name)| {
|
||||
let item = list_item(name.clone(), Event::Theme(i));
|
||||
if i == self.theme { item.subtitle("In use") } else { item }
|
||||
});
|
||||
let view = Self::hint(Self::heading("Appearance"), "Esc goes back").children(rows);
|
||||
self.with_trouble(view).into()
|
||||
}
|
||||
|
||||
fn choose_theme(&mut self, index: usize) {
|
||||
let (Some(name), Some(session)) = (self.themes.get(index), libkos::start::session()) else { return };
|
||||
match libkos::session::set_theme(session, name.as_bytes()) {
|
||||
true => self.theme = index,
|
||||
false => self.trouble = Some("That theme could not be kept.".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
fn heading(title: &str) -> k_ui::element::FlexBuilder<Event> {
|
||||
column().padding(Spacing::Xl).gap(Spacing::Md).child(text(title).style(TextStyle::Heading))
|
||||
}
|
||||
@@ -110,6 +134,7 @@ impl Settings {
|
||||
fn home(&self) -> Element<Event> {
|
||||
Self::heading("Settings")
|
||||
.child(list_item("Apps", Event::Show(Screen::Apps)).subtitle("What each app may use"))
|
||||
.child(list_item("Appearance", Event::Show(Screen::Appearance)).subtitle("The theme everything is drawn in"))
|
||||
.child(list_item("About", Event::Show(Screen::About)).subtitle("Who is signed in, and this device"))
|
||||
.child(button("Sign out", Event::SignOut).variant(ButtonVariant::Destructive))
|
||||
.into()
|
||||
@@ -176,7 +201,15 @@ impl App for Settings {
|
||||
let who = libkos::start::session()
|
||||
.and_then(|s| libkos::session::who(s, &mut name))
|
||||
.map(|(len, role)| (String::from_utf8_lossy(&name[..len]).into_owned(), role));
|
||||
let mut s = Settings { screen: Screen::Home, apps, rows: Vec::new(), who, trouble: None };
|
||||
let window = libkos::start::display();
|
||||
let themes = window.map_or(Vec::new(), |w| {
|
||||
(0..)
|
||||
.map_while(|i| libkos::display::theme_name(w, i))
|
||||
.map(|(n, len)| String::from_utf8_lossy(&n[..len]).into_owned())
|
||||
.collect()
|
||||
});
|
||||
let theme = window.and_then(libkos::display::theme).map_or(0, |(i, _)| i);
|
||||
let mut s = Settings { screen: Screen::Home, apps, rows: Vec::new(), who, themes, theme, trouble: None };
|
||||
s.reload();
|
||||
s
|
||||
}
|
||||
@@ -195,6 +228,7 @@ impl App for Settings {
|
||||
self.flip(i, cap);
|
||||
}
|
||||
}
|
||||
Event::Theme(i) => self.choose_theme(i),
|
||||
Event::SignOut => {
|
||||
if let Some(s) = libkos::start::session() {
|
||||
libkos::session::sign_out(s);
|
||||
@@ -208,6 +242,7 @@ impl App for Settings {
|
||||
Screen::Home => self.home(),
|
||||
Screen::Apps => self.app_list(),
|
||||
Screen::App(i) => self.app(i),
|
||||
Screen::Appearance => self.appearance(),
|
||||
Screen::About => self.about(),
|
||||
}
|
||||
}
|
||||
@@ -217,7 +252,7 @@ impl App for Settings {
|
||||
self.screen = match self.screen {
|
||||
Screen::Home => return false,
|
||||
Screen::App(_) => Screen::Apps,
|
||||
Screen::Apps | Screen::About => Screen::Home,
|
||||
Screen::Apps | Screen::Appearance | Screen::About => Screen::Home,
|
||||
};
|
||||
true
|
||||
}
|
||||
@@ -227,7 +262,8 @@ impl App for Settings {
|
||||
Screen::Home => 0,
|
||||
Screen::Apps => 1,
|
||||
Screen::About => 2,
|
||||
Screen::App(i) => 3 + i,
|
||||
Screen::Appearance => 3,
|
||||
Screen::App(i) => 4 + i,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user