Project dropdown menu
This commit is contained in:
parent
d000ea9739
commit
888d3b3fd6
5 changed files with 95 additions and 10 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1415,6 +1415,7 @@ dependencies = [
|
||||||
"picker",
|
"picker",
|
||||||
"postage",
|
"postage",
|
||||||
"project",
|
"project",
|
||||||
|
"recent_projects",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"settings",
|
"settings",
|
||||||
|
@ -5376,6 +5377,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"db",
|
"db",
|
||||||
"editor",
|
"editor",
|
||||||
|
"futures 0.3.28",
|
||||||
"fuzzy",
|
"fuzzy",
|
||||||
"gpui",
|
"gpui",
|
||||||
"language",
|
"language",
|
||||||
|
|
|
@ -35,6 +35,7 @@ gpui = { path = "../gpui" }
|
||||||
menu = { path = "../menu" }
|
menu = { path = "../menu" }
|
||||||
picker = { path = "../picker" }
|
picker = { path = "../picker" }
|
||||||
project = { path = "../project" }
|
project = { path = "../project" }
|
||||||
|
recent_projects = {path = "../recent_projects"}
|
||||||
settings = { path = "../settings" }
|
settings = { path = "../settings" }
|
||||||
theme = { path = "../theme" }
|
theme = { path = "../theme" }
|
||||||
theme_selector = { path = "../theme_selector" }
|
theme_selector = { path = "../theme_selector" }
|
||||||
|
@ -42,6 +43,7 @@ util = { path = "../util" }
|
||||||
workspace = { path = "../workspace" }
|
workspace = { path = "../workspace" }
|
||||||
zed-actions = {path = "../zed-actions"}
|
zed-actions = {path = "../zed-actions"}
|
||||||
|
|
||||||
|
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
|
|
|
@ -23,6 +23,7 @@ use gpui::{
|
||||||
};
|
};
|
||||||
use picker::PickerEvent;
|
use picker::PickerEvent;
|
||||||
use project::{Project, RepositoryEntry};
|
use project::{Project, RepositoryEntry};
|
||||||
|
use recent_projects::{build_recent_projects, RecentProjects};
|
||||||
use std::{ops::Range, sync::Arc};
|
use std::{ops::Range, sync::Arc};
|
||||||
use theme::{AvatarStyle, Theme};
|
use theme::{AvatarStyle, Theme};
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
|
@ -37,6 +38,7 @@ actions!(
|
||||||
ToggleContactsMenu,
|
ToggleContactsMenu,
|
||||||
ToggleUserMenu,
|
ToggleUserMenu,
|
||||||
ToggleVcsMenu,
|
ToggleVcsMenu,
|
||||||
|
ToggleProjectMenu,
|
||||||
SwitchBranch,
|
SwitchBranch,
|
||||||
ShareProject,
|
ShareProject,
|
||||||
UnshareProject,
|
UnshareProject,
|
||||||
|
@ -49,6 +51,7 @@ pub fn init(cx: &mut AppContext) {
|
||||||
cx.add_action(CollabTitlebarItem::unshare_project);
|
cx.add_action(CollabTitlebarItem::unshare_project);
|
||||||
cx.add_action(CollabTitlebarItem::toggle_user_menu);
|
cx.add_action(CollabTitlebarItem::toggle_user_menu);
|
||||||
cx.add_action(CollabTitlebarItem::toggle_vcs_menu);
|
cx.add_action(CollabTitlebarItem::toggle_vcs_menu);
|
||||||
|
cx.add_action(CollabTitlebarItem::toggle_project_menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CollabTitlebarItem {
|
pub struct CollabTitlebarItem {
|
||||||
|
@ -58,6 +61,7 @@ pub struct CollabTitlebarItem {
|
||||||
workspace: WeakViewHandle<Workspace>,
|
workspace: WeakViewHandle<Workspace>,
|
||||||
contacts_popover: Option<ViewHandle<ContactsPopover>>,
|
contacts_popover: Option<ViewHandle<ContactsPopover>>,
|
||||||
branch_popover: Option<ViewHandle<BranchList>>,
|
branch_popover: Option<ViewHandle<BranchList>>,
|
||||||
|
project_popover: Option<ViewHandle<recent_projects::RecentProjects>>,
|
||||||
user_menu: ViewHandle<ContextMenu>,
|
user_menu: ViewHandle<ContextMenu>,
|
||||||
_subscriptions: Vec<Subscription>,
|
_subscriptions: Vec<Subscription>,
|
||||||
}
|
}
|
||||||
|
@ -191,6 +195,7 @@ impl CollabTitlebarItem {
|
||||||
menu
|
menu
|
||||||
}),
|
}),
|
||||||
branch_popover: None,
|
branch_popover: None,
|
||||||
|
project_popover: None,
|
||||||
_subscriptions: subscriptions,
|
_subscriptions: subscriptions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -233,14 +238,22 @@ impl CollabTitlebarItem {
|
||||||
};
|
};
|
||||||
let highlights = (0..name.len()).into_iter().collect();
|
let highlights = (0..name.len()).into_iter().collect();
|
||||||
let mut ret = Flex::row().with_child(
|
let mut ret = Flex::row().with_child(
|
||||||
Stack::new().with_child(
|
Stack::new()
|
||||||
Label::new(name, style.clone())
|
.with_child(
|
||||||
.with_highlights(highlights)
|
MouseEventHandler::<ToggleProjectMenu, Self>::new(0, cx, |_, _| {
|
||||||
.contained()
|
Label::new(name, style.clone())
|
||||||
.aligned()
|
.with_highlights(highlights)
|
||||||
.left()
|
.contained()
|
||||||
.into_any_named("title-project-name"),
|
.aligned()
|
||||||
),
|
.left()
|
||||||
|
.into_any_named("title-project-name")
|
||||||
|
})
|
||||||
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
|
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||||
|
this.toggle_project_menu(&Default::default(), cx)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.with_children(self.render_project_popover_host(&theme.titlebar, cx)),
|
||||||
);
|
);
|
||||||
if let Some(git_branch) = branch_prepended {
|
if let Some(git_branch) = branch_prepended {
|
||||||
ret = ret.with_child(
|
ret = ret.with_child(
|
||||||
|
@ -382,6 +395,36 @@ impl CollabTitlebarItem {
|
||||||
.into_any()
|
.into_any()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
fn render_project_popover_host<'a>(
|
||||||
|
&'a self,
|
||||||
|
_theme: &'a theme::Titlebar,
|
||||||
|
cx: &'a mut ViewContext<Self>,
|
||||||
|
) -> Option<AnyElement<Self>> {
|
||||||
|
self.project_popover.as_ref().map(|child| {
|
||||||
|
let theme = theme::current(cx).clone();
|
||||||
|
let child = ChildView::new(child, cx);
|
||||||
|
let child = MouseEventHandler::<RecentProjects, Self>::new(0, cx, |_, _| {
|
||||||
|
Flex::column()
|
||||||
|
.with_child(child.flex(1., true))
|
||||||
|
.contained()
|
||||||
|
.constrained()
|
||||||
|
.with_width(theme.contacts_popover.width)
|
||||||
|
.with_height(theme.contacts_popover.height)
|
||||||
|
})
|
||||||
|
.on_click(MouseButton::Left, |_, _, _| {})
|
||||||
|
.on_down_out(MouseButton::Left, move |_, _, cx| cx.emit(()))
|
||||||
|
.into_any();
|
||||||
|
|
||||||
|
Overlay::new(child)
|
||||||
|
.with_fit_mode(OverlayFitMode::SwitchAnchor)
|
||||||
|
.with_anchor_corner(AnchorCorner::TopLeft)
|
||||||
|
.with_z_index(999)
|
||||||
|
.aligned()
|
||||||
|
.bottom()
|
||||||
|
.left()
|
||||||
|
.into_any()
|
||||||
|
})
|
||||||
|
}
|
||||||
pub fn toggle_vcs_menu(&mut self, _: &ToggleVcsMenu, cx: &mut ViewContext<Self>) {
|
pub fn toggle_vcs_menu(&mut self, _: &ToggleVcsMenu, cx: &mut ViewContext<Self>) {
|
||||||
if self.branch_popover.take().is_none() {
|
if self.branch_popover.take().is_none() {
|
||||||
if let Some(workspace) = self.workspace.upgrade(cx) {
|
if let Some(workspace) = self.workspace.upgrade(cx) {
|
||||||
|
@ -402,6 +445,26 @@ impl CollabTitlebarItem {
|
||||||
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn toggle_project_menu(&mut self, _: &ToggleProjectMenu, cx: &mut ViewContext<Self>) {
|
||||||
|
log::error!("Toggling project menu");
|
||||||
|
if self.project_popover.take().is_none() {
|
||||||
|
let view = cx.add_view(|cx| build_recent_projects(self.workspace.clone(), cx));
|
||||||
|
cx.subscribe(&view, |this, _, event, cx| {
|
||||||
|
match event {
|
||||||
|
PickerEvent::Dismiss => {
|
||||||
|
this.project_popover = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cx.notify();
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
self.project_popover = Some(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
fn render_toggle_contacts_button(
|
fn render_toggle_contacts_button(
|
||||||
&self,
|
&self,
|
||||||
theme: &Theme,
|
theme: &Theme,
|
||||||
|
|
|
@ -21,6 +21,7 @@ util = { path = "../util"}
|
||||||
theme = { path = "../theme" }
|
theme = { path = "../theme" }
|
||||||
workspace = { path = "../workspace" }
|
workspace = { path = "../workspace" }
|
||||||
|
|
||||||
|
futures.workspace = true
|
||||||
ordered-float.workspace = true
|
ordered-float.workspace = true
|
||||||
postage.workspace = true
|
postage.workspace = true
|
||||||
smol.workspace = true
|
smol.workspace = true
|
||||||
|
|
|
@ -64,9 +64,26 @@ fn toggle(
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
type RecentProjects = Picker<RecentProjectsDelegate>;
|
pub fn build_recent_projects(
|
||||||
|
workspace: WeakViewHandle<Workspace>,
|
||||||
|
cx: &mut ViewContext<RecentProjects>,
|
||||||
|
) -> RecentProjects {
|
||||||
|
let workspaces = futures::executor::block_on(async {
|
||||||
|
WORKSPACE_DB
|
||||||
|
.recent_workspaces_on_disk()
|
||||||
|
.await
|
||||||
|
.unwrap_or_default()
|
||||||
|
.into_iter()
|
||||||
|
.map(|(_, location)| location)
|
||||||
|
.collect()
|
||||||
|
});
|
||||||
|
Picker::new(RecentProjectsDelegate::new(workspace, workspaces), cx)
|
||||||
|
.with_theme(|theme| theme.picker.clone())
|
||||||
|
}
|
||||||
|
|
||||||
struct RecentProjectsDelegate {
|
pub type RecentProjects = Picker<RecentProjectsDelegate>;
|
||||||
|
|
||||||
|
pub struct RecentProjectsDelegate {
|
||||||
workspace: WeakViewHandle<Workspace>,
|
workspace: WeakViewHandle<Workspace>,
|
||||||
workspace_locations: Vec<WorkspaceLocation>,
|
workspace_locations: Vec<WorkspaceLocation>,
|
||||||
selected_match_index: usize,
|
selected_match_index: usize,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue