Apply prettier formatting

This commit is contained in:
Michael Weimann 2022-12-12 12:24:14 +01:00
parent 1cac306093
commit 526645c791
No known key found for this signature in database
GPG key ID: 53F535A266BB9584
1576 changed files with 65385 additions and 62478 deletions

View file

@ -14,20 +14,20 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { HTMLProps, useContext } from 'react';
import { Beacon, BeaconEvent } from 'matrix-js-sdk/src/matrix';
import { LocationAssetType } from 'matrix-js-sdk/src/@types/location';
import React, { HTMLProps, useContext } from "react";
import { Beacon, BeaconEvent } from "matrix-js-sdk/src/matrix";
import { LocationAssetType } from "matrix-js-sdk/src/@types/location";
import MatrixClientContext from '../../../contexts/MatrixClientContext';
import { useEventEmitterState } from '../../../hooks/useEventEmitter';
import { humanizeTime } from '../../../utils/humanize';
import { preventDefaultWrapper } from '../../../utils/NativeEventUtils';
import { _t } from '../../../languageHandler';
import MemberAvatar from '../avatars/MemberAvatar';
import BeaconStatus from './BeaconStatus';
import { BeaconDisplayStatus } from './displayStatus';
import StyledLiveBeaconIcon from './StyledLiveBeaconIcon';
import ShareLatestLocation from './ShareLatestLocation';
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import { useEventEmitterState } from "../../../hooks/useEventEmitter";
import { humanizeTime } from "../../../utils/humanize";
import { preventDefaultWrapper } from "../../../utils/NativeEventUtils";
import { _t } from "../../../languageHandler";
import MemberAvatar from "../avatars/MemberAvatar";
import BeaconStatus from "./BeaconStatus";
import { BeaconDisplayStatus } from "./displayStatus";
import StyledLiveBeaconIcon from "./StyledLiveBeaconIcon";
import ShareLatestLocation from "./ShareLatestLocation";
interface Props {
beacon: Beacon;
@ -47,38 +47,36 @@ const BeaconListItem: React.FC<Props & HTMLProps<HTMLLIElement>> = ({ beacon, ..
}
const isSelfLocation = beacon.beaconInfo.assetType === LocationAssetType.Self;
const beaconMember = isSelfLocation ?
room.getMember(beacon.beaconInfoOwner) :
undefined;
const beaconMember = isSelfLocation ? room.getMember(beacon.beaconInfoOwner) : undefined;
const humanizedUpdateTime = humanizeTime(latestLocationState.timestamp);
return <li className='mx_BeaconListItem' {...rest}>
{ isSelfLocation ?
<MemberAvatar
className='mx_BeaconListItem_avatar'
member={beaconMember}
height={32}
width={32}
/> :
<StyledLiveBeaconIcon className='mx_BeaconListItem_avatarIcon' />
}
<div className='mx_BeaconListItem_info'>
<BeaconStatus
className='mx_BeaconListItem_status'
beacon={beacon}
label={beaconMember?.name || beacon.beaconInfo.description || beacon.beaconInfoOwner}
displayStatus={BeaconDisplayStatus.Active}
>
{ /* eat events from interactive share buttons
so parent click handlers are not triggered */ }
<div className='mx_BeaconListItem_interactions' onClick={preventDefaultWrapper(() => {})}>
<ShareLatestLocation latestLocationState={latestLocationState} />
</div>
</BeaconStatus>
<span className='mx_BeaconListItem_lastUpdated'>{ _t("Updated %(humanizedUpdateTime)s", { humanizedUpdateTime }) }</span>
</div>
</li>;
return (
<li className="mx_BeaconListItem" {...rest}>
{isSelfLocation ? (
<MemberAvatar className="mx_BeaconListItem_avatar" member={beaconMember} height={32} width={32} />
) : (
<StyledLiveBeaconIcon className="mx_BeaconListItem_avatarIcon" />
)}
<div className="mx_BeaconListItem_info">
<BeaconStatus
className="mx_BeaconListItem_status"
beacon={beacon}
label={beaconMember?.name || beacon.beaconInfo.description || beacon.beaconInfoOwner}
displayStatus={BeaconDisplayStatus.Active}
>
{/* eat events from interactive share buttons
so parent click handlers are not triggered */}
<div className="mx_BeaconListItem_interactions" onClick={preventDefaultWrapper(() => {})}>
<ShareLatestLocation latestLocationState={latestLocationState} />
</div>
</BeaconStatus>
<span className="mx_BeaconListItem_lastUpdated">
{_t("Updated %(humanizedUpdateTime)s", { humanizedUpdateTime })}
</span>
</div>
</li>
);
};
export default BeaconListItem;

View file

@ -14,17 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { ReactNode, useContext } from 'react';
import maplibregl from 'maplibre-gl';
import {
Beacon,
BeaconEvent,
} from 'matrix-js-sdk/src/matrix';
import { LocationAssetType } from 'matrix-js-sdk/src/@types/location';
import React, { ReactNode, useContext } from "react";
import maplibregl from "maplibre-gl";
import { Beacon, BeaconEvent } from "matrix-js-sdk/src/matrix";
import { LocationAssetType } from "matrix-js-sdk/src/@types/location";
import MatrixClientContext from '../../../contexts/MatrixClientContext';
import { useEventEmitterState } from '../../../hooks/useEventEmitter';
import SmartMarker from '../location/SmartMarker';
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import { useEventEmitterState } from "../../../hooks/useEventEmitter";
import SmartMarker from "../location/SmartMarker";
interface Props {
map: maplibregl.Map;
@ -50,18 +47,19 @@ const BeaconMarker: React.FC<Props> = ({ map, beacon, tooltip }) => {
const geoUri = latestLocationState?.uri;
const markerRoomMember = beacon.beaconInfo.assetType === LocationAssetType.Self ?
room.getMember(beacon.beaconInfoOwner) :
undefined;
const markerRoomMember =
beacon.beaconInfo.assetType === LocationAssetType.Self ? room.getMember(beacon.beaconInfoOwner) : undefined;
return <SmartMarker
map={map}
id={beacon.identifier}
geoUri={geoUri}
roomMember={markerRoomMember}
tooltip={tooltip}
useMemberColor
/>;
return (
<SmartMarker
map={map}
id={beacon.identifier}
geoUri={geoUri}
roomMember={markerRoomMember}
tooltip={tooltip}
useMemberColor
/>
);
};
export default BeaconMarker;

View file

@ -14,16 +14,16 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { HTMLProps } from 'react';
import classNames from 'classnames';
import { Beacon } from 'matrix-js-sdk/src/matrix';
import React, { HTMLProps } from "react";
import classNames from "classnames";
import { Beacon } from "matrix-js-sdk/src/matrix";
import StyledLiveBeaconIcon from './StyledLiveBeaconIcon';
import { _t } from '../../../languageHandler';
import LiveTimeRemaining from './LiveTimeRemaining';
import { BeaconDisplayStatus } from './displayStatus';
import { getBeaconExpiryTimestamp } from '../../../utils/beacon';
import { formatTime } from '../../../DateUtils';
import StyledLiveBeaconIcon from "./StyledLiveBeaconIcon";
import { _t } from "../../../languageHandler";
import LiveTimeRemaining from "./LiveTimeRemaining";
import { BeaconDisplayStatus } from "./displayStatus";
import { getBeaconExpiryTimestamp } from "../../../utils/beacon";
import { formatTime } from "../../../DateUtils";
interface Props {
displayStatus: BeaconDisplayStatus;
@ -35,56 +35,56 @@ interface Props {
const BeaconExpiryTime: React.FC<{ beacon: Beacon }> = ({ beacon }) => {
const expiryTime = formatTime(new Date(getBeaconExpiryTimestamp(beacon)));
return <span className='mx_BeaconStatus_expiryTime'>{ _t('Live until %(expiryTime)s', { expiryTime }) }</span>;
return <span className="mx_BeaconStatus_expiryTime">{_t("Live until %(expiryTime)s", { expiryTime })}</span>;
};
const BeaconStatus: React.FC<Props & HTMLProps<HTMLDivElement>> =
({
beacon,
displayStatus,
displayLiveTimeRemaining,
label,
className,
children,
withIcon,
...rest
}) => {
const isIdle = displayStatus === BeaconDisplayStatus.Loading ||
displayStatus === BeaconDisplayStatus.Stopped;
const BeaconStatus: React.FC<Props & HTMLProps<HTMLDivElement>> = ({
beacon,
displayStatus,
displayLiveTimeRemaining,
label,
className,
children,
withIcon,
...rest
}) => {
const isIdle = displayStatus === BeaconDisplayStatus.Loading || displayStatus === BeaconDisplayStatus.Stopped;
return <div
{...rest}
className={classNames('mx_BeaconStatus', `mx_BeaconStatus_${displayStatus}`, className)}
>
{ withIcon && <StyledLiveBeaconIcon
className='mx_BeaconStatus_icon'
withError={displayStatus === BeaconDisplayStatus.Error}
isIdle={isIdle}
/> }
<div className='mx_BeaconStatus_description'>
{ displayStatus === BeaconDisplayStatus.Loading &&
<span className="mx_BeaconStatus_description_status">{ _t('Loading live location...') }</span>
}
{ displayStatus === BeaconDisplayStatus.Stopped &&
<span className="mx_BeaconStatus_description_status">{ _t('Live location ended') }</span>
}
{ displayStatus === BeaconDisplayStatus.Error &&
<span className="mx_BeaconStatus_description_status">{ _t('Live location error') }</span>
}
{ displayStatus === BeaconDisplayStatus.Active && beacon && <>
return (
<div {...rest} className={classNames("mx_BeaconStatus", `mx_BeaconStatus_${displayStatus}`, className)}>
{withIcon && (
<StyledLiveBeaconIcon
className="mx_BeaconStatus_icon"
withError={displayStatus === BeaconDisplayStatus.Error}
isIdle={isIdle}
/>
)}
<div className="mx_BeaconStatus_description">
{displayStatus === BeaconDisplayStatus.Loading && (
<span className="mx_BeaconStatus_description_status">{_t("Loading live location...")}</span>
)}
{displayStatus === BeaconDisplayStatus.Stopped && (
<span className="mx_BeaconStatus_description_status">{_t("Live location ended")}</span>
)}
{displayStatus === BeaconDisplayStatus.Error && (
<span className="mx_BeaconStatus_description_status">{_t("Live location error")}</span>
)}
{displayStatus === BeaconDisplayStatus.Active && beacon && (
<>
<span className='mx_BeaconStatus_label'>{ label }</span>
{ displayLiveTimeRemaining ?
<LiveTimeRemaining beacon={beacon} /> :
<BeaconExpiryTime beacon={beacon} />
}
<>
<span className="mx_BeaconStatus_label">{label}</span>
{displayLiveTimeRemaining ? (
<LiveTimeRemaining beacon={beacon} />
) : (
<BeaconExpiryTime beacon={beacon} />
)}
</>
</>
</>
}
)}
</div>
{ children }
</div>;
};
{children}
</div>
);
};
export default BeaconStatus;

View file

@ -14,14 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { useContext } from 'react';
import { Beacon } from 'matrix-js-sdk/src/matrix';
import { LocationAssetType } from 'matrix-js-sdk/src/@types/location';
import React, { useContext } from "react";
import { Beacon } from "matrix-js-sdk/src/matrix";
import { LocationAssetType } from "matrix-js-sdk/src/@types/location";
import MatrixClientContext from '../../../contexts/MatrixClientContext';
import BeaconStatus from './BeaconStatus';
import { BeaconDisplayStatus } from './displayStatus';
import ShareLatestLocation from './ShareLatestLocation';
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import BeaconStatus from "./BeaconStatus";
import { BeaconDisplayStatus } from "./displayStatus";
import ShareLatestLocation from "./ShareLatestLocation";
interface Props {
beacon: Beacon;
@ -42,17 +42,19 @@ const useBeaconName = (beacon: Beacon): string => {
const BeaconStatusTooltip: React.FC<Props> = ({ beacon }) => {
const label = useBeaconName(beacon);
return <div className='mx_BeaconStatusTooltip'>
<BeaconStatus
beacon={beacon}
label={label}
displayStatus={BeaconDisplayStatus.Active}
displayLiveTimeRemaining
className='mx_BeaconStatusTooltip_inner'
>
<ShareLatestLocation latestLocationState={beacon.latestLocationState} />
</BeaconStatus>
</div>;
return (
<div className="mx_BeaconStatusTooltip">
<BeaconStatus
beacon={beacon}
label={label}
displayStatus={BeaconDisplayStatus.Active}
displayLiveTimeRemaining
className="mx_BeaconStatusTooltip_inner"
>
<ShareLatestLocation latestLocationState={beacon.latestLocationState} />
</BeaconStatus>
</div>
);
};
export default BeaconStatusTooltip;

View file

@ -14,35 +14,32 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { useState, useEffect } from 'react';
import { MatrixClient } from 'matrix-js-sdk/src/client';
import {
Beacon,
Room,
} from 'matrix-js-sdk/src/matrix';
import maplibregl from 'maplibre-gl';
import React, { useState, useEffect } from "react";
import { MatrixClient } from "matrix-js-sdk/src/client";
import { Beacon, Room } from "matrix-js-sdk/src/matrix";
import maplibregl from "maplibre-gl";
import { Icon as LiveLocationIcon } from '../../../../res/img/location/live-location.svg';
import { useLiveBeacons } from '../../../utils/beacon/useLiveBeacons';
import MatrixClientContext from '../../../contexts/MatrixClientContext';
import { Icon as LiveLocationIcon } from "../../../../res/img/location/live-location.svg";
import { useLiveBeacons } from "../../../utils/beacon/useLiveBeacons";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import BaseDialog from "../dialogs/BaseDialog";
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 { _t } from '../../../languageHandler';
import AccessibleButton from '../elements/AccessibleButton';
import DialogSidebar from './DialogSidebar';
import DialogOwnBeaconStatus from './DialogOwnBeaconStatus';
import BeaconStatusTooltip from './BeaconStatusTooltip';
import MapFallback from '../location/MapFallback';
import { MapError } from '../location/MapError';
import { LocationShareError } from '../../../utils/location';
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 { _t } from "../../../languageHandler";
import AccessibleButton from "../elements/AccessibleButton";
import DialogSidebar from "./DialogSidebar";
import DialogOwnBeaconStatus from "./DialogOwnBeaconStatus";
import BeaconStatusTooltip from "./BeaconStatusTooltip";
import MapFallback from "../location/MapFallback";
import { MapError } from "../location/MapError";
import { LocationShareError } from "../../../utils/location";
interface IProps extends IDialogProps {
roomId: Room['roomId'];
roomId: Room["roomId"];
matrixClient: MatrixClient;
// open the map centered on this beacon's location
initialFocusedBeacon?: Beacon;
@ -68,13 +65,16 @@ const getBoundsCenter = (bounds: Bounds): string | undefined => {
});
};
const useMapPosition = (liveBeacons: Beacon[], { beacon, ts }: FocusedBeaconState): {
bounds?: Bounds; centerGeoUri: string;
const useMapPosition = (
liveBeacons: Beacon[],
{ beacon, ts }: FocusedBeaconState,
): {
bounds?: Bounds;
centerGeoUri: string;
} => {
const [bounds, setBounds] = useState<Bounds | undefined>(getBeaconBounds(liveBeacons));
const [centerGeoUri, setCenterGeoUri] = useState<string>(
beacon?.latestLocationState?.uri ||
getBoundsCenter(bounds),
beacon?.latestLocationState?.uri || getBoundsCenter(bounds),
);
useEffect(() => {
@ -101,15 +101,12 @@ const useMapPosition = (liveBeacons: Beacon[], { beacon, ts }: FocusedBeaconStat
/**
* Dialog to view live beacons maximised
*/
const BeaconViewDialog: React.FC<IProps> = ({
initialFocusedBeacon,
roomId,
matrixClient,
onFinished,
}) => {
const BeaconViewDialog: React.FC<IProps> = ({ initialFocusedBeacon, roomId, matrixClient, onFinished }) => {
const liveBeacons = useLiveBeacons(roomId, matrixClient);
const [focusedBeaconState, setFocusedBeaconState] =
useState<FocusedBeaconState>({ beacon: initialFocusedBeacon, ts: 0 });
const [focusedBeaconState, setFocusedBeaconState] = useState<FocusedBeaconState>({
beacon: initialFocusedBeacon,
ts: 0,
});
const [isSidebarOpen, setSidebarOpen] = useState(false);
@ -129,66 +126,63 @@ const BeaconViewDialog: React.FC<IProps> = ({
};
return (
<BaseDialog
className='mx_BeaconViewDialog'
onFinished={onFinished}
fixedWidth={false}
>
<BaseDialog className="mx_BeaconViewDialog" onFinished={onFinished} fixedWidth={false}>
<MatrixClientContext.Provider value={matrixClient}>
{ (centerGeoUri && !mapDisplayError) && <Map
id='mx_BeaconViewDialog'
bounds={bounds}
centerGeoUri={centerGeoUri}
interactive
onError={setMapDisplayError}
className="mx_BeaconViewDialog_map"
>
{
({ map }: { map: maplibregl.Map}) =>
{centerGeoUri && !mapDisplayError && (
<Map
id="mx_BeaconViewDialog"
bounds={bounds}
centerGeoUri={centerGeoUri}
interactive
onError={setMapDisplayError}
className="mx_BeaconViewDialog_map"
>
{({ map }: { map: maplibregl.Map }) => (
<>
{ liveBeacons.map(beacon => <BeaconMarker
key={beacon.identifier}
map={map}
beacon={beacon}
tooltip={<BeaconStatusTooltip beacon={beacon} />}
/>) }
{liveBeacons.map((beacon) => (
<BeaconMarker
key={beacon.identifier}
map={map}
beacon={beacon}
tooltip={<BeaconStatusTooltip beacon={beacon} />}
/>
))}
<ZoomButtons map={map} />
</>
}
</Map> }
{ mapDisplayError &&
<MapError
error={mapDisplayError.message as LocationShareError}
isMinimised
/>
}
{ !centerGeoUri && !mapDisplayError &&
<MapFallback
data-test-id='beacon-view-dialog-map-fallback'
className='mx_BeaconViewDialog_map'
>
<span className='mx_BeaconViewDialog_mapFallbackMessage'>{ _t('No live locations') }</span>
)}
</Map>
)}
{mapDisplayError && <MapError error={mapDisplayError.message as LocationShareError} isMinimised />}
{!centerGeoUri && !mapDisplayError && (
<MapFallback data-test-id="beacon-view-dialog-map-fallback" className="mx_BeaconViewDialog_map">
<span className="mx_BeaconViewDialog_mapFallbackMessage">{_t("No live locations")}</span>
<AccessibleButton
kind='primary'
kind="primary"
onClick={onFinished}
data-test-id='beacon-view-dialog-fallback-close'
data-test-id="beacon-view-dialog-fallback-close"
>
{ _t('Close') }
{_t("Close")}
</AccessibleButton>
</MapFallback>
}
{ isSidebarOpen ?
<DialogSidebar beacons={liveBeacons} onBeaconClick={onBeaconListItemClick} requestClose={() => setSidebarOpen(false)} /> :
)}
{isSidebarOpen ? (
<DialogSidebar
beacons={liveBeacons}
onBeaconClick={onBeaconListItemClick}
requestClose={() => setSidebarOpen(false)}
/>
) : (
<AccessibleButton
kind='primary'
kind="primary"
onClick={() => setSidebarOpen(true)}
data-test-id='beacon-view-dialog-open-sidebar'
className='mx_BeaconViewDialog_viewListButton'
data-test-id="beacon-view-dialog-open-sidebar"
className="mx_BeaconViewDialog_viewListButton"
>
<LiveLocationIcon height={12} />&nbsp;
{ _t('View list') }
<LiveLocationIcon height={12} />
&nbsp;
{_t("View list")}
</AccessibleButton>
}
)}
<DialogOwnBeaconStatus roomId={roomId} />
</MatrixClientContext.Provider>
</BaseDialog>

View file

@ -14,31 +14,27 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { useContext } from 'react';
import { Room, Beacon } from 'matrix-js-sdk/src/matrix';
import { LocationAssetType } from 'matrix-js-sdk/src/@types/location';
import React, { useContext } from "react";
import { Room, Beacon } from "matrix-js-sdk/src/matrix";
import { LocationAssetType } from "matrix-js-sdk/src/@types/location";
import { OwnBeaconStore, OwnBeaconStoreEvent } from '../../../stores/OwnBeaconStore';
import { useEventEmitterState } from '../../../hooks/useEventEmitter';
import OwnBeaconStatus from './OwnBeaconStatus';
import { BeaconDisplayStatus } from './displayStatus';
import MatrixClientContext from '../../../contexts/MatrixClientContext';
import MemberAvatar from '../avatars/MemberAvatar';
import StyledLiveBeaconIcon from './StyledLiveBeaconIcon';
import { OwnBeaconStore, OwnBeaconStoreEvent } from "../../../stores/OwnBeaconStore";
import { useEventEmitterState } from "../../../hooks/useEventEmitter";
import OwnBeaconStatus from "./OwnBeaconStatus";
import { BeaconDisplayStatus } from "./displayStatus";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import MemberAvatar from "../avatars/MemberAvatar";
import StyledLiveBeaconIcon from "./StyledLiveBeaconIcon";
interface Props {
roomId: Room['roomId'];
roomId: Room["roomId"];
}
const useOwnBeacon = (roomId: Room['roomId']): Beacon | undefined => {
const ownBeacon = useEventEmitterState(
OwnBeaconStore.instance,
OwnBeaconStoreEvent.LivenessChange,
() => {
const [ownBeaconId] = OwnBeaconStore.instance.getLiveBeaconIds(roomId);
return OwnBeaconStore.instance.getBeaconById(ownBeaconId);
},
);
const useOwnBeacon = (roomId: Room["roomId"]): Beacon | undefined => {
const ownBeacon = useEventEmitterState(OwnBeaconStore.instance, OwnBeaconStoreEvent.LivenessChange, () => {
const [ownBeaconId] = OwnBeaconStore.instance.getLiveBeaconIds(roomId);
return OwnBeaconStore.instance.getBeaconById(ownBeaconId);
});
return ownBeacon;
};
@ -54,26 +50,27 @@ const DialogOwnBeaconStatus: React.FC<Props> = ({ roomId }) => {
}
const isSelfLocation = beacon.beaconInfo.assetType === LocationAssetType.Self;
const beaconMember = isSelfLocation ?
room.getMember(beacon.beaconInfoOwner) :
undefined;
const beaconMember = isSelfLocation ? room.getMember(beacon.beaconInfoOwner) : undefined;
return <div className='mx_DialogOwnBeaconStatus'>
{ isSelfLocation ?
<MemberAvatar
className='mx_DialogOwnBeaconStatus_avatar'
member={beaconMember}
height={32}
width={32}
/> :
<StyledLiveBeaconIcon className='mx_DialogOwnBeaconStatus_avatarIcon' />
}
<OwnBeaconStatus
className='mx_DialogOwnBeaconStatus_status'
beacon={beacon}
displayStatus={BeaconDisplayStatus.Active}
/>
</div>;
return (
<div className="mx_DialogOwnBeaconStatus">
{isSelfLocation ? (
<MemberAvatar
className="mx_DialogOwnBeaconStatus_avatar"
member={beaconMember}
height={32}
width={32}
/>
) : (
<StyledLiveBeaconIcon className="mx_DialogOwnBeaconStatus_avatarIcon" />
)}
<OwnBeaconStatus
className="mx_DialogOwnBeaconStatus_status"
beacon={beacon}
displayStatus={BeaconDisplayStatus.Active}
/>
</div>
);
};
export default DialogOwnBeaconStatus;

View file

@ -14,14 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import { Beacon } from 'matrix-js-sdk/src/matrix';
import React from "react";
import { Beacon } from "matrix-js-sdk/src/matrix";
import { Icon as CloseIcon } from '../../../../res/img/image-view/close.svg';
import { _t } from '../../../languageHandler';
import AccessibleButton from '../elements/AccessibleButton';
import Heading from '../typography/Heading';
import BeaconListItem from './BeaconListItem';
import { Icon as CloseIcon } from "../../../../res/img/image-view/close.svg";
import { _t } from "../../../languageHandler";
import AccessibleButton from "../elements/AccessibleButton";
import Heading from "../typography/Heading";
import BeaconListItem from "./BeaconListItem";
interface Props {
beacons: Beacon[];
@ -29,36 +29,31 @@ interface Props {
onBeaconClick: (beacon: Beacon) => void;
}
const DialogSidebar: React.FC<Props> = ({
beacons,
onBeaconClick,
requestClose,
}) => {
return <div className='mx_DialogSidebar'>
<div className='mx_DialogSidebar_header'>
<Heading size='h4'>{ _t('View List') }</Heading>
<AccessibleButton
className='mx_DialogSidebar_closeButton'
onClick={requestClose}
title={_t('Close sidebar')}
data-testid='dialog-sidebar-close'
>
<CloseIcon className='mx_DialogSidebar_closeButtonIcon' />
</AccessibleButton>
</div>
{ beacons?.length
? <ol className='mx_DialogSidebar_list'>
{ beacons.map((beacon) => <BeaconListItem
key={beacon.identifier}
beacon={beacon}
onClick={() => onBeaconClick(beacon)}
/>) }
</ol>
: <div className='mx_DialogSidebar_noResults'>
{ _t('No live locations') }
const DialogSidebar: React.FC<Props> = ({ beacons, onBeaconClick, requestClose }) => {
return (
<div className="mx_DialogSidebar">
<div className="mx_DialogSidebar_header">
<Heading size="h4">{_t("View List")}</Heading>
<AccessibleButton
className="mx_DialogSidebar_closeButton"
onClick={requestClose}
title={_t("Close sidebar")}
data-testid="dialog-sidebar-close"
>
<CloseIcon className="mx_DialogSidebar_closeButtonIcon" />
</AccessibleButton>
</div>
}
</div>;
{beacons?.length ? (
<ol className="mx_DialogSidebar_list">
{beacons.map((beacon) => (
<BeaconListItem key={beacon.identifier} beacon={beacon} onClick={() => onBeaconClick(beacon)} />
))}
</ol>
) : (
<div className="mx_DialogSidebar_noResults">{_t("No live locations")}</div>
)}
</div>
);
};
export default DialogSidebar;

View file

@ -14,18 +14,18 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import classNames from 'classnames';
import React, { useEffect } from 'react';
import { Beacon, BeaconIdentifier } from 'matrix-js-sdk/src/matrix';
import classNames from "classnames";
import React, { useEffect } from "react";
import { Beacon, BeaconIdentifier } from "matrix-js-sdk/src/matrix";
import { useEventEmitterState } from '../../../hooks/useEventEmitter';
import { _t } from '../../../languageHandler';
import { OwnBeaconStore, OwnBeaconStoreEvent } from '../../../stores/OwnBeaconStore';
import { Icon as LiveLocationIcon } from '../../../../res/img/location/live-location.svg';
import { ViewRoomPayload } from '../../../dispatcher/payloads/ViewRoomPayload';
import { Action } from '../../../dispatcher/actions';
import dispatcher from '../../../dispatcher/dispatcher';
import AccessibleButton from '../elements/AccessibleButton';
import { useEventEmitterState } from "../../../hooks/useEventEmitter";
import { _t } from "../../../languageHandler";
import { OwnBeaconStore, OwnBeaconStoreEvent } from "../../../stores/OwnBeaconStore";
import { Icon as LiveLocationIcon } from "../../../../res/img/location/live-location.svg";
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
import { Action } from "../../../dispatcher/actions";
import dispatcher from "../../../dispatcher/dispatcher";
import AccessibleButton from "../elements/AccessibleButton";
interface Props {
isMinimized?: boolean;
@ -52,12 +52,12 @@ const chooseBestBeacon = (
const getLabel = (hasStoppingErrors: boolean, hasLocationErrors: boolean): string => {
if (hasStoppingErrors) {
return _t('An error occurred while stopping your live location');
return _t("An error occurred while stopping your live location");
}
if (hasLocationErrors) {
return _t('An error occurred whilst sharing your live location');
return _t("An error occurred whilst sharing your live location");
}
return _t('You are sharing your live location');
return _t("You are sharing your live location");
};
const useLivenessMonitor = (liveBeaconIds: BeaconIdentifier[], beacons: Map<BeaconIdentifier, Beacon>): void => {
@ -66,8 +66,8 @@ const useLivenessMonitor = (liveBeaconIds: BeaconIdentifier[], beacons: Map<Beac
// for inactive tabs
// refresh beacon monitors when the tab becomes active again
const onPageVisibilityChanged = () => {
if (document.visibilityState === 'visible') {
liveBeaconIds.forEach(identifier => beacons.get(identifier)?.monitorLiveness());
if (document.visibilityState === "visible") {
liveBeaconIds.forEach((identifier) => beacons.get(identifier)?.monitorLiveness());
}
};
if (liveBeaconIds.length) {
@ -95,15 +95,14 @@ const LeftPanelLiveShareWarning: React.FC<Props> = ({ isMinimized }) => {
const beaconIdsWithStoppingError = useEventEmitterState(
OwnBeaconStore.instance,
OwnBeaconStoreEvent.BeaconUpdateError,
() => OwnBeaconStore.instance.getLiveBeaconIds().filter(
beaconId => OwnBeaconStore.instance.beaconUpdateErrors.has(beaconId),
),
() =>
OwnBeaconStore.instance
.getLiveBeaconIds()
.filter((beaconId) => OwnBeaconStore.instance.beaconUpdateErrors.has(beaconId)),
);
const liveBeaconIds = useEventEmitterState(
OwnBeaconStore.instance,
OwnBeaconStoreEvent.LivenessChange,
() => OwnBeaconStore.instance.getLiveBeaconIds(),
const liveBeaconIds = useEventEmitterState(OwnBeaconStore.instance, OwnBeaconStoreEvent.LivenessChange, () =>
OwnBeaconStore.instance.getLiveBeaconIds(),
);
const hasLocationPublishErrors = !!beaconIdsWithLocationPublishError.length;
@ -116,32 +115,38 @@ const LeftPanelLiveShareWarning: React.FC<Props> = ({ isMinimized }) => {
}
const relevantBeacon = chooseBestBeacon(
liveBeaconIds, beaconIdsWithStoppingError, beaconIdsWithLocationPublishError,
liveBeaconIds,
beaconIdsWithStoppingError,
beaconIdsWithLocationPublishError,
);
const onWarningClick = relevantBeacon ? () => {
dispatcher.dispatch<ViewRoomPayload>({
action: Action.ViewRoom,
room_id: relevantBeacon.roomId,
metricsTrigger: undefined,
event_id: relevantBeacon.beaconInfoId,
scroll_into_view: true,
highlighted: true,
});
} : undefined;
const onWarningClick = relevantBeacon
? () => {
dispatcher.dispatch<ViewRoomPayload>({
action: Action.ViewRoom,
room_id: relevantBeacon.roomId,
metricsTrigger: undefined,
event_id: relevantBeacon.beaconInfoId,
scroll_into_view: true,
highlighted: true,
});
}
: undefined;
const label = getLabel(hasStoppingErrors, hasLocationPublishErrors);
return <AccessibleButton
className={classNames('mx_LeftPanelLiveShareWarning', {
'mx_LeftPanelLiveShareWarning__minimized': isMinimized,
'mx_LeftPanelLiveShareWarning__error': hasLocationPublishErrors || hasStoppingErrors,
})}
title={isMinimized ? label : undefined}
onClick={onWarningClick}
>
{ isMinimized ? <LiveLocationIcon height={10} /> : label }
</AccessibleButton>;
return (
<AccessibleButton
className={classNames("mx_LeftPanelLiveShareWarning", {
mx_LeftPanelLiveShareWarning__minimized: isMinimized,
mx_LeftPanelLiveShareWarning__error: hasLocationPublishErrors || hasStoppingErrors,
})}
title={isMinimized ? label : undefined}
onClick={onWarningClick}
>
{isMinimized ? <LiveLocationIcon height={10} /> : label}
</AccessibleButton>
);
};
export default LeftPanelLiveShareWarning;

View file

@ -14,14 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { useCallback, useEffect, useState } from 'react';
import { BeaconEvent, Beacon } from 'matrix-js-sdk/src/matrix';
import React, { useCallback, useEffect, useState } from "react";
import { BeaconEvent, Beacon } from "matrix-js-sdk/src/matrix";
import { formatDuration } from '../../../DateUtils';
import { useEventEmitterState } from '../../../hooks/useEventEmitter';
import { useInterval } from '../../../hooks/useTimeout';
import { _t } from '../../../languageHandler';
import { getBeaconMsUntilExpiry } from '../../../utils/beacon';
import { formatDuration } from "../../../DateUtils";
import { useEventEmitterState } from "../../../hooks/useEventEmitter";
import { useInterval } from "../../../hooks/useTimeout";
import { _t } from "../../../languageHandler";
import { getBeaconMsUntilExpiry } from "../../../utils/beacon";
const MINUTE_MS = 60000;
const HOUR_MS = MINUTE_MS * 60;
@ -38,11 +38,7 @@ const getUpdateInterval = (ms: number) => {
return 1000;
};
const useMsRemaining = (beacon: Beacon): number => {
const beaconInfo = useEventEmitterState(
beacon,
BeaconEvent.Update,
() => beacon.beaconInfo,
);
const beaconInfo = useEventEmitterState(beacon, BeaconEvent.Update, () => beacon.beaconInfo);
const [msRemaining, setMsRemaining] = useState(() => getBeaconMsUntilExpiry(beaconInfo));
@ -66,10 +62,11 @@ const LiveTimeRemaining: React.FC<{ beacon: Beacon }> = ({ beacon }) => {
const timeRemaining = formatDuration(msRemaining);
const liveTimeRemaining = _t(`%(timeRemaining)s left`, { timeRemaining });
return <span
data-test-id='room-live-share-expiry'
className="mx_LiveTimeRemaining"
>{ liveTimeRemaining }</span>;
return (
<span data-test-id="room-live-share-expiry" className="mx_LiveTimeRemaining">
{liveTimeRemaining}
</span>
);
};
export default LiveTimeRemaining;

View file

@ -14,15 +14,15 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import { Beacon } from 'matrix-js-sdk/src/matrix';
import React, { HTMLProps } from 'react';
import { Beacon } from "matrix-js-sdk/src/matrix";
import React, { HTMLProps } from "react";
import { _t } from '../../../languageHandler';
import { useOwnLiveBeacons } from '../../../utils/beacon';
import { preventDefaultWrapper } from '../../../utils/NativeEventUtils';
import BeaconStatus from './BeaconStatus';
import { BeaconDisplayStatus } from './displayStatus';
import AccessibleButton, { ButtonEvent } from '../elements/AccessibleButton';
import { _t } from "../../../languageHandler";
import { useOwnLiveBeacons } from "../../../utils/beacon";
import { preventDefaultWrapper } from "../../../utils/NativeEventUtils";
import BeaconStatus from "./BeaconStatus";
import { BeaconDisplayStatus } from "./displayStatus";
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
interface Props {
displayStatus: BeaconDisplayStatus;
@ -35,9 +35,7 @@ interface Props {
* Wraps BeaconStatus with more capabilities
* for errors and actions available for users own live beacons
*/
const OwnBeaconStatus: React.FC<Props & HTMLProps<HTMLDivElement>> = ({
beacon, displayStatus, ...rest
}) => {
const OwnBeaconStatus: React.FC<Props & HTMLProps<HTMLDivElement>> = ({ beacon, displayStatus, ...rest }) => {
const {
hasLocationPublishError,
hasStopSharingError,
@ -47,51 +45,55 @@ const OwnBeaconStatus: React.FC<Props & HTMLProps<HTMLDivElement>> = ({
} = useOwnLiveBeacons([beacon?.identifier]);
// combine display status with errors that only occur for user's own beacons
const ownDisplayStatus = hasLocationPublishError || hasStopSharingError ?
BeaconDisplayStatus.Error :
displayStatus;
const ownDisplayStatus = hasLocationPublishError || hasStopSharingError ? BeaconDisplayStatus.Error : displayStatus;
return <BeaconStatus
beacon={beacon}
displayStatus={ownDisplayStatus}
label={_t('Live location enabled')}
displayLiveTimeRemaining
{...rest}
>
{ ownDisplayStatus === BeaconDisplayStatus.Active && <AccessibleButton
data-test-id='beacon-status-stop-beacon'
kind='link'
// eat events here to avoid 1) the map and 2) reply or thread tiles
// moving under the beacon status on stop/retry click
onClick={preventDefaultWrapper<ButtonEvent>(onStopSharing)}
className='mx_OwnBeaconStatus_button mx_OwnBeaconStatus_destructiveButton'
disabled={stoppingInProgress}
return (
<BeaconStatus
beacon={beacon}
displayStatus={ownDisplayStatus}
label={_t("Live location enabled")}
displayLiveTimeRemaining
{...rest}
>
{ _t('Stop') }
</AccessibleButton>
}
{ hasLocationPublishError && <AccessibleButton
data-test-id='beacon-status-reset-wire-error'
kind='link'
// eat events here to avoid 1) the map and 2) reply or thread tiles
// moving under the beacon status on stop/retry click
onClick={preventDefaultWrapper(onResetLocationPublishError)}
className='mx_OwnBeaconStatus_button mx_OwnBeaconStatus_destructiveButton'
>
{ _t('Retry') }
</AccessibleButton>
}
{ hasStopSharingError && <AccessibleButton
data-test-id='beacon-status-stop-beacon-retry'
kind='link'
// eat events here to avoid 1) the map and 2) reply or thread tiles
// moving under the beacon status on stop/retry click
onClick={preventDefaultWrapper(onStopSharing)}
className='mx_OwnBeaconStatus_button mx_OwnBeaconStatus_destructiveButton'
>
{ _t('Retry') }
</AccessibleButton> }
</BeaconStatus>;
{ownDisplayStatus === BeaconDisplayStatus.Active && (
<AccessibleButton
data-test-id="beacon-status-stop-beacon"
kind="link"
// eat events here to avoid 1) the map and 2) reply or thread tiles
// moving under the beacon status on stop/retry click
onClick={preventDefaultWrapper<ButtonEvent>(onStopSharing)}
className="mx_OwnBeaconStatus_button mx_OwnBeaconStatus_destructiveButton"
disabled={stoppingInProgress}
>
{_t("Stop")}
</AccessibleButton>
)}
{hasLocationPublishError && (
<AccessibleButton
data-test-id="beacon-status-reset-wire-error"
kind="link"
// eat events here to avoid 1) the map and 2) reply or thread tiles
// moving under the beacon status on stop/retry click
onClick={preventDefaultWrapper(onResetLocationPublishError)}
className="mx_OwnBeaconStatus_button mx_OwnBeaconStatus_destructiveButton"
>
{_t("Retry")}
</AccessibleButton>
)}
{hasStopSharingError && (
<AccessibleButton
data-test-id="beacon-status-stop-beacon-retry"
kind="link"
// eat events here to avoid 1) the map and 2) reply or thread tiles
// moving under the beacon status on stop/retry click
onClick={preventDefaultWrapper(onStopSharing)}
className="mx_OwnBeaconStatus_button mx_OwnBeaconStatus_destructiveButton"
>
{_t("Retry")}
</AccessibleButton>
)}
</BeaconStatus>
);
};
export default OwnBeaconStatus;

View file

@ -27,10 +27,7 @@ import { Action } from "../../../dispatcher/actions";
import { ConnectionState, ElementCall } from "../../../models/Call";
import { useCall } from "../../../hooks/useCall";
import { useEventEmitterState } from "../../../hooks/useEventEmitter";
import {
OwnBeaconStore,
OwnBeaconStoreEvent,
} from "../../../stores/OwnBeaconStore";
import { OwnBeaconStore, OwnBeaconStoreEvent } from "../../../stores/OwnBeaconStore";
import { GroupCallDuration } from "../voip/CallDuration";
import { SdkContextClass } from "../../../contexts/SDKContext";
@ -39,10 +36,7 @@ interface RoomCallBannerProps {
call: ElementCall;
}
const RoomCallBannerInner: React.FC<RoomCallBannerProps> = ({
roomId,
call,
}) => {
const RoomCallBannerInner: React.FC<RoomCallBannerProps> = ({ roomId, call }) => {
const connect = useCallback(
(ev: ButtonEvent) => {
ev.preventDefault();
@ -58,7 +52,8 @@ const RoomCallBannerInner: React.FC<RoomCallBannerProps> = ({
const onClick = useCallback(() => {
const event = call.groupCall.room.currentState.getStateEvents(
EventType.GroupCallPrefix, call.groupCall.groupCallId,
EventType.GroupCallPrefix,
call.groupCall.groupCallId,
);
if (event === null) {
logger.error("Couldn't find a group call event to jump to");
@ -76,22 +71,14 @@ const RoomCallBannerInner: React.FC<RoomCallBannerProps> = ({
}, [call, roomId]);
return (
<div
className="mx_RoomCallBanner"
onClick={onClick}
>
<div className="mx_RoomCallBanner" onClick={onClick}>
<div className="mx_RoomCallBanner_text">
<span className="mx_RoomCallBanner_label">{ _t("Video call") }</span>
<span className="mx_RoomCallBanner_label">{_t("Video call")}</span>
<GroupCallDuration groupCall={call.groupCall} />
</div>
<AccessibleButton
onClick={connect}
kind="primary"
element="button"
disabled={false}
>
{ _t("Join") }
<AccessibleButton onClick={connect} kind="primary" element="button" disabled={false}>
{_t("Join")}
</AccessibleButton>
</div>
);
@ -111,10 +98,8 @@ const RoomCallBanner: React.FC<Props> = ({ roomId }) => {
() => OwnBeaconStore.instance.isMonitoringLiveLocation,
);
const liveBeaconIds = useEventEmitterState(
OwnBeaconStore.instance,
OwnBeaconStoreEvent.LivenessChange,
() => OwnBeaconStore.instance.getLiveBeaconIds(roomId),
const liveBeaconIds = useEventEmitterState(OwnBeaconStore.instance, OwnBeaconStoreEvent.LivenessChange, () =>
OwnBeaconStore.instance.getLiveBeaconIds(roomId),
);
if (isMonitoringLiveLocation && liveBeaconIds.length) {

View file

@ -14,35 +14,35 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import { Room } from 'matrix-js-sdk/src/matrix';
import React from "react";
import { Room } from "matrix-js-sdk/src/matrix";
import { _t } from '../../../languageHandler';
import { useEventEmitterState } from '../../../hooks/useEventEmitter';
import { OwnBeaconStore, OwnBeaconStoreEvent } from '../../../stores/OwnBeaconStore';
import { useOwnLiveBeacons } from '../../../utils/beacon';
import AccessibleButton, { ButtonEvent } from '../elements/AccessibleButton';
import Spinner from '../elements/Spinner';
import StyledLiveBeaconIcon from './StyledLiveBeaconIcon';
import { Icon as CloseIcon } from '../../../../res/img/image-view/close.svg';
import LiveTimeRemaining from './LiveTimeRemaining';
import dispatcher from '../../../dispatcher/dispatcher';
import { ViewRoomPayload } from '../../../dispatcher/payloads/ViewRoomPayload';
import { Action } from '../../../dispatcher/actions';
import { _t } from "../../../languageHandler";
import { useEventEmitterState } from "../../../hooks/useEventEmitter";
import { OwnBeaconStore, OwnBeaconStoreEvent } from "../../../stores/OwnBeaconStore";
import { useOwnLiveBeacons } from "../../../utils/beacon";
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
import Spinner from "../elements/Spinner";
import StyledLiveBeaconIcon from "./StyledLiveBeaconIcon";
import { Icon as CloseIcon } from "../../../../res/img/image-view/close.svg";
import LiveTimeRemaining from "./LiveTimeRemaining";
import dispatcher from "../../../dispatcher/dispatcher";
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
import { Action } from "../../../dispatcher/actions";
const getLabel = (hasLocationPublishError: boolean, hasStopSharingError: boolean): string => {
if (hasLocationPublishError) {
return _t('An error occurred whilst sharing your live location, please try again');
return _t("An error occurred whilst sharing your live location, please try again");
}
if (hasStopSharingError) {
return _t('An error occurred while stopping your live location, please try again');
return _t("An error occurred while stopping your live location, please try again");
}
return _t('You are sharing your live location');
return _t("You are sharing your live location");
};
interface RoomLiveShareWarningInnerProps {
liveBeaconIds: string[];
roomId: Room['roomId'];
roomId: Room["roomId"];
}
const RoomLiveShareWarningInner: React.FC<RoomLiveShareWarningInnerProps> = ({ liveBeaconIds, roomId }) => {
const {
@ -86,45 +86,48 @@ const RoomLiveShareWarningInner: React.FC<RoomLiveShareWarningInnerProps> = ({ l
});
};
return <div
className='mx_RoomLiveShareWarning'
onClick={onClick}
>
<StyledLiveBeaconIcon className="mx_RoomLiveShareWarning_icon" withError={hasError} />
return (
<div className="mx_RoomLiveShareWarning" onClick={onClick}>
<StyledLiveBeaconIcon className="mx_RoomLiveShareWarning_icon" withError={hasError} />
<span className="mx_RoomLiveShareWarning_label">
{ getLabel(hasLocationPublishError, hasStopSharingError) }
</span>
<span className="mx_RoomLiveShareWarning_label">
{getLabel(hasLocationPublishError, hasStopSharingError)}
</span>
{ stoppingInProgress &&
<span className='mx_RoomLiveShareWarning_spinner'><Spinner h={16} w={16} /></span>
}
{ !stoppingInProgress && !hasError && <LiveTimeRemaining beacon={beacon} /> }
{stoppingInProgress && (
<span className="mx_RoomLiveShareWarning_spinner">
<Spinner h={16} w={16} />
</span>
)}
{!stoppingInProgress && !hasError && <LiveTimeRemaining beacon={beacon} />}
<AccessibleButton
className='mx_RoomLiveShareWarning_stopButton'
data-test-id='room-live-share-primary-button'
onClick={stopPropagationWrapper(onButtonClick)}
kind='danger'
element='button'
disabled={stoppingInProgress}
>
{ hasError ? _t('Retry') : _t('Stop') }
</AccessibleButton>
{ hasLocationPublishError && <AccessibleButton
data-test-id='room-live-share-wire-error-close-button'
title={_t('Stop and close')}
element='button'
className='mx_RoomLiveShareWarning_closeButton'
onClick={stopPropagationWrapper(onStopSharing)}
>
<CloseIcon className='mx_RoomLiveShareWarning_closeButtonIcon' />
</AccessibleButton> }
</div>;
<AccessibleButton
className="mx_RoomLiveShareWarning_stopButton"
data-test-id="room-live-share-primary-button"
onClick={stopPropagationWrapper(onButtonClick)}
kind="danger"
element="button"
disabled={stoppingInProgress}
>
{hasError ? _t("Retry") : _t("Stop")}
</AccessibleButton>
{hasLocationPublishError && (
<AccessibleButton
data-test-id="room-live-share-wire-error-close-button"
title={_t("Stop and close")}
element="button"
className="mx_RoomLiveShareWarning_closeButton"
onClick={stopPropagationWrapper(onStopSharing)}
>
<CloseIcon className="mx_RoomLiveShareWarning_closeButtonIcon" />
</AccessibleButton>
)}
</div>
);
};
interface Props {
roomId: Room['roomId'];
roomId: Room["roomId"];
}
const RoomLiveShareWarning: React.FC<Props> = ({ roomId }) => {
// do we have an active geolocation.watchPosition
@ -134,10 +137,8 @@ const RoomLiveShareWarning: React.FC<Props> = ({ roomId }) => {
() => OwnBeaconStore.instance.isMonitoringLiveLocation,
);
const liveBeaconIds = useEventEmitterState(
OwnBeaconStore.instance,
OwnBeaconStoreEvent.LivenessChange,
() => OwnBeaconStore.instance.getLiveBeaconIds(roomId),
const liveBeaconIds = useEventEmitterState(OwnBeaconStore.instance, OwnBeaconStoreEvent.LivenessChange, () =>
OwnBeaconStore.instance.getLiveBeaconIds(roomId),
);
if (!isMonitoringLiveLocation || !liveBeaconIds.length) {

View file

@ -14,14 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { useEffect, useState } from 'react';
import { BeaconLocationState } from 'matrix-js-sdk/src/content-helpers';
import React, { useEffect, useState } from "react";
import { BeaconLocationState } from "matrix-js-sdk/src/content-helpers";
import { Icon as ExternalLinkIcon } from '../../../../res/img/external-link.svg';
import { _t } from '../../../languageHandler';
import { makeMapSiteLink, parseGeoUri } from '../../../utils/location';
import CopyableText from '../elements/CopyableText';
import TooltipTarget from '../elements/TooltipTarget';
import { Icon as ExternalLinkIcon } from "../../../../res/img/external-link.svg";
import { _t } from "../../../languageHandler";
import { makeMapSiteLink, parseGeoUri } from "../../../utils/location";
import CopyableText from "../elements/CopyableText";
import TooltipTarget from "../elements/TooltipTarget";
interface Props {
latestLocationState?: BeaconLocationState;
@ -44,23 +44,16 @@ const ShareLatestLocation: React.FC<Props> = ({ latestLocationState }) => {
const latLonString = `${coords.latitude},${coords.longitude}`;
const mapLink = makeMapSiteLink(coords);
return <>
<TooltipTarget label={_t('Open in OpenStreetMap')}>
<a
data-testid='open-location-in-osm'
href={mapLink}
target='_blank'
rel='noreferrer noopener'
>
<ExternalLinkIcon className='mx_ShareLatestLocation_icon' />
</a>
</TooltipTarget>
<CopyableText
className='mx_ShareLatestLocation_copy'
border={false}
getTextToCopy={() => latLonString}
/>
</>;
return (
<>
<TooltipTarget label={_t("Open in OpenStreetMap")}>
<a data-testid="open-location-in-osm" href={mapLink} target="_blank" rel="noreferrer noopener">
<ExternalLinkIcon className="mx_ShareLatestLocation_icon" />
</a>
</TooltipTarget>
<CopyableText className="mx_ShareLatestLocation_copy" border={false} getTextToCopy={() => latLonString} />
</>
);
};
export default ShareLatestLocation;

View file

@ -14,27 +14,24 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import classNames from 'classnames';
import React from "react";
import classNames from "classnames";
import { Icon as LiveLocationIcon } from '../../../../res/img/location/live-location.svg';
import { Icon as LiveLocationIcon } from "../../../../res/img/location/live-location.svg";
interface Props extends React.SVGProps<SVGSVGElement> {
// use error styling when true
withError?: boolean;
isIdle?: boolean;
}
const StyledLiveBeaconIcon: React.FC<Props> = ({ className, withError, isIdle, ...props }) =>
const StyledLiveBeaconIcon: React.FC<Props> = ({ className, withError, isIdle, ...props }) => (
<LiveLocationIcon
{...props}
className={classNames(
'mx_StyledLiveBeaconIcon',
className,
{
'mx_StyledLiveBeaconIcon_error': withError,
'mx_StyledLiveBeaconIcon_idle': isIdle,
})}
/>;
className={classNames("mx_StyledLiveBeaconIcon", className, {
mx_StyledLiveBeaconIcon_error: withError,
mx_StyledLiveBeaconIcon_idle: isIdle,
})}
/>
);
export default StyledLiveBeaconIcon;

View file

@ -17,10 +17,10 @@ limitations under the License.
import { BeaconLocationState } from "matrix-js-sdk/src/content-helpers";
export enum BeaconDisplayStatus {
Loading = 'Loading',
Error = 'Error',
Stopped = 'Stopped',
Active = 'Active',
Loading = "Loading",
Error = "Error",
Stopped = "Stopped",
Active = "Active",
}
export const getBeaconDisplayStatus = (
isLive: boolean,