chore: refactor app settings (#2)

# Changelog

### Added

- [x] Add `Auth Mode` setting.
- [x] Add `Room Config` setting.

### Changed

- [x] Rename `media server` setting to `file server`

### Removed

- [x] Remove `proxy` setting. Coop is no longer depend on any 3rd party services.
- [x] Remove `contact bypass` settings. All chat requests from known contacts will be bypass by default.

**Note:**
- The Settings UI has been removed. It will be re-added in a separate PR.

Reviewed-on: #2
This commit was merged in pull request #2.
This commit is contained in:
2026-01-14 09:48:15 +08:00
parent 75c3783522
commit ac9afb1790
11 changed files with 171 additions and 310 deletions

View File

@@ -209,7 +209,7 @@ impl NewAccount {
let client = nostr.read(cx).client();
// Get the user's configured NIP96 server
let nip96_server = AppSettings::get_media_server(cx);
let nip96_server = AppSettings::get_file_server(cx);
// Open native file dialog
let paths = cx.prompt_for_paths(PathPromptOptions {

View File

@@ -86,8 +86,8 @@ impl RoomListItem {
impl RenderOnce for RoomListItem {
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let hide_avatar = AppSettings::get_hide_user_avatars(cx);
let require_screening = AppSettings::get_screening(cx);
let hide_avatar = AppSettings::get_hide_avatar(cx);
let screening = AppSettings::get_screening(cx);
let (
Some(public_key),
@@ -173,7 +173,7 @@ impl RenderOnce for RoomListItem {
.on_click(move |event, window, cx| {
handler(event, window, cx);
if kind != RoomKind::Ongoing && require_screening {
if kind != RoomKind::Ongoing && screening {
let screening = screening::init(public_key, window, cx);
window.open_modal(cx, move |this, _window, _cx| {

View File

@@ -183,7 +183,7 @@ impl UserProfile {
let client = nostr.read(cx).client();
// Get the user's configured NIP96 server
let nip96_server = AppSettings::get_media_server(cx);
let nip96_server = AppSettings::get_file_server(cx);
// Open native file dialog
let paths = cx.prompt_for_paths(PathPromptOptions {

View File

@@ -1,182 +1,21 @@
use gpui::http_client::Url;
use gpui::{
div, px, App, AppContext, Context, Entity, IntoElement, ParentElement, Render, SharedString,
Styled, Window,
};
use settings::AppSettings;
use theme::ActiveTheme;
use ui::button::{Button, ButtonVariants};
use ui::input::{InputState, TextInput};
use ui::switch::Switch;
use ui::{h_flex, v_flex, IconName, Sizable, Size, StyledExt};
use gpui::{div, App, AppContext, Context, Entity, IntoElement, Render, Window};
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Preferences> {
cx.new(|cx| Preferences::new(window, cx))
}
pub struct Preferences {
media_input: Entity<InputState>,
//
}
impl Preferences {
pub fn new(window: &mut Window, cx: &mut App) -> Self {
let media_server = AppSettings::get_media_server(cx).to_string();
let media_input = cx.new(|cx| {
InputState::new(window, cx)
.default_value(media_server.clone())
.placeholder(media_server)
});
Self { media_input }
pub fn new(_window: &mut Window, _cx: &mut App) -> Self {
Self {}
}
}
impl Render for Preferences {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let auto_auth = AppSettings::get_auto_auth(cx);
let backup = AppSettings::get_backup_messages(cx);
let screening = AppSettings::get_screening(cx);
let bypass = AppSettings::get_contact_bypass(cx);
let proxy = AppSettings::get_proxy_user_avatars(cx);
let hide = AppSettings::get_hide_user_avatars(cx);
let input_state = self.media_input.downgrade();
v_flex()
.child(
v_flex()
.py_2()
.border_t_1()
.border_color(cx.theme().border)
.child(
div()
.text_sm()
.text_color(cx.theme().text_placeholder)
.font_semibold()
.child(SharedString::from("Relay and Media")),
)
.child(
v_flex()
.my_1()
.gap_1()
.child(
h_flex()
.gap_1()
.child(TextInput::new(&self.media_input).xsmall())
.child(
Button::new("update")
.icon(IconName::Check)
.ghost()
.with_size(Size::Size(px(26.)))
.on_click(move |_, _window, cx| {
if let Some(input) = input_state.upgrade() {
let Ok(url) =
Url::parse(&input.read(cx).value())
else {
return;
};
AppSettings::update_media_server(url, cx);
}
}),
),
)
.child(
div()
.text_xs()
.text_color(cx.theme().text_muted)
.child(SharedString::from("Coop currently only supports NIP-96 media servers.")),
),
)
.child(
Switch::new("auth")
.label("Automatically authenticate for known relays")
.description("After you approve the authentication request, Coop will automatically complete this step next time.")
.checked(auto_auth)
.on_click(move |_, _window, cx| {
AppSettings::update_auto_auth(!auto_auth, cx);
}),
),
)
.child(
v_flex()
.py_2()
.gap_2()
.border_t_1()
.border_color(cx.theme().border)
.child(
div()
.text_sm()
.text_color(cx.theme().text_placeholder)
.font_semibold()
.child(SharedString::from("Messages")),
)
.child(
v_flex()
.gap_2()
.child(
Switch::new("screening")
.label("Screening")
.description("When opening a chat request, Coop will show a popup to help you verify the sender.")
.checked(screening)
.on_click(move |_, _window, cx| {
AppSettings::update_screening(!screening, cx);
}),
)
.child(
Switch::new("bypass")
.label("Skip screening for contacts")
.description("Requests from your contacts will automatically go to inbox.")
.checked(bypass)
.on_click(move |_, _window, cx| {
AppSettings::update_contact_bypass(!bypass, cx);
}),
)
.child(
Switch::new("backup")
.label("Backup messages")
.description("When you send a message, Coop will also forward it to your configured Messaging Relays. Disabling this will cause all messages sent during the current session to disappear when the app is closed.")
.checked(backup)
.on_click(move |_, _window, cx| {
AppSettings::update_backup_messages(!backup, cx);
}),
),
),
)
.child(
v_flex()
.py_2()
.gap_2()
.border_t_1()
.border_color(cx.theme().border)
.child(
div()
.text_sm()
.text_color(cx.theme().text_placeholder)
.font_semibold()
.child(SharedString::from("Display")),
)
.child(
v_flex()
.gap_2()
.child(
Switch::new("hide_avatar")
.label("Hide user avatars")
.description("Unload all avatar pictures to improve performance and reduce memory usage.")
.checked(hide)
.on_click(move |_, _window, cx| {
AppSettings::update_hide_user_avatars(!hide, cx);
}),
)
.child(
Switch::new("proxy_avatar")
.label("Proxy user avatars")
.description("Use wsrv.nl to resize and downscale avatar pictures (saves ~50MB of data).")
.checked(proxy)
.on_click(move |_, _window, cx| {
AppSettings::update_proxy_user_avatars(!proxy, cx);
}),
),
),
)
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
}
}

View File

@@ -207,7 +207,7 @@ impl Screening {
.hover(|this| {
this.bg(cx.theme().elevated_surface_background)
})
.child(Avatar::new(contact.avatar(true)).size(rems(1.75)))
.child(Avatar::new(contact.avatar()).size(rems(1.75)))
.child(contact.display_name()),
);
}