tasks: Use icons instead of secondary text in a modal (#10264)
Before:  After:  Release Notes: - N/A
This commit is contained in:
parent
3e6a9f6890
commit
4f9ad300a7
4 changed files with 42 additions and 42 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -9496,6 +9496,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"editor",
|
"editor",
|
||||||
|
"file_icons",
|
||||||
"fuzzy",
|
"fuzzy",
|
||||||
"gpui",
|
"gpui",
|
||||||
"itertools 0.11.0",
|
"itertools 0.11.0",
|
||||||
|
|
|
@ -54,18 +54,20 @@ impl FileIcons {
|
||||||
let suffix = path.icon_stem_or_suffix()?;
|
let suffix = path.icon_stem_or_suffix()?;
|
||||||
|
|
||||||
if let Some(type_str) = this.stems.get(suffix) {
|
if let Some(type_str) = this.stems.get(suffix) {
|
||||||
return this
|
return this.get_type_icon(type_str);
|
||||||
.types
|
|
||||||
.get(type_str)
|
|
||||||
.map(|type_config| type_config.icon.clone());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.suffixes
|
this.suffixes
|
||||||
.get(suffix)
|
.get(suffix)
|
||||||
.and_then(|type_str| this.types.get(type_str))
|
.and_then(|type_str| this.get_type_icon(type_str))
|
||||||
.map(|type_config| type_config.icon.clone())
|
|
||||||
})
|
})
|
||||||
.or_else(|| this.types.get("default").map(|config| config.icon.clone()))
|
.or_else(|| this.get_type_icon("default"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_type_icon(&self, typ: &str) -> Option<Arc<str>> {
|
||||||
|
self.types
|
||||||
|
.get(typ)
|
||||||
|
.map(|type_config| type_config.icon.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_folder_icon(expanded: bool, cx: &AppContext) -> Option<Arc<str>> {
|
pub fn get_folder_icon(expanded: bool, cx: &AppContext) -> Option<Arc<str>> {
|
||||||
|
@ -77,9 +79,7 @@ impl FileIcons {
|
||||||
COLLAPSED_DIRECTORY_TYPE
|
COLLAPSED_DIRECTORY_TYPE
|
||||||
};
|
};
|
||||||
|
|
||||||
this.types
|
this.get_type_icon(key)
|
||||||
.get(key)
|
|
||||||
.map(|type_config| type_config.icon.clone())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_chevron_icon(expanded: bool, cx: &AppContext) -> Option<Arc<str>> {
|
pub fn get_chevron_icon(expanded: bool, cx: &AppContext) -> Option<Arc<str>> {
|
||||||
|
@ -91,8 +91,6 @@ impl FileIcons {
|
||||||
COLLAPSED_CHEVRON_TYPE
|
COLLAPSED_CHEVRON_TYPE
|
||||||
};
|
};
|
||||||
|
|
||||||
this.types
|
this.get_type_icon(key)
|
||||||
.get(key)
|
|
||||||
.map(|type_config| type_config.icon.clone())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ workspace = true
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
editor.workspace = true
|
editor.workspace = true
|
||||||
|
file_icons.workspace = true
|
||||||
fuzzy.workspace = true
|
fuzzy.workspace = true
|
||||||
gpui.workspace = true
|
gpui.workspace = true
|
||||||
picker.workspace = true
|
picker.workspace = true
|
||||||
|
@ -23,6 +24,7 @@ workspace.workspace = true
|
||||||
language.workspace = true
|
language.workspace = true
|
||||||
itertools.workspace = true
|
itertools.workspace = true
|
||||||
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
editor = { workspace = true, features = ["test-support"] }
|
editor = { workspace = true, features = ["test-support"] }
|
||||||
gpui = { workspace = true, features = ["test-support"] }
|
gpui = { workspace = true, features = ["test-support"] }
|
||||||
|
|
|
@ -3,22 +3,19 @@ use std::sync::Arc;
|
||||||
use crate::{active_item_selection_properties, schedule_task};
|
use crate::{active_item_selection_properties, schedule_task};
|
||||||
use fuzzy::{StringMatch, StringMatchCandidate};
|
use fuzzy::{StringMatch, StringMatchCandidate};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
impl_actions, rems, AppContext, DismissEvent, EventEmitter, FocusableView, InteractiveElement,
|
impl_actions, rems, AppContext, DismissEvent, EventEmitter, FocusableView, Global,
|
||||||
Model, ParentElement, Render, SharedString, Styled, Subscription, View, ViewContext,
|
InteractiveElement, Model, ParentElement, Render, SharedString, Styled, Subscription, View,
|
||||||
VisualContext, WeakView,
|
ViewContext, VisualContext, WeakView,
|
||||||
};
|
|
||||||
use picker::{
|
|
||||||
highlighted_match_with_paths::{HighlightedMatchWithPaths, HighlightedText},
|
|
||||||
Picker, PickerDelegate,
|
|
||||||
};
|
};
|
||||||
|
use picker::{highlighted_match_with_paths::HighlightedText, Picker, PickerDelegate};
|
||||||
use project::{Inventory, TaskSourceKind};
|
use project::{Inventory, TaskSourceKind};
|
||||||
use task::{oneshot_source::OneshotSource, Task, TaskContext};
|
use task::{oneshot_source::OneshotSource, Task, TaskContext};
|
||||||
use ui::{
|
use ui::{
|
||||||
div, v_flex, ButtonCommon, ButtonSize, Clickable, Color, FluentBuilder as _, IconButton,
|
div, v_flex, ButtonCommon, ButtonSize, Clickable, Color, FluentBuilder as _, Icon, IconButton,
|
||||||
IconButtonShape, IconName, IconSize, ListItem, ListItemSpacing, RenderOnce, Selectable,
|
IconButtonShape, IconName, IconSize, ListItem, ListItemSpacing, RenderOnce, Selectable,
|
||||||
Tooltip, WindowContext,
|
Tooltip, WindowContext,
|
||||||
};
|
};
|
||||||
use util::{paths::PathExt, ResultExt};
|
use util::ResultExt;
|
||||||
use workspace::{ModalView, Workspace};
|
use workspace::{ModalView, Workspace};
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -285,34 +282,31 @@ impl PickerDelegate for TasksModalDelegate {
|
||||||
cx: &mut ViewContext<picker::Picker<Self>>,
|
cx: &mut ViewContext<picker::Picker<Self>>,
|
||||||
) -> Option<Self::ListItem> {
|
) -> Option<Self::ListItem> {
|
||||||
let candidates = self.candidates.as_ref()?;
|
let candidates = self.candidates.as_ref()?;
|
||||||
let hit = &self.matches.get(ix)?;
|
let hit = &self.matches[ix];
|
||||||
let (source_kind, _) = &candidates.get(hit.candidate_id)?;
|
let (source_kind, _) = &candidates[hit.candidate_id];
|
||||||
let details = match source_kind {
|
let language_name = if let TaskSourceKind::Language { name } = source_kind {
|
||||||
TaskSourceKind::UserInput => "user input".to_string(),
|
Some(name)
|
||||||
TaskSourceKind::Language { name } => format!("{name} language"),
|
} else {
|
||||||
TaskSourceKind::Worktree { abs_path, .. } | TaskSourceKind::AbsPath(abs_path) => {
|
None
|
||||||
abs_path.compact().to_string_lossy().to_string()
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let highlighted_location = HighlightedMatchWithPaths {
|
let highlighted_location = HighlightedText {
|
||||||
match_label: HighlightedText {
|
text: hit.string.clone(),
|
||||||
text: hit.string.clone(),
|
highlight_positions: hit.positions.clone(),
|
||||||
highlight_positions: hit.positions.clone(),
|
char_count: hit.string.chars().count(),
|
||||||
char_count: hit.string.chars().count(),
|
|
||||||
},
|
|
||||||
paths: vec![HighlightedText {
|
|
||||||
char_count: details.chars().count(),
|
|
||||||
highlight_positions: Vec::new(),
|
|
||||||
text: details,
|
|
||||||
}],
|
|
||||||
};
|
};
|
||||||
|
let language_icon = language_name
|
||||||
|
.and_then(|language| {
|
||||||
|
let language = language.to_lowercase();
|
||||||
|
file_icons::FileIcons::get(cx).get_type_icon(&language)
|
||||||
|
})
|
||||||
|
.map(|icon_path| Icon::from_path(icon_path));
|
||||||
Some(
|
Some(
|
||||||
ListItem::new(SharedString::from(format!("tasks-modal-{ix}")))
|
ListItem::new(SharedString::from(format!("tasks-modal-{ix}")))
|
||||||
.inset(true)
|
.inset(true)
|
||||||
.spacing(ListItemSpacing::Sparse)
|
.spacing(ListItemSpacing::Sparse)
|
||||||
.map(|this| {
|
.map(|this| {
|
||||||
if matches!(source_kind, TaskSourceKind::UserInput) {
|
let this = if matches!(source_kind, TaskSourceKind::UserInput) {
|
||||||
let task_index = hit.candidate_id;
|
let task_index = hit.candidate_id;
|
||||||
let delete_button = div().child(
|
let delete_button = div().child(
|
||||||
IconButton::new("delete", IconName::Close)
|
IconButton::new("delete", IconName::Close)
|
||||||
|
@ -332,6 +326,11 @@ impl PickerDelegate for TasksModalDelegate {
|
||||||
this.end_hover_slot(delete_button)
|
this.end_hover_slot(delete_button)
|
||||||
} else {
|
} else {
|
||||||
this
|
this
|
||||||
|
};
|
||||||
|
if let Some(icon) = language_icon {
|
||||||
|
this.end_slot(icon)
|
||||||
|
} else {
|
||||||
|
this
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.selected(selected)
|
.selected(selected)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue