mod.rs (8122B)
1 use enostr::{FullKeypair, Pubkey}; 2 use nostrdb::{Ndb, Transaction}; 3 4 use notedeck::{Accounts, AppContext, DragResponse, Localization, SingleUnkIdAction, UnknownIds}; 5 use notedeck_ui::nip51_set::Nip51SetUiCache; 6 7 pub use crate::accounts::route::AccountsResponse; 8 use crate::app::get_active_columns_mut; 9 use crate::decks::DecksCache; 10 use crate::onboarding::Onboarding; 11 use crate::profile::{send_default_dms_relay_list, send_new_contact_list}; 12 use crate::subscriptions::Subscriptions; 13 use crate::ui::onboarding::{FollowPackOnboardingView, FollowPacksResponse, OnboardingResponse}; 14 use crate::{ 15 login_manager::AcquireKeyState, 16 route::Route, 17 ui::{ 18 account_login_view::{AccountLoginResponse, AccountLoginView}, 19 accounts::{AccountsView, AccountsViewResponse}, 20 }, 21 }; 22 use tracing::info; 23 24 mod route; 25 26 pub use route::{AccountsRoute, AccountsRouteResponse}; 27 28 impl AddAccountAction { 29 // Simple wrapper around processing the unknown action to expose too 30 // much internal logic. This allows us to have a must_use on our 31 // LoginAction type, otherwise the SingleUnkIdAction's must_use will 32 // be lost when returned in the login action 33 pub fn process_action(&mut self, ids: &mut UnknownIds, ndb: &Ndb, txn: &Transaction) { 34 self.unk_id_action.process_action(ids, ndb, txn); 35 } 36 } 37 38 #[derive(Debug, Clone)] 39 pub struct SwitchAccountAction { 40 pub source_column: usize, 41 42 /// The account to switch to 43 pub switch_to: Pubkey, 44 pub switching_to_new: bool, 45 } 46 47 impl SwitchAccountAction { 48 pub fn new(source_column: usize, switch_to: Pubkey) -> Self { 49 SwitchAccountAction { 50 source_column, 51 switch_to, 52 switching_to_new: false, 53 } 54 } 55 56 pub fn switching_to_new(mut self) -> Self { 57 self.switching_to_new = true; 58 self 59 } 60 } 61 62 #[derive(Debug)] 63 pub enum AccountsAction { 64 Switch(SwitchAccountAction), 65 Remove(Pubkey), 66 } 67 68 #[must_use = "You must call process_login_action on this to handle unknown ids"] 69 pub struct AddAccountAction { 70 pub accounts_action: Option<AccountsAction>, 71 pub unk_id_action: SingleUnkIdAction, 72 } 73 74 /// Render account management views from a route 75 #[allow(clippy::too_many_arguments)] 76 pub fn render_accounts_route( 77 ui: &mut egui::Ui, 78 app_ctx: &mut AppContext, 79 login_state: &mut AcquireKeyState, 80 onboarding: &mut Onboarding, 81 follow_packs_ui: &mut Nip51SetUiCache, 82 route: AccountsRoute, 83 ) -> DragResponse<AccountsResponse> { 84 match route { 85 AccountsRoute::Accounts => AccountsView::new( 86 app_ctx.ndb, 87 app_ctx.accounts, 88 app_ctx.media_jobs.sender(), 89 app_ctx.img_cache, 90 app_ctx.i18n, 91 ) 92 .ui(ui) 93 .map_output(AccountsRouteResponse::Accounts) 94 .map_output(AccountsResponse::Account), 95 AccountsRoute::AddAccount => { 96 let action = AccountLoginView::new(login_state, app_ctx.clipboard, app_ctx.i18n) 97 .ui(ui) 98 .inner 99 .map(AccountsRouteResponse::AddAccount) 100 .map(AccountsResponse::Account); 101 DragResponse::output(action) 102 } 103 AccountsRoute::Onboarding => FollowPackOnboardingView::new( 104 onboarding, 105 follow_packs_ui, 106 app_ctx.ndb, 107 app_ctx.img_cache, 108 app_ctx.i18n, 109 app_ctx.media_jobs.sender(), 110 ) 111 .ui(ui) 112 .map_output(|r| match r { 113 OnboardingResponse::FollowPacks(follow_packs_response) => { 114 AccountsResponse::Account(AccountsRouteResponse::AddAccount( 115 AccountLoginResponse::Onboarding(follow_packs_response), 116 )) 117 } 118 OnboardingResponse::ViewProfile(pubkey) => AccountsResponse::ViewProfile(pubkey), 119 }), 120 } 121 } 122 123 pub fn process_accounts_view_response( 124 i18n: &mut Localization, 125 accounts: &mut Accounts, 126 decks: &mut DecksCache, 127 col: usize, 128 response: AccountsViewResponse, 129 ) -> Option<AccountsAction> { 130 let router = get_active_columns_mut(i18n, accounts, decks) 131 .column_mut(col) 132 .router_mut(); 133 let mut action = None; 134 match response { 135 AccountsViewResponse::RemoveAccount(pk_to_remove) => { 136 let cur_action = AccountsAction::Remove(pk_to_remove); 137 info!("account selection: {:?}", action); 138 action = Some(cur_action); 139 } 140 AccountsViewResponse::SelectAccount(new_pk) => { 141 let acc_sel = AccountsAction::Switch(SwitchAccountAction::new(col, new_pk)); 142 info!("account selection: {:?}", acc_sel); 143 action = Some(acc_sel); 144 } 145 AccountsViewResponse::RouteToLogin => { 146 router.route_to(Route::add_account()); 147 } 148 } 149 action 150 } 151 152 pub fn process_login_view_response( 153 app_ctx: &mut AppContext, 154 decks: &mut DecksCache, 155 subs: &mut Subscriptions, 156 onboarding: &mut Onboarding, 157 col: usize, 158 response: AccountLoginResponse, 159 ) -> AddAccountAction { 160 let cur_router = get_active_columns_mut(app_ctx.i18n, app_ctx.accounts, decks) 161 .column_mut(col) 162 .router_mut(); 163 164 let r = match response { 165 AccountLoginResponse::LoginWith(keypair) => { 166 cur_router.go_back(); 167 app_ctx.accounts.add_account(keypair) 168 } 169 AccountLoginResponse::CreatingNew => { 170 cur_router.route_to(Route::Accounts(AccountsRoute::Onboarding)); 171 172 onboarding.process(app_ctx.pool, app_ctx.ndb, subs, app_ctx.unknown_ids); 173 174 None 175 } 176 AccountLoginResponse::Onboarding(onboarding_response) => match onboarding_response { 177 FollowPacksResponse::NoFollowPacks => { 178 onboarding.process(app_ctx.pool, app_ctx.ndb, subs, app_ctx.unknown_ids); 179 None 180 } 181 FollowPacksResponse::UserSelectedPacks(nip51_sets_ui_state) => { 182 let pks_to_follow = nip51_sets_ui_state.get_all_selected(); 183 184 let kp = FullKeypair::generate(); 185 186 send_new_contact_list(kp.to_filled(), app_ctx.ndb, app_ctx.pool, pks_to_follow); 187 send_default_dms_relay_list(kp.to_filled(), app_ctx.ndb, app_ctx.pool); 188 cur_router.go_back(); 189 onboarding.end_onboarding(app_ctx.pool, app_ctx.ndb); 190 191 app_ctx.accounts.add_account(kp.to_keypair()) 192 } 193 }, 194 }; 195 196 if let Some(action) = r { 197 AddAccountAction { 198 accounts_action: Some(AccountsAction::Switch(SwitchAccountAction { 199 source_column: col, 200 switch_to: action.switch_to, 201 switching_to_new: true, 202 })), 203 unk_id_action: action.unk_id_action, 204 } 205 } else { 206 AddAccountAction { 207 accounts_action: None, 208 unk_id_action: SingleUnkIdAction::NoAction, 209 } 210 } 211 } 212 213 impl AccountsRouteResponse { 214 pub fn process( 215 self, 216 app_ctx: &mut AppContext, 217 app: &mut crate::Damus, 218 col: usize, 219 ) -> AddAccountAction { 220 match self { 221 AccountsRouteResponse::Accounts(response) => { 222 let action = process_accounts_view_response( 223 app_ctx.i18n, 224 app_ctx.accounts, 225 &mut app.decks_cache, 226 col, 227 response, 228 ); 229 AddAccountAction { 230 accounts_action: action, 231 unk_id_action: notedeck::SingleUnkIdAction::no_action(), 232 } 233 } 234 AccountsRouteResponse::AddAccount(response) => { 235 let action = process_login_view_response( 236 app_ctx, 237 &mut app.decks_cache, 238 &mut app.subscriptions, 239 &mut app.onboarding, 240 col, 241 response, 242 ); 243 app.view_state.login = Default::default(); 244 245 action 246 } 247 } 248 } 249 }