notedeck

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

account_management.rs (8024B)


      1 use crate::colors::PINK;
      2 use crate::{
      3     account_manager::AccountManager,
      4     app_style::NotedeckTextStyle,
      5     ui::{profile_preview_controller, Preview, PreviewConfig, View},
      6     Damus,
      7 };
      8 use egui::{Align, Button, Frame, Image, Layout, Response, RichText, ScrollArea, Vec2};
      9 
     10 use super::profile::preview::SimpleProfilePreview;
     11 use super::profile::ProfilePreviewOp;
     12 
     13 pub struct AccountManagementView {}
     14 
     15 impl AccountManagementView {
     16     pub fn ui(app: &mut Damus, ui: &mut egui::Ui) -> Option<Response> {
     17         if app.is_mobile() {
     18             AccountManagementView::show_mobile(app, ui);
     19             None
     20         } else {
     21             Some(AccountManagementView::show(app, ui))
     22         }
     23     }
     24 
     25     fn show(app: &mut Damus, ui: &mut egui::Ui) -> Response {
     26         Frame::none()
     27             .outer_margin(24.0)
     28             .show(ui, |ui| {
     29                 Self::top_section_buttons_widget(ui);
     30                 ui.add_space(8.0);
     31                 scroll_area().show(ui, |ui| {
     32                     Self::show_accounts(app, ui);
     33                 });
     34             })
     35             .response
     36     }
     37 
     38     fn show_accounts(app: &mut Damus, ui: &mut egui::Ui) {
     39         let maybe_remove =
     40             profile_preview_controller::set_profile_previews(app, ui, account_card_ui());
     41 
     42         Self::maybe_remove_accounts(&mut app.account_manager, maybe_remove);
     43     }
     44 
     45     fn show_accounts_mobile(app: &mut Damus, ui: &mut egui::Ui) {
     46         ui.allocate_ui_with_layout(
     47             Vec2::new(ui.available_size_before_wrap().x, 32.0),
     48             Layout::top_down(egui::Align::Min),
     49             |ui| {
     50                 // create all account 'cards' and get the indicies the user requested to remove
     51                 let maybe_remove = profile_preview_controller::set_profile_previews(
     52                     app,
     53                     ui,
     54                     account_card_ui(), // closure for creating an account 'card'
     55                 );
     56 
     57                 // remove all account indicies user requested
     58                 Self::maybe_remove_accounts(&mut app.account_manager, maybe_remove);
     59             },
     60         );
     61     }
     62 
     63     fn maybe_remove_accounts(manager: &mut AccountManager, account_indices: Option<Vec<usize>>) {
     64         if let Some(to_remove) = account_indices {
     65             to_remove
     66                 .iter()
     67                 .for_each(|index| manager.remove_account(*index));
     68         }
     69     }
     70 
     71     fn show_mobile(app: &mut Damus, ui: &mut egui::Ui) {
     72         mobile_title(ui);
     73         Self::top_section_buttons_widget(ui);
     74 
     75         ui.add_space(8.0);
     76         scroll_area().show(ui, |ui| Self::show_accounts_mobile(app, ui));
     77     }
     78 
     79     fn top_section_buttons_widget(ui: &mut egui::Ui) -> egui::Response {
     80         ui.horizontal(|ui| {
     81             ui.allocate_ui_with_layout(
     82                 Vec2::new(ui.available_size_before_wrap().x, 32.0),
     83                 Layout::left_to_right(egui::Align::Center),
     84                 |ui| {
     85                     if ui.add(add_account_button()).clicked() {
     86                         // TODO: route to AccountLoginView
     87                     }
     88                 },
     89             );
     90 
     91             // UNCOMMENT FOR LOGOUTALL BUTTON
     92             // ui.allocate_ui_with_layout(
     93             //     Vec2::new(ui.available_size_before_wrap().x, 32.0),
     94             //     Layout::right_to_left(egui::Align::Center),
     95             //     |ui| {
     96             //         if ui.add(logout_all_button()).clicked() {
     97             //             for index in (0..self.account_manager.num_accounts()).rev() {
     98             //                 self.account_manager.remove_account(index);
     99             //             }
    100             //         }
    101             //     },
    102             // );
    103         })
    104         .response
    105     }
    106 }
    107 
    108 fn account_card_ui() -> fn(
    109     ui: &mut egui::Ui,
    110     preview: SimpleProfilePreview,
    111     width: f32,
    112     is_selected: bool,
    113 ) -> Option<ProfilePreviewOp> {
    114     |ui, preview, width, is_selected| {
    115         let mut op: Option<ProfilePreviewOp> = None;
    116 
    117         ui.add_sized(Vec2::new(width, 50.0), |ui: &mut egui::Ui| {
    118             Frame::none()
    119                 .show(ui, |ui| {
    120                     ui.horizontal(|ui| {
    121                         ui.add(preview);
    122 
    123                         ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
    124                             if is_selected {
    125                                 ui.add(selected_widget());
    126                             } else {
    127                                 if ui
    128                                     .add(switch_button(ui.style().visuals.dark_mode))
    129                                     .clicked()
    130                                 {
    131                                     op = Some(ProfilePreviewOp::SwitchTo);
    132                                 }
    133                                 if ui.add(sign_out_button(ui)).clicked() {
    134                                     op = Some(ProfilePreviewOp::RemoveAccount)
    135                                 }
    136                             }
    137                         });
    138                     });
    139                 })
    140                 .response
    141         });
    142         ui.add_space(16.0);
    143         op
    144     }
    145 }
    146 
    147 fn mobile_title(ui: &mut egui::Ui) -> egui::Response {
    148     ui.vertical_centered(|ui| {
    149         ui.label(
    150             RichText::new("Account Management")
    151                 .text_style(NotedeckTextStyle::Heading2.text_style())
    152                 .strong(),
    153         );
    154     })
    155     .response
    156 }
    157 
    158 fn scroll_area() -> ScrollArea {
    159     egui::ScrollArea::vertical()
    160         .scroll_bar_visibility(egui::scroll_area::ScrollBarVisibility::AlwaysHidden)
    161         .auto_shrink([false; 2])
    162 }
    163 
    164 fn add_account_button() -> Button<'static> {
    165     let img_data = egui::include_image!("../../assets/icons/add_account_icon_4x.png");
    166     let img = Image::new(img_data).fit_to_exact_size(Vec2::new(48.0, 48.0));
    167     Button::image_and_text(
    168         img,
    169         RichText::new(" Add account")
    170             .size(16.0)
    171             // TODO: this color should not be hard coded. Find some way to add it to the visuals
    172             .color(PINK),
    173     )
    174     .frame(false)
    175 }
    176 
    177 fn sign_out_button(ui: &egui::Ui) -> egui::Button<'static> {
    178     let img_data = egui::include_image!("../../assets/icons/signout_icon_4x.png");
    179     let img = Image::new(img_data).fit_to_exact_size(Vec2::new(16.0, 16.0));
    180 
    181     egui::Button::image_and_text(
    182         img,
    183         RichText::new("Sign out").color(ui.visuals().noninteractive().fg_stroke.color),
    184     )
    185     .frame(false)
    186 }
    187 
    188 fn switch_button(dark_mode: bool) -> egui::Button<'static> {
    189     let _ = dark_mode;
    190 
    191     egui::Button::new("Switch").min_size(Vec2::new(76.0, 32.0))
    192 }
    193 
    194 fn selected_widget() -> impl egui::Widget {
    195     |ui: &mut egui::Ui| {
    196         Frame::none()
    197             .show(ui, |ui| {
    198                 ui.label(RichText::new("Selected").size(13.0).color(PINK));
    199                 let img_data = egui::include_image!("../../assets/icons/select_icon_3x.png");
    200                 let img = Image::new(img_data).max_size(Vec2::new(16.0, 16.0));
    201                 ui.add(img);
    202             })
    203             .response
    204     }
    205 }
    206 
    207 // fn logout_all_button() -> egui::Button<'static> {
    208 //     egui::Button::new("Logout all")
    209 // }
    210 
    211 // PREVIEWS
    212 
    213 mod preview {
    214 
    215     use super::*;
    216     use crate::test_data;
    217 
    218     pub struct AccountManagementPreview {
    219         is_mobile: bool,
    220         app: Damus,
    221     }
    222 
    223     impl AccountManagementPreview {
    224         fn new(is_mobile: bool) -> Self {
    225             let app = test_data::test_app(is_mobile);
    226 
    227             AccountManagementPreview { is_mobile, app }
    228         }
    229     }
    230 
    231     impl View for AccountManagementPreview {
    232         fn ui(&mut self, ui: &mut egui::Ui) {
    233             ui.add_space(24.0);
    234             if self.is_mobile {
    235                 AccountManagementView::show_mobile(&mut self.app, ui);
    236             } else {
    237                 AccountManagementView::show(&mut self.app, ui);
    238             }
    239         }
    240     }
    241 
    242     impl Preview for AccountManagementView {
    243         type Prev = AccountManagementPreview;
    244 
    245         fn preview(cfg: PreviewConfig) -> Self::Prev {
    246             AccountManagementPreview::new(cfg.is_mobile)
    247         }
    248     }
    249 }