Skip to content

Commit

Permalink
Remove the "out of sync" toast when we are no longer out of sync
Browse files Browse the repository at this point in the history
Receiving the crypto secrets via secret sharing should make the toast go away.
  • Loading branch information
richvdh committed Feb 24, 2025
1 parent 51ea94d commit 2a02a07
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
7 changes: 7 additions & 0 deletions src/DeviceListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export default class DeviceListener {
this.client.on(ClientEvent.AccountData, this.onAccountData);
this.client.on(ClientEvent.Sync, this.onSync);
this.client.on(RoomStateEvent.Events, this.onRoomStateEvents);
this.client.on(ClientEvent.ToDeviceEvent, this.onToDeviceEvent);
this.shouldRecordClientInformation = SettingsStore.getValue("deviceClientInformationOptIn");
// only configurable in config, so we don't need to watch the value
this.enableBulkUnverifiedSessionsReminder = SettingsStore.getValue(UIFeature.BulkUnverifiedSessionsReminder);
Expand All @@ -119,6 +120,7 @@ export default class DeviceListener {
this.client.removeListener(ClientEvent.AccountData, this.onAccountData);
this.client.removeListener(ClientEvent.Sync, this.onSync);
this.client.removeListener(RoomStateEvent.Events, this.onRoomStateEvents);
this.client.removeListener(ClientEvent.ToDeviceEvent, this.onToDeviceEvent);
}
SettingsStore.unwatchSetting(this.deviceClientInformationSettingWatcherRef);
dis.unregister(this.dispatcherRef);
Expand Down Expand Up @@ -226,6 +228,11 @@ export default class DeviceListener {
this.updateClientInformation();
};

private onToDeviceEvent = (event: MatrixEvent): void => {
// Receiving a 4S secret can mean we are in sync where we were not before.
if (event.getType() === EventType.SecretSend) this.recheck();
};

/**
* Fetch the key backup information from the server.
*
Expand Down
63 changes: 62 additions & 1 deletion test/unit-tests/DeviceListener-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@ Please see LICENSE files in the repository root for full details.
*/

import { type Mocked, mocked } from "jest-mock";
import { MatrixEvent, type Room, type MatrixClient, Device, ClientStoppedError } from "matrix-js-sdk/src/matrix";
import {
MatrixEvent,
type Room,
type MatrixClient,
Device,
ClientStoppedError,
ClientEvent,
} from "matrix-js-sdk/src/matrix";
import {
CryptoEvent,
type CrossSigningStatus,
Expand Down Expand Up @@ -350,6 +357,60 @@ describe("DeviceListener", () => {
);
});

it("shows an out-of-sync toast when one of the secrets is missing", async () => {
mockCrypto!.getCrossSigningStatus.mockResolvedValue({
publicKeysOnDevice: true,
privateKeysInSecretStorage: true,
privateKeysCachedLocally: {
masterKey: false,
selfSigningKey: true,
userSigningKey: true,
},
});

await createAndStart();

expect(SetupEncryptionToast.showToast).toHaveBeenCalledWith(
SetupEncryptionToast.Kind.KEY_STORAGE_OUT_OF_SYNC,
);
});

it("hides the out-of-sync toast when one of the secrets is missing", async () => {
mockCrypto!.isSecretStorageReady.mockResolvedValue(true);

// First show the toast
mockCrypto!.getCrossSigningStatus.mockResolvedValue({
publicKeysOnDevice: true,
privateKeysInSecretStorage: true,
privateKeysCachedLocally: {
masterKey: false,
selfSigningKey: true,
userSigningKey: true,
},
});

await createAndStart();

expect(SetupEncryptionToast.showToast).toHaveBeenCalledWith(
SetupEncryptionToast.Kind.KEY_STORAGE_OUT_OF_SYNC,
);

// Then, when we receive the secret, it should be hidden.
mockCrypto!.getCrossSigningStatus.mockResolvedValue({
publicKeysOnDevice: true,
privateKeysInSecretStorage: true,
privateKeysCachedLocally: {
masterKey: true,
selfSigningKey: true,
userSigningKey: true,
},
});

mockClient.emit(ClientEvent.ToDeviceEvent, new MatrixEvent({ type: "m.secret.send" }));
await flushPromises();
expect(SetupEncryptionToast.hideToast).toHaveBeenCalled();
});

it("shows set up recovery toast when user has a key backup available", async () => {
// non falsy response
mockCrypto.getKeyBackupInfo.mockResolvedValue({} as unknown as KeyBackupInfo);
Expand Down

0 comments on commit 2a02a07

Please sign in to comment.