refactor
This commit is contained in:
@@ -6,8 +6,8 @@ use gpui::{App, AppContext, Context, Entity, EventEmitter, Global, Task};
|
||||
use nostr_connect::prelude::*;
|
||||
use nostr_sdk::client::SyncSummary;
|
||||
use nostr_sdk::prelude::*;
|
||||
use signed_core::{builders, filters};
|
||||
use signed_nostr::{NostrBackend, SignedAuthUrlHandler, UniversalSigner, Update};
|
||||
use signed_core::filters;
|
||||
use signed_nostr::{SignedAuthUrlHandler, UniversalSigner, Update};
|
||||
|
||||
/// Keyring entry holding the user credential (`nsec1...` or `bunker://...`
|
||||
/// with an embedded `?master=<nsec>` NIP-46 session key).
|
||||
@@ -71,7 +71,8 @@ impl BackendEvent {
|
||||
/// notification pump. Stores subscribe to [`BackendEvent`] and re-query the
|
||||
/// local database when relevant updates arrive.
|
||||
pub struct Backend {
|
||||
inner: NostrBackend,
|
||||
client: Client,
|
||||
signer: UniversalSigner,
|
||||
current_user: Option<PublicKey>,
|
||||
connected: bool,
|
||||
sync_progress: Option<(u64, u64)>,
|
||||
@@ -94,11 +95,11 @@ impl Backend {
|
||||
cx.set_global(GlobalBackend(entity));
|
||||
}
|
||||
|
||||
pub(crate) fn new(inner: NostrBackend, cx: &mut Context<Self>) -> Self {
|
||||
let client = inner.client();
|
||||
pub(crate) fn new(client: Client, signer: UniversalSigner, cx: &mut Context<Self>) -> Self {
|
||||
let pump_client = client.clone();
|
||||
|
||||
let pump = cx.spawn(async move |this, cx| {
|
||||
let mut notifications = client.notifications();
|
||||
let mut notifications = pump_client.notifications();
|
||||
|
||||
while let Some(notification) = notifications.next().await {
|
||||
let ClientNotification::Event { event, .. } = notification else {
|
||||
@@ -119,7 +120,8 @@ impl Backend {
|
||||
});
|
||||
|
||||
let mut this = Self {
|
||||
inner,
|
||||
client,
|
||||
signer,
|
||||
current_user: None,
|
||||
connected: false,
|
||||
sync_progress: None,
|
||||
@@ -133,16 +135,19 @@ impl Backend {
|
||||
/// Bootstrap the client: connect to the default relays (indexers as
|
||||
/// discovery-only) and restore the saved session, if any.
|
||||
fn bootstrap(&mut self, cx: &mut Context<Self>) {
|
||||
let backend = self.inner.clone();
|
||||
let client = self.client.clone();
|
||||
|
||||
let task = cx.background_spawn(async move {
|
||||
for url in BOOTSTRAP_RELAYS {
|
||||
backend.add_relay(url).await?;
|
||||
client.add_relay(url).await?;
|
||||
}
|
||||
for url in INDEXER_RELAYS {
|
||||
backend.add_discovery_relay(url).await?;
|
||||
client
|
||||
.add_relay(url)
|
||||
.capabilities(RelayCapabilities::DISCOVERY)
|
||||
.await?;
|
||||
}
|
||||
backend.connect().await;
|
||||
client.connect().await;
|
||||
Ok::<(), Error>(())
|
||||
});
|
||||
|
||||
@@ -276,7 +281,7 @@ impl Backend {
|
||||
this.update(cx, |this, cx| {
|
||||
// Become the new identity, so the publishes below are
|
||||
// signed with the new keys.
|
||||
this.inner.signer().swap_inner(keys);
|
||||
this.signer.swap_inner(keys);
|
||||
this.current_user = Some(public_key);
|
||||
this.bootstrap_user(public_key, cx);
|
||||
cx.emit(BackendEvent::SignerChanged);
|
||||
@@ -317,7 +322,7 @@ impl Backend {
|
||||
.map(|url| RelayUrl::parse(url).expect("valid relay URL"))
|
||||
.collect();
|
||||
|
||||
this.send(builders::grasp_list(grasp_servers), cx);
|
||||
this.send(GitUserGraspList { grasp_servers }.into_event_builder(), cx);
|
||||
})?;
|
||||
|
||||
Ok(public_key)
|
||||
@@ -441,7 +446,7 @@ impl Backend {
|
||||
delete.await.ok();
|
||||
|
||||
this.update(cx, |this, cx| {
|
||||
this.inner.signer().swap_inner(Keys::generate());
|
||||
this.signer.swap_inner(Keys::generate());
|
||||
this.current_user = None;
|
||||
cx.emit(BackendEvent::SignerChanged);
|
||||
cx.emit(BackendEvent::SignerRequired);
|
||||
@@ -455,14 +460,11 @@ impl Backend {
|
||||
/// Fetch the user's grasp list (kind `10317`) and add the listed grasp
|
||||
/// servers as relays.
|
||||
fn bootstrap_user(&mut self, public_key: PublicKey, cx: &mut Context<Self>) {
|
||||
let backend = self.inner.clone();
|
||||
let client = self.client.clone();
|
||||
|
||||
self.tasks.push(cx.spawn(async move |this, cx| {
|
||||
let result = async {
|
||||
let events = backend
|
||||
.client()
|
||||
.fetch_events(filters::grasp_list(public_key))
|
||||
.await?;
|
||||
let events = client.fetch_events(filters::grasp_list(public_key)).await?;
|
||||
|
||||
let urls: Vec<String> = events
|
||||
.into_iter()
|
||||
@@ -477,9 +479,9 @@ impl Backend {
|
||||
.unwrap_or_default();
|
||||
|
||||
for url in urls {
|
||||
backend.add_relay(&url).await.ok();
|
||||
client.add_relay(&url).await.ok();
|
||||
}
|
||||
backend.connect().await;
|
||||
client.connect().await;
|
||||
|
||||
Ok::<_, Error>(())
|
||||
}
|
||||
@@ -495,12 +497,12 @@ impl Backend {
|
||||
|
||||
/// Get the nostr client.
|
||||
pub fn client(&self) -> Client {
|
||||
self.inner.client()
|
||||
self.client.clone()
|
||||
}
|
||||
|
||||
/// Get the current signer.
|
||||
pub fn signer(&self) -> UniversalSigner {
|
||||
self.inner.signer()
|
||||
self.signer.clone()
|
||||
}
|
||||
|
||||
/// Get the current user's public key.
|
||||
@@ -536,7 +538,7 @@ impl Backend {
|
||||
match new_signer.get_public_key_async().await {
|
||||
Ok(public_key) => {
|
||||
this.update(cx, |this, cx| {
|
||||
this.inner.signer().swap_inner(new_signer);
|
||||
this.signer.swap_inner(new_signer);
|
||||
this.current_user = Some(public_key);
|
||||
this.bootstrap_user(public_key, cx);
|
||||
cx.emit(BackendEvent::SignerChanged);
|
||||
@@ -557,13 +559,13 @@ impl Backend {
|
||||
|
||||
/// Add relays and connect to them.
|
||||
pub fn add_relays(&mut self, urls: Vec<String>, cx: &mut Context<Self>) {
|
||||
let backend = self.inner.clone();
|
||||
let client = self.client.clone();
|
||||
|
||||
let task = cx.background_spawn(async move {
|
||||
for url in urls {
|
||||
backend.add_relay(&url).await?;
|
||||
client.add_relay(&url).await?;
|
||||
}
|
||||
backend.connect().await;
|
||||
client.connect().await;
|
||||
Ok::<(), Error>(())
|
||||
});
|
||||
|
||||
@@ -587,13 +589,16 @@ impl Backend {
|
||||
/// Add relays used only for discovery (e.g. NIP-65 indexers) and
|
||||
/// connect to them. No subscriptions or writes are routed through them.
|
||||
pub fn add_discovery_relays(&mut self, urls: Vec<String>, cx: &mut Context<Self>) {
|
||||
let backend = self.inner.clone();
|
||||
let client = self.client.clone();
|
||||
|
||||
let task = cx.background_spawn(async move {
|
||||
for url in urls {
|
||||
backend.add_discovery_relay(&url).await?;
|
||||
client
|
||||
.add_relay(&url)
|
||||
.capabilities(RelayCapabilities::DISCOVERY)
|
||||
.await?;
|
||||
}
|
||||
backend.connect().await;
|
||||
client.connect().await;
|
||||
Ok::<(), Error>(())
|
||||
});
|
||||
|
||||
@@ -608,9 +613,9 @@ impl Backend {
|
||||
/// Start a persistent subscription. Matching events are stored in the
|
||||
/// database automatically and surface as [`BackendEvent::NostrUpdate`].
|
||||
pub fn subscribe(&mut self, filter: Filter, cx: &mut Context<Self>) {
|
||||
let backend = self.inner.clone();
|
||||
let client = self.client.clone();
|
||||
|
||||
let task = cx.background_spawn(async move { backend.subscribe(filter).await.map(|_| ()) });
|
||||
let task = cx.background_spawn(async move { client.subscribe(filter).await.map(|_| ()) });
|
||||
|
||||
self.tasks.push(cx.spawn(async move |this, cx| {
|
||||
if let Err(e) = task.await {
|
||||
@@ -625,11 +630,10 @@ impl Backend {
|
||||
/// in the database and surface as [`BackendEvent::NostrUpdate`] while the
|
||||
/// subscription is open.
|
||||
pub fn subscribe_bootstrap(&mut self, filters: Vec<Filter>, cx: &mut Context<Self>) {
|
||||
let backend = self.inner.clone();
|
||||
let client = self.client.clone();
|
||||
|
||||
let task = cx.background_spawn(async move {
|
||||
subscribe_bootstrap_only(&backend.client(), filters).await
|
||||
});
|
||||
let task =
|
||||
cx.background_spawn(async move { subscribe_bootstrap_only(&client, filters).await });
|
||||
|
||||
self.tasks.push(cx.spawn(async move |this, cx| {
|
||||
if let Err(e) = task.await {
|
||||
@@ -644,7 +648,7 @@ impl Backend {
|
||||
/// Emits [`BackendEvent::SyncProgress`] while running (throttled to
|
||||
/// whole-percent changes) and [`BackendEvent::Synced`] on completion.
|
||||
pub fn sync_bootstrap(&mut self, filter: Filter, cx: &mut Context<Self>) {
|
||||
let backend = self.inner.clone();
|
||||
let client = self.client.clone();
|
||||
|
||||
self.sync_progress = Some((0, 0));
|
||||
cx.notify();
|
||||
@@ -681,7 +685,7 @@ impl Backend {
|
||||
|
||||
let task = cx.background_spawn(async move {
|
||||
let opts = SyncOptions::default().progress(tx);
|
||||
sync_bootstrap_only(&backend.client(), filter, opts).await
|
||||
sync_bootstrap_only(&client, filter, opts).await
|
||||
});
|
||||
|
||||
self.tasks.push(cx.spawn(async move |this, cx| {
|
||||
@@ -721,8 +725,27 @@ impl Backend {
|
||||
cx: &mut Context<Self>,
|
||||
) -> flume::Receiver<Result<Event, Error>> {
|
||||
let (tx, rx) = flume::bounded(1);
|
||||
let backend = self.inner.clone();
|
||||
let task = cx.background_spawn(async move { backend.send(builder).await });
|
||||
let client = self.client.clone();
|
||||
let signer = self.signer.clone();
|
||||
|
||||
let task = cx.background_spawn(async move {
|
||||
// Sign with the current signer, broadcast, and save locally so
|
||||
// the event is immediately visible to database queries.
|
||||
let event = builder.finalize_async(&signer).await?;
|
||||
let output = client.send_event(&event).await?;
|
||||
|
||||
if output.success.is_empty() && !output.failed.is_empty() {
|
||||
let reasons = output
|
||||
.failed
|
||||
.values()
|
||||
.cloned()
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ");
|
||||
return Err(anyhow!("event not accepted by any relay: {reasons}"));
|
||||
}
|
||||
|
||||
Ok(event)
|
||||
});
|
||||
|
||||
self.tasks.push(cx.spawn(async move |this, cx| {
|
||||
let result = task.await;
|
||||
|
||||
Reference in New Issue
Block a user