chore: clean up codebase (#186)

* refactor app state

* clean up

* clean up

* .
This commit is contained in:
reya
2025-10-18 09:46:45 +07:00
committed by GitHub
parent 32a0401907
commit a1e0934fc3
37 changed files with 516 additions and 1716 deletions

View File

@@ -32,12 +32,11 @@ ui = { path = "../ui" }
title_bar = { path = "../title_bar" }
theme = { path = "../theme" }
common = { path = "../common" }
app_state = { path = "../app_state" }
states = { path = "../states" }
registry = { path = "../registry" }
settings = { path = "../settings" }
client_keys = { path = "../client_keys" }
auto_update = { path = "../auto_update" }
signer_proxy = { path = "../signer_proxy" }
rust-i18n.workspace = true
i18n.workspace = true

View File

@@ -1,13 +1,8 @@
use std::borrow::Cow;
use std::collections::{HashMap, HashSet};
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::time::Duration;
use anyhow::{anyhow, Error};
use app_state::constants::{ACCOUNT_IDENTIFIER, BOOTSTRAP_RELAYS, DEFAULT_SIDEBAR_WIDTH};
use app_state::state::{AuthRequest, SignalKind, UnwrappingStatus};
use app_state::{app_state, default_nip17_relays, default_nip65_relays, nostr_client};
use auto_update::AutoUpdater;
use client_keys::ClientKeys;
use common::display::RenderedProfile;
@@ -24,8 +19,10 @@ use nostr_connect::prelude::*;
use nostr_sdk::prelude::*;
use registry::{Registry, RegistryEvent};
use settings::AppSettings;
use signer_proxy::{BrowserSignerProxy, BrowserSignerProxyOptions};
use smallvec::{smallvec, SmallVec};
use states::constants::{ACCOUNT_IDENTIFIER, BOOTSTRAP_RELAYS, DEFAULT_SIDEBAR_WIDTH};
use states::state::{AuthRequest, SignalKind, UnwrappingStatus};
use states::{app_state, default_nip17_relays, default_nip65_relays};
use theme::{ActiveTheme, Theme, ThemeMode};
use title_bar::TitleBar;
use ui::actions::{CopyPublicKey, OpenPublicKey};
@@ -121,21 +118,15 @@ impl ChatSpace {
let status = status.read(cx);
let all_panels = this.get_all_panel_ids(cx);
match status {
UnwrappingStatus::Processing => {
registry.update(cx, |this, cx| {
this.load_rooms(window, cx);
this.refresh_rooms(all_panels, cx);
});
}
UnwrappingStatus::Complete => {
registry.update(cx, |this, cx| {
this.load_rooms(window, cx);
this.refresh_rooms(all_panels, cx);
});
}
_ => {}
};
if matches!(
status,
UnwrappingStatus::Processing | UnwrappingStatus::Complete
) {
registry.update(cx, |this, cx| {
this.load_rooms(window, cx);
this.refresh_rooms(all_panels, cx);
});
}
}),
);
@@ -184,14 +175,14 @@ impl ChatSpace {
// Wait for the signer to be set
// Also verify NIP-65 and NIP-17 relays after the signer is set
cx.background_spawn(async move {
Self::observe_signer().await;
app_state().observe_signer().await;
}),
);
tasks.push(
// Observe gift wrap process in the background
cx.background_spawn(async move {
Self::observe_giftwrap().await;
app_state().observe_giftwrap().await;
}),
);
@@ -213,90 +204,19 @@ impl ChatSpace {
}
}
async fn observe_signer() {
let client = nostr_client();
let app_state = app_state();
let loop_duration = Duration::from_millis(800);
loop {
if let Ok(signer) = client.signer().await {
if let Ok(pk) = signer.get_public_key().await {
// Notify the app that the signer has been set
app_state.signal.send(SignalKind::SignerSet(pk)).await;
// Get user's gossip relays
app_state.get_nip65(pk).await.ok();
// Exit the current loop
break;
}
}
smol::Timer::after(loop_duration).await;
}
}
async fn observe_giftwrap() {
let client = nostr_client();
let app_state = app_state();
let loop_duration = Duration::from_secs(20);
let mut is_start_processing = false;
let mut total_loops = 0;
loop {
if client.has_signer().await {
total_loops += 1;
if app_state.gift_wrap_processing.load(Ordering::Acquire) {
is_start_processing = true;
// Reset gift wrap processing flag
let _ = app_state.gift_wrap_processing.compare_exchange(
true,
false,
Ordering::Release,
Ordering::Relaxed,
);
let signal = SignalKind::GiftWrapStatus(UnwrappingStatus::Processing);
app_state.signal.send(signal).await;
} else {
// Only run further if we are already processing
// Wait until after 2 loops to prevent exiting early while events are still being processed
if is_start_processing && total_loops >= 2 {
let signal = SignalKind::GiftWrapStatus(UnwrappingStatus::Complete);
app_state.signal.send(signal).await;
// Reset the counter
is_start_processing = false;
total_loops = 0;
}
}
}
smol::Timer::after(loop_duration).await;
}
}
async fn handle_signals(view: WeakEntity<ChatSpace>, cx: &mut AsyncWindowContext) {
let app_state = app_state();
let mut is_open_proxy_modal = false;
let states = app_state();
while let Ok(signal) = app_state.signal.receiver().recv_async().await {
cx.update(|window, cx| {
while let Ok(signal) = states.signal().receiver().recv_async().await {
view.update_in(cx, |this, window, cx| {
let registry = Registry::global(cx);
let settings = AppSettings::global(cx);
match signal {
SignalKind::SignerSet(public_key) => {
// Close the latest modal if it exists
window.close_modal(cx);
// Setup the default layout for current workspace
view.update(cx, |this, cx| {
this.set_default_layout(window, cx);
})
.ok();
// Load user's settings
settings.update(cx, |this, cx| {
this.load_settings(cx);
@@ -307,45 +227,33 @@ impl ChatSpace {
this.set_signer_pubkey(public_key, cx);
this.load_rooms(window, cx);
});
// Setup the default layout for current workspace
this.set_default_layout(window, cx);
}
SignalKind::SignerUnset => {
// Setup the onboarding layout for current workspace
view.update(cx, |this, cx| {
this.set_onboarding_layout(window, cx);
})
.ok();
// Clear all current chat rooms
registry.update(cx, |this, cx| {
this.reset(cx);
});
// Setup the onboarding layout for current workspace
this.set_onboarding_layout(window, cx);
}
SignalKind::Auth(req) => {
let url = &req.url;
let auto_auth = AppSettings::get_auto_auth(cx);
let is_authenticated = AppSettings::read_global(cx).is_authenticated(url);
view.update(cx, |this, cx| {
this.push_auth_request(&req, cx);
// Store the auth request in the current view
this.push_auth_request(&req, cx);
if auto_auth && is_authenticated {
// Automatically authenticate if the relay is authenticated before
this.auth(req, window, cx);
} else {
// Otherwise open the auth request popup
this.open_auth_request(req, window, cx);
}
})
.ok();
}
SignalKind::ProxyDown => {
if !is_open_proxy_modal {
is_open_proxy_modal = true;
view.update(cx, |this, cx| {
this.render_proxy_modal(window, cx);
})
.ok();
if auto_auth && is_authenticated {
// Automatically authenticate if the relay is authenticated before
this.auth(req, window, cx);
} else {
// Otherwise open the auth request popup
this.open_auth_request(req, window, cx);
}
}
SignalKind::GiftWrapStatus(status) => {
@@ -364,17 +272,11 @@ impl ChatSpace {
});
}
SignalKind::GossipRelaysNotFound => {
view.update(cx, |this, cx| {
this.set_required_gossip_relays(cx);
this.render_setup_gossip_relays_modal(window, cx);
})
.ok();
this.set_required_gossip_relays(cx);
this.render_setup_gossip_relays_modal(window, cx);
}
SignalKind::MessagingRelaysNotFound => {
view.update(cx, |this, cx| {
this.set_required_dm_relays(cx);
})
.ok();
this.set_required_dm_relays(cx);
}
};
})
@@ -395,8 +297,8 @@ impl ChatSpace {
self.sending_auth_request(&challenge, cx);
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
let client = nostr_client();
let app_state = app_state();
let states = app_state();
let client = states.client();
let signer = client.signer().await?;
// Construct event
@@ -427,9 +329,9 @@ impl ChatSpace {
relay.resubscribe().await?;
// Get all failed events that need to be resent
let mut event_tracker = app_state.event_tracker.write().await;
let mut tracker = states.tracker().write().await;
let ids: Vec<EventId> = event_tracker
let ids: Vec<EventId> = tracker
.resend_queue
.iter()
.filter(|(_, url)| relay_url == *url)
@@ -437,7 +339,7 @@ impl ChatSpace {
.collect();
for id in ids.into_iter() {
if let Some(relay_url) = event_tracker.resend_queue.remove(&id) {
if let Some(relay_url) = tracker.resend_queue.remove(&id) {
if let Some(event) = client.database().event_by_id(&id).await? {
let event_id = relay.send_event(&event).await?;
@@ -447,8 +349,8 @@ impl ChatSpace {
success: HashSet::from([relay_url]),
};
event_tracker.sent_ids.insert(event_id);
event_tracker.resent_ids.push(output);
tracker.sent_ids.insert(event_id);
tracker.resent_ids.push(output);
}
}
}
@@ -656,7 +558,8 @@ impl ChatSpace {
fn load_local_account(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let task = cx.background_spawn(async move {
let client = nostr_client();
let client = app_state().client();
let filter = Filter::new()
.kind(Kind::ApplicationSpecificData)
.identifier(ACCOUNT_IDENTIFIER)
@@ -717,9 +620,10 @@ impl ChatSpace {
cx: &mut Context<Self>,
) {
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
let client = nostr_client();
let app_state = app_state();
let states = app_state();
let client = states.client();
let opts = SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE);
let filter = Filter::new().kind(Kind::PrivateDirectMessage);
let pubkeys: Vec<PublicKey> = client
@@ -737,7 +641,7 @@ impl ChatSpace {
.authors(pubkeys);
client
.subscribe_to(BOOTSTRAP_RELAYS, filter, app_state.auto_close_opts)
.subscribe_to(BOOTSTRAP_RELAYS, filter, Some(opts))
.await?;
Ok(())
@@ -756,8 +660,8 @@ impl ChatSpace {
fn on_sign_out(&mut self, _e: &Logout, _window: &mut Window, cx: &mut Context<Self>) {
cx.background_spawn(async move {
let client = nostr_client();
let app_state = app_state();
let states = app_state();
let client = states.client();
let filter = Filter::new()
.kind(Kind::ApplicationSpecificData)
@@ -770,7 +674,7 @@ impl ChatSpace {
client.reset().await;
// Notify the channel about the signer being unset
app_state.signal.send(SignalKind::SignerUnset).await;
states.signal().send(SignalKind::SignerUnset).await;
})
.detach();
}
@@ -799,6 +703,37 @@ impl ChatSpace {
window.push_notification(t!("common.copied"), cx);
}
fn get_all_panel_ids(&self, cx: &App) -> Option<Vec<u64>> {
let ids: Vec<u64> = self
.dock
.read(cx)
.items
.panel_ids(cx)
.into_iter()
.filter_map(|panel| panel.parse::<u64>().ok())
.collect();
Some(ids)
}
fn set_center_panel<P>(panel: P, window: &mut Window, cx: &mut App)
where
P: PanelView,
{
if let Some(Some(root)) = window.root::<Root>() {
if let Ok(chatspace) = root.read(cx).view().clone().downcast::<ChatSpace>() {
let panel = Arc::new(panel);
let center = DockItem::panel(panel);
chatspace.update(cx, |this, cx| {
this.dock.update(cx, |this, cx| {
this.set_center(center, window, cx);
});
});
}
}
}
fn render_setup_gossip_relays_modal(&mut self, window: &mut Window, cx: &mut App) {
let relays = default_nip65_relays();
@@ -875,9 +810,9 @@ impl ChatSpace {
.on_ok(|_, window, cx| {
window
.spawn(cx, async move |cx| {
let app_state = app_state();
let states = app_state();
let relays = default_nip65_relays();
let result = app_state.set_nip65(relays).await;
let result = states.set_nip65(relays).await;
cx.update(|window, cx| {
match result {
@@ -977,9 +912,9 @@ impl ChatSpace {
.on_ok(|_, window, cx| {
window
.spawn(cx, async move |cx| {
let app_state = app_state();
let states = app_state();
let relays = default_nip17_relays();
let result = app_state.set_nip17(relays).await;
let result = states.set_nip17(relays).await;
cx.update(|window, cx| {
match result {
@@ -1001,32 +936,6 @@ impl ChatSpace {
})
}
fn render_proxy_modal(&mut self, window: &mut Window, cx: &mut App) {
window.open_modal(cx, |this, _window, _cx| {
this.overlay_closable(false)
.show_close(false)
.keyboard(false)
.alert()
.button_props(ModalButtonProps::default().ok_text(t!("common.open_browser")))
.title(shared_t!("proxy.label"))
.child(
v_flex()
.p_3()
.gap_1()
.w_full()
.items_center()
.justify_center()
.text_center()
.text_sm()
.child(shared_t!("proxy.description")),
)
.on_ok(move |_e, _window, cx| {
cx.open_url("http://localhost:7400");
false
})
});
}
fn render_client_keys_modal(&mut self, window: &mut Window, cx: &mut Context<Self>) {
window.open_modal(cx, move |this, _window, cx| {
this.overlay_closable(false)
@@ -1196,92 +1105,6 @@ impl ChatSpace {
}),
)
}
pub(crate) fn proxy_signer(window: &mut Window, cx: &mut App) {
let Some(Some(root)) = window.root::<Root>() else {
return;
};
let Ok(chatspace) = root.read(cx).view().clone().downcast::<ChatSpace>() else {
return;
};
chatspace.update(cx, |this, cx| {
let proxy = BrowserSignerProxy::new(BrowserSignerProxyOptions::default());
let url = proxy.url();
this._tasks.push(cx.background_spawn(async move {
let client = nostr_client();
let app_state = app_state();
if proxy.start().await.is_ok() {
webbrowser::open(&url).ok();
loop {
if proxy.is_session_active() {
// Save the signer to disk for further logins
if let Ok(public_key) = proxy.get_public_key().await {
let keys = Keys::generate();
let tags = vec![Tag::identifier(ACCOUNT_IDENTIFIER)];
let kind = Kind::ApplicationSpecificData;
let builder = EventBuilder::new(kind, "extension")
.tags(tags)
.build(public_key)
.sign(&keys)
.await;
if let Ok(event) = builder {
if let Err(e) = client.database().save_event(&event).await {
log::error!("Failed to save event: {e}");
};
}
}
// Set the client's signer with current proxy signer
client.set_signer(proxy.clone()).await;
break;
} else {
app_state.signal.send(SignalKind::ProxyDown).await;
}
smol::Timer::after(Duration::from_secs(1)).await;
}
}
}));
});
}
fn get_all_panel_ids(&self, cx: &App) -> Option<Vec<u64>> {
let ids: Vec<u64> = self
.dock
.read(cx)
.items
.panel_ids(cx)
.into_iter()
.filter_map(|panel| panel.parse::<u64>().ok())
.collect();
Some(ids)
}
pub(crate) fn set_center_panel<P>(panel: P, window: &mut Window, cx: &mut App)
where
P: PanelView,
{
if let Some(Some(root)) = window.root::<Root>() {
if let Ok(chatspace) = root.read(cx).view().clone().downcast::<ChatSpace>() {
let panel = Arc::new(panel);
let center = DockItem::panel(panel);
chatspace.update(cx, |this, cx| {
this.dock.update(cx, |this, cx| {
this.set_center(center, window, cx);
});
});
}
}
}
}
impl Render for ChatSpace {

View File

@@ -1,13 +1,13 @@
use std::sync::Arc;
use app_state::constants::{APP_ID, APP_NAME};
use app_state::{app_state, nostr_client};
use assets::Assets;
use gpui::{
point, px, size, AppContext, Application, Bounds, KeyBinding, Menu, MenuItem, SharedString,
TitlebarOptions, WindowBackgroundAppearance, WindowBounds, WindowDecorations, WindowKind,
WindowOptions,
};
use states::app_state;
use states::constants::{APP_ID, APP_NAME};
use ui::Root;
use crate::actions::{load_embedded_fonts, quit, Quit};
@@ -22,9 +22,6 @@ fn main() {
// Initialize logging
tracing_subscriber::fmt::init();
// Initialize the Nostr client
let _client = nostr_client();
// Initialize the coop simple storage
let _app_state = app_state();

View File

@@ -1,9 +1,6 @@
use std::time::Duration;
use anyhow::Error;
use app_state::constants::{ACCOUNT_IDENTIFIER, BUNKER_TIMEOUT};
use app_state::state::SignalKind;
use app_state::{app_state, nostr_client};
use client_keys::ClientKeys;
use common::display::RenderedProfile;
use gpui::prelude::FluentBuilder;
@@ -17,6 +14,9 @@ use i18n::{shared_t, t};
use nostr_connect::prelude::*;
use nostr_sdk::prelude::*;
use smallvec::{smallvec, SmallVec};
use states::app_state;
use states::constants::{ACCOUNT_IDENTIFIER, BUNKER_TIMEOUT};
use states::state::SignalKind;
use theme::ActiveTheme;
use ui::avatar::Avatar;
use ui::button::{Button, ButtonVariants};
@@ -28,7 +28,6 @@ use ui::popup_menu::PopupMenu;
use ui::{h_flex, v_flex, ContextModal, Sizable, StyledExt};
use crate::actions::CoopAuthUrlHandler;
use crate::chatspace::ChatSpace;
pub fn init(
profile: Profile,
@@ -43,7 +42,6 @@ pub struct Account {
profile: Profile,
stored_secret: String,
is_bunker: bool,
is_extension: bool,
loading: bool,
name: SharedString,
@@ -57,8 +55,6 @@ pub struct Account {
impl Account {
fn new(secret: String, profile: Profile, window: &mut Window, cx: &mut Context<Self>) -> Self {
let is_bunker = secret.starts_with("bunker://");
let is_extension = secret.starts_with("extension");
let mut subscriptions = smallvec![];
subscriptions.push(
@@ -74,7 +70,6 @@ impl Account {
Self {
profile,
is_bunker,
is_extension,
stored_secret: secret,
loading: false,
name: "Account".into(),
@@ -92,8 +87,6 @@ impl Account {
if let Ok(uri) = NostrConnectURI::parse(&self.stored_secret) {
self.nostr_connect(uri, window, cx);
}
} else if self.is_extension {
self.set_proxy(window, cx);
} else if let Ok(enc) = EncryptedSecretKey::from_bech32(&self.stored_secret) {
self.keys(enc, window, cx);
} else {
@@ -115,7 +108,7 @@ impl Account {
self._tasks.push(
// Handle connection in the background
cx.spawn_in(window, async move |this, cx| {
let client = nostr_client();
let client = app_state().client();
match signer.bunker_uri().await {
Ok(_) => {
@@ -134,10 +127,6 @@ impl Account {
);
}
fn set_proxy(&mut self, window: &mut Window, cx: &mut Context<Self>) {
ChatSpace::proxy_signer(window, cx);
}
fn keys(&mut self, enc: EncryptedSecretKey, window: &mut Window, cx: &mut Context<Self>) {
let pwd_input: Entity<InputState> = cx.new(|cx| InputState::new(window, cx).masked(true));
let weak_input = pwd_input.downgrade();
@@ -245,7 +234,7 @@ impl Account {
})
.ok();
let client = nostr_client();
let client = app_state().client();
let keys = Keys::new(secret);
// Set the client's signer with the current keys
@@ -268,8 +257,8 @@ impl Account {
self._tasks.push(
// Reset the nostr client in the background
cx.background_spawn(async move {
let client = nostr_client();
let app_state = app_state();
let states = app_state();
let client = states.client();
let filter = Filter::new()
.kind(Kind::ApplicationSpecificData)
@@ -282,7 +271,7 @@ impl Account {
client.unset_signer().await;
// Notify the channel about the signer being unset
app_state.signal.send(SignalKind::SignerUnset).await;
states.signal().send(SignalKind::SignerUnset).await;
}),
);
}
@@ -392,41 +381,20 @@ impl Render for Account {
.child(Avatar::new(avatar).size(rems(1.5)))
.child(div().pb_px().font_semibold().child(name)),
)
.child(
div()
.when(self.is_bunker, |this| {
let label = SharedString::from("Nostr Connect");
.child(div().when(self.is_bunker, |this| {
let label = SharedString::from("Nostr Connect");
this.child(
div()
.py_0p5()
.px_2()
.text_xs()
.bg(cx.theme().secondary_active)
.text_color(
cx.theme().secondary_foreground,
)
.rounded_full()
.child(label),
)
})
.when(self.is_extension, |this| {
let label = SharedString::from("Extension");
this.child(
div()
.py_0p5()
.px_2()
.text_xs()
.bg(cx.theme().secondary_active)
.text_color(
cx.theme().secondary_foreground,
)
.rounded_full()
.child(label),
)
}),
),
this.child(
div()
.py_0p5()
.px_2()
.text_xs()
.bg(cx.theme().secondary_active)
.text_color(cx.theme().secondary_foreground)
.rounded_full()
.child(label),
)
})),
)
})
.active(|this| this.bg(cx.theme().element_active))

View File

@@ -1,7 +1,6 @@
use std::collections::{HashMap, HashSet};
use std::time::Duration;
use app_state::{app_state, nostr_client};
use common::display::{RenderedProfile, RenderedTimestamp};
use common::nip96::nip96_upload;
use gpui::prelude::FluentBuilder;
@@ -24,6 +23,7 @@ use serde::Deserialize;
use settings::AppSettings;
use smallvec::{smallvec, SmallVec};
use smol::fs;
use states::app_state;
use theme::ActiveTheme;
use ui::actions::{CopyPublicKey, OpenPublicKey};
use ui::avatar::Avatar;
@@ -169,8 +169,8 @@ impl Chat {
let message = Message::user(event);
cx.spawn_in(window, async move |this, cx| {
let app_state = app_state();
let event_tracker = app_state.event_tracker.read().await;
let states = app_state();
let event_tracker = states.tracker().read().await;
let sent_ids = event_tracker.sent_ids();
this.update_in(cx, |this, _window, cx| {
@@ -530,7 +530,7 @@ impl Chat {
let path = paths.pop()?;
let upload = Tokio::spawn(cx, async move {
let client = nostr_client();
let client = app_state().client();
let file = fs::read(path).await.ok()?;
let url = nip96_upload(client, &nip96_server, file).await.ok()?;
@@ -1239,9 +1239,9 @@ impl Chat {
let id = ev.0;
let task: Task<Result<Vec<RelayUrl>, Error>> = cx.background_spawn(async move {
let client = nostr_client();
let app_state = app_state();
let event_tracker = app_state.event_tracker.read().await;
let states = app_state();
let client = states.client();
let event_tracker = states.tracker().read().await;
let mut relays: Vec<RelayUrl> = vec![];
let filter = Filter::new()

View File

@@ -2,8 +2,6 @@ use std::ops::Range;
use std::time::Duration;
use anyhow::{anyhow, Error};
use app_state::constants::BOOTSTRAP_RELAYS;
use app_state::{app_state, nostr_client};
use common::display::{RenderedProfile, TextUtils};
use common::nip05::nip05_profile;
use gpui::prelude::FluentBuilder;
@@ -19,6 +17,8 @@ use registry::room::Room;
use registry::Registry;
use settings::AppSettings;
use smallvec::{smallvec, SmallVec};
use states::app_state;
use states::constants::BOOTSTRAP_RELAYS;
use theme::ActiveTheme;
use ui::avatar::Avatar;
use ui::button::{Button, ButtonVariants};
@@ -129,7 +129,7 @@ impl Compose {
let mut tasks = smallvec![];
let get_contacts: Task<Result<Vec<Contact>, Error>> = cx.background_spawn(async move {
let client = nostr_client();
let client = app_state().client();
let signer = client.signer().await?;
let public_key = signer.get_public_key().await?;
let profiles = client.database().contacts(public_key).await?;
@@ -195,13 +195,15 @@ impl Compose {
}
async fn request_metadata(public_key: PublicKey) -> Result<(), Error> {
let client = nostr_client();
let app_state = app_state();
let states = app_state();
let client = states.client();
let opts = SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE);
let kinds = vec![Kind::Metadata, Kind::ContactList, Kind::RelayList];
let filter = Filter::new().author(public_key).kinds(kinds).limit(10);
client
.subscribe_to(BOOTSTRAP_RELAYS, filter, app_state.auto_close_opts)
.subscribe_to(BOOTSTRAP_RELAYS, filter, Some(opts))
.await?;
Ok(())

View File

@@ -2,7 +2,6 @@ use std::str::FromStr;
use std::time::Duration;
use anyhow::Error;
use app_state::nostr_client;
use common::nip96::nip96_upload;
use gpui::prelude::FluentBuilder;
use gpui::{
@@ -13,6 +12,7 @@ use i18n::{shared_t, t};
use nostr_sdk::prelude::*;
use settings::AppSettings;
use smol::fs;
use states::app_state;
use theme::ActiveTheme;
use ui::button::{Button, ButtonVariants};
use ui::input::{InputState, TextInput};
@@ -58,7 +58,7 @@ impl EditProfile {
};
let task: Task<Result<Option<Metadata>, Error>> = cx.background_spawn(async move {
let client = nostr_client();
let client = app_state().client();
let signer = client.signer().await?;
let public_key = signer.get_public_key().await?;
let metadata = client
@@ -125,7 +125,9 @@ impl EditProfile {
let (tx, rx) = oneshot::channel::<Url>();
nostr_sdk::async_utility::task::spawn(async move {
if let Ok(url) = nip96_upload(nostr_client(), &nip96, file_data).await {
if let Ok(url) =
nip96_upload(app_state().client(), &nip96, file_data).await
{
_ = tx.send(url);
}
});
@@ -188,7 +190,7 @@ impl EditProfile {
}
cx.background_spawn(async move {
let client = nostr_client();
let client = app_state().client();
let signer = client.signer().await?;
// Sign the new metadata event

View File

@@ -1,7 +1,5 @@
use std::time::Duration;
use app_state::constants::{ACCOUNT_IDENTIFIER, BUNKER_TIMEOUT};
use app_state::nostr_client;
use client_keys::ClientKeys;
use gpui::prelude::FluentBuilder;
use gpui::{
@@ -12,6 +10,8 @@ use gpui::{
use i18n::{shared_t, t};
use nostr_connect::prelude::*;
use smallvec::{smallvec, SmallVec};
use states::app_state;
use states::constants::{ACCOUNT_IDENTIFIER, BUNKER_TIMEOUT};
use theme::ActiveTheme;
use ui::button::{Button, ButtonVariants};
use ui::dock_area::panel::{Panel, PanelEvent};
@@ -248,7 +248,7 @@ impl Login {
// Set the client's signer with the current keys
cx.background_spawn(async move {
let client = nostr_client();
let client = app_state().client();
client.set_signer(keys).await;
})
.detach();
@@ -331,7 +331,7 @@ impl Login {
}
let task: Task<Result<(), anyhow::Error>> = cx.background_spawn(async move {
let client = nostr_client();
let client = app_state().client();
// Update the client's signer
client.set_signer(signer).await;
@@ -362,7 +362,7 @@ impl Login {
if let Ok(enc_key) =
EncryptedSecretKey::new(keys.secret_key(), &password, 8, KeySecurity::Unknown)
{
let client = nostr_client();
let client = app_state().client();
let value = enc_key.to_bech32().unwrap();
let keys = Keys::generate();
let tags = vec![Tag::identifier(ACCOUNT_IDENTIFIER)];

View File

@@ -1,6 +1,4 @@
use anyhow::{anyhow, Error};
use app_state::constants::{ACCOUNT_IDENTIFIER, BOOTSTRAP_RELAYS};
use app_state::{default_nip17_relays, default_nip65_relays, nostr_client};
use common::nip96::nip96_upload;
use gpui::{
div, relative, rems, AnyElement, App, AppContext, AsyncWindowContext, Context, Entity,
@@ -12,6 +10,8 @@ use i18n::{shared_t, t};
use nostr_sdk::prelude::*;
use settings::AppSettings;
use smol::fs;
use states::constants::{ACCOUNT_IDENTIFIER, BOOTSTRAP_RELAYS};
use states::{app_state, default_nip17_relays, default_nip65_relays};
use theme::ActiveTheme;
use ui::avatar::Avatar;
use ui::button::{Button, ButtonVariants};
@@ -124,7 +124,7 @@ impl NewAccount {
// Set the client's signer with the current keys
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
let client = nostr_client();
let client = app_state().client();
// Set the client's signer with the current keys
client.set_signer(keys).await;
@@ -176,7 +176,7 @@ impl NewAccount {
if let Ok(enc_key) =
EncryptedSecretKey::new(keys.secret_key(), &password, 8, KeySecurity::Unknown)
{
let client = nostr_client();
let client = app_state().client();
let value = enc_key.to_bech32().unwrap();
let keys = Keys::generate();
let tags = vec![Tag::identifier(ACCOUNT_IDENTIFIER)];
@@ -217,7 +217,7 @@ impl NewAccount {
Ok(Some(mut paths)) => {
if let Some(path) = paths.pop() {
let file = fs::read(path).await?;
let url = nip96_upload(nostr_client(), &nip96_server, file).await?;
let url = nip96_upload(app_state().client(), &nip96_server, file).await?;
Ok(url)
} else {

View File

@@ -1,10 +1,6 @@
use std::sync::Arc;
use std::time::Duration;
use app_state::constants::{
ACCOUNT_IDENTIFIER, APP_NAME, NOSTR_CONNECT_RELAY, NOSTR_CONNECT_TIMEOUT,
};
use app_state::nostr_client;
use client_keys::ClientKeys;
use common::display::TextUtils;
use gpui::prelude::FluentBuilder;
@@ -16,6 +12,8 @@ use gpui::{
use i18n::{shared_t, t};
use nostr_connect::prelude::*;
use smallvec::{smallvec, SmallVec};
use states::app_state;
use states::constants::{ACCOUNT_IDENTIFIER, APP_NAME, NOSTR_CONNECT_RELAY, NOSTR_CONNECT_TIMEOUT};
use theme::ActiveTheme;
use ui::button::{Button, ButtonVariants};
use ui::dock_area::panel::{Panel, PanelEvent};
@@ -23,7 +21,7 @@ use ui::notification::Notification;
use ui::popup_menu::PopupMenu;
use ui::{divider, h_flex, v_flex, ContextModal, Icon, IconName, Sizable, StyledExt};
use crate::chatspace::{self, ChatSpace};
use crate::chatspace;
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Onboarding> {
Onboarding::new(window, cx)
@@ -163,10 +161,6 @@ impl Onboarding {
)
}
fn set_proxy(&mut self, window: &mut Window, cx: &mut Context<Self>) {
ChatSpace::proxy_signer(window, cx);
}
fn write_uri_to_disk(
&mut self,
signer: NostrConnect,
@@ -181,7 +175,7 @@ impl Onboarding {
}
let task: Task<Result<(), anyhow::Error>> = cx.background_spawn(async move {
let client = nostr_client();
let client = app_state().client();
// Update the client's signer
client.set_signer(signer).await;
@@ -348,30 +342,11 @@ impl Render for Onboarding {
.child(
Button::new("key")
.label(t!("onboarding.key_login"))
.large()
.ghost_alt()
.on_click(cx.listener(move |_, _, window, cx| {
chatspace::login(window, cx);
})),
)
.child(
v_flex()
.gap_1()
.child(
Button::new("ext")
.label(t!("onboarding.ext_login"))
.ghost_alt()
.on_click(cx.listener(move |this, _, window, cx| {
this.set_proxy(window, cx);
})),
)
.child(
div()
.italic()
.text_xs()
.text_center()
.text_color(cx.theme().text_muted)
.child(shared_t!("onboarding.ext_login_note")),
),
),
),
)

View File

@@ -1,7 +1,5 @@
use std::time::Duration;
use app_state::constants::BOOTSTRAP_RELAYS;
use app_state::nostr_client;
use common::display::{shorten_pubkey, RenderedProfile, RenderedTimestamp};
use common::nip05::nip05_verify;
use gpui::prelude::FluentBuilder;
@@ -15,6 +13,8 @@ use nostr_sdk::prelude::*;
use registry::Registry;
use settings::AppSettings;
use smallvec::{smallvec, SmallVec};
use states::app_state;
use states::constants::BOOTSTRAP_RELAYS;
use theme::ActiveTheme;
use ui::avatar::Avatar;
use ui::button::{Button, ButtonVariants};
@@ -43,7 +43,7 @@ impl Screening {
let contact_check: Task<Result<(bool, Vec<Profile>), Error>> =
cx.background_spawn(async move {
let client = nostr_client();
let client = app_state().client();
let signer = client.signer().await?;
let signer_pubkey = signer.get_public_key().await?;
@@ -68,7 +68,7 @@ impl Screening {
});
let activity_check = cx.background_spawn(async move {
let client = nostr_client();
let client = app_state().client();
let filter = Filter::new().author(public_key).limit(1);
let mut activity: Option<Timestamp> = None;
@@ -157,7 +157,7 @@ impl Screening {
let public_key = self.profile.public_key();
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
let client = nostr_client();
let client = app_state().client();
let signer = client.signer().await?;
let tag = Tag::public_key_report(public_key, Report::Impersonation);

View File

@@ -2,7 +2,6 @@ use std::collections::HashSet;
use std::time::Duration;
use anyhow::{anyhow, Error};
use app_state::{app_state, nostr_client};
use gpui::prelude::FluentBuilder;
use gpui::{
div, px, uniform_list, App, AppContext, AsyncWindowContext, Context, Entity,
@@ -10,8 +9,10 @@ use gpui::{
Task, TextAlign, UniformList, Window,
};
use i18n::{shared_t, t};
use itertools::Itertools;
use nostr_sdk::prelude::*;
use smallvec::{smallvec, SmallVec};
use states::app_state;
use theme::ActiveTheme;
use ui::button::{Button, ButtonVariants};
use ui::input::{InputEvent, InputState, TextInput};
@@ -80,7 +81,7 @@ impl SetupRelay {
fn load(cx: &AsyncWindowContext) -> Task<Result<Vec<RelayUrl>, Error>> {
cx.background_spawn(async move {
let client = nostr_client();
let client = app_state().client();
let signer = client.signer().await?;
let public_key = signer.get_public_key().await?;
@@ -152,8 +153,8 @@ impl SetupRelay {
let relays = self.relays.clone();
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
let app_state = app_state();
let client = nostr_client();
let states = app_state();
let client = states.client();
let signer = client.signer().await?;
let public_key = signer.get_public_key().await?;
@@ -177,16 +178,10 @@ impl SetupRelay {
}
// Fetch gift wrap events
let sub_id = app_state.gift_wrap_sub_id.clone();
let filter = Filter::new().kind(Kind::GiftWrap).pubkey(public_key);
if client
.subscribe_with_id_to(relays.clone(), sub_id, filter, None)
states
.get_messages(public_key, &relays.into_iter().collect_vec())
.await
.is_ok()
{
log::info!("Subscribed to messages in: {relays:?}");
};
.ok();
Ok(())
});

View File

@@ -3,9 +3,6 @@ use std::ops::Range;
use std::time::Duration;
use anyhow::{anyhow, Error};
use app_state::constants::{BOOTSTRAP_RELAYS, SEARCH_RELAYS};
use app_state::state::UnwrappingStatus;
use app_state::{app_state, nostr_client};
use common::debounced_delay::DebouncedDelay;
use common::display::{RenderedTimestamp, TextUtils};
use gpui::prelude::FluentBuilder;
@@ -23,6 +20,9 @@ use registry::room::{Room, RoomKind};
use registry::{Registry, RegistryEvent};
use settings::AppSettings;
use smallvec::{smallvec, SmallVec};
use states::app_state;
use states::constants::{BOOTSTRAP_RELAYS, SEARCH_RELAYS};
use states::state::UnwrappingStatus;
use theme::ActiveTheme;
use ui::button::{Button, ButtonVariants};
use ui::dock_area::panel::{Panel, PanelEvent};
@@ -140,7 +140,7 @@ impl Sidebar {
}
async fn request_metadata(public_key: PublicKey) -> Result<(), Error> {
let client = nostr_client();
let client = app_state().client();
let opts = SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE);
let kinds = vec![Kind::Metadata, Kind::ContactList, Kind::RelayList];
let filter = Filter::new().author(public_key).kinds(kinds).limit(10);
@@ -165,7 +165,7 @@ impl Sidebar {
}
async fn nip50(query: &str) -> Result<BTreeSet<Room>, Error> {
let client = nostr_client();
let client = app_state().client();
let signer = client.signer().await?;
let public_key = signer.get_public_key().await?;
@@ -530,9 +530,8 @@ impl Sidebar {
fn on_manage(&mut self, _ev: &RelayStatus, window: &mut Window, cx: &mut Context<Self>) {
let task: Task<Result<Vec<Relay>, Error>> = cx.background_spawn(async move {
let client = nostr_client();
let app_state = app_state();
let subscription = client.subscription(&app_state.gift_wrap_sub_id).await;
let client = app_state().client();
let subscription = client.subscription(&SubscriptionId::new("inbox")).await;
let mut relays: Vec<Relay> = vec![];
for (url, _filter) in subscription.into_iter() {

View File

@@ -1,6 +1,5 @@
use std::time::Duration;
use app_state::nostr_client;
use common::display::RenderedProfile;
use common::nip05::nip05_verify;
use gpui::prelude::FluentBuilder;
@@ -14,6 +13,7 @@ use nostr_sdk::prelude::*;
use registry::Registry;
use settings::AppSettings;
use smallvec::{smallvec, SmallVec};
use states::app_state;
use theme::ActiveTheme;
use ui::avatar::Avatar;
use ui::button::{Button, ButtonVariants};
@@ -39,7 +39,7 @@ impl UserProfile {
let mut tasks = smallvec![];
let check_follow: Task<Result<bool, Error>> = cx.background_spawn(async move {
let client = nostr_client();
let client = app_state().client();
let signer = client.signer().await?;
let public_key = signer.get_public_key().await?;
let contact_list = client.database().contacts_public_keys(public_key).await?;