Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Fix ComposerContext unwanted value sharing
Browse files Browse the repository at this point in the history
  • Loading branch information
florianduros committed Dec 16, 2022
1 parent 5061d7e commit 2d13d10
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 37 deletions.
10 changes: 6 additions & 4 deletions src/components/views/rooms/wysiwyg_composer/ComposerContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@ import { createContext, useContext } from "react";

import { SubSelection } from "./types";

export const defaultContext: { selection: SubSelection } = {
selection: { anchorNode: null, anchorOffset: 0, focusNode: null, focusOffset: 0 },
};
export function getDefaultContextValue() {
return {
selection: { anchorNode: null, anchorOffset: 0, focusNode: null, focusOffset: 0 },
};
}

export interface ComposerContextState {
selection: SubSelection;
}

export const ComposerContext = createContext<ComposerContextState>(defaultContext);
export const ComposerContext = createContext<ComposerContextState>(getDefaultContextValue());
ComposerContext.displayName = "ComposerContext";

export function useComposerContext() {
Expand Down
42 changes: 23 additions & 19 deletions src/components/views/rooms/wysiwyg_composer/EditWysiwygComposer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import React, { forwardRef, RefObject } from "react";
import React, { forwardRef, RefObject, useRef } from "react";
import classNames from "classnames";

import EditorStateTransfer from "../../../../utils/EditorStateTransfer";
Expand All @@ -23,6 +23,7 @@ import { EditionButtons } from "./components/EditionButtons";
import { useWysiwygEditActionHandler } from "./hooks/useWysiwygEditActionHandler";
import { useEditing } from "./hooks/useEditing";
import { useInitialContent } from "./hooks/useInitialContent";
import { ComposerContext, getDefaultContextValue } from "./ComposerContext";

interface ContentProps {
disabled: boolean;
Expand All @@ -44,31 +45,34 @@ interface EditWysiwygComposerProps {
}

export function EditWysiwygComposer({ editorStateTransfer, className, ...props }: EditWysiwygComposerProps) {
const defaultContextValue = useRef(getDefaultContextValue());
const initialContent = useInitialContent(editorStateTransfer);
const isReady = !editorStateTransfer || initialContent !== undefined;

const { editMessage, endEditing, onChange, isSaveDisabled } = useEditing(editorStateTransfer, initialContent);

return (
isReady && (
<WysiwygComposer
className={classNames("mx_EditWysiwygComposer", className)}
initialContent={initialContent}
onChange={onChange}
onSend={editMessage}
{...props}
>
{(ref) => (
<>
<Content disabled={props.disabled} ref={ref} />
<EditionButtons
onCancelClick={endEditing}
onSaveClick={editMessage}
isSaveDisabled={isSaveDisabled}
/>
</>
)}
</WysiwygComposer>
<ComposerContext.Provider value={defaultContextValue.current}>
<WysiwygComposer
className={classNames("mx_EditWysiwygComposer", className)}
initialContent={initialContent}
onChange={onChange}
onSend={editMessage}
{...props}
>
{(ref) => (
<>
<Content disabled={props.disabled} ref={ref} />
<EditionButtons
onCancelClick={endEditing}
onSaveClick={editMessage}
isSaveDisabled={isSaveDisabled}
/>
</>
)}
</WysiwygComposer>
</ComposerContext.Provider>
)
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import React, { ForwardedRef, forwardRef, MutableRefObject } from "react";
import React, { ForwardedRef, forwardRef, MutableRefObject, useRef } from "react";

import { useWysiwygSendActionHandler } from "./hooks/useWysiwygSendActionHandler";
import { WysiwygComposer } from "./components/WysiwygComposer";
Expand All @@ -24,7 +24,7 @@ import { E2EStatus } from "../../../../utils/ShieldUtils";
import E2EIcon from "../E2EIcon";
import { AboveLeftOf } from "../../../structures/ContextMenu";
import { Emoji } from "./components/Emoji";
import { ComposerContext, defaultContext } from "./ComposerContext";
import { ComposerContext, getDefaultContextValue } from "./ComposerContext";

interface ContentProps {
disabled?: boolean;
Expand Down Expand Up @@ -57,9 +57,10 @@ export function SendWysiwygComposer({
...props
}: SendWysiwygComposerProps) {
const Composer = isRichTextEnabled ? WysiwygComposer : PlainTextComposer;
const defaultContextValue = useRef(getDefaultContextValue());

return (
<ComposerContext.Provider value={defaultContext}>
<ComposerContext.Provider value={defaultContextValue.current}>
<Composer
className="mx_SendWysiwygComposer"
leftComponent={e2eStatus && <E2EIcon status={e2eStatus} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { KeyCombo } from "../../../../../KeyBindingsManager";
import { _td } from "../../../../../languageHandler";
import { ButtonEvent } from "../../../elements/AccessibleButton";
import { openLinkModal } from "./LinkModal";
import { useComposerContext } from "../ComposerContext";

interface TooltipProps {
label: string;
Expand Down Expand Up @@ -78,6 +79,8 @@ interface FormattingButtonsProps {
}

export function FormattingButtons({ composer, actionStates }: FormattingButtonsProps) {
const composerContext = useComposerContext();

return (
<div className="mx_FormattingButtons">
<Button
Expand Down Expand Up @@ -117,7 +120,7 @@ export function FormattingButtons({ composer, actionStates }: FormattingButtonsP
<Button
isActive={actionStates.link === "reversed"}
label={_td("Link")}
onClick={() => openLinkModal(composer)}
onClick={() => openLinkModal(composer, composerContext)}
icon={<LinkIcon className="mx_FormattingButtons_Icon" />}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ import { _td } from "../../../../../languageHandler";
import Modal from "../../../../../Modal";
import QuestionDialog from "../../../dialogs/QuestionDialog";
import Field from "../../../elements/Field";
import { useComposerContext } from "../ComposerContext";
import { ComposerContextState } from "../ComposerContext";
import { isSelectionEmpty, setSelection } from "../utils/selection";

export function openLinkModal(composer: FormattingFunctions) {
export function openLinkModal(composer: FormattingFunctions, composerContext: ComposerContextState) {
const modal = Modal.createDialog(
LinkModal,
{ composer, onClose: () => modal.close(), isTextEnabled: isSelectionEmpty() },
{ composerContext, composer, onClose: () => modal.close(), isTextEnabled: isSelectionEmpty() },
"mx_CompoundDialog",
false,
true,
Expand All @@ -42,11 +42,10 @@ interface LinkModalProps {
composer: FormattingFunctions;
isTextEnabled: boolean;
onClose: () => void;
composerContext: ComposerContextState;
}

export function LinkModal({ composer, isTextEnabled, onClose }: LinkModalProps) {
const composerContext = useComposerContext();

export function LinkModal({ composer, isTextEnabled, onClose, composerContext }: LinkModalProps) {
const [fields, setFields] = useState({ text: "", link: "" });
const isSaveDisabled = (isTextEnabled && isEmpty(fields.text)) || isEmpty(fields.link);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import { render, screen, waitFor } from "@testing-library/react";
import React from "react";
import userEvent from "@testing-library/user-event";

import { ComposerContext } from "../../../../../../src/components/views/rooms/wysiwyg_composer/ComposerContext";
import { LinkModal } from "../../../../../../src/components/views/rooms/wysiwyg_composer/components/LinkModal";
import { mockPlatformPeg } from "../../../../../test-utils";
import * as selection from "../../../../../../src/components/views/rooms/wysiwyg_composer/utils/selection";
Expand All @@ -38,9 +37,12 @@ describe("LinkModal", () => {

const customRender = (isTextEnabled: boolean, onClose: () => void) => {
return render(
<ComposerContext.Provider value={{ selection: defaultValue }}>
<LinkModal composer={composer} isTextEnabled={isTextEnabled} onClose={onClose} />
</ComposerContext.Provider>,
<LinkModal
composer={composer}
isTextEnabled={isTextEnabled}
onClose={onClose}
composerContext={{ selection: defaultValue }}
/>,
);
};

Expand Down

0 comments on commit 2d13d10

Please sign in to comment.