notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

login_manager.rs (4821B)


      1 use crate::key_parsing::perform_key_retrieval;
      2 use crate::key_parsing::AcquireKeyError;
      3 use egui::{TextBuffer, TextEdit};
      4 use enostr::Keypair;
      5 use poll_promise::Promise;
      6 
      7 /// The state data for acquiring a nostr key
      8 #[derive(Default)]
      9 pub struct AcquireKeyState {
     10     desired_key: String,
     11     promise_query: Option<(String, Promise<Result<Keypair, AcquireKeyError>>)>,
     12     error: Option<AcquireKeyError>,
     13     key_on_error: Option<String>,
     14     should_create_new: bool,
     15 }
     16 
     17 impl<'a> AcquireKeyState {
     18     pub fn new() -> Self {
     19         AcquireKeyState::default()
     20     }
     21 
     22     /// Get the textedit for the UI without exposing the key variable
     23     pub fn get_acquire_textedit(
     24         &'a mut self,
     25         textedit_closure: fn(&'a mut dyn TextBuffer) -> TextEdit<'a>,
     26     ) -> TextEdit<'a> {
     27         textedit_closure(&mut self.desired_key)
     28     }
     29 
     30     /// User pressed the 'acquire' button
     31     pub fn apply_acquire(&'a mut self) {
     32         let new_promise = match &self.promise_query {
     33             Some((query, _)) => {
     34                 if query != &self.desired_key {
     35                     Some(perform_key_retrieval(&self.desired_key))
     36                 } else {
     37                     None
     38                 }
     39             }
     40             None => Some(perform_key_retrieval(&self.desired_key)),
     41         };
     42 
     43         if let Some(new_promise) = new_promise {
     44             self.promise_query = Some((self.desired_key.clone(), new_promise));
     45         }
     46     }
     47 
     48     /// Whether to indicate to the user that there is a network operation occuring
     49     pub fn is_awaiting_network(&self) -> bool {
     50         self.promise_query.is_some()
     51     }
     52 
     53     /// Whether to indicate to the user that a login error occured
     54     pub fn check_for_error(&'a mut self) -> Option<&'a AcquireKeyError> {
     55         if let Some(error_key) = &self.key_on_error {
     56             if self.desired_key != *error_key {
     57                 self.error = None;
     58                 self.key_on_error = None;
     59             }
     60         }
     61 
     62         self.error.as_ref()
     63     }
     64 
     65     /// Whether to indicate to the user that a successful login occured
     66     pub fn check_for_successful_login(&mut self) -> Option<Keypair> {
     67         if let Some((_, promise)) = &mut self.promise_query {
     68             if promise.ready().is_some() {
     69                 if let Some((_, promise)) = self.promise_query.take() {
     70                     match promise.block_and_take() {
     71                         Ok(key) => {
     72                             return Some(key);
     73                         }
     74                         Err(e) => {
     75                             self.error = Some(e);
     76                             self.key_on_error = Some(self.desired_key.clone());
     77                         }
     78                     };
     79                 }
     80             }
     81         }
     82         None
     83     }
     84 
     85     pub fn should_create_new(&mut self) {
     86         self.should_create_new = true;
     87     }
     88 
     89     pub fn check_for_create_new(&self) -> bool {
     90         self.should_create_new
     91     }
     92 }
     93 
     94 #[cfg(test)]
     95 mod tests {
     96     use enostr::Pubkey;
     97 
     98     use super::*;
     99     use std::time::{Duration, Instant};
    100 
    101     #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
    102     async fn test_retrieve_key() {
    103         let mut manager = AcquireKeyState::new();
    104         let expected_str = "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681";
    105         let expected_key = Keypair::only_pubkey(Pubkey::from_hex(expected_str).unwrap());
    106 
    107         let start_time = Instant::now();
    108 
    109         while start_time.elapsed() < Duration::from_millis(50u64) {
    110             let cur_time = start_time.elapsed();
    111 
    112             if cur_time < Duration::from_millis(10u64) {
    113                 let _ = manager.get_acquire_textedit(|text| {
    114                     text.clear();
    115                     text.insert_text("test", 0);
    116                     egui::TextEdit::singleline(text)
    117                 });
    118                 manager.apply_acquire();
    119             } else if cur_time < Duration::from_millis(30u64) {
    120                 let _ = manager.get_acquire_textedit(|text| {
    121                     text.clear();
    122                     text.insert_text("test2", 0);
    123                     egui::TextEdit::singleline(text)
    124                 });
    125                 manager.apply_acquire();
    126             } else {
    127                 let _ = manager.get_acquire_textedit(|text| {
    128                     text.clear();
    129                     text.insert_text(
    130                         "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681",
    131                         0,
    132                     );
    133                     egui::TextEdit::singleline(text)
    134                 });
    135                 manager.apply_acquire();
    136             }
    137 
    138             if let Some(key) = manager.check_for_successful_login() {
    139                 assert_eq!(expected_key, key);
    140                 return;
    141             }
    142         }
    143 
    144         panic!("Test failed to get expected key.");
    145     }
    146 }