commit 950a47119eb94364cee7036d914381d4dce49fbb
parent 3a9c7607f330e53eb6fa06b117742bc87f7edba2
Author: kernelkind <kernelkind@gmail.com>
Date: Mon, 9 Sep 2024 18:31:05 -0400
implement stateful account management view
`./preview StatefulAccountManagementView`
Signed-off-by: kernelkind <kernelkind@gmail.com>
Diffstat:
5 files changed, 166 insertions(+), 10 deletions(-)
diff --git a/src/account_manager.rs b/src/account_manager.rs
@@ -1,11 +1,13 @@
use std::cmp::Ordering;
-use enostr::{FilledKeypair, Keypair};
+use enostr::{FilledKeypair, FullKeypair, Keypair};
pub use crate::user_account::UserAccount;
use crate::{
key_storage::{KeyStorage, KeyStorageResponse, KeyStorageType},
- ui::account_management::AccountManagementViewResponse,
+ ui::{
+ account_login_view::AccountLoginResponse, account_management::AccountManagementViewResponse,
+ },
};
use tracing::info;
@@ -120,7 +122,7 @@ impl AccountManager {
}
}
-pub fn process_view_response(
+pub fn process_management_view_response_stateless(
manager: &mut AccountManager,
response: AccountManagementViewResponse,
) {
@@ -131,5 +133,17 @@ pub fn process_view_response(
AccountManagementViewResponse::SelectAccount(index) => {
manager.select_account(index);
}
+ AccountManagementViewResponse::RouteToLogin => {}
+ }
+}
+
+pub fn process_login_view_response(manager: &mut AccountManager, response: AccountLoginResponse) {
+ match response {
+ AccountLoginResponse::CreateNew => {
+ manager.add_account(FullKeypair::generate().to_keypair());
+ }
+ AccountLoginResponse::LoginWith(keypair) => {
+ manager.add_account(keypair);
+ }
}
}
diff --git a/src/ui/account_management.rs b/src/ui/account_management.rs
@@ -14,9 +14,11 @@ use super::profile_preview_controller::profile_preview_view;
pub struct AccountManagementView {}
+#[derive(Clone, Debug)]
pub enum AccountManagementViewResponse {
SelectAccount(usize),
RemoveAccount(usize),
+ RouteToLogin,
}
impl AccountManagementView {
@@ -27,7 +29,9 @@ impl AccountManagementView {
img_cache: &mut ImageCache,
) -> InnerResponse<Option<AccountManagementViewResponse>> {
Frame::none().outer_margin(12.0).show(ui, |ui| {
- Self::top_section_buttons_widget(ui);
+ if let Some(resp) = Self::top_section_buttons_widget(ui).inner {
+ return Some(resp);
+ }
ui.add_space(8.0);
scroll_area()
@@ -88,19 +92,23 @@ impl AccountManagementView {
.inner
}
- fn top_section_buttons_widget(ui: &mut egui::Ui) -> egui::Response {
+ fn top_section_buttons_widget(
+ ui: &mut egui::Ui,
+ ) -> InnerResponse<Option<AccountManagementViewResponse>> {
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 ui.add(add_account_button()).clicked() {
- // TODO: route to AccountLoginView
+ Some(AccountManagementViewResponse::RouteToLogin)
+ } else {
+ None
}
},
- );
+ )
+ .inner
})
- .response
}
}
@@ -194,7 +202,7 @@ fn selected_widget() -> impl egui::Widget {
mod preview {
use super::*;
- use crate::{account_manager::process_view_response, test_data};
+ use crate::{account_manager::process_management_view_response_stateless, test_data};
pub struct AccountManagementPreview {
app: Damus,
@@ -219,7 +227,7 @@ mod preview {
)
.inner
{
- process_view_response(&mut self.app.account_manager, response)
+ process_management_view_response_stateless(&mut self.app.account_manager, response)
}
}
}
diff --git a/src/ui/mod.rs b/src/ui/mod.rs
@@ -8,6 +8,7 @@ pub mod preview;
pub mod profile;
pub mod relay;
pub mod side_panel;
+pub mod stateful_account_management;
pub mod thread;
pub mod timeline;
pub mod username;
diff --git a/src/ui/stateful_account_management.rs b/src/ui/stateful_account_management.rs
@@ -0,0 +1,131 @@
+use egui::Ui;
+use egui_nav::{Nav, NavAction};
+use nostrdb::Ndb;
+
+use crate::{
+ account_manager::{process_login_view_response, AccountManager},
+ imgcache::ImageCache,
+ login_manager::LoginState,
+ routable_widget_state::RoutableWidgetState,
+ route::{ManageAccountRoute, ManageAcountRouteResponse},
+ Damus,
+};
+
+use super::{
+ account_login_view::AccountLoginView, account_management::AccountManagementViewResponse,
+ AccountManagementView,
+};
+
+pub struct StatefulAccountManagementView {}
+
+impl StatefulAccountManagementView {
+ pub fn show(
+ ui: &mut Ui,
+ account_management_state: &mut RoutableWidgetState<ManageAccountRoute>,
+ account_manager: &mut AccountManager,
+ img_cache: &mut ImageCache,
+ login_state: &mut LoginState,
+ ndb: &Ndb,
+ ) {
+ let routes = account_management_state.get_routes();
+
+ let nav_response =
+ Nav::new(routes)
+ .title(false)
+ .navigating(false)
+ .show_mut(ui, |ui, nav| match nav.top() {
+ ManageAccountRoute::AccountManagement => {
+ AccountManagementView::ui(ui, account_manager, ndb, img_cache)
+ .inner
+ .map(ManageAcountRouteResponse::AccountManagement)
+ }
+ ManageAccountRoute::AddAccount => AccountLoginView::new(login_state)
+ .ui(ui)
+ .inner
+ .map(ManageAcountRouteResponse::AddAccount),
+ });
+
+ if let Some(resp) = nav_response.inner {
+ match resp {
+ ManageAcountRouteResponse::AccountManagement(response) => {
+ process_management_view_response_stateful(
+ response,
+ account_manager,
+ account_management_state,
+ );
+ }
+ ManageAcountRouteResponse::AddAccount(response) => {
+ process_login_view_response(account_manager, response);
+ *login_state = Default::default();
+ account_management_state.go_back();
+ }
+ }
+ }
+ if let Some(NavAction::Returned) = nav_response.action {
+ account_management_state.go_back();
+ }
+ }
+}
+
+pub fn process_management_view_response_stateful(
+ response: AccountManagementViewResponse,
+ manager: &mut AccountManager,
+ state: &mut RoutableWidgetState<ManageAccountRoute>,
+) {
+ match response {
+ AccountManagementViewResponse::RemoveAccount(index) => {
+ manager.remove_account(index);
+ }
+ AccountManagementViewResponse::SelectAccount(index) => {
+ manager.select_account(index);
+ }
+ AccountManagementViewResponse::RouteToLogin => {
+ state.route_to(ManageAccountRoute::AddAccount);
+ }
+ }
+}
+
+mod preview {
+ use crate::{
+ test_data,
+ ui::{Preview, PreviewConfig, View},
+ };
+
+ use super::*;
+
+ pub struct StatefulAccountManagementPreview {
+ app: Damus,
+ }
+
+ impl StatefulAccountManagementPreview {
+ fn new() -> Self {
+ let mut app = test_data::test_app();
+ app.account_management_view_state
+ .route_to(ManageAccountRoute::AccountManagement);
+
+ StatefulAccountManagementPreview { app }
+ }
+ }
+
+ impl View for StatefulAccountManagementPreview {
+ fn ui(&mut self, ui: &mut egui::Ui) {
+ StatefulAccountManagementView::show(
+ ui,
+ &mut self.app.account_management_view_state,
+ &mut self.app.account_manager,
+ &mut self.app.img_cache,
+ &mut self.app.login_state,
+ &self.app.ndb,
+ );
+ }
+ }
+
+ impl Preview for StatefulAccountManagementView {
+ type Prev = StatefulAccountManagementPreview;
+
+ fn preview(cfg: PreviewConfig) -> Self::Prev {
+ let _ = cfg;
+ StatefulAccountManagementPreview::new()
+ }
+ }
+}
diff --git a/src/ui_preview/main.rs b/src/ui_preview/main.rs
@@ -2,6 +2,7 @@ use notedeck::app_creation::{
generate_mobile_emulator_native_options, generate_native_options, setup_cc,
};
use notedeck::ui::account_login_view::AccountLoginView;
+use notedeck::ui::stateful_account_management::StatefulAccountManagementView;
use notedeck::ui::{
AccountManagementView, AccountSelectionWidget, DesktopSidePanel, PostView, Preview, PreviewApp,
PreviewConfig, ProfilePic, ProfilePreview, RelayView,
@@ -104,5 +105,6 @@ async fn main() {
AccountSelectionWidget,
DesktopSidePanel,
PostView,
+ StatefulAccountManagementView,
);
}