ensure relay connection

This commit is contained in:
2026-03-14 15:17:11 +07:00
parent 0d6aec2421
commit 739088b669
4 changed files with 115 additions and 26 deletions

View File

@@ -50,6 +50,8 @@ pub enum StateEvent {
Connecting,
/// Connected to the bootstrapping relay
Connected,
/// Fetching the relay list
FetchingRelayList,
/// User has not set up NIP-65 relays
RelayNotConfigured,
/// Connected to NIP-65 relays
@@ -60,6 +62,15 @@ pub enum StateEvent {
Error(SharedString),
}
impl StateEvent {
pub fn error<T>(error: T) -> Self
where
T: Into<SharedString>,
{
Self::Error(error.into())
}
}
/// Nostr Registry
#[derive(Debug)]
pub struct NostrRegistry {
@@ -206,7 +217,7 @@ impl NostrRegistry {
}
Err(e) => {
this.update(cx, |_this, cx| {
cx.emit(StateEvent::Error(SharedString::from(e.to_string())));
cx.emit(StateEvent::error(e.to_string()));
})
.ok();
}
@@ -271,7 +282,7 @@ impl NostrRegistry {
},
Err(e) => {
this.update(cx, |_this, cx| {
cx.emit(StateEvent::Error(SharedString::from(e.to_string())));
cx.emit(StateEvent::error(e.to_string()));
})
.ok();
}
@@ -360,7 +371,7 @@ impl NostrRegistry {
}
Err(e) => {
this.update(cx, |_this, cx| {
cx.emit(StateEvent::Error(SharedString::from(e.to_string())));
cx.emit(StateEvent::error(e.to_string()));
})
.ok();
}
@@ -458,7 +469,7 @@ impl NostrRegistry {
}
Err(e) => {
this.update(cx, |_this, cx| {
cx.emit(StateEvent::Error(SharedString::from(e.to_string())));
cx.emit(StateEvent::error(e.to_string()));
})
.ok();
}
@@ -505,7 +516,7 @@ impl NostrRegistry {
}
Err(e) => {
this.update(cx, |_this, cx| {
cx.emit(StateEvent::Error(SharedString::from(e.to_string())));
cx.emit(StateEvent::error(e.to_string()));
})
.ok();
}
@@ -550,7 +561,7 @@ impl NostrRegistry {
}
Err(e) => {
this.update(cx, |_this, cx| {
cx.emit(StateEvent::Error(SharedString::from(e.to_string())));
cx.emit(StateEvent::error(e.to_string()));
})
.ok();
}
@@ -558,7 +569,7 @@ impl NostrRegistry {
}
Err(e) => {
this.update(cx, |_this, cx| {
cx.emit(StateEvent::Error(SharedString::from(e.to_string())));
cx.emit(StateEvent::error(e.to_string()));
})
.ok();
}
@@ -566,9 +577,72 @@ impl NostrRegistry {
}));
}
/// Ensure the relay list is fetched for the given public key
pub fn ensure_relay_list(&mut self, public_key: &PublicKey, cx: &mut Context<Self>) {
let task = self.get_event(public_key, Kind::RelayList, cx);
// Emit a fetching event before starting the task
cx.emit(StateEvent::FetchingRelayList);
self.tasks.push(cx.spawn(async move |this, cx| {
match task.await {
Ok(event) => {
this.update(cx, |this, cx| {
this.ensure_connection(&event, cx);
})
.ok();
}
Err(e) => {
this.update(cx, |_this, cx| {
cx.emit(StateEvent::RelayNotConfigured);
cx.emit(StateEvent::error(e.to_string()));
})
.ok();
}
};
}));
}
/// Ensure that the user is connected to the relay specified in the NIP-65 event.
pub fn ensure_connection(&mut self, event: &Event, cx: &mut Context<Self>) {
let client = self.client();
// Extract the relay list from the event
let relays: Vec<(RelayUrl, Option<RelayMetadata>)> = nip65::extract_relay_list(event)
.map(|(url, metadata)| (url.to_owned(), metadata.to_owned()))
.collect();
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
for (url, metadata) in relays.into_iter() {
match metadata {
Some(RelayMetadata::Read) => {
client
.add_relay(url)
.capabilities(RelayCapabilities::READ)
.connect_timeout(Duration::from_secs(TIMEOUT))
.and_connect()
.await?;
}
Some(RelayMetadata::Write) => {
client
.add_relay(url)
.capabilities(RelayCapabilities::WRITE)
.connect_timeout(Duration::from_secs(TIMEOUT))
.and_connect()
.await?;
}
None => {
client
.add_relay(url)
.capabilities(RelayCapabilities::NONE)
.connect_timeout(Duration::from_secs(TIMEOUT))
.and_connect()
.await?;
}
}
}
Ok(())
});
self.tasks.push(cx.spawn(async move |this, cx| {
match task.await {
Ok(_) => {
@@ -580,7 +654,7 @@ impl NostrRegistry {
Err(e) => {
this.update(cx, |_this, cx| {
cx.emit(StateEvent::RelayNotConfigured);
cx.emit(StateEvent::Error(SharedString::from(e.to_string())));
cx.emit(StateEvent::error(e.to_string()));
})
.ok();
}