Wait to update bufferview's file handle until save has completed
This commit is contained in:
@@ -3123,8 +3123,7 @@ mod tests {
|
|||||||
let mut buffers = Vec::new();
|
let mut buffers = Vec::new();
|
||||||
let mut network = Network::new();
|
let mut network = Network::new();
|
||||||
for i in 0..PEERS {
|
for i in 0..PEERS {
|
||||||
let buffer =
|
let buffer = ctx.add_model(|_| Buffer::new(i as ReplicaId, base_text.as_str()));
|
||||||
ctx.add_model(|_| Buffer::new(i as ReplicaId, base_text.as_str()));
|
|
||||||
buffers.push(buffer);
|
buffers.push(buffer);
|
||||||
replica_ids.push(i as u16);
|
replica_ids.push(i as u16);
|
||||||
network.add_peer(i as u16);
|
network.add_peer(i as u16);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use gpui::{
|
|||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use smol::Timer;
|
use smol::{future::FutureExt, Timer};
|
||||||
use std::{
|
use std::{
|
||||||
cmp::{self, Ordering},
|
cmp::{self, Ordering},
|
||||||
fmt::Write,
|
fmt::Write,
|
||||||
@@ -2136,15 +2136,20 @@ impl workspace::ItemView for BufferView {
|
|||||||
|
|
||||||
fn save(
|
fn save(
|
||||||
&mut self,
|
&mut self,
|
||||||
file: Option<FileHandle>,
|
new_file: Option<FileHandle>,
|
||||||
ctx: &mut ViewContext<Self>,
|
ctx: &mut ViewContext<Self>,
|
||||||
) -> LocalBoxFuture<'static, Result<()>> {
|
) -> LocalBoxFuture<'static, Result<()>> {
|
||||||
if file.is_some() {
|
if let Some(file) = new_file.as_ref().or(self.file.as_ref()) {
|
||||||
self.file = file;
|
let save = self.buffer.update(ctx, |b, ctx| b.save(file, ctx));
|
||||||
}
|
ctx.spawn(save, move |this, result, ctx| {
|
||||||
if let Some(file) = self.file.as_ref() {
|
if new_file.is_some() && result.is_ok() {
|
||||||
self.buffer
|
this.file = new_file;
|
||||||
.update(ctx, |buffer, ctx| buffer.save(file, ctx))
|
ctx.emit(Event::FileHandleChanged);
|
||||||
|
ctx.notify();
|
||||||
|
}
|
||||||
|
result
|
||||||
|
})
|
||||||
|
.boxed_local()
|
||||||
} else {
|
} else {
|
||||||
Box::pin(async { Ok(()) })
|
Box::pin(async { Ok(()) })
|
||||||
}
|
}
|
||||||
|
|||||||
+83
-35
@@ -369,11 +369,11 @@ impl Workspace {
|
|||||||
|
|
||||||
pub fn open_new_file(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
|
pub fn open_new_file(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
|
||||||
let buffer = ctx.add_model(|_| Buffer::new(self.replica_id, ""));
|
let buffer = ctx.add_model(|_| Buffer::new(self.replica_id, ""));
|
||||||
let buffer_view = Box::new(ctx.add_view(|ctx| {
|
let buffer_view = ctx.add_view(|ctx| {
|
||||||
BufferView::for_buffer(buffer.clone(), None, self.settings.clone(), ctx)
|
BufferView::for_buffer(buffer.clone(), None, self.settings.clone(), ctx)
|
||||||
}));
|
});
|
||||||
self.untitled_buffers.insert(buffer);
|
self.untitled_buffers.insert(buffer);
|
||||||
self.add_item(buffer_view, ctx);
|
self.add_item(Box::new(buffer_view), ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@@ -468,41 +468,45 @@ impl Workspace {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_active_item(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
|
pub fn active_item(&self, ctx: &ViewContext<Self>) -> Option<Box<dyn ItemViewHandle>> {
|
||||||
let handle = ctx.handle();
|
self.active_pane().read(ctx).active_item()
|
||||||
let first_worktree = self.worktrees.iter().next();
|
}
|
||||||
self.active_pane.update(ctx, move |pane, ctx| {
|
|
||||||
if let Some(item) = pane.active_item() {
|
|
||||||
if item.entry_id(ctx.as_ref()).is_none() {
|
|
||||||
let start_path = first_worktree
|
|
||||||
.map_or(Path::new(""), |h| h.read(ctx).abs_path())
|
|
||||||
.to_path_buf();
|
|
||||||
ctx.prompt_for_new_path(&start_path, move |path, ctx| {
|
|
||||||
if let Some(path) = path {
|
|
||||||
handle.update(ctx, move |this, ctx| {
|
|
||||||
let file = this.file_for_path(&path, ctx);
|
|
||||||
let task = item.save(Some(file), ctx.as_mut());
|
|
||||||
ctx.spawn(task, |_, result, _| {
|
|
||||||
if let Err(e) = result {
|
|
||||||
error!("failed to save item: {:?}, ", e);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.detach()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let task = item.save(None, ctx.as_mut());
|
pub fn save_active_item(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
|
||||||
ctx.spawn(task, |_, result, _| {
|
if let Some(item) = self.active_item(ctx) {
|
||||||
if let Err(e) = result {
|
if item.entry_id(ctx.as_ref()).is_none() {
|
||||||
error!("failed to save item: {:?}, ", e);
|
let handle = ctx.handle();
|
||||||
|
let start_path = self
|
||||||
|
.worktrees
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.map_or(Path::new(""), |h| h.read(ctx).abs_path())
|
||||||
|
.to_path_buf();
|
||||||
|
ctx.prompt_for_new_path(&start_path, move |path, ctx| {
|
||||||
|
if let Some(path) = path {
|
||||||
|
handle.update(ctx, move |this, ctx| {
|
||||||
|
let file = this.file_for_path(&path, ctx);
|
||||||
|
let task = item.save(Some(file), ctx.as_mut());
|
||||||
|
ctx.spawn(task, |_, result, _| {
|
||||||
|
if let Err(e) = result {
|
||||||
|
error!("failed to save item: {:?}, ", e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.detach()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
.detach()
|
return;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
let task = item.save(None, ctx.as_mut());
|
||||||
|
ctx.spawn(task, |_, result, _| {
|
||||||
|
if let Err(e) = result {
|
||||||
|
error!("failed to save item: {:?}, ", e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.detach()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn debug_elements(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
|
pub fn debug_elements(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
|
||||||
@@ -660,6 +664,7 @@ mod tests {
|
|||||||
use gpui::App;
|
use gpui::App;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::{collections::HashSet, os::unix};
|
use std::{collections::HashSet, os::unix};
|
||||||
|
use tempdir::TempDir;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_open_paths_action() {
|
fn test_open_paths_action() {
|
||||||
@@ -942,6 +947,49 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_open_and_save_new_file() {
|
||||||
|
App::test_async((), |mut app| async move {
|
||||||
|
let dir = TempDir::new("test-new-file").unwrap();
|
||||||
|
let settings = settings::channel(&app.font_cache()).unwrap().1;
|
||||||
|
let (_, workspace) = app.add_window(|ctx| {
|
||||||
|
let mut workspace = Workspace::new(0, settings, ctx);
|
||||||
|
workspace.add_worktree(dir.path(), ctx);
|
||||||
|
workspace
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create a new untitled buffer
|
||||||
|
let editor = workspace.update(&mut app, |workspace, ctx| {
|
||||||
|
workspace.open_new_file(&(), ctx);
|
||||||
|
workspace
|
||||||
|
.active_item(ctx)
|
||||||
|
.unwrap()
|
||||||
|
.to_any()
|
||||||
|
.downcast::<BufferView>()
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
editor.update(&mut app, |editor, ctx| {
|
||||||
|
assert_eq!(editor.title(ctx.as_ref()), "untitled");
|
||||||
|
editor.insert(&"hi".to_string(), ctx)
|
||||||
|
});
|
||||||
|
|
||||||
|
// Save the buffer, selecting a filename
|
||||||
|
workspace.update(&mut app, |workspace, ctx| {
|
||||||
|
workspace.save_active_item(&(), ctx)
|
||||||
|
});
|
||||||
|
app.simulate_new_path_selection(|parent_dir| {
|
||||||
|
assert_eq!(parent_dir, dir.path());
|
||||||
|
Some(parent_dir.join("the-new-name"))
|
||||||
|
});
|
||||||
|
app.read(|ctx| assert_eq!(editor.title(ctx), "untitled"));
|
||||||
|
|
||||||
|
// When the save completes, the buffer's title is updated.
|
||||||
|
editor
|
||||||
|
.condition(&app, |editor, ctx| editor.title(ctx) == "the-new-name")
|
||||||
|
.await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pane_actions() {
|
fn test_pane_actions() {
|
||||||
App::test_async((), |mut app| async move {
|
App::test_async((), |mut app| async move {
|
||||||
|
|||||||
Reference in New Issue
Block a user