diff --git a/packages/plugins/GeoLocation/CHANGELOG.md b/packages/plugins/GeoLocation/CHANGELOG.md index 19e06e469..25831a3ea 100644 --- a/packages/plugins/GeoLocation/CHANGELOG.md +++ b/packages/plugins/GeoLocation/CHANGELOG.md @@ -3,6 +3,7 @@ ## unpublished - Fix: Adjust documentation to properly describe optionality of configuration parameters. +- Feature: Position is now tracked when user is outside of the boundary layer but inside the map extent. ## 1.3.1 diff --git a/packages/plugins/GeoLocation/README.md b/packages/plugins/GeoLocation/README.md index 2d7c3a628..915eecb79 100644 --- a/packages/plugins/GeoLocation/README.md +++ b/packages/plugins/GeoLocation/README.md @@ -12,7 +12,7 @@ either `true` or `false`. When a users denies the location tracking, the button | fieldName | type | description | | - | - | - | -| boundaryLayerId | string? | Id of a vector layer to restrict geolocation markers and zooms to. When geolocation outside of its features occurs, an information will be shown once and the feature is stopped. The map will wait at most 10s for the layer to load; should it not happen, the geolocation feature is turned off. | +| boundaryLayerId | string? | Id of a vector layer to restrict geolocation markers and zooms to. When geolocation outside of its features occurs, a single information will be shown. When loading the boundary layer, the map will wait at most 10s; should it not happen, the geolocation feature is turned off. | | boundaryOnError | ('strict' \| 'permissive')? | If the boundary layer check does not work due to loading or configuration errors, style `'strict'` will disable the geolocation feature, and style `'permissive'` will act as if no boundaryLayerId was set. Defaults to `'permissive'`. | | checkLocationInitially | boolean? | If `true` the location gets checked on page load. When `false` this can be triggered with a button. Defaults to `false`. | | keepCentered | boolean? | If `true`, the map will re-center on the user on any position change. If `false`, only the first position will be centered on. Defaults to `false`. | diff --git a/packages/plugins/GeoLocation/src/store/actions.ts b/packages/plugins/GeoLocation/src/store/actions.ts index b3ecb7ac4..9d3116db3 100644 --- a/packages/plugins/GeoLocation/src/store/actions.ts +++ b/packages/plugins/GeoLocation/src/store/actions.ts @@ -1,5 +1,5 @@ +/* eslint-disable max-lines-per-function */ import { PolarActionTree } from '@polar/lib-custom-types' -import { passesBoundaryCheck } from '@polar/lib-passes-boundary-check' import VectorLayer from 'ol/layer/Vector' import Point from 'ol/geom/Point' import { Vector } from 'ol/source' @@ -11,8 +11,10 @@ import Geolocation from 'ol/Geolocation.js' import { transform as transformCoordinates } from 'ol/proj' import Overlay from 'ol/Overlay' import { getTooltip } from '@polar/lib-tooltip' +import { passesBoundaryCheck } from '@polar/lib-passes-boundary-check' import { GeoLocationState, GeoLocationGetters } from '../types' import geoLocationMarker from '../assets/geoLocationMarker' +import positionChanged from '../utils/positionChanged' const actions: PolarActionTree = { setupModule({ getters, commit, dispatch }): void { @@ -118,11 +120,13 @@ const actions: PolarActionTree = { async positioning({ rootGetters: { map, configuration }, getters: { - boundaryLayerId, boundaryOnError, + boundaryLayerId, geolocation, configuredEpsg, position, + boundaryCheck, + boundaryCheckChanged, }, commit, dispatch, @@ -132,38 +136,36 @@ const actions: PolarActionTree = { Proj.get('EPSG:4326') as Proj.Projection, configuredEpsg ) - - const boundaryCheckPassed = - typeof boundaryLayerId === 'string' - ? await passesBoundaryCheck(map, boundaryLayerId, transformedCoords) - : containsCoordinate( - // NOTE: The fallback is the default value set by @masterportal/masterportalApi - configuration?.extent || [510000.0, 5850000.0, 625000.4, 6000000.0], - transformedCoords - ) - const boundaryErrorOccurred = typeof boundaryCheckPassed === 'symbol' - - if ( - boundaryCheckPassed === false || - (boundaryErrorOccurred && boundaryOnError !== 'permissive') - ) { - dispatch('printPositioningFailed', boundaryErrorOccurred) - // if check initially breaks or user leaves boundary, turn off tracking + const coordinateInExtent = containsCoordinate( + // NOTE: The fallback is the default value set by @masterportal/masterportalApi + configuration?.extent || [510000.0, 5850000.0, 625000.4, 6000000.0], + transformedCoords + ) + const boundaryCheckPassed = await passesBoundaryCheck( + map, + boundaryLayerId, + transformedCoords + ) + commit('setBoundaryCheckChanged', boundaryCheck !== boundaryCheckPassed) + commit('setBoundaryCheck', boundaryCheckPassed) + const showBoundaryLayerError = + typeof boundaryCheckPassed === 'symbol' && boundaryOnError === 'strict' + if (!coordinateInExtent || showBoundaryLayerError) { + dispatch('printPositioningFailed', showBoundaryLayerError) dispatch('untrack') return } - - if ( - position[0] !== transformedCoords[0] || - position[1] !== transformedCoords[1] - ) { + if (positionChanged(position, transformedCoords)) { commit('setPosition', transformedCoords) dispatch('addMarker', transformedCoords) + if (boundaryCheckChanged && !boundaryCheckPassed) { + dispatch('printPositioningFailed', false) + } } }, printPositioningFailed( { dispatch, getters: { toastAction } }, - boundaryErrorOccurred: string + boundaryErrorOccurred: boolean ) { if (toastAction) { const toast = boundaryErrorOccurred @@ -194,7 +196,12 @@ const actions: PolarActionTree = { */ addMarker( { - getters: { geoLocationMarkerLayer, markerFeature, keepCentered }, + getters: { + geoLocationMarkerLayer, + markerFeature, + keepCentered, + boundaryCheck, + }, dispatch, }, coordinates @@ -213,8 +220,7 @@ const actions: PolarActionTree = { }), }) ) - - if (keepCentered || !hadPosition) { + if ((keepCentered || !hadPosition) && boundaryCheck) { dispatch('zoomAndCenter') } }, diff --git a/packages/plugins/GeoLocation/src/store/getInitialState.ts b/packages/plugins/GeoLocation/src/store/getInitialState.ts index 215d66a8f..55a854337 100644 --- a/packages/plugins/GeoLocation/src/store/getInitialState.ts +++ b/packages/plugins/GeoLocation/src/store/getInitialState.ts @@ -5,6 +5,8 @@ const getInitialState = (): GeoLocationState => ({ position: [], tracking: false, isGeolocationDenied: false, + boundaryCheck: null, + boundaryCheckChanged: true, }) export default getInitialState diff --git a/packages/plugins/GeoLocation/src/store/getters.ts b/packages/plugins/GeoLocation/src/store/getters.ts index 735828556..d275e46f2 100644 --- a/packages/plugins/GeoLocation/src/store/getters.ts +++ b/packages/plugins/GeoLocation/src/store/getters.ts @@ -38,7 +38,7 @@ const getters: PolarGetterTree = { return rootGetters.configuration?.geoLocation?.toastAction }, zoomLevel: (_, __, ___, rootGetters): number => { - return rootGetters.configuration?.geoLocation?.zoomLevel || 7 + return rootGetters.configuration?.geoLocation?.zoomLevel ?? 7 }, geoLocationMarkerLayer(_, __, ___, rootGetters) { return rootGetters?.map diff --git a/packages/plugins/GeoLocation/src/types.ts b/packages/plugins/GeoLocation/src/types.ts index 52f1f9b47..5257d9636 100644 --- a/packages/plugins/GeoLocation/src/types.ts +++ b/packages/plugins/GeoLocation/src/types.ts @@ -8,6 +8,8 @@ export interface GeoLocationState { position: number[] tracking: boolean isGeolocationDenied: boolean + boundaryCheck: boolean | symbol | null + boundaryCheckChanged: boolean } export interface GeoLocationGetters extends GeoLocationState { diff --git a/packages/plugins/GeoLocation/src/utils/positionChanged.ts b/packages/plugins/GeoLocation/src/utils/positionChanged.ts new file mode 100644 index 000000000..4c130ddae --- /dev/null +++ b/packages/plugins/GeoLocation/src/utils/positionChanged.ts @@ -0,0 +1,6 @@ +export default function positionChanged( + oldPosition: number[], + newPosition: number[] +): boolean { + return oldPosition[0] !== newPosition[0] || oldPosition[1] !== newPosition[1] +}