Merge pull request #120 from joshuamegnauth54/fix-96-military-time
Respect user config for military time
This commit is contained in:
commit
4b7d282952
3 changed files with 96 additions and 45 deletions
|
|
@ -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)]
|
||||||
|
|
|
||||||
|
|
@ -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()))?;
|
||||||
|
|
||||||
|
|
|
||||||
120
src/greeter.rs
120
src/greeter.rs
|
|
@ -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(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue