feat: automatically open the chat room
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
use std::{cmp::Reverse, collections::HashMap};
|
use std::{cmp::Reverse, collections::HashMap};
|
||||||
|
|
||||||
use anyhow::{anyhow, Error};
|
use anyhow::Error;
|
||||||
use common::room_hash;
|
use common::room_hash;
|
||||||
use global::get_client;
|
use global::get_client;
|
||||||
use gpui::{App, AppContext, Context, Entity, Global, Subscription, Task, Window};
|
use gpui::{App, AppContext, Context, Entity, Global, Subscription, Task, Window};
|
||||||
@@ -8,6 +8,7 @@ use itertools::Itertools;
|
|||||||
use nostr_sdk::prelude::*;
|
use nostr_sdk::prelude::*;
|
||||||
use room::RoomKind;
|
use room::RoomKind;
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
use ui::ContextModal;
|
||||||
|
|
||||||
use crate::room::Room;
|
use crate::room::Room;
|
||||||
|
|
||||||
@@ -261,21 +262,18 @@ impl ChatRegistry {
|
|||||||
/// Add a new room to the registry
|
/// Add a new room to the registry
|
||||||
///
|
///
|
||||||
/// Returns an error if the room already exists
|
/// Returns an error if the room already exists
|
||||||
pub fn push(&mut self, room: Room, cx: &mut Context<Self>) -> Result<(), anyhow::Error> {
|
pub fn push(&mut self, event: &Event, window: &mut Window, cx: &mut Context<Self>) -> u64 {
|
||||||
let room = cx.new(|_| room);
|
let room = Room::new(event).kind(RoomKind::Ongoing);
|
||||||
|
let id = room.id;
|
||||||
|
|
||||||
if !self
|
if !self.rooms.iter().any(|r| r.read(cx) == &room) {
|
||||||
.rooms
|
self.rooms.insert(0, cx.new(|_| room));
|
||||||
.iter()
|
|
||||||
.any(|current| current.read(cx) == room.read(cx))
|
|
||||||
{
|
|
||||||
self.rooms.insert(0, room);
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
|
||||||
Ok(())
|
|
||||||
} else {
|
} else {
|
||||||
Err(anyhow!("Room already exists"))
|
window.push_notification("Room already exists", cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Push a new message to a room
|
/// Push a new message to a room
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ use ui::{
|
|||||||
popup_menu::PopupMenu,
|
popup_menu::PopupMenu,
|
||||||
text::RichText,
|
text::RichText,
|
||||||
theme::{scale::ColorScaleStep, ActiveTheme},
|
theme::{scale::ColorScaleStep, ActiveTheme},
|
||||||
v_flex, ContextModal, Disableable, Icon, IconName, Size, StyledExt,
|
v_flex, ContextModal, Disableable, Icon, IconName, Sizable, Size, StyledExt,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::views::subject;
|
use crate::views::subject;
|
||||||
@@ -473,31 +473,33 @@ impl Panel for Chat {
|
|||||||
|
|
||||||
fn title(&self, cx: &App) -> AnyElement {
|
fn title(&self, cx: &App) -> AnyElement {
|
||||||
self.room.read_with(cx, |this, _| {
|
self.room.read_with(cx, |this, _| {
|
||||||
let facepill: Vec<SharedString> = this.avatars(cx);
|
let label = this.display_name(cx);
|
||||||
|
let url = this.display_image(cx);
|
||||||
|
|
||||||
div()
|
div()
|
||||||
.flex()
|
.flex()
|
||||||
.items_center()
|
.items_center()
|
||||||
.gap_1p5()
|
.gap_1p5()
|
||||||
.child(
|
.map(|this| {
|
||||||
div()
|
if let Some(url) = url {
|
||||||
.flex()
|
this.child(img(url).size_5().flex_shrink_0())
|
||||||
.flex_row_reverse()
|
} else {
|
||||||
.items_center()
|
this.child(
|
||||||
.justify_start()
|
div()
|
||||||
.children(
|
.flex_shrink_0()
|
||||||
facepill
|
.flex()
|
||||||
.into_iter()
|
.justify_center()
|
||||||
.enumerate()
|
.items_center()
|
||||||
.rev()
|
.size_5()
|
||||||
.map(|(ix, facepill)| {
|
.rounded_full()
|
||||||
div()
|
.bg(cx.theme().accent.step(cx, ColorScaleStep::THREE))
|
||||||
.when(ix > 0, |div| div.ml_neg_1())
|
.child(Icon::new(IconName::UsersThreeFill).xsmall().text_color(
|
||||||
.child(img(facepill).size_5())
|
cx.theme().accent.step(cx, ColorScaleStep::TWELVE),
|
||||||
}),
|
)),
|
||||||
),
|
)
|
||||||
)
|
}
|
||||||
.child(this.display_name(cx))
|
})
|
||||||
|
.child(label)
|
||||||
.into_any()
|
.into_any()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use chats::{
|
use chats::ChatRegistry;
|
||||||
room::{Room, RoomKind},
|
|
||||||
ChatRegistry,
|
|
||||||
};
|
|
||||||
use common::{profile::SharedProfile, random_name};
|
use common::{profile::SharedProfile, random_name};
|
||||||
use global::get_client;
|
use global::get_client;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
@@ -21,11 +18,14 @@ use std::{
|
|||||||
};
|
};
|
||||||
use ui::{
|
use ui::{
|
||||||
button::{Button, ButtonVariants},
|
button::{Button, ButtonVariants},
|
||||||
|
dock_area::dock::DockPlacement,
|
||||||
input::{InputEvent, TextInput},
|
input::{InputEvent, TextInput},
|
||||||
theme::{scale::ColorScaleStep, ActiveTheme},
|
theme::{scale::ColorScaleStep, ActiveTheme},
|
||||||
ContextModal, Disableable, Icon, IconName, Sizable, Size, StyledExt,
|
ContextModal, Disableable, Icon, IconName, Sizable, Size, StyledExt,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::chatspace::{AddPanel, PanelKind};
|
||||||
|
|
||||||
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Compose> {
|
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Compose> {
|
||||||
cx.new(|cx| Compose::new(window, cx))
|
cx.new(|cx| Compose::new(window, cx))
|
||||||
}
|
}
|
||||||
@@ -161,34 +161,26 @@ impl Compose {
|
|||||||
Ok(event)
|
Ok(event)
|
||||||
});
|
});
|
||||||
|
|
||||||
cx.spawn_in(window, async move |this, cx| {
|
cx.spawn_in(window, async move |this, cx| match event.await {
|
||||||
if let Ok(event) = event.await {
|
Ok(event) => {
|
||||||
cx.update(|window, cx| {
|
cx.update(|window, cx| {
|
||||||
this.update(cx, |this, cx| {
|
ChatRegistry::global(cx).update(cx, |chats, cx| {
|
||||||
this.set_submitting(false, cx);
|
let id = chats.push(&event, window, cx);
|
||||||
})
|
window.close_modal(cx);
|
||||||
.ok();
|
window.dispatch_action(
|
||||||
|
Box::new(AddPanel::new(PanelKind::Room(id), DockPlacement::Center)),
|
||||||
let chats = ChatRegistry::global(cx);
|
cx,
|
||||||
let room = Room::new(&event).kind(RoomKind::Ongoing);
|
);
|
||||||
|
|
||||||
chats.update(cx, |chats, cx| {
|
|
||||||
match chats.push(room, cx) {
|
|
||||||
Ok(_) => {
|
|
||||||
// TODO: automatically open newly created chat panel
|
|
||||||
window.close_modal(cx);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
this.update(cx, |this, cx| {
|
|
||||||
this.set_error(Some(e.to_string().into()), cx);
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
Err(e) => {
|
||||||
|
this.update(cx, |this, cx| {
|
||||||
|
this.set_error(Some(e.to_string().into()), cx);
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -284,6 +284,8 @@ impl Render for Relays {
|
|||||||
div()
|
div()
|
||||||
.track_focus(&self.focus_handle)
|
.track_focus(&self.focus_handle)
|
||||||
.size_full()
|
.size_full()
|
||||||
|
.px_3()
|
||||||
|
.pb_3()
|
||||||
.flex()
|
.flex()
|
||||||
.flex_col()
|
.flex_col()
|
||||||
.justify_between()
|
.justify_between()
|
||||||
|
|||||||
@@ -2,10 +2,7 @@ use std::time::Duration;
|
|||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use async_utility::task::spawn;
|
use async_utility::task::spawn;
|
||||||
use chats::{
|
use chats::ChatRegistry;
|
||||||
room::{Room, RoomKind},
|
|
||||||
ChatRegistry,
|
|
||||||
};
|
|
||||||
use common::profile::SharedProfile;
|
use common::profile::SharedProfile;
|
||||||
use global::{constants::SEARCH_RELAYS, get_client};
|
use global::{constants::SEARCH_RELAYS, get_client};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
@@ -18,12 +15,15 @@ use nostr_sdk::prelude::*;
|
|||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use ui::{
|
use ui::{
|
||||||
button::{Button, ButtonVariants},
|
button::{Button, ButtonVariants},
|
||||||
|
dock_area::dock::DockPlacement,
|
||||||
indicator::Indicator,
|
indicator::Indicator,
|
||||||
input::{InputEvent, TextInput},
|
input::{InputEvent, TextInput},
|
||||||
theme::{scale::ColorScaleStep, ActiveTheme},
|
theme::{scale::ColorScaleStep, ActiveTheme},
|
||||||
ContextModal, Disableable, IconName, Sizable,
|
ContextModal, Disableable, IconName, Sizable,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::chatspace::{AddPanel, PanelKind};
|
||||||
|
|
||||||
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Search> {
|
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Search> {
|
||||||
Search::new(window, cx)
|
Search::new(window, cx)
|
||||||
}
|
}
|
||||||
@@ -167,28 +167,25 @@ impl Search {
|
|||||||
Ok(event)
|
Ok(event)
|
||||||
});
|
});
|
||||||
|
|
||||||
cx.spawn_in(window, async move |this, cx| {
|
cx.spawn_in(window, async move |this, cx| match event.await {
|
||||||
if let Ok(event) = event.await {
|
Ok(event) => {
|
||||||
cx.update(|window, cx| {
|
cx.update(|window, cx| {
|
||||||
let chats = ChatRegistry::global(cx);
|
ChatRegistry::global(cx).update(cx, |chats, cx| {
|
||||||
let room = Room::new(&event).kind(RoomKind::Ongoing);
|
let id = chats.push(&event, window, cx);
|
||||||
|
window.close_modal(cx);
|
||||||
chats.update(cx, |chats, cx| {
|
window.dispatch_action(
|
||||||
match chats.push(room, cx) {
|
Box::new(AddPanel::new(PanelKind::Room(id), DockPlacement::Center)),
|
||||||
Ok(_) => {
|
cx,
|
||||||
// TODO: automatically open newly created chat panel
|
);
|
||||||
window.close_modal(cx);
|
});
|
||||||
}
|
})
|
||||||
Err(e) => {
|
.ok();
|
||||||
this.update(cx, |this, cx| {
|
}
|
||||||
this.error.update(cx, |this, cx| {
|
Err(e) => {
|
||||||
*this = Some(e.to_string().into());
|
this.update(cx, |this, cx| {
|
||||||
cx.notify();
|
this.error.update(cx, |this, cx| {
|
||||||
});
|
*this = Some(e.to_string().into());
|
||||||
})
|
cx.notify();
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
|
|||||||
@@ -306,6 +306,7 @@ impl RenderOnce for FolderItem {
|
|||||||
} else {
|
} else {
|
||||||
this.child(
|
this.child(
|
||||||
div()
|
div()
|
||||||
|
.flex_shrink_0()
|
||||||
.flex()
|
.flex()
|
||||||
.justify_center()
|
.justify_center()
|
||||||
.items_center()
|
.items_center()
|
||||||
|
|||||||
@@ -104,6 +104,28 @@ impl Sidebar {
|
|||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_logout(&mut self, _: &Logout, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
|
let task: Task<Result<(), anyhow::Error>> = cx.background_spawn(async move {
|
||||||
|
let client = get_client();
|
||||||
|
_ = client.reset().await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
|
||||||
|
cx.spawn_in(window, async move |_, cx| {
|
||||||
|
if task.await.is_ok() {
|
||||||
|
cx.update(|_, cx| {
|
||||||
|
Account::global(cx).update(cx, |this, cx| {
|
||||||
|
this.profile = None;
|
||||||
|
cx.notify();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
}
|
||||||
|
|
||||||
fn render_skeleton(&self, total: i32) -> impl IntoIterator<Item = impl IntoElement> {
|
fn render_skeleton(&self, total: i32) -> impl IntoIterator<Item = impl IntoElement> {
|
||||||
(0..total).map(|_| {
|
(0..total).map(|_| {
|
||||||
div()
|
div()
|
||||||
@@ -146,28 +168,6 @@ impl Sidebar {
|
|||||||
|
|
||||||
items
|
items
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_logout(&mut self, _: &Logout, window: &mut Window, cx: &mut Context<Self>) {
|
|
||||||
let task: Task<Result<(), anyhow::Error>> = cx.background_spawn(async move {
|
|
||||||
let client = get_client();
|
|
||||||
_ = client.reset().await;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
});
|
|
||||||
|
|
||||||
cx.spawn_in(window, async move |_, cx| {
|
|
||||||
if task.await.is_ok() {
|
|
||||||
cx.update(|_, cx| {
|
|
||||||
Account::global(cx).update(cx, |this, cx| {
|
|
||||||
this.profile = None;
|
|
||||||
cx.notify();
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Panel for Sidebar {
|
impl Panel for Sidebar {
|
||||||
@@ -206,6 +206,7 @@ impl Render for Sidebar {
|
|||||||
|
|
||||||
div()
|
div()
|
||||||
.id("sidebar")
|
.id("sidebar")
|
||||||
|
.track_focus(&self.focus_handle)
|
||||||
.track_scroll(&self.scroll_handle)
|
.track_scroll(&self.scroll_handle)
|
||||||
.on_action(cx.listener(Self::on_logout))
|
.on_action(cx.listener(Self::on_logout))
|
||||||
.overflow_y_scroll()
|
.overflow_y_scroll()
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ impl Render for Subject {
|
|||||||
.flex()
|
.flex()
|
||||||
.flex_col()
|
.flex_col()
|
||||||
.gap_3()
|
.gap_3()
|
||||||
|
.px_3()
|
||||||
|
.pb_3()
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.flex()
|
.flex()
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ impl Modal {
|
|||||||
let base = v_flex()
|
let base = v_flex()
|
||||||
.bg(cx.theme().background)
|
.bg(cx.theme().background)
|
||||||
.border_1()
|
.border_1()
|
||||||
.border_color(cx.theme().base.step(cx, ColorScaleStep::SEVEN))
|
.border_color(cx.theme().base.step(cx, ColorScaleStep::SIX))
|
||||||
.rounded_xl()
|
.rounded_xl()
|
||||||
.shadow_md();
|
.shadow_md();
|
||||||
|
|
||||||
@@ -169,9 +169,9 @@ impl RenderOnce for Modal {
|
|||||||
.w(view_size.width)
|
.w(view_size.width)
|
||||||
.h(view_size.height)
|
.h(view_size.height)
|
||||||
.when(self.overlay, |this| {
|
.when(self.overlay, |this| {
|
||||||
this.bg(cx.theme().base.step_alpha(cx, ColorScaleStep::EIGHT))
|
this.bg(cx.theme().base.step_alpha(cx, ColorScaleStep::TWO))
|
||||||
})
|
})
|
||||||
.when(self.closable, |this| {
|
.when(self.keyboard, |this| {
|
||||||
this.on_mouse_down(MouseButton::Left, {
|
this.on_mouse_down(MouseButton::Left, {
|
||||||
let on_close = self.on_close.clone();
|
let on_close = self.on_close.clone();
|
||||||
move |_, window, cx| {
|
move |_, window, cx| {
|
||||||
|
|||||||
Reference in New Issue
Block a user