Merge pull request #120 from joshuamegnauth54/fix-96-military-time

Respect user config for military time
This commit is contained in:
Jeremy Soller 2024-09-22 15:42:16 -06:00 committed by GitHub
commit 4b7d282952
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 96 additions and 45 deletions

View file

@ -11,6 +11,8 @@ pub struct UserData {
pub theme_opt: Option<Theme>, pub theme_opt: Option<Theme>,
pub wallpapers_opt: Option<Vec<(String, WallpaperData)>>, pub wallpapers_opt: Option<Vec<(String, WallpaperData)>>,
pub xkb_config_opt: Option<XkbConfig>, pub xkb_config_opt: Option<XkbConfig>,
pub clock_military_time: bool,
// pub clock_show_seconds: bool,
} }
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]

View file

@ -1,6 +1,6 @@
use cosmic_bg_config::Source; use cosmic_bg_config::Source;
use cosmic_comp_config::CosmicCompConfig; use cosmic_comp_config::CosmicCompConfig;
use cosmic_config::CosmicConfigEntry; use cosmic_config::{ConfigGet, CosmicConfigEntry};
use cosmic_greeter_daemon::{UserData, WallpaperData}; use cosmic_greeter_daemon::{UserData, WallpaperData};
use std::{env, error::Error, fs, future::pending, io, path::Path}; use std::{env, error::Error, fs, future::pending, io, path::Path};
use zbus::{ConnectionBuilder, DBusError}; use zbus::{ConnectionBuilder, DBusError};
@ -115,6 +115,8 @@ impl GreeterProxy {
//TODO: should wallpapers come from a per-user call? //TODO: should wallpapers come from a per-user call?
wallpapers_opt: None, wallpapers_opt: None,
xkb_config_opt: None, xkb_config_opt: None,
clock_military_time: false,
// clock_show_seconds: false,
}; };
//IMPORTANT: Assume the identity of the user to ensure we don't read wallpaper file data as root //IMPORTANT: Assume the identity of the user to ensure we don't read wallpaper file data as root
@ -208,6 +210,21 @@ impl GreeterProxy {
log::error!("failed to create cosmic-comp config handler: {}", err); log::error!("failed to create cosmic-comp config handler: {}", err);
} }
}; };
match cosmic_config::Config::new("com.system76.CosmicAppletTime", 1) {
Ok(config_handler) => {
user_data.clock_military_time =
config_handler.get("military_time").unwrap_or_default();
// user_data.clock_show_seconds =
// config_handler.get("show_seconds").unwrap_or_default();
}
Err(err) => {
log::error!(
"failed to create CosmicAppletTime config handler: {:?}",
err
);
}
};
}) })
.map_err(|err| GreeterError::RunAsUser(err.to_string()))?; .map_err(|err| GreeterError::RunAsUser(err.to_string()))?;

View file

@ -110,6 +110,8 @@ fn user_data_fallback() -> Vec<UserData> {
theme_opt: None, theme_opt: None,
wallpapers_opt: None, wallpapers_opt: None,
xkb_config_opt: None, xkb_config_opt: None,
clock_military_time: false,
// clock_show_seconds: false,
} }
}) })
.collect() .collect()
@ -372,6 +374,13 @@ pub enum Dropdown {
Session, Session,
} }
struct NameIndexPair {
/// Selected username
username: String,
/// Index of the [`UserData`] for the selected username
data_idx: Option<usize>,
}
/// Messages that are used specifically by our [`App`]. /// Messages that are used specifically by our [`App`].
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum Message { pub enum Message {
@ -416,7 +425,7 @@ pub struct App {
power_info_opt: Option<(String, f64)>, power_info_opt: Option<(String, f64)>,
socket_state: SocketState, socket_state: SocketState,
usernames: Vec<(String, String)>, usernames: Vec<(String, String)>,
selected_username: String, selected_username: NameIndexPair,
prompt_opt: Option<(String, bool, Option<String>)>, prompt_opt: Option<(String, bool, Option<String>)>,
session_names: Vec<String>, session_names: Vec<String>,
selected_session: String, selected_session: String,
@ -442,10 +451,9 @@ impl App {
fn set_xkb_config(&self) { fn set_xkb_config(&self) {
let user_data = match self let user_data = match self
.flags .selected_username
.user_datas .data_idx
.iter() .and_then(|i| self.flags.user_datas.get(i))
.find(|x| &x.name == &self.selected_username)
{ {
Some(some) => some, Some(some) => some,
None => return, None => return,
@ -473,10 +481,9 @@ impl App {
fn update_user_config(&mut self) -> Command<Message> { fn update_user_config(&mut self) -> Command<Message> {
let user_data = match self let user_data = match self
.flags .selected_username
.user_datas .data_idx
.iter() .and_then(|i| self.flags.user_datas.get(i))
.find(|x| &x.name == &self.selected_username)
{ {
Some(some) => some, Some(some) => some,
None => return Command::none(), None => return Command::none(),
@ -572,6 +579,12 @@ impl App {
None => Command::none(), None => Command::none(),
} }
} }
fn user_data_index(user_datas: &[UserData], username: &str) -> Option<usize> {
user_datas
.binary_search_by(|probe| probe.name.as_str().cmp(username))
.ok()
}
} }
/// Implement [`cosmic::Application`] to integrate with COSMIC. /// Implement [`cosmic::Application`] to integrate with COSMIC.
@ -618,11 +631,11 @@ impl cosmic::Application for App {
usernames.sort_by(|a, b| a.1.cmp(&b.1)); usernames.sort_by(|a, b| a.1.cmp(&b.1));
//TODO: use last selected user //TODO: use last selected user
let (selected_username, uid) = flags let (username, uid) = flags
.user_datas .user_datas
.first() .first()
.map(|x| (x.name.clone(), NonZeroU32::new(x.uid))) .map(|x| (x.name.clone(), NonZeroU32::new(x.uid)))
.unwrap_or((String::new(), None)); .unwrap_or_default();
let mut session_names: Vec<_> = flags.sessions.keys().map(|x| x.to_string()).collect(); let mut session_names: Vec<_> = flags.sessions.keys().map(|x| x.to_string()).collect();
session_names.sort(); session_names.sort();
@ -637,6 +650,8 @@ impl cosmic::Application for App {
}) })
.or_else(|| session_names.first().cloned()) .or_else(|| session_names.first().cloned())
.unwrap_or_default(); .unwrap_or_default();
let data_idx = Some(0);
let selected_username = NameIndexPair { username, data_idx };
let app = App { let app = App {
core, core,
@ -762,7 +777,7 @@ impl cosmic::Application for App {
SocketState::Open => { SocketState::Open => {
// When socket is opened, send create session // When socket is opened, send create session
return self.send_request(Request::CreateSession { return self.send_request(Request::CreateSession {
username: self.selected_username.clone(), username: self.selected_username.username.clone(),
}); });
} }
_ => {} _ => {}
@ -799,24 +814,24 @@ impl cosmic::Application for App {
if self.dropdown_opt == Some(Dropdown::User) { if self.dropdown_opt == Some(Dropdown::User) {
self.dropdown_opt = None; self.dropdown_opt = None;
} }
if username != self.selected_username { if username != self.selected_username.username {
self.selected_username = username.clone(); let data_idx = Self::user_data_index(&self.flags.user_datas, &username);
self.selected_username = NameIndexPair { username, data_idx };
self.surface_images.clear(); self.surface_images.clear();
if let Some(session) = self if let Some(session) = data_idx.and_then(|i| {
.flags self.flags
.user_datas .user_datas
.iter() .get(i)
.find(|user| user.name == username) .and_then(|UserData { uid, .. }| {
.and_then(|UserData { uid, .. }| { NonZeroU32::new(*uid).and_then(|uid| {
NonZeroU32::new(*uid).and_then(|uid| { self.flags
self.flags .greeter_config
.greeter_config .users
.users .get(&uid)
.get(&uid) .and_then(|conf| conf.last_session.as_deref())
.and_then(|conf| conf.last_session.as_deref()) })
}) })
}) }) {
{
session.clone_into(&mut self.selected_session); session.clone_into(&mut self.selected_session);
}; };
match &self.socket_state { match &self.socket_state {
@ -829,23 +844,23 @@ impl cosmic::Application for App {
} }
} }
Message::ConfigUpdateUser => { Message::ConfigUpdateUser => {
let Some(user_entry) = self let Some(user_entry) = self.selected_username.data_idx.and_then(|i| {
.flags self.flags
.user_datas .user_datas
.iter() .get(i)
.find(|user| user.name == self.selected_username) .and_then(|UserData { uid, .. }| {
.and_then(|UserData { uid, .. }| { NonZeroU32::new(*uid)
NonZeroU32::new(*uid).map(|uid| self.flags.greeter_config.users.entry(uid)) .map(|uid| self.flags.greeter_config.users.entry(uid))
}) })
else { }) else {
log::error!("Couldn't find user: {:?}", self.selected_username); log::error!("Couldn't find user: {:?}", self.selected_username.username);
return Command::none(); return Command::none();
}; };
let Some(handler) = self.flags.greeter_config_handler.as_mut() else { let Some(handler) = self.flags.greeter_config_handler.as_mut() else {
log::error!( log::error!(
"Failed to update config for {} (UID: {}): no config handler", "Failed to update config for {} (UID: {}): no config handler",
self.selected_username, self.selected_username.username,
user_entry.key() user_entry.key()
); );
return Command::none(); return Command::none();
@ -886,7 +901,7 @@ impl cosmic::Application for App {
log::error!( log::error!(
"Failed to set {} as last selected session for {} (UID: {}): {:?}", "Failed to set {} as last selected session for {} (UID: {}): {:?}",
self.selected_session, self.selected_session,
self.selected_username, self.selected_username.username,
uid, uid,
err err
); );
@ -1025,10 +1040,27 @@ impl cosmic::Application for App {
column = column column = column
.push(widget::text::title2(format!("{}", date)).style(style::Text::Accent)); .push(widget::text::title2(format!("{}", date)).style(style::Text::Accent));
let time = dt.format_localized("%R", locale); let (time, time_size) = if self
.selected_username
.data_idx
.and_then(|i| {
self.flags
.user_datas
.get(i)
.map(|user| user.clock_military_time)
})
.unwrap_or_default()
{
(dt.format_localized("%R", locale), 112.0)
} else {
// xxx format_localized doesn't seem to show am/pm for some languages, such as
// French or Hungarian. This is apparently correct
// Also, time size needs to be reduced a bit here so that it fits on one line
(dt.format_localized("%I:%M %p", locale), 75.0)
};
column = column.push( column = column.push(
widget::text(format!("{}", time)) widget::text(format!("{}", time))
.size(112.0) .size(time_size)
.style(style::Text::Accent), .style(style::Text::Accent),
); );
@ -1120,7 +1152,7 @@ impl cosmic::Application for App {
for (name, full_name) in self.usernames.iter() { for (name, full_name) in self.usernames.iter() {
items.push(menu_checklist( items.push(menu_checklist(
full_name, full_name,
name == &self.selected_username, name == &self.selected_username.username,
Message::Username(name.clone()), Message::Username(name.clone()),
)); ));
} }
@ -1211,7 +1243,7 @@ impl cosmic::Application for App {
} }
SocketState::Open => { SocketState::Open => {
for user_data in &self.flags.user_datas { for user_data in &self.flags.user_datas {
if &user_data.name == &self.selected_username { if &user_data.name == &self.selected_username.username {
match &user_data.icon_opt { match &user_data.icon_opt {
Some(icon) => { Some(icon) => {
column = column.push( column = column.push(