Skip to content

Releases: thecloudseeker/activity_files

v0.6.0

Choose a tag to compare

@thecloudseeker thecloudseeker released this 06 Jun 09:42

Breaking

  • ActivityFileFormat now includes csv and geojson; exhaustive switch statements must handle the new enum values.
  • Facade conversion/export helpers now validate by default (runValidation: true). Set runValidation: false to 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: FitCorruptionHandling and ActivityAutoFixOptions.
  • 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: autoLapByDistance option 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 ActivityFileFormat path (detectFormat, load, convert, export, parser/encoder routing, CLI options).
  • Shared lap-boundary validation logic is reused between validateRawActivity() and RawEditor.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_generated is 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 timestamp instead of runtime-dependent DateTime.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.
  • strictFitIntegrity now throws the same detailed troubleshooting FormatException across direct load and stream pipeline paths.

v0.5.1

Choose a tag to compare

@thecloudseeker thecloudseeker released this 08 May 11:05

Changed

  • Upgraded dependencies
  • Minor Fixes

v0.5.0

Choose a tag to compare

@thecloudseeker thecloudseeker released this 12 Apr 10:52

Migration

  • Upgrading? This version mitigates the 0.4.0 breaking changes: the 64MB payload limit is now configurable per-call via maxPayloadBytes and file paths work with allowFilePaths: true or by passing File objects.

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 and ChannelSnapshot accessors.
  • 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.sport field enables per-lap sport tracking, and ActivityFiles.merge()/splitBySport() combine or divide multi-sport activities.
  • FIT session + lap stats are now parsed into ActivitySummary and additional Lap fields; 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.
  • Lap class includes optional sport field; 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.md for details.
  • Payload limit now configurable per-call via optional maxPayloadBytes parameter (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

Choose a tag to compare

@thecloudseeker thecloudseeker released this 09 Feb 19:36

Added

  • New Unit tests
  • New Integration tests
  • Synthetic test data generator with clean fixtures

v0.4.3

Choose a tag to compare

@thecloudseeker thecloudseeker released this 01 Feb 11:45

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

Choose a tag to compare

@thecloudseeker thecloudseeker released this 29 Jan 09:25

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

Choose a tag to compare

@thecloudseeker thecloudseeker released this 21 Dec 14:48
  • Fix formatting and prevent it from happening again with a local git hook

v0.4.0

Choose a tag to compare

@thecloudseeker thecloudseeker released this 21 Dec 14:24

Breaking

  • Plain string sources are always treated as inline payloads; pass a File or
    set allowFilePaths: true on load/convert/convertAndExport/
    ActivityExportRequest.fromSource to 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.bytesPayload exposes
    buffered bytes even when the source was a Stream<List<int>>.
  • FIT integrity: header/trailer CRCs and truncation are reported as error
    diagnostics (or throw when strictFitIntegrity: 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: EncoderOptions and 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
    gpxVersion is GpxVersion.v1_0.

Changed

  • RawTransforms and RawEditor live in dedicated modules
    (transforms/raw_transforms.dart, transforms/raw_editor.dart); transforms.dart
    still exports both for existing imports.
  • ChannelMapper.cursor exposes reusable per-channel cursors; mapAt now 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/_resampleNearest fast on long recordings.
  • RawEditor skips work on sorted/valid inputs and reuses its timestamp cursor
    during downsampleTime.
  • FIT exports defer base64 decoding until asBytes() when FIT sources arrive as
    base64 strings.
  • RawEditor.smoothHR now uses a sliding window to stay O(n).

Fixed

  • RawEditor.downsampleDistance keeps the final point even on short hops or
    duplicate timestamps, preserving distance/duration and channel alignment.
  • RawEditor.markLapsByDistance recovers from non-monotonic distance channels
    (e.g. pause resets) to keep splits accurate.
  • RawEditor.smoothHR respects even-numbered windows instead of averaging an
    extra sample.
  • Format detection inspects only a small prefix and honors payload caps.
  • Exports with normalize: false auto-sort/dedup when needed; recomputeDistanceAndSpeed
    also self-sorts to avoid invalid speed/distance.
  • RawEditor.sortAndDedup clones lists before sorting to keep prior
    RawActivity instances immutable.
  • Malformed GPX/TCX and invalid FIT binaries now return structured
    ParseDiagnostic errors instead of raw exceptions.
  • Stream parsing (parseStream, convertAndExportStream, runPipeline with
    streams) returns diagnostics for malformed/oversized payloads instead of
    throwing.
  • CLI convert honors explicit --encoding, reads GPX/TCX as bytes to avoid
    Latin-1 corruption, and exits non-zero on parser errors.
  • ActivityFiles.runPipeline no longer runs validation twice when
    runValidation is enabled.
  • RawActivity.copyWith keeps collections immutable, recognizes canonical
    inputs to avoid clones, and reuses cached distances.
  • RawTransforms.resample sorts points before resampling to avoid RangeErrors
    and keep start/end ordering.
  • ActivityFiles.convert enforces the export ordering guard when
    normalize is false; detectFormat no longer probes filesystem paths
    unless allowed.

v0.3.2

Choose a tag to compare

@thecloudseeker thecloudseeker released this 19 Nov 19:12
  • wrong version in pubspec.yaml

v0.3.1

Choose a tag to compare

@thecloudseeker thecloudseeker released this 19 Nov 19:11

Fixed

  • ActivityFiles.load/convert now honor the encoding parameter for GPX/TCX
    byte payloads (without BOMs), so Latin-1 and other single-byte exports no
    longer throw FormatException.
  • ActivityParser.parseBytes exposes an encoding argument for callers that
    read non-UTF-8 text files directly into byte buffers.