Live location sharing: set map bounds to include all locations (#8324)

* open a dialog with map centered around first beacon

Signed-off-by: Kerry Archibald <kerrya@element.io>

* test dialog opening from beacon body

Signed-off-by: Kerry Archibald <kerrya@element.io>

* test beaconmarker

Signed-off-by: Kerry Archibald <kerrya@element.io>

* add bounds to Map comp

Signed-off-by: Kerry Archibald <kerrya@element.io>

* add focusBeacon to beaconviewdialog, use bounds

Signed-off-by: Kerry Archibald <kerrya@element.io>

* lint

Signed-off-by: Kerry Archibald <kerrya@element.io>

* use membercolor on beacon view markers

Signed-off-by: Kerry Archibald <kerrya@element.io>

* add lnglatbounds to maplibre mock

Signed-off-by: Kerry Archibald <kerrya@element.io>

* update snapshots for expanded maplibre Map mock

Signed-off-by: Kerry Archibald <kerrya@element.io>

* test map bounds

Signed-off-by: Kerry Archibald <kerrya@element.io>

* tidy copy paste comment

Signed-off-by: Kerry Archibald <kerrya@element.io>

* add fallback when no more live locations

Signed-off-by: Kerry Archibald <kerrya@element.io>

* accurate signature for getBoundsCenter

Signed-off-by: Kerry Archibald <kerrya@element.io>
This commit is contained in:
Kerry 2022-04-19 13:35:39 +02:00 committed by GitHub
parent 6b13988eaa
commit f70186ea9b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 246 additions and 21 deletions

View file

@ -29,29 +29,43 @@ import { IDialogProps } from "../dialogs/IDialogProps";
import Map from '../location/Map';
import ZoomButtons from '../location/ZoomButtons';
import BeaconMarker from './BeaconMarker';
import { Bounds, getBeaconBounds } from '../../../utils/beacon/bounds';
import { getGeoUri } from '../../../utils/beacon';
import { Icon as LocationIcon } from '../../../../res/img/element-icons/location.svg';
import { _t } from '../../../languageHandler';
import AccessibleButton from '../elements/AccessibleButton';
interface IProps extends IDialogProps {
roomId: Room['roomId'];
matrixClient: MatrixClient;
// open the map centered on this beacon's location
focusBeacon?: Beacon;
}
// TODO actual center is coming soon
// for now just center around first beacon in list
const getMapCenterUri = (beacons: Beacon[]): string => {
const firstBeaconWithLocation = beacons.find(beacon => beacon.latestLocationState);
return firstBeaconWithLocation?.latestLocationState?.uri;
const getBoundsCenter = (bounds: Bounds): string | undefined => {
if (!bounds) {
return;
}
return getGeoUri({
latitude: (bounds.north + bounds.south) / 2,
longitude: (bounds.east + bounds.west) / 2,
timestamp: Date.now(),
});
};
/**
* Dialog to view live beacons maximised
*/
const BeaconViewDialog: React.FC<IProps> = ({ roomId, matrixClient, onFinished }) => {
const BeaconViewDialog: React.FC<IProps> = ({
focusBeacon,
roomId,
matrixClient,
onFinished,
}) => {
const liveBeacons = useLiveBeacons(roomId, matrixClient);
const mapCenterUri = getMapCenterUri(liveBeacons);
// TODO probably show loader or placeholder when there is no location
// to center the map on
const bounds = getBeaconBounds(liveBeacons);
const centerGeoUri = focusBeacon?.latestLocationState?.uri || getBoundsCenter(bounds);
return (
<BaseDialog
@ -60,9 +74,10 @@ const BeaconViewDialog: React.FC<IProps> = ({ roomId, matrixClient, onFinished }
fixedWidth={false}
>
<MatrixClientContext.Provider value={matrixClient}>
<Map
{ !!bounds ? <Map
id='mx_BeaconViewDialog'
centerGeoUri={mapCenterUri}
bounds={bounds}
centerGeoUri={centerGeoUri}
interactive
className="mx_BeaconViewDialog_map"
>
@ -77,7 +92,22 @@ const BeaconViewDialog: React.FC<IProps> = ({ roomId, matrixClient, onFinished }
<ZoomButtons map={map} />
</>
}
</Map>
</Map> :
<div
data-test-id='beacon-view-dialog-map-fallback'
className='mx_BeaconViewDialog_map mx_BeaconViewDialog_mapFallback'
>
<LocationIcon className='mx_BeaconViewDialog_mapFallbackIcon' />
<span className='mx_BeaconViewDialog_mapFallbackMessage'>{ _t('No live locations') }</span>
<AccessibleButton
kind='primary'
onClick={onFinished}
data-test-id='beacon-view-dialog-fallback-close'
>
{ _t('Close') }
</AccessibleButton>
</div>
}
</MatrixClientContext.Provider>
</BaseDialog>
);