diff --git a/src/AddThreepid.ts b/src/AddThreepid.ts index d8cfb62777..e115441f5c 100644 --- a/src/AddThreepid.ts +++ b/src/AddThreepid.ts @@ -24,6 +24,7 @@ import { MatrixClient, } from "matrix-js-sdk/src/matrix"; import { MatrixError, HTTPError } from "matrix-js-sdk/src/matrix"; +import { IThreepid } from "matrix-js-sdk/src/@types/threepids"; import Modal from "./Modal"; import { _t, UserFriendlyError } from "./languageHandler"; @@ -45,6 +46,9 @@ export type Binding = { errorTitle: string; }; +// IThreepid modified stripping validated_at and added_at as they aren't necessary for our UI +export type ThirdPartyIdentifier = Omit; + /** * Allows a user to add a third party identifier to their homeserver and, * optionally, the identity servers. diff --git a/src/SlidingSyncManager.ts b/src/SlidingSyncManager.ts index 9af442932e..c59075bbc9 100644 --- a/src/SlidingSyncManager.ts +++ b/src/SlidingSyncManager.ts @@ -55,7 +55,7 @@ import { SlidingSync, } from "matrix-js-sdk/src/sliding-sync"; import { logger } from "matrix-js-sdk/src/logger"; -import { IDeferred, defer, sleep } from "matrix-js-sdk/src/utils"; +import { defer, sleep } from "matrix-js-sdk/src/utils"; // how long to long poll for const SLIDING_SYNC_TIMEOUT_MS = 20 * 1000; @@ -117,14 +117,10 @@ export class SlidingSyncManager { public static readonly ListSearch = "search_list"; private static readonly internalInstance = new SlidingSyncManager(); - public slidingSync: SlidingSync; + public slidingSync?: SlidingSync; private client?: MatrixClient; - private configureDefer: IDeferred; - - public constructor() { - this.configureDefer = defer(); - } + private configureDefer = defer(); public static get instance(): SlidingSyncManager { return SlidingSyncManager.internalInstance; @@ -185,7 +181,7 @@ export class SlidingSyncManager { public async ensureListRegistered(listKey: string, updateArgs: PartialSlidingSyncRequest): Promise { logger.debug("ensureListRegistered:::", listKey, updateArgs); await this.configureDefer.promise; - let list = this.slidingSync.getListParams(listKey); + let list = this.slidingSync!.getListParams(listKey); if (!list) { list = { ranges: [[0, 20]], @@ -224,19 +220,19 @@ export class SlidingSyncManager { try { // if we only have range changes then call a different function so we don't nuke the list from before if (updateArgs.ranges && Object.keys(updateArgs).length === 1) { - await this.slidingSync.setListRanges(listKey, updateArgs.ranges); + await this.slidingSync!.setListRanges(listKey, updateArgs.ranges); } else { - await this.slidingSync.setList(listKey, list); + await this.slidingSync!.setList(listKey, list); } } catch (err) { logger.debug("ensureListRegistered: update failed txn_id=", err); } - return this.slidingSync.getListParams(listKey)!; + return this.slidingSync!.getListParams(listKey)!; } public async setRoomVisible(roomId: string, visible: boolean): Promise { await this.configureDefer.promise; - const subscriptions = this.slidingSync.getRoomSubscriptions(); + const subscriptions = this.slidingSync!.getRoomSubscriptions(); if (visible) { subscriptions.add(roomId); } else { @@ -253,9 +249,9 @@ export class SlidingSyncManager { logger.log("SlidingSync setRoomVisible:", roomId, visible, "shouldLazyLoad:", shouldLazyLoad); if (shouldLazyLoad) { // lazy load this room - this.slidingSync.useCustomSubscription(roomId, UNENCRYPTED_SUBSCRIPTION_NAME); + this.slidingSync!.useCustomSubscription(roomId, UNENCRYPTED_SUBSCRIPTION_NAME); } - const p = this.slidingSync.modifyRoomSubscriptions(subscriptions); + const p = this.slidingSync!.modifyRoomSubscriptions(subscriptions); if (room) { return roomId; // we have data already for this room, show immediately e.g it's in a list } @@ -287,7 +283,7 @@ export class SlidingSyncManager { [startIndex, endIndex], ]; if (firstTime) { - await this.slidingSync.setList(SlidingSyncManager.ListSearch, { + await this.slidingSync!.setList(SlidingSyncManager.ListSearch, { // e.g [0,19] [20,39] then [0,19] [40,59]. We keep [0,20] constantly to ensure // any changes to the list whilst spidering are caught. ranges: ranges, @@ -313,7 +309,7 @@ export class SlidingSyncManager { }, }); } else { - await this.slidingSync.setListRanges(SlidingSyncManager.ListSearch, ranges); + await this.slidingSync!.setListRanges(SlidingSyncManager.ListSearch, ranges); } } catch (err) { // do nothing, as we reject only when we get interrupted but that's fine as the next @@ -322,7 +318,7 @@ export class SlidingSyncManager { // gradually request more over time, even on errors. await sleep(gapBetweenRequestsMs); } - const listData = this.slidingSync.getListData(SlidingSyncManager.ListSearch)!; + const listData = this.slidingSync!.getListData(SlidingSyncManager.ListSearch)!; hasMore = endIndex + 1 < listData.joinedCount; startIndex += batchSize; firstTime = false; diff --git a/src/async-components/views/dialogs/security/CreateSecretStorageDialog.tsx b/src/async-components/views/dialogs/security/CreateSecretStorageDialog.tsx index bf39565a4f..62b4502cef 100644 --- a/src/async-components/views/dialogs/security/CreateSecretStorageDialog.tsx +++ b/src/async-components/views/dialogs/security/CreateSecretStorageDialog.tsx @@ -103,7 +103,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent(); private passphraseField = createRef(); @@ -270,6 +270,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { + if (!this.recoveryKey) return; const blob = new Blob([this.recoveryKey.encodedPrivateKey!], { type: "text/plain;charset=us-ascii", }); @@ -341,7 +342,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent this.recoveryKey, + createSecretStorageKey: async () => this.recoveryKey!, setupNewKeyBackup: true, setupNewSecretStorage: true, }); @@ -357,7 +358,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent this.recoveryKey, + createSecretStorageKey: async () => this.recoveryKey!, keyBackupInfo: this.state.backupInfo!, setupNewKeyBackup: !this.state.backupInfo, getKeyBackupPassphrase: async (): Promise => { @@ -762,7 +763,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent
- {this.recoveryKey.encodedPrivateKey} + {this.recoveryKey?.encodedPrivateKey}
{ let isAlphabetical = RoomListStore.instance.getTagSorting(this.props.tagId) === SortAlgorithm.Alphabetic; let isUnreadFirst = RoomListStore.instance.getListOrder(this.props.tagId) === ListAlgorithm.Importance; if (this.slidingSyncMode) { - const slidingList = SlidingSyncManager.instance.slidingSync.getListParams(this.props.tagId); + const slidingList = SlidingSyncManager.instance.slidingSync?.getListParams(this.props.tagId); isAlphabetical = (slidingList?.sort || [])[0] === "by_name"; isUnreadFirst = (slidingList?.sort || [])[0] === "by_notification_level"; } diff --git a/src/components/views/settings/account/EmailAddresses.tsx b/src/components/views/settings/account/EmailAddresses.tsx index 3d7fe2380e..36d00d301c 100644 --- a/src/components/views/settings/account/EmailAddresses.tsx +++ b/src/components/views/settings/account/EmailAddresses.tsx @@ -16,7 +16,7 @@ limitations under the License. */ import React from "react"; -import { IThreepid, ThreepidMedium } from "matrix-js-sdk/src/@types/threepids"; +import { ThreepidMedium } from "matrix-js-sdk/src/@types/threepids"; import { logger } from "matrix-js-sdk/src/logger"; import { MatrixError } from "matrix-js-sdk/src/matrix"; @@ -25,7 +25,7 @@ import { MatrixClientPeg } from "../../../../MatrixClientPeg"; import Field from "../../elements/Field"; import AccessibleButton, { ButtonEvent } from "../../elements/AccessibleButton"; import * as Email from "../../../../email"; -import AddThreepid from "../../../../AddThreepid"; +import AddThreepid, { ThirdPartyIdentifier } from "../../../../AddThreepid"; import Modal from "../../../../Modal"; import ErrorDialog, { extractErrorMessageFromError } from "../../dialogs/ErrorDialog"; @@ -42,8 +42,8 @@ that is available. */ interface IExistingEmailAddressProps { - email: IThreepid; - onRemoved: (emails: IThreepid) => void; + email: ThirdPartyIdentifier; + onRemoved: (emails: ThirdPartyIdentifier) => void; } interface IExistingEmailAddressState { @@ -130,8 +130,8 @@ export class ExistingEmailAddress extends React.Component[]) => void; + emails: ThirdPartyIdentifier[]; + onEmailsChange: (emails: ThirdPartyIdentifier[]) => void; } interface IState { @@ -153,7 +153,7 @@ export default class EmailAddresses extends React.Component { }; } - private onRemoved = (address: IThreepid): void => { + private onRemoved = (address: ThirdPartyIdentifier): void => { const emails = this.props.emails.filter((e) => e !== address); this.props.onEmailsChange(emails); }; diff --git a/src/components/views/settings/account/PhoneNumbers.tsx b/src/components/views/settings/account/PhoneNumbers.tsx index f7a4109ae7..fe89b47134 100644 --- a/src/components/views/settings/account/PhoneNumbers.tsx +++ b/src/components/views/settings/account/PhoneNumbers.tsx @@ -16,14 +16,14 @@ limitations under the License. */ import React from "react"; -import { IThreepid, ThreepidMedium } from "matrix-js-sdk/src/@types/threepids"; +import { ThreepidMedium } from "matrix-js-sdk/src/@types/threepids"; import { logger } from "matrix-js-sdk/src/logger"; import { _t, UserFriendlyError } from "../../../../languageHandler"; import { MatrixClientPeg } from "../../../../MatrixClientPeg"; import Field from "../../elements/Field"; import AccessibleButton, { ButtonEvent } from "../../elements/AccessibleButton"; -import AddThreepid from "../../../../AddThreepid"; +import AddThreepid, { ThirdPartyIdentifier } from "../../../../AddThreepid"; import CountryDropdown from "../../auth/CountryDropdown"; import Modal from "../../../../Modal"; import ErrorDialog, { extractErrorMessageFromError } from "../../dialogs/ErrorDialog"; @@ -37,8 +37,8 @@ This is a copy/paste of EmailAddresses, mostly. // TODO: Combine EmailAddresses and PhoneNumbers to be 3pid agnostic interface IExistingPhoneNumberProps { - msisdn: IThreepid; - onRemoved: (phoneNumber: IThreepid) => void; + msisdn: ThirdPartyIdentifier; + onRemoved: (phoneNumber: ThirdPartyIdentifier) => void; } interface IExistingPhoneNumberState { @@ -125,8 +125,8 @@ export class ExistingPhoneNumber extends React.Component[]) => void; + msisdns: ThirdPartyIdentifier[]; + onMsisdnsChange: (phoneNumbers: ThirdPartyIdentifier[]) => void; } interface IState { @@ -156,7 +156,7 @@ export default class PhoneNumbers extends React.Component { }; } - private onRemoved = (address: IThreepid): void => { + private onRemoved = (address: ThirdPartyIdentifier): void => { const msisdns = this.props.msisdns.filter((e) => e !== address); this.props.onMsisdnsChange(msisdns); }; diff --git a/src/components/views/settings/discovery/EmailAddresses.tsx b/src/components/views/settings/discovery/EmailAddresses.tsx index 01b6480d73..3f913c27d8 100644 --- a/src/components/views/settings/discovery/EmailAddresses.tsx +++ b/src/components/views/settings/discovery/EmailAddresses.tsx @@ -16,14 +16,13 @@ limitations under the License. */ import React from "react"; -import { IThreepid } from "matrix-js-sdk/src/@types/threepids"; import { logger } from "matrix-js-sdk/src/logger"; import { MatrixError } from "matrix-js-sdk/src/matrix"; import { _t, UserFriendlyError } from "../../../../languageHandler"; import { MatrixClientPeg } from "../../../../MatrixClientPeg"; import Modal from "../../../../Modal"; -import AddThreepid, { Binding } from "../../../../AddThreepid"; +import AddThreepid, { Binding, ThirdPartyIdentifier } from "../../../../AddThreepid"; import ErrorDialog, { extractErrorMessageFromError } from "../../dialogs/ErrorDialog"; import SettingsSubsection from "../shared/SettingsSubsection"; import InlineSpinner from "../../elements/InlineSpinner"; @@ -46,7 +45,7 @@ TODO: Reduce all the copying between account vs. discovery components. */ interface IEmailAddressProps { - email: IThreepid; + email: ThirdPartyIdentifier; } interface IEmailAddressState { @@ -259,7 +258,7 @@ export class EmailAddress extends React.Component void; @@ -87,8 +88,8 @@ interface IState { agreedUrls: string[]; resolve: (values: string[]) => void; }; - emails: IThreepid[]; - msisdns: IThreepid[]; + emails: ThirdPartyIdentifier[]; + msisdns: ThirdPartyIdentifier[]; loading3pids: boolean; // whether or not the emails and msisdns have been loaded canChangePassword: boolean; idServerName?: string; @@ -156,11 +157,11 @@ export default class GeneralUserSettingsTab extends React.Component { + private onEmailsChange = (emails: ThirdPartyIdentifier[]): void => { this.setState({ emails }); }; - private onMsisdnsChange = (msisdns: IThreepid[]): void => { + private onMsisdnsChange = (msisdns: ThirdPartyIdentifier[]): void => { this.setState({ msisdns }); }; diff --git a/src/hooks/useSlidingSyncRoomSearch.ts b/src/hooks/useSlidingSyncRoomSearch.ts index 5cf1f6bea8..2a9d12d896 100644 --- a/src/hooks/useSlidingSyncRoomSearch.ts +++ b/src/hooks/useSlidingSyncRoomSearch.ts @@ -56,7 +56,7 @@ export const useSlidingSyncRoomSearch = (): { }, }); const rooms: Room[] = []; - const { roomIndexToRoomId } = SlidingSyncManager.instance.slidingSync.getListData( + const { roomIndexToRoomId } = SlidingSyncManager.instance.slidingSync!.getListData( SlidingSyncManager.ListSearch, )!; let i = 0; diff --git a/src/stores/room-list/SlidingRoomListStore.ts b/src/stores/room-list/SlidingRoomListStore.ts index 0d615207ae..672c0384ca 100644 --- a/src/stores/room-list/SlidingRoomListStore.ts +++ b/src/stores/room-list/SlidingRoomListStore.ts @@ -164,7 +164,7 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient impl // check all lists for each tag we know about and see if the room is there const tags: TagID[] = []; for (const tagId in this.tagIdToSortAlgo) { - const listData = this.context.slidingSyncManager.slidingSync.getListData(tagId); + const listData = this.context.slidingSyncManager.slidingSync?.getListData(tagId); if (!listData) { continue; } @@ -294,7 +294,7 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient impl if (room) { // resort it based on the slidingSync view of the list. This may cause this old sticky // room to cease to exist. - const listData = this.context.slidingSyncManager.slidingSync.getListData(tagId); + const listData = this.context.slidingSyncManager.slidingSync?.getListData(tagId); if (!listData) { continue; } @@ -313,7 +313,7 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient impl protected async onReady(): Promise { logger.info("SlidingRoomListStore.onReady"); // permanent listeners: never get destroyed. Could be an issue if we want to test this in isolation. - this.context.slidingSyncManager.slidingSync.on(SlidingSyncEvent.List, this.onSlidingSyncListUpdate.bind(this)); + this.context.slidingSyncManager.slidingSync!.on(SlidingSyncEvent.List, this.onSlidingSyncListUpdate.bind(this)); this.context.roomViewStore.addListener(UPDATE_EVENT, this.onRoomViewStoreUpdated.bind(this)); this.context.spaceStore.on(UPDATE_SELECTED_SPACE, this.onSelectedSpaceUpdated.bind(this)); if (this.context.spaceStore.activeSpace) { diff --git a/test/stores/room-list/SlidingRoomListStore-test.ts b/test/stores/room-list/SlidingRoomListStore-test.ts index 8d02ace27d..244688e3cd 100644 --- a/test/stores/room-list/SlidingRoomListStore-test.ts +++ b/test/stores/room-list/SlidingRoomListStore-test.ts @@ -194,7 +194,7 @@ describe("SlidingRoomListStore", () => { }, }, }; - mocked(context._SlidingSyncManager!.slidingSync.getListData).mockImplementation((key: string) => { + mocked(context._SlidingSyncManager!.slidingSync!.getListData).mockImplementation((key: string) => { return keyToListData[key] || null; }); @@ -237,7 +237,7 @@ describe("SlidingRoomListStore", () => { return null; }); const p = untilEmission(store, LISTS_UPDATE_EVENT); - context.slidingSyncManager.slidingSync.emit(SlidingSyncEvent.List, tagId, joinCount, roomIndexToRoomId); + context.slidingSyncManager.slidingSync!.emit(SlidingSyncEvent.List, tagId, joinCount, roomIndexToRoomId); await p; expect(store.getCount(tagId)).toEqual(joinCount); expect(store.orderedLists[tagId]).toEqual(rooms); @@ -271,7 +271,7 @@ describe("SlidingRoomListStore", () => { } return null; }); - mocked(context._SlidingSyncManager!.slidingSync.getListData).mockImplementation((key: string) => { + mocked(context._SlidingSyncManager!.slidingSync!.getListData).mockImplementation((key: string) => { if (key !== tagId) { return null; } @@ -281,7 +281,7 @@ describe("SlidingRoomListStore", () => { }; }); let p = untilEmission(store, LISTS_UPDATE_EVENT); - context.slidingSyncManager.slidingSync.emit(SlidingSyncEvent.List, tagId, joinCount, roomIndexToRoomId); + context.slidingSyncManager.slidingSync!.emit(SlidingSyncEvent.List, tagId, joinCount, roomIndexToRoomId); await p; expect(store.orderedLists[tagId]).toEqual([roomA, roomB, roomC]); @@ -294,7 +294,7 @@ describe("SlidingRoomListStore", () => { roomIndexToRoomId[1] = roomIdA; roomIndexToRoomId[2] = roomIdB; p = untilEmission(store, LISTS_UPDATE_EVENT); - context.slidingSyncManager.slidingSync.emit(SlidingSyncEvent.List, tagId, joinCount, roomIndexToRoomId); + context.slidingSyncManager.slidingSync!.emit(SlidingSyncEvent.List, tagId, joinCount, roomIndexToRoomId); await p; // check that B didn't move and that A was put below B @@ -332,7 +332,7 @@ describe("SlidingRoomListStore", () => { } return null; }); - mocked(context._SlidingSyncManager!.slidingSync.getListData).mockImplementation((key: string) => { + mocked(context._SlidingSyncManager!.slidingSync!.getListData).mockImplementation((key: string) => { if (key !== tagId) { return null; } @@ -342,7 +342,7 @@ describe("SlidingRoomListStore", () => { }; }); const p = untilEmission(store, LISTS_UPDATE_EVENT); - context.slidingSyncManager.slidingSync.emit(SlidingSyncEvent.List, tagId, joinCount, roomIndexToRoomId); + context.slidingSyncManager.slidingSync!.emit(SlidingSyncEvent.List, tagId, joinCount, roomIndexToRoomId); await p; expect(store.orderedLists[tagId]).toEqual([roomA, roomC]); });