mirror of
https://github.com/mikedilger/gossip.git
synced 2024-09-19 11:43:43 +00:00
Replies feed
This commit is contained in:
parent
2335013a07
commit
c7398a50a2
49
src/feed.rs
49
src/feed.rs
@ -3,11 +3,13 @@ use crate::globals::GLOBALS;
|
|||||||
use nostr_types::PublicKeyHex;
|
use nostr_types::PublicKeyHex;
|
||||||
use nostr_types::{Event, EventKind, Id};
|
use nostr_types::{Event, EventKind, Id};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum FeedKind {
|
pub enum FeedKind {
|
||||||
General,
|
General,
|
||||||
|
Replies,
|
||||||
Thread(Id),
|
Thread(Id),
|
||||||
Person(PublicKeyHex),
|
Person(PublicKeyHex),
|
||||||
}
|
}
|
||||||
@ -16,6 +18,7 @@ pub struct Feed {
|
|||||||
current_feed_kind: RwLock<FeedKind>,
|
current_feed_kind: RwLock<FeedKind>,
|
||||||
|
|
||||||
general_feed: RwLock<Vec<Id>>,
|
general_feed: RwLock<Vec<Id>>,
|
||||||
|
replies_feed: RwLock<Vec<Id>>,
|
||||||
|
|
||||||
// We only recompute the feed at specified intervals
|
// We only recompute the feed at specified intervals
|
||||||
interval_ms: RwLock<u32>,
|
interval_ms: RwLock<u32>,
|
||||||
@ -31,6 +34,7 @@ impl Feed {
|
|||||||
Feed {
|
Feed {
|
||||||
current_feed_kind: RwLock::new(FeedKind::General),
|
current_feed_kind: RwLock::new(FeedKind::General),
|
||||||
general_feed: RwLock::new(Vec::new()),
|
general_feed: RwLock::new(Vec::new()),
|
||||||
|
replies_feed: RwLock::new(Vec::new()),
|
||||||
interval_ms: RwLock::new(1000), // Every second, until we load from settings
|
interval_ms: RwLock::new(1000), // Every second, until we load from settings
|
||||||
last_computed: RwLock::new(Instant::now()),
|
last_computed: RwLock::new(Instant::now()),
|
||||||
my_event_ids: RwLock::new(Vec::new()),
|
my_event_ids: RwLock::new(Vec::new()),
|
||||||
@ -45,6 +49,10 @@ impl Feed {
|
|||||||
*self.current_feed_kind.write() = FeedKind::General;
|
*self.current_feed_kind.write() = FeedKind::General;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_feed_to_replies(&self) {
|
||||||
|
*self.current_feed_kind.write() = FeedKind::Replies;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_feed_to_thread(&self, id: Id) {
|
pub fn set_feed_to_thread(&self, id: Id) {
|
||||||
let _ = GLOBALS.to_minions.send(BusMessage {
|
let _ = GLOBALS.to_minions.send(BusMessage {
|
||||||
target: "all".to_string(),
|
target: "all".to_string(),
|
||||||
@ -78,6 +86,17 @@ impl Feed {
|
|||||||
self.general_feed.read().clone()
|
self.general_feed.read().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_replies(&self) -> Vec<Id> {
|
||||||
|
let now = Instant::now();
|
||||||
|
if *self.last_computed.read() + Duration::from_millis(*self.interval_ms.read() as u64) < now
|
||||||
|
{
|
||||||
|
self.recompute();
|
||||||
|
*self.last_computed.write() = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.replies_feed.read().clone()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_thread_parent(&self, id: Id) -> Id {
|
pub fn get_thread_parent(&self, id: Id) -> Id {
|
||||||
let mut event = match GLOBALS.events.blocking_read().get(&id).cloned() {
|
let mut event = match GLOBALS.events.blocking_read().get(&id).cloned() {
|
||||||
None => return id,
|
None => return id,
|
||||||
@ -173,17 +192,33 @@ impl Feed {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Filter further for the feed
|
// Filter further for the general feed
|
||||||
let mut events: Vec<Event> = events
|
let mut fevents: Vec<Event> = events
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|e| pubkeys.contains(&e.pubkey.into())) // something we follow
|
|
||||||
.filter(|e| !GLOBALS.dismissed.blocking_read().contains(&e.id))
|
.filter(|e| !GLOBALS.dismissed.blocking_read().contains(&e.id))
|
||||||
|
.filter(|e| pubkeys.contains(&e.pubkey.into())) // something we follow
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
|
fevents.sort_by(|a, b| b.created_at.cmp(&a.created_at));
|
||||||
|
*self.general_feed.write() = fevents.iter().map(|e| e.id).collect();
|
||||||
|
|
||||||
// In time order
|
// Filter differently for the replies feed
|
||||||
events.sort_by(|a, b| b.created_at.cmp(&a.created_at));
|
let my_events: HashSet<Id> = self.my_event_ids.read().iter().copied().collect();
|
||||||
|
let mut revents: Vec<Event> = events
|
||||||
*self.general_feed.write() = events.iter().map(|e| e.id).collect();
|
.iter()
|
||||||
|
.filter(|e| !GLOBALS.dismissed.blocking_read().contains(&e.id))
|
||||||
|
.filter(|e| {
|
||||||
|
// FIXME: maybe try replies_to_ancestors to go deeper
|
||||||
|
if let Some((id, _)) = e.replies_to() {
|
||||||
|
if my_events.contains(&id) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
})
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
revents.sort_by(|a, b| b.created_at.cmp(&a.created_at));
|
||||||
|
*self.replies_feed.write() = revents.iter().map(|e| e.id).collect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,7 +264,7 @@ impl Minion {
|
|||||||
// Any mentions of me
|
// Any mentions of me
|
||||||
filters.push(Filter {
|
filters.push(Filter {
|
||||||
p: vec![pubkey.into()],
|
p: vec![pubkey.into()],
|
||||||
since: Some(Unixtime::now().unwrap() - Duration::from_secs(feed_chunk)),
|
since: Some(Unixtime::now().unwrap() - Duration::from_secs(feed_chunk * 10)), // further back
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, frame: &mut eframe::Fram
|
|||||||
let mut feed_kind = GLOBALS.feed.get_feed_kind();
|
let mut feed_kind = GLOBALS.feed.get_feed_kind();
|
||||||
app.page = match feed_kind {
|
app.page = match feed_kind {
|
||||||
FeedKind::General => Page::FeedGeneral,
|
FeedKind::General => Page::FeedGeneral,
|
||||||
|
FeedKind::Replies => Page::FeedReplies,
|
||||||
FeedKind::Thread(_) => Page::FeedThread,
|
FeedKind::Thread(_) => Page::FeedThread,
|
||||||
FeedKind::Person(_) => Page::FeedPerson,
|
FeedKind::Person(_) => Page::FeedPerson,
|
||||||
};
|
};
|
||||||
@ -39,13 +40,24 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, frame: &mut eframe::Fram
|
|||||||
feed_kind = FeedKind::General;
|
feed_kind = FeedKind::General;
|
||||||
}
|
}
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
if ui
|
||||||
|
.add(SelectableLabel::new(
|
||||||
|
app.page == Page::FeedReplies,
|
||||||
|
"Replies",
|
||||||
|
))
|
||||||
|
.clicked()
|
||||||
|
{
|
||||||
|
app.page = Page::FeedReplies;
|
||||||
|
GLOBALS.feed.set_feed_to_replies();
|
||||||
|
feed_kind = FeedKind::Replies;
|
||||||
|
}
|
||||||
if matches!(feed_kind, FeedKind::Thread(..)) {
|
if matches!(feed_kind, FeedKind::Thread(..)) {
|
||||||
ui.selectable_value(&mut app.page, Page::FeedThread, "Thread");
|
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
ui.selectable_value(&mut app.page, Page::FeedThread, "Thread");
|
||||||
}
|
}
|
||||||
if matches!(feed_kind, FeedKind::Person(..)) {
|
if matches!(feed_kind, FeedKind::Person(..)) {
|
||||||
ui.selectable_value(&mut app.page, Page::FeedPerson, "Person");
|
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
ui.selectable_value(&mut app.page, Page::FeedPerson, "Person");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ui.separator();
|
ui.separator();
|
||||||
@ -103,7 +115,7 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, frame: &mut eframe::Fram
|
|||||||
if ui.link("setup your identity").clicked() {
|
if ui.link("setup your identity").clicked() {
|
||||||
app.page = Page::You;
|
app.page = Page::You;
|
||||||
}
|
}
|
||||||
ui.label(" to post.");
|
ui.label(" to post or see your replies.");
|
||||||
});
|
});
|
||||||
} else if !GLOBALS.relays.blocking_read().iter().any(|(_, r)| r.post) {
|
} else if !GLOBALS.relays.blocking_read().iter().any(|(_, r)| r.post) {
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
@ -177,6 +189,10 @@ pub(super) fn update(app: &mut GossipUi, ctx: &Context, frame: &mut eframe::Fram
|
|||||||
let feed = GLOBALS.feed.get_general();
|
let feed = GLOBALS.feed.get_general();
|
||||||
render_a_feed(app, ctx, frame, ui, feed, false);
|
render_a_feed(app, ctx, frame, ui, feed, false);
|
||||||
}
|
}
|
||||||
|
FeedKind::Replies => {
|
||||||
|
let feed = GLOBALS.feed.get_replies();
|
||||||
|
render_a_feed(app, ctx, frame, ui, feed, true);
|
||||||
|
}
|
||||||
FeedKind::Thread(id) => {
|
FeedKind::Thread(id) => {
|
||||||
let parent = GLOBALS.feed.get_thread_parent(id);
|
let parent = GLOBALS.feed.get_thread_parent(id);
|
||||||
render_a_feed(app, ctx, frame, ui, vec![parent], true);
|
render_a_feed(app, ctx, frame, ui, vec![parent], true);
|
||||||
|
@ -55,6 +55,7 @@ pub fn run() -> Result<(), Error> {
|
|||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
enum Page {
|
enum Page {
|
||||||
FeedGeneral,
|
FeedGeneral,
|
||||||
|
FeedReplies,
|
||||||
FeedThread,
|
FeedThread,
|
||||||
FeedPerson,
|
FeedPerson,
|
||||||
PeopleList,
|
PeopleList,
|
||||||
@ -189,6 +190,7 @@ impl eframe::App for GossipUi {
|
|||||||
if ui
|
if ui
|
||||||
.add(SelectableLabel::new(
|
.add(SelectableLabel::new(
|
||||||
self.page == Page::FeedGeneral
|
self.page == Page::FeedGeneral
|
||||||
|
|| self.page == Page::FeedReplies
|
||||||
|| self.page == Page::FeedThread
|
|| self.page == Page::FeedThread
|
||||||
|| self.page == Page::FeedPerson,
|
|| self.page == Page::FeedPerson,
|
||||||
"Feed",
|
"Feed",
|
||||||
@ -261,7 +263,7 @@ impl eframe::App for GossipUi {
|
|||||||
});
|
});
|
||||||
|
|
||||||
egui::CentralPanel::default().show(ctx, |ui| match self.page {
|
egui::CentralPanel::default().show(ctx, |ui| match self.page {
|
||||||
Page::FeedGeneral | Page::FeedThread | Page::FeedPerson => {
|
Page::FeedGeneral | Page::FeedReplies | Page::FeedThread | Page::FeedPerson => {
|
||||||
feed::update(self, ctx, frame, ui)
|
feed::update(self, ctx, frame, ui)
|
||||||
}
|
}
|
||||||
Page::PeopleList | Page::PeopleFollow | Page::Person => {
|
Page::PeopleList | Page::PeopleFollow | Page::Person => {
|
||||||
|
Loading…
Reference in New Issue
Block a user