refactor: encapsulate review identity changes

This commit is contained in:
Valdemar Lorenzen
2026-10-16 18:03:15 +02:00
parent 8174e81c5c
commit befa432095
3 changed files with 128 additions and 46 deletions
+71 -46
View File
@@ -9,6 +9,12 @@ enum ReviewText {
Reviews,
}
enum ReviewSource<'a> {
Stored(i64),
Json(&'a Path),
New,
}
pub(super) struct ReviewBuffer {
owner: usize,
kind: ReviewText,
@@ -204,6 +210,63 @@ impl Editor {
}
}
fn replace_local_review(
&mut self,
root: PathBuf,
source: ReviewSource<'_>,
) -> Result<(), String> {
let (document, path, dirty) = match source {
ReviewSource::Stored(id) => {
let directory = self
.review_directory
.as_deref()
.ok_or("Review storage is not configured")?;
(
crate::review::Store::open(directory)?.load(&root, id)?,
None,
false,
)
}
ReviewSource::Json(path) => (
Review::load(path, &root)?,
Some(path.to_path_buf()),
self.review_directory.is_some(),
),
ReviewSource::New => (Review::new(root), None, true),
};
// Retire old identities before autosave can synchronize their native drafts.
self.detach_review_buffers();
let state = &mut self.review_diff_mut().unwrap().local_review;
state.document = document;
state.path = path;
state.selected = None;
state.pending_navigation = None;
state.dirty = dirty;
// Persistence failure leaves the identity change applied and unsaved.
self.autosave_local_review()?;
self.open_review_overview()
}
fn delete_local_review_comment(&mut self, args: &str) -> Result<(), String> {
let id = self.review_comment_id(args)?;
let state = &mut self.review_diff_mut().unwrap().local_review;
state.document.comments.retain(|comment| comment.id != id);
state.selected = None;
state.pending_navigation = None;
state.dirty = true;
// The deleted draft cannot later overwrite another comment with the same ID.
for buffer in std::iter::once(&mut self.active).chain(self.parked.values_mut()) {
if buffer.review_buffer.as_ref().is_some_and(|binding| {
binding.owner == self.tab_id && binding.kind == ReviewText::Comment(id)
}) {
buffer.review_buffer = None;
buffer.saved_lines.clone_from(&buffer.lines);
}
}
self.autosave_local_review()?;
self.open_review_overview()
}
fn sync_review_text(&mut self) {
let owner = self.tab_id;
let updates: Vec<_> = std::iter::once(&self.active)
@@ -327,39 +390,19 @@ impl Editor {
if args.is_empty() {
return self.open_review_selector();
}
let document = if let (Some(directory), Ok(id)) =
(self.review_directory.as_deref(), args.parse::<i64>())
{
crate::review::Store::open(directory)?.load(&root, id)?
let source = if self.review_directory.is_some() {
args.parse::<i64>()
.map(ReviewSource::Stored)
.unwrap_or_else(|_| ReviewSource::Json(Path::new(args)))
} else {
Review::load(Path::new(args), &root)?
ReviewSource::Json(Path::new(args))
};
let imported = document.storage_id.is_none();
let dirty = imported && self.review_directory.is_some();
self.detach_review_buffers();
let state = &mut self.review_diff_mut().unwrap().local_review;
state.document = document;
state.path = imported.then(|| PathBuf::from(args));
state.selected = None;
state.pending_navigation = None;
state.dirty = dirty;
self.autosave_local_review()?;
return self.open_review_overview();
return self.replace_local_review(root, source);
}
self.sync_review_text();
match action {
Action::DiffComment => self.add_review_comment()?,
Action::ReviewNew => {
self.detach_review_buffers();
let state = &mut self.review_diff_mut().unwrap().local_review;
state.document = Review::new(root);
state.selected = None;
state.pending_navigation = None;
state.path = None;
state.dirty = true;
self.autosave_local_review()?;
self.open_review_overview()?;
}
Action::ReviewNew => self.replace_local_review(root, ReviewSource::New)?,
Action::ReviewEdit => {
let id = self.review_comment_id(args)?;
self.show_review_comment(id)?;
@@ -398,25 +441,7 @@ impl Editor {
self.autosave_local_review()?;
self.open_review_overview()?;
}
Action::ReviewDelete => {
let id = self.review_comment_id(args)?;
let state = &mut self.review_diff_mut().unwrap().local_review;
state.document.comments.retain(|comment| comment.id != id);
state.selected = None;
state.pending_navigation = None;
state.dirty = true;
// The deleted draft cannot later overwrite another comment with the same ID.
for buffer in std::iter::once(&mut self.active).chain(self.parked.values_mut()) {
if buffer.review_buffer.as_ref().is_some_and(|binding| {
binding.owner == self.tab_id && binding.kind == ReviewText::Comment(id)
}) {
buffer.review_buffer = None;
buffer.saved_lines.clone_from(&buffer.lines);
}
}
self.autosave_local_review()?;
self.open_review_overview()?;
}
Action::ReviewDelete => self.delete_local_review_comment(args)?,
Action::ReviewNext | Action::ReviewPrevious => {
let state = &self.workspace_diff().unwrap().local_review;
let comments = &state.document.comments;