Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Map new architecture PoC #4785

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions src/components/map_v2/MapV2.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import {getCurrentCoordinatesGlobal} from '@atb/GeolocationContext';
import {FOCUS_ORIGIN} from '@atb/api/geocoder';
import {StyleSheet} from '@atb/theme';
import MapboxGL, {LocationPuck} from '@rnmapbox/maps';
import React, {useRef} from 'react';
import {View} from 'react-native';
import {MapCameraConfig, MapViewConfig} from '@atb/components/map/MapConfig';

Check failure on line 7 in src/components/map_v2/MapV2.tsx

View workflow job for this annotation

GitHub Actions / tsc (atb)

'@atb/components/map/MapConfig' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 7 in src/components/map_v2/MapV2.tsx

View workflow job for this annotation

GitHub Actions / tsc (nfk)

'@atb/components/map/MapConfig' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 7 in src/components/map_v2/MapV2.tsx

View workflow job for this annotation

GitHub Actions / tsc (fram)

'@atb/components/map/MapConfig' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 7 in src/components/map_v2/MapV2.tsx

View workflow job for this annotation

GitHub Actions / tsc (troms)

'@atb/components/map/MapConfig' import is restricted from being used by a pattern. Not allowed to import components without going through their index file
import {getFeaturesAtClick} from '@atb/components/map/utils.ts';

Check failure on line 8 in src/components/map_v2/MapV2.tsx

View workflow job for this annotation

GitHub Actions / tsc (atb)

'@atb/components/map/utils.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 8 in src/components/map_v2/MapV2.tsx

View workflow job for this annotation

GitHub Actions / tsc (nfk)

'@atb/components/map/utils.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 8 in src/components/map_v2/MapV2.tsx

View workflow job for this annotation

GitHub Actions / tsc (fram)

'@atb/components/map/utils.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 8 in src/components/map_v2/MapV2.tsx

View workflow job for this annotation

GitHub Actions / tsc (troms)

'@atb/components/map/utils.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file
import {isFeaturePoint} from '@atb/components/map';
import {usePlugins} from '@atb/components/map_v2/plugins/use-plugins.tsx';

Check failure on line 10 in src/components/map_v2/MapV2.tsx

View workflow job for this annotation

GitHub Actions / tsc (atb)

'@atb/components/map_v2/plugins/use-plugins.tsx' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 10 in src/components/map_v2/MapV2.tsx

View workflow job for this annotation

GitHub Actions / tsc (nfk)

'@atb/components/map_v2/plugins/use-plugins.tsx' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 10 in src/components/map_v2/MapV2.tsx

View workflow job for this annotation

GitHub Actions / tsc (fram)

'@atb/components/map_v2/plugins/use-plugins.tsx' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 10 in src/components/map_v2/MapV2.tsx

View workflow job for this annotation

GitHub Actions / tsc (troms)

'@atb/components/map_v2/plugins/use-plugins.tsx' import is restricted from being used by a pattern. Not allowed to import components without going through their index file
import {useMapRegion} from '@atb/components/map_v2/use-map-region.ts';

Check failure on line 11 in src/components/map_v2/MapV2.tsx

View workflow job for this annotation

GitHub Actions / tsc (atb)

'@atb/components/map_v2/use-map-region.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 11 in src/components/map_v2/MapV2.tsx

View workflow job for this annotation

GitHub Actions / tsc (nfk)

'@atb/components/map_v2/use-map-region.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 11 in src/components/map_v2/MapV2.tsx

View workflow job for this annotation

GitHub Actions / tsc (fram)

'@atb/components/map_v2/use-map-region.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 11 in src/components/map_v2/MapV2.tsx

View workflow job for this annotation

GitHub Actions / tsc (troms)

'@atb/components/map_v2/use-map-region.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

export const MapV2 = () => {
const mapCameraRef = useRef<MapboxGL.Camera>(null);
const mapViewRef = useRef<MapboxGL.MapView>(null);
const styles = useMapStyles();

const startingCoordinates = getCurrentCoordinatesGlobal() || FOCUS_ORIGIN;
const {mapRegion, onDidFinishLoadingMap, onMapIdle} =
useMapRegion(mapViewRef);

const {renderedFeatures, handleClick} = usePlugins(mapRegion);

return (
<View style={styles.container}>
<View style={{flex: 1}}>
<MapboxGL.MapView
ref={mapViewRef}
style={{flex: 1}}
pitchEnabled={false}
onDidFinishLoadingMap={onDidFinishLoadingMap}
onMapIdle={onMapIdle}
onPress={(f) => {
if (isFeaturePoint(f)) {
getFeaturesAtClick(f, mapViewRef).then(
(f) => f && handleClick(f as any),
);
}
}}
{...MapViewConfig}
>
<MapboxGL.Camera
ref={mapCameraRef}
zoomLevel={15}
centerCoordinate={[
startingCoordinates.longitude,
startingCoordinates.latitude,
]}
{...MapCameraConfig}
/>

{renderedFeatures}

<LocationPuck puckBearing="heading" puckBearingEnabled={true} />
</MapboxGL.MapView>
</View>
</View>
);
};

const useMapStyles = StyleSheet.createThemeHook(() => ({
container: {flex: 1},
}));
1 change: 1 addition & 0 deletions src/components/map_v2/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {MapV2} from './MapV2.tsx';
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {isScooter, ScooterSheet, useVehicles} from '@atb/mobility';
import {Scooters} from '@atb/components/map/components/mobility/Scooters.tsx';

Check failure on line 2 in src/components/map_v2/plugins/el-scooter-plugin/use-el-scooters-plugin.tsx

View workflow job for this annotation

GitHub Actions / tsc (atb)

'@atb/components/map/components/mobility/Scooters.tsx' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 2 in src/components/map_v2/plugins/el-scooter-plugin/use-el-scooters-plugin.tsx

View workflow job for this annotation

GitHub Actions / tsc (nfk)

'@atb/components/map/components/mobility/Scooters.tsx' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 2 in src/components/map_v2/plugins/el-scooter-plugin/use-el-scooters-plugin.tsx

View workflow job for this annotation

GitHub Actions / tsc (fram)

'@atb/components/map/components/mobility/Scooters.tsx' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 2 in src/components/map_v2/plugins/el-scooter-plugin/use-el-scooters-plugin.tsx

View workflow job for this annotation

GitHub Actions / tsc (troms)

'@atb/components/map/components/mobility/Scooters.tsx' import is restricted from being used by a pattern. Not allowed to import components without going through their index file
import React, {useEffect} from 'react';
import {Feature, Point} from 'geojson';
import {MapPluginType} from '@atb/components/map_v2/plugins/types.ts';

Check failure on line 5 in src/components/map_v2/plugins/el-scooter-plugin/use-el-scooters-plugin.tsx

View workflow job for this annotation

GitHub Actions / tsc (atb)

'@atb/components/map_v2/plugins/types.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 5 in src/components/map_v2/plugins/el-scooter-plugin/use-el-scooters-plugin.tsx

View workflow job for this annotation

GitHub Actions / tsc (nfk)

'@atb/components/map_v2/plugins/types.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 5 in src/components/map_v2/plugins/el-scooter-plugin/use-el-scooters-plugin.tsx

View workflow job for this annotation

GitHub Actions / tsc (fram)

'@atb/components/map_v2/plugins/types.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 5 in src/components/map_v2/plugins/el-scooter-plugin/use-el-scooters-plugin.tsx

View workflow job for this annotation

GitHub Actions / tsc (troms)

'@atb/components/map_v2/plugins/types.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file
import {useBottomSheet} from '@atb/components/bottom-sheet';

export const useElScootersPlugin: MapPluginType = ({
region,
setSharedState,
}) => {
const {open: openBottomSheet, close: closeBottomSheet} = useBottomSheet();
const vehicles = useVehicles({SCOOTER: {showAll: true, operators: []}});
const elScooterFeatures = vehicles?.vehicles.scooters;
const updateRegion = vehicles?.updateRegion;

useEffect(() => {
if (region) updateRegion?.(region);
}, [region, updateRegion]);
Comment on lines +17 to +19
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After the tile server + vector source is in place, we can completely remove the updateRegion stuff :)


return {
handlePress: (features: Feature<Point>[]) => {
const scooterFeature = features.find(isScooter);
if (scooterFeature) {
openBottomSheet(() => {
return (
<ScooterSheet
vehicleId={scooterFeature.properties.id}
onClose={() => {
setSharedState({selectedEntityId: undefined});
closeBottomSheet();
}}
onReportParkingViolation={() => {}}
/>
);
}, false);
Comment on lines +25 to +36
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is something very "un-react" about calling functions like this.
I would prefer dispatching an action that would set the app in the desired state 🤔

setSharedState({selectedEntityId: scooterFeature.properties.id});
return true;
}
return false;
},
renderedFeature: elScooterFeatures ? (
<Scooters scooters={elScooterFeatures} onClusterClick={() => {}} />
) : undefined,
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React from 'react';
import {Feature, FeatureCollection, Point} from 'geojson';
import {MapPluginType} from '@atb/components/map_v2/plugins/types.ts';

Check failure on line 3 in src/components/map_v2/plugins/geofencing-zones-plugin/use-geofencing-zones-plugin.tsx

View workflow job for this annotation

GitHub Actions / tsc (atb)

'@atb/components/map_v2/plugins/types.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 3 in src/components/map_v2/plugins/geofencing-zones-plugin/use-geofencing-zones-plugin.tsx

View workflow job for this annotation

GitHub Actions / tsc (nfk)

'@atb/components/map_v2/plugins/types.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 3 in src/components/map_v2/plugins/geofencing-zones-plugin/use-geofencing-zones-plugin.tsx

View workflow job for this annotation

GitHub Actions / tsc (fram)

'@atb/components/map_v2/plugins/types.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 3 in src/components/map_v2/plugins/geofencing-zones-plugin/use-geofencing-zones-plugin.tsx

View workflow job for this annotation

GitHub Actions / tsc (troms)

'@atb/components/map_v2/plugins/types.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file
import {useVehicleQuery} from '@atb/mobility/queries/use-vehicle-query.tsx';
import {
hitboxCoveringIconOnly,
PreProcessedGeofencingZones,
usePreProcessedGeofencingZones,
} from '@atb/components/map';
import MapboxGL from '@rnmapbox/maps';
import {VehicleExtendedFragment} from '@atb/api/types/generated/fragments/vehicles.ts';

export const useGeofencingZonesPlugin: MapPluginType = ({sharedState}) => {
const {data: vehicle} = useVehicleQuery(sharedState.selectedEntityId ?? '');

return {
handlePress: (_features: Feature<Point>[]) => {
return true;
},
renderedFeature: vehicle ? (
<GeofencingZonesForVehicle vehicle={vehicle} />
) : undefined,
};
};

type GeofencingZonesForVehicleProps = {
vehicle: VehicleExtendedFragment;
};
const GeofencingZonesForVehicle = ({
vehicle,
}: GeofencingZonesForVehicleProps) => {
const preProcessedGeofencingZones = usePreProcessedGeofencingZones(vehicle);

return (
<>
{preProcessedGeofencingZones.map((geofencingZone) => (
<GeofencingZone
geofencingZone={geofencingZone}
key={geofencingZone?.renderKey}
/>
))}
</>
);
};

type GeofencingZoneProps = {
geofencingZone: PreProcessedGeofencingZones;
};
const GeofencingZone = ({geofencingZone}: GeofencingZoneProps) => {
const getGeofencingZoneCustomProps = ['get', 'geofencingZoneCustomProps'];
const bgColor = [
'get',
'background',
['get', 'color', getGeofencingZoneCustomProps],
];
const fillOpacity = ['get', 'fillOpacity', getGeofencingZoneCustomProps];
const lineOpacity = [
'get',
'background',

['get', 'strokeOpacity', getGeofencingZoneCustomProps],
];
return (
<MapboxGL.ShapeSource
id={'geofencingZonesShapeSource_' + geofencingZone?.renderKey}
shape={geofencingZone.geojson as FeatureCollection} // FeatureCollection from mobility-types_v2 and FeatureCollection from geojson used by MapboxGL don't match perfectly
hitbox={hitboxCoveringIconOnly} // to not be able to hit multiple zones with one click
>
<MapboxGL.FillLayer
id="parkingFill"
style={{
fillAntialias: true,
fillColor: bgColor,
fillOpacity,
}}
aboveLayerID="water-point-label"
/>
<MapboxGL.LineLayer
id="tariffZonesLine"
style={{
lineWidth: 3,
lineColor: bgColor,
lineOpacity,
}}
aboveLayerID="water-point-label"
/>
</MapboxGL.ShapeSource>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {Feature, Point} from 'geojson';
import {DeparturesDialogSheet} from '../../../map/components/DeparturesDialogSheet';
import React from 'react';
import {useBottomSheet} from '@atb/components/bottom-sheet';
import type {MapPluginType} from '@atb/components/map_v2/plugins/types.ts';

Check failure on line 5 in src/components/map_v2/plugins/stop-place-plugin/use-stop-place-plugin.tsx

View workflow job for this annotation

GitHub Actions / tsc (atb)

'@atb/components/map_v2/plugins/types.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 5 in src/components/map_v2/plugins/stop-place-plugin/use-stop-place-plugin.tsx

View workflow job for this annotation

GitHub Actions / tsc (nfk)

'@atb/components/map_v2/plugins/types.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 5 in src/components/map_v2/plugins/stop-place-plugin/use-stop-place-plugin.tsx

View workflow job for this annotation

GitHub Actions / tsc (fram)

'@atb/components/map_v2/plugins/types.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 5 in src/components/map_v2/plugins/stop-place-plugin/use-stop-place-plugin.tsx

View workflow job for this annotation

GitHub Actions / tsc (troms)

'@atb/components/map_v2/plugins/types.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file
import {isStopPlace} from "@atb/components/map/utils.ts";

Check failure on line 6 in src/components/map_v2/plugins/stop-place-plugin/use-stop-place-plugin.tsx

View workflow job for this annotation

GitHub Actions / tsc (atb)

'@atb/components/map/utils.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 6 in src/components/map_v2/plugins/stop-place-plugin/use-stop-place-plugin.tsx

View workflow job for this annotation

GitHub Actions / tsc (nfk)

'@atb/components/map/utils.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 6 in src/components/map_v2/plugins/stop-place-plugin/use-stop-place-plugin.tsx

View workflow job for this annotation

GitHub Actions / tsc (fram)

'@atb/components/map/utils.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 6 in src/components/map_v2/plugins/stop-place-plugin/use-stop-place-plugin.tsx

View workflow job for this annotation

GitHub Actions / tsc (troms)

'@atb/components/map/utils.ts' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

export const useStopPlacePlugin: MapPluginType = (_) => {
const {open: openBottomSheet, close: closeBottomSheet} = useBottomSheet();
return {
handlePress: (features: Feature<Point>[]): boolean => {
// if (!enabled) return true;

const stopPlaceFeature = features.find(isStopPlace);
if (stopPlaceFeature) {
openBottomSheet(
() => (
<DeparturesDialogSheet
onClose={closeBottomSheet}
distance={200}
stopPlaceFeature={stopPlaceFeature}
navigateToDetails={closeBottomSheet}
navigateToQuay={closeBottomSheet}
navigateToTripSearch={closeBottomSheet}
/>
),
false,
);
return false;
}

return true;
},
renderedFeature: undefined,
};
};
17 changes: 17 additions & 0 deletions src/components/map_v2/plugins/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {Feature, Point} from 'geojson';
import {MapRegion} from '@atb/components/map';

export type MapPluginsSharedState = {
selectedEntityId: string | undefined;
};

type MapPluginProps = {
region: MapRegion | undefined;
sharedState: MapPluginsSharedState;
setSharedState: (ms: MapPluginsSharedState) => void;
};

export type MapPluginType = (props: MapPluginProps) => {
handlePress: (features: Feature<Point>[]) => boolean;
renderedFeature: JSX.Element | undefined;
};
41 changes: 41 additions & 0 deletions src/components/map_v2/plugins/use-plugins.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import {useStopPlacePlugin} from './stop-place-plugin/use-stop-place-plugin';
import {Feature, Point} from 'geojson';
import {useElScootersPlugin} from '@atb/components/map_v2/plugins/el-scooter-plugin/use-el-scooters-plugin.tsx';

Check failure on line 3 in src/components/map_v2/plugins/use-plugins.tsx

View workflow job for this annotation

GitHub Actions / tsc (atb)

'@atb/components/map_v2/plugins/el-scooter-plugin/use-el-scooters-plugin.tsx' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 3 in src/components/map_v2/plugins/use-plugins.tsx

View workflow job for this annotation

GitHub Actions / tsc (nfk)

'@atb/components/map_v2/plugins/el-scooter-plugin/use-el-scooters-plugin.tsx' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 3 in src/components/map_v2/plugins/use-plugins.tsx

View workflow job for this annotation

GitHub Actions / tsc (fram)

'@atb/components/map_v2/plugins/el-scooter-plugin/use-el-scooters-plugin.tsx' import is restricted from being used by a pattern. Not allowed to import components without going through their index file

Check failure on line 3 in src/components/map_v2/plugins/use-plugins.tsx

View workflow job for this annotation

GitHub Actions / tsc (troms)

'@atb/components/map_v2/plugins/el-scooter-plugin/use-el-scooters-plugin.tsx' import is restricted from being used by a pattern. Not allowed to import components without going through their index file
import {MapRegion} from '@atb/components/map';
import {MapPluginsSharedState} from '@atb/components/map_v2/plugins/types.ts';
import {useState} from 'react';
import {useGeofencingZonesPlugin} from '@atb/components/map_v2/plugins/geofencing-zones-plugin/use-geofencing-zones-plugin.tsx';

export const usePlugins = (region?: MapRegion) => {
const [sharedState, setSharedState] = useState<MapPluginsSharedState>({
selectedEntityId: undefined,
});
const pluginProps = {region, sharedState, setSharedState};
const {handlePress: handleStopPlaceClick} = useStopPlacePlugin(pluginProps);
const {handlePress: handleElScooterClick, renderedFeature: elScooterFeature} =
useElScootersPlugin(pluginProps);
const {
handlePress: _handleGeofencingZonesClick,
renderedFeature: geofencingZoneFeature,
} = useGeofencingZonesPlugin(pluginProps);

const clickHandlers = [handleStopPlaceClick, handleElScooterClick];

const handleClick = (features: Feature<Point>[]) => {
for (const handle of clickHandlers) {
const cont = handle(features);
if (!cont) break;
}
return true;
};

return {
handleClick,
renderedFeatures: (
<>
{elScooterFeature}
{geofencingZoneFeature}
</>
),
};
};
40 changes: 40 additions & 0 deletions src/components/map_v2/use-map-region.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {RefObject, useState} from 'react';
import {MapRegion} from '@atb/components/map';
import MapboxGL, {MapState} from '@rnmapbox/maps';
import isEqual from 'lodash.isequal';

export const useMapRegion = (mapViewRef: RefObject<MapboxGL.MapView>) => {
const [mapRegion, setMapRegion] = useState<MapRegion>();

const onDidFinishLoadingMap = async () => {
const visibleBounds = await mapViewRef.current?.getVisibleBounds();
const zoomLevel = await mapViewRef.current?.getZoom();
const center = await mapViewRef.current?.getCenter();

if (!visibleBounds || !zoomLevel || !center) return;
setMapRegion({visibleBounds, zoomLevel, center});
};

/**
* OnMapIdle fires more often than expected, because of that we check if the
* map region is changed before updating its state.
*
* There is a slight performance overhead by deep comparing previous and new
* map regions on each on map idle, but since we have control over the size of
* the objects it should be ok. The risk of firing effects that uses the map
* region too often is greater than the risk introduced by the performance
* overhead.
*/
const onMapIdle = (state: MapState) => {
const newMapRegion: MapRegion = {
visibleBounds: [state.properties.bounds.ne, state.properties.bounds.sw],
zoomLevel: state.properties.zoom,
center: state.properties.center,
};
setMapRegion((prevMapRegion) =>
isEqual(prevMapRegion, newMapRegion) ? prevMapRegion : newMapRegion,
);
};

return {mapRegion, onDidFinishLoadingMap, onMapIdle};
};
Loading
Loading