diff --git a/src/DeviceListener.ts b/src/DeviceListener.ts index 6142621c311..ce1a0a26f04 100644 --- a/src/DeviceListener.ts +++ b/src/DeviceListener.ts @@ -47,6 +47,7 @@ import { removeClientInformation, } from "./utils/device/clientInformation"; import SettingsStore, { CallbackFn } from "./settings/SettingsStore"; +import { UIFeature } from "./settings/UIFeature"; const KEY_BACKUP_POLL_INTERVAL = 5 * 60 * 1000; @@ -68,6 +69,7 @@ export default class DeviceListener { private displayingToastsForDeviceIds = new Set(); private running = false; private shouldRecordClientInformation = false; + private enableBulkUnverifiedSessionsReminder = true; private deviceClientInformationSettingWatcherRef: string | undefined; public static sharedInstance() { @@ -86,6 +88,8 @@ export default class DeviceListener { MatrixClientPeg.get().on(ClientEvent.Sync, this.onSync); MatrixClientPeg.get().on(RoomStateEvent.Events, this.onRoomStateEvents); this.shouldRecordClientInformation = SettingsStore.getValue('deviceClientInformationOptIn'); + // only configurable in config, so we don't need to watch the value + this.enableBulkUnverifiedSessionsReminder = SettingsStore.getValue(UIFeature.BulkUnverifiedSessionsReminder); this.deviceClientInformationSettingWatcherRef = SettingsStore.watchSetting( 'deviceClientInformationOptIn', null, @@ -333,7 +337,11 @@ export default class DeviceListener { // Display or hide the batch toast for old unverified sessions // don't show the toast if the current device is unverified - if (oldUnverifiedDeviceIds.size > 0 && isCurrentDeviceTrusted) { + if ( + oldUnverifiedDeviceIds.size > 0 + && isCurrentDeviceTrusted + && this.enableBulkUnverifiedSessionsReminder + ) { showBulkUnverifiedSessionsToast(oldUnverifiedDeviceIds); } else { hideBulkUnverifiedSessionsToast(); diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 5a499dd128c..c6472868b77 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -1149,6 +1149,10 @@ export const SETTINGS: {[setting: string]: ISetting} = { supportedLevels: LEVELS_UI_FEATURE, default: true, }, + [UIFeature.BulkUnverifiedSessionsReminder]: { + supportedLevels: LEVELS_UI_FEATURE, + default: true, + }, // Electron-specific settings, they are stored by Electron and set/read over an IPC. // We store them over there are they are necessary to know before the renderer process launches. diff --git a/src/settings/UIFeature.ts b/src/settings/UIFeature.ts index 9dbe8c15779..89cbe203aaa 100644 --- a/src/settings/UIFeature.ts +++ b/src/settings/UIFeature.ts @@ -31,6 +31,7 @@ export enum UIFeature { AdvancedSettings = "UIFeature.advancedSettings", RoomHistorySettings = "UIFeature.roomHistorySettings", TimelineEnableRelativeDates = "UIFeature.timelineEnableRelativeDates", + BulkUnverifiedSessionsReminder = "UIFeature.BulkUnverifiedSessionsReminder", } export enum UIComponent { diff --git a/test/DeviceListener-test.ts b/test/DeviceListener-test.ts index 527a7f8c7be..03ad29956e4 100644 --- a/test/DeviceListener-test.ts +++ b/test/DeviceListener-test.ts @@ -34,6 +34,7 @@ import { Action } from "../src/dispatcher/actions"; import SettingsStore from "../src/settings/SettingsStore"; import { SettingLevel } from "../src/settings/SettingLevel"; import { getMockClientWithEventEmitter, mockPlatformPeg } from "./test-utils"; +import { UIFeature } from "../src/settings/UIFeature"; // don't litter test console with logs jest.mock("matrix-js-sdk/src/logger"); @@ -399,6 +400,9 @@ describe('DeviceListener', () => { // all devices verified by default mockClient!.checkDeviceTrust.mockReturnValue(deviceTrustVerified); mockClient!.deviceId = currentDevice.deviceId; + jest.spyOn(SettingsStore, 'getValue').mockImplementation( + settingName => settingName === UIFeature.BulkUnverifiedSessionsReminder, + ); }); describe('bulk unverified sessions toasts', () => { it('hides toast when cross signing is not ready', async () => { @@ -414,6 +418,24 @@ describe('DeviceListener', () => { expect(BulkUnverifiedSessionsToast.showToast).not.toHaveBeenCalled(); }); + it('hides toast when feature is disabled', async () => { + // BulkUnverifiedSessionsReminder set to false + jest.spyOn(SettingsStore, 'getValue').mockReturnValue(false); + // currentDevice, device2 are verified, device3 is unverified + // ie if reminder was enabled it should be shown + mockClient!.checkDeviceTrust.mockImplementation((_userId, deviceId) => { + switch (deviceId) { + case currentDevice.deviceId: + case device2.deviceId: + return deviceTrustVerified; + default: + return deviceTrustUnverified; + } + }); + await createAndStart(); + expect(BulkUnverifiedSessionsToast.hideToast).toHaveBeenCalled(); + }); + it('hides toast when current device is unverified', async () => { // device2 verified, current and device3 unverified mockClient!.checkDeviceTrust.mockImplementation((_userId, deviceId) => {