mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2026-10-06 22:04:06 +00:00
fixes
This commit is contained in:
@@ -68,7 +68,12 @@ mod tests {
|
||||
fn test_metadata_applies_to_selected_track() {
|
||||
let mut fx = Fixture::default();
|
||||
let data = std::fs::read("data/with_tracks.gpx").unwrap();
|
||||
crate::Load { data: &data }.apply(&mut fx.state()).unwrap();
|
||||
crate::Load {
|
||||
data: &data,
|
||||
name: "file",
|
||||
}
|
||||
.apply(&mut fx.state())
|
||||
.unwrap();
|
||||
let file = fx.files.values().next().unwrap().clone();
|
||||
fx.selection = Selection::Track {
|
||||
file_id: file.id,
|
||||
|
||||
@@ -41,7 +41,12 @@ mod tests {
|
||||
fn test_style_applies_to_all_tracks_of_selected_file_and_keeps_unset_fields() {
|
||||
let mut fx = Fixture::default();
|
||||
let data = std::fs::read("data/with_style.gpx").unwrap();
|
||||
crate::Load { data: &data }.apply(&mut fx.state()).unwrap();
|
||||
crate::Load {
|
||||
data: &data,
|
||||
name: "file",
|
||||
}
|
||||
.apply(&mut fx.state())
|
||||
.unwrap();
|
||||
let id = *fx.files.keys().next().unwrap();
|
||||
let before = fx.files[&id].clone();
|
||||
assert!(!before.trk.is_empty());
|
||||
|
||||
@@ -98,7 +98,12 @@ mod tests {
|
||||
fn loaded() -> (Fixture, FileId) {
|
||||
let mut fx = Fixture::default();
|
||||
let data = std::fs::read("data/with_tracks_and_segments.gpx").unwrap();
|
||||
Load { data: &data }.apply(&mut fx.state()).unwrap();
|
||||
Load {
|
||||
data: &data,
|
||||
name: "file",
|
||||
}
|
||||
.apply(&mut fx.state())
|
||||
.unwrap();
|
||||
let id = fx.order.0[0];
|
||||
(fx, id)
|
||||
}
|
||||
|
||||
@@ -211,7 +211,12 @@ mod tests {
|
||||
fn loaded() -> (Fixture, FileId) {
|
||||
let mut fx = Fixture::default();
|
||||
let data = std::fs::read("data/with_tracks_and_segments.gpx").unwrap();
|
||||
Load { data: &data }.apply(&mut fx.state()).unwrap();
|
||||
Load {
|
||||
data: &data,
|
||||
name: "file",
|
||||
}
|
||||
.apply(&mut fx.state())
|
||||
.unwrap();
|
||||
let id = fx.order.0[0];
|
||||
(fx, id)
|
||||
}
|
||||
|
||||
@@ -3,11 +3,18 @@ use crate::{Apply, CommandError, State, parse, produce};
|
||||
#[derive(Debug)]
|
||||
pub struct Load<'a> {
|
||||
pub data: &'a [u8],
|
||||
/// Name of the file when the data has none (typically the name of the file on disk, without
|
||||
/// its extension).
|
||||
pub name: &'a str,
|
||||
}
|
||||
|
||||
impl Apply for Load<'_> {
|
||||
fn apply(self, state: &mut State) -> Result<(), CommandError> {
|
||||
let file = parse(self.data).map_err(|err| CommandError::InvalidData(err.to_string()))?;
|
||||
let mut file =
|
||||
parse(self.data).map_err(|err| CommandError::InvalidData(err.to_string()))?;
|
||||
if file.info.name.trim().is_empty() {
|
||||
file.info.name = self.name.to_owned();
|
||||
}
|
||||
produce(state, |_| vec![file]);
|
||||
Ok(())
|
||||
}
|
||||
@@ -23,7 +30,14 @@ mod tests {
|
||||
fn test_load() {
|
||||
let mut fx = Fixture::default();
|
||||
let data = std::fs::read("data/with_tracks.gpx").unwrap();
|
||||
assert!(Load { data: &data }.apply(&mut fx.state()).is_ok());
|
||||
assert!(
|
||||
Load {
|
||||
data: &data,
|
||||
name: "file",
|
||||
}
|
||||
.apply(&mut fx.state())
|
||||
.is_ok()
|
||||
);
|
||||
assert_eq!(fx.files.len(), 1);
|
||||
let file = fx.files.values().next().unwrap();
|
||||
assert!(!file.trk.is_empty());
|
||||
@@ -38,6 +52,7 @@ mod tests {
|
||||
|
||||
let result = Load {
|
||||
data: b"<gpx><trk></gpx>",
|
||||
name: "file",
|
||||
}
|
||||
.apply(&mut fx.state());
|
||||
assert!(matches!(result, Err(CommandError::InvalidData(_))));
|
||||
@@ -45,4 +60,29 @@ mod tests {
|
||||
assert_eq!(fx.order.0.len(), 1);
|
||||
assert_eq!(fx.selected_files(), selected);
|
||||
}
|
||||
|
||||
fn load_with_name(data: &[u8]) -> String {
|
||||
let mut fx = Fixture::default();
|
||||
Load {
|
||||
data,
|
||||
name: "from disk",
|
||||
}
|
||||
.apply(&mut fx.state())
|
||||
.unwrap();
|
||||
fx.files.values().next().unwrap().info.name.clone()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_load_keeps_the_name_of_the_file() {
|
||||
let data = br#"<gpx version="1.1"><metadata><name>in the file</name></metadata></gpx>"#;
|
||||
assert_eq!(load_with_name(data), "in the file");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_load_without_name_uses_the_given_name() {
|
||||
let without = br#"<gpx version="1.1"><trk><trkseg></trkseg></trk></gpx>"#;
|
||||
assert_eq!(load_with_name(without), "from disk");
|
||||
let empty = br#"<gpx version="1.1"><metadata><name> </name></metadata></gpx>"#;
|
||||
assert_eq!(load_with_name(empty), "from disk");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,12 @@ mod tests {
|
||||
fn loaded() -> (Fixture, FileId) {
|
||||
let mut fx = Fixture::default();
|
||||
let data = std::fs::read("data/with_tracks_and_segments.gpx").unwrap();
|
||||
Load { data: &data }.apply(&mut fx.state()).unwrap();
|
||||
Load {
|
||||
data: &data,
|
||||
name: "file",
|
||||
}
|
||||
.apply(&mut fx.state())
|
||||
.unwrap();
|
||||
let id = fx.order.0[0];
|
||||
let trk = &fx.files[&id].trk[0];
|
||||
fx.selection = Selection::TrackSegment {
|
||||
@@ -282,7 +287,12 @@ mod tests {
|
||||
fn test_splice_on_multiple_files_uses_last_in_file_order() {
|
||||
let (mut fx, first) = loaded();
|
||||
let data = std::fs::read("data/with_tracks_and_segments.gpx").unwrap();
|
||||
Load { data: &data }.apply(&mut fx.state()).unwrap();
|
||||
Load {
|
||||
data: &data,
|
||||
name: "file",
|
||||
}
|
||||
.apply(&mut fx.state())
|
||||
.unwrap();
|
||||
let second = fx.order.0[1];
|
||||
fx.selection = Selection::File {
|
||||
file_ids: HashSet::from([second, first]),
|
||||
|
||||
@@ -73,7 +73,12 @@ mod tests {
|
||||
fn loaded() -> (Fixture, FileId) {
|
||||
let mut fx = Fixture::default();
|
||||
let data = std::fs::read("data/with_tracks_and_segments.gpx").unwrap();
|
||||
Load { data: &data }.apply(&mut fx.state()).unwrap();
|
||||
Load {
|
||||
data: &data,
|
||||
name: "file",
|
||||
}
|
||||
.apply(&mut fx.state())
|
||||
.unwrap();
|
||||
let id = fx.order.0[0];
|
||||
(fx, id)
|
||||
}
|
||||
|
||||
@@ -100,7 +100,12 @@ mod tests {
|
||||
fn test_structure_of_a_file() {
|
||||
let mut fx = Fixture::default();
|
||||
let data = std::fs::read("data/with_tracks_and_segments.gpx").unwrap();
|
||||
Load { data: &data }.apply(&mut fx.state()).unwrap();
|
||||
Load {
|
||||
data: &data,
|
||||
name: "file",
|
||||
}
|
||||
.apply(&mut fx.state())
|
||||
.unwrap();
|
||||
let file = &fx.files[&fx.order.0[0]];
|
||||
let node = FileStructure::new(file);
|
||||
assert_eq!(
|
||||
|
||||
@@ -41,8 +41,18 @@ mod tests {
|
||||
fn test_only_files_of_the_diff_are_recomputed() {
|
||||
let mut fx = Fixture::default();
|
||||
let data = std::fs::read("data/with_tracks_and_segments.gpx").unwrap();
|
||||
Load { data: &data }.apply(&mut fx.state()).unwrap();
|
||||
Load { data: &data }.apply(&mut fx.state()).unwrap();
|
||||
Load {
|
||||
data: &data,
|
||||
name: "file",
|
||||
}
|
||||
.apply(&mut fx.state())
|
||||
.unwrap();
|
||||
Load {
|
||||
data: &data,
|
||||
name: "file",
|
||||
}
|
||||
.apply(&mut fx.state())
|
||||
.unwrap();
|
||||
let (a, b) = (fx.order.0[0], fx.order.0[1]);
|
||||
|
||||
let mut cache = FileStructureCache::default();
|
||||
|
||||
@@ -164,7 +164,13 @@ mod tests {
|
||||
|
||||
fn load(engine: &mut Engine, path: &str) -> bool {
|
||||
let data = std::fs::read(path).unwrap();
|
||||
edit(engine, Command::Load(Load { data: &data }))
|
||||
edit(
|
||||
engine,
|
||||
Command::Load(Load {
|
||||
data: &data,
|
||||
name: "file",
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
fn selected(engine: &Engine) -> Vec<FileId> {
|
||||
@@ -213,7 +219,8 @@ mod tests {
|
||||
assert!(!edit(
|
||||
&mut engine,
|
||||
Command::Load(Load {
|
||||
data: b"<gpx><trk></gpx>"
|
||||
data: b"<gpx><trk></gpx>",
|
||||
name: "file",
|
||||
})
|
||||
));
|
||||
assert!(engine.stack.current().is_none());
|
||||
|
||||
@@ -149,9 +149,10 @@ pub fn new_file(name: &str) -> bool {
|
||||
edit(Command::New(engine::New { name }))
|
||||
}
|
||||
|
||||
/// `name`: the name of the file when the data has none (the name on disk, without extension).
|
||||
#[wasm_bindgen]
|
||||
pub fn load_file(data: &[u8]) -> bool {
|
||||
edit(Command::Load(engine::Load { data }))
|
||||
pub fn load_file(data: &[u8], name: &str) -> bool {
|
||||
edit(Command::Load(engine::Load { data, name }))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
|
||||
@@ -85,7 +85,11 @@ export class SortableFileList {
|
||||
this._unsubscribes.push(
|
||||
engine.selection.subscribe(() => tick().then(() => this.updateFromSelection()))
|
||||
);
|
||||
this._unsubscribes.push(engine.order.subscribe(() => this.updateFromFileOrder()));
|
||||
// after the elements are rendered: sorting a list that does not have the new files yet
|
||||
// would put them at the beginning
|
||||
this._unsubscribes.push(
|
||||
engine.order.subscribe(() => tick().then(() => this.updateFromFileOrder()))
|
||||
);
|
||||
}
|
||||
|
||||
/** The node of a child of the list. */
|
||||
|
||||
@@ -147,8 +147,9 @@ class Engine {
|
||||
return this.run((w) => w.new_file(name));
|
||||
}
|
||||
|
||||
loadFile(data: Uint8Array) {
|
||||
return this.run((w) => w.load_file(data));
|
||||
/** `name` is the name of the file when the data has none (the name on disk, without extension). */
|
||||
loadFile(data: Uint8Array, name: string) {
|
||||
return this.run((w) => w.load_file(data, name));
|
||||
}
|
||||
|
||||
duplicate() {
|
||||
|
||||
Reference in New Issue
Block a user