diff --git a/src/components/views/settings/tabs/user/EncryptionUserSettingsTab.tsx b/src/components/views/settings/tabs/user/EncryptionUserSettingsTab.tsx index 52ee2b1e60..a41e257b8c 100644 --- a/src/components/views/settings/tabs/user/EncryptionUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/EncryptionUserSettingsTab.tsx @@ -24,7 +24,7 @@ import { RecoveryPanelOutOfSync } from "../../encryption/RecoveryPanelOutOfSync" import { useTypedEventEmitterState } from "../../../../../hooks/useEventEmitter"; import { KeyStoragePanel } from "../../encryption/KeyStoragePanel"; import { DeleteKeyStoragePanel } from "../../encryption/DeleteKeyStoragePanel"; -import { DeviceListener, DeviceListenerEvents, type DeviceState } from "../../../../../device-listener"; +import { DeviceListener, CurrentDeviceEvents, type DeviceState } from "../../../../../device-listener"; import { useKeyStoragePanelViewModel } from "../../../../viewmodels/settings/encryption/KeyStoragePanelViewModel"; /** @@ -64,8 +64,8 @@ export function EncryptionUserSettingsTab({ initialState = "main" }: Readonly(initialState); const deviceState = useTypedEventEmitterState( - DeviceListener.sharedInstance(), - DeviceListenerEvents.DeviceState, + DeviceListener.sharedInstance().currentDeviceChangedEmitter, + CurrentDeviceEvents.DeviceStateChanged, (state?: DeviceState): DeviceState => { return state ?? DeviceListener.sharedInstance().getDeviceState(); }, diff --git a/src/device-listener/CurrentDeviceChangedEmitter.ts b/src/device-listener/CurrentDeviceChangedEmitter.ts new file mode 100644 index 0000000000..bca2c57324 --- /dev/null +++ b/src/device-listener/CurrentDeviceChangedEmitter.ts @@ -0,0 +1,36 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +import { TypedEventEmitter } from "matrix-js-sdk/src/matrix"; + +import { type DeviceState } from "."; + +/** + * The events emitted when the {@link DeviceState} of the current device + * changes. + */ +export const enum CurrentDeviceEvents { + DeviceStateChanged = "device_state", +} + +/** + * You must provide one of these if you listen to {@link CurrentDeviceEvents} + * emitted by {@link DeviceListenerCurrentDevice}. It specifies how to handle + * each type of event. + */ +type EventHandlerMap = { + [CurrentDeviceEvents.DeviceStateChanged]: (state: DeviceState) => void; +}; + +/** + * Emits events when the current device changes state. + */ +export class CurrentDeviceChangedEmitter extends TypedEventEmitter { + public onStateChanged(newState: DeviceState): void { + this.emit(CurrentDeviceEvents.DeviceStateChanged, newState); + } +} diff --git a/src/device-listener/DeviceListener.ts b/src/device-listener/DeviceListener.ts index fed7b9ad5a..4d62bf0ab5 100644 --- a/src/device-listener/DeviceListener.ts +++ b/src/device-listener/DeviceListener.ts @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com Please see LICENSE files in the repository root for full details. */ -import { type MatrixClient, ClientStoppedError, TypedEventEmitter } from "matrix-js-sdk/src/matrix"; +import { type MatrixClient, ClientStoppedError } from "matrix-js-sdk/src/matrix"; import { logger as baseLogger, LogSpan } from "matrix-js-sdk/src/logger"; import { type CryptoSessionStateChange } from "@matrix-org/analytics-events/types/typescript/CryptoSessionStateChange"; import { secureRandomString } from "matrix-js-sdk/src/randomstring"; @@ -20,22 +20,16 @@ import SdkConfig from "../SdkConfig"; import PlatformPeg from "../PlatformPeg"; import { recordClientInformation, removeClientInformation } from "../utils/device/clientInformation"; import SettingsStore, { type CallbackFn } from "../settings/SettingsStore"; -import { DeviceListenerOtherDevices, DeviceListenerCurrentDevice, type DeviceState } from "."; +import { + DeviceListenerOtherDevices, + DeviceListenerCurrentDevice, + type DeviceState, + CurrentDeviceChangedEmitter, +} from "."; const logger = baseLogger.getChild("DeviceListener:"); -/** - * The events emitted by {@link DeviceListener} - */ -export enum DeviceListenerEvents { - DeviceState = "device_state", -} - -type EventHandlerMap = { - [DeviceListenerEvents.DeviceState]: (state: DeviceState) => void; -}; - -export class DeviceListener extends TypedEventEmitter { +export class DeviceListener { private dispatcherRef?: string; /** @@ -44,11 +38,34 @@ export class DeviceListener extends TypedEventEmitter { + * return state ?? DeviceListener.sharedInstance().getDeviceState(); + * }, + * ); + * ``` + * + * Now `deviceState` will reflect the state of the current device and + * trigger an update when it changes. + */ + public currentDeviceChangedEmitter = new CurrentDeviceChangedEmitter(); + private running = false; // The client with which the instance is running. Only set if `running` is true, otherwise undefined. private client?: MatrixClient; diff --git a/src/device-listener/DeviceListenerCurrentDevice.ts b/src/device-listener/DeviceListenerCurrentDevice.ts index d74ee76507..92895663b0 100644 --- a/src/device-listener/DeviceListenerCurrentDevice.ts +++ b/src/device-listener/DeviceListenerCurrentDevice.ts @@ -18,7 +18,7 @@ import { ClientEvent, } from "matrix-js-sdk/src/matrix"; -import { type DeviceListener, type DeviceState, DeviceListenerEvents } from "."; +import { type DeviceListener, type DeviceState } from "."; import { hideToast as hideSetupEncryptionToast, showToast as showSetupEncryptionToast, @@ -263,7 +263,7 @@ export class DeviceListenerCurrentDevice { private async setDeviceState(newState: DeviceState, logSpan: LogSpan): Promise { this.deviceState = newState; - this.deviceListener.emit(DeviceListenerEvents.DeviceState, newState); + this.deviceListener.currentDeviceChangedEmitter.onStateChanged(newState); if (newState === "ok" || this.dismissedThisDeviceToast) { hideSetupEncryptionToast(); diff --git a/src/device-listener/index.ts b/src/device-listener/index.ts index af45ea9af8..03af6adec6 100644 --- a/src/device-listener/index.ts +++ b/src/device-listener/index.ts @@ -5,6 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com Please see LICENSE files in the repository root for full details. */ +export * from "./CurrentDeviceChangedEmitter"; export * from "./DeviceListener"; export * from "./DeviceListenerCurrentDevice"; export * from "./DeviceListenerOtherDevices";