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

Commit bb6ae3f

Browse files
author
Kerry
authored
Live beacons: track users live beacons (#8061)
* add simple live share warning Signed-off-by: Kerry Archibald <[email protected]> * rough first cut of OwnBeaconStore Signed-off-by: Kerry Archibald <[email protected]> * working (?) has live beacons status Signed-off-by: Kerry Archibald <[email protected]> * lint Signed-off-by: Kerry Archibald <[email protected]> * add left panel share warning Signed-off-by: Kerry Archibald <[email protected]> * setup for tests Signed-off-by: Kerry Archibald <[email protected]> * test ownbeaconstore Signed-off-by: Kerry Archibald <[email protected]> * add copyright Signed-off-by: Kerry Archibald <[email protected]> * add copyright Signed-off-by: Kerry Archibald <[email protected]> * remove warning banner Signed-off-by: Kerry Archibald <[email protected]> * fix test Signed-off-by: Kerry Archibald <[email protected]> * fix tests for weird asyncstore closure issues Signed-off-by: Kerry Archibald <[email protected]> * fix OwnBeaconStore more... Signed-off-by: Kerry Archibald <[email protected]> * revert loose change to LeftPanel Signed-off-by: Kerry Archibald <[email protected]>
1 parent e677901 commit bb6ae3f

File tree

3 files changed

+543
-0
lines changed

3 files changed

+543
-0
lines changed

src/stores/OwnBeaconStore.ts

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/*
2+
Copyright 2022 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
import {
18+
Beacon,
19+
BeaconEvent,
20+
MatrixEvent,
21+
Room,
22+
} from "matrix-js-sdk/src/matrix";
23+
24+
import defaultDispatcher from "../dispatcher/dispatcher";
25+
import { ActionPayload } from "../dispatcher/payloads";
26+
import { AsyncStoreWithClient } from "./AsyncStoreWithClient";
27+
28+
const isOwnBeacon = (beacon: Beacon, userId: string): boolean => beacon.beaconInfoOwner === userId;
29+
30+
export enum OwnBeaconStoreEvent {
31+
LivenessChange = 'OwnBeaconStore.LivenessChange'
32+
}
33+
34+
type OwnBeaconStoreState = {
35+
beacons: Map<string, Beacon>;
36+
beaconsByRoomId: Map<Room['roomId'], Set<string>>;
37+
liveBeaconIds: string[];
38+
};
39+
export class OwnBeaconStore extends AsyncStoreWithClient<OwnBeaconStoreState> {
40+
private static internalInstance = new OwnBeaconStore();
41+
public readonly beacons = new Map<string, Beacon>();
42+
public readonly beaconsByRoomId = new Map<Room['roomId'], Set<string>>();
43+
private liveBeaconIds = [];
44+
45+
public constructor() {
46+
super(defaultDispatcher);
47+
}
48+
49+
public static get instance(): OwnBeaconStore {
50+
return OwnBeaconStore.internalInstance;
51+
}
52+
53+
protected async onNotReady() {
54+
this.matrixClient.removeListener(BeaconEvent.LivenessChange, this.onBeaconLiveness);
55+
this.matrixClient.removeListener(BeaconEvent.New, this.onNewBeacon);
56+
57+
this.beacons.forEach(beacon => beacon.destroy());
58+
59+
this.beacons.clear();
60+
this.beaconsByRoomId.clear();
61+
this.liveBeaconIds = [];
62+
}
63+
64+
protected async onReady(): Promise<void> {
65+
this.matrixClient.on(BeaconEvent.LivenessChange, this.onBeaconLiveness);
66+
this.matrixClient.on(BeaconEvent.New, this.onNewBeacon);
67+
68+
this.initialiseBeaconState();
69+
}
70+
71+
protected async onAction(payload: ActionPayload): Promise<void> {
72+
// we don't actually do anything here
73+
}
74+
75+
public hasLiveBeacons(roomId?: string): boolean {
76+
return !!this.getLiveBeaconIds(roomId).length;
77+
}
78+
79+
public getLiveBeaconIds(roomId?: string): string[] {
80+
if (!roomId) {
81+
return this.liveBeaconIds;
82+
}
83+
return this.liveBeaconIds.filter(beaconId => this.beaconsByRoomId.get(roomId)?.has(beaconId));
84+
}
85+
86+
private onNewBeacon = (_event: MatrixEvent, beacon: Beacon): void => {
87+
if (!isOwnBeacon(beacon, this.matrixClient.getUserId())) {
88+
return;
89+
}
90+
this.addBeacon(beacon);
91+
this.checkLiveness();
92+
};
93+
94+
private onBeaconLiveness = (isLive: boolean, beacon: Beacon): void => {
95+
// check if we care about this beacon
96+
if (!this.beacons.has(beacon.beaconInfoId)) {
97+
return;
98+
}
99+
100+
if (!isLive && this.liveBeaconIds.includes(beacon.beaconInfoId)) {
101+
this.liveBeaconIds =
102+
this.liveBeaconIds.filter(beaconId => beaconId !== beacon.beaconInfoId);
103+
}
104+
105+
if (isLive && !this.liveBeaconIds.includes(beacon.beaconInfoId)) {
106+
this.liveBeaconIds.push(beacon.beaconInfoId);
107+
}
108+
109+
this.emit(OwnBeaconStoreEvent.LivenessChange, this.hasLiveBeacons());
110+
// TODO stop or start polling here
111+
// if not content is live but beacon is not, update state event with live: false
112+
};
113+
114+
private initialiseBeaconState = () => {
115+
const userId = this.matrixClient.getUserId();
116+
const visibleRooms = this.matrixClient.getVisibleRooms();
117+
118+
visibleRooms
119+
.forEach(room => {
120+
const roomState = room.currentState;
121+
const beacons = roomState.beacons;
122+
const ownBeaconsArray = [...beacons.values()].filter(beacon => isOwnBeacon(beacon, userId));
123+
ownBeaconsArray.forEach(beacon => this.addBeacon(beacon));
124+
});
125+
126+
this.checkLiveness();
127+
};
128+
129+
private addBeacon = (beacon: Beacon): void => {
130+
this.beacons.set(beacon.beaconInfoId, beacon);
131+
132+
if (!this.beaconsByRoomId.has(beacon.roomId)) {
133+
this.beaconsByRoomId.set(beacon.roomId, new Set<string>());
134+
}
135+
136+
this.beaconsByRoomId.get(beacon.roomId).add(beacon.beaconInfoId);
137+
beacon.monitorLiveness();
138+
};
139+
140+
private checkLiveness = (): void => {
141+
const prevLiveness = this.hasLiveBeacons();
142+
this.liveBeaconIds = [...this.beacons.values()]
143+
.filter(beacon => beacon.isLive)
144+
.map(beacon => beacon.beaconInfoId);
145+
146+
const newLiveness = this.hasLiveBeacons();
147+
148+
if (prevLiveness !== newLiveness) {
149+
this.emit(OwnBeaconStoreEvent.LivenessChange, newLiveness);
150+
}
151+
};
152+
}

0 commit comments

Comments
 (0)