From 23ac7cab48d5ab52ca3b59b7341a074363b6b870 Mon Sep 17 00:00:00 2001 From: Dlurak <84224239+Dlurak@users.noreply.github.com> Date: Fri, 18 Oct 2024 21:21:35 +0200 Subject: [PATCH] FeaturePanel: Add apple maps to the dropdown (#697) --- src/components/FeaturePanel/Coordinates.tsx | 22 ++++++++++++--- .../EditDialog/EditContent/OptionsEditor.tsx | 2 +- .../FeaturePanel/helpers/externalLinks.ts | 27 +++++++++++++++++++ src/components/Map/TopMenu/HamburgerMenu.tsx | 2 +- src/helpers/platforms.ts | 11 +++++--- src/utils.ts | 11 +------- 6 files changed, 56 insertions(+), 19 deletions(-) create mode 100644 src/components/FeaturePanel/helpers/externalLinks.ts diff --git a/src/components/FeaturePanel/Coordinates.tsx b/src/components/FeaturePanel/Coordinates.tsx index cf02c8c82..fb41f9650 100644 --- a/src/components/FeaturePanel/Coordinates.tsx +++ b/src/components/FeaturePanel/Coordinates.tsx @@ -7,10 +7,12 @@ import OpenInNewIcon from '@mui/icons-material/OpenInNew'; import { useMapStateContext } from '../utils/MapStateContext'; import { isMobileDevice, useBoolState } from '../helpers'; import { useFeatureContext } from '../utils/FeatureContext'; -import { getIdEditorLink, positionToDeg, positionToDM } from '../../utils'; +import { positionToDeg, positionToDM } from '../../utils'; import { PositionBoth } from '../../services/types'; import { getFullOsmappLink, getShortLink } from '../../services/helpers'; import { t } from '../../services/intl'; +import { isIOS } from '../../helpers/platforms'; +import { getAppleMapsLink, getIdEditorLink } from './helpers/externalLinks'; const StyledMenuItem = styled(MenuItem)` svg { @@ -64,10 +66,16 @@ const LinkItem = ({ href, label }) => ( // https://wiki.openstreetmap.org/wiki/Zoom_levels#Mapbox_GL const MAPLIBREGL_ZOOM_DIFFERENCE = 1; -const useGetItems = ([lon, lat]: PositionBoth) => { +type ExternalMapLink = { + label: string; + href: string; +}; + +const useGetItems = (position: PositionBoth): ExternalMapLink[] => { const { feature } = useFeatureContext(); - const { view } = useMapStateContext(); + const { view, activeLayers } = useMapStateContext(); const [ourZoom] = view; + const [lon, lat] = position; const zoom = parseFloat(ourZoom) + MAPLIBREGL_ZOOM_DIFFERENCE; const zoomInt = Math.round(zoom); @@ -96,6 +104,14 @@ const useGetItems = ([lon, lat]: PositionBoth) => { label: 'iD editor', href: getIdEditorLink(feature, view), // TODO coordsFeature has random id which gets forwarded LOL }, + ...(isIOS() + ? [ + { + label: 'Apple maps', + href: getAppleMapsLink(feature, position, activeLayers), + }, + ] + : []), ...(isMobileDevice() ? [ { diff --git a/src/components/FeaturePanel/EditDialog/EditContent/OptionsEditor.tsx b/src/components/FeaturePanel/EditDialog/EditContent/OptionsEditor.tsx index fc4525b7e..96a591d9b 100644 --- a/src/components/FeaturePanel/EditDialog/EditContent/OptionsEditor.tsx +++ b/src/components/FeaturePanel/EditDialog/EditContent/OptionsEditor.tsx @@ -6,7 +6,7 @@ import { DialogHeading } from '../components'; import { t, Translation } from '../../../../services/intl'; import { useOsmAuthContext } from '../../../utils/OsmAuthContext'; import { useToggleState } from '../../../helpers'; -import { getIdEditorLink } from '../../../../utils'; +import { getIdEditorLink } from '../../helpers/externalLinks'; export const PlaceCancelledToggle = () => { const { diff --git a/src/components/FeaturePanel/helpers/externalLinks.ts b/src/components/FeaturePanel/helpers/externalLinks.ts new file mode 100644 index 000000000..5be1fd1dd --- /dev/null +++ b/src/components/FeaturePanel/helpers/externalLinks.ts @@ -0,0 +1,27 @@ +import { getLabel } from '../../../helpers/featureLabel'; +import { Feature, PositionBoth } from '../../../services/types'; +import { View } from '../../utils/MapStateContext'; + +export const getIdEditorLink = (feature: Feature, view?: View) => { + const query = feature?.osmMeta?.id + ? `?${feature.osmMeta.type}=${feature.osmMeta.id}` + : ''; + const hash = view ? `#map=${view.join('/')}` : ''; + return `https://www.openstreetmap.org/edit${query}${hash}`; +}; + +export const getAppleMapsLink = ( + feature: Feature, + position: PositionBoth, + activeLayers: string[], +) => { + // TODO: satelite detection on userLayers + const layer = activeLayers.some((layer) => + ['sat', 'bingSat', 'cuzkSat'].includes(layer), + ) + ? 'h' // satelite + : 'm'; // normal + + const markerLabel = getLabel(feature); + return `https://maps.apple.com/?ll=${position[1]},${position[0]}&t=${layer}&q=${markerLabel}`; +}; diff --git a/src/components/Map/TopMenu/HamburgerMenu.tsx b/src/components/Map/TopMenu/HamburgerMenu.tsx index 47d25314e..3b04448c7 100644 --- a/src/components/Map/TopMenu/HamburgerMenu.tsx +++ b/src/components/Map/TopMenu/HamburgerMenu.tsx @@ -12,7 +12,7 @@ import { useBoolState } from '../../helpers'; import { t } from '../../../services/intl'; import { useFeatureContext } from '../../utils/FeatureContext'; import { useMapStateContext } from '../../utils/MapStateContext'; -import { getIdEditorLink } from '../../../utils'; +import { getIdEditorLink } from '../../FeaturePanel/helpers/externalLinks'; import { UserTheme, useUserThemeContext } from '../../../helpers/theme'; import GithubIcon from '../../../assets/GithubIcon'; import { LangSwitcher } from './LangSwitcher'; diff --git a/src/helpers/platforms.ts b/src/helpers/platforms.ts index 5b8d9fd0e..78028476c 100644 --- a/src/helpers/platforms.ts +++ b/src/helpers/platforms.ts @@ -1,5 +1,8 @@ +import { isBrowser } from '../components/helpers'; + export const isIOS = () => - [ + isBrowser() && + ([ 'iPad Simulator', 'iPhone Simulator', 'iPod Simulator', @@ -7,11 +10,11 @@ export const isIOS = () => 'iPhone', 'iPod', ].includes(navigator.platform) || - // iPad on iOS 13 detection - (navigator.userAgent.includes('Mac') && 'ontouchend' in document); + // iPad on iOS 13 detection + (navigator.userAgent.includes('Mac') && 'ontouchend' in document)); export const isAndroid = () => - navigator.userAgent.toLowerCase().indexOf('android') > -1; + isBrowser() && navigator.userAgent.toLowerCase().indexOf('android') > -1; export const getPlatform = () => { if (isIOS()) return 'ios'; diff --git a/src/utils.ts b/src/utils.ts index 30a6896ee..65d524156 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -4,7 +4,6 @@ import { Position, PositionBoth, } from './services/types'; -import type { View } from './components/utils/MapStateContext'; // Accuracy = 1m, see https://gis.stackexchange.com/questions/8650/measuring-accuracy-of-latitude-and-longitude export const roundDeg = (deg) => (deg.toFixed ? deg.toFixed(5) : deg); @@ -38,15 +37,7 @@ export const getRoundedPosition = ( export const roundedToDegUrl = ([lon, lat]: LonLatRounded) => `${lat},${lon}`; export const roundedToDeg = ([lon, lat]: LonLatRounded) => `${lat}° ${lon}°`; -export const getIdEditorLink = (feature: Feature, view?: View) => { - const query = feature?.osmMeta?.id - ? `?${feature.osmMeta.type}=${feature.osmMeta.id}` - : ''; - const hash = view ? `#map=${view.join('/')}` : ''; - return `https://www.openstreetmap.org/edit${query}${hash}`; -}; - -export const getUtfStrikethrough = (text) => +export const getUtfStrikethrough = (text: string) => text .split('') .map((char) => `${char}\u0336`)