Harden types around room account data

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski
2024-12-19 16:56:46 +00:00
parent 22c5c0297f
commit d5e520727e
7 changed files with 37 additions and 13 deletions

View File

@@ -447,7 +447,7 @@ export class Client {
const client = await this.prepareClient();
return client.evaluate(
async (client, { type, content }) => {
await client.setAccountData(type, content);
await client.setAccountData(type as T, content as AccountDataEvents[T]);
},
{ type, content },
);

View File

@@ -88,6 +88,23 @@ declare module "matrix-js-sdk/src/types" {
};
}
export interface RoomAccountDataEvents {
// Room account data event for pinned events
"im.vector.room.read_pins": { event_ids: string[] };
// Room account data event for voip virtual rooms
"im.vector.is_virtual_room": { native_room: string };
// Room account data event for MSC2867 mark unread
"m.marked_unread": { unread: boolean };
"com.famedly.marked_unread": { unread: boolean };
// Element settings account data events
"org.matrix.room.preview_urls": { disable: boolean };
"im.vector.setting.allowed_widgets": { [eventId: string]: boolean };
"im.vector.web.settings": Record<string, any>;
}
export interface AudioContent {
// MSC1767 + Ideals of MSC2516 as MSC3245
// https://github.com/matrix-org/matrix-doc/pull/3245

View File

@@ -267,7 +267,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
// XXX: we could track RM per TimelineSet rather than per Room.
// but for now we just do it per room for simplicity.
if (this.props.manageReadMarkers) {
const readmarker = this.props.timelineSet.room?.getAccountData("m.fully_read");
const readmarker = this.props.timelineSet.room?.getAccountData(EventType.FullyRead);
if (readmarker) {
this.initialReadMarkerId = readmarker.getContent().event_id;
} else {

View File

@@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
*/
import React, { useContext, useMemo, useState } from "react";
import { AccountDataEvents, IContent, MatrixEvent } from "matrix-js-sdk/src/matrix";
import { AccountDataEvents, IContent, MatrixEvent, RoomAccountDataEvents } from "matrix-js-sdk/src/matrix";
import BaseTool, { DevtoolsContext, IDevtoolsProps } from "./BaseTool";
import MatrixClientContext from "../../../../contexts/MatrixClientContext";
@@ -35,7 +35,7 @@ export const RoomAccountDataEventEditor: React.FC<IEditorProps> = ({ mxEvent, on
const fields = useMemo(() => [eventTypeField(mxEvent?.getType())], [mxEvent]);
const onSend = async ([eventType]: string[], content?: IContent): Promise<void> => {
const onSend = async ([eventType]: Array<keyof RoomAccountDataEvents>, content?: IContent): Promise<void> => {
await cli.setRoomAccountData(context.room.roomId, eventType, content || {});
};

View File

@@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
import { MatrixClient, MatrixEvent, Room, RoomEvent } from "matrix-js-sdk/src/matrix";
import { MatrixClient, MatrixEvent, Room, RoomAccountDataEvents, RoomEvent } from "matrix-js-sdk/src/matrix";
import { defer } from "matrix-js-sdk/src/utils";
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
@@ -79,11 +79,14 @@ export default class RoomAccountSettingsHandler extends MatrixClientBackedSettin
}
// helper function to send room account data then await it being echoed back
private async setRoomAccountData(
private async setRoomAccountData<
K extends keyof RoomAccountDataEvents,
F extends null | keyof RoomAccountDataEvents[K],
>(
roomId: string,
eventType: string,
field: string | null,
value: any,
eventType: K,
field: F,
value: F extends keyof RoomAccountDataEvents[K] ? RoomAccountDataEvents[K][F] : RoomAccountDataEvents[K],
): Promise<void> {
let content: ReturnType<RoomAccountSettingsHandler["getSettings"]>;
@@ -99,7 +102,7 @@ export default class RoomAccountSettingsHandler extends MatrixClientBackedSettin
const deferred = defer<void>();
const handler = (event: MatrixEvent, room: Room): void => {
if (room.roomId !== roomId || event.getType() !== eventType) return;
if (field !== null && event.getContent()[field] !== value) return;
if (field !== null && event.getContent<RoomAccountDataEvents[K]>()[field] !== value) return;
this.client.off(RoomEvent.AccountData, handler);
deferred.resolve();
};
@@ -132,7 +135,7 @@ export default class RoomAccountSettingsHandler extends MatrixClientBackedSettin
return this.client && !this.client.isGuest();
}
private getSettings(roomId: string, eventType = DEFAULT_SETTINGS_EVENT_TYPE): any {
private getSettings(roomId: string, eventType: keyof RoomAccountDataEvents = DEFAULT_SETTINGS_EVENT_TYPE): any {
// TODO: [TS] Type return
const event = this.client.getRoom(roomId)?.getAccountData(eventType);
if (!event || !event.getContent()) return null;

View File

@@ -1373,7 +1373,11 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
private async setRootSpaceOrder(space: Room, order?: string): Promise<void> {
this.spaceOrderLocalEchoMap.set(space.roomId, order);
try {
await this.matrixClient?.setRoomAccountData(space.roomId, EventType.SpaceOrder, { order });
await this.matrixClient?.setRoomAccountData(
space.roomId,
EventType.SpaceOrder,
order !== undefined ? { order } : {},
);
} catch (e) {
logger.warn("Failed to set root space order", e);
if (this.spaceOrderLocalEchoMap.get(space.roomId) === order) {

View File

@@ -20,7 +20,7 @@ export function setToDefaultIdentityServer(matrixClient: MatrixClient): void {
const url = getDefaultIdentityServerUrl();
// Account data change will update localstorage, client, etc through dispatcher
matrixClient.setAccountData("m.identity_server", {
base_url: url,
base_url: url ?? null,
});
}