Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Live location share - show loading UI for beacons with start timestam…
Browse files Browse the repository at this point in the history
…p in the future (PSF-1081) (#8775)

* check for beacons that are yet to start and show loading ui

Signed-off-by: Kerry Archibald <[email protected]>

* update snapshots for js-sdk rename

Signed-off-by: Kerry Archibald <[email protected]>

* remove debug

Signed-off-by: Kerry Archibald <[email protected]>

* Update test/components/views/messages/MBeaconBody-test.tsx

Co-authored-by: Travis Ralston <[email protected]>

* Update src/components/views/beacon/displayStatus.ts

Co-authored-by: Travis Ralston <[email protected]>

Co-authored-by: Travis Ralston <[email protected]>
  • Loading branch information
Kerry and turt2live authored Jun 9, 2022
1 parent 1d79c78 commit 2bdb4d3
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 4 deletions.
8 changes: 6 additions & 2 deletions src/components/views/beacon/displayStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,18 @@ export enum BeaconDisplayStatus {
export const getBeaconDisplayStatus = (
isLive: boolean,
latestLocationState?: BeaconLocationState,
error?: Error): BeaconDisplayStatus => {
error?: Error,
waitingToStart?: boolean,
): BeaconDisplayStatus => {
if (error) {
return BeaconDisplayStatus.Error;
}
if (waitingToStart) {
return BeaconDisplayStatus.Loading;
}
if (!isLive) {
return BeaconDisplayStatus.Stopped;
}

if (!latestLocationState) {
return BeaconDisplayStatus.Loading;
}
Expand Down
13 changes: 11 additions & 2 deletions src/components/views/messages/MBeaconBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import MatrixClientContext from '../../../contexts/MatrixClientContext';
import { useEventEmitterState } from '../../../hooks/useEventEmitter';
import { _t } from '../../../languageHandler';
import Modal from '../../../Modal';
import { useBeacon } from '../../../utils/beacon';
import { isBeaconWaitingToStart, useBeacon } from '../../../utils/beacon';
import { isSelfLocation } from '../../../utils/location';
import { BeaconDisplayStatus, getBeaconDisplayStatus } from '../beacon/displayStatus';
import BeaconStatus from '../beacon/BeaconStatus';
Expand All @@ -39,6 +39,7 @@ const useBeaconState = (beaconInfoEvent: MatrixEvent): {
description?: string;
latestLocationState?: BeaconLocationState;
isLive?: boolean;
waitingToStart?: boolean;
} => {
const beacon = useBeacon(beaconInfoEvent);

Expand All @@ -56,12 +57,19 @@ const useBeaconState = (beaconInfoEvent: MatrixEvent): {
return {};
}

// a beacon's starting timestamp can be in the future
// (either from small deviations in system clock times, or on purpose from another client)
// a beacon is only live between its start timestamp and expiry
// detect when a beacon is waiting to become live
// and display a loading state
const waitingToStart = !!beacon && isBeaconWaitingToStart(beacon);
const { description } = beacon.beaconInfo;

return {
beacon,
description,
isLive,
waitingToStart,
latestLocationState,
};
};
Expand All @@ -84,12 +92,13 @@ const MBeaconBody: React.FC<IBodyProps> = React.forwardRef(({ mxEvent }, ref) =>
beacon,
isLive,
latestLocationState,
waitingToStart,
} = useBeaconState(mxEvent);
const mapId = useUniqueId(mxEvent.getId());

const matrixClient = useContext(MatrixClientContext);
const [error, setError] = useState<Error>();
const displayStatus = getBeaconDisplayStatus(isLive, latestLocationState, error);
const displayStatus = getBeaconDisplayStatus(isLive, latestLocationState, error, waitingToStart);
const markerRoomMember = isSelfLocation(mxEvent.getContent()) ? mxEvent.sender : undefined;
const isOwnBeacon = beacon?.beaconInfoOwner === matrixClient.getUserId();

Expand Down
7 changes: 7 additions & 0 deletions src/utils/beacon/duration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,10 @@ export const sortBeaconsByLatestExpiry = (left: Beacon, right: Beacon): number =
// aka sort by timestamp descending
export const sortBeaconsByLatestCreation = (left: Beacon, right: Beacon): number =>
right.beaconInfo.timestamp - left.beaconInfo.timestamp;

// a beacon's starting timestamp can be in the future
// (either from small deviations in system clock times, or on purpose from another client)
// a beacon is only live between its start timestamp and expiry
// detect when a beacon is waiting to become live
export const isBeaconWaitingToStart = (beacon: Beacon): boolean =>
!beacon.isLive && beacon.beaconInfo.timestamp > Date.now() && getBeaconExpiryTimestamp(beacon) > Date.now();
13 changes: 13 additions & 0 deletions test/components/views/messages/MBeaconBody-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,19 @@ describe('<MBeaconBody />', () => {
expect(component.text()).toEqual("Live location ended");
});

it('renders loading beacon UI for a beacon that has not started yet', () => {
const beaconInfoEvent = makeBeaconInfoEvent(
aliceId,
roomId,
// puts this beacons start timestamp in the future
{ isLive: true, timestamp: now + 60000, timeout: 500 },
'$alice-room1-1',
);
makeRoomWithStateEvents([beaconInfoEvent], { roomId, mockClient });
const component = getComponent({ mxEvent: beaconInfoEvent });
expect(component.text()).toEqual("Loading live location...");
});

it('does not open maximised map when on click when beacon is stopped', () => {
const beaconInfoEvent = makeBeaconInfoEvent(aliceId,
roomId,
Expand Down

0 comments on commit 2bdb4d3

Please sign in to comment.