mirror of
https://github.com/mikedilger/gossip.git
synced 2024-09-18 03:03:45 +00:00
Crude 'tagging' ability, will improve over time
This commit is contained in:
parent
aea9c1f1a2
commit
5c1fc6a510
@ -1,4 +1,4 @@
|
||||
use nostr_types::{Event, Id, IdHex, PublicKey, PublicKeyHex};
|
||||
use nostr_types::{Event, Id, IdHex, PublicKey, PublicKeyHex, Tag};
|
||||
|
||||
/// This is a message sent to the Overlord
|
||||
#[derive(Debug, Clone)]
|
||||
@ -15,8 +15,8 @@ pub enum ToOverlordMessage {
|
||||
Like(Id, PublicKey),
|
||||
MinionIsReady,
|
||||
ProcessIncomingEvents,
|
||||
PostReply(String, Id),
|
||||
PostTextNote(String),
|
||||
PostReply(String, Vec<Tag>, Id),
|
||||
PostTextNote(String, Vec<Tag>),
|
||||
SaveRelays,
|
||||
SaveSettings,
|
||||
Shutdown,
|
||||
|
@ -436,11 +436,11 @@ impl Overlord {
|
||||
}
|
||||
});
|
||||
}
|
||||
ToOverlordMessage::PostReply(content, reply_to) => {
|
||||
self.post_reply(content, reply_to).await?;
|
||||
ToOverlordMessage::PostReply(content, tags, reply_to) => {
|
||||
self.post_reply(content, tags, reply_to).await?;
|
||||
}
|
||||
ToOverlordMessage::PostTextNote(content) => {
|
||||
self.post_textnote(content).await?;
|
||||
ToOverlordMessage::PostTextNote(content, tags) => {
|
||||
self.post_textnote(content, tags).await?;
|
||||
}
|
||||
ToOverlordMessage::SaveRelays => {
|
||||
let dirty_relays: Vec<DbRelay> = GLOBALS
|
||||
@ -619,7 +619,7 @@ impl Overlord {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn post_textnote(&mut self, content: String) -> Result<(), Error> {
|
||||
async fn post_textnote(&mut self, content: String, tags: Vec<Tag>) -> Result<(), Error> {
|
||||
let event = {
|
||||
let public_key = match GLOBALS.signer.read().await.public_key() {
|
||||
Some(pk) => pk,
|
||||
@ -633,7 +633,7 @@ impl Overlord {
|
||||
pubkey: public_key,
|
||||
created_at: Unixtime::now().unwrap(),
|
||||
kind: EventKind::TextNote,
|
||||
tags: vec![],
|
||||
tags,
|
||||
content,
|
||||
ots: None,
|
||||
};
|
||||
@ -672,9 +672,12 @@ impl Overlord {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn post_reply(&mut self, content: String, reply_to: Id) -> Result<(), Error> {
|
||||
let mut tags: Vec<Tag> = Vec::new();
|
||||
|
||||
async fn post_reply(
|
||||
&mut self,
|
||||
content: String,
|
||||
mut tags: Vec<Tag>,
|
||||
reply_to: Id,
|
||||
) -> Result<(), Error> {
|
||||
let event = {
|
||||
let public_key = match GLOBALS.signer.read().await.public_key() {
|
||||
Some(pk) => pk,
|
||||
@ -720,6 +723,8 @@ impl Overlord {
|
||||
.collect();
|
||||
tags.extend(parent_p_tags);
|
||||
|
||||
// FIXME deduplicate 'p' tags
|
||||
|
||||
let pre_event = PreEvent {
|
||||
pubkey: public_key,
|
||||
created_at: Unixtime::now().unwrap(),
|
||||
|
@ -2,7 +2,7 @@ use crate::db::DbPerson;
|
||||
use crate::error::Error;
|
||||
use crate::globals::GLOBALS;
|
||||
use image::RgbaImage;
|
||||
use nostr_types::{Metadata, PublicKeyHex, Unixtime, Url};
|
||||
use nostr_types::{Metadata, PublicKey, PublicKeyHex, Unixtime, Url};
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::time::Duration;
|
||||
@ -333,6 +333,28 @@ impl People {
|
||||
}
|
||||
}
|
||||
|
||||
/// This lets you start typing a name, and autocomplete the results for tagging
|
||||
/// someone in a post. It returns maximum 10 results.
|
||||
pub fn get_ids_from_prefix(&self, mut prefix: &str) -> Vec<(String, PublicKey)> {
|
||||
// work with or without the @ symbol:
|
||||
if prefix.starts_with('@') {
|
||||
prefix = &prefix[1..]
|
||||
}
|
||||
self.people
|
||||
.iter()
|
||||
.filter_map(|(_, person)| {
|
||||
if let Some(name) = &person.name {
|
||||
if name.starts_with(prefix) {
|
||||
let pubkey = PublicKey::try_from_hex_string(&person.pubkey).unwrap(); // FIXME
|
||||
return Some((name.clone(), pubkey));
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
.take(10)
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// This is a 'just in case' the main code isn't keeping them in sync.
|
||||
pub async fn populate_new_people() -> Result<(), Error> {
|
||||
let sql = "INSERT or IGNORE INTO person (pubkey) SELECT DISTINCT pubkey FROM EVENT";
|
||||
|
@ -145,28 +145,60 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, frame: &mut eframe::Fram
|
||||
}
|
||||
|
||||
ui.with_layout(Layout::right_to_left(Align::TOP), |ui| {
|
||||
if ui.button("Send").clicked() && !app.draft.is_empty() {
|
||||
match app.replying_to {
|
||||
Some(replying_to_id) => {
|
||||
let _ = GLOBALS.to_overlord.send(ToOverlordMessage::PostReply(
|
||||
app.draft.clone(),
|
||||
replying_to_id,
|
||||
));
|
||||
ui.with_layout(Layout::top_down(Align::RIGHT), |ui| {
|
||||
if ui.button("Send").clicked() && !app.draft.is_empty() {
|
||||
match app.replying_to {
|
||||
Some(replying_to_id) => {
|
||||
let _ = GLOBALS.to_overlord.send(ToOverlordMessage::PostReply(
|
||||
app.draft.clone(),
|
||||
app.draft_tags.clone(),
|
||||
replying_to_id,
|
||||
));
|
||||
}
|
||||
None => {
|
||||
let _ = GLOBALS.to_overlord.send(ToOverlordMessage::PostTextNote(
|
||||
app.draft.clone(),
|
||||
app.draft_tags.clone(),
|
||||
));
|
||||
}
|
||||
}
|
||||
None => {
|
||||
let _ = GLOBALS
|
||||
.to_overlord
|
||||
.send(ToOverlordMessage::PostTextNote(app.draft.clone()));
|
||||
app.draft = "".to_owned();
|
||||
app.replying_to = None;
|
||||
}
|
||||
|
||||
if ui.button("Cancel").clicked() {
|
||||
app.draft = "".to_owned();
|
||||
app.replying_to = None;
|
||||
}
|
||||
|
||||
ui.add(
|
||||
TextEdit::singleline(&mut app.tag_someone)
|
||||
.desired_width(100.0)
|
||||
.hint_text("@username"),
|
||||
);
|
||||
if !app.tag_someone.is_empty() {
|
||||
let pairs = GLOBALS
|
||||
.people
|
||||
.blocking_read()
|
||||
.get_ids_from_prefix(&app.tag_someone);
|
||||
if !pairs.is_empty() {
|
||||
ui.menu_button("@", |ui| {
|
||||
for pair in pairs {
|
||||
if ui.button(pair.0).clicked() {
|
||||
app.draft_tags.push(Tag::Pubkey {
|
||||
pubkey: pair.1,
|
||||
recommended_relay_url: None, // FIXME
|
||||
petname: None,
|
||||
});
|
||||
app.draft
|
||||
.push_str(&format!("#[{}]", app.draft_tags.len() - 1));
|
||||
app.tag_someone = "".to_owned();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
app.draft = "".to_owned();
|
||||
app.replying_to = None;
|
||||
}
|
||||
if ui.button("Cancel").clicked() {
|
||||
app.draft = "".to_owned();
|
||||
app.replying_to = None;
|
||||
}
|
||||
|
||||
});
|
||||
ui.add(
|
||||
TextEdit::multiline(&mut app.draft)
|
||||
.hint_text("Type your message here")
|
||||
|
@ -18,7 +18,7 @@ use egui::{
|
||||
ColorImage, Context, ImageData, Label, RichText, SelectableLabel, Sense, TextStyle,
|
||||
TextureHandle, TextureOptions, Ui,
|
||||
};
|
||||
use nostr_types::{Id, IdHex, PublicKey, PublicKeyHex};
|
||||
use nostr_types::{Id, IdHex, PublicKey, PublicKeyHex, Tag};
|
||||
use std::collections::HashMap;
|
||||
use std::time::{Duration, Instant};
|
||||
use zeroize::Zeroize;
|
||||
@ -76,6 +76,8 @@ struct GossipUi {
|
||||
icon: TextureHandle,
|
||||
placeholder_avatar: TextureHandle,
|
||||
draft: String,
|
||||
draft_tags: Vec<Tag>,
|
||||
tag_someone: String,
|
||||
settings: Settings,
|
||||
nip05follow: String,
|
||||
follow_bech32_pubkey: String,
|
||||
@ -148,6 +150,8 @@ impl GossipUi {
|
||||
icon: icon_texture_handle,
|
||||
placeholder_avatar: placeholder_avatar_texture_handle,
|
||||
draft: "".to_owned(),
|
||||
draft_tags: Vec::new(),
|
||||
tag_someone: "".to_owned(),
|
||||
settings,
|
||||
nip05follow: "".to_owned(),
|
||||
follow_bech32_pubkey: "".to_owned(),
|
||||
|
Loading…
Reference in New Issue
Block a user