Improve performance of RoomContext in RoomHeader (#28574)
* Improve performance of RoomContext in RoomHeader This allows a component to subscribe to only part of the RoomContext so they do not need to re-render on every single change Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update tests Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Prettier Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add comment Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
parent
8619a22f57
commit
b87437d439
56 changed files with 289 additions and 216 deletions
|
@ -34,6 +34,7 @@ import { Layout } from "../../settings/enums/Layout";
|
||||||
import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext";
|
import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext";
|
||||||
import Measured from "../views/elements/Measured";
|
import Measured from "../views/elements/Measured";
|
||||||
import EmptyState from "../views/right_panel/EmptyState";
|
import EmptyState from "../views/right_panel/EmptyState";
|
||||||
|
import { ScopedRoomContextProvider } from "../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
roomId: string;
|
roomId: string;
|
||||||
|
@ -273,12 +274,10 @@ class FilePanel extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
if (this.state.timelineSet) {
|
if (this.state.timelineSet) {
|
||||||
return (
|
return (
|
||||||
<RoomContext.Provider
|
<ScopedRoomContextProvider
|
||||||
value={{
|
{...this.context}
|
||||||
...this.context,
|
timelineRenderingType={TimelineRenderingType.File}
|
||||||
timelineRenderingType: TimelineRenderingType.File,
|
narrow={this.state.narrow}
|
||||||
narrow: this.state.narrow,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<BaseCard
|
<BaseCard
|
||||||
className="mx_FilePanel"
|
className="mx_FilePanel"
|
||||||
|
@ -302,16 +301,11 @@ class FilePanel extends React.Component<IProps, IState> {
|
||||||
layout={Layout.Group}
|
layout={Layout.Group}
|
||||||
/>
|
/>
|
||||||
</BaseCard>
|
</BaseCard>
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<RoomContext.Provider
|
<ScopedRoomContextProvider {...this.context} timelineRenderingType={TimelineRenderingType.File}>
|
||||||
value={{
|
|
||||||
...this.context,
|
|
||||||
timelineRenderingType: TimelineRenderingType.File,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<BaseCard
|
<BaseCard
|
||||||
className="mx_FilePanel"
|
className="mx_FilePanel"
|
||||||
onClose={this.props.onClose}
|
onClose={this.props.onClose}
|
||||||
|
@ -319,7 +313,7 @@ class FilePanel extends React.Component<IProps, IState> {
|
||||||
>
|
>
|
||||||
<Spinner />
|
<Spinner />
|
||||||
</BaseCard>
|
</BaseCard>
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { Layout } from "../../settings/enums/Layout";
|
||||||
import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext";
|
import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext";
|
||||||
import Measured from "../views/elements/Measured";
|
import Measured from "../views/elements/Measured";
|
||||||
import EmptyState from "../views/right_panel/EmptyState";
|
import EmptyState from "../views/right_panel/EmptyState";
|
||||||
|
import { ScopedRoomContextProvider } from "../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
onClose(): void;
|
onClose(): void;
|
||||||
|
@ -79,12 +80,10 @@ export default class NotificationPanel extends React.PureComponent<IProps, IStat
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RoomContext.Provider
|
<ScopedRoomContextProvider
|
||||||
value={{
|
{...this.context}
|
||||||
...this.context,
|
timelineRenderingType={TimelineRenderingType.Notification}
|
||||||
timelineRenderingType: TimelineRenderingType.Notification,
|
narrow={this.state.narrow}
|
||||||
narrow: this.state.narrow,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<BaseCard
|
<BaseCard
|
||||||
header={_t("notifications|enable_prompt_toast_title")}
|
header={_t("notifications|enable_prompt_toast_title")}
|
||||||
|
@ -99,7 +98,7 @@ export default class NotificationPanel extends React.PureComponent<IProps, IStat
|
||||||
{this.card.current && <Measured sensor={this.card.current} onMeasurement={this.onMeasurement} />}
|
{this.card.current && <Measured sensor={this.card.current} onMeasurement={this.onMeasurement} />}
|
||||||
{content}
|
{content}
|
||||||
</BaseCard>
|
</BaseCard>
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ import ErrorDialog from "../views/dialogs/ErrorDialog";
|
||||||
import ResizeNotifier from "../../utils/ResizeNotifier";
|
import ResizeNotifier from "../../utils/ResizeNotifier";
|
||||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||||
import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
|
import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
|
||||||
import RoomContext from "../../contexts/RoomContext";
|
import { useScopedRoomContext } from "../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
const DEBUG = false;
|
const DEBUG = false;
|
||||||
let debuglog = function (msg: string): void {};
|
let debuglog = function (msg: string): void {};
|
||||||
|
@ -53,7 +53,7 @@ interface Props {
|
||||||
export const RoomSearchView = forwardRef<ScrollPanel, Props>(
|
export const RoomSearchView = forwardRef<ScrollPanel, Props>(
|
||||||
({ term, scope, promise, abortController, resizeNotifier, className, onUpdate, inProgress }: Props, ref) => {
|
({ term, scope, promise, abortController, resizeNotifier, className, onUpdate, inProgress }: Props, ref) => {
|
||||||
const client = useContext(MatrixClientContext);
|
const client = useContext(MatrixClientContext);
|
||||||
const roomContext = useContext(RoomContext);
|
const roomContext = useScopedRoomContext("showHiddenEvents");
|
||||||
const [highlights, setHighlights] = useState<string[] | null>(null);
|
const [highlights, setHighlights] = useState<string[] | null>(null);
|
||||||
const [results, setResults] = useState<ISearchResults | null>(null);
|
const [results, setResults] = useState<ISearchResults | null>(null);
|
||||||
const aborted = useRef(false);
|
const aborted = useRef(false);
|
||||||
|
|
|
@ -9,16 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, {
|
import React, { ChangeEvent, ComponentProps, createRef, ReactElement, ReactNode, RefObject, JSX } from "react";
|
||||||
ChangeEvent,
|
|
||||||
ComponentProps,
|
|
||||||
createRef,
|
|
||||||
ReactElement,
|
|
||||||
ReactNode,
|
|
||||||
RefObject,
|
|
||||||
useContext,
|
|
||||||
JSX,
|
|
||||||
} from "react";
|
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import {
|
import {
|
||||||
IRecommendedVersion,
|
IRecommendedVersion,
|
||||||
|
@ -64,7 +55,7 @@ import WidgetEchoStore from "../../stores/WidgetEchoStore";
|
||||||
import SettingsStore from "../../settings/SettingsStore";
|
import SettingsStore from "../../settings/SettingsStore";
|
||||||
import { Layout } from "../../settings/enums/Layout";
|
import { Layout } from "../../settings/enums/Layout";
|
||||||
import AccessibleButton, { ButtonEvent } from "../views/elements/AccessibleButton";
|
import AccessibleButton, { ButtonEvent } from "../views/elements/AccessibleButton";
|
||||||
import RoomContext, { TimelineRenderingType, MainSplitContentType } from "../../contexts/RoomContext";
|
import { TimelineRenderingType, MainSplitContentType } from "../../contexts/RoomContext";
|
||||||
import { E2EStatus, shieldStatusForRoom } from "../../utils/ShieldUtils";
|
import { E2EStatus, shieldStatusForRoom } from "../../utils/ShieldUtils";
|
||||||
import { Action } from "../../dispatcher/actions";
|
import { Action } from "../../dispatcher/actions";
|
||||||
import { IMatrixClientCreds } from "../../MatrixClientPeg";
|
import { IMatrixClientCreds } from "../../MatrixClientPeg";
|
||||||
|
@ -136,6 +127,7 @@ import RightPanelStore from "../../stores/right-panel/RightPanelStore";
|
||||||
import { onView3pidInvite } from "../../stores/right-panel/action-handlers";
|
import { onView3pidInvite } from "../../stores/right-panel/action-handlers";
|
||||||
import RoomSearchAuxPanel from "../views/rooms/RoomSearchAuxPanel";
|
import RoomSearchAuxPanel from "../views/rooms/RoomSearchAuxPanel";
|
||||||
import { PinnedMessageBanner } from "../views/rooms/PinnedMessageBanner";
|
import { PinnedMessageBanner } from "../views/rooms/PinnedMessageBanner";
|
||||||
|
import { ScopedRoomContextProvider, useScopedRoomContext } from "../../contexts/ScopedRoomContext";
|
||||||
|
|
||||||
const DEBUG = false;
|
const DEBUG = false;
|
||||||
const PREVENT_MULTIPLE_JITSI_WITHIN = 30_000;
|
const PREVENT_MULTIPLE_JITSI_WITHIN = 30_000;
|
||||||
|
@ -261,6 +253,7 @@ interface LocalRoomViewProps {
|
||||||
permalinkCreator: RoomPermalinkCreator;
|
permalinkCreator: RoomPermalinkCreator;
|
||||||
roomView: RefObject<HTMLElement>;
|
roomView: RefObject<HTMLElement>;
|
||||||
onFileDrop: (dataTransfer: DataTransfer) => Promise<void>;
|
onFileDrop: (dataTransfer: DataTransfer) => Promise<void>;
|
||||||
|
mainSplitContentType: MainSplitContentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -270,7 +263,7 @@ interface LocalRoomViewProps {
|
||||||
* @returns {ReactElement}
|
* @returns {ReactElement}
|
||||||
*/
|
*/
|
||||||
function LocalRoomView(props: LocalRoomViewProps): ReactElement {
|
function LocalRoomView(props: LocalRoomViewProps): ReactElement {
|
||||||
const context = useContext(RoomContext);
|
const context = useScopedRoomContext("room");
|
||||||
const room = context.room as LocalRoom;
|
const room = context.room as LocalRoom;
|
||||||
const encryptionEvent = props.localRoom.currentState.getStateEvents(EventType.RoomEncryption)[0];
|
const encryptionEvent = props.localRoom.currentState.getStateEvents(EventType.RoomEncryption)[0];
|
||||||
let encryptionTile: ReactNode;
|
let encryptionTile: ReactNode;
|
||||||
|
@ -338,6 +331,7 @@ interface ILocalRoomCreateLoaderProps {
|
||||||
localRoom: LocalRoom;
|
localRoom: LocalRoom;
|
||||||
names: string;
|
names: string;
|
||||||
resizeNotifier: ResizeNotifier;
|
resizeNotifier: ResizeNotifier;
|
||||||
|
mainSplitContentType: MainSplitContentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2007,35 +2001,41 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
||||||
if (!this.state.room || !this.context?.client) return null;
|
if (!this.state.room || !this.context?.client) return null;
|
||||||
const names = this.state.room.getDefaultRoomName(this.context.client.getSafeUserId());
|
const names = this.state.room.getDefaultRoomName(this.context.client.getSafeUserId());
|
||||||
return (
|
return (
|
||||||
<RoomContext.Provider value={this.state}>
|
<ScopedRoomContextProvider {...this.state}>
|
||||||
<LocalRoomCreateLoader localRoom={localRoom} names={names} resizeNotifier={this.props.resizeNotifier} />
|
<LocalRoomCreateLoader
|
||||||
</RoomContext.Provider>
|
localRoom={localRoom}
|
||||||
|
names={names}
|
||||||
|
resizeNotifier={this.props.resizeNotifier}
|
||||||
|
mainSplitContentType={this.state.mainSplitContentType}
|
||||||
|
/>
|
||||||
|
</ScopedRoomContextProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderLocalRoomView(localRoom: LocalRoom): ReactNode {
|
private renderLocalRoomView(localRoom: LocalRoom): ReactNode {
|
||||||
return (
|
return (
|
||||||
<RoomContext.Provider value={this.state}>
|
<ScopedRoomContextProvider {...this.state}>
|
||||||
<LocalRoomView
|
<LocalRoomView
|
||||||
localRoom={localRoom}
|
localRoom={localRoom}
|
||||||
resizeNotifier={this.props.resizeNotifier}
|
resizeNotifier={this.props.resizeNotifier}
|
||||||
permalinkCreator={this.permalinkCreator}
|
permalinkCreator={this.permalinkCreator}
|
||||||
roomView={this.roomView}
|
roomView={this.roomView}
|
||||||
onFileDrop={this.onFileDrop}
|
onFileDrop={this.onFileDrop}
|
||||||
|
mainSplitContentType={this.state.mainSplitContentType}
|
||||||
/>
|
/>
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderWaitingForThirdPartyRoomView(inviteEvent: MatrixEvent): ReactNode {
|
private renderWaitingForThirdPartyRoomView(inviteEvent: MatrixEvent): ReactNode {
|
||||||
return (
|
return (
|
||||||
<RoomContext.Provider value={this.state}>
|
<ScopedRoomContextProvider {...this.state}>
|
||||||
<WaitingForThirdPartyRoomView
|
<WaitingForThirdPartyRoomView
|
||||||
resizeNotifier={this.props.resizeNotifier}
|
resizeNotifier={this.props.resizeNotifier}
|
||||||
roomView={this.roomView}
|
roomView={this.roomView}
|
||||||
inviteEvent={inviteEvent}
|
inviteEvent={inviteEvent}
|
||||||
/>
|
/>
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2573,7 +2573,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RoomContext.Provider value={this.state}>
|
<ScopedRoomContextProvider {...this.state}>
|
||||||
<div className={mainClasses} ref={this.roomView} onKeyDown={this.onReactKeyDown}>
|
<div className={mainClasses} ref={this.roomView} onKeyDown={this.onReactKeyDown}>
|
||||||
{showChatEffects && this.roomView.current && (
|
{showChatEffects && this.roomView.current && (
|
||||||
<EffectsOverlay roomWidth={this.roomView.current.offsetWidth} />
|
<EffectsOverlay roomWidth={this.roomView.current.offsetWidth} />
|
||||||
|
@ -2600,7 +2600,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
||||||
</MainSplit>
|
</MainSplit>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</div>
|
</div>
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ import MatrixClientContext, { useMatrixClientContext } from "../../contexts/Matr
|
||||||
import { _t } from "../../languageHandler";
|
import { _t } from "../../languageHandler";
|
||||||
import { ContextMenuButton } from "../../accessibility/context_menu/ContextMenuButton";
|
import { ContextMenuButton } from "../../accessibility/context_menu/ContextMenuButton";
|
||||||
import ContextMenu, { ChevronFace, MenuItemRadio, useContextMenu } from "./ContextMenu";
|
import ContextMenu, { ChevronFace, MenuItemRadio, useContextMenu } from "./ContextMenu";
|
||||||
import RoomContext, { TimelineRenderingType, useRoomContext } from "../../contexts/RoomContext";
|
import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext";
|
||||||
import TimelinePanel from "./TimelinePanel";
|
import TimelinePanel from "./TimelinePanel";
|
||||||
import { Layout } from "../../settings/enums/Layout";
|
import { Layout } from "../../settings/enums/Layout";
|
||||||
import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
|
import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
|
||||||
|
@ -30,6 +30,7 @@ import { ButtonEvent } from "../views/elements/AccessibleButton";
|
||||||
import Spinner from "../views/elements/Spinner";
|
import Spinner from "../views/elements/Spinner";
|
||||||
import { clearRoomNotification } from "../../utils/notifications";
|
import { clearRoomNotification } from "../../utils/notifications";
|
||||||
import EmptyState from "../views/right_panel/EmptyState";
|
import EmptyState from "../views/right_panel/EmptyState";
|
||||||
|
import { ScopedRoomContextProvider, useScopedRoomContext } from "../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
roomId: string;
|
roomId: string;
|
||||||
|
@ -68,7 +69,7 @@ export const ThreadPanelHeader: React.FC<{
|
||||||
setFilterOption: (filterOption: ThreadFilterType) => void;
|
setFilterOption: (filterOption: ThreadFilterType) => void;
|
||||||
}> = ({ filterOption, setFilterOption }) => {
|
}> = ({ filterOption, setFilterOption }) => {
|
||||||
const mxClient = useMatrixClientContext();
|
const mxClient = useMatrixClientContext();
|
||||||
const roomContext = useRoomContext();
|
const roomContext = useScopedRoomContext("room");
|
||||||
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu<HTMLElement>();
|
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu<HTMLElement>();
|
||||||
const options: readonly ThreadPanelHeaderOption[] = [
|
const options: readonly ThreadPanelHeaderOption[] = [
|
||||||
{
|
{
|
||||||
|
@ -184,13 +185,11 @@ const ThreadPanel: React.FC<IProps> = ({ roomId, onClose, permalinkCreator }) =>
|
||||||
}, [timelineSet, timelinePanel]);
|
}, [timelineSet, timelinePanel]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RoomContext.Provider
|
<ScopedRoomContextProvider
|
||||||
value={{
|
{...roomContext}
|
||||||
...roomContext,
|
timelineRenderingType={TimelineRenderingType.ThreadsList}
|
||||||
timelineRenderingType: TimelineRenderingType.ThreadsList,
|
showHiddenEvents={true}
|
||||||
showHiddenEvents: true,
|
narrow={narrow}
|
||||||
narrow,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<BaseCard
|
<BaseCard
|
||||||
header={
|
header={
|
||||||
|
@ -241,7 +240,7 @@ const ThreadPanel: React.FC<IProps> = ({ roomId, onClose, permalinkCreator }) =>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</BaseCard>
|
</BaseCard>
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default ThreadPanel;
|
export default ThreadPanel;
|
||||||
|
|
|
@ -51,6 +51,7 @@ import { ComposerInsertPayload, ComposerType } from "../../dispatcher/payloads/C
|
||||||
import Heading from "../views/typography/Heading";
|
import Heading from "../views/typography/Heading";
|
||||||
import { SdkContextClass } from "../../contexts/SDKContext";
|
import { SdkContextClass } from "../../contexts/SDKContext";
|
||||||
import { ThreadPayload } from "../../dispatcher/payloads/ThreadPayload";
|
import { ThreadPayload } from "../../dispatcher/payloads/ThreadPayload";
|
||||||
|
import { ScopedRoomContextProvider } from "../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
room: Room;
|
room: Room;
|
||||||
|
@ -422,14 +423,12 @@ export default class ThreadView extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RoomContext.Provider
|
<ScopedRoomContextProvider
|
||||||
value={{
|
{...this.context}
|
||||||
...this.context,
|
timelineRenderingType={TimelineRenderingType.Thread}
|
||||||
timelineRenderingType: TimelineRenderingType.Thread,
|
threadId={this.state.thread?.id}
|
||||||
threadId: this.state.thread?.id,
|
liveTimeline={this.state?.thread?.timelineSet?.getLiveTimeline()}
|
||||||
liveTimeline: this.state?.thread?.timelineSet?.getLiveTimeline(),
|
narrow={this.state.narrow}
|
||||||
narrow: this.state.narrow,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<BaseCard
|
<BaseCard
|
||||||
className={classNames("mx_ThreadView mx_ThreadPanel", {
|
className={classNames("mx_ThreadView mx_ThreadPanel", {
|
||||||
|
@ -463,7 +462,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</BaseCard>
|
</BaseCard>
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ Please see LICENSE files in the repository root for full details.
|
||||||
import React, { RefObject } from "react";
|
import React, { RefObject } from "react";
|
||||||
import { MatrixEvent } from "matrix-js-sdk/src/matrix";
|
import { MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import { useRoomContext } from "../../contexts/RoomContext";
|
|
||||||
import ResizeNotifier from "../../utils/ResizeNotifier";
|
import ResizeNotifier from "../../utils/ResizeNotifier";
|
||||||
import ErrorBoundary from "../views/elements/ErrorBoundary";
|
import ErrorBoundary from "../views/elements/ErrorBoundary";
|
||||||
import RoomHeader from "../views/rooms/RoomHeader";
|
import RoomHeader from "../views/rooms/RoomHeader";
|
||||||
|
@ -19,6 +18,7 @@ import NewRoomIntro from "../views/rooms/NewRoomIntro";
|
||||||
import { UnwrappedEventTile } from "../views/rooms/EventTile";
|
import { UnwrappedEventTile } from "../views/rooms/EventTile";
|
||||||
import { _t } from "../../languageHandler";
|
import { _t } from "../../languageHandler";
|
||||||
import SdkConfig from "../../SdkConfig";
|
import SdkConfig from "../../SdkConfig";
|
||||||
|
import { useScopedRoomContext } from "../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
roomView: RefObject<HTMLElement>;
|
roomView: RefObject<HTMLElement>;
|
||||||
|
@ -32,7 +32,7 @@ interface Props {
|
||||||
* To avoid UTDs, users are shown a waiting room until the others have joined.
|
* To avoid UTDs, users are shown a waiting room until the others have joined.
|
||||||
*/
|
*/
|
||||||
export const WaitingForThirdPartyRoomView: React.FC<Props> = ({ roomView, resizeNotifier, inviteEvent }) => {
|
export const WaitingForThirdPartyRoomView: React.FC<Props> = ({ roomView, resizeNotifier, inviteEvent }) => {
|
||||||
const context = useRoomContext();
|
const context = useScopedRoomContext("room");
|
||||||
const brand = SdkConfig.get().brand;
|
const brand = SdkConfig.get().brand;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -16,10 +16,10 @@ import { Avatar } from "@vector-im/compound-web";
|
||||||
|
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import { ButtonEvent } from "../elements/AccessibleButton";
|
import { ButtonEvent } from "../elements/AccessibleButton";
|
||||||
import RoomContext from "../../../contexts/RoomContext";
|
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||||
import { useTypedEventEmitter } from "../../../hooks/useEventEmitter";
|
import { useTypedEventEmitter } from "../../../hooks/useEventEmitter";
|
||||||
import { _t } from "../../../languageHandler";
|
import { _t } from "../../../languageHandler";
|
||||||
|
import { useScopedRoomContext } from "../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
name?: React.ComponentProps<typeof Avatar>["name"]; // The name (first initial used as default)
|
name?: React.ComponentProps<typeof Avatar>["name"]; // The name (first initial used as default)
|
||||||
|
@ -57,8 +57,8 @@ const calculateUrls = (url?: string | null, urls?: string[], lowBandwidth = fals
|
||||||
const useImageUrl = ({ url, urls }: { url?: string | null; urls?: string[] }): [string, () => void] => {
|
const useImageUrl = ({ url, urls }: { url?: string | null; urls?: string[] }): [string, () => void] => {
|
||||||
// Since this is a hot code path and the settings store can be slow, we
|
// Since this is a hot code path and the settings store can be slow, we
|
||||||
// use the cached lowBandwidth value from the room context if it exists
|
// use the cached lowBandwidth value from the room context if it exists
|
||||||
const roomContext = useContext(RoomContext);
|
const roomContext = useScopedRoomContext("lowBandwidth");
|
||||||
const lowBandwidth = roomContext ? roomContext.lowBandwidth : SettingsStore.getValue("lowBandwidth");
|
const lowBandwidth = roomContext?.lowBandwidth ?? SettingsStore.getValue("lowBandwidth");
|
||||||
|
|
||||||
const [imageUrls, setUrls] = useState<string[]>(calculateUrls(url, urls, lowBandwidth));
|
const [imageUrls, setUrls] = useState<string[]>(calculateUrls(url, urls, lowBandwidth));
|
||||||
const [urlsIndex, setIndex] = useState<number>(0);
|
const [urlsIndex, setIndex] = useState<number>(0);
|
||||||
|
|
|
@ -18,7 +18,6 @@ import { _t } from "../../../languageHandler";
|
||||||
import { isAppWidget } from "../../../stores/WidgetStore";
|
import { isAppWidget } from "../../../stores/WidgetStore";
|
||||||
import WidgetUtils from "../../../utils/WidgetUtils";
|
import WidgetUtils from "../../../utils/WidgetUtils";
|
||||||
import { WidgetMessagingStore } from "../../../stores/widgets/WidgetMessagingStore";
|
import { WidgetMessagingStore } from "../../../stores/widgets/WidgetMessagingStore";
|
||||||
import RoomContext from "../../../contexts/RoomContext";
|
|
||||||
import dis from "../../../dispatcher/dispatcher";
|
import dis from "../../../dispatcher/dispatcher";
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import Modal from "../../../Modal";
|
import Modal from "../../../Modal";
|
||||||
|
@ -30,6 +29,7 @@ import { Container, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayo
|
||||||
import { getConfigLivestreamUrl, startJitsiAudioLivestream } from "../../../Livestream";
|
import { getConfigLivestreamUrl, startJitsiAudioLivestream } from "../../../Livestream";
|
||||||
import { ModuleRunner } from "../../../modules/ModuleRunner";
|
import { ModuleRunner } from "../../../modules/ModuleRunner";
|
||||||
import { ElementWidget } from "../../../stores/widgets/StopGapWidget";
|
import { ElementWidget } from "../../../stores/widgets/StopGapWidget";
|
||||||
|
import { useScopedRoomContext } from "../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
interface IProps extends Omit<ComponentProps<typeof IconizedContextMenu>, "children"> {
|
interface IProps extends Omit<ComponentProps<typeof IconizedContextMenu>, "children"> {
|
||||||
app: IWidget;
|
app: IWidget;
|
||||||
|
@ -114,7 +114,7 @@ export const WidgetContextMenu: React.FC<IProps> = ({
|
||||||
...props
|
...props
|
||||||
}) => {
|
}) => {
|
||||||
const cli = useContext(MatrixClientContext);
|
const cli = useContext(MatrixClientContext);
|
||||||
const { room, roomId } = useContext(RoomContext);
|
const { room, roomId } = useScopedRoomContext("room", "roomId");
|
||||||
|
|
||||||
const widgetMessaging = WidgetMessagingStore.instance.getMessagingForUid(WidgetUtils.getWidgetUid(app));
|
const widgetMessaging = WidgetMessagingStore.instance.getMessagingForUid(WidgetUtils.getWidgetUid(app));
|
||||||
const canModify = userWidget || WidgetUtils.canUserModifyWidgets(cli, roomId);
|
const canModify = userWidget || WidgetUtils.canUserModifyWidgets(cli, roomId);
|
||||||
|
|
|
@ -12,12 +12,12 @@ import React, { useContext, useRef, useState, MouseEvent, ReactNode } from "reac
|
||||||
import { Tooltip } from "@vector-im/compound-web";
|
import { Tooltip } from "@vector-im/compound-web";
|
||||||
|
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||||
import RoomContext from "../../../contexts/RoomContext";
|
|
||||||
import { useTimeout } from "../../../hooks/useTimeout";
|
import { useTimeout } from "../../../hooks/useTimeout";
|
||||||
import { chromeFileInputFix } from "../../../utils/BrowserWorkarounds";
|
import { chromeFileInputFix } from "../../../utils/BrowserWorkarounds";
|
||||||
import AccessibleButton from "./AccessibleButton";
|
import AccessibleButton from "./AccessibleButton";
|
||||||
import Spinner from "./Spinner";
|
import Spinner from "./Spinner";
|
||||||
import { getFileChanged } from "../settings/AvatarSetting.tsx";
|
import { getFileChanged } from "../settings/AvatarSetting.tsx";
|
||||||
|
import { useScopedRoomContext } from "../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
export const AVATAR_SIZE = "52px";
|
export const AVATAR_SIZE = "52px";
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ const MiniAvatarUploader: React.FC<IProps> = ({
|
||||||
|
|
||||||
const label = hasAvatar || busy ? hasAvatarLabel : noAvatarLabel;
|
const label = hasAvatar || busy ? hasAvatarLabel : noAvatarLabel;
|
||||||
|
|
||||||
const { room } = useContext(RoomContext);
|
const { room } = useScopedRoomContext("room");
|
||||||
const canSetAvatar =
|
const canSetAvatar =
|
||||||
isUserAvatar || room?.currentState?.maySendStateEvent(EventType.RoomAvatar, cli.getSafeUserId());
|
isUserAvatar || room?.currentState?.maySendStateEvent(EventType.RoomAvatar, cli.getSafeUserId());
|
||||||
if (!canSetAvatar) return <React.Fragment>{children}</React.Fragment>;
|
if (!canSetAvatar) return <React.Fragment>{children}</React.Fragment>;
|
||||||
|
|
|
@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useCallback, useContext } from "react";
|
import React, { useCallback } from "react";
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
import { MatrixEvent, Room, RoomState } from "matrix-js-sdk/src/matrix";
|
import { MatrixEvent, Room, RoomState } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
|
@ -18,10 +18,10 @@ import { _t } from "../../../languageHandler";
|
||||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||||
import EventTileBubble from "./EventTileBubble";
|
import EventTileBubble from "./EventTileBubble";
|
||||||
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
||||||
import RoomContext from "../../../contexts/RoomContext";
|
|
||||||
import { useRoomState } from "../../../hooks/useRoomState";
|
import { useRoomState } from "../../../hooks/useRoomState";
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import MatrixToPermalinkConstructor from "../../../utils/permalinks/MatrixToPermalinkConstructor";
|
import MatrixToPermalinkConstructor from "../../../utils/permalinks/MatrixToPermalinkConstructor";
|
||||||
|
import { useScopedRoomContext } from "../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
/** The m.room.create MatrixEvent that this tile represents */
|
/** The m.room.create MatrixEvent that this tile represents */
|
||||||
|
@ -40,7 +40,7 @@ export const RoomPredecessorTile: React.FC<IProps> = ({ mxEvent, timestamp }) =>
|
||||||
// the information inside mxEvent. This allows us the flexibility later to
|
// the information inside mxEvent. This allows us the flexibility later to
|
||||||
// use a different predecessor (e.g. through MSC3946) and still display it
|
// use a different predecessor (e.g. through MSC3946) and still display it
|
||||||
// in the timeline location of the create event.
|
// in the timeline location of the create event.
|
||||||
const roomContext = useContext(RoomContext);
|
const roomContext = useScopedRoomContext("room");
|
||||||
const predecessor = useRoomState(
|
const predecessor = useRoomState(
|
||||||
roomContext.room,
|
roomContext.room,
|
||||||
useCallback(
|
useCallback(
|
||||||
|
|
|
@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useCallback, useEffect, JSX } from "react";
|
import React, { useCallback, useEffect, JSX, useContext } from "react";
|
||||||
import { Room, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
import { Room, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||||
import { Button, Separator } from "@vector-im/compound-web";
|
import { Button, Separator } from "@vector-im/compound-web";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
@ -18,7 +18,7 @@ import Spinner from "../elements/Spinner";
|
||||||
import { useMatrixClientContext } from "../../../contexts/MatrixClientContext";
|
import { useMatrixClientContext } from "../../../contexts/MatrixClientContext";
|
||||||
import { PinnedEventTile } from "../rooms/PinnedEventTile";
|
import { PinnedEventTile } from "../rooms/PinnedEventTile";
|
||||||
import { useRoomState } from "../../../hooks/useRoomState";
|
import { useRoomState } from "../../../hooks/useRoomState";
|
||||||
import RoomContext, { TimelineRenderingType, useRoomContext } from "../../../contexts/RoomContext";
|
import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContext";
|
||||||
import { ReadPinsEventId } from "./types";
|
import { ReadPinsEventId } from "./types";
|
||||||
import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
|
import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
|
||||||
import { filterBoolean } from "../../../utils/arrays";
|
import { filterBoolean } from "../../../utils/arrays";
|
||||||
|
@ -27,6 +27,7 @@ import { UnpinAllDialog } from "../dialogs/UnpinAllDialog";
|
||||||
import EmptyState from "./EmptyState";
|
import EmptyState from "./EmptyState";
|
||||||
import { usePinnedEvents, useReadPinnedEvents, useSortedFetchedPinnedEvents } from "../../../hooks/usePinnedEvents";
|
import { usePinnedEvents, useReadPinnedEvents, useSortedFetchedPinnedEvents } from "../../../hooks/usePinnedEvents";
|
||||||
import PinningUtils from "../../../utils/PinningUtils.ts";
|
import PinningUtils from "../../../utils/PinningUtils.ts";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List the pinned messages in a room inside a Card.
|
* List the pinned messages in a room inside a Card.
|
||||||
|
@ -48,7 +49,7 @@ interface PinnedMessagesCardProps {
|
||||||
|
|
||||||
export function PinnedMessagesCard({ room, onClose, permalinkCreator }: PinnedMessagesCardProps): JSX.Element {
|
export function PinnedMessagesCard({ room, onClose, permalinkCreator }: PinnedMessagesCardProps): JSX.Element {
|
||||||
const cli = useMatrixClientContext();
|
const cli = useMatrixClientContext();
|
||||||
const roomContext = useRoomContext();
|
const roomContext = useContext(RoomContext);
|
||||||
const pinnedEventIds = usePinnedEvents(room);
|
const pinnedEventIds = usePinnedEvents(room);
|
||||||
const readPinnedEvents = useReadPinnedEvents(room);
|
const readPinnedEvents = useReadPinnedEvents(room);
|
||||||
const pinnedEvents = useSortedFetchedPinnedEvents(room, pinnedEventIds);
|
const pinnedEvents = useSortedFetchedPinnedEvents(room, pinnedEventIds);
|
||||||
|
@ -89,14 +90,9 @@ export function PinnedMessagesCard({ room, onClose, permalinkCreator }: PinnedMe
|
||||||
className="mx_PinnedMessagesCard"
|
className="mx_PinnedMessagesCard"
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
>
|
>
|
||||||
<RoomContext.Provider
|
<ScopedRoomContextProvider {...roomContext} timelineRenderingType={TimelineRenderingType.Pinned}>
|
||||||
value={{
|
|
||||||
...roomContext,
|
|
||||||
timelineRenderingType: TimelineRenderingType.Pinned,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{content}
|
{content}
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
</BaseCard>
|
</BaseCard>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ import ShareDialog from "../dialogs/ShareDialog";
|
||||||
import { useEventEmitterState } from "../../../hooks/useEventEmitter";
|
import { useEventEmitterState } from "../../../hooks/useEventEmitter";
|
||||||
import { E2EStatus } from "../../../utils/ShieldUtils";
|
import { E2EStatus } from "../../../utils/ShieldUtils";
|
||||||
import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
|
import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
|
||||||
import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContext";
|
import { TimelineRenderingType } from "../../../contexts/RoomContext";
|
||||||
import RoomName from "../elements/RoomName";
|
import RoomName from "../elements/RoomName";
|
||||||
import ExportDialog from "../dialogs/ExportDialog";
|
import ExportDialog from "../dialogs/ExportDialog";
|
||||||
import RightPanelStore from "../../../stores/right-panel/RightPanelStore";
|
import RightPanelStore from "../../../stores/right-panel/RightPanelStore";
|
||||||
|
@ -76,6 +76,7 @@ import { useTransition } from "../../../hooks/useTransition";
|
||||||
import { isVideoRoom as calcIsVideoRoom } from "../../../utils/video-rooms";
|
import { isVideoRoom as calcIsVideoRoom } from "../../../utils/video-rooms";
|
||||||
import { usePinnedEvents } from "../../../hooks/usePinnedEvents";
|
import { usePinnedEvents } from "../../../hooks/usePinnedEvents";
|
||||||
import { ReleaseAnnouncement } from "../../structures/ReleaseAnnouncement.tsx";
|
import { ReleaseAnnouncement } from "../../structures/ReleaseAnnouncement.tsx";
|
||||||
|
import { useScopedRoomContext } from "../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
room: Room;
|
room: Room;
|
||||||
|
@ -232,7 +233,7 @@ const RoomSummaryCard: React.FC<IProps> = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
const isRoomEncrypted = useIsEncrypted(cli, room);
|
const isRoomEncrypted = useIsEncrypted(cli, room);
|
||||||
const roomContext = useContext(RoomContext);
|
const roomContext = useScopedRoomContext("e2eStatus", "timelineRenderingType");
|
||||||
const e2eStatus = roomContext.e2eStatus;
|
const e2eStatus = roomContext.e2eStatus;
|
||||||
const isVideoRoom = calcIsVideoRoom(room);
|
const isVideoRoom = calcIsVideoRoom(room);
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
||||||
import Measured from "../elements/Measured";
|
import Measured from "../elements/Measured";
|
||||||
import { UPDATE_EVENT } from "../../../stores/AsyncStore";
|
import { UPDATE_EVENT } from "../../../stores/AsyncStore";
|
||||||
import { SdkContextClass } from "../../../contexts/SDKContext";
|
import { SdkContextClass } from "../../../contexts/SDKContext";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
room: Room;
|
room: Room;
|
||||||
|
@ -199,13 +200,11 @@ export default class TimelineCard extends React.Component<IProps, IState> {
|
||||||
const showComposer = myMembership === KnownMembership.Join;
|
const showComposer = myMembership === KnownMembership.Join;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RoomContext.Provider
|
<ScopedRoomContextProvider
|
||||||
value={{
|
{...this.context}
|
||||||
...this.context,
|
timelineRenderingType={this.props.timelineRenderingType ?? this.context.timelineRenderingType}
|
||||||
timelineRenderingType: this.props.timelineRenderingType ?? this.context.timelineRenderingType,
|
liveTimeline={this.props.timelineSet?.getLiveTimeline()}
|
||||||
liveTimeline: this.props.timelineSet?.getLiveTimeline(),
|
narrow={this.state.narrow}
|
||||||
narrow: this.state.narrow,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<BaseCard
|
<BaseCard
|
||||||
className={this.props.classNames}
|
className={this.props.classNames}
|
||||||
|
@ -255,7 +254,7 @@ export default class TimelineCard extends React.Component<IProps, IState> {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</BaseCard>
|
</BaseCard>
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,15 +6,15 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useContext } from "react";
|
import React from "react";
|
||||||
import { EventTimeline } from "matrix-js-sdk/src/matrix";
|
import { EventTimeline } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import EventTileBubble from "../messages/EventTileBubble";
|
import EventTileBubble from "../messages/EventTileBubble";
|
||||||
import RoomContext from "../../../contexts/RoomContext";
|
|
||||||
import { _t } from "../../../languageHandler";
|
import { _t } from "../../../languageHandler";
|
||||||
|
import { useScopedRoomContext } from "../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
const HistoryTile: React.FC = () => {
|
const HistoryTile: React.FC = () => {
|
||||||
const { room } = useContext(RoomContext);
|
const { room } = useScopedRoomContext("room");
|
||||||
|
|
||||||
const oldState = room?.getLiveTimeline().getState(EventTimeline.BACKWARDS);
|
const oldState = room?.getLiveTimeline().getState(EventTimeline.BACKWARDS);
|
||||||
const historyState = oldState?.getStateEvents("m.room.history_visibility")[0]?.getContent().history_visibility;
|
const historyState = oldState?.getStateEvents("m.room.history_visibility")[0]?.getContent().history_visibility;
|
||||||
|
|
|
@ -21,7 +21,6 @@ import PollCreateDialog from "../elements/PollCreateDialog";
|
||||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||||
import ContentMessages from "../../../ContentMessages";
|
import ContentMessages from "../../../ContentMessages";
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||||
import RoomContext from "../../../contexts/RoomContext";
|
|
||||||
import { useDispatcher } from "../../../hooks/useDispatcher";
|
import { useDispatcher } from "../../../hooks/useDispatcher";
|
||||||
import { chromeFileInputFix } from "../../../utils/BrowserWorkarounds";
|
import { chromeFileInputFix } from "../../../utils/BrowserWorkarounds";
|
||||||
import IconizedContextMenu, { IconizedContextMenuOptionList } from "../context_menus/IconizedContextMenu";
|
import IconizedContextMenu, { IconizedContextMenuOptionList } from "../context_menus/IconizedContextMenu";
|
||||||
|
@ -29,6 +28,7 @@ import { EmojiButton } from "./EmojiButton";
|
||||||
import { filterBoolean } from "../../../utils/arrays";
|
import { filterBoolean } from "../../../utils/arrays";
|
||||||
import { useSettingValue } from "../../../hooks/useSettings";
|
import { useSettingValue } from "../../../hooks/useSettings";
|
||||||
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
|
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
|
||||||
|
import { useScopedRoomContext } from "../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
addEmoji: (emoji: string) => boolean;
|
addEmoji: (emoji: string) => boolean;
|
||||||
|
@ -54,7 +54,7 @@ export const OverflowMenuContext = createContext<OverflowMenuCloser | null>(null
|
||||||
|
|
||||||
const MessageComposerButtons: React.FC<IProps> = (props: IProps) => {
|
const MessageComposerButtons: React.FC<IProps> = (props: IProps) => {
|
||||||
const matrixClient = useContext(MatrixClientContext);
|
const matrixClient = useContext(MatrixClientContext);
|
||||||
const { room, narrow } = useContext(RoomContext);
|
const { room, narrow } = useScopedRoomContext("room", "narrow");
|
||||||
|
|
||||||
const isWysiwygLabEnabled = useSettingValue<boolean>("feature_wysiwyg_composer");
|
const isWysiwygLabEnabled = useSettingValue<boolean>("feature_wysiwyg_composer");
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ interface IUploadButtonProps {
|
||||||
// We put the file input outside the UploadButton component so that it doesn't get killed when the context menu closes.
|
// We put the file input outside the UploadButton component so that it doesn't get killed when the context menu closes.
|
||||||
const UploadButtonContextProvider: React.FC<IUploadButtonProps> = ({ roomId, relation, children }) => {
|
const UploadButtonContextProvider: React.FC<IUploadButtonProps> = ({ roomId, relation, children }) => {
|
||||||
const cli = useContext(MatrixClientContext);
|
const cli = useContext(MatrixClientContext);
|
||||||
const roomContext = useContext(RoomContext);
|
const roomContext = useScopedRoomContext("timelineRenderingType");
|
||||||
const uploadInput = useRef<HTMLInputElement>(null);
|
const uploadInput = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
const onUploadClick = (): void => {
|
const onUploadClick = (): void => {
|
||||||
|
|
|
@ -11,7 +11,6 @@ import { EventType, Room, User, MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||||
|
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||||
import RoomContext from "../../../contexts/RoomContext";
|
|
||||||
import DMRoomMap from "../../../utils/DMRoomMap";
|
import DMRoomMap from "../../../utils/DMRoomMap";
|
||||||
import { _t, _td, TranslationKey } from "../../../languageHandler";
|
import { _t, _td, TranslationKey } from "../../../languageHandler";
|
||||||
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
|
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
|
||||||
|
@ -30,6 +29,7 @@ import { UIComponent } from "../../../settings/UIFeature";
|
||||||
import { privateShouldBeEncrypted } from "../../../utils/rooms";
|
import { privateShouldBeEncrypted } from "../../../utils/rooms";
|
||||||
import { LocalRoom } from "../../../models/LocalRoom";
|
import { LocalRoom } from "../../../models/LocalRoom";
|
||||||
import { shouldEncryptRoomWithSingle3rdPartyInvite } from "../../../utils/room/shouldEncryptRoomWithSingle3rdPartyInvite";
|
import { shouldEncryptRoomWithSingle3rdPartyInvite } from "../../../utils/room/shouldEncryptRoomWithSingle3rdPartyInvite";
|
||||||
|
import { useScopedRoomContext } from "../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
function hasExpectedEncryptionSettings(matrixClient: MatrixClient, room: Room): boolean {
|
function hasExpectedEncryptionSettings(matrixClient: MatrixClient, room: Room): boolean {
|
||||||
const isEncrypted: boolean = matrixClient.isRoomEncrypted(room.roomId);
|
const isEncrypted: boolean = matrixClient.isRoomEncrypted(room.roomId);
|
||||||
|
@ -51,7 +51,7 @@ const determineIntroMessage = (room: Room, encryptedSingle3rdPartyInvite: boolea
|
||||||
|
|
||||||
const NewRoomIntro: React.FC = () => {
|
const NewRoomIntro: React.FC = () => {
|
||||||
const cli = useContext(MatrixClientContext);
|
const cli = useContext(MatrixClientContext);
|
||||||
const { room, roomId } = useContext(RoomContext);
|
const { room, roomId } = useScopedRoomContext("room", "roomId");
|
||||||
|
|
||||||
if (!room || !roomId) {
|
if (!room || !roomId) {
|
||||||
throw new Error("Unable to create a NewRoomIntro without room and roomId");
|
throw new Error("Unable to create a NewRoomIntro without room and roomId");
|
||||||
|
|
|
@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useCallback, useContext, useMemo, useState } from "react";
|
import React, { useCallback, useMemo, useState } from "react";
|
||||||
import { Body as BodyText, Button, IconButton, Menu, MenuItem, Tooltip } from "@vector-im/compound-web";
|
import { Body as BodyText, Button, IconButton, Menu, MenuItem, Tooltip } from "@vector-im/compound-web";
|
||||||
import VideoCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/video-call-solid";
|
import VideoCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/video-call-solid";
|
||||||
import VoiceCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/voice-call";
|
import VoiceCallIcon from "@vector-im/compound-design-tokens/assets/web/icons/voice-call";
|
||||||
|
@ -48,10 +48,10 @@ import { CallGuestLinkButton } from "./RoomHeader/CallGuestLinkButton";
|
||||||
import { ButtonEvent } from "../elements/AccessibleButton";
|
import { ButtonEvent } from "../elements/AccessibleButton";
|
||||||
import WithPresenceIndicator, { useDmMember } from "../avatars/WithPresenceIndicator";
|
import WithPresenceIndicator, { useDmMember } from "../avatars/WithPresenceIndicator";
|
||||||
import { IOOBData } from "../../../stores/ThreepidInviteStore";
|
import { IOOBData } from "../../../stores/ThreepidInviteStore";
|
||||||
import RoomContext from "../../../contexts/RoomContext";
|
|
||||||
import { MainSplitContentType } from "../../structures/RoomView";
|
import { MainSplitContentType } from "../../structures/RoomView";
|
||||||
import defaultDispatcher from "../../../dispatcher/dispatcher.ts";
|
import defaultDispatcher from "../../../dispatcher/dispatcher.ts";
|
||||||
import { RoomSettingsTab } from "../dialogs/RoomSettingsDialog.tsx";
|
import { RoomSettingsTab } from "../dialogs/RoomSettingsDialog.tsx";
|
||||||
|
import { useScopedRoomContext } from "../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
export default function RoomHeader({
|
export default function RoomHeader({
|
||||||
room,
|
room,
|
||||||
|
@ -229,7 +229,7 @@ export default function RoomHeader({
|
||||||
voiceCallButton = undefined;
|
voiceCallButton = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const roomContext = useContext(RoomContext);
|
const roomContext = useScopedRoomContext("mainSplitContentType");
|
||||||
const isVideoRoom = calcIsVideoRoom(room);
|
const isVideoRoom = calcIsVideoRoom(room);
|
||||||
const showChatButton =
|
const showChatButton =
|
||||||
isVideoRoom ||
|
isVideoRoom ||
|
||||||
|
|
|
@ -16,7 +16,6 @@ import { CardContext } from "../right_panel/context";
|
||||||
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
|
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
|
||||||
import PosthogTrackers from "../../../PosthogTrackers";
|
import PosthogTrackers from "../../../PosthogTrackers";
|
||||||
import { useTypedEventEmitterState } from "../../../hooks/useEventEmitter";
|
import { useTypedEventEmitterState } from "../../../hooks/useEventEmitter";
|
||||||
import RoomContext from "../../../contexts/RoomContext";
|
|
||||||
import MemberAvatar from "../avatars/MemberAvatar";
|
import MemberAvatar from "../avatars/MemberAvatar";
|
||||||
import { Action } from "../../../dispatcher/actions";
|
import { Action } from "../../../dispatcher/actions";
|
||||||
import { ShowThreadPayload } from "../../../dispatcher/payloads/ShowThreadPayload";
|
import { ShowThreadPayload } from "../../../dispatcher/payloads/ShowThreadPayload";
|
||||||
|
@ -24,6 +23,7 @@ import defaultDispatcher from "../../../dispatcher/dispatcher";
|
||||||
import { useUnreadNotifications } from "../../../hooks/useUnreadNotifications";
|
import { useUnreadNotifications } from "../../../hooks/useUnreadNotifications";
|
||||||
import { notificationLevelToIndicator } from "../../../utils/notifications";
|
import { notificationLevelToIndicator } from "../../../utils/notifications";
|
||||||
import { EventPreviewTile, useEventPreview } from "./EventPreview.tsx";
|
import { EventPreviewTile, useEventPreview } from "./EventPreview.tsx";
|
||||||
|
import { useScopedRoomContext } from "../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
mxEvent: MatrixEvent;
|
mxEvent: MatrixEvent;
|
||||||
|
@ -31,7 +31,7 @@ interface IProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ThreadSummary: React.FC<IProps> = ({ mxEvent, thread, ...props }) => {
|
const ThreadSummary: React.FC<IProps> = ({ mxEvent, thread, ...props }) => {
|
||||||
const roomContext = useContext(RoomContext);
|
const roomContext = useScopedRoomContext("narrow");
|
||||||
const cardContext = useContext(CardContext);
|
const cardContext = useContext(CardContext);
|
||||||
const count = useTypedEventEmitterState(thread, ThreadEvent.Update, () => thread.length);
|
const count = useTypedEventEmitterState(thread, ThreadEvent.Update, () => thread.length);
|
||||||
const { level } = useUnreadNotifications(thread.room, thread.id);
|
const { level } = useUnreadNotifications(thread.room, thread.id);
|
||||||
|
|
|
@ -13,14 +13,14 @@ import { EmojiButton } from "../../EmojiButton";
|
||||||
import dis from "../../../../../dispatcher/dispatcher";
|
import dis from "../../../../../dispatcher/dispatcher";
|
||||||
import { ComposerInsertPayload } from "../../../../../dispatcher/payloads/ComposerInsertPayload";
|
import { ComposerInsertPayload } from "../../../../../dispatcher/payloads/ComposerInsertPayload";
|
||||||
import { Action } from "../../../../../dispatcher/actions";
|
import { Action } from "../../../../../dispatcher/actions";
|
||||||
import { useRoomContext } from "../../../../../contexts/RoomContext";
|
import { useScopedRoomContext } from "../../../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
interface EmojiProps {
|
interface EmojiProps {
|
||||||
menuPosition: MenuProps;
|
menuPosition: MenuProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Emoji({ menuPosition }: EmojiProps): JSX.Element {
|
export function Emoji({ menuPosition }: EmojiProps): JSX.Element {
|
||||||
const roomContext = useRoomContext();
|
const roomContext = useScopedRoomContext("timelineRenderingType");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EmojiButton
|
<EmojiButton
|
||||||
|
|
|
@ -10,11 +10,11 @@ import React, { ForwardedRef, forwardRef, FunctionComponent } from "react";
|
||||||
import { FormattingFunctions, MappedSuggestion } from "@vector-im/matrix-wysiwyg";
|
import { FormattingFunctions, MappedSuggestion } from "@vector-im/matrix-wysiwyg";
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
||||||
import { useRoomContext } from "../../../../../contexts/RoomContext";
|
|
||||||
import Autocomplete from "../../Autocomplete";
|
import Autocomplete from "../../Autocomplete";
|
||||||
import { ICompletion } from "../../../../../autocomplete/Autocompleter";
|
import { ICompletion } from "../../../../../autocomplete/Autocompleter";
|
||||||
import { useMatrixClientContext } from "../../../../../contexts/MatrixClientContext";
|
import { useMatrixClientContext } from "../../../../../contexts/MatrixClientContext";
|
||||||
import { getMentionDisplayText, getMentionAttributes, buildQuery } from "../utils/autocomplete";
|
import { getMentionDisplayText, getMentionAttributes, buildQuery } from "../utils/autocomplete";
|
||||||
|
import { useScopedRoomContext } from "../../../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
interface WysiwygAutocompleteProps {
|
interface WysiwygAutocompleteProps {
|
||||||
/**
|
/**
|
||||||
|
@ -53,7 +53,7 @@ const WysiwygAutocomplete = forwardRef(
|
||||||
{ suggestion, handleMention, handleCommand, handleAtRoomMention }: WysiwygAutocompleteProps,
|
{ suggestion, handleMention, handleCommand, handleAtRoomMention }: WysiwygAutocompleteProps,
|
||||||
ref: ForwardedRef<Autocomplete>,
|
ref: ForwardedRef<Autocomplete>,
|
||||||
): JSX.Element | null => {
|
): JSX.Element | null => {
|
||||||
const { room } = useRoomContext();
|
const { room } = useScopedRoomContext("room");
|
||||||
const client = useMatrixClientContext();
|
const client = useMatrixClientContext();
|
||||||
|
|
||||||
function handleConfirm(completion: ICompletion): void {
|
function handleConfirm(completion: ICompletion): void {
|
||||||
|
|
|
@ -19,12 +19,12 @@ import { Editor } from "./Editor";
|
||||||
import { useInputEventProcessor } from "../hooks/useInputEventProcessor";
|
import { useInputEventProcessor } from "../hooks/useInputEventProcessor";
|
||||||
import { useSetCursorPosition } from "../hooks/useSetCursorPosition";
|
import { useSetCursorPosition } from "../hooks/useSetCursorPosition";
|
||||||
import { useIsFocused } from "../hooks/useIsFocused";
|
import { useIsFocused } from "../hooks/useIsFocused";
|
||||||
import { useRoomContext } from "../../../../../contexts/RoomContext";
|
|
||||||
import defaultDispatcher from "../../../../../dispatcher/dispatcher";
|
import defaultDispatcher from "../../../../../dispatcher/dispatcher";
|
||||||
import { Action } from "../../../../../dispatcher/actions";
|
import { Action } from "../../../../../dispatcher/actions";
|
||||||
import { parsePermalink } from "../../../../../utils/permalinks/Permalinks";
|
import { parsePermalink } from "../../../../../utils/permalinks/Permalinks";
|
||||||
import { isNotNull } from "../../../../../Typeguards";
|
import { isNotNull } from "../../../../../Typeguards";
|
||||||
import { useSettingValue } from "../../../../../hooks/useSettings";
|
import { useSettingValue } from "../../../../../hooks/useSettings";
|
||||||
|
import { useScopedRoomContext } from "../../../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
interface WysiwygComposerProps {
|
interface WysiwygComposerProps {
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
@ -56,7 +56,7 @@ export const WysiwygComposer = memo(function WysiwygComposer({
|
||||||
children,
|
children,
|
||||||
eventRelation,
|
eventRelation,
|
||||||
}: WysiwygComposerProps) {
|
}: WysiwygComposerProps) {
|
||||||
const { room } = useRoomContext();
|
const { room } = useScopedRoomContext("room");
|
||||||
const autocompleteRef = useRef<Autocomplete | null>(null);
|
const autocompleteRef = useRef<Autocomplete | null>(null);
|
||||||
|
|
||||||
const inputEventProcessor = useInputEventProcessor(onSend, autocompleteRef, initialContent, eventRelation);
|
const inputEventProcessor = useInputEventProcessor(onSend, autocompleteRef, initialContent, eventRelation);
|
||||||
|
|
|
@ -10,10 +10,10 @@ import { ISendEventResponse } from "matrix-js-sdk/src/matrix";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
import { useMatrixClientContext } from "../../../../../contexts/MatrixClientContext";
|
import { useMatrixClientContext } from "../../../../../contexts/MatrixClientContext";
|
||||||
import { useRoomContext } from "../../../../../contexts/RoomContext";
|
|
||||||
import EditorStateTransfer from "../../../../../utils/EditorStateTransfer";
|
import EditorStateTransfer from "../../../../../utils/EditorStateTransfer";
|
||||||
import { endEditing } from "../utils/editing";
|
import { endEditing } from "../utils/editing";
|
||||||
import { editMessage } from "../utils/message";
|
import { editMessage } from "../utils/message";
|
||||||
|
import { useScopedRoomContext } from "../../../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
export function useEditing(
|
export function useEditing(
|
||||||
editorStateTransfer: EditorStateTransfer,
|
editorStateTransfer: EditorStateTransfer,
|
||||||
|
@ -24,7 +24,7 @@ export function useEditing(
|
||||||
editMessage(): Promise<ISendEventResponse | undefined>;
|
editMessage(): Promise<ISendEventResponse | undefined>;
|
||||||
endEditing(): void;
|
endEditing(): void;
|
||||||
} {
|
} {
|
||||||
const roomContext = useRoomContext();
|
const roomContext = useScopedRoomContext("timelineRenderingType");
|
||||||
const mxClient = useMatrixClientContext();
|
const mxClient = useMatrixClientContext();
|
||||||
|
|
||||||
const [isSaveDisabled, setIsSaveDisabled] = useState(true);
|
const [isSaveDisabled, setIsSaveDisabled] = useState(true);
|
||||||
|
|
|
@ -10,11 +10,11 @@ import { MatrixClient, Room } from "matrix-js-sdk/src/matrix";
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
|
|
||||||
import { useMatrixClientContext } from "../../../../../contexts/MatrixClientContext";
|
import { useMatrixClientContext } from "../../../../../contexts/MatrixClientContext";
|
||||||
import { useRoomContext } from "../../../../../contexts/RoomContext";
|
|
||||||
import { parseEvent } from "../../../../../editor/deserialize";
|
import { parseEvent } from "../../../../../editor/deserialize";
|
||||||
import { CommandPartCreator, Part } from "../../../../../editor/parts";
|
import { CommandPartCreator, Part } from "../../../../../editor/parts";
|
||||||
import SettingsStore from "../../../../../settings/SettingsStore";
|
import SettingsStore from "../../../../../settings/SettingsStore";
|
||||||
import EditorStateTransfer from "../../../../../utils/EditorStateTransfer";
|
import EditorStateTransfer from "../../../../../utils/EditorStateTransfer";
|
||||||
|
import { useScopedRoomContext } from "../../../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
function getFormattedContent(editorStateTransfer: EditorStateTransfer): string {
|
function getFormattedContent(editorStateTransfer: EditorStateTransfer): string {
|
||||||
return (
|
return (
|
||||||
|
@ -60,12 +60,12 @@ export function parseEditorStateTransfer(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useInitialContent(editorStateTransfer: EditorStateTransfer): string | undefined {
|
export function useInitialContent(editorStateTransfer: EditorStateTransfer): string | undefined {
|
||||||
const roomContext = useRoomContext();
|
const { room } = useScopedRoomContext("room");
|
||||||
const mxClient = useMatrixClientContext();
|
const mxClient = useMatrixClientContext();
|
||||||
|
|
||||||
return useMemo<string | undefined>(() => {
|
return useMemo<string | undefined>(() => {
|
||||||
if (editorStateTransfer && roomContext.room && mxClient) {
|
if (editorStateTransfer && room && mxClient) {
|
||||||
return parseEditorStateTransfer(editorStateTransfer, roomContext.room, mxClient);
|
return parseEditorStateTransfer(editorStateTransfer, room, mxClient);
|
||||||
}
|
}
|
||||||
}, [editorStateTransfer, roomContext, mxClient]);
|
}, [editorStateTransfer, room, mxClient]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ import { KeyBindingAction } from "../../../../../accessibility/KeyboardShortcuts
|
||||||
import { findEditableEvent } from "../../../../../utils/EventUtils";
|
import { findEditableEvent } from "../../../../../utils/EventUtils";
|
||||||
import dis from "../../../../../dispatcher/dispatcher";
|
import dis from "../../../../../dispatcher/dispatcher";
|
||||||
import { Action } from "../../../../../dispatcher/actions";
|
import { Action } from "../../../../../dispatcher/actions";
|
||||||
import { useRoomContext } from "../../../../../contexts/RoomContext";
|
|
||||||
import { IRoomState } from "../../../../structures/RoomView";
|
import { IRoomState } from "../../../../structures/RoomView";
|
||||||
import { ComposerContextState, useComposerContext } from "../ComposerContext";
|
import { ComposerContextState, useComposerContext } from "../ComposerContext";
|
||||||
import EditorStateTransfer from "../../../../../utils/EditorStateTransfer";
|
import EditorStateTransfer from "../../../../../utils/EditorStateTransfer";
|
||||||
|
@ -26,6 +25,7 @@ import { getEventsFromEditorStateTransfer, getEventsFromRoom } from "../utils/ev
|
||||||
import { endEditing } from "../utils/editing";
|
import { endEditing } from "../utils/editing";
|
||||||
import Autocomplete from "../../Autocomplete";
|
import Autocomplete from "../../Autocomplete";
|
||||||
import { handleClipboardEvent, handleEventWithAutocomplete, isEventToHandleAsClipboardEvent } from "./utils";
|
import { handleClipboardEvent, handleEventWithAutocomplete, isEventToHandleAsClipboardEvent } from "./utils";
|
||||||
|
import { useScopedRoomContext } from "../../../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
export function useInputEventProcessor(
|
export function useInputEventProcessor(
|
||||||
onSend: () => void,
|
onSend: () => void,
|
||||||
|
@ -33,7 +33,7 @@ export function useInputEventProcessor(
|
||||||
initialContent?: string,
|
initialContent?: string,
|
||||||
eventRelation?: IEventRelation,
|
eventRelation?: IEventRelation,
|
||||||
): (event: WysiwygEvent, composer: Wysiwyg, editor: HTMLElement) => WysiwygEvent | null {
|
): (event: WysiwygEvent, composer: Wysiwyg, editor: HTMLElement) => WysiwygEvent | null {
|
||||||
const roomContext = useRoomContext();
|
const roomContext = useScopedRoomContext("liveTimeline", "room", "replyToEvent", "timelineRenderingType");
|
||||||
const composerContext = useComposerContext();
|
const composerContext = useComposerContext();
|
||||||
const mxClient = useMatrixClientContext();
|
const mxClient = useMatrixClientContext();
|
||||||
const isCtrlEnterToSend = useSettingValue<boolean>("MessageComposerInput.ctrlEnterToSend");
|
const isCtrlEnterToSend = useSettingValue<boolean>("MessageComposerInput.ctrlEnterToSend");
|
||||||
|
@ -94,7 +94,7 @@ function handleKeyboardEvent(
|
||||||
initialContent: string | undefined,
|
initialContent: string | undefined,
|
||||||
composer: Wysiwyg,
|
composer: Wysiwyg,
|
||||||
editor: HTMLElement,
|
editor: HTMLElement,
|
||||||
roomContext: IRoomState,
|
roomContext: Pick<IRoomState, "liveTimeline" | "timelineRenderingType" | "room">,
|
||||||
composerContext: ComposerContextState,
|
composerContext: ComposerContextState,
|
||||||
mxClient: MatrixClient | undefined,
|
mxClient: MatrixClient | undefined,
|
||||||
autocompleteRef: React.RefObject<Autocomplete>,
|
autocompleteRef: React.RefObject<Autocomplete>,
|
||||||
|
@ -175,7 +175,7 @@ function dispatchEditEvent(
|
||||||
isForward: boolean,
|
isForward: boolean,
|
||||||
editorStateTransfer: EditorStateTransfer | undefined,
|
editorStateTransfer: EditorStateTransfer | undefined,
|
||||||
composerContext: ComposerContextState,
|
composerContext: ComposerContextState,
|
||||||
roomContext: IRoomState,
|
roomContext: Pick<IRoomState, "liveTimeline" | "timelineRenderingType" | "room">,
|
||||||
mxClient: MatrixClient,
|
mxClient: MatrixClient,
|
||||||
): boolean {
|
): boolean {
|
||||||
const foundEvents = editorStateTransfer
|
const foundEvents = editorStateTransfer
|
||||||
|
|
|
@ -16,8 +16,8 @@ import Autocomplete from "../../Autocomplete";
|
||||||
import { handleClipboardEvent, handleEventWithAutocomplete, isEventToHandleAsClipboardEvent } from "./utils";
|
import { handleClipboardEvent, handleEventWithAutocomplete, isEventToHandleAsClipboardEvent } from "./utils";
|
||||||
import { useSuggestion } from "./useSuggestion";
|
import { useSuggestion } from "./useSuggestion";
|
||||||
import { isNotNull, isNotUndefined } from "../../../../../Typeguards";
|
import { isNotNull, isNotUndefined } from "../../../../../Typeguards";
|
||||||
import { useRoomContext } from "../../../../../contexts/RoomContext";
|
|
||||||
import { useMatrixClientContext } from "../../../../../contexts/MatrixClientContext";
|
import { useMatrixClientContext } from "../../../../../contexts/MatrixClientContext";
|
||||||
|
import { useScopedRoomContext } from "../../../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
function isDivElement(target: EventTarget): target is HTMLDivElement {
|
function isDivElement(target: EventTarget): target is HTMLDivElement {
|
||||||
return target instanceof HTMLDivElement;
|
return target instanceof HTMLDivElement;
|
||||||
|
@ -63,7 +63,7 @@ export function usePlainTextListeners(
|
||||||
onSelect: (event: SyntheticEvent<HTMLDivElement>) => void;
|
onSelect: (event: SyntheticEvent<HTMLDivElement>) => void;
|
||||||
suggestion: MappedSuggestion | null;
|
suggestion: MappedSuggestion | null;
|
||||||
} {
|
} {
|
||||||
const roomContext = useRoomContext();
|
const roomContext = useScopedRoomContext("room", "timelineRenderingType", "replyToEvent");
|
||||||
const mxClient = useMatrixClientContext();
|
const mxClient = useMatrixClientContext();
|
||||||
|
|
||||||
const ref = useRef<HTMLDivElement | null>(null);
|
const ref = useRef<HTMLDivElement | null>(null);
|
||||||
|
|
|
@ -11,20 +11,21 @@ import { RefObject, useCallback, useRef } from "react";
|
||||||
import defaultDispatcher from "../../../../../dispatcher/dispatcher";
|
import defaultDispatcher from "../../../../../dispatcher/dispatcher";
|
||||||
import { Action } from "../../../../../dispatcher/actions";
|
import { Action } from "../../../../../dispatcher/actions";
|
||||||
import { ActionPayload } from "../../../../../dispatcher/payloads";
|
import { ActionPayload } from "../../../../../dispatcher/payloads";
|
||||||
import { TimelineRenderingType, useRoomContext } from "../../../../../contexts/RoomContext";
|
import { TimelineRenderingType } from "../../../../../contexts/RoomContext";
|
||||||
import { useDispatcher } from "../../../../../hooks/useDispatcher";
|
import { useDispatcher } from "../../../../../hooks/useDispatcher";
|
||||||
import { focusComposer } from "./utils";
|
import { focusComposer } from "./utils";
|
||||||
import { ComposerType } from "../../../../../dispatcher/payloads/ComposerInsertPayload";
|
import { ComposerType } from "../../../../../dispatcher/payloads/ComposerInsertPayload";
|
||||||
import { ComposerFunctions } from "../types";
|
import { ComposerFunctions } from "../types";
|
||||||
import { setSelection } from "../utils/selection";
|
import { setSelection } from "../utils/selection";
|
||||||
import { useComposerContext } from "../ComposerContext";
|
import { useComposerContext } from "../ComposerContext";
|
||||||
|
import { useScopedRoomContext } from "../../../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
export function useWysiwygEditActionHandler(
|
export function useWysiwygEditActionHandler(
|
||||||
disabled: boolean,
|
disabled: boolean,
|
||||||
composerElement: RefObject<HTMLElement>,
|
composerElement: RefObject<HTMLElement>,
|
||||||
composerFunctions: ComposerFunctions,
|
composerFunctions: ComposerFunctions,
|
||||||
): void {
|
): void {
|
||||||
const roomContext = useRoomContext();
|
const roomContext = useScopedRoomContext("timelineRenderingType");
|
||||||
const composerContext = useComposerContext();
|
const composerContext = useComposerContext();
|
||||||
const timeoutId = useRef<number | null>(null);
|
const timeoutId = useRef<number | null>(null);
|
||||||
|
|
||||||
|
|
|
@ -11,20 +11,21 @@ import { MutableRefObject, useCallback, useRef } from "react";
|
||||||
import defaultDispatcher from "../../../../../dispatcher/dispatcher";
|
import defaultDispatcher from "../../../../../dispatcher/dispatcher";
|
||||||
import { Action } from "../../../../../dispatcher/actions";
|
import { Action } from "../../../../../dispatcher/actions";
|
||||||
import { ActionPayload } from "../../../../../dispatcher/payloads";
|
import { ActionPayload } from "../../../../../dispatcher/payloads";
|
||||||
import { TimelineRenderingType, useRoomContext } from "../../../../../contexts/RoomContext";
|
import { TimelineRenderingType } from "../../../../../contexts/RoomContext";
|
||||||
import { useDispatcher } from "../../../../../hooks/useDispatcher";
|
import { useDispatcher } from "../../../../../hooks/useDispatcher";
|
||||||
import { focusComposer } from "./utils";
|
import { focusComposer } from "./utils";
|
||||||
import { ComposerFunctions } from "../types";
|
import { ComposerFunctions } from "../types";
|
||||||
import { ComposerType } from "../../../../../dispatcher/payloads/ComposerInsertPayload";
|
import { ComposerType } from "../../../../../dispatcher/payloads/ComposerInsertPayload";
|
||||||
import { useComposerContext } from "../ComposerContext";
|
import { useComposerContext } from "../ComposerContext";
|
||||||
import { setSelection } from "../utils/selection";
|
import { setSelection } from "../utils/selection";
|
||||||
|
import { useScopedRoomContext } from "../../../../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
export function useWysiwygSendActionHandler(
|
export function useWysiwygSendActionHandler(
|
||||||
disabled: boolean,
|
disabled: boolean,
|
||||||
composerElement: MutableRefObject<HTMLElement>,
|
composerElement: MutableRefObject<HTMLElement>,
|
||||||
composerFunctions: ComposerFunctions,
|
composerFunctions: ComposerFunctions,
|
||||||
): void {
|
): void {
|
||||||
const roomContext = useRoomContext();
|
const roomContext = useScopedRoomContext("timelineRenderingType");
|
||||||
const composerContext = useComposerContext();
|
const composerContext = useComposerContext();
|
||||||
const timeoutId = useRef<number | null>(null);
|
const timeoutId = useRef<number | null>(null);
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ import { isNotNull } from "../../../../../Typeguards";
|
||||||
export function focusComposer(
|
export function focusComposer(
|
||||||
composerElement: MutableRefObject<HTMLElement | null>,
|
composerElement: MutableRefObject<HTMLElement | null>,
|
||||||
renderingType: TimelineRenderingType,
|
renderingType: TimelineRenderingType,
|
||||||
roomContext: IRoomState,
|
roomContext: Pick<IRoomState, "timelineRenderingType">,
|
||||||
timeoutId: MutableRefObject<number | null>,
|
timeoutId: MutableRefObject<number | null>,
|
||||||
): void {
|
): void {
|
||||||
if (renderingType === roomContext.timelineRenderingType) {
|
if (renderingType === roomContext.timelineRenderingType) {
|
||||||
|
@ -123,7 +123,7 @@ export function handleEventWithAutocomplete(
|
||||||
export function handleClipboardEvent(
|
export function handleClipboardEvent(
|
||||||
event: ClipboardEvent | InputEvent,
|
event: ClipboardEvent | InputEvent,
|
||||||
data: DataTransfer | null,
|
data: DataTransfer | null,
|
||||||
roomContext: IRoomState,
|
roomContext: Pick<IRoomState, "room" | "timelineRenderingType" | "replyToEvent">,
|
||||||
mxClient: MatrixClient,
|
mxClient: MatrixClient,
|
||||||
eventRelation?: IEventRelation,
|
eventRelation?: IEventRelation,
|
||||||
): boolean {
|
): boolean {
|
||||||
|
|
|
@ -13,7 +13,7 @@ import dis from "../../../../../dispatcher/dispatcher";
|
||||||
import { Action } from "../../../../../dispatcher/actions";
|
import { Action } from "../../../../../dispatcher/actions";
|
||||||
import EditorStateTransfer from "../../../../../utils/EditorStateTransfer";
|
import EditorStateTransfer from "../../../../../utils/EditorStateTransfer";
|
||||||
|
|
||||||
export function endEditing(roomContext: IRoomState): void {
|
export function endEditing(roomContext: Pick<IRoomState, "timelineRenderingType">): void {
|
||||||
// todo local storage
|
// todo local storage
|
||||||
// localStorage.removeItem(this.editorRoomKey);
|
// localStorage.removeItem(this.editorRoomKey);
|
||||||
// localStorage.removeItem(this.editorStateKey);
|
// localStorage.removeItem(this.editorStateKey);
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { ComposerContextState } from "../ComposerContext";
|
||||||
// From EditMessageComposer private get events(): MatrixEvent[]
|
// From EditMessageComposer private get events(): MatrixEvent[]
|
||||||
export function getEventsFromEditorStateTransfer(
|
export function getEventsFromEditorStateTransfer(
|
||||||
editorStateTransfer: EditorStateTransfer,
|
editorStateTransfer: EditorStateTransfer,
|
||||||
roomContext: IRoomState,
|
roomContext: Pick<IRoomState, "liveTimeline">,
|
||||||
mxClient: MatrixClient,
|
mxClient: MatrixClient,
|
||||||
): MatrixEvent[] | undefined {
|
): MatrixEvent[] | undefined {
|
||||||
const liveTimelineEvents = roomContext.liveTimeline?.getEvents();
|
const liveTimelineEvents = roomContext.liveTimeline?.getEvents();
|
||||||
|
@ -41,7 +41,7 @@ export function getEventsFromEditorStateTransfer(
|
||||||
// From SendMessageComposer private onKeyDown = (event: KeyboardEvent): void
|
// From SendMessageComposer private onKeyDown = (event: KeyboardEvent): void
|
||||||
export function getEventsFromRoom(
|
export function getEventsFromRoom(
|
||||||
composerContext: ComposerContextState,
|
composerContext: ComposerContextState,
|
||||||
roomContext: IRoomState,
|
roomContext: Pick<IRoomState, "liveTimeline" | "room">,
|
||||||
): MatrixEvent[] | undefined {
|
): MatrixEvent[] | undefined {
|
||||||
const isReplyingToThread = composerContext.eventRelation?.key === THREAD_RELATION_TYPE.name;
|
const isReplyingToThread = composerContext.eventRelation?.key === THREAD_RELATION_TYPE.name;
|
||||||
return roomContext.liveTimeline
|
return roomContext.liveTimeline
|
||||||
|
|
|
@ -39,7 +39,7 @@ export interface SendMessageParams {
|
||||||
mxClient: MatrixClient;
|
mxClient: MatrixClient;
|
||||||
relation?: IEventRelation;
|
relation?: IEventRelation;
|
||||||
replyToEvent?: MatrixEvent;
|
replyToEvent?: MatrixEvent;
|
||||||
roomContext: IRoomState;
|
roomContext: Pick<IRoomState, "timelineRenderingType" | "room">;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function sendMessage(
|
export async function sendMessage(
|
||||||
|
@ -177,7 +177,7 @@ export async function sendMessage(
|
||||||
|
|
||||||
interface EditMessageParams {
|
interface EditMessageParams {
|
||||||
mxClient: MatrixClient;
|
mxClient: MatrixClient;
|
||||||
roomContext: IRoomState;
|
roomContext: Pick<IRoomState, "timelineRenderingType">;
|
||||||
editorStateTransfer: EditorStateTransfer;
|
editorStateTransfer: EditorStateTransfer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { createContext, useContext } from "react";
|
import { createContext } from "react";
|
||||||
|
|
||||||
import { IRoomState } from "../components/structures/RoomView";
|
import { IRoomState } from "../components/structures/RoomView";
|
||||||
import { Layout } from "../settings/enums/Layout";
|
import { Layout } from "../settings/enums/Layout";
|
||||||
|
@ -79,6 +79,3 @@ const RoomContext = createContext<
|
||||||
});
|
});
|
||||||
RoomContext.displayName = "RoomContext";
|
RoomContext.displayName = "RoomContext";
|
||||||
export default RoomContext;
|
export default RoomContext;
|
||||||
export function useRoomContext(): IRoomState {
|
|
||||||
return useContext(RoomContext);
|
|
||||||
}
|
|
||||||
|
|
78
src/contexts/ScopedRoomContext.tsx
Normal file
78
src/contexts/ScopedRoomContext.tsx
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
Copyright 2024 New Vector Ltd.
|
||||||
|
Copyright 2019 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||||
|
Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { TypedEventEmitter } from "matrix-js-sdk/src/matrix";
|
||||||
|
import React, { ContextType, createContext, memo, ReactNode, useContext, useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
|
import { objectKeyChanges } from "../utils/objects.ts";
|
||||||
|
import { useTypedEventEmitter } from "../hooks/useEventEmitter.ts";
|
||||||
|
import RoomContext from "./RoomContext.ts";
|
||||||
|
|
||||||
|
// React Contexts with frequently changing values (like State where the object reference is changed on every update)
|
||||||
|
// cause performance issues by triggering a re-render on every component subscribed to that context.
|
||||||
|
// With ScopedRoomContext we're effectively setting up virtual contexts which are a subset of the overall context object
|
||||||
|
// and subscribers specify which fields they care about, and they will only be awoken on updates to those specific fields.
|
||||||
|
|
||||||
|
type ContextValue = ContextType<typeof RoomContext>;
|
||||||
|
|
||||||
|
export enum NotificationStateEvents {
|
||||||
|
Update = "update",
|
||||||
|
}
|
||||||
|
|
||||||
|
type EventHandlerMap<C extends Record<string, any>> = {
|
||||||
|
[NotificationStateEvents.Update]: (keys: Array<keyof C>) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EfficientContext<C extends Record<string, any>> extends TypedEventEmitter<
|
||||||
|
NotificationStateEvents,
|
||||||
|
EventHandlerMap<C>
|
||||||
|
> {
|
||||||
|
public constructor(public state: C) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public setState(state: C): void {
|
||||||
|
const changedKeys = objectKeyChanges(this.state ?? ({} as C), state);
|
||||||
|
this.state = state;
|
||||||
|
this.emit(NotificationStateEvents.Update, changedKeys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ScopedRoomContext = createContext<EfficientContext<ContextValue> | undefined>(undefined);
|
||||||
|
|
||||||
|
// Uses react memo and leverages splatting the value to ensure that the context is only updated when the state changes (shallow compare)
|
||||||
|
export const ScopedRoomContextProvider = memo(
|
||||||
|
({ children, ...state }: { children: ReactNode } & ContextValue): JSX.Element => {
|
||||||
|
const contextRef = useRef(new EfficientContext<ContextValue>(state));
|
||||||
|
useEffect(() => {
|
||||||
|
contextRef.current.setState(state);
|
||||||
|
}, [state]);
|
||||||
|
|
||||||
|
// Includes the legacy RoomContext provider for backwards compatibility with class components
|
||||||
|
return (
|
||||||
|
<RoomContext.Provider value={state}>
|
||||||
|
<ScopedRoomContext.Provider value={contextRef.current}>{children}</ScopedRoomContext.Provider>
|
||||||
|
</RoomContext.Provider>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
type ScopedRoomContext<K extends Array<keyof ContextValue>> = { [key in K[number]]: ContextValue[key] };
|
||||||
|
|
||||||
|
export function useScopedRoomContext<K extends Array<keyof ContextValue>>(...keys: K): ScopedRoomContext<K> {
|
||||||
|
const context = useContext(ScopedRoomContext);
|
||||||
|
const [state, setState] = useState<ScopedRoomContext<K>>(context?.state ?? ({} as ScopedRoomContext<K>));
|
||||||
|
|
||||||
|
useTypedEventEmitter(context, NotificationStateEvents.Update, (updatedKeys: K): void => {
|
||||||
|
if (context?.state && updatedKeys.some((updatedKey) => keys.includes(updatedKey))) {
|
||||||
|
setState(context.state);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
|
@ -7,10 +7,11 @@ Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { RoomMember } from "matrix-js-sdk/src/matrix";
|
import { RoomMember } from "matrix-js-sdk/src/matrix";
|
||||||
import { useContext, useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
|
|
||||||
import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext";
|
import { TimelineRenderingType } from "../../contexts/RoomContext";
|
||||||
import { useSettingValue } from "../useSettings";
|
import { useSettingValue } from "../useSettings";
|
||||||
|
import { useScopedRoomContext } from "../../contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
export function useRoomMemberProfile({
|
export function useRoomMemberProfile({
|
||||||
userId = "",
|
userId = "",
|
||||||
|
@ -21,7 +22,7 @@ export function useRoomMemberProfile({
|
||||||
member?: RoomMember | null;
|
member?: RoomMember | null;
|
||||||
forceHistorical?: boolean;
|
forceHistorical?: boolean;
|
||||||
}): RoomMember | undefined | null {
|
}): RoomMember | undefined | null {
|
||||||
const context = useContext(RoomContext);
|
const context = useScopedRoomContext("room", "timelineRenderingType");
|
||||||
const useOnlyCurrentProfiles = useSettingValue("useOnlyCurrentProfiles");
|
const useOnlyCurrentProfiles = useSettingValue("useOnlyCurrentProfiles");
|
||||||
|
|
||||||
const member = useMemo(() => {
|
const member = useMemo(() => {
|
||||||
|
|
|
@ -30,6 +30,7 @@ import {
|
||||||
import ResizeNotifier from "../../../../src/utils/ResizeNotifier";
|
import ResizeNotifier from "../../../../src/utils/ResizeNotifier";
|
||||||
import { IRoomState } from "../../../../src/components/structures/RoomView";
|
import { IRoomState } from "../../../../src/components/structures/RoomView";
|
||||||
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
jest.mock("../../../../src/utils/beacon", () => ({
|
jest.mock("../../../../src/utils/beacon", () => ({
|
||||||
useBeacon: jest.fn(),
|
useBeacon: jest.fn(),
|
||||||
|
@ -91,9 +92,9 @@ describe("MessagePanel", function () {
|
||||||
|
|
||||||
const getComponent = (props = {}, roomContext: Partial<IRoomState> = {}) => (
|
const getComponent = (props = {}, roomContext: Partial<IRoomState> = {}) => (
|
||||||
<MatrixClientContext.Provider value={client}>
|
<MatrixClientContext.Provider value={client}>
|
||||||
<RoomContext.Provider value={{ ...defaultRoomContext, ...roomContext }}>
|
<ScopedRoomContextProvider {...defaultRoomContext} {...roomContext}>
|
||||||
<MessagePanel {...defaultProps} {...props} />
|
<MessagePanel {...defaultProps} {...props} />
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
</MatrixClientContext.Provider>
|
</MatrixClientContext.Provider>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@ import {
|
||||||
|
|
||||||
import ThreadPanel, { ThreadFilterType, ThreadPanelHeader } from "../../../../src/components/structures/ThreadPanel";
|
import ThreadPanel, { ThreadFilterType, ThreadPanelHeader } from "../../../../src/components/structures/ThreadPanel";
|
||||||
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
|
||||||
import RoomContext from "../../../../src/contexts/RoomContext";
|
|
||||||
import { _t } from "../../../../src/languageHandler";
|
import { _t } from "../../../../src/languageHandler";
|
||||||
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
||||||
import { RoomPermalinkCreator } from "../../../../src/utils/permalinks/Permalinks";
|
import { RoomPermalinkCreator } from "../../../../src/utils/permalinks/Permalinks";
|
||||||
|
@ -28,6 +27,7 @@ import ResizeNotifier from "../../../../src/utils/ResizeNotifier";
|
||||||
import { createTestClient, getRoomContext, mkRoom, mockPlatformPeg, stubClient } from "../../../test-utils";
|
import { createTestClient, getRoomContext, mkRoom, mockPlatformPeg, stubClient } from "../../../test-utils";
|
||||||
import { mkThread } from "../../../test-utils/threads";
|
import { mkThread } from "../../../test-utils/threads";
|
||||||
import { IRoomState } from "../../../../src/components/structures/RoomView";
|
import { IRoomState } from "../../../../src/components/structures/RoomView";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
jest.mock("../../../../src/utils/Feedback");
|
jest.mock("../../../../src/utils/Feedback");
|
||||||
|
|
||||||
|
@ -81,11 +81,11 @@ describe("ThreadPanel", () => {
|
||||||
room: mockRoom,
|
room: mockRoom,
|
||||||
} as unknown as IRoomState;
|
} as unknown as IRoomState;
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
<RoomContext.Provider value={roomContextObject}>
|
<ScopedRoomContextProvider {...roomContextObject}>
|
||||||
<MatrixClientContext.Provider value={mockClient}>
|
<MatrixClientContext.Provider value={mockClient}>
|
||||||
<ThreadPanelHeader filterOption={ThreadFilterType.All} setFilterOption={() => undefined} />
|
<ThreadPanelHeader filterOption={ThreadFilterType.All} setFilterOption={() => undefined} />
|
||||||
</MatrixClientContext.Provider>
|
</MatrixClientContext.Provider>
|
||||||
</RoomContext.Provider>,
|
</ScopedRoomContextProvider>,
|
||||||
);
|
);
|
||||||
fireEvent.click(getByRole(container, "button", { name: "Mark all as read" }));
|
fireEvent.click(getByRole(container, "button", { name: "Mark all as read" }));
|
||||||
await waitFor(() =>
|
await waitFor(() =>
|
||||||
|
@ -114,8 +114,8 @@ describe("ThreadPanel", () => {
|
||||||
|
|
||||||
const TestThreadPanel = () => (
|
const TestThreadPanel = () => (
|
||||||
<MatrixClientContext.Provider value={mockClient}>
|
<MatrixClientContext.Provider value={mockClient}>
|
||||||
<RoomContext.Provider
|
<ScopedRoomContextProvider
|
||||||
value={getRoomContext(room, {
|
{...getRoomContext(room, {
|
||||||
canSendMessages: true,
|
canSendMessages: true,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
|
@ -125,7 +125,7 @@ describe("ThreadPanel", () => {
|
||||||
resizeNotifier={new ResizeNotifier()}
|
resizeNotifier={new ResizeNotifier()}
|
||||||
permalinkCreator={new RoomPermalinkCreator(room)}
|
permalinkCreator={new RoomPermalinkCreator(room)}
|
||||||
/>
|
/>
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
</MatrixClientContext.Provider>
|
</MatrixClientContext.Provider>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ import React, { useState } from "react";
|
||||||
|
|
||||||
import ThreadView from "../../../../src/components/structures/ThreadView";
|
import ThreadView from "../../../../src/components/structures/ThreadView";
|
||||||
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
|
||||||
import RoomContext from "../../../../src/contexts/RoomContext";
|
|
||||||
import { SdkContextClass } from "../../../../src/contexts/SDKContext";
|
import { SdkContextClass } from "../../../../src/contexts/SDKContext";
|
||||||
import { Action } from "../../../../src/dispatcher/actions";
|
import { Action } from "../../../../src/dispatcher/actions";
|
||||||
import dispatcher from "../../../../src/dispatcher/dispatcher";
|
import dispatcher from "../../../../src/dispatcher/dispatcher";
|
||||||
|
@ -34,6 +33,7 @@ import { mockPlatformPeg } from "../../../test-utils/platform";
|
||||||
import { getRoomContext } from "../../../test-utils/room";
|
import { getRoomContext } from "../../../test-utils/room";
|
||||||
import { mkMessage, stubClient } from "../../../test-utils/test-utils";
|
import { mkMessage, stubClient } from "../../../test-utils/test-utils";
|
||||||
import { mkThread } from "../../../test-utils/threads";
|
import { mkThread } from "../../../test-utils/threads";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
describe("ThreadView", () => {
|
describe("ThreadView", () => {
|
||||||
const ROOM_ID = "!roomId:example.org";
|
const ROOM_ID = "!roomId:example.org";
|
||||||
|
@ -51,8 +51,8 @@ describe("ThreadView", () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MatrixClientContext.Provider value={mockClient}>
|
<MatrixClientContext.Provider value={mockClient}>
|
||||||
<RoomContext.Provider
|
<ScopedRoomContextProvider
|
||||||
value={getRoomContext(room, {
|
{...getRoomContext(room, {
|
||||||
canSendMessages: true,
|
canSendMessages: true,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
|
@ -63,7 +63,7 @@ describe("ThreadView", () => {
|
||||||
initialEvent={initialEvent}
|
initialEvent={initialEvent}
|
||||||
resizeNotifier={new ResizeNotifier()}
|
resizeNotifier={new ResizeNotifier()}
|
||||||
/>
|
/>
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
,
|
,
|
||||||
</MatrixClientContext.Provider>
|
</MatrixClientContext.Provider>
|
||||||
);
|
);
|
||||||
|
|
|
@ -15,10 +15,11 @@ import RecordingPlayback, {
|
||||||
PlaybackLayout,
|
PlaybackLayout,
|
||||||
} from "../../../../../src/components/views/audio_messages/RecordingPlayback";
|
} from "../../../../../src/components/views/audio_messages/RecordingPlayback";
|
||||||
import { Playback } from "../../../../../src/audio/Playback";
|
import { Playback } from "../../../../../src/audio/Playback";
|
||||||
import RoomContext, { TimelineRenderingType } from "../../../../../src/contexts/RoomContext";
|
import { TimelineRenderingType } from "../../../../../src/contexts/RoomContext";
|
||||||
import { createAudioContext } from "../../../../../src/audio/compat";
|
import { createAudioContext } from "../../../../../src/audio/compat";
|
||||||
import { flushPromises } from "../../../../test-utils";
|
import { flushPromises } from "../../../../test-utils";
|
||||||
import { IRoomState } from "../../../../../src/components/structures/RoomView";
|
import { IRoomState } from "../../../../../src/components/structures/RoomView";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
jest.mock("../../../../../src/WorkerManager", () => ({
|
jest.mock("../../../../../src/WorkerManager", () => ({
|
||||||
WorkerManager: jest.fn(() => ({
|
WorkerManager: jest.fn(() => ({
|
||||||
|
@ -56,9 +57,9 @@ describe("<RecordingPlayback />", () => {
|
||||||
const defaultRoom = { roomId: "!room:server.org", timelineRenderingType: TimelineRenderingType.File } as IRoomState;
|
const defaultRoom = { roomId: "!room:server.org", timelineRenderingType: TimelineRenderingType.File } as IRoomState;
|
||||||
const getComponent = (props: React.ComponentProps<typeof RecordingPlayback>, room = defaultRoom) =>
|
const getComponent = (props: React.ComponentProps<typeof RecordingPlayback>, room = defaultRoom) =>
|
||||||
render(
|
render(
|
||||||
<RoomContext.Provider value={room}>
|
<ScopedRoomContextProvider {...room}>
|
||||||
<RecordingPlayback {...props} />
|
<RecordingPlayback {...props} />
|
||||||
</RoomContext.Provider>,
|
</ScopedRoomContextProvider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|
|
@ -12,11 +12,11 @@ import { MatrixClient, PendingEventOrdering, Room, RoomMember } from "matrix-js-
|
||||||
import React, { ComponentProps } from "react";
|
import React, { ComponentProps } from "react";
|
||||||
|
|
||||||
import MemberAvatar from "../../../../../src/components/views/avatars/MemberAvatar";
|
import MemberAvatar from "../../../../../src/components/views/avatars/MemberAvatar";
|
||||||
import RoomContext from "../../../../../src/contexts/RoomContext";
|
|
||||||
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
|
||||||
import SettingsStore from "../../../../../src/settings/SettingsStore";
|
import SettingsStore from "../../../../../src/settings/SettingsStore";
|
||||||
import { getRoomContext } from "../../../../test-utils/room";
|
import { getRoomContext } from "../../../../test-utils/room";
|
||||||
import { stubClient } from "../../../../test-utils/test-utils";
|
import { stubClient } from "../../../../test-utils/test-utils";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
describe("MemberAvatar", () => {
|
describe("MemberAvatar", () => {
|
||||||
const ROOM_ID = "roomId";
|
const ROOM_ID = "roomId";
|
||||||
|
@ -27,9 +27,9 @@ describe("MemberAvatar", () => {
|
||||||
|
|
||||||
function getComponent(props: Partial<ComponentProps<typeof MemberAvatar>>) {
|
function getComponent(props: Partial<ComponentProps<typeof MemberAvatar>>) {
|
||||||
return (
|
return (
|
||||||
<RoomContext.Provider value={getRoomContext(room, {})}>
|
<ScopedRoomContextProvider {...getRoomContext(room, {})}>
|
||||||
<MemberAvatar member={null} size="35px" {...props} />
|
<MemberAvatar member={null} size="35px" {...props} />
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ import { mocked } from "jest-mock";
|
||||||
import userEvent from "@testing-library/user-event";
|
import userEvent from "@testing-library/user-event";
|
||||||
|
|
||||||
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
|
||||||
import RoomContext, { TimelineRenderingType } from "../../../../../src/contexts/RoomContext";
|
import { TimelineRenderingType } from "../../../../../src/contexts/RoomContext";
|
||||||
import { IRoomState } from "../../../../../src/components/structures/RoomView";
|
import { IRoomState } from "../../../../../src/components/structures/RoomView";
|
||||||
import { canEditContent } from "../../../../../src/utils/EventUtils";
|
import { canEditContent } from "../../../../../src/utils/EventUtils";
|
||||||
import { copyPlaintext, getSelectedText } from "../../../../../src/utils/strings";
|
import { copyPlaintext, getSelectedText } from "../../../../../src/utils/strings";
|
||||||
|
@ -40,6 +40,7 @@ import { Action } from "../../../../../src/dispatcher/actions";
|
||||||
import { mkVoiceBroadcastInfoStateEvent } from "../../../voice-broadcast/utils/test-utils";
|
import { mkVoiceBroadcastInfoStateEvent } from "../../../voice-broadcast/utils/test-utils";
|
||||||
import { VoiceBroadcastInfoState } from "../../../../../src/voice-broadcast";
|
import { VoiceBroadcastInfoState } from "../../../../../src/voice-broadcast";
|
||||||
import { createMessageEventContent } from "../../../../test-utils/events";
|
import { createMessageEventContent } from "../../../../test-utils/events";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
jest.mock("../../../../../src/utils/strings", () => ({
|
jest.mock("../../../../../src/utils/strings", () => ({
|
||||||
copyPlaintext: jest.fn(),
|
copyPlaintext: jest.fn(),
|
||||||
|
@ -546,8 +547,8 @@ function createMenu(
|
||||||
client.getRoom = jest.fn().mockReturnValue(room);
|
client.getRoom = jest.fn().mockReturnValue(room);
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
<RoomContext.Provider value={context as IRoomState}>
|
<ScopedRoomContextProvider {...(context as IRoomState)}>
|
||||||
<MessageContextMenu mxEvent={mxEvent} onFinished={jest.fn()} {...props} />
|
<MessageContextMenu mxEvent={mxEvent} onFinished={jest.fn()} {...props} />
|
||||||
</RoomContext.Provider>,
|
</ScopedRoomContextProvider>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,8 @@ import {
|
||||||
import { MediaEventHelper } from "../../../../../src/utils/MediaEventHelper";
|
import { MediaEventHelper } from "../../../../../src/utils/MediaEventHelper";
|
||||||
import SettingsStore from "../../../../../src/settings/SettingsStore";
|
import SettingsStore from "../../../../../src/settings/SettingsStore";
|
||||||
import MFileBody from "../../../../../src/components/views/messages/MFileBody.tsx";
|
import MFileBody from "../../../../../src/components/views/messages/MFileBody.tsx";
|
||||||
import RoomContext, { TimelineRenderingType } from "../../../../../src/contexts/RoomContext.ts";
|
import { TimelineRenderingType } from "../../../../../src/contexts/RoomContext.ts";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
jest.mock("matrix-encrypt-attachment", () => ({
|
jest.mock("matrix-encrypt-attachment", () => ({
|
||||||
decryptAttachment: jest.fn(),
|
decryptAttachment: jest.fn(),
|
||||||
|
@ -72,14 +73,14 @@ describe("<MFileBody/>", () => {
|
||||||
|
|
||||||
it("should show a download button in file rendering type", async () => {
|
it("should show a download button in file rendering type", async () => {
|
||||||
const { container, getByRole } = render(
|
const { container, getByRole } = render(
|
||||||
<RoomContext.Provider value={{ timelineRenderingType: TimelineRenderingType.File } as any}>
|
<ScopedRoomContextProvider {...({ timelineRenderingType: TimelineRenderingType.File } as any)}>
|
||||||
<MFileBody
|
<MFileBody
|
||||||
{...props}
|
{...props}
|
||||||
mxEvent={mediaEvent}
|
mxEvent={mediaEvent}
|
||||||
mediaEventHelper={new MediaEventHelper(mediaEvent)}
|
mediaEventHelper={new MediaEventHelper(mediaEvent)}
|
||||||
showGenericPlaceholder={false}
|
showGenericPlaceholder={false}
|
||||||
/>
|
/>
|
||||||
</RoomContext.Provider>,
|
</ScopedRoomContextProvider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(getByRole("link", { name: "Download" })).toBeInTheDocument();
|
expect(getByRole("link", { name: "Download" })).toBeInTheDocument();
|
||||||
|
|
|
@ -35,6 +35,7 @@ import dispatcher from "../../../../../src/dispatcher/dispatcher";
|
||||||
import SettingsStore from "../../../../../src/settings/SettingsStore";
|
import SettingsStore from "../../../../../src/settings/SettingsStore";
|
||||||
import { Action } from "../../../../../src/dispatcher/actions";
|
import { Action } from "../../../../../src/dispatcher/actions";
|
||||||
import PinningUtils from "../../../../../src/utils/PinningUtils";
|
import PinningUtils from "../../../../../src/utils/PinningUtils";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
jest.mock("../../../../../src/dispatcher/dispatcher");
|
jest.mock("../../../../../src/dispatcher/dispatcher");
|
||||||
|
|
||||||
|
@ -117,9 +118,9 @@ describe("<MessageActionBar />", () => {
|
||||||
} as unknown as IRoomState;
|
} as unknown as IRoomState;
|
||||||
const getComponent = (props = {}, roomContext: Partial<IRoomState> = {}) =>
|
const getComponent = (props = {}, roomContext: Partial<IRoomState> = {}) =>
|
||||||
render(
|
render(
|
||||||
<RoomContext.Provider value={{ ...defaultRoomContext, ...roomContext }}>
|
<ScopedRoomContextProvider {...defaultRoomContext} {...roomContext}>
|
||||||
<MessageActionBar {...defaultProps} {...props} />
|
<MessageActionBar {...defaultProps} {...props} />
|
||||||
</RoomContext.Provider>,
|
</ScopedRoomContextProvider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|
|
@ -20,9 +20,9 @@ import {
|
||||||
} from "../../../../../src/components/views/messages/RoomPredecessorTile";
|
} from "../../../../../src/components/views/messages/RoomPredecessorTile";
|
||||||
import { stubClient, upsertRoomStateEvents } from "../../../../test-utils/test-utils";
|
import { stubClient, upsertRoomStateEvents } from "../../../../test-utils/test-utils";
|
||||||
import { Action } from "../../../../../src/dispatcher/actions";
|
import { Action } from "../../../../../src/dispatcher/actions";
|
||||||
import RoomContext from "../../../../../src/contexts/RoomContext";
|
|
||||||
import { filterConsole, getRoomContext } from "../../../../test-utils";
|
import { filterConsole, getRoomContext } from "../../../../test-utils";
|
||||||
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
jest.mock("../../../../../src/dispatcher/dispatcher");
|
jest.mock("../../../../../src/dispatcher/dispatcher");
|
||||||
|
|
||||||
|
@ -99,9 +99,9 @@ describe("<RoomPredecessorTile />", () => {
|
||||||
expect(createEvent).toBeTruthy();
|
expect(createEvent).toBeTruthy();
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
<RoomContext.Provider value={getRoomContext(room, {})}>
|
<ScopedRoomContextProvider {...getRoomContext(room, {})}>
|
||||||
<RoomPredecessorTile mxEvent={createEvent} />
|
<RoomPredecessorTile mxEvent={createEvent} />
|
||||||
</RoomContext.Provider>,
|
</ScopedRoomContextProvider>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,8 @@ import { _t } from "../../../../../src/languageHandler";
|
||||||
import { tagRoom } from "../../../../../src/utils/room/tagRoom";
|
import { tagRoom } from "../../../../../src/utils/room/tagRoom";
|
||||||
import { DefaultTagID } from "../../../../../src/stores/room-list/models";
|
import { DefaultTagID } from "../../../../../src/stores/room-list/models";
|
||||||
import { Action } from "../../../../../src/dispatcher/actions";
|
import { Action } from "../../../../../src/dispatcher/actions";
|
||||||
import RoomContext, { TimelineRenderingType } from "../../../../../src/contexts/RoomContext";
|
import { TimelineRenderingType } from "../../../../../src/contexts/RoomContext";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
jest.mock("../../../../../src/utils/room/tagRoom");
|
jest.mock("../../../../../src/utils/room/tagRoom");
|
||||||
|
|
||||||
|
@ -172,14 +173,14 @@ describe("<RoomSummaryCard />", () => {
|
||||||
const onSearchChange = jest.fn();
|
const onSearchChange = jest.fn();
|
||||||
const { rerender } = render(
|
const { rerender } = render(
|
||||||
<MatrixClientContext.Provider value={mockClient}>
|
<MatrixClientContext.Provider value={mockClient}>
|
||||||
<RoomContext.Provider value={{ timelineRenderingType: TimelineRenderingType.Search } as any}>
|
<ScopedRoomContextProvider {...({ timelineRenderingType: TimelineRenderingType.Search } as any)}>
|
||||||
<RoomSummaryCard
|
<RoomSummaryCard
|
||||||
room={room}
|
room={room}
|
||||||
permalinkCreator={new RoomPermalinkCreator(room)}
|
permalinkCreator={new RoomPermalinkCreator(room)}
|
||||||
onSearchChange={onSearchChange}
|
onSearchChange={onSearchChange}
|
||||||
focusRoomSearch={true}
|
focusRoomSearch={true}
|
||||||
/>
|
/>
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
</MatrixClientContext.Provider>,
|
</MatrixClientContext.Provider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -188,13 +189,13 @@ describe("<RoomSummaryCard />", () => {
|
||||||
|
|
||||||
rerender(
|
rerender(
|
||||||
<MatrixClientContext.Provider value={mockClient}>
|
<MatrixClientContext.Provider value={mockClient}>
|
||||||
<RoomContext.Provider value={{ timelineRenderingType: TimelineRenderingType.Room } as any}>
|
<ScopedRoomContextProvider {...({ timelineRenderingType: TimelineRenderingType.Room } as any)}>
|
||||||
<RoomSummaryCard
|
<RoomSummaryCard
|
||||||
room={room}
|
room={room}
|
||||||
permalinkCreator={new RoomPermalinkCreator(room)}
|
permalinkCreator={new RoomPermalinkCreator(room)}
|
||||||
onSearchChange={onSearchChange}
|
onSearchChange={onSearchChange}
|
||||||
/>
|
/>
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
</MatrixClientContext.Provider>,
|
</MatrixClientContext.Provider>,
|
||||||
);
|
);
|
||||||
expect(screen.getByPlaceholderText("Search messages…")).toHaveValue("");
|
expect(screen.getByPlaceholderText("Search messages…")).toHaveValue("");
|
||||||
|
|
|
@ -27,12 +27,12 @@ import {
|
||||||
import DocumentOffset from "../../../../../src/editor/offset";
|
import DocumentOffset from "../../../../../src/editor/offset";
|
||||||
import SettingsStore from "../../../../../src/settings/SettingsStore";
|
import SettingsStore from "../../../../../src/settings/SettingsStore";
|
||||||
import EditorStateTransfer from "../../../../../src/utils/EditorStateTransfer";
|
import EditorStateTransfer from "../../../../../src/utils/EditorStateTransfer";
|
||||||
import RoomContext from "../../../../../src/contexts/RoomContext";
|
|
||||||
import { IRoomState } from "../../../../../src/components/structures/RoomView";
|
import { IRoomState } from "../../../../../src/components/structures/RoomView";
|
||||||
import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
|
||||||
import Autocompleter, { IProviderCompletions } from "../../../../../src/autocomplete/Autocompleter";
|
import Autocompleter, { IProviderCompletions } from "../../../../../src/autocomplete/Autocompleter";
|
||||||
import NotifProvider from "../../../../../src/autocomplete/NotifProvider";
|
import NotifProvider from "../../../../../src/autocomplete/NotifProvider";
|
||||||
import DMRoomMap from "../../../../../src/utils/DMRoomMap";
|
import DMRoomMap from "../../../../../src/utils/DMRoomMap";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
describe("<EditMessageComposer/>", () => {
|
describe("<EditMessageComposer/>", () => {
|
||||||
const userId = "@alice:server.org";
|
const userId = "@alice:server.org";
|
||||||
|
@ -79,7 +79,7 @@ describe("<EditMessageComposer/>", () => {
|
||||||
render(<EditMessageComposerWithMatrixClient editState={editState} />, {
|
render(<EditMessageComposerWithMatrixClient editState={editState} />, {
|
||||||
wrapper: ({ children }) => (
|
wrapper: ({ children }) => (
|
||||||
<MatrixClientContext.Provider value={mockClient}>
|
<MatrixClientContext.Provider value={mockClient}>
|
||||||
<RoomContext.Provider value={roomContext}>{children}</RoomContext.Provider>
|
<ScopedRoomContextProvider {...roomContext}>{children}</ScopedRoomContextProvider>
|
||||||
</MatrixClientContext.Provider>
|
</MatrixClientContext.Provider>
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
|
@ -30,7 +30,7 @@ import { mkEncryptedMatrixEvent } from "matrix-js-sdk/src/testing";
|
||||||
|
|
||||||
import EventTile, { EventTileProps } from "../../../../../src/components/views/rooms/EventTile";
|
import EventTile, { EventTileProps } from "../../../../../src/components/views/rooms/EventTile";
|
||||||
import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
|
||||||
import RoomContext, { TimelineRenderingType } from "../../../../../src/contexts/RoomContext";
|
import { TimelineRenderingType } from "../../../../../src/contexts/RoomContext";
|
||||||
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
|
||||||
import { filterConsole, flushPromises, getRoomContext, mkEvent, mkMessage, stubClient } from "../../../../test-utils";
|
import { filterConsole, flushPromises, getRoomContext, mkEvent, mkMessage, stubClient } from "../../../../test-utils";
|
||||||
import { mkThread } from "../../../../test-utils/threads";
|
import { mkThread } from "../../../../test-utils/threads";
|
||||||
|
@ -40,6 +40,7 @@ import { Action } from "../../../../../src/dispatcher/actions";
|
||||||
import { IRoomState } from "../../../../../src/components/structures/RoomView";
|
import { IRoomState } from "../../../../../src/components/structures/RoomView";
|
||||||
import PinningUtils from "../../../../../src/utils/PinningUtils";
|
import PinningUtils from "../../../../../src/utils/PinningUtils";
|
||||||
import { Layout } from "../../../../../src/settings/enums/Layout";
|
import { Layout } from "../../../../../src/settings/enums/Layout";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
describe("EventTile", () => {
|
describe("EventTile", () => {
|
||||||
const ROOM_ID = "!roomId:example.org";
|
const ROOM_ID = "!roomId:example.org";
|
||||||
|
@ -56,13 +57,13 @@ describe("EventTile", () => {
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<MatrixClientContext.Provider value={client}>
|
<MatrixClientContext.Provider value={client}>
|
||||||
<RoomContext.Provider value={props.roomContext}>
|
<ScopedRoomContextProvider {...props.roomContext}>
|
||||||
<EventTile
|
<EventTile
|
||||||
mxEvent={mxEvent}
|
mxEvent={mxEvent}
|
||||||
replacingEventId={mxEvent.replacingEventId()}
|
replacingEventId={mxEvent.replacingEventId()}
|
||||||
{...(props.eventTilePropertyOverrides ?? {})}
|
{...(props.eventTilePropertyOverrides ?? {})}
|
||||||
/>
|
/>
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
</MatrixClientContext.Provider>
|
</MatrixClientContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import {
|
||||||
import MessageComposer from "../../../../../src/components/views/rooms/MessageComposer";
|
import MessageComposer from "../../../../../src/components/views/rooms/MessageComposer";
|
||||||
import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
|
||||||
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
|
||||||
import RoomContext from "../../../../../src/contexts/RoomContext";
|
|
||||||
import { IRoomState } from "../../../../../src/components/structures/RoomView";
|
import { IRoomState } from "../../../../../src/components/structures/RoomView";
|
||||||
import ResizeNotifier from "../../../../../src/utils/ResizeNotifier";
|
import ResizeNotifier from "../../../../../src/utils/ResizeNotifier";
|
||||||
import { RoomPermalinkCreator } from "../../../../../src/utils/permalinks/Permalinks";
|
import { RoomPermalinkCreator } from "../../../../../src/utils/permalinks/Permalinks";
|
||||||
|
@ -40,6 +39,7 @@ import { Action } from "../../../../../src/dispatcher/actions";
|
||||||
import { VoiceBroadcastInfoState, VoiceBroadcastRecording } from "../../../../../src/voice-broadcast";
|
import { VoiceBroadcastInfoState, VoiceBroadcastRecording } from "../../../../../src/voice-broadcast";
|
||||||
import { mkVoiceBroadcastInfoStateEvent } from "../../../voice-broadcast/utils/test-utils";
|
import { mkVoiceBroadcastInfoStateEvent } from "../../../voice-broadcast/utils/test-utils";
|
||||||
import { SdkContextClass } from "../../../../../src/contexts/SDKContext";
|
import { SdkContextClass } from "../../../../../src/contexts/SDKContext";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
const openStickerPicker = async (): Promise<void> => {
|
const openStickerPicker = async (): Promise<void> => {
|
||||||
await userEvent.click(screen.getByLabelText("More options"));
|
await userEvent.click(screen.getByLabelText("More options"));
|
||||||
|
@ -512,9 +512,9 @@ function wrapAndRender(
|
||||||
|
|
||||||
const getRawComponent = (props = {}, context = roomContext, client = mockClient) => (
|
const getRawComponent = (props = {}, context = roomContext, client = mockClient) => (
|
||||||
<MatrixClientContext.Provider value={client}>
|
<MatrixClientContext.Provider value={client}>
|
||||||
<RoomContext.Provider value={context}>
|
<ScopedRoomContextProvider {...context}>
|
||||||
<MessageComposer {...defaultProps} {...props} />
|
<MessageComposer {...defaultProps} {...props} />
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
</MatrixClientContext.Provider>
|
</MatrixClientContext.Provider>
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -10,11 +10,11 @@ import React from "react";
|
||||||
import { render, screen, waitFor } from "jest-matrix-react";
|
import { render, screen, waitFor } from "jest-matrix-react";
|
||||||
|
|
||||||
import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
|
||||||
import RoomContext from "../../../../../src/contexts/RoomContext";
|
|
||||||
import { createTestClient, getRoomContext, mkStubRoom } from "../../../../test-utils";
|
import { createTestClient, getRoomContext, mkStubRoom } from "../../../../test-utils";
|
||||||
import { IRoomState } from "../../../../../src/components/structures/RoomView";
|
import { IRoomState } from "../../../../../src/components/structures/RoomView";
|
||||||
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
|
||||||
import MessageComposerButtons from "../../../../../src/components/views/rooms/MessageComposerButtons";
|
import MessageComposerButtons from "../../../../../src/components/views/rooms/MessageComposerButtons";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
describe("MessageComposerButtons", () => {
|
describe("MessageComposerButtons", () => {
|
||||||
// @ts-ignore - we're deliberately not implementing the whole interface here, but
|
// @ts-ignore - we're deliberately not implementing the whole interface here, but
|
||||||
|
@ -54,7 +54,7 @@ describe("MessageComposerButtons", () => {
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
<MatrixClientContext.Provider value={mockClient}>
|
<MatrixClientContext.Provider value={mockClient}>
|
||||||
<RoomContext.Provider value={defaultRoomContext}>{component}</RoomContext.Provider>
|
<ScopedRoomContextProvider {...defaultRoomContext}>{component}</ScopedRoomContextProvider>
|
||||||
</MatrixClientContext.Provider>,
|
</MatrixClientContext.Provider>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,19 +13,19 @@ import { MatrixClient, Room } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import { LocalRoom } from "../../../../../src/models/LocalRoom";
|
import { LocalRoom } from "../../../../../src/models/LocalRoom";
|
||||||
import { filterConsole, mkRoomMemberJoinEvent, mkThirdPartyInviteEvent, stubClient } from "../../../../test-utils";
|
import { filterConsole, mkRoomMemberJoinEvent, mkThirdPartyInviteEvent, stubClient } from "../../../../test-utils";
|
||||||
import RoomContext from "../../../../../src/contexts/RoomContext";
|
|
||||||
import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
|
||||||
import NewRoomIntro from "../../../../../src/components/views/rooms/NewRoomIntro";
|
import NewRoomIntro from "../../../../../src/components/views/rooms/NewRoomIntro";
|
||||||
import { IRoomState } from "../../../../../src/components/structures/RoomView";
|
import { IRoomState } from "../../../../../src/components/structures/RoomView";
|
||||||
import DMRoomMap from "../../../../../src/utils/DMRoomMap";
|
import DMRoomMap from "../../../../../src/utils/DMRoomMap";
|
||||||
import { DirectoryMember } from "../../../../../src/utils/direct-messages";
|
import { DirectoryMember } from "../../../../../src/utils/direct-messages";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
const renderNewRoomIntro = (client: MatrixClient, room: Room | LocalRoom) => {
|
const renderNewRoomIntro = (client: MatrixClient, room: Room | LocalRoom) => {
|
||||||
render(
|
render(
|
||||||
<MatrixClientContext.Provider value={client}>
|
<MatrixClientContext.Provider value={client}>
|
||||||
<RoomContext.Provider value={{ room, roomId: room.roomId } as unknown as IRoomState}>
|
<ScopedRoomContextProvider {...({ room, roomId: room.roomId } as unknown as IRoomState)}>
|
||||||
<NewRoomIntro />
|
<NewRoomIntro />
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
</MatrixClientContext.Provider>,
|
</MatrixClientContext.Provider>,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,7 +18,7 @@ import SendMessageComposer, {
|
||||||
isQuickReaction,
|
isQuickReaction,
|
||||||
} from "../../../../../src/components/views/rooms/SendMessageComposer";
|
} from "../../../../../src/components/views/rooms/SendMessageComposer";
|
||||||
import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
|
||||||
import RoomContext, { TimelineRenderingType } from "../../../../../src/contexts/RoomContext";
|
import { TimelineRenderingType } from "../../../../../src/contexts/RoomContext";
|
||||||
import EditorModel from "../../../../../src/editor/model";
|
import EditorModel from "../../../../../src/editor/model";
|
||||||
import { createPartCreator } from "../../../editor/mock";
|
import { createPartCreator } from "../../../editor/mock";
|
||||||
import { createTestClient, mkEvent, mkStubRoom, stubClient } from "../../../../test-utils";
|
import { createTestClient, mkEvent, mkStubRoom, stubClient } from "../../../../test-utils";
|
||||||
|
@ -30,6 +30,7 @@ import { IRoomState, MainSplitContentType } from "../../../../../src/components/
|
||||||
import { mockPlatformPeg } from "../../../../test-utils/platform";
|
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";
|
||||||
|
|
||||||
jest.mock("../../../../../src/utils/local-room", () => ({
|
jest.mock("../../../../../src/utils/local-room", () => ({
|
||||||
doMaybeLocalRoomAction: jest.fn(),
|
doMaybeLocalRoomAction: jest.fn(),
|
||||||
|
@ -365,9 +366,9 @@ describe("<SendMessageComposer/>", () => {
|
||||||
};
|
};
|
||||||
const getRawComponent = (props = {}, roomContext = defaultRoomContext, client = mockClient) => (
|
const getRawComponent = (props = {}, roomContext = defaultRoomContext, client = mockClient) => (
|
||||||
<MatrixClientContext.Provider value={client}>
|
<MatrixClientContext.Provider value={client}>
|
||||||
<RoomContext.Provider value={roomContext}>
|
<ScopedRoomContextProvider {...roomContext}>
|
||||||
<SendMessageComposer {...defaultProps} {...props} />
|
<SendMessageComposer {...defaultProps} {...props} />
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
</MatrixClientContext.Provider>
|
</MatrixClientContext.Provider>
|
||||||
);
|
);
|
||||||
const getComponent = (props = {}, roomContext = defaultRoomContext, client = mockClient) => {
|
const getComponent = (props = {}, roomContext = defaultRoomContext, client = mockClient) => {
|
||||||
|
|
|
@ -11,7 +11,6 @@ import React from "react";
|
||||||
import { fireEvent, render, screen, waitFor } from "jest-matrix-react";
|
import { fireEvent, render, screen, waitFor } from "jest-matrix-react";
|
||||||
|
|
||||||
import MatrixClientContext from "../../../../../../src/contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../../../../src/contexts/MatrixClientContext";
|
||||||
import RoomContext from "../../../../../../src/contexts/RoomContext";
|
|
||||||
import defaultDispatcher from "../../../../../../src/dispatcher/dispatcher";
|
import defaultDispatcher from "../../../../../../src/dispatcher/dispatcher";
|
||||||
import { Action } from "../../../../../../src/dispatcher/actions";
|
import { Action } from "../../../../../../src/dispatcher/actions";
|
||||||
import { flushPromises, mkEvent } from "../../../../../test-utils";
|
import { flushPromises, mkEvent } from "../../../../../test-utils";
|
||||||
|
@ -23,6 +22,7 @@ import { ComposerInsertPayload, ComposerType } from "../../../../../../src/dispa
|
||||||
import { ActionPayload } from "../../../../../../src/dispatcher/payloads";
|
import { ActionPayload } from "../../../../../../src/dispatcher/payloads";
|
||||||
import * as EmojiButton from "../../../../../../src/components/views/rooms/EmojiButton";
|
import * as EmojiButton from "../../../../../../src/components/views/rooms/EmojiButton";
|
||||||
import { createMocks } from "./utils";
|
import { createMocks } from "./utils";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
describe("EditWysiwygComposer", () => {
|
describe("EditWysiwygComposer", () => {
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
@ -39,9 +39,9 @@ describe("EditWysiwygComposer", () => {
|
||||||
) => {
|
) => {
|
||||||
return render(
|
return render(
|
||||||
<MatrixClientContext.Provider value={client}>
|
<MatrixClientContext.Provider value={client}>
|
||||||
<RoomContext.Provider value={roomContext}>
|
<ScopedRoomContextProvider {...roomContext}>
|
||||||
<EditWysiwygComposer disabled={disabled} editorStateTransfer={_editorStateTransfer} />
|
<EditWysiwygComposer disabled={disabled} editorStateTransfer={_editorStateTransfer} />
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
</MatrixClientContext.Provider>,
|
</MatrixClientContext.Provider>,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -64,9 +64,9 @@ describe("EditWysiwygComposer", () => {
|
||||||
|
|
||||||
rerender(
|
rerender(
|
||||||
<MatrixClientContext.Provider value={mockClient}>
|
<MatrixClientContext.Provider value={mockClient}>
|
||||||
<RoomContext.Provider value={{ ...defaultRoomContext, room: undefined }}>
|
<ScopedRoomContextProvider {...defaultRoomContext} room={undefined}>
|
||||||
<EditWysiwygComposer disabled={false} editorStateTransfer={editorStateTransfer} />
|
<EditWysiwygComposer disabled={false} editorStateTransfer={editorStateTransfer} />
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
</MatrixClientContext.Provider>,
|
</MatrixClientContext.Provider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -275,10 +275,10 @@ describe("EditWysiwygComposer", () => {
|
||||||
);
|
);
|
||||||
render(
|
render(
|
||||||
<MatrixClientContext.Provider value={mockClient}>
|
<MatrixClientContext.Provider value={mockClient}>
|
||||||
<RoomContext.Provider value={defaultRoomContext}>
|
<ScopedRoomContextProvider {...defaultRoomContext}>
|
||||||
<EditWysiwygComposer editorStateTransfer={editorStateTransfer} />
|
<EditWysiwygComposer editorStateTransfer={editorStateTransfer} />
|
||||||
<Emoji menuPosition={{ chevronFace: ChevronFace.Top }} />
|
<Emoji menuPosition={{ chevronFace: ChevronFace.Top }} />
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
</MatrixClientContext.Provider>,
|
</MatrixClientContext.Provider>,
|
||||||
);
|
);
|
||||||
// Same behavior as in RoomView.tsx
|
// Same behavior as in RoomView.tsx
|
||||||
|
|
|
@ -11,7 +11,6 @@ import React from "react";
|
||||||
import { act, fireEvent, render, screen, waitFor } from "jest-matrix-react";
|
import { act, fireEvent, render, screen, waitFor } from "jest-matrix-react";
|
||||||
|
|
||||||
import MatrixClientContext from "../../../../../../src/contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../../../../src/contexts/MatrixClientContext";
|
||||||
import RoomContext from "../../../../../../src/contexts/RoomContext";
|
|
||||||
import defaultDispatcher from "../../../../../../src/dispatcher/dispatcher";
|
import defaultDispatcher from "../../../../../../src/dispatcher/dispatcher";
|
||||||
import { Action } from "../../../../../../src/dispatcher/actions";
|
import { Action } from "../../../../../../src/dispatcher/actions";
|
||||||
import { flushPromises } from "../../../../../test-utils";
|
import { flushPromises } from "../../../../../test-utils";
|
||||||
|
@ -20,6 +19,7 @@ import { aboveLeftOf } from "../../../../../../src/components/structures/Context
|
||||||
import { ComposerInsertPayload, ComposerType } from "../../../../../../src/dispatcher/payloads/ComposerInsertPayload";
|
import { ComposerInsertPayload, ComposerType } from "../../../../../../src/dispatcher/payloads/ComposerInsertPayload";
|
||||||
import { setSelection } from "../../../../../../src/components/views/rooms/wysiwyg_composer/utils/selection";
|
import { setSelection } from "../../../../../../src/components/views/rooms/wysiwyg_composer/utils/selection";
|
||||||
import { createMocks } from "./utils";
|
import { createMocks } from "./utils";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
jest.mock("../../../../../../src/components/views/rooms/EmojiButton", () => ({
|
jest.mock("../../../../../../src/components/views/rooms/EmojiButton", () => ({
|
||||||
EmojiButton: ({ addEmoji }: { addEmoji: (emoji: string) => void }) => {
|
EmojiButton: ({ addEmoji }: { addEmoji: (emoji: string) => void }) => {
|
||||||
|
@ -66,7 +66,7 @@ describe("SendWysiwygComposer", () => {
|
||||||
) => {
|
) => {
|
||||||
return render(
|
return render(
|
||||||
<MatrixClientContext.Provider value={mockClient}>
|
<MatrixClientContext.Provider value={mockClient}>
|
||||||
<RoomContext.Provider value={defaultRoomContext}>
|
<ScopedRoomContextProvider {...defaultRoomContext}>
|
||||||
<SendWysiwygComposer
|
<SendWysiwygComposer
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
onSend={onSend}
|
onSend={onSend}
|
||||||
|
@ -75,7 +75,7 @@ describe("SendWysiwygComposer", () => {
|
||||||
menuPosition={aboveLeftOf({ top: 0, bottom: 0, right: 0 })}
|
menuPosition={aboveLeftOf({ top: 0, bottom: 0, right: 0 })}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
/>
|
/>
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
</MatrixClientContext.Provider>,
|
</MatrixClientContext.Provider>,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { PlainTextComposer } from "../../../../../../../src/components/views/roo
|
||||||
import * as mockUseSettingsHook from "../../../../../../../src/hooks/useSettings";
|
import * as mockUseSettingsHook from "../../../../../../../src/hooks/useSettings";
|
||||||
import * as mockKeyboard from "../../../../../../../src/Keyboard";
|
import * as mockKeyboard from "../../../../../../../src/Keyboard";
|
||||||
import { createMocks } from "../utils";
|
import { createMocks } from "../utils";
|
||||||
import RoomContext from "../../../../../../../src/contexts/RoomContext";
|
import { ScopedRoomContextProvider } from "../../../../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
describe("PlainTextComposer", () => {
|
describe("PlainTextComposer", () => {
|
||||||
const customRender = (
|
const customRender = (
|
||||||
|
@ -275,9 +275,9 @@ describe("PlainTextComposer", () => {
|
||||||
const { defaultRoomContext } = createMocks();
|
const { defaultRoomContext } = createMocks();
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<RoomContext.Provider value={defaultRoomContext}>
|
<ScopedRoomContextProvider {...defaultRoomContext}>
|
||||||
<PlainTextComposer onChange={jest.fn()} onSend={jest.fn()} disabled={false} initialContent="" />
|
<PlainTextComposer onChange={jest.fn()} onSend={jest.fn()} disabled={false} initialContent="" />
|
||||||
</RoomContext.Provider>,
|
</ScopedRoomContextProvider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(screen.getByTestId("autocomplete-wrapper")).toBeInTheDocument();
|
expect(screen.getByTestId("autocomplete-wrapper")).toBeInTheDocument();
|
||||||
|
|
|
@ -11,12 +11,12 @@ import React, { createRef } from "react";
|
||||||
import { render, screen, waitFor } from "jest-matrix-react";
|
import { render, screen, waitFor } from "jest-matrix-react";
|
||||||
|
|
||||||
import MatrixClientContext from "../../../../../../../src/contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../../../../../src/contexts/MatrixClientContext";
|
||||||
import RoomContext from "../../../../../../../src/contexts/RoomContext";
|
|
||||||
import { WysiwygAutocomplete } from "../../../../../../../src/components/views/rooms/wysiwyg_composer/components/WysiwygAutocomplete";
|
import { WysiwygAutocomplete } from "../../../../../../../src/components/views/rooms/wysiwyg_composer/components/WysiwygAutocomplete";
|
||||||
import { getRoomContext, mkStubRoom, stubClient } from "../../../../../../test-utils";
|
import { getRoomContext, mkStubRoom, stubClient } from "../../../../../../test-utils";
|
||||||
import Autocomplete from "../../../../../../../src/components/views/rooms/Autocomplete";
|
import Autocomplete from "../../../../../../../src/components/views/rooms/Autocomplete";
|
||||||
import Autocompleter, { ICompletion } from "../../../../../../../src/autocomplete/Autocompleter";
|
import Autocompleter, { ICompletion } from "../../../../../../../src/autocomplete/Autocompleter";
|
||||||
import AutocompleteProvider from "../../../../../../../src/autocomplete/AutocompleteProvider";
|
import AutocompleteProvider from "../../../../../../../src/autocomplete/AutocompleteProvider";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
const mockCompletion: ICompletion[] = [
|
const mockCompletion: ICompletion[] = [
|
||||||
{
|
{
|
||||||
|
@ -71,7 +71,7 @@ describe("WysiwygAutocomplete", () => {
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
<MatrixClientContext.Provider value={mockClient}>
|
<MatrixClientContext.Provider value={mockClient}>
|
||||||
<RoomContext.Provider value={mockRoomContext}>
|
<ScopedRoomContextProvider {...mockRoomContext}>
|
||||||
<WysiwygAutocomplete
|
<WysiwygAutocomplete
|
||||||
ref={autocompleteRef}
|
ref={autocompleteRef}
|
||||||
suggestion={null}
|
suggestion={null}
|
||||||
|
@ -80,7 +80,7 @@ describe("WysiwygAutocomplete", () => {
|
||||||
handleAtRoomMention={mockHandleAtRoomMention}
|
handleAtRoomMention={mockHandleAtRoomMention}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
</MatrixClientContext.Provider>,
|
</MatrixClientContext.Provider>,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,7 +18,6 @@ import defaultDispatcher from "../../../../../../../src/dispatcher/dispatcher";
|
||||||
import * as EventUtils from "../../../../../../../src/utils/EventUtils";
|
import * as EventUtils from "../../../../../../../src/utils/EventUtils";
|
||||||
import { Action } from "../../../../../../../src/dispatcher/actions";
|
import { Action } from "../../../../../../../src/dispatcher/actions";
|
||||||
import MatrixClientContext from "../../../../../../../src/contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../../../../../src/contexts/MatrixClientContext";
|
||||||
import RoomContext from "../../../../../../../src/contexts/RoomContext";
|
|
||||||
import {
|
import {
|
||||||
ComposerContext,
|
ComposerContext,
|
||||||
getDefaultContextValue,
|
getDefaultContextValue,
|
||||||
|
@ -32,20 +31,21 @@ import Autocompleter, { ICompletion } from "../../../../../../../src/autocomplet
|
||||||
import AutocompleteProvider from "../../../../../../../src/autocomplete/AutocompleteProvider";
|
import AutocompleteProvider from "../../../../../../../src/autocomplete/AutocompleteProvider";
|
||||||
import * as Permalinks from "../../../../../../../src/utils/permalinks/Permalinks";
|
import * as Permalinks from "../../../../../../../src/utils/permalinks/Permalinks";
|
||||||
import { PermalinkParts } from "../../../../../../../src/utils/permalinks/PermalinkConstructor";
|
import { PermalinkParts } from "../../../../../../../src/utils/permalinks/PermalinkConstructor";
|
||||||
|
import { ScopedRoomContextProvider } from "../../../../../../../src/contexts/ScopedRoomContext.tsx";
|
||||||
|
|
||||||
describe("WysiwygComposer", () => {
|
describe("WysiwygComposer", () => {
|
||||||
const customRender = (onChange = jest.fn(), onSend = jest.fn(), disabled = false, initialContent?: string) => {
|
const customRender = (onChange = jest.fn(), onSend = jest.fn(), disabled = false, initialContent?: string) => {
|
||||||
const { mockClient, defaultRoomContext } = createMocks();
|
const { mockClient, defaultRoomContext } = createMocks();
|
||||||
return render(
|
return render(
|
||||||
<MatrixClientContext.Provider value={mockClient}>
|
<MatrixClientContext.Provider value={mockClient}>
|
||||||
<RoomContext.Provider value={defaultRoomContext}>
|
<ScopedRoomContextProvider {...defaultRoomContext}>
|
||||||
<WysiwygComposer
|
<WysiwygComposer
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
onSend={onSend}
|
onSend={onSend}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
initialContent={initialContent}
|
initialContent={initialContent}
|
||||||
/>
|
/>
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
</MatrixClientContext.Provider>,
|
</MatrixClientContext.Provider>,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -523,7 +523,7 @@ describe("WysiwygComposer", () => {
|
||||||
) => {
|
) => {
|
||||||
return render(
|
return render(
|
||||||
<MatrixClientContext.Provider value={client}>
|
<MatrixClientContext.Provider value={client}>
|
||||||
<RoomContext.Provider value={roomContext}>
|
<ScopedRoomContextProvider {...roomContext}>
|
||||||
<ComposerContext.Provider
|
<ComposerContext.Provider
|
||||||
value={getDefaultContextValue({ editorStateTransfer: _editorStateTransfer })}
|
value={getDefaultContextValue({ editorStateTransfer: _editorStateTransfer })}
|
||||||
>
|
>
|
||||||
|
@ -537,7 +537,7 @@ describe("WysiwygComposer", () => {
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</ComposerContext.Provider>
|
</ComposerContext.Provider>
|
||||||
</RoomContext.Provider>
|
</ScopedRoomContextProvider>
|
||||||
</MatrixClientContext.Provider>,
|
</MatrixClientContext.Provider>,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue