diff --git a/src/BasePlatform.ts b/src/BasePlatform.ts index 7bd830f3f2..5c81beb9ff 100644 --- a/src/BasePlatform.ts +++ b/src/BasePlatform.ts @@ -88,7 +88,7 @@ export default abstract class BasePlatform { protected onAction(payload: ActionPayload): void { switch (payload.action) { - case "on_client_not_viable": + case Action.ClientNotViable: case Action.OnLoggedOut: this.setNotificationCount(0); break; diff --git a/src/Lifecycle.ts b/src/Lifecycle.ts index dcd4ae9c00..30638454c2 100644 --- a/src/Lifecycle.ts +++ b/src/Lifecycle.ts @@ -1001,7 +1001,7 @@ export function softLogout(): void { // Ensure that we dispatch a view change **before** stopping the client so // so that React components unmount first. This avoids React soft crashes // that can occur when components try to use a null client. - dis.dispatch({ action: "on_client_not_viable" }); // generic version of on_logged_out + dis.dispatch({ action: Action.ClientNotViable }); // generic version of on_logged_out stopMatrixClient(/*unsetClient=*/ false); // DO NOT CALL LOGOUT. A soft logout preserves data, logout does not. @@ -1034,7 +1034,7 @@ async function startMatrixClient( // to add listeners for the 'sync' event so otherwise we'd have // a race condition (and we need to dispatch synchronously for this // to work). - dis.dispatch({ action: "will_start_client" }, true); + dis.dispatch({ action: Action.WillStartClient }, true); // reset things first just in case SdkContextClass.instance.typingStore.reset(); @@ -1080,7 +1080,7 @@ async function startMatrixClient( // dispatch that we finished starting up to wire up any other bits // of the matrix client that cannot be set prior to starting up. - dis.dispatch({ action: "client_started" }); + dis.dispatch({ action: Action.ClientStarted }); if (isSoftLogout()) { softLogout(); diff --git a/src/Presence.ts b/src/Presence.ts index 7388e2d165..7ccafdf68c 100644 --- a/src/Presence.ts +++ b/src/Presence.ts @@ -15,6 +15,7 @@ import { MatrixClientPeg } from "./MatrixClientPeg"; import dis from "./dispatcher/dispatcher"; import Timer from "./utils/Timer"; import { type ActionPayload } from "./dispatcher/payloads"; +import { Action } from "./dispatcher/actions.ts"; // Time in ms after that a user is considered as unavailable/away const UNAVAILABLE_TIME_MS = 3 * 60 * 1000; // 3 mins @@ -61,7 +62,7 @@ class Presence { } private onAction = (payload: ActionPayload): void => { - if (payload.action === "user_activity") { + if (payload.action === Action.UserActivity) { this.setState(SetPresence.Online); this.unavailableTimer?.restart(); } diff --git a/src/UserActivity.ts b/src/UserActivity.ts index c63b595b41..61f786e861 100644 --- a/src/UserActivity.ts +++ b/src/UserActivity.ts @@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details. import dis from "./dispatcher/dispatcher"; import Timer from "./utils/Timer"; +import { Action } from "./dispatcher/actions.ts"; // important these are larger than the timeouts of timers // used with UserActivity.timeWhileActive*, @@ -190,11 +191,9 @@ export default class UserActivity { this.lastScreenY = event.screenY; } - dis.dispatch({ action: "user_activity" }); + dis.dispatch({ action: Action.UserActivity }); if (!this.activeNowTimeout.isRunning()) { this.activeNowTimeout.start(); - dis.dispatch({ action: "user_activity_start" }); - UserActivity.runTimersUntilTimeout(this.attachedActiveNowTimers, this.activeNowTimeout); } else { this.activeNowTimeout.restart(); diff --git a/src/components/structures/EmbeddedPage.tsx b/src/components/structures/EmbeddedPage.tsx index b1702c87c7..53a5d7d537 100644 --- a/src/components/structures/EmbeddedPage.tsx +++ b/src/components/structures/EmbeddedPage.tsx @@ -18,6 +18,7 @@ import { MatrixClientPeg } from "../../MatrixClientPeg"; import MatrixClientContext from "../../contexts/MatrixClientContext"; import AutoHideScrollbar from "./AutoHideScrollbar"; import { type ActionPayload } from "../../dispatcher/payloads"; +import { Action } from "../../dispatcher/actions.ts"; interface IProps { // URL to request embedded page content from @@ -109,7 +110,7 @@ export default class EmbeddedPage extends React.PureComponent { private onAction = (payload: ActionPayload): void => { // HACK: Workaround for the context's MatrixClient not being set up at render time. - if (payload.action === "client_started") { + if (payload.action === Action.ClientStarted) { this.forceUpdate(); } }; diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 218f31e889..95214e2e38 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -812,13 +812,6 @@ export default class MatrixChat extends React.PureComponent { } break; } - case "view_last_screen": - // This function does what we want, despite the name. The idea is that it shows - // the last room we were looking at or some reasonable default/guess. We don't - // have to worry about email invites or similar being re-triggered because the - // function will have cleared that state and not execute that path. - this.showScreenAfterLogin(); - break; case "hide_left_panel": this.setState( { @@ -856,13 +849,13 @@ export default class MatrixChat extends React.PureComponent { this.onLoggedIn(); } break; - case "on_client_not_viable": + case Action.ClientNotViable: this.onSoftLogout(); break; case Action.OnLoggedOut: this.onLoggedOut(); break; - case "will_start_client": + case Action.WillStartClient: this.setState({ ready: false }, () => { // if the client is about to start, we are, by definition, not ready. // Set ready to false now, then it'll be set to true when the sync @@ -870,7 +863,7 @@ export default class MatrixChat extends React.PureComponent { this.onWillStartClient(); }); break; - case "client_started": + case Action.ClientStarted: // No need to make this handler async to wait for the result of this this.onClientStarted().catch((e) => { logger.error("Exception in onClientStarted", e); diff --git a/src/dispatcher/actions.ts b/src/dispatcher/actions.ts index 99e6a7d0f1..50f9c3497a 100644 --- a/src/dispatcher/actions.ts +++ b/src/dispatcher/actions.ts @@ -316,16 +316,39 @@ export enum Action { */ ShowRoomTopic = "show_room_topic", + /** + * Fired when the client is no longer viable to use: specifically, that we have been "soft-logged out". + */ + ClientNotViable = "client_not_viable", + /** * Fired when the client was logged out. No additional payload information required. */ OnLoggedOut = "on_logged_out", /** - * Fired when the client was logged in. No additional payload information required. + * Fired when the client was logged in, or has otherwise been set up with authentication data (e.g., by loading the + * access token from local storage). Note that this does not necessarily mean that a login action has happened, + * just that authentication creds have been set up. + * + * No additional payload information required. */ OnLoggedIn = "on_logged_in", + /** + * Fired when the client is about to be started, shortly after {@link OnLoggedIn}. + * + * No additional payload information required. + */ + WillStartClient = "will_start_client", + + /** + * Fired when the client has started, shortly after {@link WillStartClient}. + * + * No additional payload information required. + */ + ClientStarted = "client_started", + /** * Overwrites the existing login with fresh session credentials. Use with a OverwriteLoginPayload. */ @@ -380,4 +403,10 @@ export enum Action { * Open the create room dialog */ CreateRoom = "view_create_room", + + /** + * The `UserActivity` tracker determined that there was some activity from the user (typically a mouse movement + * or keyboard event). + */ + UserActivity = "user_activity", } diff --git a/src/stores/LifecycleStore.ts b/src/stores/LifecycleStore.ts index 6efeffa013..1afc105f19 100644 --- a/src/stores/LifecycleStore.ts +++ b/src/stores/LifecycleStore.ts @@ -69,7 +69,7 @@ class LifecycleStore extends AsyncStore { dis.dispatch(deferredAction); break; } - case "on_client_not_viable": + case Action.ClientNotViable: case Action.OnLoggedOut: this.reset(); break; diff --git a/src/stores/ReadyWatchingStore.ts b/src/stores/ReadyWatchingStore.ts index 91d7144c71..1c7b92ade7 100644 --- a/src/stores/ReadyWatchingStore.ts +++ b/src/stores/ReadyWatchingStore.ts @@ -77,7 +77,7 @@ export abstract class ReadyWatchingStore extends EventEmitter implements IDestro this.matrixClient = payload.matrixClient; await this.onReady(); } - } else if (payload.action === "on_client_not_viable" || payload.action === Action.OnLoggedOut) { + } else if (payload.action === Action.ClientNotViable || payload.action === Action.OnLoggedOut) { if (this.matrixClient) { await this.onNotReady(); this.matrixClient = undefined; diff --git a/src/stores/RoomViewStore.tsx b/src/stores/RoomViewStore.tsx index 017e1c4b66..e75de3da89 100644 --- a/src/stores/RoomViewStore.tsx +++ b/src/stores/RoomViewStore.tsx @@ -285,7 +285,7 @@ export class RoomViewStore extends EventEmitter { break; } - case "on_client_not_viable": + case Action.ClientNotViable: case Action.OnLoggedOut: this.reset(); break; diff --git a/src/vector/platform/ElectronPlatform.tsx b/src/vector/platform/ElectronPlatform.tsx index 0671801f09..941963602e 100644 --- a/src/vector/platform/ElectronPlatform.tsx +++ b/src/vector/platform/ElectronPlatform.tsx @@ -218,7 +218,7 @@ export default class ElectronPlatform extends BasePlatform { this.electron.send("app_onAction", payload); } - if (payload.action === "client_started") { + if (payload.action === Action.ClientStarted) { this.clientStartedPromiseWithResolvers.resolve(); } } diff --git a/src/vector/platform/WebPlatform.ts b/src/vector/platform/WebPlatform.ts index 87ed2389dc..a794e160a4 100644 --- a/src/vector/platform/WebPlatform.ts +++ b/src/vector/platform/WebPlatform.ts @@ -53,7 +53,7 @@ export default class WebPlatform extends BasePlatform { super.onAction(payload); switch (payload.action) { - case "client_started": + case Action.ClientStarted: // Defer drawing the toast until the client is started as the lifecycle methods reset the ToastStore right before this.registerServiceWorkerPromise.catch(this.handleServiceWorkerRegistrationError); break; diff --git a/test/unit-tests/components/structures/MatrixChat-test.tsx b/test/unit-tests/components/structures/MatrixChat-test.tsx index e7a6aea68a..4d03659045 100644 --- a/test/unit-tests/components/structures/MatrixChat-test.tsx +++ b/test/unit-tests/components/structures/MatrixChat-test.tsx @@ -547,11 +547,11 @@ describe("", () => { getComponent({ realQueryParams }); defaultDispatcher.dispatch({ - action: "will_start_client", + action: Action.WillStartClient, }); // client successfully started await waitFor(() => - expect(defaultDispatcher.dispatch).toHaveBeenCalledWith({ action: "client_started" }), + expect(defaultDispatcher.dispatch).toHaveBeenCalledWith({ action: Action.ClientStarted }), ); // set up keys screen is rendered @@ -1172,10 +1172,10 @@ describe("", () => { getComponent({ realQueryParams }); defaultDispatcher.dispatch({ - action: "will_start_client", + action: Action.WillStartClient, }); await waitFor(() => - expect(defaultDispatcher.dispatch).toHaveBeenCalledWith({ action: "client_started" }), + expect(defaultDispatcher.dispatch).toHaveBeenCalledWith({ action: Action.ClientStarted }), ); // Then we are not allowed in - we are being asked to verify @@ -1568,7 +1568,7 @@ describe("", () => { it("should continue to post login setup when no session is found in local storage", async () => { getComponent({ realQueryParams }); defaultDispatcher.dispatch({ - action: "will_start_client", + action: Action.WillStartClient, }); // set up keys screen is rendered @@ -1828,7 +1828,7 @@ describe("", () => { getComponent({}); defaultDispatcher.dispatch({ - action: "will_start_client", + action: Action.WillStartClient, }); await flushPromises(); mockClient.emit(CryptoEvent.KeyBackupFailed, "error code"); @@ -1851,7 +1851,7 @@ describe("", () => { getComponent({}); defaultDispatcher.dispatch({ - action: "will_start_client", + action: Action.WillStartClient, }); await flushPromises(); mockClient.emit(CryptoEvent.KeyBackupFailed, "error code"); diff --git a/test/unit-tests/stores/WidgetLayoutStore-test.ts b/test/unit-tests/stores/WidgetLayoutStore-test.ts index 1b5748f3a8..982c65e210 100644 --- a/test/unit-tests/stores/WidgetLayoutStore-test.ts +++ b/test/unit-tests/stores/WidgetLayoutStore-test.ts @@ -14,6 +14,7 @@ import { Container, WidgetLayoutStore } from "../../../src/stores/widgets/Widget import { stubClient } from "../../test-utils"; import defaultDispatcher from "../../../src/dispatcher/dispatcher"; import SettingsStore from "../../../src/settings/SettingsStore"; +import { Action } from "../../../src/dispatcher/actions.ts"; // setup test env values const roomId = "!room:server"; @@ -196,12 +197,7 @@ describe("WidgetLayoutStore", () => { it("should clear the layout if the client is not viable", () => { store.recalculateRoom(mockRoom); - defaultDispatcher.dispatch( - { - action: "on_client_not_viable", - }, - true, - ); + defaultDispatcher.dispatch({ action: Action.ClientNotViable }, true); expect(store.getContainerWidgets(mockRoom, Container.Top)).toEqual([]); expect(store.getContainerWidgets(mockRoom, Container.Center)).toEqual([]); diff --git a/test/unit-tests/vector/platform/ElectronPlatform-test.ts b/test/unit-tests/vector/platform/ElectronPlatform-test.ts index 90b69f7fcf..83f6984197 100644 --- a/test/unit-tests/vector/platform/ElectronPlatform-test.ts +++ b/test/unit-tests/vector/platform/ElectronPlatform-test.ts @@ -132,7 +132,7 @@ describe("ElectronPlatform", () => { new ElectronPlatform(); dispatcher.dispatch( { - action: "client_started", + action: Action.ClientStarted, }, true, ); diff --git a/test/unit-tests/vector/platform/WebPlatform-test.ts b/test/unit-tests/vector/platform/WebPlatform-test.ts index 7c1048fe05..f07a0f5533 100644 --- a/test/unit-tests/vector/platform/WebPlatform-test.ts +++ b/test/unit-tests/vector/platform/WebPlatform-test.ts @@ -15,6 +15,7 @@ import { setupLanguageMock } from "../../../setup/setupLanguage"; import ToastStore from "../../../../src/stores/ToastStore.ts"; import defaultDispatcher from "../../../../src/dispatcher/dispatcher.ts"; import { emitPromise } from "../../../test-utils"; +import { Action } from "../../../../src/dispatcher/actions.ts"; fetchMock.config.overwriteRoutes = true; @@ -49,7 +50,7 @@ describe("WebPlatform", () => { }; new WebPlatform(); - defaultDispatcher.dispatch({ action: "client_started" }); + defaultDispatcher.dispatch({ action: Action.ClientStarted }); await emitPromise(ToastStore.sharedInstance(), "update"); const toasts = ToastStore.sharedInstance().getToasts(); expect(toasts).toHaveLength(1);