finish ui
This commit is contained in:
@@ -29,7 +29,7 @@ nostr = { git = "https://github.com/rust-nostr/nostr", features = [ "nip59", "ni
|
|||||||
|
|
||||||
# Others
|
# Others
|
||||||
anyhow = "1.0.44"
|
anyhow = "1.0.44"
|
||||||
chrono = "0.4.38"
|
chrono = { version = "0.4.38", features = ["wasmbind"] }
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
itertools = "0.13.0"
|
itertools = "0.13.0"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ pub trait StyledExt: Styled + Sized {
|
|||||||
.border_1()
|
.border_1()
|
||||||
.border_color(cx.theme().border)
|
.border_color(cx.theme().border)
|
||||||
.shadow_md()
|
.shadow_md()
|
||||||
.rounded(cx.theme().radius)
|
.rounded(cx.theme().radius_lg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ use device::{DeviceEvent, DeviceRegistry};
|
|||||||
use gpui::prelude::FluentBuilder;
|
use gpui::prelude::FluentBuilder;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
Action, App, AppContext, Axis, Context, Entity, InteractiveElement, IntoElement, ParentElement,
|
Action, App, AppContext, Axis, Context, Entity, InteractiveElement, IntoElement, ParentElement,
|
||||||
Render, SharedString, StatefulInteractiveElement, Styled, Subscription, Task, Window, div,
|
Render, SharedString, Styled, Subscription, Task, Window, div, image_cache, px,
|
||||||
image_cache, px, relative,
|
|
||||||
};
|
};
|
||||||
use nostr_sdk::prelude::*;
|
use nostr_sdk::prelude::*;
|
||||||
use person::{PersonRegistry, shorten_pubkey};
|
use person::{PersonRegistry, shorten_pubkey};
|
||||||
@@ -27,7 +26,7 @@ use ui::{Icon, IconName, Root, Sizable, TitleBar, WindowExtension, h_flex, v_fle
|
|||||||
use crate::dialogs::import::ImportIdentity;
|
use crate::dialogs::import::ImportIdentity;
|
||||||
use crate::dialogs::restore::RestoreEncryption;
|
use crate::dialogs::restore::RestoreEncryption;
|
||||||
use crate::dialogs::settings;
|
use crate::dialogs::settings;
|
||||||
use crate::panels::{backup, contact_list, greeter, messaging_relays, profile, relay_list, trash};
|
use crate::panels::{backup, contact_list, greeter, messaging_relays, profile, relay_list};
|
||||||
use crate::sidebar::Sidebar;
|
use crate::sidebar::Sidebar;
|
||||||
|
|
||||||
mod dialogs;
|
mod dialogs;
|
||||||
@@ -277,7 +276,7 @@ impl Workspace {
|
|||||||
self.dock.update(cx, |this, cx| {
|
self.dock.update(cx, |this, cx| {
|
||||||
this.add_panel(
|
this.add_panel(
|
||||||
Arc::new(profile::init(public_key, window, cx)),
|
Arc::new(profile::init(public_key, window, cx)),
|
||||||
DockPlacement::Right,
|
DockPlacement::Left,
|
||||||
window,
|
window,
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
@@ -288,7 +287,7 @@ impl Workspace {
|
|||||||
self.dock.update(cx, |this, cx| {
|
self.dock.update(cx, |this, cx| {
|
||||||
this.add_panel(
|
this.add_panel(
|
||||||
Arc::new(contact_list::init(window, cx)),
|
Arc::new(contact_list::init(window, cx)),
|
||||||
DockPlacement::Right,
|
DockPlacement::Left,
|
||||||
window,
|
window,
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
@@ -298,7 +297,7 @@ impl Workspace {
|
|||||||
self.dock.update(cx, |this, cx| {
|
self.dock.update(cx, |this, cx| {
|
||||||
this.add_panel(
|
this.add_panel(
|
||||||
Arc::new(backup::init(window, cx)),
|
Arc::new(backup::init(window, cx)),
|
||||||
DockPlacement::Right,
|
DockPlacement::Left,
|
||||||
window,
|
window,
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
@@ -308,7 +307,7 @@ impl Workspace {
|
|||||||
self.dock.update(cx, |this, cx| {
|
self.dock.update(cx, |this, cx| {
|
||||||
this.add_panel(
|
this.add_panel(
|
||||||
Arc::new(messaging_relays::init(window, cx)),
|
Arc::new(messaging_relays::init(window, cx)),
|
||||||
DockPlacement::Right,
|
DockPlacement::Left,
|
||||||
window,
|
window,
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
@@ -435,10 +434,11 @@ impl Workspace {
|
|||||||
let import = cx.new(|cx| ImportIdentity::new(window, cx));
|
let import = cx.new(|cx| ImportIdentity::new(window, cx));
|
||||||
|
|
||||||
window.open_modal(cx, move |this, _window, _cx| {
|
window.open_modal(cx, move |this, _window, _cx| {
|
||||||
this.width(px(420.))
|
this.width(px(450.))
|
||||||
.show_close(false)
|
.show_close(false)
|
||||||
.overlay_closable(false)
|
.overlay_closable(false)
|
||||||
.title("Import Identity")
|
.keyboard(false)
|
||||||
|
.title("Onboarding")
|
||||||
.child(import.clone())
|
.child(import.clone())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -598,9 +598,7 @@ impl Workspace {
|
|||||||
|
|
||||||
fn titlebar_right(&mut self, cx: &mut Context<Self>) -> impl IntoElement {
|
fn titlebar_right(&mut self, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
let chat = ChatRegistry::global(cx);
|
let chat = ChatRegistry::global(cx);
|
||||||
let trash_messages = chat.read(cx).count_trash_messages(cx);
|
let nip4e_enabled = AppSettings::get_nip4e(cx);
|
||||||
|
|
||||||
let is_nip4e_enabled = AppSettings::get_nip4e(cx);
|
|
||||||
let nostr = NostrRegistry::global(cx);
|
let nostr = NostrRegistry::global(cx);
|
||||||
|
|
||||||
let Some(public_key) = nostr.read(cx).current_user() else {
|
let Some(public_key) = nostr.read(cx).current_user() else {
|
||||||
@@ -614,39 +612,7 @@ impl Workspace {
|
|||||||
h_flex()
|
h_flex()
|
||||||
.when(!cx.theme().platform.is_mac(), |this| this.pr_2())
|
.when(!cx.theme().platform.is_mac(), |this| this.pr_2())
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.when(trash_messages > 0, |this| {
|
.when(nip4e_enabled, |this| {
|
||||||
this.child(
|
|
||||||
h_flex()
|
|
||||||
.id("trash-messages")
|
|
||||||
.h_6()
|
|
||||||
.px_1()
|
|
||||||
.gap_1()
|
|
||||||
.rounded(cx.theme().radius)
|
|
||||||
.hover(|this| this.bg(cx.theme().ghost_element_hover))
|
|
||||||
.child(
|
|
||||||
Icon::new(IconName::Warning)
|
|
||||||
.small()
|
|
||||||
.text_color(cx.theme().text_danger),
|
|
||||||
)
|
|
||||||
.child(
|
|
||||||
div()
|
|
||||||
.text_xs()
|
|
||||||
.line_height(relative(1.))
|
|
||||||
.child(format!("{trash_messages}")),
|
|
||||||
)
|
|
||||||
.on_click(move |_ev, window, cx| {
|
|
||||||
cx.stop_propagation();
|
|
||||||
// Add the trash panel to the center workspace
|
|
||||||
Self::add_panel(
|
|
||||||
trash::init(window, cx),
|
|
||||||
DockPlacement::Center,
|
|
||||||
window,
|
|
||||||
cx,
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.when(is_nip4e_enabled, |this| {
|
|
||||||
this.child(
|
this.child(
|
||||||
Button::new("key")
|
Button::new("key")
|
||||||
.icon(IconName::UserKey)
|
.icon(IconName::UserKey)
|
||||||
@@ -738,17 +704,7 @@ impl Workspace {
|
|||||||
.w_full()
|
.w_full()
|
||||||
.text_sm()
|
.text_sm()
|
||||||
.justify_between()
|
.justify_between()
|
||||||
.child(
|
.child(url.clone())
|
||||||
h_flex()
|
|
||||||
.gap_2()
|
|
||||||
.child(
|
|
||||||
div()
|
|
||||||
.size_1p5()
|
|
||||||
.rounded_full()
|
|
||||||
.bg(cx.theme().icon_accent),
|
|
||||||
)
|
|
||||||
.child(url.clone()),
|
|
||||||
)
|
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.text_xs()
|
.text_xs()
|
||||||
@@ -760,11 +716,6 @@ impl Workspace {
|
|||||||
|
|
||||||
// Footer
|
// Footer
|
||||||
menu.separator()
|
menu.separator()
|
||||||
.menu_with_icon(
|
|
||||||
"Reload",
|
|
||||||
IconName::Refresh,
|
|
||||||
Box::new(Command::RefreshMessagingRelays),
|
|
||||||
)
|
|
||||||
.menu_with_icon(
|
.menu_with_icon(
|
||||||
"Manage gossip relays",
|
"Manage gossip relays",
|
||||||
IconName::Relay,
|
IconName::Relay,
|
||||||
@@ -772,9 +723,15 @@ impl Workspace {
|
|||||||
)
|
)
|
||||||
.menu_with_icon(
|
.menu_with_icon(
|
||||||
"Manage messaging relays",
|
"Manage messaging relays",
|
||||||
IconName::Settings,
|
IconName::Relay,
|
||||||
Box::new(Command::ShowMessaging),
|
Box::new(Command::ShowMessaging),
|
||||||
)
|
)
|
||||||
|
.separator()
|
||||||
|
.menu_with_icon(
|
||||||
|
"Reload",
|
||||||
|
IconName::Refresh,
|
||||||
|
Box::new(Command::RefreshMessagingRelays),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ use ui::avatar::Avatar;
|
|||||||
use ui::button::{Button, ButtonVariants};
|
use ui::button::{Button, ButtonVariants};
|
||||||
use ui::dock::{Panel, PanelEvent};
|
use ui::dock::{Panel, PanelEvent};
|
||||||
use ui::input::{Input, InputEvent, InputState};
|
use ui::input::{Input, InputEvent, InputState};
|
||||||
|
use ui::scroll::ScrollableElement;
|
||||||
use ui::{Disableable, IconName, Sizable, StyledExt, WindowExtension, h_flex, v_flex};
|
use ui::{Disableable, IconName, Sizable, StyledExt, WindowExtension, h_flex, v_flex};
|
||||||
|
|
||||||
pub fn init(window: &mut Window, cx: &mut App) -> Entity<ContactListPanel> {
|
pub fn init(window: &mut Window, cx: &mut App) -> Entity<ContactListPanel> {
|
||||||
@@ -220,8 +221,7 @@ impl ContactListPanel {
|
|||||||
.px_2()
|
.px_2()
|
||||||
.justify_between()
|
.justify_between()
|
||||||
.rounded(cx.theme().radius)
|
.rounded(cx.theme().radius)
|
||||||
.bg(cx.theme().secondary_background)
|
.hover(|this| this.bg(cx.theme().ghost_element_hover))
|
||||||
.text_color(cx.theme().secondary_foreground)
|
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
@@ -283,74 +283,78 @@ impl Focusable for ContactListPanel {
|
|||||||
|
|
||||||
impl Render for ContactListPanel {
|
impl Render for ContactListPanel {
|
||||||
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 {
|
||||||
v_flex().p_3().gap_3().w_full().child(
|
v_flex()
|
||||||
v_flex()
|
.p_3()
|
||||||
.gap_2()
|
.gap_3()
|
||||||
.flex_1()
|
.w_full()
|
||||||
.w_full()
|
.overflow_y_scrollbar()
|
||||||
.text_sm()
|
.child(
|
||||||
.child(
|
v_flex()
|
||||||
div()
|
.gap_2()
|
||||||
.text_xs()
|
.flex_1()
|
||||||
.font_semibold()
|
.w_full()
|
||||||
.text_color(cx.theme().text_muted)
|
.text_sm()
|
||||||
.child(SharedString::from("New contact:")),
|
.child(
|
||||||
)
|
div()
|
||||||
.child(
|
.text_xs()
|
||||||
v_flex()
|
.font_semibold()
|
||||||
.gap_1()
|
.text_color(cx.theme().text_muted)
|
||||||
.child(
|
.child("New contact:"),
|
||||||
h_flex()
|
)
|
||||||
.gap_1()
|
.child(
|
||||||
.w_full()
|
v_flex()
|
||||||
.child(Input::new(&self.input).small().cleanable(true))
|
.gap_1()
|
||||||
.child(
|
.child(
|
||||||
Button::new("add")
|
h_flex()
|
||||||
.icon(IconName::Plus)
|
.gap_1()
|
||||||
.tooltip("Add contact")
|
.w_full()
|
||||||
.ghost()
|
.child(Input::new(&self.input).small().cleanable(true))
|
||||||
.size(rems(2.))
|
.child(
|
||||||
.on_click(cx.listener(move |this, _, window, cx| {
|
Button::new("add")
|
||||||
this.add(window, cx);
|
.icon(IconName::Plus)
|
||||||
})),
|
.tooltip("Add contact")
|
||||||
),
|
.ghost()
|
||||||
)
|
.size(rems(2.))
|
||||||
.when_some(self.error.as_ref(), |this, error| {
|
.on_click(cx.listener(move |this, _, window, cx| {
|
||||||
this.child(
|
this.add(window, cx);
|
||||||
div()
|
})),
|
||||||
.italic()
|
),
|
||||||
.text_xs()
|
|
||||||
.text_color(cx.theme().text_danger)
|
|
||||||
.child(error.clone()),
|
|
||||||
)
|
)
|
||||||
}),
|
.when_some(self.error.as_ref(), |this, error| {
|
||||||
)
|
this.child(
|
||||||
.map(|this| {
|
div()
|
||||||
if self.contacts.is_empty() {
|
.italic()
|
||||||
this.child(self.render_empty(window, cx))
|
.text_xs()
|
||||||
} else {
|
.text_color(cx.theme().text_danger)
|
||||||
this.child(
|
.child(error.clone()),
|
||||||
v_flex()
|
)
|
||||||
.gap_1()
|
}),
|
||||||
.flex_1()
|
)
|
||||||
.w_full()
|
.map(|this| {
|
||||||
.children(self.render_list_items(cx)),
|
if self.contacts.is_empty() {
|
||||||
)
|
this.child(self.render_empty(window, cx))
|
||||||
}
|
} else {
|
||||||
})
|
this.child(
|
||||||
.child(
|
v_flex()
|
||||||
Button::new("submit")
|
.gap_1()
|
||||||
.icon(IconName::CheckCircle)
|
.flex_1()
|
||||||
.label("Update")
|
.w_full()
|
||||||
.primary()
|
.children(self.render_list_items(cx)),
|
||||||
.small()
|
)
|
||||||
.font_semibold()
|
}
|
||||||
.loading(self.updating)
|
})
|
||||||
.disabled(self.updating)
|
.child(
|
||||||
.on_click(cx.listener(move |this, _ev, window, cx| {
|
Button::new("submit")
|
||||||
this.update(window, cx);
|
.icon(IconName::CheckCircle)
|
||||||
})),
|
.label("Update")
|
||||||
),
|
.primary()
|
||||||
)
|
.font_semibold()
|
||||||
|
.loading(self.updating)
|
||||||
|
.disabled(self.updating)
|
||||||
|
.on_click(cx.listener(move |this, _ev, window, cx| {
|
||||||
|
this.update(window, cx);
|
||||||
|
})),
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ use ui::button::{Button, ButtonVariants};
|
|||||||
use ui::dock::{DockPlacement, Panel, PanelEvent};
|
use ui::dock::{DockPlacement, Panel, PanelEvent};
|
||||||
use ui::{Icon, IconName, Sizable, StyledExt, h_flex, v_flex};
|
use ui::{Icon, IconName, Sizable, StyledExt, h_flex, v_flex};
|
||||||
|
|
||||||
use crate::Workspace;
|
|
||||||
use crate::panels::profile;
|
use crate::panels::profile;
|
||||||
|
use crate::{Command, Workspace};
|
||||||
|
|
||||||
pub fn init(window: &mut Window, cx: &mut App) -> Entity<GreeterPanel> {
|
pub fn init(window: &mut Window, cx: &mut App) -> Entity<GreeterPanel> {
|
||||||
cx.new(|cx| GreeterPanel::new(window, cx))
|
cx.new(|cx| GreeterPanel::new(window, cx))
|
||||||
@@ -146,17 +146,20 @@ impl Render for GreeterPanel {
|
|||||||
.ghost()
|
.ghost()
|
||||||
.small()
|
.small()
|
||||||
.justify_start()
|
.justify_start()
|
||||||
.on_click(cx.listener(move |this, _ev, window, cx| {
|
.on_click(cx.listener(move |this, _, window, cx| {
|
||||||
this.add_profile_panel(window, cx)
|
this.add_profile_panel(window, cx)
|
||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
Button::new("invite")
|
Button::new("theme")
|
||||||
.icon(Icon::new(IconName::Invite))
|
.icon(Icon::new(IconName::Moon))
|
||||||
.label("Invite friends")
|
.label("Change theme")
|
||||||
.ghost()
|
.ghost()
|
||||||
.small()
|
.small()
|
||||||
.justify_start(),
|
.justify_start()
|
||||||
|
.on_click(cx.listener(move |_, _, _, cx| {
|
||||||
|
cx.dispatch_action(&Command::ToggleTheme);
|
||||||
|
})),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -360,7 +360,6 @@ impl Render for MessagingRelayPanel {
|
|||||||
.icon(IconName::CheckCircle)
|
.icon(IconName::CheckCircle)
|
||||||
.label("Update")
|
.label("Update")
|
||||||
.primary()
|
.primary()
|
||||||
.small()
|
|
||||||
.font_semibold()
|
.font_semibold()
|
||||||
.loading(self.updating)
|
.loading(self.updating)
|
||||||
.disabled(self.updating)
|
.disabled(self.updating)
|
||||||
|
|||||||
@@ -4,4 +4,3 @@ pub mod greeter;
|
|||||||
pub mod messaging_relays;
|
pub mod messaging_relays;
|
||||||
pub mod profile;
|
pub mod profile;
|
||||||
pub mod relay_list;
|
pub mod relay_list;
|
||||||
pub mod trash;
|
|
||||||
|
|||||||
@@ -419,7 +419,6 @@ impl Render for ProfilePanel {
|
|||||||
.icon(IconName::CheckCircle)
|
.icon(IconName::CheckCircle)
|
||||||
.label("Update")
|
.label("Update")
|
||||||
.primary()
|
.primary()
|
||||||
.small()
|
|
||||||
.font_semibold()
|
.font_semibold()
|
||||||
.loading(self.updating)
|
.loading(self.updating)
|
||||||
.disabled(self.updating)
|
.disabled(self.updating)
|
||||||
|
|||||||
@@ -429,7 +429,6 @@ impl Render for RelayListPanel {
|
|||||||
.icon(IconName::CheckCircle)
|
.icon(IconName::CheckCircle)
|
||||||
.label("Update")
|
.label("Update")
|
||||||
.primary()
|
.primary()
|
||||||
.small()
|
|
||||||
.font_semibold()
|
.font_semibold()
|
||||||
.loading(self.updating)
|
.loading(self.updating)
|
||||||
.disabled(self.updating)
|
.disabled(self.updating)
|
||||||
|
|||||||
@@ -1,152 +0,0 @@
|
|||||||
use chat::ChatRegistry;
|
|
||||||
use gpui::{
|
|
||||||
AnyElement, App, AppContext, ClipboardItem, Context, Entity, EventEmitter, FocusHandle,
|
|
||||||
Focusable, InteractiveElement, IntoElement, ListAlignment, ListState, ParentElement, Render,
|
|
||||||
SharedString, Styled, Window, div, list, px, relative,
|
|
||||||
};
|
|
||||||
use theme::ActiveTheme;
|
|
||||||
use ui::button::{Button, ButtonVariants};
|
|
||||||
use ui::dock::{Panel, PanelEvent};
|
|
||||||
use ui::scroll::Scrollbar;
|
|
||||||
use ui::{Icon, IconName, Sizable, h_flex, v_flex};
|
|
||||||
|
|
||||||
pub fn init(window: &mut Window, cx: &mut App) -> Entity<TrashPanel> {
|
|
||||||
cx.new(|cx| TrashPanel::new(window, cx))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct TrashPanel {
|
|
||||||
name: SharedString,
|
|
||||||
focus_handle: FocusHandle,
|
|
||||||
|
|
||||||
/// List state for messages
|
|
||||||
list_state: ListState,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TrashPanel {
|
|
||||||
fn new(_window: &mut Window, cx: &mut App) -> Self {
|
|
||||||
let chat = ChatRegistry::global(cx);
|
|
||||||
let count = chat.read(cx).count_trash_messages(cx);
|
|
||||||
let list_state = ListState::new(count, ListAlignment::Bottom, px(1024.));
|
|
||||||
|
|
||||||
Self {
|
|
||||||
name: "Trash".into(),
|
|
||||||
focus_handle: cx.focus_handle(),
|
|
||||||
list_state,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn copy(&self, ix: usize, cx: &App) {
|
|
||||||
let chat = ChatRegistry::global(cx);
|
|
||||||
let trash_events = chat.read(cx).trash();
|
|
||||||
|
|
||||||
if let Some(message) = trash_events.read(cx).iter().nth(ix) {
|
|
||||||
let item = ClipboardItem::new_string(message.raw_event.to_string());
|
|
||||||
cx.write_to_clipboard(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_list_item(
|
|
||||||
&mut self,
|
|
||||||
ix: usize,
|
|
||||||
_window: &mut Window,
|
|
||||||
cx: &mut Context<Self>,
|
|
||||||
) -> AnyElement {
|
|
||||||
let chat = ChatRegistry::global(cx);
|
|
||||||
let trash_events = chat.read(cx).trash();
|
|
||||||
|
|
||||||
if let Some(message) = trash_events.read(cx).iter().nth(ix) {
|
|
||||||
v_flex()
|
|
||||||
.id(ix)
|
|
||||||
.p_2()
|
|
||||||
.w_full()
|
|
||||||
.child(
|
|
||||||
v_flex()
|
|
||||||
.p_2()
|
|
||||||
.w_full()
|
|
||||||
.gap_1()
|
|
||||||
.rounded(cx.theme().radius_lg)
|
|
||||||
.bg(cx.theme().surface_background)
|
|
||||||
.text_sm()
|
|
||||||
.child(
|
|
||||||
div()
|
|
||||||
.text_color(cx.theme().text_danger)
|
|
||||||
.child(message.reason.clone()),
|
|
||||||
)
|
|
||||||
.child(
|
|
||||||
h_flex()
|
|
||||||
.h_10()
|
|
||||||
.w_full()
|
|
||||||
.px_2()
|
|
||||||
.justify_between()
|
|
||||||
.bg(cx.theme().elevated_surface_background)
|
|
||||||
.border_1()
|
|
||||||
.border_color(cx.theme().border)
|
|
||||||
.rounded(cx.theme().radius)
|
|
||||||
.child(
|
|
||||||
div()
|
|
||||||
.truncate()
|
|
||||||
.text_ellipsis()
|
|
||||||
.text_xs()
|
|
||||||
.line_height(relative(1.))
|
|
||||||
.child(message.raw_event.clone()),
|
|
||||||
)
|
|
||||||
.child(
|
|
||||||
Button::new(format!("copy-{ix}"))
|
|
||||||
.icon(IconName::Copy)
|
|
||||||
.ghost()
|
|
||||||
.small()
|
|
||||||
.on_click(cx.listener(move |this, _ev, _window, cx| {
|
|
||||||
this.copy(ix, cx);
|
|
||||||
})),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.into_any_element()
|
|
||||||
} else {
|
|
||||||
div().id(ix).into_any_element()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Panel for TrashPanel {
|
|
||||||
fn panel_id(&self) -> SharedString {
|
|
||||||
self.name.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn title(&self, _cx: &App) -> AnyElement {
|
|
||||||
h_flex()
|
|
||||||
.gap_1()
|
|
||||||
.text_sm()
|
|
||||||
.child(Icon::new(IconName::Warning).small())
|
|
||||||
.child("Errors")
|
|
||||||
.into_any_element()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EventEmitter<PanelEvent> for TrashPanel {}
|
|
||||||
|
|
||||||
impl Focusable for TrashPanel {
|
|
||||||
fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
|
|
||||||
self.focus_handle.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Render for TrashPanel {
|
|
||||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
|
||||||
v_flex().size_full().relative().child(
|
|
||||||
v_flex()
|
|
||||||
.flex_1()
|
|
||||||
.relative()
|
|
||||||
.child(
|
|
||||||
list(
|
|
||||||
self.list_state.clone(),
|
|
||||||
cx.processor(move |this, ix, window, cx| {
|
|
||||||
this.render_list_item(ix, window, cx)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.size_full(),
|
|
||||||
)
|
|
||||||
.child(Scrollbar::vertical(&self.list_state)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -691,15 +691,16 @@ impl Render for Sidebar {
|
|||||||
this.child(
|
this.child(
|
||||||
div()
|
div()
|
||||||
.absolute()
|
.absolute()
|
||||||
.bottom_0()
|
.bottom_2()
|
||||||
.left_0()
|
.left_0()
|
||||||
.h_9()
|
.h_9()
|
||||||
.w_full()
|
.w_full()
|
||||||
.p_4()
|
.px_4()
|
||||||
.child(
|
.child(
|
||||||
Button::new("create")
|
Button::new("create")
|
||||||
.label(button_label)
|
.label(button_label)
|
||||||
.primary()
|
.primary()
|
||||||
|
.rounded()
|
||||||
.shadow_md()
|
.shadow_md()
|
||||||
.on_click(cx.listener(move |this, _ev, window, cx| {
|
.on_click(cx.listener(move |this, _ev, window, cx| {
|
||||||
this.create_room(window, cx);
|
this.create_room(window, cx);
|
||||||
|
|||||||
@@ -31,8 +31,10 @@ pub fn run() -> Result<(), JsValue> {
|
|||||||
|
|
||||||
#[cfg(target_family = "wasm")]
|
#[cfg(target_family = "wasm")]
|
||||||
gpui_platform::web_init();
|
gpui_platform::web_init();
|
||||||
|
|
||||||
#[cfg(not(target_family = "wasm"))]
|
#[cfg(not(target_family = "wasm"))]
|
||||||
let app = gpui_platform::application();
|
let app = gpui_platform::application();
|
||||||
|
|
||||||
#[cfg(target_family = "wasm")]
|
#[cfg(target_family = "wasm")]
|
||||||
let app = {
|
let app = {
|
||||||
let app = gpui_platform::single_threaded_web();
|
let app = gpui_platform::single_threaded_web();
|
||||||
|
|||||||
Reference in New Issue
Block a user