mirror of
https://seed.radicle.dev/rad:z39mP9rQAaGmERfUMPULfPUi473tY.git
synced 2026-11-15 16:00:38 +08:00
bin: Refactor quitting in patch select
This commit is contained in:
@@ -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,
|
||||
})
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user