diff --git a/playwright/tsconfig.json b/playwright/tsconfig.json index cea25ebab7..55f979f3ce 100644 --- a/playwright/tsconfig.json +++ b/playwright/tsconfig.json @@ -10,6 +10,7 @@ }, "include": [ "**/*.ts", + "../src/@types/matrix-js-sdk.d.ts", "../node_modules/matrix-js-sdk/src/@types/*.d.ts", "../node_modules/matrix-js-sdk/node_modules/@matrix-org/olm/index.d.ts" ] diff --git a/src/@types/matrix-js-sdk.d.ts b/src/@types/matrix-js-sdk.d.ts index 1ce1702f1f..4a32ee0f37 100644 --- a/src/@types/matrix-js-sdk.d.ts +++ b/src/@types/matrix-js-sdk.d.ts @@ -14,14 +14,40 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { BLURHASH_FIELD } from "../utils/image-media"; +import type { IWidget } from "matrix-widget-api"; +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 { VoiceBroadcastInfoEventContent, VoiceBroadcastInfoEventType } from "../voice-broadcast/types"; // Matrix JS SDK extensions -declare module "matrix-js-sdk" { +declare module "matrix-js-sdk/src/types" { export interface FileInfo { /** * @see https://github.com/matrix-org/matrix-spec-proposals/pull/2448 */ [BLURHASH_FIELD]?: string; } + + export interface StateEvents { + // Jitsi-backed video room state events + [JitsiCallMemberEventType]: JitsiCallMemberContent; + + // Unstable widgets state events + "im.vector.modular.widgets": IWidget | {}; + [WIDGET_LAYOUT_EVENT_TYPE]: ILayoutStateEvent; + + // Unstable voice broadcast state events + [VoiceBroadcastInfoEventType]: VoiceBroadcastInfoEventContent; + + // Element custom state events + "im.vector.web.settings": Record; + "org.matrix.room.preview_urls": { disable: boolean }; + + // XXX unspecced usages of `m.room.*` events + "m.room.plumbing": { + status: string; + }; + "m.room.bot.options": unknown; + } } diff --git a/src/call-types.ts b/src/call-types.ts index d042faaaf3..40cd006dcc 100644 --- a/src/call-types.ts +++ b/src/call-types.ts @@ -17,3 +17,12 @@ limitations under the License. // Event type for room account data and room creation content used to mark rooms as virtual rooms // (and store the ID of their native room) export const VIRTUAL_ROOM_EVENT_TYPE = "im.vector.is_virtual_room"; + +export const JitsiCallMemberEventType = "io.element.video.member"; + +export interface JitsiCallMemberContent { + // Connected device IDs + devices: string[]; + // Time at which this state event should be considered stale + expires_ts: number; +} diff --git a/src/models/Call.ts b/src/models/Call.ts index 369f712534..eeae614bd8 100644 --- a/src/models/Call.ts +++ b/src/models/Call.ts @@ -57,6 +57,7 @@ import { UPDATE_EVENT } from "../stores/AsyncStore"; import { getJoinedNonFunctionalMembers } from "../utils/room/getJoinedNonFunctionalMembers"; import { isVideoRoom } from "../utils/video-rooms"; import { FontWatcher } from "../settings/watchers/FontWatcher"; +import { JitsiCallMemberContent, JitsiCallMemberEventType } from "../call-types"; const TIMEOUT_MS = 16000; @@ -321,18 +322,13 @@ export abstract class Call extends TypedEventEmitter this.setDisconnected(); } -export interface JitsiCallMemberContent { - // Connected device IDs - devices: string[]; - // Time at which this state event should be considered stale - expires_ts: number; -} +export type { JitsiCallMemberContent }; /** * A group call using Jitsi as a backend. */ export class JitsiCall extends Call { - public static readonly MEMBER_EVENT_TYPE = "io.element.video.member"; + public static readonly MEMBER_EVENT_TYPE = JitsiCallMemberEventType; public readonly STUCK_DEVICE_TIMEOUT_MS = 1000 * 60 * 60; // 1 hour private resendDevicesTimer: number | null = null; diff --git a/src/stores/widgets/WidgetLayoutStore.ts b/src/stores/widgets/WidgetLayoutStore.ts index c965836c8b..eef5d84d0d 100644 --- a/src/stores/widgets/WidgetLayoutStore.ts +++ b/src/stores/widgets/WidgetLayoutStore.ts @@ -28,55 +28,10 @@ import { ReadyWatchingStore } from "../ReadyWatchingStore"; import { SettingLevel } from "../../settings/SettingLevel"; import { arrayFastClone } from "../../utils/arrays"; import { UPDATE_EVENT } from "../AsyncStore"; +import { Container, IStoredLayout, ILayoutStateEvent, WIDGET_LAYOUT_EVENT_TYPE, IWidgetLayouts } from "./types"; -export const WIDGET_LAYOUT_EVENT_TYPE = "io.element.widgets.layout"; - -export enum Container { - // "Top" is the app drawer, and currently the only sensible value. - Top = "top", - - // "Right" is the right panel, and the default for widgets. Setting - // this as a container on a widget is essentially like saying "no - // changes needed", though this may change in the future. - Right = "right", - - Center = "center", -} - -export interface IStoredLayout { - // Where to store the widget. Required. - container: Container; - - // The index (order) to position the widgets in. Only applies for - // ordered containers (like the top container). Smaller numbers first, - // and conflicts resolved by comparing widget IDs. - index?: number; - - // Percentage (integer) for relative width of the container to consume. - // Clamped to 0-100 and may have minimums imposed upon it. Only applies - // to containers which support inner resizing (currently only the top - // container). - width?: number; - - // Percentage (integer) for relative height of the container. Note that - // this only applies to the top container currently, and that container - // will take the highest value among widgets in the container. Clamped - // to 0-100 and may have minimums imposed on it. - height?: number | null; - - // TODO: [Deferred] Maximizing (fullscreen) widgets by default. -} - -interface IWidgetLayouts { - [widgetId: string]: IStoredLayout; -} - -interface ILayoutStateEvent { - // TODO: [Deferred] Forced layout (fixed with no changes) - - // The widget layouts. - widgets: IWidgetLayouts; -} +export type { IStoredLayout, ILayoutStateEvent }; +export { Container, WIDGET_LAYOUT_EVENT_TYPE }; interface ILayoutSettings extends ILayoutStateEvent { overrides?: string; // event ID for layout state event, if present diff --git a/src/stores/widgets/types.ts b/src/stores/widgets/types.ts new file mode 100644 index 0000000000..36d5d86472 --- /dev/null +++ b/src/stores/widgets/types.ts @@ -0,0 +1,64 @@ +/* +Copyright 2024 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +export interface IStoredLayout { + // Where to store the widget. Required. + container: Container; + + // The index (order) to position the widgets in. Only applies for + // ordered containers (like the top container). Smaller numbers first, + // and conflicts resolved by comparing widget IDs. + index?: number; + + // Percentage (integer) for relative width of the container to consume. + // Clamped to 0-100 and may have minimums imposed upon it. Only applies + // to containers which support inner resizing (currently only the top + // container). + width?: number; + + // Percentage (integer) for relative height of the container. Note that + // this only applies to the top container currently, and that container + // will take the highest value among widgets in the container. Clamped + // to 0-100 and may have minimums imposed on it. + height?: number | null; + + // TODO: [Deferred] Maximizing (fullscreen) widgets by default. +} + +export interface IWidgetLayouts { + [widgetId: string]: IStoredLayout; +} + +export interface ILayoutStateEvent { + // TODO: [Deferred] Forced layout (fixed with no changes) + + // The widget layouts. + widgets: IWidgetLayouts; +} + +export const WIDGET_LAYOUT_EVENT_TYPE = "io.element.widgets.layout"; + +export enum Container { + // "Top" is the app drawer, and currently the only sensible value. + Top = "top", + + // "Right" is the right panel, and the default for widgets. Setting + // this as a container on a widget is essentially like saying "no + // changes needed", though this may change in the future. + Right = "right", + + Center = "center", +}