fix: pos-tracker is search-context aware, panic on no-action

This commit is contained in:
imgurbot12 2023-07-21 16:10:27 -07:00
parent c83febd10b
commit 25ee2f32c4
5 changed files with 32 additions and 19 deletions

View File

@ -52,6 +52,10 @@ div.actions {
padding-left: 5%;
}
div.action-name {
width: 10%;
}
div.actions.active {
display: flex;
flex-direction: column;

View File

@ -75,6 +75,7 @@ impl<'de> Deserialize<'de> for Keybind {
#[derive(Debug, PartialEq, Deserialize)]
pub struct KeyConfig {
pub exec: Vec<Keybind>,
pub exit: Vec<Keybind>,
pub move_up: Vec<Keybind>,
pub move_down: Vec<Keybind>,
@ -87,6 +88,7 @@ pub struct KeyConfig {
impl Default for KeyConfig {
fn default() -> Self {
return Self {
exec: vec![Keybind::new(Code::Enter)],
exit: vec![Keybind::new(Code::Escape)],
move_up: vec![Keybind::new(Code::ArrowUp)],
move_down: vec![Keybind::new(Code::ArrowDown)],

View File

@ -9,5 +9,6 @@ pub fn execute(action: &Action) {
Ok(args) => args,
Err(err) => panic!("{:?} invalid command {err}", action.exec),
};
Command::new(&args[0]).args(&args[1..]).exec();
let err = Command::new(&args[0]).args(&args[1..]).exec();
panic!("Command Error: {err:?}");
}

View File

@ -156,9 +156,17 @@ fn App(cx: Scope<App>) -> Element {
std::process::exit(0);
}
// retrieve results and filter based on search
let searchfn = new_searchfn(&cx.props.config, &search);
let results: Vec<&Entry> = cx
.props
.entries
.iter()
.filter(|entry| searchfn(entry))
.collect();
// retrieve results build and build position-tracker
let results = &cx.props.entries;
let tracker = PosTracker::new(cx, results);
let tracker = PosTracker::new(cx, results.clone());
let (pos, subpos) = tracker.position();
log::debug!("pos: {pos}, {subpos}");
@ -168,7 +176,12 @@ fn App(cx: Scope<App>) -> Element {
let key = &evt.code();
let mods = &evt.modifiers();
log::debug!("key: {key:?} mods: {mods:?}");
if matches(&keybinds.exit, mods, key) {
if matches(&keybinds.exec, mods, key) {
match tracker.action() {
Some(action) => execute(action),
None => panic!("No Action Configured"),
}
} else if matches(&keybinds.exit, mods, key) {
quit.set(true);
} else if matches(&keybinds.move_up, mods, key) {
tracker.shift_up();
@ -184,10 +197,8 @@ fn App(cx: Scope<App>) -> Element {
};
// pre-render results into elements
let searchfn = new_searchfn(&cx.props.config, &search);
let results_rendered: Vec<Element> = results
.iter()
.filter(|entry| searchfn(entry))
.enumerate()
.map(|(index, entry)| {
cx.render(rsx! {

View File

@ -1,6 +1,6 @@
//! GUI Application State Trackers and Utilities
use dioxus::prelude::{use_state, Scope, UseState};
use rmenu_plugin::Entry;
use rmenu_plugin::{Action, Entry};
use crate::App;
@ -8,21 +8,11 @@ use crate::App;
pub struct PosTracker<'a> {
pos: &'a UseState<usize>,
subpos: &'a UseState<usize>,
results: &'a Vec<Entry>,
}
impl<'a> Clone for PosTracker<'a> {
fn clone(&self) -> Self {
Self {
pos: self.pos,
subpos: self.subpos,
results: self.results,
}
}
results: Vec<&'a Entry>,
}
impl<'a> PosTracker<'a> {
pub fn new(cx: Scope<'a, App>, results: &'a Vec<Entry>) -> Self {
pub fn new(cx: Scope<'a, App>, results: Vec<&'a Entry>) -> Self {
let pos = use_state(cx, || 0);
let subpos = use_state(cx, || 0);
Self {
@ -46,6 +36,11 @@ impl<'a> PosTracker<'a> {
pub fn position(&self) -> (usize, usize) {
(self.pos.get().clone(), self.subpos.get().clone())
}
/// Get Action Linked To The Current Position
pub fn action(&self) -> Option<&Action> {
let (pos, subpos) = self.position();
self.results[pos].actions.get(subpos)
}
/// Move Position To SubMenu if it Exists
pub fn open_menu(&self) {
let index = *self.pos.get();