Skip to content

Commit

Permalink
Live location sharing - refresh beacon timers on tab becoming active (#…
Browse files Browse the repository at this point in the history
…8515)

* add visibilitychange listener

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

* test

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

* restore event listener mock

Signed-off-by: Kerry Archibald <kerrya@element.io>
  • Loading branch information
Kerry committed May 6, 2022
1 parent 2c19d28 commit e97536e
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
25 changes: 23 additions & 2 deletions src/components/views/beacon/LeftPanelLiveShareWarning.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ limitations under the License.
*/

import classNames from 'classnames';
import React from 'react';
import { BeaconIdentifier, Room } from 'matrix-js-sdk/src/matrix';
import React, { useEffect } from 'react';
import { Beacon, BeaconIdentifier, Room } from 'matrix-js-sdk/src/matrix';

import { useEventEmitterState } from '../../../hooks/useEventEmitter';
import { _t } from '../../../languageHandler';
Expand Down Expand Up @@ -61,6 +61,25 @@ const getLabel = (hasStoppingErrors: boolean, hasLocationErrors: boolean): strin
return _t('You are sharing your live location');
};

const useLivenessMonitor = (liveBeaconIds: BeaconIdentifier[], beacons: Map<BeaconIdentifier, Beacon>): void => {
useEffect(() => {
// chromium sets the minimum timer interval to 1000ms
// for inactive tabs
// refresh beacon monitors when the tab becomes active again
const onPageVisibilityChanged = () => {
if (document.visibilityState === 'visible') {
liveBeaconIds.map(identifier => beacons.get(identifier)?.monitorLiveness());
}
};
if (liveBeaconIds.length) {
document.addEventListener("visibilitychange", onPageVisibilityChanged);
}
() => {
document.removeEventListener("visibilitychange", onPageVisibilityChanged);
};
}, [liveBeaconIds, beacons]);
};

const LeftPanelLiveShareWarning: React.FC<Props> = ({ isMinimized }) => {
const isMonitoringLiveLocation = useEventEmitterState(
OwnBeaconStore.instance,
Expand Down Expand Up @@ -91,6 +110,8 @@ const LeftPanelLiveShareWarning: React.FC<Props> = ({ isMinimized }) => {
const hasLocationPublishErrors = !!beaconIdsWithLocationPublishError.length;
const hasStoppingErrors = !!beaconIdsWithStoppingError.length;

useLivenessMonitor(liveBeaconIds, OwnBeaconStore.instance.beacons);

if (!isMonitoringLiveLocation) {
return null;
}
Expand Down
23 changes: 23 additions & 0 deletions test/components/views/beacon/LeftPanelLiveShareWarning-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ jest.mock('../../../../src/stores/OwnBeaconStore', () => {
public getBeaconById = jest.fn();
public getLiveBeaconIds = jest.fn().mockReturnValue([]);
public readonly beaconUpdateErrors = new Map<BeaconIdentifier, Error>();
public readonly beacons = new Map<BeaconIdentifier, Beacon>();
}
return {
// @ts-ignore
Expand Down Expand Up @@ -103,6 +104,10 @@ describe('<LeftPanelLiveShareWarning />', () => {
mocked(OwnBeaconStore.instance).getLiveBeaconIds.mockReturnValue([beacon2.identifier, beacon1.identifier]);
});

afterAll(() => {
jest.spyOn(document, 'addEventListener').mockRestore();
});

it('renders correctly when not minimized', () => {
const component = getComponent();
expect(component).toMatchSnapshot();
Expand Down Expand Up @@ -195,6 +200,24 @@ describe('<LeftPanelLiveShareWarning />', () => {
expect(component.html()).toBe(null);
});

it('refreshes beacon liveness monitors when pagevisibilty changes to visible', () => {
OwnBeaconStore.instance.beacons.set(beacon1.identifier, beacon1);
OwnBeaconStore.instance.beacons.set(beacon2.identifier, beacon2);
const beacon1MonitorSpy = jest.spyOn(beacon1, 'monitorLiveness');
const beacon2MonitorSpy = jest.spyOn(beacon1, 'monitorLiveness');

jest.spyOn(document, 'addEventListener').mockImplementation(
(_e, listener) => (listener as EventListener)(new Event('')),
);

expect(beacon1MonitorSpy).not.toHaveBeenCalled();

getComponent();

expect(beacon1MonitorSpy).toHaveBeenCalled();
expect(beacon2MonitorSpy).toHaveBeenCalled();
});

describe('stopping errors', () => {
it('renders stopping error', () => {
OwnBeaconStore.instance.beaconUpdateErrors.set(beacon2.identifier, new Error('error'));
Expand Down

0 comments on commit e97536e

Please sign in to comment.