refactor: encapsulate review identity changes
This commit is contained in:
+71
-46
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user