feat: basic entry selection
This commit is contained in:
parent
2fd3b41e03
commit
95bfede1e0
1 changed files with 64 additions and 14 deletions
|
|
@ -22,6 +22,10 @@ enum Message {
|
|||
OpenDb,
|
||||
DbOpened(Result<keepass::Database, String>),
|
||||
|
||||
SelectionChanged(usize),
|
||||
SelectionUp,
|
||||
SelectionDown,
|
||||
|
||||
FocusNext,
|
||||
FocusPrevious,
|
||||
}
|
||||
|
|
@ -33,6 +37,9 @@ struct State {
|
|||
|
||||
db: Option<keepass::Database>,
|
||||
|
||||
db_view: Vec<keepass::db::Entry>,
|
||||
selected_entry: usize,
|
||||
|
||||
password: String,
|
||||
|
||||
is_secure: bool,
|
||||
|
|
@ -88,6 +95,10 @@ impl State {
|
|||
match result {
|
||||
Ok(db) => {
|
||||
self.error = "".into();
|
||||
self.db_view = db
|
||||
.iter_all_entries()
|
||||
.map(|entry_ref| entry_ref.clone())
|
||||
.collect();
|
||||
self.db = Some(db)
|
||||
}
|
||||
Err(e) => self.error = e.into(),
|
||||
|
|
@ -95,6 +106,20 @@ impl State {
|
|||
self.status = "".into();
|
||||
}
|
||||
|
||||
Message::SelectionChanged(val) => self.selected_entry = val,
|
||||
Message::SelectionUp => {
|
||||
self.selected_entry =
|
||||
dbg!((self.selected_entry.wrapping_sub(1)).clamp(0, self.db_view.len() - 1))
|
||||
}
|
||||
Message::SelectionDown => {
|
||||
self.selected_entry = if self.selected_entry == self.db_view.len() - 1 {
|
||||
// essentially do a wrapping_add up to the highest index in the view
|
||||
0
|
||||
} else {
|
||||
dbg!((self.selected_entry.wrapping_add(1)).clamp(0, self.db_view.len() - 1))
|
||||
}
|
||||
}
|
||||
|
||||
Message::FocusNext => return widget::operation::focus_next(),
|
||||
Message::FocusPrevious => return widget::operation::focus_previous(),
|
||||
}
|
||||
|
|
@ -102,21 +127,39 @@ impl State {
|
|||
Task::none()
|
||||
}
|
||||
fn view(&self) -> Element<'_> {
|
||||
let main = if let Some(db) = self.db.as_ref() {
|
||||
widget::scrollable(widget::row([
|
||||
widget::column(db.iter_all_entries().map(|entry| {
|
||||
widget::text(entry.get_title().unwrap_or_default().to_string()).into()
|
||||
let main = if !self.db_view.is_empty() {
|
||||
widget::scrollable(
|
||||
widget::grid(self.db_view.iter().enumerate().flat_map(|(i, entry)| {
|
||||
[
|
||||
widget::button(widget::text(entry.get_title().unwrap_or_default()))
|
||||
.style(if i == self.selected_entry {
|
||||
widget::button::primary
|
||||
} else {
|
||||
widget::button::subtle
|
||||
})
|
||||
.on_press(Message::SelectionChanged(i))
|
||||
.into(),
|
||||
widget::button(widget::text(entry.get_username().unwrap_or_default()))
|
||||
.style(if i == self.selected_entry {
|
||||
widget::button::primary
|
||||
} else {
|
||||
widget::button::subtle
|
||||
})
|
||||
.on_press(Message::SelectionChanged(i))
|
||||
.into(),
|
||||
widget::button(widget::text(entry.get_url().unwrap_or_default()))
|
||||
.style(if i == self.selected_entry {
|
||||
widget::button::primary
|
||||
} else {
|
||||
widget::button::subtle
|
||||
})
|
||||
.on_press(Message::SelectionChanged(i))
|
||||
.into(),
|
||||
]
|
||||
}))
|
||||
.into(),
|
||||
widget::column(db.iter_all_entries().map(|entry| {
|
||||
widget::text(entry.get_username().unwrap_or_default().to_string()).into()
|
||||
}))
|
||||
.into(),
|
||||
widget::column(db.iter_all_entries().map(|entry| {
|
||||
widget::text(entry.get_url().unwrap_or_default().to_string()).into()
|
||||
}))
|
||||
.into(),
|
||||
]))
|
||||
.height(Length::Shrink)
|
||||
.columns(3),
|
||||
)
|
||||
.into()
|
||||
} else {
|
||||
widget::container(
|
||||
|
|
@ -195,6 +238,13 @@ impl State {
|
|||
}
|
||||
Key::Character("p" | "f" | "i") if !db_loaded => Some(Message::PickDb),
|
||||
|
||||
Key::Character("k") | Key::Named(key::Named::ArrowUp) => {
|
||||
Some(Message::SelectionUp)
|
||||
}
|
||||
Key::Character("j") | Key::Named(key::Named::ArrowDown) => {
|
||||
Some(Message::SelectionDown)
|
||||
}
|
||||
|
||||
// ignore unused keys
|
||||
_ => None,
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue