Files
TREK/client/src/components/Planner/placeCoMaps.ts
T
Konstantinos Thermos 8065af28ef feat(planner): open places and day routes in CoMaps
Add CoMaps, the offline OpenStreetMap navigator, alongside the existing
map integrations. A geolocated place gains a CoMaps entry in its
navigation menu, and a day's route toolbar gains a button that hands the
day's bookended stops to CoMaps in that day's travel mode.

CoMaps' route link carries only a start and a destination, so a two-stop
day goes as a route and a longer one as named pins rather than silently
losing the stops in between. Links use the https form so a device without
CoMaps installed lands on comaps.at instead of a dead scheme.

The hotel-bookend logic behind the Google Maps export was duplicated
between desktop and mobile; both now share dayExportStops so the two
links cannot disagree about which hotel legs are real.

Addresses discussion #1904
2026-08-14 10:24:14 +03:00

23 lines
1.0 KiB
TypeScript

import type { AssignmentPlace, Place } from '../../types'
type PlaceLike = Pick<Place | AssignmentPlace, 'name' | 'lat' | 'lng'>
/**
* Open a place in CoMaps, the privacy-focused offline OpenStreetMap navigator.
* Requested in discussion #1904.
*
* The https form rather than the `cm://` scheme CoMaps also answers to: both open
* the app when it is installed, but only this one has somewhere to land when it is
* not — comaps.at, which is the install page. A PWA cannot ask whether an Android
* app exists, so the fallback has to be the link itself.
*
* Coordinates are required: CoMaps places the pin from `ll` and uses `n` only to
* label it, so a name on its own has nothing to attach to.
*/
export function getCoMapsUrlForPlace(place: PlaceLike | null | undefined): string | null {
if (!place || place.lat == null || place.lng == null) return null
const name = place.name?.trim()
const n = name ? `&n=${encodeURIComponent(name)}` : ''
return `https://comaps.at/map?v=1&ll=${place.lat},${place.lng}${n}`
}