mirror of
https://github.com/gitui-org/gitui
synced 2026-05-24 01:18:21 +00:00
parent
7ba62b82df
commit
bbc0488d22
1 changed files with 98 additions and 76 deletions
|
|
@ -3,9 +3,11 @@ use super::{
|
||||||
DrawableComponent,
|
DrawableComponent,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
components::ScrollType,
|
||||||
keys::SharedKeyConfig,
|
keys::SharedKeyConfig,
|
||||||
queue::{Action, InternalEvent, NeedsUpdate, Queue},
|
queue::{Action, InternalEvent, NeedsUpdate, Queue},
|
||||||
strings, ui,
|
strings,
|
||||||
|
ui::{self, calc_scroll_top},
|
||||||
};
|
};
|
||||||
use asyncgit::{
|
use asyncgit::{
|
||||||
sync::{
|
sync::{
|
||||||
|
|
@ -14,7 +16,7 @@ use asyncgit::{
|
||||||
CWD,
|
CWD,
|
||||||
};
|
};
|
||||||
use crossterm::event::Event;
|
use crossterm::event::Event;
|
||||||
use std::{cmp, convert::TryFrom};
|
use std::{cell::Cell, convert::TryInto};
|
||||||
use tui::{
|
use tui::{
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
layout::{Alignment, Rect},
|
layout::{Alignment, Rect},
|
||||||
|
|
@ -32,6 +34,7 @@ pub struct SelectBranchComponent {
|
||||||
branch_names: Vec<BranchForDisplay>,
|
branch_names: Vec<BranchForDisplay>,
|
||||||
visible: bool,
|
visible: bool,
|
||||||
selection: u16,
|
selection: u16,
|
||||||
|
scroll_top: Cell<usize>,
|
||||||
queue: Queue,
|
queue: Queue,
|
||||||
theme: SharedTheme,
|
theme: SharedTheme,
|
||||||
key_config: SharedKeyConfig,
|
key_config: SharedKeyConfig,
|
||||||
|
|
@ -56,22 +59,28 @@ impl DrawableComponent for SelectBranchComponent {
|
||||||
ui::rect_inside(MIN_SIZE, f.size().into(), area);
|
ui::rect_inside(MIN_SIZE, f.size().into(), area);
|
||||||
let area = area.intersection(rect);
|
let area = area.intersection(rect);
|
||||||
|
|
||||||
let scroll_threshold = area.height / 3;
|
let height_in_lines =
|
||||||
let scroll =
|
(area.height as usize).saturating_sub(2);
|
||||||
self.selection.saturating_sub(scroll_threshold);
|
|
||||||
|
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(Clear, area);
|
||||||
f.render_widget(
|
f.render_widget(
|
||||||
Paragraph::new(
|
Paragraph::new(self.get_text(
|
||||||
self.get_text(&self.theme, area.width)?,
|
&self.theme,
|
||||||
)
|
area.width,
|
||||||
|
height_in_lines,
|
||||||
|
)?)
|
||||||
.block(
|
.block(
|
||||||
Block::default()
|
Block::default()
|
||||||
.title(strings::SELECT_BRANCH_POPUP_MSG)
|
.title(strings::SELECT_BRANCH_POPUP_MSG)
|
||||||
.borders(Borders::ALL)
|
.borders(Borders::ALL)
|
||||||
.border_type(BorderType::Thick),
|
.border_type(BorderType::Thick),
|
||||||
)
|
)
|
||||||
.scroll((scroll, 0))
|
|
||||||
.alignment(Alignment::Left),
|
.alignment(Alignment::Left),
|
||||||
area,
|
area,
|
||||||
);
|
);
|
||||||
|
|
@ -135,9 +144,9 @@ impl Component for SelectBranchComponent {
|
||||||
if e == self.key_config.exit_popup {
|
if e == self.key_config.exit_popup {
|
||||||
self.hide()
|
self.hide()
|
||||||
} else if e == self.key_config.move_down {
|
} else if e == self.key_config.move_down {
|
||||||
self.move_selection(true)
|
return self.move_selection(ScrollType::Up);
|
||||||
} else if e == self.key_config.move_up {
|
} else if e == self.key_config.move_up {
|
||||||
self.move_selection(false)
|
return self.move_selection(ScrollType::Down);
|
||||||
} else if e == self.key_config.enter {
|
} else if e == self.key_config.enter {
|
||||||
if let Err(e) = self.switch_to_selected_branch() {
|
if let Err(e) = self.switch_to_selected_branch() {
|
||||||
log::error!("switch branch error: {}", e);
|
log::error!("switch branch error: {}", e);
|
||||||
|
|
@ -211,6 +220,7 @@ impl SelectBranchComponent {
|
||||||
branch_names: Vec::new(),
|
branch_names: Vec::new(),
|
||||||
visible: false,
|
visible: false,
|
||||||
selection: 0,
|
selection: 0,
|
||||||
|
scroll_top: Cell::new(0),
|
||||||
queue,
|
queue,
|
||||||
theme,
|
theme,
|
||||||
key_config,
|
key_config,
|
||||||
|
|
@ -248,21 +258,23 @@ impl SelectBranchComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
fn move_selection(&mut self, inc: bool) {
|
fn move_selection(&mut self, scroll: ScrollType) -> Result<bool> {
|
||||||
let mut new_selection = self.selection;
|
let num_branches: u16 = self.branch_names.len().try_into()?;
|
||||||
|
let num_branches = num_branches.saturating_sub(1);
|
||||||
|
|
||||||
new_selection = if inc {
|
let mut new_selection = match scroll {
|
||||||
new_selection.saturating_add(1)
|
ScrollType::Up => self.selection.saturating_add(1),
|
||||||
} else {
|
ScrollType::Down => self.selection.saturating_sub(1),
|
||||||
new_selection.saturating_sub(1)
|
_ => self.selection,
|
||||||
};
|
};
|
||||||
new_selection = cmp::max(new_selection, 0);
|
|
||||||
|
|
||||||
if let Ok(max) =
|
if new_selection > num_branches {
|
||||||
u16::try_from(self.branch_names.len().saturating_sub(1))
|
new_selection = num_branches;
|
||||||
{
|
|
||||||
self.selection = cmp::min(new_selection, max);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.selection = new_selection;
|
||||||
|
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get branches to display
|
/// Get branches to display
|
||||||
|
|
@ -270,6 +282,7 @@ impl SelectBranchComponent {
|
||||||
&self,
|
&self,
|
||||||
theme: &SharedTheme,
|
theme: &SharedTheme,
|
||||||
width_available: u16,
|
width_available: u16,
|
||||||
|
height: usize,
|
||||||
) -> Result<Text> {
|
) -> Result<Text> {
|
||||||
const COMMIT_HASH_LENGTH: usize = 8;
|
const COMMIT_HASH_LENGTH: usize = 8;
|
||||||
const IS_HEAD_STAR_LENGTH: usize = 3; // "* "
|
const IS_HEAD_STAR_LENGTH: usize = 3; // "* "
|
||||||
|
|
@ -286,7 +299,12 @@ impl SelectBranchComponent {
|
||||||
.saturating_sub(THREE_DOTS_LENGTH);
|
.saturating_sub(THREE_DOTS_LENGTH);
|
||||||
let mut txt = Vec::new();
|
let mut txt = Vec::new();
|
||||||
|
|
||||||
for (i, displaybranch) in self.branch_names.iter().enumerate()
|
for (i, displaybranch) in self
|
||||||
|
.branch_names
|
||||||
|
.iter()
|
||||||
|
.skip(self.scroll_top.get())
|
||||||
|
.take(height)
|
||||||
|
.enumerate()
|
||||||
{
|
{
|
||||||
let mut commit_message =
|
let mut commit_message =
|
||||||
displaybranch.top_commit_message.clone();
|
displaybranch.top_commit_message.clone();
|
||||||
|
|
@ -310,63 +328,67 @@ impl SelectBranchComponent {
|
||||||
let is_head_str =
|
let is_head_str =
|
||||||
if displaybranch.is_head { "*" } else { " " };
|
if displaybranch.is_head { "*" } else { " " };
|
||||||
|
|
||||||
txt.push(Spans::from(if self.selection as usize == i {
|
txt.push(Spans::from(
|
||||||
vec![
|
if self.selection as usize - self.scroll_top.get()
|
||||||
Span::styled(
|
== i
|
||||||
format!("{} ", is_head_str),
|
{
|
||||||
theme.commit_author(true),
|
vec![
|
||||||
),
|
Span::styled(
|
||||||
Span::styled(
|
format!("{} ", is_head_str),
|
||||||
format!(
|
theme.commit_author(true),
|
||||||
">{:w$} ",
|
|
||||||
branch_name,
|
|
||||||
w = branch_name_length
|
|
||||||
),
|
),
|
||||||
theme.commit_author(true),
|
Span::styled(
|
||||||
),
|
format!(
|
||||||
Span::styled(
|
">{:w$} ",
|
||||||
format!(
|
branch_name,
|
||||||
"{} ",
|
w = branch_name_length
|
||||||
displaybranch
|
),
|
||||||
.top_commit
|
theme.commit_author(true),
|
||||||
.get_short_string()
|
|
||||||
),
|
),
|
||||||
theme.commit_hash(true),
|
Span::styled(
|
||||||
),
|
format!(
|
||||||
Span::styled(
|
"{} ",
|
||||||
commit_message.to_string(),
|
displaybranch
|
||||||
theme.text(true, true),
|
.top_commit
|
||||||
),
|
.get_short_string()
|
||||||
]
|
),
|
||||||
} else {
|
theme.commit_hash(true),
|
||||||
vec![
|
|
||||||
Span::styled(
|
|
||||||
format!("{} ", is_head_str),
|
|
||||||
theme.commit_author(false),
|
|
||||||
),
|
|
||||||
Span::styled(
|
|
||||||
format!(
|
|
||||||
" {:w$} ",
|
|
||||||
branch_name,
|
|
||||||
w = branch_name_length
|
|
||||||
),
|
),
|
||||||
theme.commit_author(false),
|
Span::styled(
|
||||||
),
|
commit_message.to_string(),
|
||||||
Span::styled(
|
theme.text(true, true),
|
||||||
format!(
|
|
||||||
"{} ",
|
|
||||||
displaybranch
|
|
||||||
.top_commit
|
|
||||||
.get_short_string()
|
|
||||||
),
|
),
|
||||||
theme.commit_hash(false),
|
]
|
||||||
),
|
} else {
|
||||||
Span::styled(
|
vec![
|
||||||
commit_message.to_string(),
|
Span::styled(
|
||||||
theme.text(true, false),
|
format!("{} ", is_head_str),
|
||||||
),
|
theme.commit_author(false),
|
||||||
]
|
),
|
||||||
}));
|
Span::styled(
|
||||||
|
format!(
|
||||||
|
" {:w$} ",
|
||||||
|
branch_name,
|
||||||
|
w = branch_name_length
|
||||||
|
),
|
||||||
|
theme.commit_author(false),
|
||||||
|
),
|
||||||
|
Span::styled(
|
||||||
|
format!(
|
||||||
|
"{} ",
|
||||||
|
displaybranch
|
||||||
|
.top_commit
|
||||||
|
.get_short_string()
|
||||||
|
),
|
||||||
|
theme.commit_hash(false),
|
||||||
|
),
|
||||||
|
Span::styled(
|
||||||
|
commit_message.to_string(),
|
||||||
|
theme.text(true, false),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Text::from(txt))
|
Ok(Text::from(txt))
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue