feat: add relay tracking for gift wrap events #21
@@ -105,12 +105,17 @@ impl ChatRegistry {
|
|||||||
subscriptions.push(
|
subscriptions.push(
|
||||||
// Subscribe to the signer event
|
// Subscribe to the signer event
|
||||||
cx.subscribe(&nostr, |this, _state, event, cx| {
|
cx.subscribe(&nostr, |this, _state, event, cx| {
|
||||||
if let StateEvent::SignerSet = event {
|
match event {
|
||||||
this.reset(cx);
|
StateEvent::SignerSet => {
|
||||||
this.get_rooms(cx);
|
this.reset(cx);
|
||||||
this.get_contact_list(cx);
|
this.get_rooms(cx);
|
||||||
this.get_messages(cx)
|
}
|
||||||
}
|
StateEvent::RelayConnected => {
|
||||||
|
this.get_contact_list(cx);
|
||||||
|
this.get_messages(cx)
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -332,6 +337,7 @@ impl ChatRegistry {
|
|||||||
|
|
||||||
while let Some((_url, res)) = stream.next().await {
|
while let Some((_url, res)) = stream.next().await {
|
||||||
if let Ok(event) = res {
|
if let Ok(event) = res {
|
||||||
|
log::debug!("Got event: {:?}", event);
|
||||||
let urls: Vec<RelayUrl> = nip17::extract_owned_relay_list(event).collect();
|
let urls: Vec<RelayUrl> = nip17::extract_owned_relay_list(event).collect();
|
||||||
return Ok(urls);
|
return Ok(urls);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,6 +134,14 @@ impl Workspace {
|
|||||||
|
|
||||||
window.push_notification(note, cx);
|
window.push_notification(note, cx);
|
||||||
}
|
}
|
||||||
|
StateEvent::FetchingRelayList => {
|
||||||
|
let note = Notification::new()
|
||||||
|
.id::<RelayNotifcation>()
|
||||||
|
.message("Getting relay list...")
|
||||||
|
.with_kind(NotificationKind::Info);
|
||||||
|
|
||||||
|
window.push_notification(note, cx);
|
||||||
|
}
|
||||||
StateEvent::RelayNotConfigured => {
|
StateEvent::RelayNotConfigured => {
|
||||||
this.relay_notification(window, cx);
|
this.relay_notification(window, cx);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,14 +73,19 @@ impl DeviceRegistry {
|
|||||||
let nostr = NostrRegistry::global(cx);
|
let nostr = NostrRegistry::global(cx);
|
||||||
let state = DeviceState::default();
|
let state = DeviceState::default();
|
||||||
|
|
||||||
let subscription =
|
let subscription = Some(cx.subscribe_in(
|
||||||
Some(
|
&nostr,
|
||||||
cx.subscribe_in(&nostr, window, |this, _state, ev, _window, cx| {
|
window,
|
||||||
if let StateEvent::SignerSet = ev {
|
|this, _state, event, _window, cx| match event {
|
||||||
this.get_announcement(cx);
|
StateEvent::SignerSet => {
|
||||||
}
|
this.reset(cx);
|
||||||
}),
|
}
|
||||||
);
|
StateEvent::RelayConnected => {
|
||||||
|
this.get_announcement(cx);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
));
|
||||||
|
|
||||||
cx.defer_in(window, |this, window, cx| {
|
cx.defer_in(window, |this, window, cx| {
|
||||||
this.handle_notifications(window, cx);
|
this.handle_notifications(window, cx);
|
||||||
@@ -269,9 +274,6 @@ impl DeviceRegistry {
|
|||||||
let nostr = NostrRegistry::global(cx);
|
let nostr = NostrRegistry::global(cx);
|
||||||
let client = nostr.read(cx).client();
|
let client = nostr.read(cx).client();
|
||||||
|
|
||||||
// Reset state before fetching announcement
|
|
||||||
self.reset(cx);
|
|
||||||
|
|
||||||
let task: Task<Result<Event, Error>> = cx.background_spawn(async move {
|
let task: Task<Result<Event, Error>> = cx.background_spawn(async move {
|
||||||
let signer = client.signer().context("Signer not found")?;
|
let signer = client.signer().context("Signer not found")?;
|
||||||
let public_key = signer.get_public_key().await?;
|
let public_key = signer.get_public_key().await?;
|
||||||
@@ -373,7 +375,6 @@ impl DeviceRegistry {
|
|||||||
if keys.public_key() != device_pubkey {
|
if keys.public_key() != device_pubkey {
|
||||||
return Err(anyhow!("Key mismatch"));
|
return Err(anyhow!("Key mismatch"));
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(keys)
|
Ok(keys)
|
||||||
} else {
|
} else {
|
||||||
Err(anyhow!("Key not found"))
|
Err(anyhow!("Key not found"))
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ pub enum StateEvent {
|
|||||||
Connecting,
|
Connecting,
|
||||||
/// Connected to the bootstrapping relay
|
/// Connected to the bootstrapping relay
|
||||||
Connected,
|
Connected,
|
||||||
|
/// Fetching the relay list
|
||||||
|
FetchingRelayList,
|
||||||
/// User has not set up NIP-65 relays
|
/// User has not set up NIP-65 relays
|
||||||
RelayNotConfigured,
|
RelayNotConfigured,
|
||||||
/// Connected to NIP-65 relays
|
/// Connected to NIP-65 relays
|
||||||
@@ -60,6 +62,15 @@ pub enum StateEvent {
|
|||||||
Error(SharedString),
|
Error(SharedString),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl StateEvent {
|
||||||
|
pub fn error<T>(error: T) -> Self
|
||||||
|
where
|
||||||
|
T: Into<SharedString>,
|
||||||
|
{
|
||||||
|
Self::Error(error.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Nostr Registry
|
/// Nostr Registry
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NostrRegistry {
|
pub struct NostrRegistry {
|
||||||
@@ -206,7 +217,7 @@ impl NostrRegistry {
|
|||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
this.update(cx, |_this, cx| {
|
this.update(cx, |_this, cx| {
|
||||||
cx.emit(StateEvent::Error(SharedString::from(e.to_string())));
|
cx.emit(StateEvent::error(e.to_string()));
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
@@ -271,7 +282,7 @@ impl NostrRegistry {
|
|||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
this.update(cx, |_this, cx| {
|
this.update(cx, |_this, cx| {
|
||||||
cx.emit(StateEvent::Error(SharedString::from(e.to_string())));
|
cx.emit(StateEvent::error(e.to_string()));
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
@@ -360,7 +371,7 @@ impl NostrRegistry {
|
|||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
this.update(cx, |_this, cx| {
|
this.update(cx, |_this, cx| {
|
||||||
cx.emit(StateEvent::Error(SharedString::from(e.to_string())));
|
cx.emit(StateEvent::error(e.to_string()));
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
@@ -458,7 +469,7 @@ impl NostrRegistry {
|
|||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
this.update(cx, |_this, cx| {
|
this.update(cx, |_this, cx| {
|
||||||
cx.emit(StateEvent::Error(SharedString::from(e.to_string())));
|
cx.emit(StateEvent::error(e.to_string()));
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
@@ -505,7 +516,7 @@ impl NostrRegistry {
|
|||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
this.update(cx, |_this, cx| {
|
this.update(cx, |_this, cx| {
|
||||||
cx.emit(StateEvent::Error(SharedString::from(e.to_string())));
|
cx.emit(StateEvent::error(e.to_string()));
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
@@ -550,7 +561,7 @@ impl NostrRegistry {
|
|||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
this.update(cx, |_this, cx| {
|
this.update(cx, |_this, cx| {
|
||||||
cx.emit(StateEvent::Error(SharedString::from(e.to_string())));
|
cx.emit(StateEvent::error(e.to_string()));
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
@@ -558,7 +569,7 @@ impl NostrRegistry {
|
|||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
this.update(cx, |_this, cx| {
|
this.update(cx, |_this, cx| {
|
||||||
cx.emit(StateEvent::Error(SharedString::from(e.to_string())));
|
cx.emit(StateEvent::error(e.to_string()));
|
||||||
})
|
})
|
||||||
.ok();
|
.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>) {
|
pub fn ensure_relay_list(&mut self, public_key: &PublicKey, cx: &mut Context<Self>) {
|
||||||
let task = self.get_event(public_key, Kind::RelayList, cx);
|
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| {
|
self.tasks.push(cx.spawn(async move |this, cx| {
|
||||||
match task.await {
|
match task.await {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
@@ -580,7 +654,7 @@ impl NostrRegistry {
|
|||||||
Err(e) => {
|
Err(e) => {
|
||||||
this.update(cx, |_this, cx| {
|
this.update(cx, |_this, cx| {
|
||||||
cx.emit(StateEvent::RelayNotConfigured);
|
cx.emit(StateEvent::RelayNotConfigured);
|
||||||
cx.emit(StateEvent::Error(SharedString::from(e.to_string())));
|
cx.emit(StateEvent::error(e.to_string()));
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user