Store refactor: use non-global stores in components (#9293)
* Add Stores and StoresContext and use it in MatrixChat and RoomView Added a new kind of class: - Add God object `Stores` which will hold refs to all known stores and the `MatrixClient`. This object is NOT a singleton. - Add `StoresContext` to hold onto a ref of `Stores` for use inside components. `StoresContext` is created via: - Create `Stores` in `MatrixChat`, assigning the `MatrixClient` when we have one set. Currently sets the RVS to `RoomViewStore.instance`. - Wrap `MatrixChat`s `render()` function in a `StoresContext.Provider` so it can be used anywhere. `StoresContext` is currently only used in `RoomView` via the following changes: - Remove the HOC, which redundantly set `mxClient` as a prop. We don't need this as `RoomView` was using the client from `this.context`. - Change the type of context accepted from `MatrixClientContext` to `StoresContext`. - Modify alllll the places where `this.context` is used to interact with the client and suffix `.client`. - Modify places where we use `RoomViewStore.instance` and replace them with `this.context.roomViewStore`. This makes `RoomView` use a non-global instance of RVS. * Linting * SDKContext and make client an optional constructor arg * Move SDKContext to /src/contexts * Inject all RVS deps * Linting * Remove reset calls; deep copy the INITIAL_STATE to avoid test pollution * DI singletons used in RoomView; DI them in RoomView-test too * Initial RoomViewStore.instance after all files are imported to avoid cyclical deps * Lazily init stores to allow for circular dependencies Rather than stores accepting a list of other stores in their constructors, which doesn't work when A needs B and B needs A, make new-style stores simply accept Stores. When a store needs another store, they access it via `Stores` which then lazily constructs that store if it needs it. This breaks the circular dependency at constructor time, without needing to introduce wiring diagrams or any complex DI framework. * Delete RoomViewStore.instance Replaced with Stores.instance.roomViewStore * Linting * Move OverridableStores to test/TestStores * Rejig how eager stores get made; don't automatically do it else tests break * Linting * Linting and review comments * Fix new code to use Stores.instance * s/Stores/SdkContextClass/g * Update docs * Remove unused imports * Update src/stores/RoomViewStore.tsx Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> * Remove empty c'tor to make sonar happy Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
parent
84f2974b57
commit
e946674df3
36 changed files with 467 additions and 275 deletions
|
@ -43,7 +43,6 @@ import { RoomUpload } from "./models/RoomUpload";
|
|||
import SettingsStore from "./settings/SettingsStore";
|
||||
import { decorateStartSendingTime, sendRoundTripMetric } from "./sendTimePerformanceMetrics";
|
||||
import { TimelineRenderingType } from "./contexts/RoomContext";
|
||||
import { RoomViewStore } from "./stores/RoomViewStore";
|
||||
import { addReplyToMessageContent } from "./utils/Reply";
|
||||
import ErrorDialog from "./components/views/dialogs/ErrorDialog";
|
||||
import UploadFailureDialog from "./components/views/dialogs/UploadFailureDialog";
|
||||
|
@ -51,6 +50,7 @@ import UploadConfirmDialog from "./components/views/dialogs/UploadConfirmDialog"
|
|||
import { createThumbnail } from "./utils/image-media";
|
||||
import { attachRelation } from "./components/views/rooms/SendMessageComposer";
|
||||
import { doMaybeLocalRoomAction } from "./utils/local-room";
|
||||
import { SdkContextClass } from "./contexts/SDKContext";
|
||||
|
||||
// scraped out of a macOS hidpi (5660ppm) screenshot png
|
||||
// 5669 px (x-axis) , 5669 px (y-axis) , per metre
|
||||
|
@ -361,7 +361,7 @@ export default class ContentMessages {
|
|||
return;
|
||||
}
|
||||
|
||||
const replyToEvent = RoomViewStore.instance.getQuotingEvent();
|
||||
const replyToEvent = SdkContextClass.instance.roomViewStore.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);
|
||||
|
|
|
@ -41,12 +41,12 @@ 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 UserActivity from "./UserActivity";
|
||||
import { mediaFromMxc } from "./customisations/Media";
|
||||
import ErrorDialog from "./components/views/dialogs/ErrorDialog";
|
||||
import LegacyCallHandler from "./LegacyCallHandler";
|
||||
import VoipUserMapper from "./VoipUserMapper";
|
||||
import { SdkContextClass } from "./contexts/SDKContext";
|
||||
import { localNotificationsAreSilenced } from "./utils/notifications";
|
||||
import { getIncomingCallToastKey, IncomingCallToast } from "./toasts/IncomingCallToast";
|
||||
import ToastStore from "./stores/ToastStore";
|
||||
|
@ -435,7 +435,7 @@ export const Notifier = {
|
|||
if (actions?.notify) {
|
||||
this._performCustomEventHandling(ev);
|
||||
|
||||
if (RoomViewStore.instance.getRoomId() === room.roomId &&
|
||||
if (SdkContextClass.instance.roomViewStore.getRoomId() === room.roomId &&
|
||||
UserActivity.sharedInstance().userActiveRecently() &&
|
||||
!Modal.hasDialogs()
|
||||
) {
|
||||
|
|
|
@ -272,12 +272,12 @@ 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 { _t } from './languageHandler';
|
||||
import { IntegrationManagers } from "./integrations/IntegrationManagers";
|
||||
import { WidgetType } from "./widgets/WidgetType";
|
||||
import { objectClone } from "./utils/objects";
|
||||
import { EffectiveMembership, getEffectiveMembership } from './utils/membership';
|
||||
import { SdkContextClass } from './contexts/SDKContext';
|
||||
|
||||
enum Action {
|
||||
CloseScalar = "close_scalar",
|
||||
|
@ -721,7 +721,7 @@ const onMessage = function(event: MessageEvent<any>): void {
|
|||
}
|
||||
}
|
||||
|
||||
if (roomId !== RoomViewStore.instance.getRoomId()) {
|
||||
if (roomId !== SdkContextClass.instance.roomViewStore.getRoomId()) {
|
||||
sendError(event, _t('Room %(roomId)s not visible', { roomId: roomId }));
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,6 @@ 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 { XOR } from "./@types/common";
|
||||
import { PosthogAnalytics } from "./PosthogAnalytics";
|
||||
import { ViewRoomPayload } from "./dispatcher/payloads/ViewRoomPayload";
|
||||
|
@ -70,6 +69,7 @@ import VoipUserMapper from './VoipUserMapper';
|
|||
import { htmlSerializeFromMdIfNeeded } from './editor/serialize';
|
||||
import { leaveRoomBehaviour } from "./utils/leave-behaviour";
|
||||
import { isLocalRoom } from './utils/localRoom/isLocalRoom';
|
||||
import { SdkContextClass } from './contexts/SDKContext';
|
||||
|
||||
// XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816
|
||||
interface HTMLInputEvent extends Event {
|
||||
|
@ -209,7 +209,7 @@ function successSync(value: any) {
|
|||
|
||||
const isCurrentLocalRoom = (): boolean => {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const room = cli.getRoom(RoomViewStore.instance.getRoomId());
|
||||
const room = cli.getRoom(SdkContextClass.instance.roomViewStore.getRoomId());
|
||||
return isLocalRoom(room);
|
||||
};
|
||||
|
||||
|
@ -868,7 +868,7 @@ export const Commands = [
|
|||
description: _td('Define the power level of a user'),
|
||||
isEnabled(): boolean {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const room = cli.getRoom(RoomViewStore.instance.getRoomId());
|
||||
const room = cli.getRoom(SdkContextClass.instance.roomViewStore.getRoomId());
|
||||
return room?.currentState.maySendStateEvent(EventType.RoomPowerLevels, cli.getUserId())
|
||||
&& !isLocalRoom(room);
|
||||
},
|
||||
|
@ -909,7 +909,7 @@ export const Commands = [
|
|||
description: _td('Deops user with given id'),
|
||||
isEnabled(): boolean {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const room = cli.getRoom(RoomViewStore.instance.getRoomId());
|
||||
const room = cli.getRoom(SdkContextClass.instance.roomViewStore.getRoomId());
|
||||
return room?.currentState.maySendStateEvent(EventType.RoomPowerLevels, cli.getUserId())
|
||||
&& !isLocalRoom(room);
|
||||
},
|
||||
|
|
|
@ -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 { SdkContextClass } from "../contexts/SDKContext";
|
||||
|
||||
/**
|
||||
* Audio playback queue management for a given room. This keeps track of where the user
|
||||
|
@ -51,7 +51,7 @@ export class PlaybackQueue {
|
|||
constructor(private room: Room) {
|
||||
this.loadClocks();
|
||||
|
||||
RoomViewStore.instance.addRoomListener(this.room.roomId, (isActive) => {
|
||||
SdkContextClass.instance.roomViewStore.addRoomListener(this.room.roomId, (isActive) => {
|
||||
if (!isActive) return;
|
||||
|
||||
// Reset the state of the playbacks before they start mounting and enqueuing updates.
|
||||
|
|
|
@ -137,6 +137,7 @@ import { TimelineRenderingType } from "../../contexts/RoomContext";
|
|||
import { UseCaseSelection } from '../views/elements/UseCaseSelection';
|
||||
import { ValidatedServerConfig } from '../../utils/ValidatedServerConfig';
|
||||
import { isLocalRoom } from '../../utils/localRoom/isLocalRoom';
|
||||
import { SdkContextClass, SDKContext } from '../../contexts/SDKContext';
|
||||
import { viewUserDeviceSettings } from '../../actions/handlers/viewUserDeviceSettings';
|
||||
|
||||
// legacy export
|
||||
|
@ -238,9 +239,12 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
private readonly dispatcherRef: string;
|
||||
private readonly themeWatcher: ThemeWatcher;
|
||||
private readonly fontWatcher: FontWatcher;
|
||||
private readonly stores: SdkContextClass;
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
this.stores = SdkContextClass.instance;
|
||||
this.stores.constructEagerStores();
|
||||
|
||||
this.state = {
|
||||
view: Views.LOADING,
|
||||
|
@ -762,6 +766,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
Modal.createDialog(DialPadModal, {}, "mx_Dialog_dialPadWrapper");
|
||||
break;
|
||||
case Action.OnLoggedIn:
|
||||
this.stores.client = MatrixClientPeg.get();
|
||||
if (
|
||||
// Skip this handling for token login as that always calls onLoggedIn itself
|
||||
!this.tokenLogin &&
|
||||
|
@ -2087,7 +2092,9 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
|
||||
return <ErrorBoundary>
|
||||
{ view }
|
||||
<SDKContext.Provider value={this.stores}>
|
||||
{ view }
|
||||
</SDKContext.Provider>
|
||||
</ErrorBoundary>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,21 +44,18 @@ import { RoomPermalinkCreator } from '../../utils/permalinks/Permalinks';
|
|||
import ResizeNotifier from '../../utils/ResizeNotifier';
|
||||
import ContentMessages from '../../ContentMessages';
|
||||
import Modal from '../../Modal';
|
||||
import LegacyCallHandler, { LegacyCallHandlerEvent } from '../../LegacyCallHandler';
|
||||
import { LegacyCallHandlerEvent } from '../../LegacyCallHandler';
|
||||
import dis, { defaultDispatcher } from '../../dispatcher/dispatcher';
|
||||
import * as Rooms from '../../Rooms';
|
||||
import eventSearch, { searchPagination } from '../../Searching';
|
||||
import MainSplit from './MainSplit';
|
||||
import RightPanel from './RightPanel';
|
||||
import { RoomViewStore } from '../../stores/RoomViewStore';
|
||||
import RoomScrollStateStore, { ScrollState } from '../../stores/RoomScrollStateStore';
|
||||
import WidgetEchoStore from '../../stores/WidgetEchoStore';
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
import { Layout } from "../../settings/enums/Layout";
|
||||
import AccessibleButton from "../views/elements/AccessibleButton";
|
||||
import RightPanelStore from "../../stores/right-panel/RightPanelStore";
|
||||
import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext";
|
||||
import MatrixClientContext, { MatrixClientProps, withMatrixClientHOC } from "../../contexts/MatrixClientContext";
|
||||
import { E2EStatus, shieldStatusForRoom } from '../../utils/ShieldUtils';
|
||||
import { Action } from "../../dispatcher/actions";
|
||||
import { IMatrixClientCreds } from "../../MatrixClientPeg";
|
||||
|
@ -76,12 +73,10 @@ import { IOOBData, IThreepidInvite } from "../../stores/ThreepidInviteStore";
|
|||
import EffectsOverlay from "../views/elements/EffectsOverlay";
|
||||
import { containsEmoji } from '../../effects/utils';
|
||||
import { CHAT_EFFECTS } from '../../effects';
|
||||
import WidgetStore from "../../stores/WidgetStore";
|
||||
import { CallView } from "../views/voip/CallView";
|
||||
import { UPDATE_EVENT } from "../../stores/AsyncStore";
|
||||
import Notifier from "../../Notifier";
|
||||
import { showToast as showNotificationsToast } from "../../toasts/DesktopNotificationsToast";
|
||||
import { RoomNotificationStateStore } from "../../stores/notifications/RoomNotificationStateStore";
|
||||
import { Container, WidgetLayoutStore } from "../../stores/widgets/WidgetLayoutStore";
|
||||
import { getKeyBindingsManager } from '../../KeyBindingsManager';
|
||||
import { objectHasDiff } from "../../utils/objects";
|
||||
|
@ -120,6 +115,7 @@ import { RoomStatusBarUnsentMessages } from './RoomStatusBarUnsentMessages';
|
|||
import { LargeLoader } from './LargeLoader';
|
||||
import { VoiceBroadcastInfoEventType } from '../../voice-broadcast';
|
||||
import { isVideoRoom } from '../../utils/video-rooms';
|
||||
import { SDKContext } from '../../contexts/SDKContext';
|
||||
import { CallStore, CallStoreEvent } from "../../stores/CallStore";
|
||||
import { Call } from "../../models/Call";
|
||||
|
||||
|
@ -133,7 +129,7 @@ if (DEBUG) {
|
|||
debuglog = logger.log.bind(console);
|
||||
}
|
||||
|
||||
interface IRoomProps extends MatrixClientProps {
|
||||
interface IRoomProps {
|
||||
threepidInvite: IThreepidInvite;
|
||||
oobData?: IOOBData;
|
||||
|
||||
|
@ -381,13 +377,13 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
private messagePanel: TimelinePanel;
|
||||
private roomViewBody = createRef<HTMLDivElement>();
|
||||
|
||||
static contextType = MatrixClientContext;
|
||||
public context!: React.ContextType<typeof MatrixClientContext>;
|
||||
static contextType = SDKContext;
|
||||
public context!: React.ContextType<typeof SDKContext>;
|
||||
|
||||
constructor(props: IRoomProps, context: React.ContextType<typeof MatrixClientContext>) {
|
||||
constructor(props: IRoomProps, context: React.ContextType<typeof SDKContext>) {
|
||||
super(props, context);
|
||||
|
||||
const llMembers = context.hasLazyLoadMembersEnabled();
|
||||
const llMembers = context.client.hasLazyLoadMembersEnabled();
|
||||
this.state = {
|
||||
roomId: null,
|
||||
roomLoading: true,
|
||||
|
@ -422,7 +418,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
showJoinLeaves: true,
|
||||
showAvatarChanges: true,
|
||||
showDisplaynameChanges: true,
|
||||
matrixClientIsReady: context?.isInitialSyncComplete(),
|
||||
matrixClientIsReady: context.client?.isInitialSyncComplete(),
|
||||
mainSplitContentType: MainSplitContentType.Timeline,
|
||||
timelineRenderingType: TimelineRenderingType.Room,
|
||||
liveTimeline: undefined,
|
||||
|
@ -430,25 +426,25 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
};
|
||||
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
context.on(ClientEvent.Room, this.onRoom);
|
||||
context.on(RoomEvent.Timeline, this.onRoomTimeline);
|
||||
context.on(RoomEvent.TimelineReset, this.onRoomTimelineReset);
|
||||
context.on(RoomEvent.Name, this.onRoomName);
|
||||
context.on(RoomStateEvent.Events, this.onRoomStateEvents);
|
||||
context.on(RoomStateEvent.Update, this.onRoomStateUpdate);
|
||||
context.on(RoomEvent.MyMembership, this.onMyMembership);
|
||||
context.on(CryptoEvent.KeyBackupStatus, this.onKeyBackupStatus);
|
||||
context.on(CryptoEvent.DeviceVerificationChanged, this.onDeviceVerificationChanged);
|
||||
context.on(CryptoEvent.UserTrustStatusChanged, this.onUserVerificationChanged);
|
||||
context.on(CryptoEvent.KeysChanged, this.onCrossSigningKeysChanged);
|
||||
context.on(MatrixEventEvent.Decrypted, this.onEventDecrypted);
|
||||
context.client.on(ClientEvent.Room, this.onRoom);
|
||||
context.client.on(RoomEvent.Timeline, this.onRoomTimeline);
|
||||
context.client.on(RoomEvent.TimelineReset, this.onRoomTimelineReset);
|
||||
context.client.on(RoomEvent.Name, this.onRoomName);
|
||||
context.client.on(RoomStateEvent.Events, this.onRoomStateEvents);
|
||||
context.client.on(RoomStateEvent.Update, this.onRoomStateUpdate);
|
||||
context.client.on(RoomEvent.MyMembership, this.onMyMembership);
|
||||
context.client.on(CryptoEvent.KeyBackupStatus, this.onKeyBackupStatus);
|
||||
context.client.on(CryptoEvent.DeviceVerificationChanged, this.onDeviceVerificationChanged);
|
||||
context.client.on(CryptoEvent.UserTrustStatusChanged, this.onUserVerificationChanged);
|
||||
context.client.on(CryptoEvent.KeysChanged, this.onCrossSigningKeysChanged);
|
||||
context.client.on(MatrixEventEvent.Decrypted, this.onEventDecrypted);
|
||||
// Start listening for RoomViewStore updates
|
||||
RoomViewStore.instance.on(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
||||
context.roomViewStore.on(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
||||
|
||||
RightPanelStore.instance.on(UPDATE_EVENT, this.onRightPanelStoreUpdate);
|
||||
context.rightPanelStore.on(UPDATE_EVENT, this.onRightPanelStoreUpdate);
|
||||
|
||||
WidgetEchoStore.on(UPDATE_EVENT, this.onWidgetEchoStoreUpdate);
|
||||
WidgetStore.instance.on(UPDATE_EVENT, this.onWidgetStoreUpdate);
|
||||
context.widgetStore.on(UPDATE_EVENT, this.onWidgetStoreUpdate);
|
||||
|
||||
CallStore.instance.on(CallStoreEvent.ActiveCalls, this.onActiveCalls);
|
||||
|
||||
|
@ -501,16 +497,16 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
action: "appsDrawer",
|
||||
show: true,
|
||||
});
|
||||
if (WidgetLayoutStore.instance.hasMaximisedWidget(this.state.room)) {
|
||||
if (this.context.widgetLayoutStore.hasMaximisedWidget(this.state.room)) {
|
||||
// Show chat in right panel when a widget is maximised
|
||||
RightPanelStore.instance.setCard({ phase: RightPanelPhases.Timeline });
|
||||
this.context.rightPanelStore.setCard({ phase: RightPanelPhases.Timeline });
|
||||
}
|
||||
this.checkWidgets(this.state.room);
|
||||
};
|
||||
|
||||
private checkWidgets = (room: Room): void => {
|
||||
this.setState({
|
||||
hasPinnedWidgets: WidgetLayoutStore.instance.hasPinnedWidgets(room),
|
||||
hasPinnedWidgets: this.context.widgetLayoutStore.hasPinnedWidgets(room),
|
||||
mainSplitContentType: this.getMainSplitContentType(room),
|
||||
showApps: this.shouldShowApps(room),
|
||||
});
|
||||
|
@ -518,12 +514,12 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
|
||||
private getMainSplitContentType = (room: Room) => {
|
||||
if (
|
||||
(SettingsStore.getValue("feature_group_calls") && RoomViewStore.instance.isViewingCall())
|
||||
(SettingsStore.getValue("feature_group_calls") && this.context.roomViewStore.isViewingCall())
|
||||
|| isVideoRoom(room)
|
||||
) {
|
||||
return MainSplitContentType.Call;
|
||||
}
|
||||
if (WidgetLayoutStore.instance.hasMaximisedWidget(room)) {
|
||||
if (this.context.widgetLayoutStore.hasMaximisedWidget(room)) {
|
||||
return MainSplitContentType.MaximisedWidget;
|
||||
}
|
||||
return MainSplitContentType.Timeline;
|
||||
|
@ -534,7 +530,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!initial && this.state.roomId !== RoomViewStore.instance.getRoomId()) {
|
||||
if (!initial && this.state.roomId !== this.context.roomViewStore.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
|
||||
|
@ -549,45 +545,45 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
return;
|
||||
}
|
||||
|
||||
const roomId = RoomViewStore.instance.getRoomId();
|
||||
const room = this.context.getRoom(roomId);
|
||||
const roomId = this.context.roomViewStore.getRoomId();
|
||||
const room = this.context.client.getRoom(roomId);
|
||||
|
||||
// This convoluted type signature ensures we get IntelliSense *and* correct typing
|
||||
const newState: Partial<IRoomState> & Pick<IRoomState, any> = {
|
||||
roomId,
|
||||
roomAlias: RoomViewStore.instance.getRoomAlias(),
|
||||
roomLoading: RoomViewStore.instance.isRoomLoading(),
|
||||
roomLoadError: RoomViewStore.instance.getRoomLoadError(),
|
||||
joining: RoomViewStore.instance.isJoining(),
|
||||
replyToEvent: RoomViewStore.instance.getQuotingEvent(),
|
||||
roomAlias: this.context.roomViewStore.getRoomAlias(),
|
||||
roomLoading: this.context.roomViewStore.isRoomLoading(),
|
||||
roomLoadError: this.context.roomViewStore.getRoomLoadError(),
|
||||
joining: this.context.roomViewStore.isJoining(),
|
||||
replyToEvent: this.context.roomViewStore.getQuotingEvent(),
|
||||
// we should only peek once we have a ready client
|
||||
shouldPeek: this.state.matrixClientIsReady && RoomViewStore.instance.shouldPeek(),
|
||||
shouldPeek: this.state.matrixClientIsReady && this.context.roomViewStore.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.instance.getWasContextSwitch(),
|
||||
wasContextSwitch: this.context.roomViewStore.getWasContextSwitch(),
|
||||
mainSplitContentType: room === null ? undefined : this.getMainSplitContentType(room),
|
||||
initialEventId: null, // default to clearing this, will get set later in the method if needed
|
||||
showRightPanel: RightPanelStore.instance.isOpenForRoom(roomId),
|
||||
showRightPanel: this.context.rightPanelStore.isOpenForRoom(roomId),
|
||||
activeCall: CallStore.instance.getActiveCall(roomId),
|
||||
};
|
||||
|
||||
if (
|
||||
this.state.mainSplitContentType !== MainSplitContentType.Timeline
|
||||
&& newState.mainSplitContentType === MainSplitContentType.Timeline
|
||||
&& RightPanelStore.instance.isOpen
|
||||
&& RightPanelStore.instance.currentCard.phase === RightPanelPhases.Timeline
|
||||
&& RightPanelStore.instance.roomPhaseHistory.some(card => (card.phase === RightPanelPhases.Timeline))
|
||||
&& this.context.rightPanelStore.isOpen
|
||||
&& this.context.rightPanelStore.currentCard.phase === RightPanelPhases.Timeline
|
||||
&& this.context.rightPanelStore.roomPhaseHistory.some(card => (card.phase === RightPanelPhases.Timeline))
|
||||
) {
|
||||
// We're returning to the main timeline, so hide the right panel timeline
|
||||
RightPanelStore.instance.setCard({ phase: RightPanelPhases.RoomSummary });
|
||||
RightPanelStore.instance.togglePanel(this.state.roomId ?? null);
|
||||
this.context.rightPanelStore.setCard({ phase: RightPanelPhases.RoomSummary });
|
||||
this.context.rightPanelStore.togglePanel(this.state.roomId ?? null);
|
||||
newState.showRightPanel = false;
|
||||
}
|
||||
|
||||
const initialEventId = RoomViewStore.instance.getInitialEventId();
|
||||
const initialEventId = this.context.roomViewStore.getInitialEventId();
|
||||
if (initialEventId) {
|
||||
let initialEvent = room?.findEventById(initialEventId);
|
||||
// The event does not exist in the current sync data
|
||||
|
@ -600,7 +596,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
// becomes available to fetch a whole thread
|
||||
if (!initialEvent) {
|
||||
initialEvent = await fetchInitialEvent(
|
||||
this.context,
|
||||
this.context.client,
|
||||
roomId,
|
||||
initialEventId,
|
||||
);
|
||||
|
@ -616,21 +612,21 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
action: Action.ShowThread,
|
||||
rootEvent: thread.rootEvent,
|
||||
initialEvent,
|
||||
highlighted: RoomViewStore.instance.isInitialEventHighlighted(),
|
||||
scroll_into_view: RoomViewStore.instance.initialEventScrollIntoView(),
|
||||
highlighted: this.context.roomViewStore.isInitialEventHighlighted(),
|
||||
scroll_into_view: this.context.roomViewStore.initialEventScrollIntoView(),
|
||||
});
|
||||
} else {
|
||||
newState.initialEventId = initialEventId;
|
||||
newState.isInitialEventHighlighted = RoomViewStore.instance.isInitialEventHighlighted();
|
||||
newState.initialEventScrollIntoView = RoomViewStore.instance.initialEventScrollIntoView();
|
||||
newState.isInitialEventHighlighted = this.context.roomViewStore.isInitialEventHighlighted();
|
||||
newState.initialEventScrollIntoView = this.context.roomViewStore.initialEventScrollIntoView();
|
||||
|
||||
if (thread && initialEvent?.isThreadRoot) {
|
||||
dis.dispatch<ShowThreadPayload>({
|
||||
action: Action.ShowThread,
|
||||
rootEvent: thread.rootEvent,
|
||||
initialEvent,
|
||||
highlighted: RoomViewStore.instance.isInitialEventHighlighted(),
|
||||
scroll_into_view: RoomViewStore.instance.initialEventScrollIntoView(),
|
||||
highlighted: this.context.roomViewStore.isInitialEventHighlighted(),
|
||||
scroll_into_view: this.context.roomViewStore.initialEventScrollIntoView(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -657,7 +653,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
|
||||
if (!initial && this.state.shouldPeek && !newState.shouldPeek) {
|
||||
// Stop peeking because we have joined this room now
|
||||
this.context.stopPeeking();
|
||||
this.context.client.stopPeeking();
|
||||
}
|
||||
|
||||
// Temporary logging to diagnose https://github.com/vector-im/element-web/issues/4307
|
||||
|
@ -674,7 +670,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
// NB: This does assume that the roomID will not change for the lifetime of
|
||||
// the RoomView instance
|
||||
if (initial) {
|
||||
newState.room = this.context.getRoom(newState.roomId);
|
||||
newState.room = this.context.client.getRoom(newState.roomId);
|
||||
if (newState.room) {
|
||||
newState.showApps = this.shouldShowApps(newState.room);
|
||||
this.onRoomLoaded(newState.room);
|
||||
|
@ -784,7 +780,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
peekLoading: true,
|
||||
isPeeking: true, // this will change to false if peeking fails
|
||||
});
|
||||
this.context.peekInRoom(roomId).then((room) => {
|
||||
this.context.client.peekInRoom(roomId).then((room) => {
|
||||
if (this.unmounted) {
|
||||
return;
|
||||
}
|
||||
|
@ -817,7 +813,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
});
|
||||
} else if (room) {
|
||||
// Stop peeking because we have joined this room previously
|
||||
this.context.stopPeeking();
|
||||
this.context.client.stopPeeking();
|
||||
this.setState({ isPeeking: false });
|
||||
}
|
||||
}
|
||||
|
@ -835,7 +831,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
// Otherwise (in case the user set hideWidgetDrawer by clicking the button) follow the parameter.
|
||||
const isManuallyShown = hideWidgetDrawer ? hideWidgetDrawer === "false": true;
|
||||
|
||||
const widgets = WidgetLayoutStore.instance.getContainerWidgets(room, Container.Top);
|
||||
const widgets = this.context.widgetLayoutStore.getContainerWidgets(room, Container.Top);
|
||||
return isManuallyShown && widgets.length > 0;
|
||||
}
|
||||
|
||||
|
@ -848,7 +844,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
callState: callState,
|
||||
});
|
||||
|
||||
LegacyCallHandler.instance.on(LegacyCallHandlerEvent.CallState, this.onCallState);
|
||||
this.context.legacyCallHandler.on(LegacyCallHandlerEvent.CallState, this.onCallState);
|
||||
window.addEventListener('beforeunload', this.onPageUnload);
|
||||
}
|
||||
|
||||
|
@ -885,7 +881,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
// (We could use isMounted, but facebook have deprecated that.)
|
||||
this.unmounted = true;
|
||||
|
||||
LegacyCallHandler.instance.removeListener(LegacyCallHandlerEvent.CallState, this.onCallState);
|
||||
this.context.legacyCallHandler.removeListener(LegacyCallHandlerEvent.CallState, this.onCallState);
|
||||
|
||||
// update the scroll map before we get unmounted
|
||||
if (this.state.roomId) {
|
||||
|
@ -893,47 +889,47 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
}
|
||||
|
||||
if (this.state.shouldPeek) {
|
||||
this.context.stopPeeking();
|
||||
this.context.client.stopPeeking();
|
||||
}
|
||||
|
||||
// stop tracking room changes to format permalinks
|
||||
this.stopAllPermalinkCreators();
|
||||
|
||||
dis.unregister(this.dispatcherRef);
|
||||
if (this.context) {
|
||||
this.context.removeListener(ClientEvent.Room, this.onRoom);
|
||||
this.context.removeListener(RoomEvent.Timeline, this.onRoomTimeline);
|
||||
this.context.removeListener(RoomEvent.TimelineReset, this.onRoomTimelineReset);
|
||||
this.context.removeListener(RoomEvent.Name, this.onRoomName);
|
||||
this.context.removeListener(RoomStateEvent.Events, this.onRoomStateEvents);
|
||||
this.context.removeListener(RoomEvent.MyMembership, this.onMyMembership);
|
||||
this.context.removeListener(RoomStateEvent.Update, this.onRoomStateUpdate);
|
||||
this.context.removeListener(CryptoEvent.KeyBackupStatus, this.onKeyBackupStatus);
|
||||
this.context.removeListener(CryptoEvent.DeviceVerificationChanged, this.onDeviceVerificationChanged);
|
||||
this.context.removeListener(CryptoEvent.UserTrustStatusChanged, this.onUserVerificationChanged);
|
||||
this.context.removeListener(CryptoEvent.KeysChanged, this.onCrossSigningKeysChanged);
|
||||
this.context.removeListener(MatrixEventEvent.Decrypted, this.onEventDecrypted);
|
||||
if (this.context.client) {
|
||||
this.context.client.removeListener(ClientEvent.Room, this.onRoom);
|
||||
this.context.client.removeListener(RoomEvent.Timeline, this.onRoomTimeline);
|
||||
this.context.client.removeListener(RoomEvent.TimelineReset, this.onRoomTimelineReset);
|
||||
this.context.client.removeListener(RoomEvent.Name, this.onRoomName);
|
||||
this.context.client.removeListener(RoomStateEvent.Events, this.onRoomStateEvents);
|
||||
this.context.client.removeListener(RoomEvent.MyMembership, this.onMyMembership);
|
||||
this.context.client.removeListener(RoomStateEvent.Update, this.onRoomStateUpdate);
|
||||
this.context.client.removeListener(CryptoEvent.KeyBackupStatus, this.onKeyBackupStatus);
|
||||
this.context.client.removeListener(CryptoEvent.DeviceVerificationChanged, this.onDeviceVerificationChanged);
|
||||
this.context.client.removeListener(CryptoEvent.UserTrustStatusChanged, this.onUserVerificationChanged);
|
||||
this.context.client.removeListener(CryptoEvent.KeysChanged, this.onCrossSigningKeysChanged);
|
||||
this.context.client.removeListener(MatrixEventEvent.Decrypted, this.onEventDecrypted);
|
||||
}
|
||||
|
||||
window.removeEventListener('beforeunload', this.onPageUnload);
|
||||
|
||||
RoomViewStore.instance.off(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
||||
this.context.roomViewStore.off(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
||||
|
||||
RightPanelStore.instance.off(UPDATE_EVENT, this.onRightPanelStoreUpdate);
|
||||
this.context.rightPanelStore.off(UPDATE_EVENT, this.onRightPanelStoreUpdate);
|
||||
WidgetEchoStore.removeListener(UPDATE_EVENT, this.onWidgetEchoStoreUpdate);
|
||||
WidgetStore.instance.removeListener(UPDATE_EVENT, this.onWidgetStoreUpdate);
|
||||
this.context.widgetStore.removeListener(UPDATE_EVENT, this.onWidgetStoreUpdate);
|
||||
|
||||
this.props.resizeNotifier.off("isResizing", this.onIsResizing);
|
||||
|
||||
if (this.state.room) {
|
||||
WidgetLayoutStore.instance.off(
|
||||
this.context.widgetLayoutStore.off(
|
||||
WidgetLayoutStore.emissionForRoom(this.state.room),
|
||||
this.onWidgetLayoutChange,
|
||||
);
|
||||
}
|
||||
|
||||
CallStore.instance.off(CallStoreEvent.ActiveCalls, this.onActiveCalls);
|
||||
LegacyCallHandler.instance.off(LegacyCallHandlerEvent.CallState, this.onCallState);
|
||||
this.context.legacyCallHandler.off(LegacyCallHandlerEvent.CallState, this.onCallState);
|
||||
|
||||
// cancel any pending calls to the throttled updated
|
||||
this.updateRoomMembers.cancel();
|
||||
|
@ -944,13 +940,13 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
|
||||
if (this.viewsLocalRoom) {
|
||||
// clean up if this was a local room
|
||||
this.props.mxClient.store.removeRoom(this.state.room.roomId);
|
||||
this.context.client.store.removeRoom(this.state.room.roomId);
|
||||
}
|
||||
}
|
||||
|
||||
private onRightPanelStoreUpdate = () => {
|
||||
this.setState({
|
||||
showRightPanel: RightPanelStore.instance.isOpenForRoom(this.state.roomId),
|
||||
showRightPanel: this.context.rightPanelStore.isOpenForRoom(this.state.roomId),
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1017,7 +1013,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
break;
|
||||
case 'picture_snapshot':
|
||||
ContentMessages.sharedInstance().sendContentListToRoom(
|
||||
[payload.file], this.state.room.roomId, null, this.context);
|
||||
[payload.file], this.state.room.roomId, null, this.context.client);
|
||||
break;
|
||||
case 'notifier_enabled':
|
||||
case Action.UploadStarted:
|
||||
|
@ -1043,7 +1039,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
case 'MatrixActions.sync':
|
||||
if (!this.state.matrixClientIsReady) {
|
||||
this.setState({
|
||||
matrixClientIsReady: this.context?.isInitialSyncComplete(),
|
||||
matrixClientIsReady: this.context.client?.isInitialSyncComplete(),
|
||||
}, () => {
|
||||
// send another "initial" RVS update to trigger peeking if needed
|
||||
this.onRoomViewStoreUpdate(true);
|
||||
|
@ -1112,7 +1108,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
|
||||
private onLocalRoomEvent(roomId: string) {
|
||||
if (roomId !== this.state.room.roomId) return;
|
||||
createRoomFromLocalRoom(this.props.mxClient, this.state.room as LocalRoom);
|
||||
createRoomFromLocalRoom(this.context.client, this.state.room as LocalRoom);
|
||||
}
|
||||
|
||||
private onRoomTimeline = (ev: MatrixEvent, room: Room | null, toStartOfTimeline: boolean, removed, data) => {
|
||||
|
@ -1145,7 +1141,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
this.handleEffects(ev);
|
||||
}
|
||||
|
||||
if (ev.getSender() !== this.context.credentials.userId) {
|
||||
if (ev.getSender() !== this.context.client.credentials.userId) {
|
||||
// update unread count when scrolled up
|
||||
if (!this.state.searchResults && this.state.atEndOfLiveTimeline) {
|
||||
// no change
|
||||
|
@ -1165,7 +1161,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
};
|
||||
|
||||
private handleEffects = (ev: MatrixEvent) => {
|
||||
const notifState = RoomNotificationStateStore.instance.getRoomState(this.state.room);
|
||||
const notifState = this.context.roomNotificationStateStore.getRoomState(this.state.room);
|
||||
if (!notifState.isUnread) return;
|
||||
|
||||
CHAT_EFFECTS.forEach(effect => {
|
||||
|
@ -1202,7 +1198,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
private onRoomLoaded = (room: Room) => {
|
||||
if (this.unmounted) return;
|
||||
// Attach a widget store listener only when we get a room
|
||||
WidgetLayoutStore.instance.on(WidgetLayoutStore.emissionForRoom(room), this.onWidgetLayoutChange);
|
||||
this.context.widgetLayoutStore.on(WidgetLayoutStore.emissionForRoom(room), this.onWidgetLayoutChange);
|
||||
|
||||
this.calculatePeekRules(room);
|
||||
this.updatePreviewUrlVisibility(room);
|
||||
|
@ -1214,10 +1210,10 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
|
||||
if (
|
||||
this.getMainSplitContentType(room) !== MainSplitContentType.Timeline
|
||||
&& RoomNotificationStateStore.instance.getRoomState(room).isUnread
|
||||
&& this.context.roomNotificationStateStore.getRoomState(room).isUnread
|
||||
) {
|
||||
// Automatically open the chat panel to make unread messages easier to discover
|
||||
RightPanelStore.instance.setCard({ phase: RightPanelPhases.Timeline }, true, room.roomId);
|
||||
this.context.rightPanelStore.setCard({ phase: RightPanelPhases.Timeline }, true, room.roomId);
|
||||
}
|
||||
|
||||
this.setState({
|
||||
|
@ -1244,7 +1240,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
|
||||
private async loadMembersIfJoined(room: Room) {
|
||||
// lazy load members if enabled
|
||||
if (this.context.hasLazyLoadMembersEnabled()) {
|
||||
if (this.context.client.hasLazyLoadMembersEnabled()) {
|
||||
if (room && room.getMyMembership() === 'join') {
|
||||
try {
|
||||
await room.loadMembersIfNeeded();
|
||||
|
@ -1270,7 +1266,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
|
||||
private updatePreviewUrlVisibility({ roomId }: Room) {
|
||||
// URL Previews in E2EE rooms can be a privacy leak so use a different setting which is per-room explicit
|
||||
const key = this.context.isRoomEncrypted(roomId) ? 'urlPreviewsEnabled_e2ee' : 'urlPreviewsEnabled';
|
||||
const key = this.context.client.isRoomEncrypted(roomId) ? 'urlPreviewsEnabled_e2ee' : 'urlPreviewsEnabled';
|
||||
this.setState({
|
||||
showUrlPreview: SettingsStore.getValue(key, roomId),
|
||||
});
|
||||
|
@ -1283,7 +1279,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
|
||||
// Detach the listener if the room is changing for some reason
|
||||
if (this.state.room) {
|
||||
WidgetLayoutStore.instance.off(
|
||||
this.context.widgetLayoutStore.off(
|
||||
WidgetLayoutStore.emissionForRoom(this.state.room),
|
||||
this.onWidgetLayoutChange,
|
||||
);
|
||||
|
@ -1320,15 +1316,15 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
};
|
||||
|
||||
private async updateE2EStatus(room: Room) {
|
||||
if (!this.context.isRoomEncrypted(room.roomId)) return;
|
||||
if (!this.context.client.isRoomEncrypted(room.roomId)) return;
|
||||
|
||||
// If crypto is not currently enabled, we aren't tracking devices at all,
|
||||
// so we don't know what the answer is. Let's error on the safe side and show
|
||||
// a warning for this case.
|
||||
let e2eStatus = E2EStatus.Warning;
|
||||
if (this.context.isCryptoEnabled()) {
|
||||
if (this.context.client.isCryptoEnabled()) {
|
||||
/* At this point, the user has encryption on and cross-signing on */
|
||||
e2eStatus = await shieldStatusForRoom(this.context, room);
|
||||
e2eStatus = await shieldStatusForRoom(this.context.client, room);
|
||||
}
|
||||
|
||||
if (this.unmounted) return;
|
||||
|
@ -1374,7 +1370,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
|
||||
private updatePermissions(room: Room) {
|
||||
if (room) {
|
||||
const me = this.context.getUserId();
|
||||
const me = this.context.client.getUserId();
|
||||
const canReact = (
|
||||
room.getMyMembership() === "join" &&
|
||||
room.currentState.maySendEvent(EventType.Reaction, me)
|
||||
|
@ -1442,7 +1438,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
|
||||
private onJoinButtonClicked = () => {
|
||||
// If the user is a ROU, allow them to transition to a PWLU
|
||||
if (this.context?.isGuest()) {
|
||||
if (this.context.client?.isGuest()) {
|
||||
// Join this room once the user has registered and logged in
|
||||
// (If we failed to peek, we may not have a valid room object.)
|
||||
dis.dispatch<DoAfterSyncPreparedPayload<ViewRoomPayload>>({
|
||||
|
@ -1499,13 +1495,13 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
};
|
||||
|
||||
private injectSticker(url: string, info: object, text: string, threadId: string | null) {
|
||||
if (this.context.isGuest()) {
|
||||
if (this.context.client.isGuest()) {
|
||||
dis.dispatch({ action: 'require_registration' });
|
||||
return;
|
||||
}
|
||||
|
||||
ContentMessages.sharedInstance()
|
||||
.sendStickerContentToRoom(url, this.state.room.roomId, threadId, info, text, this.context)
|
||||
.sendStickerContentToRoom(url, this.state.room.roomId, threadId, info, text, this.context.client)
|
||||
.then(undefined, (error) => {
|
||||
if (error.name === "UnknownDeviceError") {
|
||||
// Let the staus bar handle this
|
||||
|
@ -1578,7 +1574,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
return b.length - a.length;
|
||||
});
|
||||
|
||||
if (this.context.supportsExperimentalThreads()) {
|
||||
if (this.context.client.supportsExperimentalThreads()) {
|
||||
// Process all thread roots returned in this batch of search results
|
||||
// XXX: This won't work for results coming from Seshat which won't include the bundled relationship
|
||||
for (const result of results.results) {
|
||||
|
@ -1586,7 +1582,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
const bundledRelationship = event
|
||||
.getServerAggregatedRelation<IThreadBundledRelationship>(THREAD_RELATION_TYPE.name);
|
||||
if (!bundledRelationship || event.getThread()) continue;
|
||||
const room = this.context.getRoom(event.getRoomId());
|
||||
const room = this.context.client.getRoom(event.getRoomId());
|
||||
const thread = room.findThreadForEvent(event);
|
||||
if (thread) {
|
||||
event.setThread(thread);
|
||||
|
@ -1658,7 +1654,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
|
||||
const mxEv = result.context.getEvent();
|
||||
const roomId = mxEv.getRoomId();
|
||||
const room = this.context.getRoom(roomId);
|
||||
const room = this.context.client.getRoom(roomId);
|
||||
if (!room) {
|
||||
// if we do not have the room in js-sdk stores then hide it as we cannot easily show it
|
||||
// As per the spec, an all rooms search can create this condition,
|
||||
|
@ -1715,7 +1711,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
this.setState({
|
||||
rejecting: true,
|
||||
});
|
||||
this.context.leave(this.state.roomId).then(() => {
|
||||
this.context.client.leave(this.state.roomId).then(() => {
|
||||
dis.dispatch({ action: Action.ViewHomePage });
|
||||
this.setState({
|
||||
rejecting: false,
|
||||
|
@ -1742,13 +1738,13 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
});
|
||||
|
||||
try {
|
||||
const myMember = this.state.room.getMember(this.context.getUserId());
|
||||
const myMember = this.state.room.getMember(this.context.client.getUserId());
|
||||
const inviteEvent = myMember.events.member;
|
||||
const ignoredUsers = this.context.getIgnoredUsers();
|
||||
const ignoredUsers = this.context.client.getIgnoredUsers();
|
||||
ignoredUsers.push(inviteEvent.getSender()); // de-duped internally in the js-sdk
|
||||
await this.context.setIgnoredUsers(ignoredUsers);
|
||||
await this.context.client.setIgnoredUsers(ignoredUsers);
|
||||
|
||||
await this.context.leave(this.state.roomId);
|
||||
await this.context.client.leave(this.state.roomId);
|
||||
dis.dispatch({ action: Action.ViewHomePage });
|
||||
this.setState({
|
||||
rejecting: false,
|
||||
|
@ -1911,7 +1907,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
if (!this.state.room) {
|
||||
return null;
|
||||
}
|
||||
return LegacyCallHandler.instance.getCallForRoom(this.state.room.roomId);
|
||||
return this.context.legacyCallHandler.getCallForRoom(this.state.room.roomId);
|
||||
}
|
||||
|
||||
// this has to be a proper method rather than an unnamed function,
|
||||
|
@ -1924,7 +1920,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
const createEvent = this.state.room.currentState.getStateEvents(EventType.RoomCreate, "");
|
||||
if (!createEvent || !createEvent.getContent()['predecessor']) return null;
|
||||
|
||||
return this.context.getRoom(createEvent.getContent()['predecessor']['room_id']);
|
||||
return this.context.client.getRoom(createEvent.getContent()['predecessor']['room_id']);
|
||||
}
|
||||
|
||||
getHiddenHighlightCount() {
|
||||
|
@ -1953,7 +1949,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
Array.from(dataTransfer.files),
|
||||
this.state.room?.roomId ?? this.state.roomId,
|
||||
null,
|
||||
this.context,
|
||||
this.context.client,
|
||||
TimelineRenderingType.Room,
|
||||
);
|
||||
|
||||
|
@ -1970,7 +1966,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
}
|
||||
|
||||
private renderLocalRoomCreateLoader(): ReactElement {
|
||||
const names = this.state.room.getDefaultRoomName(this.props.mxClient.getUserId());
|
||||
const names = this.state.room.getDefaultRoomName(this.context.client.getUserId());
|
||||
return <RoomContext.Provider value={this.state}>
|
||||
<LocalRoomCreateLoader
|
||||
names={names}
|
||||
|
@ -2081,7 +2077,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
</ErrorBoundary>
|
||||
);
|
||||
} else {
|
||||
const myUserId = this.context.credentials.userId;
|
||||
const myUserId = this.context.client.credentials.userId;
|
||||
const myMember = this.state.room.getMember(myUserId);
|
||||
const inviteEvent = myMember ? myMember.events.member : null;
|
||||
let inviterName = _t("Unknown");
|
||||
|
@ -2162,7 +2158,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
const showRoomUpgradeBar = (
|
||||
roomVersionRecommendation &&
|
||||
roomVersionRecommendation.needsUpgrade &&
|
||||
this.state.room.userMayUpgradeRoom(this.context.credentials.userId)
|
||||
this.state.room.userMayUpgradeRoom(this.context.client.credentials.userId)
|
||||
);
|
||||
|
||||
const hiddenHighlightCount = this.getHiddenHighlightCount();
|
||||
|
@ -2174,7 +2170,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
searchInProgress={this.state.searchInProgress}
|
||||
onCancelClick={this.onCancelSearchClick}
|
||||
onSearch={this.onSearch}
|
||||
isRoomEncrypted={this.context.isRoomEncrypted(this.state.room.roomId)}
|
||||
isRoomEncrypted={this.context.client.isRoomEncrypted(this.state.room.roomId)}
|
||||
/>;
|
||||
} else if (showRoomUpgradeBar) {
|
||||
aux = <RoomUpgradeWarningBar room={this.state.room} />;
|
||||
|
@ -2236,7 +2232,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
const auxPanel = (
|
||||
<AuxPanel
|
||||
room={this.state.room}
|
||||
userId={this.context.credentials.userId}
|
||||
userId={this.context.client.credentials.userId}
|
||||
showApps={this.state.showApps}
|
||||
resizeNotifier={this.props.resizeNotifier}
|
||||
>
|
||||
|
@ -2397,7 +2393,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
mainSplitBody = <>
|
||||
<AppsDrawer
|
||||
room={this.state.room}
|
||||
userId={this.context.credentials.userId}
|
||||
userId={this.context.client.credentials.userId}
|
||||
resizeNotifier={this.props.resizeNotifier}
|
||||
showApps={true}
|
||||
/>
|
||||
|
@ -2451,7 +2447,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
onAppsClick = null;
|
||||
onForgetClick = null;
|
||||
onSearchClick = null;
|
||||
if (this.state.room.canInvite(this.context.credentials.userId)) {
|
||||
if (this.state.room.canInvite(this.context.client.credentials.userId)) {
|
||||
onInviteClick = this.onInviteClick;
|
||||
}
|
||||
viewingCall = true;
|
||||
|
@ -2493,5 +2489,4 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
}
|
||||
}
|
||||
|
||||
const RoomViewWithMatrixClient = withMatrixClientHOC(RoomView);
|
||||
export default RoomViewWithMatrixClient;
|
||||
export default RoomView;
|
||||
|
|
|
@ -60,13 +60,13 @@ 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 { ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload";
|
||||
import { JoinRoomReadyPayload } from "../../dispatcher/payloads/JoinRoomReadyPayload";
|
||||
import { KeyBindingAction } from "../../accessibility/KeyboardShortcuts";
|
||||
import { getKeyBindingsManager } from "../../KeyBindingsManager";
|
||||
import { Alignment } from "../views/elements/Tooltip";
|
||||
import { getTopic } from "../../hooks/room/useTopic";
|
||||
import { SdkContextClass } from "../../contexts/SDKContext";
|
||||
|
||||
interface IProps {
|
||||
space: Room;
|
||||
|
@ -378,7 +378,7 @@ export const joinRoom = (cli: MatrixClient, hierarchy: RoomHierarchy, roomId: st
|
|||
metricsTrigger: "SpaceHierarchy",
|
||||
});
|
||||
}, err => {
|
||||
RoomViewStore.instance.showJoinRoomError(err, roomId);
|
||||
SdkContextClass.instance.roomViewStore.showJoinRoomError(err, roomId);
|
||||
});
|
||||
|
||||
return prom;
|
||||
|
|
|
@ -51,10 +51,10 @@ import { KeyBindingAction } from "../../accessibility/KeyboardShortcuts";
|
|||
import Measured from '../views/elements/Measured';
|
||||
import PosthogTrackers from "../../PosthogTrackers";
|
||||
import { ButtonEvent } from "../views/elements/AccessibleButton";
|
||||
import { RoomViewStore } from '../../stores/RoomViewStore';
|
||||
import Spinner from "../views/elements/Spinner";
|
||||
import { ComposerInsertPayload, ComposerType } from "../../dispatcher/payloads/ComposerInsertPayload";
|
||||
import Heading from '../views/typography/Heading';
|
||||
import { SdkContextClass } from '../../contexts/SDKContext';
|
||||
|
||||
interface IProps {
|
||||
room: Room;
|
||||
|
@ -113,7 +113,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
|
|||
room.removeListener(ThreadEvent.New, this.onNewThread);
|
||||
SettingsStore.unwatchSetting(this.layoutWatcherRef);
|
||||
|
||||
const hasRoomChanged = RoomViewStore.instance.getRoomId() !== roomId;
|
||||
const hasRoomChanged = SdkContextClass.instance.roomViewStore.getRoomId() !== roomId;
|
||||
if (this.props.isInitialEventHighlighted && !hasRoomChanged) {
|
||||
dis.dispatch<ViewRoomPayload>({
|
||||
action: Action.ViewRoom,
|
||||
|
|
|
@ -24,13 +24,13 @@ import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
|||
import { Action } from "../../../dispatcher/actions";
|
||||
import { Call, ConnectionState, ElementCall } from "../../../models/Call";
|
||||
import { useCall } from "../../../hooks/useCall";
|
||||
import { RoomViewStore } from "../../../stores/RoomViewStore";
|
||||
import { useEventEmitterState } from "../../../hooks/useEventEmitter";
|
||||
import {
|
||||
OwnBeaconStore,
|
||||
OwnBeaconStoreEvent,
|
||||
} from "../../../stores/OwnBeaconStore";
|
||||
import { CallDurationFromEvent } from "../voip/CallDuration";
|
||||
import { SdkContextClass } from "../../../contexts/SDKContext";
|
||||
|
||||
interface RoomCallBannerProps {
|
||||
roomId: Room["roomId"];
|
||||
|
@ -114,7 +114,7 @@ const RoomCallBanner: React.FC<Props> = ({ roomId }) => {
|
|||
}
|
||||
|
||||
// Check if the call is already showing. No banner is needed in this case.
|
||||
if (RoomViewStore.instance.isViewingCall()) {
|
||||
if (SdkContextClass.instance.roomViewStore.isViewingCall()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@ import Modal from "../../../Modal";
|
|||
import ExportDialog from "../dialogs/ExportDialog";
|
||||
import { useFeatureEnabled } from "../../../hooks/useSettings";
|
||||
import { usePinnedEvents } from "../right_panel/PinnedMessagesCard";
|
||||
import { RoomViewStore } from "../../../stores/RoomViewStore";
|
||||
import { RightPanelPhases } from '../../../stores/right-panel/RightPanelStorePhases';
|
||||
import { ROOM_NOTIFICATIONS_TAB } from "../dialogs/RoomSettingsDialog";
|
||||
import { useEventEmitterState } from "../../../hooks/useEventEmitter";
|
||||
|
@ -50,6 +49,7 @@ import { getKeyBindingsManager } from "../../../KeyBindingsManager";
|
|||
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import DevtoolsDialog from "../dialogs/DevtoolsDialog";
|
||||
import { SdkContextClass } from "../../../contexts/SDKContext";
|
||||
|
||||
interface IProps extends IContextMenuProps {
|
||||
room: Room;
|
||||
|
@ -332,7 +332,7 @@ const RoomContextMenu = ({ room, onFinished, ...props }: IProps) => {
|
|||
};
|
||||
|
||||
const ensureViewingRoom = (ev: ButtonEvent) => {
|
||||
if (RoomViewStore.instance.getRoomId() === room.roomId) return;
|
||||
if (SdkContextClass.instance.roomViewStore.getRoomId() === room.roomId) return;
|
||||
dis.dispatch<ViewRoomPayload>({
|
||||
action: Action.ViewRoom,
|
||||
room_id: room.roomId,
|
||||
|
@ -377,7 +377,7 @@ const RoomContextMenu = ({ room, onFinished, ...props }: IProps) => {
|
|||
ev.stopPropagation();
|
||||
|
||||
Modal.createDialog(DevtoolsDialog, {
|
||||
roomId: RoomViewStore.instance.getRoomId(),
|
||||
roomId: SdkContextClass.instance.roomViewStore.getRoomId(),
|
||||
}, "mx_DevtoolsDialog_wrapper");
|
||||
onFinished();
|
||||
}}
|
||||
|
|
|
@ -66,7 +66,7 @@ import { BreadcrumbsStore } from "../../../../stores/BreadcrumbsStore";
|
|||
import { RoomNotificationState } from "../../../../stores/notifications/RoomNotificationState";
|
||||
import { RoomNotificationStateStore } from "../../../../stores/notifications/RoomNotificationStateStore";
|
||||
import { RecentAlgorithm } from "../../../../stores/room-list/algorithms/tag-sorting/RecentAlgorithm";
|
||||
import { RoomViewStore } from "../../../../stores/RoomViewStore";
|
||||
import { SdkContextClass } from "../../../../contexts/SDKContext";
|
||||
import { getMetaSpaceName } from "../../../../stores/spaces";
|
||||
import SpaceStore from "../../../../stores/spaces/SpaceStore";
|
||||
import { DirectoryMember, Member, startDmOnFirstMessage } from "../../../../utils/direct-messages";
|
||||
|
@ -1060,7 +1060,7 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = n
|
|||
</h4>
|
||||
<div>
|
||||
{ BreadcrumbsStore.instance.rooms
|
||||
.filter(r => r.roomId !== RoomViewStore.instance.getRoomId())
|
||||
.filter(r => r.roomId !== SdkContextClass.instance.roomViewStore.getRoomId())
|
||||
.map(room => (
|
||||
<TooltipOption
|
||||
id={`mx_SpotlightDialog_button_recentlyViewed_${room.roomId}`}
|
||||
|
|
|
@ -43,13 +43,13 @@ import { IApp } from "../../../stores/WidgetStore";
|
|||
import { Container, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
|
||||
import { OwnProfileStore } from '../../../stores/OwnProfileStore';
|
||||
import { UPDATE_EVENT } from '../../../stores/AsyncStore';
|
||||
import { RoomViewStore } from '../../../stores/RoomViewStore';
|
||||
import WidgetUtils from '../../../utils/WidgetUtils';
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import { ActionPayload } from "../../../dispatcher/payloads";
|
||||
import { Action } from '../../../dispatcher/actions';
|
||||
import { ElementWidgetCapabilities } from '../../../stores/widgets/ElementWidgetCapabilities';
|
||||
import { WidgetMessagingStore } from '../../../stores/widgets/WidgetMessagingStore';
|
||||
import { SdkContextClass } from '../../../contexts/SDKContext';
|
||||
|
||||
interface IProps {
|
||||
app: IApp;
|
||||
|
@ -175,7 +175,7 @@ export default class AppTile extends React.Component<IProps, IState> {
|
|||
);
|
||||
if (isActiveWidget) {
|
||||
// We just left the room that the active widget was from.
|
||||
if (this.props.room && RoomViewStore.instance.getRoomId() !== this.props.room.roomId) {
|
||||
if (this.props.room && SdkContextClass.instance.roomViewStore.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)) {
|
||||
|
|
|
@ -33,7 +33,6 @@ 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 ContentMessages from '../../../ContentMessages';
|
||||
import UploadBar from '../../structures/UploadBar';
|
||||
import SettingsStore from '../../../settings/SettingsStore';
|
||||
|
@ -42,6 +41,7 @@ import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
|||
import Measured from '../elements/Measured';
|
||||
import Heading from '../typography/Heading';
|
||||
import { UPDATE_EVENT } from '../../../stores/AsyncStore';
|
||||
import { SdkContextClass } from '../../../contexts/SDKContext';
|
||||
|
||||
interface IProps {
|
||||
room: Room;
|
||||
|
@ -91,7 +91,7 @@ export default class TimelineCard extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
public componentDidMount(): void {
|
||||
RoomViewStore.instance.addListener(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
||||
SdkContextClass.instance.roomViewStore.addListener(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
this.readReceiptsSettingWatcher = SettingsStore.watchSetting("showReadReceipts", null, (...[,,, value]) =>
|
||||
this.setState({ showReadReceipts: value as boolean }),
|
||||
|
@ -102,7 +102,7 @@ export default class TimelineCard extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
public componentWillUnmount(): void {
|
||||
RoomViewStore.instance.removeListener(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
||||
SdkContextClass.instance.roomViewStore.removeListener(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
||||
|
||||
if (this.readReceiptsSettingWatcher) {
|
||||
SettingsStore.unwatchSetting(this.readReceiptsSettingWatcher);
|
||||
|
@ -116,12 +116,9 @@ export default class TimelineCard extends React.Component<IProps, IState> {
|
|||
|
||||
private onRoomViewStoreUpdate = async (initial?: boolean): Promise<void> => {
|
||||
const newState: Pick<IState, any> = {
|
||||
// roomLoading: RoomViewStore.instance.isRoomLoading(),
|
||||
// roomLoadError: RoomViewStore.instance.getRoomLoadError(),
|
||||
|
||||
initialEventId: RoomViewStore.instance.getInitialEventId(),
|
||||
isInitialEventHighlighted: RoomViewStore.instance.isInitialEventHighlighted(),
|
||||
replyToEvent: RoomViewStore.instance.getQuotingEvent(),
|
||||
initialEventId: SdkContextClass.instance.roomViewStore.getInitialEventId(),
|
||||
isInitialEventHighlighted: SdkContextClass.instance.roomViewStore.isInitialEventHighlighted(),
|
||||
replyToEvent: SdkContextClass.instance.roomViewStore.getQuotingEvent(),
|
||||
};
|
||||
|
||||
this.setState(newState);
|
||||
|
|
|
@ -36,7 +36,6 @@ import { _t } from '../../../languageHandler';
|
|||
import DMRoomMap from '../../../utils/DMRoomMap';
|
||||
import AccessibleButton, { ButtonEvent } from '../elements/AccessibleButton';
|
||||
import SdkConfig from '../../../SdkConfig';
|
||||
import { RoomViewStore } from "../../../stores/RoomViewStore";
|
||||
import MultiInviter from "../../../utils/MultiInviter";
|
||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||
import E2EIcon from "../rooms/E2EIcon";
|
||||
|
@ -77,6 +76,7 @@ import UserIdentifierCustomisations from '../../../customisations/UserIdentifier
|
|||
import PosthogTrackers from "../../../PosthogTrackers";
|
||||
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
||||
import { DirectoryMember, startDmOnFirstMessage } from '../../../utils/direct-messages';
|
||||
import { SdkContextClass } from '../../../contexts/SDKContext';
|
||||
|
||||
export interface IDevice {
|
||||
deviceId: string;
|
||||
|
@ -412,7 +412,7 @@ const UserOptionsSection: React.FC<{
|
|||
}
|
||||
|
||||
if (canInvite && (member?.membership ?? 'leave') === 'leave' && shouldShowComponent(UIComponent.InviteUsers)) {
|
||||
const roomId = member && member.roomId ? member.roomId : RoomViewStore.instance.getRoomId();
|
||||
const roomId = member && member.roomId ? member.roomId : SdkContextClass.instance.roomViewStore.getRoomId();
|
||||
const onInviteUserButton = async (ev: ButtonEvent) => {
|
||||
try {
|
||||
// We use a MultiInviter to re-use the invite logic, even though we're only inviting one user.
|
||||
|
|
|
@ -38,7 +38,6 @@ import { ITagMap } from "../../../stores/room-list/algorithms/models";
|
|||
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
||||
import { UPDATE_EVENT } from "../../../stores/AsyncStore";
|
||||
import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore";
|
||||
import { RoomViewStore } from "../../../stores/RoomViewStore";
|
||||
import {
|
||||
isMetaSpace,
|
||||
ISuggestedRoom,
|
||||
|
@ -62,6 +61,7 @@ import IconizedContextMenu, {
|
|||
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
||||
import ExtraTile from "./ExtraTile";
|
||||
import RoomSublist, { IAuxButtonProps } from "./RoomSublist";
|
||||
import { SdkContextClass } from "../../../contexts/SDKContext";
|
||||
|
||||
interface IProps {
|
||||
onKeyDown: (ev: React.KeyboardEvent, state: IRovingTabIndexState) => void;
|
||||
|
@ -421,7 +421,7 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
|
|||
|
||||
public componentDidMount(): void {
|
||||
this.dispatcherRef = defaultDispatcher.register(this.onAction);
|
||||
RoomViewStore.instance.on(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
||||
SdkContextClass.instance.roomViewStore.on(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
||||
SpaceStore.instance.on(UPDATE_SUGGESTED_ROOMS, this.updateSuggestedRooms);
|
||||
RoomListStore.instance.on(LISTS_UPDATE_EVENT, this.updateLists);
|
||||
this.favouriteMessageWatcher =
|
||||
|
@ -436,19 +436,19 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
|
|||
RoomListStore.instance.off(LISTS_UPDATE_EVENT, this.updateLists);
|
||||
SettingsStore.unwatchSetting(this.favouriteMessageWatcher);
|
||||
defaultDispatcher.unregister(this.dispatcherRef);
|
||||
RoomViewStore.instance.off(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
||||
SdkContextClass.instance.roomViewStore.off(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
||||
}
|
||||
|
||||
private onRoomViewStoreUpdate = () => {
|
||||
this.setState({
|
||||
currentRoomId: RoomViewStore.instance.getRoomId(),
|
||||
currentRoomId: SdkContextClass.instance.roomViewStore.getRoomId(),
|
||||
});
|
||||
};
|
||||
|
||||
private onAction = (payload: ActionPayload) => {
|
||||
if (payload.action === Action.ViewRoomDelta) {
|
||||
const viewRoomDeltaPayload = payload as ViewRoomDeltaPayload;
|
||||
const currentRoomId = RoomViewStore.instance.getRoomId();
|
||||
const currentRoomId = SdkContextClass.instance.roomViewStore.getRoomId();
|
||||
const room = this.getRoomDelta(currentRoomId, viewRoomDeltaPayload.delta, viewRoomDeltaPayload.unread);
|
||||
if (room) {
|
||||
defaultDispatcher.dispatch<ViewRoomPayload>({
|
||||
|
|
|
@ -44,10 +44,10 @@ import PosthogTrackers from "../../../PosthogTrackers";
|
|||
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
||||
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
|
||||
import { getKeyBindingsManager } from "../../../KeyBindingsManager";
|
||||
import { RoomViewStore } from "../../../stores/RoomViewStore";
|
||||
import { RoomTileCallSummary } from "./RoomTileCallSummary";
|
||||
import { RoomGeneralContextMenu } from "../context_menus/RoomGeneralContextMenu";
|
||||
import { CallStore, CallStoreEvent } from "../../../stores/CallStore";
|
||||
import { SdkContextClass } from "../../../contexts/SDKContext";
|
||||
|
||||
interface IProps {
|
||||
room: Room;
|
||||
|
@ -86,7 +86,7 @@ export default class RoomTile extends React.PureComponent<IProps, IState> {
|
|||
super(props);
|
||||
|
||||
this.state = {
|
||||
selected: RoomViewStore.instance.getRoomId() === this.props.room.roomId,
|
||||
selected: SdkContextClass.instance.roomViewStore.getRoomId() === this.props.room.roomId,
|
||||
notificationsMenuPosition: null,
|
||||
generalMenuPosition: null,
|
||||
call: CallStore.instance.getCall(this.props.room.roomId),
|
||||
|
@ -146,7 +146,7 @@ export default class RoomTile extends React.PureComponent<IProps, IState> {
|
|||
this.scrollIntoView();
|
||||
}
|
||||
|
||||
RoomViewStore.instance.addRoomListener(this.props.room.roomId, this.onActiveRoomUpdate);
|
||||
SdkContextClass.instance.roomViewStore.addRoomListener(this.props.room.roomId, this.onActiveRoomUpdate);
|
||||
this.dispatcherRef = defaultDispatcher.register(this.onAction);
|
||||
MessagePreviewStore.instance.on(
|
||||
MessagePreviewStore.getPreviewChangedEventName(this.props.room),
|
||||
|
@ -163,7 +163,7 @@ export default class RoomTile extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
RoomViewStore.instance.removeRoomListener(this.props.room.roomId, this.onActiveRoomUpdate);
|
||||
SdkContextClass.instance.roomViewStore.removeRoomListener(this.props.room.roomId, this.onActiveRoomUpdate);
|
||||
MessagePreviewStore.instance.off(
|
||||
MessagePreviewStore.getPreviewChangedEventName(this.props.room),
|
||||
this.onRoomPreviewChanged,
|
||||
|
|
|
@ -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 { SdkContextClass } from "../../../contexts/SDKContext";
|
||||
|
||||
const QuickSettingsButton = ({ isPanelCollapsed = false }) => {
|
||||
const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu<HTMLDivElement>();
|
||||
|
@ -72,7 +72,7 @@ const QuickSettingsButton = ({ isPanelCollapsed = false }) => {
|
|||
onClick={() => {
|
||||
closeMenu();
|
||||
Modal.createDialog(DevtoolsDialog, {
|
||||
roomId: RoomViewStore.instance.getRoomId(),
|
||||
roomId: SdkContextClass.instance.roomViewStore.getRoomId(),
|
||||
}, "mx_DevtoolsDialog_wrapper");
|
||||
}}
|
||||
kind="danger_outline"
|
||||
|
|
|
@ -21,7 +21,6 @@ import classNames from 'classnames';
|
|||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
|
||||
import LegacyCallView from "./LegacyCallView";
|
||||
import { RoomViewStore } from '../../../stores/RoomViewStore';
|
||||
import LegacyCallHandler, { LegacyCallHandlerEvent } from '../../../LegacyCallHandler';
|
||||
import PersistentApp from "../elements/PersistentApp";
|
||||
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
||||
|
@ -34,6 +33,7 @@ import ActiveWidgetStore, { ActiveWidgetStoreEvent } from '../../../stores/Activ
|
|||
import WidgetStore, { IApp } from "../../../stores/WidgetStore";
|
||||
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
||||
import { UPDATE_EVENT } from '../../../stores/AsyncStore';
|
||||
import { SdkContextClass } from '../../../contexts/SDKContext';
|
||||
import { CallStore } from "../../../stores/CallStore";
|
||||
import {
|
||||
VoiceBroadcastRecording,
|
||||
|
@ -129,7 +129,7 @@ class PipView extends React.Component<IProps, IState> {
|
|||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
const roomId = RoomViewStore.instance.getRoomId();
|
||||
const roomId = SdkContextClass.instance.roomViewStore.getRoomId();
|
||||
|
||||
const [primaryCall, secondaryCalls] = getPrimarySecondaryCallsForPip(roomId);
|
||||
|
||||
|
@ -147,7 +147,7 @@ class PipView extends React.Component<IProps, IState> {
|
|||
public componentDidMount() {
|
||||
LegacyCallHandler.instance.addListener(LegacyCallHandlerEvent.CallChangeRoom, this.updateCalls);
|
||||
LegacyCallHandler.instance.addListener(LegacyCallHandlerEvent.CallState, this.updateCalls);
|
||||
RoomViewStore.instance.addListener(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
||||
SdkContextClass.instance.roomViewStore.addListener(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
||||
MatrixClientPeg.get().on(CallEvent.RemoteHoldUnhold, this.onCallRemoteHold);
|
||||
const room = MatrixClientPeg.get()?.getRoom(this.state.viewedRoomId);
|
||||
if (room) {
|
||||
|
@ -164,7 +164,7 @@ class PipView extends React.Component<IProps, IState> {
|
|||
LegacyCallHandler.instance.removeListener(LegacyCallHandlerEvent.CallState, this.updateCalls);
|
||||
const cli = MatrixClientPeg.get();
|
||||
cli?.removeListener(CallEvent.RemoteHoldUnhold, this.onCallRemoteHold);
|
||||
RoomViewStore.instance.removeListener(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
||||
SdkContextClass.instance.roomViewStore.removeListener(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
||||
const room = cli?.getRoom(this.state.viewedRoomId);
|
||||
if (room) {
|
||||
WidgetLayoutStore.instance.off(WidgetLayoutStore.emissionForRoom(room), this.updateCalls);
|
||||
|
@ -186,7 +186,7 @@ class PipView extends React.Component<IProps, IState> {
|
|||
private onMove = () => this.movePersistedElement.current?.();
|
||||
|
||||
private onRoomViewStoreUpdate = () => {
|
||||
const newRoomId = RoomViewStore.instance.getRoomId();
|
||||
const newRoomId = SdkContextClass.instance.roomViewStore.getRoomId();
|
||||
const oldRoomId = this.state.viewedRoomId;
|
||||
if (newRoomId === oldRoomId) return;
|
||||
// The WidgetLayoutStore observer always tracks the currently viewed Room,
|
||||
|
|
127
src/contexts/SDKContext.ts
Normal file
127
src/contexts/SDKContext.ts
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
Copyright 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.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
import { createContext } from "react";
|
||||
|
||||
import defaultDispatcher from "../dispatcher/dispatcher";
|
||||
import LegacyCallHandler from "../LegacyCallHandler";
|
||||
import { PosthogAnalytics } from "../PosthogAnalytics";
|
||||
import { SlidingSyncManager } from "../SlidingSyncManager";
|
||||
import { RoomNotificationStateStore } from "../stores/notifications/RoomNotificationStateStore";
|
||||
import RightPanelStore from "../stores/right-panel/RightPanelStore";
|
||||
import { RoomViewStore } from "../stores/RoomViewStore";
|
||||
import SpaceStore, { SpaceStoreClass } from "../stores/spaces/SpaceStore";
|
||||
import { WidgetLayoutStore } from "../stores/widgets/WidgetLayoutStore";
|
||||
import WidgetStore from "../stores/WidgetStore";
|
||||
|
||||
export const SDKContext = createContext<SdkContextClass>(undefined);
|
||||
SDKContext.displayName = "SDKContext";
|
||||
|
||||
/**
|
||||
* A class which lazily initialises stores as and when they are requested, ensuring they remain
|
||||
* as singletons scoped to this object.
|
||||
*/
|
||||
export class SdkContextClass {
|
||||
/**
|
||||
* The global SdkContextClass instance. This is a temporary measure whilst so many stores remain global
|
||||
* as well. Over time, these stores should accept a `SdkContextClass` instance in their constructor.
|
||||
* When all stores do this, this static variable can be deleted.
|
||||
*/
|
||||
public static readonly instance = new SdkContextClass();
|
||||
|
||||
// Optional as we don't have a client on initial load if unregistered. This should be set
|
||||
// when the MatrixClient is first acquired in the dispatcher event Action.OnLoggedIn.
|
||||
// It is only safe to set this once, as updating this value will NOT notify components using
|
||||
// this Context.
|
||||
public client?: MatrixClient;
|
||||
|
||||
// All protected fields to make it easier to derive test stores
|
||||
protected _RightPanelStore?: RightPanelStore;
|
||||
protected _RoomNotificationStateStore?: RoomNotificationStateStore;
|
||||
protected _RoomViewStore?: RoomViewStore;
|
||||
protected _WidgetLayoutStore?: WidgetLayoutStore;
|
||||
protected _WidgetStore?: WidgetStore;
|
||||
protected _PosthogAnalytics?: PosthogAnalytics;
|
||||
protected _SlidingSyncManager?: SlidingSyncManager;
|
||||
protected _SpaceStore?: SpaceStoreClass;
|
||||
protected _LegacyCallHandler?: LegacyCallHandler;
|
||||
|
||||
/**
|
||||
* Automatically construct stores which need to be created eagerly so they can register with
|
||||
* the dispatcher.
|
||||
*/
|
||||
public constructEagerStores() {
|
||||
this._RoomViewStore = this.roomViewStore;
|
||||
}
|
||||
|
||||
public get legacyCallHandler(): LegacyCallHandler {
|
||||
if (!this._LegacyCallHandler) {
|
||||
this._LegacyCallHandler = LegacyCallHandler.instance;
|
||||
}
|
||||
return this._LegacyCallHandler;
|
||||
}
|
||||
public get rightPanelStore(): RightPanelStore {
|
||||
if (!this._RightPanelStore) {
|
||||
this._RightPanelStore = RightPanelStore.instance;
|
||||
}
|
||||
return this._RightPanelStore;
|
||||
}
|
||||
public get roomNotificationStateStore(): RoomNotificationStateStore {
|
||||
if (!this._RoomNotificationStateStore) {
|
||||
this._RoomNotificationStateStore = RoomNotificationStateStore.instance;
|
||||
}
|
||||
return this._RoomNotificationStateStore;
|
||||
}
|
||||
public get roomViewStore(): RoomViewStore {
|
||||
if (!this._RoomViewStore) {
|
||||
this._RoomViewStore = new RoomViewStore(
|
||||
defaultDispatcher, this,
|
||||
);
|
||||
}
|
||||
return this._RoomViewStore;
|
||||
}
|
||||
public get widgetLayoutStore(): WidgetLayoutStore {
|
||||
if (!this._WidgetLayoutStore) {
|
||||
this._WidgetLayoutStore = WidgetLayoutStore.instance;
|
||||
}
|
||||
return this._WidgetLayoutStore;
|
||||
}
|
||||
public get widgetStore(): WidgetStore {
|
||||
if (!this._WidgetStore) {
|
||||
this._WidgetStore = WidgetStore.instance;
|
||||
}
|
||||
return this._WidgetStore;
|
||||
}
|
||||
public get posthogAnalytics(): PosthogAnalytics {
|
||||
if (!this._PosthogAnalytics) {
|
||||
this._PosthogAnalytics = PosthogAnalytics.instance;
|
||||
}
|
||||
return this._PosthogAnalytics;
|
||||
}
|
||||
public get slidingSyncManager(): SlidingSyncManager {
|
||||
if (!this._SlidingSyncManager) {
|
||||
this._SlidingSyncManager = SlidingSyncManager.instance;
|
||||
}
|
||||
return this._SlidingSyncManager;
|
||||
}
|
||||
public get spaceStore(): SpaceStoreClass {
|
||||
if (!this._SpaceStore) {
|
||||
this._SpaceStore = SpaceStore.instance;
|
||||
}
|
||||
return this._SpaceStore;
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React, { ReactNode } from "react";
|
||||
import * as utils from 'matrix-js-sdk/src/utils';
|
||||
import { MatrixError } from "matrix-js-sdk/src/http-api";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { ViewRoom as ViewRoomEvent } from "@matrix-org/analytics-events/types/typescript/ViewRoom";
|
||||
|
@ -27,7 +28,7 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
|||
import { Optional } from "matrix-events-sdk";
|
||||
import EventEmitter from "events";
|
||||
|
||||
import { defaultDispatcher, MatrixDispatcher } from '../dispatcher/dispatcher';
|
||||
import { MatrixDispatcher } from '../dispatcher/dispatcher';
|
||||
import { MatrixClientPeg } from '../MatrixClientPeg';
|
||||
import Modal from '../Modal';
|
||||
import { _t } from '../languageHandler';
|
||||
|
@ -35,10 +36,8 @@ import { getCachedRoomIDForAlias, storeRoomAliasInCache } from '../RoomAliasCach
|
|||
import { Action } from "../dispatcher/actions";
|
||||
import { retry } from "../utils/promise";
|
||||
import { TimelineRenderingType } from "../contexts/RoomContext";
|
||||
import { PosthogAnalytics } from "../PosthogAnalytics";
|
||||
import { ViewRoomPayload } from "../dispatcher/payloads/ViewRoomPayload";
|
||||
import DMRoomMap from "../utils/DMRoomMap";
|
||||
import SpaceStore from "./spaces/SpaceStore";
|
||||
import { isMetaSpace, MetaSpace } from "./spaces";
|
||||
import { JoinRoomPayload } from "../dispatcher/payloads/JoinRoomPayload";
|
||||
import { JoinRoomReadyPayload } from "../dispatcher/payloads/JoinRoomReadyPayload";
|
||||
|
@ -47,9 +46,9 @@ import { ViewRoomErrorPayload } from "../dispatcher/payloads/ViewRoomErrorPayloa
|
|||
import ErrorDialog from "../components/views/dialogs/ErrorDialog";
|
||||
import { ActiveRoomChangedPayload } from "../dispatcher/payloads/ActiveRoomChangedPayload";
|
||||
import SettingsStore from "../settings/SettingsStore";
|
||||
import { SlidingSyncManager } from "../SlidingSyncManager";
|
||||
import { awaitRoomDownSync } from "../utils/RoomUpgrade";
|
||||
import { UPDATE_EVENT } from "./AsyncStore";
|
||||
import { SdkContextClass } from "../contexts/SDKContext";
|
||||
import { CallStore } from "./CallStore";
|
||||
|
||||
const NUM_JOIN_RETRY = 5;
|
||||
|
@ -131,17 +130,16 @@ type Listener = (isActive: boolean) => void;
|
|||
* A class for storing application state for RoomView.
|
||||
*/
|
||||
export class RoomViewStore extends EventEmitter {
|
||||
// Important: This cannot be a dynamic getter (lazily-constructed instance) because
|
||||
// otherwise we'll miss view_room dispatches during startup, breaking relaunches of
|
||||
// the app. We need to eagerly create the instance.
|
||||
public static readonly instance = new RoomViewStore(defaultDispatcher);
|
||||
|
||||
private state: State = INITIAL_STATE; // initialize state
|
||||
// initialize state as a copy of the initial state. We need to copy else one RVS can talk to
|
||||
// another RVS via INITIAL_STATE as they share the same underlying object. Mostly relevant for tests.
|
||||
private state = utils.deepCopy(INITIAL_STATE);
|
||||
|
||||
private dis: MatrixDispatcher;
|
||||
private dispatchToken: string;
|
||||
|
||||
public constructor(dis: MatrixDispatcher) {
|
||||
public constructor(
|
||||
dis: MatrixDispatcher, private readonly stores: SdkContextClass,
|
||||
) {
|
||||
super();
|
||||
this.resetDispatcher(dis);
|
||||
}
|
||||
|
@ -248,7 +246,7 @@ export class RoomViewStore extends EventEmitter {
|
|||
: numMembers > 1 ? "Two"
|
||||
: "One";
|
||||
|
||||
PosthogAnalytics.instance.trackEvent<JoinedRoomEvent>({
|
||||
this.stores.posthogAnalytics.trackEvent<JoinedRoomEvent>({
|
||||
eventName: "JoinedRoom",
|
||||
trigger: payload.metricsTrigger,
|
||||
roomSize,
|
||||
|
@ -291,17 +289,17 @@ export class RoomViewStore extends EventEmitter {
|
|||
|
||||
if (payload.metricsTrigger !== null && payload.room_id !== this.state.roomId) {
|
||||
let activeSpace: ViewRoomEvent["activeSpace"];
|
||||
if (SpaceStore.instance.activeSpace === MetaSpace.Home) {
|
||||
if (this.stores.spaceStore.activeSpace === MetaSpace.Home) {
|
||||
activeSpace = "Home";
|
||||
} else if (isMetaSpace(SpaceStore.instance.activeSpace)) {
|
||||
} else if (isMetaSpace(this.stores.spaceStore.activeSpace)) {
|
||||
activeSpace = "Meta";
|
||||
} else {
|
||||
activeSpace = SpaceStore.instance.activeSpaceRoom.getJoinRule() === JoinRule.Public
|
||||
activeSpace = this.stores.spaceStore.activeSpaceRoom?.getJoinRule() === JoinRule.Public
|
||||
? "Public"
|
||||
: "Private";
|
||||
}
|
||||
|
||||
PosthogAnalytics.instance.trackEvent<ViewRoomEvent>({
|
||||
this.stores.posthogAnalytics.trackEvent<ViewRoomEvent>({
|
||||
eventName: "ViewRoom",
|
||||
trigger: payload.metricsTrigger,
|
||||
viaKeyboard: payload.metricsViaKeyboard,
|
||||
|
@ -314,7 +312,7 @@ export class RoomViewStore extends EventEmitter {
|
|||
if (SettingsStore.getValue("feature_sliding_sync") && this.state.roomId !== payload.room_id) {
|
||||
if (this.state.subscribingRoomId && this.state.subscribingRoomId !== payload.room_id) {
|
||||
// unsubscribe from this room, but don't await it as we don't care when this gets done.
|
||||
SlidingSyncManager.instance.setRoomVisible(this.state.subscribingRoomId, false);
|
||||
this.stores.slidingSyncManager.setRoomVisible(this.state.subscribingRoomId, false);
|
||||
}
|
||||
this.setState({
|
||||
subscribingRoomId: payload.room_id,
|
||||
|
@ -332,11 +330,11 @@ export class RoomViewStore extends EventEmitter {
|
|||
});
|
||||
// set this room as the room subscription. We need to await for it as this will fetch
|
||||
// all room state for this room, which is required before we get the state below.
|
||||
await SlidingSyncManager.instance.setRoomVisible(payload.room_id, true);
|
||||
await this.stores.slidingSyncManager.setRoomVisible(payload.room_id, true);
|
||||
// Whilst we were subscribing another room was viewed, so stop what we're doing and
|
||||
// unsubscribe
|
||||
if (this.state.subscribingRoomId !== payload.room_id) {
|
||||
SlidingSyncManager.instance.setRoomVisible(payload.room_id, false);
|
||||
this.stores.slidingSyncManager.setRoomVisible(payload.room_id, false);
|
||||
return;
|
||||
}
|
||||
// Re-fire the payload: we won't re-process it because the prev room ID == payload room ID now
|
||||
|
@ -599,7 +597,7 @@ export class RoomViewStore extends EventEmitter {
|
|||
// // Not joined
|
||||
// }
|
||||
// } else {
|
||||
// if (RoomViewStore.instance.isJoining()) {
|
||||
// if (this.stores.roomViewStore.isJoining()) {
|
||||
// // show spinner
|
||||
// } else {
|
||||
// // show join prompt
|
||||
|
|
|
@ -34,7 +34,7 @@ import {
|
|||
import { ActionPayload } from "../../dispatcher/payloads";
|
||||
import { Action } from "../../dispatcher/actions";
|
||||
import { ActiveRoomChangedPayload } from "../../dispatcher/payloads/ActiveRoomChangedPayload";
|
||||
import { RoomViewStore } from "../RoomViewStore";
|
||||
import { SdkContextClass } from "../../contexts/SDKContext";
|
||||
|
||||
/**
|
||||
* A class for tracking the state of the right panel between layouts and
|
||||
|
@ -64,7 +64,7 @@ export default class RightPanelStore extends ReadyWatchingStore {
|
|||
}
|
||||
|
||||
protected async onReady(): Promise<any> {
|
||||
this.viewedRoomId = RoomViewStore.instance.getRoomId();
|
||||
this.viewedRoomId = SdkContextClass.instance.roomViewStore.getRoomId();
|
||||
this.matrixClient.on(CryptoEvent.VerificationRequest, this.onVerificationRequestUpdate);
|
||||
this.loadCacheFromSettings();
|
||||
this.emitAndUpdateSettings();
|
||||
|
|
|
@ -27,7 +27,6 @@ import { ActionPayload } from "../../dispatcher/payloads";
|
|||
import defaultDispatcher from "../../dispatcher/dispatcher";
|
||||
import { readReceiptChangeIsFor } from "../../utils/read-receipts";
|
||||
import { FILTER_CHANGED, IFilterCondition } from "./filters/IFilterCondition";
|
||||
import { RoomViewStore } from "../RoomViewStore";
|
||||
import { Algorithm, LIST_UPDATED_EVENT } from "./algorithms/Algorithm";
|
||||
import { EffectiveMembership, getEffectiveMembership } from "../../utils/membership";
|
||||
import RoomListLayoutStore from "./RoomListLayoutStore";
|
||||
|
@ -40,6 +39,7 @@ import { IRoomTimelineActionPayload } from "../../actions/MatrixActionCreators";
|
|||
import { RoomListStore as Interface, RoomListStoreEvent } from "./Interface";
|
||||
import { SlidingRoomListStoreClass } from "./SlidingRoomListStore";
|
||||
import { UPDATE_EVENT } from "../AsyncStore";
|
||||
import { SdkContextClass } from "../../contexts/SDKContext";
|
||||
|
||||
interface IState {
|
||||
// state is tracked in underlying classes
|
||||
|
@ -105,7 +105,7 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> implements
|
|||
this.readyStore.useUnitTestClient(forcedClient);
|
||||
}
|
||||
|
||||
RoomViewStore.instance.addListener(UPDATE_EVENT, () => this.handleRVSUpdate({}));
|
||||
SdkContextClass.instance.roomViewStore.addListener(UPDATE_EVENT, () => this.handleRVSUpdate({}));
|
||||
this.algorithm.on(LIST_UPDATED_EVENT, this.onAlgorithmListUpdated);
|
||||
this.algorithm.on(FILTER_CHANGED, this.onAlgorithmFilterUpdated);
|
||||
this.setupWatchers();
|
||||
|
@ -128,7 +128,7 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> implements
|
|||
private handleRVSUpdate({ trigger = true }) {
|
||||
if (!this.matrixClient) return; // We assume there won't be RVS updates without a client
|
||||
|
||||
const activeRoomId = RoomViewStore.instance.getRoomId();
|
||||
const activeRoomId = SdkContextClass.instance.roomViewStore.getRoomId();
|
||||
if (!activeRoomId && this.algorithm.stickyRoom) {
|
||||
this.algorithm.setStickyRoom(null);
|
||||
} else if (activeRoomId) {
|
||||
|
|
|
@ -29,8 +29,8 @@ import { SlidingSyncManager } from "../../SlidingSyncManager";
|
|||
import SpaceStore from "../spaces/SpaceStore";
|
||||
import { MetaSpace, SpaceKey, UPDATE_SELECTED_SPACE } from "../spaces";
|
||||
import { LISTS_LOADING_EVENT } from "./RoomListStore";
|
||||
import { RoomViewStore } from "../RoomViewStore";
|
||||
import { UPDATE_EVENT } from "../AsyncStore";
|
||||
import { SdkContextClass } from "../../contexts/SDKContext";
|
||||
|
||||
interface IState {
|
||||
// state is tracked in underlying classes
|
||||
|
@ -207,7 +207,7 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
|
|||
|
||||
// this room will not move due to it being viewed: it is sticky. This can be null to indicate
|
||||
// no sticky room if you aren't viewing a room.
|
||||
this.stickyRoomId = RoomViewStore.instance.getRoomId();
|
||||
this.stickyRoomId = SdkContextClass.instance.roomViewStore.getRoomId();
|
||||
let stickyRoomNewIndex = -1;
|
||||
const stickyRoomOldIndex = (tagMap[tagId] || []).findIndex((room) => {
|
||||
return room.roomId === this.stickyRoomId;
|
||||
|
@ -273,7 +273,7 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
|
|||
|
||||
private onRoomViewStoreUpdated() {
|
||||
// we only care about this to know when the user has clicked on a room to set the stickiness value
|
||||
if (RoomViewStore.instance.getRoomId() === this.stickyRoomId) {
|
||||
if (SdkContextClass.instance.roomViewStore.getRoomId() === this.stickyRoomId) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -303,7 +303,7 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
|
|||
}
|
||||
}
|
||||
// in the event we didn't call refreshOrderedLists, it helps to still remember the sticky room ID.
|
||||
this.stickyRoomId = RoomViewStore.instance.getRoomId();
|
||||
this.stickyRoomId = SdkContextClass.instance.roomViewStore.getRoomId();
|
||||
|
||||
if (hasUpdatedAnyList) {
|
||||
this.emit(LISTS_UPDATE_EVENT);
|
||||
|
@ -314,7 +314,7 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
|
|||
logger.info("SlidingRoomListStore.onReady");
|
||||
// permanent listeners: never get destroyed. Could be an issue if we want to test this in isolation.
|
||||
SlidingSyncManager.instance.slidingSync.on(SlidingSyncEvent.List, this.onSlidingSyncListUpdate.bind(this));
|
||||
RoomViewStore.instance.addListener(UPDATE_EVENT, this.onRoomViewStoreUpdated.bind(this));
|
||||
SdkContextClass.instance.roomViewStore.addListener(UPDATE_EVENT, this.onRoomViewStoreUpdated.bind(this));
|
||||
SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.onSelectedSpaceUpdated.bind(this));
|
||||
if (SpaceStore.instance.activeSpace) {
|
||||
this.onSelectedSpaceUpdated(SpaceStore.instance.activeSpace, false);
|
||||
|
|
|
@ -34,7 +34,6 @@ 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 { Action } from "../../dispatcher/actions";
|
||||
import { arrayHasDiff, arrayHasOrderChange } from "../../utils/arrays";
|
||||
import { reorderLexicographically } from "../../utils/stringOrderField";
|
||||
|
@ -64,6 +63,7 @@ import { ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload";
|
|||
import { ViewHomePagePayload } from "../../dispatcher/payloads/ViewHomePagePayload";
|
||||
import { SwitchSpacePayload } from "../../dispatcher/payloads/SwitchSpacePayload";
|
||||
import { AfterLeaveRoomPayload } from "../../dispatcher/payloads/AfterLeaveRoomPayload";
|
||||
import { SdkContextClass } from "../../contexts/SDKContext";
|
||||
|
||||
interface IState { }
|
||||
|
||||
|
@ -797,7 +797,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
|||
this.updateNotificationStates(notificationStatesToUpdate);
|
||||
};
|
||||
|
||||
private switchSpaceIfNeeded = (roomId = RoomViewStore.instance.getRoomId()) => {
|
||||
private switchSpaceIfNeeded = (roomId = SdkContextClass.instance.roomViewStore.getRoomId()) => {
|
||||
if (!this.isRoomInSpace(this.activeSpace, roomId) && !this.matrixClient.getRoom(roomId)?.isSpaceRoom()) {
|
||||
this.switchToRelatedSpace(roomId);
|
||||
}
|
||||
|
@ -848,7 +848,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
|||
}
|
||||
|
||||
// if the room currently being viewed was just joined then switch to its related space
|
||||
if (newMembership === "join" && room.roomId === RoomViewStore.instance.getRoomId()) {
|
||||
if (newMembership === "join" && room.roomId === SdkContextClass.instance.roomViewStore.getRoomId()) {
|
||||
this.switchSpaceIfNeeded(room.roomId);
|
||||
}
|
||||
}
|
||||
|
@ -875,7 +875,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
|
|||
this.emit(room.roomId);
|
||||
}
|
||||
|
||||
if (membership === "join" && room.roomId === RoomViewStore.instance.getRoomId()) {
|
||||
if (membership === "join" && room.roomId === SdkContextClass.instance.roomViewStore.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) {
|
||||
|
|
|
@ -41,7 +41,6 @@ import { ClientEvent } from "matrix-js-sdk/src/client";
|
|||
import { _t } from "../../languageHandler";
|
||||
import { StopGapWidgetDriver } from "./StopGapWidgetDriver";
|
||||
import { WidgetMessagingStore } from "./WidgetMessagingStore";
|
||||
import { RoomViewStore } from "../RoomViewStore";
|
||||
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
||||
import { OwnProfileStore } from "../OwnProfileStore";
|
||||
import WidgetUtils from '../../utils/WidgetUtils';
|
||||
|
@ -65,6 +64,7 @@ import { arrayFastClone } from "../../utils/arrays";
|
|||
import { ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload";
|
||||
import Modal from "../../Modal";
|
||||
import ErrorDialog from "../../components/views/dialogs/ErrorDialog";
|
||||
import { SdkContextClass } from "../../contexts/SDKContext";
|
||||
import { VoiceBroadcastRecordingsStore } from "../../voice-broadcast";
|
||||
|
||||
// TODO: Destroy all of this code
|
||||
|
@ -185,7 +185,7 @@ export class StopGapWidget extends EventEmitter {
|
|||
|
||||
if (this.roomId) return this.roomId;
|
||||
|
||||
return RoomViewStore.instance.getRoomId();
|
||||
return SdkContextClass.instance.roomViewStore.getRoomId();
|
||||
}
|
||||
|
||||
public get widgetApi(): ClientWidgetApi {
|
||||
|
@ -381,7 +381,7 @@ export class StopGapWidget extends EventEmitter {
|
|||
|
||||
// noinspection JSIgnoredPromiseFromCall
|
||||
IntegrationManagers.sharedInstance().getPrimaryManager().open(
|
||||
this.client.getRoom(RoomViewStore.instance.getRoomId()),
|
||||
this.client.getRoom(SdkContextClass.instance.roomViewStore.getRoomId()),
|
||||
`type_${integType}`,
|
||||
integId,
|
||||
);
|
||||
|
|
|
@ -53,9 +53,9 @@ import { CHAT_EFFECTS } from "../../effects";
|
|||
import { containsEmoji } from "../../effects/utils";
|
||||
import dis from "../../dispatcher/dispatcher";
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
import { RoomViewStore } from "../RoomViewStore";
|
||||
import { ElementWidgetCapabilities } from "./ElementWidgetCapabilities";
|
||||
import { navigateToPermalink } from "../../utils/permalinks/navigator";
|
||||
import { SdkContextClass } from "../../contexts/SDKContext";
|
||||
|
||||
// TODO: Purge this from the universe
|
||||
|
||||
|
@ -210,7 +210,7 @@ export class StopGapWidgetDriver extends WidgetDriver {
|
|||
targetRoomId: string = null,
|
||||
): Promise<ISendEventDetails> {
|
||||
const client = MatrixClientPeg.get();
|
||||
const roomId = targetRoomId || RoomViewStore.instance.getRoomId();
|
||||
const roomId = targetRoomId || SdkContextClass.instance.roomViewStore.getRoomId();
|
||||
|
||||
if (!client || !roomId) throw new Error("Not in a room or not attached to a client");
|
||||
|
||||
|
@ -291,7 +291,7 @@ export class StopGapWidgetDriver extends WidgetDriver {
|
|||
|
||||
const targetRooms = roomIds
|
||||
? (roomIds.includes(Symbols.AnyRoom) ? client.getVisibleRooms() : roomIds.map(r => client.getRoom(r)))
|
||||
: [client.getRoom(RoomViewStore.instance.getRoomId())];
|
||||
: [client.getRoom(SdkContextClass.instance.roomViewStore.getRoomId())];
|
||||
return targetRooms.filter(r => !!r);
|
||||
}
|
||||
|
||||
|
@ -430,7 +430,7 @@ export class StopGapWidgetDriver extends WidgetDriver {
|
|||
): Promise<IReadEventRelationsResult> {
|
||||
const client = MatrixClientPeg.get();
|
||||
const dir = direction as Direction;
|
||||
roomId = roomId ?? RoomViewStore.instance.getRoomId() ?? undefined;
|
||||
roomId = roomId ?? SdkContextClass.instance.roomViewStore.getRoomId() ?? undefined;
|
||||
|
||||
if (typeof roomId !== "string") {
|
||||
throw new Error('Error while reading the current room');
|
||||
|
|
|
@ -20,7 +20,6 @@ import defaultDispatcher from "../dispatcher/dispatcher";
|
|||
import { ActionPayload } from "../dispatcher/payloads";
|
||||
import Modal from "../Modal";
|
||||
import RoomSettingsDialog from "../components/views/dialogs/RoomSettingsDialog";
|
||||
import { RoomViewStore } from "../stores/RoomViewStore";
|
||||
import ForwardDialog from "../components/views/dialogs/ForwardDialog";
|
||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
||||
import { Action } from "../dispatcher/actions";
|
||||
|
@ -32,6 +31,7 @@ import AddExistingToSpaceDialog from "../components/views/dialogs/AddExistingToS
|
|||
import { ButtonEvent } from "../components/views/elements/AccessibleButton";
|
||||
import PosthogTrackers from "../PosthogTrackers";
|
||||
import { showAddExistingSubspace, showCreateNewRoom } from "./space";
|
||||
import { SdkContextClass } from "../contexts/SDKContext";
|
||||
|
||||
/**
|
||||
* Auxiliary class to listen for dialog opening over the dispatcher and
|
||||
|
@ -58,7 +58,7 @@ export class DialogOpener {
|
|||
switch (payload.action) {
|
||||
case 'open_room_settings':
|
||||
Modal.createDialog(RoomSettingsDialog, {
|
||||
roomId: payload.room_id || RoomViewStore.instance.getRoomId(),
|
||||
roomId: payload.room_id || SdkContextClass.instance.roomViewStore.getRoomId(),
|
||||
initialTabId: payload.initial_tab_id,
|
||||
}, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true);
|
||||
break;
|
||||
|
@ -108,7 +108,7 @@ export class DialogOpener {
|
|||
onAddSubspaceClick: () => showAddExistingSubspace(space),
|
||||
space,
|
||||
onFinished: (added: boolean) => {
|
||||
if (added && RoomViewStore.instance.getRoomId() === space.roomId) {
|
||||
if (added && SdkContextClass.instance.roomViewStore.getRoomId() === space.roomId) {
|
||||
defaultDispatcher.fire(Action.UpdateSpaceHierarchy);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -27,7 +27,6 @@ import { _t } from "../languageHandler";
|
|||
import ErrorDialog from "../components/views/dialogs/ErrorDialog";
|
||||
import { isMetaSpace } from "../stores/spaces";
|
||||
import SpaceStore from "../stores/spaces/SpaceStore";
|
||||
import { RoomViewStore } from "../stores/RoomViewStore";
|
||||
import dis from "../dispatcher/dispatcher";
|
||||
import { ViewRoomPayload } from "../dispatcher/payloads/ViewRoomPayload";
|
||||
import { Action } from "../dispatcher/actions";
|
||||
|
@ -35,6 +34,7 @@ import { ViewHomePagePayload } from "../dispatcher/payloads/ViewHomePagePayload"
|
|||
import LeaveSpaceDialog from "../components/views/dialogs/LeaveSpaceDialog";
|
||||
import { AfterLeaveRoomPayload } from "../dispatcher/payloads/AfterLeaveRoomPayload";
|
||||
import { bulkSpaceBehaviour } from "./space";
|
||||
import { SdkContextClass } from "../contexts/SDKContext";
|
||||
|
||||
export async function leaveRoomBehaviour(roomId: string, retry = true, spinner = true) {
|
||||
let spinnerModal: IHandle<any>;
|
||||
|
@ -130,7 +130,7 @@ export async function leaveRoomBehaviour(roomId: string, retry = true, spinner =
|
|||
|
||||
if (!isMetaSpace(SpaceStore.instance.activeSpace) &&
|
||||
SpaceStore.instance.activeSpace !== roomId &&
|
||||
RoomViewStore.instance.getRoomId() === roomId
|
||||
SdkContextClass.instance.roomViewStore.getRoomId() === roomId
|
||||
) {
|
||||
dis.dispatch<ViewRoomPayload>({
|
||||
action: Action.ViewRoom,
|
||||
|
|
|
@ -30,7 +30,6 @@ import { showRoomInviteDialog } from "../RoomInvite";
|
|||
import CreateSubspaceDialog from "../components/views/dialogs/CreateSubspaceDialog";
|
||||
import AddExistingSubspaceDialog from "../components/views/dialogs/AddExistingSubspaceDialog";
|
||||
import defaultDispatcher from "../dispatcher/dispatcher";
|
||||
import { RoomViewStore } from "../stores/RoomViewStore";
|
||||
import { Action } from "../dispatcher/actions";
|
||||
import Spinner from "../components/views/elements/Spinner";
|
||||
import { shouldShowComponent } from "../customisations/helpers/UIComponents";
|
||||
|
@ -38,6 +37,7 @@ import { UIComponent } from "../settings/UIFeature";
|
|||
import { OpenSpacePreferencesPayload, SpacePreferenceTab } from "../dispatcher/payloads/OpenSpacePreferencesPayload";
|
||||
import { OpenSpaceSettingsPayload } from "../dispatcher/payloads/OpenSpaceSettingsPayload";
|
||||
import { OpenAddExistingToSpaceDialogPayload } from "../dispatcher/payloads/OpenAddExistingToSpaceDialogPayload";
|
||||
import { SdkContextClass } from "../contexts/SDKContext";
|
||||
|
||||
export const shouldShowSpaceSettings = (space: Room) => {
|
||||
const userId = space.client.getUserId();
|
||||
|
@ -113,7 +113,7 @@ export const showAddExistingSubspace = (space: Room): void => {
|
|||
space,
|
||||
onCreateSubspaceClick: () => showCreateNewSubspace(space),
|
||||
onFinished: (added: boolean) => {
|
||||
if (added && RoomViewStore.instance.getRoomId() === space.roomId) {
|
||||
if (added && SdkContextClass.instance.roomViewStore.getRoomId() === space.roomId) {
|
||||
defaultDispatcher.fire(Action.UpdateSpaceHierarchy);
|
||||
}
|
||||
},
|
||||
|
@ -125,7 +125,7 @@ export const showCreateNewSubspace = (space: Room): void => {
|
|||
space,
|
||||
onAddExistingSpaceClick: () => showAddExistingSubspace(space),
|
||||
onFinished: (added: boolean) => {
|
||||
if (added && RoomViewStore.instance.getRoomId() === space.roomId) {
|
||||
if (added && SdkContextClass.instance.roomViewStore.getRoomId() === space.roomId) {
|
||||
defaultDispatcher.fire(Action.UpdateSpaceHierarchy);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -21,9 +21,9 @@ import { Command, Commands, getCommand } from '../src/SlashCommands';
|
|||
import { createTestClient } from './test-utils';
|
||||
import { MatrixClientPeg } from '../src/MatrixClientPeg';
|
||||
import { LocalRoom, LOCAL_ROOM_ID_PREFIX } from '../src/models/LocalRoom';
|
||||
import { RoomViewStore } from '../src/stores/RoomViewStore';
|
||||
import SettingsStore from '../src/settings/SettingsStore';
|
||||
import LegacyCallHandler from '../src/LegacyCallHandler';
|
||||
import { SdkContextClass } from '../src/contexts/SDKContext';
|
||||
|
||||
describe('SlashCommands', () => {
|
||||
let client: MatrixClient;
|
||||
|
@ -38,14 +38,14 @@ describe('SlashCommands', () => {
|
|||
};
|
||||
|
||||
const setCurrentRoom = (): void => {
|
||||
mocked(RoomViewStore.instance.getRoomId).mockReturnValue(roomId);
|
||||
mocked(SdkContextClass.instance.roomViewStore.getRoomId).mockReturnValue(roomId);
|
||||
mocked(client.getRoom).mockImplementation((rId: string): Room => {
|
||||
if (rId === roomId) return room;
|
||||
});
|
||||
};
|
||||
|
||||
const setCurrentLocalRoon = (): void => {
|
||||
mocked(RoomViewStore.instance.getRoomId).mockReturnValue(localRoomId);
|
||||
mocked(SdkContextClass.instance.roomViewStore.getRoomId).mockReturnValue(localRoomId);
|
||||
mocked(client.getRoom).mockImplementation((rId: string): Room => {
|
||||
if (rId === localRoomId) return localRoom;
|
||||
});
|
||||
|
@ -60,7 +60,7 @@ describe('SlashCommands', () => {
|
|||
room = new Room(roomId, client, client.getUserId());
|
||||
localRoom = new LocalRoom(localRoomId, client, client.getUserId());
|
||||
|
||||
jest.spyOn(RoomViewStore.instance, "getRoomId");
|
||||
jest.spyOn(SdkContextClass.instance.roomViewStore, "getRoomId");
|
||||
});
|
||||
|
||||
describe('/topic', () => {
|
||||
|
|
44
test/TestStores.ts
Normal file
44
test/TestStores.ts
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
Copyright 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.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { SdkContextClass } from "../src/contexts/SDKContext";
|
||||
import { PosthogAnalytics } from "../src/PosthogAnalytics";
|
||||
import { SlidingSyncManager } from "../src/SlidingSyncManager";
|
||||
import { RoomNotificationStateStore } from "../src/stores/notifications/RoomNotificationStateStore";
|
||||
import RightPanelStore from "../src/stores/right-panel/RightPanelStore";
|
||||
import { RoomViewStore } from "../src/stores/RoomViewStore";
|
||||
import { SpaceStoreClass } from "../src/stores/spaces/SpaceStore";
|
||||
import { WidgetLayoutStore } from "../src/stores/widgets/WidgetLayoutStore";
|
||||
import WidgetStore from "../src/stores/WidgetStore";
|
||||
|
||||
/**
|
||||
* A class which provides the same API as Stores but adds additional unsafe setters which can
|
||||
* replace individual stores. This is useful for tests which need to mock out stores.
|
||||
*/
|
||||
export class TestStores extends SdkContextClass {
|
||||
public _RightPanelStore?: RightPanelStore;
|
||||
public _RoomNotificationStateStore?: RoomNotificationStateStore;
|
||||
public _RoomViewStore?: RoomViewStore;
|
||||
public _WidgetLayoutStore?: WidgetLayoutStore;
|
||||
public _WidgetStore?: WidgetStore;
|
||||
public _PosthogAnalytics?: PosthogAnalytics;
|
||||
public _SlidingSyncManager?: SlidingSyncManager;
|
||||
public _SpaceStore?: SpaceStoreClass;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
}
|
|
@ -32,17 +32,16 @@ import { defaultDispatcher } from "../../../src/dispatcher/dispatcher";
|
|||
import { ViewRoomPayload } from "../../../src/dispatcher/payloads/ViewRoomPayload";
|
||||
import { RoomView as _RoomView } from "../../../src/components/structures/RoomView";
|
||||
import ResizeNotifier from "../../../src/utils/ResizeNotifier";
|
||||
import { RoomViewStore } from "../../../src/stores/RoomViewStore";
|
||||
import SettingsStore from "../../../src/settings/SettingsStore";
|
||||
import { SettingLevel } from "../../../src/settings/SettingLevel";
|
||||
import DMRoomMap from "../../../src/utils/DMRoomMap";
|
||||
import { NotificationState } from "../../../src/stores/notifications/NotificationState";
|
||||
import RightPanelStore from "../../../src/stores/right-panel/RightPanelStore";
|
||||
import { RightPanelPhases } from "../../../src/stores/right-panel/RightPanelStorePhases";
|
||||
import { LocalRoom, LocalRoomState } from "../../../src/models/LocalRoom";
|
||||
import { DirectoryMember } from "../../../src/utils/direct-messages";
|
||||
import { createDmLocalRoom } from "../../../src/utils/dm/createDmLocalRoom";
|
||||
import { UPDATE_EVENT } from "../../../src/stores/AsyncStore";
|
||||
import { SdkContextClass, SDKContext } from "../../../src/contexts/SDKContext";
|
||||
|
||||
const RoomView = wrapInMatrixClientContext(_RoomView);
|
||||
|
||||
|
@ -50,6 +49,7 @@ describe("RoomView", () => {
|
|||
let cli: MockedObject<MatrixClient>;
|
||||
let room: Room;
|
||||
let roomCount = 0;
|
||||
let stores: SdkContextClass;
|
||||
|
||||
beforeEach(async () => {
|
||||
mockPlatformPeg({ reload: () => {} });
|
||||
|
@ -64,7 +64,9 @@ describe("RoomView", () => {
|
|||
room.on(RoomEvent.TimelineReset, (...args) => cli.emit(RoomEvent.TimelineReset, ...args));
|
||||
|
||||
DMRoomMap.makeShared();
|
||||
RightPanelStore.instance.useUnitTestClient(cli);
|
||||
stores = new SdkContextClass();
|
||||
stores.client = cli;
|
||||
stores.rightPanelStore.useUnitTestClient(cli);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
|
@ -73,15 +75,15 @@ describe("RoomView", () => {
|
|||
});
|
||||
|
||||
const mountRoomView = async (): Promise<ReactWrapper> => {
|
||||
if (RoomViewStore.instance.getRoomId() !== room.roomId) {
|
||||
if (stores.roomViewStore.getRoomId() !== room.roomId) {
|
||||
const switchedRoom = new Promise<void>(resolve => {
|
||||
const subFn = () => {
|
||||
if (RoomViewStore.instance.getRoomId()) {
|
||||
RoomViewStore.instance.off(UPDATE_EVENT, subFn);
|
||||
if (stores.roomViewStore.getRoomId()) {
|
||||
stores.roomViewStore.off(UPDATE_EVENT, subFn);
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
RoomViewStore.instance.on(UPDATE_EVENT, subFn);
|
||||
stores.roomViewStore.on(UPDATE_EVENT, subFn);
|
||||
});
|
||||
|
||||
defaultDispatcher.dispatch<ViewRoomPayload>({
|
||||
|
@ -94,15 +96,16 @@ describe("RoomView", () => {
|
|||
}
|
||||
|
||||
const roomView = mount(
|
||||
<RoomView
|
||||
mxClient={cli}
|
||||
threepidInvite={null}
|
||||
oobData={null}
|
||||
resizeNotifier={new ResizeNotifier()}
|
||||
justCreatedOpts={null}
|
||||
forceTimeline={false}
|
||||
onRegistered={null}
|
||||
/>,
|
||||
<SDKContext.Provider value={stores}>
|
||||
<RoomView
|
||||
threepidInvite={null}
|
||||
oobData={null}
|
||||
resizeNotifier={new ResizeNotifier()}
|
||||
justCreatedOpts={null}
|
||||
forceTimeline={false}
|
||||
onRegistered={null}
|
||||
/>
|
||||
</SDKContext.Provider>,
|
||||
);
|
||||
await act(() => Promise.resolve()); // Allow state to settle
|
||||
return roomView;
|
||||
|
@ -162,14 +165,14 @@ describe("RoomView", () => {
|
|||
it("normally doesn't open the chat panel", async () => {
|
||||
jest.spyOn(NotificationState.prototype, "isUnread", "get").mockReturnValue(false);
|
||||
await mountRoomView();
|
||||
expect(RightPanelStore.instance.isOpen).toEqual(false);
|
||||
expect(stores.rightPanelStore.isOpen).toEqual(false);
|
||||
});
|
||||
|
||||
it("opens the chat panel if there are unread messages", async () => {
|
||||
jest.spyOn(NotificationState.prototype, "isUnread", "get").mockReturnValue(true);
|
||||
await mountRoomView();
|
||||
expect(RightPanelStore.instance.isOpen).toEqual(true);
|
||||
expect(RightPanelStore.instance.currentCard.phase).toEqual(RightPanelPhases.Timeline);
|
||||
expect(stores.rightPanelStore.isOpen).toEqual(true);
|
||||
expect(stores.rightPanelStore.currentCard.phase).toEqual(RightPanelPhases.Timeline);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -42,8 +42,8 @@ import RoomCallBanner from "../../../../src/components/views/beacon/RoomCallBann
|
|||
import { CallStore } from "../../../../src/stores/CallStore";
|
||||
import { WidgetMessagingStore } from "../../../../src/stores/widgets/WidgetMessagingStore";
|
||||
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
||||
import { RoomViewStore } from "../../../../src/stores/RoomViewStore";
|
||||
import { ConnectionState } from "../../../../src/models/Call";
|
||||
import { SdkContextClass } from "../../../../src/contexts/SDKContext";
|
||||
|
||||
describe("<RoomCallBanner />", () => {
|
||||
let client: Mocked<MatrixClient>;
|
||||
|
@ -132,7 +132,8 @@ describe("<RoomCallBanner />", () => {
|
|||
});
|
||||
|
||||
it("doesn't show banner if the call is shown", async () => {
|
||||
jest.spyOn(RoomViewStore.instance, 'isViewingCall').mockReturnValue(true);
|
||||
jest.spyOn(SdkContextClass.instance.roomViewStore, "isViewingCall");
|
||||
mocked(SdkContextClass.instance.roomViewStore.isViewingCall).mockReturnValue(true);
|
||||
await renderBanner();
|
||||
const banner = await screen.queryByText("Video call");
|
||||
expect(banner).toBeFalsy();
|
||||
|
|
|
@ -21,10 +21,21 @@ import { Action } from '../../src/dispatcher/actions';
|
|||
import { getMockClientWithEventEmitter, untilDispatch, untilEmission } from '../test-utils';
|
||||
import SettingsStore from '../../src/settings/SettingsStore';
|
||||
import { SlidingSyncManager } from '../../src/SlidingSyncManager';
|
||||
import { PosthogAnalytics } from '../../src/PosthogAnalytics';
|
||||
import { TimelineRenderingType } from '../../src/contexts/RoomContext';
|
||||
import { MatrixDispatcher } from '../../src/dispatcher/dispatcher';
|
||||
import { UPDATE_EVENT } from '../../src/stores/AsyncStore';
|
||||
import { ActiveRoomChangedPayload } from '../../src/dispatcher/payloads/ActiveRoomChangedPayload';
|
||||
import { SpaceStoreClass } from '../../src/stores/spaces/SpaceStore';
|
||||
import { TestStores } from '../TestStores';
|
||||
|
||||
// mock out the injected classes
|
||||
jest.mock('../../src/PosthogAnalytics');
|
||||
const MockPosthogAnalytics = <jest.Mock<PosthogAnalytics>><unknown>PosthogAnalytics;
|
||||
jest.mock('../../src/SlidingSyncManager');
|
||||
const MockSlidingSyncManager = <jest.Mock<SlidingSyncManager>><unknown>SlidingSyncManager;
|
||||
jest.mock('../../src/stores/spaces/SpaceStore');
|
||||
const MockSpaceStore = <jest.Mock<SpaceStoreClass>><unknown>SpaceStoreClass;
|
||||
|
||||
jest.mock('../../src/utils/DMRoomMap', () => {
|
||||
const mock = {
|
||||
|
@ -51,6 +62,9 @@ describe('RoomViewStore', function() {
|
|||
isGuest: jest.fn(),
|
||||
});
|
||||
const room = new Room(roomId, mockClient, userId);
|
||||
|
||||
let roomViewStore: RoomViewStore;
|
||||
let slidingSyncManager: SlidingSyncManager;
|
||||
let dis: MatrixDispatcher;
|
||||
|
||||
beforeEach(function() {
|
||||
|
@ -60,10 +74,17 @@ describe('RoomViewStore', function() {
|
|||
mockClient.getRoom.mockReturnValue(room);
|
||||
mockClient.isGuest.mockReturnValue(false);
|
||||
|
||||
// Reset the state of the store
|
||||
// Make the RVS to test
|
||||
dis = new MatrixDispatcher();
|
||||
RoomViewStore.instance.reset();
|
||||
RoomViewStore.instance.resetDispatcher(dis);
|
||||
slidingSyncManager = new MockSlidingSyncManager();
|
||||
const stores = new TestStores();
|
||||
stores._SlidingSyncManager = slidingSyncManager;
|
||||
stores._PosthogAnalytics = new MockPosthogAnalytics();
|
||||
stores._SpaceStore = new MockSpaceStore();
|
||||
roomViewStore = new RoomViewStore(
|
||||
dis, stores,
|
||||
);
|
||||
stores._RoomViewStore = roomViewStore;
|
||||
});
|
||||
|
||||
it('can be used to view a room by ID and join', async () => {
|
||||
|
@ -71,14 +92,14 @@ describe('RoomViewStore', function() {
|
|||
dis.dispatch({ action: Action.JoinRoom });
|
||||
await untilDispatch(Action.JoinRoomReady, dis);
|
||||
expect(mockClient.joinRoom).toHaveBeenCalledWith(roomId, { viaServers: [] });
|
||||
expect(RoomViewStore.instance.isJoining()).toBe(true);
|
||||
expect(roomViewStore.isJoining()).toBe(true);
|
||||
});
|
||||
|
||||
it('can auto-join a room', async () => {
|
||||
dis.dispatch({ action: Action.ViewRoom, room_id: roomId, auto_join: true });
|
||||
await untilDispatch(Action.JoinRoomReady, dis);
|
||||
expect(mockClient.joinRoom).toHaveBeenCalledWith(roomId, { viaServers: [] });
|
||||
expect(RoomViewStore.instance.isJoining()).toBe(true);
|
||||
expect(roomViewStore.isJoining()).toBe(true);
|
||||
});
|
||||
|
||||
it('emits ActiveRoomChanged when the viewed room changes', async () => {
|
||||
|
@ -97,7 +118,7 @@ describe('RoomViewStore', function() {
|
|||
it('invokes room activity listeners when the viewed room changes', async () => {
|
||||
const roomId2 = "!roomid:2";
|
||||
const callback = jest.fn();
|
||||
RoomViewStore.instance.addRoomListener(roomId, callback);
|
||||
roomViewStore.addRoomListener(roomId, callback);
|
||||
dis.dispatch({ action: Action.ViewRoom, room_id: roomId });
|
||||
await untilDispatch(Action.ActiveRoomChanged, dis) as ActiveRoomChangedPayload;
|
||||
expect(callback).toHaveBeenCalledWith(true);
|
||||
|
@ -116,14 +137,14 @@ describe('RoomViewStore', function() {
|
|||
}, dis);
|
||||
|
||||
// roomId is set to id of the room alias
|
||||
expect(RoomViewStore.instance.getRoomId()).toBe(roomId);
|
||||
expect(roomViewStore.getRoomId()).toBe(roomId);
|
||||
|
||||
// join the room
|
||||
dis.dispatch({ action: Action.JoinRoom }, true);
|
||||
|
||||
await untilDispatch(Action.JoinRoomReady, dis);
|
||||
|
||||
expect(RoomViewStore.instance.isJoining()).toBeTruthy();
|
||||
expect(roomViewStore.isJoining()).toBeTruthy();
|
||||
expect(mockClient.joinRoom).toHaveBeenCalledWith(alias, { viaServers: [] });
|
||||
});
|
||||
|
||||
|
@ -134,7 +155,7 @@ describe('RoomViewStore', function() {
|
|||
const payload = await untilDispatch(Action.ViewRoomError, dis);
|
||||
expect(payload.room_id).toBeNull();
|
||||
expect(payload.room_alias).toEqual(alias);
|
||||
expect(RoomViewStore.instance.getRoomAlias()).toEqual(alias);
|
||||
expect(roomViewStore.getRoomAlias()).toEqual(alias);
|
||||
});
|
||||
|
||||
it('emits JoinRoomError if joining the room fails', async () => {
|
||||
|
@ -143,8 +164,8 @@ describe('RoomViewStore', function() {
|
|||
dis.dispatch({ action: Action.ViewRoom, room_id: roomId });
|
||||
dis.dispatch({ action: Action.JoinRoom });
|
||||
await untilDispatch(Action.JoinRoomError, dis);
|
||||
expect(RoomViewStore.instance.isJoining()).toBe(false);
|
||||
expect(RoomViewStore.instance.getJoinError()).toEqual(joinErr);
|
||||
expect(roomViewStore.isJoining()).toBe(false);
|
||||
expect(roomViewStore.getJoinError()).toEqual(joinErr);
|
||||
});
|
||||
|
||||
it('remembers the event being replied to when swapping rooms', async () => {
|
||||
|
@ -154,13 +175,13 @@ describe('RoomViewStore', function() {
|
|||
getRoomId: () => roomId,
|
||||
};
|
||||
dis.dispatch({ action: 'reply_to_event', event: replyToEvent, context: TimelineRenderingType.Room });
|
||||
await untilEmission(RoomViewStore.instance, UPDATE_EVENT);
|
||||
expect(RoomViewStore.instance.getQuotingEvent()).toEqual(replyToEvent);
|
||||
await untilEmission(roomViewStore, UPDATE_EVENT);
|
||||
expect(roomViewStore.getQuotingEvent()).toEqual(replyToEvent);
|
||||
// view the same room, should remember the event.
|
||||
// set the highlighed flag to make sure there is a state change so we get an update event
|
||||
dis.dispatch({ action: Action.ViewRoom, room_id: roomId, highlighted: true });
|
||||
await untilEmission(RoomViewStore.instance, UPDATE_EVENT);
|
||||
expect(RoomViewStore.instance.getQuotingEvent()).toEqual(replyToEvent);
|
||||
await untilEmission(roomViewStore, UPDATE_EVENT);
|
||||
expect(roomViewStore.getQuotingEvent()).toEqual(replyToEvent);
|
||||
});
|
||||
|
||||
it('swaps to the replied event room if it is not the current room', async () => {
|
||||
|
@ -172,18 +193,18 @@ describe('RoomViewStore', function() {
|
|||
};
|
||||
dis.dispatch({ action: 'reply_to_event', event: replyToEvent, context: TimelineRenderingType.Room });
|
||||
await untilDispatch(Action.ViewRoom, dis);
|
||||
expect(RoomViewStore.instance.getQuotingEvent()).toEqual(replyToEvent);
|
||||
expect(RoomViewStore.instance.getRoomId()).toEqual(roomId2);
|
||||
expect(roomViewStore.getQuotingEvent()).toEqual(replyToEvent);
|
||||
expect(roomViewStore.getRoomId()).toEqual(roomId2);
|
||||
});
|
||||
|
||||
it('removes the roomId on ViewHomePage', async () => {
|
||||
dis.dispatch({ action: Action.ViewRoom, room_id: roomId });
|
||||
await untilDispatch(Action.ActiveRoomChanged, dis);
|
||||
expect(RoomViewStore.instance.getRoomId()).toEqual(roomId);
|
||||
expect(roomViewStore.getRoomId()).toEqual(roomId);
|
||||
|
||||
dis.dispatch({ action: Action.ViewHomePage });
|
||||
await untilEmission(RoomViewStore.instance, UPDATE_EVENT);
|
||||
expect(RoomViewStore.instance.getRoomId()).toBeNull();
|
||||
await untilEmission(roomViewStore, UPDATE_EVENT);
|
||||
expect(roomViewStore.getRoomId()).toBeNull();
|
||||
});
|
||||
|
||||
describe('Sliding Sync', function() {
|
||||
|
@ -191,23 +212,22 @@ describe('RoomViewStore', function() {
|
|||
jest.spyOn(SettingsStore, 'getValue').mockImplementation((settingName, roomId, value) => {
|
||||
return settingName === "feature_sliding_sync"; // this is enabled, everything else is disabled.
|
||||
});
|
||||
RoomViewStore.instance.reset();
|
||||
});
|
||||
|
||||
it("subscribes to the room", async () => {
|
||||
const setRoomVisible = jest.spyOn(SlidingSyncManager.instance, "setRoomVisible").mockReturnValue(
|
||||
const setRoomVisible = jest.spyOn(slidingSyncManager, "setRoomVisible").mockReturnValue(
|
||||
Promise.resolve(""),
|
||||
);
|
||||
const subscribedRoomId = "!sub1:localhost";
|
||||
dis.dispatch({ action: Action.ViewRoom, room_id: subscribedRoomId });
|
||||
await untilDispatch(Action.ActiveRoomChanged, dis);
|
||||
expect(RoomViewStore.instance.getRoomId()).toBe(subscribedRoomId);
|
||||
expect(roomViewStore.getRoomId()).toBe(subscribedRoomId);
|
||||
expect(setRoomVisible).toHaveBeenCalledWith(subscribedRoomId, true);
|
||||
});
|
||||
|
||||
// Regression test for an in-the-wild bug where rooms would rapidly switch forever in sliding sync mode
|
||||
it("doesn't get stuck in a loop if you view rooms quickly", async () => {
|
||||
const setRoomVisible = jest.spyOn(SlidingSyncManager.instance, "setRoomVisible").mockReturnValue(
|
||||
const setRoomVisible = jest.spyOn(slidingSyncManager, "setRoomVisible").mockReturnValue(
|
||||
Promise.resolve(""),
|
||||
);
|
||||
const subscribedRoomId = "!sub1:localhost";
|
|
@ -20,8 +20,8 @@ import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo";
|
|||
import { Direction, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { Widget, MatrixWidgetType, WidgetKind, WidgetDriver, ITurnServer } from "matrix-widget-api";
|
||||
|
||||
import { SdkContextClass } from "../../../src/contexts/SDKContext";
|
||||
import { MatrixClientPeg } from "../../../src/MatrixClientPeg";
|
||||
import { RoomViewStore } from "../../../src/stores/RoomViewStore";
|
||||
import { StopGapWidgetDriver } from "../../../src/stores/widgets/StopGapWidgetDriver";
|
||||
import { stubClient } from "../../test-utils";
|
||||
|
||||
|
@ -201,7 +201,7 @@ describe("StopGapWidgetDriver", () => {
|
|||
beforeEach(() => { driver = mkDefaultDriver(); });
|
||||
|
||||
it('reads related events from the current room', async () => {
|
||||
jest.spyOn(RoomViewStore.instance, 'getRoomId').mockReturnValue('!this-room-id');
|
||||
jest.spyOn(SdkContextClass.instance.roomViewStore, 'getRoomId').mockReturnValue('!this-room-id');
|
||||
|
||||
client.relations.mockResolvedValue({
|
||||
originalEvent: new MatrixEvent(),
|
||||
|
|
Loading…
Reference in a new issue