chore: add missing ui elements (#153)
* add empty state * . * update welcome panel
This commit is contained in:
@@ -26,7 +26,7 @@ use smallvec::{smallvec, SmallVec};
|
|||||||
use smol::fs;
|
use smol::fs;
|
||||||
use theme::ActiveTheme;
|
use theme::ActiveTheme;
|
||||||
use ui::avatar::Avatar;
|
use ui::avatar::Avatar;
|
||||||
use ui::button::{Button, ButtonRounded, ButtonVariants};
|
use ui::button::{Button, ButtonVariants};
|
||||||
use ui::dock_area::panel::{Panel, PanelEvent};
|
use ui::dock_area::panel::{Panel, PanelEvent};
|
||||||
use ui::emoji_picker::EmojiPicker;
|
use ui::emoji_picker::EmojiPicker;
|
||||||
use ui::input::{InputEvent, InputState, TextInput};
|
use ui::input::{InputEvent, InputState, TextInput};
|
||||||
@@ -761,7 +761,7 @@ impl Chat {
|
|||||||
.label(t!("common.resend"))
|
.label(t!("common.resend"))
|
||||||
.danger()
|
.danger()
|
||||||
.xsmall()
|
.xsmall()
|
||||||
.rounded(ButtonRounded::Full)
|
.rounded()
|
||||||
.on_click(cx.listener(
|
.on_click(cx.listener(
|
||||||
move |this, _, window, cx| {
|
move |this, _, window, cx| {
|
||||||
this.resend_message(&id, window, cx);
|
this.resend_message(&id, window, cx);
|
||||||
@@ -1031,45 +1031,6 @@ impl Chat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn render_actions(&self, id: &EventId, cx: &Context<Self>) -> impl IntoElement {
|
fn render_actions(&self, id: &EventId, cx: &Context<Self>) -> impl IntoElement {
|
||||||
let reply = Button::new("reply")
|
|
||||||
.icon(IconName::Reply)
|
|
||||||
.tooltip(t!("chat.reply_button"))
|
|
||||||
.small()
|
|
||||||
.ghost()
|
|
||||||
.on_click({
|
|
||||||
let id = id.to_owned();
|
|
||||||
cx.listener(move |this, _event, _window, cx| {
|
|
||||||
this.reply_to(&id, cx);
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.into_any_element();
|
|
||||||
|
|
||||||
let copy = Button::new("copy")
|
|
||||||
.icon(IconName::Copy)
|
|
||||||
.tooltip(t!("chat.copy_message_button"))
|
|
||||||
.small()
|
|
||||||
.ghost()
|
|
||||||
.on_click({
|
|
||||||
let id = id.to_owned();
|
|
||||||
cx.listener(move |this, _event, _window, cx| {
|
|
||||||
this.copy_message(&id, cx);
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.into_any_element();
|
|
||||||
|
|
||||||
let more = Button::new("seen-on")
|
|
||||||
.icon(IconName::Ellipsis)
|
|
||||||
.small()
|
|
||||||
.ghost()
|
|
||||||
.popup_menu({
|
|
||||||
let id = id.to_owned();
|
|
||||||
move |this, _window, _cx| {
|
|
||||||
// TODO: add more actions
|
|
||||||
this.menu(t!("common.seen_on"), Box::new(SeenOn(id)))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.into_any_element();
|
|
||||||
|
|
||||||
h_flex()
|
h_flex()
|
||||||
.p_0p5()
|
.p_0p5()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
@@ -1082,7 +1043,45 @@ impl Chat {
|
|||||||
.border_1()
|
.border_1()
|
||||||
.border_color(cx.theme().border)
|
.border_color(cx.theme().border)
|
||||||
.bg(cx.theme().background)
|
.bg(cx.theme().background)
|
||||||
.children(vec![reply, copy, more])
|
.child(
|
||||||
|
Button::new("reply")
|
||||||
|
.icon(IconName::Reply)
|
||||||
|
.tooltip(t!("chat.reply_button"))
|
||||||
|
.small()
|
||||||
|
.ghost()
|
||||||
|
.on_click({
|
||||||
|
let id = id.to_owned();
|
||||||
|
cx.listener(move |this, _event, _window, cx| {
|
||||||
|
this.reply_to(&id, cx);
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Button::new("copy")
|
||||||
|
.icon(IconName::Copy)
|
||||||
|
.tooltip(t!("chat.copy_message_button"))
|
||||||
|
.small()
|
||||||
|
.ghost()
|
||||||
|
.on_click({
|
||||||
|
let id = id.to_owned();
|
||||||
|
cx.listener(move |this, _event, _window, cx| {
|
||||||
|
this.copy_message(&id, cx);
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.child(div().flex_shrink_0().h_4().w_px().bg(cx.theme().border))
|
||||||
|
.child(
|
||||||
|
Button::new("seen-on")
|
||||||
|
.icon(IconName::Ellipsis)
|
||||||
|
.small()
|
||||||
|
.ghost()
|
||||||
|
.popup_menu({
|
||||||
|
let id = id.to_owned();
|
||||||
|
move |this, _window, _cx| {
|
||||||
|
this.menu(t!("common.seen_on"), Box::new(SeenOn(id)))
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
.group_hover("", |this| this.visible())
|
.group_hover("", |this| this.visible())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use smallvec::{smallvec, SmallVec};
|
|||||||
use smol::Timer;
|
use smol::Timer;
|
||||||
use theme::ActiveTheme;
|
use theme::ActiveTheme;
|
||||||
use ui::avatar::Avatar;
|
use ui::avatar::Avatar;
|
||||||
use ui::button::{Button, ButtonRounded, ButtonVariants};
|
use ui::button::{Button, ButtonVariants};
|
||||||
use ui::input::{InputEvent, InputState, TextInput};
|
use ui::input::{InputEvent, InputState, TextInput};
|
||||||
use ui::notification::Notification;
|
use ui::notification::Notification;
|
||||||
use ui::{h_flex, v_flex, ContextModal, Disableable, Icon, IconName, Sizable, StyledExt};
|
use ui::{h_flex, v_flex, ContextModal, Disableable, Icon, IconName, Sizable, StyledExt};
|
||||||
@@ -34,7 +34,7 @@ pub fn compose_button() -> impl IntoElement {
|
|||||||
.ghost_alt()
|
.ghost_alt()
|
||||||
.cta()
|
.cta()
|
||||||
.small()
|
.small()
|
||||||
.rounded(ButtonRounded::Full)
|
.rounded()
|
||||||
.on_click(move |_, window, cx| {
|
.on_click(move |_, window, cx| {
|
||||||
let compose = cx.new(|cx| Compose::new(window, cx));
|
let compose = cx.new(|cx| Compose::new(window, cx));
|
||||||
let title = SharedString::new(t!("sidebar.direct_messages"));
|
let title = SharedString::new(t!("sidebar.direct_messages"));
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use settings::AppSettings;
|
|||||||
use smol::fs;
|
use smol::fs;
|
||||||
use theme::ActiveTheme;
|
use theme::ActiveTheme;
|
||||||
use ui::avatar::Avatar;
|
use ui::avatar::Avatar;
|
||||||
use ui::button::{Button, ButtonRounded, ButtonVariants};
|
use ui::button::{Button, ButtonVariants};
|
||||||
use ui::dock_area::panel::{Panel, PanelEvent};
|
use ui::dock_area::panel::{Panel, PanelEvent};
|
||||||
use ui::input::{InputState, TextInput};
|
use ui::input::{InputState, TextInput};
|
||||||
use ui::modal::ModalButtonProps;
|
use ui::modal::ModalButtonProps;
|
||||||
@@ -352,7 +352,7 @@ impl Render for NewAccount {
|
|||||||
.label(t!("common.upload"))
|
.label(t!("common.upload"))
|
||||||
.ghost()
|
.ghost()
|
||||||
.small()
|
.small()
|
||||||
.rounded(ButtonRounded::Full)
|
.rounded()
|
||||||
.disabled(self.submitting || self.uploading)
|
.disabled(self.submitting || self.uploading)
|
||||||
.loading(self.uploading)
|
.loading(self.uploading)
|
||||||
.on_click(cx.listener(move |this, _, window, cx| {
|
.on_click(cx.listener(move |this, _, window, cx| {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use registry::Registry;
|
|||||||
use settings::AppSettings;
|
use settings::AppSettings;
|
||||||
use theme::ActiveTheme;
|
use theme::ActiveTheme;
|
||||||
use ui::avatar::Avatar;
|
use ui::avatar::Avatar;
|
||||||
use ui::button::{Button, ButtonRounded, ButtonVariants};
|
use ui::button::{Button, ButtonVariants};
|
||||||
use ui::input::{InputState, TextInput};
|
use ui::input::{InputState, TextInput};
|
||||||
use ui::modal::ModalButtonProps;
|
use ui::modal::ModalButtonProps;
|
||||||
use ui::switch::Switch;
|
use ui::switch::Switch;
|
||||||
@@ -169,7 +169,7 @@ impl Render for Preferences {
|
|||||||
.label("Messaging Relays")
|
.label("Messaging Relays")
|
||||||
.xsmall()
|
.xsmall()
|
||||||
.ghost_alt()
|
.ghost_alt()
|
||||||
.rounded(ButtonRounded::Full)
|
.rounded()
|
||||||
.on_click(cx.listener(move |this, _e, window, cx| {
|
.on_click(cx.listener(move |this, _e, window, cx| {
|
||||||
this.open_relays(window, cx);
|
this.open_relays(window, cx);
|
||||||
})),
|
})),
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use settings::AppSettings;
|
|||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use theme::ActiveTheme;
|
use theme::ActiveTheme;
|
||||||
use ui::avatar::Avatar;
|
use ui::avatar::Avatar;
|
||||||
use ui::button::{Button, ButtonRounded, ButtonVariants};
|
use ui::button::{Button, ButtonVariants};
|
||||||
use ui::indicator::Indicator;
|
use ui::indicator::Indicator;
|
||||||
use ui::{h_flex, v_flex, ContextModal, Icon, IconName, Sizable, StyledExt};
|
use ui::{h_flex, v_flex, ContextModal, Icon, IconName, Sizable, StyledExt};
|
||||||
|
|
||||||
@@ -268,7 +268,7 @@ impl Render for Screening {
|
|||||||
.label(t!("profile.njump"))
|
.label(t!("profile.njump"))
|
||||||
.secondary()
|
.secondary()
|
||||||
.small()
|
.small()
|
||||||
.rounded(ButtonRounded::Full)
|
.rounded()
|
||||||
.on_click(cx.listener(move |this, _e, window, cx| {
|
.on_click(cx.listener(move |this, _e, window, cx| {
|
||||||
this.open_njump(window, cx);
|
this.open_njump(window, cx);
|
||||||
})),
|
})),
|
||||||
@@ -278,7 +278,7 @@ impl Render for Screening {
|
|||||||
.tooltip(t!("screening.report"))
|
.tooltip(t!("screening.report"))
|
||||||
.icon(IconName::Report)
|
.icon(IconName::Report)
|
||||||
.danger()
|
.danger()
|
||||||
.rounded(ButtonRounded::Full)
|
.rounded()
|
||||||
.on_click(cx.listener(move |this, _e, window, cx| {
|
.on_click(cx.listener(move |this, _e, window, cx| {
|
||||||
this.report(window, cx);
|
this.report(window, cx);
|
||||||
})),
|
})),
|
||||||
@@ -330,7 +330,7 @@ impl Render for Screening {
|
|||||||
.icon(IconName::Info)
|
.icon(IconName::Info)
|
||||||
.xsmall()
|
.xsmall()
|
||||||
.ghost()
|
.ghost()
|
||||||
.rounded(ButtonRounded::Full)
|
.rounded()
|
||||||
.tooltip(t!("screening.active_tooltip")),
|
.tooltip(t!("screening.active_tooltip")),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -402,7 +402,7 @@ impl Render for Screening {
|
|||||||
.icon(IconName::Info)
|
.icon(IconName::Info)
|
||||||
.xsmall()
|
.xsmall()
|
||||||
.ghost()
|
.ghost()
|
||||||
.rounded(ButtonRounded::Full)
|
.rounded()
|
||||||
.on_click(cx.listener(
|
.on_click(cx.listener(
|
||||||
move |this, _, window, cx| {
|
move |this, _, window, cx| {
|
||||||
this.mutual_contacts(window, cx);
|
this.mutual_contacts(window, cx);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use nostr_sdk::prelude::*;
|
|||||||
use registry::Registry;
|
use registry::Registry;
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use theme::ActiveTheme;
|
use theme::ActiveTheme;
|
||||||
use ui::button::{Button, ButtonRounded, ButtonVariants};
|
use ui::button::{Button, ButtonVariants};
|
||||||
use ui::input::{InputEvent, InputState, TextInput};
|
use ui::input::{InputEvent, InputState, TextInput};
|
||||||
use ui::modal::ModalButtonProps;
|
use ui::modal::ModalButtonProps;
|
||||||
use ui::{h_flex, v_flex, ContextModal, IconName, Sizable, StyledExt};
|
use ui::{h_flex, v_flex, ContextModal, IconName, Sizable, StyledExt};
|
||||||
@@ -33,7 +33,7 @@ where
|
|||||||
.label(label)
|
.label(label)
|
||||||
.warning()
|
.warning()
|
||||||
.xsmall()
|
.xsmall()
|
||||||
.rounded(ButtonRounded::Full)
|
.rounded()
|
||||||
.on_click(move |_, window, cx| {
|
.on_click(move |_, window, cx| {
|
||||||
let view = cx.new(|cx| SetupRelay::new(Kind::InboxRelays, window, cx));
|
let view = cx.new(|cx| SetupRelay::new(Kind::InboxRelays, window, cx));
|
||||||
let weak_view = view.downgrade();
|
let weak_view = view.downgrade();
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ use global::constants::{BOOTSTRAP_RELAYS, SEARCH_RELAYS};
|
|||||||
use global::{css, nostr_client, UnwrappingStatus};
|
use global::{css, nostr_client, UnwrappingStatus};
|
||||||
use gpui::prelude::FluentBuilder;
|
use gpui::prelude::FluentBuilder;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, uniform_list, AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle,
|
div, relative, uniform_list, AnyElement, App, AppContext, Context, Entity, EventEmitter,
|
||||||
Focusable, InteractiveElement, IntoElement, ParentElement, Render, RetainAllImageCache,
|
FocusHandle, Focusable, InteractiveElement, IntoElement, ParentElement, Render,
|
||||||
SharedString, Styled, Subscription, Task, Window,
|
RetainAllImageCache, SharedString, Styled, Subscription, Task, Window,
|
||||||
};
|
};
|
||||||
use gpui_tokio::Tokio;
|
use gpui_tokio::Tokio;
|
||||||
use i18n::{shared_t, t};
|
use i18n::{shared_t, t};
|
||||||
@@ -23,7 +23,7 @@ use registry::{Registry, RegistryEvent};
|
|||||||
use settings::AppSettings;
|
use settings::AppSettings;
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use theme::ActiveTheme;
|
use theme::ActiveTheme;
|
||||||
use ui::button::{Button, ButtonRounded, ButtonVariants};
|
use ui::button::{Button, ButtonVariants};
|
||||||
use ui::dock_area::panel::{Panel, PanelEvent};
|
use ui::dock_area::panel::{Panel, PanelEvent};
|
||||||
use ui::input::{InputEvent, InputState, TextInput};
|
use ui::input::{InputEvent, InputState, TextInput};
|
||||||
use ui::popup_menu::{PopupMenu, PopupMenuExt};
|
use ui::popup_menu::{PopupMenu, PopupMenuExt};
|
||||||
@@ -669,6 +669,7 @@ impl Focusable for Sidebar {
|
|||||||
impl Render for Sidebar {
|
impl Render for Sidebar {
|
||||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
let registry = Registry::read_global(cx);
|
let registry = Registry::read_global(cx);
|
||||||
|
let loading = registry.unwrapping_status.read(cx) != &UnwrappingStatus::Complete;
|
||||||
|
|
||||||
// Get rooms from either search results or the chat registry
|
// Get rooms from either search results or the chat registry
|
||||||
let rooms = if let Some(results) = self.local_result.read(cx).as_ref() {
|
let rooms = if let Some(results) = self.local_result.read(cx).as_ref() {
|
||||||
@@ -688,7 +689,7 @@ impl Render for Sidebar {
|
|||||||
let mut total_rooms = rooms.len();
|
let mut total_rooms = rooms.len();
|
||||||
|
|
||||||
// Add 3 dummy rooms to display as skeletons
|
// Add 3 dummy rooms to display as skeletons
|
||||||
if registry.unwrapping_status.read(cx) != &UnwrappingStatus::Complete {
|
if loading {
|
||||||
total_rooms += 3
|
total_rooms += 3
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -752,7 +753,7 @@ impl Render for Sidebar {
|
|||||||
.cta()
|
.cta()
|
||||||
.bold()
|
.bold()
|
||||||
.secondary()
|
.secondary()
|
||||||
.rounded(ButtonRounded::Full)
|
.rounded()
|
||||||
.selected(self.filter(&RoomKind::Ongoing, cx))
|
.selected(self.filter(&RoomKind::Ongoing, cx))
|
||||||
.on_click(cx.listener(|this, _, _, cx| {
|
.on_click(cx.listener(|this, _, _, cx| {
|
||||||
this.set_filter(RoomKind::Ongoing, cx);
|
this.set_filter(RoomKind::Ongoing, cx);
|
||||||
@@ -773,7 +774,7 @@ impl Render for Sidebar {
|
|||||||
.cta()
|
.cta()
|
||||||
.bold()
|
.bold()
|
||||||
.secondary()
|
.secondary()
|
||||||
.rounded(ButtonRounded::Full)
|
.rounded()
|
||||||
.selected(!self.filter(&RoomKind::Ongoing, cx))
|
.selected(!self.filter(&RoomKind::Ongoing, cx))
|
||||||
.on_click(cx.listener(|this, _, _, cx| {
|
.on_click(cx.listener(|this, _, _, cx| {
|
||||||
this.set_filter(RoomKind::default(), cx);
|
this.set_filter(RoomKind::default(), cx);
|
||||||
@@ -791,7 +792,7 @@ impl Render for Sidebar {
|
|||||||
.icon(IconName::Ellipsis)
|
.icon(IconName::Ellipsis)
|
||||||
.xsmall()
|
.xsmall()
|
||||||
.ghost()
|
.ghost()
|
||||||
.rounded(ButtonRounded::Full)
|
.rounded()
|
||||||
.popup_menu(move |this, _window, _cx| {
|
.popup_menu(move |this, _window, _cx| {
|
||||||
this.menu(
|
this.menu(
|
||||||
t!("sidebar.reload_menu"),
|
t!("sidebar.reload_menu"),
|
||||||
@@ -805,6 +806,57 @@ impl Render for Sidebar {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
.when(!loading && total_rooms == 0, |this| {
|
||||||
|
this.map(|this| {
|
||||||
|
if self.filter(&RoomKind::Ongoing, cx) {
|
||||||
|
this.child(
|
||||||
|
v_flex()
|
||||||
|
.py_2()
|
||||||
|
.gap_1p5()
|
||||||
|
.items_center()
|
||||||
|
.justify_center()
|
||||||
|
.text_center()
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.text_sm()
|
||||||
|
.font_semibold()
|
||||||
|
.line_height(relative(1.25))
|
||||||
|
.child(shared_t!("sidebar.no_conversations")),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.text_xs()
|
||||||
|
.text_color(cx.theme().text_muted)
|
||||||
|
.line_height(relative(1.25))
|
||||||
|
.child(shared_t!("sidebar.no_conversations_label")),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
this.child(
|
||||||
|
v_flex()
|
||||||
|
.py_2()
|
||||||
|
.gap_1p5()
|
||||||
|
.items_center()
|
||||||
|
.justify_center()
|
||||||
|
.text_center()
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.text_sm()
|
||||||
|
.font_semibold()
|
||||||
|
.line_height(relative(1.25))
|
||||||
|
.child(shared_t!("sidebar.no_requests")),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.text_xs()
|
||||||
|
.text_color(cx.theme().text_muted)
|
||||||
|
.line_height(relative(1.25))
|
||||||
|
.child(shared_t!("sidebar.no_requests_label")),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
.child(
|
.child(
|
||||||
uniform_list(
|
uniform_list(
|
||||||
"rooms",
|
"rooms",
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
use gpui::{
|
use gpui::{
|
||||||
div, svg, AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable,
|
div, svg, AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable,
|
||||||
IntoElement, ParentElement, Render, SharedString, Styled, Window,
|
InteractiveElement, IntoElement, ParentElement, Render, SharedString,
|
||||||
|
StatefulInteractiveElement, Styled, Window,
|
||||||
};
|
};
|
||||||
use theme::ActiveTheme;
|
use theme::ActiveTheme;
|
||||||
use ui::button::Button;
|
use ui::button::Button;
|
||||||
use ui::dock_area::panel::{Panel, PanelEvent};
|
use ui::dock_area::panel::{Panel, PanelEvent};
|
||||||
use ui::popup_menu::PopupMenu;
|
use ui::popup_menu::PopupMenu;
|
||||||
use ui::StyledExt;
|
use ui::{v_flex, StyledExt};
|
||||||
|
|
||||||
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Welcome> {
|
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Welcome> {
|
||||||
Welcome::new(window, cx)
|
Welcome::new(window, cx)
|
||||||
@@ -14,8 +15,7 @@ pub fn init(window: &mut Window, cx: &mut App) -> Entity<Welcome> {
|
|||||||
|
|
||||||
pub struct Welcome {
|
pub struct Welcome {
|
||||||
name: SharedString,
|
name: SharedString,
|
||||||
closable: bool,
|
version: SharedString,
|
||||||
zoomable: bool,
|
|
||||||
focus_handle: FocusHandle,
|
focus_handle: FocusHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,10 +25,11 @@ impl Welcome {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn view(_window: &mut Window, cx: &mut Context<Self>) -> Self {
|
fn view(_window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||||
|
let version = SharedString::from(format!("Version: {}", env!("CARGO_PKG_VERSION")));
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
version,
|
||||||
name: "Welcome".into(),
|
name: "Welcome".into(),
|
||||||
closable: true,
|
|
||||||
zoomable: true,
|
|
||||||
focus_handle: cx.focus_handle(),
|
focus_handle: cx.focus_handle(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,16 +40,15 @@ impl Panel for Welcome {
|
|||||||
self.name.clone()
|
self.name.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn title(&self, _cx: &App) -> AnyElement {
|
fn title(&self, cx: &App) -> AnyElement {
|
||||||
"👋".into_any_element()
|
div()
|
||||||
}
|
.child(
|
||||||
|
svg()
|
||||||
fn closable(&self, _cx: &App) -> bool {
|
.path("brand/coop.svg")
|
||||||
self.closable
|
.size_4()
|
||||||
}
|
.text_color(cx.theme().element_background),
|
||||||
|
)
|
||||||
fn zoomable(&self, _cx: &App) -> bool {
|
.into_any_element()
|
||||||
self.zoomable
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn popup_menu(&self, menu: PopupMenu, _cx: &App) -> PopupMenu {
|
fn popup_menu(&self, menu: PopupMenu, _cx: &App) -> PopupMenu {
|
||||||
@@ -76,23 +76,37 @@ impl Render for Welcome {
|
|||||||
.items_center()
|
.items_center()
|
||||||
.justify_center()
|
.justify_center()
|
||||||
.child(
|
.child(
|
||||||
div()
|
v_flex()
|
||||||
.flex()
|
.gap_2()
|
||||||
.flex_col()
|
|
||||||
.items_center()
|
.items_center()
|
||||||
.gap_1()
|
.justify_center()
|
||||||
.child(
|
.child(
|
||||||
svg()
|
svg()
|
||||||
.path("brand/coop.svg")
|
.path("brand/coop.svg")
|
||||||
.size_12()
|
.size_12()
|
||||||
.text_color(cx.theme().elevated_surface_background),
|
.text_color(cx.theme().elevated_surface_background),
|
||||||
)
|
)
|
||||||
|
.child(
|
||||||
|
v_flex()
|
||||||
|
.items_center()
|
||||||
|
.justify_center()
|
||||||
|
.text_center()
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.child("coop on nostr")
|
|
||||||
.text_color(cx.theme().text_placeholder)
|
|
||||||
.font_semibold()
|
.font_semibold()
|
||||||
.text_sm(),
|
.text_color(cx.theme().text_muted)
|
||||||
|
.child("coop on nostr"),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.id("version")
|
||||||
|
.text_color(cx.theme().text_placeholder)
|
||||||
|
.text_xs()
|
||||||
|
.child(self.version.clone())
|
||||||
|
.on_click(|_, _window, cx| {
|
||||||
|
cx.open_url("https://github.com/lumehq/coop/releases");
|
||||||
|
}),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,4 +3,4 @@
|
|||||||
///
|
///
|
||||||
/// Magic number: There is one extra pixel of padding on the left side due to
|
/// Magic number: There is one extra pixel of padding on the left side due to
|
||||||
/// the 1px border around the window on macOS apps.
|
/// the 1px border around the window on macOS apps.
|
||||||
pub const TRAFFIC_LIGHT_PADDING: f32 = 71.;
|
pub const TRAFFIC_LIGHT_PADDING: f32 = 80.;
|
||||||
|
|||||||
@@ -10,11 +10,6 @@ use crate::indicator::Indicator;
|
|||||||
use crate::tooltip::Tooltip;
|
use crate::tooltip::Tooltip;
|
||||||
use crate::{h_flex, Disableable, Icon, Selectable, Sizable, Size, StyledExt};
|
use crate::{h_flex, Disableable, Icon, Selectable, Sizable, Size, StyledExt};
|
||||||
|
|
||||||
pub enum ButtonRounded {
|
|
||||||
Normal,
|
|
||||||
Full,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct ButtonCustomVariant {
|
pub struct ButtonCustomVariant {
|
||||||
color: Hsla,
|
color: Hsla,
|
||||||
@@ -130,7 +125,7 @@ pub struct Button {
|
|||||||
children: Vec<AnyElement>,
|
children: Vec<AnyElement>,
|
||||||
|
|
||||||
variant: ButtonVariant,
|
variant: ButtonVariant,
|
||||||
rounded: ButtonRounded,
|
rounded: bool,
|
||||||
size: Size,
|
size: Size,
|
||||||
|
|
||||||
disabled: bool,
|
disabled: bool,
|
||||||
@@ -163,7 +158,7 @@ impl Button {
|
|||||||
disabled: false,
|
disabled: false,
|
||||||
selected: false,
|
selected: false,
|
||||||
variant: ButtonVariant::default(),
|
variant: ButtonVariant::default(),
|
||||||
rounded: ButtonRounded::Normal,
|
rounded: false,
|
||||||
size: Size::Medium,
|
size: Size::Medium,
|
||||||
tooltip: None,
|
tooltip: None,
|
||||||
on_click: None,
|
on_click: None,
|
||||||
@@ -177,9 +172,9 @@ impl Button {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the border radius of the Button.
|
/// Make the button rounded.
|
||||||
pub fn rounded(mut self, rounded: impl Into<ButtonRounded>) -> Self {
|
pub fn rounded(mut self) -> Self {
|
||||||
self.rounded = rounded.into();
|
self.rounded = true;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,8 +310,8 @@ impl RenderOnce for Button {
|
|||||||
.cursor_default()
|
.cursor_default()
|
||||||
.overflow_hidden()
|
.overflow_hidden()
|
||||||
.map(|this| match self.rounded {
|
.map(|this| match self.rounded {
|
||||||
ButtonRounded::Normal => this.rounded(cx.theme().radius),
|
false => this.rounded(cx.theme().radius),
|
||||||
ButtonRounded::Full => this.rounded_full(),
|
true => this.rounded_full(),
|
||||||
})
|
})
|
||||||
.map(|this| {
|
.map(|this| {
|
||||||
if self.label.is_none() && self.children.is_empty() {
|
if self.label.is_none() && self.children.is_empty() {
|
||||||
|
|||||||
@@ -412,16 +412,15 @@ impl TabPanel {
|
|||||||
let is_zoomed = self.is_zoomed && state.zoomable;
|
let is_zoomed = self.is_zoomed && state.zoomable;
|
||||||
let view = cx.entity().clone();
|
let view = cx.entity().clone();
|
||||||
let build_popup_menu = move |this, cx: &App| view.read(cx).popup_menu(this, cx);
|
let build_popup_menu = move |this, cx: &App| view.read(cx).popup_menu(this, cx);
|
||||||
|
let toolbar = self.toolbar_buttons(window, cx);
|
||||||
|
let has_toolbar = !toolbar.is_empty();
|
||||||
|
|
||||||
h_flex()
|
h_flex()
|
||||||
|
.p_0p5()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
.occlude()
|
.occlude()
|
||||||
.items_center()
|
.rounded_full()
|
||||||
.children(
|
.children(toolbar.into_iter().map(|btn| btn.small().ghost().rounded()))
|
||||||
self.toolbar_buttons(window, cx)
|
|
||||||
.into_iter()
|
|
||||||
.map(|btn| btn.small().ghost()),
|
|
||||||
)
|
|
||||||
.when(self.is_zoomed, |this| {
|
.when(self.is_zoomed, |this| {
|
||||||
this.child(
|
this.child(
|
||||||
Button::new("zoom")
|
Button::new("zoom")
|
||||||
@@ -434,11 +433,16 @@ impl TabPanel {
|
|||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
.when(has_toolbar, |this| {
|
||||||
|
this.bg(cx.theme().surface_background)
|
||||||
|
.child(div().flex_shrink_0().h_4().w_px().bg(cx.theme().border))
|
||||||
|
})
|
||||||
.child(
|
.child(
|
||||||
Button::new("menu")
|
Button::new("menu")
|
||||||
.icon(IconName::Ellipsis)
|
.icon(IconName::Ellipsis)
|
||||||
.small()
|
.small()
|
||||||
.ghost()
|
.ghost()
|
||||||
|
.rounded()
|
||||||
.popup_menu({
|
.popup_menu({
|
||||||
let zoomable = state.zoomable;
|
let zoomable = state.zoomable;
|
||||||
let closable = state.closable;
|
let closable = state.closable;
|
||||||
@@ -647,7 +651,7 @@ impl TabPanel {
|
|||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.size_full()
|
.size_full()
|
||||||
.rounded_lg()
|
.rounded_xl()
|
||||||
.shadow_sm()
|
.shadow_sm()
|
||||||
.when(cx.theme().mode.is_dark(), |this| this.shadow_lg())
|
.when(cx.theme().mode.is_dark(), |this| this.shadow_lg())
|
||||||
.bg(cx.theme().panel_background)
|
.bg(cx.theme().panel_background)
|
||||||
@@ -667,7 +671,7 @@ impl TabPanel {
|
|||||||
.p_1()
|
.p_1()
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.rounded_lg()
|
.rounded_xl()
|
||||||
.border_1()
|
.border_1()
|
||||||
.border_color(cx.theme().element_disabled)
|
.border_color(cx.theme().element_disabled)
|
||||||
.bg(cx.theme().drop_target_background)
|
.bg(cx.theme().drop_target_background)
|
||||||
|
|||||||
@@ -405,13 +405,14 @@ impl Render for ResizablePanel {
|
|||||||
return div();
|
return div();
|
||||||
}
|
}
|
||||||
|
|
||||||
let view = cx.entity().clone();
|
|
||||||
let total_size = self
|
let total_size = self
|
||||||
.group
|
.group
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|group| group.upgrade())
|
.and_then(|group| group.upgrade())
|
||||||
.map(|group| group.read(cx).total_size());
|
.map(|group| group.read(cx).total_size());
|
||||||
|
|
||||||
|
let view = cx.entity();
|
||||||
|
|
||||||
div()
|
div()
|
||||||
.flex()
|
.flex()
|
||||||
.flex_grow()
|
.flex_grow()
|
||||||
|
|||||||
@@ -401,6 +401,14 @@ sidebar:
|
|||||||
en: "Incoming new conversations"
|
en: "Incoming new conversations"
|
||||||
trusted_contacts_tooltip:
|
trusted_contacts_tooltip:
|
||||||
en: "Only show rooms from trusted contacts"
|
en: "Only show rooms from trusted contacts"
|
||||||
|
no_requests:
|
||||||
|
en: "No message requests"
|
||||||
|
no_requests_label:
|
||||||
|
en: "New message requests from people you don't know will appear here."
|
||||||
|
no_conversations:
|
||||||
|
en: "No conversations"
|
||||||
|
no_conversations_label:
|
||||||
|
en: "Start a conversation with someone to get started."
|
||||||
|
|
||||||
loading:
|
loading:
|
||||||
label:
|
label:
|
||||||
|
|||||||
Reference in New Issue
Block a user