improv(network): focus the secure input
This commit is contained in:
parent
19f577c0ea
commit
4d56b2accc
2 changed files with 58 additions and 3 deletions
|
|
@ -4,10 +4,12 @@
|
||||||
pub mod nmcli;
|
pub mod nmcli;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, LazyLock};
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use cosmic::dialog::file_chooser::FileFilter;
|
use cosmic::dialog::file_chooser::FileFilter;
|
||||||
|
use cosmic::task;
|
||||||
|
use cosmic::widget::text_input::focus;
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
Apply, Element, Task,
|
Apply, Element, Task,
|
||||||
iced::{Alignment, Length},
|
iced::{Alignment, Length},
|
||||||
|
|
@ -26,6 +28,8 @@ use tokio::sync::Mutex;
|
||||||
|
|
||||||
use crate::pages::networking::SecretSender;
|
use crate::pages::networking::SecretSender;
|
||||||
|
|
||||||
|
pub static SECURE_INPUT_VPN: LazyLock<widget::Id> = LazyLock::new(widget::Id::unique);
|
||||||
|
|
||||||
pub type ConnectionId = Arc<str>;
|
pub type ConnectionId = Arc<str>;
|
||||||
pub type InterfaceId = String;
|
pub type InterfaceId = String;
|
||||||
|
|
||||||
|
|
@ -47,6 +51,8 @@ pub enum Message {
|
||||||
Deactivate(ConnectionId),
|
Deactivate(ConnectionId),
|
||||||
/// An error occurred.
|
/// An error occurred.
|
||||||
Error(ErrorKind, String),
|
Error(ErrorKind, String),
|
||||||
|
/// Focus the secure input
|
||||||
|
FocusSecureInput,
|
||||||
/// VPN connection error.
|
/// VPN connection error.
|
||||||
VpnDialogError(VpnDialog),
|
VpnDialogError(VpnDialog),
|
||||||
/// Update the list of known connections.
|
/// Update the list of known connections.
|
||||||
|
|
@ -252,6 +258,7 @@ impl page::Page<crate::pages::Message> for Page {
|
||||||
Some(Message::TogglePasswordVisibility),
|
Some(Message::TogglePasswordVisibility),
|
||||||
*password_hidden,
|
*password_hidden,
|
||||||
)
|
)
|
||||||
|
.id(SECURE_INPUT_VPN.clone())
|
||||||
.on_input(|input| Message::PasswordUpdate(SecureString::from(input)))
|
.on_input(|input| Message::PasswordUpdate(SecureString::from(input)))
|
||||||
.on_submit(|_| {
|
.on_submit(|_| {
|
||||||
if error.is_some() {
|
if error.is_some() {
|
||||||
|
|
@ -518,6 +525,7 @@ impl Page {
|
||||||
error: None,
|
error: None,
|
||||||
tx: Arc::new(Mutex::new(None)),
|
tx: Arc::new(Mutex::new(None)),
|
||||||
});
|
});
|
||||||
|
return task::message(Message::FocusSecureInput);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let connection_name = settings.id.clone();
|
let connection_name = settings.id.clone();
|
||||||
|
|
@ -796,6 +804,7 @@ impl Page {
|
||||||
tx,
|
tx,
|
||||||
error: None,
|
error: None,
|
||||||
});
|
});
|
||||||
|
return task::message(Message::FocusSecureInput);
|
||||||
}
|
}
|
||||||
nm_secret_agent::Event::CancelGetSecrets { uuid: _, name: _ } => {
|
nm_secret_agent::Event::CancelGetSecrets { uuid: _, name: _ } => {
|
||||||
self.dialog = self
|
self.dialog = self
|
||||||
|
|
@ -824,9 +833,27 @@ impl Page {
|
||||||
password_hidden: true,
|
password_hidden: true,
|
||||||
tx: Arc::new(Mutex::new(None)),
|
tx: Arc::new(Mutex::new(None)),
|
||||||
});
|
});
|
||||||
|
return task::message(Message::FocusSecureInput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Message::FocusSecureInput => {
|
||||||
|
// retry until the widget is in the tree and focused or the dialog is removed.
|
||||||
|
if matches!(self.dialog, Some(VpnDialog::Password { .. })) {
|
||||||
|
return cosmic::iced_runtime::task::widget(
|
||||||
|
cosmic::iced_core::widget::operation::focusable::find_focused(),
|
||||||
|
)
|
||||||
|
.collect()
|
||||||
|
.then(|id| {
|
||||||
|
if id.get(0).is_some_and(|id| *id == SECURE_INPUT_VPN.clone()) {
|
||||||
|
Task::none()
|
||||||
|
} else {
|
||||||
|
focus(SECURE_INPUT_VPN.clone())
|
||||||
|
.chain(task::message(Message::FocusSecureInput))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::none()
|
Task::none()
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::{BTreeMap, BTreeSet},
|
collections::{BTreeMap, BTreeSet},
|
||||||
sync::Arc,
|
sync::{Arc, LazyLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
|
@ -13,7 +13,8 @@ use cosmic::{
|
||||||
iced::{Alignment, Length},
|
iced::{Alignment, Length},
|
||||||
iced_core::text::Wrapping,
|
iced_core::text::Wrapping,
|
||||||
iced_widget::focus_next,
|
iced_widget::focus_next,
|
||||||
widget::{self, column, icon},
|
task,
|
||||||
|
widget::{self, column, icon, text_input::focus},
|
||||||
};
|
};
|
||||||
use cosmic_settings_network_manager_subscription::{
|
use cosmic_settings_network_manager_subscription::{
|
||||||
self as network_manager, NetworkManagerState,
|
self as network_manager, NetworkManagerState,
|
||||||
|
|
@ -29,6 +30,8 @@ use tokio::sync::Mutex;
|
||||||
|
|
||||||
use crate::pages::networking::SecretSender;
|
use crate::pages::networking::SecretSender;
|
||||||
|
|
||||||
|
pub static SECURE_INPUT_WIFI: LazyLock<widget::Id> = LazyLock::new(widget::Id::unique);
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
/// Add a network connection with nm-connection-editor
|
/// Add a network connection with nm-connection-editor
|
||||||
|
|
@ -47,6 +50,8 @@ pub enum Message {
|
||||||
Error(String),
|
Error(String),
|
||||||
/// Identity update from the dialog
|
/// Identity update from the dialog
|
||||||
IdentityUpdate(String),
|
IdentityUpdate(String),
|
||||||
|
/// Focus the secure input
|
||||||
|
FocusSecureInput,
|
||||||
/// Create a dialog to ask for confirmation on forgetting a connection.
|
/// Create a dialog to ask for confirmation on forgetting a connection.
|
||||||
ForgetRequest(network_manager::SSID),
|
ForgetRequest(network_manager::SSID),
|
||||||
/// Forget a known access point.
|
/// Forget a known access point.
|
||||||
|
|
@ -178,6 +183,7 @@ impl page::Page<crate::pages::Message> for Page {
|
||||||
Some(Message::TogglePasswordVisibility),
|
Some(Message::TogglePasswordVisibility),
|
||||||
*password_hidden,
|
*password_hidden,
|
||||||
)
|
)
|
||||||
|
.id(SECURE_INPUT_WIFI.clone())
|
||||||
.on_input(|input| Message::PasswordUpdate(SecureString::from(input)))
|
.on_input(|input| Message::PasswordUpdate(SecureString::from(input)))
|
||||||
.on_submit(|_| Message::ConnectWithPassword);
|
.on_submit(|_| Message::ConnectWithPassword);
|
||||||
|
|
||||||
|
|
@ -365,6 +371,7 @@ impl Page {
|
||||||
password_hidden: true,
|
password_hidden: true,
|
||||||
tx: Arc::new(Mutex::new(None)),
|
tx: Arc::new(Mutex::new(None)),
|
||||||
});
|
});
|
||||||
|
return task::message(Message::FocusSecureInput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -386,6 +393,7 @@ impl Page {
|
||||||
password_hidden: true,
|
password_hidden: true,
|
||||||
tx: Arc::new(Mutex::new(None)),
|
tx: Arc::new(Mutex::new(None)),
|
||||||
});
|
});
|
||||||
|
return task::message(Message::FocusSecureInput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -525,6 +533,7 @@ impl Page {
|
||||||
password_hidden: true,
|
password_hidden: true,
|
||||||
tx: Arc::new(Mutex::new(None)),
|
tx: Arc::new(Mutex::new(None)),
|
||||||
});
|
});
|
||||||
|
return task::message(Message::FocusSecureInput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::PasswordUpdate(pass) => {
|
Message::PasswordUpdate(pass) => {
|
||||||
|
|
@ -713,6 +722,7 @@ impl Page {
|
||||||
identity: matches!(ap.network_type, NetworkType::EAP).then(String::new),
|
identity: matches!(ap.network_type, NetworkType::EAP).then(String::new),
|
||||||
tx,
|
tx,
|
||||||
});
|
});
|
||||||
|
return task::message(Message::FocusSecureInput);
|
||||||
}
|
}
|
||||||
nm_secret_agent::Event::CancelGetSecrets { uuid: _, name: _ } => {
|
nm_secret_agent::Event::CancelGetSecrets { uuid: _, name: _ } => {
|
||||||
self.dialog = self
|
self.dialog = self
|
||||||
|
|
@ -738,9 +748,27 @@ impl Page {
|
||||||
identity,
|
identity,
|
||||||
hw_address,
|
hw_address,
|
||||||
});
|
});
|
||||||
|
return task::message(Message::FocusSecureInput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Message::FocusSecureInput => {
|
||||||
|
// retry until the widget is in the tree and focused or the dialog is removed.
|
||||||
|
if matches!(self.dialog, Some(WiFiDialog::Password { .. })) {
|
||||||
|
return cosmic::iced_runtime::task::widget(
|
||||||
|
cosmic::iced_core::widget::operation::focusable::find_focused(),
|
||||||
|
)
|
||||||
|
.collect()
|
||||||
|
.then(|id| {
|
||||||
|
if id.get(0).is_some_and(|id| *id == SECURE_INPUT_WIFI.clone()) {
|
||||||
|
Task::none()
|
||||||
|
} else {
|
||||||
|
focus(SECURE_INPUT_WIFI.clone())
|
||||||
|
.chain(task::message(Message::FocusSecureInput))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::none()
|
Task::none()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue