This commit is contained in:
vcoppe
2026-10-03 19:17:58 +02:00
parent 438a87f06f
commit fd76e0fa46
9 changed files with 42 additions and 24 deletions
+1 -1
View File
@@ -31,7 +31,7 @@ impl TrackpointChunk {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct WaypointChunkId(Uuid);
impl Default for WaypointChunkId {
+10
View File
@@ -13,12 +13,22 @@ impl Default for FileId {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct FileWaypointsRevisionId(pub Uuid);
impl Default for FileWaypointsRevisionId {
fn default() -> Self {
Self(Uuid::new_v4())
}
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct File {
pub id: FileId,
pub info: FileInfo,
pub trk: Vec<Track>,
pub wpt: Vec<Rc<WaypointChunk>>,
pub wpt_rev_id: FileWaypointsRevisionId,
// TODO routes
}
@@ -181,7 +181,9 @@ mod tests {
file_id: id,
wpt_ids: HashSet::from([ids[1]]),
};
let rev = fx.files[&id].wpt_rev_id;
Delete.apply(&mut fx.state()).unwrap();
assert_ne!(fx.files[&id].wpt_rev_id, rev);
let left: Vec<_> = fx.files[&id]
.wpt
.iter()
@@ -161,6 +161,7 @@ fn duplicate_waypoints(
chunks
};
file.wpt.splice(last_chunk..=last_chunk, replacement);
file.wpt_rev_id = Default::default();
files.insert(file_id, Rc::new(file));
Ok(Selection::Waypoint {
file_id,
@@ -304,7 +305,9 @@ mod tests {
file_id: id,
wpt_ids: HashSet::from([ids[0]]),
};
let rev = fx.files[&id].wpt_rev_id;
Duplicate.apply(&mut fx.state()).unwrap();
assert_ne!(fx.files[&id].wpt_rev_id, rev);
let all: Vec<_> = fx.files[&id]
.wpt
.iter()
@@ -33,5 +33,8 @@ pub fn edit_waypoint_chunks(
}
}
file.wpt = chunks;
if changed {
file.wpt_rev_id = Default::default();
}
changed
}
@@ -305,7 +305,9 @@ mod tests {
file_id: id,
wpt_ids: HashSet::from([ids[1]]),
};
let rev = fx.files[&id].wpt_rev_id;
update_selected(&mut fx.state(), &mut Name);
assert_ne!(fx.files[&id].wpt_rev_id, rev);
let chunk = &fx.files[&id].wpt[0];
assert_ne!(chunk.id, chunk_id);
let named: Vec<_> = chunk.wpt.iter().map(|w| w.name.is_some()).collect();
@@ -1,7 +1,7 @@
use std::collections::{HashMap, HashSet};
use crate::{
FileId, StackEntry as Files, TrackSegmentId, TrackSegmentRevisionId, waypoints_revision,
FileId, FileWaypointsRevisionId, StackEntry as Files, TrackSegmentId, TrackSegmentRevisionId,
};
/// Coordinates buffers, as flat `[lng, lat, lng, lat, ...]` arrays so that they can be handed
@@ -11,7 +11,7 @@ use crate::{
#[derive(Debug, Default)]
pub struct CoordinatesCache {
segments: HashMap<TrackSegmentId, (TrackSegmentRevisionId, Vec<f64>)>,
waypoints: HashMap<FileId, (u64, Vec<f64>)>,
waypoints: HashMap<FileId, (FileWaypointsRevisionId, Vec<f64>)>,
}
impl CoordinatesCache {
@@ -20,15 +20,19 @@ impl CoordinatesCache {
let mut waypoints = HashSet::new();
for file in files.into_iter().flat_map(|files| files.values()) {
waypoints.insert(file.id);
let rev = waypoints_revision(file);
if self.waypoints.get(&file.id).is_none_or(|(r, _)| *r != rev) {
if self
.waypoints
.get(&file.id)
.is_none_or(|(r, _)| *r != file.wpt_rev_id)
{
let coordinates = file
.wpt
.iter()
.flat_map(|chunk| &chunk.wpt)
.flat_map(|wpt| [wpt.coordinates.lng, wpt.coordinates.lat])
.collect();
self.waypoints.insert(file.id, (rev, coordinates));
self.waypoints
.insert(file.id, (file.wpt_rev_id, coordinates));
}
for seg in file.trk.iter().flat_map(|trk| &trk.trkseg) {
segments.insert(seg.id);
@@ -131,6 +135,7 @@ mod tests {
..Default::default()
};
let mut file = (*fx.files[&id]).clone();
file.wpt_rev_id = Default::default();
file.wpt = vec![
Rc::new(WaypointChunk {
wpt: vec![wpt(1.0, 2.0)],
@@ -1,6 +1,7 @@
use std::hash::{Hash, Hasher};
use crate::{File, FileId, TrackId, TrackSegmentId, TrackSegmentRevisionId, WaypointId};
use crate::{
File, FileId, FileWaypointsRevisionId, TrackId, TrackSegmentId, TrackSegmentRevisionId,
WaypointId,
};
/// What the UI needs to display a file: its name and the structure of its tracks and waypoints,
/// with the ids that reference every element. Coordinates are not part of it, they are read
@@ -14,7 +15,7 @@ pub struct FileStructure {
pub tracks: Vec<TrackNode>,
pub waypoints: Vec<WaypointNode>,
/// Changes whenever the waypoints of the file (hence their buffer) change.
pub waypoints_rev: u64,
pub wpt_rev_id: FileWaypointsRevisionId,
}
#[derive(Debug, Clone, PartialEq)]
@@ -69,20 +70,11 @@ impl FileStructure {
name: wpt.name.clone(),
})
.collect(),
waypoints_rev: waypoints_revision(file),
wpt_rev_id: file.wpt_rev_id,
}
}
}
/// Identifies the current waypoints of a file: chunks are immutable, so their ids are enough.
pub fn waypoints_revision(file: &File) -> u64 {
let mut hasher = std::collections::hash_map::DefaultHasher::new();
for chunk in &file.wpt {
chunk.id.hash(&mut hasher);
}
hasher.finish()
}
#[cfg(test)]
mod tests {
use std::rc::Rc;
@@ -116,7 +108,8 @@ mod tests {
name: Some(n.to_string()),
..Default::default()
};
let before = waypoints_revision(&file);
let before = file.wpt_rev_id;
file.wpt_rev_id = Default::default();
file.wpt = vec![
Rc::new(WaypointChunk {
wpt: vec![wpt("a"), wpt("b")],
@@ -134,7 +127,7 @@ mod tests {
.map(|w| w.name.clone().unwrap())
.collect();
assert_eq!(names, ["a", "b", "c"]);
assert_ne!(node.waypoints_rev, before);
assert_eq!(node.waypoints_rev, waypoints_revision(&file));
assert_ne!(node.wpt_rev_id, before);
assert_eq!(node.wpt_rev_id, file.wpt_rev_id);
}
}