wip: refactor
This commit is contained in:
BIN
assets/brand/coop-dark.png
Normal file
BIN
assets/brand/coop-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
BIN
assets/brand/coop-light.png
Normal file
BIN
assets/brand/coop-light.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
3
assets/icons/group.svg
Normal file
3
assets/icons/group.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
||||||
|
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M17.75 19.25h2.596c1.163 0 2.106-1.001 1.788-2.12-.733-2.573-2.465-4.38-5.134-4.38-.446 0-.866.05-1.26.147M11.25 7a3.25 3.25 0 1 1-6.5 0 3.25 3.25 0 0 1 6.5 0Zm8.5.5a2.75 2.75 0 1 1-5.5 0 2.75 2.75 0 0 1 5.5 0ZM2.08 18.126c.78-3.14 2.78-5.376 5.92-5.376s5.14 2.237 5.918 5.376c.28 1.128-.658 2.124-1.82 2.124H3.901c-1.162 0-2.1-.996-1.82-2.124Z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 550 B |
@@ -1,5 +1,6 @@
|
|||||||
use coop_ui::{
|
use coop_ui::{
|
||||||
button::{Button, ButtonVariants},
|
button::{Button, ButtonVariants},
|
||||||
|
popup_menu::PopupMenuExt,
|
||||||
Icon, IconName, Sizable,
|
Icon, IconName, Sizable,
|
||||||
};
|
};
|
||||||
use gpui::*;
|
use gpui::*;
|
||||||
@@ -12,6 +13,8 @@ use crate::{
|
|||||||
states::{metadata::MetadataRegistry, signal::SignalRegistry},
|
states::{metadata::MetadataRegistry, signal::SignalRegistry},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
actions!(account, [ToDo]);
|
||||||
|
|
||||||
pub struct Account {
|
pub struct Account {
|
||||||
public_key: PublicKey,
|
public_key: PublicKey,
|
||||||
metadata: Model<Option<Metadata>>,
|
metadata: Model<Option<Metadata>>,
|
||||||
@@ -83,5 +86,12 @@ impl Render for Account {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
.popup_menu(move |this, _cx| {
|
||||||
|
this.menu("Profile", Box::new(ToDo))
|
||||||
|
.menu("Contacts", Box::new(ToDo))
|
||||||
|
.menu("Settings", Box::new(ToDo))
|
||||||
|
.separator()
|
||||||
|
.menu("Change account", Box::new(ToDo))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
use coop_ui::{
|
use coop_ui::{
|
||||||
button::{Button, ButtonCustomVariant, ButtonRounded, ButtonVariants},
|
|
||||||
dock::{DockArea, DockItem, DockPlacement},
|
dock::{DockArea, DockItem, DockPlacement},
|
||||||
theme::{ActiveTheme, Theme, ThemeMode},
|
theme::Theme,
|
||||||
ContextModal, IconName, Root, Sizable, TitleBar,
|
Root, TitleBar,
|
||||||
};
|
};
|
||||||
use gpui::*;
|
use gpui::*;
|
||||||
use prelude::FluentBuilder;
|
use prelude::FluentBuilder;
|
||||||
@@ -11,14 +10,20 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
account::Account,
|
account::Account,
|
||||||
dock::{chat::ChatPanel, left_dock::LeftDock, welcome::WelcomePanel},
|
dock::{chat::ChatPanel, contact::ContactPanel, left_dock::LeftDock, welcome::WelcomePanel},
|
||||||
onboarding::Onboarding,
|
onboarding::Onboarding,
|
||||||
};
|
};
|
||||||
use crate::states::{account::AccountRegistry, chat::Room};
|
use crate::states::{account::AccountRegistry, chat::Room};
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Deserialize)]
|
||||||
|
pub enum PanelKind {
|
||||||
|
Room(Arc<Room>),
|
||||||
|
Contact,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Deserialize)]
|
#[derive(Clone, PartialEq, Eq, Deserialize)]
|
||||||
pub struct AddPanel {
|
pub struct AddPanel {
|
||||||
pub room: Arc<Room>,
|
pub panel: PanelKind,
|
||||||
pub position: DockPlacement,
|
pub position: DockPlacement,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,19 +85,6 @@ impl AppView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_theme_mode(&mut self, _: &ClickEvent, cx: &mut ViewContext<Self>) {
|
|
||||||
let mode = match cx.theme().mode.is_dark() {
|
|
||||||
true => ThemeMode::Light,
|
|
||||||
false => ThemeMode::Dark,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Change theme
|
|
||||||
Theme::change(mode, cx);
|
|
||||||
|
|
||||||
// Rerender
|
|
||||||
cx.refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init_layout(dock_area: WeakView<DockArea>, cx: &mut WindowContext) {
|
fn init_layout(dock_area: WeakView<DockArea>, cx: &mut WindowContext) {
|
||||||
let left = DockItem::panel(Arc::new(LeftDock::new(cx)));
|
let left = DockItem::panel(Arc::new(LeftDock::new(cx)));
|
||||||
let center = Self::init_dock_items(&dock_area, cx);
|
let center = Self::init_dock_items(&dock_area, cx);
|
||||||
@@ -129,11 +121,22 @@ impl AppView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn on_action_add_panel(&mut self, action: &AddPanel, cx: &mut ViewContext<Self>) {
|
fn on_action_add_panel(&mut self, action: &AddPanel, cx: &mut ViewContext<Self>) {
|
||||||
let chat_panel = Arc::new(ChatPanel::new(&action.room, cx));
|
match &action.panel {
|
||||||
|
PanelKind::Room(room) => {
|
||||||
|
let panel = Arc::new(ChatPanel::new(room, cx));
|
||||||
|
|
||||||
self.dock.update(cx, |dock_area, cx| {
|
self.dock.update(cx, |dock_area, cx| {
|
||||||
dock_area.add_panel(chat_panel, action.position, cx);
|
dock_area.add_panel(panel, action.position, cx);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
PanelKind::Contact => {
|
||||||
|
let panel = Arc::new(ContactPanel::new(cx));
|
||||||
|
|
||||||
|
self.dock.update(cx, |dock_area, cx| {
|
||||||
|
dock_area.add_panel(panel, action.position, cx);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,59 +152,18 @@ impl Render for AppView {
|
|||||||
.child(
|
.child(
|
||||||
TitleBar::new()
|
TitleBar::new()
|
||||||
// Left side
|
// Left side
|
||||||
.child(
|
.child(div())
|
||||||
div()
|
|
||||||
.flex()
|
|
||||||
.items_center()
|
|
||||||
.gap_2()
|
|
||||||
.child(
|
|
||||||
div().when_some(
|
|
||||||
self.account.read(cx).as_ref(),
|
|
||||||
|this, account| this.child(account.clone()),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.child(
|
|
||||||
Button::new("new")
|
|
||||||
.custom(
|
|
||||||
ButtonCustomVariant::new(cx)
|
|
||||||
.shadow(false)
|
|
||||||
.color(cx.theme().primary)
|
|
||||||
.border(cx.theme().primary)
|
|
||||||
.foreground(cx.theme().primary_foreground)
|
|
||||||
.active(cx.theme().primary_active)
|
|
||||||
.hover(cx.theme().primary_hover),
|
|
||||||
)
|
|
||||||
.xsmall()
|
|
||||||
.rounded(ButtonRounded::Size(px(24.)))
|
|
||||||
.label("Compose")
|
|
||||||
.on_click(move |_, cx| {
|
|
||||||
cx.open_modal(move |modal, _| {
|
|
||||||
modal.title("Compose").child("TODO").min_h(px(300.))
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
// Right side
|
// Right side
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.flex()
|
.flex()
|
||||||
.items_center()
|
.items_center()
|
||||||
.justify_end()
|
.justify_end()
|
||||||
|
.gap_1()
|
||||||
.px_2()
|
.px_2()
|
||||||
.gap_2()
|
.when_some(self.account.read(cx).as_ref(), |this, account| {
|
||||||
.child(
|
this.child(account.clone())
|
||||||
Button::new("theme-mode")
|
}),
|
||||||
.map(|this| {
|
|
||||||
if cx.theme().mode.is_dark() {
|
|
||||||
this.icon(IconName::Sun)
|
|
||||||
} else {
|
|
||||||
this.icon(IconName::Moon)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.small()
|
|
||||||
.ghost()
|
|
||||||
.on_click(cx.listener(Self::change_theme_mode)),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.child(self.dock.clone())
|
.child(self.dock.clone())
|
||||||
@@ -213,8 +175,6 @@ impl Render for AppView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div()
|
div()
|
||||||
.bg(cx.theme().background)
|
|
||||||
.text_color(cx.theme().foreground)
|
|
||||||
.size_full()
|
.size_full()
|
||||||
.child(content)
|
.child(content)
|
||||||
.child(div().absolute().top_8().children(notification_layer))
|
.child(div().absolute().top_8().children(notification_layer))
|
||||||
|
|||||||
72
crates/app/src/views/dock/contact.rs
Normal file
72
crates/app/src/views/dock/contact.rs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
use coop_ui::{
|
||||||
|
button::Button,
|
||||||
|
dock::{Panel, PanelEvent, PanelState},
|
||||||
|
popup_menu::PopupMenu,
|
||||||
|
};
|
||||||
|
use gpui::*;
|
||||||
|
|
||||||
|
pub struct ContactPanel {
|
||||||
|
name: SharedString,
|
||||||
|
closeable: bool,
|
||||||
|
zoomable: bool,
|
||||||
|
focus_handle: FocusHandle,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ContactPanel {
|
||||||
|
pub fn new(cx: &mut WindowContext) -> View<Self> {
|
||||||
|
cx.new_view(Self::view)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view(cx: &mut ViewContext<Self>) -> Self {
|
||||||
|
Self {
|
||||||
|
name: "Contacts".into(),
|
||||||
|
closeable: true,
|
||||||
|
zoomable: true,
|
||||||
|
focus_handle: cx.focus_handle(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Panel for ContactPanel {
|
||||||
|
fn panel_id(&self) -> SharedString {
|
||||||
|
"Contact".into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn title(&self, _cx: &WindowContext) -> AnyElement {
|
||||||
|
self.name.clone().into_any_element()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn closeable(&self, _cx: &WindowContext) -> bool {
|
||||||
|
self.closeable
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zoomable(&self, _cx: &WindowContext) -> bool {
|
||||||
|
self.zoomable
|
||||||
|
}
|
||||||
|
|
||||||
|
fn popup_menu(&self, menu: PopupMenu, _cx: &WindowContext) -> PopupMenu {
|
||||||
|
menu.track_focus(&self.focus_handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn toolbar_buttons(&self, _cx: &WindowContext) -> Vec<Button> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dump(&self, _cx: &AppContext) -> PanelState {
|
||||||
|
PanelState::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventEmitter<PanelEvent> for ContactPanel {}
|
||||||
|
|
||||||
|
impl FocusableView for ContactPanel {
|
||||||
|
fn focus_handle(&self, _: &AppContext) -> gpui::FocusHandle {
|
||||||
|
self.focus_handle.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Render for ContactPanel {
|
||||||
|
fn render(&mut self, _cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
|
||||||
|
div().size_full().child("TODO")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ use crate::{
|
|||||||
get_client,
|
get_client,
|
||||||
states::{chat::Room, metadata::MetadataRegistry, signal::SignalRegistry},
|
states::{chat::Room, metadata::MetadataRegistry, signal::SignalRegistry},
|
||||||
utils::{ago, get_room_id, show_npub},
|
utils::{ago, get_room_id, show_npub},
|
||||||
views::app::AddPanel,
|
views::app::{AddPanel, PanelKind},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct InboxItem {
|
pub struct InboxItem {
|
||||||
@@ -73,7 +73,7 @@ impl InboxItem {
|
|||||||
let room = Arc::new(Room::new(&self.event, cx));
|
let room = Arc::new(Room::new(&self.event, cx));
|
||||||
|
|
||||||
cx.dispatch_action(Box::new(AddPanel {
|
cx.dispatch_action(Box::new(AddPanel {
|
||||||
room,
|
panel: PanelKind::Room(room),
|
||||||
position: coop_ui::dock::DockPlacement::Center,
|
position: coop_ui::dock::DockPlacement::Center,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -189,9 +189,8 @@ impl Render for Inbox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
v_flex()
|
v_flex()
|
||||||
.gap_1()
|
|
||||||
.pt_2()
|
|
||||||
.px_2()
|
.px_2()
|
||||||
|
.gap_1()
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.id("inbox")
|
.id("inbox")
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
use coop_ui::{
|
use coop_ui::{
|
||||||
button::Button,
|
button::{Button, ButtonVariants},
|
||||||
dock::{Panel, PanelEvent, PanelState},
|
dock::{Panel, PanelEvent, PanelState},
|
||||||
popup_menu::PopupMenu,
|
popup_menu::PopupMenu,
|
||||||
scroll::ScrollbarAxis,
|
scroll::ScrollbarAxis,
|
||||||
StyledExt,
|
v_flex, ContextModal, Icon, IconName, Sizable, StyledExt,
|
||||||
};
|
};
|
||||||
use gpui::*;
|
use gpui::*;
|
||||||
|
|
||||||
|
use crate::views::app::{AddPanel, PanelKind};
|
||||||
|
|
||||||
use super::inbox::Inbox;
|
use super::inbox::Inbox;
|
||||||
|
|
||||||
pub struct LeftDock {
|
pub struct LeftDock {
|
||||||
@@ -79,8 +81,54 @@ impl FocusableView for LeftDock {
|
|||||||
|
|
||||||
impl Render for LeftDock {
|
impl Render for LeftDock {
|
||||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||||
div()
|
v_flex()
|
||||||
.child(self.inbox.clone())
|
|
||||||
.scrollable(self.view_id, ScrollbarAxis::Vertical)
|
.scrollable(self.view_id, ScrollbarAxis::Vertical)
|
||||||
|
.pt_3()
|
||||||
|
.gap_3()
|
||||||
|
.child(
|
||||||
|
v_flex()
|
||||||
|
.px_2()
|
||||||
|
.gap_1()
|
||||||
|
.child(
|
||||||
|
Button::new("new")
|
||||||
|
.small()
|
||||||
|
.ghost()
|
||||||
|
.not_centered()
|
||||||
|
.bold()
|
||||||
|
.icon(Icon::new(IconName::Plus))
|
||||||
|
.label("Compose")
|
||||||
|
.on_click(|_, cx| {
|
||||||
|
cx.open_modal(move |modal, _| modal.title("Compose").child("TODO"));
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Button::new("contacts")
|
||||||
|
.small()
|
||||||
|
.ghost()
|
||||||
|
.not_centered()
|
||||||
|
.bold()
|
||||||
|
.icon(Icon::new(IconName::Group))
|
||||||
|
.label("Contacts")
|
||||||
|
.on_click(|_, cx| {
|
||||||
|
cx.dispatch_action(Box::new(AddPanel {
|
||||||
|
panel: PanelKind::Contact,
|
||||||
|
position: coop_ui::dock::DockPlacement::Center,
|
||||||
|
}))
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Button::new("find")
|
||||||
|
.small()
|
||||||
|
.ghost()
|
||||||
|
.not_centered()
|
||||||
|
.bold()
|
||||||
|
.icon(Icon::new(IconName::Search))
|
||||||
|
.label("Find")
|
||||||
|
.on_click(|_, cx| {
|
||||||
|
cx.open_modal(move |modal, _| modal.title("Find").child("TODO"));
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.child(self.inbox.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
pub mod chat;
|
pub mod chat;
|
||||||
|
pub mod contact;
|
||||||
pub mod inbox;
|
pub mod inbox;
|
||||||
pub mod left_dock;
|
pub mod left_dock;
|
||||||
pub mod welcome;
|
pub mod welcome;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use crate::{
|
|||||||
indicator::Indicator,
|
indicator::Indicator,
|
||||||
theme::{ActiveTheme, Colorize as _},
|
theme::{ActiveTheme, Colorize as _},
|
||||||
tooltip::Tooltip,
|
tooltip::Tooltip,
|
||||||
Disableable, Icon, Selectable, Sizable, Size,
|
Disableable, Icon, Selectable, Sizable, Size, StyledExt,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub enum ButtonRounded {
|
pub enum ButtonRounded {
|
||||||
@@ -169,6 +169,8 @@ pub struct Button {
|
|||||||
size: Size,
|
size: Size,
|
||||||
compact: bool,
|
compact: bool,
|
||||||
reverse: bool,
|
reverse: bool,
|
||||||
|
bold: bool,
|
||||||
|
centered: bool,
|
||||||
tooltip: Option<SharedString>,
|
tooltip: Option<SharedString>,
|
||||||
on_click: OnClick,
|
on_click: OnClick,
|
||||||
pub(crate) stop_propagation: bool,
|
pub(crate) stop_propagation: bool,
|
||||||
@@ -202,6 +204,8 @@ impl Button {
|
|||||||
loading: false,
|
loading: false,
|
||||||
reverse: false,
|
reverse: false,
|
||||||
compact: false,
|
compact: false,
|
||||||
|
bold: false,
|
||||||
|
centered: true,
|
||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
loading_icon: None,
|
loading_icon: None,
|
||||||
}
|
}
|
||||||
@@ -261,6 +265,16 @@ impl Button {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn not_centered(mut self) -> Self {
|
||||||
|
self.centered = false;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bold(mut self) -> Self {
|
||||||
|
self.bold = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
|
pub fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
|
||||||
self.on_click = Some(Box::new(handler));
|
self.on_click = Some(Box::new(handler));
|
||||||
self
|
self
|
||||||
@@ -340,7 +354,7 @@ impl RenderOnce for Button {
|
|||||||
.id(self.id)
|
.id(self.id)
|
||||||
.flex()
|
.flex()
|
||||||
.items_center()
|
.items_center()
|
||||||
.justify_center()
|
.when(self.centered, |this| this.justify_center())
|
||||||
.cursor_pointer()
|
.cursor_pointer()
|
||||||
.overflow_hidden()
|
.overflow_hidden()
|
||||||
.when(cx.theme().shadow && normal_style.shadow, |this| {
|
.when(cx.theme().shadow && normal_style.shadow, |this| {
|
||||||
@@ -359,8 +373,8 @@ impl RenderOnce for Button {
|
|||||||
// Normal Button
|
// Normal Button
|
||||||
match self.size {
|
match self.size {
|
||||||
Size::Size(size) => this.px(size * 0.2),
|
Size::Size(size) => this.px(size * 0.2),
|
||||||
Size::XSmall => this.h_5().px_2().when(self.compact, |this| this.px_0()),
|
Size::XSmall => this.h_5().px_1().when(self.compact, |this| this.px_0()),
|
||||||
Size::Small => this.h_6().px_3().when(self.compact, |this| this.px_0p5()),
|
Size::Small => this.h_6().px_2().when(self.compact, |this| this.px_0p5()),
|
||||||
_ => this.h_8().px_4().when(self.compact, |this| this.px_1()),
|
_ => this.h_8().px_4().when(self.compact, |this| this.px_1()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -445,7 +459,7 @@ impl RenderOnce for Button {
|
|||||||
.justify_center()
|
.justify_center()
|
||||||
.map(|this| match self.size {
|
.map(|this| match self.size {
|
||||||
Size::XSmall => this.gap_1().text_xs(),
|
Size::XSmall => this.gap_1().text_xs(),
|
||||||
Size::Small => this.gap_1().text_xs(),
|
Size::Small => this.gap_2().text_xs(),
|
||||||
_ => this.gap_2().text_base(),
|
_ => this.gap_2().text_base(),
|
||||||
})
|
})
|
||||||
.when(!self.loading, |this| {
|
.when(!self.loading, |this| {
|
||||||
@@ -461,7 +475,13 @@ impl RenderOnce for Button {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
.when_some(self.label, |this, label| {
|
.when_some(self.label, |this, label| {
|
||||||
this.child(div().flex_none().line_height(relative(1.)).child(label))
|
this.child(
|
||||||
|
div()
|
||||||
|
.flex_none()
|
||||||
|
.line_height(relative(1.))
|
||||||
|
.child(label)
|
||||||
|
.when(self.bold, |this| this.font_semibold()),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.children(self.children)
|
.children(self.children)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ pub enum IconName {
|
|||||||
GalleryVerticalEnd,
|
GalleryVerticalEnd,
|
||||||
GitHub,
|
GitHub,
|
||||||
Globe,
|
Globe,
|
||||||
|
Group,
|
||||||
Heart,
|
Heart,
|
||||||
HeartOff,
|
HeartOff,
|
||||||
Inbox,
|
Inbox,
|
||||||
@@ -120,6 +121,7 @@ impl IconName {
|
|||||||
Self::GalleryVerticalEnd => "icons/gallery-vertical-end.svg",
|
Self::GalleryVerticalEnd => "icons/gallery-vertical-end.svg",
|
||||||
Self::GitHub => "icons/github.svg",
|
Self::GitHub => "icons/github.svg",
|
||||||
Self::Globe => "icons/globe.svg",
|
Self::Globe => "icons/globe.svg",
|
||||||
|
Self::Group => "icons/group.svg",
|
||||||
Self::Heart => "icons/heart.svg",
|
Self::Heart => "icons/heart.svg",
|
||||||
Self::HeartOff => "icons/heart-off.svg",
|
Self::HeartOff => "icons/heart-off.svg",
|
||||||
Self::Inbox => "icons/inbox.svg",
|
Self::Inbox => "icons/inbox.svg",
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ use crate::{
|
|||||||
|
|
||||||
actions!(menu, [Confirm, Dismiss, SelectNext, SelectPrev]);
|
actions!(menu, [Confirm, Dismiss, SelectNext, SelectPrev]);
|
||||||
|
|
||||||
|
const ITEM_HEIGHT: Pixels = px(26.);
|
||||||
|
|
||||||
pub fn init(cx: &mut AppContext) {
|
pub fn init(cx: &mut AppContext) {
|
||||||
let context = Some("PopupMenu");
|
let context = Some("PopupMenu");
|
||||||
cx.bind_keys([
|
cx.bind_keys([
|
||||||
@@ -492,8 +494,6 @@ impl Render for PopupMenu {
|
|||||||
let window_haft_height = cx.window_bounds().get_bounds().size.height * 0.5;
|
let window_haft_height = cx.window_bounds().get_bounds().size.height * 0.5;
|
||||||
let max_height = window_haft_height.min(px(450.));
|
let max_height = window_haft_height.min(px(450.));
|
||||||
|
|
||||||
const ITEM_HEIGHT: Pixels = px(26.);
|
|
||||||
|
|
||||||
v_flex()
|
v_flex()
|
||||||
.id("popup-menu")
|
.id("popup-menu")
|
||||||
.key_context("PopupMenu")
|
.key_context("PopupMenu")
|
||||||
@@ -540,11 +540,11 @@ impl Render for PopupMenu {
|
|||||||
.map(|(ix, item)| {
|
.map(|(ix, item)| {
|
||||||
let this = ListItem::new(("menu-item", ix))
|
let this = ListItem::new(("menu-item", ix))
|
||||||
.relative()
|
.relative()
|
||||||
.text_sm()
|
.items_center()
|
||||||
.py_0()
|
.py_0()
|
||||||
.px_2()
|
.px_2()
|
||||||
.rounded_md()
|
.rounded_md()
|
||||||
.items_center()
|
.text_xs()
|
||||||
.on_mouse_enter(cx.listener(move |this, _, cx| {
|
.on_mouse_enter(cx.listener(move |this, _, cx| {
|
||||||
this.hovered_menu_ix = Some(ix);
|
this.hovered_menu_ix = Some(ix);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
@@ -667,7 +667,7 @@ impl Render for PopupMenu {
|
|||||||
|
|
||||||
if hovered_ix == ix {
|
if hovered_ix == ix {
|
||||||
this.child(
|
this.child(
|
||||||
anchored()
|
anchored()
|
||||||
.anchor(anchor)
|
.anchor(anchor)
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
@@ -741,33 +741,3 @@ pub fn key_shortcut(key: Keystroke) -> String {
|
|||||||
parts.push(&key);
|
parts.push(&key);
|
||||||
parts.join("+")
|
parts.join("+")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
#[test]
|
|
||||||
fn test_key_shortcut() {
|
|
||||||
use super::key_shortcut;
|
|
||||||
use gpui::Keystroke;
|
|
||||||
|
|
||||||
if cfg!(target_os = "windows") {
|
|
||||||
assert_eq!(key_shortcut(Keystroke::parse("a").unwrap()), "A");
|
|
||||||
assert_eq!(key_shortcut(Keystroke::parse("ctrl-a").unwrap()), "Ctrl+A");
|
|
||||||
assert_eq!(
|
|
||||||
key_shortcut(Keystroke::parse("ctrl-alt-a").unwrap()),
|
|
||||||
"Ctrl+Alt+A"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
key_shortcut(Keystroke::parse("ctrl-alt-shift-a").unwrap()),
|
|
||||||
"Ctrl+Alt+Shift+A"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
key_shortcut(Keystroke::parse("ctrl-alt-shift-win-a").unwrap()),
|
|
||||||
"Ctrl+Alt+Win+Shift+A"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
key_shortcut(Keystroke::parse("ctrl-shift-backspace").unwrap()),
|
|
||||||
"Ctrl+Shift+Backspace"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ pub trait StyledExt: Styled + Sized {
|
|||||||
.border_1()
|
.border_1()
|
||||||
.border_color(cx.theme().border)
|
.border_color(cx.theme().border)
|
||||||
.shadow_lg()
|
.shadow_lg()
|
||||||
.rounded(px(cx.theme().radius))
|
.rounded_lg()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user