thread_view: Fix issues with images (#36509)
- Clean up failed load tasks for mentions that require async processing - When dragging and dropping files, hold onto added worktrees until any async processing has completed; this fixes a bug when dragging items from outside the project Release Notes: - N/A
This commit is contained in:
parent
a91acb5f41
commit
df9c2aefb1
3 changed files with 85 additions and 61 deletions
|
@ -763,14 +763,16 @@ fn confirm_completion_callback(
|
|||
message_editor
|
||||
.clone()
|
||||
.update(cx, |message_editor, cx| {
|
||||
message_editor.confirm_completion(
|
||||
crease_text,
|
||||
start,
|
||||
content_len,
|
||||
mention_uri,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
message_editor
|
||||
.confirm_completion(
|
||||
crease_text,
|
||||
start,
|
||||
content_len,
|
||||
mention_uri,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
.detach();
|
||||
})
|
||||
.ok();
|
||||
});
|
||||
|
|
|
@ -26,7 +26,7 @@ use gpui::{
|
|||
};
|
||||
use language::{Buffer, Language};
|
||||
use language_model::LanguageModelImage;
|
||||
use project::{CompletionIntent, Project, ProjectPath, Worktree};
|
||||
use project::{Project, ProjectPath, Worktree};
|
||||
use rope::Point;
|
||||
use settings::Settings;
|
||||
use std::{
|
||||
|
@ -202,18 +202,18 @@ impl MessageEditor {
|
|||
mention_uri: MentionUri,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
) -> Task<()> {
|
||||
let snapshot = self
|
||||
.editor
|
||||
.update(cx, |editor, cx| editor.snapshot(window, cx));
|
||||
let Some((excerpt_id, _, _)) = snapshot.buffer_snapshot.as_singleton() else {
|
||||
return;
|
||||
return Task::ready(());
|
||||
};
|
||||
let Some(anchor) = snapshot
|
||||
.buffer_snapshot
|
||||
.anchor_in_excerpt(*excerpt_id, start)
|
||||
else {
|
||||
return;
|
||||
return Task::ready(());
|
||||
};
|
||||
|
||||
if let MentionUri::File { abs_path, .. } = &mention_uri {
|
||||
|
@ -228,7 +228,7 @@ impl MessageEditor {
|
|||
.read(cx)
|
||||
.project_path_for_absolute_path(abs_path, cx)
|
||||
else {
|
||||
return;
|
||||
return Task::ready(());
|
||||
};
|
||||
let image = cx
|
||||
.spawn(async move |_, cx| {
|
||||
|
@ -252,9 +252,9 @@ impl MessageEditor {
|
|||
window,
|
||||
cx,
|
||||
) else {
|
||||
return;
|
||||
return Task::ready(());
|
||||
};
|
||||
self.confirm_mention_for_image(
|
||||
return self.confirm_mention_for_image(
|
||||
crease_id,
|
||||
anchor,
|
||||
Some(abs_path.clone()),
|
||||
|
@ -262,7 +262,6 @@ impl MessageEditor {
|
|||
window,
|
||||
cx,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,27 +275,28 @@ impl MessageEditor {
|
|||
window,
|
||||
cx,
|
||||
) else {
|
||||
return;
|
||||
return Task::ready(());
|
||||
};
|
||||
|
||||
match mention_uri {
|
||||
MentionUri::Fetch { url } => {
|
||||
self.confirm_mention_for_fetch(crease_id, anchor, url, window, cx);
|
||||
self.confirm_mention_for_fetch(crease_id, anchor, url, window, cx)
|
||||
}
|
||||
MentionUri::Directory { abs_path } => {
|
||||
self.confirm_mention_for_directory(crease_id, anchor, abs_path, window, cx);
|
||||
self.confirm_mention_for_directory(crease_id, anchor, abs_path, window, cx)
|
||||
}
|
||||
MentionUri::Thread { id, name } => {
|
||||
self.confirm_mention_for_thread(crease_id, anchor, id, name, window, cx);
|
||||
self.confirm_mention_for_thread(crease_id, anchor, id, name, window, cx)
|
||||
}
|
||||
MentionUri::TextThread { path, name } => {
|
||||
self.confirm_mention_for_text_thread(crease_id, anchor, path, name, window, cx);
|
||||
self.confirm_mention_for_text_thread(crease_id, anchor, path, name, window, cx)
|
||||
}
|
||||
MentionUri::File { .. }
|
||||
| MentionUri::Symbol { .. }
|
||||
| MentionUri::Rule { .. }
|
||||
| MentionUri::Selection { .. } => {
|
||||
self.mention_set.insert_uri(crease_id, mention_uri.clone());
|
||||
Task::ready(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -308,7 +308,7 @@ impl MessageEditor {
|
|||
abs_path: PathBuf,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
) -> Task<()> {
|
||||
fn collect_files_in_path(worktree: &Worktree, path: &Path) -> Vec<(Arc<Path>, PathBuf)> {
|
||||
let mut files = Vec::new();
|
||||
|
||||
|
@ -331,13 +331,13 @@ impl MessageEditor {
|
|||
.read(cx)
|
||||
.project_path_for_absolute_path(&abs_path, cx)
|
||||
else {
|
||||
return;
|
||||
return Task::ready(());
|
||||
};
|
||||
let Some(entry) = self.project.read(cx).entry_for_path(&project_path, cx) else {
|
||||
return;
|
||||
return Task::ready(());
|
||||
};
|
||||
let Some(worktree) = self.project.read(cx).worktree_for_entry(entry.id, cx) else {
|
||||
return;
|
||||
return Task::ready(());
|
||||
};
|
||||
let project = self.project.clone();
|
||||
let task = cx.spawn(async move |_, cx| {
|
||||
|
@ -396,7 +396,9 @@ impl MessageEditor {
|
|||
})
|
||||
.shared();
|
||||
|
||||
self.mention_set.directories.insert(abs_path, task.clone());
|
||||
self.mention_set
|
||||
.directories
|
||||
.insert(abs_path.clone(), task.clone());
|
||||
|
||||
let editor = self.editor.clone();
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
|
@ -414,9 +416,12 @@ impl MessageEditor {
|
|||
editor.remove_creases([crease_id], cx);
|
||||
})
|
||||
.ok();
|
||||
this.update(cx, |this, _cx| {
|
||||
this.mention_set.directories.remove(&abs_path);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn confirm_mention_for_fetch(
|
||||
|
@ -426,13 +431,13 @@ impl MessageEditor {
|
|||
url: url::Url,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
) -> Task<()> {
|
||||
let Some(http_client) = self
|
||||
.workspace
|
||||
.update(cx, |workspace, _cx| workspace.client().http_client())
|
||||
.ok()
|
||||
else {
|
||||
return;
|
||||
return Task::ready(());
|
||||
};
|
||||
|
||||
let url_string = url.to_string();
|
||||
|
@ -450,9 +455,9 @@ impl MessageEditor {
|
|||
cx.spawn_in(window, async move |this, cx| {
|
||||
let fetch = fetch.await.notify_async_err(cx);
|
||||
this.update(cx, |this, cx| {
|
||||
let mention_uri = MentionUri::Fetch { url };
|
||||
if fetch.is_some() {
|
||||
this.mention_set.insert_uri(crease_id, mention_uri.clone());
|
||||
this.mention_set
|
||||
.insert_uri(crease_id, MentionUri::Fetch { url });
|
||||
} else {
|
||||
// Remove crease if we failed to fetch
|
||||
this.editor.update(cx, |editor, cx| {
|
||||
|
@ -461,11 +466,11 @@ impl MessageEditor {
|
|||
});
|
||||
editor.remove_creases([crease_id], cx);
|
||||
});
|
||||
this.mention_set.fetch_results.remove(&url);
|
||||
}
|
||||
})
|
||||
.ok();
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
pub fn confirm_mention_for_selection(
|
||||
|
@ -528,7 +533,7 @@ impl MessageEditor {
|
|||
name: String,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
) -> Task<()> {
|
||||
let uri = MentionUri::Thread {
|
||||
id: id.clone(),
|
||||
name,
|
||||
|
@ -546,7 +551,7 @@ impl MessageEditor {
|
|||
})
|
||||
.shared();
|
||||
|
||||
self.mention_set.insert_thread(id, task.clone());
|
||||
self.mention_set.insert_thread(id.clone(), task.clone());
|
||||
|
||||
let editor = self.editor.clone();
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
|
@ -564,9 +569,12 @@ impl MessageEditor {
|
|||
editor.remove_creases([crease_id], cx);
|
||||
})
|
||||
.ok();
|
||||
this.update(cx, |this, _| {
|
||||
this.mention_set.thread_summaries.remove(&id);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn confirm_mention_for_text_thread(
|
||||
|
@ -577,7 +585,7 @@ impl MessageEditor {
|
|||
name: String,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
) -> Task<()> {
|
||||
let uri = MentionUri::TextThread {
|
||||
path: path.clone(),
|
||||
name,
|
||||
|
@ -595,7 +603,8 @@ impl MessageEditor {
|
|||
})
|
||||
.shared();
|
||||
|
||||
self.mention_set.insert_text_thread(path, task.clone());
|
||||
self.mention_set
|
||||
.insert_text_thread(path.clone(), task.clone());
|
||||
|
||||
let editor = self.editor.clone();
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
|
@ -613,9 +622,12 @@ impl MessageEditor {
|
|||
editor.remove_creases([crease_id], cx);
|
||||
})
|
||||
.ok();
|
||||
this.update(cx, |this, _| {
|
||||
this.mention_set.text_thread_summaries.remove(&path);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
pub fn contents(
|
||||
|
@ -784,13 +796,15 @@ impl MessageEditor {
|
|||
) else {
|
||||
return;
|
||||
};
|
||||
self.confirm_mention_for_image(crease_id, anchor, None, task, window, cx);
|
||||
self.confirm_mention_for_image(crease_id, anchor, None, task, window, cx)
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_dragged_files(
|
||||
&self,
|
||||
&mut self,
|
||||
paths: Vec<project::ProjectPath>,
|
||||
added_worktrees: Vec<Entity<Worktree>>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
|
@ -798,6 +812,7 @@ impl MessageEditor {
|
|||
let Some(buffer) = buffer.read(cx).as_singleton() else {
|
||||
return;
|
||||
};
|
||||
let mut tasks = Vec::new();
|
||||
for path in paths {
|
||||
let Some(entry) = self.project.read(cx).entry_for_path(&path, cx) else {
|
||||
continue;
|
||||
|
@ -805,39 +820,44 @@ impl MessageEditor {
|
|||
let Some(abs_path) = self.project.read(cx).absolute_path(&path, cx) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let anchor = buffer.update(cx, |buffer, _cx| buffer.anchor_before(buffer.len()));
|
||||
let path_prefix = abs_path
|
||||
.file_name()
|
||||
.unwrap_or(path.path.as_os_str())
|
||||
.display()
|
||||
.to_string();
|
||||
let Some(completion) = ContextPickerCompletionProvider::completion_for_path(
|
||||
path,
|
||||
&path_prefix,
|
||||
false,
|
||||
entry.is_dir(),
|
||||
anchor..anchor,
|
||||
cx.weak_entity(),
|
||||
self.project.clone(),
|
||||
cx,
|
||||
) else {
|
||||
continue;
|
||||
let (file_name, _) =
|
||||
crate::context_picker::file_context_picker::extract_file_name_and_directory(
|
||||
&path.path,
|
||||
&path_prefix,
|
||||
);
|
||||
|
||||
let uri = if entry.is_dir() {
|
||||
MentionUri::Directory { abs_path }
|
||||
} else {
|
||||
MentionUri::File { abs_path }
|
||||
};
|
||||
|
||||
let new_text = format!("{} ", uri.as_link());
|
||||
let content_len = new_text.len() - 1;
|
||||
|
||||
let anchor = buffer.update(cx, |buffer, _cx| buffer.anchor_before(buffer.len()));
|
||||
|
||||
self.editor.update(cx, |message_editor, cx| {
|
||||
message_editor.edit(
|
||||
[(
|
||||
multi_buffer::Anchor::max()..multi_buffer::Anchor::max(),
|
||||
completion.new_text,
|
||||
new_text,
|
||||
)],
|
||||
cx,
|
||||
);
|
||||
});
|
||||
if let Some(confirm) = completion.confirm.clone() {
|
||||
confirm(CompletionIntent::Complete, window, cx);
|
||||
}
|
||||
tasks.push(self.confirm_completion(file_name, anchor, content_len, uri, window, cx));
|
||||
}
|
||||
cx.spawn(async move |_, _| {
|
||||
join_all(tasks).await;
|
||||
drop(added_worktrees);
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
pub fn set_read_only(&mut self, read_only: bool, cx: &mut Context<Self>) {
|
||||
|
@ -855,7 +875,7 @@ impl MessageEditor {
|
|||
image: Shared<Task<Result<Arc<Image>, String>>>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
) -> Task<()> {
|
||||
let editor = self.editor.clone();
|
||||
let task = cx
|
||||
.spawn_in(window, {
|
||||
|
@ -900,9 +920,12 @@ impl MessageEditor {
|
|||
editor.remove_creases([crease_id], cx);
|
||||
})
|
||||
.ok();
|
||||
this.update(cx, |this, _cx| {
|
||||
this.mention_set.images.remove(&crease_id);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
pub fn set_mode(&mut self, mode: EditorMode, cx: &mut Context<Self>) {
|
||||
|
|
|
@ -3429,8 +3429,7 @@ impl AcpThreadView {
|
|||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.message_editor.update(cx, |message_editor, cx| {
|
||||
message_editor.insert_dragged_files(paths, window, cx);
|
||||
drop(added_worktrees);
|
||||
message_editor.insert_dragged_files(paths, added_worktrees, window, cx);
|
||||
})
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue