Add option to find own location in map views
parent
a756b33fe9
commit
e5a7e83b48
|
@ -125,6 +125,9 @@ const BeaconViewDialog: React.FC<IProps> = ({ initialFocusedBeacon, roomId, matr
|
|||
setFocusedBeaconState({ beacon, ts: Date.now() });
|
||||
};
|
||||
|
||||
const hasOwnBeacon =
|
||||
liveBeacons.filter((beacon) => beacon?.beaconInfoOwner === matrixClient.getUserId()).length > 0;
|
||||
|
||||
return (
|
||||
<BaseDialog className="mx_BeaconViewDialog" onFinished={onFinished} fixedWidth={false}>
|
||||
<MatrixClientContext.Provider value={matrixClient}>
|
||||
|
@ -136,6 +139,7 @@ const BeaconViewDialog: React.FC<IProps> = ({ initialFocusedBeacon, roomId, matr
|
|||
interactive
|
||||
onError={setMapDisplayError}
|
||||
className="mx_BeaconViewDialog_map"
|
||||
allowGeolocate={!hasOwnBeacon}
|
||||
>
|
||||
{({ map }: { map: maplibregl.Map }) => (
|
||||
<>
|
||||
|
|
|
@ -23,10 +23,9 @@ import { ClientEvent, IClientWellKnown } from "matrix-js-sdk/src/client";
|
|||
import { _t } from "../../../languageHandler";
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import Modal from "../../../Modal";
|
||||
import SdkConfig from "../../../SdkConfig";
|
||||
import { tileServerFromWellKnown } from "../../../utils/WellKnownUtils";
|
||||
import { GenericPosition, genericPositionFromGeolocation, getGeoUri } from "../../../utils/beacon";
|
||||
import { LocationShareError, findMapStyleUrl } from "../../../utils/location";
|
||||
import { LocationShareError, findMapStyleUrl, positionFailureMessage } from "../../../utils/location";
|
||||
import ErrorDialog from "../dialogs/ErrorDialog";
|
||||
import AccessibleButton from "../elements/AccessibleButton";
|
||||
import { MapError } from "./MapError";
|
||||
|
@ -266,21 +265,3 @@ class LocationPicker extends React.Component<ILocationPickerProps, IState> {
|
|||
}
|
||||
|
||||
export default LocationPicker;
|
||||
|
||||
function positionFailureMessage(code: number): string {
|
||||
const brand = SdkConfig.get().brand;
|
||||
switch (code) {
|
||||
case 1:
|
||||
return _t(
|
||||
"%(brand)s was denied permission to fetch your location. " +
|
||||
"Please allow location access in your browser settings.",
|
||||
{ brand },
|
||||
);
|
||||
case 2:
|
||||
return _t("Failed to fetch your location. Please try again later.");
|
||||
case 3:
|
||||
return _t("Timed out trying to fetch your location. Please try again later.");
|
||||
case 4:
|
||||
return _t("Unknown error fetching location. Please try again later.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ export default class LocationViewDialog extends React.Component<IProps, IState>
|
|||
onError={this.onError}
|
||||
interactive
|
||||
className="mx_LocationViewDialog_map"
|
||||
allowGeolocate={true}
|
||||
>
|
||||
{({ map }) => (
|
||||
<>
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { ReactNode, useContext, useEffect } from "react";
|
||||
import React, { ReactNode, useContext, useEffect, useState } from "react";
|
||||
import classNames from "classnames";
|
||||
import * as maplibregl from "maplibre-gl";
|
||||
import { ClientEvent, IClientWellKnown } from "matrix-js-sdk/src/matrix";
|
||||
|
@ -22,10 +22,13 @@ import { logger } from "matrix-js-sdk/src/logger";
|
|||
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import { useEventEmitterState } from "../../../hooks/useEventEmitter";
|
||||
import { parseGeoUri } from "../../../utils/location";
|
||||
import { parseGeoUri, positionFailureMessage } from "../../../utils/location";
|
||||
import { tileServerFromWellKnown } from "../../../utils/WellKnownUtils";
|
||||
import { useMap } from "../../../utils/location/useMap";
|
||||
import { Bounds } from "../../../utils/beacon/bounds";
|
||||
import Modal from "../../../Modal";
|
||||
import ErrorDialog from "../dialogs/ErrorDialog";
|
||||
import { _t } from "../../../languageHandler";
|
||||
|
||||
const useMapWithStyle = ({
|
||||
id,
|
||||
|
@ -33,12 +36,14 @@ const useMapWithStyle = ({
|
|||
onError,
|
||||
interactive,
|
||||
bounds,
|
||||
allowGeolocate,
|
||||
}: {
|
||||
id: string;
|
||||
centerGeoUri?: string;
|
||||
onError(error: Error): void;
|
||||
interactive?: boolean;
|
||||
bounds?: Bounds;
|
||||
onError(error: Error): void;
|
||||
allowGeolocate: boolean;
|
||||
}): {
|
||||
map: maplibregl.Map;
|
||||
bodyId: string;
|
||||
|
@ -86,12 +91,41 @@ const useMapWithStyle = ({
|
|||
}
|
||||
}, [map, bounds]);
|
||||
|
||||
const [geolocate] = useState(
|
||||
allowGeolocate
|
||||
? new maplibregl.GeolocateControl({
|
||||
positionOptions: {
|
||||
enableHighAccuracy: true,
|
||||
},
|
||||
trackUserLocation: false,
|
||||
})
|
||||
: null,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (map && geolocate) {
|
||||
map.addControl(geolocate);
|
||||
geolocate.on("error", onGeolocateError);
|
||||
return () => {
|
||||
geolocate.off("error", onGeolocateError);
|
||||
};
|
||||
}
|
||||
}, [map, geolocate]);
|
||||
|
||||
return {
|
||||
map,
|
||||
bodyId,
|
||||
};
|
||||
};
|
||||
|
||||
const onGeolocateError = (e: GeolocationPositionError): void => {
|
||||
logger.error("Could not fetch location", e);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: _t("Could not fetch location"),
|
||||
description: positionFailureMessage(e.code),
|
||||
});
|
||||
};
|
||||
|
||||
interface MapProps {
|
||||
id: string;
|
||||
interactive?: boolean;
|
||||
|
@ -105,13 +139,24 @@ interface MapProps {
|
|||
centerGeoUri?: string;
|
||||
bounds?: Bounds;
|
||||
className?: string;
|
||||
allowGeolocate?: boolean;
|
||||
onClick?: () => void;
|
||||
onError?: (error: Error) => void;
|
||||
children?: (renderProps: { map: maplibregl.Map }) => ReactNode;
|
||||
}
|
||||
|
||||
const Map: React.FC<MapProps> = ({ bounds, centerGeoUri, children, className, id, interactive, onError, onClick }) => {
|
||||
const { map, bodyId } = useMapWithStyle({ centerGeoUri, onError, id, interactive, bounds });
|
||||
const Map: React.FC<MapProps> = ({
|
||||
bounds,
|
||||
centerGeoUri,
|
||||
children,
|
||||
className,
|
||||
allowGeolocate,
|
||||
id,
|
||||
interactive,
|
||||
onError,
|
||||
onClick,
|
||||
}) => {
|
||||
const { map, bodyId } = useMapWithStyle({ centerGeoUri, onError, id, interactive, bounds, allowGeolocate });
|
||||
|
||||
const onMapClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>): void => {
|
||||
// Eat click events when clicking the attribution button
|
||||
|
|
|
@ -20,3 +20,4 @@ export * from "./locationEventGeoUri";
|
|||
export * from "./LocationShareErrors";
|
||||
export * from "./map";
|
||||
export * from "./parseGeoUri";
|
||||
export * from "./positionFailureMessage";
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { _t } from "../../languageHandler";
|
||||
import SdkConfig from "../../SdkConfig";
|
||||
|
||||
export const positionFailureMessage = (code: number): string => {
|
||||
const brand = SdkConfig.get().brand;
|
||||
switch (code) {
|
||||
case 1:
|
||||
return _t(
|
||||
"%(brand)s was denied permission to fetch your location. " +
|
||||
"Please allow location access in your browser settings.",
|
||||
{ brand },
|
||||
);
|
||||
case 2:
|
||||
return _t("Failed to fetch your location. Please try again later.");
|
||||
case 3:
|
||||
return _t("Timed out trying to fetch your location. Please try again later.");
|
||||
case 4:
|
||||
return _t("Unknown error fetching location. Please try again later.");
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue