project panel: Persist full filename when renaming auto-folded entries (#19728)
This fixes a debug-only panic when processing filenames. The underflow that happens in Preview/Stable shouldn't cause any issues (other than maybe unmarking an entry in the project panel). /cc @notpeter Closes #ISSUE Release Notes: - N/A
This commit is contained in:
parent
0173479d18
commit
5769065f27
1 changed files with 51 additions and 14 deletions
|
@ -94,12 +94,18 @@ pub struct ProjectPanel {
|
||||||
struct EditState {
|
struct EditState {
|
||||||
worktree_id: WorktreeId,
|
worktree_id: WorktreeId,
|
||||||
entry_id: ProjectEntryId,
|
entry_id: ProjectEntryId,
|
||||||
is_new_entry: bool,
|
leaf_entry_id: Option<ProjectEntryId>,
|
||||||
is_dir: bool,
|
is_dir: bool,
|
||||||
depth: usize,
|
depth: usize,
|
||||||
processing_filename: Option<String>,
|
processing_filename: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl EditState {
|
||||||
|
fn is_new_entry(&self) -> bool {
|
||||||
|
self.leaf_entry_id.is_none()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
enum ClipboardEntry {
|
enum ClipboardEntry {
|
||||||
Copied(BTreeSet<SelectedEntry>),
|
Copied(BTreeSet<SelectedEntry>),
|
||||||
|
@ -824,10 +830,10 @@ impl ProjectPanel {
|
||||||
cx.focus(&self.focus_handle);
|
cx.focus(&self.focus_handle);
|
||||||
|
|
||||||
let worktree_id = edit_state.worktree_id;
|
let worktree_id = edit_state.worktree_id;
|
||||||
let is_new_entry = edit_state.is_new_entry;
|
let is_new_entry = edit_state.is_new_entry();
|
||||||
let filename = self.filename_editor.read(cx).text(cx);
|
let filename = self.filename_editor.read(cx).text(cx);
|
||||||
edit_state.is_dir = edit_state.is_dir
|
edit_state.is_dir = edit_state.is_dir
|
||||||
|| (edit_state.is_new_entry && filename.ends_with(std::path::MAIN_SEPARATOR));
|
|| (edit_state.is_new_entry() && filename.ends_with(std::path::MAIN_SEPARATOR));
|
||||||
let is_dir = edit_state.is_dir;
|
let is_dir = edit_state.is_dir;
|
||||||
let worktree = self.project.read(cx).worktree_for_id(worktree_id, cx)?;
|
let worktree = self.project.read(cx).worktree_for_id(worktree_id, cx)?;
|
||||||
let entry = worktree.read(cx).entry_for_id(edit_state.entry_id)?.clone();
|
let entry = worktree.read(cx).entry_for_id(edit_state.entry_id)?.clone();
|
||||||
|
@ -858,7 +864,6 @@ impl ProjectPanel {
|
||||||
if path_already_exists(new_path.as_path()) {
|
if path_already_exists(new_path.as_path()) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
edited_entry_id = entry.id;
|
edited_entry_id = entry.id;
|
||||||
edit_task = self.project.update(cx, |project, cx| {
|
edit_task = self.project.update(cx, |project, cx| {
|
||||||
project.rename_entry(entry.id, new_path.as_path(), cx)
|
project.rename_entry(entry.id, new_path.as_path(), cx)
|
||||||
|
@ -1013,7 +1018,7 @@ impl ProjectPanel {
|
||||||
self.edit_state = Some(EditState {
|
self.edit_state = Some(EditState {
|
||||||
worktree_id,
|
worktree_id,
|
||||||
entry_id: directory_id,
|
entry_id: directory_id,
|
||||||
is_new_entry: true,
|
leaf_entry_id: None,
|
||||||
is_dir,
|
is_dir,
|
||||||
processing_filename: None,
|
processing_filename: None,
|
||||||
depth: 0,
|
depth: 0,
|
||||||
|
@ -1047,12 +1052,12 @@ impl ProjectPanel {
|
||||||
}) = self.selection
|
}) = self.selection
|
||||||
{
|
{
|
||||||
if let Some(worktree) = self.project.read(cx).worktree_for_id(worktree_id, cx) {
|
if let Some(worktree) = self.project.read(cx).worktree_for_id(worktree_id, cx) {
|
||||||
let entry_id = self.unflatten_entry_id(entry_id);
|
let sub_entry_id = self.unflatten_entry_id(entry_id);
|
||||||
if let Some(entry) = worktree.read(cx).entry_for_id(entry_id) {
|
if let Some(entry) = worktree.read(cx).entry_for_id(sub_entry_id) {
|
||||||
self.edit_state = Some(EditState {
|
self.edit_state = Some(EditState {
|
||||||
worktree_id,
|
worktree_id,
|
||||||
entry_id,
|
entry_id: sub_entry_id,
|
||||||
is_new_entry: false,
|
leaf_entry_id: Some(entry_id),
|
||||||
is_dir: entry.is_dir(),
|
is_dir: entry.is_dir(),
|
||||||
processing_filename: None,
|
processing_filename: None,
|
||||||
depth: 0,
|
depth: 0,
|
||||||
|
@ -1835,7 +1840,7 @@ impl ProjectPanel {
|
||||||
let mut new_entry_parent_id = None;
|
let mut new_entry_parent_id = None;
|
||||||
let mut new_entry_kind = EntryKind::Dir;
|
let mut new_entry_kind = EntryKind::Dir;
|
||||||
if let Some(edit_state) = &self.edit_state {
|
if let Some(edit_state) = &self.edit_state {
|
||||||
if edit_state.worktree_id == worktree_id && edit_state.is_new_entry {
|
if edit_state.worktree_id == worktree_id && edit_state.is_new_entry() {
|
||||||
new_entry_parent_id = Some(edit_state.entry_id);
|
new_entry_parent_id = Some(edit_state.entry_id);
|
||||||
new_entry_kind = if edit_state.is_dir {
|
new_entry_kind = if edit_state.is_dir {
|
||||||
EntryKind::Dir
|
EntryKind::Dir
|
||||||
|
@ -2351,7 +2356,7 @@ impl ProjectPanel {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(edit_state) = &self.edit_state {
|
if let Some(edit_state) = &self.edit_state {
|
||||||
let is_edited_entry = if edit_state.is_new_entry {
|
let is_edited_entry = if edit_state.is_new_entry() {
|
||||||
entry.id == NEW_ENTRY_ID
|
entry.id == NEW_ENTRY_ID
|
||||||
} else {
|
} else {
|
||||||
entry.id == edit_state.entry_id
|
entry.id == edit_state.entry_id
|
||||||
|
@ -2369,10 +2374,41 @@ impl ProjectPanel {
|
||||||
if is_edited_entry {
|
if is_edited_entry {
|
||||||
if let Some(processing_filename) = &edit_state.processing_filename {
|
if let Some(processing_filename) = &edit_state.processing_filename {
|
||||||
details.is_processing = true;
|
details.is_processing = true;
|
||||||
details.filename.clear();
|
if let Some(ancestors) = edit_state
|
||||||
details.filename.push_str(processing_filename);
|
.leaf_entry_id
|
||||||
|
.and_then(|entry| self.ancestors.get(&entry))
|
||||||
|
{
|
||||||
|
let position = ancestors.ancestors.iter().position(|entry_id| *entry_id == edit_state.entry_id).expect("Edited sub-entry should be an ancestor of selected leaf entry") + 1;
|
||||||
|
let all_components = ancestors.ancestors.len();
|
||||||
|
|
||||||
|
let prefix_components = all_components - position;
|
||||||
|
let suffix_components = position.checked_sub(1);
|
||||||
|
let mut previous_components =
|
||||||
|
Path::new(&details.filename).components();
|
||||||
|
let mut new_path = previous_components
|
||||||
|
.by_ref()
|
||||||
|
.take(prefix_components)
|
||||||
|
.collect::<PathBuf>();
|
||||||
|
if let Some(last_component) =
|
||||||
|
Path::new(processing_filename).components().last()
|
||||||
|
{
|
||||||
|
new_path.push(last_component);
|
||||||
|
previous_components.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(_) = suffix_components {
|
||||||
|
new_path.push(previous_components);
|
||||||
|
}
|
||||||
|
if let Some(str) = new_path.to_str() {
|
||||||
|
details.filename.clear();
|
||||||
|
details.filename.push_str(str);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
details.filename.clear();
|
||||||
|
details.filename.push_str(processing_filename);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if edit_state.is_new_entry {
|
if edit_state.is_new_entry() {
|
||||||
details.filename.clear();
|
details.filename.clear();
|
||||||
}
|
}
|
||||||
details.is_editing = true;
|
details.is_editing = true;
|
||||||
|
@ -2571,6 +2607,7 @@ impl ProjectPanel {
|
||||||
comp_str
|
comp_str
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let components_len = components.len();
|
let components_len = components.len();
|
||||||
let active_index = components_len
|
let active_index = components_len
|
||||||
- 1
|
- 1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue