Merge kernel's "can't remove damoose fixes" and more! #1001

kernelkind (9):
      appease clippy
      use `NwcError` instead of nwc::Error
      make `UserAccount` cloneable
      allow removal of Damoose account
      expose `AccountCache::falback`
      move select account logic to own method
      bugfix: properly sub to new selected acc after removal of selected
      bugfix: unsubscribe from timelines on deck deletion
      bugfix: unsubscribe all decks when log out account
This commit is contained in:
William Casarin
2025-07-20 17:13:34 -07:00
12 changed files with 215 additions and 33 deletions

View File

@@ -124,7 +124,7 @@ impl Columns {
IntermediaryRoute::Timeline(mut timeline) => {
let route = Route::timeline(timeline.kind.clone());
timeline.subscription.increment();
timeline_cache.insert(timeline.kind.clone(), timeline);
timeline_cache.insert(timeline.kind.clone(), *timeline);
route
}
IntermediaryRoute::Route(route) => route,
@@ -247,7 +247,7 @@ impl Columns {
}
pub enum IntermediaryRoute {
Timeline(Timeline),
Timeline(Box<Timeline>),
Route(Route),
}

View File

@@ -1,6 +1,6 @@
use std::collections::{hash_map::ValuesMut, HashMap};
use enostr::Pubkey;
use enostr::{Pubkey, RelayPool};
use nostrdb::Transaction;
use notedeck::{AppContext, FALLBACK_PUBKEY};
use tracing::{error, info};
@@ -155,9 +155,24 @@ impl DecksCache {
}
}
pub fn remove_for(&mut self, key: &Pubkey) {
pub fn remove(
&mut self,
key: &Pubkey,
timeline_cache: &mut TimelineCache,
ndb: &mut nostrdb::Ndb,
pool: &mut RelayPool,
) {
let Some(decks) = self.account_to_decks.remove(key) else {
return;
};
info!("Removing decks for {:?}", key);
self.account_to_decks.remove(key);
decks.unsubscribe_all(timeline_cache, ndb, pool);
if !self.account_to_decks.contains_key(&self.fallback_pubkey) {
self.account_to_decks
.insert(self.fallback_pubkey, Decks::default());
}
}
pub fn get_fallback_pubkey(&self) -> &Pubkey {
@@ -265,10 +280,25 @@ impl Decks {
}
}
pub fn remove_deck(&mut self, index: usize) {
pub fn remove_deck(
&mut self,
index: usize,
timeline_cache: &mut TimelineCache,
ndb: &mut nostrdb::Ndb,
pool: &mut enostr::RelayPool,
) {
let Some(deck) = self.remove_deck_internal(index) else {
return;
};
delete_deck(deck, timeline_cache, ndb, pool);
}
fn remove_deck_internal(&mut self, index: usize) -> Option<Deck> {
let mut res = None;
if index < self.decks.len() {
if self.decks.len() > 1 {
self.decks.remove(index);
res = Some(self.decks.remove(index));
let info_prefix = format!("Removed deck at index {index}");
match index.cmp(&self.active_deck) {
@@ -311,6 +341,37 @@ impl Decks {
} else {
error!("index was out of bounds");
}
res
}
pub fn unsubscribe_all(
self,
timeline_cache: &mut TimelineCache,
ndb: &mut nostrdb::Ndb,
pool: &mut enostr::RelayPool,
) {
for deck in self.decks {
delete_deck(deck, timeline_cache, ndb, pool);
}
}
}
fn delete_deck(
mut deck: Deck,
timeline_cache: &mut TimelineCache,
ndb: &mut nostrdb::Ndb,
pool: &mut enostr::RelayPool,
) {
let cols = deck.columns_mut();
let num_cols = cols.num_columns();
for i in (0..num_cols).rev() {
let kinds_to_pop = cols.delete_column(i);
for kind in &kinds_to_pop {
if let Err(err) = timeline_cache.pop(kind, ndb, pool) {
error!("error popping timeline: {err}");
}
}
}
}

View File

@@ -94,7 +94,16 @@ impl SwitchingAction {
.router_mut()
.go_back();
}
AccountsAction::Remove(to_remove) => ctx.accounts.remove_account(to_remove),
AccountsAction::Remove(to_remove) => 's: {
if !ctx
.accounts
.remove_account(to_remove, ctx.ndb, ctx.pool, ui_ctx)
{
break 's;
}
decks_cache.remove(to_remove, timeline_cache, ctx.ndb, ctx.pool);
}
},
SwitchingAction::Columns(columns_action) => match *columns_action {
ColumnsAction::Remove(index) => {
@@ -116,7 +125,12 @@ impl SwitchingAction {
get_decks_mut(ctx.accounts, decks_cache).set_active(index)
}
DecksAction::Removing(index) => {
get_decks_mut(ctx.accounts, decks_cache).remove_deck(index)
get_decks_mut(ctx.accounts, decks_cache).remove_deck(
index,
timeline_cache,
ctx.ndb,
ctx.pool,
);
}
},
}

View File

@@ -351,9 +351,9 @@ impl CleanIntermediaryRoute {
match self {
CleanIntermediaryRoute::ToTimeline(timeline_kind) => {
let txn = Transaction::new(ndb).unwrap();
Some(IntermediaryRoute::Timeline(
Some(IntermediaryRoute::Timeline(Box::new(
timeline_kind.into_timeline(&txn, ndb)?,
))
)))
}
CleanIntermediaryRoute::ToRoute(route) => Some(IntermediaryRoute::Route(route)),
}