diff --git a/gpx-rs/engine/src/engine/command/edit/metadata.rs b/gpx-rs/engine/src/engine/command/edit/metadata.rs
index 4009d1cc0..72fa76d4d 100644
--- a/gpx-rs/engine/src/engine/command/edit/metadata.rs
+++ b/gpx-rs/engine/src/engine/command/edit/metadata.rs
@@ -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,
diff --git a/gpx-rs/engine/src/engine/command/edit/style.rs b/gpx-rs/engine/src/engine/command/edit/style.rs
index 009f98d94..fcef0d2c8 100644
--- a/gpx-rs/engine/src/engine/command/edit/style.rs
+++ b/gpx-rs/engine/src/engine/command/edit/style.rs
@@ -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());
diff --git a/gpx-rs/engine/src/engine/command/file/delete.rs b/gpx-rs/engine/src/engine/command/file/delete.rs
index d420168bc..9099e9bcc 100644
--- a/gpx-rs/engine/src/engine/command/file/delete.rs
+++ b/gpx-rs/engine/src/engine/command/file/delete.rs
@@ -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)
}
diff --git a/gpx-rs/engine/src/engine/command/file/duplicate.rs b/gpx-rs/engine/src/engine/command/file/duplicate.rs
index 709f93ccf..4be58e267 100644
--- a/gpx-rs/engine/src/engine/command/file/duplicate.rs
+++ b/gpx-rs/engine/src/engine/command/file/duplicate.rs
@@ -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)
}
diff --git a/gpx-rs/engine/src/engine/command/file/load.rs b/gpx-rs/engine/src/engine/command/file/load.rs
index 141257c63..8522e1371 100644
--- a/gpx-rs/engine/src/engine/command/file/load.rs
+++ b/gpx-rs/engine/src/engine/command/file/load.rs
@@ -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"",
+ 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#"in the file"#;
+ assert_eq!(load_with_name(data), "in the file");
+ }
+
+ #[test]
+ fn test_load_without_name_uses_the_given_name() {
+ let without = br#""#;
+ assert_eq!(load_with_name(without), "from disk");
+ let empty = br#" "#;
+ assert_eq!(load_with_name(empty), "from disk");
+ }
}
diff --git a/gpx-rs/engine/src/engine/command/tools/splice_trackpoints.rs b/gpx-rs/engine/src/engine/command/tools/splice_trackpoints.rs
index e45cdfc75..d439d1531 100644
--- a/gpx-rs/engine/src/engine/command/tools/splice_trackpoints.rs
+++ b/gpx-rs/engine/src/engine/command/tools/splice_trackpoints.rs
@@ -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]),
diff --git a/gpx-rs/engine/src/engine/derived/coordinates_cache.rs b/gpx-rs/engine/src/engine/derived/coordinates_cache.rs
index 461c6166f..6c5772c75 100644
--- a/gpx-rs/engine/src/engine/derived/coordinates_cache.rs
+++ b/gpx-rs/engine/src/engine/derived/coordinates_cache.rs
@@ -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)
}
diff --git a/gpx-rs/engine/src/engine/derived/file_structure.rs b/gpx-rs/engine/src/engine/derived/file_structure.rs
index 613ab4214..df68afa5c 100644
--- a/gpx-rs/engine/src/engine/derived/file_structure.rs
+++ b/gpx-rs/engine/src/engine/derived/file_structure.rs
@@ -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!(
diff --git a/gpx-rs/engine/src/engine/derived/file_structure_cache.rs b/gpx-rs/engine/src/engine/derived/file_structure_cache.rs
index 0ab33fbb9..e13668146 100644
--- a/gpx-rs/engine/src/engine/derived/file_structure_cache.rs
+++ b/gpx-rs/engine/src/engine/derived/file_structure_cache.rs
@@ -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();
diff --git a/gpx-rs/engine/src/engine/engine.rs b/gpx-rs/engine/src/engine/engine.rs
index 83301158c..018f955e0 100644
--- a/gpx-rs/engine/src/engine/engine.rs
+++ b/gpx-rs/engine/src/engine/engine.rs
@@ -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 {
@@ -213,7 +219,8 @@ mod tests {
assert!(!edit(
&mut engine,
Command::Load(Load {
- data: b""
+ data: b"",
+ name: "file",
})
));
assert!(engine.stack.current().is_none());
diff --git a/gpx-rs/wasm/src/lib.rs b/gpx-rs/wasm/src/lib.rs
index dff664211..7658d26da 100644
--- a/gpx-rs/wasm/src/lib.rs
+++ b/gpx-rs/wasm/src/lib.rs
@@ -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]
diff --git a/website/src/lib/components/file-list/sortable-file-list.ts b/website/src/lib/components/file-list/sortable-file-list.ts
index 221279bc4..91327d4dc 100644
--- a/website/src/lib/components/file-list/sortable-file-list.ts
+++ b/website/src/lib/components/file-list/sortable-file-list.ts
@@ -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. */
diff --git a/website/src/lib/engine.ts b/website/src/lib/engine.ts
index c1dd5b0d5..75beae061 100644
--- a/website/src/lib/engine.ts
+++ b/website/src/lib/engine.ts
@@ -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() {