gm_lib/tui/app/pages/
complete_setup.rs1use 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}