Only allow save_as for pane if can_save_as is true (#25028)
When saving an item, some logic is done to determine whether one can save it. In the special case where the intent is to `SaveAs`, it was previously allowed to proceed as long as the buffer was a singleton (presumably since it only makes sense to provide a save path for a single file). However, we need to _also_ check that this item can be "saved as" at all. For this, we resurrect the `ItemHandle`/`Item` trait method `can_save_as`. We have given it the default implementation of returning `false`, and then overridden this in the implementation for `TerminalView`. Closes #25023 Release Notes: - Fixed crash when trying to save terminal buffer --------- Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This commit is contained in:
@@ -706,6 +706,10 @@ impl Item for Editor {
|
||||
self.buffer.read(cx).is_singleton()
|
||||
}
|
||||
|
||||
fn can_save_as(&self, cx: &App) -> bool {
|
||||
self.buffer.read(cx).is_singleton()
|
||||
}
|
||||
|
||||
fn clone_on_split(
|
||||
&self,
|
||||
_workspace_id: Option<WorkspaceId>,
|
||||
|
||||
@@ -1342,6 +1342,10 @@ impl Item for TerminalView {
|
||||
false
|
||||
}
|
||||
|
||||
fn can_save_as(&self, _cx: &App) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn is_singleton(&self, _cx: &App) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
@@ -276,6 +276,9 @@ pub trait Item: Focusable + EventEmitter<Self::Event> + Render + Sized {
|
||||
fn can_save(&self, _cx: &App) -> bool {
|
||||
false
|
||||
}
|
||||
fn can_save_as(&self, _: &App) -> bool {
|
||||
false
|
||||
}
|
||||
fn save(
|
||||
&mut self,
|
||||
_format: bool,
|
||||
@@ -477,6 +480,7 @@ pub trait ItemHandle: 'static + Send {
|
||||
fn has_deleted_file(&self, cx: &App) -> bool;
|
||||
fn has_conflict(&self, cx: &App) -> bool;
|
||||
fn can_save(&self, cx: &App) -> bool;
|
||||
fn can_save_as(&self, cx: &App) -> bool;
|
||||
fn save(
|
||||
&self,
|
||||
format: bool,
|
||||
@@ -890,6 +894,10 @@ impl<T: Item> ItemHandle for Entity<T> {
|
||||
self.read(cx).can_save(cx)
|
||||
}
|
||||
|
||||
fn can_save_as(&self, cx: &App) -> bool {
|
||||
self.read(cx).can_save_as(cx)
|
||||
}
|
||||
|
||||
fn save(
|
||||
&self,
|
||||
format: bool,
|
||||
@@ -1468,6 +1476,10 @@ pub mod test {
|
||||
.all(|item| item.read(cx).entry_id.is_some())
|
||||
}
|
||||
|
||||
fn can_save_as(&self, _cx: &App) -> bool {
|
||||
self.is_singleton
|
||||
}
|
||||
|
||||
fn save(
|
||||
&mut self,
|
||||
_: bool,
|
||||
|
||||
@@ -1794,18 +1794,23 @@ impl Pane {
|
||||
return Ok(true);
|
||||
};
|
||||
|
||||
let (mut has_conflict, mut is_dirty, mut can_save, is_singleton, has_deleted_file) = cx
|
||||
.update(|_window, cx| {
|
||||
(
|
||||
item.has_conflict(cx),
|
||||
item.is_dirty(cx),
|
||||
item.can_save(cx),
|
||||
item.is_singleton(cx),
|
||||
item.has_deleted_file(cx),
|
||||
)
|
||||
})?;
|
||||
|
||||
let can_save_as = is_singleton;
|
||||
let (
|
||||
mut has_conflict,
|
||||
mut is_dirty,
|
||||
mut can_save,
|
||||
can_save_as,
|
||||
is_singleton,
|
||||
has_deleted_file,
|
||||
) = cx.update(|_window, cx| {
|
||||
(
|
||||
item.has_conflict(cx),
|
||||
item.is_dirty(cx),
|
||||
item.can_save(cx),
|
||||
item.can_save_as(cx),
|
||||
item.is_singleton(cx),
|
||||
item.has_deleted_file(cx),
|
||||
)
|
||||
})?;
|
||||
|
||||
// when saving a single buffer, we ignore whether or not it's dirty.
|
||||
if save_intent == SaveIntent::Save || save_intent == SaveIntent::SaveWithoutFormat {
|
||||
@@ -1939,7 +1944,7 @@ impl Pane {
|
||||
item.save(should_format, project, window, cx)
|
||||
})?
|
||||
.await?;
|
||||
} else if can_save_as {
|
||||
} else if can_save_as && is_singleton {
|
||||
let abs_path = pane.update_in(cx, |pane, window, cx| {
|
||||
pane.activate_item(item_ix, true, true, window, cx);
|
||||
pane.workspace.update(cx, |workspace, cx| {
|
||||
|
||||
Reference in New Issue
Block a user