Proactively fix stuck devices in video rooms (#8587)
* Proactively fix stuck devices in video rooms * Fix tests * Explain why we're disabling the lint rule * Apply code review suggestions * Back VideoChannelStore's flags by SettingsStore instead of localStorage
This commit is contained in:
parent
6f851108be
commit
ceda77d7dc
9 changed files with 149 additions and 49 deletions
|
@ -16,6 +16,8 @@ limitations under the License.
|
|||
|
||||
import { useState } from "react";
|
||||
import { throttle } from "lodash";
|
||||
import { Optional } from "matrix-events-sdk";
|
||||
import { IMyDevice } from "matrix-js-sdk/src/client";
|
||||
import { CallType } from "matrix-js-sdk/src/webrtc/call";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { RoomStateEvent } from "matrix-js-sdk/src/models/room-state";
|
||||
|
@ -26,14 +28,16 @@ import WidgetStore, { IApp } from "../stores/WidgetStore";
|
|||
import { WidgetType } from "../widgets/WidgetType";
|
||||
import WidgetUtils from "./WidgetUtils";
|
||||
|
||||
export const VIDEO_CHANNEL = "io.element.video";
|
||||
export const VIDEO_CHANNEL_MEMBER = "io.element.video.member";
|
||||
const STUCK_DEVICE_TIMEOUT_MS = 1000 * 60 * 60;
|
||||
|
||||
export interface IVideoChannelMemberContent {
|
||||
interface IVideoChannelMemberContent {
|
||||
// Connected device IDs
|
||||
devices: string[];
|
||||
}
|
||||
|
||||
export const VIDEO_CHANNEL = "io.element.video";
|
||||
export const VIDEO_CHANNEL_MEMBER = "io.element.video.member";
|
||||
|
||||
export const getVideoChannel = (roomId: string): IApp => {
|
||||
const apps = WidgetStore.instance.getApps(roomId);
|
||||
return apps.find(app => WidgetType.JITSI.matches(app.type) && app.id === VIDEO_CHANNEL);
|
||||
|
@ -72,3 +76,54 @@ export const useConnectedMembers = (
|
|||
}, throttleMs, { leading: true, trailing: true }));
|
||||
return members;
|
||||
};
|
||||
|
||||
const updateDevices = async (room: Optional<Room>, fn: (devices: string[] | null) => string[]) => {
|
||||
if (room?.getMyMembership() !== "join") return;
|
||||
|
||||
const devicesState = room.currentState.getStateEvents(VIDEO_CHANNEL_MEMBER, room.client.getUserId());
|
||||
const devices = devicesState?.getContent<IVideoChannelMemberContent>()?.devices ?? [];
|
||||
const newDevices = fn(devices);
|
||||
|
||||
if (newDevices) {
|
||||
await room.client.sendStateEvent(
|
||||
room.roomId, VIDEO_CHANNEL_MEMBER, { devices: newDevices }, room.client.getUserId(),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const addOurDevice = async (room: Room) => {
|
||||
await updateDevices(room, devices => Array.from(new Set(devices).add(room.client.getDeviceId())));
|
||||
};
|
||||
|
||||
export const removeOurDevice = async (room: Room) => {
|
||||
await updateDevices(room, devices => {
|
||||
const devicesSet = new Set(devices);
|
||||
devicesSet.delete(room.client.getDeviceId());
|
||||
return Array.from(devicesSet);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Fixes devices that may have gotten stuck in video channel member state after
|
||||
* an unclean disconnection, by filtering out logged out devices, inactive
|
||||
* devices, and our own device (if we're disconnected).
|
||||
* @param {Room} room The room to fix
|
||||
* @param {boolean} connectedLocalEcho Local echo of whether this device is connected
|
||||
*/
|
||||
export const fixStuckDevices = async (room: Room, connectedLocalEcho: boolean) => {
|
||||
const now = new Date().valueOf();
|
||||
const { devices: myDevices } = await room.client.getDevices();
|
||||
const deviceMap = new Map<string, IMyDevice>(myDevices.map(d => [d.device_id, d]));
|
||||
|
||||
await updateDevices(room, devices => {
|
||||
const newDevices = devices.filter(d => {
|
||||
const device = deviceMap.get(d);
|
||||
return device?.last_seen_ts
|
||||
&& !(d === room.client.getDeviceId() && !connectedLocalEcho)
|
||||
&& (now - device.last_seen_ts) < STUCK_DEVICE_TIMEOUT_MS;
|
||||
});
|
||||
|
||||
// Skip the update if the devices are unchanged
|
||||
return newDevices.length === devices.length ? null : newDevices;
|
||||
});
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue