migrate to gpui-component
This commit is contained in:
@@ -4,15 +4,26 @@ use std::sync::Arc;
|
||||
pub use actions::*;
|
||||
use anyhow::{Context as AnyhowContext, Error};
|
||||
use chat::{ChatRegistry, Message, RenderedMessage, Room, RoomEvent, SendReport, SendStatus};
|
||||
use common::{TimestampExt, coop_cache};
|
||||
use common::{CoopIcon, TimestampExt, coop_cache};
|
||||
use gpui::prelude::FluentBuilder;
|
||||
use gpui::{
|
||||
AnyElement, App, AppContext, ClipboardItem, Context, Entity, EventEmitter, FocusHandle,
|
||||
Focusable, InteractiveElement, IntoElement, ListAlignment, ListOffset, ListState, MouseButton,
|
||||
ObjectFit, ParentElement, PathPromptOptions, Render, SharedString, SharedUri,
|
||||
AnyElement, App, AppContext, ClipboardItem, Context, Element, Entity, EventEmitter,
|
||||
FocusHandle, Focusable, InteractiveElement, IntoElement, ListAlignment, ListOffset, ListState,
|
||||
MouseButton, ObjectFit, ParentElement, PathPromptOptions, Render, SharedString, SharedUri,
|
||||
StatefulInteractiveElement, Styled, StyledImage, Subscription, Task, WeakEntity, Window,
|
||||
deferred, div, img, list, px, red, relative, svg, white,
|
||||
};
|
||||
use gpui_component::avatar::Avatar;
|
||||
use gpui_component::button::{Button, ButtonVariants};
|
||||
use gpui_component::dock::{Panel, PanelEvent};
|
||||
use gpui_component::input::{Input, InputEvent, InputState};
|
||||
use gpui_component::menu::DropdownMenu;
|
||||
use gpui_component::notification::Notification;
|
||||
use gpui_component::scroll::Scrollbar;
|
||||
use gpui_component::{
|
||||
ActiveTheme, Disableable, Icon, InteractiveElementExt, Sizable, StyledExt, WindowExt, h_flex,
|
||||
v_flex,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use nostr_sdk::prelude::*;
|
||||
use person::{Person, PersonRegistry};
|
||||
@@ -20,18 +31,6 @@ use settings::{AppSettings, SignerKind};
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use smol::lock::RwLock;
|
||||
use state::{NostrRegistry, upload};
|
||||
use theme::ActiveTheme;
|
||||
use ui::avatar::Avatar;
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
use ui::dock::{Panel, PanelEvent};
|
||||
use ui::input::{InputEvent, InputState, TextInput};
|
||||
use ui::menu::DropdownMenu;
|
||||
use ui::notification::Notification;
|
||||
use ui::scroll::Scrollbar;
|
||||
use ui::{
|
||||
Disableable, Icon, IconName, InteractiveElementExt, Sizable, StyledExt, WindowExtension,
|
||||
h_flex, v_flex,
|
||||
};
|
||||
|
||||
use crate::text::RenderedText;
|
||||
|
||||
@@ -119,7 +118,7 @@ impl ChatPanel {
|
||||
InputState::new(window, cx)
|
||||
.placeholder(format!("Message {}", name))
|
||||
.auto_grow(1, 20)
|
||||
.prevent_new_line_on_enter()
|
||||
.submit_on_enter(true)
|
||||
.clean_on_escape()
|
||||
});
|
||||
|
||||
@@ -674,8 +673,8 @@ impl ChatPanel {
|
||||
let chat = ChatRegistry::global(cx);
|
||||
let seen_on = chat.read(cx).rumor_seen_on(id);
|
||||
|
||||
window.open_modal(cx, move |this, _window, cx| {
|
||||
this.title("Seen on").show_close(true).child(
|
||||
window.open_dialog(cx, move |this, _window, cx| {
|
||||
this.title("Seen on").close_button(true).child(
|
||||
v_flex()
|
||||
.gap_1()
|
||||
.when_none(&seen_on, |this| {
|
||||
@@ -684,7 +683,7 @@ impl ChatPanel {
|
||||
.h_10()
|
||||
.justify_center()
|
||||
.text_sm()
|
||||
.bg(cx.theme().elevated_surface_background)
|
||||
.bg(cx.theme().muted)
|
||||
.rounded(cx.theme().radius)
|
||||
.child("Message isn't traced yet"),
|
||||
)
|
||||
@@ -699,7 +698,7 @@ impl ChatPanel {
|
||||
.h_7()
|
||||
.px_2()
|
||||
.gap_2()
|
||||
.bg(cx.theme().elevated_surface_background)
|
||||
.bg(cx.theme().muted)
|
||||
.rounded(cx.theme().radius)
|
||||
.text_sm()
|
||||
.child(div().size_1p5().rounded_full().bg(gpui::green()))
|
||||
@@ -717,11 +716,11 @@ impl ChatPanel {
|
||||
fn open_relays(&mut self, public_key: &PublicKey, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let profile = self.profile(public_key, cx);
|
||||
|
||||
window.open_modal(cx, move |this, _window, cx| {
|
||||
window.open_dialog(cx, move |this, _window, cx| {
|
||||
let relays = profile.messaging_relays();
|
||||
|
||||
this.title("Messaging Relays")
|
||||
.show_close(true)
|
||||
.close_button(true)
|
||||
.child(v_flex().gap_1().children({
|
||||
let mut items = vec![];
|
||||
|
||||
@@ -731,7 +730,7 @@ impl ChatPanel {
|
||||
.h_7()
|
||||
.px_2()
|
||||
.gap_2()
|
||||
.bg(cx.theme().elevated_surface_background)
|
||||
.bg(cx.theme().muted)
|
||||
.rounded(cx.theme().radius)
|
||||
.text_sm()
|
||||
.child(div().size_1p5().rounded_full().bg(gpui::green()))
|
||||
@@ -760,13 +759,13 @@ impl ChatPanel {
|
||||
.justify_center()
|
||||
.text_center()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_placeholder)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.line_height(relative(1.3))
|
||||
.child(
|
||||
svg()
|
||||
.path("brand/coop.svg")
|
||||
.size_12()
|
||||
.text_color(cx.theme().ghost_element_active),
|
||||
.text_color(cx.theme().muted_foreground),
|
||||
)
|
||||
.child(SharedString::from(ANNOUNCEMENT))
|
||||
.into_any_element()
|
||||
@@ -789,9 +788,9 @@ impl ChatPanel {
|
||||
.size_8()
|
||||
.justify_center()
|
||||
.rounded_full()
|
||||
.bg(cx.theme().warning_background)
|
||||
.bg(cx.theme().warning)
|
||||
.text_color(cx.theme().warning_foreground)
|
||||
.child(Icon::new(IconName::Warning).small()),
|
||||
.child(Icon::new(CoopIcon::Warning).small()),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
@@ -867,15 +866,11 @@ impl ChatPanel {
|
||||
.gap_3()
|
||||
.when(!hide_avatar, |this| {
|
||||
this.child(
|
||||
Avatar::new(author.avatar())
|
||||
Avatar::new()
|
||||
.src(author.avatar())
|
||||
.name(author.name())
|
||||
.flex_shrink_0()
|
||||
.relative()
|
||||
.dropdown_menu(move |this, _window, _cx| {
|
||||
this.menu("Public Key", Box::new(Command::Copy(pk)))
|
||||
.menu("View Relays", Box::new(Command::Relays(pk)))
|
||||
.separator()
|
||||
.menu("View on njump.me", Box::new(Command::Njump(pk)))
|
||||
}),
|
||||
.relative(),
|
||||
)
|
||||
})
|
||||
.child(
|
||||
@@ -888,17 +883,17 @@ impl ChatPanel {
|
||||
h_flex()
|
||||
.gap_2()
|
||||
.text_sm()
|
||||
.text_color(cx.theme().text_placeholder)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(
|
||||
div()
|
||||
.font_semibold()
|
||||
.text_color(cx.theme().text)
|
||||
.text_color(cx.theme().foreground)
|
||||
.child(author.name()),
|
||||
)
|
||||
.when(encrypted_by_dekey, |this| {
|
||||
this.child(
|
||||
Button::new(format!("dekey-{ix}"))
|
||||
.icon(IconName::Shield)
|
||||
.icon(CoopIcon::Shield)
|
||||
.ghost()
|
||||
.xsmall()
|
||||
.px_4()
|
||||
@@ -920,13 +915,13 @@ impl ChatPanel {
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.group_hover("", |this| this.bg(cx.theme().element_active))
|
||||
.group_hover("", |this| this.bg(cx.theme().primary_active))
|
||||
.absolute()
|
||||
.left_0()
|
||||
.top_0()
|
||||
.w(px(2.))
|
||||
.h_full()
|
||||
.bg(cx.theme().border_transparent),
|
||||
.bg(cx.theme().transparent),
|
||||
)
|
||||
.child(self.render_actions(&id, &pk, cx))
|
||||
.on_mouse_down(
|
||||
@@ -938,7 +933,7 @@ impl ChatPanel {
|
||||
.on_double_click(cx.listener(move |this, _, _window, cx| {
|
||||
this.reply_to(&id, cx);
|
||||
}))
|
||||
.hover(|this| this.bg(cx.theme().surface_background))
|
||||
.hover(|this| this.bg(cx.theme().muted))
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
@@ -953,7 +948,7 @@ impl ChatPanel {
|
||||
return div().child(
|
||||
img(media[0].clone())
|
||||
.border_1()
|
||||
.border_color(cx.theme().border_variant)
|
||||
.border_color(cx.theme().border)
|
||||
.h(px(250.))
|
||||
.object_fit(ObjectFit::Cover)
|
||||
.rounded(cx.theme().radius),
|
||||
@@ -981,7 +976,7 @@ impl ChatPanel {
|
||||
img(item.clone())
|
||||
.h_32()
|
||||
.border_1()
|
||||
.border_color(cx.theme().border_variant)
|
||||
.border_color(cx.theme().border)
|
||||
.rounded(cx.theme().radius),
|
||||
),
|
||||
);
|
||||
@@ -1010,11 +1005,11 @@ impl ChatPanel {
|
||||
.w_full()
|
||||
.px_2()
|
||||
.border_l_2()
|
||||
.border_color(cx.theme().element_selected)
|
||||
.border_color(cx.theme().primary_active)
|
||||
.text_sm()
|
||||
.child(
|
||||
div()
|
||||
.text_color(cx.theme().text_accent)
|
||||
.text_color(cx.theme().accent_foreground)
|
||||
.child(author.name()),
|
||||
)
|
||||
.child(
|
||||
@@ -1024,7 +1019,7 @@ impl ChatPanel {
|
||||
.line_clamp(1)
|
||||
.child(SharedString::from(&message.content)),
|
||||
)
|
||||
.hover(|this| this.bg(cx.theme().elevated_surface_background))
|
||||
.hover(|this| this.bg(cx.theme().muted))
|
||||
.on_click({
|
||||
let id = *id;
|
||||
cx.listener(move |this, _event, _window, _cx| {
|
||||
@@ -1065,15 +1060,15 @@ impl ChatPanel {
|
||||
div()
|
||||
.id(SharedString::from(id.to_hex()))
|
||||
.child(label)
|
||||
.when(failed, |this| this.text_color(cx.theme().text_danger))
|
||||
.when(failed, |this| this.text_color(cx.theme().danger_foreground))
|
||||
.when_some(reports, |this, reports| {
|
||||
this.when(!pending, |this| {
|
||||
this.on_click(move |_e, window, cx| {
|
||||
let reports = reports.clone();
|
||||
|
||||
window.open_modal(cx, move |this, _window, cx| {
|
||||
window.open_dialog(cx, move |this, _window, cx| {
|
||||
this.title(SharedString::from("Sent Reports"))
|
||||
.show_close(true)
|
||||
.close_button(true)
|
||||
.child(v_flex().gap_4().children({
|
||||
let mut items = Vec::with_capacity(reports.len());
|
||||
|
||||
@@ -1107,7 +1102,7 @@ impl ChatPanel {
|
||||
h_flex()
|
||||
.gap_1()
|
||||
.font_semibold()
|
||||
.child(Avatar::new(avatar).small())
|
||||
.child(Avatar::new().src(avatar).name(name.clone()).small())
|
||||
.child(name.clone()),
|
||||
),
|
||||
)
|
||||
@@ -1121,7 +1116,7 @@ impl ChatPanel {
|
||||
.w_full()
|
||||
.text_sm()
|
||||
.rounded(cx.theme().radius)
|
||||
.bg(cx.theme().warning_background)
|
||||
.bg(cx.theme().warning)
|
||||
.text_color(cx.theme().warning_foreground)
|
||||
.child(div().flex_1().w_full().text_center().child(error)),
|
||||
)
|
||||
@@ -1141,7 +1136,7 @@ impl ChatPanel {
|
||||
.p_1()
|
||||
.w_full()
|
||||
.rounded(cx.theme().radius)
|
||||
.bg(cx.theme().danger_background)
|
||||
.bg(cx.theme().danger)
|
||||
.child(
|
||||
div()
|
||||
.text_xs()
|
||||
@@ -1171,7 +1166,7 @@ impl ChatPanel {
|
||||
.p_1()
|
||||
.w_full()
|
||||
.rounded(cx.theme().radius)
|
||||
.bg(cx.theme().elevated_surface_background)
|
||||
.bg(cx.theme().muted)
|
||||
.child(
|
||||
div()
|
||||
.text_xs()
|
||||
@@ -1214,7 +1209,7 @@ impl ChatPanel {
|
||||
.bg(cx.theme().background)
|
||||
.child(
|
||||
Button::new("reply")
|
||||
.icon(IconName::Reply)
|
||||
.icon(CoopIcon::Reply)
|
||||
.tooltip("Reply")
|
||||
.small()
|
||||
.ghost()
|
||||
@@ -1227,7 +1222,7 @@ impl ChatPanel {
|
||||
)
|
||||
.child(
|
||||
Button::new("copy")
|
||||
.icon(IconName::Copy)
|
||||
.icon(CoopIcon::Copy)
|
||||
.tooltip("Copy")
|
||||
.small()
|
||||
.ghost()
|
||||
@@ -1241,7 +1236,7 @@ impl ChatPanel {
|
||||
.child(div().flex_shrink_0().h_4().w_px().bg(cx.theme().border))
|
||||
.child(
|
||||
Button::new("advance")
|
||||
.icon(IconName::Ellipsis)
|
||||
.icon(CoopIcon::Ellipsis)
|
||||
.small()
|
||||
.ghost()
|
||||
.dropdown_menu({
|
||||
@@ -1279,7 +1274,7 @@ impl ChatPanel {
|
||||
.justify_center()
|
||||
.rounded_full()
|
||||
.bg(red())
|
||||
.child(Icon::new(IconName::Close).size_2().text_color(white())),
|
||||
.child(Icon::new(CoopIcon::Close).size_2().text_color(white())),
|
||||
)
|
||||
.on_click({
|
||||
let url = url.clone();
|
||||
@@ -1312,7 +1307,7 @@ impl ChatPanel {
|
||||
.w_full()
|
||||
.pl_2()
|
||||
.border_l_2()
|
||||
.border_color(cx.theme().element_active)
|
||||
.border_color(cx.theme().secondary_active)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
@@ -1324,17 +1319,17 @@ impl ChatPanel {
|
||||
.items_baseline()
|
||||
.gap_1()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from("Replying to:"))
|
||||
.child(
|
||||
div()
|
||||
.text_color(cx.theme().text_accent)
|
||||
.text_color(cx.theme().secondary_foreground)
|
||||
.child(profile.name()),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
Button::new("remove-reply")
|
||||
.icon(IconName::Close)
|
||||
.icon(CoopIcon::Close)
|
||||
.xsmall()
|
||||
.ghost()
|
||||
.on_click({
|
||||
@@ -1382,7 +1377,7 @@ impl ChatPanel {
|
||||
.unwrap_or((true, SignerKind::default()));
|
||||
|
||||
Button::new("encryption")
|
||||
.icon(IconName::Settings2)
|
||||
.icon(CoopIcon::Settings2)
|
||||
.tooltip("Configuration")
|
||||
.ghost()
|
||||
.large()
|
||||
@@ -1418,11 +1413,11 @@ impl ChatPanel {
|
||||
|
||||
fn render_emoji_menu(&self, _window: &Window, _cx: &Context<Self>) -> impl IntoElement {
|
||||
Button::new("emoji")
|
||||
.icon(IconName::Emoji)
|
||||
.icon(CoopIcon::Emoji)
|
||||
.ghost()
|
||||
.large()
|
||||
.dropdown_menu_with_anchor(gpui::Anchor::BottomLeft, move |this, _window, _cx| {
|
||||
this.horizontal()
|
||||
this.separator()
|
||||
.menu("👍", Box::new(Command::Insert("👍")))
|
||||
.menu("👎", Box::new(Command::Insert("👎")))
|
||||
.menu("😄", Box::new(Command::Insert("😄")))
|
||||
@@ -1436,11 +1431,11 @@ impl ChatPanel {
|
||||
}
|
||||
|
||||
impl Panel for ChatPanel {
|
||||
fn panel_id(&self) -> SharedString {
|
||||
self.id.clone()
|
||||
fn panel_name(&self) -> &'static str {
|
||||
"Chat"
|
||||
}
|
||||
|
||||
fn title(&self, cx: &App) -> AnyElement {
|
||||
fn title(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
self.room
|
||||
.read_with(cx, |this, cx| {
|
||||
let label = this.display_name(cx);
|
||||
@@ -1448,19 +1443,24 @@ impl Panel for ChatPanel {
|
||||
|
||||
h_flex()
|
||||
.gap_1p5()
|
||||
.child(Avatar::new(url).xsmall())
|
||||
.child(Avatar::new().src(url).xsmall())
|
||||
.child(label)
|
||||
.into_any_element()
|
||||
})
|
||||
.unwrap_or(div().child("Unknown").into_any_element())
|
||||
.unwrap_or(div().child("Unknown").into_any())
|
||||
.into_any()
|
||||
}
|
||||
|
||||
fn toolbar_buttons(&self, _window: &Window, _cx: &App) -> Vec<Button> {
|
||||
fn toolbar_buttons(
|
||||
&mut self,
|
||||
_window: &mut Window,
|
||||
_cx: &mut Context<Self>,
|
||||
) -> Option<Vec<Button>> {
|
||||
let subject_bar = self.subject_bar.clone();
|
||||
|
||||
vec![
|
||||
Some(vec![
|
||||
Button::new("subject")
|
||||
.icon(IconName::Input)
|
||||
.icon(CoopIcon::Input)
|
||||
.tooltip("Change subject")
|
||||
.small()
|
||||
.ghost()
|
||||
@@ -1470,7 +1470,7 @@ impl Panel for ChatPanel {
|
||||
cx.notify();
|
||||
});
|
||||
}),
|
||||
]
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1497,15 +1497,10 @@ impl Render for ChatPanel {
|
||||
.gap_2()
|
||||
.border_b_1()
|
||||
.border_color(cx.theme().border)
|
||||
.child(
|
||||
TextInput::new(&self.subject_input)
|
||||
.text_sm()
|
||||
.small()
|
||||
.bordered(false),
|
||||
)
|
||||
.child(Input::new(&self.subject_input).text_sm().bordered(false))
|
||||
.child(
|
||||
Button::new("change")
|
||||
.icon(IconName::CheckCircle)
|
||||
.icon(CoopIcon::CheckCircle)
|
||||
.label("Change")
|
||||
.secondary()
|
||||
.disabled(self.uploading)
|
||||
@@ -1543,7 +1538,7 @@ impl Render for ChatPanel {
|
||||
.items_end()
|
||||
.child(
|
||||
Button::new("upload")
|
||||
.icon(IconName::Plus)
|
||||
.icon(CoopIcon::Plus)
|
||||
.tooltip("Upload media")
|
||||
.loading(self.uploading)
|
||||
.disabled(self.uploading)
|
||||
@@ -1553,12 +1548,7 @@ impl Render for ChatPanel {
|
||||
this.upload(window, cx);
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
TextInput::new(&self.input)
|
||||
.appearance(false)
|
||||
.text_sm()
|
||||
.flex_1(),
|
||||
)
|
||||
.child(Input::new(&self.input).appearance(false).text_sm().flex_1())
|
||||
.child(
|
||||
h_flex()
|
||||
.pl_1()
|
||||
@@ -1567,7 +1557,7 @@ impl Render for ChatPanel {
|
||||
.child(self.render_config_menu(window, cx))
|
||||
.child(
|
||||
Button::new("send")
|
||||
.icon(IconName::PaperPlaneFill)
|
||||
.icon(CoopIcon::PaperPlaneFill)
|
||||
.disabled(self.uploading)
|
||||
.ghost()
|
||||
.large()
|
||||
|
||||
Reference in New Issue
Block a user