maia_wasm/ui/
preferences.rs1use super::input::InputElement;
2use serde::{Deserialize, Serialize};
3use wasm_bindgen::JsValue;
4use web_sys::{Storage, Window};
5
6const PREFERENCES_KEY: &str = "preferences";
7
8pub struct Preferences {
9 storage: Option<Storage>,
10 data: PreferenceData,
11}
12
13macro_rules! impl_preference_data {
14 {$($name:ident : $ty:ty = $default:expr,)*} => {
15 #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
16 struct PreferenceData {
17 $(
18 $name: $ty,
19 )*
20 }
21
22 impl Default for PreferenceData {
23 fn default() -> Self {
24 Self {
25 $(
26 $name: $default,
27 )*
28 }
29 }
30 }
31
32 impl Preferences {
33 $(
34 paste::paste! {
35 pub fn [<update_ $name>](&mut self, value: &$ty) -> Result<(), JsValue> {
36 if (*value != self.data.$name) {
37 self.data.$name.clone_from(value);
38 self.store()
39 } else {
40 Ok(())
41 }
42 }
43 }
44 )*
45 }
46
47 impl Preferences {
48 pub(super) fn apply(&self, ui: &super::Ui) -> Result<(), JsValue> {
51 $(
52 ui.elements.$name.set(&self.data.$name);
53 if let Some(onchange) = ui.elements.$name.onchange() {
54 onchange.call0(&JsValue::NULL)?;
55 }
56 )*
57 Ok(())
58 }
59 }
60 }
61}
62
63impl_preference_data! {
64 colormap_select: super::colormap::Colormap = super::colormap::Colormap::Turbo,
65 waterfall_show_waterfall: bool = true,
66 waterfall_show_spectrum: bool = false,
67 waterfall_show_ddc: bool = true,
68 waterfall_min: f32 = 35.0,
69 waterfall_max: f32 = 85.0,
70 ad9361_rx_lo_frequency: u64 = 2_400_000_000,
71 ad9361_sampling_frequency: u32 = 61_440_000,
72 ad9361_rx_rf_bandwidth: u32 = 56_000_000,
73 ad9361_rx_gain_mode: maia_json::Ad9361GainMode = maia_json::Ad9361GainMode::SlowAttack,
74 ad9361_rx_gain: f64 = 70.0,
75 ddc_frequency: f64 = 0.0,
76 ddc_decimation: u32 = 20,
77 ddc_transition_bandwidth: f64 = 0.05,
78 ddc_passband_ripple: f64 = 0.01,
79 ddc_stopband_attenuation_db: f64 = 60.0,
80 ddc_stopband_one_over_f: bool = true,
81 spectrometer_input: maia_json::SpectrometerInput = maia_json::SpectrometerInput::AD9361,
82 spectrometer_output_sampling_frequency: f64 = 20.0,
83 spectrometer_mode: maia_json::SpectrometerMode = maia_json::SpectrometerMode::Average,
84 recording_metadata_filename: String = "recording".to_string(),
85 recorder_prepend_timestamp: bool = false,
86 recording_metadata_description: String = "".to_string(),
87 recording_metadata_author: String = "".to_string(),
88 recorder_mode: maia_json::RecorderMode = maia_json::RecorderMode::IQ12bit,
89 recorder_maximum_duration: f64 = 0.0,
90 geolocation_watch: bool = false,
91}
92
93impl Preferences {
94 pub fn new(window: &Window) -> Result<Preferences, JsValue> {
95 let storage = window.local_storage()?;
96 let data = match &storage {
97 Some(storage) => match storage.get_item(PREFERENCES_KEY)? {
98 Some(data) => match serde_json::from_str(&data) {
99 Ok(x) => x,
100 Err(_) => {
101 web_sys::console::error_1(&"preferences corrupted; removing".into());
102 storage.remove_item(PREFERENCES_KEY)?;
103 PreferenceData::default()
104 }
105 },
106 None => PreferenceData::default(),
107 },
108 None => PreferenceData::default(),
109 };
110 Ok(Preferences { storage, data })
111 }
112
113 fn store(&self) -> Result<(), JsValue> {
114 if let Some(storage) = self.storage.as_ref() {
115 let data = serde_json::to_string(&self.data).unwrap();
116 storage.set_item(PREFERENCES_KEY, &data)
117 } else {
118 Ok(())
119 }
120 }
121}
122
123#[macro_export]
149macro_rules! impl_dummy_preferences {
150 {$($name:ident : $ty:ty,)*} => {
151 impl Preferences {
152 $(
153 paste::paste! {
154 pub fn [<update_ $name>](&mut self, _value: &$ty) -> Result<(), wasm_bindgen::JsValue> {
155 Ok(())
156 }
157 }
158 )*
159 }
160 }
161}
162
163impl_dummy_preferences!(
164 ddc_output_sampling_frequency: f64,
165 ddc_max_input_sampling_frequency: f64,
166);