1 use crate::{ 2 components::{ 3 visibility_blocking, CommandBlocking, CommandInfo, 4 CommitList, Component, DrawableComponent, 5 }, 6 keys::SharedKeyConfig, 7 queue::{Action, InternalEvent, Queue}, 8 strings, 9 ui::style::SharedTheme, 10 }; 11 use anyhow::Result; 12 use asyncgit::{ 13 sync::{self, CommitId}, 14 CWD, 15 }; 16 use crossterm::event::Event; 17 18 pub struct StashList { 19 list: CommitList, 20 visible: bool, 21 queue: Queue, 22 key_config: SharedKeyConfig, 23 } 24 25 impl StashList { 26 /// new( queue: &Queue, theme: SharedTheme, key_config: SharedKeyConfig, ) -> Self27 pub fn new( 28 queue: &Queue, 29 theme: SharedTheme, 30 key_config: SharedKeyConfig, 31 ) -> Self { 32 Self { 33 visible: false, 34 list: CommitList::new( 35 &strings::stashlist_title(&key_config), 36 theme, 37 key_config.clone(), 38 ), 39 queue: queue.clone(), 40 key_config, 41 } 42 } 43 44 /// update(&mut self) -> Result<()>45 pub fn update(&mut self) -> Result<()> { 46 if self.visible { 47 let stashes = sync::get_stashes(CWD)?; 48 let commits = 49 sync::get_commits_info(CWD, stashes.as_slice(), 100)?; 50 51 self.list.set_count_total(commits.len()); 52 self.list.items().set_items(0, commits); 53 } 54 55 Ok(()) 56 } 57 apply_stash(&mut self)58 fn apply_stash(&mut self) { 59 if let Some(e) = self.list.selected_entry() { 60 match sync::stash_apply(CWD, e.id) { 61 Ok(_) => { 62 self.queue 63 .borrow_mut() 64 .push_back(InternalEvent::TabSwitch); 65 } 66 Err(e) => { 67 self.queue.borrow_mut().push_back( 68 InternalEvent::ShowErrorMsg(format!( 69 "stash apply error:\n{}", 70 e, 71 )), 72 ); 73 } 74 } 75 } 76 } 77 drop_stash(&mut self)78 fn drop_stash(&mut self) { 79 if let Some(e) = self.list.selected_entry() { 80 self.queue.borrow_mut().push_back( 81 InternalEvent::ConfirmAction(Action::StashDrop(e.id)), 82 ); 83 } 84 } 85 inspect(&mut self)86 fn inspect(&mut self) { 87 if let Some(e) = self.list.selected_entry() { 88 self.queue 89 .borrow_mut() 90 .push_back(InternalEvent::InspectCommit(e.id, None)); 91 } 92 } 93 94 /// drop(id: CommitId) -> bool95 pub fn drop(id: CommitId) -> bool { 96 sync::stash_drop(CWD, id).is_ok() 97 } 98 } 99 100 impl DrawableComponent for StashList { draw<B: tui::backend::Backend>( &self, f: &mut tui::Frame<B>, rect: tui::layout::Rect, ) -> Result<()>101 fn draw<B: tui::backend::Backend>( 102 &self, 103 f: &mut tui::Frame<B>, 104 rect: tui::layout::Rect, 105 ) -> Result<()> { 106 self.list.draw(f, rect)?; 107 108 Ok(()) 109 } 110 } 111 112 impl Component for StashList { commands( &self, out: &mut Vec<CommandInfo>, force_all: bool, ) -> CommandBlocking113 fn commands( 114 &self, 115 out: &mut Vec<CommandInfo>, 116 force_all: bool, 117 ) -> CommandBlocking { 118 if self.visible || force_all { 119 self.list.commands(out, force_all); 120 121 let selection_valid = 122 self.list.selected_entry().is_some(); 123 out.push(CommandInfo::new( 124 strings::commands::stashlist_apply(&self.key_config), 125 selection_valid, 126 true, 127 )); 128 out.push(CommandInfo::new( 129 strings::commands::stashlist_drop(&self.key_config), 130 selection_valid, 131 true, 132 )); 133 out.push(CommandInfo::new( 134 strings::commands::stashlist_inspect( 135 &self.key_config, 136 ), 137 selection_valid, 138 true, 139 )); 140 } 141 142 visibility_blocking(self) 143 } 144 event(&mut self, ev: crossterm::event::Event) -> Result<bool>145 fn event(&mut self, ev: crossterm::event::Event) -> Result<bool> { 146 if self.visible { 147 if self.list.event(ev)? { 148 return Ok(true); 149 } 150 151 if let Event::Key(k) = ev { 152 if k == self.key_config.enter { 153 self.apply_stash() 154 } else if k == self.key_config.stash_drop { 155 self.drop_stash() 156 } else if k == self.key_config.stash_open { 157 self.inspect() 158 } else { 159 } 160 } 161 } 162 163 Ok(false) 164 } 165 is_visible(&self) -> bool166 fn is_visible(&self) -> bool { 167 self.visible 168 } 169 hide(&mut self)170 fn hide(&mut self) { 171 self.visible = false; 172 } 173 show(&mut self) -> Result<()>174 fn show(&mut self) -> Result<()> { 175 self.visible = true; 176 self.update()?; 177 Ok(()) 178 } 179 } 180