feat: mark fully checked collapsed diff folders
This commit is contained in:
+104
-4
@@ -5692,10 +5692,22 @@ fn draw_file_list(
|
||||
.and_then(|file| file.old_path.as_deref())
|
||||
.or(entry.old_path);
|
||||
let mut spans = Vec::with_capacity(8);
|
||||
let reviewed = changed.is_some()
|
||||
&& entry.catalog_index.is_some_and(|index| {
|
||||
changed_files.is_some_and(|(_, reviewed)| reviewed.contains(&index))
|
||||
});
|
||||
let reviewed = changed_files.is_some_and(|(_, reviewed)| {
|
||||
if entry.is_dir {
|
||||
if entry.expanded {
|
||||
return false;
|
||||
}
|
||||
let mut descendants =
|
||||
picker.descendant_catalog_indices(entry.path).peekable();
|
||||
descendants.peek().is_some()
|
||||
&& descendants.all(|index| reviewed.contains(&index))
|
||||
} else {
|
||||
changed.is_some()
|
||||
&& entry
|
||||
.catalog_index
|
||||
.is_some_and(|index| reviewed.contains(&index))
|
||||
}
|
||||
});
|
||||
if changed_files.is_none() {
|
||||
spans.push(Span::raw(if selected { ">" } else { " " }));
|
||||
spans.push(Span::raw(" "));
|
||||
@@ -9541,6 +9553,94 @@ mod tests {
|
||||
assert!(!screen_text(&terminal).contains('✓'));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn collapsed_diff_folders_reflect_all_catalog_descendants() {
|
||||
let files: Vec<_> = [
|
||||
"src/top.rs",
|
||||
"src/deep/leaf.rs",
|
||||
"src/deep/other.rs",
|
||||
"srcish/unreviewed.rs",
|
||||
"src",
|
||||
"compact/a/b/only.rs",
|
||||
]
|
||||
.into_iter()
|
||||
.map(|path| {
|
||||
let mut file = deletion_file();
|
||||
file.path = path.into();
|
||||
file
|
||||
})
|
||||
.collect();
|
||||
let paths = || {
|
||||
files
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, file)| (index, file.path.clone()))
|
||||
};
|
||||
let mut picker = FilePicker::from_paths(PathBuf::new(), paths());
|
||||
let mut terminal = Terminal::new(ratatui::backend::TestBackend::new(100, 18)).unwrap();
|
||||
let mut check = |picker: &FilePicker, reviewed: &BTreeSet<usize>, label: &str, marked| {
|
||||
terminal
|
||||
.draw(|frame| {
|
||||
draw_file_list(
|
||||
frame,
|
||||
picker,
|
||||
frame.area(),
|
||||
"",
|
||||
&mut WheelPanels::default(),
|
||||
Some((&files, reviewed)),
|
||||
);
|
||||
})
|
||||
.unwrap();
|
||||
let text = screen_text(&terminal);
|
||||
let row = text.lines().find(|row| row.contains(label)).unwrap();
|
||||
assert_eq!(row.contains('✓'), marked, "{row}");
|
||||
if marked {
|
||||
let buffer = terminal.backend().buffer();
|
||||
let y = text.lines().position(|row| row.contains(label)).unwrap() as u16;
|
||||
let x = (0..100).find(|&x| buffer[(x, y)].symbol() == "✓").unwrap();
|
||||
assert_eq!(buffer[(x, y)].fg, Color::Green);
|
||||
}
|
||||
};
|
||||
let mut reviewed = BTreeSet::from([0, 1]);
|
||||
check(&picker, &reviewed, "src/", false);
|
||||
reviewed.insert(2);
|
||||
check(&picker, &reviewed, "src/", true);
|
||||
check(&picker, &reviewed, "srcish/", false);
|
||||
check(&picker, &reviewed, "compact/a/b/", false);
|
||||
reviewed.insert(5);
|
||||
check(&picker, &reviewed, "compact/a/b/", true);
|
||||
|
||||
let selected = picker
|
||||
.entries()
|
||||
.position(|row| row.is_dir && row.path == std::path::Path::new("src"))
|
||||
.unwrap();
|
||||
picker.selected = selected;
|
||||
picker.right();
|
||||
check(&picker, &reviewed, "src/", false);
|
||||
check(&picker, &reviewed, "deep/", true);
|
||||
|
||||
reviewed.remove(&2);
|
||||
picker.query = "leaf.rs".into();
|
||||
picker.refilter();
|
||||
let selected = picker
|
||||
.entries()
|
||||
.position(|row| row.is_dir && row.path == std::path::Path::new("src/deep"))
|
||||
.unwrap();
|
||||
picker.selected = selected;
|
||||
picker.accept();
|
||||
check(&picker, &reviewed, "deep/", false);
|
||||
reviewed.insert(2);
|
||||
check(&picker, &reviewed, "deep/", true);
|
||||
reviewed.remove(&2);
|
||||
check(&picker, &reviewed, "deep/", false);
|
||||
|
||||
// A reverted file no longer in the picker must not block its folder's mark.
|
||||
picker.replace_paths(paths().filter(|(index, _)| *index != 2));
|
||||
check(&picker, &reviewed, "deep/", true);
|
||||
picker.accept();
|
||||
check(&picker, &reviewed, "deep/", false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normal_file_markers_keep_clean_rows_and_match_diff_colors_in_every_view() {
|
||||
use crate::repository::WorkingFileChange;
|
||||
|
||||
Reference in New Issue
Block a user