Skip to content
This repository has been archived by the owner on Oct 22, 2024. It is now read-only.

Refactor stores and their relationship to the MatrixClientPeg #124

Merged
merged 2 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/MatrixClientPeg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import { formatList } from "./utils/FormattingUtils";
import SdkConfig from "./SdkConfig";
import { Features } from "./settings/Settings";
import { setDeviceIsolationMode } from "./settings/controllers/DeviceIsolationModeController.ts";
import { ReadyWatchingStore } from "./stores/ReadyWatchingStore.ts";

export interface IMatrixClientCreds {
homeserverUrl: string;
Expand Down Expand Up @@ -309,6 +310,7 @@ class MatrixClientPegClass implements IMatrixClientPeg {
MatrixActionCreators.start(this.matrixClient);
MatrixClientBackedSettingsHandler.matrixClient = this.matrixClient;
MatrixClientBackedController.matrixClient = this.matrixClient;
ReadyWatchingStore.matrixClient = this.matrixClient;

return opts;
}
Expand Down
9 changes: 7 additions & 2 deletions src/stores/AsyncStoreWithClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,13 @@ export abstract class AsyncStoreWithClient<T extends Object> extends AsyncStore<
})(dispatcher);
}

public async start(): Promise<void> {
await this.readyStore.start();
protected async start(matrixClient: MatrixClient | null): Promise<void> {
await this.readyStore.start(matrixClient);
}

// XXX: This method is intended only for use in tests.
public async useUnitTestClient(cli: MatrixClient): Promise<void> {
await this.readyStore.useUnitTestClient(cli);
}

public get matrixClient(): MatrixClient | null {
Expand Down
4 changes: 1 addition & 3 deletions src/stores/AutoRageshakeStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,7 @@ interface IState {
*/
export default class AutoRageshakeStore extends AsyncStoreWithClient<IState> {
private static readonly internalInstance = (() => {
const instance = new AutoRageshakeStore();
instance.start();
return instance;
return new AutoRageshakeStore();
})();

private constructor() {
Expand Down
4 changes: 1 addition & 3 deletions src/stores/BreadcrumbsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ interface IState {

export class BreadcrumbsStore extends AsyncStoreWithClient<IState> {
private static readonly internalInstance = (() => {
const instance = new BreadcrumbsStore();
instance.start();
return instance;
return new BreadcrumbsStore();
})();

private waitingRooms: { roomId: string; addedTs: number }[] = [];
Expand Down
1 change: 0 additions & 1 deletion src/stores/CallStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export class CallStore extends AsyncStoreWithClient<{}> {
public static get instance(): CallStore {
if (!this._instance) {
this._instance = new CallStore();
this._instance.start();
}
return this._instance;
}
Expand Down
1 change: 0 additions & 1 deletion src/stores/ModalWidgetStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ interface IState {
export class ModalWidgetStore extends AsyncStoreWithClient<IState> {
private static readonly internalInstance = (() => {
const instance = new ModalWidgetStore();
instance.start();
return instance;
})();
private modalInstance: IHandle<typeof ModalWidgetDialog> | null = null;
Expand Down
1 change: 0 additions & 1 deletion src/stores/OwnBeaconStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ const getLocallyCreatedBeaconEventIds = (): string[] => {
export class OwnBeaconStore extends AsyncStoreWithClient<OwnBeaconStoreState> {
private static readonly internalInstance = (() => {
const instance = new OwnBeaconStore();
instance.start();
return instance;
})();
// users beacons, keyed by event type
Expand Down
1 change: 0 additions & 1 deletion src/stores/OwnProfileStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ const KEY_AVATAR_URL = "mx_profile_avatar_url";
export class OwnProfileStore extends AsyncStoreWithClient<IState> {
private static readonly internalInstance = (() => {
const instance = new OwnProfileStore();
instance.start();
return instance;
})();

Expand Down
37 changes: 26 additions & 11 deletions src/stores/ReadyWatchingStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,40 @@
import { MatrixClient, SyncState } from "matrix-js-sdk/src/matrix";
import { EventEmitter } from "events";

import { MatrixClientPeg } from "../MatrixClientPeg";
import { ActionPayload } from "../dispatcher/payloads";
import { IDestroyable } from "../utils/IDestroyable";
import { Action } from "../dispatcher/actions";
import { MatrixDispatcher } from "../dispatcher/dispatcher";

export abstract class ReadyWatchingStore extends EventEmitter implements IDestroyable {
protected matrixClient: MatrixClient | null = null;
private static instances: ReadyWatchingStore[] = [];
protected _matrixClient: MatrixClient | null = null;
private dispatcherRef: string | null = null;

public static set matrixClient(client: MatrixClient) {
for (const instance of ReadyWatchingStore.instances) {
instance.start(client);
}
}

public constructor(protected readonly dispatcher: MatrixDispatcher) {
super();
}

public async start(): Promise<void> {
this.dispatcherRef = this.dispatcher.register(this.onAction);
}

// MatrixClientPeg can be undefined in tests because of circular dependencies with other stores
const matrixClient = MatrixClientPeg?.get();
public get matrixClient(): MatrixClient | null {
return this._matrixClient;
}

public async start(matrixClient: MatrixClient | null): Promise<void> {
const oldClient = this._matrixClient;
this._matrixClient = matrixClient;

if (oldClient !== matrixClient) {
await this.onNotReady();
}
if (matrixClient) {
this.matrixClient = matrixClient;
await this.onReady();
}
}
Expand All @@ -38,8 +51,10 @@ export abstract class ReadyWatchingStore extends EventEmitter implements IDestro
return this.matrixClient; // for external readonly access
}

public useUnitTestClient(cli: MatrixClient): void {
this.matrixClient = cli;
// XXX: This method is intended only for use in tests.
public async useUnitTestClient(cli: MatrixClient): Promise<void> {
this._matrixClient = cli;
await this.onReady();
}

public destroy(): void {
Expand Down Expand Up @@ -74,13 +89,13 @@ export abstract class ReadyWatchingStore extends EventEmitter implements IDestro
if (this.matrixClient) {
await this.onNotReady();
}
this.matrixClient = payload.matrixClient;
this._matrixClient = payload.matrixClient;
await this.onReady();
}
} else if (payload.action === "on_client_not_viable" || payload.action === Action.OnLoggedOut) {
if (this.matrixClient) {
await this.onNotReady();
this.matrixClient = null;
this._matrixClient = null;
}
}
};
Expand Down
1 change: 0 additions & 1 deletion src/stores/VoiceRecordingStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export class VoiceRecordingStore extends AsyncStoreWithClient<IState> {
public static get instance(): VoiceRecordingStore {
if (!this.internalInstance) {
this.internalInstance = new VoiceRecordingStore();
this.internalInstance.start();
}
return this.internalInstance;
}
Expand Down
1 change: 0 additions & 1 deletion src/stores/WidgetStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ interface IRoomWidgets {
export default class WidgetStore extends AsyncStoreWithClient<IState> {
private static readonly internalInstance = (() => {
const instance = new WidgetStore();
instance.start();
return instance;
})();

Expand Down
1 change: 0 additions & 1 deletion src/stores/local-echo/EchoStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ export class EchoStore extends AsyncStoreWithClient<IState> {
public static get instance(): EchoStore {
if (!this._instance) {
this._instance = new EchoStore();
this._instance.start();
}
return this._instance;
}
Expand Down
1 change: 0 additions & 1 deletion src/stores/notifications/RoomNotificationStateStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export const UPDATE_STATUS_INDICATOR = Symbol("update-status-indicator");
export class RoomNotificationStateStore extends AsyncStoreWithClient<IState> {
private static readonly internalInstance = (() => {
const instance = new RoomNotificationStateStore();
instance.start();
return instance;
})();
private roomMap = new Map<Room, RoomNotificationState>();
Expand Down
1 change: 0 additions & 1 deletion src/stores/right-panel/RightPanelStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,6 @@ export default class RightPanelStore extends ReadyWatchingStore {
public static get instance(): RightPanelStore {
if (!this.internalInstance) {
this.internalInstance = new RightPanelStore();
this.internalInstance.start();
}
return this.internalInstance;
}
Expand Down
6 changes: 1 addition & 5 deletions src/stores/room-list/MessagePreviewStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,7 @@ const mkMessagePreview = (text: string, event: MatrixEvent): MessagePreview => {
};

export class MessagePreviewStore extends AsyncStoreWithClient<IState> {
private static readonly internalInstance = (() => {
const instance = new MessagePreviewStore();
instance.start();
return instance;
})();
private static readonly internalInstance = (() => new MessagePreviewStore())();

/**
* @internal Public for test only
Expand Down
1 change: 0 additions & 1 deletion src/stores/room-list/RoomListLayoutStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ export default class RoomListLayoutStore extends AsyncStoreWithClient<IState> {
public static get instance(): RoomListLayoutStore {
if (!this.internalInstance) {
this.internalInstance = new RoomListLayoutStore();
this.internalInstance.start();
}
return RoomListLayoutStore.internalInstance;
}
Expand Down
2 changes: 0 additions & 2 deletions src/stores/room-list/RoomListStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -643,11 +643,9 @@ export default class RoomListStore {
if (SettingsStore.getValue("feature_sliding_sync")) {
logger.info("using SlidingRoomListStoreClass");
const instance = new SlidingRoomListStoreClass(defaultDispatcher, SdkContextClass.instance);
instance.start();
RoomListStore.internalInstance = instance;
} else {
const instance = new RoomListStoreClass(defaultDispatcher);
instance.start();
RoomListStore.internalInstance = instance;
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/stores/spaces/SpaceStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
MatrixEvent,
ClientEvent,
ISendEventResponse,
MatrixClient,
} from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types";
import { logger } from "matrix-js-sdk/src/logger";
Expand Down Expand Up @@ -1397,7 +1398,6 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
export default class SpaceStore {
private static readonly internalInstance = (() => {
const instance = new SpaceStoreClass();
instance.start();
return instance;
})();

Expand All @@ -1408,9 +1408,9 @@ export default class SpaceStore {
/**
* @internal for test only
*/
public static testInstance(): SpaceStoreClass {
public static testInstance(client: MatrixClient): SpaceStoreClass {
const store = new SpaceStoreClass();
store.start();
store.useUnitTestClient(client);
return store;
}
}
Expand Down
1 change: 0 additions & 1 deletion src/stores/widgets/WidgetLayoutStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ export class WidgetLayoutStore extends ReadyWatchingStore {
public static get instance(): WidgetLayoutStore {
if (!this.internalInstance) {
this.internalInstance = new WidgetLayoutStore();
this.internalInstance.start();
}
return this.internalInstance;
}
Expand Down
1 change: 0 additions & 1 deletion src/stores/widgets/WidgetMessagingStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ export enum WidgetMessagingStoreEvent {
export class WidgetMessagingStore extends AsyncStoreWithClient<{}> {
private static readonly internalInstance = (() => {
const instance = new WidgetMessagingStore();
instance.start();
return instance;
})();

Expand Down
2 changes: 1 addition & 1 deletion test/stores/AutoRageshakeStore-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ describe("AutoRageshakeStore", () => {

// @ts-ignore bypass private ctor for tests
autoRageshakeStore = new AutoRageshakeStore();
autoRageshakeStore.start();
autoRageshakeStore.useUnitTestClient(client);

utdEvent = mkEvent({
event: true,
Expand Down
6 changes: 3 additions & 3 deletions test/stores/OwnProfileStore-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ describe("OwnProfileStore", () => {
displayname: "Display Name",
avatar_url: "mxc://example.com/abc123",
});
await ownProfileStore.start();
await ownProfileStore.useUnitTestClient(client);

expect(onUpdate).toHaveBeenCalled();
expect(ownProfileStore.displayName).toBe("Display Name");
Expand All @@ -54,7 +54,7 @@ describe("OwnProfileStore", () => {
errcode: "M_NOT_FOUND",
}),
);
await ownProfileStore.start();
await ownProfileStore.useUnitTestClient(client);

expect(onUpdate).toHaveBeenCalled();
expect(ownProfileStore.displayName).toBe(client.getSafeUserId());
Expand All @@ -69,7 +69,7 @@ describe("OwnProfileStore", () => {
}),
);
try {
await ownProfileStore.start();
await ownProfileStore.useUnitTestClient(client);
} catch (ignore) {}

expect(onUpdate).not.toHaveBeenCalled();
Expand Down
4 changes: 2 additions & 2 deletions test/stores/SpaceStore-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1428,7 +1428,7 @@ describe("SpaceStore", () => {

it("passes that value in calls to getVisibleRooms during getSpaceFilteredRoomIds", () => {
// Given a store
const store = SpaceStore.testInstance();
const store = SpaceStore.testInstance(client);

// When we ask for filtered room ids
store.getSpaceFilteredRoomIds(MetaSpace.Home);
Expand Down Expand Up @@ -1478,7 +1478,7 @@ describe("SpaceStore", () => {

it("passes that value in calls to getVisibleRooms during getSpaceFilteredRoomIds", () => {
// Given a store
const store = SpaceStore.testInstance();
const store = SpaceStore.testInstance(client);
// When we ask for filtered room ids
store.getSpaceFilteredRoomIds(MetaSpace.Home);

Expand Down
2 changes: 1 addition & 1 deletion test/stores/VoiceRecordingStore-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ describe("VoiceRecordingStore", () => {

const mkStore = (): VoiceRecordingStore => {
const store = new VoiceRecordingStore();
store.start();
store.useUnitTestClient(stubClient);
return store;
};

Expand Down
8 changes: 4 additions & 4 deletions test/stores/WidgetLayoutStore-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ describe("WidgetLayoutStore", () => {

it("should recalculate all rooms when the client is ready", async () => {
mocked(client.getVisibleRooms).mockReturnValue([mockRoom]);
await store.start();
await store.start(client);

expect(roomUpdateListener).toHaveBeenCalled();
expect(store.getContainerWidgets(mockRoom, Container.Top)).toEqual([]);
Expand Down Expand Up @@ -243,7 +243,7 @@ describe("WidgetLayoutStore", () => {
});

it("should copy the layout to the room", async () => {
await store.start();
await store.start(client);
store.recalculateRoom(mockRoom);
store.moveToContainer(mockRoom, mockApps[0], Container.Top);
store.copyLayoutToRoom(mockRoom);
Expand Down Expand Up @@ -297,7 +297,7 @@ describe("WidgetLayoutStore", () => {
mocked(client.getVisibleRooms).mockReturnValue([]);
// @ts-ignore bypass private ctor for tests
const store = new WidgetLayoutStore();
await store.start();
await store.start(client);
expect(client.getVisibleRooms).toHaveBeenCalledWith(false);
});
});
Expand All @@ -314,7 +314,7 @@ describe("WidgetLayoutStore", () => {
mocked(client.getVisibleRooms).mockReturnValue([]);
// @ts-ignore bypass private ctor for tests
const store = new WidgetLayoutStore();
await store.start();
await store.start(client);
expect(client.getVisibleRooms).toHaveBeenCalledWith(true);
});
});
Expand Down
2 changes: 1 addition & 1 deletion test/stores/room-list/MessagePreviewStore-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ describe("MessagePreviewStore", () => {
mocked(client.getRoom).mockReturnValue(room);

store = MessagePreviewStore.testInstance();
await store.start();
await store.useUnitTestClient(client);
await setupAsyncStoreWithClient(store, client);
});

Expand Down
Loading
Loading