This commit is contained in:
2026-06-07 17:18:11 +07:00
parent 57a129fa93
commit 04983be23f
3 changed files with 46 additions and 49 deletions

View File

@@ -10,8 +10,8 @@ use gpui::{
AnyElement, App, AppContext, ClipboardItem, Context, Entity, EventEmitter, FocusHandle, AnyElement, App, AppContext, ClipboardItem, Context, Entity, EventEmitter, FocusHandle,
Focusable, InteractiveElement, IntoElement, ListAlignment, ListOffset, ListState, MouseButton, Focusable, InteractiveElement, IntoElement, ListAlignment, ListOffset, ListState, MouseButton,
ObjectFit, ParentElement, PathPromptOptions, Render, SharedString, SharedUri, ObjectFit, ParentElement, PathPromptOptions, Render, SharedString, SharedUri,
StatefulInteractiveElement, Styled, StyledImage, Subscription, Task, WeakEntity, Window, StatefulInteractiveElement, Styled, StyledImage, Subscription, Task, WeakEntity, Window, div,
deferred, div, img, list, px, red, relative, svg, white, img, list, px, red, relative, svg, white,
}; };
use itertools::Itertools; use itertools::Itertools;
use nostr_sdk::prelude::*; use nostr_sdk::prelude::*;
@@ -889,7 +889,7 @@ impl ChatPanel {
) )
.child(message.created_at.to_human_time()) .child(message.created_at.to_human_time())
.when(has_reports, |this| { .when(has_reports, |this| {
this.child(deferred(self.render_sent_reports(&id, cx))) this.child(self.render_sent_reports(&id, cx))
}), }),
) )
.when(has_replies, |this| { .when(has_replies, |this| {
@@ -1534,7 +1534,7 @@ impl Render for ChatPanel {
this.upload(window, cx); this.upload(window, cx);
})), })),
) )
.child(Input::new(&self.input).appearance(false).text_sm().flex_1()) .child(Input::new(&self.input).appearance(false).flex_1())
.child( .child(
h_flex() h_flex()
.pl_1() .pl_1()

View File

@@ -89,14 +89,14 @@ impl DeviceRegistry {
fn new(window: &mut Window, cx: &mut Context<Self>) -> Self { fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
let nostr = NostrRegistry::global(cx); let nostr = NostrRegistry::global(cx);
let settings = AppSettings::global(cx); let settings = AppSettings::global(cx);
let is_nip4e_enabled = settings.read(cx).is_nip4e_enabled(); let is_nip4e_enabled = settings.read(cx).is_nip4e_enabled(cx);
let mut subscriptions = smallvec![]; let mut subscriptions = smallvec![];
subscriptions.push( subscriptions.push(
// Subscribe to nostr state events // Subscribe to nostr state events
cx.observe(&settings, move |this, settings, cx| { cx.observe(&settings, move |this, settings, cx| {
if settings.read(cx).is_nip4e_enabled() { if settings.read(cx).is_nip4e_enabled(cx) {
this.get_announcement(cx); this.get_announcement(cx);
}; };
}), }),

View File

@@ -20,13 +20,15 @@ macro_rules! setting_accessors {
$( $(
paste::paste! { paste::paste! {
pub fn [<get_ $field>](cx: &App) -> $type { pub fn [<get_ $field>](cx: &App) -> $type {
Self::global(cx).read(cx).values.$field.clone() Self::global(cx).read(cx).inner.read(cx).$field.clone()
} }
pub fn [<update_ $field>](value: $type, cx: &mut App) { pub fn [<update_ $field>](value: $type, cx: &mut App) {
Self::global(cx).update(cx, |this, cx| { Self::global(cx).update(cx, |this, cx| {
this.values.$field = value; this.inner.update(cx, |inner, cx| {
cx.notify(); inner.$field = value;
cx.notify();
});
}); });
} }
} }
@@ -185,7 +187,7 @@ impl Global for GlobalAppSettings {}
/// Application settings /// Application settings
pub struct AppSettings { pub struct AppSettings {
/// Settings /// Settings
values: Settings, inner: Entity<Settings>,
/// Event subscriptions /// Event subscriptions
_subscriptions: SmallVec<[Subscription; 2]>, _subscriptions: SmallVec<[Subscription; 2]>,
@@ -203,11 +205,12 @@ impl AppSettings {
} }
fn new(window: &mut Window, cx: &mut Context<Self>) -> Self { fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
let inner = cx.new(|_| Settings::default());
let mut subscriptions = smallvec![]; let mut subscriptions = smallvec![];
subscriptions.push( subscriptions.push(
// Observe and automatically save settings on changes // Observe and automatically save settings on changes
cx.observe_self(|this, cx| { cx.observe(&inner, |this, _inner, cx| {
this.save(cx); this.save(cx);
}), }),
); );
@@ -218,15 +221,17 @@ impl AppSettings {
}); });
Self { Self {
values: Settings::default(), inner,
_subscriptions: subscriptions, _subscriptions: subscriptions,
} }
} }
/// Update settings /// Update settings
fn set_settings(&mut self, settings: Settings, cx: &mut Context<Self>) { fn set_settings(&mut self, settings: Settings, cx: &mut Context<Self>) {
self.values = settings; self.inner.update(cx, |this, cx| {
cx.notify(); *this = settings;
cx.notify();
});
} }
/// Load settings /// Load settings
@@ -256,19 +261,16 @@ impl AppSettings {
/// Save settings /// Save settings
pub fn save(&mut self, cx: &mut Context<Self>) { pub fn save(&mut self, cx: &mut Context<Self>) {
let settings = self.values.clone(); let settings = self.inner.read(cx);
let task: Task<Result<(), Error>> = cx.background_spawn(async move { if let Ok(content) = serde_json::to_string(&settings) {
let path = config_dir().join(".settings"); cx.background_spawn(async move {
let content = serde_json::to_string(&settings)?; let path = config_dir().join(".settings");
// Write settings to file
// Write settings to file smol::fs::write(&path, content).await.ok();
smol::fs::write(&path, content).await?; })
.detach();
Ok(()) }
});
task.detach();
} }
/// Set theme /// Set theme
@@ -277,8 +279,10 @@ impl AppSettings {
T: Into<String>, T: Into<String>,
{ {
// Update settings // Update settings
self.values.theme = Some(theme.into()); self.inner.update(cx, |this, cx| {
cx.notify(); this.theme = Some(theme.into());
cx.notify();
});
// Apply the new theme // Apply the new theme
self.apply_theme(window, cx); self.apply_theme(window, cx);
@@ -286,16 +290,17 @@ impl AppSettings {
/// Reset theme /// Reset theme
pub fn reset_theme(&mut self, window: &mut Window, cx: &mut Context<Self>) { pub fn reset_theme(&mut self, window: &mut Window, cx: &mut Context<Self>) {
self.values.theme = None; self.inner.update(cx, |this, cx| {
cx.notify(); this.theme = None;
cx.notify();
});
self.apply_theme(window, cx); self.apply_theme(window, cx);
} }
/// Apply theme /// Apply theme
pub fn apply_theme(&mut self, window: &mut Window, cx: &mut Context<Self>) { pub fn apply_theme(&mut self, window: &mut Window, cx: &mut Context<Self>) {
if let Some(name) = self.values.theme.as_ref() { if let Some(name) = self.inner.read(cx).theme.as_ref() {
let mode = self.values.theme_mode; let mode = self.inner.read(cx).theme_mode;
if let Ok(new_theme) = ThemeFamily::from_assets(name) { if let Ok(new_theme) = ThemeFamily::from_assets(name) {
Theme::apply_theme(Rc::new(new_theme), Some(window), cx); Theme::apply_theme(Rc::new(new_theme), Some(window), cx);
@@ -309,30 +314,22 @@ impl AppSettings {
} }
/// Check if decoupling encryption key is enabled /// Check if decoupling encryption key is enabled
pub fn is_nip4e_enabled(&self) -> bool { pub fn is_nip4e_enabled(&self, cx: &App) -> bool {
self.values.encryption_key self.inner.read(cx).encryption_key
} }
/// Check if the given relay is already authenticated /// Check if the given relay is already authenticated
pub fn trusted_relay(&self, url: &RelayUrl, _cx: &App) -> bool { pub fn trusted_relay(&self, url: &RelayUrl, cx: &App) -> bool {
self.values.trusted_relays.iter().any(|relay| { self.inner.read(cx).trusted_relays.iter().any(|relay| {
relay.as_str_without_trailing_slash() == url.as_str_without_trailing_slash() relay.as_str_without_trailing_slash() == url.as_str_without_trailing_slash()
}) })
} }
/// Add a relay to the trusted list /// Add a relay to the trusted list
pub fn add_trusted_relay(&mut self, url: &RelayUrl, cx: &mut Context<Self>) { pub fn add_trusted_relay(&mut self, url: &RelayUrl, cx: &mut Context<Self>) {
self.values.trusted_relays.insert(url.clone()); self.inner.update(cx, |this, cx| {
cx.notify(); this.trusted_relays.insert(url.clone());
} cx.notify();
});
/// Add a room configuration
pub fn add_room_config(&mut self, id: u64, config: RoomConfig, cx: &mut Context<Self>) {
self.values
.room_configs
.entry(id)
.and_modify(|this| *this = config)
.or_default();
cx.notify();
} }
} }