refactor: allow entering username
This commit is contained in:
parent
7aa41f6a16
commit
abc591db6d
5 changed files with 692 additions and 464 deletions
1068
Cargo.lock
generated
1068
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -45,13 +45,13 @@ xdg = "2.5.2"
|
||||||
tokio = { workspace = true, features = ["full"] }
|
tokio = { workspace = true, features = ["full"] }
|
||||||
wayland-client = "0.31.8"
|
wayland-client = "0.31.8"
|
||||||
# For network status using networkmanager feature
|
# For network status using networkmanager feature
|
||||||
cosmic-dbus-networkmanager = { git = "https://github.com/pop-os/dbus-settings-bindings", rev = "badfc6a", optional = true }
|
cosmic-dbus-networkmanager = { git = "https://github.com/pop-os/dbus-settings-bindings", optional = true }
|
||||||
# For logind integration using logind feature
|
# For logind integration using logind feature
|
||||||
logind-zbus = { version = "4", optional = true }
|
logind-zbus = { version = "5", optional = true }
|
||||||
# Fix zbus compilation by manually adding nix with user feature
|
# Fix zbus compilation by manually adding nix with user feature
|
||||||
nix = { workspace = true, optional = true }
|
nix = { workspace = true, optional = true }
|
||||||
# For power status with upower feature
|
# For power status with upower feature
|
||||||
upower_dbus = { git = "https://github.com/pop-os/dbus-settings-bindings", rev = "badfc6a", optional = true }
|
upower_dbus = { git = "https://github.com/pop-os/dbus-settings-bindings", optional = true }
|
||||||
# Required for some features
|
# Required for some features
|
||||||
zbus = { workspace = true, optional = true }
|
zbus = { workspace = true, optional = true }
|
||||||
# CLI arguments
|
# CLI arguments
|
||||||
|
|
@ -102,7 +102,7 @@ pwd = "1.4.0"
|
||||||
ron = "0.10.1"
|
ron = "0.10.1"
|
||||||
serde = "1"
|
serde = "1"
|
||||||
tokio = "1.39.1"
|
tokio = "1.39.1"
|
||||||
zbus = "4"
|
zbus = "5"
|
||||||
|
|
||||||
[workspace.dependencies.cosmic-applets-config]
|
[workspace.dependencies.cosmic-applets-config]
|
||||||
git = "https://github.com/pop-os/cosmic-applets"
|
git = "https://github.com/pop-os/cosmic-applets"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use cosmic_greeter_daemon::UserData;
|
use cosmic_greeter_daemon::UserData;
|
||||||
use std::{env, error::Error, future::pending, io, path::Path};
|
use std::{env, error::Error, future::pending, io, path::Path};
|
||||||
use zbus::{ConnectionBuilder, DBusError};
|
use zbus::{connection::Builder, DBusError};
|
||||||
|
|
||||||
//IMPORTANT: this function is critical to the security of this proxy. It must ensure that the
|
//IMPORTANT: this function is critical to the security of this proxy. It must ensure that the
|
||||||
// callback is executed with the permissions of the specified user id. A good test is to see if
|
// callback is executed with the permissions of the specified user id. A good test is to see if
|
||||||
|
|
@ -101,7 +101,7 @@ impl GreeterProxy {
|
||||||
async fn main() -> Result<(), Box<dyn Error>> {
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")).init();
|
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")).init();
|
||||||
|
|
||||||
let _conn = ConnectionBuilder::system()?
|
let _conn = Builder::system()?
|
||||||
.name("com.system76.CosmicGreeter")?
|
.name("com.system76.CosmicGreeter")?
|
||||||
.serve_at("/com/system76/CosmicGreeter", GreeterProxy)?
|
.serve_at("/com/system76/CosmicGreeter", GreeterProxy)?
|
||||||
.build()
|
.build()
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
cancel = Cancel
|
cancel = Cancel
|
||||||
caps-lock = Caps Lock is active.
|
caps-lock = Caps Lock is active.
|
||||||
|
enter-user = Enter name manually...
|
||||||
|
type-username = Username:
|
||||||
keyboard-layout = Keyboard layout
|
keyboard-layout = Keyboard layout
|
||||||
restart = Restart
|
restart = Restart
|
||||||
restart-now = Restart now?
|
restart-now = Restart now?
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ use cosmic::{
|
||||||
use cosmic_greeter_config::Config as CosmicGreeterConfig;
|
use cosmic_greeter_config::Config as CosmicGreeterConfig;
|
||||||
use cosmic_greeter_daemon::UserData;
|
use cosmic_greeter_daemon::UserData;
|
||||||
use greetd_ipc::Request;
|
use greetd_ipc::Request;
|
||||||
|
use std::sync::LazyLock;
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, hash_map},
|
collections::{HashMap, hash_map},
|
||||||
error::Error,
|
error::Error,
|
||||||
|
|
@ -49,6 +50,8 @@ use crate::{
|
||||||
fl,
|
fl,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static USERNAME_ID: LazyLock<iced::id::Id> = LazyLock::new(|| iced::id::Id::new("username-id"));
|
||||||
|
|
||||||
#[proxy(
|
#[proxy(
|
||||||
interface = "com.system76.CosmicGreeter",
|
interface = "com.system76.CosmicGreeter",
|
||||||
default_service = "com.system76.CosmicGreeter",
|
default_service = "com.system76.CosmicGreeter",
|
||||||
|
|
@ -351,6 +354,7 @@ pub enum Message {
|
||||||
Surface(surface::Action),
|
Surface(surface::Action),
|
||||||
Suspend,
|
Suspend,
|
||||||
Username(String),
|
Username(String),
|
||||||
|
EnterUser(bool, String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<common::Message> for Message {
|
impl From<common::Message> for Message {
|
||||||
|
|
@ -372,10 +376,12 @@ pub struct App {
|
||||||
dialog_page_opt: Option<DialogPage>,
|
dialog_page_opt: Option<DialogPage>,
|
||||||
dropdown_opt: Option<Dropdown>,
|
dropdown_opt: Option<Dropdown>,
|
||||||
heartbeat_handle: Option<cosmic::iced::task::Handle>,
|
heartbeat_handle: Option<cosmic::iced::task::Handle>,
|
||||||
|
entering_name: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
fn menu(&self, id: SurfaceId) -> Element<Message> {
|
fn menu(&self, id: SurfaceId) -> Element<Message> {
|
||||||
|
const DEFAULT_MENU_ITEM_HEIGHT: f32 = 36.;
|
||||||
let window_width = self
|
let window_width = self
|
||||||
.common
|
.common
|
||||||
.window_size
|
.window_size
|
||||||
|
|
@ -430,8 +436,20 @@ impl App {
|
||||||
.on_press(message),
|
.on_press(message),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let dropdown_menu = |items| {
|
let dropdown_menu = |items: Vec<_>| {
|
||||||
widget::container(widget::column::with_children(items))
|
let item_cnt = items.len();
|
||||||
|
|
||||||
|
let items = widget::column::with_children(items);
|
||||||
|
let items = if item_cnt > 7 {
|
||||||
|
Element::from(
|
||||||
|
widget::scrollable(items)
|
||||||
|
.height(Length::Fixed(DEFAULT_MENU_ITEM_HEIGHT * 7.)),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Element::from(items)
|
||||||
|
};
|
||||||
|
|
||||||
|
widget::container(items)
|
||||||
.padding(1)
|
.padding(1)
|
||||||
//TODO: move style to libcosmic
|
//TODO: move style to libcosmic
|
||||||
.class(theme::Container::custom(|theme| {
|
.class(theme::Container::custom(|theme| {
|
||||||
|
|
@ -485,7 +503,29 @@ impl App {
|
||||||
Message::Username(name.clone()),
|
Message::Username(name.clone()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
user_button = user_button.popup(dropdown_menu(items));
|
let item_cnt = items.len();
|
||||||
|
let menu_button = widget::menu::menu_button(vec![
|
||||||
|
Element::from(widget::Space::with_width(Length::Fixed(25.0))),
|
||||||
|
widget::text(fl!("enter-user"))
|
||||||
|
.align_x(iced::alignment::Horizontal::Left)
|
||||||
|
.into(),
|
||||||
|
])
|
||||||
|
.on_press(Message::EnterUser(true, String::new()))
|
||||||
|
.into();
|
||||||
|
let items = if item_cnt >= 6 {
|
||||||
|
dropdown_menu(vec![
|
||||||
|
widget::scrollable(widget::column::with_children(items))
|
||||||
|
.height(Length::Fixed(DEFAULT_MENU_ITEM_HEIGHT * 6.))
|
||||||
|
.into(),
|
||||||
|
widget::divider::horizontal::light().into(),
|
||||||
|
menu_button,
|
||||||
|
])
|
||||||
|
} else {
|
||||||
|
items.push(menu_button);
|
||||||
|
dropdown_menu(items)
|
||||||
|
};
|
||||||
|
|
||||||
|
user_button = user_button.popup(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut session_button = widget::popover(
|
let mut session_button = widget::popover(
|
||||||
|
|
@ -575,7 +615,8 @@ impl 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.username {
|
if !self.entering_name && 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(
|
||||||
|
|
@ -600,6 +641,17 @@ impl App {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if self.entering_name {
|
||||||
|
column = column.push(
|
||||||
|
widget::text_input(
|
||||||
|
fl!("type-username"),
|
||||||
|
self.selected_username.username.as_str(),
|
||||||
|
)
|
||||||
|
.id(USERNAME_ID.clone())
|
||||||
|
.on_input(|input| Message::EnterUser(false, input))
|
||||||
|
.on_submit(|v| Message::Username(v)),
|
||||||
|
)
|
||||||
|
}
|
||||||
match &self.common.prompt_opt {
|
match &self.common.prompt_opt {
|
||||||
Some((prompt, secret, value_opt)) => match value_opt {
|
Some((prompt, secret, value_opt)) => match value_opt {
|
||||||
Some(value) => {
|
Some(value) => {
|
||||||
|
|
@ -875,6 +927,7 @@ impl cosmic::Application for App {
|
||||||
dialog_page_opt: None,
|
dialog_page_opt: None,
|
||||||
dropdown_opt: None,
|
dropdown_opt: None,
|
||||||
heartbeat_handle: None,
|
heartbeat_handle: None,
|
||||||
|
entering_name: false,
|
||||||
};
|
};
|
||||||
(app, common_task)
|
(app, common_task)
|
||||||
}
|
}
|
||||||
|
|
@ -1035,11 +1088,22 @@ impl cosmic::Application for App {
|
||||||
self.dropdown_opt = None;
|
self.dropdown_opt = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Message::EnterUser(focus_input, username) => {
|
||||||
|
self.entering_name = true;
|
||||||
|
self.selected_username = NameIndexPair {
|
||||||
|
data_idx: Self::user_data_index(&self.flags.user_datas, &username),
|
||||||
|
username,
|
||||||
|
};
|
||||||
|
if focus_input {
|
||||||
|
return widget::text_input::focus(USERNAME_ID.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
Message::Username(username) => {
|
Message::Username(username) => {
|
||||||
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.username {
|
if self.entering_name || username != self.selected_username.username {
|
||||||
|
self.entering_name = false;
|
||||||
let data_idx = Self::user_data_index(&self.flags.user_datas, &username);
|
let data_idx = Self::user_data_index(&self.flags.user_datas, &username);
|
||||||
self.selected_username = NameIndexPair { username, data_idx };
|
self.selected_username = NameIndexPair { username, data_idx };
|
||||||
self.common.surface_images.clear();
|
self.common.surface_images.clear();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue