Separate out SDKContext (#34053)

* Separate out SDKContext

...from SDKContextClass, as the comments hopefully explain.

Also make the captitalisation consistent.

* Adding the new file usually helps too

* Fix import

* More comment

* Update the various imports of SDKContextClass

* Also fix case of TestSDKContext

* Update the mock
This commit is contained in:
David Baker
2026-07-01 12:49:18 +00:00
committed by GitHub
parent 1c1bda9cab
commit 54d27fd59c
89 changed files with 493 additions and 458 deletions
+3 -3
View File
@@ -56,7 +56,7 @@ import SdkConfig from "./SdkConfig";
import { DialogOpener } from "./utils/DialogOpener";
import { Action } from "./dispatcher/actions";
import { type OverwriteLoginPayload } from "./dispatcher/payloads/OverwriteLoginPayload";
import { SdkContextClass } from "./contexts/SDKContext";
import { SDKContextClass } from "./contexts/SDKContextClass";
import { messageForLoginError } from "./utils/ErrorUtils";
import { completeOidcLogin, type CompleteOidcLoginResponse } from "./utils/oidc/authorize";
import { getOidcErrorMessage } from "./utils/oidc/error";
@@ -1093,7 +1093,7 @@ async function startMatrixClient(
dis.dispatch({ action: Action.WillStartClient }, true);
// reset things first just in case
SdkContextClass.instance.typingStore.reset();
SDKContextClass.instance.typingStore.reset();
ToastStore.sharedInstance().reset();
DialogOpener.instance.prepare(client);
@@ -1231,7 +1231,7 @@ export function stopMatrixClient(unsetClient = true): void {
Notifier.stop();
LegacyCallHandler.instance.stop();
UserActivity.sharedInstance().stop();
SdkContextClass.instance.typingStore.reset();
SDKContextClass.instance.typingStore.reset();
Presence.stop();
ActiveWidgetStore.instance.stop();
IntegrationManagers.sharedInstance().stopWatching();
+2 -2
View File
@@ -43,7 +43,7 @@ import { isPushNotifyDisabled } from "./settings/controllers/NotificationControl
import UserActivity from "./UserActivity";
import { mediaFromMxc } from "./customisations/Media";
import ErrorDialog from "./components/views/dialogs/ErrorDialog";
import { SdkContextClass } from "./contexts/SDKContext";
import { SDKContextClass } from "./contexts/SDKContextClass";
import { localNotificationsAreSilenced, createLocalNotificationSettingsIfNeeded } from "./utils/notifications";
import { getIncomingCallToastKey, getNotificationEventSendTs, IncomingCallToast } from "./toasts/IncomingCallToast";
import ToastStore from "./stores/ToastStore";
@@ -514,7 +514,7 @@ class NotifierClass extends TypedEventEmitter<keyof EmittedEvents, EmittedEvents
if (actions?.notify) {
this.performCustomEventHandling(ev);
const store = SdkContextClass.instance.roomViewStore;
const store = SDKContextClass.instance.roomViewStore;
const isViewingRoom = store.getRoomId() === room.roomId;
const threadId: string | undefined = ev.getId() !== ev.threadRootId ? ev.threadRootId : undefined;
const isViewingThread = store.getThreadId() === threadId;
+2 -2
View File
@@ -294,7 +294,7 @@ 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";
import { SDKContextClass } from "./contexts/SDKContextClass";
enum Action {
CloseScalar = "close_scalar",
@@ -903,7 +903,7 @@ const onMessage = function (event: MessageEvent<any>): void {
}
}
if (roomId !== SdkContextClass.instance.roomViewStore.getRoomId()) {
if (roomId !== SDKContextClass.instance.roomViewStore.getRoomId()) {
sendError(event, _t("scalar|error_room_not_visible", { roomId: roomId }));
return;
}
@@ -118,7 +118,8 @@ import RightPanelStore from "../../stores/right-panel/RightPanelStore";
import { TimelineRenderingType } from "../../contexts/RoomContext";
import { type ValidatedServerConfig } from "../../utils/ValidatedServerConfig";
import { isLocalRoom } from "../../utils/localRoom/isLocalRoom";
import { SDKContext, SdkContextClass } from "../../contexts/SDKContext";
import { SDKContext } from "../../contexts/SDKContext";
import { SDKContextClass } from "../../contexts/SDKContextClass.ts";
import { viewUserDeviceSettings } from "../../actions/handlers/viewUserDeviceSettings";
import GenericToast from "../views/toasts/GenericToast";
import RovingSpotlightDialog from "../views/dialogs/spotlight/SpotlightDialog";
@@ -240,14 +241,14 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
private dispatcherRef?: string;
private themeWatcher?: ThemeWatcher;
private fontWatcher?: FontWatcher;
private readonly stores: SdkContextClass;
private readonly stores: SDKContextClass;
private loadSessionAbortController = new AbortController();
private sessionLoadStarted = false;
public constructor(props: IProps) {
super(props);
this.stores = SdkContextClass.instance;
this.stores = SDKContextClass.instance;
this.stores.constructEagerStores();
this.state = {
@@ -21,7 +21,7 @@ import { WidgetLayoutStore } from "../../stores/widgets/WidgetLayoutStore";
import ActiveWidgetStore, { ActiveWidgetStoreEvent } from "../../stores/ActiveWidgetStore";
import { type ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload";
import { UPDATE_EVENT } from "../../stores/AsyncStore";
import { SdkContextClass } from "../../contexts/SDKContext";
import { SDKContextClass } from "../../contexts/SDKContextClass";
import RoomAvatar from "../views/avatars/RoomAvatar";
import { WidgetPipViewModel, type Props as WidgetPipViewModelProps } from "../../viewmodels/room/WidgetPipViewModel";
@@ -99,7 +99,7 @@ class PipContainerInner extends React.Component<IProps, IState> {
public constructor(props: IProps) {
super(props);
const roomId = SdkContextClass.instance.roomViewStore.getRoomId();
const roomId = SDKContextClass.instance.roomViewStore.getRoomId();
const [primaryCall, secondaryCalls] = getPrimarySecondaryCallsForPip(roomId);
@@ -116,7 +116,7 @@ class PipContainerInner extends React.Component<IProps, IState> {
public componentDidMount(): void {
LegacyCallHandler.instance.addListener(LegacyCallHandlerEvent.CallChangeRoom, this.updateCalls);
LegacyCallHandler.instance.addListener(LegacyCallHandlerEvent.CallState, this.updateCalls);
SdkContextClass.instance.roomViewStore.addListener(UPDATE_EVENT, this.onRoomViewStoreUpdate);
SDKContextClass.instance.roomViewStore.addListener(UPDATE_EVENT, this.onRoomViewStoreUpdate);
MatrixClientPeg.safeGet().on(CallEvent.RemoteHoldUnhold, this.onCallRemoteHold);
const room = MatrixClientPeg.safeGet().getRoom(this.state.viewedRoomId);
if (room) {
@@ -132,7 +132,7 @@ class PipContainerInner extends React.Component<IProps, IState> {
LegacyCallHandler.instance.removeListener(LegacyCallHandlerEvent.CallState, this.updateCalls);
const cli = MatrixClientPeg.get();
cli?.removeListener(CallEvent.RemoteHoldUnhold, this.onCallRemoteHold);
SdkContextClass.instance.roomViewStore.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);
@@ -145,7 +145,7 @@ class PipContainerInner extends React.Component<IProps, IState> {
private onMove = (): void => this.props.movePersistedElement.current?.();
private onRoomViewStoreUpdate = (): void => {
const newRoomId = SdkContextClass.instance.roomViewStore.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,
@@ -55,7 +55,7 @@ import Modal from "../../../Modal";
import dis from "../../../dispatcher/dispatcher";
import { privateShouldBeEncrypted } from "../../../utils/rooms";
import { type NonEmptyArray } from "../../../@types/common";
import { SdkContextClass } from "../../../contexts/SDKContext";
import { SDKContextClass } from "../../../contexts/SDKContextClass";
import { type UserProfilesStore } from "../../../stores/UserProfilesStore";
import InviteProgressBody from "./InviteProgressBody.tsx";
import MultiInviter, { type CompletionStates as MultiInviterCompletionStates } from "../../../utils/MultiInviter.ts";
@@ -204,7 +204,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
throw new Error("When using InviteKind.CallTransfer a call is required for an InviteDialog");
}
this.profilesStore = SdkContextClass.instance.userProfilesStore;
this.profilesStore = SDKContextClass.instance.userProfilesStore;
const cli = MatrixClientPeg.safeGet();
const excludedIds = new Set([cli.getSafeUserId()]);
@@ -42,14 +42,15 @@ import { type NonEmptyArray } from "../../../@types/common";
import { PollHistoryTab } from "../settings/tabs/room/PollHistoryTab";
import ErrorBoundary from "../elements/ErrorBoundary";
import { PeopleRoomSettingsTab } from "../settings/tabs/room/PeopleRoomSettingsTab";
import { SDKContext, type SdkContextClass } from "../../../contexts/SDKContext";
import { SDKContext } from "../../../contexts/SDKContext";
import { type SDKContextClass } from "../../../contexts/SDKContextClass";
import { RoomSettingsTab } from "./RoomSettingsDialog-tab.ts";
interface IProps {
roomId: string;
onFinished: (success?: boolean) => void;
initialTabId?: RoomSettingsTab;
sdkContext: SdkContextClass;
sdkContext: SDKContextClass;
}
interface IState {
@@ -44,7 +44,8 @@ import KeyboardUserSettingsTab from "../settings/tabs/user/KeyboardUserSettingsT
import SessionManagerTab from "../settings/tabs/user/SessionManagerTab";
import { UserTab } from "./UserTab";
import { type NonEmptyArray } from "../../../@types/common";
import { SDKContext, type SdkContextClass } from "../../../contexts/SDKContext";
import { SDKContext } from "../../../contexts/SDKContext";
import { type SDKContextClass } from "../../../contexts/SDKContextClass";
import { useSettingValue } from "../../../hooks/useSettings";
import { NoChange, useEventEmitterAsyncState, type AsyncStateCallbackResult } from "../../../hooks/useEventEmitter";
import { EncryptionUserSettingsTab, type State } from "../settings/tabs/user/EncryptionUserSettingsTab";
@@ -57,7 +58,7 @@ interface IProps {
* If undefined, the default state is used ("loading").
*/
initialEncryptionState?: State;
sdkContext: SdkContextClass;
sdkContext: SDKContextClass;
onFinished(this: void): void;
}
@@ -16,7 +16,7 @@ import { _t } from "../../../languageHandler";
import { OIDCState } from "../../../stores/widgets/WidgetPermissionStore";
import BaseDialog from "./BaseDialog";
import DialogButtons from "../elements/DialogButtons";
import { SdkContextClass } from "../../../contexts/SDKContext";
import { SDKContextClass } from "../../../contexts/SDKContextClass";
interface IProps {
widget: Widget;
@@ -50,7 +50,7 @@ export default class WidgetOpenIDPermissionsDialog extends React.PureComponent<I
if (this.state.rememberSelection) {
logger.log(`Remembering ${this.props.widget.id} as allowed=${allowed} for OpenID`);
SdkContextClass.instance.widgetPermissionStore.setOIDCState(
SDKContextClass.instance.widgetPermissionStore.setOIDCState(
this.props.widget,
this.props.widgetKind,
this.props.inRoomId,
@@ -71,7 +71,7 @@ import { BreadcrumbsStore } from "../../../../stores/BreadcrumbsStore";
import { type RoomNotificationState } from "../../../../stores/notifications/RoomNotificationState";
import { RoomNotificationStateStore } from "../../../../stores/notifications/RoomNotificationStateStore";
import { compareRoomsByRecency } from "../../../../utils/room/sortRoomsByRecency";
import { SdkContextClass } from "../../../../contexts/SDKContext";
import { SDKContextClass } from "../../../../contexts/SDKContextClass";
import { getMetaSpaceName, MetaSpace } from "../../../../stores/spaces";
import SpaceStore from "../../../../stores/spaces/SpaceStore";
import { DirectoryMember, type Member, startDmOnFirstMessage } from "../../../../utils/direct-messages";
@@ -1119,7 +1119,7 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = n
</h4>
<div>
{BreadcrumbsStore.instance.rooms
.filter((r) => r.roomId !== SdkContextClass.instance.roomViewStore.getRoomId())
.filter((r) => r.roomId !== SDKContextClass.instance.roomViewStore.getRoomId())
.map((room) => (
<TooltipOption
id={`mx_SpotlightDialog_button_recentlyViewed_${room.roomId}`}
@@ -56,7 +56,7 @@ import { type 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";
import { SDKContextClass } from "../../../contexts/SDKContextClass";
import { ModuleRunner } from "../../../modules/ModuleRunner";
import { ModuleApi } from "../../../modules/Api";
import { toWidgetDescriptor } from "../../../modules/WidgetLifecycleApi";
@@ -257,7 +257,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 && SdkContextClass.instance.roomViewStore.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)) {
@@ -41,7 +41,7 @@ import { type ICompletion } from "../../../autocomplete/Autocompleter";
import { getKeyBindingsManager } from "../../../KeyBindingsManager";
import { ALTERNATE_KEY_NAME, KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
import { _t } from "../../../languageHandler";
import { SdkContextClass } from "../../../contexts/SDKContext";
import { SDKContextClass } from "../../../contexts/SDKContextClass";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import { Landmark, LandmarkNavigation } from "../../../accessibility/LandmarkNavigation";
@@ -251,7 +251,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
isTyping = false;
}
}
SdkContextClass.instance.typingStore.setSelfTyping(
SDKContextClass.instance.typingStore.setSelfTyping(
this.props.room.roomId,
this.props.threadId ?? null,
isTyping,
@@ -69,7 +69,7 @@ import IconizedContextMenu, {
} from "../context_menus/IconizedContextMenu.tsx";
import ExtraTile from "./ExtraTile.tsx";
import RoomSublist, { type IAuxButtonProps } from "./RoomSublist.tsx";
import { SdkContextClass } from "../../../contexts/SDKContext.ts";
import { SDKContextClass } from "../../../contexts/SDKContextClass";
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts.ts";
import { getKeyBindingsManager } from "../../../KeyBindingsManager.ts";
import AccessibleButton from "../elements/AccessibleButton.tsx";
@@ -462,7 +462,7 @@ export default class LegacyRoomList extends React.PureComponent<IProps, IState>
public componentDidMount(): void {
this.dispatcherRef = defaultDispatcher.register(this.onAction);
SdkContextClass.instance.roomViewStore.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);
LegacyCallHandler.instance.on(LegacyCallHandlerEvent.ProtocolSupport, this.updateProtocolSupport);
@@ -473,7 +473,7 @@ export default class LegacyRoomList extends React.PureComponent<IProps, IState>
SpaceStore.instance.off(UPDATE_SUGGESTED_ROOMS, this.updateSuggestedRooms);
RoomListStore.instance.off(LISTS_UPDATE_EVENT, this.updateLists);
defaultDispatcher.unregister(this.dispatcherRef);
SdkContextClass.instance.roomViewStore.off(UPDATE_EVENT, this.onRoomViewStoreUpdate);
SDKContextClass.instance.roomViewStore.off(UPDATE_EVENT, this.onRoomViewStoreUpdate);
LegacyCallHandler.instance.off(LegacyCallHandlerEvent.ProtocolSupport, this.updateProtocolSupport);
}
@@ -483,14 +483,14 @@ export default class LegacyRoomList extends React.PureComponent<IProps, IState>
private onRoomViewStoreUpdate = (): void => {
this.setState({
currentRoomId: SdkContextClass.instance.roomViewStore.getRoomId() ?? undefined,
currentRoomId: SDKContextClass.instance.roomViewStore.getRoomId() ?? undefined,
});
};
private onAction = (payload: ActionPayload): void => {
if (payload.action === Action.ViewRoomDelta) {
const viewRoomDeltaPayload = payload as ViewRoomDeltaPayload;
const currentRoomId = SdkContextClass.instance.roomViewStore.getRoomId();
const currentRoomId = SDKContextClass.instance.roomViewStore.getRoomId();
if (!currentRoomId) return;
const room = this.getRoomDelta(currentRoomId, viewRoomDeltaPayload.delta, viewRoomDeltaPayload.unread);
if (room) {
@@ -39,7 +39,7 @@ import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
import { getKeyBindingsManager } from "../../../KeyBindingsManager";
import { RoomGeneralContextMenu } from "../context_menus/RoomGeneralContextMenu";
import { CallStore, CallStoreEvent } from "../../../stores/CallStore";
import { SdkContextClass } from "../../../contexts/SDKContext";
import { SDKContextClass } from "../../../contexts/SDKContextClass";
import { RoomTileSubtitle } from "./RoomTileSubtitle";
import { shouldShowComponent } from "../../../customisations/helpers/UIComponents";
import { UIComponent } from "../../../settings/UIFeature";
@@ -84,7 +84,7 @@ class RoomTile extends React.PureComponent<Props, State> {
super(props);
this.state = {
selected: SdkContextClass.instance.roomViewStore.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),
@@ -150,7 +150,7 @@ class RoomTile extends React.PureComponent<Props, State> {
this.scrollIntoView();
}
SdkContextClass.instance.roomViewStore.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),
@@ -167,7 +167,7 @@ class RoomTile extends React.PureComponent<Props, State> {
}
public componentWillUnmount(): void {
SdkContextClass.instance.roomViewStore.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,
@@ -30,7 +30,7 @@ import { UserTab } from "../dialogs/UserTab";
import QuickThemeSwitcher from "./QuickThemeSwitcher";
import Modal from "../../../Modal";
import DevtoolsDialog from "../dialogs/DevtoolsDialog";
import { SdkContextClass } from "../../../contexts/SDKContext";
import { SDKContextClass } from "../../../contexts/SDKContextClass";
const QuickSettingsButton: React.FC<{
isPanelCollapsed: boolean;
@@ -40,7 +40,7 @@ const QuickSettingsButton: React.FC<{
const { [MetaSpace.Favourites]: favouritesEnabled, [MetaSpace.People]: peopleEnabled } =
useSettingValue("Spaces.enabledMetaSpaces");
const currentRoomId = SdkContextClass.instance.roomViewStore.getRoomId();
const currentRoomId = SDKContextClass.instance.roomViewStore.getRoomId();
const developerModeEnabled = useSettingValue("developerMode");
// "Favourites" and "People" meta spaces are not available in the new room list
const newRoomListEnabled = useSettingValue("feature_new_room_list");
@@ -13,7 +13,7 @@ import { type Call, CallEvent } from "../../../models/Call";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import AppTile from "../elements/AppTile";
import { CallStore } from "../../../stores/CallStore";
import { SdkContextClass } from "../../../contexts/SDKContext";
import { SDKContextClass } from "../../../contexts/SDKContextClass";
import { useTypedEventEmitter } from "../../../hooks/useEventEmitter";
import { useCall } from "../../../hooks/useCall";
@@ -38,7 +38,7 @@ const JoinCallView: FC<JoinCallViewProps> = ({ room, resizing, call, role, onClo
// The stickyPromise has to resolve before the widget actually becomes sticky.
// We only let the widget become sticky after disconnecting all other active calls.
const calls = [...CallStore.instance.connectedCalls].filter(
(call) => SdkContextClass.instance.roomViewStore.getRoomId() !== call.roomId,
(call) => SDKContextClass.instance.roomViewStore.getRoomId() !== call.roomId,
);
await Promise.all(calls.map(async (call) => await call.disconnect()));
}, []);
+5 -185
View File
@@ -7,194 +7,14 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type 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 { MemberListStore } from "../stores/MemberListStore";
import { RoomNotificationStateStore } from "../stores/notifications/RoomNotificationStateStore";
import RightPanelStore from "../stores/right-panel/RightPanelStore";
import { RoomViewStore } from "../stores/RoomViewStore";
import SpaceStore, { type SpaceStoreClass } from "../stores/spaces/SpaceStore";
import TypingStore from "../stores/TypingStore";
import { UserProfilesStore } from "../stores/UserProfilesStore";
import { WidgetLayoutStore } from "../stores/widgets/WidgetLayoutStore";
import { WidgetPermissionStore } from "../stores/widgets/WidgetPermissionStore";
import { OidcClientStore } from "../stores/oidc/OidcClientStore";
import WidgetStore from "../stores/WidgetStore";
import ResizeNotifier from "../utils/ResizeNotifier";
import { MultiRoomViewStore } from "../stores/MultiRoomViewStore";
import { type SDKContextClass } from "./SDKContextClass";
// This context is available to components under MatrixChat,
// the context must not be used by components outside a SdkContextClass tree.
// the context must not be used by components outside a SDKContextClass tree.
// This assertion allows us to make the type not nullable.
export const SDKContext = createContext<SdkContextClass>(null as any);
// This file is deliberately kept separate from the actual instantiation of the
// stores to keep just a type import to the SDKContextClass itself.
export const SDKContext = createContext<SDKContextClass>(null as any);
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 _WidgetPermissionStore?: WidgetPermissionStore;
protected _MemberListStore?: MemberListStore;
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;
protected _TypingStore?: TypingStore;
protected _UserProfilesStore?: UserProfilesStore;
protected _OidcClientStore?: OidcClientStore;
protected _ResizeNotifier?: ResizeNotifier;
protected _MultiRoomViewStore?: MultiRoomViewStore;
/**
* Automatically construct stores which need to be created eagerly so they can register with
* the dispatcher.
*/
public constructEagerStores(): void {
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 widgetPermissionStore(): WidgetPermissionStore {
if (!this._WidgetPermissionStore) {
this._WidgetPermissionStore = new WidgetPermissionStore(this);
}
return this._WidgetPermissionStore;
}
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 memberListStore(): MemberListStore {
if (!this._MemberListStore) {
this._MemberListStore = new MemberListStore(this);
}
return this._MemberListStore;
}
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;
}
public get typingStore(): TypingStore {
if (!this._TypingStore) {
this._TypingStore = new TypingStore(this);
window.mxTypingStore = this._TypingStore;
}
return this._TypingStore;
}
public get userProfilesStore(): UserProfilesStore {
if (!this.client) {
throw new Error("Unable to create UserProfilesStore without a client");
}
if (!this._UserProfilesStore) {
this._UserProfilesStore = new UserProfilesStore(this.client);
}
return this._UserProfilesStore;
}
public get oidcClientStore(): OidcClientStore {
if (!this.client) {
throw new Error("Unable to create OidcClientStore without a client");
}
if (!this._OidcClientStore) {
this._OidcClientStore = new OidcClientStore(this.client);
}
return this._OidcClientStore;
}
// This is getting increasingly tenuous to have here but we still have class components so it's
// awkward to consume multiple contexts in them. This should be replaced with ResizeObservers
// anyway really.
public get resizeNotifier(): ResizeNotifier {
if (!this._ResizeNotifier) {
this._ResizeNotifier = new ResizeNotifier();
}
return this._ResizeNotifier;
}
public get multiRoomViewStore(): MultiRoomViewStore {
if (!this._MultiRoomViewStore) {
this._MultiRoomViewStore = new MultiRoomViewStore(defaultDispatcher, this);
}
return this._MultiRoomViewStore;
}
public onLoggedOut(): void {
this._UserProfilesStore = undefined;
this._OidcClientStore = undefined;
}
}
+197
View File
@@ -0,0 +1,197 @@
/*
Copyright 2026 Element Creations Ltd.
Copyright 2024 New Vector Ltd.
Copyright 2022 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
import defaultDispatcher from "../dispatcher/dispatcher";
import LegacyCallHandler from "../LegacyCallHandler";
import { PosthogAnalytics } from "../PosthogAnalytics";
import { SlidingSyncManager } from "../SlidingSyncManager";
import { MemberListStore } from "../stores/MemberListStore";
import { RoomNotificationStateStore } from "../stores/notifications/RoomNotificationStateStore";
import RightPanelStore from "../stores/right-panel/RightPanelStore";
import { RoomViewStore } from "../stores/RoomViewStore";
import SpaceStore, { type SpaceStoreClass } from "../stores/spaces/SpaceStore";
import TypingStore from "../stores/TypingStore";
import { UserProfilesStore } from "../stores/UserProfilesStore";
import { WidgetLayoutStore } from "../stores/widgets/WidgetLayoutStore";
import { WidgetPermissionStore } from "../stores/widgets/WidgetPermissionStore";
import { OidcClientStore } from "../stores/oidc/OidcClientStore";
import WidgetStore from "../stores/WidgetStore";
import ResizeNotifier from "../utils/ResizeNotifier";
import { MultiRoomViewStore } from "../stores/MultiRoomViewStore";
/**
* A class which (mostly) lazily initialises stores as and when they are requested, ensuring they remain
* as singletons scoped to this object.
*
* Since this does the actual construction of all stores, it is *very* heavy on imports and lives right near
* the top of the import tree. If anything other than code to set up the app (or tests) are importing this file,
* it's doing it wrong and should be accessing whatever it needs via the react context.
*/
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 _WidgetPermissionStore?: WidgetPermissionStore;
protected _MemberListStore?: MemberListStore;
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;
protected _TypingStore?: TypingStore;
protected _UserProfilesStore?: UserProfilesStore;
protected _OidcClientStore?: OidcClientStore;
protected _ResizeNotifier?: ResizeNotifier;
protected _MultiRoomViewStore?: MultiRoomViewStore;
/**
* Automatically construct stores which need to be created eagerly so they can register with
* the dispatcher.
*/
public constructEagerStores(): void {
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 widgetPermissionStore(): WidgetPermissionStore {
if (!this._WidgetPermissionStore) {
this._WidgetPermissionStore = new WidgetPermissionStore(this);
}
return this._WidgetPermissionStore;
}
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 memberListStore(): MemberListStore {
if (!this._MemberListStore) {
this._MemberListStore = new MemberListStore(this);
}
return this._MemberListStore;
}
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;
}
public get typingStore(): TypingStore {
if (!this._TypingStore) {
this._TypingStore = new TypingStore(this);
window.mxTypingStore = this._TypingStore;
}
return this._TypingStore;
}
public get userProfilesStore(): UserProfilesStore {
if (!this.client) {
throw new Error("Unable to create UserProfilesStore without a client");
}
if (!this._UserProfilesStore) {
this._UserProfilesStore = new UserProfilesStore(this.client);
}
return this._UserProfilesStore;
}
public get oidcClientStore(): OidcClientStore {
if (!this.client) {
throw new Error("Unable to create OidcClientStore without a client");
}
if (!this._OidcClientStore) {
this._OidcClientStore = new OidcClientStore(this.client);
}
return this._OidcClientStore;
}
// This is getting increasingly tenuous to have here but we still have class components so it's
// awkward to consume multiple contexts in them. This should be replaced with ResizeObservers
// anyway really.
public get resizeNotifier(): ResizeNotifier {
if (!this._ResizeNotifier) {
this._ResizeNotifier = new ResizeNotifier();
}
return this._ResizeNotifier;
}
public get multiRoomViewStore(): MultiRoomViewStore {
if (!this._MultiRoomViewStore) {
this._MultiRoomViewStore = new MultiRoomViewStore(defaultDispatcher, this);
}
return this._MultiRoomViewStore;
}
public onLoggedOut(): void {
this._UserProfilesStore = undefined;
this._OidcClientStore = undefined;
}
}
+3 -3
View File
@@ -38,7 +38,7 @@ import { type InteractionName } from "../../PosthogTrackers";
import { ElementCallMemberEventType } from "../../call-types";
import { LocalRoom, LocalRoomState } from "../../models/LocalRoom";
import { useScopedRoomContext } from "../../contexts/ScopedRoomContext";
import { SdkContextClass } from "../../contexts/SDKContext";
import { SDKContextClass } from "../../contexts/SDKContextClass";
const logger = rootLogger.getChild("useRoomCall");
@@ -132,9 +132,9 @@ export const useRoomCall = (
}, [useElementCallExclusively, serverIsConfiguredForElementCall]);
const hasLegacyCall = useEventEmitterState(
SdkContextClass.instance.legacyCallHandler,
SDKContextClass.instance.legacyCallHandler,
LegacyCallHandlerEvent.CallsChanged,
() => SdkContextClass.instance.legacyCallHandler.getCallForRoom(room.roomId) !== null,
() => SDKContextClass.instance.legacyCallHandler.getCallForRoom(room.roomId) !== null,
);
// settings
const widgets = useWidgets(room);
+3 -2
View File
@@ -10,7 +10,8 @@ import { type IMatrixProfile, type MatrixEvent, type Room, RoomMember } from "ma
import { useContext, useEffect, useState } from "react";
import { PillType } from "../components/views/elements/PillType";
import { SDKContext, type SdkContextClass } from "../contexts/SDKContext";
import { SDKContext } from "../contexts/SDKContext";
import { type SDKContextClass } from "../contexts/SDKContextClass";
import { type PermalinkParts } from "../utils/permalinks/PermalinkConstructor";
const createMemberFromProfile = (userId: string, profile: IMatrixProfile): RoomMember => {
@@ -65,7 +66,7 @@ const determineUserId = (
* If sharing at least one room with the user, then the result will be the profile fetched via API.
* null in all other cases.
*/
const determineMember = (userId: string, targetRoom: Room, context: SdkContextClass): RoomMember | null => {
const determineMember = (userId: string, targetRoom: Room, context: SDKContextClass): RoomMember | null => {
const targetRoomMember = targetRoom.getMember(userId);
if (targetRoomMember) return targetRoomMember;
+2 -2
View File
@@ -11,7 +11,7 @@ Please see LICENSE files in the repository root for full details.
import { EventType, type MatrixClient } from "matrix-js-sdk/src/matrix";
import { SdkContextClass } from "../contexts/SDKContext";
import { SDKContextClass } from "../contexts/SDKContextClass";
import { isLocalRoom } from "../utils/localRoom/isLocalRoom";
import Modal from "../Modal";
import UploadConfirmDialog from "../components/views/dialogs/UploadConfirmDialog";
@@ -70,7 +70,7 @@ export const singleMxcUpload = async (cli: MatrixClient): Promise<string | null>
};
export const isCurrentLocalRoom = (cli: MatrixClient | null): boolean => {
const roomId = SdkContextClass.instance.roomViewStore.getRoomId();
const roomId = SDKContextClass.instance.roomViewStore.getRoomId();
if (!roomId) return false;
const room = cli?.getRoom(roomId);
if (!room) return false;
+2 -2
View File
@@ -10,7 +10,7 @@ import { type Room, type RoomMember } from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types";
import SettingsStore from "../settings/SettingsStore";
import { type SdkContextClass } from "../contexts/SDKContext";
import { type SDKContextClass } from "../contexts/SDKContextClass";
import SdkConfig from "../SdkConfig";
// Regex applied to filter our punctuation in member names before applying sort, to fuzzy it a little
@@ -28,7 +28,7 @@ export class MemberListStore {
private collator?: Intl.Collator;
public constructor(private readonly stores: SdkContextClass) {}
public constructor(private readonly stores: SDKContextClass) {}
/**
* Load the member list. Call this whenever the list may have changed.
+2 -2
View File
@@ -9,7 +9,7 @@ import { logger } from "matrix-js-sdk/src/logger";
import { RoomViewStore } from "./RoomViewStore";
import { type MatrixDispatcher } from "../dispatcher/dispatcher";
import { type SdkContextClass } from "../contexts/SDKContext";
import { type SDKContextClass } from "../contexts/SDKContextClass";
import { Action } from "../dispatcher/actions";
/**
@@ -24,7 +24,7 @@ export class MultiRoomViewStore {
public constructor(
private dispatcher: MatrixDispatcher,
private sdkContextClass: SdkContextClass,
private sdkContextClass: SDKContextClass,
) {}
/**
+2 -2
View File
@@ -41,7 +41,7 @@ import { type ActiveRoomChangedPayload } from "../dispatcher/payloads/ActiveRoom
import SettingsStore from "../settings/SettingsStore";
import { awaitRoomDownSync } from "../utils/RoomUpgrade";
import { UPDATE_EVENT } from "./AsyncStore";
import { type SdkContextClass } from "../contexts/SDKContext";
import { type SDKContextClass } from "../contexts/SDKContextClass";
import { CallStore } from "./CallStore";
import { type ThreadPayload } from "../dispatcher/payloads/ThreadPayload";
import { type ActionPayload } from "../dispatcher/payloads";
@@ -152,7 +152,7 @@ export class RoomViewStore extends EventEmitter {
public constructor(
dis: MatrixDispatcher,
private readonly stores: SdkContextClass,
private readonly stores: SDKContextClass,
private readonly lockedToRoomId?: string,
) {
super();
+2 -2
View File
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type SdkContextClass } from "../contexts/SDKContext";
import { type SDKContextClass } from "../contexts/SDKContextClass";
import SettingsStore from "../settings/SettingsStore";
import { isLocalRoom } from "../utils/localRoom/isLocalRoom";
import Timer from "../utils/Timer";
@@ -26,7 +26,7 @@ export default class TypingStore {
};
} = {};
public constructor(private readonly context: SdkContextClass) {
public constructor(private readonly context: SDKContextClass) {
this.reset();
}
@@ -26,7 +26,7 @@ import {
import { type ActionPayload } from "../../dispatcher/payloads";
import { Action } from "../../dispatcher/actions";
import { type ActiveRoomChangedPayload } from "../../dispatcher/payloads/ActiveRoomChangedPayload";
import { SdkContextClass } from "../../contexts/SDKContext";
import { SDKContextClass } from "../../contexts/SDKContextClass";
import { MatrixClientPeg } from "../../MatrixClientPeg";
/**
@@ -74,7 +74,7 @@ export default class RightPanelStore extends ReadyWatchingStore {
}
protected async onReady(): Promise<any> {
this.viewedRoomId = SdkContextClass.instance.roomViewStore.getRoomId();
this.viewedRoomId = SDKContextClass.instance.roomViewStore.getRoomId();
this.matrixClient?.on(CryptoEvent.VerificationRequestReceived, this.onVerificationRequestUpdate);
this.loadCacheFromSettings();
this.emitAndUpdateSettings();
@@ -33,7 +33,7 @@ import { SpaceWatcher } from "./SpaceWatcher";
import { type IRoomTimelineActionPayload } from "../../actions/MatrixActionCreators";
import { type RoomListStore as Interface, RoomListStoreEvent } from "./Interface";
import { UPDATE_EVENT } from "../AsyncStore";
import { SdkContextClass } from "../../contexts/SDKContext";
import { SDKContextClass } from "../../contexts/SDKContextClass";
import { getChangedOverrideRoomMutePushRules } from "../room-list-v3/utils";
import { type TagID } from "../room-list-v3/skip-list/tag";
@@ -113,7 +113,7 @@ export class RoomListStoreClass extends AsyncStoreWithClient<EmptyObject> implem
this.readyStore.useUnitTestClient(forcedClient);
}
SdkContextClass.instance.roomViewStore.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();
@@ -136,7 +136,7 @@ export class RoomListStoreClass extends AsyncStoreWithClient<EmptyObject> implem
private handleRVSUpdate({ trigger = true }): void {
if (!this.matrixClient) return; // We assume there won't be RVS updates without a client
const activeRoomId = SdkContextClass.instance.roomViewStore.getRoomId();
const activeRoomId = SDKContextClass.instance.roomViewStore.getRoomId();
if (!activeRoomId && this.algorithm.stickyRoom) {
this.algorithm.setStickyRoom(null);
} else if (activeRoomId) {
+4 -4
View File
@@ -61,7 +61,7 @@ import { type ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload"
import { type ViewHomePagePayload } from "../../dispatcher/payloads/ViewHomePagePayload";
import { type SwitchSpacePayload } from "../../dispatcher/payloads/SwitchSpacePayload";
import { type AfterLeaveRoomPayload } from "../../dispatcher/payloads/AfterLeaveRoomPayload";
import { SdkContextClass } from "../../contexts/SDKContext";
import { SDKContextClass } from "../../contexts/SDKContextClass";
import { ModuleApi } from "../../modules/Api.ts";
const ACTIVE_SPACE_LS_KEY = "mx_active_space";
@@ -919,7 +919,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<EmptyObject> {
this.updateNotificationStates(notificationStatesToUpdate);
};
private switchSpaceIfNeeded = (roomId = SdkContextClass.instance.roomViewStore.getRoomId()): void => {
private switchSpaceIfNeeded = (roomId = SDKContextClass.instance.roomViewStore.getRoomId()): void => {
if (!roomId) return;
if (!this.isRoomInSpace(this.activeSpace, roomId) && !this.matrixClient?.getRoom(roomId)?.isSpaceRoom()) {
this.switchToRelatedSpace(roomId);
@@ -975,7 +975,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<EmptyObject> {
// if the room currently being viewed was just joined then switch to its related space
if (
newMembership === KnownMembership.Join &&
room.roomId === SdkContextClass.instance.roomViewStore.getRoomId()
room.roomId === SDKContextClass.instance.roomViewStore.getRoomId()
) {
this.switchSpaceIfNeeded(room.roomId);
}
@@ -1003,7 +1003,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<EmptyObject> {
this.emit(room.roomId);
}
if (membership === KnownMembership.Join && room.roomId === SdkContextClass.instance.roomViewStore.getRoomId()) {
if (membership === KnownMembership.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 === KnownMembership.Leave && room.roomId === this.activeSpace) {
@@ -62,7 +62,7 @@ import { containsEmoji } from "../../effects/utils";
import dis from "../../dispatcher/dispatcher";
import { ElementWidgetCapabilities } from "./ElementWidgetCapabilities";
import { navigateToPermalink } from "../../utils/permalinks/navigator";
import { SdkContextClass } from "../../contexts/SDKContext";
import { SDKContextClass } from "../../contexts/SDKContextClass";
import { ModuleRunner } from "../../modules/ModuleRunner";
import { ModuleApi } from "../../modules/Api";
import { toWidgetDescriptor } from "../../modules/WidgetLifecycleApi";
@@ -232,7 +232,7 @@ export class ElementWidgetDriver extends WidgetDriver {
}
// To always allow OIDC requests for element call, the widgetPermissionStore is used:
SdkContextClass.instance.widgetPermissionStore.setOIDCState(
SDKContextClass.instance.widgetPermissionStore.setOIDCState(
forWidget,
forWidgetKind,
inRoomId,
@@ -303,7 +303,7 @@ export class ElementWidgetDriver extends WidgetDriver {
private getSendEventTarget(roomId: string | null = null): { client: MatrixClient; roomId: string } {
const client = MatrixClientPeg.safeGet();
roomId = roomId || SdkContextClass.instance.roomViewStore.getRoomId() || null;
roomId = roomId || SDKContextClass.instance.roomViewStore.getRoomId() || null;
if (!roomId) throw new Error("No room specified and no room in RoomViewStore focus.");
return { client, roomId };
}
@@ -691,7 +691,7 @@ export class ElementWidgetDriver extends WidgetDriver {
});
}
const oidcState = SdkContextClass.instance.widgetPermissionStore.getOIDCState(
const oidcState = SDKContextClass.instance.widgetPermissionStore.getOIDCState(
this.forWidget,
this.forWidgetKind,
this.inRoomId,
@@ -773,7 +773,7 @@ export class ElementWidgetDriver extends WidgetDriver {
): Promise<IReadEventRelationsResult> {
const client = MatrixClientPeg.safeGet();
const dir = direction as Direction;
roomId = roomId ?? SdkContextClass.instance.roomViewStore.getRoomId() ?? undefined;
roomId = roomId ?? SDKContextClass.instance.roomViewStore.getRoomId() ?? undefined;
if (typeof roomId !== "string") {
throw new Error("Error while reading the current room");
@@ -61,7 +61,7 @@ import { arrayFastClone } from "../../utils/arrays";
import { type ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload";
import Modal from "../../Modal";
import ErrorDialog from "../../components/views/dialogs/ErrorDialog";
import { SdkContextClass } from "../../contexts/SDKContext";
import { SDKContextClass } from "../../contexts/SDKContextClass";
import { UPDATE_EVENT } from "../AsyncStore";
// TODO: Purge this code of its overgrown hacks and compatibility shims.
@@ -293,7 +293,7 @@ export class WidgetMessaging extends TypedEventEmitter<WidgetMessagingEvent, Wid
// This listener is only active for account widgets, which may follow the
// user to different rooms
private onRoomViewStoreUpdate = (): void => {
const roomId = SdkContextClass.instance.roomViewStore.getRoomId() ?? null;
const roomId = SDKContextClass.instance.roomViewStore.getRoomId() ?? null;
if (roomId !== this.viewedRoomId) {
this.widgetApi!.setViewedRoomId(roomId);
this.viewedRoomId = roomId;
@@ -323,8 +323,8 @@ export class WidgetMessaging extends TypedEventEmitter<WidgetMessagingEvent, Wid
// receiving events for the right room
if (this.roomId === undefined) {
// Account widgets listen to the currently active room
this.widgetApi.setViewedRoomId(SdkContextClass.instance.roomViewStore.getRoomId() ?? null);
SdkContextClass.instance.roomViewStore.on(UPDATE_EVENT, this.onRoomViewStoreUpdate);
this.widgetApi.setViewedRoomId(SDKContextClass.instance.roomViewStore.getRoomId() ?? null);
SDKContextClass.instance.roomViewStore.on(UPDATE_EVENT, this.onRoomViewStoreUpdate);
} else {
// Room widgets get locked to the room they were added in
this.widgetApi.setViewedRoomId(this.roomId);
@@ -435,7 +435,7 @@ export class WidgetMessaging extends TypedEventEmitter<WidgetMessagingEvent, Wid
const integType = data?.integType as string;
const integId = <string>data?.integId;
const roomId = SdkContextClass.instance.roomViewStore.getRoomId();
const roomId = SDKContextClass.instance.roomViewStore.getRoomId();
const room = roomId ? this.client.getRoom(roomId) : undefined;
if (!room) return;
@@ -516,7 +516,7 @@ export class WidgetMessaging extends TypedEventEmitter<WidgetMessagingEvent, Wid
this.iframe = null;
WidgetMessagingStore.instance.stopMessaging(this.widget, this.roomId);
SdkContextClass.instance.roomViewStore.off(UPDATE_EVENT, this.onRoomViewStoreUpdate);
SDKContextClass.instance.roomViewStore.off(UPDATE_EVENT, this.onRoomViewStoreUpdate);
this.client.off(ClientEvent.Event, this.onEvent);
this.client.off(MatrixEventEvent.Decrypted, this.onEventDecrypted);
@@ -10,7 +10,7 @@ import { type Widget, WidgetKind } from "matrix-widget-api";
import SettingsStore from "../../settings/SettingsStore";
import { SettingLevel } from "../../settings/SettingLevel";
import { type SdkContextClass } from "../../contexts/SDKContext";
import { type SDKContextClass } from "../../contexts/SDKContextClass";
export enum OIDCState {
Allowed, // user has set the remembered value as allowed
@@ -19,7 +19,7 @@ export enum OIDCState {
}
export class WidgetPermissionStore {
public constructor(private readonly context: SdkContextClass) {}
public constructor(private readonly context: SDKContextClass) {}
// TODO (all functions here): Merge widgetKind with the widget definition
+4 -4
View File
@@ -24,7 +24,7 @@ import AddExistingToSpaceDialog from "../components/views/dialogs/AddExistingToS
import { type ButtonEvent } from "../components/views/elements/AccessibleButton";
import PosthogTrackers from "../PosthogTrackers";
import { showAddExistingSubspace, showCreateNewRoom } from "./space";
import { SdkContextClass } from "../contexts/SDKContext";
import { SDKContextClass } from "../contexts/SDKContextClass";
/**
* Auxiliary class to listen for dialog opening over the dispatcher and
@@ -55,9 +55,9 @@ export class DialogOpener {
Modal.createDialog(
RoomSettingsDialog,
{
roomId: payload.room_id || SdkContextClass.instance.roomViewStore.getRoomId(),
roomId: payload.room_id || SDKContextClass.instance.roomViewStore.getRoomId(),
initialTabId: payload.initial_tab_id,
sdkContext: SdkContextClass.instance,
sdkContext: SDKContextClass.instance,
},
/*className=*/ undefined,
/*isPriority=*/ false,
@@ -133,7 +133,7 @@ export class DialogOpener {
"mx_AddExistingToSpaceDialog_wrapper",
);
finished.then(([added]) => {
if (added && SdkContextClass.instance.roomViewStore.getRoomId() === space.roomId) {
if (added && SDKContextClass.instance.roomViewStore.getRoomId() === space.roomId) {
defaultDispatcher.fire(Action.UpdateSpaceHierarchy);
}
});
@@ -30,7 +30,8 @@ import MatrixClientContext from "../../contexts/MatrixClientContext";
import getExportCSS from "./exportCSS";
import { textForEvent } from "../../TextForEvent";
import { haveRendererForEvent } from "../../events/EventTileFactory";
import { SDKContext, SdkContextClass } from "../../contexts/SDKContext.ts";
import { SDKContext } from "../../contexts/SDKContext.ts";
import { SDKContextClass } from "../../contexts/SDKContextClass";
import { DateSeparatorViewModel } from "../../viewmodels/room/timeline/DateSeparatorViewModel";
import exportJS from "./exportJS.js?raw";
@@ -285,7 +286,7 @@ export default class HTMLExporter extends Exporter {
{/* Export rendering uses an isolated root, so provide I18nContext explicitly. */}
<I18nContext.Provider value={window.mxModuleApi.i18n}>
<MatrixClientContext.Provider value={this.room.client}>
<SDKContext.Provider value={SdkContextClass.instance}>
<SDKContext.Provider value={SDKContextClass.instance}>
<TooltipProvider>
<EventTile
mxEvent={mxEv}
+2 -2
View File
@@ -24,7 +24,7 @@ import { type ViewHomePagePayload } from "../dispatcher/payloads/ViewHomePagePay
import LeaveSpaceDialog from "../components/views/dialogs/LeaveSpaceDialog";
import { type AfterLeaveRoomPayload } from "../dispatcher/payloads/AfterLeaveRoomPayload";
import { bulkSpaceBehaviour } from "./space";
import { SdkContextClass } from "../contexts/SDKContext";
import { SDKContextClass } from "../contexts/SDKContextClass";
import SettingsStore from "../settings/SettingsStore";
import { CallStore } from "../stores/CallStore";
import LegacyCallHandler from "../LegacyCallHandler";
@@ -161,7 +161,7 @@ export async function leaveRoomBehaviour(
return;
}
if (SdkContextClass.instance.roomViewStore.getRoomId() === roomId) {
if (SDKContextClass.instance.roomViewStore.getRoomId() === roomId) {
// We were viewing the room that was just left. In order to avoid
// accidentally viewing the next room in the list and clearing its
// notifications, switch to a neutral ground such as the home page or
+3 -3
View File
@@ -31,7 +31,7 @@ import {
} from "../dispatcher/payloads/OpenSpacePreferencesPayload";
import { type OpenSpaceSettingsPayload } from "../dispatcher/payloads/OpenSpaceSettingsPayload";
import { type OpenAddExistingToSpaceDialogPayload } from "../dispatcher/payloads/OpenAddExistingToSpaceDialogPayload";
import { SdkContextClass } from "../contexts/SDKContext";
import { SDKContextClass } from "../contexts/SDKContextClass";
export const shouldShowSpaceSettings = (space: Room): boolean => {
const userId = space.client.getUserId()!;
@@ -115,7 +115,7 @@ export const showAddExistingSubspace = (space: Room): void => {
"mx_AddExistingToSpaceDialog_wrapper",
);
finished.then(([added]) => {
if (added && SdkContextClass.instance.roomViewStore.getRoomId() === space.roomId) {
if (added && SDKContextClass.instance.roomViewStore.getRoomId() === space.roomId) {
defaultDispatcher.fire(Action.UpdateSpaceHierarchy);
}
});
@@ -131,7 +131,7 @@ export const showCreateNewSubspace = (space: Room): void => {
"mx_CreateSubspaceDialog_wrapper",
);
finished.then(([added]) => {
if (added && SdkContextClass.instance.roomViewStore.getRoomId() === space.roomId) {
if (added && SDKContextClass.instance.roomViewStore.getRoomId() === space.roomId) {
defaultDispatcher.fire(Action.UpdateSpaceHierarchy);
}
});
@@ -34,7 +34,7 @@ import {
UPDATE_STATUS_INDICATOR,
} from "../../stores/notifications/RoomNotificationStateStore";
import { RoomListItemViewModel } from "./RoomListItemViewModel";
import { SdkContextClass } from "../../contexts/SDKContext";
import { SDKContextClass } from "../../contexts/SDKContextClass";
import { hasCreateRoomRights } from "./utils";
import { keepIfSame } from "../../utils/keepIfSame";
import { DefaultTagID } from "../../stores/room-list-v3/skip-list/tag";
@@ -490,7 +490,7 @@ export class RoomListViewModel
* Migrated from useRoomListNavigation hook.
*/
private handleViewRoomDelta(payload: ViewRoomDeltaPayload): void {
const currentRoomId = SdkContextClass.instance.roomViewStore.getRoomId();
const currentRoomId = SDKContextClass.instance.roomViewStore.getRoomId();
if (!currentRoomId) return;
const { delta, unread } = payload;
@@ -668,7 +668,7 @@ export class RoomListViewModel
): Promise<void> {
// Determine the room ID to use for calculations
// Use override if provided (e.g., during space changes), otherwise fall back to RoomViewStore
const roomId = roomIdOverride ?? SdkContextClass.instance.roomViewStore.getRoomId();
const roomId = roomIdOverride ?? SDKContextClass.instance.roomViewStore.getRoomId();
// Apply sticky room logic to keep selected room at same position within its section
const stickySections = this.applyStickyRoom(isRoomChange, roomId);
@@ -28,7 +28,7 @@ import { UIFeature } from "../../../settings/UIFeature";
import ErrorDialog from "../../../components/views/dialogs/ErrorDialog";
import BugReportDialog from "../../../components/views/dialogs/BugReportDialog";
import AccessibleButton from "../../../components/views/elements/AccessibleButton";
import { SdkContextClass } from "../../../contexts/SDKContext";
import { SDKContextClass } from "../../../contexts/SDKContextClass";
export interface DateSeparatorViewModelProps {
/**
@@ -159,7 +159,7 @@ export class DateSeparatorViewModel
// Only try to navigate to the room if the user is still viewing the same
// room. We don't want to jump someone back to a room after a slow request
// if they've already navigated away to another room.
const currentRoomId = SdkContextClass.instance.roomViewStore.getRoomId();
const currentRoomId = SDKContextClass.instance.roomViewStore.getRoomId();
if (currentRoomId === roomIdForJumpRequest) {
dispatcher.dispatch<ViewRoomPayload>({
action: Action.ViewRoom,
@@ -185,7 +185,7 @@ export class DateSeparatorViewModel
// don't want to worry someone about an error in a room they no longer care
// about after a slow request if they've already navigated away to another
// room.
const currentRoomId = SdkContextClass.instance.roomViewStore.getRoomId();
const currentRoomId = SDKContextClass.instance.roomViewStore.getRoomId();
if (currentRoomId === roomIdForJumpRequest) {
let friendlyErrorMessage = "An error occured while trying to find and jump to the given date.";
let submitDebugLogsContent: React.ReactElement = <></>;