account_login_view.rs (4811B)
1 use crate::app_style::NotedeckTextStyle; 2 use crate::key_parsing::AcquireKeyError; 3 use crate::login_manager::AcquireKeyState; 4 use crate::ui::{Preview, PreviewConfig, View}; 5 use egui::TextEdit; 6 use egui::{Align, Button, Color32, Frame, InnerResponse, Margin, RichText, Vec2}; 7 use enostr::Keypair; 8 9 pub struct AccountLoginView<'a> { 10 manager: &'a mut AcquireKeyState, 11 } 12 13 pub enum AccountLoginResponse { 14 CreateNew, 15 LoginWith(Keypair), 16 } 17 18 impl<'a> AccountLoginView<'a> { 19 pub fn new(state: &'a mut AcquireKeyState) -> Self { 20 AccountLoginView { manager: state } 21 } 22 23 pub fn ui(&mut self, ui: &mut egui::Ui) -> InnerResponse<Option<AccountLoginResponse>> { 24 Frame::none() 25 .outer_margin(12.0) 26 .show(ui, |ui| self.show(ui)) 27 } 28 29 fn show(&mut self, ui: &mut egui::Ui) -> Option<AccountLoginResponse> { 30 ui.vertical(|ui| { 31 ui.vertical_centered(|ui| { 32 ui.add_space(32.0); 33 ui.label(login_title_text()); 34 }); 35 36 ui.horizontal(|ui| { 37 ui.label(login_textedit_info_text()); 38 }); 39 40 ui.vertical_centered_justified(|ui| { 41 ui.add(login_textedit(self.manager)); 42 43 self.loading_and_error(ui); 44 45 if ui.add(login_button()).clicked() { 46 self.manager.apply_acquire(); 47 } 48 }); 49 50 ui.horizontal(|ui| { 51 ui.label( 52 RichText::new("New to Nostr?") 53 .color(ui.style().visuals.noninteractive().fg_stroke.color) 54 .text_style(NotedeckTextStyle::Body.text_style()), 55 ); 56 57 if ui 58 .add(Button::new(RichText::new("Create Account")).frame(false)) 59 .clicked() 60 { 61 self.manager.should_create_new(); 62 } 63 }); 64 }); 65 66 if self.manager.check_for_create_new() { 67 return Some(AccountLoginResponse::CreateNew); 68 } 69 70 if let Some(keypair) = self.manager.check_for_successful_login() { 71 return Some(AccountLoginResponse::LoginWith(keypair)); 72 } 73 None 74 } 75 76 fn loading_and_error(&mut self, ui: &mut egui::Ui) { 77 ui.add_space(8.0); 78 79 ui.vertical_centered(|ui| { 80 if self.manager.is_awaiting_network() { 81 ui.add(egui::Spinner::new()); 82 } 83 }); 84 85 if let Some(err) = self.manager.check_for_error() { 86 show_error(ui, err); 87 } 88 89 ui.add_space(8.0); 90 } 91 } 92 93 fn show_error(ui: &mut egui::Ui, err: &AcquireKeyError) { 94 ui.horizontal(|ui| { 95 let error_label = match err { 96 AcquireKeyError::InvalidKey => { 97 egui::Label::new(RichText::new("Invalid key.").color(ui.visuals().error_fg_color)) 98 } 99 AcquireKeyError::Nip05Failed(e) => { 100 egui::Label::new(RichText::new(e).color(ui.visuals().error_fg_color)) 101 } 102 }; 103 ui.add(error_label.truncate()); 104 }); 105 } 106 107 fn login_title_text() -> RichText { 108 RichText::new("Login") 109 .text_style(NotedeckTextStyle::Heading2.text_style()) 110 .strong() 111 } 112 113 fn login_textedit_info_text() -> RichText { 114 RichText::new("Enter your key") 115 .strong() 116 .text_style(NotedeckTextStyle::Body.text_style()) 117 } 118 119 fn login_button() -> Button<'static> { 120 Button::new( 121 RichText::new("Login now — let's do this!") 122 .text_style(NotedeckTextStyle::Body.text_style()) 123 .strong(), 124 ) 125 .fill(Color32::from_rgb(0xF8, 0x69, 0xB6)) // TODO: gradient 126 .min_size(Vec2::new(0.0, 40.0)) 127 } 128 129 fn login_textedit(manager: &mut AcquireKeyState) -> TextEdit { 130 manager.get_acquire_textedit(|text| { 131 egui::TextEdit::singleline(text) 132 .hint_text( 133 RichText::new("Enter your public key (npub), nostr address (e.g. vrod@damus.io), or private key (nsec) here...") 134 .text_style(NotedeckTextStyle::Body.text_style()), 135 ) 136 .vertical_align(Align::Center) 137 .min_size(Vec2::new(0.0, 40.0)) 138 .margin(Margin::same(12.0)) 139 }) 140 } 141 142 mod preview { 143 use super::*; 144 145 pub struct AccountLoginPreview { 146 manager: AcquireKeyState, 147 } 148 149 impl View for AccountLoginPreview { 150 fn ui(&mut self, ui: &mut egui::Ui) { 151 AccountLoginView::new(&mut self.manager).ui(ui); 152 } 153 } 154 155 impl Preview for AccountLoginView<'_> { 156 type Prev = AccountLoginPreview; 157 158 fn preview(cfg: PreviewConfig) -> Self::Prev { 159 let _ = cfg; 160 let manager = AcquireKeyState::new(); 161 AccountLoginPreview { manager } 162 } 163 } 164 }