chore: release 0.1.4
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "coop"
|
||||
version = "0.1.3"
|
||||
version = "0.1.4"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user