mirror of
https://github.com/mikedilger/gossip.git
synced 2024-09-19 19:46:50 +00:00
PART 4 of globals/process revamp: strip out feed_event and feed_event map from globals; get_feed rewritten
This commit is contained in:
parent
b544603d5e
commit
7e18d33f71
@ -1,90 +0,0 @@
|
|||||||
use crate::db::DbEvent;
|
|
||||||
use crate::error::Error;
|
|
||||||
use nostr_types::{Event, EventKind, Id};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
|
||||||
pub struct Reactions {
|
|
||||||
pub upvotes: u64,
|
|
||||||
pub downvotes: u64,
|
|
||||||
pub emojis: Vec<(char, u64)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This contains event-related data that is relevant at the time of
|
|
||||||
/// rendering the event, most of which is gathered from other related
|
|
||||||
/// events.
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
||||||
pub struct FeedEvent {
|
|
||||||
pub id: Id,
|
|
||||||
pub event: Option<Event>,
|
|
||||||
pub feed_related: bool,
|
|
||||||
pub replies: Vec<Id>,
|
|
||||||
pub in_reply_to: Option<Id>,
|
|
||||||
pub reactions: Reactions,
|
|
||||||
pub deleted_reason: Option<String>,
|
|
||||||
pub client: Option<String>,
|
|
||||||
pub hashtags: Vec<String>,
|
|
||||||
pub subject: Option<String>,
|
|
||||||
pub urls: Vec<String>,
|
|
||||||
pub last_reply_at: Option<i64>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FeedEvent {
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn new(id: Id) -> FeedEvent {
|
|
||||||
FeedEvent {
|
|
||||||
id,
|
|
||||||
event: None,
|
|
||||||
feed_related: false,
|
|
||||||
replies: Vec::new(),
|
|
||||||
in_reply_to: None,
|
|
||||||
reactions: Default::default(),
|
|
||||||
deleted_reason: None,
|
|
||||||
client: None,
|
|
||||||
hashtags: Vec::new(),
|
|
||||||
subject: None,
|
|
||||||
urls: Vec::new(),
|
|
||||||
last_reply_at: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&Event> for FeedEvent {
|
|
||||||
fn from(event: &Event) -> FeedEvent {
|
|
||||||
FeedEvent {
|
|
||||||
id: event.id,
|
|
||||||
event: Some(event.to_owned()),
|
|
||||||
feed_related: event.kind == EventKind::TextNote,
|
|
||||||
replies: Vec::new(),
|
|
||||||
in_reply_to: None,
|
|
||||||
reactions: Default::default(),
|
|
||||||
deleted_reason: None,
|
|
||||||
client: None,
|
|
||||||
hashtags: Vec::new(),
|
|
||||||
subject: None,
|
|
||||||
urls: Vec::new(),
|
|
||||||
last_reply_at: Some(event.created_at.0),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<&DbEvent> for FeedEvent {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn try_from(dbevent: &DbEvent) -> Result<FeedEvent, Error> {
|
|
||||||
Ok(FeedEvent {
|
|
||||||
id: dbevent.id.clone().try_into()?,
|
|
||||||
event: serde_json::from_str(&dbevent.raw)?,
|
|
||||||
feed_related: dbevent.kind == 1,
|
|
||||||
replies: Vec::new(),
|
|
||||||
in_reply_to: None,
|
|
||||||
reactions: Default::default(),
|
|
||||||
deleted_reason: None,
|
|
||||||
client: None,
|
|
||||||
hashtags: Vec::new(),
|
|
||||||
subject: None,
|
|
||||||
urls: Vec::new(),
|
|
||||||
last_reply_at: Some(dbevent.created_at),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,6 @@
|
|||||||
use crate::comms::BusMessage;
|
use crate::comms::BusMessage;
|
||||||
use crate::db::{DbPerson, DbPersonRelay, DbRelay};
|
use crate::db::{DbPerson, DbPersonRelay, DbRelay};
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::feed_event::FeedEvent;
|
|
||||||
use crate::relationship::Relationship;
|
use crate::relationship::Relationship;
|
||||||
use crate::settings::Settings;
|
use crate::settings::Settings;
|
||||||
use async_recursion::async_recursion;
|
use async_recursion::async_recursion;
|
||||||
@ -29,15 +28,10 @@ pub struct Globals {
|
|||||||
/// and stolen away when the Overlord is created.
|
/// and stolen away when the Overlord is created.
|
||||||
pub from_minions: Mutex<Option<mpsc::UnboundedReceiver<BusMessage>>>,
|
pub from_minions: Mutex<Option<mpsc::UnboundedReceiver<BusMessage>>>,
|
||||||
|
|
||||||
/// All nostr event related data, keyed by the event Id
|
|
||||||
pub feed_events: Mutex<HashMap<Id, FeedEvent>>,
|
|
||||||
|
|
||||||
/// All nostr events, keyed by the event Id
|
/// All nostr events, keyed by the event Id
|
||||||
/// This will replace feed_events.
|
|
||||||
pub events: Mutex<HashMap<Id, Event>>,
|
pub events: Mutex<HashMap<Id, Event>>,
|
||||||
|
|
||||||
/// All relationships between events
|
/// All relationships between events
|
||||||
/// This will also replace feed_events.
|
|
||||||
pub relationships: Mutex<HashMap<Id, Vec<(Id, Relationship)>>>,
|
pub relationships: Mutex<HashMap<Id, Vec<(Id, Relationship)>>>,
|
||||||
|
|
||||||
/// The date of the latest reply. Only reply relationships count, not reactions,
|
/// The date of the latest reply. Only reply relationships count, not reactions,
|
||||||
@ -73,7 +67,6 @@ lazy_static! {
|
|||||||
to_minions,
|
to_minions,
|
||||||
to_overlord,
|
to_overlord,
|
||||||
from_minions: Mutex::new(Some(from_minions)),
|
from_minions: Mutex::new(Some(from_minions)),
|
||||||
feed_events: Mutex::new(HashMap::new()),
|
|
||||||
events: Mutex::new(HashMap::new()),
|
events: Mutex::new(HashMap::new()),
|
||||||
relationships: Mutex::new(HashMap::new()),
|
relationships: Mutex::new(HashMap::new()),
|
||||||
last_reply: Mutex::new(HashMap::new()),
|
last_reply: Mutex::new(HashMap::new()),
|
||||||
@ -88,20 +81,20 @@ lazy_static! {
|
|||||||
impl Globals {
|
impl Globals {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub async fn get_feed(threaded: bool) -> Vec<Id> {
|
pub async fn get_feed(threaded: bool) -> Vec<Id> {
|
||||||
let feed: Vec<FeedEvent> = GLOBALS
|
let feed: Vec<Event> = GLOBALS
|
||||||
.feed_events
|
.events
|
||||||
.lock()
|
.lock()
|
||||||
.await
|
.await
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, e)| e)
|
.map(|(_, e)| e)
|
||||||
.filter(|e| e.event.is_some() && e.event.as_ref().unwrap().kind == EventKind::TextNote)
|
.filter(|e| e.kind == EventKind::TextNote)
|
||||||
.filter(|e| {
|
.filter(|e| {
|
||||||
if threaded {
|
if threaded {
|
||||||
e.in_reply_to.is_none()
|
e.replies_to().is_none()
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}) // only root events
|
})
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
@ -110,44 +103,36 @@ impl Globals {
|
|||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn blocking_get_feed(threaded: bool) -> Vec<Id> {
|
pub fn blocking_get_feed(threaded: bool) -> Vec<Id> {
|
||||||
let feed: Vec<FeedEvent> = GLOBALS
|
let feed: Vec<Event> = GLOBALS
|
||||||
.feed_events
|
.events
|
||||||
.blocking_lock()
|
.blocking_lock()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, e)| e)
|
.map(|(_, e)| e)
|
||||||
.filter(|e| e.event.is_some() && e.event.as_ref().unwrap().kind == EventKind::TextNote)
|
.filter(|e| e.kind == EventKind::TextNote)
|
||||||
.filter(|e| {
|
.filter(|e| {
|
||||||
if threaded {
|
if threaded {
|
||||||
e.in_reply_to.is_none()
|
e.replies_to().is_none()
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}) // only root events
|
})
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Self::sort_feed(feed, threaded)
|
Self::sort_feed(feed, threaded)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sort_feed(mut feed: Vec<FeedEvent>, threaded: bool) -> Vec<Id> {
|
fn sort_feed(mut feed: Vec<Event>, threaded: bool) -> Vec<Id> {
|
||||||
if threaded {
|
if threaded {
|
||||||
feed.sort_unstable_by(|a, b| b.last_reply_at.cmp(&a.last_reply_at));
|
|
||||||
} else {
|
|
||||||
feed.sort_unstable_by(|a, b| {
|
feed.sort_unstable_by(|a, b| {
|
||||||
if a.event.is_some() && b.event.is_some() {
|
let a_last = GLOBALS.last_reply.blocking_lock().get(&a.id).cloned();
|
||||||
b.event
|
let b_last = GLOBALS.last_reply.blocking_lock().get(&b.id).cloned();
|
||||||
.as_ref()
|
let a_time = a_last.unwrap_or(a.created_at);
|
||||||
.unwrap()
|
let b_time = b_last.unwrap_or(b.created_at);
|
||||||
.created_at
|
b_time.cmp(&a_time)
|
||||||
.cmp(&a.event.as_ref().unwrap().created_at)
|
|
||||||
} else if a.event.is_some() {
|
|
||||||
std::cmp::Ordering::Greater
|
|
||||||
} else if b.event.is_some() {
|
|
||||||
std::cmp::Ordering::Less
|
|
||||||
} else {
|
|
||||||
std::cmp::Ordering::Equal
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
feed.sort_unstable_by(|a, b| b.created_at.cmp(&a.created_at));
|
||||||
}
|
}
|
||||||
|
|
||||||
feed.iter().map(|e| e.id).collect()
|
feed.iter().map(|e| e.id).collect()
|
||||||
@ -203,13 +188,25 @@ impl Globals {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_replies_sync(id: Id) -> Vec<Id> {
|
||||||
|
let mut output: Vec<Id> = Vec::new();
|
||||||
|
if let Some(vec) = GLOBALS.relationships.blocking_lock().get(&id) {
|
||||||
|
for (id, relationship) in vec.iter() {
|
||||||
|
if *relationship == Relationship::Reply {
|
||||||
|
output.push(*id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME - this allows people to react many times to the same event, and
|
// FIXME - this allows people to react many times to the same event, and
|
||||||
// it counts them all!
|
// it counts them all!
|
||||||
#[allow(dead_code)]
|
pub fn get_reactions_sync(id: Id) -> HashMap<char, usize> {
|
||||||
pub async fn get_reactions(id: Id) -> HashMap<char, usize> {
|
|
||||||
let mut output: HashMap<char, usize> = HashMap::new();
|
let mut output: HashMap<char, usize> = HashMap::new();
|
||||||
|
|
||||||
if let Some(relationships) = GLOBALS.relationships.lock().await.get(&id).cloned() {
|
if let Some(relationships) = GLOBALS.relationships.blocking_lock().get(&id).cloned() {
|
||||||
for (_id, relationship) in relationships.iter() {
|
for (_id, relationship) in relationships.iter() {
|
||||||
if let Relationship::Reaction(reaction) = relationship {
|
if let Relationship::Reaction(reaction) = relationship {
|
||||||
if let Some(ch) = reaction.chars().next() {
|
if let Some(ch) = reaction.chars().next() {
|
||||||
|
@ -8,7 +8,6 @@ mod comms;
|
|||||||
mod date_ago;
|
mod date_ago;
|
||||||
mod db;
|
mod db;
|
||||||
mod error;
|
mod error;
|
||||||
mod feed_event;
|
|
||||||
mod globals;
|
mod globals;
|
||||||
mod overlord;
|
mod overlord;
|
||||||
mod process;
|
mod process;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use super::GossipUi;
|
use super::GossipUi;
|
||||||
use crate::globals::Globals;
|
use crate::globals::{Globals, GLOBALS};
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use egui::{Align, Color32, Context, Layout, RichText, ScrollArea, TextStyle, Ui, Vec2};
|
use egui::{Align, Color32, Context, Layout, RichText, ScrollArea, TextStyle, Ui, Vec2};
|
||||||
use nostr_types::{EventKind, Id, PublicKey};
|
use nostr_types::{EventKind, Id, PublicKey};
|
||||||
@ -46,31 +46,21 @@ fn render_post(
|
|||||||
id: Id,
|
id: Id,
|
||||||
indent: usize,
|
indent: usize,
|
||||||
) {
|
) {
|
||||||
let maybe_fevent = crate::globals::GLOBALS
|
let maybe_event = GLOBALS.events.blocking_lock().get(&id).cloned();
|
||||||
.feed_events
|
if maybe_event.is_none() {
|
||||||
.blocking_lock()
|
|
||||||
.get(&id)
|
|
||||||
.cloned();
|
|
||||||
if maybe_fevent.is_none() {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let fevent = maybe_fevent.unwrap();
|
let event = maybe_event.unwrap();
|
||||||
|
|
||||||
if fevent.event.is_none() {
|
|
||||||
return;
|
|
||||||
} // don't render related info w/o nostr event.
|
|
||||||
let event = fevent.event.as_ref().unwrap().to_owned();
|
|
||||||
|
|
||||||
// Only render TextNote events
|
// Only render TextNote events
|
||||||
if event.kind != EventKind::TextNote {
|
if event.kind != EventKind::TextNote {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let maybe_person = crate::globals::GLOBALS
|
let maybe_person = GLOBALS.people.blocking_lock().get(&event.pubkey).cloned();
|
||||||
.people
|
|
||||||
.blocking_lock()
|
let reactions = Globals::get_reactions_sync(event.id);
|
||||||
.get(&event.pubkey)
|
let replies = Globals::get_replies_sync(event.id);
|
||||||
.cloned();
|
|
||||||
|
|
||||||
// Person Things we can render:
|
// Person Things we can render:
|
||||||
// pubkey
|
// pubkey
|
||||||
@ -149,19 +139,25 @@ fn render_post(
|
|||||||
|
|
||||||
// Second row
|
// Second row
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
if fevent.reactions.upvotes > 0 {
|
for (ch, count) in reactions.iter() {
|
||||||
ui.label(
|
if *ch == '+' {
|
||||||
RichText::new(&format!("+{}", fevent.reactions.upvotes))
|
ui.label(
|
||||||
.text_style(TextStyle::Name("Bold".into()))
|
RichText::new(&format!("{} {}", ch, count))
|
||||||
.color(Color32::DARK_GREEN),
|
.text_style(TextStyle::Name("Bold".into()))
|
||||||
);
|
.color(Color32::DARK_GREEN),
|
||||||
}
|
);
|
||||||
if fevent.reactions.downvotes > 0 {
|
} else if *ch == '-' {
|
||||||
ui.label(
|
ui.label(
|
||||||
RichText::new(&format!("-{}", fevent.reactions.downvotes))
|
RichText::new(&format!("{} {}", ch, count))
|
||||||
.text_style(TextStyle::Name("Bold".into()))
|
.text_style(TextStyle::Name("Bold".into()))
|
||||||
.color(Color32::DARK_RED),
|
.color(Color32::DARK_RED),
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
ui.label(
|
||||||
|
RichText::new(&format!("{} {}", ch, count))
|
||||||
|
.text_style(TextStyle::Name("Bold".into())),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -172,7 +168,7 @@ fn render_post(
|
|||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
if app.settings.view_threaded {
|
if app.settings.view_threaded {
|
||||||
for reply_id in fevent.replies {
|
for reply_id in replies {
|
||||||
render_post(app, _ctx, _frame, ui, reply_id, indent + 1);
|
render_post(app, _ctx, _frame, ui, reply_id, indent + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user