chore: release 0.1.4

This commit is contained in:
2025-03-13 13:02:58 +07:00
parent 0a7f0475a4
commit cae96157ca
8 changed files with 85 additions and 51 deletions

View File

@@ -1,6 +1,6 @@
[package]
name = "coop"
version = "0.1.3"
version = "0.1.4"
edition = "2021"
publish = false

View File

@@ -211,6 +211,10 @@ impl Device {
cx.set_global(GlobalDevice(device));
}
pub fn client_keys(&self) -> Arc<Keys> {
self.client_keys.clone()
}
pub fn profile(&self) -> Option<&NostrProfile> {
self.profile.as_ref()
}

View File

@@ -141,19 +141,15 @@ fn main() {
pubkeys.push(event.pubkey);
// Save the event to the database, use for query directly.
if let Err(e) =
client.database().save_event(&event).await
{
log::error!("Failed to save event: {}", e);
}
// Send all pubkeys to the batch
_ = batch_tx.send(pubkeys).await;
_ = client.database().save_event(&event).await;
// Send this event to the GPUI
if new_id == *subscription_id {
_ = event_tx.send(Signal::Event(event)).await;
}
// Send all pubkeys to the batch
_ = batch_tx.send(pubkeys).await;
}
}
}
@@ -180,12 +176,18 @@ fn main() {
Kind::Custom(DEVICE_ANNOUNCEMENT_KIND) => {
log::info!("Device Announcement received");
if let Some(tag) = event
.tags
.find(TagKind::custom("client"))
.and_then(|tag| tag.content())
{
set_device_name(tag).await;
if let Ok(signer) = client.signer().await {
if let Ok(public_key) = signer.get_public_key().await {
if event.pubkey == public_key {
if let Some(tag) = event
.tags
.find(TagKind::custom("client"))
.and_then(|tag| tag.content())
{
set_device_name(tag).await;
}
}
}
}
}
_ => {}

View File

@@ -98,6 +98,7 @@ pub struct Chat {
// Chat Room
room: WeakEntity<Room>,
messages: Entity<Vec<Message>>,
seens: Entity<Vec<EventId>>,
list_state: ListState,
#[allow(dead_code)]
subscriptions: Vec<Subscription>,
@@ -116,6 +117,7 @@ impl Chat {
cx: &mut App,
) -> Entity<Self> {
let messages = cx.new(|_| vec![Message::placeholder()]);
let seens = cx.new(|_| vec![]);
let attaches = cx.new(|_| None);
let input = cx.new(|cx| {
TextInput::new(window, cx)
@@ -165,6 +167,7 @@ impl Chat {
id: id.to_string().into(),
room,
messages,
seens,
list_state,
input,
attaches,
@@ -244,11 +247,18 @@ impl Chat {
self.list_state.splice(old_len..old_len, 1);
}
fn push_message(&self, event: &Event, _window: &mut Window, cx: &mut Context<Self>) {
fn push_message(&mut self, event: &Event, _window: &mut Window, cx: &mut Context<Self>) {
let Some(model) = self.room.upgrade() else {
return;
};
// Prevent duplicate messages
if self.seens.read(cx).iter().any(|id| id == &event.id) {
return;
}
// Add ID to seen list
self.seen(event.id, cx);
let old_len = self.messages.read(cx).len();
let room = model.read(cx);
@@ -450,6 +460,13 @@ impl Chat {
cx.notify();
}
fn seen(&mut self, id: EventId, cx: &mut Context<Self>) {
self.seens.update(cx, |this, cx| {
this.push(id);
cx.notify();
});
}
fn render_message(
&self,
ix: usize,

View File

@@ -5,7 +5,7 @@ use gpui::{
};
use nostr_connect::prelude::*;
use smallvec::{smallvec, SmallVec};
use std::{path::PathBuf, time::Duration};
use std::{path::PathBuf, sync::Arc, time::Duration};
use ui::{
button::{Button, ButtonCustomVariant, ButtonVariants},
input::{InputEvent, TextInput},
@@ -104,8 +104,12 @@ impl Onboarding {
}
fn connect(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let Some(model) = Device::global(cx) else {
return;
};
let text = self.bunker_input.read(cx).text().to_string();
let keys = Keys::generate();
let keys = Arc::unwrap_or_clone(model.read(cx).client_keys());
self.set_loading(true, cx);

View File

@@ -1,7 +1,11 @@
use std::collections::HashSet;
use anyhow::{anyhow, Context, Error};
use common::{last_seen::LastSeen, profile::NostrProfile, utils::room_hash};
use anyhow::{anyhow, Error};
use common::{
last_seen::LastSeen,
profile::NostrProfile,
utils::{device_pubkey, room_hash},
};
use global::{constants::DEVICE_ANNOUNCEMENT_KIND, get_client, get_device_keys};
use gpui::{App, AppContext, Entity, EventEmitter, SharedString, Task};
use nostr_sdk::prelude::*;
@@ -194,41 +198,35 @@ impl Room {
// Check if the pubkey has a device announcement,
// then choose the appropriate signer based on device presence
if let Some(event) = client.database().query(filter).await?.first_owned() {
log::info!("Use device signer to send message");
let signer = &device;
let event = match client.database().query(filter).await?.first() {
Some(event) => {
log::info!("Use device signer to send message");
let signer = &device;
// Get the device's public key of other user
let device_pubkey = device_pubkey(event)?;
// Get the device's public key of other user
let n_tag = event.tags.find(TagKind::custom("n")).context("Not found")?;
let hex = n_tag.content().context("Not found")?;
let target_pubkey = PublicKey::parse(hex)?;
let rumor = EventBuilder::private_msg_rumor(*pubkey, &content)
.tags(tags.clone())
.build(user_pubkey);
let rumor = EventBuilder::private_msg_rumor(*pubkey, &content)
.tags(tags.clone())
.build(user_pubkey);
let event = EventBuilder::gift_wrap(
signer,
&target_pubkey,
rumor,
vec![Tag::public_key(*pubkey)],
)
.await?;
if let Err(e) = client.send_event(&event).await {
// Convert error into string, then push it to the report
report.push(e.to_string());
EventBuilder::gift_wrap(
signer,
&device_pubkey,
rumor,
vec![Tag::public_key(*pubkey)],
)
.await?
}
} else {
log::info!("Use user signer to send message");
let signer = &client.signer().await?;
None => {
log::info!("Use user signer to send message");
let signer = client.signer().await?;
let event =
EventBuilder::private_msg(signer, *pubkey, &content, tags.clone()).await?;
if let Err(e) = client.send_event(&event).await {
report.push(e.to_string());
EventBuilder::private_msg(&signer, *pubkey, &content, tags.clone()).await?
}
};
if let Err(e) = client.send_event(&event).await {
report.push(e.to_string());
}
}

View File

@@ -1,3 +1,4 @@
use anyhow::Context;
use global::constants::NIP96_SERVER;
use itertools::Itertools;
use nostr_sdk::prelude::*;
@@ -43,6 +44,14 @@ pub fn room_hash(event: &Event) -> u64 {
hasher.finish()
}
pub fn device_pubkey(event: &Event) -> Result<PublicKey, anyhow::Error> {
let n_tag = event.tags.find(TagKind::custom("n")).context("Invalid")?;
let hex = n_tag.content().context("Invalid")?;
let pubkey = PublicKey::parse(hex)?;
Ok(pubkey)
}
pub fn random_name(length: usize) -> String {
let rng = RNG::from(&Language::Roman);
rng.generate_names(length, true).join("-").to_lowercase()