Provide RoomViewStore from the RoomContext (#30980)
* Pass roomViewStore to the RoomView and add to the RoomContext. * lint * lint * Make constants more DRY * Make constants more DRY * Commend non-null assertion on roomViewStore property of the RoomContext * Update tsdocs.
This commit is contained in:
@@ -68,7 +68,7 @@ import { monitorSyncedPushRules } from "../../utils/pushRules/monitorSyncedPushR
|
|||||||
import { type ConfigOptions } from "../../SdkConfig";
|
import { type ConfigOptions } from "../../SdkConfig";
|
||||||
import { MatrixClientContextProvider } from "./MatrixClientContextProvider";
|
import { MatrixClientContextProvider } from "./MatrixClientContextProvider";
|
||||||
import { Landmark, LandmarkNavigation } from "../../accessibility/LandmarkNavigation";
|
import { Landmark, LandmarkNavigation } from "../../accessibility/LandmarkNavigation";
|
||||||
import { SDKContext } from "../../contexts/SDKContext.ts";
|
import { SDKContext, SdkContextClass } from "../../contexts/SDKContext.ts";
|
||||||
|
|
||||||
// We need to fetch each pinned message individually (if we don't already have it)
|
// We need to fetch each pinned message individually (if we don't already have it)
|
||||||
// so each pinned message may trigger a request. Limit the number per room for sanity.
|
// so each pinned message may trigger a request. Limit the number per room for sanity.
|
||||||
@@ -690,6 +690,7 @@ class LoggedInView extends React.Component<IProps, IState> {
|
|||||||
key={this.props.currentRoomId || "roomview"}
|
key={this.props.currentRoomId || "roomview"}
|
||||||
justCreatedOpts={this.props.roomJustCreatedOpts}
|
justCreatedOpts={this.props.roomJustCreatedOpts}
|
||||||
forceTimeline={this.props.forceTimeline}
|
forceTimeline={this.props.forceTimeline}
|
||||||
|
roomViewStore={SdkContextClass.instance.roomViewStore}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ import { ScopedRoomContextProvider, useScopedRoomContext } from "../../contexts/
|
|||||||
import { DeclineAndBlockInviteDialog } from "../views/dialogs/DeclineAndBlockInviteDialog";
|
import { DeclineAndBlockInviteDialog } from "../views/dialogs/DeclineAndBlockInviteDialog";
|
||||||
import { type FocusMessageSearchPayload } from "../../dispatcher/payloads/FocusMessageSearchPayload.ts";
|
import { type FocusMessageSearchPayload } from "../../dispatcher/payloads/FocusMessageSearchPayload.ts";
|
||||||
import { isRoomEncrypted } from "../../hooks/useIsEncrypted";
|
import { isRoomEncrypted } from "../../hooks/useIsEncrypted";
|
||||||
|
import { type RoomViewStore } from "../../stores/RoomViewStore.tsx";
|
||||||
|
|
||||||
const DEBUG = false;
|
const DEBUG = false;
|
||||||
const PREVENT_MULTIPLE_JITSI_WITHIN = 30_000;
|
const PREVENT_MULTIPLE_JITSI_WITHIN = 30_000;
|
||||||
@@ -157,11 +158,19 @@ interface IRoomProps {
|
|||||||
|
|
||||||
// Called with the credentials of a registered user (if they were a ROU that transitioned to PWLU)
|
// Called with the credentials of a registered user (if they were a ROU that transitioned to PWLU)
|
||||||
onRegistered?(credentials: IMatrixClientCreds): void;
|
onRegistered?(credentials: IMatrixClientCreds): void;
|
||||||
|
/**
|
||||||
|
* The RoomViewStore instance for the room to be displayed.
|
||||||
|
*/
|
||||||
|
roomViewStore: RoomViewStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { MainSplitContentType };
|
export { MainSplitContentType };
|
||||||
|
|
||||||
export interface IRoomState {
|
export interface IRoomState {
|
||||||
|
/**
|
||||||
|
* The RoomViewStore instance for the room we are displaying
|
||||||
|
*/
|
||||||
|
roomViewStore: RoomViewStore;
|
||||||
room?: Room;
|
room?: Room;
|
||||||
roomId?: string;
|
roomId?: string;
|
||||||
roomAlias?: string;
|
roomAlias?: string;
|
||||||
@@ -394,6 +403,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||||||
|
|
||||||
const llMembers = context.client.hasLazyLoadMembersEnabled();
|
const llMembers = context.client.hasLazyLoadMembersEnabled();
|
||||||
this.state = {
|
this.state = {
|
||||||
|
roomViewStore: props.roomViewStore,
|
||||||
roomId: undefined,
|
roomId: undefined,
|
||||||
roomLoading: true,
|
roomLoading: true,
|
||||||
peekLoading: false,
|
peekLoading: false,
|
||||||
@@ -525,7 +535,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private getMainSplitContentType = (room: Room): MainSplitContentType => {
|
private getMainSplitContentType = (room: Room): MainSplitContentType => {
|
||||||
if (this.context.roomViewStore.isViewingCall() || isVideoRoom(room)) {
|
if (this.state.roomViewStore.isViewingCall() || isVideoRoom(room)) {
|
||||||
return MainSplitContentType.Call;
|
return MainSplitContentType.Call;
|
||||||
}
|
}
|
||||||
if (this.context.widgetLayoutStore.hasMaximisedWidget(room)) {
|
if (this.context.widgetLayoutStore.hasMaximisedWidget(room)) {
|
||||||
@@ -539,8 +549,8 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const roomLoadError = this.context.roomViewStore.getRoomLoadError() ?? undefined;
|
const roomLoadError = this.state.roomViewStore.getRoomLoadError() ?? undefined;
|
||||||
if (!initial && !roomLoadError && this.state.roomId !== this.context.roomViewStore.getRoomId()) {
|
if (!initial && !roomLoadError && this.state.roomId !== this.state.roomViewStore.getRoomId()) {
|
||||||
// RoomView explicitly does not support changing what room
|
// RoomView explicitly does not support changing what room
|
||||||
// is being viewed: instead it should just be re-mounted when
|
// is being viewed: instead it should just be re-mounted when
|
||||||
// switching rooms. Therefore, if the room ID changes, we
|
// switching rooms. Therefore, if the room ID changes, we
|
||||||
@@ -554,30 +564,38 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||||||
// it was, it means we're about to be unmounted.
|
// it was, it means we're about to be unmounted.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const roomViewStore = this.state.roomViewStore;
|
||||||
const roomId = this.context.roomViewStore.getRoomId() ?? null;
|
const roomId = roomViewStore.getRoomId() ?? null;
|
||||||
|
const roomAlias = roomViewStore.getRoomAlias() ?? undefined;
|
||||||
|
const roomLoading = roomViewStore.isRoomLoading();
|
||||||
|
const joining = roomViewStore.isJoining();
|
||||||
|
const replyToEvent = roomViewStore.getQuotingEvent() ?? undefined;
|
||||||
|
const shouldPeek = this.state.matrixClientIsReady && roomViewStore.shouldPeek();
|
||||||
|
const wasContextSwitch = roomViewStore.getWasContextSwitch();
|
||||||
|
const promptAskToJoin = roomViewStore.promptAskToJoin();
|
||||||
|
const viewRoomOpts = roomViewStore.getViewRoomOpts();
|
||||||
const room = this.context.client?.getRoom(roomId ?? undefined) ?? undefined;
|
const room = this.context.client?.getRoom(roomId ?? undefined) ?? undefined;
|
||||||
|
|
||||||
const newState: Partial<IRoomState> = {
|
const newState: Partial<IRoomState> = {
|
||||||
roomId: roomId ?? undefined,
|
roomId: roomId ?? undefined,
|
||||||
roomAlias: this.context.roomViewStore.getRoomAlias() ?? undefined,
|
roomAlias: roomAlias,
|
||||||
roomLoading: this.context.roomViewStore.isRoomLoading(),
|
roomLoading: roomLoading,
|
||||||
roomLoadError,
|
roomLoadError,
|
||||||
joining: this.context.roomViewStore.isJoining(),
|
joining: joining,
|
||||||
replyToEvent: this.context.roomViewStore.getQuotingEvent() ?? undefined,
|
replyToEvent: replyToEvent,
|
||||||
// we should only peek once we have a ready client
|
// we should only peek once we have a ready client
|
||||||
shouldPeek: this.state.matrixClientIsReady && this.context.roomViewStore.shouldPeek(),
|
shouldPeek: shouldPeek,
|
||||||
showReadReceipts: SettingsStore.getValue("showReadReceipts", roomId),
|
showReadReceipts: SettingsStore.getValue("showReadReceipts", roomId),
|
||||||
showRedactions: SettingsStore.getValue("showRedactions", roomId),
|
showRedactions: SettingsStore.getValue("showRedactions", roomId),
|
||||||
showJoinLeaves: SettingsStore.getValue("showJoinLeaves", roomId),
|
showJoinLeaves: SettingsStore.getValue("showJoinLeaves", roomId),
|
||||||
showAvatarChanges: SettingsStore.getValue("showAvatarChanges", roomId),
|
showAvatarChanges: SettingsStore.getValue("showAvatarChanges", roomId),
|
||||||
showDisplaynameChanges: SettingsStore.getValue("showDisplaynameChanges", roomId),
|
showDisplaynameChanges: SettingsStore.getValue("showDisplaynameChanges", roomId),
|
||||||
wasContextSwitch: this.context.roomViewStore.getWasContextSwitch(),
|
wasContextSwitch: wasContextSwitch,
|
||||||
mainSplitContentType: room ? this.getMainSplitContentType(room) : undefined,
|
mainSplitContentType: room ? this.getMainSplitContentType(room) : undefined,
|
||||||
initialEventId: undefined, // default to clearing this, will get set later in the method if needed
|
initialEventId: undefined, // default to clearing this, will get set later in the method if needed
|
||||||
showRightPanel: roomId ? this.context.rightPanelStore.isOpenForRoom(roomId) : false,
|
showRightPanel: roomId ? this.context.rightPanelStore.isOpenForRoom(roomId) : false,
|
||||||
promptAskToJoin: this.context.roomViewStore.promptAskToJoin(),
|
promptAskToJoin: promptAskToJoin,
|
||||||
viewRoomOpts: this.context.roomViewStore.getViewRoomOpts(),
|
viewRoomOpts: viewRoomOpts,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -593,7 +611,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||||||
newState.showRightPanel = false;
|
newState.showRightPanel = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialEventId = this.context.roomViewStore.getInitialEventId() ?? this.state.initialEventId;
|
const initialEventId = this.state.roomViewStore.getInitialEventId() ?? this.state.initialEventId;
|
||||||
if (initialEventId) {
|
if (initialEventId) {
|
||||||
let initialEvent = room?.findEventById(initialEventId);
|
let initialEvent = room?.findEventById(initialEventId);
|
||||||
// The event does not exist in the current sync data
|
// The event does not exist in the current sync data
|
||||||
@@ -619,13 +637,13 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||||||
action: Action.ShowThread,
|
action: Action.ShowThread,
|
||||||
rootEvent: thread.rootEvent,
|
rootEvent: thread.rootEvent,
|
||||||
initialEvent,
|
initialEvent,
|
||||||
highlighted: this.context.roomViewStore.isInitialEventHighlighted(),
|
highlighted: this.state.roomViewStore.isInitialEventHighlighted(),
|
||||||
scroll_into_view: this.context.roomViewStore.initialEventScrollIntoView(),
|
scroll_into_view: this.state.roomViewStore.initialEventScrollIntoView(),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
newState.initialEventId = initialEventId;
|
newState.initialEventId = initialEventId;
|
||||||
newState.isInitialEventHighlighted = this.context.roomViewStore.isInitialEventHighlighted();
|
newState.isInitialEventHighlighted = this.state.roomViewStore.isInitialEventHighlighted();
|
||||||
newState.initialEventScrollIntoView = this.context.roomViewStore.initialEventScrollIntoView();
|
newState.initialEventScrollIntoView = this.state.roomViewStore.initialEventScrollIntoView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -885,7 +903,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||||||
this.context.client.on(MatrixEventEvent.Decrypted, this.onEventDecrypted);
|
this.context.client.on(MatrixEventEvent.Decrypted, this.onEventDecrypted);
|
||||||
}
|
}
|
||||||
// Start listening for RoomViewStore updates
|
// Start listening for RoomViewStore updates
|
||||||
this.context.roomViewStore.on(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
this.state.roomViewStore.on(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
||||||
|
|
||||||
this.context.rightPanelStore.on(UPDATE_EVENT, this.onRightPanelStoreUpdate);
|
this.context.rightPanelStore.on(UPDATE_EVENT, this.onRightPanelStoreUpdate);
|
||||||
|
|
||||||
@@ -1002,7 +1020,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||||||
|
|
||||||
window.removeEventListener("beforeunload", this.onPageUnload);
|
window.removeEventListener("beforeunload", this.onPageUnload);
|
||||||
|
|
||||||
this.context.roomViewStore.off(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
this.state.roomViewStore.off(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
||||||
|
|
||||||
this.context.rightPanelStore.off(UPDATE_EVENT, this.onRightPanelStoreUpdate);
|
this.context.rightPanelStore.off(UPDATE_EVENT, this.onRightPanelStoreUpdate);
|
||||||
WidgetEchoStore.removeListener(UPDATE_EVENT, this.onWidgetEchoStoreUpdate);
|
WidgetEchoStore.removeListener(UPDATE_EVENT, this.onWidgetEchoStoreUpdate);
|
||||||
|
|||||||
@@ -75,6 +75,9 @@ const RoomContext = createContext<
|
|||||||
promptAskToJoin: false,
|
promptAskToJoin: false,
|
||||||
viewRoomOpts: { buttons: [] },
|
viewRoomOpts: { buttons: [] },
|
||||||
isRoomEncrypted: null,
|
isRoomEncrypted: null,
|
||||||
|
// roomViewStore should always be present as it is passed to RoomView constructor.
|
||||||
|
// In time when we migrate the RoomView to MVVM it will cease to exist(become a ViewModel).
|
||||||
|
roomViewStore: undefined!,
|
||||||
});
|
});
|
||||||
RoomContext.displayName = "RoomContext";
|
RoomContext.displayName = "RoomContext";
|
||||||
export default RoomContext;
|
export default RoomContext;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { type IRoomState, MainSplitContentType } from "../../src/components/stru
|
|||||||
import { TimelineRenderingType } from "../../src/contexts/RoomContext";
|
import { TimelineRenderingType } from "../../src/contexts/RoomContext";
|
||||||
import { Layout } from "../../src/settings/enums/Layout";
|
import { Layout } from "../../src/settings/enums/Layout";
|
||||||
import { mkEvent } from "./test-utils";
|
import { mkEvent } from "./test-utils";
|
||||||
|
import { SdkContextClass } from "../../src/contexts/SDKContext";
|
||||||
|
|
||||||
export const makeMembershipEvent = (roomId: string, userId: string, membership = KnownMembership.Join) =>
|
export const makeMembershipEvent = (roomId: string, userId: string, membership = KnownMembership.Join) =>
|
||||||
mkEvent({
|
mkEvent({
|
||||||
@@ -44,6 +45,7 @@ export const makeRoomWithStateEvents = (
|
|||||||
|
|
||||||
export function getRoomContext(room: Room, override: Partial<IRoomState>): IRoomState {
|
export function getRoomContext(room: Room, override: Partial<IRoomState>): IRoomState {
|
||||||
return {
|
return {
|
||||||
|
roomViewStore: SdkContextClass.instance.roomViewStore,
|
||||||
room,
|
room,
|
||||||
roomLoading: true,
|
roomLoading: true,
|
||||||
peekLoading: false,
|
peekLoading: false,
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ describe("RoomView", () => {
|
|||||||
threepidInvite={undefined as any}
|
threepidInvite={undefined as any}
|
||||||
forceTimeline={false}
|
forceTimeline={false}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
roomViewStore={stores.roomViewStore}
|
||||||
/>
|
/>
|
||||||
</SDKContext.Provider>
|
</SDKContext.Provider>
|
||||||
</MatrixClientContext.Provider>,
|
</MatrixClientContext.Provider>,
|
||||||
@@ -196,6 +197,7 @@ describe("RoomView", () => {
|
|||||||
threepidInvite={undefined}
|
threepidInvite={undefined}
|
||||||
forceTimeline={false}
|
forceTimeline={false}
|
||||||
onRegistered={jest.fn()}
|
onRegistered={jest.fn()}
|
||||||
|
roomViewStore={stores.roomViewStore}
|
||||||
/>
|
/>
|
||||||
</SDKContext.Provider>
|
</SDKContext.Provider>
|
||||||
</MatrixClientContext.Provider>,
|
</MatrixClientContext.Provider>,
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import { mockPlatformPeg } from "../../../../test-utils/platform";
|
|||||||
import { doMaybeLocalRoomAction } from "../../../../../src/utils/local-room";
|
import { doMaybeLocalRoomAction } from "../../../../../src/utils/local-room";
|
||||||
import { addTextToComposer } from "../../../../test-utils/composer";
|
import { addTextToComposer } from "../../../../test-utils/composer";
|
||||||
import { ScopedRoomContextProvider } from "../../../../../src/contexts/ScopedRoomContext.tsx";
|
import { ScopedRoomContextProvider } from "../../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
import { SdkContextClass } from "../../../../../src/contexts/SDKContext.ts";
|
||||||
|
|
||||||
jest.mock("../../../../../src/utils/local-room", () => ({
|
jest.mock("../../../../../src/utils/local-room", () => ({
|
||||||
doMaybeLocalRoomAction: jest.fn(),
|
doMaybeLocalRoomAction: jest.fn(),
|
||||||
@@ -37,6 +38,7 @@ jest.mock("../../../../../src/utils/local-room", () => ({
|
|||||||
|
|
||||||
describe("<SendMessageComposer/>", () => {
|
describe("<SendMessageComposer/>", () => {
|
||||||
const defaultRoomContext: IRoomState = {
|
const defaultRoomContext: IRoomState = {
|
||||||
|
roomViewStore: SdkContextClass.instance.roomViewStore,
|
||||||
roomLoading: true,
|
roomLoading: true,
|
||||||
peekLoading: false,
|
peekLoading: false,
|
||||||
shouldPeek: true,
|
shouldPeek: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user