fix dmenu empty selection
This commit is contained in:
parent
2114403ae9
commit
c040a28539
3 changed files with 69 additions and 37 deletions
|
@ -1,15 +1,15 @@
|
||||||
|
use enigo::{Enigo, Keyboard};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use enigo::{Enigo, Keyboard};
|
|
||||||
|
|
||||||
use worf_lib::{config, gui, Error};
|
|
||||||
use worf_lib::config::Config;
|
use worf_lib::config::Config;
|
||||||
use worf_lib::gui::{KeyBinding, ItemProvider, MenuItem, Modifier, Key};
|
use worf_lib::gui::{ItemProvider, Key, KeyBinding, MenuItem, Modifier};
|
||||||
|
use worf_lib::{Error, config, gui};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct PasswordProvider {
|
struct PasswordProvider {
|
||||||
items: Vec<MenuItem<String>>
|
items: Vec<MenuItem<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PasswordProvider {
|
impl PasswordProvider {
|
||||||
|
@ -22,20 +22,29 @@ impl PasswordProvider {
|
||||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||||
|
|
||||||
// todo the own solution should support images.
|
// todo the own solution should support images.
|
||||||
let mut items: Vec<_>= stdout.lines().map(|line|
|
let mut items: Vec<_> = stdout
|
||||||
MenuItem::new(line.to_owned(), None, None, vec![], None, 0.0, Some(String::new()))
|
.lines()
|
||||||
).collect();
|
.map(|line| {
|
||||||
|
MenuItem::new(
|
||||||
|
line.to_owned(),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
vec![],
|
||||||
|
None,
|
||||||
|
0.0,
|
||||||
|
Some(String::new()),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
gui::apply_sort(&mut items, &config.sort_order());
|
gui::apply_sort(&mut items, &config.sort_order());
|
||||||
|
|
||||||
Self {
|
Self { items }
|
||||||
items
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ItemProvider<String> for PasswordProvider {
|
impl ItemProvider<String> for PasswordProvider {
|
||||||
fn get_elements(&mut self, _: Option<&str>) -> (bool, Vec<MenuItem<String>>) {
|
fn get_elements(&mut self, _: Option<&str>) -> (bool, Vec<MenuItem<String>>) {
|
||||||
(false, self.items.clone())
|
(false, self.items.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_sub_elements(&mut self, _: &MenuItem<String>) -> (bool, Option<Vec<MenuItem<String>>>) {
|
fn get_sub_elements(&mut self, _: &MenuItem<String>) -> (bool, Option<Vec<MenuItem<String>>>) {
|
||||||
|
@ -52,10 +61,12 @@ fn rbw_get(name: &str, field: &str) -> String {
|
||||||
.output()
|
.output()
|
||||||
.expect("Failed to execute command");
|
.expect("Failed to execute command");
|
||||||
|
|
||||||
String::from_utf8_lossy(&output.stdout).trim_end().to_string()
|
String::from_utf8_lossy(&output.stdout)
|
||||||
|
.trim_end()
|
||||||
|
.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rbw_get_user(name: &str) -> String{
|
fn rbw_get_user(name: &str) -> String {
|
||||||
rbw_get(name, "user")
|
rbw_get(name, "user")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +88,7 @@ fn main() -> anyhow::Result<()> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let type_user = KeyBinding {
|
let type_user = KeyBinding {
|
||||||
key: Key::Num2,
|
key: Key::Num2,
|
||||||
modifiers: Modifier::Alt,
|
modifiers: Modifier::Alt,
|
||||||
label: "<b>Alt+2</b> Type All".to_string(),
|
label: "<b>Alt+2</b> Type All".to_string(),
|
||||||
};
|
};
|
||||||
|
@ -89,25 +100,25 @@ fn main() -> anyhow::Result<()> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let reload = KeyBinding {
|
let reload = KeyBinding {
|
||||||
key: Key::R,
|
key: Key::R,
|
||||||
modifiers: Modifier::Alt,
|
modifiers: Modifier::Alt,
|
||||||
label: "<b>Alt+r</b> Sync".to_string(),
|
label: "<b>Alt+r</b> Sync".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let urls = KeyBinding {
|
let urls = KeyBinding {
|
||||||
key: Key::U, // switch view to urls
|
key: Key::U, // switch view to urls
|
||||||
modifiers: Modifier::Alt,
|
modifiers: Modifier::Alt,
|
||||||
label: "<b>Alt+u</b> Sync".to_string(),
|
label: "<b>Alt+u</b> Sync".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let names = KeyBinding {
|
let names = KeyBinding {
|
||||||
key: Key::N, // switch view to names
|
key: Key::N, // switch view to names
|
||||||
modifiers: Modifier::Alt,
|
modifiers: Modifier::Alt,
|
||||||
label: "<b>Alt+n</b> Sync".to_string(),
|
label: "<b>Alt+n</b> Sync".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let folders = KeyBinding {
|
let folders = KeyBinding {
|
||||||
key: Key::C, // switch view to folders
|
key: Key::C, // switch view to folders
|
||||||
modifiers: Modifier::Alt,
|
modifiers: Modifier::Alt,
|
||||||
label: "<b>Alt+c</b> Sync".to_string(),
|
label: "<b>Alt+c</b> Sync".to_string(),
|
||||||
};
|
};
|
||||||
|
@ -124,23 +135,37 @@ fn main() -> anyhow::Result<()> {
|
||||||
label: "<b>Alt+l</b> Sync".to_string(),
|
label: "<b>Alt+l</b> Sync".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
match gui::show(config, provider, false, None, Some(vec![type_all.clone(), type_user, type_totp, reload, urls, names, folders, totp, lock])) {
|
match gui::show(
|
||||||
|
config,
|
||||||
|
provider,
|
||||||
|
false,
|
||||||
|
None,
|
||||||
|
Some(vec![
|
||||||
|
type_all.clone(),
|
||||||
|
type_user,
|
||||||
|
type_totp,
|
||||||
|
reload,
|
||||||
|
urls,
|
||||||
|
names,
|
||||||
|
folders,
|
||||||
|
totp,
|
||||||
|
lock,
|
||||||
|
]),
|
||||||
|
) {
|
||||||
Ok(selection) => {
|
Ok(selection) => {
|
||||||
let mut enigo = Enigo::new(&enigo::Settings::default())?;
|
let mut enigo = Enigo::new(&enigo::Settings::default())?;
|
||||||
let id = selection.menu.label.replace("\n", "");
|
let id = selection.menu.label.replace("\n", "");
|
||||||
sleep(Duration::from_millis(250));
|
sleep(Duration::from_millis(250));
|
||||||
if let Some(key) = selection.custom_key {
|
if let Some(key) = selection.custom_key {
|
||||||
if key.label == type_all.label {
|
if key.label == type_all.label {
|
||||||
enigo.text(&rbw_get_user(&id))?;
|
enigo.text(&rbw_get_user(&id))?;
|
||||||
enigo.key(enigo::Key::Tab, enigo::Direction::Press)?;
|
enigo.key(enigo::Key::Tab, enigo::Direction::Press)?;
|
||||||
enigo.key(enigo::Key::Tab, enigo::Direction::Release)?;
|
enigo.key(enigo::Key::Tab, enigo::Direction::Release)?;
|
||||||
enigo.text(&rbw_get_password(&id))?;
|
enigo.text(&rbw_get_password(&id))?;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => return Err(anyhow::anyhow!(e)),
|
||||||
return Err(anyhow::anyhow!(e))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -793,7 +793,7 @@ fn handle_key_press<T: Clone + 'static + Send>(
|
||||||
Some(&search_lock),
|
Some(&search_lock),
|
||||||
None,
|
None,
|
||||||
meta.new_on_empty,
|
meta.new_on_empty,
|
||||||
Some(&custom_key),
|
Some(custom_key),
|
||||||
) {
|
) {
|
||||||
log::error!("{e}");
|
log::error!("{e}");
|
||||||
}
|
}
|
||||||
|
@ -953,14 +953,16 @@ where
|
||||||
T: Clone + Send,
|
T: Clone + Send,
|
||||||
{
|
{
|
||||||
if let Some(selected_item) = item {
|
if let Some(selected_item) = item {
|
||||||
send_selected_item(&ui, meta, custom_key, &selected_item);
|
send_selected_item(ui, meta, custom_key, &selected_item);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else if let Some(s) = ui.main_box.selected_children().into_iter().next() {
|
} else if let Some(s) = ui.main_box.selected_children().into_iter().next() {
|
||||||
let list_items = ui.menu_rows.lock().unwrap();
|
let list_items = ui.menu_rows.lock().unwrap();
|
||||||
let item = list_items.get(&s);
|
let item = list_items.get(&s);
|
||||||
if let Some(selected_item) = item {
|
if let Some(selected_item) = item {
|
||||||
send_selected_item(&ui, meta, custom_key, selected_item);
|
if selected_item.visible {
|
||||||
return Ok(());
|
send_selected_item(ui, meta, custom_key, selected_item);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -984,9 +986,13 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_selected_item<T>(ui: &&UiElements<T>, meta: &MetaData<T>, custom_key: Option<&KeyBinding>, selected_item: &MenuItem<T>)
|
fn send_selected_item<T>(
|
||||||
where
|
ui: &UiElements<T>,
|
||||||
T: Clone + Send
|
meta: &MetaData<T>,
|
||||||
|
custom_key: Option<&KeyBinding>,
|
||||||
|
selected_item: &MenuItem<T>,
|
||||||
|
) where
|
||||||
|
T: Clone + Send,
|
||||||
{
|
{
|
||||||
close_gui(&ui.app);
|
close_gui(&ui.app);
|
||||||
if let Err(e) = meta.selected_sender.send(Ok(Selection {
|
if let Err(e) = meta.selected_sender.send(Ok(Selection {
|
||||||
|
|
|
@ -38,6 +38,7 @@ fn main() -> anyhow::Result<()> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(anyhow!("No mode provided"))
|
log::error!("No mode provided");
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue