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

fix add center button and blue dot #40759

Merged
merged 39 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
be55619
fix add center button and blue dot
nkdengineer Apr 23, 2024
0a4b847
fix use util.getBounds
nkdengineer Apr 23, 2024
6093f69
fix update center button
nkdengineer Apr 24, 2024
e7420da
fix native issue
nkdengineer Apr 25, 2024
b7b9fbb
fix lint
nkdengineer Apr 25, 2024
a5ea387
fix lint
nkdengineer Apr 25, 2024
a218054
fix create blueDot color
nkdengineer Apr 25, 2024
b7a31bc
fix lint
nkdengineer Apr 25, 2024
f29e65b
fix only display center button if user interacted
nkdengineer Apr 26, 2024
f975e08
fix merge main
nkdengineer Apr 28, 2024
9754dce
fix using toggleCenterButton and related comment
nkdengineer Apr 30, 2024
ee0584b
fix type error
nkdengineer Apr 30, 2024
50208b8
fix blue dot radius
nkdengineer May 2, 2024
ee76e2e
Merge branch 'main' into fix/40209
nkdengineer May 2, 2024
3acd03f
fix hide center button if already centered
nkdengineer May 2, 2024
757865a
fix lint
nkdengineer May 2, 2024
f1de15d
fix fade in and out 300ms
nkdengineer May 3, 2024
d179015
fix remove inline style and rename function
nkdengineer May 3, 2024
1ff830a
fix merge main
nkdengineer May 8, 2024
eadb32a
fix lint
nkdengineer May 8, 2024
ee8cef6
fix using onTouchCancel instead of onTouchEnd
nkdengineer May 8, 2024
ee451b3
fix merge main
nkdengineer May 16, 2024
273741e
fix native issues
nkdengineer May 16, 2024
b253ae1
fix remove redundant logic
nkdengineer May 16, 2024
b12c374
fix merge main
nkdengineer May 20, 2024
aa487e7
fix compare two coordinates in web
nkdengineer May 21, 2024
6ee0862
fix lint
nkdengineer May 21, 2024
6c90e66
fix lint
nkdengineer May 21, 2024
b38b19f
fix always display center button
nkdengineer May 21, 2024
0688a0e
fix lint
nkdengineer May 21, 2024
e30eb90
fix remove maxZoom prop and change the default zoom value
nkdengineer May 23, 2024
76679ed
fix remove currentZoom variable
nkdengineer May 23, 2024
55f6535
fix merge main
nkdengineer May 24, 2024
0f09d6f
fix merge main
nkdengineer May 28, 2024
1732367
Merge branch 'main' into fix/40209
nkdengineer May 29, 2024
cc42428
fix lint
nkdengineer May 29, 2024
2d79bd8
fix lint
nkdengineer May 29, 2024
95591d9
fix add explaination about haversineDistance
nkdengineer Jun 3, 2024
3fe0372
fix haversineDistance: add new line
nkdengineer Jun 3, 2024
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
23 changes: 23 additions & 0 deletions assets/images/crosshair.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3508,10 +3508,12 @@ const CONST = {
COLON: ':',
MAPBOX: {
PADDING: 50,
DEFAULT_ZOOM: 10,
DEFAULT_ZOOM: 15,
SINGLE_MARKER_ZOOM: 15,
DEFAULT_COORDINATE: [-122.4021, 37.7911],
STYLE_URL: 'mapbox://styles/expensify/cllcoiqds00cs01r80kp34tmq',
ANIMATION_DURATION_ON_CENTER_ME: 1000,
Copy link
Member

Choose a reason for hiding this comment

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

I think this duration can be shortened.

CENTER_BUTTON_FADE_DURATION: 300,
},
ONYX_UPDATE_TYPES: {
HTTPS: 'https',
Expand Down
2 changes: 2 additions & 0 deletions src/components/Icon/Expensicons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import ConnectionComplete from '@assets/images/connection-complete.svg';
import Copy from '@assets/images/copy.svg';
import CreditCardHourglass from '@assets/images/credit-card-hourglass.svg';
import CreditCard from '@assets/images/creditcard.svg';
import Crosshair from '@assets/images/crosshair.svg';
import DocumentPlus from '@assets/images/document-plus.svg';
import DocumentSlash from '@assets/images/document-slash.svg';
import Document from '@assets/images/document.svg';
Expand Down Expand Up @@ -206,6 +207,7 @@ export {
Concierge,
ConciergeAvatar,
Connect,
Crosshair,
ConnectionComplete,
Copy,
CreditCard,
Expand Down
65 changes: 64 additions & 1 deletion src/components/MapView/MapView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@ import Mapbox, {MarkerView, setAccessToken} from '@rnmapbox/maps';
import {forwardRef, memo, useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react';
import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import {PressableWithoutFeedback} from '@components/Pressable';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import * as UserLocation from '@libs/actions/UserLocation';
import compose from '@libs/compose';
import getCurrentPosition from '@libs/getCurrentPosition';
import type {GeolocationErrorCallback} from '@libs/getCurrentPosition/getCurrentPosition.types';
import {GeolocationErrorCode} from '@libs/getCurrentPosition/getCurrentPosition.types';
import colors from '@styles/theme/colors';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import useLocalize from '@src/hooks/useLocalize';
import useNetwork from '@src/hooks/useNetwork';
Expand All @@ -27,7 +33,7 @@ const MapView = forwardRef<MapViewHandle, ComponentProps>(
const {isOffline} = useNetwork();
const {translate} = useLocalize();
const styles = useThemeStyles();

const theme = useTheme();
const cameraRef = useRef<Mapbox.Camera>(null);
const [isIdle, setIsIdle] = useState(false);
const [currentPosition, setCurrentPosition] = useState(cachedUserLocation);
Expand Down Expand Up @@ -148,6 +154,19 @@ const MapView = forwardRef<MapViewHandle, ComponentProps>(
onMapReady();
}
};
const centerMap = useCallback(() => {
if (directionCoordinates && directionCoordinates.length > 1) {
const {southWest, northEast} = utils.getBounds(waypoints?.map((waypoint) => waypoint.coordinate) ?? [], directionCoordinates);
cameraRef.current?.fitBounds(southWest, northEast, mapPadding, CONST.MAPBOX.ANIMATION_DURATION_ON_CENTER_ME);
return;
}
cameraRef?.current?.setCamera({
heading: 0,
centerCoordinate: [currentPosition?.longitude ?? 0, currentPosition?.latitude ?? 0],
animationDuration: CONST.MAPBOX.ANIMATION_DURATION_ON_CENTER_ME,
zoomLevel: CONST.MAPBOX.SINGLE_MARKER_ZOOM,
});
}, [directionCoordinates, currentPosition, mapPadding, waypoints]);

const centerCoordinate = currentPosition ? [currentPosition.longitude, currentPosition.latitude] : initialState?.location;
return !isOffline && Boolean(accessToken) && Boolean(currentPosition) ? (
Expand All @@ -174,9 +193,37 @@ const MapView = forwardRef<MapViewHandle, ComponentProps>(
// displayed after the first render when the app's storage is cleared.
centerCoordinate={centerCoordinate}
/>
<Mapbox.ShapeSource
id="user-location"
shape={{
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [currentPosition?.longitude ?? 0, currentPosition?.latitude ?? 0],
},
properties: {},
},
],
}}
>
<Mapbox.CircleLayer
id="user-location-layer"
sourceID="user-location"
style={{
circleColor: colors.blue400,
circleRadius: 8,
}}
/>
</Mapbox.ShapeSource>

{waypoints?.map(({coordinate, markerComponent, id}) => {
const MarkerComponent = markerComponent;
if (utils.areSameCoordinate([coordinate[0], coordinate[1]], [currentPosition?.longitude ?? 0, currentPosition?.latitude ?? 0])) {
return null;
}
return (
<MarkerView
id={id}
Expand All @@ -190,6 +237,22 @@ const MapView = forwardRef<MapViewHandle, ComponentProps>(

{directionCoordinates && <Direction coordinates={directionCoordinates} />}
</Mapbox.MapView>
<View style={[styles.pAbsolute, styles.p5, styles.t0, styles.r0, {zIndex: 1}]}>
<PressableWithoutFeedback
Copy link
Contributor

Choose a reason for hiding this comment

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

Coming from #43058. We missed adding hover and press effect on this button.

Copy link
Member

Choose a reason for hiding this comment

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

This is wrong. It was not part of the requirement. Design team approved this PR. So the mentioned issued is a new feature/change. @jjcoffee Could you please update the bug list to remove this PR?

Copy link
Contributor

Choose a reason for hiding this comment

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

We might have missed this but the @Expensify/design explicitly stated several times that we wanted this button behavior to match all of our other default buttons. Don't our default buttons all have a hover and press style?

Copy link
Member

Choose a reason for hiding this comment

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

Ok. I see. We were pushed to merge this quickly so it might be missed.

accessibilityRole={CONST.ROLE.BUTTON}
onPress={centerMap}
accessibilityLabel={translate('common.center')}
>
<View style={styles.primaryMediumIcon}>
<Icon
width={variables.iconSizeNormal}
height={variables.iconSizeNormal}
src={Expensicons.Crosshair}
fill={theme.icon}
/>
</View>
</PressableWithoutFeedback>
</View>
</View>
) : (
<PendingMapView
Expand Down
50 changes: 50 additions & 0 deletions src/components/MapView/MapView.website.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@ import type {MapRef} from 'react-map-gl';
import Map, {Marker} from 'react-map-gl';
import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import {PressableWithoutFeedback} from '@components/Pressable';
import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import type {GeolocationErrorCallback} from '@libs/getCurrentPosition/getCurrentPosition.types';
import {GeolocationErrorCode} from '@libs/getCurrentPosition/getCurrentPosition.types';
import variables from '@styles/variables';
import * as UserLocation from '@userActions/UserLocation';
import CONST from '@src/CONST';
import useLocalize from '@src/hooks/useLocalize';
Expand Down Expand Up @@ -183,6 +187,26 @@ const MapView = forwardRef<MapViewHandle, ComponentProps>(
[mapRef],
);

const centerMap = useCallback(() => {
if (!mapRef) {
return;
}
if (directionCoordinates && directionCoordinates.length > 1) {
const {northEast, southWest} = utils.getBounds(waypoints?.map((waypoint) => waypoint.coordinate) ?? [], directionCoordinates);
const map = mapRef?.getMap();
map?.fitBounds([southWest, northEast], {padding: mapPadding, animate: true, duration: CONST.MAPBOX.ANIMATION_DURATION_ON_CENTER_ME});
return;
}

mapRef.flyTo({
center: [currentPosition?.longitude ?? 0, currentPosition?.latitude ?? 0],
zoom: CONST.MAPBOX.SINGLE_MARKER_ZOOM,
bearing: 0,
animate: true,
duration: CONST.MAPBOX.ANIMATION_DURATION_ON_CENTER_ME,
});
}, [directionCoordinates, currentPosition, mapRef, waypoints, mapPadding]);

return !isOffline && Boolean(accessToken) && Boolean(currentPosition) ? (
<View
style={style}
Expand All @@ -203,8 +227,18 @@ const MapView = forwardRef<MapViewHandle, ComponentProps>(
mapStyle={styleURL}
interactive={interactive}
>
<Marker
key="Current-position"
longitude={currentPosition?.longitude ?? 0}
latitude={currentPosition?.latitude ?? 0}
>
<View style={styles.currentPositionDot} />
</Marker>
{waypoints?.map(({coordinate, markerComponent, id}) => {
const MarkerComponent = markerComponent;
if (utils.areSameCoordinate([coordinate[0], coordinate[1]], [currentPosition?.longitude ?? 0, currentPosition?.latitude ?? 0])) {
return null;
}
return (
<Marker
key={id}
Expand All @@ -217,6 +251,22 @@ const MapView = forwardRef<MapViewHandle, ComponentProps>(
})}
{directionCoordinates && <Direction coordinates={directionCoordinates} />}
</Map>
<View style={[styles.pAbsolute, styles.p5, styles.t0, styles.r0, {zIndex: 1}]}>
<PressableWithoutFeedback
accessibilityRole={CONST.ROLE.BUTTON}
onPress={centerMap}
accessibilityLabel={translate('common.center')}
>
<View style={styles.primaryMediumIcon}>
<Icon
width={variables.iconSizeNormal}
height={variables.iconSizeNormal}
src={Expensicons.Crosshair}
fill={theme.icon}
/>
</View>
</PressableWithoutFeedback>
</View>
</View>
) : (
<PendingMapView
Expand Down
25 changes: 25 additions & 0 deletions src/components/MapView/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,31 @@ function getBounds(waypoints: Array<[number, number]>, directionCoordinates: und
};
}

/**
* Calculates the distance between two points on the Earth's surface given their latitude and longitude coordinates.
*/
function haversineDistance(coordinate1: number[], coordinate2: number[]) {
nkdengineer marked this conversation as resolved.
Show resolved Hide resolved
// Radius of the Earth in meters
const R = 6371e3;
const lat1 = (coordinate1[0] * Math.PI) / 180;
const lat2 = (coordinate2[0] * Math.PI) / 180;
const deltaLat = ((coordinate2[0] - coordinate1[0]) * Math.PI) / 180;
const deltaLon = ((coordinate2[1] - coordinate1[1]) * Math.PI) / 180;
// The square of half the chord length between the points
nkdengineer marked this conversation as resolved.
Show resolved Hide resolved
const halfChordLengthSq = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) + Math.cos(lat1) * Math.cos(lat2) * Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2);

// The angular distance in radians
const angularDistance = 2 * Math.atan2(Math.sqrt(halfChordLengthSq), Math.sqrt(1 - halfChordLengthSq));

// Distance in meters
return R * angularDistance;
}

function areSameCoordinate(coordinate1: number[], coordinate2: number[]) {
return haversineDistance(coordinate1, coordinate2) < 20;
}

export default {
getBounds,
areSameCoordinate,
};
1 change: 1 addition & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ export default {
buttonConfirm: 'Got it',
name: 'Name',
attachment: 'Attachment',
center: 'Center',
from: 'From',
to: 'To',
optional: 'Optional',
Expand Down
1 change: 1 addition & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export default {
to: 'A',
optional: 'Opcional',
new: 'Nuevo',
center: 'Centrar',
search: 'Buscar',
find: 'Encontrar',
searchWithThreeDots: 'Buscar...',
Expand Down
1 change: 1 addition & 0 deletions src/styles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4417,6 +4417,7 @@ const styles = (theme: ThemeColors) =>
borderWidth: variables.componentBorderWidth,
borderColor: theme.appBG,
},
currentPositionDot: {backgroundColor: colors.blue400, width: 16, height: 16, borderRadius: 16},

mapViewOverlay: {
flex: 1,
Expand Down
Loading