diff --git a/src/greeter.rs b/src/greeter.rs index f828ecd..cb55f97 100644 --- a/src/greeter.rs +++ b/src/greeter.rs @@ -374,6 +374,13 @@ pub enum Dropdown { Session, } +struct NameIndexPair { + /// Selected username + username: String, + /// Index of the [`UserData`] for the selected username + data_idx: Option, +} + /// Messages that are used specifically by our [`App`]. #[derive(Clone, Debug)] pub enum Message { @@ -418,7 +425,7 @@ pub struct App { power_info_opt: Option<(String, f64)>, socket_state: SocketState, usernames: Vec<(String, String)>, - selected_username: String, + selected_username: NameIndexPair, prompt_opt: Option<(String, bool, Option)>, session_names: Vec, selected_session: String, @@ -444,10 +451,9 @@ impl App { fn set_xkb_config(&self) { let user_data = match self - .flags - .user_datas - .iter() - .find(|x| &x.name == &self.selected_username) + .selected_username + .data_idx + .and_then(|i| self.flags.user_datas.get(i)) { Some(some) => some, None => return, @@ -475,10 +481,9 @@ impl App { fn update_user_config(&mut self) -> Command { let user_data = match self - .flags - .user_datas - .iter() - .find(|x| &x.name == &self.selected_username) + .selected_username + .data_idx + .and_then(|i| self.flags.user_datas.get(i)) { Some(some) => some, None => return Command::none(), @@ -574,6 +579,12 @@ impl App { None => Command::none(), } } + + fn user_data_index(user_datas: &[UserData], username: &str) -> Option { + user_datas + .binary_search_by(|probe| probe.name.as_str().cmp(username)) + .ok() + } } /// Implement [`cosmic::Application`] to integrate with COSMIC. @@ -620,11 +631,11 @@ impl cosmic::Application for App { usernames.sort_by(|a, b| a.1.cmp(&b.1)); //TODO: use last selected user - let (selected_username, uid) = flags + let (username, uid) = flags .user_datas .first() .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(); session_names.sort(); @@ -639,6 +650,8 @@ impl cosmic::Application for App { }) .or_else(|| session_names.first().cloned()) .unwrap_or_default(); + let data_idx = Some(0); + let selected_username = NameIndexPair { username, data_idx }; let app = App { core, @@ -764,7 +777,7 @@ impl cosmic::Application for App { SocketState::Open => { // When socket is opened, send create session return self.send_request(Request::CreateSession { - username: self.selected_username.clone(), + username: self.selected_username.username.clone(), }); } _ => {} @@ -801,14 +814,16 @@ impl cosmic::Application for App { if self.dropdown_opt == Some(Dropdown::User) { self.dropdown_opt = None; } - if username != self.selected_username { - self.selected_username = username.clone(); + if username != self.selected_username.username { + let data_idx = Self::user_data_index(&self.flags.user_datas, &username); + self.selected_username = NameIndexPair { username, data_idx }; self.surface_images.clear(); + // TODO: Remove search if let Some(session) = self .flags .user_datas .iter() - .find(|user| user.name == username) + .find(|user| user.name == self.selected_username.username) .and_then(|UserData { uid, .. }| { NonZeroU32::new(*uid).and_then(|uid| { self.flags @@ -835,19 +850,19 @@ impl cosmic::Application for App { .flags .user_datas .iter() - .find(|user| user.name == self.selected_username) + .find(|user| user.name == self.selected_username.username) .and_then(|UserData { uid, .. }| { NonZeroU32::new(*uid).map(|uid| self.flags.greeter_config.users.entry(uid)) }) else { - log::error!("Couldn't find user: {:?}", self.selected_username); + log::error!("Couldn't find user: {:?}", self.selected_username.username); return Command::none(); }; let Some(handler) = self.flags.greeter_config_handler.as_mut() else { log::error!( "Failed to update config for {} (UID: {}): no config handler", - self.selected_username, + self.selected_username.username, user_entry.key() ); return Command::none(); @@ -888,7 +903,7 @@ impl cosmic::Application for App { log::error!( "Failed to set {} as last selected session for {} (UID: {}): {:?}", self.selected_session, - self.selected_username, + self.selected_username.username, uid, err ); @@ -1030,11 +1045,14 @@ impl cosmic::Application for App { // xxx It may be prudent to store the index of the selected user to avoid // searches. This would also simplify logic elsewhere. let time = if self - .flags - .user_datas - .binary_search_by(|probe| probe.name.cmp(&self.selected_username)) - .ok() - .map(|i| self.flags.user_datas[i].clock_military_time) + .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) @@ -1135,7 +1153,7 @@ impl cosmic::Application for App { for (name, full_name) in self.usernames.iter() { items.push(menu_checklist( full_name, - name == &self.selected_username, + name == &self.selected_username.username, Message::Username(name.clone()), )); } @@ -1226,7 +1244,7 @@ impl cosmic::Application for App { } SocketState::Open => { 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 { Some(icon) => { column = column.push(