From 9697817c812eb292a2b1b85ced6529c1e28c6fa7 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 17 Dec 2024 12:12:26 +0000 Subject: [PATCH] Use mapped types around account data events Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/@types/matrix-js-sdk.d.ts | 28 +++++++++++++++++++ .../views/dialogs/devtools/AccountData.tsx | 4 +-- .../handlers/AccountSettingsHandler.ts | 13 +++++---- src/utils/device/clientInformation.ts | 7 +++-- src/utils/notifications.ts | 4 ++- test/unit-tests/Notifier-test.ts | 3 +- test/unit-tests/utils/notifications-test.ts | 11 ++++++-- 7 files changed, 55 insertions(+), 15 deletions(-) diff --git a/src/@types/matrix-js-sdk.d.ts b/src/@types/matrix-js-sdk.d.ts index 41ccfcbb3b..54aa28a470 100644 --- a/src/@types/matrix-js-sdk.d.ts +++ b/src/@types/matrix-js-sdk.d.ts @@ -11,6 +11,10 @@ import type { BLURHASH_FIELD } from "../utils/image-media"; import type { JitsiCallMemberEventType, JitsiCallMemberContent } from "../call-types"; import type { ILayoutStateEvent, WIDGET_LAYOUT_EVENT_TYPE } from "../stores/widgets/types"; import type { EncryptedFile } from "matrix-js-sdk/src/types"; +import { PosthogAnalytics } from "../PosthogAnalytics.ts"; +import { string } from "css-tree"; +import { DeviceClientInformation } from "../utils/device/clientInformation.ts"; +import { UserWidget } from "../utils/WidgetUtils.ts"; // Extend Matrix JS SDK types via Typescript declaration merging to support unspecced event fields and types declare module "matrix-js-sdk/src/types" { @@ -57,6 +61,30 @@ declare module "matrix-js-sdk/src/types" { }; } + export interface AccountDataEvents { + [PosthogAnalytics.ANALYTICS_EVENT_TYPE]: { + id: string; + pseudonymousAnalyticsOptIn?: boolean; + }; + [key: `io.element.matrix_client_information.${string}`]: DeviceClientInformation; + "im.vector.setting.breadcrumbs": { recent_rooms: string[] }; + "io.element.recent_emoji": { recent_emoji: string[] }; + "im.vector.setting.integration_provisioning": { enabled: boolean }; + "im.vector.web.settings": Record; + + "org.matrix.preview_urls": { disable: boolean }; + + // This is not yet in the Matrix spec yet is being used as if it was + "m.widgets": { + [widgetId: string]: UserWidget; + }; + + // This is not in the Matrix spec yet seems to use an `m.` prefix + "m.accepted_terms": { + accepted: string[]; + }; + } + export interface AudioContent { // MSC1767 + Ideals of MSC2516 as MSC3245 // https://github.com/matrix-org/matrix-doc/pull/3245 diff --git a/src/components/views/dialogs/devtools/AccountData.tsx b/src/components/views/dialogs/devtools/AccountData.tsx index f1fc081b00..920cab8860 100644 --- a/src/components/views/dialogs/devtools/AccountData.tsx +++ b/src/components/views/dialogs/devtools/AccountData.tsx @@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details. */ import React, { useContext, useMemo, useState } from "react"; -import { IContent, MatrixEvent } from "matrix-js-sdk/src/matrix"; +import { AccountDataEvents, IContent, MatrixEvent } from "matrix-js-sdk/src/matrix"; import BaseTool, { DevtoolsContext, IDevtoolsProps } from "./BaseTool"; import MatrixClientContext from "../../../../contexts/MatrixClientContext"; @@ -21,7 +21,7 @@ export const AccountDataEventEditor: React.FC = ({ mxEvent, onBack const fields = useMemo(() => [eventTypeField(mxEvent?.getType())], [mxEvent]); - const onSend = async ([eventType]: string[], content?: IContent): Promise => { + const onSend = async ([eventType]: Array, content?: IContent): Promise => { await cli.setAccountData(eventType, content || {}); }; diff --git a/src/settings/handlers/AccountSettingsHandler.ts b/src/settings/handlers/AccountSettingsHandler.ts index 051e6fc7a6..60fb6eed19 100644 --- a/src/settings/handlers/AccountSettingsHandler.ts +++ b/src/settings/handlers/AccountSettingsHandler.ts @@ -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 { ClientEvent, MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix"; +import { AccountDataEvents, ClientEvent, MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix"; import { defer } from "matrix-js-sdk/src/utils"; import { isEqual } from "lodash"; @@ -140,10 +140,10 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa } // helper function to set account data then await it being echoed back - private async setAccountData( - eventType: string, - field: string, - value: any, + private async setAccountData( + eventType: K, + field: F, + value: AccountDataEvents[K][F], legacyEventType?: string, ): Promise { let content = this.getSettings(eventType); @@ -161,7 +161,8 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa // which race between different lines. const deferred = defer(); const handler = (event: MatrixEvent): void => { - if (event.getType() !== eventType || !isEqual(event.getContent()[field], value)) return; + if (event.getType() !== eventType || !isEqual(event.getContent()[field], value)) + return; this.client.off(ClientEvent.AccountData, handler); deferred.resolve(); }; diff --git a/src/utils/device/clientInformation.ts b/src/utils/device/clientInformation.ts index 500bfdd550..e88c6b2bc0 100644 --- a/src/utils/device/clientInformation.ts +++ b/src/utils/device/clientInformation.ts @@ -6,7 +6,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 } from "matrix-js-sdk/src/matrix"; +import { AccountDataEvents, MatrixClient } from "matrix-js-sdk/src/matrix"; import BasePlatform from "../../BasePlatform"; import { IConfigOptions } from "../../IConfigOptions"; @@ -34,7 +34,8 @@ const formatUrl = (): string | undefined => { }; const clientInformationEventPrefix = "io.element.matrix_client_information."; -export const getClientInformationEventType = (deviceId: string): string => `${clientInformationEventPrefix}${deviceId}`; +export const getClientInformationEventType = (deviceId: string): `${typeof clientInformationEventPrefix}${string}` => + `${clientInformationEventPrefix}${deviceId}`; /** * Record extra client information for the current device @@ -70,7 +71,7 @@ export const pruneClientInformation = (validDeviceIds: string[], matrixClient: M } const [, deviceId] = event.getType().split(clientInformationEventPrefix); if (deviceId && !validDeviceIds.includes(deviceId)) { - matrixClient.deleteAccountData(event.getType()); + matrixClient.deleteAccountData(event.getType() as keyof AccountDataEvents); } }); }; diff --git a/src/utils/notifications.ts b/src/utils/notifications.ts index 30d2948380..164b888d02 100644 --- a/src/utils/notifications.ts +++ b/src/utils/notifications.ts @@ -40,7 +40,9 @@ export const deviceNotificationSettingsKeys = [ "audioNotificationsEnabled", ]; -export function getLocalNotificationAccountDataEventType(deviceId: string | null): string { +export function getLocalNotificationAccountDataEventType( + deviceId: string | null, +): `${typeof LOCAL_NOTIFICATION_SETTINGS_PREFIX.name}.${string}` { return `${LOCAL_NOTIFICATION_SETTINGS_PREFIX.name}.${deviceId}`; } diff --git a/test/unit-tests/Notifier-test.ts b/test/unit-tests/Notifier-test.ts index f94f50724d..4c4897dbc3 100644 --- a/test/unit-tests/Notifier-test.ts +++ b/test/unit-tests/Notifier-test.ts @@ -16,6 +16,7 @@ import { IContent, MatrixEvent, SyncState, + AccountDataEvents, } from "matrix-js-sdk/src/matrix"; import { waitFor } from "jest-matrix-react"; import { CallMembership, MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc"; @@ -69,7 +70,7 @@ describe("Notifier", () => { let MockPlatform: MockedObject; let mockClient: MockedObject; let testRoom: Room; - let accountDataEventKey: string; + let accountDataEventKey: keyof AccountDataEvents; let accountDataStore: Record = {}; let mockSettings: Record = {}; diff --git a/test/unit-tests/utils/notifications-test.ts b/test/unit-tests/utils/notifications-test.ts index 6cf6e3496b..2432d477a9 100644 --- a/test/unit-tests/utils/notifications-test.ts +++ b/test/unit-tests/utils/notifications-test.ts @@ -6,7 +6,14 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import { MatrixEvent, NotificationCountType, Room, MatrixClient, ReceiptType } from "matrix-js-sdk/src/matrix"; +import { + MatrixEvent, + NotificationCountType, + Room, + MatrixClient, + ReceiptType, + AccountDataEvents, +} from "matrix-js-sdk/src/matrix"; import { Mocked, mocked } from "jest-mock"; import { @@ -32,7 +39,7 @@ jest.mock("../../../src/settings/SettingsStore"); describe("notifications", () => { let accountDataStore: Record = {}; let mockClient: Mocked; - let accountDataEventKey: string; + let accountDataEventKey: keyof AccountDataEvents; beforeEach(() => { jest.clearAllMocks();