add settings: am/pm clock, opaque background, hide username

This commit is contained in:
Aleksander
2025-11-07 19:40:38 +01:00
parent 433b7f53b5
commit d2c23ac6a9
9 changed files with 132 additions and 59 deletions

View File

@@ -64,9 +64,12 @@
height="100%"
overflow_x="scroll">
<!-- CONTENT -->
<!-- color and color2 alpha will be modified at runtime -->
<rectangle
color2="#0d131aee"
color="#244179dd"
id="rect_content"
color2="#0d131a00"
color="#24417900"
gradient="vertical"
round="8"
flex_grow="1"

View File

@@ -26,5 +26,6 @@
"ENABLE_PASSTHROUGH": "Passthrough aktivieren"
},
"RESTART_SOFTWARE": "Software neu starten"
}
},
"HELLO": "Hallo!"
}

View File

@@ -6,6 +6,7 @@
"SETTINGS": "Settings",
"PROCESSES": "Processes",
"HELLO_USER": "Hello, {USER}!",
"HELLO": "Hello!",
"GENERAL_SETTINGS": "General settings",
"APPLICATION_LAUNCHER": "Application launcher",
"APP_SETTINGS": {

View File

@@ -26,5 +26,6 @@
"ENABLE_PASSTHROUGH": "Habilitar Passthrough"
},
"RESTART_SOFTWARE": "Reiniciar software"
}
},
"HELLO": "¡Hola!"
}

View File

@@ -26,5 +26,6 @@
"ENABLE_PASSTHROUGH": "Passthroughを有効にする"
},
"RESTART_SOFTWARE": "ソフトウェアを再起動"
}
},
"HELLO": "こんにちは!"
}

View File

@@ -1,30 +1,31 @@
{
"HOME_SCREEN": "Ekran główny",
"MONADO_RUNTIME": "„Monado” środowisko uruchomieniowe",
"APPLICATIONS": "Aplikacje",
"GAMES": "Gry",
"SETTINGS": "Ustawienia",
"PROCESSES": "Procesy",
"HELLO_USER": "Witaj, {USER}!",
"GENERAL_SETTINGS": "Ustawienia ogólne",
"APPLICATION_LAUNCHER": "Uruchamiacz aplikacji",
"APP_SETTINGS": {
"HIDE_USERNAME": "Ukryj nazwę użytkownika",
"OPAQUE_BACKGROUND": "Nieprzezroczysty tło",
"RUN_IN_XWAYLAND_MODE_BY_DEFAULT": "Uruchom domyślnie w trybie XWayland",
"WLX_OVERLAY_S_SETTINGS": "Ustawienia wlx-overlay-s",
"HEADSET_SETTINGS": "Ustawienia głośności",
"BRIGHTNESS": "Jasność",
"WLX": {
"NOTIFICATIONS_ENABLED": "Powiadomienia",
"NOTIFICATIONS_SOUND_ENABLED": "Dźwięk powiadomień",
"KEYBOARD_SOUND_ENABLED": "Dźwięki klawiatury",
"BLOCK_GAME_INPUT": "Zablokuj sterowanie grą podczas używania Wlx",
"SPACE_DRAG_MULTIPLIER": "Mnożnik space-drag",
"SPACE_DRAG_ROTATION_ENABLED": "Włącz rotację w space-drag",
"SHOW_SKYBOX": "Pokaż skybox",
"ENABLE_PASSTHROUGH": "Włącz passthrough"
},
"RESTART_SOFTWARE": "Uruchom ponownie oprogramowanie"
}
}
"HOME_SCREEN": "Ekran główny",
"MONADO_RUNTIME": "„Monado” środowisko uruchomieniowe",
"APPLICATIONS": "Aplikacje",
"GAMES": "Gry",
"SETTINGS": "Ustawienia",
"PROCESSES": "Procesy",
"HELLO_USER": "Witaj, {USER}!",
"GENERAL_SETTINGS": "Ustawienia ogólne",
"APPLICATION_LAUNCHER": "Uruchamiacz aplikacji",
"APP_SETTINGS": {
"HIDE_USERNAME": "Ukryj nazwę użytkownika",
"OPAQUE_BACKGROUND": "Nieprzezroczysty tło",
"RUN_IN_XWAYLAND_MODE_BY_DEFAULT": "Uruchom domyślnie w trybie XWayland",
"WLX_OVERLAY_S_SETTINGS": "Ustawienia wlx-overlay-s",
"HEADSET_SETTINGS": "Ustawienia głośności",
"BRIGHTNESS": "Jasność",
"WLX": {
"NOTIFICATIONS_ENABLED": "Powiadomienia",
"NOTIFICATIONS_SOUND_ENABLED": "Dźwięk powiadomień",
"KEYBOARD_SOUND_ENABLED": "Dźwięki klawiatury",
"BLOCK_GAME_INPUT": "Zablokuj sterowanie grą podczas używania Wlx",
"SPACE_DRAG_MULTIPLIER": "Mnożnik space-drag",
"SPACE_DRAG_ROTATION_ENABLED": "Włącz rotację w space-drag",
"SHOW_SKYBOX": "Pokaż skybox",
"ENABLE_PASSTHROUGH": "Włącz passthrough"
},
"RESTART_SOFTWARE": "Uruchom ponownie oprogramowanie"
},
"HELLO": "Witaj!"
}

View File

@@ -10,7 +10,7 @@ use wgui::{
i18n::Translation,
layout::{LayoutParams, RcLayout, WidgetID},
parser::{Fetchable, ParseDocumentParams, ParserState},
widget::label::WidgetLabel,
widget::{label::WidgetLabel, rectangle::WidgetRectangle},
};
use crate::{
@@ -36,7 +36,8 @@ pub struct Frontend {
ticks: u32,
label_time_id: WidgetID,
id_label_time: WidgetID,
id_rect_content: WidgetID,
}
pub struct InitParams {
@@ -47,6 +48,8 @@ pub type RcFrontend = Rc<RefCell<Frontend>>;
pub enum FrontendTask {
SetTab(TabType),
RefreshClock,
RefreshBackground,
}
impl Frontend {
@@ -67,18 +70,26 @@ impl Frontend {
let mut tasks = VecDeque::<FrontendTask>::new();
tasks.push_back(FrontendTask::SetTab(TabType::Home));
let label_time_id = state.get_widget_id("label_time")?;
let id_label_time = state.get_widget_id("label_time")?;
let id_rect_content = state.get_widget_id("rect_content")?;
let res = Rc::new(RefCell::new(Self {
let frontend = Self {
layout: rc_layout.clone(),
state,
current_tab: None,
globals,
tasks,
ticks: 0,
label_time_id,
id_label_time,
id_rect_content,
settings: params.settings,
}));
};
// init some things first
frontend.update_background()?;
frontend.update_time()?;
let res = Rc::new(RefCell::new(frontend));
Frontend::register_widgets(&res)?;
@@ -97,31 +108,65 @@ impl Frontend {
}
fn tick(&mut self, width: f32, height: f32, timestep_alpha: f32) -> anyhow::Result<()> {
let mut layout = self.layout.borrow_mut();
let mut c = layout.start_common();
// fixme: timer events instead of this thing
if self.ticks.is_multiple_of(1000) {
self.update_time(&mut c.common());
self.update_time()?;
}
c.finish()?;
layout.update(Vec2::new(width, height), timestep_alpha)?;
{
let mut layout = self.layout.borrow_mut();
layout.update(Vec2::new(width, height), timestep_alpha)?;
}
Ok(())
}
fn update_time(&self, common: &mut CallbackDataCommon) {
let Some(mut label) = common.state.widgets.get_as::<WidgetLabel>(self.label_time_id) else {
return;
fn update_time(&self) -> anyhow::Result<()> {
let mut layout = self.layout.borrow_mut();
let mut c = layout.start_common();
let mut common = c.common();
{
let Some(mut label) = common.state.widgets.get_as::<WidgetLabel>(self.id_label_time) else {
anyhow::bail!("");
};
let now = chrono::Local::now();
let hours = now.hour();
let minutes = now.minute();
let text: String = if !self.settings.general.am_pm_clock {
format!("{hours:02}:{minutes:02}")
} else {
let hours_ampm = (hours + 11) % 12 + 1;
let suffix = if hours >= 12 { "PM" } else { "AM" };
format!("{hours_ampm:02}:{minutes:02} {suffix}")
};
label.set_text(&mut common, Translation::from_raw_text(&text));
}
c.finish()?;
Ok(())
}
fn update_background(&self) -> anyhow::Result<()> {
let layout = self.layout.borrow_mut();
let Some(mut rect) = layout.state.widgets.get_as::<WidgetRectangle>(self.id_rect_content) else {
anyhow::bail!("");
};
let now = chrono::Local::now();
let hours = now.hour();
let minutes = now.minute();
let (alpha1, alpha2) = if !self.settings.general.opaque_background {
(0.8666, 0.9333)
} else {
(1.0, 1.0)
};
label.set_text(common, Translation::from_raw_text(&format!("{hours:02}:{minutes:02}")));
rect.params.color.a = alpha1;
rect.params.color2.a = alpha2;
Ok(())
}
pub fn get_layout(&self) -> &RcLayout {
@@ -135,6 +180,8 @@ impl Frontend {
fn process_task(&mut self, rc_this: &RcFrontend, task: FrontendTask) -> anyhow::Result<()> {
match task {
FrontendTask::SetTab(tab_type) => self.set_tab(tab_type, rc_this)?,
FrontendTask::RefreshClock => self.update_time()?,
FrontendTask::RefreshBackground => self.update_background()?,
}
Ok(())
}

View File

@@ -7,6 +7,7 @@ use wgui::{
};
use crate::{
settings,
tab::{Tab, TabParams, TabType},
various,
};
@@ -22,7 +23,7 @@ impl Tab for TabHome {
}
}
fn configure_label_hello(label_hello: &mut WidgetLabel, i18n: &mut wgui::i18n::I18n) {
fn configure_label_hello(label_hello: &mut WidgetLabel, i18n: &mut wgui::i18n::I18n, settings: &settings::Settings) {
let mut username = various::get_username();
// first character as uppercase
if let Some(first) = username.chars().next() {
@@ -30,7 +31,12 @@ fn configure_label_hello(label_hello: &mut WidgetLabel, i18n: &mut wgui::i18n::I
username.replace_range(0..1, &first);
}
let translated = i18n.translate_and_replace("HELLO_USER", ("{USER}", &username));
let translated = if !settings.home_screen.hide_username {
i18n.translate_and_replace("HELLO_USER", ("{USER}", &username))
} else {
i18n.translate("HELLO").to_string()
};
label_hello.set_text_simple(i18n, Translation::from_raw_text(&translated));
}
@@ -47,7 +53,7 @@ impl TabHome {
)?;
let mut label_hello = state.fetch_widget_as::<WidgetLabel>(&params.layout.state, "label_hello")?;
configure_label_hello(&mut label_hello, &mut params.globals.i18n());
configure_label_hello(&mut label_hello, &mut params.globals.i18n(), params.settings);
let btn_apps = state.fetch_component_as::<ComponentButton>("btn_apps")?;
let btn_games = state.fetch_component_as::<ComponentButton>("btn_games")?;

View File

@@ -3,12 +3,11 @@ use std::rc::Rc;
use wgui::{
assets::AssetPath,
components::checkbox::ComponentCheckbox,
event::CallbackDataCommon,
parser::{Fetchable, ParseDocumentParams, ParserState},
};
use crate::{
frontend::{Frontend, RcFrontend},
frontend::{Frontend, FrontendTask},
settings,
tab::{Tab, TabParams, TabType},
};
@@ -28,6 +27,7 @@ fn init_setting_checkbox(
params: &mut TabParams,
checkbox: Rc<ComponentCheckbox>,
fetch_callback: fn(&mut settings::Settings) -> &mut bool,
change_callback: Option<fn(&mut Frontend, bool)>,
) -> anyhow::Result<()> {
let mut c = params.layout.start_common();
@@ -36,6 +36,10 @@ fn init_setting_checkbox(
checkbox.on_toggle(Box::new(move |_common, e| {
let mut frontend = rc_frontend.borrow_mut();
*fetch_callback(&mut frontend.settings) = e.checked;
if let Some(change_callback) = &change_callback {
change_callback(&mut frontend, e.checked);
}
Ok(())
}));
@@ -59,12 +63,16 @@ impl TabSettings {
&mut params,
state.data.fetch_component_as::<ComponentCheckbox>("cb_hide_username")?,
|settings| &mut settings.home_screen.hide_username,
None,
)?;
init_setting_checkbox(
&mut params,
state.data.fetch_component_as::<ComponentCheckbox>("cb_am_pm_clock")?,
|settings| &mut settings.general.am_pm_clock,
Some(|frontend, _| {
frontend.push_task(FrontendTask::RefreshClock);
}),
)?;
init_setting_checkbox(
@@ -73,6 +81,9 @@ impl TabSettings {
.data
.fetch_component_as::<ComponentCheckbox>("cb_opaque_background")?,
|settings| &mut settings.general.opaque_background,
Some(|frontend, _| {
frontend.push_task(FrontendTask::RefreshBackground);
}),
)?;
init_setting_checkbox(
@@ -81,6 +92,7 @@ impl TabSettings {
.data
.fetch_component_as::<ComponentCheckbox>("cb_xwayland_by_default")?,
|settings| &mut settings.tweaks.xwayland_by_default,
None,
)?;
Ok(Self { state })