From e2dd1b32980b9d75063f658d48f8366aca9909ca Mon Sep 17 00:00:00 2001 From: kernelkind Date: Wed, 25 Sep 2024 22:59:08 -0400 Subject: [PATCH] remote sub new timeline Signed-off-by: kernelkind --- src/app.rs | 124 ++++++++++++++++++++++++++++++++----------- src/nav.rs | 8 ++- src/ui/add_column.rs | 27 +++++----- 3 files changed, 112 insertions(+), 47 deletions(-) diff --git a/src/app.rs b/src/app.rs index 5e7b0af..c14b677 100644 --- a/src/app.rs +++ b/src/app.rs @@ -6,8 +6,7 @@ use crate::{ column::{Column, Columns}, draft::Drafts, error::{Error, FilterError}, - filter, - filter::FilterState, + filter::{self, FilterState}, frame_history::FrameHistory, imgcache::ImageCache, key_storage::KeyStorageType, @@ -17,7 +16,7 @@ use crate::{ route::Route, subscriptions::{SubKind, Subscriptions}, thread::Threads, - timeline::{Timeline, TimelineKind, ViewFilter}, + timeline::{Timeline, TimelineId, TimelineKind, ViewFilter}, ui::{self, DesktopSidePanel}, unknowns::UnknownIds, view_state::ViewState, @@ -41,6 +40,7 @@ use tracing::{debug, error, info, trace, warn}; pub enum DamusState { Initializing, Initialized, + NewTimelineSub(TimelineId), } /// We derive Deserialize/Serialize so we can persist app state on shutdown. @@ -394,44 +394,100 @@ fn setup_initial_nostrdb_subs( columns: &mut Columns, ) -> Result<()> { for timeline in columns.timelines_mut() { - match &timeline.filter { - FilterState::Ready(filters) => { - { setup_initial_timeline(ndb, timeline, note_cache, &filters.clone()) }? - } + setup_nostrdb_sub(ndb, note_cache, timeline)? + } - FilterState::Broken(err) => { - error!("FetchingRemote state broken in setup_initial_nostr_subs: {err}") - } - FilterState::FetchingRemote(_) => { - error!("FetchingRemote state in setup_initial_nostr_subs") - } - FilterState::GotRemote(_) => { - error!("GotRemote state in setup_initial_nostr_subs") - } - FilterState::NeedsRemote(_filters) => { - // can't do anything yet, we defer to first connect to send - // remote filters - } + Ok(()) +} + +fn setup_nostrdb_sub(ndb: &Ndb, note_cache: &mut NoteCache, timeline: &mut Timeline) -> Result<()> { + match &timeline.filter { + FilterState::Ready(filters) => { + { setup_initial_timeline(ndb, timeline, note_cache, &filters.clone()) }? + } + + FilterState::Broken(err) => { + error!("FetchingRemote state broken in setup_initial_nostr_subs: {err}") + } + FilterState::FetchingRemote(_) => { + error!("FetchingRemote state in setup_initial_nostr_subs") + } + FilterState::GotRemote(_) => { + error!("GotRemote state in setup_initial_nostr_subs") + } + FilterState::NeedsRemote(_filters) => { + // can't do anything yet, we defer to first connect to send + // remote filters } } Ok(()) } -fn update_damus(damus: &mut Damus, ctx: &egui::Context) { - if damus.state == DamusState::Initializing { - #[cfg(feature = "profiling")] - setup_profiling(); - - damus.state = DamusState::Initialized; - // this lets our eose handler know to close unknownids right away - damus - .subscriptions() - .insert("unknownids".to_string(), SubKind::OneShot); - setup_initial_nostrdb_subs(&damus.ndb, &mut damus.note_cache, &mut damus.columns) - .expect("home subscription failed"); +fn setup_new_nostrdb_sub( + ndb: &Ndb, + note_cache: &mut NoteCache, + columns: &mut Columns, + new_timeline_id: TimelineId, +) -> Result<()> { + if let Some(timeline) = columns.find_timeline_mut(new_timeline_id) { + info!("Setting up timeline sub for {}", timeline.id); + if let FilterState::Ready(filters) = &timeline.filter { + for filter in filters { + info!("Setting up filter {:?}", filter.json()); + } + } + setup_nostrdb_sub(ndb, note_cache, timeline)? } + Ok(()) +} + +fn update_damus(damus: &mut Damus, ctx: &egui::Context) { + match damus.state { + DamusState::Initializing => { + #[cfg(feature = "profiling")] + setup_profiling(); + + damus.state = DamusState::Initialized; + // this lets our eose handler know to close unknownids right away + damus + .subscriptions() + .insert("unknownids".to_string(), SubKind::OneShot); + setup_initial_nostrdb_subs(&damus.ndb, &mut damus.note_cache, &mut damus.columns) + .expect("home subscription failed"); + } + + DamusState::NewTimelineSub(new_timeline_id) => { + info!("adding new timeline {}", new_timeline_id); + setup_new_nostrdb_sub( + &damus.ndb, + &mut damus.note_cache, + &mut damus.columns, + new_timeline_id, + ) + .expect("new timeline subscription failed"); + + if let Some(filter) = { + let timeline = damus + .columns + .find_timeline(new_timeline_id) + .expect("timeline"); + match &timeline.filter { + FilterState::Ready(filters) => Some(filters.clone()), + _ => None, + } + } { + let subid = Uuid::new_v4().to_string(); + damus.pool.subscribe(subid, filter); + + damus.state = DamusState::Initialized; + } + } + + DamusState::Initialized => (), + }; + if let Err(err) = try_process_event(damus, ctx) { error!("error processing event: {}", err); } @@ -714,6 +770,10 @@ impl Damus { } } + pub fn add_new_timeline(&mut self, timeline_id: TimelineId) { + self.state = DamusState::NewTimelineSub(timeline_id); + } + pub fn mock>(data_path: P) -> Self { let mut columns = Columns::new(); let filter = Filter::from_json(include_str!("../queries/global.json")).unwrap(); diff --git a/src/nav.rs b/src/nav.rs index 26409e9..57e9404 100644 --- a/src/nav.rs +++ b/src/nav.rs @@ -5,7 +5,10 @@ use crate::{ thread::thread_unsubscribe, timeline::route::{render_timeline_route, AfterRouteExecution, TimelineRoute}, ui::{ - self, add_column::{AddColumnResponse, AddColumnView}, note::PostAction, RelayView, View + self, + add_column::{AddColumnResponse, AddColumnView}, + note::PostAction, + RelayView, View, }, Damus, }; @@ -75,7 +78,7 @@ pub fn render_nav(col: usize, app: &mut Damus, ui: &mut egui::Ui) { None } - Route::AddColumn => AddColumnView::new(app.accounts.get_selected_account()) + Route::AddColumn => AddColumnView::new(&app.ndb, app.accounts.get_selected_account()) .ui(ui) .map(AfterRouteExecution::AddColumn), }); @@ -96,6 +99,7 @@ pub fn render_nav(col: usize, app: &mut Damus, ui: &mut egui::Ui) { AfterRouteExecution::AddColumn(add_column_resp) => { match add_column_resp { AddColumnResponse::Timeline(timeline) => { + app.add_new_timeline(timeline.id); app.columns_mut().add_timeline(timeline); } }; diff --git a/src/ui/add_column.rs b/src/ui/add_column.rs index a174f95..dcfd9c4 100644 --- a/src/ui/add_column.rs +++ b/src/ui/add_column.rs @@ -1,40 +1,41 @@ use egui::{RichText, Ui}; -use nostrdb::FilterBuilder; +use nostrdb::Ndb; -use crate::{app_style::NotedeckTextStyle, timeline::Timeline, user_account::UserAccount}; +use crate::{ + app_style::NotedeckTextStyle, + timeline::{Timeline, TimelineKind}, + user_account::UserAccount, +}; pub enum AddColumnResponse { Timeline(Timeline), } pub struct AddColumnView<'a> { + ndb: &'a Ndb, cur_account: Option<&'a UserAccount>, } impl<'a> AddColumnView<'a> { - pub fn new(cur_account: Option<&'a UserAccount>) -> Self { - Self { cur_account } + pub fn new(ndb: &'a Ndb, cur_account: Option<&'a UserAccount>) -> Self { + Self { ndb, cur_account } } pub fn ui(&mut self, ui: &mut Ui) -> Option { ui.label(RichText::new("Add column").text_style(NotedeckTextStyle::Heading.text_style())); if ui.button("create global timeline").clicked() { - Some(AddColumnResponse::Timeline(create_global_timeline())) + Some(AddColumnResponse::Timeline( + TimelineKind::Universe + .into_timeline(self.ndb, None) + .expect("universe timeline"), + )) } else { None } } } -fn create_global_timeline() -> Timeline { - let filter = FilterBuilder::new().kinds([1]).build(); - Timeline::new( - crate::timeline::TimelineKind::Generic, - crate::filter::FilterState::Ready(vec![filter]), - ) -} - // struct ColumnOption { // title: &'static str, // description: &'static str,