remote sub new timeline

Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
kernelkind
2024-09-25 22:59:08 -04:00
parent 731f206424
commit e2dd1b3298
3 changed files with 112 additions and 47 deletions

View File

@@ -6,8 +6,7 @@ use crate::{
column::{Column, Columns}, column::{Column, Columns},
draft::Drafts, draft::Drafts,
error::{Error, FilterError}, error::{Error, FilterError},
filter, filter::{self, FilterState},
filter::FilterState,
frame_history::FrameHistory, frame_history::FrameHistory,
imgcache::ImageCache, imgcache::ImageCache,
key_storage::KeyStorageType, key_storage::KeyStorageType,
@@ -17,7 +16,7 @@ use crate::{
route::Route, route::Route,
subscriptions::{SubKind, Subscriptions}, subscriptions::{SubKind, Subscriptions},
thread::Threads, thread::Threads,
timeline::{Timeline, TimelineKind, ViewFilter}, timeline::{Timeline, TimelineId, TimelineKind, ViewFilter},
ui::{self, DesktopSidePanel}, ui::{self, DesktopSidePanel},
unknowns::UnknownIds, unknowns::UnknownIds,
view_state::ViewState, view_state::ViewState,
@@ -41,6 +40,7 @@ use tracing::{debug, error, info, trace, warn};
pub enum DamusState { pub enum DamusState {
Initializing, Initializing,
Initialized, Initialized,
NewTimelineSub(TimelineId),
} }
/// We derive Deserialize/Serialize so we can persist app state on shutdown. /// We derive Deserialize/Serialize so we can persist app state on shutdown.
@@ -394,44 +394,100 @@ fn setup_initial_nostrdb_subs(
columns: &mut Columns, columns: &mut Columns,
) -> Result<()> { ) -> Result<()> {
for timeline in columns.timelines_mut() { for timeline in columns.timelines_mut() {
match &timeline.filter { setup_nostrdb_sub(ndb, note_cache, timeline)?
FilterState::Ready(filters) => { }
{ setup_initial_timeline(ndb, timeline, note_cache, &filters.clone()) }?
}
FilterState::Broken(err) => { Ok(())
error!("FetchingRemote state broken in setup_initial_nostr_subs: {err}") }
}
FilterState::FetchingRemote(_) => { fn setup_nostrdb_sub(ndb: &Ndb, note_cache: &mut NoteCache, timeline: &mut Timeline) -> Result<()> {
error!("FetchingRemote state in setup_initial_nostr_subs") match &timeline.filter {
} FilterState::Ready(filters) => {
FilterState::GotRemote(_) => { { setup_initial_timeline(ndb, timeline, note_cache, &filters.clone()) }?
error!("GotRemote state in setup_initial_nostr_subs") }
}
FilterState::NeedsRemote(_filters) => { FilterState::Broken(err) => {
// can't do anything yet, we defer to first connect to send error!("FetchingRemote state broken in setup_initial_nostr_subs: {err}")
// remote filters }
} 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(()) Ok(())
} }
fn update_damus(damus: &mut Damus, ctx: &egui::Context) { fn setup_new_nostrdb_sub(
if damus.state == DamusState::Initializing { ndb: &Ndb,
#[cfg(feature = "profiling")] note_cache: &mut NoteCache,
setup_profiling(); columns: &mut Columns,
new_timeline_id: TimelineId,
damus.state = DamusState::Initialized; ) -> Result<()> {
// this lets our eose handler know to close unknownids right away if let Some(timeline) = columns.find_timeline_mut(new_timeline_id) {
damus info!("Setting up timeline sub for {}", timeline.id);
.subscriptions() if let FilterState::Ready(filters) = &timeline.filter {
.insert("unknownids".to_string(), SubKind::OneShot); for filter in filters {
setup_initial_nostrdb_subs(&damus.ndb, &mut damus.note_cache, &mut damus.columns) info!("Setting up filter {:?}", filter.json());
.expect("home subscription failed"); }
}
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) { if let Err(err) = try_process_event(damus, ctx) {
error!("error processing event: {}", err); 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<P: AsRef<Path>>(data_path: P) -> Self { pub fn mock<P: AsRef<Path>>(data_path: P) -> Self {
let mut columns = Columns::new(); let mut columns = Columns::new();
let filter = Filter::from_json(include_str!("../queries/global.json")).unwrap(); let filter = Filter::from_json(include_str!("../queries/global.json")).unwrap();

View File

@@ -5,7 +5,10 @@ use crate::{
thread::thread_unsubscribe, thread::thread_unsubscribe,
timeline::route::{render_timeline_route, AfterRouteExecution, TimelineRoute}, timeline::route::{render_timeline_route, AfterRouteExecution, TimelineRoute},
ui::{ ui::{
self, add_column::{AddColumnResponse, AddColumnView}, note::PostAction, RelayView, View self,
add_column::{AddColumnResponse, AddColumnView},
note::PostAction,
RelayView, View,
}, },
Damus, Damus,
}; };
@@ -75,7 +78,7 @@ pub fn render_nav(col: usize, app: &mut Damus, ui: &mut egui::Ui) {
None None
} }
Route::AddColumn => AddColumnView::new(app.accounts.get_selected_account()) Route::AddColumn => AddColumnView::new(&app.ndb, app.accounts.get_selected_account())
.ui(ui) .ui(ui)
.map(AfterRouteExecution::AddColumn), .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) => { AfterRouteExecution::AddColumn(add_column_resp) => {
match add_column_resp { match add_column_resp {
AddColumnResponse::Timeline(timeline) => { AddColumnResponse::Timeline(timeline) => {
app.add_new_timeline(timeline.id);
app.columns_mut().add_timeline(timeline); app.columns_mut().add_timeline(timeline);
} }
}; };

View File

@@ -1,40 +1,41 @@
use egui::{RichText, Ui}; 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 { pub enum AddColumnResponse {
Timeline(Timeline), Timeline(Timeline),
} }
pub struct AddColumnView<'a> { pub struct AddColumnView<'a> {
ndb: &'a Ndb,
cur_account: Option<&'a UserAccount>, cur_account: Option<&'a UserAccount>,
} }
impl<'a> AddColumnView<'a> { impl<'a> AddColumnView<'a> {
pub fn new(cur_account: Option<&'a UserAccount>) -> Self { pub fn new(ndb: &'a Ndb, cur_account: Option<&'a UserAccount>) -> Self {
Self { cur_account } Self { ndb, cur_account }
} }
pub fn ui(&mut self, ui: &mut Ui) -> Option<AddColumnResponse> { pub fn ui(&mut self, ui: &mut Ui) -> Option<AddColumnResponse> {
ui.label(RichText::new("Add column").text_style(NotedeckTextStyle::Heading.text_style())); ui.label(RichText::new("Add column").text_style(NotedeckTextStyle::Heading.text_style()));
if ui.button("create global timeline").clicked() { 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 { } else {
None 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 { // struct ColumnOption {
// title: &'static str, // title: &'static str,
// description: &'static str, // description: &'static str,