Add a button to upload images into comments (#6092)
This commit is contained in:
@@ -1,16 +1,22 @@
|
||||
import { m } from "framer-motion";
|
||||
import { action } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import { ImageIcon } from "outline-icons";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { VisuallyHidden } from "reakit";
|
||||
import { toast } from "sonner";
|
||||
import { useTheme } from "styled-components";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { CommentValidation } from "@shared/validations";
|
||||
import { getEventFiles } from "@shared/utils/files";
|
||||
import { AttachmentValidation, CommentValidation } from "@shared/validations";
|
||||
import Comment from "~/models/Comment";
|
||||
import Avatar from "~/components/Avatar";
|
||||
import ButtonSmall from "~/components/ButtonSmall";
|
||||
import { useDocumentContext } from "~/components/DocumentContext";
|
||||
import Flex from "~/components/Flex";
|
||||
import NudeButton from "~/components/NudeButton";
|
||||
import Tooltip from "~/components/Tooltip";
|
||||
import type { Editor as SharedEditor } from "~/editor";
|
||||
import useCurrentUser from "~/hooks/useCurrentUser";
|
||||
import useOnClickOutside from "~/hooks/useOnClickOutside";
|
||||
@@ -64,6 +70,8 @@ function CommentForm({
|
||||
const editorRef = React.useRef<SharedEditor>(null);
|
||||
const [forceRender, setForceRender] = React.useState(0);
|
||||
const [inputFocused, setInputFocused] = React.useState(autoFocus);
|
||||
const file = React.useRef<HTMLInputElement>(null);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const { comments } = useStores();
|
||||
const user = useCurrentUser();
|
||||
@@ -188,6 +196,23 @@ function CommentForm({
|
||||
onBlur?.();
|
||||
};
|
||||
|
||||
const handleFilePicked = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
const files = getEventFiles(event);
|
||||
if (!files.length) {
|
||||
return;
|
||||
}
|
||||
editorRef.current?.insertFiles(event, files);
|
||||
};
|
||||
|
||||
const handleImageUpload = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
file.current?.click();
|
||||
};
|
||||
|
||||
// Focus the editor when it's a new comment just mounted, after a delay as the
|
||||
// editor is mounted within a fade transition.
|
||||
React.useEffect(() => {
|
||||
@@ -227,6 +252,15 @@ function CommentForm({
|
||||
{...presence}
|
||||
{...rest}
|
||||
>
|
||||
<VisuallyHidden>
|
||||
<input
|
||||
ref={file}
|
||||
type="file"
|
||||
onChange={handleFilePicked}
|
||||
accept={AttachmentValidation.imageContentTypes.join(", ")}
|
||||
tabIndex={-1}
|
||||
/>
|
||||
</VisuallyHidden>
|
||||
<Flex gap={8} align="flex-start" reverse={dir === "rtl"}>
|
||||
<Avatar model={user} size={24} style={{ marginTop: 8 }} />
|
||||
<Bubble
|
||||
@@ -256,13 +290,20 @@ function CommentForm({
|
||||
}
|
||||
/>
|
||||
{(inputFocused || data) && (
|
||||
<Flex justify={dir === "rtl" ? "flex-end" : "flex-start"} gap={8}>
|
||||
<ButtonSmall type="submit" borderOnHover>
|
||||
{thread && !thread.isNew ? t("Reply") : t("Post")}
|
||||
</ButtonSmall>
|
||||
<ButtonSmall onClick={handleCancel} neutral borderOnHover>
|
||||
{t("Cancel")}
|
||||
</ButtonSmall>
|
||||
<Flex justify="space-between" reverse={dir === "rtl"} gap={8}>
|
||||
<Flex gap={8}>
|
||||
<ButtonSmall type="submit" borderOnHover>
|
||||
{thread && !thread.isNew ? t("Reply") : t("Post")}
|
||||
</ButtonSmall>
|
||||
<ButtonSmall onClick={handleCancel} neutral borderOnHover>
|
||||
{t("Cancel")}
|
||||
</ButtonSmall>
|
||||
</Flex>
|
||||
<Tooltip delay={500} tooltip={t("Upload image")} placement="top">
|
||||
<NudeButton onClick={handleImageUpload}>
|
||||
<ImageIcon color={theme.textTertiary} />
|
||||
</NudeButton>
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
)}
|
||||
</Bubble>
|
||||
|
||||
Reference in New Issue
Block a user