mirror of
https://github.com/aljazceru/notedeck.git
synced 2025-12-18 17:14:21 +01:00
@@ -1,8 +1,7 @@
|
||||
use tracing::{debug, error, info};
|
||||
|
||||
use crate::{
|
||||
KeyStorageResponse, KeyStorageType, MuteFun, Muted, RelaySpec, SingleUnkIdAction, UnknownIds,
|
||||
UserAccount,
|
||||
FileKeyStorage, MuteFun, Muted, RelaySpec, SingleUnkIdAction, UnknownIds, UserAccount,
|
||||
};
|
||||
use enostr::{ClientMessage, FilledKeypair, Keypair, RelayPool};
|
||||
use nostrdb::{Filter, Ndb, Note, NoteBuilder, NoteKey, Subscription, Transaction};
|
||||
@@ -309,7 +308,7 @@ pub struct AccountData {
|
||||
pub struct Accounts {
|
||||
currently_selected_account: Option<usize>,
|
||||
accounts: Vec<UserAccount>,
|
||||
key_store: KeyStorageType,
|
||||
key_store: Option<FileKeyStorage>,
|
||||
account_data: BTreeMap<[u8; 32], AccountData>,
|
||||
forced_relays: BTreeSet<RelaySpec>,
|
||||
bootstrap_relays: BTreeSet<RelaySpec>,
|
||||
@@ -317,14 +316,24 @@ pub struct Accounts {
|
||||
}
|
||||
|
||||
impl Accounts {
|
||||
pub fn new(key_store: KeyStorageType, forced_relays: Vec<String>) -> Self {
|
||||
let accounts = if let KeyStorageResponse::ReceivedResult(res) = key_store.get_keys() {
|
||||
res.unwrap_or_default()
|
||||
} else {
|
||||
Vec::new()
|
||||
pub fn new(key_store: Option<FileKeyStorage>, forced_relays: Vec<String>) -> Self {
|
||||
let accounts = match &key_store {
|
||||
Some(keystore) => match keystore.get_keys() {
|
||||
Ok(k) => k,
|
||||
Err(e) => {
|
||||
tracing::error!("could not get keys: {e}");
|
||||
Vec::new()
|
||||
}
|
||||
},
|
||||
None => Vec::new(),
|
||||
};
|
||||
|
||||
let currently_selected_account = if let Some(key_store) = &key_store {
|
||||
get_selected_index(&accounts, key_store)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let currently_selected_account = get_selected_index(&accounts, &key_store);
|
||||
let account_data = BTreeMap::new();
|
||||
let forced_relays: BTreeSet<RelaySpec> = forced_relays
|
||||
.into_iter()
|
||||
@@ -367,7 +376,12 @@ impl Accounts {
|
||||
|
||||
pub fn remove_account(&mut self, index: usize) {
|
||||
if let Some(account) = self.accounts.get(index) {
|
||||
let _ = self.key_store.remove_key(account);
|
||||
if let Some(key_store) = &self.key_store {
|
||||
if let Err(e) = key_store.remove_key(account) {
|
||||
tracing::error!("Could not remove account at index {index}: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
self.accounts.remove(index);
|
||||
|
||||
if let Some(selected_index) = self.currently_selected_account {
|
||||
@@ -426,7 +440,12 @@ impl Accounts {
|
||||
"user provided nsec, but we already have npub {}. Upgrading to nsec",
|
||||
pubkey
|
||||
);
|
||||
let _ = self.key_store.add_key(&account);
|
||||
|
||||
if let Some(key_store) = &self.key_store {
|
||||
if let Err(e) = key_store.add_key(&account) {
|
||||
tracing::error!("Could not add key for {:?}: {e}", account.pubkey);
|
||||
}
|
||||
}
|
||||
|
||||
self.accounts[contains_acc.index] = account;
|
||||
} else {
|
||||
@@ -435,7 +454,11 @@ impl Accounts {
|
||||
contains_acc.index
|
||||
} else {
|
||||
info!("adding new account {}", pubkey);
|
||||
let _ = self.key_store.add_key(&account);
|
||||
if let Some(key_store) = &self.key_store {
|
||||
if let Err(e) = key_store.add_key(&account) {
|
||||
tracing::error!("Could not add key for {:?}: {e}", account.pubkey);
|
||||
}
|
||||
}
|
||||
self.accounts.push(account);
|
||||
self.accounts.len() - 1
|
||||
};
|
||||
@@ -493,13 +516,21 @@ impl Accounts {
|
||||
pub fn select_account(&mut self, index: usize) {
|
||||
if let Some(account) = self.accounts.get(index) {
|
||||
self.currently_selected_account = Some(index);
|
||||
self.key_store.select_key(Some(account.pubkey));
|
||||
if let Some(key_store) = &self.key_store {
|
||||
if let Err(e) = key_store.select_key(Some(account.pubkey)) {
|
||||
tracing::error!("Could not select key {:?}: {e}", account.pubkey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear_selected_account(&mut self) {
|
||||
self.currently_selected_account = None;
|
||||
self.key_store.select_key(None);
|
||||
if let Some(key_store) = &self.key_store {
|
||||
if let Err(e) = key_store.select_key(None) {
|
||||
tracing::error!("Could not select None key: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mutefun(&self) -> Box<MuteFun> {
|
||||
@@ -794,14 +825,13 @@ enum RelayAction {
|
||||
Remove,
|
||||
}
|
||||
|
||||
fn get_selected_index(accounts: &[UserAccount], keystore: &KeyStorageType) -> Option<usize> {
|
||||
fn get_selected_index(accounts: &[UserAccount], keystore: &FileKeyStorage) -> Option<usize> {
|
||||
match keystore.get_selected_key() {
|
||||
KeyStorageResponse::ReceivedResult(Ok(Some(pubkey))) => {
|
||||
Ok(Some(pubkey)) => {
|
||||
return accounts.iter().position(|account| account.pubkey == pubkey);
|
||||
}
|
||||
|
||||
KeyStorageResponse::ReceivedResult(Err(e)) => error!("Error getting selected key: {}", e),
|
||||
KeyStorageResponse::Waiting | KeyStorageResponse::ReceivedResult(Ok(None)) => {}
|
||||
Ok(None) => {}
|
||||
Err(e) => error!("Error getting selected key: {}", e),
|
||||
};
|
||||
|
||||
None
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::persist::{AppSizeHandler, ZoomHandler};
|
||||
use crate::{
|
||||
Accounts, AppContext, Args, DataPath, DataPathType, Directory, FileKeyStorage, Images,
|
||||
KeyStorageType, NoteCache, RelayDebugView, ThemeHandler, UnknownIds,
|
||||
NoteCache, RelayDebugView, ThemeHandler, UnknownIds,
|
||||
};
|
||||
use egui::ThemePreference;
|
||||
use egui_winit::clipboard::Clipboard;
|
||||
@@ -149,12 +149,12 @@ impl Notedeck {
|
||||
let keystore = if parsed_args.use_keystore {
|
||||
let keys_path = path.path(DataPathType::Keys);
|
||||
let selected_key_path = path.path(DataPathType::SelectedKey);
|
||||
KeyStorageType::FileSystem(FileKeyStorage::new(
|
||||
Some(FileKeyStorage::new(
|
||||
Directory::new(keys_path),
|
||||
Directory::new(selected_key_path),
|
||||
))
|
||||
} else {
|
||||
KeyStorageType::None
|
||||
None
|
||||
};
|
||||
|
||||
let mut accounts = Accounts::new(keystore, parsed_args.relays.clone());
|
||||
|
||||
@@ -44,9 +44,7 @@ pub use persist::*;
|
||||
pub use relay_debug::RelayDebugView;
|
||||
pub use relayspec::RelaySpec;
|
||||
pub use result::Result;
|
||||
pub use storage::{
|
||||
DataPath, DataPathType, Directory, FileKeyStorage, KeyStorageResponse, KeyStorageType,
|
||||
};
|
||||
pub use storage::{DataPath, DataPathType, Directory, FileKeyStorage};
|
||||
pub use style::NotedeckTextStyle;
|
||||
pub use theme::ColorTheme;
|
||||
pub use time::time_ago_since;
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
use crate::Result;
|
||||
use enostr::{Keypair, Pubkey, SerializableKeypair};
|
||||
|
||||
use super::{
|
||||
file_storage::{delete_file, write_file, Directory},
|
||||
key_storage_impl::KeyStorageResponse,
|
||||
};
|
||||
use super::file_storage::{delete_file, write_file, Directory};
|
||||
|
||||
static SELECTED_PUBKEY_FILE_NAME: &str = "selected_pubkey";
|
||||
|
||||
@@ -23,7 +20,7 @@ impl FileKeyStorage {
|
||||
}
|
||||
}
|
||||
|
||||
fn add_key_internal(&self, key: &Keypair) -> Result<()> {
|
||||
pub fn add_key(&self, key: &Keypair) -> Result<()> {
|
||||
write_file(
|
||||
&self.keys_directory.file_path,
|
||||
key.pubkey.hex(),
|
||||
@@ -31,7 +28,7 @@ impl FileKeyStorage {
|
||||
)
|
||||
}
|
||||
|
||||
fn get_keys_internal(&self) -> Result<Vec<Keypair>> {
|
||||
pub fn get_keys(&self) -> Result<Vec<Keypair>> {
|
||||
let keys = self
|
||||
.keys_directory
|
||||
.get_files()?
|
||||
@@ -42,11 +39,11 @@ impl FileKeyStorage {
|
||||
Ok(keys)
|
||||
}
|
||||
|
||||
fn remove_key_internal(&self, key: &Keypair) -> Result<()> {
|
||||
pub fn remove_key(&self, key: &Keypair) -> Result<()> {
|
||||
delete_file(&self.keys_directory.file_path, key.pubkey.hex())
|
||||
}
|
||||
|
||||
fn get_selected_pubkey(&self) -> Result<Option<Pubkey>> {
|
||||
pub fn get_selected_key(&self) -> Result<Option<Pubkey>> {
|
||||
match self
|
||||
.selected_key_directory
|
||||
.get_file(SELECTED_PUBKEY_FILE_NAME.to_owned())
|
||||
@@ -57,7 +54,7 @@ impl FileKeyStorage {
|
||||
}
|
||||
}
|
||||
|
||||
fn select_pubkey(&self, pubkey: Option<Pubkey>) -> Result<()> {
|
||||
pub fn select_key(&self, pubkey: Option<Pubkey>) -> Result<()> {
|
||||
if let Some(pubkey) = pubkey {
|
||||
write_file(
|
||||
&self.selected_key_directory.file_path,
|
||||
@@ -80,28 +77,6 @@ impl FileKeyStorage {
|
||||
}
|
||||
}
|
||||
|
||||
impl FileKeyStorage {
|
||||
pub fn get_keys(&self) -> KeyStorageResponse<Vec<enostr::Keypair>> {
|
||||
KeyStorageResponse::ReceivedResult(self.get_keys_internal())
|
||||
}
|
||||
|
||||
pub fn add_key(&self, key: &enostr::Keypair) -> KeyStorageResponse<()> {
|
||||
KeyStorageResponse::ReceivedResult(self.add_key_internal(key))
|
||||
}
|
||||
|
||||
pub fn remove_key(&self, key: &enostr::Keypair) -> KeyStorageResponse<()> {
|
||||
KeyStorageResponse::ReceivedResult(self.remove_key_internal(key))
|
||||
}
|
||||
|
||||
pub fn get_selected_key(&self) -> KeyStorageResponse<Option<Pubkey>> {
|
||||
KeyStorageResponse::ReceivedResult(self.get_selected_pubkey())
|
||||
}
|
||||
|
||||
pub fn select_key(&self, key: Option<Pubkey>) -> KeyStorageResponse<()> {
|
||||
KeyStorageResponse::ReceivedResult(self.select_pubkey(key))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::PathBuf;
|
||||
@@ -128,27 +103,21 @@ mod tests {
|
||||
let storage = FileKeyStorage::mock().unwrap();
|
||||
let resp = storage.add_key(&kp);
|
||||
|
||||
assert_eq!(resp, KeyStorageResponse::ReceivedResult(Ok(())));
|
||||
assert!(resp.is_ok());
|
||||
assert_num_storage(&storage.get_keys(), 1);
|
||||
|
||||
assert_eq!(
|
||||
storage.remove_key(&kp),
|
||||
KeyStorageResponse::ReceivedResult(Ok(()))
|
||||
);
|
||||
assert!(storage.remove_key(&kp).is_ok());
|
||||
assert_num_storage(&storage.get_keys(), 0);
|
||||
}
|
||||
|
||||
fn assert_num_storage(keys_response: &KeyStorageResponse<Vec<Keypair>>, n: usize) {
|
||||
fn assert_num_storage(keys_response: &Result<Vec<Keypair>>, n: usize) {
|
||||
match keys_response {
|
||||
KeyStorageResponse::ReceivedResult(Ok(keys)) => {
|
||||
Ok(keys) => {
|
||||
assert_eq!(keys.len(), n);
|
||||
}
|
||||
KeyStorageResponse::ReceivedResult(Err(_e)) => {
|
||||
Err(_e) => {
|
||||
panic!("could not get keys");
|
||||
}
|
||||
KeyStorageResponse::Waiting => {
|
||||
panic!("did not receive result");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,10 +129,10 @@ mod tests {
|
||||
let _ = storage.add_key(&kp);
|
||||
assert_num_storage(&storage.get_keys(), 1);
|
||||
|
||||
let resp = storage.select_pubkey(Some(kp.pubkey));
|
||||
let resp = storage.select_key(Some(kp.pubkey));
|
||||
assert!(resp.is_ok());
|
||||
|
||||
let resp = storage.get_selected_pubkey();
|
||||
let resp = storage.get_selected_key();
|
||||
|
||||
assert!(resp.is_ok());
|
||||
}
|
||||
@@ -174,7 +143,7 @@ mod tests {
|
||||
|
||||
// Should return Ok(None) when no key has been selected
|
||||
match storage.get_selected_key() {
|
||||
KeyStorageResponse::ReceivedResult(Ok(None)) => (), // This is what we expect
|
||||
Ok(None) => (), // This is what we expect
|
||||
other => panic!("Expected Ok(None), got {:?}", other),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
use enostr::{Keypair, Pubkey};
|
||||
|
||||
use super::file_key_storage::FileKeyStorage;
|
||||
use crate::Result;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum KeyStorageType {
|
||||
None,
|
||||
FileSystem(FileKeyStorage),
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum KeyStorageResponse<R> {
|
||||
Waiting,
|
||||
ReceivedResult(Result<R>),
|
||||
}
|
||||
|
||||
impl<R: PartialEq> PartialEq for KeyStorageResponse<R> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(KeyStorageResponse::Waiting, KeyStorageResponse::Waiting) => true,
|
||||
(
|
||||
KeyStorageResponse::ReceivedResult(Ok(r1)),
|
||||
KeyStorageResponse::ReceivedResult(Ok(r2)),
|
||||
) => r1 == r2,
|
||||
(
|
||||
KeyStorageResponse::ReceivedResult(Err(_)),
|
||||
KeyStorageResponse::ReceivedResult(Err(_)),
|
||||
) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl KeyStorageType {
|
||||
pub fn get_keys(&self) -> KeyStorageResponse<Vec<Keypair>> {
|
||||
match self {
|
||||
Self::None => KeyStorageResponse::ReceivedResult(Ok(Vec::new())),
|
||||
Self::FileSystem(f) => f.get_keys(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_key(&self, key: &Keypair) -> KeyStorageResponse<()> {
|
||||
let _ = key;
|
||||
match self {
|
||||
Self::None => KeyStorageResponse::ReceivedResult(Ok(())),
|
||||
Self::FileSystem(f) => f.add_key(key),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_key(&self, key: &Keypair) -> KeyStorageResponse<()> {
|
||||
let _ = key;
|
||||
match self {
|
||||
Self::None => KeyStorageResponse::ReceivedResult(Ok(())),
|
||||
Self::FileSystem(f) => f.remove_key(key),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_selected_key(&self) -> KeyStorageResponse<Option<Pubkey>> {
|
||||
match self {
|
||||
Self::None => KeyStorageResponse::ReceivedResult(Ok(None)),
|
||||
Self::FileSystem(f) => f.get_selected_key(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn select_key(&self, key: Option<Pubkey>) -> KeyStorageResponse<()> {
|
||||
match self {
|
||||
Self::None => KeyStorageResponse::ReceivedResult(Ok(())),
|
||||
Self::FileSystem(f) => f.select_key(key),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,3 @@ mod file_storage;
|
||||
|
||||
pub use file_key_storage::FileKeyStorage;
|
||||
pub use file_storage::{delete_file, write_file, DataPath, DataPathType, Directory};
|
||||
|
||||
pub mod key_storage_impl;
|
||||
pub use key_storage_impl::{KeyStorageResponse, KeyStorageType};
|
||||
|
||||
Reference in New Issue
Block a user