Skip to content

Commit f05df80

Browse files
committed
Revert "Distinguish room state and timeline events when dealing with widgets (#28681)"
This reverts commit a0ab889.
1 parent 9a109cd commit f05df80

File tree

4 files changed

+89
-301
lines changed

4 files changed

+89
-301
lines changed

src/stores/widgets/StopGapWidget.ts

Lines changed: 14 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,7 @@
66
* Please see LICENSE files in the repository root for full details.
77
*/
88

9-
import {
10-
Room,
11-
MatrixEvent,
12-
MatrixEventEvent,
13-
MatrixClient,
14-
ClientEvent,
15-
RoomStateEvent,
16-
} from "matrix-js-sdk/src/matrix";
9+
import { Room, MatrixEvent, MatrixEventEvent, MatrixClient, ClientEvent } from "matrix-js-sdk/src/matrix";
1710
import { KnownMembership } from "matrix-js-sdk/src/types";
1811
import {
1912
ClientWidgetApi,
@@ -33,6 +26,7 @@ import {
3326
WidgetApiFromWidgetAction,
3427
WidgetKind,
3528
} from "matrix-widget-api";
29+
import { Optional } from "matrix-events-sdk";
3630
import { EventEmitter } from "events";
3731
import { logger } from "matrix-js-sdk/src/logger";
3832

@@ -62,7 +56,6 @@ import { ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload";
6256
import Modal from "../../Modal";
6357
import ErrorDialog from "../../components/views/dialogs/ErrorDialog";
6458
import { SdkContextClass } from "../../contexts/SDKContext";
65-
import { UPDATE_EVENT } from "../AsyncStore";
6659

6760
// TODO: Destroy all of this code
6861

@@ -158,9 +151,6 @@ export class StopGapWidget extends EventEmitter {
158151
private mockWidget: ElementWidget;
159152
private scalarToken?: string;
160153
private roomId?: string;
161-
// The room that we're currently allowing the widget to interact with. Only
162-
// used for account widgets, which may follow the user to different rooms.
163-
private viewedRoomId: string | null = null;
164154
private kind: WidgetKind;
165155
private readonly virtual: boolean;
166156
private readUpToMap: { [roomId: string]: string } = {}; // room ID to event ID
@@ -187,6 +177,17 @@ export class StopGapWidget extends EventEmitter {
187177
this.stickyPromise = appTileProps.stickyPromise;
188178
}
189179

180+
private get eventListenerRoomId(): Optional<string> {
181+
// When widgets are listening to events, we need to make sure they're only
182+
// receiving events for the right room. In particular, room widgets get locked
183+
// to the room they were added in while account widgets listen to the currently
184+
// active room.
185+
186+
if (this.roomId) return this.roomId;
187+
188+
return SdkContextClass.instance.roomViewStore.getRoomId();
189+
}
190+
190191
public get widgetApi(): ClientWidgetApi | null {
191192
return this.messaging;
192193
}
@@ -258,17 +259,6 @@ export class StopGapWidget extends EventEmitter {
258259
});
259260
}
260261
};
261-
262-
// This listener is only active for account widgets, which may follow the
263-
// user to different rooms
264-
private onRoomViewStoreUpdate = (): void => {
265-
const roomId = SdkContextClass.instance.roomViewStore.getRoomId() ?? null;
266-
if (roomId !== this.viewedRoomId) {
267-
this.messaging!.setViewedRoomId(roomId);
268-
this.viewedRoomId = roomId;
269-
}
270-
};
271-
272262
/**
273263
* This starts the messaging for the widget if it is not in the state `started` yet.
274264
* @param iframe the iframe the widget should use
@@ -295,17 +285,6 @@ export class StopGapWidget extends EventEmitter {
295285
this.messaging.on("capabilitiesNotified", () => this.emit("capabilitiesNotified"));
296286
this.messaging.on(`action:${WidgetApiFromWidgetAction.OpenModalWidget}`, this.onOpenModal);
297287

298-
// When widgets are listening to events, we need to make sure they're only
299-
// receiving events for the right room
300-
if (this.roomId === undefined) {
301-
// Account widgets listen to the currently active room
302-
this.messaging.setViewedRoomId(SdkContextClass.instance.roomViewStore.getRoomId() ?? null);
303-
SdkContextClass.instance.roomViewStore.on(UPDATE_EVENT, this.onRoomViewStoreUpdate);
304-
} else {
305-
// Room widgets get locked to the room they were added in
306-
this.messaging.setViewedRoomId(this.roomId);
307-
}
308-
309288
// Always attach a handler for ViewRoom, but permission check it internally
310289
this.messaging.on(`action:${ElementWidgetActions.ViewRoom}`, (ev: CustomEvent<IViewRoomApiRequest>) => {
311290
ev.preventDefault(); // stop the widget API from auto-rejecting this
@@ -350,7 +329,6 @@ export class StopGapWidget extends EventEmitter {
350329
// Attach listeners for feeding events - the underlying widget classes handle permissions for us
351330
this.client.on(ClientEvent.Event, this.onEvent);
352331
this.client.on(MatrixEventEvent.Decrypted, this.onEventDecrypted);
353-
this.client.on(RoomStateEvent.Events, this.onStateUpdate);
354332
this.client.on(ClientEvent.ToDeviceEvent, this.onToDeviceEvent);
355333

356334
this.messaging.on(
@@ -479,11 +457,8 @@ export class StopGapWidget extends EventEmitter {
479457
WidgetMessagingStore.instance.stopMessaging(this.mockWidget, this.roomId);
480458
this.messaging = null;
481459

482-
SdkContextClass.instance.roomViewStore.off(UPDATE_EVENT, this.onRoomViewStoreUpdate);
483-
484460
this.client.off(ClientEvent.Event, this.onEvent);
485461
this.client.off(MatrixEventEvent.Decrypted, this.onEventDecrypted);
486-
this.client.off(RoomStateEvent.Events, this.onStateUpdate);
487462
this.client.off(ClientEvent.ToDeviceEvent, this.onToDeviceEvent);
488463
}
489464

@@ -496,14 +471,6 @@ export class StopGapWidget extends EventEmitter {
496471
this.feedEvent(ev);
497472
};
498473

499-
private onStateUpdate = (ev: MatrixEvent): void => {
500-
if (this.messaging === null) return;
501-
const raw = ev.getEffectiveEvent();
502-
this.messaging.feedStateUpdate(raw as IRoomEvent).catch((e) => {
503-
logger.error("Error sending state update to widget: ", e);
504-
});
505-
};
506-
507474
private onToDeviceEvent = async (ev: MatrixEvent): Promise<void> => {
508475
await this.client.decryptEventIfNeeded(ev);
509476
if (ev.isDecryptionFailure()) return;
@@ -603,7 +570,7 @@ export class StopGapWidget extends EventEmitter {
603570
this.eventsToFeed.add(ev);
604571
} else {
605572
const raw = ev.getEffectiveEvent();
606-
this.messaging.feedEvent(raw as IRoomEvent).catch((e) => {
573+
this.messaging.feedEvent(raw as IRoomEvent, this.eventListenerRoomId!).catch((e) => {
607574
logger.error("Error sending event to widget: ", e);
608575
});
609576
}

src/stores/widgets/StopGapWidgetDriver.ts

Lines changed: 60 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
MatrixCapabilities,
2020
OpenIDRequestState,
2121
SimpleObservable,
22+
Symbols,
2223
Widget,
2324
WidgetDriver,
2425
WidgetEventCapability,
@@ -35,6 +36,7 @@ import {
3536
IContent,
3637
MatrixError,
3738
MatrixEvent,
39+
Room,
3840
Direction,
3941
THREAD_RELATION_TYPE,
4042
SendDelayedEventResponse,
@@ -467,69 +469,70 @@ export class StopGapWidgetDriver extends WidgetDriver {
467469
}
468470
}
469471

470-
/**
471-
* Reads all events of the given type, and optionally `msgtype` (if applicable/defined),
472-
* the user has access to. The widget API will have already verified that the widget is
473-
* capable of receiving the events. Less events than the limit are allowed to be returned,
474-
* but not more.
475-
* @param roomId The ID of the room to look within.
476-
* @param eventType The event type to be read.
477-
* @param msgtype The msgtype of the events to be read, if applicable/defined.
478-
* @param stateKey The state key of the events to be read, if applicable/defined.
479-
* @param limit The maximum number of events to retrieve. Will be zero to denote "as many as
480-
* possible".
481-
* @param since When null, retrieves the number of events specified by the "limit" parameter.
482-
* Otherwise, the event ID at which only subsequent events will be returned, as many as specified
483-
* in "limit".
484-
* @returns {Promise<IRoomEvent[]>} Resolves to the room events, or an empty array.
485-
*/
486-
public async readRoomTimeline(
487-
roomId: string,
472+
private pickRooms(roomIds?: (string | Symbols.AnyRoom)[]): Room[] {
473+
const client = MatrixClientPeg.get();
474+
if (!client) throw new Error("Not attached to a client");
475+
476+
const targetRooms = roomIds
477+
? roomIds.includes(Symbols.AnyRoom)
478+
? client.getVisibleRooms(SettingsStore.getValue("feature_dynamic_room_predecessors"))
479+
: roomIds.map((r) => client.getRoom(r))
480+
: [client.getRoom(SdkContextClass.instance.roomViewStore.getRoomId()!)];
481+
return targetRooms.filter((r) => !!r) as Room[];
482+
}
483+
484+
public async readRoomEvents(
488485
eventType: string,
489486
msgtype: string | undefined,
490-
stateKey: string | undefined,
491-
limit: number,
492-
since: string | undefined,
487+
limitPerRoom: number,
488+
roomIds?: (string | Symbols.AnyRoom)[],
493489
): Promise<IRoomEvent[]> {
494-
limit = limit > 0 ? Math.min(limit, Number.MAX_SAFE_INTEGER) : Number.MAX_SAFE_INTEGER; // relatively arbitrary
495-
496-
const room = MatrixClientPeg.safeGet().getRoom(roomId);
497-
if (room === null) return [];
498-
const results: MatrixEvent[] = [];
499-
const events = room.getLiveTimeline().getEvents(); // timelines are most recent last
500-
for (let i = events.length - 1; i >= 0; i--) {
501-
const ev = events[i];
502-
if (results.length >= limit) break;
503-
if (since !== undefined && ev.getId() === since) break;
504-
505-
if (ev.getType() !== eventType || ev.isState()) continue;
506-
if (eventType === EventType.RoomMessage && msgtype && msgtype !== ev.getContent()["msgtype"]) continue;
507-
if (ev.getStateKey() !== undefined && stateKey !== undefined && ev.getStateKey() !== stateKey) continue;
508-
results.push(ev);
509-
}
490+
limitPerRoom = limitPerRoom > 0 ? Math.min(limitPerRoom, Number.MAX_SAFE_INTEGER) : Number.MAX_SAFE_INTEGER; // relatively arbitrary
491+
492+
const rooms = this.pickRooms(roomIds);
493+
const allResults: IRoomEvent[] = [];
494+
for (const room of rooms) {
495+
const results: MatrixEvent[] = [];
496+
const events = room.getLiveTimeline().getEvents(); // timelines are most recent last
497+
for (let i = events.length - 1; i > 0; i--) {
498+
if (results.length >= limitPerRoom) break;
499+
500+
const ev = events[i];
501+
if (ev.getType() !== eventType || ev.isState()) continue;
502+
if (eventType === EventType.RoomMessage && msgtype && msgtype !== ev.getContent()["msgtype"]) continue;
503+
results.push(ev);
504+
}
510505

511-
return results.map((e) => e.getEffectiveEvent() as IRoomEvent);
506+
results.forEach((e) => allResults.push(e.getEffectiveEvent() as IRoomEvent));
507+
}
508+
return allResults;
512509
}
513510

514-
/**
515-
* Reads the current values of all matching room state entries.
516-
* @param roomId The ID of the room.
517-
* @param eventType The event type of the entries to be read.
518-
* @param stateKey The state key of the entry to be read. If undefined,
519-
* all room state entries with a matching event type should be returned.
520-
* @returns {Promise<IRoomEvent[]>} Resolves to the events representing the
521-
* current values of the room state entries.
522-
*/
523-
public async readRoomState(roomId: string, eventType: string, stateKey: string | undefined): Promise<IRoomEvent[]> {
524-
const room = MatrixClientPeg.safeGet().getRoom(roomId);
525-
if (room === null) return [];
526-
const state = room.getLiveTimeline().getState(Direction.Forward);
527-
if (state === undefined) return [];
528-
529-
if (stateKey === undefined)
530-
return state.getStateEvents(eventType).map((e) => e.getEffectiveEvent() as IRoomEvent);
531-
const event = state.getStateEvents(eventType, stateKey);
532-
return event === null ? [] : [event.getEffectiveEvent() as IRoomEvent];
511+
public async readStateEvents(
512+
eventType: string,
513+
stateKey: string | undefined,
514+
limitPerRoom: number,
515+
roomIds?: (string | Symbols.AnyRoom)[],
516+
): Promise<IRoomEvent[]> {
517+
limitPerRoom = limitPerRoom > 0 ? Math.min(limitPerRoom, Number.MAX_SAFE_INTEGER) : Number.MAX_SAFE_INTEGER; // relatively arbitrary
518+
519+
const rooms = this.pickRooms(roomIds);
520+
const allResults: IRoomEvent[] = [];
521+
for (const room of rooms) {
522+
const results: MatrixEvent[] = [];
523+
const state = room.currentState.events.get(eventType);
524+
if (state) {
525+
if (stateKey === "" || !!stateKey) {
526+
const forKey = state.get(stateKey);
527+
if (forKey) results.push(forKey);
528+
} else {
529+
results.push(...Array.from(state.values()));
530+
}
531+
}
532+
533+
results.slice(0, limitPerRoom).forEach((e) => allResults.push(e.getEffectiveEvent() as IRoomEvent));
534+
}
535+
return allResults;
533536
}
534537

535538
public async askOpenID(observer: SimpleObservable<IOpenIDUpdate>): Promise<void> {
@@ -690,17 +693,6 @@ export class StopGapWidgetDriver extends WidgetDriver {
690693
return { file: blob };
691694
}
692695

693-
/**
694-
* Gets the IDs of all joined or invited rooms currently known to the
695-
* client.
696-
* @returns The room IDs.
697-
*/
698-
public getKnownRooms(): string[] {
699-
return MatrixClientPeg.safeGet()
700-
.getVisibleRooms(SettingsStore.getValue("feature_dynamic_room_predecessors"))
701-
.map((r) => r.roomId);
702-
}
703-
704696
/**
705697
* Expresses a {@link MatrixError} as a JSON payload
706698
* for use by Widget API error responses.

0 commit comments

Comments
 (0)