diff --git a/assets/checkout-remote.gif b/assets/checkout-remote.gif index 9d3fa9e0..a37ac9c4 100644 Binary files a/assets/checkout-remote.gif and b/assets/checkout-remote.gif differ diff --git a/assets/vim_style_key_config.ron b/assets/vim_style_key_config.ron index 2e05689c..9b8ea8c6 100644 --- a/assets/vim_style_key_config.ron +++ b/assets/vim_style_key_config.ron @@ -71,7 +71,6 @@ rename_branch: ( code: Char('r'), modifiers: ( bits: 0,),), select_branch: ( code: Char('b'), modifiers: ( bits: 0,),), delete_branch: ( code: Char('D'), modifiers: ( bits: 1,),), - toggle_remote_branches: ( code: Char('t'), modifiers: ( bits: 0,),), push: ( code: Char('p'), modifiers: ( bits: 0,),), force_push: ( code: Char('P'), modifiers: ( bits: 1,),), pull: ( code: Char('f'), modifiers: ( bits: 0,),), diff --git a/src/components/branchlist.rs b/src/components/branchlist.rs index 372e27a4..7fa04bec 100644 --- a/src/components/branchlist.rs +++ b/src/components/branchlist.rs @@ -21,9 +21,11 @@ use crossterm::event::Event; use std::{cell::Cell, convert::TryInto}; use tui::{ backend::Backend, - layout::{Alignment, Rect}, + layout::{ + Alignment, Constraint, Direction, Layout, Margin, Rect, + }, text::{Span, Spans, Text}, - widgets::{Block, BorderType, Borders, Clear, Paragraph}, + widgets::{Block, BorderType, Borders, Clear, Paragraph, Tabs}, Frame, }; use ui::style::SharedTheme; @@ -49,7 +51,7 @@ impl DrawableComponent for BranchListComponent { rect: Rect, ) -> Result<()> { if self.visible { - const PERCENT_SIZE: Size = Size::new(80, 25); + const PERCENT_SIZE: Size = Size::new(80, 50); const MIN_SIZE: Size = Size::new(60, 20); let area = ui::centered_rect( @@ -61,41 +63,32 @@ impl DrawableComponent for BranchListComponent { ui::rect_inside(MIN_SIZE, f.size().into(), area); let area = area.intersection(rect); - let height_in_lines = - (area.height as usize).saturating_sub(2); - - self.scroll_top.set(calc_scroll_top( - self.scroll_top.get(), - height_in_lines, - self.selection as usize, - )); - f.render_widget(Clear, area); + f.render_widget( - Paragraph::new(self.get_text( - &self.theme, - area.width, - height_in_lines, - )) - .block( - Block::default() - .title(strings::title_branches(self.local)) - .border_type(BorderType::Thick) - .borders(Borders::ALL), + Block::default() + .title(strings::title_branches()) + .border_type(BorderType::Thick) + .borders(Borders::ALL), + area, + ); + + let area = area.inner(&Margin { + vertical: 1, + horizontal: 1, + }); + + let chunks = Layout::default() + .direction(Direction::Vertical) + .constraints( + [Constraint::Length(2), Constraint::Min(1)] + .as_ref(), ) - .alignment(Alignment::Left), - area, - ); + .split(area); - ui::draw_scrollbar( - f, - area, - &self.theme, - self.branches.len(), - self.scroll_top.get(), - ); + self.draw_tabs(f, chunks[0]); - self.current_height.set(height_in_lines.try_into()?); + self.draw_list(f, chunks[1])?; } Ok(()) @@ -123,6 +116,15 @@ impl Component for BranchListComponent { true, )); + out.push(CommandInfo::new( + strings::commands::toggle_branch_popup( + &self.key_config, + self.local, + ), + true, + true, + )); + out.push(CommandInfo::new( strings::commands::select_branch_popup( &self.key_config, @@ -154,15 +156,6 @@ impl Component for BranchListComponent { true, self.local, )); - - out.push(CommandInfo::new( - strings::commands::toggle_branch_popup( - &self.key_config, - self.local, - ), - true, - true, - )); } visibility_blocking(self) } @@ -215,8 +208,7 @@ impl Component for BranchListComponent { ), ), ); - } else if e == self.key_config.toggle_remote_branches - { + } else if e == self.key_config.tab_toggle { self.local = !self.local; self.update_branches()?; } @@ -462,4 +454,65 @@ impl BranchListComponent { Ok(()) } + + fn draw_tabs(&self, f: &mut Frame, r: Rect) { + let tabs = [Span::raw("Local"), Span::raw("Remote")] + .iter() + .cloned() + .map(Spans::from) + .collect(); + + f.render_widget( + Tabs::new(tabs) + .block( + Block::default() + .borders(Borders::BOTTOM) + .border_style(self.theme.block(false)), + ) + .style(self.theme.tab(false)) + .highlight_style(self.theme.tab(true)) + .divider(strings::tab_divider(&self.key_config)) + .select(if self.local { 0 } else { 1 }), + r, + ); + } + + fn draw_list( + &self, + f: &mut Frame, + r: Rect, + ) -> Result<()> { + let height_in_lines = r.height as usize; + + self.scroll_top.set(calc_scroll_top( + self.scroll_top.get(), + height_in_lines, + self.selection as usize, + )); + + f.render_widget( + Paragraph::new(self.get_text( + &self.theme, + r.width, + height_in_lines, + )) + .alignment(Alignment::Left), + r, + ); + + let mut r = r; + r.width += 1; + + ui::draw_scrollbar( + f, + r, + &self.theme, + self.branches.len(), + self.scroll_top.get(), + ); + + self.current_height.set(height_in_lines.try_into()?); + + Ok(()) + } } diff --git a/src/keys.rs b/src/keys.rs index 9eed5b59..8fa40b39 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -67,7 +67,6 @@ pub struct KeyConfig { pub rename_branch: KeyEvent, pub select_branch: KeyEvent, pub delete_branch: KeyEvent, - pub toggle_remote_branches: KeyEvent, pub push: KeyEvent, pub force_push: KeyEvent, pub pull: KeyEvent, @@ -124,7 +123,6 @@ impl Default for KeyConfig { rename_branch: KeyEvent { code: KeyCode::Char('r'), modifiers: KeyModifiers::NONE}, select_branch: KeyEvent { code: KeyCode::Char('b'), modifiers: KeyModifiers::NONE}, delete_branch: KeyEvent{code: KeyCode::Char('D'), modifiers: KeyModifiers::SHIFT}, - toggle_remote_branches: KeyEvent{code: KeyCode::Char('t'), modifiers: KeyModifiers::NONE}, push: KeyEvent { code: KeyCode::Char('p'), modifiers: KeyModifiers::empty()}, force_push: KeyEvent { code: KeyCode::Char('P'), modifiers: KeyModifiers::SHIFT}, pull: KeyEvent { code: KeyCode::Char('f'), modifiers: KeyModifiers::empty()}, diff --git a/src/strings.rs b/src/strings.rs index 4492cfc0..8480bfb9 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -19,15 +19,9 @@ pub static PUSH_TAGS_STATES_FETCHING: &str = "fetching"; pub static PUSH_TAGS_STATES_PUSHING: &str = "pushing"; pub static PUSH_TAGS_STATES_DONE: &str = "done"; -pub fn title_branches(local: bool) -> String { - if local { - "Branches (local)" - } else { - "Branches (remote)" - } - .to_string() +pub fn title_branches() -> String { + "Branches".to_string() } - pub fn title_status(_key_config: &SharedKeyConfig) -> String { "Unstaged Changes".to_string() } @@ -925,10 +919,9 @@ pub mod commands { ) -> CommandText { CommandText::new( format!( - "{} Branches [{}]", + "{} [{}]", if local { "Remote" } else { "Local" }, - key_config - .get_hint(key_config.toggle_remote_branches), + key_config.get_hint(key_config.tab_toggle), ), "toggle branch type (remote/local)", CMD_GROUP_GENERAL,