Conform more of the codebase to strictNullChecks
(#10518
* Conform more of the codebase to `strictNullChecks` * Iterate * Fix tests
This commit is contained in:
parent
e9cc88b872
commit
55d3548330
23 changed files with 107 additions and 99 deletions
|
@ -130,7 +130,7 @@ export async function loadSession(opts: ILoadSessionOpts = {}): Promise<boolean>
|
||||||
enableGuest = false;
|
enableGuest = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enableGuest && fragmentQueryParams.guest_user_id && fragmentQueryParams.guest_access_token) {
|
if (enableGuest && guestHsUrl && fragmentQueryParams.guest_user_id && fragmentQueryParams.guest_access_token) {
|
||||||
logger.log("Using guest access credentials");
|
logger.log("Using guest access credentials");
|
||||||
return doSetLoggedIn(
|
return doSetLoggedIn(
|
||||||
{
|
{
|
||||||
|
@ -150,7 +150,7 @@ export async function loadSession(opts: ILoadSessionOpts = {}): Promise<boolean>
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enableGuest) {
|
if (enableGuest && guestHsUrl) {
|
||||||
return registerAsGuest(guestHsUrl, guestIsUrl, defaultDeviceDisplayName);
|
return registerAsGuest(guestHsUrl, guestIsUrl, defaultDeviceDisplayName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ export async function loadSession(opts: ILoadSessionOpts = {}): Promise<boolean>
|
||||||
* session is for a guest user, if an owner exists. If there is no stored session,
|
* session is for a guest user, if an owner exists. If there is no stored session,
|
||||||
* return [null, null].
|
* return [null, null].
|
||||||
*/
|
*/
|
||||||
export async function getStoredSessionOwner(): Promise<[string, boolean]> {
|
export async function getStoredSessionOwner(): Promise<[string, boolean] | [null, null]> {
|
||||||
const { hsUrl, userId, hasAccessToken, isGuest } = await getStoredSessionVars();
|
const { hsUrl, userId, hasAccessToken, isGuest } = await getStoredSessionVars();
|
||||||
return hsUrl && userId && hasAccessToken ? [userId, isGuest] : [null, null];
|
return hsUrl && userId && hasAccessToken ? [userId, isGuest] : [null, null];
|
||||||
}
|
}
|
||||||
|
@ -259,7 +259,7 @@ export function attemptTokenLogin(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleInvalidStoreError(e: InvalidStoreError): Promise<void> {
|
export function handleInvalidStoreError(e: InvalidStoreError): Promise<void> | void {
|
||||||
if (e.reason === InvalidStoreError.TOGGLED_LAZY_LOADING) {
|
if (e.reason === InvalidStoreError.TOGGLED_LAZY_LOADING) {
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -292,7 +292,7 @@ export function handleInvalidStoreError(e: InvalidStoreError): Promise<void> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerAsGuest(hsUrl: string, isUrl: string, defaultDeviceDisplayName: string): Promise<boolean> {
|
function registerAsGuest(hsUrl: string, isUrl?: string, defaultDeviceDisplayName?: string): Promise<boolean> {
|
||||||
logger.log(`Doing guest login on ${hsUrl}`);
|
logger.log(`Doing guest login on ${hsUrl}`);
|
||||||
|
|
||||||
// create a temporary MatrixClient to do the login
|
// create a temporary MatrixClient to do the login
|
||||||
|
@ -346,14 +346,14 @@ export interface IStoredSession {
|
||||||
export async function getStoredSessionVars(): Promise<IStoredSession> {
|
export async function getStoredSessionVars(): Promise<IStoredSession> {
|
||||||
const hsUrl = localStorage.getItem(HOMESERVER_URL_KEY);
|
const hsUrl = localStorage.getItem(HOMESERVER_URL_KEY);
|
||||||
const isUrl = localStorage.getItem(ID_SERVER_URL_KEY);
|
const isUrl = localStorage.getItem(ID_SERVER_URL_KEY);
|
||||||
let accessToken;
|
let accessToken: string | undefined;
|
||||||
try {
|
try {
|
||||||
accessToken = await StorageManager.idbLoad("account", "mx_access_token");
|
accessToken = await StorageManager.idbLoad("account", "mx_access_token");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error("StorageManager.idbLoad failed for account:mx_access_token", e);
|
logger.error("StorageManager.idbLoad failed for account:mx_access_token", e);
|
||||||
}
|
}
|
||||||
if (!accessToken) {
|
if (!accessToken) {
|
||||||
accessToken = localStorage.getItem("mx_access_token");
|
accessToken = localStorage.getItem("mx_access_token") ?? undefined;
|
||||||
if (accessToken) {
|
if (accessToken) {
|
||||||
try {
|
try {
|
||||||
// try to migrate access token to IndexedDB if we can
|
// try to migrate access token to IndexedDB if we can
|
||||||
|
@ -370,7 +370,7 @@ export async function getStoredSessionVars(): Promise<IStoredSession> {
|
||||||
const userId = localStorage.getItem("mx_user_id");
|
const userId = localStorage.getItem("mx_user_id");
|
||||||
const deviceId = localStorage.getItem("mx_device_id");
|
const deviceId = localStorage.getItem("mx_device_id");
|
||||||
|
|
||||||
let isGuest;
|
let isGuest: boolean;
|
||||||
if (localStorage.getItem("mx_is_guest") !== null) {
|
if (localStorage.getItem("mx_is_guest") !== null) {
|
||||||
isGuest = localStorage.getItem("mx_is_guest") === "true";
|
isGuest = localStorage.getItem("mx_is_guest") === "true";
|
||||||
} else {
|
} else {
|
||||||
|
@ -447,7 +447,7 @@ export async function restoreFromLocalStorage(opts?: { ignoreGuest?: boolean }):
|
||||||
}
|
}
|
||||||
|
|
||||||
let decryptedAccessToken = accessToken;
|
let decryptedAccessToken = accessToken;
|
||||||
const pickleKey = await PlatformPeg.get().getPickleKey(userId, deviceId);
|
const pickleKey = await PlatformPeg.get()?.getPickleKey(userId, deviceId);
|
||||||
if (pickleKey) {
|
if (pickleKey) {
|
||||||
logger.log("Got pickle key");
|
logger.log("Got pickle key");
|
||||||
if (typeof accessToken !== "string") {
|
if (typeof accessToken !== "string") {
|
||||||
|
@ -471,7 +471,7 @@ export async function restoreFromLocalStorage(opts?: { ignoreGuest?: boolean }):
|
||||||
homeserverUrl: hsUrl,
|
homeserverUrl: hsUrl,
|
||||||
identityServerUrl: isUrl,
|
identityServerUrl: isUrl,
|
||||||
guest: isGuest,
|
guest: isGuest,
|
||||||
pickleKey: pickleKey,
|
pickleKey: pickleKey ?? undefined,
|
||||||
freshLogin: freshLogin,
|
freshLogin: freshLogin,
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
|
@ -561,7 +561,8 @@ export async function hydrateSession(credentials: IMatrixClientCreds): Promise<M
|
||||||
|
|
||||||
if (!credentials.pickleKey) {
|
if (!credentials.pickleKey) {
|
||||||
logger.info("Lifecycle#hydrateSession: Pickle key not provided - trying to get one");
|
logger.info("Lifecycle#hydrateSession: Pickle key not provided - trying to get one");
|
||||||
credentials.pickleKey = await PlatformPeg.get().getPickleKey(credentials.userId, credentials.deviceId);
|
credentials.pickleKey =
|
||||||
|
(await PlatformPeg.get()?.getPickleKey(credentials.userId, credentials.deviceId)) ?? undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return doSetLoggedIn(credentials, overwrite);
|
return doSetLoggedIn(credentials, overwrite);
|
||||||
|
@ -646,12 +647,10 @@ async function doSetLoggedIn(credentials: IMatrixClientCreds, clearStorageEnable
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
function showStorageEvictedDialog(): Promise<boolean> {
|
async function showStorageEvictedDialog(): Promise<boolean> {
|
||||||
return new Promise((resolve) => {
|
const { finished } = Modal.createDialog(StorageEvictedDialog);
|
||||||
Modal.createDialog(StorageEvictedDialog, {
|
const [ok] = await finished;
|
||||||
onFinished: resolve,
|
return !!ok;
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: Babel 6 requires the `transform-builtin-extend` plugin for this to satisfy
|
// Note: Babel 6 requires the `transform-builtin-extend` plugin for this to satisfy
|
||||||
|
@ -675,7 +674,7 @@ async function persistCredentials(credentials: IMatrixClientCreds): Promise<void
|
||||||
}
|
}
|
||||||
|
|
||||||
if (credentials.pickleKey) {
|
if (credentials.pickleKey) {
|
||||||
let encryptedAccessToken: IEncryptedPayload;
|
let encryptedAccessToken: IEncryptedPayload | undefined;
|
||||||
try {
|
try {
|
||||||
// try to encrypt the access token using the pickle key
|
// try to encrypt the access token using the pickle key
|
||||||
const encrKey = await pickleKeyToAesKey(credentials.pickleKey);
|
const encrKey = await pickleKeyToAesKey(credentials.pickleKey);
|
||||||
|
@ -741,7 +740,7 @@ export function logout(): void {
|
||||||
|
|
||||||
_isLoggingOut = true;
|
_isLoggingOut = true;
|
||||||
const client = MatrixClientPeg.get();
|
const client = MatrixClientPeg.get();
|
||||||
PlatformPeg.get().destroyPickleKey(client.getUserId(), client.getDeviceId());
|
PlatformPeg.get()?.destroyPickleKey(client.getSafeUserId(), client.getDeviceId());
|
||||||
client.logout(true).then(onLoggedOut, (err) => {
|
client.logout(true).then(onLoggedOut, (err) => {
|
||||||
// Just throwing an error here is going to be very unhelpful
|
// Just throwing an error here is going to be very unhelpful
|
||||||
// if you're trying to log out because your server's down and
|
// if you're trying to log out because your server's down and
|
||||||
|
@ -870,7 +869,7 @@ export async function onLoggedOut(): Promise<void> {
|
||||||
logger.log("Redirecting to external provider to finish logout");
|
logger.log("Redirecting to external provider to finish logout");
|
||||||
// XXX: Defer this so that it doesn't race with MatrixChat unmounting the world by going to /#/login
|
// XXX: Defer this so that it doesn't race with MatrixChat unmounting the world by going to /#/login
|
||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
window.location.href = SdkConfig.get().logout_redirect_url;
|
window.location.href = SdkConfig.get().logout_redirect_url!;
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
// Do this last to prevent racing `stopMatrixClient` and `on_logged_out` with MatrixChat handling Session.logged_out
|
// Do this last to prevent racing `stopMatrixClient` and `on_logged_out` with MatrixChat handling Session.logged_out
|
||||||
|
|
|
@ -160,7 +160,7 @@ class MatrixClientPegClass implements IMatrixClientPeg {
|
||||||
}
|
}
|
||||||
|
|
||||||
public currentUserIsJustRegistered(): boolean {
|
public currentUserIsJustRegistered(): boolean {
|
||||||
return this.matrixClient && this.matrixClient.credentials.userId === this.justRegisteredUserId;
|
return !!this.matrixClient && this.matrixClient.credentials.userId === this.justRegisteredUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public userRegisteredWithinLastHours(hours: number): boolean {
|
public userRegisteredWithinLastHours(hours: number): boolean {
|
||||||
|
|
|
@ -79,7 +79,7 @@ export default class EditHistoryMessage extends React.PureComponent<IProps, ISta
|
||||||
ConfirmAndWaitRedactDialog,
|
ConfirmAndWaitRedactDialog,
|
||||||
{
|
{
|
||||||
redact: async () => {
|
redact: async () => {
|
||||||
await cli.redactEvent(event.getRoomId()!, event.getId());
|
await cli.redactEvent(event.getRoomId()!, event.getId()!);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"mx_Dialog_confirmredact",
|
"mx_Dialog_confirmredact",
|
||||||
|
|
|
@ -56,7 +56,7 @@ export default class ReactionsRowButton extends React.PureComponent<IProps, ISta
|
||||||
public onClick = (): void => {
|
public onClick = (): void => {
|
||||||
const { mxEvent, myReactionEvent, content } = this.props;
|
const { mxEvent, myReactionEvent, content } = this.props;
|
||||||
if (myReactionEvent) {
|
if (myReactionEvent) {
|
||||||
this.context.redactEvent(mxEvent.getRoomId()!, myReactionEvent.getId());
|
this.context.redactEvent(mxEvent.getRoomId()!, myReactionEvent.getId()!);
|
||||||
} else {
|
} else {
|
||||||
this.context.sendEvent(mxEvent.getRoomId()!, "m.reaction", {
|
this.context.sendEvent(mxEvent.getRoomId()!, "m.reaction", {
|
||||||
"m.relates_to": {
|
"m.relates_to": {
|
||||||
|
|
|
@ -206,7 +206,7 @@ export default class PhoneNumbers extends React.Component<IProps, IState> {
|
||||||
const address = this.state.verifyMsisdn;
|
const address = this.state.verifyMsisdn;
|
||||||
this.state.addTask
|
this.state.addTask
|
||||||
?.haveMsisdnToken(token)
|
?.haveMsisdnToken(token)
|
||||||
.then(([finished]) => {
|
.then(([finished] = []) => {
|
||||||
let newPhoneNumber = this.state.newPhoneNumber;
|
let newPhoneNumber = this.state.newPhoneNumber;
|
||||||
if (finished) {
|
if (finished) {
|
||||||
const msisdns = [...this.props.msisdns, { address, medium: ThreepidMedium.Phone }];
|
const msisdns = [...this.props.msisdns, { address, medium: ThreepidMedium.Phone }];
|
||||||
|
|
|
@ -320,7 +320,7 @@ export default async function createRoom(opts: IOpts): Promise<string | null> {
|
||||||
return SpaceStore.instance.addRoomToSpace(
|
return SpaceStore.instance.addRoomToSpace(
|
||||||
opts.parentSpace,
|
opts.parentSpace,
|
||||||
roomId,
|
roomId,
|
||||||
[client.getDomain()],
|
[client.getDomain()!],
|
||||||
opts.suggested,
|
opts.suggested,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ export abstract class AsyncStoreWithClient<T extends Object> extends AsyncStore<
|
||||||
// Create an anonymous class to avoid code duplication
|
// Create an anonymous class to avoid code duplication
|
||||||
const asyncStore = this; // eslint-disable-line @typescript-eslint/no-this-alias
|
const asyncStore = this; // eslint-disable-line @typescript-eslint/no-this-alias
|
||||||
this.readyStore = new (class extends ReadyWatchingStore {
|
this.readyStore = new (class extends ReadyWatchingStore {
|
||||||
public get mxClient(): MatrixClient {
|
public get mxClient(): MatrixClient | null {
|
||||||
return this.matrixClient;
|
return this.matrixClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ export abstract class AsyncStoreWithClient<T extends Object> extends AsyncStore<
|
||||||
await this.readyStore.start();
|
await this.readyStore.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public get matrixClient(): MatrixClient {
|
public get matrixClient(): MatrixClient | null {
|
||||||
return this.readyStore.mxClient;
|
return this.readyStore.mxClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,7 +135,7 @@ export default class AutoRageshakeStore extends AsyncStoreWithClient<IState> {
|
||||||
...eventInfo,
|
...eventInfo,
|
||||||
recipient_rageshake: rageshakeURL,
|
recipient_rageshake: rageshakeURL,
|
||||||
};
|
};
|
||||||
this.matrixClient.sendToDevice(
|
this.matrixClient?.sendToDevice(
|
||||||
AUTO_RS_REQUEST,
|
AUTO_RS_REQUEST,
|
||||||
new Map([["messageContent.user_id", new Map([[messageContent.device_id, messageContent]])]]),
|
new Map([["messageContent.user_id", new Map([[messageContent.device_id, messageContent]])]]),
|
||||||
);
|
);
|
||||||
|
|
|
@ -21,7 +21,7 @@ import { ClientEvent } from "matrix-js-sdk/src/client";
|
||||||
import SettingsStore from "../settings/SettingsStore";
|
import SettingsStore from "../settings/SettingsStore";
|
||||||
import { AsyncStoreWithClient } from "./AsyncStoreWithClient";
|
import { AsyncStoreWithClient } from "./AsyncStoreWithClient";
|
||||||
import defaultDispatcher from "../dispatcher/dispatcher";
|
import defaultDispatcher from "../dispatcher/dispatcher";
|
||||||
import { arrayHasDiff } from "../utils/arrays";
|
import { arrayHasDiff, filterBoolean } from "../utils/arrays";
|
||||||
import { SettingLevel } from "../settings/SettingLevel";
|
import { SettingLevel } from "../settings/SettingLevel";
|
||||||
import { Action } from "../dispatcher/actions";
|
import { Action } from "../dispatcher/actions";
|
||||||
import { SettingUpdatedPayload } from "../dispatcher/payloads/SettingUpdatedPayload";
|
import { SettingUpdatedPayload } from "../dispatcher/payloads/SettingUpdatedPayload";
|
||||||
|
@ -75,7 +75,7 @@ export class BreadcrumbsStore extends AsyncStoreWithClient<IState> {
|
||||||
public get meetsRoomRequirement(): boolean {
|
public get meetsRoomRequirement(): boolean {
|
||||||
if (SettingsStore.getValue("feature_breadcrumbs_v2")) return true;
|
if (SettingsStore.getValue("feature_breadcrumbs_v2")) return true;
|
||||||
const msc3946ProcessDynamicPredecessor = SettingsStore.getValue("feature_dynamic_room_predecessors");
|
const msc3946ProcessDynamicPredecessor = SettingsStore.getValue("feature_dynamic_room_predecessors");
|
||||||
return this.matrixClient?.getVisibleRooms(msc3946ProcessDynamicPredecessor).length >= 20;
|
return !!this.matrixClient && this.matrixClient.getVisibleRooms(msc3946ProcessDynamicPredecessor).length >= 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async onAction(payload: SettingUpdatedPayload | ViewRoomPayload | JoinRoomPayload): Promise<void> {
|
protected async onAction(payload: SettingUpdatedPayload | ViewRoomPayload | JoinRoomPayload): Promise<void> {
|
||||||
|
@ -107,13 +107,17 @@ export class BreadcrumbsStore extends AsyncStoreWithClient<IState> {
|
||||||
await this.updateRooms();
|
await this.updateRooms();
|
||||||
await this.updateState({ enabled: SettingsStore.getValue("breadcrumbs", null) });
|
await this.updateState({ enabled: SettingsStore.getValue("breadcrumbs", null) });
|
||||||
|
|
||||||
this.matrixClient.on(RoomEvent.MyMembership, this.onMyMembership);
|
if (this.matrixClient) {
|
||||||
this.matrixClient.on(ClientEvent.Room, this.onRoom);
|
this.matrixClient.on(RoomEvent.MyMembership, this.onMyMembership);
|
||||||
|
this.matrixClient.on(ClientEvent.Room, this.onRoom);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async onNotReady(): Promise<void> {
|
protected async onNotReady(): Promise<void> {
|
||||||
this.matrixClient.removeListener(RoomEvent.MyMembership, this.onMyMembership);
|
if (this.matrixClient) {
|
||||||
this.matrixClient.removeListener(ClientEvent.Room, this.onRoom);
|
this.matrixClient.removeListener(RoomEvent.MyMembership, this.onMyMembership);
|
||||||
|
this.matrixClient.removeListener(ClientEvent.Room, this.onRoom);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onMyMembership = async (room: Room): Promise<void> => {
|
private onMyMembership = async (room: Room): Promise<void> => {
|
||||||
|
@ -137,7 +141,7 @@ export class BreadcrumbsStore extends AsyncStoreWithClient<IState> {
|
||||||
let roomIds = SettingsStore.getValue<string[]>("breadcrumb_rooms");
|
let roomIds = SettingsStore.getValue<string[]>("breadcrumb_rooms");
|
||||||
if (!roomIds || roomIds.length === 0) roomIds = [];
|
if (!roomIds || roomIds.length === 0) roomIds = [];
|
||||||
|
|
||||||
const rooms = roomIds.map((r) => this.matrixClient.getRoom(r)).filter((r) => !!r);
|
const rooms = filterBoolean(roomIds.map((r) => this.matrixClient?.getRoom(r)));
|
||||||
const currentRooms = this.state.rooms || [];
|
const currentRooms = this.state.rooms || [];
|
||||||
if (!arrayHasDiff(rooms, currentRooms)) return; // no change (probably echo)
|
if (!arrayHasDiff(rooms, currentRooms)) return; // no change (probably echo)
|
||||||
await this.updateState({ rooms });
|
await this.updateState({ rooms });
|
||||||
|
@ -150,8 +154,8 @@ export class BreadcrumbsStore extends AsyncStoreWithClient<IState> {
|
||||||
|
|
||||||
// If the room is upgraded, use that room instead. We'll also splice out
|
// If the room is upgraded, use that room instead. We'll also splice out
|
||||||
// any children of the room.
|
// any children of the room.
|
||||||
const history = this.matrixClient.getRoomUpgradeHistory(room.roomId, false, msc3946ProcessDynamicPredecessor);
|
const history = this.matrixClient?.getRoomUpgradeHistory(room.roomId, false, msc3946ProcessDynamicPredecessor);
|
||||||
if (history.length > 1) {
|
if (history && history.length > 1) {
|
||||||
room = history[history.length - 1]; // Last room is most recent in history
|
room = history[history.length - 1]; // Last room is most recent in history
|
||||||
|
|
||||||
// Take out any room that isn't the most recent room
|
// Take out any room that isn't the most recent room
|
||||||
|
|
|
@ -53,6 +53,7 @@ export class CallStore extends AsyncStoreWithClient<{}> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async onReady(): Promise<any> {
|
protected async onReady(): Promise<any> {
|
||||||
|
if (!this.matrixClient) return;
|
||||||
// We assume that the calls present in a room are a function of room
|
// We assume that the calls present in a room are a function of room
|
||||||
// widgets and group calls, so we initialize the room map here and then
|
// widgets and group calls, so we initialize the room map here and then
|
||||||
// update it whenever those change
|
// update it whenever those change
|
||||||
|
@ -90,9 +91,11 @@ export class CallStore extends AsyncStoreWithClient<{}> {
|
||||||
this.calls.clear();
|
this.calls.clear();
|
||||||
this._activeCalls.clear();
|
this._activeCalls.clear();
|
||||||
|
|
||||||
this.matrixClient.off(GroupCallEventHandlerEvent.Incoming, this.onGroupCall);
|
if (this.matrixClient) {
|
||||||
this.matrixClient.off(GroupCallEventHandlerEvent.Outgoing, this.onGroupCall);
|
this.matrixClient.off(GroupCallEventHandlerEvent.Incoming, this.onGroupCall);
|
||||||
this.matrixClient.off(GroupCallEventHandlerEvent.Ended, this.onGroupCall);
|
this.matrixClient.off(GroupCallEventHandlerEvent.Outgoing, this.onGroupCall);
|
||||||
|
this.matrixClient.off(GroupCallEventHandlerEvent.Ended, this.onGroupCall);
|
||||||
|
}
|
||||||
WidgetStore.instance.off(UPDATE_EVENT, this.onWidgets);
|
WidgetStore.instance.off(UPDATE_EVENT, this.onWidgets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,6 +177,7 @@ export class CallStore extends AsyncStoreWithClient<{}> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private onWidgets = (roomId: string | null): void => {
|
private onWidgets = (roomId: string | null): void => {
|
||||||
|
if (!this.matrixClient) return;
|
||||||
if (roomId === null) {
|
if (roomId === null) {
|
||||||
// This store happened to start before the widget store was done
|
// This store happened to start before the widget store was done
|
||||||
// loading all rooms, so we need to initialize each room again
|
// loading all rooms, so we need to initialize each room again
|
||||||
|
|
|
@ -142,11 +142,13 @@ export class OwnBeaconStore extends AsyncStoreWithClient<OwnBeaconStoreState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async onNotReady(): Promise<void> {
|
protected async onNotReady(): Promise<void> {
|
||||||
this.matrixClient.removeListener(BeaconEvent.LivenessChange, this.onBeaconLiveness);
|
if (this.matrixClient) {
|
||||||
this.matrixClient.removeListener(BeaconEvent.New, this.onNewBeacon);
|
this.matrixClient.removeListener(BeaconEvent.LivenessChange, this.onBeaconLiveness);
|
||||||
this.matrixClient.removeListener(BeaconEvent.Update, this.onUpdateBeacon);
|
this.matrixClient.removeListener(BeaconEvent.New, this.onNewBeacon);
|
||||||
this.matrixClient.removeListener(BeaconEvent.Destroy, this.onDestroyBeacon);
|
this.matrixClient.removeListener(BeaconEvent.Update, this.onUpdateBeacon);
|
||||||
this.matrixClient.removeListener(RoomStateEvent.Members, this.onRoomStateMembers);
|
this.matrixClient.removeListener(BeaconEvent.Destroy, this.onDestroyBeacon);
|
||||||
|
this.matrixClient.removeListener(RoomStateEvent.Members, this.onRoomStateMembers);
|
||||||
|
}
|
||||||
SettingsStore.unwatchSetting(this.dynamicWatcherRef ?? "");
|
SettingsStore.unwatchSetting(this.dynamicWatcherRef ?? "");
|
||||||
|
|
||||||
this.clearBeacons();
|
this.clearBeacons();
|
||||||
|
@ -164,11 +166,13 @@ export class OwnBeaconStore extends AsyncStoreWithClient<OwnBeaconStoreState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async onReady(): Promise<void> {
|
protected async onReady(): Promise<void> {
|
||||||
this.matrixClient.on(BeaconEvent.LivenessChange, this.onBeaconLiveness);
|
if (this.matrixClient) {
|
||||||
this.matrixClient.on(BeaconEvent.New, this.onNewBeacon);
|
this.matrixClient.on(BeaconEvent.LivenessChange, this.onBeaconLiveness);
|
||||||
this.matrixClient.on(BeaconEvent.Update, this.onUpdateBeacon);
|
this.matrixClient.on(BeaconEvent.New, this.onNewBeacon);
|
||||||
this.matrixClient.on(BeaconEvent.Destroy, this.onDestroyBeacon);
|
this.matrixClient.on(BeaconEvent.Update, this.onUpdateBeacon);
|
||||||
this.matrixClient.on(RoomStateEvent.Members, this.onRoomStateMembers);
|
this.matrixClient.on(BeaconEvent.Destroy, this.onDestroyBeacon);
|
||||||
|
this.matrixClient.on(RoomStateEvent.Members, this.onRoomStateMembers);
|
||||||
|
}
|
||||||
this.dynamicWatcherRef = SettingsStore.watchSetting(
|
this.dynamicWatcherRef = SettingsStore.watchSetting(
|
||||||
"feature_dynamic_room_predecessors",
|
"feature_dynamic_room_predecessors",
|
||||||
null,
|
null,
|
||||||
|
@ -200,7 +204,8 @@ export class OwnBeaconStore extends AsyncStoreWithClient<OwnBeaconStoreState> {
|
||||||
* Then consider it to have an error
|
* Then consider it to have an error
|
||||||
*/
|
*/
|
||||||
public beaconHasLocationPublishError = (beaconId: string): boolean => {
|
public beaconHasLocationPublishError = (beaconId: string): boolean => {
|
||||||
return this.beaconLocationPublishErrorCounts.get(beaconId) >= BAIL_AFTER_CONSECUTIVE_ERROR_COUNT;
|
const counts = this.beaconLocationPublishErrorCounts.get(beaconId);
|
||||||
|
return counts !== undefined && counts >= BAIL_AFTER_CONSECUTIVE_ERROR_COUNT;
|
||||||
};
|
};
|
||||||
|
|
||||||
public resetLocationPublishError = (beaconId: string): void => {
|
public resetLocationPublishError = (beaconId: string): void => {
|
||||||
|
@ -246,7 +251,7 @@ export class OwnBeaconStore extends AsyncStoreWithClient<OwnBeaconStoreState> {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private onNewBeacon = (_event: MatrixEvent, beacon: Beacon): void => {
|
private onNewBeacon = (_event: MatrixEvent, beacon: Beacon): void => {
|
||||||
if (!isOwnBeacon(beacon, this.matrixClient.getUserId()!)) {
|
if (!this.matrixClient || !isOwnBeacon(beacon, this.matrixClient.getUserId()!)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.addBeacon(beacon);
|
this.addBeacon(beacon);
|
||||||
|
@ -257,7 +262,7 @@ export class OwnBeaconStore extends AsyncStoreWithClient<OwnBeaconStoreState> {
|
||||||
* This will be called when a beacon is replaced
|
* This will be called when a beacon is replaced
|
||||||
*/
|
*/
|
||||||
private onUpdateBeacon = (_event: MatrixEvent, beacon: Beacon): void => {
|
private onUpdateBeacon = (_event: MatrixEvent, beacon: Beacon): void => {
|
||||||
if (!isOwnBeacon(beacon, this.matrixClient.getUserId()!)) {
|
if (!this.matrixClient || !isOwnBeacon(beacon, this.matrixClient.getUserId()!)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,7 +301,11 @@ export class OwnBeaconStore extends AsyncStoreWithClient<OwnBeaconStoreState> {
|
||||||
*/
|
*/
|
||||||
private onRoomStateMembers = (_event: MatrixEvent, roomState: RoomState, member: RoomMember): void => {
|
private onRoomStateMembers = (_event: MatrixEvent, roomState: RoomState, member: RoomMember): void => {
|
||||||
// no beacons for this room, ignore
|
// no beacons for this room, ignore
|
||||||
if (!this.beaconsByRoomId.has(roomState.roomId) || member.userId !== this.matrixClient.getUserId()) {
|
if (
|
||||||
|
!this.matrixClient ||
|
||||||
|
!this.beaconsByRoomId.has(roomState.roomId) ||
|
||||||
|
member.userId !== this.matrixClient.getUserId()
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,7 +341,8 @@ export class OwnBeaconStore extends AsyncStoreWithClient<OwnBeaconStoreState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
private initialiseBeaconState = (): void => {
|
private initialiseBeaconState = (): void => {
|
||||||
const userId = this.matrixClient.getUserId()!;
|
if (!this.matrixClient) return;
|
||||||
|
const userId = this.matrixClient.getSafeUserId();
|
||||||
const visibleRooms = this.matrixClient.getVisibleRooms(
|
const visibleRooms = this.matrixClient.getVisibleRooms(
|
||||||
SettingsStore.getValue("feature_dynamic_room_predecessors"),
|
SettingsStore.getValue("feature_dynamic_room_predecessors"),
|
||||||
);
|
);
|
||||||
|
|
|
@ -112,7 +112,8 @@ export class OwnProfileStore extends AsyncStoreWithClient<IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async onReady(): Promise<void> {
|
protected async onReady(): Promise<void> {
|
||||||
const myUserId = this.matrixClient.getUserId()!;
|
if (!this.matrixClient) return;
|
||||||
|
const myUserId = this.matrixClient.getSafeUserId();
|
||||||
this.monitoredUser = this.matrixClient.getUser(myUserId);
|
this.monitoredUser = this.matrixClient.getUser(myUserId);
|
||||||
if (this.monitoredUser) {
|
if (this.monitoredUser) {
|
||||||
this.monitoredUser.on(UserEvent.DisplayName, this.onProfileUpdate);
|
this.monitoredUser.on(UserEvent.DisplayName, this.onProfileUpdate);
|
||||||
|
@ -132,9 +133,10 @@ export class OwnProfileStore extends AsyncStoreWithClient<IState> {
|
||||||
|
|
||||||
private onProfileUpdate = throttle(
|
private onProfileUpdate = throttle(
|
||||||
async (): Promise<void> => {
|
async (): Promise<void> => {
|
||||||
|
if (!this.matrixClient) return;
|
||||||
// We specifically do not use the User object we stored for profile info as it
|
// We specifically do not use the User object we stored for profile info as it
|
||||||
// could easily be wrong (such as per-room instead of global profile).
|
// could easily be wrong (such as per-room instead of global profile).
|
||||||
const profileInfo = await this.matrixClient.getProfileInfo(this.matrixClient.getUserId()!);
|
const profileInfo = await this.matrixClient.getProfileInfo(this.matrixClient.getSafeUserId());
|
||||||
if (profileInfo.displayname) {
|
if (profileInfo.displayname) {
|
||||||
window.localStorage.setItem(KEY_DISPLAY_NAME, profileInfo.displayname);
|
window.localStorage.setItem(KEY_DISPLAY_NAME, profileInfo.displayname);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -27,7 +27,6 @@ import defaultDispatcher from "../dispatcher/dispatcher";
|
||||||
import WidgetEchoStore from "../stores/WidgetEchoStore";
|
import WidgetEchoStore from "../stores/WidgetEchoStore";
|
||||||
import ActiveWidgetStore from "../stores/ActiveWidgetStore";
|
import ActiveWidgetStore from "../stores/ActiveWidgetStore";
|
||||||
import WidgetUtils from "../utils/WidgetUtils";
|
import WidgetUtils from "../utils/WidgetUtils";
|
||||||
import { WidgetType } from "../widgets/WidgetType";
|
|
||||||
import { UPDATE_EVENT } from "./AsyncStore";
|
import { UPDATE_EVENT } from "./AsyncStore";
|
||||||
|
|
||||||
interface IState {}
|
interface IState {}
|
||||||
|
@ -74,6 +73,7 @@ export default class WidgetStore extends AsyncStoreWithClient<IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async onReady(): Promise<any> {
|
protected async onReady(): Promise<any> {
|
||||||
|
if (!this.matrixClient) return;
|
||||||
this.matrixClient.on(ClientEvent.Room, this.onRoom);
|
this.matrixClient.on(ClientEvent.Room, this.onRoom);
|
||||||
this.matrixClient.on(RoomStateEvent.Events, this.onRoomStateEvents);
|
this.matrixClient.on(RoomStateEvent.Events, this.onRoomStateEvents);
|
||||||
this.matrixClient.getRooms().forEach((room: Room) => {
|
this.matrixClient.getRooms().forEach((room: Room) => {
|
||||||
|
@ -83,8 +83,10 @@ export default class WidgetStore extends AsyncStoreWithClient<IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async onNotReady(): Promise<any> {
|
protected async onNotReady(): Promise<any> {
|
||||||
this.matrixClient.off(ClientEvent.Room, this.onRoom);
|
if (this.matrixClient) {
|
||||||
this.matrixClient.off(RoomStateEvent.Events, this.onRoomStateEvents);
|
this.matrixClient.off(ClientEvent.Room, this.onRoom);
|
||||||
|
this.matrixClient.off(RoomStateEvent.Events, this.onRoomStateEvents);
|
||||||
|
}
|
||||||
this.widgetMap = new Map();
|
this.widgetMap = new Map();
|
||||||
this.roomMap = new Map();
|
this.roomMap = new Map();
|
||||||
await this.reset({});
|
await this.reset({});
|
||||||
|
@ -95,9 +97,9 @@ export default class WidgetStore extends AsyncStoreWithClient<IState> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
private onWidgetEchoStoreUpdate = (roomId: string, widgetId: string): void => {
|
private onWidgetEchoStoreUpdate = (roomId: string): void => {
|
||||||
this.initRoom(roomId);
|
this.initRoom(roomId);
|
||||||
this.loadRoomWidgets(this.matrixClient.getRoom(roomId));
|
this.loadRoomWidgets(this.matrixClient?.getRoom(roomId) ?? null);
|
||||||
this.emit(UPDATE_EVENT, roomId);
|
this.emit(UPDATE_EVENT, roomId);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -174,7 +176,7 @@ export default class WidgetStore extends AsyncStoreWithClient<IState> {
|
||||||
if (ev.getType() !== "im.vector.modular.widgets") return; // TODO: Support m.widget too
|
if (ev.getType() !== "im.vector.modular.widgets") return; // TODO: Support m.widget too
|
||||||
const roomId = ev.getRoomId()!;
|
const roomId = ev.getRoomId()!;
|
||||||
this.initRoom(roomId);
|
this.initRoom(roomId);
|
||||||
this.loadRoomWidgets(this.matrixClient.getRoom(roomId));
|
this.loadRoomWidgets(this.matrixClient?.getRoom(roomId) ?? null);
|
||||||
this.emit(UPDATE_EVENT, roomId);
|
this.emit(UPDATE_EVENT, roomId);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -207,24 +209,6 @@ export default class WidgetStore extends AsyncStoreWithClient<IState> {
|
||||||
roomApps.widgets = roomApps.widgets.filter((app) => !(app.id === widgetId && app.roomId === roomId));
|
roomApps.widgets = roomApps.widgets.filter((app) => !(app.id === widgetId && app.roomId === roomId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public doesRoomHaveConference(room: Room): boolean {
|
|
||||||
const roomInfo = this.getRoom(room.roomId);
|
|
||||||
if (!roomInfo) return false;
|
|
||||||
|
|
||||||
const currentWidgets = roomInfo.widgets.filter((w) => WidgetType.JITSI.matches(w.type));
|
|
||||||
const hasPendingWidgets = WidgetEchoStore.roomHasPendingWidgetsOfType(room.roomId, [], WidgetType.JITSI);
|
|
||||||
return currentWidgets.length > 0 || hasPendingWidgets;
|
|
||||||
}
|
|
||||||
|
|
||||||
public isJoinedToConferenceIn(room: Room): boolean {
|
|
||||||
const roomInfo = this.getRoom(room.roomId);
|
|
||||||
if (!roomInfo) return false;
|
|
||||||
|
|
||||||
// A persistent conference widget indicates that we're participating
|
|
||||||
const widgets = roomInfo.widgets.filter((w) => WidgetType.JITSI.matches(w.type));
|
|
||||||
return widgets.some((w) => ActiveWidgetStore.instance.getWidgetPersistence(w.id, room.roomId));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
window.mxWidgetStore = WidgetStore.instance;
|
window.mxWidgetStore = WidgetStore.instance;
|
||||||
|
|
|
@ -47,6 +47,7 @@ export class RoomEchoChamber extends GenericEchoChamber<RoomEchoContext, CachedR
|
||||||
}
|
}
|
||||||
|
|
||||||
private onAccountData = (event: MatrixEvent): void => {
|
private onAccountData = (event: MatrixEvent): void => {
|
||||||
|
if (!this.matrixClient) return;
|
||||||
if (event.getType() === EventType.PushRules) {
|
if (event.getType() === EventType.PushRules) {
|
||||||
const currentVolume = this.properties.get(CachedRoomKey.NotificationVolume);
|
const currentVolume = this.properties.get(CachedRoomKey.NotificationVolume);
|
||||||
const newVolume = getRoomNotifsState(this.matrixClient, this.context.room.roomId);
|
const newVolume = getRoomNotifsState(this.matrixClient, this.context.room.roomId);
|
||||||
|
|
|
@ -119,6 +119,7 @@ export class RoomNotificationStateStore extends AsyncStoreWithClient<IState> {
|
||||||
* @internal public for test
|
* @internal public for test
|
||||||
*/
|
*/
|
||||||
public emitUpdateIfStateChanged = (state: SyncState, forceEmit: boolean): void => {
|
public emitUpdateIfStateChanged = (state: SyncState, forceEmit: boolean): void => {
|
||||||
|
if (!this.matrixClient) return;
|
||||||
// Only count visible rooms to not torment the user with notification counts in rooms they can't see.
|
// Only count visible rooms to not torment the user with notification counts in rooms they can't see.
|
||||||
// This will include highlights from the previous version of the room internally
|
// This will include highlights from the previous version of the room internally
|
||||||
const msc3946ProcessDynamicPredecessor = SettingsStore.getValue("feature_dynamic_room_predecessors");
|
const msc3946ProcessDynamicPredecessor = SettingsStore.getValue("feature_dynamic_room_predecessors");
|
||||||
|
@ -149,7 +150,7 @@ export class RoomNotificationStateStore extends AsyncStoreWithClient<IState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
protected async onReady(): Promise<void> {
|
protected async onReady(): Promise<void> {
|
||||||
this.matrixClient.on(ClientEvent.Sync, this.onSync);
|
this.matrixClient?.on(ClientEvent.Sync, this.onSync);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async onNotReady(): Promise<any> {
|
protected async onNotReady(): Promise<any> {
|
||||||
|
|
|
@ -77,7 +77,8 @@ export class SpaceNotificationState extends NotificationState {
|
||||||
this._count = 0;
|
this._count = 0;
|
||||||
this._color = NotificationColor.None;
|
this._color = NotificationColor.None;
|
||||||
for (const [roomId, state] of Object.entries(this.states)) {
|
for (const [roomId, state] of Object.entries(this.states)) {
|
||||||
const roomTags = RoomListStore.instance.getTagsForRoom(this.rooms.find((r) => r.roomId === roomId));
|
const room = this.rooms.find((r) => r.roomId === roomId);
|
||||||
|
const roomTags = room ? RoomListStore.instance.getTagsForRoom(room) : [];
|
||||||
|
|
||||||
// We ignore unreads in LowPriority rooms, see https://github.com/vector-im/element-web/issues/16836
|
// We ignore unreads in LowPriority rooms, see https://github.com/vector-im/element-web/issues/16836
|
||||||
if (roomTags.includes(DefaultTagID.LowPriority) && state.color === NotificationColor.Bold) continue;
|
if (roomTags.includes(DefaultTagID.LowPriority) && state.color === NotificationColor.Bold) continue;
|
||||||
|
|
|
@ -165,7 +165,7 @@ export class MessagePreviewStore extends AsyncStoreWithClient<IState> {
|
||||||
|
|
||||||
const event = events[i];
|
const event = events[i];
|
||||||
|
|
||||||
await this.matrixClient.decryptEventIfNeeded(event);
|
await this.matrixClient?.decryptEventIfNeeded(event);
|
||||||
|
|
||||||
const previewDef = PREVIEWS[event.getType()];
|
const previewDef = PREVIEWS[event.getType()];
|
||||||
if (!previewDef) continue;
|
if (!previewDef) continue;
|
||||||
|
|
|
@ -189,8 +189,7 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> implements
|
||||||
|
|
||||||
protected async onDispatchAsync(payload: ActionPayload): Promise<void> {
|
protected async onDispatchAsync(payload: ActionPayload): Promise<void> {
|
||||||
// Everything here requires a MatrixClient or some sort of logical readiness.
|
// Everything here requires a MatrixClient or some sort of logical readiness.
|
||||||
const logicallyReady = this.matrixClient && this.initialListsGenerated;
|
if (!this.matrixClient || !this.initialListsGenerated) return;
|
||||||
if (!logicallyReady) return;
|
|
||||||
|
|
||||||
if (!this.algorithm) {
|
if (!this.algorithm) {
|
||||||
// This shouldn't happen because `initialListsGenerated` implies we have an algorithm.
|
// This shouldn't happen because `initialListsGenerated` implies we have an algorithm.
|
||||||
|
@ -229,7 +228,7 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> implements
|
||||||
eventPayload.event.getType() === EventType.RoomTombstone &&
|
eventPayload.event.getType() === EventType.RoomTombstone &&
|
||||||
eventPayload.event.getStateKey() === ""
|
eventPayload.event.getStateKey() === ""
|
||||||
) {
|
) {
|
||||||
const newRoom = this.matrixClient.getRoom(eventPayload.event.getContent()["replacement_room"]);
|
const newRoom = this.matrixClient?.getRoom(eventPayload.event.getContent()["replacement_room"]);
|
||||||
if (newRoom) {
|
if (newRoom) {
|
||||||
// If we have the new room, then the new room check will have seen the predecessor
|
// If we have the new room, then the new room check will have seen the predecessor
|
||||||
// and did the required updates, so do nothing here.
|
// and did the required updates, so do nothing here.
|
||||||
|
@ -243,7 +242,7 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> implements
|
||||||
logger.warn(`Live timeline event ${eventPayload.event.getId()} received without associated room`);
|
logger.warn(`Live timeline event ${eventPayload.event.getId()} received without associated room`);
|
||||||
logger.warn(`Queuing failed room update for retry as a result.`);
|
logger.warn(`Queuing failed room update for retry as a result.`);
|
||||||
window.setTimeout(async (): Promise<void> => {
|
window.setTimeout(async (): Promise<void> => {
|
||||||
const updatedRoom = this.matrixClient.getRoom(roomId);
|
const updatedRoom = this.matrixClient?.getRoom(roomId);
|
||||||
|
|
||||||
if (updatedRoom) {
|
if (updatedRoom) {
|
||||||
await tryUpdate(updatedRoom);
|
await tryUpdate(updatedRoom);
|
||||||
|
@ -307,7 +306,7 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> implements
|
||||||
const roomState: RoomState = membershipPayload.room.currentState;
|
const roomState: RoomState = membershipPayload.room.currentState;
|
||||||
const predecessor = roomState.findPredecessor(this.msc3946ProcessDynamicPredecessor);
|
const predecessor = roomState.findPredecessor(this.msc3946ProcessDynamicPredecessor);
|
||||||
if (predecessor) {
|
if (predecessor) {
|
||||||
const prevRoom = this.matrixClient.getRoom(predecessor.roomId);
|
const prevRoom = this.matrixClient?.getRoom(predecessor.roomId);
|
||||||
if (prevRoom) {
|
if (prevRoom) {
|
||||||
const isSticky = this.algorithm.stickyRoom === prevRoom;
|
const isSticky = this.algorithm.stickyRoom === prevRoom;
|
||||||
if (isSticky) {
|
if (isSticky) {
|
||||||
|
|
|
@ -252,7 +252,7 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
|
||||||
// now set the rooms
|
// now set the rooms
|
||||||
const rooms: Room[] = [];
|
const rooms: Room[] = [];
|
||||||
orderedRoomIds.forEach((roomId) => {
|
orderedRoomIds.forEach((roomId) => {
|
||||||
const room = this.matrixClient.getRoom(roomId);
|
const room = this.matrixClient?.getRoom(roomId);
|
||||||
if (!room) {
|
if (!room) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,7 +178,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
|
|
||||||
public get activeSpaceRoom(): Room | null {
|
public get activeSpaceRoom(): Room | null {
|
||||||
if (isMetaSpace(this._activeSpace)) return null;
|
if (isMetaSpace(this._activeSpace)) return null;
|
||||||
return this.matrixClient?.getRoom(this._activeSpace);
|
return this.matrixClient?.getRoom(this._activeSpace) ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get suggestedRooms(): ISuggestedRoom[] {
|
public get suggestedRooms(): ISuggestedRoom[] {
|
||||||
|
@ -290,7 +290,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
SpaceStore.instance.traverseSpace(
|
SpaceStore.instance.traverseSpace(
|
||||||
space,
|
space,
|
||||||
(roomId) => {
|
(roomId) => {
|
||||||
this.matrixClient.getRoom(roomId)?.loadMembersIfNeeded();
|
this.matrixClient?.getRoom(roomId)?.loadMembersIfNeeded();
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
@ -324,7 +324,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
.filter((roomInfo) => {
|
.filter((roomInfo) => {
|
||||||
return (
|
return (
|
||||||
roomInfo.room_type !== RoomType.Space &&
|
roomInfo.room_type !== RoomType.Space &&
|
||||||
this.matrixClient.getRoom(roomInfo.room_id)?.getMyMembership() !== "join"
|
this.matrixClient?.getRoom(roomInfo.room_id)?.getMyMembership() !== "join"
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.map((roomInfo) => ({
|
.map((roomInfo) => ({
|
||||||
|
@ -396,7 +396,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
// only respect the relationship if the sender has sufficient permissions in the parent to set
|
// only respect the relationship if the sender has sufficient permissions in the parent to set
|
||||||
// child relations, as per MSC1772.
|
// child relations, as per MSC1772.
|
||||||
// https://github.com/matrix-org/matrix-doc/blob/main/proposals/1772-groups-as-rooms.md#relationship-between-rooms-and-spaces
|
// https://github.com/matrix-org/matrix-doc/blob/main/proposals/1772-groups-as-rooms.md#relationship-between-rooms-and-spaces
|
||||||
const parent = this.matrixClient.getRoom(ev.getStateKey());
|
const parent = this.matrixClient?.getRoom(ev.getStateKey());
|
||||||
const relation = parent?.currentState.getStateEvents(EventType.SpaceChild, roomId);
|
const relation = parent?.currentState.getStateEvents(EventType.SpaceChild, roomId);
|
||||||
if (
|
if (
|
||||||
!parent?.currentState.maySendStateEvent(EventType.SpaceChild, userId) ||
|
!parent?.currentState.maySendStateEvent(EventType.SpaceChild, userId) ||
|
||||||
|
@ -877,7 +877,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
|
|
||||||
private switchSpaceIfNeeded = (roomId = SdkContextClass.instance.roomViewStore.getRoomId()): void => {
|
private switchSpaceIfNeeded = (roomId = SdkContextClass.instance.roomViewStore.getRoomId()): void => {
|
||||||
if (!roomId) return;
|
if (!roomId) return;
|
||||||
if (!this.isRoomInSpace(this.activeSpace, roomId) && !this.matrixClient.getRoom(roomId)?.isSpaceRoom()) {
|
if (!this.isRoomInSpace(this.activeSpace, roomId) && !this.matrixClient?.getRoom(roomId)?.isSpaceRoom()) {
|
||||||
this.switchToRelatedSpace(roomId);
|
this.switchToRelatedSpace(roomId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -972,7 +972,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private onRoomState = (ev: MatrixEvent): void => {
|
private onRoomState = (ev: MatrixEvent): void => {
|
||||||
const room = this.matrixClient.getRoom(ev.getRoomId());
|
const room = this.matrixClient?.getRoom(ev.getRoomId());
|
||||||
|
|
||||||
if (!room) return;
|
if (!room) return;
|
||||||
|
|
||||||
|
@ -1022,7 +1022,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
|
|
||||||
// listening for m.room.member events in onRoomState above doesn't work as the Member object isn't updated by then
|
// listening for m.room.member events in onRoomState above doesn't work as the Member object isn't updated by then
|
||||||
private onRoomStateMembers = (ev: MatrixEvent): void => {
|
private onRoomStateMembers = (ev: MatrixEvent): void => {
|
||||||
const room = this.matrixClient.getRoom(ev.getRoomId());
|
const room = this.matrixClient?.getRoom(ev.getRoomId());
|
||||||
|
|
||||||
const userId = ev.getStateKey()!;
|
const userId = ev.getStateKey()!;
|
||||||
if (
|
if (
|
||||||
|
@ -1135,6 +1135,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async onReady(): Promise<void> {
|
protected async onReady(): Promise<void> {
|
||||||
|
if (!this.matrixClient) return;
|
||||||
this.matrixClient.on(ClientEvent.Room, this.onRoom);
|
this.matrixClient.on(ClientEvent.Room, this.onRoom);
|
||||||
this.matrixClient.on(RoomEvent.MyMembership, this.onRoom);
|
this.matrixClient.on(RoomEvent.MyMembership, this.onRoom);
|
||||||
this.matrixClient.on(RoomEvent.AccountData, this.onRoomAccountData);
|
this.matrixClient.on(RoomEvent.AccountData, this.onRoomAccountData);
|
||||||
|
@ -1350,7 +1351,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
||||||
private async setRootSpaceOrder(space: Room, order: string): Promise<void> {
|
private async setRootSpaceOrder(space: Room, order: string): Promise<void> {
|
||||||
this.spaceOrderLocalEchoMap.set(space.roomId, order);
|
this.spaceOrderLocalEchoMap.set(space.roomId, order);
|
||||||
try {
|
try {
|
||||||
await this.matrixClient.setRoomAccountData(space.roomId, EventType.SpaceOrder, { order });
|
await this.matrixClient?.setRoomAccountData(space.roomId, EventType.SpaceOrder, { order });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.warn("Failed to set root space order", e);
|
logger.warn("Failed to set root space order", e);
|
||||||
if (this.spaceOrderLocalEchoMap.get(space.roomId) === order) {
|
if (this.spaceOrderLocalEchoMap.get(space.roomId) === order) {
|
||||||
|
|
|
@ -42,6 +42,7 @@ describe("<RoomLiveShareWarning />", () => {
|
||||||
const mockClient = getMockClientWithEventEmitter({
|
const mockClient = getMockClientWithEventEmitter({
|
||||||
getVisibleRooms: jest.fn().mockReturnValue([]),
|
getVisibleRooms: jest.fn().mockReturnValue([]),
|
||||||
getUserId: jest.fn().mockReturnValue(aliceId),
|
getUserId: jest.fn().mockReturnValue(aliceId),
|
||||||
|
getSafeUserId: jest.fn().mockReturnValue(aliceId),
|
||||||
unstable_setLiveBeacon: jest.fn().mockResolvedValue({ event_id: "1" }),
|
unstable_setLiveBeacon: jest.fn().mockResolvedValue({ event_id: "1" }),
|
||||||
sendEvent: jest.fn(),
|
sendEvent: jest.fn(),
|
||||||
isGuest: jest.fn().mockReturnValue(false),
|
isGuest: jest.fn().mockReturnValue(false),
|
||||||
|
|
|
@ -42,7 +42,7 @@ describe("NotificatinSettingsTab", () => {
|
||||||
const room = mkStubRoom(roomId, "test room", cli);
|
const room = mkStubRoom(roomId, "test room", cli);
|
||||||
roomProps = EchoChamber.forRoom(room);
|
roomProps = EchoChamber.forRoom(room);
|
||||||
|
|
||||||
NotificationSettingsTab.contextType = React.createContext<MatrixClient | undefined>(cli);
|
NotificationSettingsTab.contextType = React.createContext<MatrixClient>(cli);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should prevent »Settings« link click from bubbling up to radio buttons", async () => {
|
it("should prevent »Settings« link click from bubbling up to radio buttons", async () => {
|
||||||
|
|
|
@ -59,6 +59,7 @@ describe("OwnBeaconStore", () => {
|
||||||
const bobId = "@bob:server.org";
|
const bobId = "@bob:server.org";
|
||||||
const mockClient = getMockClientWithEventEmitter({
|
const mockClient = getMockClientWithEventEmitter({
|
||||||
getUserId: jest.fn().mockReturnValue(aliceId),
|
getUserId: jest.fn().mockReturnValue(aliceId),
|
||||||
|
getSafeUserId: jest.fn().mockReturnValue(aliceId),
|
||||||
getVisibleRooms: jest.fn().mockReturnValue([]),
|
getVisibleRooms: jest.fn().mockReturnValue([]),
|
||||||
unstable_setLiveBeacon: jest.fn().mockResolvedValue({ event_id: "1" }),
|
unstable_setLiveBeacon: jest.fn().mockResolvedValue({ event_id: "1" }),
|
||||||
sendEvent: jest.fn().mockResolvedValue({ event_id: "1" }),
|
sendEvent: jest.fn().mockResolvedValue({ event_id: "1" }),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue