Skip to content

Commit

Permalink
Map panning fix (#2)
Browse files Browse the repository at this point in the history
* Fix Map Panning behavior

* Add screen focus state props to MapView

Added new props to avoid introducing unnecessary dependencies ('@react-navigation/native') to the 'react-native-x-maps' library.

* feat: Move code from react-native-x-maps to the App

* fix: rename mapbox consts

* fix: Fix app crashing on waypoint delete

* Remove unnecessary re exports

* Fix react duplicate keys Expensify#35

* Fix Not Found Page appearing issue and add comment

* Fix panning issue

* fix: add PropTypes import which is mised during conflict resolution
  • Loading branch information
gegham-khachatryan authored Sep 1, 2023
1 parent 64c65ff commit 065a6dd
Show file tree
Hide file tree
Showing 14 changed files with 413 additions and 80 deletions.
2 changes: 1 addition & 1 deletion config/webpack/webpack.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ const webpackConfig = ({envFile = '.env', platform = 'web'}) => ({
// This is also why we have to use .website.js for our own web-specific files...
// Because desktop also relies on "web-specific" module implementations
// This also skips packing web only dependencies to desktop and vice versa
extensions: ['.web.js', platform === 'web' ? '.website.js' : '.desktop.js', '.js', '.jsx', '.web.ts', platform === 'web' ? '.website.ts' : '.desktop.ts', '.ts', '.tsx'],
extensions: ['.web.js', platform === 'web' ? '.website.js' : '.desktop.js', '.js', '.jsx', '.web.ts', platform === 'web' ? '.website.ts' : '.desktop.ts', '.ts', '.web.tsx', '.tsx'],
fallback: {
'process/browser': require.resolve('process/browser'),
},
Expand Down
19 changes: 0 additions & 19 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@
"react-native-web-linear-gradient": "^1.1.2",
"react-native-web-lottie": "^1.4.4",
"react-native-webview": "^11.17.2",
"react-native-x-maps": "1.0.10",
"react-pdf": "^6.2.2",
"react-plaid-link": "3.3.2",
"react-web-config": "^1.0.0",
Expand Down
8 changes: 7 additions & 1 deletion src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2604,7 +2604,6 @@ const CONST = {

SF_COORDINATES: [-122.4194, 37.7749],

MAPBOX_STYLE_URL: 'mapbox://styles/expensify/cllcoiqds00cs01r80kp34tmq',
NAVIGATION: {
TYPE: {
FORCED_UP: 'FORCED_UP',
Expand All @@ -2623,6 +2622,13 @@ const CONST = {
SAASTR: 'SaaStrDemoSetup',
SBE: 'SbeDemoSetup',
},

MAPBOX: {
PADDING: 50,
DEFAULT_ZOOM: 10,
DEFAULT_COORDINATE: [-122.4021, 37.7911],
STYLE_URL: 'mapbox://styles/expensify/cllcoiqds00cs01r80kp34tmq',
},
} as const;

export default CONST;
115 changes: 60 additions & 55 deletions src/components/DistanceRequest.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,42 @@
import React, {useEffect, useState} from 'react';
import React, {useEffect, useMemo, useState} from 'react';
import {ScrollView, View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import lodashGet from 'lodash/get';
import lodashHas from 'lodash/has';
import _ from 'underscore';
import PropTypes from 'prop-types';
import {withOnyx} from 'react-native-onyx';
import MapView from 'react-native-x-maps';
import _ from 'underscore';

import CONST from '../CONST';
import ROUTES from '../ROUTES';
import ONYXKEYS from '../ONYXKEYS';
import * as Transaction from '../libs/actions/Transaction';
import * as TransactionUtils from '../libs/TransactionUtils';
import MenuItemWithTopDescription from './MenuItemWithTopDescription';
import * as Expensicons from './Icon/Expensicons';
import theme from '../styles/themes/default';
import Button from './Button';

import styles from '../styles/styles';
import variables from '../styles/variables';
import LinearGradient from './LinearGradient';
import * as MapboxToken from '../libs/actions/MapboxToken';
import CONST from '../CONST';
import BlockingView from './BlockingViews/BlockingView';
import theme from '../styles/themes/default';

import transactionPropTypes from './transactionPropTypes';

import useNetwork from '../hooks/useNetwork';
import usePrevious from '../hooks/usePrevious';
import useLocalize from '../hooks/useLocalize';

import * as ErrorUtils from '../libs/ErrorUtils';
import Navigation from '../libs/Navigation/Navigation';
import ROUTES from '../ROUTES';
import * as IOU from '../libs/actions/IOU';
import reportPropTypes from '../pages/reportPropTypes';
import transactionPropTypes from './transactionPropTypes';
import * as MapboxToken from '../libs/actions/MapboxToken';
import * as Transaction from '../libs/actions/Transaction';
import * as TransactionUtils from '../libs/TransactionUtils';

import Button from './Button';
import MapView from './MapView';
import LinearGradient from './LinearGradient';
import * as Expensicons from './Icon/Expensicons';
import BlockingView from './BlockingViews/BlockingView';
import DotIndicatorMessage from './DotIndicatorMessage';
import * as ErrorUtils from '../libs/ErrorUtils';
import usePrevious from '../hooks/usePrevious';
import {iouPropTypes} from '../pages/iou/propTypes';
import MenuItemWithTopDescription from './MenuItemWithTopDescription';

const MAX_WAYPOINTS = 25;
const MAX_WAYPOINTS_TO_DISPLAY = 4;

const DEFAULT_ZOOM_LEVEL = 10;

const propTypes = {
/** Holds data related to Money Request view state, rather than the underlying Money Request data. */
iou: iouPropTypes,
Expand Down Expand Up @@ -75,7 +76,7 @@ function DistanceRequest({iou, iouType, report, transaction, mapboxAccessToken})
const {translate} = useLocalize();

const reportID = lodashGet(report, 'reportID', '');
const waypoints = lodashGet(transaction, 'comment.waypoints', {});
const waypoints = useMemo(() => lodashGet(transaction, 'comment.waypoints', {}), [transaction]);
const numberOfWaypoints = _.size(waypoints);

const lastWaypointIndex = numberOfWaypoints - 1;
Expand All @@ -86,34 +87,39 @@ function DistanceRequest({iou, iouType, report, transaction, mapboxAccessToken})
const doesRouteExist = lodashHas(transaction, 'routes.route0.geometry.coordinates');
const shouldFetchRoute = (!doesRouteExist || haveWaypointsChanged) && !isLoadingRoute && TransactionUtils.validateWaypoints(waypoints);

const waypointMarkers = _.filter(
_.map(waypoints, (waypoint, key) => {
if (!waypoint || !lodashHas(waypoint, 'lat') || !lodashHas(waypoint, 'lng')) {
return;
}
const waypointMarkers = useMemo(
() =>
_.filter(
_.map(waypoints, (waypoint, key) => {
if (!waypoint || !lodashHas(waypoint, 'lat') || !lodashHas(waypoint, 'lng')) {
return;
}

const index = Number(key.replace('waypoint', ''));
let MarkerComponent;
if (index === 0) {
MarkerComponent = Expensicons.DotIndicatorUnfilled;
} else if (index === lastWaypointIndex) {
MarkerComponent = Expensicons.Location;
} else {
MarkerComponent = Expensicons.DotIndicator;
}
const index = Number(key.replace('waypoint', ''));
let MarkerComponent;
if (index === 0) {
MarkerComponent = Expensicons.DotIndicatorUnfilled;
} else if (index === lastWaypointIndex) {
MarkerComponent = Expensicons.Location;
} else {
MarkerComponent = Expensicons.DotIndicator;
}

return {
coordinate: [waypoint.lng, waypoint.lat],
markerComponent: () => (
<MarkerComponent
width={CONST.MAP_MARKER_SIZE}
height={CONST.MAP_MARKER_SIZE}
fill={theme.icon}
/>
),
};
}),
(waypoint) => waypoint,
return {
id: `${waypoint.lng},${waypoint.lat},${index}`,
coordinate: [waypoint.lng, waypoint.lat],
markerComponent: () => (
<MarkerComponent
width={CONST.MAP_MARKER_SIZE}
height={CONST.MAP_MARKER_SIZE}
fill={theme.icon}
/>
),
};
}),
(waypoint) => waypoint,
),
[waypoints, lastWaypointIndex],
);

// Show up to the max number of waypoints plus 1/2 of one to hint at scrolling
Expand Down Expand Up @@ -218,17 +224,16 @@ function DistanceRequest({iou, iouType, report, transaction, mapboxAccessToken})
{!isOffline && Boolean(mapboxAccessToken.token) ? (
<MapView
accessToken={mapboxAccessToken.token}
mapPadding={CONST.MAP_PADDING}
mapPadding={CONST.MAPBOX.PADDING}
pitchEnabled={false}
initialState={{
location: CONST.SF_COORDINATES,
zoom: DEFAULT_ZOOM_LEVEL,
zoom: CONST.MAPBOX.DEFAULT_ZOOM,
location: CONST.MAPBOX.DEFAULT_COORDINATE,
}}
directionCoordinates={lodashGet(transaction, 'routes.route0.geometry.coordinates', [])}
directionStyle={styles.mapDirection}
style={styles.mapView}
waypoints={waypointMarkers}
styleURL={CONST.MAPBOX_STYLE_URL}
styleURL={CONST.MAPBOX.STYLE_URL}
/>
) : (
<View style={[styles.mapPendingView]}>
Expand Down
30 changes: 30 additions & 0 deletions src/components/MapView/Direction.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import Mapbox from '@rnmapbox/maps';
import {DirectionProps} from './MapViewTypes';
import styles from '../../styles/styles';

function Direction({coordinates}: DirectionProps) {
if (coordinates.length < 1) {
return null;
}

return (
<Mapbox.ShapeSource
id="routeSource"
shape={{
type: 'Feature',
properties: {},
geometry: {
type: 'LineString',
coordinates,
},
}}
>
<Mapbox.LineLayer
id="routeFill"
style={styles.mapDirection}
/>
</Mapbox.ShapeSource>
);
}

export default Direction;
48 changes: 48 additions & 0 deletions src/components/MapView/Direction.web.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Explanation: Different Mapbox libraries are required for web and native mobile platforms.
// This is why we have separate components for web and native to handle the specific implementations.
// For the web version, we use the Mapbox Web library called react-map-gl, while for the native mobile version,
// we utilize a different Mapbox library @rnmapbox/maps tailored for mobile development.

import React from 'react';
import {View} from 'react-native';
import {Layer, Source} from 'react-map-gl';
import {DirectionProps} from './MapViewTypes';

import styles from '../../styles/styles';

function Direction({coordinates}: DirectionProps) {
const layerLayoutStyle: Record<string, string> = styles.mapDirectionLayer.layout;
const layerPointStyle: Record<string, string | number> = styles.mapDirectionLayer.paint;

if (coordinates.length < 1) {
return null;
}
return (
<View>
{coordinates && (
<Source
id="route"
type="geojson"
data={{
type: 'Feature',
properties: {},
geometry: {
type: 'LineString',
coordinates,
},
}}
>
<Layer
id="route"
type="line"
source="route"
paint={layerPointStyle}
layout={layerLayoutStyle}
/>
</Source>
)}
</View>
);
}

export default Direction;
Loading

0 comments on commit 065a6dd

Please sign in to comment.