gromnie_cli/wizards/
launch.rs1use ratatui::Frame;
2use std::error::Error;
3
4use gromnie_client::config::GromnieConfig;
5
6use crate::app::App;
7use crate::draw::Draw;
8
9#[derive(Debug, Clone, PartialEq)]
10pub enum WizardStage {
11 Welcome,
12 SelectingServer,
13 SelectingAccount,
14 Confirming,
15 Complete,
16}
17
18#[derive(Clone)]
19pub struct LaunchWizard {
20 #[allow(dead_code)]
21 pub config: GromnieConfig,
22 pub stage: WizardStage,
23 pub selected_server_idx: usize,
24 pub selected_account_idx: usize,
25 pub server_list: Vec<(String, gromnie_client::config::ServerConfig)>,
26 pub account_list: Vec<(String, gromnie_client::config::AccountConfig)>,
27}
28
29impl LaunchWizard {
30 pub fn new(config: GromnieConfig) -> Self {
31 assert!(
33 !config.servers.is_empty(),
34 "Config must have at least one server configured"
35 );
36 assert!(
37 !config.accounts.is_empty(),
38 "Config must have at least one account configured"
39 );
40
41 let server_list: Vec<_> = config
42 .servers
43 .iter()
44 .map(|(k, v)| (k.clone(), v.clone()))
45 .collect();
46 let account_list: Vec<_> = config
47 .accounts
48 .iter()
49 .map(|(k, v)| (k.clone(), v.clone()))
50 .collect();
51
52 Self {
53 config,
54 stage: WizardStage::Welcome,
55 selected_server_idx: 0,
56 selected_account_idx: 0,
57 server_list,
58 account_list,
59 }
60 }
61
62 pub fn get_selected_server(&self) -> &gromnie_client::config::ServerConfig {
63 &self.server_list[self.selected_server_idx].1
64 }
65
66 pub fn get_selected_account(&self) -> &gromnie_client::config::AccountConfig {
67 &self.account_list[self.selected_account_idx].1
68 }
69}
70
71impl Draw for LaunchWizard {
72 fn draw(self, _app: &mut App, frame: &mut Frame) -> Result<(), Box<dyn Error>> {
73 use ratatui::style::{Color, Style};
74 use ratatui::text::{Line, Span, Text};
75 use ratatui::widgets::Paragraph;
76
77 let mut lines = Vec::new();
78
79 lines.push(Line::from("Welcome to Gromnie!"));
81 lines.push(Line::from(Span::styled(
82 format!("Config: {}", GromnieConfig::config_path().display()),
83 Style::default().fg(Color::DarkGray),
84 )));
85 lines.push(Line::from(""));
86
87 match self.stage {
89 WizardStage::Welcome => {
90 }
92 WizardStage::SelectingServer => {
93 lines.push(Line::from("? Pick a server"));
94 for (idx, (_name, server)) in self.server_list.iter().enumerate() {
95 let marker = if idx == self.selected_server_idx {
96 "●"
97 } else {
98 "○"
99 };
100 lines.push(Line::from(format!(" {} {}", marker, server)));
101 }
102 }
103 WizardStage::SelectingAccount | WizardStage::Confirming | WizardStage::Complete => {
104 lines.push(Line::from("* Pick a server"));
106 let selected_server = &self.server_list[self.selected_server_idx].1;
107 lines.push(Line::from(format!(" {}", selected_server)));
108 lines.push(Line::from(""));
109
110 if self.stage == WizardStage::SelectingAccount {
111 lines.push(Line::from("? Pick an account"));
112 for (idx, (_name, account)) in self.account_list.iter().enumerate() {
113 let marker = if idx == self.selected_account_idx {
114 "●"
115 } else {
116 "○"
117 };
118 lines.push(Line::from(format!(" {} {}", marker, account)));
119 }
120 } else {
121 lines.push(Line::from("* Pick an account"));
123 let selected_account = &self.account_list[self.selected_account_idx].1;
124 lines.push(Line::from(format!(" {}", selected_account)));
125 lines.push(Line::from(""));
126
127 if self.stage == WizardStage::Confirming {
128 lines.push(Line::from("? Ready to log in? <enter>"));
129 }
130 }
131 }
132 }
133
134 let text = Text::from(lines);
135 let paragraph = Paragraph::new(text);
136 frame.render_widget(paragraph, frame.area());
137
138 Ok(())
139 }
140}