wip: command bar
Some checks failed
Rust / build (ubuntu-latest, stable) (push) Failing after 1m35s
Rust / build (ubuntu-latest, stable) (pull_request) Failing after 1m36s
Some checks failed
Rust / build (ubuntu-latest, stable) (push) Failing after 1m35s
Rust / build (ubuntu-latest, stable) (pull_request) Failing after 1m36s
This commit is contained in:
@@ -6,7 +6,7 @@ use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{anyhow, Context as AnyhowContext, Error};
|
||||
use common::EventUtils;
|
||||
use common::{EventUtils, BOOTSTRAP_RELAYS};
|
||||
use device::DeviceRegistry;
|
||||
use flume::Sender;
|
||||
use fuzzy_matcher::skim::SkimMatcherV2;
|
||||
@@ -16,7 +16,7 @@ use gpui::{
|
||||
};
|
||||
use nostr_sdk::prelude::*;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use state::{tracker, NostrRegistry, RelayState, DEVICE_GIFTWRAP, USER_GIFTWRAP};
|
||||
use state::{tracker, NostrAddress, NostrRegistry, RelayState, DEVICE_GIFTWRAP, USER_GIFTWRAP};
|
||||
|
||||
mod message;
|
||||
mod room;
|
||||
@@ -336,6 +336,7 @@ impl ChatRegistry {
|
||||
}
|
||||
|
||||
/// Emit an open room event.
|
||||
///
|
||||
/// If the room is new, add it to the registry.
|
||||
pub fn emit_room(&mut self, room: WeakEntity<Room>, cx: &mut Context<Self>) {
|
||||
if let Some(room) = room.upgrade() {
|
||||
@@ -364,28 +365,96 @@ impl ChatRegistry {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
/// Search rooms by their name.
|
||||
pub fn search(&self, query: &str, cx: &App) -> Vec<Entity<Room>> {
|
||||
let matcher = SkimMatcherV2::default();
|
||||
/// Find for rooms that match the query.
|
||||
pub fn find(&self, query: &str, cx: &App) -> Task<Result<Vec<Entity<Room>>, Error>> {
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
let client = nostr.read(cx).client();
|
||||
let http_client = cx.http_client();
|
||||
let query = query.to_string();
|
||||
|
||||
self.rooms
|
||||
.iter()
|
||||
.filter(|room| {
|
||||
matcher
|
||||
.fuzzy_match(room.read(cx).display_name(cx).as_ref(), query)
|
||||
.is_some()
|
||||
if let Ok(addr) = Nip05Address::parse(&query) {
|
||||
let task: Task<Result<PublicKey, Error>> = cx.background_spawn(async move {
|
||||
let profile = addr.profile(&http_client).await?;
|
||||
let public_key = profile.public_key;
|
||||
|
||||
let opts = SubscribeAutoCloseOptions::default()
|
||||
.exit_policy(ReqExitPolicy::ExitOnEOSE)
|
||||
.timeout(Some(Duration::from_secs(3)));
|
||||
|
||||
// Construct the filter for the metadata event
|
||||
let filter = Filter::new()
|
||||
.kind(Kind::Metadata)
|
||||
.author(public_key)
|
||||
.limit(1);
|
||||
|
||||
// Subscribe to bootstrap relays
|
||||
client
|
||||
.subscribe_to(BOOTSTRAP_RELAYS, vec![filter], Some(opts))
|
||||
.await?;
|
||||
|
||||
Ok(public_key)
|
||||
});
|
||||
|
||||
cx.spawn(async move |cx| {
|
||||
let public_key = task.await?;
|
||||
let results = cx.read_global::<GlobalChatRegistry, _>(|this, cx| {
|
||||
this.0
|
||||
.read_with(cx, |this, cx| this.find_rooms(&public_key.to_hex(), cx))
|
||||
});
|
||||
Ok(results)
|
||||
})
|
||||
.cloned()
|
||||
.collect()
|
||||
} else {
|
||||
cx.spawn(async move |cx| {
|
||||
let results = cx.read_global::<GlobalChatRegistry, _>(|this, cx| {
|
||||
this.0.read_with(cx, |this, cx| this.find_rooms(&query, cx))
|
||||
});
|
||||
Ok(results)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Search rooms by public keys.
|
||||
pub fn search_by_public_key(&self, public_key: PublicKey, cx: &App) -> Vec<Entity<Room>> {
|
||||
self.rooms
|
||||
.iter()
|
||||
.filter(|room| room.read(cx).members.contains(&public_key))
|
||||
.cloned()
|
||||
.collect()
|
||||
/// Internal find function for finding rooms based on a query.
|
||||
fn find_rooms(&self, query: &str, cx: &App) -> Vec<Entity<Room>> {
|
||||
let matcher = SkimMatcherV2::default();
|
||||
|
||||
if let Ok(public_key) = PublicKey::parse(query) {
|
||||
self.rooms
|
||||
.iter()
|
||||
.filter(|room| room.read(cx).members.contains(&public_key))
|
||||
.cloned()
|
||||
.collect()
|
||||
} else {
|
||||
self.rooms
|
||||
.iter()
|
||||
.filter(|room| {
|
||||
matcher
|
||||
.fuzzy_match(room.read(cx).display_name(cx).as_ref(), query)
|
||||
.is_some()
|
||||
})
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a chat room based on NIP-05 address.
|
||||
pub fn address_to_room(&self, addr: Nip05Address, cx: &App) -> Task<Result<Room, Error>> {
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
let client = nostr.read(cx).client();
|
||||
let http_client = cx.http_client();
|
||||
|
||||
cx.background_spawn(async move {
|
||||
let signer = client.signer().await?;
|
||||
let public_key = signer.get_public_key().await?;
|
||||
|
||||
// Get the profile belonging to the address
|
||||
let profile = addr.profile(&http_client).await?;
|
||||
|
||||
// Construct the room
|
||||
let receivers = vec![profile.public_key];
|
||||
let room = Room::new(None, public_key, receivers);
|
||||
|
||||
Ok(room)
|
||||
})
|
||||
}
|
||||
|
||||
/// Reset the registry.
|
||||
@@ -531,7 +600,7 @@ impl ChatRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a Nostr event into a Coop Message and push it to the belonging room
|
||||
/// Parse a nostr event into a message and push it to the belonging room
|
||||
///
|
||||
/// If the room doesn't exist, it will be created.
|
||||
/// Updates room ordering based on the most recent messages.
|
||||
@@ -578,7 +647,7 @@ impl ChatRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
// Unwraps a gift-wrapped event and processes its contents.
|
||||
/// Unwraps a gift-wrapped event and processes its contents.
|
||||
async fn extract_rumor(
|
||||
client: &Client,
|
||||
device_signer: &Option<Arc<dyn NostrSigner>>,
|
||||
@@ -602,7 +671,7 @@ impl ChatRegistry {
|
||||
Ok(rumor_unsigned)
|
||||
}
|
||||
|
||||
// Helper method to try unwrapping with different signers
|
||||
/// Helper method to try unwrapping with different signers
|
||||
async fn try_unwrap(
|
||||
client: &Client,
|
||||
device_signer: &Option<Arc<dyn NostrSigner>>,
|
||||
|
||||
Reference in New Issue
Block a user