chore: restructure and refine the ui (#199)

* update deps

* clean up

* add account crate

* add person crate

* add chat and chat ui crates

* .

* clean up the ui crate

* .

* .
This commit is contained in:
reya
2025-11-01 09:16:02 +07:00
committed by GitHub
parent a1bd4954eb
commit 7091fa1cab
42 changed files with 980 additions and 794 deletions

View File

@@ -34,9 +34,12 @@ theme = { path = "../theme" }
common = { path = "../common" }
states = { path = "../states" }
key_store = { path = "../key_store" }
registry = { path = "../registry" }
chat = { path = "../chat" }
chat_ui = { path = "../chat_ui" }
settings = { path = "../settings" }
auto_update = { path = "../auto_update" }
account = { path = "../account" }
person = { path = "../person" }
rust-i18n.workspace = true
i18n.workspace = true

View File

@@ -1,10 +1,9 @@
use std::sync::Mutex;
use gpui::{actions, App, AppContext};
use gpui::{actions, App};
use key_store::backend::KeyItem;
use key_store::KeyStore;
use nostr_connect::prelude::*;
use registry::Registry;
use states::app_state;
actions!(coop, [ReloadMetadata, DarkMode, Settings, Logout, Quit]);
@@ -48,31 +47,30 @@ pub fn load_embedded_fonts(cx: &App) {
}
pub fn reset(cx: &mut App) {
let registry = Registry::global(cx);
let backend = KeyStore::global(cx).read(cx).backend();
cx.spawn(async move |cx| {
cx.background_spawn(async move {
let client = app_state().client();
client.unset_signer().await;
})
.await;
let client = app_state().client();
// Remove the signer
client.unset_signer().await;
// Delete user's credentials
backend
.delete_credentials(&KeyItem::User.to_string(), cx)
.await
.ok();
// Remove bunker's credentials if available
backend
.delete_credentials(&KeyItem::Bunker.to_string(), cx)
.await
.ok();
registry
.update(cx, |this, cx| {
this.reset(cx);
})
.ok();
cx.update(|cx| {
cx.restart();
})
.ok();
})
.detach();
}

View File

@@ -2,8 +2,11 @@ use std::borrow::Cow;
use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use account::Account;
use anyhow::{anyhow, Error};
use auto_update::AutoUpdater;
use chat::{ChatEvent, ChatRegistry};
use chat_ui::{CopyPublicKey, OpenPublicKey};
use common::display::{shorten_pubkey, RenderedProfile};
use common::event::EventUtils;
use gpui::prelude::FluentBuilder;
@@ -18,7 +21,7 @@ use key_store::backend::KeyItem;
use key_store::KeyStore;
use nostr_connect::prelude::*;
use nostr_sdk::prelude::*;
use registry::{Registry, RegistryEvent};
use person::PersonRegistry;
use settings::AppSettings;
use smallvec::{smallvec, SmallVec};
use states::{
@@ -27,7 +30,6 @@ use states::{
};
use theme::{ActiveTheme, Theme, ThemeMode};
use title_bar::TitleBar;
use ui::actions::{CopyPublicKey, OpenPublicKey};
use ui::avatar::Avatar;
use ui::button::{Button, ButtonVariants};
use ui::dock_area::dock::DockPlacement;
@@ -42,7 +44,8 @@ use crate::actions::{reset, DarkMode, Logout, ReloadMetadata, Settings};
use crate::views::compose::compose_button;
use crate::views::setup_relay::SetupRelay;
use crate::views::{
account, chat, login, new_account, onboarding, preferences, sidebar, user_profile, welcome,
account as account_view, login, new_account, onboarding, preferences, sidebar, user_profile,
welcome,
};
pub fn init(window: &mut Window, cx: &mut App) -> Entity<ChatSpace> {
@@ -59,6 +62,7 @@ pub fn new_account(window: &mut Window, cx: &mut App) {
ChatSpace::set_center_panel(panel, window, cx);
}
#[derive(Debug)]
pub struct ChatSpace {
/// App's Title Bar
title_bar: Entity<TitleBar>,
@@ -84,7 +88,7 @@ pub struct ChatSpace {
impl ChatSpace {
pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
let registry = Registry::global(cx);
let chat = ChatRegistry::global(cx);
let keystore = KeyStore::global(cx);
let title_bar = cx.new(|_| TitleBar::new());
@@ -102,55 +106,49 @@ impl ChatSpace {
);
subscriptions.push(
// Observe device changes
cx.observe_in(&keystore, window, move |this, state, window, cx| {
// Observe keystore changes
cx.observe_in(&keystore, window, move |_this, state, window, cx| {
if state.read(cx).initialized {
let backend = state.read(cx).backend();
if state.read(cx).initialized {
if state.read(cx).is_using_file_keystore() {
this.render_keyring_installation(window, cx);
}
cx.spawn_in(window, async move |this, cx| {
let result = backend
.read_credentials(&KeyItem::User.to_string(), cx)
.await;
cx.spawn_in(window, async move |this, cx| {
let result = backend
.read_credentials(&KeyItem::User.to_string(), cx)
.await;
this.update_in(cx, |this, window, cx| {
match result {
Ok(Some((user, secret))) => {
let public_key = PublicKey::parse(&user).unwrap();
let secret = String::from_utf8(secret).unwrap();
this.update_in(cx, |this, window, cx| {
match result {
Ok(Some((user, secret))) => {
let public_key = PublicKey::parse(&user).unwrap();
let secret = String::from_utf8(secret).unwrap();
this.set_account_layout(public_key, secret, window, cx);
}
_ => {
this.set_onboarding_layout(window, cx);
}
};
})
.ok();
this.set_account_layout(public_key, secret, window, cx);
}
_ => {
this.set_onboarding_layout(window, cx);
}
};
})
.detach();
}
.ok();
})
.detach();
}
}),
);
subscriptions.push(
// Handle registry events
cx.subscribe_in(&registry, window, move |this, _, ev, window, cx| {
cx.subscribe_in(&chat, window, move |this, chat, ev, window, cx| {
match ev {
RegistryEvent::Open(room) => {
if let Some(room) = room.upgrade() {
ChatEvent::OpenRoom(id) => {
if let Some(room) = chat.read(cx).room(id, cx) {
this.dock.update(cx, |this, cx| {
let panel = chat::init(room, window, cx);
let panel = chat_ui::init(room, window, cx);
this.add_panel(Arc::new(panel), DockPlacement::Center, window, cx);
});
}
}
RegistryEvent::Close(..) => {
ChatEvent::CloseRoom(..) => {
this.dock.update(cx, |this, cx| {
this.focus_tab_panel(window, cx);
@@ -217,7 +215,8 @@ impl ChatSpace {
while let Ok(signal) = states.signal().receiver().recv_async().await {
view.update_in(cx, |this, window, cx| {
let registry = Registry::global(cx);
let chat = ChatRegistry::global(cx);
let persons = PersonRegistry::global(cx);
let settings = AppSettings::global(cx);
match signal {
@@ -234,8 +233,8 @@ impl ChatSpace {
this.receive_encryption(response, window, cx);
}
SignalKind::SignerSet(public_key) => {
// Close all opened modals
window.close_all_modals(cx);
// Set the global account state
account::init(public_key, cx);
// Load user's settings
settings.update(cx, |this, cx| {
@@ -243,11 +242,13 @@ impl ChatSpace {
});
// Load all chat rooms
registry.update(cx, |this, cx| {
this.set_signer_pubkey(public_key, cx);
chat.update(cx, |this, cx| {
this.load_rooms(window, cx);
});
// Close all opened modals
window.close_all_modals(cx);
// Setup the default layout for current workspace
this.set_default_layout(window, cx);
}
@@ -271,7 +272,7 @@ impl ChatSpace {
if matches!(s, UnwrappingStatus::Processing | UnwrappingStatus::Complete) {
let all_panels = this.get_all_panel_ids(cx);
registry.update(cx, |this, cx| {
chat.update(cx, |this, cx| {
this.load_rooms(window, cx);
this.refresh_rooms(all_panels, cx);
@@ -282,13 +283,13 @@ impl ChatSpace {
}
}
SignalKind::NewProfile(profile) => {
registry.update(cx, |this, cx| {
persons.update(cx, |this, cx| {
this.insert_or_update_person(profile, cx);
});
}
SignalKind::NewMessage((gift_wrap_id, event)) => {
registry.update(cx, |this, cx| {
this.event_to_message(gift_wrap_id, event, window, cx);
SignalKind::NewMessage(msg) => {
chat.update(cx, |this, cx| {
this.new_message(msg, window, cx);
});
}
SignalKind::GossipRelaysNotFound => {
@@ -621,7 +622,7 @@ impl ChatSpace {
window: &mut Window,
cx: &mut Context<Self>,
) {
let panel = Arc::new(account::init(public_key, secret, window, cx));
let panel = Arc::new(account_view::init(public_key, secret, window, cx));
let center = DockItem::panel(panel);
self.dock.update(cx, |this, cx| {
@@ -785,32 +786,6 @@ impl ChatSpace {
}
}
fn render_keyring_installation(&mut self, window: &mut Window, cx: &mut App) {
window.open_modal(cx, move |this, _window, cx| {
this.overlay_closable(false)
.show_close(false)
.keyboard(false)
.alert()
.button_props(ModalButtonProps::default().ok_text(t!("common.continue")))
.title(shared_t!("keyring_disable.label"))
.child(
v_flex()
.gap_2()
.text_sm()
.child(shared_t!("keyring_disable.body_1"))
.child(shared_t!("keyring_disable.body_2"))
.child(shared_t!("keyring_disable.body_3"))
.child(shared_t!("keyring_disable.body_4"))
.child(
div()
.text_xs()
.text_color(cx.theme().danger_foreground)
.child(shared_t!("keyring_disable.body_5")),
),
)
});
}
fn render_request(&mut self, ann: Announcement, window: &mut Window, cx: &mut Context<Self>) {
let client_name = SharedString::from(ann.client().to_string());
let target = ann.public_key();
@@ -907,8 +882,25 @@ impl ChatSpace {
),
)
.on_cancel(move |_ev, window, cx| {
_ = view.update(cx, |this, cx| {
this.render_reset(window, cx);
_ = view.update(cx, |_, cx| {
cx.spawn_in(window, async move |this, cx| {
let state = app_state();
let result = state.init_encryption_keys().await;
this.update_in(cx, |_, window, cx| {
match result {
Ok(_) => {
window.push_notification(t!("encryption.success"), cx);
window.close_all_modals(cx);
}
Err(e) => {
window.push_notification(e.to_string(), cx);
}
};
})
.ok();
})
.detach();
});
// false to keep modal open
false
@@ -916,27 +908,6 @@ impl ChatSpace {
});
}
fn render_reset(&mut self, window: &mut Window, cx: &mut Context<Self>) {
cx.spawn_in(window, async move |this, cx| {
let state = app_state();
let result = state.init_encryption_keys().await;
this.update_in(cx, |_, window, cx| {
match result {
Ok(_) => {
window.push_notification(t!("encryption.success"), cx);
window.close_all_modals(cx);
}
Err(e) => {
window.push_notification(e.to_string(), cx);
}
};
})
.ok();
})
.detach();
}
fn render_setup_gossip_relays_modal(&mut self, window: &mut Window, cx: &mut App) {
let relays = default_nip65_relays();
@@ -1139,13 +1110,39 @@ impl ChatSpace {
})
}
fn render_titlebar_left_side(
&mut self,
_window: &mut Window,
cx: &Context<Self>,
) -> impl IntoElement {
let registry = Registry::global(cx);
let status = registry.read(cx).loading;
fn render_keyring_warning(window: &mut Window, cx: &mut App) {
window.open_modal(cx, move |this, _window, cx| {
this.overlay_closable(false)
.show_close(false)
.keyboard(false)
.alert()
.button_props(ModalButtonProps::default().ok_text(t!("common.continue")))
.title(shared_t!("keyring_disable.label"))
.child(
v_flex()
.gap_2()
.text_sm()
.child(shared_t!("keyring_disable.body_1"))
.child(shared_t!("keyring_disable.body_2"))
.child(shared_t!("keyring_disable.body_3"))
.child(shared_t!("keyring_disable.body_4"))
.child(
div()
.text_xs()
.text_color(cx.theme().danger_foreground)
.child(shared_t!("keyring_disable.body_5")),
),
)
});
}
fn titlebar_left(&mut self, _window: &mut Window, cx: &Context<Self>) -> impl IntoElement {
let chat = ChatRegistry::global(cx);
let status = chat.read(cx).loading;
if !Account::has_global(cx) {
return div();
}
h_flex()
.gap_2()
@@ -1166,12 +1163,8 @@ impl ChatSpace {
})
}
fn render_titlebar_right_side(
&mut self,
profile: &Profile,
_window: &mut Window,
cx: &mut Context<Self>,
) -> impl IntoElement {
fn titlebar_right(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let file_keystore = KeyStore::global(cx).read(cx).is_using_file_keystore();
let proxy = AppSettings::get_proxy_user_avatars(cx);
let updating = AutoUpdater::read_global(cx).status.is_updating();
let updated = AutoUpdater::read_global(cx).status.is_updated();
@@ -1179,6 +1172,19 @@ impl ChatSpace {
h_flex()
.gap_1()
.when(file_keystore, |this| {
this.child(
Button::new("keystore-warning")
.icon(IconName::Warning)
.label("Keyring Disabled")
.ghost()
.xsmall()
.rounded()
.on_click(move |_ev, window, cx| {
Self::render_keyring_warning(window, cx);
}),
)
})
.when(updating, |this| {
this.child(
h_flex()
@@ -1236,7 +1242,7 @@ impl ChatSpace {
Button::new("setup-relays-button")
.icon(IconName::Info)
.label(t!("messaging.button"))
.warning()
.ghost()
.xsmall()
.rounded()
.on_click(move |_ev, window, cx| {
@@ -1244,22 +1250,29 @@ impl ChatSpace {
}),
)
})
.child(
Button::new("user")
.small()
.reverse()
.transparent()
.icon(IconName::CaretDown)
.child(Avatar::new(profile.avatar(proxy)).size(rems(1.49)))
.popup_menu(|this, _window, _cx| {
this.menu(t!("user.dark_mode"), Box::new(DarkMode))
.menu(t!("user.settings"), Box::new(Settings))
.separator()
.menu(t!("user.reload_metadata"), Box::new(ReloadMetadata))
.separator()
.menu(t!("user.sign_out"), Box::new(Logout))
}),
)
.when(Account::has_global(cx), |this| {
let persons = PersonRegistry::global(cx);
let account = Account::global(cx);
let public_key = account.read(cx).public_key();
let profile = persons.read(cx).get_person(&public_key, cx);
this.child(
Button::new("user")
.small()
.reverse()
.transparent()
.icon(IconName::CaretDown)
.child(Avatar::new(profile.avatar(proxy)).size(rems(1.49)))
.popup_menu(|this, _window, _cx| {
this.menu(t!("user.dark_mode"), Box::new(DarkMode))
.menu(t!("user.settings"), Box::new(Settings))
.separator()
.menu(t!("user.reload_metadata"), Box::new(ReloadMetadata))
.separator()
.menu(t!("user.sign_out"), Box::new(Logout))
}),
)
})
}
}
@@ -1267,24 +1280,14 @@ impl Render for ChatSpace {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let modal_layer = Root::render_modal_layer(window, cx);
let notification_layer = Root::render_notification_layer(window, cx);
let registry = Registry::read_global(cx);
// Only render titlebar child elements if user is logged in
if let Some(public_key) = registry.signer_pubkey() {
let profile = registry.get_person(&public_key, cx);
let left = self.titlebar_left(window, cx).into_any_element();
let right = self.titlebar_right(window, cx).into_any_element();
let left_side = self
.render_titlebar_left_side(window, cx)
.into_any_element();
let right_side = self
.render_titlebar_right_side(&profile, window, cx)
.into_any_element();
self.title_bar.update(cx, |this, _cx| {
this.set_children(vec![left_side, right_side]);
})
}
// Update title bar children
self.title_bar.update(cx, |this, _cx| {
this.set_children(vec![left, right]);
});
div()
.id(SharedString::from("chatspace"))

View File

@@ -83,9 +83,12 @@ fn main() {
ui::init(cx);
// Initialize app registry
registry::init(cx);
chat::init(cx);
// Initialize backend for credentials storage
// Initialize person registry
person::init(cx);
// Initialize backend for keys storage
key_store::init(cx);
// Initialize settings

View File

@@ -12,7 +12,7 @@ use i18n::{shared_t, t};
use key_store::backend::KeyItem;
use key_store::KeyStore;
use nostr_connect::prelude::*;
use registry::Registry;
use person::PersonRegistry;
use smallvec::{smallvec, SmallVec};
use states::{app_state, BUNKER_TIMEOUT};
use theme::ActiveTheme;
@@ -207,8 +207,8 @@ impl Focusable for Account {
impl Render for Account {
fn render(&mut self, _window: &mut gpui::Window, cx: &mut Context<Self>) -> impl IntoElement {
let registry = Registry::global(cx);
let profile = registry.read(cx).get_person(&self.public_key, cx);
let persons = PersonRegistry::global(cx);
let profile = persons.read(cx).get_person(&self.public_key, cx);
let bunker = self.secret.starts_with("bunker://");
v_flex()

File diff suppressed because it is too large Load Diff

View File

@@ -1,55 +0,0 @@
use gpui::{
div, App, AppContext, Context, Entity, IntoElement, ParentElement, Render, SharedString,
Styled, Window,
};
use i18n::{shared_t, t};
use theme::ActiveTheme;
use ui::input::{InputState, TextInput};
use ui::{v_flex, Sizable};
pub fn init(subject: Option<String>, window: &mut Window, cx: &mut App) -> Entity<Subject> {
Subject::new(subject, window, cx)
}
pub struct Subject {
input: Entity<InputState>,
}
impl Subject {
pub fn new(subject: Option<String>, window: &mut Window, cx: &mut App) -> Entity<Self> {
let input = cx.new(|cx| {
let mut this = InputState::new(window, cx).placeholder(t!("subject.placeholder"));
if let Some(text) = subject.as_ref() {
this.set_value(text, window, cx);
}
this
});
cx.new(|_| Self { input })
}
pub fn new_subject(&self, cx: &App) -> String {
self.input.read(cx).value().to_string()
}
}
impl Render for Subject {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.gap_1()
.child(
div()
.text_sm()
.text_color(cx.theme().text_muted)
.child(shared_t!("subject.title")),
)
.child(TextInput::new(&self.input).small())
.child(
div()
.text_xs()
.italic()
.text_color(cx.theme().text_placeholder)
.child(shared_t!("subject.help_text")),
)
}
}

View File

@@ -2,6 +2,8 @@ use std::ops::Range;
use std::time::Duration;
use anyhow::{anyhow, Error};
use chat::room::Room;
use chat::ChatRegistry;
use common::display::{RenderedProfile, TextUtils};
use common::nip05::nip05_profile;
use gpui::prelude::FluentBuilder;
@@ -13,8 +15,7 @@ use gpui::{
use gpui_tokio::Tokio;
use i18n::{shared_t, t};
use nostr_sdk::prelude::*;
use registry::room::Room;
use registry::Registry;
use person::PersonRegistry;
use settings::AppSettings;
use smallvec::{smallvec, SmallVec};
use states::{app_state, BOOTSTRAP_RELAYS};
@@ -311,7 +312,7 @@ impl Compose {
}
fn submit(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let registry = Registry::global(cx);
let chat = ChatRegistry::global(cx);
let receivers: Vec<PublicKey> = self.selected(cx);
let subject_input = self.title_input.read(cx).value();
let subject = (!subject_input.is_empty()).then(|| subject_input.to_string());
@@ -327,10 +328,9 @@ impl Compose {
this.update_in(cx, |this, window, cx| {
match result {
Ok(room) => {
registry.update(cx, |this, cx| {
chat.update(cx, |this, cx| {
this.push_room(cx.new(|_| room), cx);
});
window.close_modal(cx);
}
Err(e) => {
@@ -372,7 +372,7 @@ impl Compose {
fn list_items(&self, range: Range<usize>, cx: &Context<Self>) -> Vec<impl IntoElement> {
let proxy = AppSettings::get_proxy_user_avatars(cx);
let registry = Registry::read_global(cx);
let persons = PersonRegistry::global(cx);
let mut items = Vec::with_capacity(self.contacts.read(cx).len());
for ix in range {
@@ -381,7 +381,7 @@ impl Compose {
};
let public_key = contact.public_key;
let profile = registry.get_person(&public_key, cx);
let profile = persons.read(cx).get_person(&public_key, cx);
items.push(
h_flex()

View File

@@ -1,6 +1,5 @@
pub mod account;
pub mod backup_keys;
pub mod chat;
pub mod compose;
pub mod edit_profile;
pub mod login;

View File

@@ -1,12 +1,12 @@
use account::Account;
use common::display::RenderedProfile;
use gpui::http_client::Url;
use gpui::prelude::FluentBuilder;
use gpui::{
div, px, relative, rems, App, AppContext, Context, Entity, InteractiveElement, IntoElement,
ParentElement, Render, SharedString, StatefulInteractiveElement, Styled, Window,
};
use i18n::{shared_t, t};
use registry::Registry;
use person::PersonRegistry;
use settings::AppSettings;
use theme::ActiveTheme;
use ui::avatar::Avatar;
@@ -53,7 +53,7 @@ impl Preferences {
.on_ok(move |_, window, cx| {
weak_view
.update(cx, |this, cx| {
let registry = Registry::global(cx);
let persons = PersonRegistry::global(cx);
let set_metadata = this.set_metadata(cx);
cx.spawn_in(window, async move |this, cx| {
@@ -62,7 +62,7 @@ impl Preferences {
this.update_in(cx, |_, window, cx| {
match result {
Ok(profile) => {
registry.update(cx, |this, cx| {
persons.update(cx, |this, cx| {
this.insert_or_update_person(profile, cx);
});
}
@@ -115,7 +115,11 @@ impl Render for Preferences {
let proxy = AppSettings::get_proxy_user_avatars(cx);
let hide = AppSettings::get_hide_user_avatars(cx);
let registry = Registry::read_global(cx);
let persons = PersonRegistry::global(cx);
let account = Account::global(cx);
let public_key = account.read(cx).public_key();
let profile = persons.read(cx).get_person(&public_key, cx);
let input_state = self.media_input.downgrade();
v_flex()
@@ -130,54 +134,48 @@ impl Render for Preferences {
.font_semibold()
.child(shared_t!("preferences.account_header")),
)
.when_some(registry.signer_pubkey(), |this, public_key| {
let profile = registry.get_person(&public_key, cx);
this.child(
h_flex()
.w_full()
.justify_between()
.child(
h_flex()
.id("user")
.gap_2()
.child(Avatar::new(profile.avatar(proxy)).size(rems(2.4)))
.child(
div()
.flex_1()
.text_sm()
.child(
div()
.font_semibold()
.line_height(relative(1.3))
.child(profile.display_name()),
)
.child(
div()
.text_xs()
.text_color(cx.theme().text_muted)
.line_height(relative(1.3))
.child(shared_t!(
"preferences.account_btn"
)),
),
)
.on_click(cx.listener(move |this, _e, window, cx| {
this.open_edit_profile(window, cx);
})),
)
.child(
Button::new("relays")
.label("Messaging Relays")
.xsmall()
.ghost_alt()
.rounded()
.on_click(cx.listener(move |this, _e, window, cx| {
this.open_relays(window, cx);
})),
),
)
}),
.child(
h_flex()
.w_full()
.justify_between()
.child(
h_flex()
.id("user")
.gap_2()
.child(Avatar::new(profile.avatar(proxy)).size(rems(2.4)))
.child(
div()
.flex_1()
.text_sm()
.child(
div()
.font_semibold()
.line_height(relative(1.3))
.child(profile.display_name()),
)
.child(
div()
.text_xs()
.text_color(cx.theme().text_muted)
.line_height(relative(1.3))
.child(shared_t!("preferences.account_btn")),
),
)
.on_click(cx.listener(move |this, _e, window, cx| {
this.open_edit_profile(window, cx);
})),
)
.child(
Button::new("relays")
.label("Messaging Relays")
.xsmall()
.ghost_alt()
.rounded()
.on_click(cx.listener(move |this, _e, window, cx| {
this.open_relays(window, cx);
})),
),
),
)
.child(
v_flex()

View File

@@ -10,7 +10,7 @@ use gpui::{
use gpui_tokio::Tokio;
use i18n::{shared_t, t};
use nostr_sdk::prelude::*;
use registry::Registry;
use person::PersonRegistry;
use settings::AppSettings;
use smallvec::{smallvec, SmallVec};
use states::{app_state, BOOTSTRAP_RELAYS};
@@ -35,8 +35,8 @@ pub struct Screening {
impl Screening {
pub fn new(public_key: PublicKey, window: &mut Window, cx: &mut Context<Self>) -> Self {
let registry = Registry::read_global(cx);
let profile = registry.get_person(&public_key, cx);
let persons = PersonRegistry::global(cx);
let profile = persons.read(cx).get_person(&public_key, cx);
let mut tasks = smallvec![];

View File

@@ -1,5 +1,8 @@
use std::rc::Rc;
use chat::room::RoomKind;
use chat::ChatRegistry;
use chat_ui::{CopyPublicKey, OpenPublicKey};
use gpui::prelude::FluentBuilder;
use gpui::{
div, rems, App, ClickEvent, InteractiveElement, IntoElement, ParentElement as _, RenderOnce,
@@ -7,11 +10,8 @@ use gpui::{
};
use i18n::t;
use nostr_sdk::prelude::*;
use registry::room::RoomKind;
use registry::Registry;
use settings::AppSettings;
use theme::ActiveTheme;
use ui::actions::{CopyPublicKey, OpenPublicKey};
use ui::avatar::Avatar;
use ui::context_menu::ContextMenuExt;
use ui::modal::ModalButtonProps;
@@ -187,7 +187,7 @@ impl RenderOnce for RoomListItem {
.ok_text(t!("screening.response")),
)
.on_cancel(move |_event, _window, cx| {
Registry::global(cx).update(cx, |this, cx| {
ChatRegistry::global(cx).update(cx, |this, cx| {
this.close_room(room_id, cx);
});
// false to prevent closing the modal

View File

@@ -3,6 +3,8 @@ use std::ops::Range;
use std::time::Duration;
use anyhow::{anyhow, Error};
use chat::room::{Room, RoomKind};
use chat::{ChatEvent, ChatRegistry};
use common::debounced_delay::DebouncedDelay;
use common::display::{RenderedProfile, RenderedTimestamp, TextUtils};
use gpui::prelude::FluentBuilder;
@@ -16,8 +18,6 @@ use i18n::{shared_t, t};
use itertools::Itertools;
use list_item::RoomListItem;
use nostr_sdk::prelude::*;
use registry::room::{Room, RoomKind};
use registry::{Registry, RegistryEvent};
use settings::AppSettings;
use smallvec::{smallvec, SmallVec};
use states::{app_state, BOOTSTRAP_RELAYS, SEARCH_RELAYS};
@@ -73,7 +73,7 @@ impl Sidebar {
let find_input =
cx.new(|cx| InputState::new(window, cx).placeholder(t!("sidebar.search_label")));
let registry = Registry::global(cx);
let chat = ChatRegistry::global(cx);
let mut subscriptions = smallvec![];
subscriptions.push(
@@ -87,8 +87,8 @@ impl Sidebar {
subscriptions.push(
// Subscribe for registry new events
cx.subscribe_in(&registry, window, move |this, _, event, _window, cx| {
if let RegistryEvent::NewRequest(kind) = event {
cx.subscribe_in(&chat, window, move |this, _, event, _window, cx| {
if let ChatEvent::NewChatRequest(kind) = event {
this.indicator.update(cx, |this, cx| {
*this = Some(kind.to_owned());
cx.notify();
@@ -326,8 +326,8 @@ impl Sidebar {
Ok(room) => {
cx.update(|window, cx| {
this.update(cx, |this, cx| {
let registry = Registry::read_global(cx);
let result = registry.search_by_public_key(public_key, cx);
let chat = ChatRegistry::global(cx);
let result = chat.read(cx).search_by_public_key(public_key, cx);
if !result.is_empty() {
this.results(result, false, window, cx);
@@ -394,9 +394,9 @@ impl Sidebar {
}
}
let chats = Registry::read_global(cx);
let chat = ChatRegistry::global(cx);
// Get all local results with current query
let local_results = chats.search(&query, cx);
let local_results = chat.read(cx).search(&query, cx);
if !local_results.is_empty() {
// Try to update with local results first
@@ -495,7 +495,7 @@ impl Sidebar {
}
fn open_room(&mut self, id: u64, window: &mut Window, cx: &mut Context<Self>) {
let room = if let Some(room) = Registry::read_global(cx).room(&id, cx) {
let room = if let Some(room) = ChatRegistry::global(cx).read(cx).room(&id, cx) {
room
} else {
let Some(result) = self.global_result.read(cx).as_ref() else {
@@ -514,13 +514,13 @@ impl Sidebar {
room
};
Registry::global(cx).update(cx, |this, cx| {
ChatRegistry::global(cx).update(cx, |this, cx| {
this.push_room(room, cx);
});
}
fn on_reload(&mut self, _ev: &Reload, window: &mut Window, cx: &mut Context<Self>) {
Registry::global(cx).update(cx, |this, cx| {
ChatRegistry::global(cx).update(cx, |this, cx| {
this.load_rooms(window, cx);
});
window.push_notification(t!("common.refreshed"), cx);
@@ -661,8 +661,8 @@ impl Focusable for Sidebar {
impl Render for Sidebar {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let registry = Registry::read_global(cx);
let loading = registry.loading;
let chat = ChatRegistry::global(cx);
let loading = chat.read(cx).loading;
// Get rooms from either search results or the chat registry
let rooms = if let Some(results) = self.local_result.read(cx).as_ref() {
@@ -672,9 +672,9 @@ impl Render for Sidebar {
} else {
#[allow(clippy::collapsible_else_if)]
if self.active_filter.read(cx) == &RoomKind::Ongoing {
registry.ongoing_rooms(cx)
chat.read(cx).ongoing_rooms(cx)
} else {
registry.request_rooms(cx)
chat.read(cx).request_rooms(cx)
}
};
@@ -738,9 +738,9 @@ impl Render for Sidebar {
.tooltip(t!("sidebar.all_conversations_tooltip"))
.when_some(self.indicator.read(cx).as_ref(), |this, kind| {
this.when(kind == &RoomKind::Ongoing, |this| {
this.child(deferred(
this.child(
div().size_1().rounded_full().bg(cx.theme().cursor),
))
)
})
})
.small()
@@ -759,9 +759,9 @@ impl Render for Sidebar {
.tooltip(t!("sidebar.requests_tooltip"))
.when_some(self.indicator.read(cx).as_ref(), |this, kind| {
this.when(kind != &RoomKind::Ongoing, |this| {
this.child(deferred(
this.child(
div().size_1().rounded_full().bg(cx.theme().cursor),
))
)
})
})
.small()

View File

@@ -10,7 +10,7 @@ use gpui::{
use gpui_tokio::Tokio;
use i18n::{shared_t, t};
use nostr_sdk::prelude::*;
use registry::Registry;
use person::PersonRegistry;
use settings::AppSettings;
use smallvec::{smallvec, SmallVec};
use states::app_state;
@@ -33,8 +33,8 @@ pub struct UserProfile {
impl UserProfile {
pub fn new(target: PublicKey, window: &mut Window, cx: &mut Context<Self>) -> Self {
let registry = Registry::read_global(cx);
let profile = registry.get_person(&target, cx);
let persons = PersonRegistry::global(cx);
let profile = persons.read(cx).get_person(&target, cx);
let mut tasks = smallvec![];