add password + enter for worf warden

This commit is contained in:
Alexander Mohr 2025-05-16 22:31:58 +02:00
parent 6632f2f123
commit ab56048574
3 changed files with 79 additions and 61 deletions

View file

@ -44,7 +44,7 @@ impl PasswordProvider {
key.clone(),
None,
None,
vec![],
vec![].into_iter().collect(),
None,
0.0,
Some(MenuItemMetaData { ids: value.clone() }),
@ -59,7 +59,7 @@ impl PasswordProvider {
format!("Error from rbw: {error}"),
None,
None,
vec![],
vec![].into_iter().collect(),
None,
0.0,
None,
@ -79,11 +79,11 @@ impl PasswordProvider {
rbw_get_user(id, false)?,
None,
None,
vec![],
vec![].into_iter().collect(),
None,
0.0,
Some(MenuItemMetaData {
ids: vec![id.clone()],
ids: vec![id.clone()].into_iter().collect(),
}),
))
})
@ -125,7 +125,16 @@ fn keyboard_type(text: &str) {
fn keyboard_tab() {
Command::new("ydotool")
.arg("TAB")
.arg("type")
.arg("\t")
.output()
.expect("Failed to execute ydotool");
}
fn keyboard_return() {
Command::new("ydotool")
.arg("type")
.arg("\n")
.output()
.expect("Failed to execute ydotool");
}
@ -178,7 +187,7 @@ fn rbw_get_totp(id: &str, copy: bool) -> Result<String, String> {
fn key_type_all() -> KeyBinding {
KeyBinding {
key: Key::Num1,
modifiers: Modifier::Alt,
modifiers: vec![Modifier::Alt].into_iter().collect(),
label: "<b>Alt+1</b> Type All".to_string(),
}
}
@ -186,7 +195,7 @@ fn key_type_all() -> KeyBinding {
fn key_type_user() -> KeyBinding {
KeyBinding {
key: Key::Num2,
modifiers: Modifier::Alt,
modifiers: vec![Modifier::Alt].into_iter().collect(),
label: "<b>Alt+2</b> Type User".to_string(),
}
}
@ -194,15 +203,23 @@ fn key_type_user() -> KeyBinding {
fn key_type_password() -> KeyBinding {
KeyBinding {
key: Key::Num3,
modifiers: Modifier::Alt,
modifiers: vec![Modifier::Alt].into_iter().collect(),
label: "<b>Alt+3</b> Type Password".to_string(),
}
}
fn key_type_password_and_enter() -> KeyBinding {
KeyBinding {
key: Key::Hash,
modifiers: vec![Modifier::Alt, Modifier::Shift].into_iter().collect(),
label: "<b>Alt+Shift+3</b> Type Password + Enter".to_string(),
}
}
fn key_type_totp() -> KeyBinding {
KeyBinding {
key: Key::Num4,
modifiers: Modifier::Alt,
modifiers: vec![Modifier::Alt].into_iter().collect(),
label: "<b>Alt+4</b> Type Totp".to_string(),
}
}
@ -210,7 +227,7 @@ fn key_type_totp() -> KeyBinding {
fn key_sync() -> KeyBinding {
KeyBinding {
key: Key::R,
modifiers: Modifier::Alt,
modifiers: vec![Modifier::Alt].into_iter().collect(),
label: "<b>Alt+r</b> Sync".to_string(),
}
}
@ -219,7 +236,7 @@ fn key_sync() -> KeyBinding {
fn key_totp() -> KeyBinding {
KeyBinding {
key: Key::T,
modifiers: Modifier::Alt,
modifiers: vec![Modifier::Alt].into_iter().collect(),
label: "<b>Alt+t</b> Totp".to_string(),
}
}
@ -227,7 +244,7 @@ fn key_totp() -> KeyBinding {
fn key_lock() -> KeyBinding {
KeyBinding {
key: Key::L,
modifiers: Modifier::Alt,
modifiers: vec![Modifier::Alt].into_iter().collect(),
label: "<b>Alt+l</b> Lock".to_string(),
}
}
@ -242,6 +259,7 @@ fn show(config: Config, provider: PasswordProvider) -> Result<(), String> {
key_type_all(),
key_type_user(),
key_type_password(),
key_type_password_and_enter(),
key_type_totp(),
key_sync(),
key_totp(),
@ -256,7 +274,7 @@ fn show(config: Config, provider: PasswordProvider) -> Result<(), String> {
let id = meta.ids.first().unwrap_or(&selection.menu.label);
sleep(Duration::from_millis(250));
sleep(Duration::from_millis(500));
if let Some(key) = selection.custom_key {
if key == key_type_all() {
keyboard_type(&rbw_get_user(id, false)?);
@ -266,6 +284,9 @@ fn show(config: Config, provider: PasswordProvider) -> Result<(), String> {
keyboard_type(&rbw_get_user(id, false)?);
} else if key == key_type_password() {
keyboard_type(&rbw_get_password(id, false)?);
} else if key == key_type_password_and_enter() {
keyboard_type(&rbw_get_password(id, false)?);
keyboard_return();
} else if key == key_type_totp() {
keyboard_type(&rbw_get_totp(id, false)?);
} else if key == key_lock() {

View file

@ -1,12 +1,11 @@
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::{Duration, Instant};
use std::time::Instant;
use crossbeam::channel;
use crossbeam::channel::Sender;
use crossbeam::channel::internal::SelectHandle;
use gdk4::Display;
use gdk4::gio::File;
use gdk4::glib::{MainContext, Propagation};
@ -339,24 +338,39 @@ pub enum Modifier {
None,
}
impl From<gdk4::ModifierType> for Modifier {
fn from(value: gdk4::ModifierType) -> Self {
match value {
gdk4::ModifierType::SHIFT_MASK => Modifier::Shift,
gdk4::ModifierType::CONTROL_MASK => Modifier::Control,
gdk4::ModifierType::ALT_MASK => Modifier::Alt,
gdk4::ModifierType::SUPER_MASK => Modifier::Super,
gdk4::ModifierType::META_MASK => Modifier::Meta,
gdk4::ModifierType::LOCK_MASK => Modifier::CapsLock,
_ => Modifier::None,
fn modifiers_from_mask(mask: gdk4::ModifierType) -> HashSet<Modifier> {
let mut modifiers = HashSet::new();
if mask.contains(gdk4::ModifierType::SHIFT_MASK) {
modifiers.insert(Modifier::Shift);
}
if mask.contains(gdk4::ModifierType::CONTROL_MASK) {
modifiers.insert(Modifier::Control);
}
if mask.contains(gdk4::ModifierType::ALT_MASK) {
modifiers.insert(Modifier::Alt);
}
if mask.contains(gdk4::ModifierType::SUPER_MASK) {
modifiers.insert(Modifier::Super);
}
if mask.contains(gdk4::ModifierType::META_MASK) {
modifiers.insert(Modifier::Meta);
}
if mask.contains(gdk4::ModifierType::LOCK_MASK) {
modifiers.insert(Modifier::CapsLock);
}
#[derive(Clone, PartialEq)]
if modifiers.is_empty() {
modifiers.insert(Modifier::None);
}
modifiers
}
#[derive(Clone, PartialEq, Debug)]
pub struct KeyBinding {
pub key: Key,
pub modifiers: Modifier, // todo support masks
pub modifiers: HashSet<Modifier>,
pub label: String,
}
@ -566,22 +580,19 @@ fn build_ui<T, P>(
let (_changed, provider_elements) = get_provider_elements.join().unwrap();
log::debug!("got items after {:?}", wait_for_items.elapsed());
let animate_cfg = config.clone();
let active_cfg = config.clone();
let map_cfg = config.clone();
let animate_window = ui_elements.window.clone();
let (sender, receiver) = channel::bounded(1);
animate_window.connect_is_active_notify(move |w| {
w.set_opacity(1.0);
window_show_resize(&animate_cfg.clone(), w);
if let Err(e) = sender.send(()) {
log::debug!("cannot unblock menu builder {e:?}");
}
window_show_resize(&active_cfg.clone(), w);
});
animate_window.connect_map(move |w| {
window_show_resize(&map_cfg.clone(), w);
});
build_ui_from_menu_items(&ui_elements, &meta, provider_elements, Some(receiver));
build_ui_from_menu_items(&ui_elements, &meta, provider_elements);
// hide the fact that we are starting with a small window
ui_elements.window.set_opacity(0.01);
let window_start = Instant::now();
ui_elements.window.present();
log::debug!("window show took {:?}", window_start.elapsed());
@ -685,7 +696,6 @@ fn build_ui_from_menu_items<T: Clone + 'static + Send>(
ui: &Rc<UiElements<T>>,
meta: &Rc<MetaData<T>>,
mut items: Vec<MenuItem<T>>,
wait_for_signal: Option<channel::Receiver<()>>,
) {
let start = Instant::now();
{
@ -699,12 +709,6 @@ fn build_ui_from_menu_items<T: Clone + 'static + Send>(
let ui_clone = Rc::<UiElements<T>>::clone(ui);
glib::idle_add_local(move || {
if let Some(wait) = &wait_for_signal {
if !wait.is_ready() {
return ControlFlow::Continue;
}
}
ui_clone.main_box.unset_sort_func();
let mut done = false;
{
@ -797,15 +801,18 @@ fn handle_key_press<T: Clone + 'static + Send>(
let update_view_from_provider = |query: &String| {
let (changed, filtered_list) = meta.item_provider.lock().unwrap().get_elements(Some(query));
if changed {
build_ui_from_menu_items(ui, meta, filtered_list, None);
build_ui_from_menu_items(ui, meta, filtered_list);
}
update_view(query);
};
if let Some(custom_keys) = custom_keys {
let mods = modifiers_from_mask(modifier_type);
for custom_key in custom_keys {
if custom_key.key == keyboard_key.into() && custom_key.modifiers == modifier_type.into()
{
log::debug!(
"comparing custom key {custom_key:?} to mask {mods:?} and key {keyboard_key}"
);
if custom_key.key == keyboard_key.into() && mods.is_subset(&custom_key.modifiers) {
let search_lock = ui.search_text.lock().unwrap();
if let Err(e) = handle_selected_item(
ui,
@ -874,7 +881,7 @@ fn handle_key_press<T: Clone + 'static + Send>(
if let Some(changed) = opt_changed {
let items = changed.0.1.unwrap_or_default();
if changed.0.0 {
build_ui_from_menu_items(ui, meta, items, None);
build_ui_from_menu_items(ui, meta, items);
}
let query = changed.1;

View file

@ -1,8 +1,7 @@
use crate::config::Config;
use crate::desktop::{copy_to_clipboard, spawn_fork};
use crate::desktop::spawn_fork;
use crate::gui::{ItemProvider, MenuItem};
use crate::modes::drun::{DRunProvider, update_drun_cache_and_run};
use crate::modes::emoji::EmojiProvider;
use crate::modes::file::FileItemProvider;
use crate::modes::math::MathProvider;
use crate::modes::ssh;
@ -16,7 +15,6 @@ enum AutoRunType {
DRun,
File,
Ssh,
Emoji,
// WebSearch,
}
@ -152,14 +150,6 @@ pub fn show(config: &Config) -> Result<(), Error> {
ssh::launch(&selection_result, config)?;
break;
}
AutoRunType::Emoji => {
if let Some(action) = selection_result.action {
copy_to_clipboard(action, None)?;
} else {
return Err(Error::MissingAction);
}
break;
}
}
} else if selection_result.label.starts_with("ssh") {
selection_result.label = selection_result.label.chars().skip(4).collect();