diff --git a/README.md b/README.md index 6e18bcc1..a9dff867 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,6 @@ GITUI_LOGGING=true gitui # todo for 0.1 (first release) * [ ] fix: run in non-git folder -> crash -* [ ] confirm destructive commands (revert/reset) * [ ] (un)staging selected hunks * [ ] publish as homebrew-tap diff --git a/src/app.rs b/src/app.rs index 5a4c25d4..afa82e7b 100644 --- a/src/app.rs +++ b/src/app.rs @@ -2,7 +2,7 @@ use crate::{ components::{ ChangesComponent, CommandBlocking, CommandInfo, CommitComponent, Component, DiffComponent, DrawableComponent, - EventUpdate, HelpComponent, + EventUpdate, HelpComponent, ResetComponent, }, keys, queue::{InternalEvent, Queue}, @@ -46,6 +46,7 @@ pub struct App { focus: Focus, diff_target: DiffTarget, do_quit: bool, + reset: ResetComponent, commit: CommitComponent, help: HelpComponent, index: ChangesComponent, @@ -66,6 +67,7 @@ impl App { focus: Focus::WorkDir, diff_target: DiffTarget::WorkingDir, do_quit: false, + reset: ResetComponent::new(queue.clone()), commit: CommitComponent::default(), help: HelpComponent::default(), index_wd: ChangesComponent::new( @@ -151,6 +153,7 @@ impl App { self.commit.draw(f, f.size()); self.help.draw(f, f.size()); + self.reset.draw(f, f.size()); } /// @@ -277,6 +280,10 @@ impl App { self.update(); } } + InternalEvent::ConfirmResetFile(p) => { + self.reset.open_for_path(p); + self.update_commands(); + } }; } @@ -292,8 +299,9 @@ impl App { } } - let main_cmds_available = - !self.commit.is_visible() && !self.help.is_visible(); + let main_cmds_available = !self.commit.is_visible() + && !self.help.is_visible() + && !self.reset.is_visible(); { { @@ -349,6 +357,7 @@ impl App { fn components(&self) -> Vec<&dyn Component> { vec![ + &self.reset, &self.commit, &self.help, &self.index, @@ -359,6 +368,7 @@ impl App { fn components_mut(&mut self) -> Vec<&mut dyn Component> { vec![ + &mut self.reset, &mut self.commit, &mut self.help, &mut self.index, diff --git a/src/components/changes.rs b/src/components/changes.rs index c9c70462..1cda8a78 100644 --- a/src/components/changes.rs +++ b/src/components/changes.rs @@ -124,7 +124,7 @@ impl ChangesComponent { if let Some(i) = self.selection() { self.queue .borrow_mut() - .push_back(InternalEvent::ResetFile(i.path)); + .push_back(InternalEvent::ConfirmResetFile(i.path)); return true; } diff --git a/src/components/mod.rs b/src/components/mod.rs index 1cc519f8..ab1449ee 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -6,11 +6,13 @@ mod command; mod commit; mod diff; mod help; +mod reset; pub use changes::ChangesComponent; pub use command::{CommandInfo, CommandText}; pub use commit::CommitComponent; pub use diff::DiffComponent; pub use help::HelpComponent; +pub use reset::ResetComponent; /// pub enum EventUpdate { diff --git a/src/components/reset.rs b/src/components/reset.rs new file mode 100644 index 00000000..4cd6c513 --- /dev/null +++ b/src/components/reset.rs @@ -0,0 +1,124 @@ +use super::{ + visibility_blocking, CommandBlocking, CommandInfo, Component, + DrawableComponent, EventUpdate, +}; +use crate::{ + queue::{InternalEvent, Queue}, + strings, ui, +}; + +use crossterm::event::{Event, KeyCode}; +use std::borrow::Cow; +use strings::commands; +use tui::{ + backend::Backend, + layout::{Alignment, Rect}, + style::{Color, Style}, + widgets::{Block, Borders, Paragraph, Text, Widget}, + Frame, +}; + +pub struct ResetComponent { + path: String, + visible: bool, + queue: Queue, +} + +impl DrawableComponent for ResetComponent { + fn draw(&self, f: &mut Frame, _rect: Rect) { + if self.visible { + let mut txt = Vec::new(); + txt.push(Text::Styled( + Cow::from(strings::RESET_MSG), + Style::default().fg(Color::Red), + )); + + ui::Clear::new( + Paragraph::new(txt.iter()) + .block( + Block::default() + .title(strings::RESET_TITLE) + .borders(Borders::ALL), + ) + .alignment(Alignment::Left), + ) + .render(f, ui::centered_rect(30, 20, f.size())); + } + } +} + +impl Component for ResetComponent { + fn commands( + &self, + out: &mut Vec, + _force_all: bool, + ) -> CommandBlocking { + out.push(CommandInfo::new( + commands::RESET_CONFIRM, + true, + self.visible, + )); + out.push(CommandInfo::new( + commands::CLOSE_POPUP, + true, + self.visible, + )); + + visibility_blocking(self) + } + + fn event(&mut self, ev: Event) -> Option { + if self.visible { + if let Event::Key(e) = ev { + return Some(match e.code { + KeyCode::Esc => { + self.hide(); + EventUpdate::Commands + } + KeyCode::Enter => { + self.confirm(); + EventUpdate::None + } + + _ => EventUpdate::None, + }); + } + } + None + } + + fn is_visible(&self) -> bool { + self.visible + } + + fn hide(&mut self) { + self.visible = false + } + + fn show(&mut self) { + self.visible = true + } +} + +impl ResetComponent { + /// + pub fn new(queue: Queue) -> Self { + Self { + path: String::default(), + visible: false, + queue, + } + } + /// + pub fn open_for_path(&mut self, path: &str) { + self.path = path.to_string(); + self.show(); + } + /// + pub fn confirm(&mut self) { + self.hide(); + self.queue + .borrow_mut() + .push_back(InternalEvent::ResetFile(self.path.clone())); + } +} diff --git a/src/queue.rs b/src/queue.rs index 462cdd1c..3f570a1a 100644 --- a/src/queue.rs +++ b/src/queue.rs @@ -2,6 +2,8 @@ use std::{cell::RefCell, collections::VecDeque, rc::Rc}; /// pub enum InternalEvent { + /// + ConfirmResetFile(String), /// ResetFile(String), } diff --git a/src/strings.rs b/src/strings.rs index 98d7b6b2..91572b4b 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -6,10 +6,11 @@ pub static TAB_STATUS: &str = "Status"; pub static TAB_DIVIDER: &str = " | "; pub static CMD_SPLITTER: &str = " "; -// pub static CMD_SCROLL: &str = "Scroll [\u{2191}\u{2193}]"; //↑↓ pub static COMMIT_TITLE: &str = "Commit"; pub static COMMIT_MSG: &str = "type commit message.."; +pub static RESET_TITLE: &str = "Reset"; +pub static RESET_MSG: &str = "confirm file reset?"; pub static HELP_TITLE: &str = "Help"; @@ -98,4 +99,10 @@ pub mod commands { "quit gitui application", CMD_GROUP_GENERAL, ); + /// + pub static RESET_CONFIRM: CommandText = CommandText::new( + "Confirm [enter]", + "resets the file in question", + CMD_GROUP_GENERAL, + ); }