bin: Refactor quitting in patch select

This commit is contained in:
Erik Kundt
2024-08-16 12:53:28 +02:00
parent 829bb494c7
commit a8dc311b9b
2 changed files with 48 additions and 52 deletions
+47 -5
View File
@@ -27,7 +27,7 @@ use tui::{BoxedAny, Channel, Exit, PageStack};
use self::ui::{Browser, BrowserProps};
use super::common::Mode;
use super::common::{Mode, PatchOperation};
use crate::cob::patch;
use crate::ui::items::{Filter, PatchItem, PatchItemFilter};
@@ -68,6 +68,18 @@ impl BrowserState {
.cloned()
.collect()
}
pub fn patches_ref(&self) -> Vec<&PatchItem> {
self.items
.iter()
.filter(|patch| self.filter.matches(patch))
.collect()
}
pub fn selected_item(&self) -> Option<&PatchItem> {
self.selected
.and_then(|selected| self.patches_ref().get(selected).copied())
}
}
#[derive(Clone, Debug)]
@@ -118,7 +130,9 @@ impl TryFrom<&Context> for State {
}
pub enum Message {
Exit { selection: Option<Selection> },
Quit,
Exit { operation: Option<PatchOperation> },
ExitFromMode,
Select { selected: Option<usize> },
OpenSearch,
UpdateSearch { value: String },
@@ -134,7 +148,28 @@ impl store::State<Selection> for State {
fn update(&mut self, message: Message) -> Option<Exit<Selection>> {
match message {
Message::Exit { selection } => Some(Exit { value: selection }),
Message::Quit => Some(Exit { value: None }),
Message::Exit { operation } => self.browser.selected_item().map(|issue| Exit {
value: Some(Selection {
operation: operation.map(|op| op.to_string()),
ids: vec![issue.id],
args: vec![],
}),
}),
Message::ExitFromMode => {
let operation = match self.mode {
Mode::Operation => Some(PatchOperation::Show.to_string()),
Mode::Id => None,
};
self.browser.selected_item().map(|issue| Exit {
value: Some(Selection {
operation,
ids: vec![issue.id],
args: vec![],
}),
})
}
Message::Select { selected } => {
self.browser.selected = selected;
None
@@ -255,8 +290,15 @@ fn browser_page(_state: &State, channel: &Channel<Message>) -> Widget<State, Mes
if props.handle_keys {
match key {
Key::Esc | Key::Ctrl('c') => Some(Message::Exit { selection: None }),
Key::Esc | Key::Ctrl('c') => Some(Message::Quit),
Key::Char('?') => Some(Message::OpenHelp),
Key::Char('\n') => Some(Message::ExitFromMode),
Key::Char('c') => Some(Message::Exit {
operation: Some(PatchOperation::Checkout),
}),
Key::Char('d') => Some(Message::Exit {
operation: Some(PatchOperation::Diff),
}),
_ => None,
}
} else {
@@ -329,7 +371,7 @@ fn help_page(_state: &State, channel: &Channel<Message>) -> Widget<State, Messag
.shortcuts(shortcuts)
.to_widget(tx.clone())
.on_event(|key, _, _| match key {
Key::Esc | Key::Ctrl('c') => Some(Message::Exit { selection: None }),
Key::Esc | Key::Ctrl('c') => Some(Message::Quit),
Key::Char('?') => Some(Message::LeavePage),
_ => None,
})
+1 -47
View File
@@ -26,10 +26,8 @@ use tui::ui::widget::list::{Table, TableProps};
use tui::ui::widget::ViewProps;
use tui::ui::widget::{RenderProps, ToWidget, View};
use tui::{BoxedAny, Selection};
use tui::BoxedAny;
use crate::tui_patch::common::Mode;
use crate::tui_patch::common::PatchOperation;
use crate::ui::items::{PatchItem, PatchItemFilter};
use super::{Message, State};
@@ -38,12 +36,8 @@ type Widget = widget::Widget<State, Message>;
#[derive(Clone, Default)]
pub struct BrowserProps<'a> {
/// Application mode: openation and id or id only.
mode: Mode,
/// Filtered patches.
patches: Vec<PatchItem>,
/// Current (selected) table index
selected: Option<usize>,
/// Patch statistics.
stats: HashMap<String, usize>,
/// Header columns
@@ -85,9 +79,7 @@ impl<'a> From<&State> for BrowserProps<'a> {
]);
Self {
mode: state.mode.clone(),
patches,
selected: state.browser.selected,
stats,
header: [
Column::new(" ● ", Constraint::Length(3)),
@@ -218,45 +210,7 @@ impl View for Browser {
}
} else {
match key {
Key::Esc | Key::Ctrl('c') => Some(Message::Exit { selection: None }),
Key::Char('/') => Some(Message::OpenSearch),
Key::Char('\n') => {
let operation = match props.mode {
Mode::Operation => Some(PatchOperation::Show.to_string()),
Mode::Id => None,
};
props
.selected
.and_then(|selected| props.patches.get(selected))
.map(|patch| Message::Exit {
selection: Some(Selection {
operation,
ids: vec![patch.id],
args: vec![],
}),
})
}
Key::Char('c') => props
.selected
.and_then(|selected| props.patches.get(selected))
.map(|patch| Message::Exit {
selection: Some(Selection {
operation: Some(PatchOperation::Checkout.to_string()),
ids: vec![patch.id],
args: vec![],
}),
}),
Key::Char('d') => props
.selected
.and_then(|selected| props.patches.get(selected))
.map(|patch| Message::Exit {
selection: Some(Selection {
operation: Some(PatchOperation::Diff.to_string()),
ids: vec![patch.id],
args: vec![],
}),
}),
_ => {
self.patches.handle_event(key);
None