mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-08 07:35:01 +03:00
Add icon and hover description for symlinks (#12263)
![image](https://github.com/zed-industries/zed/assets/12102857/c6ed8140-1256-4618-aa46-64e66becdf7e) ![Screenshot_20240524_201346](https://github.com/zed-industries/zed/assets/12102857/2577067c-4f61-486a-8613-14941555f5a8) Resolves https://github.com/zed-industries/zed/issues/12142 Release Notes: - Added in project panel an icon and hover description for symlinks ([12142](https://github.com/zed-industries/zed/issues/12142))
This commit is contained in:
parent
f7115be3d1
commit
a03813a471
@ -29,7 +29,7 @@ use std::{
|
|||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use theme::ThemeSettings;
|
use theme::ThemeSettings;
|
||||||
use ui::{prelude::*, v_flex, ContextMenu, Icon, KeyBinding, Label, ListItem};
|
use ui::{prelude::*, v_flex, ContextMenu, Icon, KeyBinding, Label, ListItem, Tooltip};
|
||||||
use unicase::UniCase;
|
use unicase::UniCase;
|
||||||
use util::{maybe, NumericPrefixWithSuffix, ResultExt, TryFutureExt};
|
use util::{maybe, NumericPrefixWithSuffix, ResultExt, TryFutureExt};
|
||||||
use workspace::{
|
use workspace::{
|
||||||
@ -103,6 +103,7 @@ pub struct EntryDetails {
|
|||||||
is_cut: bool,
|
is_cut: bool,
|
||||||
git_status: Option<GitFileStatus>,
|
git_status: Option<GitFileStatus>,
|
||||||
is_private: bool,
|
is_private: bool,
|
||||||
|
canonical_path: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Default, Debug, Deserialize)]
|
#[derive(PartialEq, Clone, Default, Debug, Deserialize)]
|
||||||
@ -1444,11 +1445,12 @@ impl ProjectPanel {
|
|||||||
path: entry.path.join("\0").into(),
|
path: entry.path.join("\0").into(),
|
||||||
inode: 0,
|
inode: 0,
|
||||||
mtime: entry.mtime,
|
mtime: entry.mtime,
|
||||||
is_symlink: false,
|
|
||||||
is_ignored: entry.is_ignored,
|
is_ignored: entry.is_ignored,
|
||||||
is_external: false,
|
is_external: false,
|
||||||
is_private: false,
|
is_private: false,
|
||||||
git_status: entry.git_status,
|
git_status: entry.git_status,
|
||||||
|
canonical_path: entry.canonical_path.clone(),
|
||||||
|
is_symlink: entry.is_symlink,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if expanded_dir_ids.binary_search(&entry.id).is_err()
|
if expanded_dir_ids.binary_search(&entry.id).is_err()
|
||||||
@ -1646,6 +1648,7 @@ impl ProjectPanel {
|
|||||||
.map_or(false, |e| e.is_cut() && e.entry_id() == entry.id),
|
.map_or(false, |e| e.is_cut() && e.entry_id() == entry.id),
|
||||||
git_status: status,
|
git_status: status,
|
||||||
is_private: entry.is_private,
|
is_private: entry.is_private,
|
||||||
|
canonical_path: entry.canonical_path.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(edit_state) = &self.edit_state {
|
if let Some(edit_state) = &self.edit_state {
|
||||||
@ -1738,6 +1741,12 @@ impl ProjectPanel {
|
|||||||
icon = FileIcons::get_icon(Path::new(&filename), cx);
|
icon = FileIcons::get_icon(Path::new(&filename), cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let canonical_path = details
|
||||||
|
.canonical_path
|
||||||
|
.as_ref()
|
||||||
|
.map(|f| f.to_string_lossy().to_string());
|
||||||
|
|
||||||
let depth = details.depth;
|
let depth = details.depth;
|
||||||
div()
|
div()
|
||||||
.id(entry_id.to_proto() as usize)
|
.id(entry_id.to_proto() as usize)
|
||||||
@ -1759,6 +1768,14 @@ impl ProjectPanel {
|
|||||||
.indent_level(depth)
|
.indent_level(depth)
|
||||||
.indent_step_size(px(settings.indent_size))
|
.indent_step_size(px(settings.indent_size))
|
||||||
.selected(is_selected)
|
.selected(is_selected)
|
||||||
|
.when_some(canonical_path, |this, path| {
|
||||||
|
this.end_slot::<Icon>(
|
||||||
|
Icon::new(IconName::ArrowUpRight)
|
||||||
|
.size(IconSize::Indicator)
|
||||||
|
.color(filename_text_color),
|
||||||
|
)
|
||||||
|
.tooltip(move |cx| Tooltip::text(format!("{path} • Symbolic Link"), cx))
|
||||||
|
})
|
||||||
.child(if let Some(icon) = &icon {
|
.child(if let Some(icon) = &icon {
|
||||||
h_flex().child(Icon::from_path(icon.to_string()).color(filename_text_color))
|
h_flex().child(Icon::from_path(icon.to_string()).color(filename_text_color))
|
||||||
} else {
|
} else {
|
||||||
|
@ -471,6 +471,7 @@ impl Worktree {
|
|||||||
&metadata,
|
&metadata,
|
||||||
&next_entry_id,
|
&next_entry_id,
|
||||||
snapshot.root_char_bag,
|
snapshot.root_char_bag,
|
||||||
|
None
|
||||||
),
|
),
|
||||||
fs.as_ref(),
|
fs.as_ref(),
|
||||||
);
|
);
|
||||||
@ -3060,8 +3061,9 @@ pub struct Entry {
|
|||||||
pub path: Arc<Path>,
|
pub path: Arc<Path>,
|
||||||
pub inode: u64,
|
pub inode: u64,
|
||||||
pub mtime: Option<SystemTime>,
|
pub mtime: Option<SystemTime>,
|
||||||
pub is_symlink: bool,
|
|
||||||
|
|
||||||
|
pub canonical_path: Option<PathBuf>,
|
||||||
|
pub is_symlink: bool,
|
||||||
/// Whether this entry is ignored by Git.
|
/// Whether this entry is ignored by Git.
|
||||||
///
|
///
|
||||||
/// We only scan ignored entries once the directory is expanded and
|
/// We only scan ignored entries once the directory is expanded and
|
||||||
@ -3119,6 +3121,7 @@ impl Entry {
|
|||||||
metadata: &fs::Metadata,
|
metadata: &fs::Metadata,
|
||||||
next_entry_id: &AtomicUsize,
|
next_entry_id: &AtomicUsize,
|
||||||
root_char_bag: CharBag,
|
root_char_bag: CharBag,
|
||||||
|
canonical_path: Option<PathBuf>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: ProjectEntryId::new(next_entry_id),
|
id: ProjectEntryId::new(next_entry_id),
|
||||||
@ -3130,6 +3133,7 @@ impl Entry {
|
|||||||
path,
|
path,
|
||||||
inode: metadata.inode,
|
inode: metadata.inode,
|
||||||
mtime: Some(metadata.mtime),
|
mtime: Some(metadata.mtime),
|
||||||
|
canonical_path,
|
||||||
is_symlink: metadata.is_symlink,
|
is_symlink: metadata.is_symlink,
|
||||||
is_ignored: false,
|
is_ignored: false,
|
||||||
is_external: false,
|
is_external: false,
|
||||||
@ -3861,6 +3865,7 @@ impl BackgroundScanner {
|
|||||||
&child_metadata,
|
&child_metadata,
|
||||||
&next_entry_id,
|
&next_entry_id,
|
||||||
root_char_bag,
|
root_char_bag,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
if job.is_external {
|
if job.is_external {
|
||||||
@ -3894,6 +3899,8 @@ impl BackgroundScanner {
|
|||||||
if !canonical_path.starts_with(root_canonical_path) {
|
if !canonical_path.starts_with(root_canonical_path) {
|
||||||
child_entry.is_external = true;
|
child_entry.is_external = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
child_entry.canonical_path = Some(canonical_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if child_entry.is_dir() {
|
if child_entry.is_dir() {
|
||||||
@ -4049,7 +4056,13 @@ impl BackgroundScanner {
|
|||||||
metadata,
|
metadata,
|
||||||
self.next_entry_id.as_ref(),
|
self.next_entry_id.as_ref(),
|
||||||
state.snapshot.root_char_bag,
|
state.snapshot.root_char_bag,
|
||||||
|
if metadata.is_symlink {
|
||||||
|
Some(canonical_path.to_path_buf())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let is_dir = fs_entry.is_dir();
|
let is_dir = fs_entry.is_dir();
|
||||||
fs_entry.is_ignored = ignore_stack.is_abs_path_ignored(&abs_path, is_dir);
|
fs_entry.is_ignored = ignore_stack.is_abs_path_ignored(&abs_path, is_dir);
|
||||||
fs_entry.is_external = !canonical_path.starts_with(&root_canonical_path);
|
fs_entry.is_external = !canonical_path.starts_with(&root_canonical_path);
|
||||||
@ -5048,11 +5061,12 @@ impl<'a> TryFrom<(&'a CharBag, proto::Entry)> for Entry {
|
|||||||
path,
|
path,
|
||||||
inode: entry.inode,
|
inode: entry.inode,
|
||||||
mtime: entry.mtime.map(|time| time.into()),
|
mtime: entry.mtime.map(|time| time.into()),
|
||||||
is_symlink: entry.is_symlink,
|
canonical_path: None,
|
||||||
is_ignored: entry.is_ignored,
|
is_ignored: entry.is_ignored,
|
||||||
is_external: entry.is_external,
|
is_external: entry.is_external,
|
||||||
git_status: git_status_from_proto(entry.git_status),
|
git_status: git_status_from_proto(entry.git_status),
|
||||||
is_private: false,
|
is_private: false,
|
||||||
|
is_symlink: entry.is_symlink,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user