AccountManagementView
View used to add and remove accounts from the app Signed-off-by: kernelkind <kernelkind@gmail.com> Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
committed by
William Casarin
parent
93800e0d04
commit
e9c3596067
107
src/account_manager.rs
Normal file
107
src/account_manager.rs
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
use nostr_sdk::Keys;
|
||||||
|
use nostrdb::{Ndb, Transaction};
|
||||||
|
|
||||||
|
pub use crate::user_account::UserAccount;
|
||||||
|
use crate::{
|
||||||
|
imgcache::ImageCache, key_storage::KeyStorage, relay_generation::RelayGenerator,
|
||||||
|
ui::profile::preview::SimpleProfilePreview,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct SimpleProfilePreviewController<'a> {
|
||||||
|
ndb: &'a Ndb,
|
||||||
|
img_cache: &'a mut ImageCache,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> SimpleProfilePreviewController<'a> {
|
||||||
|
pub fn new(ndb: &'a Ndb, img_cache: &'a mut ImageCache) -> Self {
|
||||||
|
SimpleProfilePreviewController { ndb, img_cache }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_profile_previews(
|
||||||
|
&mut self,
|
||||||
|
account_manager: &AccountManager<'a>,
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
edit_mode: bool,
|
||||||
|
add_preview_ui: fn(
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
preview: SimpleProfilePreview,
|
||||||
|
edit_mode: bool,
|
||||||
|
) -> bool,
|
||||||
|
) -> Option<Vec<usize>> {
|
||||||
|
let mut to_remove: Option<Vec<usize>> = None;
|
||||||
|
|
||||||
|
for i in 0..account_manager.num_accounts() {
|
||||||
|
if let Some(account) = account_manager.get_account(i) {
|
||||||
|
if let Ok(txn) = Transaction::new(self.ndb) {
|
||||||
|
let profile = self
|
||||||
|
.ndb
|
||||||
|
.get_profile_by_pubkey(&txn, &account.key.public_key().to_bytes());
|
||||||
|
|
||||||
|
if let Ok(profile) = profile {
|
||||||
|
let preview = SimpleProfilePreview::new(&profile, self.img_cache);
|
||||||
|
|
||||||
|
if add_preview_ui(ui, preview, edit_mode) {
|
||||||
|
if to_remove.is_none() {
|
||||||
|
to_remove = Some(Vec::new());
|
||||||
|
}
|
||||||
|
to_remove.as_mut().unwrap().push(i);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
to_remove
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The interface for managing the user's accounts.
|
||||||
|
/// Represents all user-facing operations related to account management.
|
||||||
|
pub struct AccountManager<'a> {
|
||||||
|
accounts: &'a mut Vec<UserAccount>,
|
||||||
|
key_store: KeyStorage,
|
||||||
|
relay_generator: RelayGenerator,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> AccountManager<'a> {
|
||||||
|
pub fn new(
|
||||||
|
accounts: &'a mut Vec<UserAccount>,
|
||||||
|
key_store: KeyStorage,
|
||||||
|
relay_generator: RelayGenerator,
|
||||||
|
) -> Self {
|
||||||
|
AccountManager {
|
||||||
|
accounts,
|
||||||
|
key_store,
|
||||||
|
relay_generator,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_accounts(&'a self) -> &'a Vec<UserAccount> {
|
||||||
|
self.accounts
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_account(&'a self, index: usize) -> Option<&'a UserAccount> {
|
||||||
|
self.accounts.get(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_account(&mut self, index: usize) {
|
||||||
|
if let Some(account) = self.accounts.get(index) {
|
||||||
|
self.key_store.remove_key(&account.key);
|
||||||
|
}
|
||||||
|
if index < self.accounts.len() {
|
||||||
|
self.accounts.remove(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_account(&'a mut self, key: Keys, ctx: &egui::Context) {
|
||||||
|
self.key_store.add_key(&key);
|
||||||
|
let relays = self.relay_generator.generate_relays_for(&key, ctx);
|
||||||
|
let account = UserAccount { key, relays };
|
||||||
|
|
||||||
|
self.accounts.push(account)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn num_accounts(&self) -> usize {
|
||||||
|
self.accounts.len()
|
||||||
|
}
|
||||||
|
}
|
||||||
48
src/key_storage.rs
Normal file
48
src/key_storage.rs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
use nostr_sdk::Keys;
|
||||||
|
|
||||||
|
pub enum KeyStorage {
|
||||||
|
None,
|
||||||
|
// TODO:
|
||||||
|
// Linux,
|
||||||
|
// Windows,
|
||||||
|
// Android,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KeyStorage {
|
||||||
|
pub fn get_keys(&self) -> Result<Vec<Keys>, KeyStorageError> {
|
||||||
|
match self {
|
||||||
|
Self::None => Ok(Vec::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_key(&self, key: &Keys) -> Result<(), KeyStorageError> {
|
||||||
|
match self {
|
||||||
|
Self::None => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_key(&self, key: &Keys) -> Result<(), KeyStorageError> {
|
||||||
|
match self {
|
||||||
|
Self::None => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum KeyStorageError<'a> {
|
||||||
|
Retrieval,
|
||||||
|
Addition(&'a Keys),
|
||||||
|
Removal(&'a Keys),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for KeyStorageError<'_> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Retrieval => write!(f, "Failed to retrieve keys."),
|
||||||
|
Self::Addition(key) => write!(f, "Failed to add key: {:?}", key.public_key()),
|
||||||
|
Self::Removal(key) => write!(f, "Failed to remove key: {:?}", key.public_key()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for KeyStorageError<'_> {}
|
||||||
@@ -4,6 +4,7 @@ mod error;
|
|||||||
//mod note;
|
//mod note;
|
||||||
//mod block;
|
//mod block;
|
||||||
mod abbrev;
|
mod abbrev;
|
||||||
|
pub mod account_manager;
|
||||||
pub mod app_creation;
|
pub mod app_creation;
|
||||||
mod app_style;
|
mod app_style;
|
||||||
mod colors;
|
mod colors;
|
||||||
@@ -13,9 +14,11 @@ mod frame_history;
|
|||||||
mod images;
|
mod images;
|
||||||
mod imgcache;
|
mod imgcache;
|
||||||
mod key_parsing;
|
mod key_parsing;
|
||||||
|
mod key_storage;
|
||||||
pub mod login_manager;
|
pub mod login_manager;
|
||||||
mod notecache;
|
mod notecache;
|
||||||
mod profile;
|
mod profile;
|
||||||
|
mod relay_generation;
|
||||||
pub mod relay_pool_manager;
|
pub mod relay_pool_manager;
|
||||||
mod result;
|
mod result;
|
||||||
mod test_data;
|
mod test_data;
|
||||||
@@ -23,6 +26,7 @@ mod time;
|
|||||||
mod timecache;
|
mod timecache;
|
||||||
mod timeline;
|
mod timeline;
|
||||||
pub mod ui;
|
pub mod ui;
|
||||||
|
mod user_account;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|||||||
54
src/relay_generation.rs
Normal file
54
src/relay_generation.rs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
use crate::relay_pool_manager::create_wakeup;
|
||||||
|
use enostr::RelayPool;
|
||||||
|
use nostr_sdk::Keys;
|
||||||
|
use tracing::error;
|
||||||
|
|
||||||
|
pub enum RelayGenerator {
|
||||||
|
GossipModel,
|
||||||
|
Nip65,
|
||||||
|
Constant,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RelayGenerator {
|
||||||
|
pub fn generate_relays_for(&self, key: &Keys, ctx: &egui::Context) -> RelayPool {
|
||||||
|
match self {
|
||||||
|
Self::GossipModel => generate_relays_gossip(key, ctx),
|
||||||
|
Self::Nip65 => generate_relays_nip65(key, ctx),
|
||||||
|
Self::Constant => generate_constant_relays(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_relays_gossip(key: &Keys, ctx: &egui::Context) -> RelayPool {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_relays_nip65(key: &Keys, ctx: &egui::Context) -> RelayPool {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_constant_relays(ctx: &egui::Context) -> RelayPool {
|
||||||
|
let mut pool = RelayPool::new();
|
||||||
|
let wakeup = create_wakeup(ctx);
|
||||||
|
|
||||||
|
if let Err(e) = pool.add_url("ws://localhost:8080".to_string(), wakeup.clone()) {
|
||||||
|
error!("{:?}", e)
|
||||||
|
}
|
||||||
|
if let Err(e) = pool.add_url("wss://relay.damus.io".to_string(), wakeup.clone()) {
|
||||||
|
error!("{:?}", e)
|
||||||
|
}
|
||||||
|
if let Err(e) = pool.add_url("wss://pyramid.fiatjaf.com".to_string(), wakeup.clone()) {
|
||||||
|
error!("{:?}", e)
|
||||||
|
}
|
||||||
|
if let Err(e) = pool.add_url("wss://nos.lol".to_string(), wakeup.clone()) {
|
||||||
|
error!("{:?}", e)
|
||||||
|
}
|
||||||
|
if let Err(e) = pool.add_url("wss://nostr.wine".to_string(), wakeup.clone()) {
|
||||||
|
error!("{:?}", e)
|
||||||
|
}
|
||||||
|
if let Err(e) = pool.add_url("wss://purplepag.es".to_string(), wakeup) {
|
||||||
|
error!("{:?}", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
pool
|
||||||
|
}
|
||||||
@@ -46,7 +46,7 @@ impl<'a> RelayPoolManager<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_wakeup(ctx: &egui::Context) -> impl Fn() + Send + Sync + Clone + 'static {
|
pub fn create_wakeup(ctx: &egui::Context) -> impl Fn() + Send + Sync + Clone + 'static {
|
||||||
let ctx = ctx.clone();
|
let ctx = ctx.clone();
|
||||||
move || {
|
move || {
|
||||||
ctx.request_repaint();
|
ctx.request_repaint();
|
||||||
|
|||||||
328
src/ui/account_management.rs
Normal file
328
src/ui/account_management.rs
Normal file
@@ -0,0 +1,328 @@
|
|||||||
|
use egui::{Align, Align2, Button, Frame, Layout, Margin, RichText, ScrollArea, Vec2, Window};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
account_manager::{AccountManager, SimpleProfilePreviewController},
|
||||||
|
app_style::NotedeckTextStyle,
|
||||||
|
ui::{self, Preview, View},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct AccountManagementView<'a> {
|
||||||
|
account_manager: AccountManager<'a>,
|
||||||
|
simple_preview_controller: SimpleProfilePreviewController<'a>,
|
||||||
|
edit_mode: &'a mut bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> View for AccountManagementView<'a> {
|
||||||
|
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||||
|
if ui::is_mobile(ui.ctx()) {
|
||||||
|
self.show_mobile(ui);
|
||||||
|
} else {
|
||||||
|
self.show(ui);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> AccountManagementView<'a> {
|
||||||
|
pub fn new(
|
||||||
|
account_manager: AccountManager<'a>,
|
||||||
|
simple_preview_controller: SimpleProfilePreviewController<'a>,
|
||||||
|
edit_mode: &'a mut bool,
|
||||||
|
) -> Self {
|
||||||
|
AccountManagementView {
|
||||||
|
account_manager,
|
||||||
|
simple_preview_controller,
|
||||||
|
edit_mode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show(&mut self, ui: &mut egui::Ui) {
|
||||||
|
ui.add_space(24.0);
|
||||||
|
let screen_size = ui.ctx().screen_rect();
|
||||||
|
let margin_amt = 128.0;
|
||||||
|
let window_size = Vec2::new(
|
||||||
|
screen_size.width() - margin_amt,
|
||||||
|
screen_size.height() - margin_amt,
|
||||||
|
);
|
||||||
|
|
||||||
|
Window::new("Account Management")
|
||||||
|
.frame(Frame::window(ui.style()))
|
||||||
|
.collapsible(false)
|
||||||
|
.anchor(Align2::CENTER_CENTER, [0.0, 0.0])
|
||||||
|
.resizable(false)
|
||||||
|
.title_bar(false)
|
||||||
|
.default_size(window_size)
|
||||||
|
.show(ui.ctx(), |ui| {
|
||||||
|
ui.add(title());
|
||||||
|
ui.add(self.buttons_widget());
|
||||||
|
ui.add_space(8.0);
|
||||||
|
self.show_accounts(ui);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_accounts(&mut self, ui: &mut egui::Ui) {
|
||||||
|
scroll_area().show(ui, |ui| {
|
||||||
|
ui.horizontal_wrapped(|ui| {
|
||||||
|
let maybe_remove = self.simple_preview_controller.set_profile_previews(
|
||||||
|
&self.account_manager,
|
||||||
|
ui,
|
||||||
|
*self.edit_mode,
|
||||||
|
|ui, preview, edit_mode| {
|
||||||
|
let mut should_remove = false;
|
||||||
|
|
||||||
|
ui.add_sized(preview.dimensions(), |ui: &mut egui::Ui| {
|
||||||
|
simple_preview_frame(ui)
|
||||||
|
.show(ui, |ui| {
|
||||||
|
ui.vertical_centered(|ui| {
|
||||||
|
ui.add(preview);
|
||||||
|
if edit_mode {
|
||||||
|
should_remove = ui
|
||||||
|
.add(delete_button(ui.visuals().dark_mode))
|
||||||
|
.clicked();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.response
|
||||||
|
});
|
||||||
|
should_remove
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
self.maybe_remove_accounts(maybe_remove);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_accounts_mobile(&mut self, ui: &mut egui::Ui) {
|
||||||
|
scroll_area().show(ui, |ui| {
|
||||||
|
ui.allocate_ui_with_layout(
|
||||||
|
Vec2::new(ui.available_size_before_wrap().x, 32.0),
|
||||||
|
Layout::top_down(egui::Align::Min),
|
||||||
|
|ui| {
|
||||||
|
let maybe_remove = self.simple_preview_controller.set_profile_previews(
|
||||||
|
&self.account_manager,
|
||||||
|
ui,
|
||||||
|
*self.edit_mode,
|
||||||
|
|ui, preview, edit_mode| {
|
||||||
|
let mut should_remove = false;
|
||||||
|
|
||||||
|
ui.add_sized(
|
||||||
|
Vec2::new(ui.available_width(), 50.0),
|
||||||
|
|ui: &mut egui::Ui| {
|
||||||
|
Frame::none()
|
||||||
|
.show(ui, |ui| {
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.add(preview);
|
||||||
|
if edit_mode {
|
||||||
|
ui.with_layout(
|
||||||
|
Layout::right_to_left(Align::Center),
|
||||||
|
|ui| {
|
||||||
|
should_remove = ui
|
||||||
|
.add(delete_button(
|
||||||
|
ui.visuals().dark_mode,
|
||||||
|
))
|
||||||
|
.clicked();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.response
|
||||||
|
},
|
||||||
|
);
|
||||||
|
ui.add_space(16.0);
|
||||||
|
should_remove
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
self.maybe_remove_accounts(maybe_remove);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn maybe_remove_accounts(&mut self, account_indices: Option<Vec<usize>>) {
|
||||||
|
if let Some(to_remove) = account_indices {
|
||||||
|
to_remove
|
||||||
|
.iter()
|
||||||
|
.for_each(|index| self.account_manager.remove_account(*index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_mobile(&mut self, ui: &mut egui::Ui) -> egui::Response {
|
||||||
|
egui::CentralPanel::default()
|
||||||
|
.show(ui.ctx(), |ui| {
|
||||||
|
ui.add(title());
|
||||||
|
ui.add(self.buttons_widget());
|
||||||
|
ui.add_space(8.0);
|
||||||
|
self.show_accounts_mobile(ui);
|
||||||
|
})
|
||||||
|
.response
|
||||||
|
}
|
||||||
|
|
||||||
|
fn buttons_widget(&mut self) -> impl egui::Widget + '_ {
|
||||||
|
|ui: &mut egui::Ui| {
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.allocate_ui_with_layout(
|
||||||
|
Vec2::new(ui.available_size_before_wrap().x, 32.0),
|
||||||
|
Layout::left_to_right(egui::Align::Center),
|
||||||
|
|ui| {
|
||||||
|
if *self.edit_mode {
|
||||||
|
if ui.add(done_account_button()).clicked() {
|
||||||
|
*self.edit_mode = false;
|
||||||
|
}
|
||||||
|
} else if ui.add(edit_account_button()).clicked() {
|
||||||
|
*self.edit_mode = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
ui.allocate_ui_with_layout(
|
||||||
|
Vec2::new(ui.available_size_before_wrap().x, 32.0),
|
||||||
|
Layout::right_to_left(egui::Align::Center),
|
||||||
|
|ui| {
|
||||||
|
if ui.add(add_account_button()).clicked() {
|
||||||
|
// TODO: route to AccountLoginView
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.response
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn simple_preview_frame(ui: &mut egui::Ui) -> Frame {
|
||||||
|
Frame::none()
|
||||||
|
.rounding(ui.visuals().window_rounding)
|
||||||
|
.fill(ui.visuals().window_fill)
|
||||||
|
.stroke(ui.visuals().window_stroke)
|
||||||
|
.outer_margin(Margin::same(2.0))
|
||||||
|
.inner_margin(12.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn title() -> impl egui::Widget {
|
||||||
|
|ui: &mut egui::Ui| {
|
||||||
|
ui.vertical_centered(|ui| {
|
||||||
|
ui.label(
|
||||||
|
RichText::new("Accounts")
|
||||||
|
.text_style(NotedeckTextStyle::Heading2.text_style())
|
||||||
|
.strong(),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.response
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scroll_area() -> ScrollArea {
|
||||||
|
egui::ScrollArea::vertical()
|
||||||
|
.scroll_bar_visibility(egui::scroll_area::ScrollBarVisibility::AlwaysHidden)
|
||||||
|
.auto_shrink([false; 2])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_account_button() -> Button<'static> {
|
||||||
|
Button::new("Add Account").min_size(Vec2::new(0.0, 32.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn edit_account_button() -> Button<'static> {
|
||||||
|
Button::new("Edit").min_size(Vec2::new(0.0, 32.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn done_account_button() -> Button<'static> {
|
||||||
|
Button::new("Done").min_size(Vec2::new(0.0, 32.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delete_button(_dark_mode: bool) -> egui::Button<'static> {
|
||||||
|
let img_data = egui::include_image!("../../assets/icons/delete_icon_4x.png");
|
||||||
|
|
||||||
|
egui::Button::image(egui::Image::new(img_data).max_width(30.0)).frame(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PREVIEWS
|
||||||
|
|
||||||
|
mod preview {
|
||||||
|
use nostr_sdk::{Keys, PublicKey};
|
||||||
|
use nostrdb::{Config, Ndb};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use crate::key_storage::KeyStorage;
|
||||||
|
use crate::relay_generation::RelayGenerator;
|
||||||
|
use crate::{account_manager::UserAccount, imgcache::ImageCache, test_data};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
pub struct AccountManagementPreview {
|
||||||
|
accounts: Vec<UserAccount>,
|
||||||
|
ndb: Ndb,
|
||||||
|
img_cache: ImageCache,
|
||||||
|
edit_mode: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AccountManagementPreview {
|
||||||
|
fn new() -> Self {
|
||||||
|
let account_hexes = [
|
||||||
|
"3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681",
|
||||||
|
"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245",
|
||||||
|
"bd1e19980e2c91e6dc657e92c25762ca882eb9272d2579e221f037f93788de91",
|
||||||
|
"5c10ed0678805156d39ef1ef6d46110fe1e7e590ae04986ccf48ba1299cb53e2",
|
||||||
|
"4c96d763eb2fe01910f7e7220b7c7ecdbe1a70057f344b9f79c28af080c3ee30",
|
||||||
|
"edf16b1dd61eab353a83af470cc13557029bff6827b4cb9b7fc9bdb632a2b8e6",
|
||||||
|
"3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681",
|
||||||
|
"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245",
|
||||||
|
"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245",
|
||||||
|
"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245",
|
||||||
|
];
|
||||||
|
|
||||||
|
let accounts: Vec<UserAccount> = account_hexes
|
||||||
|
.iter()
|
||||||
|
.map(|account_hex| {
|
||||||
|
let key = Keys::from_public_key(PublicKey::from_hex(account_hex).unwrap());
|
||||||
|
|
||||||
|
UserAccount {
|
||||||
|
key,
|
||||||
|
relays: test_data::sample_pool(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut config = Config::new();
|
||||||
|
config.set_ingester_threads(2);
|
||||||
|
|
||||||
|
let db_dir = Path::new(".");
|
||||||
|
let path = db_dir.to_str().unwrap();
|
||||||
|
let ndb = Ndb::new(path, &config).expect("ndb");
|
||||||
|
let imgcache_dir = db_dir.join("cache/img");
|
||||||
|
let img_cache = ImageCache::new(imgcache_dir);
|
||||||
|
|
||||||
|
AccountManagementPreview {
|
||||||
|
accounts,
|
||||||
|
ndb,
|
||||||
|
img_cache,
|
||||||
|
edit_mode: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl View for AccountManagementPreview {
|
||||||
|
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||||
|
let account_manager = AccountManager::new(
|
||||||
|
&mut self.accounts,
|
||||||
|
KeyStorage::None,
|
||||||
|
RelayGenerator::Constant,
|
||||||
|
);
|
||||||
|
|
||||||
|
AccountManagementView::new(
|
||||||
|
account_manager,
|
||||||
|
SimpleProfilePreviewController::new(&self.ndb, &mut self.img_cache),
|
||||||
|
&mut self.edit_mode,
|
||||||
|
)
|
||||||
|
.ui(ui);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Preview for AccountManagementView<'a> {
|
||||||
|
type Prev = AccountManagementPreview;
|
||||||
|
|
||||||
|
fn preview() -> Self::Prev {
|
||||||
|
AccountManagementPreview::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
pub mod account_login_view;
|
pub mod account_login_view;
|
||||||
|
pub mod account_management;
|
||||||
pub mod anim;
|
pub mod anim;
|
||||||
pub mod mention;
|
pub mod mention;
|
||||||
pub mod note;
|
pub mod note;
|
||||||
@@ -7,6 +8,7 @@ pub mod profile;
|
|||||||
pub mod relay;
|
pub mod relay;
|
||||||
pub mod username;
|
pub mod username;
|
||||||
|
|
||||||
|
pub use account_management::AccountManagementView;
|
||||||
pub use mention::Mention;
|
pub use mention::Mention;
|
||||||
pub use note::Note;
|
pub use note::Note;
|
||||||
pub use preview::{Preview, PreviewApp};
|
pub use preview::{Preview, PreviewApp};
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ use notedeck::app_creation::{
|
|||||||
generate_mobile_emulator_native_options, generate_native_options, setup_cc,
|
generate_mobile_emulator_native_options, generate_native_options, setup_cc,
|
||||||
};
|
};
|
||||||
use notedeck::ui::account_login_view::AccountLoginView;
|
use notedeck::ui::account_login_view::AccountLoginView;
|
||||||
use notedeck::ui::{Preview, PreviewApp, ProfilePic, ProfilePreview, RelayView};
|
use notedeck::ui::{
|
||||||
|
AccountManagementView, Preview, PreviewApp, ProfilePic, ProfilePreview, RelayView,
|
||||||
|
};
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
struct PreviewRunner {
|
struct PreviewRunner {
|
||||||
@@ -82,6 +84,7 @@ async fn main() {
|
|||||||
RelayView,
|
RelayView,
|
||||||
AccountLoginView,
|
AccountLoginView,
|
||||||
ProfilePreview,
|
ProfilePreview,
|
||||||
ProfilePic
|
ProfilePic,
|
||||||
|
AccountManagementView,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
6
src/user_account.rs
Normal file
6
src/user_account.rs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
use enostr::RelayPool;
|
||||||
|
|
||||||
|
pub struct UserAccount {
|
||||||
|
pub key: nostr_sdk::Keys,
|
||||||
|
pub relays: RelayPool,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user