commit 8c49e6e5f60dab531301d6c493996e1337941246
parent 0d22debb05bc46b21106a3cd0d1df22735bea411
Author: William Casarin <jb55@jb55.com>
Date: Fri, 7 Feb 2025 11:07:14 -0800
Merge explicitly activate and deactivate account relay/muted list #678
Ken Sedgwick (4):
drive-by compiler warning fixes
improve debug logging, comments, and variable names for clarity
explicitly activate and deactivate account relay list subs
explicitly activate and deactivate account muted list subs
Diffstat:
2 files changed, 144 insertions(+), 58 deletions(-)
diff --git a/crates/notedeck/src/accounts.rs b/crates/notedeck/src/accounts.rs
@@ -37,7 +37,7 @@ pub enum AccountsAction {
pub struct AccountRelayData {
filter: Filter,
- subid: String,
+ subid: Option<String>,
sub: Option<Subscription>,
local: BTreeSet<RelaySpec>, // used locally but not advertised
advertised: BTreeSet<RelaySpec>, // advertised via NIP-65
@@ -56,7 +56,7 @@ pub struct AddAccountAction {
}
impl AccountRelayData {
- pub fn new(ndb: &Ndb, pool: &mut RelayPool, pubkey: &[u8; 32]) -> Self {
+ pub fn new(ndb: &Ndb, pubkey: &[u8; 32]) -> Self {
// Construct a filter for the user's NIP-65 relay list
let filter = Filter::new()
.authors([pubkey])
@@ -64,11 +64,6 @@ impl AccountRelayData {
.limit(1)
.build();
- // Local ndb subscription
- let ndbsub = ndb
- .subscribe(&[filter.clone()])
- .expect("ndb relay list subscription");
-
// Query the ndb immediately to see if the user list is already there
let txn = Transaction::new(ndb).expect("transaction");
let lim = filter.limit().unwrap_or(crate::filter::default_limit()) as i32;
@@ -85,21 +80,51 @@ impl AccountRelayData {
relays
);
- // Id for future remote relay subscriptions
- let subid = Uuid::new_v4().to_string();
-
- // Add remote subscription to existing relays
- pool.subscribe(subid.clone(), vec![filter.clone()]);
-
AccountRelayData {
filter,
- subid,
- sub: Some(ndbsub),
+ subid: None,
+ sub: None,
local: BTreeSet::new(),
advertised: relays.into_iter().collect(),
}
}
+ // make this account the current selected account
+ pub fn activate(&mut self, ndb: &Ndb, pool: &mut RelayPool) {
+ debug!("activating relay sub {}", self.filter.json().unwrap());
+ assert_eq!(self.subid, None, "subid already exists");
+ assert_eq!(self.sub, None, "sub already exists");
+
+ // local subscription
+ let sub = ndb
+ .subscribe(&[self.filter.clone()])
+ .expect("ndb relay list subscription");
+
+ // remote subscription
+ let subid = Uuid::new_v4().to_string();
+ pool.subscribe(subid.clone(), vec![self.filter.clone()]);
+
+ self.sub = Some(sub);
+ self.subid = Some(subid);
+ }
+
+ // this account is no longer the selected account
+ pub fn deactivate(&mut self, ndb: &mut Ndb, pool: &mut RelayPool) {
+ debug!("deactivating relay sub {}", self.filter.json().unwrap());
+ assert_ne!(self.subid, None, "subid doesn't exist");
+ assert_ne!(self.sub, None, "sub doesn't exist");
+
+ // remote subscription
+ pool.unsubscribe(self.subid.as_ref().unwrap().clone());
+
+ // local subscription
+ ndb.unsubscribe(self.sub.unwrap())
+ .expect("ndb relay list unsubscribe");
+
+ self.sub = None;
+ self.subid = None;
+ }
+
// standardize the format (ie, trailing slashes) to avoid dups
pub fn canonicalize_url(url: &str) -> String {
match Url::parse(url) {
@@ -162,13 +187,13 @@ impl AccountRelayData {
pub struct AccountMutedData {
filter: Filter,
- subid: String,
+ subid: Option<String>,
sub: Option<Subscription>,
muted: Arc<Muted>,
}
impl AccountMutedData {
- pub fn new(ndb: &Ndb, pool: &mut RelayPool, pubkey: &[u8; 32]) -> Self {
+ pub fn new(ndb: &Ndb, pubkey: &[u8; 32]) -> Self {
// Construct a filter for the user's NIP-51 muted list
let filter = Filter::new()
.authors([pubkey])
@@ -176,11 +201,6 @@ impl AccountMutedData {
.limit(1)
.build();
- // Local ndb subscription
- let ndbsub = ndb
- .subscribe(&[filter.clone()])
- .expect("ndb muted subscription");
-
// Query the ndb immediately to see if the user's muted list is already there
let txn = Transaction::new(ndb).expect("transaction");
let lim = filter.limit().unwrap_or(crate::filter::default_limit()) as i32;
@@ -193,20 +213,50 @@ impl AccountMutedData {
let muted = Self::harvest_nip51_muted(ndb, &txn, &nks);
debug!("pubkey {}: initial muted {:?}", hex::encode(pubkey), muted);
- // Id for future remote relay subscriptions
- let subid = Uuid::new_v4().to_string();
-
- // Add remote subscription to existing relays
- pool.subscribe(subid.clone(), vec![filter.clone()]);
-
AccountMutedData {
filter,
- subid,
- sub: Some(ndbsub),
+ subid: None,
+ sub: None,
muted: Arc::new(muted),
}
}
+ // make this account the current selected account
+ pub fn activate(&mut self, ndb: &Ndb, pool: &mut RelayPool) {
+ debug!("activating muted sub {}", self.filter.json().unwrap());
+ assert_eq!(self.subid, None, "subid already exists");
+ assert_eq!(self.sub, None, "sub already exists");
+
+ // local subscription
+ let sub = ndb
+ .subscribe(&[self.filter.clone()])
+ .expect("ndb muted subscription");
+
+ // remote subscription
+ let subid = Uuid::new_v4().to_string();
+ pool.subscribe(subid.clone(), vec![self.filter.clone()]);
+
+ self.sub = Some(sub);
+ self.subid = Some(subid);
+ }
+
+ // this account is no longer the selected account
+ pub fn deactivate(&mut self, ndb: &mut Ndb, pool: &mut RelayPool) {
+ debug!("deactivating muted sub {}", self.filter.json().unwrap());
+ assert_ne!(self.subid, None, "subid doesn't exist");
+ assert_ne!(self.sub, None, "sub doesn't exist");
+
+ // remote subscription
+ pool.unsubscribe(self.subid.as_ref().unwrap().clone());
+
+ // local subscription
+ ndb.unsubscribe(self.sub.unwrap())
+ .expect("ndb muted unsubscribe");
+
+ self.sub = None;
+ self.subid = None;
+ }
+
fn harvest_nip51_muted(ndb: &Ndb, txn: &Transaction, nks: &[NoteKey]) -> Muted {
let mut muted = Muted::default();
for nk in nks.iter() {
@@ -432,13 +482,12 @@ impl Accounts {
}
}
- pub fn get_selected_account_data(&self) -> Option<&AccountData> {
- if let Some(account) = self.get_selected_account() {
- if let Some(account_data) = self.account_data.get(account.pubkey.bytes()) {
- return Some(account_data);
- }
- }
- None
+ pub fn get_selected_account_data(&mut self) -> Option<&mut AccountData> {
+ let account_pubkey = {
+ let account = self.get_selected_account()?;
+ *account.pubkey.bytes()
+ };
+ self.account_data.get_mut(&account_pubkey)
}
pub fn select_account(&mut self, index: usize) {
@@ -470,18 +519,25 @@ impl Accounts {
pub fn send_initial_filters(&mut self, pool: &mut RelayPool, relay_url: &str) {
for data in self.account_data.values() {
- pool.send_to(
- &ClientMessage::req(data.relay.subid.clone(), vec![data.relay.filter.clone()]),
- relay_url,
- );
- pool.send_to(
- &ClientMessage::req(data.muted.subid.clone(), vec![data.muted.filter.clone()]),
- relay_url,
- );
+ // send the active account's relay list subscription
+ if let Some(relay_subid) = &data.relay.subid {
+ pool.send_to(
+ &ClientMessage::req(relay_subid.clone(), vec![data.relay.filter.clone()]),
+ relay_url,
+ );
+ }
+ // send the active account's muted subscription
+ if let Some(muted_subid) = &data.muted.subid {
+ pool.send_to(
+ &ClientMessage::req(muted_subid.clone(), vec![data.muted.filter.clone()]),
+ relay_url,
+ );
+ }
}
}
- // Returns added and removed accounts
+ // Return accounts which have no account_data yet (added) and accounts
+ // which have still data but are no longer in our account list (removed).
fn delta_accounts(&self) -> (Vec<[u8; 32]>, Vec<[u8; 32]>) {
let mut added = Vec::new();
for pubkey in self.accounts.iter().map(|a| a.pubkey.bytes()) {
@@ -498,13 +554,13 @@ impl Accounts {
(added, removed)
}
- fn handle_added_account(&mut self, ndb: &Ndb, pool: &mut RelayPool, pubkey: &[u8; 32]) {
+ fn handle_added_account(&mut self, ndb: &Ndb, pubkey: &[u8; 32]) {
debug!("handle_added_account {}", hex::encode(pubkey));
// Create the user account data
let new_account_data = AccountData {
- relay: AccountRelayData::new(ndb, pool, pubkey),
- muted: AccountMutedData::new(ndb, pool, pubkey),
+ relay: AccountRelayData::new(ndb, pubkey),
+ muted: AccountMutedData::new(ndb, pubkey),
};
self.account_data.insert(*pubkey, new_account_data);
}
@@ -552,8 +608,9 @@ impl Accounts {
wakeup: impl Fn() + Send + Sync + Clone + 'static,
) {
debug!(
- "updating relay configuration for currently selected account {:?}",
+ "updating relay configuration for currently selected {:?}",
self.currently_selected_account
+ .map(|i| hex::encode(self.accounts.get(i).unwrap().pubkey.bytes()))
);
// If forced relays are set use them only
@@ -600,37 +657,66 @@ impl Accounts {
debug!("current relays: {:?}", pool.urls());
}
- pub fn update(&mut self, ndb: &Ndb, pool: &mut RelayPool, ctx: &egui::Context) {
+ pub fn update(&mut self, ndb: &mut Ndb, pool: &mut RelayPool, ctx: &egui::Context) {
// IMPORTANT - This function is called in the UI update loop,
// make sure it is fast when idle
// On the initial update the relays need config even if nothing changes below
- let mut relays_changed = self.needs_relay_config;
+ let mut need_reconfig = self.needs_relay_config;
let ctx2 = ctx.clone();
let wakeup = move || {
ctx2.request_repaint();
};
+ // Do we need to deactivate any existing account subs?
+ for (ndx, account) in self.accounts.iter().enumerate() {
+ if Some(ndx) != self.currently_selected_account {
+ // this account is not currently selected
+ if let Some(data) = self.account_data.get_mut(account.pubkey.bytes()) {
+ if data.relay.sub.is_some() {
+ // this account has relay subs, deactivate them
+ data.relay.deactivate(ndb, pool);
+ }
+ if data.muted.sub.is_some() {
+ // this account has muted subs, deactivate them
+ data.muted.deactivate(ndb, pool);
+ }
+ }
+ }
+ }
+
// Were any accounts added or removed?
let (added, removed) = self.delta_accounts();
for pk in added {
- self.handle_added_account(ndb, pool, &pk);
- relays_changed = true;
+ self.handle_added_account(ndb, &pk);
+ need_reconfig = true;
}
for pk in removed {
self.handle_removed_account(&pk);
- relays_changed = true;
+ need_reconfig = true;
}
// Did any accounts receive updates (ie NIP-65 relay lists)
- relays_changed = self.poll_for_updates(ndb) || relays_changed;
+ need_reconfig = self.poll_for_updates(ndb) || need_reconfig;
// If needed, update the relay configuration
- if relays_changed {
+ if need_reconfig {
self.update_relay_configuration(pool, wakeup);
self.needs_relay_config = false;
}
+
+ // Do we need to activate account subs?
+ if let Some(data) = self.get_selected_account_data() {
+ if data.relay.sub.is_none() {
+ // the currently selected account doesn't have relay subs, activate them
+ data.relay.activate(ndb, pool);
+ }
+ if data.muted.sub.is_none() {
+ // the currently selected account doesn't have muted subs, activate them
+ data.muted.activate(ndb, pool);
+ }
+ }
}
pub fn get_full<'a>(&'a self, pubkey: &[u8; 32]) -> Option<FilledKeypair<'a>> {
diff --git a/crates/notedeck/src/app.rs b/crates/notedeck/src/app.rs
@@ -69,7 +69,7 @@ impl eframe::App for Notedeck {
puffin::GlobalProfiler::lock().new_frame();
// handle account updates
- self.accounts.update(&self.ndb, &mut self.pool, ctx);
+ self.accounts.update(&mut self.ndb, &mut self.pool, ctx);
main_panel(&ctx.style(), crate::ui::is_narrow(ctx)).show(ctx, |ui| {
// render app