feat: automatically open the chat room

This commit is contained in:
2025-05-04 10:12:15 +07:00
parent 3bd8592f86
commit 3fea18f038
9 changed files with 105 additions and 110 deletions

View File

@@ -1,6 +1,6 @@
use std::{cmp::Reverse, collections::HashMap};
use anyhow::{anyhow, Error};
use anyhow::Error;
use common::room_hash;
use global::get_client;
use gpui::{App, AppContext, Context, Entity, Global, Subscription, Task, Window};
@@ -8,6 +8,7 @@ use itertools::Itertools;
use nostr_sdk::prelude::*;
use room::RoomKind;
use smallvec::{smallvec, SmallVec};
use ui::ContextModal;
use crate::room::Room;
@@ -261,21 +262,18 @@ impl ChatRegistry {
/// Add a new room to the registry
///
/// Returns an error if the room already exists
pub fn push(&mut self, room: Room, cx: &mut Context<Self>) -> Result<(), anyhow::Error> {
let room = cx.new(|_| room);
pub fn push(&mut self, event: &Event, window: &mut Window, cx: &mut Context<Self>) -> u64 {
let room = Room::new(event).kind(RoomKind::Ongoing);
let id = room.id;
if !self
.rooms
.iter()
.any(|current| current.read(cx) == room.read(cx))
{
self.rooms.insert(0, room);
if !self.rooms.iter().any(|r| r.read(cx) == &room) {
self.rooms.insert(0, cx.new(|_| room));
cx.notify();
Ok(())
} else {
Err(anyhow!("Room already exists"))
window.push_notification("Room already exists", cx);
}
id
}
/// Push a new message to a room

View File

@@ -28,7 +28,7 @@ use ui::{
popup_menu::PopupMenu,
text::RichText,
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;
@@ -473,31 +473,33 @@ impl Panel for Chat {
fn title(&self, cx: &App) -> AnyElement {
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()
.flex()
.items_center()
.gap_1p5()
.child(
.map(|this| {
if let Some(url) = url {
this.child(img(url).size_5().flex_shrink_0())
} else {
this.child(
div()
.flex_shrink_0()
.flex()
.flex_row_reverse()
.justify_center()
.items_center()
.justify_start()
.children(
facepill
.into_iter()
.enumerate()
.rev()
.map(|(ix, facepill)| {
div()
.when(ix > 0, |div| div.ml_neg_1())
.child(img(facepill).size_5())
}),
),
.size_5()
.rounded_full()
.bg(cx.theme().accent.step(cx, ColorScaleStep::THREE))
.child(Icon::new(IconName::UsersThreeFill).xsmall().text_color(
cx.theme().accent.step(cx, ColorScaleStep::TWELVE),
)),
)
.child(this.display_name(cx))
}
})
.child(label)
.into_any()
})
}

View File

@@ -1,8 +1,5 @@
use anyhow::Error;
use chats::{
room::{Room, RoomKind},
ChatRegistry,
};
use chats::ChatRegistry;
use common::{profile::SharedProfile, random_name};
use global::get_client;
use gpui::{
@@ -21,11 +18,14 @@ use std::{
};
use ui::{
button::{Button, ButtonVariants},
dock_area::dock::DockPlacement,
input::{InputEvent, TextInput},
theme::{scale::ColorScaleStep, ActiveTheme},
ContextModal, Disableable, Icon, IconName, Sizable, Size, StyledExt,
};
use crate::chatspace::{AddPanel, PanelKind};
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Compose> {
cx.new(|cx| Compose::new(window, cx))
}
@@ -161,22 +161,19 @@ impl Compose {
Ok(event)
});
cx.spawn_in(window, async move |this, cx| {
if let Ok(event) = event.await {
cx.spawn_in(window, async move |this, cx| match event.await {
Ok(event) => {
cx.update(|window, cx| {
this.update(cx, |this, cx| {
this.set_submitting(false, cx);
ChatRegistry::global(cx).update(cx, |chats, cx| {
let id = chats.push(&event, window, cx);
window.close_modal(cx);
window.dispatch_action(
Box::new(AddPanel::new(PanelKind::Room(id), DockPlacement::Center)),
cx,
);
});
})
.ok();
let chats = ChatRegistry::global(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| {
@@ -184,11 +181,6 @@ impl Compose {
})
.ok();
}
}
});
})
.ok();
}
})
.detach();
}

View File

@@ -284,6 +284,8 @@ impl Render for Relays {
div()
.track_focus(&self.focus_handle)
.size_full()
.px_3()
.pb_3()
.flex()
.flex_col()
.justify_between()

View File

@@ -2,10 +2,7 @@ use std::time::Duration;
use anyhow::Error;
use async_utility::task::spawn;
use chats::{
room::{Room, RoomKind},
ChatRegistry,
};
use chats::ChatRegistry;
use common::profile::SharedProfile;
use global::{constants::SEARCH_RELAYS, get_client};
use gpui::{
@@ -18,12 +15,15 @@ use nostr_sdk::prelude::*;
use smallvec::{smallvec, SmallVec};
use ui::{
button::{Button, ButtonVariants},
dock_area::dock::DockPlacement,
indicator::Indicator,
input::{InputEvent, TextInput},
theme::{scale::ColorScaleStep, ActiveTheme},
ContextModal, Disableable, IconName, Sizable,
};
use crate::chatspace::{AddPanel, PanelKind};
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Search> {
Search::new(window, cx)
}
@@ -167,17 +167,19 @@ impl Search {
Ok(event)
});
cx.spawn_in(window, async move |this, cx| {
if let Ok(event) = event.await {
cx.spawn_in(window, async move |this, cx| match event.await {
Ok(event) => {
cx.update(|window, cx| {
let chats = ChatRegistry::global(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
ChatRegistry::global(cx).update(cx, |chats, cx| {
let id = chats.push(&event, window, cx);
window.close_modal(cx);
window.dispatch_action(
Box::new(AddPanel::new(PanelKind::Room(id), DockPlacement::Center)),
cx,
);
});
})
.ok();
}
Err(e) => {
this.update(cx, |this, cx| {
@@ -188,11 +190,6 @@ impl Search {
})
.ok();
}
}
});
})
.ok();
}
})
.detach();
}

View File

@@ -306,6 +306,7 @@ impl RenderOnce for FolderItem {
} else {
this.child(
div()
.flex_shrink_0()
.flex()
.justify_center()
.items_center()

View File

@@ -104,6 +104,28 @@ impl Sidebar {
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> {
(0..total).map(|_| {
div()
@@ -146,28 +168,6 @@ impl Sidebar {
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 {
@@ -206,6 +206,7 @@ impl Render for Sidebar {
div()
.id("sidebar")
.track_focus(&self.focus_handle)
.track_scroll(&self.scroll_handle)
.on_action(cx.listener(Self::on_logout))
.overflow_y_scroll()

View File

@@ -80,6 +80,8 @@ impl Render for Subject {
.flex()
.flex_col()
.gap_3()
.px_3()
.pb_3()
.child(
div()
.flex()

View File

@@ -47,7 +47,7 @@ impl Modal {
let base = v_flex()
.bg(cx.theme().background)
.border_1()
.border_color(cx.theme().base.step(cx, ColorScaleStep::SEVEN))
.border_color(cx.theme().base.step(cx, ColorScaleStep::SIX))
.rounded_xl()
.shadow_md();
@@ -169,9 +169,9 @@ impl RenderOnce for Modal {
.w(view_size.width)
.h(view_size.height)
.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, {
let on_close = self.on_close.clone();
move |_, window, cx| {