Skip to content

[History] 5 - Favorite media #291

Description

@KacperKozak

Parent

What to build

Favorite Media (ADR 0030): photo/video attachments move to Favorites and become favorite-owned. The picker-based attach flow appears only in the favorite mode of the detail sheet. Picked files are imported into canonical app storage keyed by Favorite and Favorite Media ids (replacing derived-session-id keying). Add a native favorite_media manifest table on both platforms; the filesystem is no longer the only record and filenames are not metadata. Map placement uses the nearest recording-backed GPS fix to capture time, unchanged. Each immutable manifest row has a native-minted stable UUID primary key id, favorite_id, captured_at, MIME/media kind, byte_count, SHA-256 content_hash, and created_at. Deleting a Favorite raw-deletes its manifest rows as a parent-covered cascade and schedules/best-effort deletes its media directory; orphan cleanup repairs filesystem failures. Attaching media to non-favorited rides is removed. Legacy per-session media folders are left alone (PoC; no cleanup, no migration).

Likely files

  • modules/vescape-core/ios/telemetry/TelemetryDatabase.swift and TelemetryDao.swift - Favorite Media manifest schema/import/delete APIs
  • modules/vescape-core/android/src/main/java/expo/modules/vescapecore/telemetry/TelemetryDatabase.kt and TelemetryDao.kt - Android peer manifest schema/import/delete APIs
  • src/modules/history/store/rideMediaFiles.ts - replace filesystem-as-truth with bridge-backed import/list and canonical paths
  • src/modules/history/lib/mediaHistory.ts - filename encode/decode + GPS matching
  • src/modules/history/hooks/useMediaHistory.ts - read path wiring
  • src/modules/history/components/MediaHistoryGallery.tsx - gallery UI moving to favorite mode
  • src/modules/history/components/MediaHistoryViewer.tsx - viewer surface
  • src/modules/history/components/MediaHistoryPin.tsx - map pin placement

Implementation hints

  • Native owns the durable manifest and file import. Import computes SHA-256 and byte count while copying, then publishes the manifest row only for a completed canonical file. A startup/read reconciliation removes incomplete temp files and reports/removes manifest rows whose local file is missing; never invent manifest metadata by parsing filenames.
  • GPS placement must use the favorite range's loaded GPS samples (slice 4's load path), same nearest-fix-by-capture-time rule as today.
  • Remove the attach entry points from history mode entirely — favoriting is the gateway to media.

Acceptance criteria

  • Attach photos/videos via picker from favorite detail only
  • Files stored under canonical per-favorite/per-media paths; survive photo-library changes
  • Native favorite_media manifest exists on both platforms with stable UUID primary key, parent id, capture/type metadata, byte count, SHA-256 hash, and creation time
  • Manifest rows are the durable metadata truth; filenames are not parsed as metadata
  • Interrupted imports and manifest/filesystem disagreement are reconciled without publishing partial media
  • Media pins placed on the favorite route by capture time
  • Deleting a Favorite deletes its media directory
  • No media attach option on non-favorited history rides
  • Legacy per-session media folders untouched

Blocked by

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:historyRide history, sessions, buckets, graphscomplexity:mediumNeeds care, moderate integration surface. Use sonnet.ready-for-agentFully specified, ready for an AFK agent

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions