diff --git a/src/ActiveRoomObserver.ts b/src/ActiveRoomObserver.ts index ef64192203..bcdc249fea 100644 --- a/src/ActiveRoomObserver.ts +++ b/src/ActiveRoomObserver.ts @@ -16,7 +16,7 @@ limitations under the License. import { logger } from "matrix-js-sdk/src/logger"; -import RoomViewStore from './stores/RoomViewStore'; +import { RoomViewStore } from './stores/RoomViewStore'; type Listener = (isActive: boolean) => void; @@ -31,11 +31,12 @@ type Listener = (isActive: boolean) => void; */ export class ActiveRoomObserver { private listeners: {[key: string]: Listener[]} = {}; - private _activeRoomId = RoomViewStore.getRoomId(); + private _activeRoomId = RoomViewStore.instance.getRoomId(); + private readonly roomStoreToken: EventSubscription; constructor() { // TODO: We could self-destruct when the last listener goes away, or at least stop listening. - RoomViewStore.addListener(this.onRoomViewStoreUpdate); + this.roomStoreToken = RoomViewStore.instance.addListener(this.onRoomViewStoreUpdate); } public get activeRoomId(): string { @@ -71,7 +72,7 @@ export class ActiveRoomObserver { if (this._activeRoomId) this.emit(this._activeRoomId, false); // update our cache - this._activeRoomId = RoomViewStore.getRoomId(); + this._activeRoomId = RoomViewStore.instance.getRoomId(); // and emit for the new one if (this._activeRoomId) this.emit(this._activeRoomId, true); diff --git a/src/ContentMessages.ts b/src/ContentMessages.ts index ed0999fe07..7dc5b7f4a8 100644 --- a/src/ContentMessages.ts +++ b/src/ContentMessages.ts @@ -44,7 +44,7 @@ import { BlurhashEncoder } from "./BlurhashEncoder"; import SettingsStore from "./settings/SettingsStore"; import { decorateStartSendingTime, sendRoundTripMetric } from "./sendTimePerformanceMetrics"; import { TimelineRenderingType } from "./contexts/RoomContext"; -import RoomViewStore from "./stores/RoomViewStore"; +import { RoomViewStore } from "./stores/RoomViewStore"; import { addReplyToMessageContent } from "./utils/Reply"; import ErrorDialog from "./components/views/dialogs/ErrorDialog"; import UploadFailureDialog from "./components/views/dialogs/UploadFailureDialog"; @@ -468,7 +468,7 @@ export default class ContentMessages { return; } - const replyToEvent = RoomViewStore.getQuotingEvent(); + const replyToEvent = RoomViewStore.instance.getQuotingEvent(); if (!this.mediaConfig) { // hot-path optimization to not flash a spinner if we don't need to const modal = Modal.createDialog(Spinner, null, 'mx_Dialog_spinner'); await this.ensureMediaConfigFetched(matrixClient); diff --git a/src/Notifier.ts b/src/Notifier.ts index 3f17ae0091..62e2f09370 100644 --- a/src/Notifier.ts +++ b/src/Notifier.ts @@ -37,7 +37,7 @@ import SettingsStore from "./settings/SettingsStore"; import { hideToast as hideNotificationsToast } from "./toasts/DesktopNotificationsToast"; import { SettingLevel } from "./settings/SettingLevel"; import { isPushNotifyDisabled } from "./settings/controllers/NotificationControllers"; -import RoomViewStore from "./stores/RoomViewStore"; +import { RoomViewStore } from "./stores/RoomViewStore"; import UserActivity from "./UserActivity"; import { mediaFromMxc } from "./customisations/Media"; import ErrorDialog from "./components/views/dialogs/ErrorDialog"; @@ -401,7 +401,7 @@ export const Notifier = { const actions = MatrixClientPeg.get().getPushActionsForEvent(ev); if (actions?.notify) { - if (RoomViewStore.getRoomId() === room.roomId && + if (RoomViewStore.instance.getRoomId() === room.roomId && UserActivity.sharedInstance().userActiveRecently() && !Modal.hasDialogs() ) { diff --git a/src/ScalarMessaging.ts b/src/ScalarMessaging.ts index b0b8b3a0d4..a380c760b5 100644 --- a/src/ScalarMessaging.ts +++ b/src/ScalarMessaging.ts @@ -241,7 +241,7 @@ import { logger } from "matrix-js-sdk/src/logger"; import { MatrixClientPeg } from './MatrixClientPeg'; import dis from './dispatcher/dispatcher'; import WidgetUtils from './utils/WidgetUtils'; -import RoomViewStore from './stores/RoomViewStore'; +import { RoomViewStore } from './stores/RoomViewStore'; import { _t } from './languageHandler'; import { IntegrationManagers } from "./integrations/IntegrationManagers"; import { WidgetType } from "./widgets/WidgetType"; @@ -638,7 +638,7 @@ const onMessage = function(event: MessageEvent): void { } } - if (roomId !== RoomViewStore.getRoomId()) { + if (roomId !== RoomViewStore.instance.getRoomId()) { sendError(event, _t('Room %(roomId)s not visible', { roomId: roomId })); return; } diff --git a/src/SlashCommands.tsx b/src/SlashCommands.tsx index 59a25cdef2..75897bbb0a 100644 --- a/src/SlashCommands.tsx +++ b/src/SlashCommands.tsx @@ -61,7 +61,7 @@ import InfoDialog from "./components/views/dialogs/InfoDialog"; import SlashCommandHelpDialog from "./components/views/dialogs/SlashCommandHelpDialog"; import { shouldShowComponent } from "./customisations/helpers/UIComponents"; import { TimelineRenderingType } from './contexts/RoomContext'; -import RoomViewStore from "./stores/RoomViewStore"; +import { RoomViewStore } from "./stores/RoomViewStore"; import { XOR } from "./@types/common"; import { PosthogAnalytics } from "./PosthogAnalytics"; import { ViewRoomPayload } from "./dispatcher/payloads/ViewRoomPayload"; @@ -851,7 +851,7 @@ export const Commands = [ description: _td('Define the power level of a user'), isEnabled(): boolean { const cli = MatrixClientPeg.get(); - const room = cli.getRoom(RoomViewStore.getRoomId()); + const room = cli.getRoom(RoomViewStore.instance.getRoomId()); return room?.currentState.maySendStateEvent(EventType.RoomPowerLevels, cli.getUserId()); }, runFn: function(roomId, args) { @@ -891,7 +891,7 @@ export const Commands = [ description: _td('Deops user with given id'), isEnabled(): boolean { const cli = MatrixClientPeg.get(); - const room = cli.getRoom(RoomViewStore.getRoomId()); + const room = cli.getRoom(RoomViewStore.instance.getRoomId()); return room?.currentState.maySendStateEvent(EventType.RoomPowerLevels, cli.getUserId()); }, runFn: function(roomId, args) { diff --git a/src/audio/PlaybackQueue.ts b/src/audio/PlaybackQueue.ts index d470b6b94c..d90051d0f1 100644 --- a/src/audio/PlaybackQueue.ts +++ b/src/audio/PlaybackQueue.ts @@ -25,7 +25,7 @@ import { MatrixClientPeg } from "../MatrixClientPeg"; import { arrayFastClone } from "../utils/arrays"; import { PlaybackManager } from "./PlaybackManager"; import { isVoiceMessage } from "../utils/EventUtils"; -import RoomViewStore from "../stores/RoomViewStore"; +import { RoomViewStore } from "../stores/RoomViewStore"; /** * Audio playback queue management for a given room. This keeps track of where the user @@ -51,8 +51,8 @@ export class PlaybackQueue { constructor(private room: Room) { this.loadClocks(); - RoomViewStore.addListener(() => { - if (RoomViewStore.getRoomId() === this.room.roomId) { + RoomViewStore.instance.addListener(() => { + if (RoomViewStore.instance.getRoomId() === this.room.roomId) { // Reset the state of the playbacks before they start mounting and enqueuing updates. // We reset the entirety of the queue, including order, to ensure the user isn't left // confused with what order the messages are playing in. diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 906c32c0d9..d57f1651d2 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -48,7 +48,7 @@ import * as Rooms from '../../Rooms'; import eventSearch, { searchPagination } from '../../Searching'; import MainSplit from './MainSplit'; import RightPanel from './RightPanel'; -import RoomViewStore from '../../stores/RoomViewStore'; +import { RoomViewStore } from '../../stores/RoomViewStore'; import RoomScrollStateStore, { ScrollState } from '../../stores/RoomScrollStateStore'; import WidgetEchoStore from '../../stores/WidgetEchoStore'; import SettingsStore from "../../settings/SettingsStore"; @@ -296,7 +296,7 @@ export class RoomView extends React.Component { context.on(CryptoEvent.KeysChanged, this.onCrossSigningKeysChanged); context.on(MatrixEventEvent.Decrypted, this.onEventDecrypted); // Start listening for RoomViewStore updates - this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate); + this.roomStoreToken = RoomViewStore.instance.addListener(this.onRoomViewStoreUpdate); RightPanelStore.instance.on(UPDATE_EVENT, this.onRightPanelStoreUpdate); @@ -387,7 +387,7 @@ export class RoomView extends React.Component { return; } - if (!initial && this.state.roomId !== RoomViewStore.getRoomId()) { + if (!initial && this.state.roomId !== RoomViewStore.instance.getRoomId()) { // RoomView explicitly does not support changing what room // is being viewed: instead it should just be re-mounted when // switching rooms. Therefore, if the room ID changes, we @@ -402,28 +402,28 @@ export class RoomView extends React.Component { return; } - const roomId = RoomViewStore.getRoomId(); + const roomId = RoomViewStore.instance.getRoomId(); const newState: Pick = { roomId, - roomAlias: RoomViewStore.getRoomAlias(), - roomLoading: RoomViewStore.isRoomLoading(), - roomLoadError: RoomViewStore.getRoomLoadError(), - joining: RoomViewStore.isJoining(), - replyToEvent: RoomViewStore.getQuotingEvent(), + roomAlias: RoomViewStore.instance.getRoomAlias(), + roomLoading: RoomViewStore.instance.isRoomLoading(), + roomLoadError: RoomViewStore.instance.getRoomLoadError(), + joining: RoomViewStore.instance.isJoining(), + replyToEvent: RoomViewStore.instance.getQuotingEvent(), // we should only peek once we have a ready client - shouldPeek: this.state.matrixClientIsReady && RoomViewStore.shouldPeek(), + shouldPeek: this.state.matrixClientIsReady && RoomViewStore.instance.shouldPeek(), showReadReceipts: SettingsStore.getValue("showReadReceipts", roomId), showRedactions: SettingsStore.getValue("showRedactions", roomId), showJoinLeaves: SettingsStore.getValue("showJoinLeaves", roomId), showAvatarChanges: SettingsStore.getValue("showAvatarChanges", roomId), showDisplaynameChanges: SettingsStore.getValue("showDisplaynameChanges", roomId), - wasContextSwitch: RoomViewStore.getWasContextSwitch(), + wasContextSwitch: RoomViewStore.instance.getWasContextSwitch(), initialEventId: null, // default to clearing this, will get set later in the method if needed showRightPanel: RightPanelStore.instance.isOpenForRoom(roomId), }; - const initialEventId = RoomViewStore.getInitialEventId(); + const initialEventId = RoomViewStore.instance.getInitialEventId(); if (initialEventId) { const room = this.context.getRoom(roomId); let initialEvent = room?.findEventById(initialEventId); @@ -448,17 +448,17 @@ export class RoomView extends React.Component { showThread({ rootEvent: thread.rootEvent, initialEvent, - highlighted: RoomViewStore.isInitialEventHighlighted(), + highlighted: RoomViewStore.instance.isInitialEventHighlighted(), }); } else { newState.initialEventId = initialEventId; - newState.isInitialEventHighlighted = RoomViewStore.isInitialEventHighlighted(); + newState.isInitialEventHighlighted = RoomViewStore.instance.isInitialEventHighlighted(); if (thread && initialEvent?.isThreadRoot) { showThread({ rootEvent: thread.rootEvent, initialEvent, - highlighted: RoomViewStore.isInitialEventHighlighted(), + highlighted: RoomViewStore.instance.isInitialEventHighlighted(), }); } } diff --git a/src/components/structures/SpaceHierarchy.tsx b/src/components/structures/SpaceHierarchy.tsx index 625a252365..756cacab1f 100644 --- a/src/components/structures/SpaceHierarchy.tsx +++ b/src/components/structures/SpaceHierarchy.tsx @@ -60,7 +60,7 @@ import MatrixClientContext from "../../contexts/MatrixClientContext"; import { useTypedEventEmitterState } from "../../hooks/useEventEmitter"; import { IOOBData } from "../../stores/ThreepidInviteStore"; import { awaitRoomDownSync } from "../../utils/RoomUpgrade"; -import RoomViewStore from "../../stores/RoomViewStore"; +import { RoomViewStore } from "../../stores/RoomViewStore"; import { ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload"; import { JoinRoomReadyPayload } from "../../dispatcher/payloads/JoinRoomReadyPayload"; import { KeyBindingAction } from "../../accessibility/KeyboardShortcuts"; @@ -371,7 +371,7 @@ export const joinRoom = (cli: MatrixClient, hierarchy: RoomHierarchy, roomId: st metricsTrigger: "SpaceHierarchy", }); }, err => { - RoomViewStore.showJoinRoomError(err, roomId); + RoomViewStore.instance.showJoinRoomError(err, roomId); }); return prom; diff --git a/src/components/views/context_menus/RoomContextMenu.tsx b/src/components/views/context_menus/RoomContextMenu.tsx index 1d2ca8f171..132942aa1e 100644 --- a/src/components/views/context_menus/RoomContextMenu.tsx +++ b/src/components/views/context_menus/RoomContextMenu.tsx @@ -37,7 +37,7 @@ import Modal from "../../../Modal"; import ExportDialog from "../dialogs/ExportDialog"; import { useSettingValue } from "../../../hooks/useSettings"; import { usePinnedEvents } from "../right_panel/PinnedMessagesCard"; -import RoomViewStore from "../../../stores/RoomViewStore"; +import { RoomViewStore } from "../../../stores/RoomViewStore"; import { RightPanelPhases } from '../../../stores/right-panel/RightPanelStorePhases'; import { ROOM_NOTIFICATIONS_TAB } from "../dialogs/RoomSettingsDialog"; import { useEventEmitterState } from "../../../hooks/useEventEmitter"; @@ -280,7 +280,7 @@ const RoomContextMenu = ({ room, onFinished, ...props }: IProps) => { }; const ensureViewingRoom = (ev: ButtonEvent) => { - if (RoomViewStore.getRoomId() === room.roomId) return; + if (RoomViewStore.instance.getRoomId() === room.roomId) return; dis.dispatch({ action: Action.ViewRoom, room_id: room.roomId, @@ -361,7 +361,7 @@ const RoomContextMenu = ({ room, onFinished, ...props }: IProps) => { ev.stopPropagation(); Modal.createDialog(DevtoolsDialog, { - roomId: RoomViewStore.getRoomId(), + roomId: RoomViewStore.instance.getRoomId(), }, "mx_DevtoolsDialog_wrapper"); onFinished(); }} diff --git a/src/components/views/dialogs/SpotlightDialog.tsx b/src/components/views/dialogs/SpotlightDialog.tsx index 7568e45f0f..da13b85919 100644 --- a/src/components/views/dialogs/SpotlightDialog.tsx +++ b/src/components/views/dialogs/SpotlightDialog.tsx @@ -58,7 +58,7 @@ import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar"; import { Action } from "../../../dispatcher/actions"; import Modal from "../../../Modal"; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; -import RoomViewStore from "../../../stores/RoomViewStore"; +import { RoomViewStore } from "../../../stores/RoomViewStore"; import { showStartChatInviteDialog } from "../../../RoomInvite"; import SettingsStore from "../../../settings/SettingsStore"; import { SettingLevel } from "../../../settings/SettingLevel"; @@ -559,7 +559,7 @@ const SpotlightDialog: React.FC = ({ initialText = "", onFinished }) =>

{ _t("Recently viewed") }

{ BreadcrumbsStore.instance.rooms - .filter(r => r.roomId !== RoomViewStore.getRoomId()) + .filter(r => r.roomId !== RoomViewStore.instance.getRoomId()) .map(room => ( { ); if (isActiveWidget) { // We just left the room that the active widget was from. - if (this.props.room && RoomViewStore.getRoomId() !== this.props.room.roomId) { + if (this.props.room && RoomViewStore.instance.getRoomId() !== this.props.room.roomId) { // If we are not actively looking at the room then destroy this widget entirely. this.endWidgetActions(); } else if (WidgetType.JITSI.matches(this.props.app.type)) { diff --git a/src/components/views/right_panel/TimelineCard.tsx b/src/components/views/right_panel/TimelineCard.tsx index 82f651281c..fd9d42d1a7 100644 --- a/src/components/views/right_panel/TimelineCard.tsx +++ b/src/components/views/right_panel/TimelineCard.tsx @@ -35,7 +35,7 @@ import dis from '../../../dispatcher/dispatcher'; import { _t } from '../../../languageHandler'; import { ActionPayload } from '../../../dispatcher/payloads'; import { Action } from '../../../dispatcher/actions'; -import RoomViewStore from '../../../stores/RoomViewStore'; +import { RoomViewStore } from '../../../stores/RoomViewStore'; import ContentMessages from '../../../ContentMessages'; import UploadBar from '../../structures/UploadBar'; import SettingsStore from '../../../settings/SettingsStore'; @@ -92,7 +92,7 @@ export default class TimelineCard extends React.Component { } public componentDidMount(): void { - this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate); + this.roomStoreToken = RoomViewStore.instance.addListener(this.onRoomViewStoreUpdate); this.dispatcherRef = dis.register(this.onAction); this.readReceiptsSettingWatcher = SettingsStore.watchSetting("showReadReceipts", null, (...[,,, value]) => this.setState({ showReadReceipts: value as boolean }), @@ -119,12 +119,12 @@ export default class TimelineCard extends React.Component { private onRoomViewStoreUpdate = async (initial?: boolean): Promise => { const newState: Pick = { - // roomLoading: RoomViewStore.isRoomLoading(), - // roomLoadError: RoomViewStore.getRoomLoadError(), + // roomLoading: RoomViewStore.instance.isRoomLoading(), + // roomLoadError: RoomViewStore.instance.getRoomLoadError(), - initialEventId: RoomViewStore.getInitialEventId(), - isInitialEventHighlighted: RoomViewStore.isInitialEventHighlighted(), - replyToEvent: RoomViewStore.getQuotingEvent(), + initialEventId: RoomViewStore.instance.getInitialEventId(), + isInitialEventHighlighted: RoomViewStore.instance.isInitialEventHighlighted(), + replyToEvent: RoomViewStore.instance.getQuotingEvent(), }; this.setState(newState); diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index 2aa9046056..263a64c609 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -37,7 +37,7 @@ import createRoom, { findDMForUser, privateShouldBeEncrypted } from '../../../cr import DMRoomMap from '../../../utils/DMRoomMap'; import AccessibleButton, { ButtonEvent } from '../elements/AccessibleButton'; import SdkConfig from '../../../SdkConfig'; -import RoomViewStore from "../../../stores/RoomViewStore"; +import { RoomViewStore } from "../../../stores/RoomViewStore"; import MultiInviter from "../../../utils/MultiInviter"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import E2EIcon from "../rooms/E2EIcon"; @@ -425,7 +425,7 @@ const UserOptionsSection: React.FC<{ } if (canInvite && (member?.membership ?? 'leave') === 'leave' && shouldShowComponent(UIComponent.InviteUsers)) { - const roomId = member && member.roomId ? member.roomId : RoomViewStore.getRoomId(); + const roomId = member && member.roomId ? member.roomId : RoomViewStore.instance.getRoomId(); const onInviteUserButton = async (ev: ButtonEvent) => { try { // We use a MultiInviter to re-use the invite logic, even though diff --git a/src/components/views/rooms/RoomList.tsx b/src/components/views/rooms/RoomList.tsx index 6444cbfe67..1d1c49aab1 100644 --- a/src/components/views/rooms/RoomList.tsx +++ b/src/components/views/rooms/RoomList.tsx @@ -23,7 +23,7 @@ import { _t, _td } from "../../../languageHandler"; import { IState as IRovingTabIndexState, RovingTabIndexProvider } from "../../../accessibility/RovingTabIndex"; import ResizeNotifier from "../../../utils/ResizeNotifier"; import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore"; -import RoomViewStore from "../../../stores/RoomViewStore"; +import { RoomViewStore } from "../../../stores/RoomViewStore"; import { ITagMap } from "../../../stores/room-list/algorithms/models"; import { DefaultTagID, TagID } from "../../../stores/room-list/models"; import defaultDispatcher from "../../../dispatcher/dispatcher"; @@ -368,7 +368,7 @@ export default class RoomList extends React.PureComponent { public componentDidMount(): void { this.dispatcherRef = defaultDispatcher.register(this.onAction); - this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate); + this.roomStoreToken = RoomViewStore.instance.addListener(this.onRoomViewStoreUpdate); SpaceStore.instance.on(UPDATE_SUGGESTED_ROOMS, this.updateSuggestedRooms); RoomListStore.instance.on(LISTS_UPDATE_EVENT, this.updateLists); this.updateLists(); // trigger the first update @@ -383,14 +383,14 @@ export default class RoomList extends React.PureComponent { private onRoomViewStoreUpdate = () => { this.setState({ - currentRoomId: RoomViewStore.getRoomId(), + currentRoomId: RoomViewStore.instance.getRoomId(), }); }; private onAction = (payload: ActionPayload) => { if (payload.action === Action.ViewRoomDelta) { const viewRoomDeltaPayload = payload as ViewRoomDeltaPayload; - const currentRoomId = RoomViewStore.getRoomId(); + const currentRoomId = RoomViewStore.instance.getRoomId(); const room = this.getRoomDelta(currentRoomId, viewRoomDeltaPayload.delta, viewRoomDeltaPayload.unread); if (room) { defaultDispatcher.dispatch({ diff --git a/src/components/views/spaces/QuickSettingsButton.tsx b/src/components/views/spaces/QuickSettingsButton.tsx index 9206e35664..8c3ee07199 100644 --- a/src/components/views/spaces/QuickSettingsButton.tsx +++ b/src/components/views/spaces/QuickSettingsButton.tsx @@ -36,7 +36,7 @@ import { Icon as FavoriteIcon } from '../../../../res/img/element-icons/roomlist import SettingsStore from "../../../settings/SettingsStore"; import Modal from "../../../Modal"; import DevtoolsDialog from "../dialogs/DevtoolsDialog"; -import RoomViewStore from "../../../stores/RoomViewStore"; +import { RoomViewStore } from "../../../stores/RoomViewStore"; const QuickSettingsButton = ({ isPanelCollapsed = false }) => { const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu(); @@ -72,7 +72,7 @@ const QuickSettingsButton = ({ isPanelCollapsed = false }) => { onClick={() => { closeMenu(); Modal.createDialog(DevtoolsDialog, { - roomId: RoomViewStore.getRoomId(), + roomId: RoomViewStore.instance.getRoomId(), }, "mx_DevtoolsDialog_wrapper"); }} kind="danger_outline" diff --git a/src/components/views/voip/PipView.tsx b/src/components/views/voip/PipView.tsx index 3bd26c2043..ae7dd7a1af 100644 --- a/src/components/views/voip/PipView.tsx +++ b/src/components/views/voip/PipView.tsx @@ -21,7 +21,7 @@ import { logger } from "matrix-js-sdk/src/logger"; import classNames from 'classnames'; import CallView from "./CallView"; -import RoomViewStore from '../../../stores/RoomViewStore'; +import { RoomViewStore } from '../../../stores/RoomViewStore'; import CallHandler, { CallHandlerEvent } from '../../../CallHandler'; import PersistentApp from "../elements/PersistentApp"; import SettingsStore from "../../../settings/SettingsStore"; @@ -111,7 +111,7 @@ export default class PipView extends React.Component { constructor(props: IProps) { super(props); - const roomId = RoomViewStore.getRoomId(); + const roomId = RoomViewStore.instance.getRoomId(); const [primaryCall, secondaryCalls] = getPrimarySecondaryCallsForPip(roomId); @@ -129,7 +129,7 @@ export default class PipView extends React.Component { public componentDidMount() { CallHandler.instance.addListener(CallHandlerEvent.CallChangeRoom, this.updateCalls); CallHandler.instance.addListener(CallHandlerEvent.CallState, this.updateCalls); - this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate); + this.roomStoreToken = RoomViewStore.instance.addListener(this.onRoomViewStoreUpdate); MatrixClientPeg.get().on(CallEvent.RemoteHoldUnhold, this.onCallRemoteHold); const room = MatrixClientPeg.get()?.getRoom(this.state.viewedRoomId); if (room) { @@ -162,7 +162,7 @@ export default class PipView extends React.Component { } private onRoomViewStoreUpdate = () => { - const newRoomId = RoomViewStore.getRoomId(); + const newRoomId = RoomViewStore.instance.getRoomId(); const oldRoomId = this.state.viewedRoomId; if (newRoomId === oldRoomId) return; // The WidgetLayoutStore observer always tracks the currently viewed Room, diff --git a/src/stores/RoomViewStore.tsx b/src/stores/RoomViewStore.tsx index 44f049c27e..1177444d98 100644 --- a/src/stores/RoomViewStore.tsx +++ b/src/stores/RoomViewStore.tsx @@ -1,7 +1,7 @@ /* Copyright 2017 Vector Creations Ltd Copyright 2017, 2018 New Vector Ltd -Copyright 2019 The Matrix.org Foundation C.I.C. +Copyright 2019 - 2022 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -84,14 +84,16 @@ const INITIAL_STATE = { * with a subset of the js-sdk. * ``` */ -class RoomViewStore extends Store { +export class RoomViewStore extends Store { + public static readonly instance = new RoomViewStore(); + private state = INITIAL_STATE; // initialize state - constructor() { + public constructor() { super(dis); } - setState(newState: Partial) { + private setState(newState: Partial) { // If values haven't changed, there's nothing to do. // This only tries a shallow comparison, so unchanged objects will slip // through, but that's probably okay for now. @@ -110,7 +112,7 @@ class RoomViewStore extends Store { this.__emitChange(); } - __onDispatch(payload) { // eslint-disable-line @typescript-eslint/naming-convention + protected __onDispatch(payload) { // eslint-disable-line @typescript-eslint/naming-convention switch (payload.action) { // view_room: // - room_alias: '#somealias:matrix.org' @@ -367,7 +369,7 @@ class RoomViewStore extends Store { } } - private static getInvitingUserId(roomId: string): string { + private getInvitingUserId(roomId: string): string { const cli = MatrixClientPeg.get(); const room = cli.getRoom(roomId); if (room && room.getMyMembership() === "invite") { @@ -389,7 +391,7 @@ class RoomViewStore extends Store { { _t("Please contact your homeserver administrator.") }
; } else if (err.httpStatus === 404) { - const invitingUserId = RoomViewStore.getInvitingUserId(roomId); + const invitingUserId = this.getInvitingUserId(roomId); // only provide a better error message for invites if (invitingUserId) { // if the inviting user is on the same HS, there can only be one cause: they left. @@ -466,7 +468,7 @@ class RoomViewStore extends Store { // // Not joined // } // } else { - // if (RoomViewStore.isJoining()) { + // if (RoomViewStore.instance.isJoining()) { // // show spinner // } else { // // show join prompt @@ -494,9 +496,3 @@ class RoomViewStore extends Store { return this.state.wasContextSwitch; } } - -let singletonRoomViewStore: RoomViewStore = null; -if (!singletonRoomViewStore) { - singletonRoomViewStore = new RoomViewStore(); -} -export default singletonRoomViewStore; diff --git a/src/stores/right-panel/RightPanelStore.ts b/src/stores/right-panel/RightPanelStore.ts index 5a86dd38c5..0fa5616428 100644 --- a/src/stores/right-panel/RightPanelStore.ts +++ b/src/stores/right-panel/RightPanelStore.ts @@ -31,7 +31,7 @@ import { IRightPanelCard, IRightPanelForRoom, } from './RightPanelStoreIPanelState'; -import RoomViewStore from '../RoomViewStore'; +import { RoomViewStore } from '../RoomViewStore'; /** * A class for tracking the state of the right panel between layouts and @@ -55,9 +55,9 @@ export default class RightPanelStore extends ReadyWatchingStore { } protected async onReady(): Promise { - this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate); + this.roomStoreToken = RoomViewStore.instance.addListener(this.onRoomViewStoreUpdate); this.matrixClient.on(CryptoEvent.VerificationRequest, this.onVerificationRequestUpdate); - this.viewedRoomId = RoomViewStore.getRoomId(); + this.viewedRoomId = RoomViewStore.instance.getRoomId(); this.loadCacheFromSettings(); this.emitAndUpdateSettings(); } @@ -338,7 +338,7 @@ export default class RightPanelStore extends ReadyWatchingStore { private onRoomViewStoreUpdate = () => { const oldRoomId = this.viewedRoomId; - this.viewedRoomId = RoomViewStore.getRoomId(); + this.viewedRoomId = RoomViewStore.instance.getRoomId(); // load values from byRoomCache with the viewedRoomId. this.loadCacheFromSettings(); diff --git a/src/stores/room-list/RoomListStore.ts b/src/stores/room-list/RoomListStore.ts index 22237b801f..125b045c9a 100644 --- a/src/stores/room-list/RoomListStore.ts +++ b/src/stores/room-list/RoomListStore.ts @@ -27,7 +27,7 @@ import { ActionPayload } from "../../dispatcher/payloads"; import defaultDispatcher from "../../dispatcher/dispatcher"; import { readReceiptChangeIsFor } from "../../utils/read-receipts"; import { FILTER_CHANGED, FilterKind, IFilterCondition } from "./filters/IFilterCondition"; -import RoomViewStore from "../RoomViewStore"; +import { RoomViewStore } from "../RoomViewStore"; import { Algorithm, LIST_UPDATED_EVENT } from "./algorithms/Algorithm"; import { EffectiveMembership, getEffectiveMembership } from "../../utils/membership"; import RoomListLayoutStore from "./RoomListLayoutStore"; @@ -111,7 +111,7 @@ export class RoomListStoreClass extends AsyncStoreWithClient { this.readyStore.useUnitTestClient(forcedClient); } - RoomViewStore.addListener(() => this.handleRVSUpdate({})); + RoomViewStore.instance.addListener(() => this.handleRVSUpdate({})); this.algorithm.on(LIST_UPDATED_EVENT, this.onAlgorithmListUpdated); this.algorithm.on(FILTER_CHANGED, this.onAlgorithmFilterUpdated); this.setupWatchers(); @@ -134,7 +134,7 @@ export class RoomListStoreClass extends AsyncStoreWithClient { private handleRVSUpdate({ trigger = true }) { if (!this.matrixClient) return; // We assume there won't be RVS updates without a client - const activeRoomId = RoomViewStore.getRoomId(); + const activeRoomId = RoomViewStore.instance.getRoomId(); if (!activeRoomId && this.algorithm.stickyRoom) { this.algorithm.setStickyRoom(null); } else if (activeRoomId) { diff --git a/src/stores/spaces/SpaceStore.ts b/src/stores/spaces/SpaceStore.ts index 6e98868712..6293a11902 100644 --- a/src/stores/spaces/SpaceStore.ts +++ b/src/stores/spaces/SpaceStore.ts @@ -34,7 +34,7 @@ import { RoomNotificationStateStore } from "../notifications/RoomNotificationSta import { DefaultTagID } from "../room-list/models"; import { EnhancedMap, mapDiff } from "../../utils/maps"; import { setDiff, setHasDiff } from "../../utils/sets"; -import RoomViewStore from "../RoomViewStore"; +import { RoomViewStore } from "../RoomViewStore"; import { Action } from "../../dispatcher/actions"; import { arrayHasDiff, arrayHasOrderChange } from "../../utils/arrays"; import { reorderLexicographically } from "../../utils/stringOrderField"; @@ -804,7 +804,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { }; private switchSpaceIfNeeded = () => { - const roomId = RoomViewStore.getRoomId(); + const roomId = RoomViewStore.instance.getRoomId(); if (!this.isRoomInSpace(this.activeSpace, roomId) && !this.matrixClient.getRoom(roomId)?.isSpaceRoom()) { this.switchToRelatedSpace(roomId); } @@ -855,7 +855,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { } // if the room currently being viewed was just joined then switch to its related space - if (newMembership === "join" && room.roomId === RoomViewStore.getRoomId()) { + if (newMembership === "join" && room.roomId === RoomViewStore.instance.getRoomId()) { this.switchToRelatedSpace(room.roomId); } } @@ -882,7 +882,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { this.emit(room.roomId); } - if (membership === "join" && room.roomId === RoomViewStore.getRoomId()) { + if (membership === "join" && room.roomId === RoomViewStore.instance.getRoomId()) { // if the user was looking at the space and then joined: select that space this.setActiveSpace(room.roomId, false); } else if (membership === "leave" && room.roomId === this.activeSpace) { diff --git a/src/stores/widgets/StopGapWidget.ts b/src/stores/widgets/StopGapWidget.ts index 2ddd0d1761..723d335652 100644 --- a/src/stores/widgets/StopGapWidget.ts +++ b/src/stores/widgets/StopGapWidget.ts @@ -39,7 +39,7 @@ import { ClientEvent } from "matrix-js-sdk/src/client"; import { StopGapWidgetDriver } from "./StopGapWidgetDriver"; import { WidgetMessagingStore } from "./WidgetMessagingStore"; -import RoomViewStore from "../RoomViewStore"; +import { RoomViewStore } from "../RoomViewStore"; import { MatrixClientPeg } from "../../MatrixClientPeg"; import { OwnProfileStore } from "../OwnProfileStore"; import WidgetUtils from '../../utils/WidgetUtils'; @@ -175,7 +175,7 @@ export class StopGapWidget extends EventEmitter { if (this.roomId) return this.roomId; - return RoomViewStore.getRoomId(); + return RoomViewStore.instance.getRoomId(); } public get widgetApi(): ClientWidgetApi { @@ -361,13 +361,13 @@ export class StopGapWidget extends EventEmitter { // TODO: Open the right integration manager for the widget if (SettingsStore.getValue("feature_many_integration_managers")) { IntegrationManagers.sharedInstance().openAll( - MatrixClientPeg.get().getRoom(RoomViewStore.getRoomId()), + MatrixClientPeg.get().getRoom(RoomViewStore.instance.getRoomId()), `type_${integType}`, integId, ); } else { IntegrationManagers.sharedInstance().getPrimaryManager().open( - MatrixClientPeg.get().getRoom(RoomViewStore.getRoomId()), + MatrixClientPeg.get().getRoom(RoomViewStore.instance.getRoomId()), `type_${integType}`, integId, ); diff --git a/src/utils/membership.ts b/src/utils/membership.ts index 4a92fb303f..93cf0fc981 100644 --- a/src/utils/membership.ts +++ b/src/utils/membership.ts @@ -24,7 +24,7 @@ import { _t } from "../languageHandler"; import Modal, { IHandle } from "../Modal"; import ErrorDialog from "../components/views/dialogs/ErrorDialog"; import dis from "../dispatcher/dispatcher"; -import RoomViewStore from "../stores/RoomViewStore"; +import { RoomViewStore } from "../stores/RoomViewStore"; import Spinner from "../components/views/elements/Spinner"; import { isMetaSpace } from "../stores/spaces"; import SpaceStore from "../stores/spaces/SpaceStore"; @@ -186,7 +186,7 @@ export async function leaveRoomBehaviour(roomId: string, retry = true, spinner = if (!isMetaSpace(SpaceStore.instance.activeSpace) && SpaceStore.instance.activeSpace !== roomId && - RoomViewStore.getRoomId() === roomId + RoomViewStore.instance.getRoomId() === roomId ) { dis.dispatch({ action: Action.ViewRoom, diff --git a/src/utils/space.tsx b/src/utils/space.tsx index 442a411af8..e2b05c8ddf 100644 --- a/src/utils/space.tsx +++ b/src/utils/space.tsx @@ -33,7 +33,7 @@ import CreateSubspaceDialog from "../components/views/dialogs/CreateSubspaceDial import AddExistingSubspaceDialog from "../components/views/dialogs/AddExistingSubspaceDialog"; import defaultDispatcher from "../dispatcher/dispatcher"; import dis from "../dispatcher/dispatcher"; -import RoomViewStore from "../stores/RoomViewStore"; +import { RoomViewStore } from "../stores/RoomViewStore"; import { Action } from "../dispatcher/actions"; import { leaveRoomBehaviour } from "./membership"; import Spinner from "../components/views/elements/Spinner"; @@ -83,7 +83,7 @@ export const showAddExistingRooms = (space: Room): void => { onAddSubspaceClick: () => showAddExistingSubspace(space), space, onFinished: (added: boolean) => { - if (added && RoomViewStore.getRoomId() === space.roomId) { + if (added && RoomViewStore.instance.getRoomId() === space.roomId) { defaultDispatcher.fire(Action.UpdateSpaceHierarchy); } }, @@ -142,7 +142,7 @@ export const showAddExistingSubspace = (space: Room): void => { space, onCreateSubspaceClick: () => showCreateNewSubspace(space), onFinished: (added: boolean) => { - if (added && RoomViewStore.getRoomId() === space.roomId) { + if (added && RoomViewStore.instance.getRoomId() === space.roomId) { defaultDispatcher.fire(Action.UpdateSpaceHierarchy); } }, @@ -160,7 +160,7 @@ export const showCreateNewSubspace = (space: Room): void => { space, onAddExistingSpaceClick: () => showAddExistingSubspace(space), onFinished: (added: boolean) => { - if (added && RoomViewStore.getRoomId() === space.roomId) { + if (added && RoomViewStore.instance.getRoomId() === space.roomId) { defaultDispatcher.fire(Action.UpdateSpaceHierarchy); } }, diff --git a/test/stores/RoomViewStore-test.js b/test/stores/RoomViewStore-test.js index bc2bd2e936..d948fa6496 100644 --- a/test/stores/RoomViewStore-test.js +++ b/test/stores/RoomViewStore-test.js @@ -14,12 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -import RoomViewStore from '../../src/stores/RoomViewStore'; +import { RoomViewStore } from '../../src/stores/RoomViewStore'; import { Action } from '../../src/dispatcher/actions'; import { MatrixClientPeg as peg } from '../../src/MatrixClientPeg'; import * as testUtils from '../test-utils'; -const dispatch = testUtils.getDispatchForStore(RoomViewStore); +const dispatch = testUtils.getDispatchForStore(RoomViewStore.instance); jest.mock('../../src/utils/DMRoomMap', () => { const mock = { @@ -41,7 +41,7 @@ describe('RoomViewStore', function() { peg.get().off = jest.fn(); // Reset the state of the store - RoomViewStore.reset(); + RoomViewStore.instance.reset(); }); it('can be used to view a room by ID and join', function(done) { @@ -52,16 +52,16 @@ describe('RoomViewStore', function() { dispatch({ action: Action.ViewRoom, room_id: '!randomcharacters:aser.ver' }); dispatch({ action: 'join_room' }); - expect(RoomViewStore.isJoining()).toBe(true); + expect(RoomViewStore.instance.isJoining()).toBe(true); }); it('can be used to view a room by alias and join', function(done) { - const token = RoomViewStore.addListener(() => { + const token = RoomViewStore.instance.addListener(() => { // Wait until the room alias has resolved and the room ID is - if (!RoomViewStore.isRoomLoading()) { - expect(RoomViewStore.getRoomId()).toBe("!randomcharacters:aser.ver"); + if (!RoomViewStore.instance.isRoomLoading()) { + expect(RoomViewStore.instance.getRoomId()).toBe("!randomcharacters:aser.ver"); dispatch({ action: 'join_room' }); - expect(RoomViewStore.isJoining()).toBe(true); + expect(RoomViewStore.instance.isJoining()).toBe(true); } });