Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/components/structures/LoggedInView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ import { monitorSyncedPushRules } from "../../utils/pushRules/monitorSyncedPushR
import { type ConfigOptions } from "../../SdkConfig";
import { MatrixClientContextProvider } from "./MatrixClientContextProvider";
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)
// so each pinned message may trigger a request. Limit the number per room for sanity.
Expand Down Expand Up @@ -690,6 +690,7 @@ class LoggedInView extends React.Component<IProps, IState> {
key={this.props.currentRoomId || "roomview"}
justCreatedOpts={this.props.roomJustCreatedOpts}
forceTimeline={this.props.forceTimeline}
roomViewStore={SdkContextClass.instance.roomViewStore}
/>
);
break;
Expand Down
58 changes: 38 additions & 20 deletions src/components/structures/RoomView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ import { ScopedRoomContextProvider, useScopedRoomContext } from "../../contexts/
import { DeclineAndBlockInviteDialog } from "../views/dialogs/DeclineAndBlockInviteDialog";
import { type FocusMessageSearchPayload } from "../../dispatcher/payloads/FocusMessageSearchPayload.ts";
import { isRoomEncrypted } from "../../hooks/useIsEncrypted";
import { type RoomViewStore } from "../../stores/RoomViewStore.tsx";

const DEBUG = false;
const PREVENT_MULTIPLE_JITSI_WITHIN = 30_000;
Expand All @@ -157,11 +158,19 @@ interface IRoomProps {

// Called with the credentials of a registered user (if they were a ROU that transitioned to PWLU)
onRegistered?(credentials: IMatrixClientCreds): void;
/**
* The RoomViewStore instance for the room to be displayed.
*/
roomViewStore: RoomViewStore;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing tsdoc

}

export { MainSplitContentType };

export interface IRoomState {
/**
* The RoomViewStore instance for the room we are displaying
*/
roomViewStore: RoomViewStore;
room?: Room;
roomId?: string;
roomAlias?: string;
Expand Down Expand Up @@ -394,6 +403,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {

const llMembers = context.client.hasLazyLoadMembersEnabled();
this.state = {
roomViewStore: props.roomViewStore,
roomId: undefined,
roomLoading: true,
peekLoading: false,
Expand Down Expand Up @@ -525,7 +535,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
};

private getMainSplitContentType = (room: Room): MainSplitContentType => {
if (this.context.roomViewStore.isViewingCall() || isVideoRoom(room)) {
if (this.state.roomViewStore.isViewingCall() || isVideoRoom(room)) {
return MainSplitContentType.Call;
}
if (this.context.widgetLayoutStore.hasMaximisedWidget(room)) {
Expand All @@ -539,8 +549,8 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
return;
}

const roomLoadError = this.context.roomViewStore.getRoomLoadError() ?? undefined;
if (!initial && !roomLoadError && this.state.roomId !== this.context.roomViewStore.getRoomId()) {
const roomLoadError = this.state.roomViewStore.getRoomLoadError() ?? undefined;
if (!initial && !roomLoadError && this.state.roomId !== this.state.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
Expand All @@ -554,30 +564,38 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
// it was, it means we're about to be unmounted.
return;
}

const roomId = this.context.roomViewStore.getRoomId() ?? null;
const roomViewStore = this.state.roomViewStore;
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 newState: Partial<IRoomState> = {
roomId: roomId ?? undefined,
roomAlias: this.context.roomViewStore.getRoomAlias() ?? undefined,
roomLoading: this.context.roomViewStore.isRoomLoading(),
roomAlias: roomAlias,
roomLoading: roomLoading,
roomLoadError,
joining: this.context.roomViewStore.isJoining(),
replyToEvent: this.context.roomViewStore.getQuotingEvent() ?? undefined,
joining: joining,
replyToEvent: replyToEvent,
// 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),
showRedactions: SettingsStore.getValue("showRedactions", roomId),
showJoinLeaves: SettingsStore.getValue("showJoinLeaves", roomId),
showAvatarChanges: SettingsStore.getValue("showAvatarChanges", roomId),
showDisplaynameChanges: SettingsStore.getValue("showDisplaynameChanges", roomId),
wasContextSwitch: this.context.roomViewStore.getWasContextSwitch(),
wasContextSwitch: wasContextSwitch,
mainSplitContentType: room ? this.getMainSplitContentType(room) : undefined,
initialEventId: undefined, // default to clearing this, will get set later in the method if needed
showRightPanel: roomId ? this.context.rightPanelStore.isOpenForRoom(roomId) : false,
promptAskToJoin: this.context.roomViewStore.promptAskToJoin(),
viewRoomOpts: this.context.roomViewStore.getViewRoomOpts(),
promptAskToJoin: promptAskToJoin,
viewRoomOpts: viewRoomOpts,
};

if (
Expand All @@ -593,7 +611,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
newState.showRightPanel = false;
}

const initialEventId = this.context.roomViewStore.getInitialEventId() ?? this.state.initialEventId;
const initialEventId = this.state.roomViewStore.getInitialEventId() ?? this.state.initialEventId;
if (initialEventId) {
let initialEvent = room?.findEventById(initialEventId);
// The event does not exist in the current sync data
Expand All @@ -619,13 +637,13 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
action: Action.ShowThread,
rootEvent: thread.rootEvent,
initialEvent,
highlighted: this.context.roomViewStore.isInitialEventHighlighted(),
scroll_into_view: this.context.roomViewStore.initialEventScrollIntoView(),
highlighted: this.state.roomViewStore.isInitialEventHighlighted(),
scroll_into_view: this.state.roomViewStore.initialEventScrollIntoView(),
});
} else {
newState.initialEventId = initialEventId;
newState.isInitialEventHighlighted = this.context.roomViewStore.isInitialEventHighlighted();
newState.initialEventScrollIntoView = this.context.roomViewStore.initialEventScrollIntoView();
newState.isInitialEventHighlighted = this.state.roomViewStore.isInitialEventHighlighted();
newState.initialEventScrollIntoView = this.state.roomViewStore.initialEventScrollIntoView();
}
}

Expand Down Expand Up @@ -885,7 +903,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
this.context.client.on(MatrixEventEvent.Decrypted, this.onEventDecrypted);
}
// 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);

Expand Down Expand Up @@ -1002,7 +1020,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {

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);
WidgetEchoStore.removeListener(UPDATE_EVENT, this.onWidgetEchoStoreUpdate);
Expand Down
3 changes: 3 additions & 0 deletions src/contexts/RoomContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ const RoomContext = createContext<
promptAskToJoin: false,
viewRoomOpts: { buttons: [] },
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";
export default RoomContext;
2 changes: 2 additions & 0 deletions test/test-utils/room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { type IRoomState, MainSplitContentType } from "../../src/components/stru
import { TimelineRenderingType } from "../../src/contexts/RoomContext";
import { Layout } from "../../src/settings/enums/Layout";
import { mkEvent } from "./test-utils";
import { SdkContextClass } from "../../src/contexts/SDKContext";

export const makeMembershipEvent = (roomId: string, userId: string, membership = KnownMembership.Join) =>
mkEvent({
Expand Down Expand Up @@ -44,6 +45,7 @@ export const makeRoomWithStateEvents = (

export function getRoomContext(room: Room, override: Partial<IRoomState>): IRoomState {
return {
roomViewStore: SdkContextClass.instance.roomViewStore,
room,
roomLoading: true,
peekLoading: false,
Expand Down
2 changes: 2 additions & 0 deletions test/unit-tests/components/structures/RoomView-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ describe("RoomView", () => {
threepidInvite={undefined as any}
forceTimeline={false}
ref={ref}
roomViewStore={stores.roomViewStore}
/>
</SDKContext.Provider>
</MatrixClientContext.Provider>,
Expand Down Expand Up @@ -196,6 +197,7 @@ describe("RoomView", () => {
threepidInvite={undefined}
forceTimeline={false}
onRegistered={jest.fn()}
roomViewStore={stores.roomViewStore}
/>
</SDKContext.Provider>
</MatrixClientContext.Provider>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ import { mockPlatformPeg } from "../../../../test-utils/platform";
import { doMaybeLocalRoomAction } from "../../../../../src/utils/local-room";
import { addTextToComposer } from "../../../../test-utils/composer";
import { ScopedRoomContextProvider } from "../../../../../src/contexts/ScopedRoomContext.tsx";
import { SdkContextClass } from "../../../../../src/contexts/SDKContext.ts";

jest.mock("../../../../../src/utils/local-room", () => ({
doMaybeLocalRoomAction: jest.fn(),
}));

describe("<SendMessageComposer/>", () => {
const defaultRoomContext: IRoomState = {
roomViewStore: SdkContextClass.instance.roomViewStore,
roomLoading: true,
peekLoading: false,
shouldPeek: true,
Expand Down
Loading