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
|
/// This is a message sent to the Overlord
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -15,8 +15,8 @@ pub enum ToOverlordMessage {
|
|||||||
Like(Id, PublicKey),
|
Like(Id, PublicKey),
|
||||||
MinionIsReady,
|
MinionIsReady,
|
||||||
ProcessIncomingEvents,
|
ProcessIncomingEvents,
|
||||||
PostReply(String, Id),
|
PostReply(String, Vec<Tag>, Id),
|
||||||
PostTextNote(String),
|
PostTextNote(String, Vec<Tag>),
|
||||||
SaveRelays,
|
SaveRelays,
|
||||||
SaveSettings,
|
SaveSettings,
|
||||||
Shutdown,
|
Shutdown,
|
||||||
|
@ -436,11 +436,11 @@ impl Overlord {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ToOverlordMessage::PostReply(content, reply_to) => {
|
ToOverlordMessage::PostReply(content, tags, reply_to) => {
|
||||||
self.post_reply(content, reply_to).await?;
|
self.post_reply(content, tags, reply_to).await?;
|
||||||
}
|
}
|
||||||
ToOverlordMessage::PostTextNote(content) => {
|
ToOverlordMessage::PostTextNote(content, tags) => {
|
||||||
self.post_textnote(content).await?;
|
self.post_textnote(content, tags).await?;
|
||||||
}
|
}
|
||||||
ToOverlordMessage::SaveRelays => {
|
ToOverlordMessage::SaveRelays => {
|
||||||
let dirty_relays: Vec<DbRelay> = GLOBALS
|
let dirty_relays: Vec<DbRelay> = GLOBALS
|
||||||
@ -619,7 +619,7 @@ impl Overlord {
|
|||||||
Ok(())
|
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 event = {
|
||||||
let public_key = match GLOBALS.signer.read().await.public_key() {
|
let public_key = match GLOBALS.signer.read().await.public_key() {
|
||||||
Some(pk) => pk,
|
Some(pk) => pk,
|
||||||
@ -633,7 +633,7 @@ impl Overlord {
|
|||||||
pubkey: public_key,
|
pubkey: public_key,
|
||||||
created_at: Unixtime::now().unwrap(),
|
created_at: Unixtime::now().unwrap(),
|
||||||
kind: EventKind::TextNote,
|
kind: EventKind::TextNote,
|
||||||
tags: vec![],
|
tags,
|
||||||
content,
|
content,
|
||||||
ots: None,
|
ots: None,
|
||||||
};
|
};
|
||||||
@ -672,9 +672,12 @@ impl Overlord {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn post_reply(&mut self, content: String, reply_to: Id) -> Result<(), Error> {
|
async fn post_reply(
|
||||||
let mut tags: Vec<Tag> = Vec::new();
|
&mut self,
|
||||||
|
content: String,
|
||||||
|
mut tags: Vec<Tag>,
|
||||||
|
reply_to: Id,
|
||||||
|
) -> Result<(), Error> {
|
||||||
let event = {
|
let event = {
|
||||||
let public_key = match GLOBALS.signer.read().await.public_key() {
|
let public_key = match GLOBALS.signer.read().await.public_key() {
|
||||||
Some(pk) => pk,
|
Some(pk) => pk,
|
||||||
@ -720,6 +723,8 @@ impl Overlord {
|
|||||||
.collect();
|
.collect();
|
||||||
tags.extend(parent_p_tags);
|
tags.extend(parent_p_tags);
|
||||||
|
|
||||||
|
// FIXME deduplicate 'p' tags
|
||||||
|
|
||||||
let pre_event = PreEvent {
|
let pre_event = PreEvent {
|
||||||
pubkey: public_key,
|
pubkey: public_key,
|
||||||
created_at: Unixtime::now().unwrap(),
|
created_at: Unixtime::now().unwrap(),
|
||||||
|
@ -2,7 +2,7 @@ use crate::db::DbPerson;
|
|||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::globals::GLOBALS;
|
use crate::globals::GLOBALS;
|
||||||
use image::RgbaImage;
|
use image::RgbaImage;
|
||||||
use nostr_types::{Metadata, PublicKeyHex, Unixtime, Url};
|
use nostr_types::{Metadata, PublicKey, PublicKeyHex, Unixtime, Url};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::time::Duration;
|
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.
|
/// This is a 'just in case' the main code isn't keeping them in sync.
|
||||||
pub async fn populate_new_people() -> Result<(), Error> {
|
pub async fn populate_new_people() -> Result<(), Error> {
|
||||||
let sql = "INSERT or IGNORE INTO person (pubkey) SELECT DISTINCT pubkey FROM EVENT";
|
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| {
|
ui.with_layout(Layout::right_to_left(Align::TOP), |ui| {
|
||||||
if ui.button("Send").clicked() && !app.draft.is_empty() {
|
ui.with_layout(Layout::top_down(Align::RIGHT), |ui| {
|
||||||
match app.replying_to {
|
if ui.button("Send").clicked() && !app.draft.is_empty() {
|
||||||
Some(replying_to_id) => {
|
match app.replying_to {
|
||||||
let _ = GLOBALS.to_overlord.send(ToOverlordMessage::PostReply(
|
Some(replying_to_id) => {
|
||||||
app.draft.clone(),
|
let _ = GLOBALS.to_overlord.send(ToOverlordMessage::PostReply(
|
||||||
replying_to_id,
|
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 => {
|
app.draft = "".to_owned();
|
||||||
let _ = GLOBALS
|
app.replying_to = None;
|
||||||
.to_overlord
|
}
|
||||||
.send(ToOverlordMessage::PostTextNote(app.draft.clone()));
|
|
||||||
|
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(
|
ui.add(
|
||||||
TextEdit::multiline(&mut app.draft)
|
TextEdit::multiline(&mut app.draft)
|
||||||
.hint_text("Type your message here")
|
.hint_text("Type your message here")
|
||||||
|
@ -18,7 +18,7 @@ use egui::{
|
|||||||
ColorImage, Context, ImageData, Label, RichText, SelectableLabel, Sense, TextStyle,
|
ColorImage, Context, ImageData, Label, RichText, SelectableLabel, Sense, TextStyle,
|
||||||
TextureHandle, TextureOptions, Ui,
|
TextureHandle, TextureOptions, Ui,
|
||||||
};
|
};
|
||||||
use nostr_types::{Id, IdHex, PublicKey, PublicKeyHex};
|
use nostr_types::{Id, IdHex, PublicKey, PublicKeyHex, Tag};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use zeroize::Zeroize;
|
use zeroize::Zeroize;
|
||||||
@ -76,6 +76,8 @@ struct GossipUi {
|
|||||||
icon: TextureHandle,
|
icon: TextureHandle,
|
||||||
placeholder_avatar: TextureHandle,
|
placeholder_avatar: TextureHandle,
|
||||||
draft: String,
|
draft: String,
|
||||||
|
draft_tags: Vec<Tag>,
|
||||||
|
tag_someone: String,
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
nip05follow: String,
|
nip05follow: String,
|
||||||
follow_bech32_pubkey: String,
|
follow_bech32_pubkey: String,
|
||||||
@ -148,6 +150,8 @@ impl GossipUi {
|
|||||||
icon: icon_texture_handle,
|
icon: icon_texture_handle,
|
||||||
placeholder_avatar: placeholder_avatar_texture_handle,
|
placeholder_avatar: placeholder_avatar_texture_handle,
|
||||||
draft: "".to_owned(),
|
draft: "".to_owned(),
|
||||||
|
draft_tags: Vec::new(),
|
||||||
|
tag_someone: "".to_owned(),
|
||||||
settings,
|
settings,
|
||||||
nip05follow: "".to_owned(),
|
nip05follow: "".to_owned(),
|
||||||
follow_bech32_pubkey: "".to_owned(),
|
follow_bech32_pubkey: "".to_owned(),
|
||||||
|
Loading…
Reference in New Issue
Block a user