notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

commit 99405378972e9e3c6f42cb9f3278cbe301650118
parent 497c102af123e7f7c2230d42758a46dd99fdf2ff
Author: kernelkind <kernelkind@gmail.com>
Date:   Mon,  7 Jul 2025 17:53:13 -0400

Unify sub for contacts in accounts & timeline

Signed-off-by: kernelkind <kernelkind@gmail.com>

Diffstat:
Mcrates/notedeck_columns/src/app.rs | 61++++++++++++++++++++++---------------------------------------
Mcrates/notedeck_columns/src/nav.rs | 16+++++++++++++++-
Mcrates/notedeck_columns/src/timeline/mod.rs | 51+++++++++++++++++++++++----------------------------
Mcrates/notedeck_columns/src/ui/add_column.rs | 2++
4 files changed, 62 insertions(+), 68 deletions(-)

diff --git a/crates/notedeck_columns/src/app.rs b/crates/notedeck_columns/src/app.rs @@ -8,14 +8,16 @@ use crate::{ storage, subscriptions::{SubKind, Subscriptions}, support::Support, - timeline::{self, thread::Threads, TimelineCache}, + timeline::{ + self, fetch_contact_list, kind::ListKind, thread::Threads, TimelineCache, TimelineKind, + }, ui::{self, DesktopSidePanel}, view_state::ViewState, Result, }; use notedeck::{ - ui::is_narrow, Accounts, AppAction, AppContext, DataPath, DataPathType, FilterState, UnknownIds, + ui::is_narrow, Accounts, AppAction, AppContext, DataPath, DataPathType, UnknownIds, }; use notedeck_ui::{jobs::JobsCache, NoteOptions}; @@ -116,13 +118,21 @@ fn try_process_event( .accounts .send_initial_filters(app_ctx.pool, &ev.relay); + let data = app_ctx.accounts.get_subs(); + damus.subscriptions.subs.insert( + data.contacts.remote.clone(), + SubKind::FetchingContactList(TimelineKind::List(ListKind::Contact( + *app_ctx.accounts.selected_account_pubkey(), + ))), + ); + timeline::send_initial_timeline_filters( - app_ctx.ndb, damus.since_optimize, &mut damus.timeline_cache, &mut damus.subscriptions, app_ctx.pool, &ev.relay, + app_ctx.accounts, ); } // TODO: handle reconnects @@ -248,44 +258,11 @@ fn handle_eose( } SubKind::FetchingContactList(timeline_uid) => { - let timeline = if let Some(tl) = timeline_cache.timelines.get_mut(timeline_uid) { - tl - } else { - error!( - "timeline uid:{} not found for FetchingContactList", - timeline_uid - ); + let Some(timeline) = timeline_cache.timelines.get_mut(timeline_uid) else { return Ok(()); }; - let filter_state = timeline.filter.get_mut(relay_url); - - // If this request was fetching a contact list, our filter - // state should be "FetchingRemote". We look at the local - // subscription for that filter state and get the subscription id - let local_sub = if let FilterState::FetchingRemote(unisub) = filter_state { - unisub.local - } else { - // TODO: we could have multiple contact list results, we need - // to check to see if this one is newer and use that instead - warn!( - "Expected timeline to have FetchingRemote state but was {:?}", - timeline.filter - ); - return Ok(()); - }; - - info!( - "got contact list from {}, updating filter_state to got_remote", - relay_url - ); - - // We take the subscription id and pass it to the new state of - // "GotRemote". This will let future frames know that it can try - // to look for the contact list in nostrdb. - timeline - .filter - .set_relay_state(relay_url.to_string(), FilterState::got_remote(local_sub)); + fetch_contact_list(relay_url, timeline, ctx.accounts); } } @@ -704,7 +681,13 @@ fn timelines_view( let mut save_cols = false; if let Some(action) = side_panel_action { save_cols = save_cols - || action.process(&mut app.timeline_cache, &mut app.decks_cache, ctx, ui.ctx()); + || action.process( + &mut app.timeline_cache, + &mut app.decks_cache, + &mut app.subscriptions, + ctx, + ui.ctx(), + ); } let mut app_action: Option<AppAction> = None; diff --git a/crates/notedeck_columns/src/nav.rs b/crates/notedeck_columns/src/nav.rs @@ -7,9 +7,11 @@ use crate::{ profile::{ProfileAction, SaveProfileChanges}, profile_state::ProfileState, route::{Route, Router, SingletonRouter}, + subscriptions::{SubKind, Subscriptions}, timeline::{ + kind::ListKind, route::{render_thread_route, render_timeline_route}, - TimelineCache, + TimelineCache, TimelineKind, }, ui::{ self, @@ -72,6 +74,7 @@ impl SwitchingAction { &self, timeline_cache: &mut TimelineCache, decks_cache: &mut DecksCache, + subs: &mut Subscriptions, ctx: &mut AppContext<'_>, ui_ctx: &egui::Context, ) -> bool { @@ -86,6 +89,16 @@ impl SwitchingAction { ctx.pool, ui_ctx, ); + + let new_subs = ctx.accounts.get_subs(); + + subs.subs.insert( + new_subs.contacts.remote.clone(), + SubKind::FetchingContactList(TimelineKind::List(ListKind::Contact( + *ctx.accounts.selected_account_pubkey(), + ))), + ); + // pop nav after switch get_active_columns_mut(ctx.accounts, decks_cache) .column_mut(switch_action.source_column) @@ -380,6 +393,7 @@ fn process_render_nav_action( if switching_action.process( &mut app.timeline_cache, &mut app.decks_cache, + &mut app.subscriptions, ctx, ui.ctx(), ) { diff --git a/crates/notedeck_columns/src/timeline/mod.rs b/crates/notedeck_columns/src/timeline/mod.rs @@ -7,7 +7,8 @@ use crate::{ }; use notedeck::{ - filter, CachedNote, FilterError, FilterState, FilterStates, NoteCache, NoteRef, UnknownIds, + filter, Accounts, CachedNote, FilterError, FilterState, FilterStates, NoteCache, NoteRef, + UnknownIds, }; use egui_virtual_list::VirtualList; @@ -474,6 +475,7 @@ pub fn setup_new_timeline( pool: &mut RelayPool, note_cache: &mut NoteCache, since_optimize: bool, + accounts: &Accounts, ) { // if we're ready, setup local subs if is_timeline_ready(ndb, pool, note_cache, timeline) { @@ -483,7 +485,7 @@ pub fn setup_new_timeline( } for relay in &mut pool.relays { - send_initial_timeline_filter(ndb, since_optimize, subs, relay, timeline); + send_initial_timeline_filter(since_optimize, subs, relay, timeline, accounts); } } @@ -492,29 +494,29 @@ pub fn setup_new_timeline( /// situations where you are adding a new timeline, use /// setup_new_timeline. pub fn send_initial_timeline_filters( - ndb: &Ndb, since_optimize: bool, timeline_cache: &mut TimelineCache, subs: &mut Subscriptions, pool: &mut RelayPool, relay_id: &str, + accounts: &Accounts, ) -> Option<()> { info!("Sending initial filters to {}", relay_id); let relay = &mut pool.relays.iter_mut().find(|r| r.url() == relay_id)?; for (_kind, timeline) in timeline_cache.timelines.iter_mut() { - send_initial_timeline_filter(ndb, since_optimize, subs, relay, timeline); + send_initial_timeline_filter(since_optimize, subs, relay, timeline, accounts); } Some(()) } pub fn send_initial_timeline_filter( - ndb: &Ndb, can_since_optimize: bool, subs: &mut Subscriptions, relay: &mut PoolRelay, timeline: &mut Timeline, + accounts: &Accounts, ) { let filter_state = timeline.filter.get_mut(relay.url()); @@ -572,34 +574,27 @@ pub fn send_initial_timeline_filter( } // we need some data first - FilterState::NeedsRemote(filter) => { - fetch_contact_list(filter.to_owned(), ndb, subs, relay, timeline) - } + FilterState::NeedsRemote(_filter) => fetch_contact_list(relay.url(), timeline, accounts), } } -fn fetch_contact_list( - filter: Vec<Filter>, - ndb: &Ndb, - subs: &mut Subscriptions, - relay: &mut PoolRelay, - timeline: &mut Timeline, -) { - let sub_kind = SubKind::FetchingContactList(timeline.kind.clone()); - let sub_id = subscriptions::new_sub_id(); - let local_sub = ndb.subscribe(&filter).expect("sub"); - - timeline.filter.set_relay_state( - relay.url().to_string(), - FilterState::fetching_remote(sub_id.clone(), local_sub), - ); +pub fn fetch_contact_list(relay_url: &str, timeline: &mut Timeline, accounts: &Accounts) { + let account_subs = accounts.get_subs(); + let local = account_subs.contacts.local; - subs.subs.insert(sub_id.clone(), sub_kind); + let filter_state = match accounts.get_selected_account().data.contacts.get_state() { + notedeck::ContactState::Unreceived => { + FilterState::fetching_remote(account_subs.contacts.remote.clone(), local) + } + notedeck::ContactState::Received { + contacts: _, + note_key: _, + } => FilterState::GotRemote(local), + }; - info!("fetching contact list from {}", relay.url()); - if let Err(err) = relay.subscribe(sub_id, filter) { - error!("error subscribing: {err}"); - } + timeline + .filter + .set_relay_state(relay_url.to_owned(), filter_state); } fn setup_initial_timeline( diff --git a/crates/notedeck_columns/src/ui/add_column.rs b/crates/notedeck_columns/src/ui/add_column.rs @@ -626,6 +626,7 @@ pub fn render_add_column_routes( ctx.pool, ctx.note_cache, app.since_optimize, + ctx.accounts, ); app.columns_mut(ctx.accounts) @@ -667,6 +668,7 @@ pub fn render_add_column_routes( ctx.pool, ctx.note_cache, app.since_optimize, + ctx.accounts, ); app.columns_mut(ctx.accounts)