use super::utils::logitems::{ItemBatch, LogEntry};
use crate::{
components::{
utils::string_width_align, CommandBlocking, CommandInfo,
Component, DrawableComponent, EventState, ScrollType,
},
keys::{key_match, SharedKeyConfig},
queue::{InternalEvent, Queue},
strings::{self, symbol},
try_or_popup,
ui::style::{SharedTheme, Theme},
ui::{calc_scroll_top, draw_scrollbar, Orientation},
};
use anyhow::Result;
use asyncgit::sync::{
self, checkout_commit, BranchDetails, BranchInfo, CommitId,
RepoPathRef, Tags,
};
use chrono::{DateTime, Local};
use crossterm::event::Event;
use indexmap::IndexSet;
use itertools::Itertools;
use ratatui::{
backend::Backend,
layout::{Alignment, Rect},
style::Style,
text::{Line, Span},
widgets::{Block, Borders, Paragraph},
Frame,
};
use std::{
borrow::Cow, cell::Cell, cmp, collections::BTreeMap,
convert::TryFrom, rc::Rc, time::Instant,
};
const ELEMENTS_PER_LINE: usize = 9;
const SLICE_SIZE: usize = 1200;
///
pub struct CommitList {
repo: RepoPathRef,
title: Box<str>,
selection: usize,
highlighted_selection: Option<usize>,
items: ItemBatch,
highlights: Option<Rc<IndexSet<CommitId>>>,
commits: IndexSet<CommitId>,
marked: Vec<(usize, CommitId)>,
scroll_state: (Instant, f32),
tags: Option<Tags>,
local_branches: BTreeMap<CommitId, Vec<BranchInfo>>,
remote_branches: BTreeMap<CommitId, Vec<BranchInfo>>,
current_size: Cell<Option<(u16, u16)>>,
scroll_top: Cell<usize>,
theme: SharedTheme,
queue: Queue,
key_config: SharedKeyConfig,
}
impl CommitList {
///
pub fn new(
repo: RepoPathRef,
title: &str,
theme: SharedTheme,
queue: Queue,
key_config: SharedKeyConfig,
) -> Self {
Self {
repo,
items: ItemBatch::default(),
marked: Vec::with_capacity(2),
selection: 0,
highlighted_selection: None,
commits: IndexSet::new(),
highlights: None,
scroll_state: (Instant::now(), 0_f32),
tags: None,
local_branches: BTreeMap::default(),
remote_branches: BTreeMap::default(),
current_size: Cell::new(None),
scroll_top: Cell::new(0),
theme,
queue,
key_config,
title: title.into(),
}
}
///
pub const fn tags(&self) -> Option<&Tags> {
self.tags.as_ref()
}
///
pub fn clear(&mut self) {
self.items.clear();
self.commits.clear();
}
///
pub fn copy_items(&self) -> Vec<CommitId> {
self.commits.iter().copied().collect_vec()
}
///
pub fn set_tags(&mut self, tags: Tags) {
self.tags = Some(tags);
}
///
pub fn selected_entry(&self) -> Option<&LogEntry> {
self.items.iter().nth(
self.selection.saturating_sub(self.items.index_offset()),
)
}
///
pub fn marked_count(&self) -> usize {
self.marked.len()
}
///
pub fn marked(&self) -> &[(usize, CommitId)] {
&self.marked
}
///
pub fn clear_marked(&mut self) {
self.marked.clear();
}
///
pub fn marked_commits(&self) -> Vec<CommitId> {
let (_, commits): (Vec<_