update
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
pub mod import;
|
||||
pub mod new_chat;
|
||||
pub mod new_community;
|
||||
pub mod restore;
|
||||
pub mod settings;
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
use chat::{ChatRegistry, Room, RoomKind};
|
||||
use gpui::prelude::FluentBuilder;
|
||||
use gpui::{
|
||||
App, AppContext, Context, Entity, IntoElement, ParentElement, Render, SharedString, Styled,
|
||||
Subscription, Window, div, px,
|
||||
};
|
||||
use nostr_sdk::prelude::*;
|
||||
use state::NostrRegistry;
|
||||
use theme::ActiveTheme;
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
use ui::input::{Input, InputEvent, InputState};
|
||||
use ui::{StyledExt, WindowExtension, v_flex};
|
||||
|
||||
pub fn open(window: &mut Window, cx: &mut App) {
|
||||
let view = cx.new(|cx| NewChat::new(window, cx));
|
||||
|
||||
window.open_modal(cx, move |this, _window, _cx| {
|
||||
this.width(px(420.)).title("New chat").child(view.clone())
|
||||
});
|
||||
}
|
||||
|
||||
pub struct NewChat {
|
||||
/// Public key input
|
||||
input: Entity<InputState>,
|
||||
|
||||
/// Error message
|
||||
error: Option<SharedString>,
|
||||
|
||||
/// Input subscription
|
||||
_subscription: Option<Subscription>,
|
||||
}
|
||||
|
||||
impl NewChat {
|
||||
fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||
let input = cx.new(|cx| InputState::new(window, cx).placeholder("npub"));
|
||||
|
||||
let subscription = cx.subscribe_in(&input, window, |this, _input, event, window, cx| {
|
||||
if let InputEvent::PressEnter { .. } = event {
|
||||
this.start_chat(window, cx);
|
||||
}
|
||||
});
|
||||
|
||||
Self {
|
||||
input,
|
||||
error: None,
|
||||
_subscription: Some(subscription),
|
||||
}
|
||||
}
|
||||
|
||||
fn start_chat(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let value = self.input.read(cx).value().to_string();
|
||||
|
||||
let Ok(peer) = PublicKey::parse(&value) else {
|
||||
self.set_error("Public key is invalid", cx);
|
||||
return;
|
||||
};
|
||||
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
let Some(current_user) = nostr.read(cx).current_user() else {
|
||||
self.set_error("You are not signed in", cx);
|
||||
return;
|
||||
};
|
||||
|
||||
if peer == current_user {
|
||||
self.set_error("You cannot chat with yourself", cx);
|
||||
return;
|
||||
}
|
||||
|
||||
let room = Room::new(current_user, [peer])
|
||||
.organize(¤t_user)
|
||||
.kind(RoomKind::Ongoing);
|
||||
|
||||
let chat = ChatRegistry::global(cx);
|
||||
chat.update(cx, |chat, cx| {
|
||||
let room = cx.new(|_| room);
|
||||
chat.emit_room(&room, window, cx);
|
||||
});
|
||||
|
||||
window.close_modal(cx);
|
||||
}
|
||||
|
||||
fn set_error(&mut self, message: impl Into<SharedString>, cx: &mut Context<Self>) {
|
||||
self.error = Some(message.into());
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for NewChat {
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
v_flex()
|
||||
.gap_4()
|
||||
.child(
|
||||
v_flex()
|
||||
.gap_1()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.child("Public key of the person you want to chat with")
|
||||
.child(Input::new(&self.input)),
|
||||
)
|
||||
.child(
|
||||
Button::new("start-chat")
|
||||
.label("Start chat")
|
||||
.primary()
|
||||
.font_semibold()
|
||||
.on_click(cx.listener(|this, _event, window, cx| {
|
||||
this.start_chat(window, cx);
|
||||
})),
|
||||
)
|
||||
.when_some(self.error.clone(), |this, error| {
|
||||
this.child(
|
||||
div()
|
||||
.text_xs()
|
||||
.text_center()
|
||||
.text_color(cx.theme().text_danger)
|
||||
.child(error),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
use community::{CommunityMetadata, CommunityRegistry};
|
||||
use gpui::{App, AppContext, ParentElement, Window, px};
|
||||
use ui::WindowExtension;
|
||||
use ui::input::{Input, InputState};
|
||||
|
||||
pub fn open(window: &mut Window, cx: &mut App) {
|
||||
let name_input = cx.new(|cx| InputState::new(window, cx).placeholder("Community name"));
|
||||
|
||||
window.open_modal(cx, move |this, _window, _cx| {
|
||||
let name_input = name_input.clone();
|
||||
|
||||
this.width(px(380.))
|
||||
.confirm()
|
||||
.title("New community")
|
||||
.child(Input::new(&name_input))
|
||||
.on_ok(move |_event, _window, cx| {
|
||||
let name = name_input.read(cx).value().trim().to_owned();
|
||||
|
||||
if name.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let metadata = CommunityMetadata {
|
||||
name,
|
||||
..CommunityMetadata::default()
|
||||
};
|
||||
|
||||
CommunityRegistry::global(cx)
|
||||
.update(cx, |registry, cx| registry.create(metadata, cx));
|
||||
|
||||
true
|
||||
})
|
||||
});
|
||||
}
|
||||
@@ -26,7 +26,7 @@ use ui::{Icon, IconName, Root, Sizable, WindowExtension, h_flex, v_flex};
|
||||
|
||||
use crate::dialogs::import::ImportIdentity;
|
||||
use crate::dialogs::restore::RestoreEncryption;
|
||||
use crate::dialogs::settings;
|
||||
use crate::dialogs::{new_chat, new_community, settings};
|
||||
use crate::panels::{
|
||||
backup, browse, contact_list, greeter, inbox, messaging_relays, profile, relay_list, requests,
|
||||
search,
|
||||
@@ -64,6 +64,8 @@ enum Command {
|
||||
ShowRequests,
|
||||
ShowBrowse,
|
||||
ShowSearch,
|
||||
NewChat,
|
||||
NewCommunity,
|
||||
}
|
||||
|
||||
pub struct Workspace {
|
||||
@@ -324,6 +326,12 @@ impl Workspace {
|
||||
Command::ShowSearch => {
|
||||
self.add_panel_to_dock(search::init(window, cx), DockPlacement::Center, window, cx);
|
||||
}
|
||||
Command::NewChat => {
|
||||
new_chat::open(window, cx);
|
||||
}
|
||||
Command::NewCommunity => {
|
||||
new_community::open(window, cx);
|
||||
}
|
||||
Command::ShowBackup => {
|
||||
self.add_panel_to_dock(backup::init(window, cx), DockPlacement::Left, window, cx);
|
||||
}
|
||||
|
||||
@@ -22,10 +22,11 @@ use ui::dock::{Panel, PanelEvent};
|
||||
use ui::indicator::Indicator;
|
||||
use ui::menu::{DropdownMenu, PopupMenuItem};
|
||||
use ui::nav_item::NavItem;
|
||||
use ui::notification::Notification;
|
||||
use ui::scroll::Scrollbar;
|
||||
use ui::{
|
||||
Icon, IconName, Sizable, StyledExt, TRAFFIC_LIGHT_PADDING, h_flex, title_bar_drag_handlers,
|
||||
v_flex,
|
||||
Icon, IconName, Sizable, StyledExt, TRAFFIC_LIGHT_PADDING, WindowExtension, h_flex,
|
||||
title_bar_drag_handlers, v_flex,
|
||||
};
|
||||
|
||||
use crate::Command;
|
||||
@@ -62,13 +63,16 @@ impl Sidebar {
|
||||
}),
|
||||
);
|
||||
|
||||
subscriptions.push(
|
||||
cx.subscribe(&communities, |_this, _communities, event, _cx| {
|
||||
subscriptions.push(cx.subscribe_in(
|
||||
&communities,
|
||||
window,
|
||||
|_this, _communities, event, window, cx| {
|
||||
if let CommunityEvent::Error(error) = event {
|
||||
log::error!("community: {error}");
|
||||
window
|
||||
.push_notification(Notification::error(error.clone()).autohide(false), cx);
|
||||
}
|
||||
}),
|
||||
);
|
||||
},
|
||||
));
|
||||
|
||||
Self {
|
||||
focus_handle: cx.focus_handle(),
|
||||
@@ -456,7 +460,7 @@ impl Render for Sidebar {
|
||||
.border_r_1()
|
||||
.border_color(cx.theme().border_variant)
|
||||
.child(self.render_user(window, cx))
|
||||
.when(active_tab == SidebarTab::Chats, |this| {
|
||||
.when(active_tab.chat(), |this| {
|
||||
this.child(
|
||||
v_flex()
|
||||
.px_2()
|
||||
@@ -492,16 +496,43 @@ impl Render for Sidebar {
|
||||
window.dispatch_action(Box::new(Command::ShowRequests), cx);
|
||||
}
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
NavItem::new(
|
||||
"nav-new-chat",
|
||||
"New chat",
|
||||
Icon::new(IconName::Plus).small(),
|
||||
)
|
||||
.on_click(|_event, window, cx| {
|
||||
window.dispatch_action(Box::new(Command::NewChat), cx)
|
||||
}),
|
||||
),
|
||||
)
|
||||
})
|
||||
.when(active_tab == SidebarTab::Communities, |this| {
|
||||
.when(active_tab.community(), |this| {
|
||||
this.child(
|
||||
v_flex().px_2().gap_1().child(
|
||||
NavItem::new("nav-browse", "Browse", Icon::new(IconName::Compass).small())
|
||||
v_flex()
|
||||
.px_2()
|
||||
.gap_1()
|
||||
.child(
|
||||
NavItem::new(
|
||||
"nav-browse",
|
||||
"Browse",
|
||||
Icon::new(IconName::Compass).small(),
|
||||
)
|
||||
.on_click(|_event, window, cx| {
|
||||
window.dispatch_action(Box::new(Command::ShowBrowse), cx)
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
NavItem::new(
|
||||
"nav-new-community",
|
||||
"New community",
|
||||
Icon::new(IconName::Plus).small(),
|
||||
)
|
||||
.on_click(|_event, window, cx| {
|
||||
window.dispatch_action(Box::new(Command::NewCommunity), cx)
|
||||
}),
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
@@ -47,6 +47,18 @@ impl SidebarTab {
|
||||
Self::Communities => 2,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recents(self) -> bool {
|
||||
matches!(self, Self::Recents)
|
||||
}
|
||||
|
||||
pub fn chat(self) -> bool {
|
||||
matches!(self, Self::Chats)
|
||||
}
|
||||
|
||||
pub fn community(self) -> bool {
|
||||
matches!(self, Self::Communities)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(IntoElement)]
|
||||
|
||||
Reference in New Issue
Block a user