GPX tracks were silently failing to render for large real-world files: point_extensions used REXML's "extensions//*" XPath, and the // descendant axis costs low-single-digit milliseconds per call regardless of subtree size. Run once per point, that's negligible on small files but ~30s on a real 8000-point track — long enough to hit a proxy timeout in production, so the file just never appeared with no error. Replaced with plain recursive child traversal (~40x faster on the same file, confirmed 29.9s -> 3.16s); test_parsing_many_points_with_extensions_stays_fast guards against reintroducing it. Also adds support for <rte> routes (not just <trk> tracks and <wpt> waypoints), sharing the track/route conversion logic via a new line_feature helper. Routes get their own "route" kind and a dashed ROUTE_ICON in the file tree so the type is visible at a glance.
66 lines
2.8 KiB
JavaScript
66 lines
2.8 KiB
JavaScript
// Small hand-authored monoline SVG icons for the sidebar, so the app
|
|
// doesn't need to vendor an icon font/library for four glyphs.
|
|
|
|
export const LAYERS_ICON = `
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round" stroke-linecap="round">
|
|
<path d="M12 3 2 9l10 6 10-6-10-6z"/>
|
|
<path d="M2 14l10 6 10-6"/>
|
|
</svg>`;
|
|
|
|
export const GPX_ICON = `
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
|
<circle cx="5" cy="6" r="2"/>
|
|
<circle cx="19" cy="18" r="2"/>
|
|
<path d="M6.5 7.5C10 11 8 13 12 13s2 5 6.5 5"/>
|
|
</svg>`;
|
|
|
|
export const RADAR_ICON = `
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round" stroke-linecap="round">
|
|
<path d="M7 18a4 4 0 1 1 .7-7.94A5 5 0 0 1 17 9a4 4 0 0 1 0 8H7z"/>
|
|
</svg>`;
|
|
|
|
export const GNSS_ICON = `
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round">
|
|
<circle cx="12" cy="12" r="5.5"/>
|
|
<circle cx="12" cy="12" r="1.4" fill="currentColor" stroke="none"/>
|
|
<path d="M12 2v3M12 19v3M2 12h3M19 12h3"/>
|
|
</svg>`;
|
|
|
|
export const NEW_FOLDER_ICON = `
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7z"/>
|
|
<path d="M12 11v5M9.5 13.5h5"/>
|
|
</svg>`;
|
|
|
|
export const UPLOAD_ICON = `
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M12 15V4M8 8l4-4 4 4"/>
|
|
<path d="M4 15v3a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3"/>
|
|
</svg>`;
|
|
|
|
// Shown next to each file in the GPX tree, indicating whether it has
|
|
// waypoints, a track, or both.
|
|
export const WAYPOINT_ICON = `
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M12 21s7-7.58 7-12a7 7 0 0 0-14 0c0 4.42 7 12 7 12z"/>
|
|
<circle cx="12" cy="9" r="2.2"/>
|
|
</svg>`;
|
|
|
|
export const TRACK_ICON = GPX_ICON;
|
|
|
|
// Same shape as TRACK_ICON, dashed — a route is planned rather than
|
|
// recorded, the same visual convention most map apps use for the
|
|
// distinction.
|
|
export const ROUTE_ICON = `
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
|
<circle cx="5" cy="6" r="2"/>
|
|
<circle cx="19" cy="18" r="2"/>
|
|
<path d="M6.5 7.5C10 11 8 13 12 13s2 5 6.5 5" stroke-dasharray="2 2.2"/>
|
|
</svg>`;
|
|
|
|
export const LIVETRACK_ICON = `
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M12 21s7-7.58 7-12a7 7 0 0 0-14 0c0 4.42 7 12 7 12z"/>
|
|
<path d="M8.5 9a3.5 3.5 0 0 1 7 0" stroke-dasharray="1.5 2.2"/>
|
|
</svg>`;
|