feat: refresh diffs when selected jj bookmarks move
This commit is contained in:
+48
-16
@@ -63,6 +63,10 @@ impl ComparisonMode {
|
||||
pub enum RevisionTarget {
|
||||
Working,
|
||||
Commit(String),
|
||||
Bookmark {
|
||||
name: String,
|
||||
remote: Option<String>,
|
||||
},
|
||||
Remote {
|
||||
remote: String,
|
||||
reference: String,
|
||||
@@ -178,6 +182,7 @@ pub enum Outcome {
|
||||
},
|
||||
Comparison(Comparison),
|
||||
CheckoutRefresh(Option<Comparison>),
|
||||
BookmarkRefresh(Comparison),
|
||||
File {
|
||||
comparison_id: u64,
|
||||
file_index: usize,
|
||||
@@ -299,6 +304,7 @@ pub struct DiffState {
|
||||
max_before: usize,
|
||||
max_after: usize,
|
||||
after_widths: Vec<usize>,
|
||||
pub(crate) refresh_view: Option<(usize, usize, usize)>,
|
||||
}
|
||||
|
||||
impl DiffState {
|
||||
@@ -355,6 +361,7 @@ impl DiffState {
|
||||
max_before: 0,
|
||||
max_after: 0,
|
||||
after_widths: Vec::new(),
|
||||
refresh_view: None,
|
||||
}
|
||||
}
|
||||
pub(crate) fn set_resolver_paths(&mut self, root: PathBuf, paths: Vec<PathBuf>, file: usize) {
|
||||
@@ -516,10 +523,15 @@ impl DiffState {
|
||||
|| self.request_kind.is_some()
|
||||
|| self.pending.is_some()
|
||||
|| self.comparison.is_none()
|
||||
|| self
|
||||
.after
|
||||
.as_ref()
|
||||
.is_none_or(|after| after.target == RevisionTarget::Working && !follow_working)
|
||||
|| self.after.as_ref().is_none_or(|after| {
|
||||
after.target == RevisionTarget::Working
|
||||
&& !follow_working
|
||||
&& !self
|
||||
.before
|
||||
.iter()
|
||||
.chain(self.after.iter())
|
||||
.any(|revision| matches!(revision.target, RevisionTarget::Bookmark { .. }))
|
||||
})
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -635,18 +647,22 @@ impl DiffState {
|
||||
}
|
||||
self.request_kind = None;
|
||||
let deferred = self.pending.take();
|
||||
let bookmark_refresh = matches!(&result, Ok(Outcome::BookmarkRefresh(_)));
|
||||
match result {
|
||||
Ok(Outcome::CheckoutRefresh(None)) => {
|
||||
let recovered = self.error.take().is_some();
|
||||
if let Some(operation) = deferred {
|
||||
self.queue(operation);
|
||||
}
|
||||
return false;
|
||||
return recovered;
|
||||
}
|
||||
Ok(Outcome::CheckoutRefresh(Some(mut comparison))) => {
|
||||
let pinned = self
|
||||
.after
|
||||
.as_ref()
|
||||
.is_some_and(|after| after.target != RevisionTarget::Working);
|
||||
Ok(Outcome::CheckoutRefresh(Some(mut comparison)))
|
||||
| Ok(Outcome::BookmarkRefresh(mut comparison)) => {
|
||||
let pinned = !bookmark_refresh
|
||||
&& self
|
||||
.after
|
||||
.as_ref()
|
||||
.is_some_and(|after| after.target != RevisionTarget::Working);
|
||||
let view = (self.top, self.left_before, self.left_after);
|
||||
if !pinned {
|
||||
self.reviewed_files.clear();
|
||||
@@ -690,12 +706,17 @@ impl DiffState {
|
||||
self.live_files.clear();
|
||||
self.live_buffer = None;
|
||||
self.live_revision = None;
|
||||
self.refresh_view = None;
|
||||
self.follow_caret = false;
|
||||
self.prepare_selected_file();
|
||||
if pinned {
|
||||
self.top = view.0.min(self.display_rows.len().saturating_sub(1));
|
||||
self.left_before = view.1.min(self.max_before);
|
||||
self.left_after = view.2.min(self.max_after);
|
||||
if pinned || bookmark_refresh {
|
||||
if self.selected_file_loaded() {
|
||||
self.top = view.0.min(self.display_rows.len().saturating_sub(1));
|
||||
self.left_before = view.1.min(self.max_before);
|
||||
self.left_after = view.2.min(self.max_after);
|
||||
} else {
|
||||
self.refresh_view = Some(view);
|
||||
}
|
||||
}
|
||||
self.normalize_focus();
|
||||
}
|
||||
@@ -713,7 +734,10 @@ impl DiffState {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if matches!(result, Ok(Outcome::CheckoutRefresh(_))) {
|
||||
if matches!(
|
||||
result,
|
||||
Ok(Outcome::CheckoutRefresh(_) | Outcome::BookmarkRefresh(_))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if let Ok(Outcome::File {
|
||||
@@ -758,6 +782,7 @@ impl DiffState {
|
||||
Ok(Outcome::Comparison(comparison)) if expected == Some(RequestKind::Comparison) => {
|
||||
self.live_files.clear();
|
||||
self.frozen_after.clear();
|
||||
self.refresh_view = None;
|
||||
self.reviewed_files.clear();
|
||||
self.live_buffer = None;
|
||||
self.live_revision = None;
|
||||
@@ -811,6 +836,11 @@ impl DiffState {
|
||||
*selected = file;
|
||||
if self.file == file_index {
|
||||
self.align_file();
|
||||
if let Some(view) = self.refresh_view.take() {
|
||||
self.top = view.0.min(self.display_rows.len().saturating_sub(1));
|
||||
self.left_before = view.1.min(self.max_before);
|
||||
self.left_after = view.2.min(self.max_after);
|
||||
}
|
||||
self.normalize_focus();
|
||||
}
|
||||
self.error = None;
|
||||
@@ -1488,6 +1518,7 @@ impl DiffState {
|
||||
return true;
|
||||
}
|
||||
self.file = index;
|
||||
self.refresh_view = None;
|
||||
self.normalize_focus();
|
||||
self.live_buffer = None;
|
||||
self.live_revision = None;
|
||||
@@ -4267,7 +4298,8 @@ mod tests {
|
||||
..
|
||||
})
|
||||
));
|
||||
assert!(!state.apply_result(8, Ok(Outcome::CheckoutRefresh(None))));
|
||||
assert!(state.apply_result(8, Ok(Outcome::CheckoutRefresh(None))));
|
||||
assert!(state.error.is_none());
|
||||
assert_eq!(state.comparison_id, Some(7));
|
||||
assert_eq!(state.reviewed_files, BTreeSet::from([0]));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user