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

Commit 542b385

Browse files
author
Kerry Archibald
committed
Handle multiple live beacons in room share warning, test
Signed-off-by: Kerry Archibald <[email protected]>
1 parent ce06c27 commit 542b385

File tree

9 files changed

+352
-80
lines changed

9 files changed

+352
-80
lines changed

res/css/_components.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
@import "./_spacing.scss";
77
@import "./components/views/beacon/_LeftPanelLiveShareWarning.scss";
88
@import "./components/views/beacon/_RoomLiveShareWarning.scss";
9+
@import "./components/views/beacon/_StyledLiveBeaconIcon.scss";
910
@import "./components/views/location/_LiveDurationDropdown.scss";
1011
@import "./components/views/location/_LocationShareMenu.scss";
1112
@import "./components/views/location/_MapError.scss";

res/css/components/views/beacon/_RoomLiveShareWarning.scss

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
.mx_RoomLiveShareWarning {
32
width: 100%;
43

@@ -13,14 +12,23 @@
1312
background-color: $system;
1413
}
1514

15+
.mx_RoomLiveShareWarning_icon {
16+
height: 32px;
17+
width: 32px;
18+
margin-right: $spacing-8;
19+
}
20+
1621
.mx_RoomLiveShareWarning_label {
1722
flex: 1;
1823
font-size: $font-15px;
1924
}
2025

21-
2226
.mx_RoomLiveShareWarning_expiry {
2327
color: $secondary-content;
2428
font-size: $font-12px;
2529
margin-right: $spacing-16;
26-
}
30+
}
31+
32+
.mx_RoomLiveShareWarning_spinner {
33+
margin-right: $spacing-16;
34+
}

res/css/components/views/beacon/_StyledLiveBeaconIcon.scss

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ limitations under the License.
2323
border-radius: 50%;
2424

2525
background-color: $location-live-color;
26-
// 20% brightness $location-live-color
27-
border-color: #deddfd;
28-
padding: 2px;
29-
// colors icon
30-
color: white;
26+
// 20% brightness $location-live-color
27+
border-color: #deddfd;
28+
padding: 2px;
29+
// colors icon
30+
color: white;
3131
}

res/css/components/views/location/_ShareType.scss

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,19 +83,12 @@ limitations under the License.
8383
border-style: solid;
8484
border-radius: 50%;
8585

86+
// Live is styled by StyledLiveBeaconIcon
87+
8688
&.Own {
8789
border-color: $accent;
8890
}
8991

90-
&.Live {
91-
background-color: $location-live-color;
92-
// 20% brightness $location-live-color
93-
border-color: #deddfd;
94-
padding: 2px;
95-
// colors icon
96-
color: white;
97-
}
98-
9992
&.Pin {
10093
border-color: $accent;
10194
background-color: $accent;

src/components/views/beacon/RoomLiveShareWarning.tsx

Lines changed: 70 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,61 +14,109 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17+
import React, { useEffect, useState } from 'react';
1718
import classNames from 'classnames';
18-
import React from 'react';
1919
import { Room } from 'matrix-js-sdk/src/matrix';
2020

21-
import { useEventEmitterState } from '../../../hooks/useEventEmitter';
2221
import { _t } from '../../../languageHandler';
22+
import { useEventEmitterState } from '../../../hooks/useEventEmitter';
2323
import { OwnBeaconStore, OwnBeaconStoreEvent } from '../../../stores/OwnBeaconStore';
24-
import { Icon as LiveLocationIcon } from '../../../../res/img/location/live-location.svg';
2524
import AccessibleButton from '../elements/AccessibleButton';
25+
import StyledLiveBeaconIcon from './StyledLiveBeaconIcon';
26+
import { formatDuration } from '../../../DateUtils';
27+
import { getBeaconMsUntilExpiry, sortBeaconsByLatestExpiry } from '../../../utils/beacon';
28+
import Spinner from '../elements/Spinner';
2629

2730
interface Props {
2831
roomId: Room['roomId'];
2932
}
3033

31-
const RoomLiveShareWarning: React.FC<Props> = ({ roomId }) => {
34+
/**
35+
* It's technically possible to have multiple live beacons in one room
36+
* Select the latest expiry to display,
37+
* and kill all beacons on stop sharing
38+
*/
39+
type LiveBeaconsState = {
40+
liveBeaconIds: string[];
41+
msRemaining?: number;
42+
onStopSharing?: () => void;
43+
stoppingInProgress?: boolean;
44+
};
45+
const useLiveBeacons = (roomId: Room['roomId']): LiveBeaconsState => {
46+
const [stoppingInProgress, setStoppingInProgress] = useState(false);
3247
const liveBeaconIds = useEventEmitterState(
3348
OwnBeaconStore.instance,
3449
OwnBeaconStoreEvent.LivenessChange,
3550
() => OwnBeaconStore.instance.getLiveBeaconIds(roomId),
3651
);
3752

53+
// reset stopping in progress on change in live ids
54+
useEffect(() => {
55+
setStoppingInProgress(false);
56+
}, [liveBeaconIds, setStoppingInProgress]);
57+
3858
if (!liveBeaconIds?.length) {
39-
return null;
59+
return { liveBeaconIds };
4060
}
4161

42-
if (liveBeaconIds.length > 1) {
43-
throw new Error('not handled yet');
44-
}
62+
// select the beacon with latest expiry to display expiry time
63+
const beacon = liveBeaconIds.map(beaconId => OwnBeaconStore.instance.getBeaconById(beaconId))
64+
.sort(sortBeaconsByLatestExpiry)
65+
.shift();
4566

46-
const beaconId = liveBeaconIds[0];
67+
const onStopSharing = async () => {
68+
setStoppingInProgress(true);
69+
try {
70+
await Promise.all(liveBeaconIds.map(beaconId => OwnBeaconStore.instance.stopBeacon(beaconId)));
71+
} catch (error) {
72+
// only clear loading in case of error
73+
// to avoid flash of not-loading state
74+
// after beacons have been stopped but we wait for sync
75+
setStoppingInProgress(false);
76+
}
77+
};
4778

48-
const beacon = OwnBeaconStore.instance.getBeaconById(liveBeaconIds[0]);
49-
const liveTimeRemaining = `${beacon.beaconInfo.timeout}`;
79+
const msRemaining = getBeaconMsUntilExpiry(beacon);
5080

51-
const onStopSharing = () => {
52-
OwnBeaconStore.instance.stopBeacon(beaconId);
53-
};
81+
return { liveBeaconIds, onStopSharing, msRemaining, stoppingInProgress };
82+
};
83+
84+
const RoomLiveShareWarning: React.FC<Props> = ({ roomId }) => {
85+
const {
86+
liveBeaconIds,
87+
onStopSharing,
88+
msRemaining,
89+
stoppingInProgress,
90+
} = useLiveBeacons(roomId);
91+
92+
if (!liveBeaconIds?.length) {
93+
return null;
94+
}
95+
96+
const timeRemaining = formatDuration(msRemaining);
97+
const liveTimeRemaining = _t(`%(timeRemaining)s left`, { timeRemaining });
5498

5599
return <div
56100
className={classNames('mx_RoomLiveShareWarning')}
57101
>
58-
<LiveLocationIcon />
102+
<StyledLiveBeaconIcon className="mx_RoomLiveShareWarning_icon" />
59103
<span className="mx_RoomLiveShareWarning_label">
60-
61-
{ _t('You are sharing your live location') }
104+
{ _t('You are sharing %(count)s live locations', { count: liveBeaconIds.length }) }
62105
</span>
63-
<span
64-
data-test-id='room-live-share-expiry'
65-
className="mx_RoomLiveShareWarning_expiry"
66-
>{ liveTimeRemaining }</span>
106+
107+
{ stoppingInProgress ?
108+
<span className='mx_RoomLiveShareWarning_spinner'><Spinner h={16} w={16} /></span> :
109+
<span
110+
data-test-id='room-live-share-expiry'
111+
className="mx_RoomLiveShareWarning_expiry"
112+
>{ liveTimeRemaining }</span>
113+
}
67114
<AccessibleButton
68115
data-test-id='room-live-share-stop-sharing'
69-
onClick={ onStopSharing }
116+
onClick={onStopSharing}
70117
kind='danger'
71118
element='button'
119+
disabled={stoppingInProgress}
72120
>
73121
{ _t('Stop sharing') }
74122
</AccessibleButton>

src/i18n/strings/en_EN.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2967,6 +2967,9 @@
29672967
"Leave the beta": "Leave the beta",
29682968
"Join the beta": "Join the beta",
29692969
"You are sharing your live location": "You are sharing your live location",
2970+
"%(timeRemaining)s left": "%(timeRemaining)s left",
2971+
"You are sharing %(count)s live locations|one": "You are sharing your live location",
2972+
"You are sharing %(count)s live locations|other": "You are sharing %(count)s live locations",
29702973
"Stop sharing": "Stop sharing",
29712974
"Avatar": "Avatar",
29722975
"This room is public": "This room is public",

0 commit comments

Comments
 (0)