1use crate::check_network::CheckNetworkViewAssistant;
6#[allow(unused)]
7use crate::constants::constants::{
8 ScreenSplit, ICON_FACTORY_RESET, ICON_REINSTALL_SOFTWARE, IMAGE_DEFAULT_SIZE,
9 IMAGE_DEVICE_CONNECT, IMAGE_DEVICE_INSTALL, IMAGE_DEVICE_UPDATING, IMAGE_DEVICE_UPDATING_SIZE,
10 IMAGE_PHONE_HOME_APP, IMAGE_PHONE_HOME_APP_SIZE, IMAGE_RESET_FAILED,
11};
12use crate::font;
13use crate::generic_view::{ButtonInfo, GenericSplitViewAssistant};
14use crate::keyboard::KeyboardViewAssistant;
15use crate::network::NetworkViewAssistant;
16use crate::proxy_view_assistant::ProxyMessages;
17use crate::text_field::TextVisibility;
18use carnelian::{make_message, AppSender, MessageTarget, ViewAssistantPtr, ViewKey};
19use recovery_util::ota::state_machine::DataSharingConsent::Allow;
20use recovery_util::ota::state_machine::{
21 DataSharingConsent, Event, Operation, State, StateHandler,
22};
23use recovery_util::wlan::NetworkInfo;
24
25pub struct Screens {
26 app_sender: AppSender,
27 view_key: ViewKey,
28}
29
30impl Screens {
31 pub fn new(app_sender: AppSender, view_key: ViewKey) -> Self {
32 Self { app_sender, view_key }
33 }
34
35 pub fn initial_screen(&self) -> ViewAssistantPtr {
36 self.home()
37 }
38
39 fn state(&mut self, state: &State) {
40 let new_view = match state {
41 State::Home => self.home(),
42 State::FactoryReset => self.progress(Operation::FactoryDataReset, 0),
43 State::FactoryResetConfirm => self.factory_reset_confirm(),
44 State::Failed(operation, error) => self.failed(operation, error),
45 State::Reinstall => self.reinstall(),
46 State::Rebooting(_) => self.rebooting(),
47 State::GetWiFiNetworks => self.select_wifi(&Vec::new()),
48 State::SelectWiFi(networks) => self.select_wifi(networks),
49 State::EnterWiFi => {
50 self.user_entry("Enter Network Name".to_string(), TextVisibility::Always)
51 }
52 State::EnterPassword(network) => self.user_entry(
53 format!("Enter Password for {} ", network),
54 TextVisibility::Toggleable(false),
55 ),
56 State::Connecting(network, password) => self.connecting(network, password),
57 State::ConnectionFailed(network, password) => self.connection_failed(network, password),
58 State::ReinstallConfirm { desired: user_data_sharing_consent, reported } => {
59 self.reinstall_confirm(user_data_sharing_consent.clone(), reported.clone())
60 }
61 State::ExecuteReinstall => self.progress(Operation::Reinstall, 0),
62 State::ReinstallRunning { progress, .. } => {
63 let mapped_progess: f32 = (*progress as f32) * 0.93;
67 self.progress(Operation::Reinstall, mapped_progess as u8)
68 }
69 State::FinalizeReinstall(_) => {
70 self.progress(Operation::Reinstall, 95)
73 }
74 };
75 self.app_sender.queue_message(
76 MessageTarget::View(self.view_key),
77 make_message(ProxyMessages::ReplaceViewAssistant(Some(new_view))),
78 );
79 }
80
81 fn factory_reset_confirm(&self) -> ViewAssistantPtr {
82 let view_assistant_ptr = Box::new(
83 GenericSplitViewAssistant::new(
84 self.app_sender.clone(),
85 self.view_key,
86 ScreenSplit::None,
87 Some("Confirm factory reset".to_string()),
88 Some(
89 "• This will clear your data from the device and can't be undone\n\
90 • Upon completion, the device will automatically restart"
91 .to_string(),
92 ),
93 None,
94 Some(vec![
95 ButtonInfo::new("Cancel", None, false, true, Event::Cancel),
96 ButtonInfo::new(
97 "Start Factory Reset",
98 Some(ICON_FACTORY_RESET),
99 false,
100 false,
101 Event::StartFactoryReset,
102 ),
103 ]),
104 None,
105 None,
106 Some(IMAGE_DEVICE_UPDATING),
107 Some(IMAGE_DEVICE_UPDATING_SIZE),
108 )
109 .unwrap(),
110 );
111 view_assistant_ptr
112 }
113
114 fn progress(&self, operation: Operation, percent: u8) -> ViewAssistantPtr {
115 let title = match operation {
116 Operation::FactoryDataReset => "Resetting".to_string(),
118 Operation::Reinstall => format!("Updating {}%", percent),
119 };
120 let content = match operation {
121 Operation::FactoryDataReset => "• Resetting user data\n\
122 • Upon completion, the\n \
123 device will automatically\n \
124 restart"
125 .to_string(),
126 Operation::Reinstall => "• This may take several minutes\n\
127 • Upon completion, the\n \
128 device will automatically\n \
129 restart"
130 .to_string(),
131 };
132 let view_assistant_ptr = Box::new(
133 GenericSplitViewAssistant::new(
134 self.app_sender.clone(),
135 self.view_key,
136 ScreenSplit::Even,
137 Some(title),
138 Some(content),
139 None,
140 None,
141 None,
142 None,
143 Some(IMAGE_DEVICE_UPDATING),
144 Some(IMAGE_DEVICE_UPDATING_SIZE),
145 )
146 .unwrap(),
147 );
148 view_assistant_ptr
149 }
150
151 fn home(&self) -> ViewAssistantPtr {
152 let view_assistant_ptr = Box::new(
153 GenericSplitViewAssistant::new(
154 self.app_sender.clone(),
155 self.view_key,
156 ScreenSplit::Wide,
157 Some("Factory reset".to_string()),
158 Some("• A factory reset can fix a device problem\n• This will clear your data from the device and can't be undone".to_string()),
159 Some("Still having issues after factory reset?".to_string()),
160 Some(vec![ButtonInfo::new("Start factory reset", Some(ICON_FACTORY_RESET), false, false, Event::StartFactoryReset)]),
161 Some(vec![ButtonInfo::new("Try another option", None, true, true, Event::TryAnotherWay)]),
162 None,
163 None,
164 None,
165 )
166 .unwrap(),
167 );
168 view_assistant_ptr
169 }
170
171 fn failed(&self, operation: &Operation, error: &Option<String>) -> ViewAssistantPtr {
172 let text1 = match operation {
173 Operation::FactoryDataReset => "Reset failed",
174 Operation::Reinstall => "Recovery failed",
175 };
176 let error = if let Some(error) = error { error.clone() } else { "".to_string() };
177 let text2 = match operation {
178 Operation::FactoryDataReset => "An error occurred while\nrecovering".to_string(),
179 Operation::Reinstall => error + "\n\nPlease reconnect and try again.",
180 };
181 let view_assistant_ptr = Box::new(
182 GenericSplitViewAssistant::new(
183 self.app_sender.clone(),
184 self.view_key,
185 ScreenSplit::Even,
186 Some(text1.to_string()),
187 Some(text2),
188 None,
189 Some(vec![
190 ButtonInfo::new("Cancel", None, false, true, Event::Cancel),
191 ButtonInfo::new("Try again", None, false, false, Event::TryAgain),
192 ]),
193 None,
194 None,
195 Some(IMAGE_RESET_FAILED),
196 None,
197 )
198 .unwrap(),
199 );
200 view_assistant_ptr
201 }
202
203 fn rebooting(&self) -> ViewAssistantPtr {
204 let view_assistant_ptr = Box::new(
205 GenericSplitViewAssistant::new(
206 self.app_sender.clone(),
207 self.view_key,
208 ScreenSplit::Even,
209 Some("Rebooting...".to_string()),
210 Some("Your device will now reboot.".to_string()),
211 None,
212 None,
213 None,
214 None,
215 Some(IMAGE_DEVICE_UPDATING),
216 None,
217 )
218 .unwrap(),
219 );
220 view_assistant_ptr
221 }
222
223 fn reinstall(&self) -> ViewAssistantPtr {
224 let view_assistant_ptr = Box::new(
225 GenericSplitViewAssistant::new(
226 self.app_sender.clone(),
227 self.view_key,
228 ScreenSplit::Wide,
229 Some("Reinstall Software".to_string()),
230 Some(
231 "• Install the latest software to fix bugs and update the system\n\
232 • This will clear your data from the device and can't be undone\n\
233 • You'll need a Wi-Fi connection to proceed"
234 .to_string(),
235 ),
236 None,
237 Some(vec![
238 ButtonInfo::new("Cancel", None, false, true, Event::Cancel),
239 ButtonInfo::new(
240 "Reinstall Software",
241 Some(ICON_REINSTALL_SOFTWARE),
242 false,
243 false,
244 Event::Reinstall,
245 ),
246 ]),
247 Some(vec![ButtonInfo::new("Reboot", None, true, true, Event::Reboot)]),
248 None,
249 None,
250 None,
251 )
252 .unwrap(),
253 );
254 view_assistant_ptr
255 }
256
257 fn select_wifi(&self, networks: &Vec<NetworkInfo>) -> ViewAssistantPtr {
258 let network_view = Box::new(
259 NetworkViewAssistant::new(self.app_sender.clone(), self.view_key, networks.to_vec())
260 .unwrap(),
261 );
262 network_view
263 }
264
265 fn user_entry(&self, text: String, privacy: TextVisibility) -> ViewAssistantPtr {
266 let mut keyboard = Box::new(
267 KeyboardViewAssistant::new(
268 self.app_sender.clone(),
269 self.view_key,
270 font::get_default_font_face().clone(),
271 )
272 .unwrap(),
273 );
274 keyboard.set_field_name(text);
275 keyboard.set_text_field(String::new());
276 keyboard.set_privacy(privacy);
277 keyboard
278 }
279
280 fn connecting(&self, _network: &String, _password: &String) -> ViewAssistantPtr {
281 let view_assistant_ptr = Box::new(
282 GenericSplitViewAssistant::new(
283 self.app_sender.clone(),
284 self.view_key,
285 ScreenSplit::Even,
286 Some("Connecting Wi-Fi".to_string()),
287 Some("Sit tight. This may take a few\nseconds.".to_string()),
288 None,
289 Some(vec![ButtonInfo::new("Cancel", None, false, true, Event::Cancel)]),
290 None,
291 None,
292 Some(IMAGE_DEVICE_CONNECT),
293 Some(IMAGE_DEFAULT_SIZE),
294 )
295 .unwrap(),
296 );
297 view_assistant_ptr
298 }
299
300 fn connection_failed(&self, network: &String, password: &String) -> ViewAssistantPtr {
301 let title_text = "Check Wi-Fi Network".to_string();
302 let body_text = format!(
303 "Incorrect password for Wi-Fi “{}”\n\
304 Try again or choose a different Wi-Fi network.",
305 network
306 );
307 let view_assistant_ptr = Box::new(
308 CheckNetworkViewAssistant::new(
309 self.app_sender.clone(),
310 self.view_key,
311 title_text,
312 body_text,
313 network.into(),
314 password.into(),
315 vec![
316 ButtonInfo::new("Cancel", None, false, true, Event::Cancel),
317 ButtonInfo::new("Choose network", None, false, true, Event::ChooseNetwork),
318 ButtonInfo::new("Try Again", None, false, false, Event::TryAgain),
319 ],
320 )
321 .unwrap(),
322 );
323 view_assistant_ptr
324 }
325
326 fn reinstall_confirm(
327 &self,
328 _desired: DataSharingConsent,
329 reported: DataSharingConsent,
330 ) -> ViewAssistantPtr {
331 let next_privacy_state = match reported {
332 DataSharingConsent::Unknown => Allow,
333 _ => reported.toggle(),
334 };
335 let view_assistant_ptr = Box::new(
336 GenericSplitViewAssistant::new(
337 self.app_sender.clone(),
338 self.view_key,
339 ScreenSplit::Even,
340 Some("Reinstall Software".to_string()),
341 Some(
343 "• This will clear your data from the\n \
344 device and can't be undone\n\
345 • It may take several minutes\n\
346 • Upon completion, the device will\n \
347 automatically restart"
348 .to_string(),
349 ),
350 None,
351 Some(vec![
352 ButtonInfo::new("Cancel", None, false, true, Event::Cancel),
353 ButtonInfo::new("Reinstall Now", None, false, false, Event::Reinstall),
354 ]),
355 None,
356 Some(vec![ButtonInfo::new(
357 "Permission",
358 None,
359 false,
360 reported == Allow, Event::SendReports(next_privacy_state),
362 )]),
363 Some(IMAGE_DEVICE_INSTALL),
364 Some(IMAGE_DEFAULT_SIZE),
365 )
366 .unwrap(),
367 );
368 view_assistant_ptr
369 }
370}
371
372impl StateHandler for Screens {
373 fn handle_state(&mut self, state: State) {
374 self.state(&state);
375 }
376}