Skip to content

Commit ba226f8

Browse files
committed
fix selectors
1 parent 61473c2 commit ba226f8

File tree

3 files changed

+138
-81
lines changed

3 files changed

+138
-81
lines changed

src/app.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ pub fn App() -> Element {
4242
let loaded_yamls = load_yamls();
4343
app_state.write().loaded_yamls = loaded_yamls;
4444
}
45+
46+
4547
});
4648

4749
use_context_provider(|| app_state);

src/ui/top_panel.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,19 +104,23 @@ pub fn TopPanel() -> Element {
104104
select {
105105
value: "{app_state().selected_yaml}",
106106
onchange: move |evt| {
107-
app_state.write().selected_yaml = evt.value();
108-
if let Ok(new_yaml) = get_yaml_manager().load_yaml(&evt.value()) {
107+
let selected_yaml = evt.value().to_string();
108+
app_state.write().selected_yaml = selected_yaml.clone();
109+
if let Ok(new_yaml) = get_yaml_manager().load_yaml(&selected_yaml) {
109110
app_state.write().yaml = new_yaml;
110111
} else {
111-
error!("Failed to load yaml: {}", evt.value());
112+
error!("Failed to load yaml: {}", selected_yaml);
112113
}
113114
},
114115
for option in options.iter() {
115-
option { value: "{option}", "{option}" }
116+
option {
117+
value: "{option}",
118+
selected: if *option == app_state().selected_yaml { true } else { false },
119+
"{option}"
120+
}
116121
}
117122
}
118123

119-
label { "Life Expectancy: " }
120124
select {
121125
value: "{app_state().yaml.life_expectancy}",
122126
onchange: move |evt| {
@@ -127,7 +131,11 @@ pub fn TopPanel() -> Element {
127131
}
128132
},
129133
for year in 60..=120 {
130-
option { value: "{year}", "{year}" }
134+
option {
135+
value: "{year}",
136+
selected: if year == app_state().yaml.life_expectancy { true } else { false },
137+
"{year}"
138+
}
131139
}
132140
}
133141
}

src/yaml_manager.rs

Lines changed: 122 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::models::Yaml;
22
use std::io;
3+
34
#[cfg(not(target_arch = "wasm32"))]
45
use std::fs;
56
#[cfg(not(target_arch = "wasm32"))]
@@ -13,11 +14,11 @@ use web_sys::{Blob, HtmlAnchorElement, Url, FileReader};
1314
use wasm_bindgen_futures::JsFuture;
1415
#[cfg(target_arch = "wasm32")]
1516
use js_sys;
16-
#[cfg(target_arch = "wasm32")]
17-
use rfd;
1817

1918
use dioxus::prelude::*;
2019
use crate::models::MyLifeApp;
20+
use rfd::FileDialog;
21+
2122

2223
#[cfg(target_arch = "wasm32")]
2324
const DEFAULT_YAML: &str = include_str!("../data/default.yaml");
@@ -43,33 +44,33 @@ impl NativeYamlManager {
4344
#[cfg(not(target_arch = "wasm32"))]
4445
impl YamlManager for NativeYamlManager {
4546
fn load_yaml(&self, yaml_file: &str) -> io::Result<Yaml> {
46-
let yaml_path = std::path::Path::new(&self.data_folder).join(yaml_file);
47-
let yaml_content = std::fs::read_to_string(yaml_path)?;
48-
let yaml: Yaml = serde_yaml::from_str(&yaml_content)
49-
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
50-
Ok(yaml)
47+
let yaml_path = Path::new(&self.data_folder).join(yaml_file);
48+
let yaml_content = fs::read_to_string(yaml_path)?;
49+
serde_yaml::from_str(&yaml_content)
50+
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
5151
}
5252

5353
fn save_yaml(&self, yaml: &Yaml, yaml_file: &str) -> io::Result<()> {
54-
let yaml_content = serde_yaml::to_string(&yaml)
54+
let yaml_content = serde_yaml::to_string(yaml)
5555
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
56-
let yaml_path = std::path::Path::new(&self.data_folder).join(yaml_file);
57-
std::fs::write(yaml_path, yaml_content)
56+
let yaml_path = Path::new(&self.data_folder).join(yaml_file);
57+
fs::write(yaml_path, yaml_content)
5858
}
59-
6059
fn get_available_yamls(&self) -> io::Result<Vec<String>> {
6160
let data_folder = Path::new(&self.data_folder);
62-
Ok(fs::read_dir(data_folder)?
61+
let yamls = fs::read_dir(data_folder)?
6362
.filter_map(|entry| {
64-
let entry = entry.ok()?;
65-
let path = entry.path();
66-
if path.extension()? == "yaml" {
67-
Some(path.file_name()?.to_string_lossy().into_owned())
68-
} else {
69-
None
70-
}
63+
entry.ok().and_then(|e| {
64+
let path = e.path();
65+
if path.extension().and_then(|s| s.to_str()) == Some("yaml") {
66+
path.file_name().and_then(|s| s.to_str()).map(String::from)
67+
} else {
68+
None
69+
}
70+
})
7171
})
72-
.collect())
72+
.collect::<Vec<String>>();
73+
Ok(yamls)
7374
}
7475
}
7576

@@ -83,7 +84,7 @@ impl YamlManager for WasmYamlManager {
8384
}
8485

8586
fn save_yaml(&self, yaml: &Yaml, _yaml_file: &str) -> io::Result<()> {
86-
let yaml_content = serde_yaml::to_string(&yaml)
87+
let yaml_content = serde_yaml::to_string(yaml)
8788
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
8889

8990
let blob = Blob::new_with_str_sequence(&js_sys::Array::of1(&yaml_content.into()))
@@ -129,40 +130,45 @@ pub fn get_yaml_manager() -> Box<dyn YamlManager> {
129130

130131
#[cfg(target_arch = "wasm32")]
131132
pub fn get_default_yaml() -> Yaml {
132-
load_yaml_from_yaml_content(DEFAULT_YAML).expect("Failed to load default yaml")
133+
serde_yaml::from_str(DEFAULT_YAML).expect("Failed to load default yaml")
133134
}
134135

135-
#[cfg(target_arch = "wasm32")]
136-
pub fn load_yaml_from_yaml_content(yaml_content: &str) -> Result<Yaml, String> {
137-
serde_yaml::from_str(yaml_content)
138-
.map_err(|e| format!("Failed to parse YAML: {:?}", e))
139-
}
140-
141-
#[cfg(target_arch = "wasm32")]
142136
pub async fn load_yaml_async() -> Option<(String, Yaml)> {
143-
let file = rfd::AsyncFileDialog::new()
144-
.add_filter("YAML", &["yaml", "yml"])
145-
.pick_file()
146-
.await?;
147-
148-
let file_name = file.file_name();
149-
let file_content = file.read().await;
137+
#[cfg(target_arch = "wasm32")]
138+
{
139+
let file = rfd::AsyncFileDialog::new()
140+
.add_filter("YAML", &["yaml", "yml"])
141+
.pick_file()
142+
.await?;
143+
144+
let file_name = file.file_name();
145+
let content = String::from_utf8(file.read().await).ok()?;
146+
147+
serde_yaml::from_str(&content)
148+
.map(|yaml| Some((file_name, yaml)))
149+
.unwrap_or_else(|e| {
150+
log::error!("Failed to load yaml from YAML: {:?}", e);
151+
None
152+
})
153+
}
150154

151-
let blob = Blob::new_with_u8_array_sequence(&js_sys::Array::of1(&js_sys::Uint8Array::from(&file_content[..])))
152-
.map_err(|_| "Failed to create Blob".to_string()).ok()?;
155+
#[cfg(not(target_arch = "wasm32"))]
156+
{
157+
use tokio::fs;
153158

154-
let reader = FileReader::new().unwrap();
155-
reader.read_as_text(&blob).unwrap();
159+
let file = rfd::FileDialog::new()
160+
.add_filter("YAML", &["yaml", "yml"])
161+
.pick_file()?;
156162

157-
let promise = js_sys::Promise::resolve(&reader.result().unwrap());
158-
let content = JsFuture::from(promise).await.ok()?.as_string().unwrap();
163+
let file_name = file.file_name()?.to_string_lossy().into_owned();
164+
let content = fs::read_to_string(&file).await.ok()?;
159165

160-
match load_yaml_from_yaml_content(&content) {
161-
Ok(yaml) => Some((file_name, yaml)),
162-
Err(e) => {
163-
log::error!("Failed to load yaml from YAML: {:?}", e);
164-
None
165-
}
166+
serde_yaml::from_str(&content)
167+
.map(|yaml| Some((file_name, yaml)))
168+
.unwrap_or_else(|e| {
169+
log::error!("Failed to load yaml from YAML: {:?}", e);
170+
None
171+
})
166172
}
167173
}
168174

@@ -173,44 +179,85 @@ pub fn get_yaml() -> Yaml {
173179
}
174180

175181
pub fn save_yaml(yaml: &Yaml, yaml_file: &str) -> Result<(), String> {
176-
get_yaml_manager()
177-
.save_yaml(yaml, yaml_file)
178-
.map_err(|e| format!("Failed to save yaml: {:?}", e))
179-
}
182+
#[cfg(not(target_arch = "wasm32"))]
183+
{
184+
let yaml_content = serde_yaml::to_string(yaml)
185+
.map_err(|e| format!("Failed to serialize YAML: {:?}", e))?;
186+
187+
let file_path = FileDialog::new()
188+
.set_file_name(yaml_file)
189+
.add_filter("YAML File", &["yaml", "yml"])
190+
.save_file();
191+
192+
if let Some(path) = file_path {
193+
std::fs::write(path, yaml_content)
194+
.map_err(|e| format!("Failed to save YAML file: {:?}", e))?;
195+
Ok(())
196+
} else {
197+
Err("File save cancelled".to_string())
198+
}
199+
}
180200

201+
#[cfg(target_arch = "wasm32")]
202+
{
203+
get_yaml_manager()
204+
.save_yaml(yaml, yaml_file)
205+
.map_err(|e| format!("Failed to save yaml: {:?}", e))
206+
}
207+
}
181208
pub fn get_available_yamls() -> Vec<String> {
182209
get_yaml_manager()
183210
.get_available_yamls()
184211
.expect("Failed to get available yamls")
185212
}
186213

187-
#[cfg(not(target_arch = "wasm32"))]
188214
pub fn import_yaml() -> Option<(String, Yaml)> {
189-
let app_state = use_context::<Signal<MyLifeApp>>();
190-
191-
if let Some(file_path) = rfd::FileDialog::new()
192-
.add_filter("YAML", &["yaml", "yml"])
193-
.pick_file()
215+
#[cfg(not(target_arch = "wasm32"))]
194216
{
195-
let file_name = file_path.file_name()?.to_str()?.to_string();
196-
let content = fs::read_to_string(&file_path).ok()?;
197-
let yaml: Yaml = serde_yaml::from_str(&content).ok()?;
198-
199-
let data_folder_string = app_state.read().data_folder.clone();
200-
let data_folder = Path::new(&data_folder_string);
201-
202-
let mut new_file_name = file_name.clone();
203-
let mut counter = 1;
204-
205-
while data_folder.join(&new_file_name).exists() {
206-
new_file_name = format!("{}-{}.yaml", file_name.trim_end_matches(".yaml"), counter);
207-
counter += 1;
217+
let app_state = use_context::<Signal<MyLifeApp>>();
218+
219+
if let Some(file_path) = rfd::FileDialog::new()
220+
.add_filter("YAML", &["yaml", "yml"])
221+
.pick_file()
222+
{
223+
let file_name = file_path.file_name()?.to_str()?.to_string();
224+
let content = fs::read_to_string(&file_path).ok()?;
225+
let yaml: Yaml = serde_yaml::from_str(&content).ok()?;
226+
227+
let data_folder_string = app_state.read().data_folder.clone();
228+
let data_folder = Path::new(&data_folder_string);
229+
230+
let mut new_file_name = file_name.clone();
231+
let mut counter = 1;
232+
233+
while data_folder.join(&new_file_name).exists() {
234+
new_file_name = format!("{}-{}.yaml", file_name.trim_end_matches(".yaml"), counter);
235+
counter += 1;
236+
}
237+
238+
fs::copy(file_path, data_folder.join(&new_file_name)).ok()?;
239+
240+
Some((new_file_name, yaml))
241+
} else {
242+
None
208243
}
244+
}
245+
246+
#[cfg(target_arch = "wasm32")]
247+
{
248+
// For WASM, we'll use the load_yaml_async function
249+
use wasm_bindgen_futures::spawn_local;
209250

210-
fs::copy(file_path, data_folder.join(&new_file_name)).ok()?;
251+
let (tx, rx) = std::sync::mpsc::channel();
211252

212-
Some((new_file_name, yaml))
213-
} else {
214-
None
253+
spawn_local(async move {
254+
if let Some((name, yaml)) = load_yaml_async().await {
255+
tx.send(Some((name, yaml))).unwrap();
256+
} else {
257+
tx.send(None).unwrap();
258+
}
259+
});
260+
261+
rx.recv().unwrap()
215262
}
216263
}

0 commit comments

Comments
 (0)