PART 4 of globals/process revamp: strip out feed_event and feed_event map from globals; get_feed rewritten

This commit is contained in:
Mike Dilger 2022-12-24 15:41:07 +13:00
parent b544603d5e
commit 7e18d33f71
4 changed files with 61 additions and 159 deletions

View File

@ -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),
})
}
}

View File

@ -1,7 +1,6 @@
use crate::comms::BusMessage;
use crate::db::{DbPerson, DbPersonRelay, DbRelay};
use crate::error::Error;
use crate::feed_event::FeedEvent;
use crate::relationship::Relationship;
use crate::settings::Settings;
use async_recursion::async_recursion;
@ -29,15 +28,10 @@ pub struct Globals {
/// and stolen away when the Overlord is created.
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
/// This will replace feed_events.
pub events: Mutex<HashMap<Id, Event>>,
/// All relationships between events
/// This will also replace feed_events.
pub relationships: Mutex<HashMap<Id, Vec<(Id, Relationship)>>>,
/// The date of the latest reply. Only reply relationships count, not reactions,
@ -73,7 +67,6 @@ lazy_static! {
to_minions,
to_overlord,
from_minions: Mutex::new(Some(from_minions)),
feed_events: Mutex::new(HashMap::new()),
events: Mutex::new(HashMap::new()),
relationships: Mutex::new(HashMap::new()),
last_reply: Mutex::new(HashMap::new()),
@ -88,20 +81,20 @@ lazy_static! {
impl Globals {
#[allow(dead_code)]
pub async fn get_feed(threaded: bool) -> Vec<Id> {
let feed: Vec<FeedEvent> = GLOBALS
.feed_events
let feed: Vec<Event> = GLOBALS
.events
.lock()
.await
.iter()
.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| {
if threaded {
e.in_reply_to.is_none()
e.replies_to().is_none()
} else {
true
}
}) // only root events
})
.cloned()
.collect();
@ -110,44 +103,36 @@ impl Globals {
#[allow(dead_code)]
pub fn blocking_get_feed(threaded: bool) -> Vec<Id> {
let feed: Vec<FeedEvent> = GLOBALS
.feed_events
let feed: Vec<Event> = GLOBALS
.events
.blocking_lock()
.iter()
.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| {
if threaded {
e.in_reply_to.is_none()
e.replies_to().is_none()
} else {
true
}
}) // only root events
})
.cloned()
.collect();
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 {
feed.sort_unstable_by(|a, b| b.last_reply_at.cmp(&a.last_reply_at));
} else {
feed.sort_unstable_by(|a, b| {
if a.event.is_some() && b.event.is_some() {
b.event
.as_ref()
.unwrap()
.created_at
.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
}
let a_last = GLOBALS.last_reply.blocking_lock().get(&a.id).cloned();
let b_last = GLOBALS.last_reply.blocking_lock().get(&b.id).cloned();
let a_time = a_last.unwrap_or(a.created_at);
let b_time = b_last.unwrap_or(b.created_at);
b_time.cmp(&a_time)
});
} else {
feed.sort_unstable_by(|a, b| b.created_at.cmp(&a.created_at));
}
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
// it counts them all!
#[allow(dead_code)]
pub async fn get_reactions(id: Id) -> HashMap<char, usize> {
pub fn get_reactions_sync(id: Id) -> HashMap<char, usize> {
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() {
if let Relationship::Reaction(reaction) = relationship {
if let Some(ch) = reaction.chars().next() {

View File

@ -8,7 +8,6 @@ mod comms;
mod date_ago;
mod db;
mod error;
mod feed_event;
mod globals;
mod overlord;
mod process;

View File

@ -1,5 +1,5 @@
use super::GossipUi;
use crate::globals::Globals;
use crate::globals::{Globals, GLOBALS};
use eframe::egui;
use egui::{Align, Color32, Context, Layout, RichText, ScrollArea, TextStyle, Ui, Vec2};
use nostr_types::{EventKind, Id, PublicKey};
@ -46,31 +46,21 @@ fn render_post(
id: Id,
indent: usize,
) {
let maybe_fevent = crate::globals::GLOBALS
.feed_events
.blocking_lock()
.get(&id)
.cloned();
if maybe_fevent.is_none() {
let maybe_event = GLOBALS.events.blocking_lock().get(&id).cloned();
if maybe_event.is_none() {
return;
}
let fevent = maybe_fevent.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();
let event = maybe_event.unwrap();
// Only render TextNote events
if event.kind != EventKind::TextNote {
return;
}
let maybe_person = crate::globals::GLOBALS
.people
.blocking_lock()
.get(&event.pubkey)
.cloned();
let maybe_person = GLOBALS.people.blocking_lock().get(&event.pubkey).cloned();
let reactions = Globals::get_reactions_sync(event.id);
let replies = Globals::get_replies_sync(event.id);
// Person Things we can render:
// pubkey
@ -149,19 +139,25 @@ fn render_post(
// Second row
ui.horizontal(|ui| {
if fevent.reactions.upvotes > 0 {
for (ch, count) in reactions.iter() {
if *ch == '+' {
ui.label(
RichText::new(&format!("+{}", fevent.reactions.upvotes))
RichText::new(&format!("{} {}", ch, count))
.text_style(TextStyle::Name("Bold".into()))
.color(Color32::DARK_GREEN),
);
}
if fevent.reactions.downvotes > 0 {
} else if *ch == '-' {
ui.label(
RichText::new(&format!("-{}", fevent.reactions.downvotes))
RichText::new(&format!("{} {}", ch, count))
.text_style(TextStyle::Name("Bold".into()))
.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();
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);
}
}