From 01c806d6ea3b674a732244d26384c4481063be3e Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Thu, 28 Dec 2023 21:31:40 -0500 Subject: [PATCH] fix: Comment form should not collapse with draft --- .../Document/components/CommentForm.tsx | 34 ++++++++++--------- .../Document/components/CommentThread.tsx | 15 ++++++-- app/scenes/Document/components/Comments.tsx | 9 +++++ 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/app/scenes/Document/components/CommentForm.tsx b/app/scenes/Document/components/CommentForm.tsx index 6eae5663d..6c4dadc67 100644 --- a/app/scenes/Document/components/CommentForm.tsx +++ b/app/scenes/Document/components/CommentForm.tsx @@ -8,6 +8,7 @@ import { VisuallyHidden } from "reakit"; import { toast } from "sonner"; import { useTheme } from "styled-components"; import { v4 as uuidv4 } from "uuid"; +import { ProsemirrorData } from "@shared/types"; import { getEventFiles } from "@shared/utils/files"; import { AttachmentValidation, CommentValidation } from "@shared/validations"; import Comment from "~/models/Comment"; @@ -20,12 +21,15 @@ import Tooltip from "~/components/Tooltip"; import type { Editor as SharedEditor } from "~/editor"; import useCurrentUser from "~/hooks/useCurrentUser"; import useOnClickOutside from "~/hooks/useOnClickOutside"; -import usePersistedState from "~/hooks/usePersistedState"; import useStores from "~/hooks/useStores"; import CommentEditor from "./CommentEditor"; import { Bubble } from "./CommentThreadItem"; type Props = { + /** Callback when the draft should be saved. */ + onSaveDraft: (data: ProsemirrorData | undefined) => void; + /** A draft comment for this thread. */ + draft?: ProsemirrorData; /** The document that the comment will be associated with */ documentId: string; /** The comment thread that the comment will be associated with */ @@ -51,6 +55,8 @@ type Props = { function CommentForm({ documentId, thread, + draft, + onSaveDraft, onTyping, onFocus, onBlur, @@ -62,10 +68,6 @@ function CommentForm({ ...rest }: Props) { const { editor } = useDocumentContext(); - const [data, setData] = usePersistedState | undefined>( - `draft-${documentId}-${!thread ? "new" : thread?.id}`, - undefined - ); const formRef = React.useRef(null); const editorRef = React.useRef(null); const [forceRender, setForceRender] = React.useState(0); @@ -92,7 +94,7 @@ function CommentForm({ const handleCreateComment = action(async (event: React.FormEvent) => { event.preventDefault(); - setData(undefined); + onSaveDraft(undefined); setForceRender((s) => ++s); setInputFocused(false); @@ -101,7 +103,7 @@ function CommentForm({ new Comment( { documentId, - data, + data: draft, }, comments ); @@ -109,7 +111,7 @@ function CommentForm({ comment .save({ documentId, - data, + data: draft, }) .catch(() => { comment.isNew = true; @@ -124,18 +126,18 @@ function CommentForm({ const handleCreateReply = action(async (event: React.FormEvent) => { event.preventDefault(); - if (!data) { + if (!draft) { return; } - setData(undefined); + onSaveDraft(undefined); setForceRender((s) => ++s); const comment = new Comment( { parentCommentId: thread?.id, documentId, - data, + data: draft, }, comments ); @@ -161,10 +163,10 @@ function CommentForm({ }); const handleChange = ( - value: (asString: boolean, trim: boolean) => Record + value: (asString: boolean, trim: boolean) => ProsemirrorData ) => { const text = value(true, true); - setData(text ? value(false, true) : undefined); + onSaveDraft(text ? value(false, true) : undefined); onTyping?.(); }; @@ -181,7 +183,7 @@ function CommentForm({ }; const handleCancel = async () => { - setData(undefined); + onSaveDraft(undefined); setForceRender((s) => ++s); setInputFocused(false); await reset(); @@ -274,7 +276,7 @@ function CommentForm({ - {(inputFocused || data) && ( + {(inputFocused || draft) && ( diff --git a/app/scenes/Document/components/CommentThread.tsx b/app/scenes/Document/components/CommentThread.tsx index ada63bcef..ca42f4df3 100644 --- a/app/scenes/Document/components/CommentThread.tsx +++ b/app/scenes/Document/components/CommentThread.tsx @@ -7,6 +7,7 @@ import scrollIntoView from "smooth-scroll-into-view-if-needed"; import styled, { css } from "styled-components"; import breakpoint from "styled-components-breakpoint"; import { s } from "@shared/styles"; +import { ProsemirrorData } from "@shared/types"; import Comment from "~/models/Comment"; import Document from "~/models/Document"; import Avatar from "~/components/Avatar"; @@ -17,6 +18,7 @@ import Typing from "~/components/Typing"; import { WebsocketContext } from "~/components/WebsocketProvider"; import useCurrentUser from "~/hooks/useCurrentUser"; import useOnClickOutside from "~/hooks/useOnClickOutside"; +import usePersistedState from "~/hooks/usePersistedState"; import usePolicy from "~/hooks/usePolicy"; import useStores from "~/hooks/useStores"; import { hover } from "~/styles"; @@ -138,6 +140,11 @@ function CommentThread({ } }, [focused, thread.id]); + const [draft, onSaveDraft] = usePersistedState( + `draft-${document.id}-${thread.id}`, + undefined + ); + return ( - {(focused || commentsInThread.length === 0) && can.comment && ( + {(focused || draft || commentsInThread.length === 0) && can.comment && ( )} - {!focused && !recessed && can.comment && ( + {!focused && !recessed && !draft && can.comment && ( setAutoFocus(true)}>{t("Reply")}… )} diff --git a/app/scenes/Document/components/Comments.tsx b/app/scenes/Document/components/Comments.tsx index 5fd73c133..a6b63a88c 100644 --- a/app/scenes/Document/components/Comments.tsx +++ b/app/scenes/Document/components/Comments.tsx @@ -4,12 +4,14 @@ import * as React from "react"; import { useTranslation } from "react-i18next"; import { useRouteMatch } from "react-router-dom"; import styled from "styled-components"; +import { ProsemirrorData } from "@shared/types"; import Empty from "~/components/Empty"; import Flex from "~/components/Flex"; import Scrollable from "~/components/Scrollable"; import useCurrentUser from "~/hooks/useCurrentUser"; import useFocusedComment from "~/hooks/useFocusedComment"; import useKeyDown from "~/hooks/useKeyDown"; +import usePersistedState from "~/hooks/usePersistedState"; import usePolicy from "~/hooks/usePolicy"; import useStores from "~/hooks/useStores"; import CommentForm from "./CommentForm"; @@ -27,6 +29,11 @@ function Comments() { useKeyDown("Escape", () => document && ui.collapseComments(document?.id)); + const [draft, onSaveDraft] = usePersistedState( + `draft-${document?.id}-new`, + undefined + ); + if (!document) { return null; } @@ -69,6 +76,8 @@ function Comments() { {!focusedComment && can.comment && (