/ web / src / pages / panels / flash_panel / hooks.rs
hooks.rs
  1  use super::{bridge::*, state::*};
  2  use dioxus::prelude::*;
  3  use ui::components::toast::use_toast;
  4  
  5  #[derive(Clone, Copy, PartialEq)]
  6  pub struct FlashController {
  7      pub device: FlashDeviceState,
  8      pub chip: FlashChipInfo,
  9      pub firmware: FlashFirmwareState,
 10      pub config: FlashConfig,
 11  }
 12  
 13  impl FlashController {
 14      pub fn connect(&self) {
 15          let mut device = self.device;
 16          let chip = self.chip;
 17          let mut firmware = self.firmware;
 18          let baud_val = self.config.baud.read().clone();
 19  
 20          device.connecting.set(true);
 21  
 22          spawn(async move {
 23              document::eval(JS_INIT_TERMINAL);
 24              eval_send_and_process(JS_CONNECT, baud_val, device, chip, firmware).await;
 25              device.connecting.set(false);
 26  
 27              if *device.is_connected.read() {
 28                  restart_monitor(device, chip, firmware).await;
 29              }
 30          });
 31      }
 32  
 33      pub fn disconnect(&self) {
 34          let mut device = self.device;
 35          let mut chip = self.chip;
 36          let mut firmware = self.firmware;
 37  
 38          device.is_connected.set(false);
 39          device.monitor_active.set(false);
 40          firmware.clear();
 41          chip.clear();
 42  
 43          spawn(async move {
 44              eval_and_process(JS_DISCONNECT, device, chip, firmware).await;
 45          });
 46      }
 47  
 48      pub fn flash(&self) {
 49          let mut device = self.device;
 50          let mut chip = self.chip;
 51          let mut firmware = self.firmware;
 52          let config = self.config;
 53  
 54          firmware.flashing.set(true);
 55          firmware.progress.set(0);
 56  
 57          let flash_config = serde_json::json!({
 58              "baud": *config.baud.read(),
 59              "mode": *config.mode.read(),
 60              "freq": *config.freq.read(),
 61              "size": *config.size.read(),
 62              "addr": *config.address.read(),
 63              "compress": *config.compress.read(),
 64              "eraseAll": *config.erase_first.read(),
 65              "wifiSsid": *config.wifi_ssid.read(),
 66              "wifiPass": *config.wifi_pass.read(),
 67          });
 68  
 69          spawn(async move {
 70              eval_send_and_process(JS_FLASH, flash_config, device, chip, firmware).await;
 71              firmware.flashing.set(false);
 72              restart_monitor(device, chip, firmware).await;
 73          });
 74      }
 75  
 76      pub fn erase(&self) {
 77          let mut device = self.device;
 78          let mut chip = self.chip;
 79          let mut firmware = self.firmware;
 80          let baud_val = self.config.baud.read().clone();
 81  
 82          spawn(async move {
 83              eval_send_and_process(JS_ERASE, baud_val, device, chip, firmware).await;
 84              restart_monitor(device, chip, firmware).await;
 85          });
 86      }
 87  
 88      pub fn reset(&self) {
 89          let device = self.device;
 90          let chip = self.chip;
 91          let firmware = self.firmware;
 92          let baud_val = self.config.baud.read().clone();
 93  
 94          spawn(async move {
 95              eval_send_and_process(JS_RESET, baud_val, device, chip, firmware).await;
 96              restart_monitor(device, chip, firmware).await;
 97          });
 98      }
 99  
100      pub fn select_firmware(&self) {
101          let device = self.device;
102          let chip = self.chip;
103          let firmware = self.firmware;
104  
105          spawn(async move {
106              eval_and_process(JS_SELECT_FIRMWARE, device, chip, firmware).await;
107          });
108      }
109  
110      pub fn toggle_monitor(&self) {
111          if *self.device.monitor_active.read() {
112              document::eval(JS_MONITOR_STOP);
113          } else {
114              let device = self.device;
115              let chip = self.chip;
116              let firmware = self.firmware;
117              spawn(async move {
118                  restart_monitor(device, chip, firmware).await;
119              });
120          }
121      }
122  }
123  
124  async fn restart_monitor(
125      device: FlashDeviceState,
126      chip: FlashChipInfo,
127      firmware: FlashFirmwareState,
128  ) {
129      eval_send_and_process(JS_MONITOR_START, "115200", device, chip, firmware).await;
130  }
131  
132  pub fn use_flash_controller() -> FlashController {
133      let mut device = FlashDeviceState::new();
134      let mut chip = FlashChipInfo::new();
135      let mut firmware = FlashFirmwareState::new();
136      let mut config = FlashConfig::new();
137      let mut config_loaded = use_signal(|| false);
138  
139      let toasts = use_toast();
140  
141      // Load config from localStorage on mount
142      use_effect(move || {
143          let mut config = config;
144          spawn(async move {
145              let eval = document::eval(
146                  r#"
147                  try {
148                      const c = JSON.parse(localStorage.getItem('flash_options') || '{}');
149                      return JSON.stringify(c);
150                  } catch(e) { return '{}'; }
151              "#,
152              );
153              if let Ok(json) = eval.await {
154                  if let Ok(map) =
155                      serde_json::from_value::<serde_json::Map<String, serde_json::Value>>(json)
156                  {
157                      if let Some(v) = map.get("baud").and_then(|v| v.as_str()) {
158                          config.baud.set(v.to_string());
159                      }
160                      if let Some(v) = map.get("mode").and_then(|v| v.as_str()) {
161                          config.mode.set(v.to_string());
162                      }
163                      if let Some(v) = map.get("freq").and_then(|v| v.as_str()) {
164                          config.freq.set(v.to_string());
165                      }
166                      if let Some(v) = map.get("size").and_then(|v| v.as_str()) {
167                          config.size.set(v.to_string());
168                      }
169                      if let Some(v) = map.get("addr").and_then(|v| v.as_str()) {
170                          config.address.set(v.to_string());
171                      }
172                      if let Some(v) = map.get("compress").and_then(|v| v.as_bool()) {
173                          config.compress.set(v);
174                      }
175                      if let Some(v) = map.get("eraseAll").and_then(|v| v.as_bool()) {
176                          config.erase_first.set(v);
177                      }
178                  }
179              }
180              config_loaded.set(true);
181          });
182      });
183  
184      use_effect(move || {
185          if !*config_loaded.read() {
186              return;
187          }
188          let baud = config.baud.read().clone();
189          let mode = config.mode.read().clone();
190          let freq = config.freq.read().clone();
191          let size = config.size.read().clone();
192          let addr = config.address.read().clone();
193          let compress = *config.compress.read();
194          let erase = *config.erase_first.read();
195          let config_json = serde_json::json!({
196              "baud": baud,
197              "mode": mode,
198              "freq": freq,
199              "size": size,
200              "addr": addr,
201              "compress": compress,
202              "eraseAll": erase,
203          });
204          document::eval(&format!(
205              "localStorage.setItem('flash_options',{});",
206              serde_json::to_string(&config_json).unwrap_or_default()
207          ));
208      });
209  
210      use_effect(move || {
211          if *device.device_lost.read() {
212              toasts.error("Device disconnected unexpectedly".to_string(), None);
213              device.device_lost.set(false);
214          }
215      });
216  
217      use_drop(|| {
218          document::eval(JS_CLEANUP);
219      });
220  
221      FlashController {
222          device,
223          chip,
224          firmware,
225          config,
226      }
227  }