feat: add setting for relay authentication (#133)
* remember auth relay * . * .
This commit is contained in:
@@ -520,10 +520,19 @@ impl ChatSpace {
|
|||||||
IngesterSignal::Auth(req) => {
|
IngesterSignal::Auth(req) => {
|
||||||
let relay_url = &req.url;
|
let relay_url = &req.url;
|
||||||
let challenge = &req.challenge;
|
let challenge = &req.challenge;
|
||||||
|
let auth_auth = AppSettings::get_auto_auth(cx);
|
||||||
|
let auth_relays = AppSettings::read_global(cx).auth_relays();
|
||||||
|
|
||||||
view.update(cx, |this, cx| {
|
view.update(cx, |this, cx| {
|
||||||
this.push_auth_request(challenge, relay_url, cx);
|
this.push_auth_request(challenge, relay_url, cx);
|
||||||
|
|
||||||
|
if auth_auth && auth_relays.contains(relay_url) {
|
||||||
|
// Automatically authenticate if the relay is authenticated before
|
||||||
|
this.auth(challenge, relay_url, window, cx);
|
||||||
|
} else {
|
||||||
|
// Otherwise open the auth request popup
|
||||||
this.open_auth_request(challenge, relay_url, window, cx);
|
this.open_auth_request(challenge, relay_url, window, cx);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
@@ -783,6 +792,7 @@ impl ChatSpace {
|
|||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
|
let settings = AppSettings::global(cx);
|
||||||
let challenge = challenge.to_string();
|
let challenge = challenge.to_string();
|
||||||
let url = url.to_owned();
|
let url = url.to_owned();
|
||||||
let challenge_clone = challenge.clone();
|
let challenge_clone = challenge.clone();
|
||||||
@@ -841,8 +851,15 @@ impl ChatSpace {
|
|||||||
cx.update(|window, cx| {
|
cx.update(|window, cx| {
|
||||||
this.update(cx, |this, cx| {
|
this.update(cx, |this, cx| {
|
||||||
this.remove_auth_request(&challenge, cx);
|
this.remove_auth_request(&challenge, cx);
|
||||||
|
|
||||||
|
// Save the authenticated relay to automatically authenticate future requests
|
||||||
|
settings.update(cx, |this, cx| {
|
||||||
|
this.push_auth_relay(url.clone(), cx);
|
||||||
|
});
|
||||||
|
|
||||||
// Clear the current notification
|
// Clear the current notification
|
||||||
window.clear_notification_by_id(SharedString::from(challenge), cx);
|
window.clear_notification_by_id(SharedString::from(challenge), cx);
|
||||||
|
|
||||||
// Push a new notification after current cycle
|
// Push a new notification after current cycle
|
||||||
cx.defer_in(window, move |_, window, cx| {
|
cx.defer_in(window, move |_, window, cx| {
|
||||||
window
|
window
|
||||||
@@ -1039,7 +1056,7 @@ impl ChatSpace {
|
|||||||
window.open_modal(cx, move |modal, _window, _cx| {
|
window.open_modal(cx, move |modal, _window, _cx| {
|
||||||
modal
|
modal
|
||||||
.title(shared_t!("common.preferences"))
|
.title(shared_t!("common.preferences"))
|
||||||
.width(px(480.))
|
.width(px(580.))
|
||||||
.child(view.clone())
|
.child(view.clone())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1201,6 +1218,7 @@ impl ChatSpace {
|
|||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> impl IntoElement {
|
) -> impl IntoElement {
|
||||||
let proxy = AppSettings::get_proxy_user_avatars(cx);
|
let proxy = AppSettings::get_proxy_user_avatars(cx);
|
||||||
|
let is_auto_auth = AppSettings::read_global(cx).is_auto_auth();
|
||||||
let updating = AutoUpdater::read_global(cx).status.is_updating();
|
let updating = AutoUpdater::read_global(cx).status.is_updating();
|
||||||
let updated = AutoUpdater::read_global(cx).status.is_updated();
|
let updated = AutoUpdater::read_global(cx).status.is_updated();
|
||||||
let auth_requests = self.auth_requests.len();
|
let auth_requests = self.auth_requests.len();
|
||||||
@@ -1239,7 +1257,7 @@ impl ChatSpace {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.when(auth_requests > 0, |this| {
|
.when(auth_requests > 0 && !is_auto_auth, |this| {
|
||||||
this.child(
|
this.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
.id("requests")
|
.id("requests")
|
||||||
|
|||||||
@@ -4,22 +4,22 @@ use gpui::{
|
|||||||
div, px, relative, rems, App, AppContext, Context, Entity, InteractiveElement, IntoElement,
|
div, px, relative, rems, App, AppContext, Context, Entity, InteractiveElement, IntoElement,
|
||||||
ParentElement, Render, SharedString, StatefulInteractiveElement, Styled, Window,
|
ParentElement, Render, SharedString, StatefulInteractiveElement, Styled, Window,
|
||||||
};
|
};
|
||||||
use i18n::t;
|
use i18n::{shared_t, t};
|
||||||
use nostr_sdk::prelude::*;
|
use nostr_sdk::prelude::*;
|
||||||
use registry::Registry;
|
use registry::Registry;
|
||||||
use settings::AppSettings;
|
use settings::AppSettings;
|
||||||
use theme::ActiveTheme;
|
use theme::ActiveTheme;
|
||||||
use ui::avatar::Avatar;
|
use ui::avatar::Avatar;
|
||||||
use ui::button::{Button, ButtonVariants};
|
use ui::button::{Button, ButtonRounded, ButtonVariants};
|
||||||
use ui::input::{InputState, TextInput};
|
use ui::input::{InputState, TextInput};
|
||||||
use ui::modal::ModalButtonProps;
|
use ui::modal::ModalButtonProps;
|
||||||
use ui::switch::Switch;
|
use ui::switch::Switch;
|
||||||
use ui::{v_flex, ContextModal, IconName, Sizable, Size, StyledExt};
|
use ui::{h_flex, v_flex, ContextModal, IconName, Sizable, Size, StyledExt};
|
||||||
|
|
||||||
use crate::views::{edit_profile, setup_relay};
|
use crate::views::{edit_profile, setup_relay};
|
||||||
|
|
||||||
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Preferences> {
|
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Preferences> {
|
||||||
Preferences::new(window, cx)
|
cx.new(|cx| Preferences::new(window, cx))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Preferences {
|
pub struct Preferences {
|
||||||
@@ -27,8 +27,7 @@ pub struct Preferences {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Preferences {
|
impl Preferences {
|
||||||
pub fn new(window: &mut Window, cx: &mut App) -> Entity<Self> {
|
pub fn new(window: &mut Window, cx: &mut App) -> Self {
|
||||||
cx.new(|cx| {
|
|
||||||
let media_server = AppSettings::get_media_server(cx).to_string();
|
let media_server = AppSettings::get_media_server(cx).to_string();
|
||||||
let media_input = cx.new(|cx| {
|
let media_input = cx.new(|cx| {
|
||||||
InputState::new(window, cx)
|
InputState::new(window, cx)
|
||||||
@@ -37,7 +36,6 @@ impl Preferences {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Self { media_input }
|
Self { media_input }
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open_edit_profile(&self, window: &mut Window, cx: &mut Context<Self>) {
|
fn open_edit_profile(&self, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
@@ -117,58 +115,50 @@ impl Render for Preferences {
|
|||||||
let input_state = self.media_input.downgrade();
|
let input_state = self.media_input.downgrade();
|
||||||
let profile = Registry::read_global(cx).identity(cx);
|
let profile = Registry::read_global(cx).identity(cx);
|
||||||
|
|
||||||
let backup_messages = AppSettings::get_backup_messages(cx);
|
let auto_auth = AppSettings::get_auto_auth(cx);
|
||||||
|
let backup = AppSettings::get_backup_messages(cx);
|
||||||
let screening = AppSettings::get_screening(cx);
|
let screening = AppSettings::get_screening(cx);
|
||||||
let contact_bypass = AppSettings::get_contact_bypass(cx);
|
let bypass = AppSettings::get_contact_bypass(cx);
|
||||||
let proxy_avatar = AppSettings::get_proxy_user_avatars(cx);
|
let proxy = AppSettings::get_proxy_user_avatars(cx);
|
||||||
let hide_avatar = AppSettings::get_hide_user_avatars(cx);
|
let hide = AppSettings::get_hide_user_avatars(cx);
|
||||||
|
|
||||||
v_flex()
|
v_flex()
|
||||||
.child(
|
.child(
|
||||||
v_flex()
|
v_flex()
|
||||||
.py_2()
|
.pb_2()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.text_sm()
|
.text_sm()
|
||||||
.text_color(cx.theme().text_placeholder)
|
.text_color(cx.theme().text_placeholder)
|
||||||
.font_semibold()
|
.font_semibold()
|
||||||
.child(SharedString::new(t!("preferences.account_header"))),
|
.child(shared_t!("preferences.account_header")),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
div()
|
h_flex()
|
||||||
.w_full()
|
.w_full()
|
||||||
.flex()
|
|
||||||
.justify_between()
|
.justify_between()
|
||||||
.items_center()
|
|
||||||
.child(
|
.child(
|
||||||
div()
|
h_flex()
|
||||||
.id("current-user")
|
.id("user")
|
||||||
.flex()
|
|
||||||
.items_center()
|
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.child(
|
.child(Avatar::new(profile.avatar_url(proxy)).size(rems(2.4)))
|
||||||
Avatar::new(profile.avatar_url(proxy_avatar))
|
|
||||||
.size(rems(2.4)),
|
|
||||||
)
|
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.flex_1()
|
.flex_1()
|
||||||
.text_sm()
|
.text_sm()
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.line_height(relative(1.3))
|
|
||||||
.font_semibold()
|
.font_semibold()
|
||||||
|
.line_height(relative(1.3))
|
||||||
.child(profile.display_name()),
|
.child(profile.display_name()),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.line_height(relative(1.3))
|
|
||||||
.text_xs()
|
.text_xs()
|
||||||
.text_color(cx.theme().text_muted)
|
.text_color(cx.theme().text_muted)
|
||||||
.child(SharedString::new(t!(
|
.line_height(relative(1.3))
|
||||||
"preferences.see_your_profile"
|
.child(shared_t!("preferences.account_btn")),
|
||||||
))),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.on_click(cx.listener(move |this, _e, window, cx| {
|
.on_click(cx.listener(move |this, _e, window, cx| {
|
||||||
@@ -178,8 +168,9 @@ impl Render for Preferences {
|
|||||||
.child(
|
.child(
|
||||||
Button::new("relays")
|
Button::new("relays")
|
||||||
.label("Messaging Relays")
|
.label("Messaging Relays")
|
||||||
.ghost()
|
.xsmall()
|
||||||
.small()
|
.ghost_alt()
|
||||||
|
.rounded(ButtonRounded::Full)
|
||||||
.on_click(cx.listener(move |this, _e, window, cx| {
|
.on_click(cx.listener(move |this, _e, window, cx| {
|
||||||
this.open_relays(window, cx);
|
this.open_relays(window, cx);
|
||||||
})),
|
})),
|
||||||
@@ -196,27 +187,26 @@ impl Render for Preferences {
|
|||||||
.text_sm()
|
.text_sm()
|
||||||
.text_color(cx.theme().text_placeholder)
|
.text_color(cx.theme().text_placeholder)
|
||||||
.font_semibold()
|
.font_semibold()
|
||||||
.child(SharedString::new(t!("preferences.media_server_header"))),
|
.child(shared_t!("preferences.relay_and_media")),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
div()
|
v_flex()
|
||||||
.my_1()
|
.my_1()
|
||||||
.flex()
|
.gap_1()
|
||||||
.items_start()
|
.child(
|
||||||
|
h_flex()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
.child(TextInput::new(&self.media_input).xsmall())
|
.child(TextInput::new(&self.media_input).xsmall())
|
||||||
.child(
|
.child(
|
||||||
Button::new("update")
|
Button::new("update")
|
||||||
.icon(IconName::CheckCircleFill)
|
.icon(IconName::Check)
|
||||||
.ghost()
|
.ghost()
|
||||||
.with_size(Size::Size(px(26.)))
|
.with_size(Size::Size(px(26.)))
|
||||||
.on_click(move |_, window, cx| {
|
.on_click(move |_, _window, cx| {
|
||||||
if let Some(input) = input_state.upgrade() {
|
if let Some(input) = input_state.upgrade() {
|
||||||
let Ok(url) = Url::parse(input.read(cx).value()) else {
|
let Ok(url) =
|
||||||
window.push_notification(
|
Url::parse(input.read(cx).value())
|
||||||
t!("preferences.url_not_valid"),
|
else {
|
||||||
cx,
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
AppSettings::update_media_server(url, cx);
|
AppSettings::update_media_server(url, cx);
|
||||||
@@ -228,7 +218,17 @@ impl Render for Preferences {
|
|||||||
div()
|
div()
|
||||||
.text_xs()
|
.text_xs()
|
||||||
.text_color(cx.theme().text_muted)
|
.text_color(cx.theme().text_muted)
|
||||||
.child(SharedString::new(t!("preferences.media_description"))),
|
.child(shared_t!("preferences.media_description")),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Switch::new("auth")
|
||||||
|
.label(t!("preferences.auto_auth"))
|
||||||
|
.description(t!("preferences.auto_auth_description"))
|
||||||
|
.checked(auto_auth)
|
||||||
|
.on_click(move |_, _window, cx| {
|
||||||
|
AppSettings::update_auto_auth(!auto_auth, cx);
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
@@ -242,7 +242,7 @@ impl Render for Preferences {
|
|||||||
.text_sm()
|
.text_sm()
|
||||||
.text_color(cx.theme().text_placeholder)
|
.text_color(cx.theme().text_placeholder)
|
||||||
.font_semibold()
|
.font_semibold()
|
||||||
.child(SharedString::new(t!("preferences.messages_header"))),
|
.child(shared_t!("preferences.messages_header")),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
v_flex()
|
v_flex()
|
||||||
@@ -260,18 +260,18 @@ impl Render for Preferences {
|
|||||||
Switch::new("bypass")
|
Switch::new("bypass")
|
||||||
.label(t!("preferences.bypass_label"))
|
.label(t!("preferences.bypass_label"))
|
||||||
.description(t!("preferences.bypass_description"))
|
.description(t!("preferences.bypass_description"))
|
||||||
.checked(contact_bypass)
|
.checked(bypass)
|
||||||
.on_click(move |_, _window, cx| {
|
.on_click(move |_, _window, cx| {
|
||||||
AppSettings::update_contact_bypass(!contact_bypass, cx);
|
AppSettings::update_contact_bypass(!bypass, cx);
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
Switch::new("backup_messages")
|
Switch::new("backup")
|
||||||
.label(t!("preferences.backup_messages_label"))
|
.label(t!("preferences.backup_label"))
|
||||||
.description(t!("preferences.backup_description"))
|
.description(t!("preferences.backup_description"))
|
||||||
.checked(backup_messages)
|
.checked(backup)
|
||||||
.on_click(move |_, _window, cx| {
|
.on_click(move |_, _window, cx| {
|
||||||
AppSettings::update_backup_messages(!backup_messages, cx);
|
AppSettings::update_backup_messages(!backup, cx);
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -287,27 +287,27 @@ impl Render for Preferences {
|
|||||||
.text_sm()
|
.text_sm()
|
||||||
.text_color(cx.theme().text_placeholder)
|
.text_color(cx.theme().text_placeholder)
|
||||||
.font_semibold()
|
.font_semibold()
|
||||||
.child(SharedString::new(t!("preferences.display_header"))),
|
.child(shared_t!("preferences.display_header")),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
v_flex()
|
v_flex()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.child(
|
.child(
|
||||||
Switch::new("hide_user_avatars")
|
Switch::new("hide_avatar")
|
||||||
.label(t!("preferences.hide_avatars_label"))
|
.label(t!("preferences.hide_avatars_label"))
|
||||||
.description(t!("preferences.hide_avatar_description"))
|
.description(t!("preferences.hide_avatar_description"))
|
||||||
.checked(hide_avatar)
|
.checked(hide)
|
||||||
.on_click(move |_, _window, cx| {
|
.on_click(move |_, _window, cx| {
|
||||||
AppSettings::update_hide_user_avatars(!hide_avatar, cx);
|
AppSettings::update_hide_user_avatars(!hide, cx);
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
Switch::new("proxy_user_avatars")
|
Switch::new("proxy_avatar")
|
||||||
.label(t!("preferences.proxy_avatars_label"))
|
.label(t!("preferences.proxy_avatars_label"))
|
||||||
.description(t!("preferences.proxy_description"))
|
.description(t!("preferences.proxy_description"))
|
||||||
.checked(proxy_avatar)
|
.checked(proxy)
|
||||||
.on_click(move |_, _window, cx| {
|
.on_click(move |_, _window, cx| {
|
||||||
AppSettings::update_proxy_user_avatars(!proxy_avatar, cx);
|
AppSettings::update_proxy_user_avatars(!proxy, cx);
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ pub const APP_UPDATER_ENDPOINT: &str = "https://coop-updater.reya.su/";
|
|||||||
pub const KEYRING_URL: &str = "Coop Safe Storage";
|
pub const KEYRING_URL: &str = "Coop Safe Storage";
|
||||||
|
|
||||||
pub const ACCOUNT_IDENTIFIER: &str = "coop:user";
|
pub const ACCOUNT_IDENTIFIER: &str = "coop:user";
|
||||||
pub const SETTINGS_D: &str = "coop:settings";
|
pub const SETTINGS_IDENTIFIER: &str = "coop:settings";
|
||||||
|
|
||||||
/// Bootstrap Relays.
|
/// Bootstrap Relays.
|
||||||
pub const BOOTSTRAP_RELAYS: [&str; 5] = [
|
pub const BOOTSTRAP_RELAYS: [&str; 5] = [
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use global::constants::SETTINGS_D;
|
use global::constants::SETTINGS_IDENTIFIER;
|
||||||
use global::nostr_client;
|
use global::nostr_client;
|
||||||
use gpui::{App, AppContext, Context, Entity, Global, Subscription, Task};
|
use gpui::{App, AppContext, Context, Entity, Global, Subscription, Task};
|
||||||
use nostr_sdk::prelude::*;
|
use nostr_sdk::prelude::*;
|
||||||
@@ -11,7 +11,7 @@ pub fn init(cx: &mut App) {
|
|||||||
|
|
||||||
// Observe for state changes and save settings to database
|
// Observe for state changes and save settings to database
|
||||||
state.update(cx, |this, cx| {
|
state.update(cx, |this, cx| {
|
||||||
this.subscriptions
|
this._subscriptions
|
||||||
.push(cx.observe(&state, |this, _state, cx| {
|
.push(cx.observe(&state, |this, _state, cx| {
|
||||||
this.set_settings(cx);
|
this.set_settings(cx);
|
||||||
}));
|
}));
|
||||||
@@ -49,6 +49,7 @@ setting_accessors! {
|
|||||||
pub screening: bool,
|
pub screening: bool,
|
||||||
pub contact_bypass: bool,
|
pub contact_bypass: bool,
|
||||||
pub auto_login: bool,
|
pub auto_login: bool,
|
||||||
|
pub auto_auth: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
@@ -60,6 +61,8 @@ pub struct Settings {
|
|||||||
pub screening: bool,
|
pub screening: bool,
|
||||||
pub contact_bypass: bool,
|
pub contact_bypass: bool,
|
||||||
pub auto_login: bool,
|
pub auto_login: bool,
|
||||||
|
pub auto_auth: bool,
|
||||||
|
pub authenticated_relays: Vec<RelayUrl>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Settings {
|
impl Default for Settings {
|
||||||
@@ -72,6 +75,8 @@ impl Default for Settings {
|
|||||||
screening: true,
|
screening: true,
|
||||||
contact_bypass: true,
|
contact_bypass: true,
|
||||||
auto_login: false,
|
auto_login: false,
|
||||||
|
auto_auth: true,
|
||||||
|
authenticated_relays: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,8 +93,8 @@ impl Global for GlobalAppSettings {}
|
|||||||
|
|
||||||
pub struct AppSettings {
|
pub struct AppSettings {
|
||||||
setting_values: Settings,
|
setting_values: Settings,
|
||||||
#[allow(dead_code)]
|
_subscriptions: SmallVec<[Subscription; 1]>,
|
||||||
subscriptions: SmallVec<[Subscription; 1]>,
|
_tasks: SmallVec<[Task<()>; 1]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppSettings {
|
impl AppSettings {
|
||||||
@@ -110,33 +115,24 @@ impl AppSettings {
|
|||||||
|
|
||||||
fn new(cx: &mut Context<Self>) -> Self {
|
fn new(cx: &mut Context<Self>) -> Self {
|
||||||
let setting_values = Settings::default();
|
let setting_values = Settings::default();
|
||||||
let mut subscriptions = smallvec![];
|
let mut tasks = smallvec![];
|
||||||
|
|
||||||
subscriptions.push(cx.observe_new::<Self>(move |this, _window, cx| {
|
|
||||||
this.get_settings_from_db(cx);
|
|
||||||
}));
|
|
||||||
|
|
||||||
Self {
|
|
||||||
setting_values,
|
|
||||||
subscriptions,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn get_settings_from_db(&self, cx: &mut Context<Self>) {
|
|
||||||
let task: Task<Result<Settings, anyhow::Error>> = cx.background_spawn(async move {
|
let task: Task<Result<Settings, anyhow::Error>> = cx.background_spawn(async move {
|
||||||
|
let client = nostr_client();
|
||||||
let filter = Filter::new()
|
let filter = Filter::new()
|
||||||
.kind(Kind::ApplicationSpecificData)
|
.kind(Kind::ApplicationSpecificData)
|
||||||
.identifier(SETTINGS_D)
|
.identifier(SETTINGS_IDENTIFIER)
|
||||||
.limit(1);
|
.limit(1);
|
||||||
|
|
||||||
if let Some(event) = nostr_client().database().query(filter).await?.first_owned() {
|
if let Some(event) = client.database().query(filter).await?.first_owned() {
|
||||||
log::info!("Successfully loaded settings from database");
|
|
||||||
Ok(serde_json::from_str(&event.content).unwrap_or(Settings::default()))
|
Ok(serde_json::from_str(&event.content).unwrap_or(Settings::default()))
|
||||||
} else {
|
} else {
|
||||||
Err(anyhow!("Not found"))
|
Err(anyhow!("Not found"))
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
tasks.push(
|
||||||
|
// Load settings from database
|
||||||
cx.spawn(async move |this, cx| {
|
cx.spawn(async move |this, cx| {
|
||||||
if let Ok(settings) = task.await {
|
if let Ok(settings) = task.await {
|
||||||
this.update(cx, |this, cx| {
|
this.update(cx, |this, cx| {
|
||||||
@@ -145,19 +141,27 @@ impl AppSettings {
|
|||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
})
|
}),
|
||||||
.detach();
|
);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
setting_values,
|
||||||
|
_subscriptions: smallvec![],
|
||||||
|
_tasks: tasks,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_settings(&self, cx: &mut Context<Self>) {
|
pub(crate) fn set_settings(&self, cx: &mut Context<Self>) {
|
||||||
if let Ok(content) = serde_json::to_string(&self.setting_values) {
|
if let Ok(content) = serde_json::to_string(&self.setting_values) {
|
||||||
cx.background_spawn(async move {
|
cx.background_spawn(async move {
|
||||||
if let Ok(event) = EventBuilder::new(Kind::ApplicationSpecificData, content)
|
let client = nostr_client();
|
||||||
.tags(vec![Tag::identifier(SETTINGS_D)])
|
let builder = EventBuilder::new(Kind::ApplicationSpecificData, content)
|
||||||
|
.tags(vec![Tag::identifier(SETTINGS_IDENTIFIER)])
|
||||||
.sign(&Keys::generate())
|
.sign(&Keys::generate())
|
||||||
.await
|
.await;
|
||||||
{
|
|
||||||
if let Err(e) = nostr_client().database().save_event(&event).await {
|
if let Ok(event) = builder {
|
||||||
|
if let Err(e) = client.database().save_event(&event).await {
|
||||||
log::error!("Failed to save user settings: {e}");
|
log::error!("Failed to save user settings: {e}");
|
||||||
} else {
|
} else {
|
||||||
log::info!("New settings have been saved successfully");
|
log::info!("New settings have been saved successfully");
|
||||||
@@ -167,4 +171,17 @@ impl AppSettings {
|
|||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_auto_auth(&self) -> bool {
|
||||||
|
!self.setting_values.authenticated_relays.is_empty() && self.setting_values.auto_auth
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn auth_relays(&self) -> Vec<RelayUrl> {
|
||||||
|
self.setting_values.authenticated_relays.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_auth_relay(&mut self, relay_url: RelayUrl, cx: &mut Context<Self>) {
|
||||||
|
self.setting_values.authenticated_relays.push(relay_url);
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,40 +257,42 @@ profile:
|
|||||||
en: "No bio."
|
en: "No bio."
|
||||||
|
|
||||||
preferences:
|
preferences:
|
||||||
media_description:
|
|
||||||
en: "Coop currently only supports NIP-96 media servers."
|
|
||||||
backup_description:
|
|
||||||
en: "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."
|
|
||||||
screening_description:
|
|
||||||
en: "When opening a chat request, Coop will show a popup to help you verify the sender."
|
|
||||||
bypass_description:
|
|
||||||
en: "Requests from your contacts will automatically go to inbox."
|
|
||||||
hide_avatar_description:
|
|
||||||
en: "Unload all avatar pictures to improve performance and reduce memory usage."
|
|
||||||
proxy_description:
|
|
||||||
en: "Use wsrv.nl to resize and downscale avatar pictures (saves ~50MB of data)."
|
|
||||||
account_header:
|
account_header:
|
||||||
en: "Account"
|
en: "Account"
|
||||||
see_your_profile:
|
account_btn:
|
||||||
en: "See your profile"
|
en: "See your profile"
|
||||||
media_server_header:
|
relay_and_media:
|
||||||
en: "Media Server"
|
en: "Relay and Media"
|
||||||
url_not_valid:
|
media_description:
|
||||||
en: "URL is not valid"
|
en: "Coop currently only supports NIP-96 media servers."
|
||||||
messages_header:
|
auto_auth:
|
||||||
en: "Messages"
|
en: "Automatically authenticate for known relays"
|
||||||
backup_messages_label:
|
auto_auth_description:
|
||||||
|
en: "After you approve the authentication request, Coop will automatically complete this step next time."
|
||||||
|
backup_label:
|
||||||
en: "Backup messages"
|
en: "Backup messages"
|
||||||
|
backup_description:
|
||||||
|
en: "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."
|
||||||
screening_label:
|
screening_label:
|
||||||
en: "Screening"
|
en: "Screening"
|
||||||
|
screening_description:
|
||||||
|
en: "When opening a chat request, Coop will show a popup to help you verify the sender."
|
||||||
bypass_label:
|
bypass_label:
|
||||||
en: "Skip screening for contacts"
|
en: "Skip screening for contacts"
|
||||||
display_header:
|
bypass_description:
|
||||||
en: "Display"
|
en: "Requests from your contacts will automatically go to inbox."
|
||||||
hide_avatars_label:
|
hide_avatars_label:
|
||||||
en: "Hide user avatars"
|
en: "Hide user avatars"
|
||||||
|
hide_avatar_description:
|
||||||
|
en: "Unload all avatar pictures to improve performance and reduce memory usage."
|
||||||
proxy_avatars_label:
|
proxy_avatars_label:
|
||||||
en: "Proxy user avatars"
|
en: "Proxy user avatars"
|
||||||
|
proxy_description:
|
||||||
|
en: "Use wsrv.nl to resize and downscale avatar pictures (saves ~50MB of data)."
|
||||||
|
messages_header:
|
||||||
|
en: "Messages"
|
||||||
|
display_header:
|
||||||
|
en: "Display"
|
||||||
|
|
||||||
compose:
|
compose:
|
||||||
placeholder_npub:
|
placeholder_npub:
|
||||||
|
|||||||
Reference in New Issue
Block a user