Apply strictNullChecks
to src/utils/*!exportUtils
(#10455
* Apply `strictNullChecks` to `src/utils/exportUtils` * strict fix * fix strictNullChecks issues in some utils * fix error message * test coverage * lint * more strictNullChecks * small optimisation for getUniqueRoomsWithIndividuals * tidy * test coverage
This commit is contained in:
parent
4ed6e39067
commit
81a4498a8f
18 changed files with 143 additions and 81 deletions
|
@ -20,7 +20,6 @@ import { logger } from "matrix-js-sdk/src/logger";
|
|||
import { IClientWellKnown } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { _t, UserFriendlyError } from "../languageHandler";
|
||||
import { makeType } from "./TypeUtils";
|
||||
import SdkConfig from "../SdkConfig";
|
||||
import { ValidatedServerConfig } from "./ValidatedServerConfig";
|
||||
|
||||
|
@ -43,7 +42,7 @@ export default class AutoDiscoveryUtils {
|
|||
* @param {string | Error} error The error to check
|
||||
* @returns {boolean} True if the error is a liveliness error.
|
||||
*/
|
||||
public static isLivelinessError(error: string | Error): boolean {
|
||||
public static isLivelinessError(error?: string | Error | null): boolean {
|
||||
if (!error) return false;
|
||||
return !!LIVELINESS_DISCOVERY_ERRORS.find((e) =>
|
||||
typeof error === "string" ? e === error : e === error.message,
|
||||
|
@ -197,7 +196,7 @@ export default class AutoDiscoveryUtils {
|
|||
): ValidatedServerConfig {
|
||||
if (!discoveryResult || !discoveryResult["m.homeserver"]) {
|
||||
// This shouldn't happen without major misconfiguration, so we'll log a bit of information
|
||||
// in the log so we can find this bit of codee but otherwise tell teh user "it broke".
|
||||
// in the log so we can find this bit of code but otherwise tell the user "it broke".
|
||||
logger.error("Ended up in a state of not knowing which homeserver to connect to.");
|
||||
throw new UserFriendlyError("Unexpected error resolving homeserver configuration");
|
||||
}
|
||||
|
@ -216,7 +215,7 @@ export default class AutoDiscoveryUtils {
|
|||
// of Element.
|
||||
let preferredIdentityUrl = defaultConfig && defaultConfig["isUrl"];
|
||||
if (isResult && isResult.state === AutoDiscovery.SUCCESS) {
|
||||
preferredIdentityUrl = isResult["base_url"];
|
||||
preferredIdentityUrl = isResult["base_url"] ?? undefined;
|
||||
} else if (isResult && isResult.state !== AutoDiscovery.PROMPT) {
|
||||
logger.error("Error determining preferred identity server URL:", isResult);
|
||||
if (isResult.state === AutoDiscovery.FAIL_ERROR) {
|
||||
|
@ -244,6 +243,12 @@ export default class AutoDiscoveryUtils {
|
|||
}
|
||||
|
||||
const preferredHomeserverUrl = hsResult["base_url"];
|
||||
|
||||
if (!preferredHomeserverUrl) {
|
||||
logger.error("No homeserver URL configured");
|
||||
throw new UserFriendlyError("Unexpected error resolving homeserver configuration");
|
||||
}
|
||||
|
||||
let preferredHomeserverName = serverName ? serverName : hsResult["server_name"];
|
||||
|
||||
const url = new URL(preferredHomeserverUrl);
|
||||
|
@ -255,7 +260,7 @@ export default class AutoDiscoveryUtils {
|
|||
throw new UserFriendlyError("Unexpected error resolving homeserver configuration");
|
||||
}
|
||||
|
||||
return makeType(ValidatedServerConfig, {
|
||||
return {
|
||||
hsUrl: preferredHomeserverUrl,
|
||||
hsName: preferredHomeserverName,
|
||||
hsNameIsDifferent: url.hostname !== preferredHomeserverName,
|
||||
|
@ -263,6 +268,6 @@ export default class AutoDiscoveryUtils {
|
|||
isDefault: false,
|
||||
warning: hsResult.error,
|
||||
isNameResolvable: !isSynthetic,
|
||||
});
|
||||
} as ValidatedServerConfig;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,8 +103,6 @@ export default class DMRoomMap {
|
|||
}
|
||||
|
||||
private onAccountData = (ev: MatrixEvent): void => {
|
||||
console.log("onAccountData");
|
||||
|
||||
if (ev.getType() == EventType.Direct) {
|
||||
this.setMDirectFromContent(ev.getContent());
|
||||
this.userToRooms = null;
|
||||
|
@ -207,13 +205,16 @@ export default class DMRoomMap {
|
|||
|
||||
public getUniqueRoomsWithIndividuals(): { [userId: string]: Room } {
|
||||
if (!this.roomToUser) return {}; // No rooms means no map.
|
||||
return Object.keys(this.roomToUser)
|
||||
.map((r) => ({ userId: this.getUserIdForRoomId(r), room: this.matrixClient.getRoom(r) }))
|
||||
.filter((r) => r.userId && r.room?.getInvitedAndJoinedMemberCount() === 2)
|
||||
.reduce((obj, r) => {
|
||||
obj[r.userId] = r.room;
|
||||
return obj;
|
||||
}, {} as Record<string, Room>);
|
||||
// map roomToUser to valid rooms with two participants
|
||||
return Object.keys(this.roomToUser).reduce((acc, roomId: string) => {
|
||||
const userId = this.getUserIdForRoomId(roomId);
|
||||
const room = this.matrixClient.getRoom(roomId);
|
||||
const hasTwoMembers = room?.getInvitedAndJoinedMemberCount() === 2;
|
||||
if (userId && room && hasTwoMembers) {
|
||||
acc[userId] = room;
|
||||
}
|
||||
return acc;
|
||||
}, {} as Record<string, Room>);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -236,9 +237,7 @@ export default class DMRoomMap {
|
|||
// to avoid multiple devices fighting to correct
|
||||
// the account data, only try to send the corrected
|
||||
// version once.
|
||||
logger.warn(
|
||||
`Invalid m.direct account data detected ` + `(self-chats that shouldn't be), patching it up.`,
|
||||
);
|
||||
logger.warn(`Invalid m.direct account data detected (self-chats that shouldn't be), patching it up.`);
|
||||
if (neededPatching && !this.hasSentOutPatchDirectAccountDataPatch) {
|
||||
this.hasSentOutPatchDirectAccountDataPatch = true;
|
||||
this.matrixClient.setAccountData(EventType.Direct, userToRooms);
|
||||
|
|
|
@ -21,8 +21,8 @@ import SdkConfig from "../SdkConfig";
|
|||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
||||
import { Policies } from "../Terms";
|
||||
|
||||
export function getDefaultIdentityServerUrl(): string {
|
||||
return SdkConfig.get("validated_server_config").isUrl;
|
||||
export function getDefaultIdentityServerUrl(): string | undefined {
|
||||
return SdkConfig.get("validated_server_config")?.isUrl;
|
||||
}
|
||||
|
||||
export function setToDefaultIdentityServer(): void {
|
||||
|
|
|
@ -102,7 +102,10 @@ export class MediaEventHelper implements IDestroyable {
|
|||
}
|
||||
}
|
||||
|
||||
return fetch(this.media.thumbnailHttp).then((r) => r.blob());
|
||||
const thumbnailHttp = this.media.thumbnailHttp;
|
||||
if (!thumbnailHttp) return Promise.resolve(null);
|
||||
|
||||
return fetch(thumbnailHttp).then((r) => r.blob());
|
||||
};
|
||||
|
||||
public static isEligible(event: MatrixEvent): boolean {
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
Copyright 2019 New Vector Ltd
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a class of a given type using the objects defined. This
|
||||
* is a stopgap function while we don't have TypeScript interfaces.
|
||||
* In future, we'd define the `type` as an interface and just cast
|
||||
* it instead of cheating like we are here.
|
||||
* @param {Type} Type The type of class to construct.
|
||||
* @param {*} opts The options (properties) to set on the object.
|
||||
* @returns {*} The created object.
|
||||
*/
|
||||
export function makeType<T>(Type: { new (): T }, opts: Partial<T>): T {
|
||||
const c = new Type();
|
||||
Object.assign(c, opts);
|
||||
return c;
|
||||
}
|
|
@ -24,7 +24,7 @@ type FunctionWithUIA<R, A> = (auth?: IAuthData, ...args: A[]) => Promise<UIAResp
|
|||
|
||||
export function wrapRequestWithDialog<R, A = any>(
|
||||
requestFunction: FunctionWithUIA<R, A>,
|
||||
opts: Omit<InteractiveAuthDialogProps, "makeRequest" | "onFinished">,
|
||||
opts: Omit<InteractiveAuthDialogProps<R>, "makeRequest" | "onFinished">,
|
||||
): (...args: A[]) => Promise<R> {
|
||||
return async function (...args): Promise<R> {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
|
|
@ -119,6 +119,7 @@ export default class WidgetUtils {
|
|||
if (
|
||||
testUrl.protocol === scalarUrl.protocol &&
|
||||
testUrl.host === scalarUrl.host &&
|
||||
scalarUrl.pathname &&
|
||||
testUrl.pathname?.startsWith(scalarUrl.pathname)
|
||||
) {
|
||||
return true;
|
||||
|
|
|
@ -61,6 +61,12 @@ export async function leaveRoomBehaviour(roomId: string, retry = true, spinner =
|
|||
}
|
||||
|
||||
const room = cli.getRoom(roomId);
|
||||
|
||||
// should not encounter this
|
||||
if (!room) {
|
||||
throw new Error(`Expected to find room for id ${roomId}`);
|
||||
}
|
||||
|
||||
// await any queued messages being sent so that they do not fail
|
||||
await Promise.all(
|
||||
room
|
||||
|
|
|
@ -85,12 +85,14 @@ export const createMapSiteLinkFromEvent = (event: MatrixEvent): string | null =>
|
|||
if (mLocation !== undefined) {
|
||||
const uri = mLocation["uri"];
|
||||
if (uri !== undefined) {
|
||||
return makeMapSiteLink(parseGeoUri(uri));
|
||||
const geoCoords = parseGeoUri(uri);
|
||||
return geoCoords ? makeMapSiteLink(geoCoords) : null;
|
||||
}
|
||||
} else {
|
||||
const geoUri = content["geo_uri"];
|
||||
if (geoUri) {
|
||||
return makeMapSiteLink(parseGeoUri(geoUri));
|
||||
const geoCoords = parseGeoUri(geoUri);
|
||||
return geoCoords ? makeMapSiteLink(geoCoords) : null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -28,16 +28,23 @@ export const parseGeoUri = (uri: string): GeolocationCoordinates | undefined =>
|
|||
if (!m) return;
|
||||
const parts = m[1].split(";");
|
||||
const coords = parts[0].split(",");
|
||||
let uncertainty: number | null;
|
||||
let uncertainty: number | null | undefined = undefined;
|
||||
for (const param of parts.slice(1)) {
|
||||
const m = param.match(/u=(.*)/);
|
||||
if (m) uncertainty = parse(m[1]);
|
||||
}
|
||||
const latitude = parse(coords[0]);
|
||||
const longitude = parse(coords[1]);
|
||||
|
||||
if (latitude === null || longitude === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
latitude: parse(coords[0]),
|
||||
longitude: parse(coords[1]),
|
||||
latitude: latitude!,
|
||||
longitude: longitude!,
|
||||
altitude: parse(coords[2]),
|
||||
accuracy: uncertainty,
|
||||
accuracy: uncertainty!,
|
||||
altitudeAccuracy: null,
|
||||
heading: null,
|
||||
speed: null,
|
||||
|
|
|
@ -120,7 +120,7 @@ export const reorderLexicographically = (
|
|||
// verify the right move would be sufficient
|
||||
if (
|
||||
rightBoundIdx === newOrder.length - 1 &&
|
||||
(newOrder[rightBoundIdx] ? stringToBase(newOrder[rightBoundIdx].order) : BigInt(Number.MAX_VALUE)) -
|
||||
(newOrder[rightBoundIdx]?.order ? stringToBase(newOrder[rightBoundIdx].order!) : BigInt(Number.MAX_VALUE)) -
|
||||
prevBase <=
|
||||
rightBoundIdx - toIndex
|
||||
) {
|
||||
|
|
|
@ -65,6 +65,9 @@ export const lookupThreePids = async (
|
|||
if (threePids.length === 0) return [];
|
||||
|
||||
const token = await client.identityServer.getAccessToken();
|
||||
|
||||
if (!token) return [];
|
||||
|
||||
const lookedUp = await client.bulkLookupThreePids(
|
||||
threePids.map((t) => [t.isEmail ? "email" : "msisdn", t.userId]),
|
||||
token,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue