canonize UserAccount

Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
kernelkind
2025-03-17 14:45:55 -04:00
parent 675a223b11
commit ad90a9565a
8 changed files with 71 additions and 87 deletions

View File

@@ -3,7 +3,7 @@ use tracing::{debug, error, info};
use crate::{ use crate::{
FileKeyStorage, MuteFun, Muted, RelaySpec, SingleUnkIdAction, UnknownIds, UserAccount, FileKeyStorage, MuteFun, Muted, RelaySpec, SingleUnkIdAction, UnknownIds, UserAccount,
}; };
use enostr::{ClientMessage, FilledKeypair, Keypair, RelayPool}; use enostr::{ClientMessage, FilledKeypair, Keypair, Pubkey, RelayPool};
use nostrdb::{Filter, Ndb, Note, NoteBuilder, NoteKey, Subscription, Transaction}; use nostrdb::{Filter, Ndb, Note, NoteBuilder, NoteKey, Subscription, Transaction};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::{BTreeMap, BTreeSet}; use std::collections::{BTreeMap, BTreeSet};
@@ -319,7 +319,7 @@ impl Accounts {
pub fn new(key_store: Option<FileKeyStorage>, forced_relays: Vec<String>) -> Self { pub fn new(key_store: Option<FileKeyStorage>, forced_relays: Vec<String>) -> Self {
let accounts = match &key_store { let accounts = match &key_store {
Some(keystore) => match keystore.get_keys() { Some(keystore) => match keystore.get_keys() {
Ok(k) => k, Ok(k) => k.into_iter().map(|key| UserAccount { key }).collect(),
Err(e) => { Err(e) => {
tracing::error!("could not get keys: {e}"); tracing::error!("could not get keys: {e}");
Vec::new() Vec::new()
@@ -371,13 +371,15 @@ impl Accounts {
} }
pub fn find_account(&self, pk: &[u8; 32]) -> Option<&UserAccount> { pub fn find_account(&self, pk: &[u8; 32]) -> Option<&UserAccount> {
self.accounts.iter().find(|acc| acc.pubkey.bytes() == pk) self.accounts
.iter()
.find(|acc| acc.key.pubkey.bytes() == pk)
} }
pub fn remove_account(&mut self, index: usize) { pub fn remove_account(&mut self, index: usize) {
if let Some(account) = self.accounts.get(index) { if let Some(account) = self.accounts.get(index) {
if let Some(key_store) = &self.key_store { if let Some(key_store) = &self.key_store {
if let Err(e) = key_store.remove_key(account) { if let Err(e) = key_store.remove_key(&account.key) {
tracing::error!("Could not remove account at index {index}: {e}"); tracing::error!("Could not remove account at index {index}: {e}");
} }
} }
@@ -413,8 +415,8 @@ impl Accounts {
fn contains_account(&self, pubkey: &[u8; 32]) -> Option<ContainsAccount> { fn contains_account(&self, pubkey: &[u8; 32]) -> Option<ContainsAccount> {
for (index, account) in self.accounts.iter().enumerate() { for (index, account) in self.accounts.iter().enumerate() {
let has_pubkey = account.pubkey.bytes() == pubkey; let has_pubkey = account.key.pubkey.bytes() == pubkey;
let has_nsec = account.secret_key.is_some(); let has_nsec = account.key.secret_key.is_some();
if has_pubkey { if has_pubkey {
return Some(ContainsAccount { has_nsec, index }); return Some(ContainsAccount { has_nsec, index });
} }
@@ -447,7 +449,7 @@ impl Accounts {
} }
} }
self.accounts[contains_acc.index] = account; self.accounts[contains_acc.index].key = account;
} else { } else {
info!("already have account, not adding {}", pubkey); info!("already have account, not adding {}", pubkey);
} }
@@ -459,7 +461,7 @@ impl Accounts {
tracing::error!("Could not add key for {:?}: {e}", account.pubkey); tracing::error!("Could not add key for {:?}: {e}", account.pubkey);
} }
} }
self.accounts.push(account); self.accounts.push(UserAccount::new(account));
self.accounts.len() - 1 self.accounts.len() - 1
}; };
@@ -483,33 +485,27 @@ impl Accounts {
pub fn selected_or_first_nsec(&self) -> Option<FilledKeypair<'_>> { pub fn selected_or_first_nsec(&self) -> Option<FilledKeypair<'_>> {
self.get_selected_account() self.get_selected_account()
.and_then(|kp| kp.to_full()) .and_then(|kp| kp.key.to_full())
.or_else(|| self.accounts.iter().find_map(|a| a.to_full())) .or_else(|| self.accounts.iter().find_map(|a| a.key.to_full()))
} }
/// Get the selected account's pubkey as bytes. Common operation so /// Get the selected account's pubkey as bytes. Common operation so
/// we make it a helper here. /// we make it a helper here.
pub fn selected_account_pubkey_bytes(&self) -> Option<&[u8; 32]> { pub fn selected_account_pubkey_bytes(&self) -> Option<&[u8; 32]> {
self.get_selected_account().map(|kp| kp.pubkey.bytes()) self.get_selected_account().map(|kp| kp.key.pubkey.bytes())
}
pub fn selected_account_pubkey(&self) -> Option<&Pubkey> {
self.get_selected_account().map(|acc| &acc.key.pubkey)
} }
pub fn get_selected_account(&self) -> Option<&UserAccount> { pub fn get_selected_account(&self) -> Option<&UserAccount> {
if let Some(account_index) = self.currently_selected_account { self.currently_selected_account
if let Some(account) = self.get_account(account_index) { .map(|i| self.get_account(i))?
Some(account)
} else {
None
}
} else {
None
}
} }
pub fn get_selected_account_data(&mut self) -> Option<&mut AccountData> { pub fn get_selected_account_data(&mut self) -> Option<&mut AccountData> {
let account_pubkey = { let account_pubkey = *self.selected_account_pubkey_bytes()?;
let account = self.get_selected_account()?;
*account.pubkey.bytes()
};
self.account_data.get_mut(&account_pubkey) self.account_data.get_mut(&account_pubkey)
} }
@@ -517,8 +513,8 @@ impl Accounts {
if let Some(account) = self.accounts.get(index) { if let Some(account) = self.accounts.get(index) {
self.currently_selected_account = Some(index); self.currently_selected_account = Some(index);
if let Some(key_store) = &self.key_store { if let Some(key_store) = &self.key_store {
if let Err(e) = key_store.select_key(Some(account.pubkey)) { if let Err(e) = key_store.select_key(Some(account.key.pubkey)) {
tracing::error!("Could not select key {:?}: {e}", account.pubkey); tracing::error!("Could not select key {:?}: {e}", account.key.pubkey);
} }
} }
} }
@@ -536,7 +532,7 @@ impl Accounts {
pub fn mutefun(&self) -> Box<MuteFun> { pub fn mutefun(&self) -> Box<MuteFun> {
if let Some(index) = self.currently_selected_account { if let Some(index) = self.currently_selected_account {
if let Some(account) = self.accounts.get(index) { if let Some(account) = self.accounts.get(index) {
let pubkey = account.pubkey.bytes(); let pubkey = account.key.pubkey.bytes();
if let Some(account_data) = self.account_data.get(pubkey) { if let Some(account_data) = self.account_data.get(pubkey) {
let muted = Arc::clone(&account_data.muted.muted); let muted = Arc::clone(&account_data.muted.muted);
return Box::new(move |note: &Note, thread: &[u8; 32]| { return Box::new(move |note: &Note, thread: &[u8; 32]| {
@@ -571,7 +567,7 @@ impl Accounts {
// which have still data but are no longer in our account list (removed). // which have still data but are no longer in our account list (removed).
fn delta_accounts(&self) -> (Vec<[u8; 32]>, Vec<[u8; 32]>) { fn delta_accounts(&self) -> (Vec<[u8; 32]>, Vec<[u8; 32]>) {
let mut added = Vec::new(); let mut added = Vec::new();
for pubkey in self.accounts.iter().map(|a| a.pubkey.bytes()) { for pubkey in self.accounts.iter().map(|a| a.key.pubkey.bytes()) {
if !self.account_data.contains_key(pubkey) { if !self.account_data.contains_key(pubkey) {
added.push(*pubkey); added.push(*pubkey);
} }
@@ -641,7 +637,7 @@ impl Accounts {
debug!( debug!(
"updating relay configuration for currently selected {:?}", "updating relay configuration for currently selected {:?}",
self.currently_selected_account self.currently_selected_account
.map(|i| hex::encode(self.accounts.get(i).unwrap().pubkey.bytes())) .map(|i| hex::encode(self.accounts.get(i).unwrap().key.pubkey.bytes()))
); );
// If forced relays are set use them only // If forced relays are set use them only
@@ -704,7 +700,7 @@ impl Accounts {
for (ndx, account) in self.accounts.iter().enumerate() { for (ndx, account) in self.accounts.iter().enumerate() {
if Some(ndx) != self.currently_selected_account { if Some(ndx) != self.currently_selected_account {
// this account is not currently selected // this account is not currently selected
if let Some(data) = self.account_data.get_mut(account.pubkey.bytes()) { if let Some(data) = self.account_data.get_mut(account.key.pubkey.bytes()) {
if data.relay.sub.is_some() { if data.relay.sub.is_some() {
// this account has relay subs, deactivate them // this account has relay subs, deactivate them
data.relay.deactivate(ndb, pool); data.relay.deactivate(ndb, pool);
@@ -754,7 +750,7 @@ impl Accounts {
if let Some(contains) = self.contains_account(pubkey) { if let Some(contains) = self.contains_account(pubkey) {
if contains.has_nsec { if contains.has_nsec {
if let Some(kp) = self.get_account(contains.index) { if let Some(kp) = self.get_account(contains.index) {
return kp.to_full(); return kp.key.to_full();
} }
} }
} }
@@ -778,7 +774,7 @@ impl Accounts {
Some(index) => match self.accounts.get(index) { Some(index) => match self.accounts.get(index) {
None => error!("selected account index {} is out of range.", index), None => error!("selected account index {} is out of range.", index),
Some(keypair) => { Some(keypair) => {
let key_bytes: [u8; 32] = *keypair.pubkey.bytes(); let key_bytes: [u8; 32] = *keypair.key.pubkey.bytes();
match self.account_data.get_mut(&key_bytes) { match self.account_data.get_mut(&key_bytes) {
None => error!("no account data found for the provided key."), None => error!("no account data found for the provided key."),
Some(account_data) => { Some(account_data) => {
@@ -799,7 +795,7 @@ impl Accounts {
self.needs_relay_config = true; self.needs_relay_config = true;
// If we have the secret key publish the NIP-65 relay list // If we have the secret key publish the NIP-65 relay list
if let Some(secretkey) = &keypair.secret_key { if let Some(secretkey) = &keypair.key.secret_key {
account_data account_data
.relay .relay
.publish_nip65_relays(&secretkey.to_secret_bytes(), pool); .publish_nip65_relays(&secretkey.to_secret_bytes(), pool);
@@ -828,7 +824,9 @@ enum RelayAction {
fn get_selected_index(accounts: &[UserAccount], keystore: &FileKeyStorage) -> Option<usize> { fn get_selected_index(accounts: &[UserAccount], keystore: &FileKeyStorage) -> Option<usize> {
match keystore.get_selected_key() { match keystore.get_selected_key() {
Ok(Some(pubkey)) => { Ok(Some(pubkey)) => {
return accounts.iter().position(|account| account.pubkey == pubkey); return accounts
.iter()
.position(|account| account.key.pubkey == pubkey);
} }
Ok(None) => {} Ok(None) => {}
Err(e) => error!("Error getting selected key: {}", e), Err(e) => error!("Error getting selected key: {}", e),

View File

@@ -1,9 +1,11 @@
use enostr::Keypair; use enostr::Keypair;
//pub struct UserAccount { pub struct UserAccount {
//pub key: Keypair, pub key: Keypair,
//pub relays: RelayPool, }
//pub relays: Vec<String>,
//}
pub type UserAccount = Keypair; impl UserAccount {
pub fn new(key: Keypair) -> Self {
Self { key }
}
}

View File

@@ -372,19 +372,10 @@ impl Damus {
pub fn new(ctx: &mut AppContext<'_>, args: &[String]) -> Self { pub fn new(ctx: &mut AppContext<'_>, args: &[String]) -> Self {
// arg parsing // arg parsing
let (parsed_args, unrecognized_args) = ColumnsArgs::parse( let (parsed_args, unrecognized_args) =
args, ColumnsArgs::parse(args, ctx.accounts.selected_account_pubkey());
ctx.accounts
.get_selected_account()
.as_ref()
.map(|kp| &kp.pubkey),
);
let account = ctx let account = ctx.accounts.selected_account_pubkey_bytes();
.accounts
.get_selected_account()
.as_ref()
.map(|a| a.pubkey.bytes());
let mut timeline_cache = TimelineCache::default(); let mut timeline_cache = TimelineCache::default();
let tmp_columns = !parsed_args.columns.is_empty(); let tmp_columns = !parsed_args.columns.is_empty();
@@ -425,7 +416,7 @@ impl Damus {
info!("DecksCache: creating new with demo configuration"); info!("DecksCache: creating new with demo configuration");
let mut cache = DecksCache::new_with_demo_config(&mut timeline_cache, ctx); let mut cache = DecksCache::new_with_demo_config(&mut timeline_cache, ctx);
for account in ctx.accounts.get_accounts() { for account in ctx.accounts.get_accounts() {
cache.add_deck_default(account.pubkey); cache.add_deck_default(account.key.pubkey);
} }
set_demo(&mut cache, ctx.ndb, ctx.accounts, ctx.unknown_ids); set_demo(&mut cache, ctx.ndb, ctx.accounts, ctx.unknown_ids);
@@ -657,11 +648,9 @@ pub fn get_active_columns<'a>(accounts: &Accounts, decks_cache: &'a DecksCache)
} }
pub fn get_decks<'a>(accounts: &Accounts, decks_cache: &'a DecksCache) -> &'a Decks { pub fn get_decks<'a>(accounts: &Accounts, decks_cache: &'a DecksCache) -> &'a Decks {
let key = if let Some(acc) = accounts.get_selected_account() { let key = accounts
&acc.pubkey .selected_account_pubkey()
} else { .unwrap_or_else(|| decks_cache.get_fallback_pubkey());
decks_cache.get_fallback_pubkey()
};
decks_cache.decks(key) decks_cache.decks(key)
} }
@@ -675,10 +664,9 @@ pub fn get_active_columns_mut<'a>(
} }
pub fn get_decks_mut<'a>(accounts: &Accounts, decks_cache: &'a mut DecksCache) -> &'a mut Decks { pub fn get_decks_mut<'a>(accounts: &Accounts, decks_cache: &'a mut DecksCache) -> &'a mut Decks {
if let Some(acc) = accounts.get_selected_account() { match accounts.selected_account_pubkey() {
decks_cache.decks_mut(&acc.pubkey) Some(acc) => decks_cache.decks_mut(acc),
} else { None => decks_cache.fallback_mut(),
decks_cache.fallback_mut()
} }
} }

View File

@@ -370,7 +370,7 @@ fn render_nav_body(
} }
Route::ComposeNote => { Route::ComposeNote => {
let kp = ctx.accounts.get_selected_account()?.to_full()?; let kp = ctx.accounts.get_selected_account()?.key.to_full()?;
let draft = app.drafts.compose_mut(); let draft = app.drafts.compose_mut();
let txn = Transaction::new(ctx.ndb).expect("txn"); let txn = Transaction::new(ctx.ndb).expect("txn");
@@ -433,11 +433,9 @@ fn render_nav_body(
let new_deck_state = app.view_state.id_to_deck_state.entry(id).or_default(); let new_deck_state = app.view_state.id_to_deck_state.entry(id).or_default();
let mut resp = None; let mut resp = None;
if let Some(config_resp) = ConfigureDeckView::new(new_deck_state).ui(ui) { if let Some(config_resp) = ConfigureDeckView::new(new_deck_state).ui(ui) {
if let Some(cur_acc) = ctx.accounts.get_selected_account() { if let Some(cur_acc) = ctx.accounts.selected_account_pubkey() {
app.decks_cache.add_deck( app.decks_cache
cur_acc.pubkey, .add_deck(*cur_acc, Deck::new(config_resp.icon, config_resp.name));
Deck::new(config_resp.icon, config_resp.name),
);
// set new deck as active // set new deck as active
let cur_index = get_decks_mut(ctx.accounts, &mut app.decks_cache) let cur_index = get_decks_mut(ctx.accounts, &mut app.decks_cache)
@@ -462,11 +460,9 @@ fn render_nav_body(
.decks_mut() .decks_mut()
.get_mut(*index) .get_mut(*index)
.expect("index wasn't valid"); .expect("index wasn't valid");
let id = ui.id().with(( let id = ui
"edit-deck", .id()
ctx.accounts.get_selected_account().map(|k| k.pubkey), .with(("edit-deck", ctx.accounts.selected_account_pubkey(), index));
index,
));
let deck_state = app let deck_state = app
.view_state .view_state
.id_to_deck_state .id_to_deck_state

View File

@@ -69,7 +69,7 @@ impl<'a> AccountsView<'a> {
for i in 0..accounts.num_accounts() { for i in 0..accounts.num_accounts() {
let (account_pubkey, has_nsec) = match accounts.get_account(i) { let (account_pubkey, has_nsec) = match accounts.get_account(i) {
Some(acc) => (acc.pubkey.bytes(), acc.secret_key.is_some()), Some(acc) => (acc.key.pubkey.bytes(), acc.key.secret_key.is_some()),
None => continue, None => continue,
}; };

View File

@@ -143,18 +143,18 @@ impl AddColumnOption {
AddColumnOption::Algo(algo_option) => AddColumnResponse::Algo(algo_option), AddColumnOption::Algo(algo_option) => AddColumnResponse::Algo(algo_option),
AddColumnOption::Universe => AddColumnResponse::Timeline(TimelineKind::Universe), AddColumnOption::Universe => AddColumnResponse::Timeline(TimelineKind::Universe),
AddColumnOption::Notification(pubkey) => AddColumnResponse::Timeline( AddColumnOption::Notification(pubkey) => AddColumnResponse::Timeline(
TimelineKind::Notifications(*pubkey.as_pubkey(&cur_account.pubkey)), TimelineKind::Notifications(*pubkey.as_pubkey(&cur_account.key.pubkey)),
), ),
AddColumnOption::UndecidedNotification => AddColumnResponse::UndecidedNotification, AddColumnOption::UndecidedNotification => AddColumnResponse::UndecidedNotification,
AddColumnOption::Contacts(pk_src) => AddColumnResponse::Timeline( AddColumnOption::Contacts(pk_src) => AddColumnResponse::Timeline(
TimelineKind::contact_list(*pk_src.as_pubkey(&cur_account.pubkey)), TimelineKind::contact_list(*pk_src.as_pubkey(&cur_account.key.pubkey)),
), ),
AddColumnOption::ExternalNotification => AddColumnResponse::ExternalNotification, AddColumnOption::ExternalNotification => AddColumnResponse::ExternalNotification,
AddColumnOption::UndecidedHashtag => AddColumnResponse::Hashtag, AddColumnOption::UndecidedHashtag => AddColumnResponse::Hashtag,
AddColumnOption::UndecidedIndividual => AddColumnResponse::UndecidedIndividual, AddColumnOption::UndecidedIndividual => AddColumnResponse::UndecidedIndividual,
AddColumnOption::ExternalIndividual => AddColumnResponse::ExternalIndividual, AddColumnOption::ExternalIndividual => AddColumnResponse::ExternalIndividual,
AddColumnOption::Individual(pubkey_source) => AddColumnResponse::Timeline( AddColumnOption::Individual(pubkey_source) => AddColumnResponse::Timeline(
TimelineKind::profile(*pubkey_source.as_pubkey(&cur_account.pubkey)), TimelineKind::profile(*pubkey_source.as_pubkey(&cur_account.key.pubkey)),
), ),
} }
} }
@@ -453,10 +453,10 @@ impl<'a> AddColumnView<'a> {
}); });
if let Some(acc) = self.cur_account { if let Some(acc) = self.cur_account {
let source = if acc.secret_key.is_some() { let source = if acc.key.secret_key.is_some() {
PubkeySource::DeckAuthor PubkeySource::DeckAuthor
} else { } else {
PubkeySource::Explicit(acc.pubkey) PubkeySource::Explicit(acc.key.pubkey)
}; };
vec.push(ColumnOptionData { vec.push(ColumnOptionData {
@@ -498,10 +498,10 @@ impl<'a> AddColumnView<'a> {
let mut vec = Vec::new(); let mut vec = Vec::new();
if let Some(acc) = self.cur_account { if let Some(acc) = self.cur_account {
let source = if acc.secret_key.is_some() { let source = if acc.key.secret_key.is_some() {
PubkeySource::DeckAuthor PubkeySource::DeckAuthor
} else { } else {
PubkeySource::Explicit(acc.pubkey) PubkeySource::Explicit(acc.key.pubkey)
}; };
vec.push(ColumnOptionData { vec.push(ColumnOptionData {
@@ -528,10 +528,10 @@ impl<'a> AddColumnView<'a> {
let mut vec = Vec::new(); let mut vec = Vec::new();
if let Some(acc) = self.cur_account { if let Some(acc) = self.cur_account {
let source = if acc.secret_key.is_some() { let source = if acc.key.secret_key.is_some() {
PubkeySource::DeckAuthor PubkeySource::DeckAuthor
} else { } else {
PubkeySource::Explicit(acc.pubkey) PubkeySource::Explicit(acc.key.pubkey)
}; };
vec.push(ColumnOptionData { vec.push(ColumnOptionData {
@@ -606,7 +606,7 @@ pub fn render_add_column_routes(
AddAlgoRoute::Base => add_column_view.algo_ui(ui), AddAlgoRoute::Base => add_column_view.algo_ui(ui),
AddAlgoRoute::LastPerPubkey => { AddAlgoRoute::LastPerPubkey => {
if let Some(deck_author) = ctx.accounts.get_selected_account() { if let Some(deck_author) = ctx.accounts.get_selected_account() {
add_column_view.algo_last_per_pk_ui(ui, deck_author.pubkey) add_column_view.algo_last_per_pk_ui(ui, deck_author.key.pubkey)
} else { } else {
None None
} }

View File

@@ -166,7 +166,7 @@ pub fn get_account_url<'a>(
account: Option<&UserAccount>, account: Option<&UserAccount>,
) -> &'a str { ) -> &'a str {
if let Some(selected_account) = account { if let Some(selected_account) = account {
if let Ok(profile) = ndb.get_profile_by_pubkey(txn, selected_account.pubkey.bytes()) { if let Ok(profile) = ndb.get_profile_by_pubkey(txn, selected_account.key.pubkey.bytes()) {
get_profile_url_owned(Some(profile)) get_profile_url_owned(Some(profile))
} else { } else {
get_profile_url_owned(None) get_profile_url_owned(None)

View File

@@ -111,7 +111,7 @@ impl<'a> DesktopSidePanel<'a> {
ui.add_space(16.0); ui.add_space(16.0);
let is_interactive = self let is_interactive = self
.selected_account .selected_account
.is_some_and(|s| s.secret_key.is_some()); .is_some_and(|s| s.key.secret_key.is_some());
let compose_resp = ui.add(compose_note_button(is_interactive, dark_mode)); let compose_resp = ui.add(compose_note_button(is_interactive, dark_mode));
let compose_resp = if is_interactive { let compose_resp = if is_interactive {
compose_resp compose_resp
@@ -599,7 +599,7 @@ fn show_decks<'a>(
) -> InnerResponse<Option<usize>> { ) -> InnerResponse<Option<usize>> {
let show_decks_id = ui.id().with("show-decks"); let show_decks_id = ui.id().with("show-decks");
let account_id = if let Some(acc) = selected_account { let account_id = if let Some(acc) = selected_account {
acc.pubkey acc.key.pubkey
} else { } else {
*decks_cache.get_fallback_pubkey() *decks_cache.get_fallback_pubkey()
}; };