Skip to main content

gm_lib/tui/app/pages/
complete_setup.rs

1use std::sync::{atomic::AtomicBool, mpsc, Arc};
2
3use ratatui::{buffer::Buffer, layout::Rect, style::Stylize, text::Line, widgets::Widget};
4use strum::EnumIter;
5
6use super::{account::AccountPage, Page};
7use crate::{
8    disk::{Config, DiskInterface},
9    tui::{
10        app::{
11            widgets::form::{Form, FormItemIndex, FormWidget},
12            SharedState,
13        },
14        events::Event,
15        traits::{Component, HandleResult, RectUtil},
16    },
17};
18
19#[derive(PartialEq, EnumIter)]
20pub enum FormItem {
21    CreateOrImportWallet,
22    AlchemyApiKey,
23    Save,
24    Display,
25}
26
27impl FormItemIndex for FormItem {
28    fn index(self) -> usize {
29        self as usize
30    }
31}
32
33impl TryFrom<FormItem> for FormWidget {
34    type Error = crate::Error;
35    fn try_from(value: FormItem) -> crate::Result<Self> {
36        let widget = match value {
37            FormItem::CreateOrImportWallet => FormWidget::Button {
38                label: "Create or Import Wallet",
39            },
40            FormItem::AlchemyApiKey => {
41                let mut config = Config::load()?;
42                if config.alchemy_api_key.is_none() {
43                    config.alchemy_api_key = Some("".to_string());
44                };
45
46                FormWidget::InputBox {
47                    label: "Alchemy API Key",
48                    text: config.alchemy_api_key.unwrap_or_default(),
49                    empty_text: Some("Please get an Alchemy API key from https://www.alchemy.com/"),
50                    currency: None,
51                }
52            }
53            FormItem::Save => FormWidget::Button { label: "Save" },
54            FormItem::Display => FormWidget::DisplayText(String::new()),
55        };
56        Ok(widget)
57    }
58}
59
60pub struct CompleteSetupPage {
61    pub form: Form<FormItem>,
62}
63
64impl CompleteSetupPage {
65    pub fn new() -> crate::Result<Self> {
66        Ok(Self {
67            form: Form::init(|form| {
68                let config = Config::load()?;
69                if config.current_account.is_some() {
70                    form.hide_item(FormItem::CreateOrImportWallet);
71                }
72                if config
73                    .alchemy_api_key
74                    .map(|s| !s.is_empty())
75                    .unwrap_or(false)
76                {
77                    form.hide_item(FormItem::AlchemyApiKey);
78                    form.hide_item(FormItem::Save);
79                    form.hide_item(FormItem::Display);
80                }
81                Ok(())
82            })?,
83        })
84    }
85}
86impl Component for CompleteSetupPage {
87    fn set_focus(&mut self, focus: bool) {
88        self.form.set_form_focus(focus);
89    }
90
91    fn reload(&mut self, _ss: &SharedState) -> crate::Result<()> {
92        let fresh = Self::new()?;
93        self.form = fresh.form;
94        Ok(())
95    }
96
97    fn handle_event(
98        &mut self,
99        event: &Event,
100        _area: Rect,
101        transmitter: &mpsc::Sender<Event>,
102        _shutdown_signal: &Arc<AtomicBool>,
103        _shared_state: &SharedState,
104    ) -> crate::Result<HandleResult> {
105        let display_text = self.form.get_text_mut(FormItem::Display);
106        *display_text = "".to_string();
107
108        let mut handle_result = HandleResult::default();
109
110        self.form.handle_event(
111            event,
112            |_, _| Ok(()),
113            |label, form| {
114                if label == FormItem::CreateOrImportWallet {
115                    handle_result
116                        .page_inserts
117                        .push(Page::Account(AccountPage::new()?));
118                } else {
119                    handle_result.reload = true;
120
121                    let mut config = Config::load()?;
122                    config.alchemy_api_key = Some(form.get_text(FormItem::AlchemyApiKey).clone());
123                    config.save()?;
124                    transmitter.send(Event::ConfigUpdate)?;
125
126                    let display_text = form.get_text_mut(FormItem::Display);
127                    *display_text = "Configuration saved".to_string();
128                }
129                Ok(())
130            },
131        )?;
132
133        Ok(handle_result)
134    }
135
136    fn render_component(&self, area: Rect, buf: &mut Buffer, ss: &SharedState) -> Rect
137    where
138        Self: Sized,
139    {
140        Line::from("Complete Setup").bold().render(area, buf);
141        let Ok(area) = area.consume_height(2) else {
142            return area;
143        };
144
145        if self.form.visible_count() == 0 {
146            Line::from("You have completed the setup please press ESC to return back.")
147                .render(area, buf);
148        } else {
149            "Complete the following steps to get started:".render(area, buf);
150            let Ok(area) = area.consume_height(2) else {
151                return area;
152            };
153
154            self.form.render(area, buf, &ss.theme);
155        }
156        area
157    }
158}