Add AccountManager to app

Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
kernelkind
2024-05-22 16:27:23 -04:00
committed by William Casarin
parent 748d9d2358
commit 11b3effa51
5 changed files with 93 additions and 59 deletions

View File

@@ -19,7 +19,7 @@ impl<'a> SimpleProfilePreviewController<'a> {
pub fn set_profile_previews( pub fn set_profile_previews(
&mut self, &mut self,
account_manager: &AccountManager<'a>, account_manager: &AccountManager,
ui: &mut egui::Ui, ui: &mut egui::Ui,
edit_mode: bool, edit_mode: bool,
add_preview_ui: fn( add_preview_ui: fn(
@@ -56,7 +56,7 @@ impl<'a> SimpleProfilePreviewController<'a> {
pub fn view_profile_previews( pub fn view_profile_previews(
&mut self, &mut self,
account_manager: &'a AccountManager<'a>, account_manager: &'a AccountManager,
ui: &mut egui::Ui, ui: &mut egui::Ui,
add_preview_ui: fn(ui: &mut egui::Ui, preview: SimpleProfilePreview, index: usize) -> bool, add_preview_ui: fn(ui: &mut egui::Ui, preview: SimpleProfilePreview, index: usize) -> bool,
) -> Option<usize> { ) -> Option<usize> {
@@ -86,18 +86,31 @@ impl<'a> SimpleProfilePreviewController<'a> {
/// The interface for managing the user's accounts. /// The interface for managing the user's accounts.
/// Represents all user-facing operations related to account management. /// Represents all user-facing operations related to account management.
pub struct AccountManager<'a> { pub struct AccountManager {
accounts: &'a mut Vec<UserAccount>, accounts: Vec<UserAccount>,
key_store: KeyStorage, key_store: KeyStorage,
relay_generator: RelayGenerator, relay_generator: RelayGenerator,
} }
impl<'a> AccountManager<'a> { impl AccountManager {
pub fn new( pub fn new(
accounts: &'a mut Vec<UserAccount>,
key_store: KeyStorage, key_store: KeyStorage,
// TODO: right now, there is only one way of generating relays for all accounts. In the future
// each account should have the option of generating relays differently
relay_generator: RelayGenerator, relay_generator: RelayGenerator,
wakeup: impl Fn() + Send + Sync + Clone + 'static,
) -> Self { ) -> Self {
let accounts = if let Ok(keys) = key_store.get_keys() {
keys.into_iter()
.map(|key| {
let relays = relay_generator.generate_relays_for(&key.pubkey, wakeup.clone());
UserAccount { key, relays }
})
.collect()
} else {
Vec::new()
};
AccountManager { AccountManager {
accounts, accounts,
key_store, key_store,
@@ -105,11 +118,11 @@ impl<'a> AccountManager<'a> {
} }
} }
pub fn get_accounts(&'a self) -> &'a Vec<UserAccount> { pub fn get_accounts(&self) -> &Vec<UserAccount> {
self.accounts &self.accounts
} }
pub fn get_account(&'a self, index: usize) -> Option<&'a UserAccount> { pub fn get_account(&self, index: usize) -> Option<&UserAccount> {
self.accounts.get(index) self.accounts.get(index)
} }
@@ -122,9 +135,15 @@ impl<'a> AccountManager<'a> {
} }
} }
pub fn add_account(&'a mut self, key: FullKeypair, ctx: &egui::Context) { pub fn add_account(
&mut self,
key: FullKeypair,
wakeup: impl Fn() + Send + Sync + Clone + 'static,
) {
let _ = self.key_store.add_key(&key); let _ = self.key_store.add_key(&key);
let relays = self.relay_generator.generate_relays_for(&key.pubkey, ctx); let relays = self
.relay_generator
.generate_relays_for(&key.pubkey, wakeup);
let account = UserAccount { key, relays }; let account = UserAccount { key, relays };
self.accounts.push(account) self.accounts.push(account)

View File

@@ -1,10 +1,11 @@
use crate::account_manager::UserAccount; use crate::account_manager::AccountManager;
use crate::app_creation::setup_cc; use crate::app_creation::setup_cc;
use crate::app_style::user_requested_visuals_change; use crate::app_style::user_requested_visuals_change;
use crate::error::Error; use crate::error::Error;
use crate::frame_history::FrameHistory; use crate::frame_history::FrameHistory;
use crate::imgcache::ImageCache; use crate::imgcache::ImageCache;
use crate::notecache::{CachedNote, NoteCache}; use crate::notecache::{CachedNote, NoteCache};
use crate::relay_pool_manager::create_wakeup;
use crate::timeline; use crate::timeline;
use crate::timeline::{NoteRef, Timeline, ViewFilter}; use crate::timeline::{NoteRef, Timeline, ViewFilter};
use crate::ui::{is_mobile, DesktopGlobalPopup, DesktopSidePanel, View}; use crate::ui::{is_mobile, DesktopGlobalPopup, DesktopSidePanel, View};
@@ -44,7 +45,7 @@ pub struct Damus {
pub img_cache: ImageCache, pub img_cache: ImageCache,
pub ndb: Ndb, pub ndb: Ndb,
pub accounts: Vec<UserAccount>, pub account_manager: AccountManager,
frame_history: crate::frame_history::FrameHistory, frame_history: crate::frame_history::FrameHistory,
} }
@@ -646,7 +647,13 @@ impl Damus {
timelines, timelines,
textmode: false, textmode: false,
ndb: Ndb::new(data_path.as_ref().to_str().expect("db path ok"), &config).expect("ndb"), ndb: Ndb::new(data_path.as_ref().to_str().expect("db path ok"), &config).expect("ndb"),
accounts: Vec::new(), account_manager: AccountManager::new(
// TODO: use correct KeyStorage mechanism for current OS arch
crate::key_storage::KeyStorage::None,
// TODO: setting for relay generator
crate::relay_generation::RelayGenerator::Constant,
create_wakeup(&cc.egui_ctx),
),
//compose: "".to_string(), //compose: "".to_string(),
frame_history: FrameHistory::default(), frame_history: FrameHistory::default(),
} }
@@ -672,7 +679,11 @@ impl Damus {
timelines, timelines,
textmode: false, textmode: false,
ndb: Ndb::new(data_path.as_ref().to_str().expect("db path ok"), &config).expect("ndb"), ndb: Ndb::new(data_path.as_ref().to_str().expect("db path ok"), &config).expect("ndb"),
accounts: Vec::new(), account_manager: AccountManager::new(
crate::key_storage::KeyStorage::None,
crate::relay_generation::RelayGenerator::Constant,
|| {},
),
frame_history: FrameHistory::default(), frame_history: FrameHistory::default(),
} }
} }

View File

@@ -1,4 +1,3 @@
use crate::relay_pool_manager::create_wakeup;
use enostr::{Pubkey, RelayPool}; use enostr::{Pubkey, RelayPool};
use tracing::error; use tracing::error;
@@ -9,30 +8,39 @@ pub enum RelayGenerator {
} }
impl RelayGenerator { impl RelayGenerator {
pub fn generate_relays_for(&self, key: &Pubkey, ctx: &egui::Context) -> RelayPool { pub fn generate_relays_for(
&self,
key: &Pubkey,
wakeup: impl Fn() + Send + Sync + Clone + 'static,
) -> RelayPool {
match self { match self {
Self::GossipModel => generate_relays_gossip(key, ctx), Self::GossipModel => generate_relays_gossip(key, wakeup),
Self::Nip65 => generate_relays_nip65(key, ctx), Self::Nip65 => generate_relays_nip65(key, wakeup),
Self::Constant => generate_constant_relays(ctx), Self::Constant => generate_constant_relays(wakeup),
} }
} }
} }
fn generate_relays_gossip(key: &Pubkey, ctx: &egui::Context) -> RelayPool { fn generate_relays_gossip(
let _ = ctx; key: &Pubkey,
wakeup: impl Fn() + Send + Sync + Clone + 'static,
) -> RelayPool {
let _ = wakeup;
let _ = key; let _ = key;
todo!() todo!()
} }
fn generate_relays_nip65(key: &Pubkey, ctx: &egui::Context) -> RelayPool { fn generate_relays_nip65(
let _ = ctx; key: &Pubkey,
wakeup: impl Fn() + Send + Sync + Clone + 'static,
) -> RelayPool {
let _ = wakeup;
let _ = key; let _ = key;
todo!() todo!()
} }
fn generate_constant_relays(ctx: &egui::Context) -> RelayPool { fn generate_constant_relays(wakeup: impl Fn() + Send + Sync + Clone + 'static) -> RelayPool {
let mut pool = RelayPool::new(); let mut pool = RelayPool::new();
let wakeup = create_wakeup(ctx);
if let Err(e) = pool.add_url("ws://localhost:8080".to_string(), wakeup.clone()) { if let Err(e) = pool.add_url("ws://localhost:8080".to_string(), wakeup.clone()) {
error!("{:?}", e) error!("{:?}", e)

View File

@@ -11,7 +11,7 @@ use super::profile::preview::SimpleProfilePreview;
use super::state_in_memory::STATE_ACCOUNT_MANAGEMENT; use super::state_in_memory::STATE_ACCOUNT_MANAGEMENT;
pub struct AccountManagementView<'a> { pub struct AccountManagementView<'a> {
account_manager: AccountManager<'a>, account_manager: &'a mut AccountManager,
simple_preview_controller: SimpleProfilePreviewController<'a>, simple_preview_controller: SimpleProfilePreviewController<'a>,
} }
@@ -27,7 +27,7 @@ impl<'a> View for AccountManagementView<'a> {
impl<'a> AccountManagementView<'a> { impl<'a> AccountManagementView<'a> {
pub fn new( pub fn new(
account_manager: AccountManager<'a>, account_manager: &'a mut AccountManager,
simple_preview_controller: SimpleProfilePreviewController<'a>, simple_preview_controller: SimpleProfilePreviewController<'a>,
) -> Self { ) -> Self {
AccountManagementView { AccountManagementView {
@@ -47,7 +47,7 @@ impl<'a> AccountManagementView<'a> {
fn show_accounts(&mut self, ui: &mut egui::Ui) { fn show_accounts(&mut self, ui: &mut egui::Ui) {
ui.horizontal_wrapped(|ui| { ui.horizontal_wrapped(|ui| {
let maybe_remove = self.simple_preview_controller.set_profile_previews( let maybe_remove = self.simple_preview_controller.set_profile_previews(
&self.account_manager, self.account_manager,
ui, ui,
STATE_ACCOUNT_MANAGEMENT.get_state(ui.ctx()), STATE_ACCOUNT_MANAGEMENT.get_state(ui.ctx()),
desktop_account_card_ui(), desktop_account_card_ui(),
@@ -64,7 +64,7 @@ impl<'a> AccountManagementView<'a> {
|ui| { |ui| {
// create all account 'cards' and get the indicies the user requested to remove // create all account 'cards' and get the indicies the user requested to remove
let maybe_remove = self.simple_preview_controller.set_profile_previews( let maybe_remove = self.simple_preview_controller.set_profile_previews(
&self.account_manager, self.account_manager,
ui, ui,
STATE_ACCOUNT_MANAGEMENT.get_state(ui.ctx()), STATE_ACCOUNT_MANAGEMENT.get_state(ui.ctx()),
mobile_account_card_ui(), // closure for creating an account 'card' mobile_account_card_ui(), // closure for creating an account 'card'
@@ -180,13 +180,8 @@ fn desktop_account_card_ui(
impl<'a> FromApp<'a> for AccountManagementView<'a> { impl<'a> FromApp<'a> for AccountManagementView<'a> {
fn from_app(app: &'a mut crate::Damus) -> Self { fn from_app(app: &'a mut crate::Damus) -> Self {
// TODO: don't hard-code key store & relay generator
AccountManagementView::new( AccountManagementView::new(
AccountManager::new( &mut app.account_manager,
&mut app.accounts,
crate::key_storage::KeyStorage::None,
crate::relay_generation::RelayGenerator::Constant,
),
SimpleProfilePreviewController::new(&app.ndb, &mut app.img_cache), SimpleProfilePreviewController::new(&app.ndb, &mut app.img_cache),
) )
} }
@@ -239,7 +234,7 @@ fn delete_button(_dark_mode: bool) -> egui::Button<'static> {
} }
pub struct AccountSelectionWidget<'a> { pub struct AccountSelectionWidget<'a> {
account_manager: AccountManager<'a>, account_manager: &'a mut AccountManager,
simple_preview_controller: SimpleProfilePreviewController<'a>, simple_preview_controller: SimpleProfilePreviewController<'a>,
} }
@@ -249,7 +244,7 @@ impl<'a> AccountSelectionWidget<'a> {
scroll_area().show(ui, |ui| { scroll_area().show(ui, |ui| {
ui.horizontal_wrapped(|ui| { ui.horizontal_wrapped(|ui| {
let clicked_at = self.simple_preview_controller.view_profile_previews( let clicked_at = self.simple_preview_controller.view_profile_previews(
&self.account_manager, self.account_manager,
ui, ui,
|ui, preview, index| { |ui, preview, index| {
let resp = ui.add_sized(preview.dimensions(), |ui: &mut egui::Ui| { let resp = ui.add_sized(preview.dimensions(), |ui: &mut egui::Ui| {
@@ -278,7 +273,7 @@ impl<'a> AccountSelectionWidget<'a> {
impl<'a> AccountSelectionWidget<'a> { impl<'a> AccountSelectionWidget<'a> {
pub fn new( pub fn new(
account_manager: AccountManager<'a>, account_manager: &'a mut AccountManager,
simple_preview_controller: SimpleProfilePreviewController<'a>, simple_preview_controller: SimpleProfilePreviewController<'a>,
) -> Self { ) -> Self {
AccountSelectionWidget { AccountSelectionWidget {
@@ -301,7 +296,7 @@ mod preview {
use std::path::Path; use std::path::Path;
pub struct AccountManagementPreview { pub struct AccountManagementPreview {
accounts: Vec<UserAccount>, account_manager: AccountManager,
ndb: Ndb, ndb: Ndb,
img_cache: ImageCache, img_cache: ImageCache,
} }
@@ -320,11 +315,16 @@ mod preview {
impl AccountManagementPreview { impl AccountManagementPreview {
fn new() -> Self { fn new() -> Self {
let mut account_manager =
AccountManager::new(KeyStorage::None, RelayGenerator::Constant, || {});
let accounts = test_data::get_test_accounts(); let accounts = test_data::get_test_accounts();
accounts
.into_iter()
.for_each(|acc| account_manager.add_account(acc.key, || {}));
let (ndb, img_cache) = get_ndb_and_img_cache(); let (ndb, img_cache) = get_ndb_and_img_cache();
AccountManagementPreview { AccountManagementPreview {
accounts, account_manager,
ndb, ndb,
img_cache, img_cache,
} }
@@ -333,15 +333,9 @@ mod preview {
impl View for AccountManagementPreview { impl View for AccountManagementPreview {
fn ui(&mut self, ui: &mut egui::Ui) { fn ui(&mut self, ui: &mut egui::Ui) {
let account_manager = AccountManager::new(
&mut self.accounts,
KeyStorage::None,
RelayGenerator::Constant,
);
ui.add_space(24.0); ui.add_space(24.0);
AccountManagementView::new( AccountManagementView::new(
account_manager, &mut self.account_manager,
SimpleProfilePreviewController::new(&self.ndb, &mut self.img_cache), SimpleProfilePreviewController::new(&self.ndb, &mut self.img_cache),
) )
.ui(ui); .ui(ui);
@@ -357,17 +351,22 @@ mod preview {
} }
pub struct AccountSelectionPreview { pub struct AccountSelectionPreview {
accounts: Vec<UserAccount>, account_manager: AccountManager,
ndb: Ndb, ndb: Ndb,
img_cache: ImageCache, img_cache: ImageCache,
} }
impl AccountSelectionPreview { impl AccountSelectionPreview {
fn new() -> Self { fn new() -> Self {
let mut account_manager =
AccountManager::new(KeyStorage::None, RelayGenerator::Constant, || {});
let accounts = test_data::get_test_accounts(); let accounts = test_data::get_test_accounts();
accounts
.into_iter()
.for_each(|acc| account_manager.add_account(acc.key, || {}));
let (ndb, img_cache) = get_ndb_and_img_cache(); let (ndb, img_cache) = get_ndb_and_img_cache();
AccountSelectionPreview { AccountSelectionPreview {
accounts, account_manager,
ndb, ndb,
img_cache, img_cache,
} }
@@ -376,14 +375,8 @@ mod preview {
impl View for AccountSelectionPreview { impl View for AccountSelectionPreview {
fn ui(&mut self, ui: &mut egui::Ui) { fn ui(&mut self, ui: &mut egui::Ui) {
let account_manager = AccountManager::new(
&mut self.accounts,
KeyStorage::None,
RelayGenerator::Constant,
);
let mut widget = AccountSelectionWidget::new( let mut widget = AccountSelectionWidget::new(
account_manager, &mut self.account_manager,
SimpleProfilePreviewController::new(&self.ndb, &mut self.img_cache), SimpleProfilePreviewController::new(&self.ndb, &mut self.img_cache),
); );

View File

@@ -91,7 +91,7 @@ impl<'a> DesktopGlobalPopup<'a> {
mod preview { mod preview {
use crate::{ use crate::{
test_data::get_test_accounts, test_data,
ui::{DesktopSidePanel, Preview, View}, ui::{DesktopSidePanel, Preview, View},
Damus, Damus,
}; };
@@ -113,7 +113,10 @@ mod preview {
impl GlobalPopupPreview { impl GlobalPopupPreview {
fn new() -> Self { fn new() -> Self {
let mut app = Damus::mock("."); let mut app = Damus::mock(".");
app.accounts = get_test_accounts(); let accounts = test_data::get_test_accounts();
accounts
.into_iter()
.for_each(|acc| app.account_manager.add_account(acc.key, || {}));
GlobalPopupPreview { app } GlobalPopupPreview { app }
} }
} }