This commit is contained in:
vcoppe
2026-10-04 11:00:46 +02:00
parent caba9388af
commit f458a1104f
15 changed files with 797 additions and 455 deletions
@@ -17,6 +17,10 @@ impl Editor for Metadata<'_> {
fn file(&mut self, file: &mut File) -> Edit {
file.info.name = self.name.to_owned();
file.info.desc = Some(self.desc.to_owned());
// a single track is named like the file
if let [track] = file.trk.as_mut_slice() {
track.info.name = Some(self.name.to_owned());
}
Edit::Changed
}
@@ -31,7 +35,7 @@ impl Editor for Metadata<'_> {
mod tests {
use std::collections::HashSet;
use crate::{New, Selection, engine::command::fixture::Fixture};
use crate::{New, NewTrack, Selection, engine::command::fixture::Fixture};
use super::*;
@@ -83,4 +87,55 @@ mod tests {
assert_eq!(after.trk[0].info.name.as_deref(), Some("renamed"));
assert_eq!(after.trk[1].info, file.trk[1].info);
}
/// A new file with `nb_tracks` tracks (without name), selected.
fn file_with_tracks(fx: &mut Fixture, nb_tracks: usize) {
New { name: "file" }.apply(&mut fx.state()).unwrap();
for _ in 0..nb_tracks {
NewTrack.apply(&mut fx.state()).unwrap();
}
}
fn rename(fx: &mut Fixture) {
Metadata {
name: "renamed",
desc: "",
}
.apply(&mut fx.state())
.unwrap();
}
#[test]
fn test_single_track_is_renamed_like_the_file() {
let mut fx = Fixture::default();
file_with_tracks(&mut fx, 1);
rename(&mut fx);
let file = fx.files.values().next().unwrap();
assert_eq!(file.info.name, "renamed");
assert_eq!(file.trk[0].info.name.as_deref(), Some("renamed"));
}
#[test]
fn test_single_track_with_a_name_is_renamed_too() {
let mut fx = Fixture::default();
file_with_tracks(&mut fx, 1);
let id = *fx.files.keys().next().unwrap();
std::rc::Rc::make_mut(fx.files.get_mut(&id).unwrap()).trk[0]
.info
.name = Some("track".to_owned());
rename(&mut fx);
let file = &fx.files[&id];
assert_eq!(file.info.name, "renamed");
assert_eq!(file.trk[0].info.name.as_deref(), Some("renamed"));
}
#[test]
fn test_several_tracks_are_not_renamed() {
let mut fx = Fixture::default();
file_with_tracks(&mut fx, 2);
rename(&mut fx);
let file = fx.files.values().next().unwrap();
assert_eq!(file.info.name, "renamed");
assert!(file.trk.iter().all(|trk| trk.info.name.is_none()));
}
}
@@ -12,6 +12,7 @@ use crate::{
pub struct FileStructure {
pub id: FileId,
pub name: String,
pub desc: Option<String>,
pub tracks: Vec<TrackNode>,
pub waypoints: Vec<WaypointNode>,
/// Changes whenever the waypoints of the file (hence their buffer) change.
@@ -22,6 +23,7 @@ pub struct FileStructure {
pub struct TrackNode {
pub id: TrackId,
pub name: Option<String>,
pub desc: Option<String>,
/// Style of the track, only when the file defines it.
pub color: Option<String>,
pub opacity: Option<f64>,
@@ -49,12 +51,14 @@ impl FileStructure {
Self {
id: file.id,
name: file.info.name.clone(),
desc: file.info.desc.clone(),
tracks: file
.trk
.iter()
.map(|trk| TrackNode {
id: trk.id,
name: trk.info.name.clone(),
desc: trk.info.desc.clone(),
color: trk.info.color.clone(),
opacity: trk.info.opacity,
width: trk.info.width,
@@ -99,10 +103,13 @@ mod tests {
Load { data: &data }.apply(&mut fx.state()).unwrap();
let file = &fx.files[&fx.order.0[0]];
let node = FileStructure::new(file);
assert_eq!((node.id, &node.name), (file.id, &file.info.name));
assert_eq!(
(node.id, &node.name, &node.desc),
(file.id, &file.info.name, &file.info.desc)
);
assert_eq!(node.tracks.len(), file.trk.len());
for (n, t) in node.tracks.iter().zip(&file.trk) {
assert_eq!((n.id, &n.name), (t.id, &t.info.name));
assert_eq!((n.id, &n.name, &n.desc), (t.id, &t.info.name, &t.info.desc));
assert_eq!(
(&n.color, n.opacity, n.width),
(&t.info.color, t.info.opacity, t.info.width)
+8
View File
@@ -436,6 +436,7 @@ export interface FilesUpdate {
export interface FileStructure {
id: string;
name: string;
desc?: string;
tracks: TrackNode[];
waypoints: WaypointNode[];
/** Changes when the waypoints of the file change: refetch their coordinates. */
@@ -463,6 +464,7 @@ export interface FileStatistics {
export interface TrackNode {
id: string;
name?: string;
desc?: string;
/** Style of the track, only present when the file defines it. */
color?: string;
opacity?: number;
@@ -520,11 +522,17 @@ fn named_node(id: uuid::Uuid, name: Option<&str>) -> Object {
fn structure_object(file: &engine::FileStructure) -> Object {
let node = named_node(file.id.0, Some(&file.name));
if let Some(desc) = &file.desc {
set(&node, "desc", desc.as_str());
}
set(
&node,
"tracks",
array(&file.tracks, |trk| {
let node = named_node(trk.id.0, trk.name.as_deref());
if let Some(desc) = &trk.desc {
set(&node, "desc", desc.as_str());
}
if let Some(color) = &trk.color {
set(&node, "color", color.as_str());
}