Releases: thecloudseeker/activity_files
Releases · thecloudseeker/activity_files
Release list
v0.6.0
Breaking
ActivityFileFormatnow includescsvandgeojson; exhaustiveswitchstatements must handle the new enum values.- Facade conversion/export helpers now validate by default (
runValidation: true). SetrunValidation: falseto keep previous behavior.
Added
- FIT regression suite for problematic real-world files.
- Additional integration coverage for CSV/GeoJSON conversion and format detection.
- New pipeline option models:
FitCorruptionHandlingandActivityAutoFixOptions. - FIT Developer-Fields Support: decodes developer fields and exposes them as channels. (lib/src/parse/fit_parser.dart)
- Extended FIT Message Coverage: handlers for messages 23, 34, 49. (lib/src/parse/fit_parser.dart)
- Typed FIT Views:
asFitView()typed accessors for session/lap/record data. (lib/src/fit/typed_views.dart) - Auto-Lap Heuristics:
autoLapByDistanceoption generates laps by distance with sport defaults. (lib/src/api/pipeline_options.dart, lib/src/api/activity_files_facade.dart)
Changed
- CI workflows were consolidated and hardened
- CSV/GeoJSON are now first-class in the unified
ActivityFileFormatpath (detectFormat,load,convert,export, parser/encoder routing, CLI options). - Shared lap-boundary validation logic is reused between
validateRawActivity()andRawEditor.validateLapBoundaries(). - GPX parser: more robust TrackPoint parsing and TrackPointExtension handling
Fixed
- Auto-Lap: regenerate placeholder laps and recompute distance before marking. (lib/src/api/activity_files_facade.dart)
- Autofix diagnostic
autofix.laps.auto_generatedis emitted when laps are generated. (lib/src/api/activity_files_facade.dart) - FIT parser now performs best-effort extraction for problematic FIT variants by applying in-stream local-definition updates and bounded timestamp recovery (
fit.record.recovered_timestamp) instead of returning empty output. - GeoJSON parser now uses a deterministic UTC-epoch fallback timestamp for points without
timestampinstead of runtime-dependentDateTime.now(). - TCX parser cache lifecycle is now scoped with weak-key caching to avoid retaining parsed XML documents.
ActivityFiles.splitBySport()now preserves lap metadata fields (e.g. avg/max metrics, calories, FIT event fields) while removing per-lap sport in split outputs.strictFitIntegritynow throws the same detailed troubleshootingFormatExceptionacross direct load and stream pipeline paths.
v0.5.1
Changed
- Upgraded dependencies
- Minor Fixes
v0.5.0
Migration
- Upgrading? This version mitigates the 0.4.0 breaking changes: the 64MB payload limit is now configurable per-call via
maxPayloadBytesand file paths work withallowFilePaths: trueor by passingFileobjects.
Added
- CSV & GeoJSON Support: Full import/export for CSV and GeoJSON formats with roundtrip testing.
- Public API Methods: Facade methods for CSV/GeoJSON:
exportToCsv(),importFromCsv(),exportToGeojson(),exportToGeojsonPoints(),importFromGeojson(). - Better Error Messages: All exceptions now include actionable recovery hints and troubleshooting steps.
- Parser Performance: XML element caching and batch lookups reduce parsing time by 2-5x for large files (5000+ points).
- Full Garmin TrackPointExtension v2 schema support: GPX parser and encoder now handle all v2 fields (
wtemp,depth,speed,course,bearing) plus existing v1 fields (hr,cad,power,atemp) with corresponding channel types andChannelSnapshotaccessors. - Expanded FIT manufacturer database from 28 to 179 entries for comprehensive device identification.
- Multi-sport activity support: TCX and FIT parsers handle triathlon files with multiple sport segments. New
Lap.sportfield enables per-lap sport tracking, andActivityFiles.merge()/splitBySport()combine or divide multi-sport activities. - FIT session + lap stats are now parsed into
ActivitySummaryand additionalLapfields; extra record fields are surfaced as custom channels. - Added an artificial fixture generator (
scripts/generate_artificial_fixtures.dart) that refreshes sample fixtures for tests and examples. - Lap boundary validation via
RawEditor.validateLapBoundaries()for detecting timing mismatches. - Performance improvements in normalization and hot paths.
- Parser optimization: through eliminating redundant XML traversals, removing case-insensitive string comparisons and caching child element lookups during trackpoint parsing. Large files (>5000 points) see the most benefit.
Changed
- CSV parser normalizes line endings (
\r\n→\n). - Optimized sport string conversion with caching.
- GPX/TCX parsing now uses batch element lookups instead of repeated traversals.
Lapclass includes optionalsportfield; null values inherit from activity-level sport.- TCX parser sport mapping extended to include swimming.
- Test suite reorganized into focused categories with shared fixtures. See
doc/testing.mdfor details. - Payload limit now configurable per-call via optional
maxPayloadBytesparameter (default: 64MB).
Fixed
- FIT parser now fails gracefully (with diagnostics) instead of crashing when a data message references an unknown local definition (e.g. issue #2 user fixture). New diagnostics:
fit.data.unknown_definition,fit.no_usable_data.
v0.4.4
Added
- New Unit tests
- New Integration tests
- Synthetic test data generator with clean fixtures
v0.4.3
Fixed
- Fix FIT parser to remove corrupted data points with invalid timestamps or coordinates, ensuring FIT→GPX and FIT→TCX output matches reference files
v0.4.2
Fixed
- Fix FIT parser for non-standard message ordering. Thanks @hallr-boulder for reporting (fixes #2)
- Improved support for swimming activity files with non-standard message ordering
- Parser now gracefully handles unknown message types instead of crashing
v0.4.1
- Fix formatting and prevent it from happening again with a local git hook
v0.4.0
Breaking
- Plain string sources are always treated as inline payloads; pass a
Fileor
setallowFilePaths: trueonload/convert/convertAndExport/
ActivityExportRequest.fromSourceto read from disk. - A 64MB cap (
ActivityFiles.defaultMaxPayloadBytes) applies to
load/convert/detect and streamed pipelines; oversized inputs throw or emit
error diagnostics. Stream from disk/network or split files to go larger; only
ActivityParser.parseStream(maxBytes: ...)lets you override the limit.
Added
- Stream-backed loads are replayable;
ActivityLoadResult.bytesPayloadexposes
buffered bytes even when the source was aStream<List<int>>. - FIT integrity: header/trailer CRCs and truncation are reported as error
diagnostics (or throw whenstrictFitIntegrity: true); the encoder now emits
invalid coordinate sentinels for sensor-only activities. - Structural validation enforces lap ordering/overlap and warns when sensor
channels extend past the point timeline during load/convert/export flows. - GPX/TCX version selection:
EncoderOptionsand CLI flags can emit GPX 1.0/1.1
and TCX v1/v2; defaults remain GPX 1.1/TCX v2. FIT remains core-workout only. - GPX 1.0 round-trips root metadata, track extensions, and labels when
gpxVersionisGpxVersion.v1_0.
Changed
RawTransformsandRawEditorlive in dedicated modules
(transforms/raw_transforms.dart,transforms/raw_editor.dart);transforms.dart
still exports both for existing imports.ChannelMapper.cursorexposes reusable per-channel cursors;mapAtnow wraps
it so overlays reuse cached lookups.- GPX/TCX/FIT encoders reuse the cursor (TCX/FIT also use distance readings) to
avoid repeated binary searches. - Resampling pre-sizes timetables and reuses sliding cursors to keep
RawTransforms.resample/_resampleNearestfast on long recordings. RawEditorskips work on sorted/valid inputs and reuses its timestamp cursor
duringdownsampleTime.- FIT exports defer base64 decoding until
asBytes()when FIT sources arrive as
base64 strings. RawEditor.smoothHRnow uses a sliding window to stay O(n).
Fixed
RawEditor.downsampleDistancekeeps the final point even on short hops or
duplicate timestamps, preserving distance/duration and channel alignment.RawEditor.markLapsByDistancerecovers from non-monotonic distance channels
(e.g. pause resets) to keep splits accurate.RawEditor.smoothHRrespects even-numbered windows instead of averaging an
extra sample.- Format detection inspects only a small prefix and honors payload caps.
- Exports with
normalize: falseauto-sort/dedup when needed;recomputeDistanceAndSpeed
also self-sorts to avoid invalid speed/distance. RawEditor.sortAndDedupclones lists before sorting to keep prior
RawActivityinstances immutable.- Malformed GPX/TCX and invalid FIT binaries now return structured
ParseDiagnosticerrors instead of raw exceptions. - Stream parsing (
parseStream,convertAndExportStream,runPipelinewith
streams) returns diagnostics for malformed/oversized payloads instead of
throwing. - CLI
converthonors explicit--encoding, reads GPX/TCX as bytes to avoid
Latin-1 corruption, and exits non-zero on parser errors. ActivityFiles.runPipelineno longer runs validation twice when
runValidationis enabled.RawActivity.copyWithkeeps collections immutable, recognizes canonical
inputs to avoid clones, and reuses cached distances.RawTransforms.resamplesorts points before resampling to avoid RangeErrors
and keep start/end ordering.ActivityFiles.convertenforces the export ordering guard when
normalizeisfalse;detectFormatno longer probes filesystem paths
unless allowed.
v0.3.2
v0.3.1
Fixed
ActivityFiles.load/convertnow honor theencodingparameter for GPX/TCX
byte payloads (without BOMs), so Latin-1 and other single-byte exports no
longer throwFormatException.ActivityParser.parseBytesexposes anencodingargument for callers that
read non-UTF-8 text files directly into byte buffers.