feat(nostr): integrate nostr

This commit is contained in:
Ryan Mwangi 2024-12-10 22:28:38 +03:00
parent 893c2d9ea7
commit eb0d678521
3 changed files with 82 additions and 5 deletions

View File

@ -4,23 +4,48 @@ use leptos::*;
use leptos_meta::*; use leptos_meta::*;
use crate::components::{item_form::ItemForm, items_list::ItemsList}; use crate::components::{item_form::ItemForm, items_list::ItemsList};
use crate::models::item::Item; use crate::models::item::Item;
use crate::nostr::NostrClient;
use tokio::sync::mpsc;
use uuid::Uuid; use uuid::Uuid;
use serde_json;
use leptos::spawn_local;
#[component] #[component]
pub fn App() -> impl IntoView { pub fn App() -> impl IntoView {
provide_meta_context(); provide_meta_context();
// Signal to store and update the list of items. // Signal to store and update the list of items.
let (items_signal, set_items) = create_signal(Vec::<Item>::new()); let (items_signal, set_items) = create_signal(Vec::<Item>::new());
let (tx, mut rx) = mpsc::channel::<String>(100);
spawn_local(async move {
//initialize nostr client
let nostr_client = NostrClient::new("wss://relay.example.com").await.unwrap();
nostr_client.subscribe_to_items(tx.clone()).await.unwrap();
// Handle incoming events
while let Some(content) = rx.recv().await {
if let Ok(item) = serde_json::from_str::<Item>(&content) {
set_items.update(|items| items.push(item));
}
}
});
// Function to handle adding a new item to the list. // Function to handle adding a new item to the list.
let add_item = move |name: String, description: String, tags: Vec<(String, String)>| { let add_item = move |name: String, description: String, tags: Vec<(String, String)>| {
set_items.update(|items| { set_items.update(|items| {
items.push(Item { let item = Item {
id: Uuid::new_v4().to_string(), id: Uuid::new_v4().to_string(),
name, name: name.clone(),
description, description: description.clone(),
tags, tags: tags.clone(),
}); };
items.push(item);
});
spawn_local(async move {
let nostr_client = NostrClient::new("wss://relay.example.com").await.unwrap();
nostr_client.publish_item(name, description, tags).await.unwrap();
}); });
}; };

View File

@ -1,6 +1,7 @@
pub mod app; pub mod app;
pub mod components; pub mod components;
pub mod models; pub mod models;
pub mod nostr;
#[cfg(feature = "hydrate")] #[cfg(feature = "hydrate")]

51
src/nostr.rs Normal file
View File

@ -0,0 +1,51 @@
use nostr_sdk::client::Error;
use nostr_sdk::prelude::*;
use tokio::sync::mpsc;
use nostr_sdk::RelayPoolNotification;
pub struct NostrClient {
client: Client,
}
impl NostrClient {
pub async fn new(relay_url: &str) -> Result<Self, Error> {
let keys = Keys::generate_from_os_random();
let client = Client::new(&keys);
client.add_relay(relay_url, None).await?;
client.connect().await;
Ok(Self { client })
}
pub async fn publish_item(
&self,
name: String,
description: String,
tags: Vec<(String, String)>
) -> Result<(), Error> {
let content = serde_json::json!({
"name": name,
"description": description,
"tags": tags
});
self.client.publish_text_note(content.to_string(), &[]).await?;
Ok(())
}
pub async fn subscribe_to_items(
&self,
tx: mpsc::Sender<String>
) -> Result<(), Error> {
let mut notifications = self.client.notifications();
tokio::spawn(async move {
while let Ok(notification) = notifications.recv().await {
if let RelayPoolNotification::Event(_url, event) = notification {
let content = event.content.clone();
tx.send(content).await.unwrap();
}
}
});
Ok(())
}
}