Files
ThreadNet-Web/src/stores/WidgetEchoStore.ts
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

111 lines
4.2 KiB
TypeScript
Raw Normal View History

2018-07-03 11:16:44 +01:00
/*
2024-09-09 14:57:16 +01:00
Copyright 2024 New Vector Ltd.
2021-04-06 12:26:50 +01:00
Copyright 2018-2021 The Matrix.org Foundation C.I.C.
2018-07-03 11:16:44 +01:00
2024-09-09 14:57:16 +01:00
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
2018-07-03 11:16:44 +01:00
*/
import EventEmitter from "events";
2021-04-06 12:26:50 +01:00
import { IWidget } from "matrix-widget-api";
import { MatrixEvent } from "matrix-js-sdk/src/matrix";
2021-10-22 17:23:32 -05:00
2021-06-17 14:24:53 +01:00
import { WidgetType } from "../widgets/WidgetType";
2018-07-03 11:16:44 +01:00
/**
* Acts as a place to get & set widget state, storing local echo state and
* proxying through state from the js-sdk.
*/
class WidgetEchoStore extends EventEmitter {
private roomWidgetEcho: {
2021-04-06 12:26:50 +01:00
[roomId: string]: {
2021-07-01 23:23:03 +01:00
[widgetId: string]: IWidget;
};
2021-04-06 12:26:50 +01:00
};
public constructor() {
2018-07-03 11:16:44 +01:00
super();
this.roomWidgetEcho = {
2018-07-05 19:40:45 +01:00
// Map as below. Object is the content of the widget state event,
// so for widgets that have been deleted locally, the object is empty.
2018-07-03 11:16:44 +01:00
// roomId: {
2021-04-26 15:38:43 +01:00
// widgetId: IWidget
2018-07-03 11:16:44 +01:00
// }
};
}
/**
* Gets the widgets for a room, subtracting those that are pending deletion.
2018-07-03 11:16:44 +01:00
* Widgets that are pending addition are not included, since widgets are
* represented as MatrixEvents, so to do this we'd have to create fake MatrixEvents,
2018-07-03 11:16:44 +01:00
* and we don't really need the actual widget events anyway since we just want to
* show a spinner / prevent widgets being added twice.
2018-07-03 11:22:19 +01:00
*
2021-04-26 15:38:43 +01:00
* @param {string} roomId The ID of the room to get widgets for
2018-07-03 11:22:19 +01:00
* @param {MatrixEvent[]} currentRoomWidgets Current widgets for the room
* @returns {MatrixEvent[]} List of widgets in the room, minus any pending removal
2018-07-03 11:16:44 +01:00
*/
public getEchoedRoomWidgets(roomId: string, currentRoomWidgets: MatrixEvent[]): MatrixEvent[] {
const echoedWidgets: MatrixEvent[] = [];
2018-07-03 11:16:44 +01:00
const roomEchoState = Object.assign({}, this.roomWidgetEcho[roomId]);
2018-07-03 11:16:44 +01:00
for (const w of currentRoomWidgets) {
const widgetId = w.getStateKey()!;
2018-07-05 19:46:37 +01:00
// If there's no echo, or the echo still has a widget present, show the *old* widget
2018-07-16 13:18:10 +01:00
// we don't include widgets that have changed for the same reason we don't include new ones,
// ie. we'd need to fake matrix events to do so and there's currently no need.
2018-07-05 19:46:37 +01:00
if (!roomEchoState[widgetId] || Object.keys(roomEchoState[widgetId]).length !== 0) {
2018-07-03 11:16:44 +01:00
echoedWidgets.push(w);
}
delete roomEchoState[widgetId];
}
return echoedWidgets;
}
public roomHasPendingWidgetsOfType(roomId: string, currentRoomWidgets: MatrixEvent[], type?: WidgetType): boolean {
const roomEchoState = Object.assign({}, this.roomWidgetEcho[roomId]);
2018-07-03 11:16:44 +01:00
2018-07-05 19:57:24 +01:00
// any widget IDs that are already in the room are not pending, so
// echoes for them don't count as pending.
2018-07-03 11:16:44 +01:00
for (const w of currentRoomWidgets) {
const widgetId = w.getStateKey()!;
2018-07-03 11:16:44 +01:00
delete roomEchoState[widgetId];
}
2018-07-05 19:57:24 +01:00
// if there's anything left then there are pending widgets.
2018-07-03 11:16:44 +01:00
if (type === undefined) {
return Object.keys(roomEchoState).length > 0;
} else {
return Object.values(roomEchoState).some((widget) => {
return type.matches(widget.type);
2018-07-03 11:16:44 +01:00
});
}
}
public roomHasPendingWidgets(roomId: string, currentRoomWidgets: MatrixEvent[]): boolean {
2018-07-05 18:43:20 +01:00
return this.roomHasPendingWidgetsOfType(roomId, currentRoomWidgets);
2018-07-03 11:16:44 +01:00
}
public setRoomWidgetEcho(roomId: string, widgetId: string, state: IWidget): void {
if (this.roomWidgetEcho[roomId] === undefined) this.roomWidgetEcho[roomId] = {};
2018-07-03 11:16:44 +01:00
this.roomWidgetEcho[roomId][widgetId] = state;
this.emit("update", roomId, widgetId);
2018-07-03 11:16:44 +01:00
}
public removeRoomWidgetEcho(roomId: string, widgetId: string): void {
delete this.roomWidgetEcho[roomId][widgetId];
if (Object.keys(this.roomWidgetEcho[roomId]).length === 0) delete this.roomWidgetEcho[roomId];
this.emit("update", roomId, widgetId);
2018-07-03 11:16:44 +01:00
}
}
let singletonWidgetEchoStore: WidgetEchoStore | null = null;
2018-07-03 11:16:44 +01:00
if (!singletonWidgetEchoStore) {
singletonWidgetEchoStore = new WidgetEchoStore();
}
export default singletonWidgetEchoStore!;