Import any valid GPX file and create the appropriate entities — markers from <wpt>, tracks from <trk>, and routes from <rte>. A single GPX file can contain any combination of these, so one import may create multiple entities.
Parsing (lib/importGPX.ts)
Use fast-xml-parser XMLParser (the inverse of the existing XMLBuilder used for export) to parse GPX XML into a JS object, then map elements to database inserts.
type ImportResult = {
markers: Marker[];
tracks: Track[];
routes: Route[];
};
async function importGPX(xml: string): Promise<ImportResult>;
Element Mapping
<wpt> → Marker:
latitude ← wpt@lat
longitude ← wpt@lon
name ← wpt/name
notes ← wpt/desc
icon ← wpt/sym (map to nearest AnnotationIcon, or null)
<trk> → Track + TrackPoints:
name ← trk/name
started_at ← first trkpt/time
ended_at ← last trkpt/time
distance ← computed from point-to-point distances
Per trkpt:
latitude ← trkpt@lat
longitude ← trkpt@lon
timestamp ← trkpt/time
speed ← trkpt/extensions/speed
heading ← trkpt/extensions/course
Multiple <trkseg> within a single <trk> are concatenated into one track.
<rte> → Route + RoutePoints:
name ← rte/name
Per rtept:
latitude ← rtept@lat
longitude ← rtept@lon
name ← rtept/name
position ← index order in file
Entry Points
1. Share sheet / "Open with"
Register SeaScape as a handler for .gpx files (UTI: com.topografix.gpx, MIME: application/gpx+xml) via iOS document types config in app.json. When a user shares a GPX file to SeaScape or opens one from Files, the app receives the file URI.
2. Import button in MainSheet
Add an "Import GPX" option that opens the system file picker (expo-document-picker) filtered to .gpx files.
Import Flow
- Read file contents (from share URI or document picker)
- Parse XML via
fast-xml-parser
- Validate: check for
<gpx> root element, bail with user-friendly error if invalid
- Process all
<wpt>, <trk>, and <rte> elements in a single DB transaction
- Show summary: "Imported 3 markers, 1 track, 2 routes"
- Navigate to the first imported entity (or route list if multiple routes)
Error Handling
- Invalid XML → "This file doesn't appear to be a valid GPX file"
- Missing required fields (lat/lon) → skip that element, include in summary ("1 waypoint skipped — missing coordinates")
- Empty file (no elements) → "No waypoints, tracks, or routes found in this file"
New Files
| File |
Purpose |
lib/importGPX.ts |
GPX parser — creates markers, tracks, and routes |
Modified Files
| File |
Change |
app.json |
Register GPX file type handler (UTI: com.topografix.gpx) |
app/MainSheet.tsx |
Add "Import GPX" button |
Implementation Order
- GPX parser —
lib/importGPX.ts with pure parsing logic + comprehensive tests
- Import UI — File picker in MainSheet via
expo-document-picker
- File type registration —
app.json config for "Open with" / share sheet handling
Testing
Pure parsing logic with no React dependencies — test with sample GPX files:
- File with only
<wpt> elements
- File with only
<trk> elements (single and multi-segment)
- File with only
<rte> elements
- File with a mix of all three
- Real-world GPX files from common apps (Navionics, OpenCPN, etc.)
- Malformed / missing fields
- Round-trip: export then import, verify data matches
Import any valid GPX file and create the appropriate entities — markers from
<wpt>, tracks from<trk>, and routes from<rte>. A single GPX file can contain any combination of these, so one import may create multiple entities.Parsing (
lib/importGPX.ts)Use
fast-xml-parserXMLParser(the inverse of the existingXMLBuilderused for export) to parse GPX XML into a JS object, then map elements to database inserts.Element Mapping
<wpt>→ Marker:<trk>→ Track + TrackPoints:Multiple
<trkseg>within a single<trk>are concatenated into one track.<rte>→ Route + RoutePoints:Entry Points
1. Share sheet / "Open with"
Register SeaScape as a handler for
.gpxfiles (UTI:com.topografix.gpx, MIME:application/gpx+xml) via iOS document types config inapp.json. When a user shares a GPX file to SeaScape or opens one from Files, the app receives the file URI.2. Import button in MainSheet
Add an "Import GPX" option that opens the system file picker (
expo-document-picker) filtered to.gpxfiles.Import Flow
fast-xml-parser<gpx>root element, bail with user-friendly error if invalid<wpt>,<trk>, and<rte>elements in a single DB transactionError Handling
New Files
lib/importGPX.tsModified Files
app.jsoncom.topografix.gpx)app/MainSheet.tsxImplementation Order
lib/importGPX.tswith pure parsing logic + comprehensive testsexpo-document-pickerapp.jsonconfig for "Open with" / share sheet handlingTesting
Pure parsing logic with no React dependencies — test with sample GPX files:
<wpt>elements<trk>elements (single and multi-segment)<rte>elements