diff --git a/res/css/components/views/beacon/_RoomLiveShareWarning.scss b/res/css/components/views/beacon/_RoomLiveShareWarning.scss index f82c7f4de4..f85cebe8bb 100644 --- a/res/css/components/views/beacon/_RoomLiveShareWarning.scss +++ b/res/css/components/views/beacon/_RoomLiveShareWarning.scss @@ -26,6 +26,7 @@ limitations under the License. color: $primary-content; background-color: $system; + cursor: pointer; } .mx_RoomLiveShareWarning_icon { diff --git a/src/components/views/beacon/LeftPanelLiveShareWarning.tsx b/src/components/views/beacon/LeftPanelLiveShareWarning.tsx index b268628592..ce31e46262 100644 --- a/src/components/views/beacon/LeftPanelLiveShareWarning.tsx +++ b/src/components/views/beacon/LeftPanelLiveShareWarning.tsx @@ -16,7 +16,7 @@ limitations under the License. import classNames from 'classnames'; import React, { useEffect } from 'react'; -import { Beacon, BeaconIdentifier, Room } from 'matrix-js-sdk/src/matrix'; +import { Beacon, BeaconIdentifier } from 'matrix-js-sdk/src/matrix'; import { useEventEmitterState } from '../../../hooks/useEventEmitter'; import { _t } from '../../../languageHandler'; @@ -33,13 +33,12 @@ interface Props { /** * Choose the most relevant beacon - * and get its roomId */ -const chooseBestBeaconRoomId = ( +const chooseBestBeacon = ( liveBeaconIds: BeaconIdentifier[], updateErrorBeaconIds: BeaconIdentifier[], locationErrorBeaconIds: BeaconIdentifier[], -): Room['roomId'] | undefined => { +): Beacon | undefined => { // both lists are ordered by creation timestamp in store // so select latest beacon const beaconId = updateErrorBeaconIds?.[0] ?? locationErrorBeaconIds?.[0] ?? liveBeaconIds?.[0]; @@ -48,7 +47,7 @@ const chooseBestBeaconRoomId = ( } const beacon = OwnBeaconStore.instance.getBeaconById(beaconId); - return beacon?.roomId; + return beacon; }; const getLabel = (hasStoppingErrors: boolean, hasLocationErrors: boolean): string => { @@ -116,15 +115,18 @@ const LeftPanelLiveShareWarning: React.FC = ({ isMinimized }) => { return null; } - const relevantBeaconRoomId = chooseBestBeaconRoomId( + const relevantBeacon = chooseBestBeacon( liveBeaconIds, beaconIdsWithStoppingError, beaconIdsWithLocationPublishError, ); - const onWarningClick = relevantBeaconRoomId ? () => { + const onWarningClick = relevantBeacon ? () => { dispatcher.dispatch({ action: Action.ViewRoom, - room_id: relevantBeaconRoomId, + room_id: relevantBeacon.roomId, metricsTrigger: undefined, + event_id: relevantBeacon.beaconInfoId, + scroll_into_view: true, + highlighted: true, }); } : undefined; diff --git a/src/components/views/beacon/RoomLiveShareWarning.tsx b/src/components/views/beacon/RoomLiveShareWarning.tsx index ecd200cf96..dec2b5c042 100644 --- a/src/components/views/beacon/RoomLiveShareWarning.tsx +++ b/src/components/views/beacon/RoomLiveShareWarning.tsx @@ -21,11 +21,14 @@ import { _t } from '../../../languageHandler'; import { useEventEmitterState } from '../../../hooks/useEventEmitter'; import { OwnBeaconStore, OwnBeaconStoreEvent } from '../../../stores/OwnBeaconStore'; import { useOwnLiveBeacons } from '../../../utils/beacon'; -import AccessibleButton from '../elements/AccessibleButton'; +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) { @@ -57,6 +60,13 @@ const RoomLiveShareWarningInner: React.FC = ({ l const hasError = hasStopSharingError || hasLocationPublishError; + // eat events from buttons so navigate to tile + // is not triggered + const stopPropagationWrapper = (callback: () => void) => (e?: ButtonEvent) => { + e?.stopPropagation(); + callback(); + }; + const onButtonClick = () => { if (hasLocationPublishError) { onResetLocationPublishError(); @@ -65,8 +75,20 @@ const RoomLiveShareWarningInner: React.FC = ({ l } }; + const onClick = () => { + dispatcher.dispatch({ + action: Action.ViewRoom, + room_id: beacon.roomId, + metricsTrigger: undefined, + event_id: beacon.beaconInfoId, + scroll_into_view: true, + highlighted: true, + }); + }; + return
@@ -82,7 +104,7 @@ const RoomLiveShareWarningInner: React.FC = ({ l = ({ l title={_t('Stop sharing and close')} element='button' className='mx_RoomLiveShareWarning_closeButton' - onClick={onStopSharing} + onClick={stopPropagationWrapper(onStopSharing)} > } diff --git a/test/components/views/beacon/LeftPanelLiveShareWarning-test.tsx b/test/components/views/beacon/LeftPanelLiveShareWarning-test.tsx index 8a10f73575..aeef98c259 100644 --- a/test/components/views/beacon/LeftPanelLiveShareWarning-test.tsx +++ b/test/components/views/beacon/LeftPanelLiveShareWarning-test.tsx @@ -126,6 +126,9 @@ describe('', () => { metricsTrigger: undefined, // latest beacon's room room_id: roomId2, + event_id: beacon2.beaconInfoId, + highlighted: true, + scroll_into_view: true, }); }); @@ -158,6 +161,9 @@ describe('', () => { metricsTrigger: undefined, // error beacon's room room_id: roomId1, + event_id: beacon1.beaconInfoId, + highlighted: true, + scroll_into_view: true, }); }); @@ -264,6 +270,9 @@ describe('', () => { metricsTrigger: undefined, // stopping error beacon's room room_id: beacon2.roomId, + event_id: beacon2.beaconInfoId, + highlighted: true, + scroll_into_view: true, }); }); }); diff --git a/test/components/views/beacon/RoomLiveShareWarning-test.tsx b/test/components/views/beacon/RoomLiveShareWarning-test.tsx index 2a6956c92b..535c046b99 100644 --- a/test/components/views/beacon/RoomLiveShareWarning-test.tsx +++ b/test/components/views/beacon/RoomLiveShareWarning-test.tsx @@ -32,6 +32,8 @@ import { resetAsyncStoreWithClient, setupAsyncStoreWithClient, } from '../../../test-utils'; +import defaultDispatcher from '../../../../src/dispatcher/dispatcher'; +import { Action } from '../../../../src/dispatcher/actions'; jest.useFakeTimers(); describe('', () => { @@ -117,6 +119,7 @@ describe('', () => { afterAll(() => { jest.spyOn(global.Date, 'now').mockRestore(); localStorageSpy.mockRestore(); + jest.spyOn(defaultDispatcher, 'dispatch').mockRestore(); }); const getExpiryText = wrapper => findByTestId(wrapper, 'room-live-share-expiry').text(); @@ -263,6 +266,24 @@ describe('', () => { expect(clearIntervalSpy).toHaveBeenCalled(); }); + it('navigates to beacon tile on click', () => { + const dispatcherSpy = jest.spyOn(defaultDispatcher, 'dispatch'); + const component = getComponent({ roomId: room1Id }); + + act(() => { + component.simulate('click'); + }); + + expect(dispatcherSpy).toHaveBeenCalledWith({ + action: Action.ViewRoom, + event_id: room1Beacon1.getId(), + room_id: room1Id, + highlighted: true, + scroll_into_view: true, + metricsTrigger: undefined, + }); + }); + describe('stopping beacons', () => { it('stops beacon on stop sharing click', () => { const component = getComponent({ roomId: room2Id }); diff --git a/test/components/views/beacon/__snapshots__/RoomLiveShareWarning-test.tsx.snap b/test/components/views/beacon/__snapshots__/RoomLiveShareWarning-test.tsx.snap index 8701c83c91..843f0f963e 100644 --- a/test/components/views/beacon/__snapshots__/RoomLiveShareWarning-test.tsx.snap +++ b/test/components/views/beacon/__snapshots__/RoomLiveShareWarning-test.tsx.snap @@ -20,6 +20,7 @@ exports[` when user has live beacons and geolocation is >