From b534a44ae9f2e62b96c406a2a05be33c3a87ca6c Mon Sep 17 00:00:00 2001 From: Iacopo Leardini Date: Tue, 14 May 2024 16:46:21 +0200 Subject: [PATCH 01/24] refactor: Remove unused mediaFiles var in CommentBox component --- src/stories/chat/parts/commentBox.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/stories/chat/parts/commentBox.tsx b/src/stories/chat/parts/commentBox.tsx index c7078360..37a3b724 100644 --- a/src/stories/chat/parts/commentBox.tsx +++ b/src/stories/chat/parts/commentBox.tsx @@ -208,10 +208,6 @@ export const CommentBox = ({ ed.on("create", ({ editor }) => setEditor(editor as TipTapEditor)); ed.on("update", ({ editor }) => setEditor(editor as TipTapEditor)); - const mediaFiles = thumbnails.map((file) => { - return Object.assign(file, { isLoadingMedia: file.isLoadingMedia }); - }); - return ( <> {isOpen && selectedImage && ( @@ -225,7 +221,7 @@ export const CommentBox = ({ onSlideChange={slideChange} initialSlide={selectedImageIndex} > - {mediaFiles.map((item, index) => ( + {thumbnails.map((item, index) => ( {item.type.includes("image") && ( Date: Tue, 14 May 2024 17:30:56 +0200 Subject: [PATCH 02/24] refactor: use unique Lightbox component --- src/stories/chat/_types.tsx | 1 + src/stories/chat/index.stories.tsx | 44 +++++++-- src/stories/chat/parts/MediaLightbox.tsx | 63 +++++++++++++ src/stories/chat/parts/comment.tsx | 108 ++++++++--------------- src/stories/chat/parts/commentBox.tsx | 47 +++------- 5 files changed, 149 insertions(+), 114 deletions(-) create mode 100644 src/stories/chat/parts/MediaLightbox.tsx diff --git a/src/stories/chat/_types.tsx b/src/stories/chat/_types.tsx index 8c23a9f6..17f3fa1a 100644 --- a/src/stories/chat/_types.tsx +++ b/src/stories/chat/_types.tsx @@ -47,6 +47,7 @@ export interface FileItem extends File { isLoadingMedia: boolean; isError?: boolean; internal_id: string; + url?: string; } export interface FloatingMenuArgs extends Partial {} diff --git a/src/stories/chat/index.stories.tsx b/src/stories/chat/index.stories.tsx index 0bd63548..39738071 100644 --- a/src/stories/chat/index.stories.tsx +++ b/src/stories/chat/index.stories.tsx @@ -8,7 +8,7 @@ import { Col } from "../grid/col"; import { Grid } from "../grid/grid"; import { Row } from "../grid/row"; import { ChatEditorArgs, FileItem, SuggestedUser } from "./_types"; -import { Comment, MediaType } from "./parts/comment"; +import { Comment } from "./parts/comment"; import { theme } from "../theme"; import { Data } from "./context/chatContext"; import { ToastProvider } from "@zendeskgarden/react-notifications"; @@ -27,7 +27,7 @@ interface EditorStoryArgs extends ChatEditorArgs { }; message: string; date: string; - media?: MediaType[]; + media?: FileItem[]; }[]; editorText?: string; background?: string; @@ -37,7 +37,7 @@ interface EditorStoryArgs extends ChatEditorArgs { } const ChatPanel = ({ background, ...args }: EditorStoryArgs) => { - const { editor, triggerSave, clearInput } = useChatContext(); + const { triggerSave, clearInput } = useChatContext(); return ( @@ -212,12 +212,46 @@ const defaultArgs: EditorStoryArgs = { { url: "https://images.unsplash.com/photo-1638799692504-9b3c0093d54d?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", type: "image", - id: 1, + internal_id: "1", + isLoadingMedia: false, + lastModified: 0, + name: "", + webkitRelativePath: "", + size: 0, + arrayBuffer: function (): Promise { + throw new Error("Function not implemented."); + }, + slice: function (start?: number | undefined, end?: number | undefined, contentType?: string | undefined): Blob { + throw new Error("Function not implemented."); + }, + stream: function (): ReadableStream { + throw new Error("Function not implemented."); + }, + text: function (): Promise { + throw new Error("Function not implemented."); + } }, { url: "https://images.unsplash.com/photo-1544085311-11a028465b03?q=80&w=1932&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", type: "image", - id: 2, + internal_id: "2", + isLoadingMedia: false, + lastModified: 0, + name: "", + webkitRelativePath: "", + size: 0, + arrayBuffer: function (): Promise { + throw new Error("Function not implemented."); + }, + slice: function (start?: number | undefined, end?: number | undefined, contentType?: string | undefined): Blob { + throw new Error("Function not implemented."); + }, + stream: function (): ReadableStream { + throw new Error("Function not implemented."); + }, + text: function (): Promise { + throw new Error("Function not implemented."); + } }, ], }, diff --git a/src/stories/chat/parts/MediaLightbox.tsx b/src/stories/chat/parts/MediaLightbox.tsx new file mode 100644 index 00000000..c8a23f02 --- /dev/null +++ b/src/stories/chat/parts/MediaLightbox.tsx @@ -0,0 +1,63 @@ +import { Lightbox } from "../../lightbox"; +import { Slider } from "../../slider"; +import { FileItem } from "../_types"; +import { Player } from "../../player"; + +interface MediaLightBoxProps { + isOpen: boolean; + header: React.ReactNode; + onClose: () => void; + slideChange: (index: number) => void; + selectedImageIndex: number; + thumbnails: FileItem[]; + videoRefs: React.MutableRefObject>; + details?: React.ReactNode; +}; + +const MediaLightBox = ({header, onClose, slideChange, selectedImageIndex, thumbnails, videoRefs, isOpen, details}: MediaLightBoxProps) => { + if (!isOpen) { + return null; + } + return ( + + {header} + + + } + nextArrow={} + onSlideChange={slideChange} + initialSlide={selectedImageIndex} + > + {thumbnails.map((item) => ( + + {item.type.includes("image") && ( + {`media + )} + {item.type.includes("video") && ( + { + videoRefs.current.push(ref); + }} + url={item.url || URL.createObjectURL(item)} + /> + )} + + ))} + + + {details && ( + + {details} + + )} + + + + ); +} + +export default MediaLightBox; \ No newline at end of file diff --git a/src/stories/chat/parts/comment.tsx b/src/stories/chat/parts/comment.tsx index 2fda030d..e2c0728c 100644 --- a/src/stories/chat/parts/comment.tsx +++ b/src/stories/chat/parts/comment.tsx @@ -2,21 +2,19 @@ import { PropsWithChildren, useCallback, useRef, useState } from "react"; import { Title } from "../../title"; import { Card } from "../../cards"; import { styled } from "styled-components"; -import { Author } from "../_types"; +import { Author, FileItem } from "../_types"; import { Avatar } from "../../avatar"; import { useChatContext } from "../context/chatContext"; import { Content, useEditor, EditorContent } from "@tiptap/react"; import { editorExtensions } from "./extensions"; import { EditorContainer } from "./containers"; -import { Lightbox } from "../../lightbox"; -import { Slider } from "../../slider"; import { MD } from "@zendeskgarden/react-typography"; -import { Player } from "../../player"; import { Grid } from "../../grid/grid"; import { Row } from "../../grid/row"; import { Col } from "../../grid/col"; import ImageThumbnail from "./ThumbnailContainer/ImageThumbnail"; import VideoThumbnail from "./ThumbnailContainer/VideoThumbnail"; +import MediaLightBox from "./MediaLightbox"; const CommentCard = styled(Card)` padding: ${({ theme }) => `${theme.space.base * 3}px ${theme.space.sm}`}; @@ -64,12 +62,6 @@ const Grey800Span = styled.span` color: ${({ theme }) => theme.palette.grey[800]}; `; -export type MediaType = { - url: string; - id: number; - type: "image" | "video"; -}; - export const Comment = ({ author, message, @@ -81,7 +73,7 @@ export const Comment = ({ author: Author; message: string; date: string; - media?: MediaType[]; + media?: FileItem[]; header: { title: string; message?: string; @@ -89,14 +81,14 @@ export const Comment = ({ }>) => { const { mentionableUsers } = useChatContext(); const [isOpen, setIsOpen] = useState(false); - const [selectedImage, setSelectedImage] = useState( - {} as MediaType + const [selectedImage, setSelectedImage] = useState( + {} as FileItem ); const [selectedImageIndex, setSelectedImageIndex] = useState(0); const ext = editorExtensions({ mentionableUsers }); - const handleClickThumbnail = (file: MediaType, index: number) => { + const handleClickThumbnail = (file: FileItem, index: number) => { if (!file) throw Error("Error with the image"); setSelectedImage(file); @@ -164,7 +156,7 @@ export const Comment = ({ - {isOpen && selectedImage && ( - - - - {header && header.title} - {header && header.message && ( - | {header.message} - )} - - - - - } - nextArrow={} - onSlideChange={slideChange} - initialSlide={selectedImageIndex} - > - {media.map((item, index) => ( - - {item.type === "image" && ( - {`{{${item.url}}}`} - )} - {item.type === "video" && ( - { - videoRefs.current.push(ref); - }} - url={item.url} - /> - )} - - ))} - - - - - <> -
- -
-
-
- - - -
- )} - + + {header && header.title} + {header && header.message && ( + | {header.message} + )} + } + onClose={closeLightbox} + slideChange={slideChange} + selectedImageIndex={selectedImageIndex} + thumbnails={media} + videoRefs={videoRefs} + details={ + <> +
+ +
} + />
{children}
); diff --git a/src/stories/chat/parts/commentBox.tsx b/src/stories/chat/parts/commentBox.tsx index 37a3b724..28626a98 100644 --- a/src/stories/chat/parts/commentBox.tsx +++ b/src/stories/chat/parts/commentBox.tsx @@ -27,6 +27,8 @@ import ThumbnailContainer from "./ThumbnailContainer"; import { Lightbox } from "../../lightbox"; import { Slider } from "../../slider"; import { Player } from "../../player"; +import { Media } from "../../slider/index.stories"; +import MediaLightBox from "./MediaLightbox"; const ChatBoxContainer = styled.div` display: flex; @@ -210,42 +212,15 @@ export const CommentBox = ({ return ( <> - {isOpen && selectedImage && ( - - {selectedImage.name} - - - } - nextArrow={} - onSlideChange={slideChange} - initialSlide={selectedImageIndex} - > - {thumbnails.map((item, index) => ( - - {item.type.includes("image") && ( - {`media - )} - {item.type.includes("video") && ( - { - videoRefs.current.push(ref); - }} - url={URL.createObjectURL(item)} - /> - )} - - ))} - - - - - - )} - + {hasFloatingMenu && ( From 1bb093d07c9c5c448b9e64255987f25adc8d49db Mon Sep 17 00:00:00 2001 From: Kariamos Date: Wed, 15 May 2024 10:30:04 +0200 Subject: [PATCH 03/24] refactor: removed unused state --- src/stories/chat/parts/comment.tsx | 51 +++++++++++++++--------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/src/stories/chat/parts/comment.tsx b/src/stories/chat/parts/comment.tsx index e2c0728c..95c815e9 100644 --- a/src/stories/chat/parts/comment.tsx +++ b/src/stories/chat/parts/comment.tsx @@ -81,9 +81,7 @@ export const Comment = ({ }>) => { const { mentionableUsers } = useChatContext(); const [isOpen, setIsOpen] = useState(false); - const [selectedImage, setSelectedImage] = useState( - {} as FileItem - ); + const [selectedImageIndex, setSelectedImageIndex] = useState(0); const ext = editorExtensions({ mentionableUsers }); @@ -91,7 +89,6 @@ export const Comment = ({ const handleClickThumbnail = (file: FileItem, index: number) => { if (!file) throw Error("Error with the image"); - setSelectedImage(file); setSelectedImageIndex(index); setIsOpen(true); }; @@ -104,7 +101,6 @@ export const Comment = ({ const slideChange = useCallback( (index: number) => { - setSelectedImage(media[index]); setSelectedImageIndex(index); videoRefs.current.forEach((ref) => { if (ref) { @@ -137,8 +133,7 @@ export const Comment = ({
- {author.name ?? "User"}{" "} - {date} + {author.name ?? "User"} {date} @@ -187,30 +182,34 @@ export const Comment = ({ - {header && header.title} - {header && header.message && ( - | {header.message} - )} - } + header={ + + {header && header.title} + {header && header.message && ( + | {header.message} + )} + + } onClose={closeLightbox} slideChange={slideChange} selectedImageIndex={selectedImageIndex} thumbnails={media} videoRefs={videoRefs} - details={ - <> -
- -
} + details={ + + <> +
+ +
+ } />
{children}
From 33db7ed540512b158b72e122f748879b1cfd5488 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Wed, 15 May 2024 10:30:32 +0200 Subject: [PATCH 04/24] refactor: removed unused import --- src/stories/chat/_types.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/stories/chat/_types.tsx b/src/stories/chat/_types.tsx index 17f3fa1a..555519e7 100644 --- a/src/stories/chat/_types.tsx +++ b/src/stories/chat/_types.tsx @@ -1,6 +1,5 @@ import { PlaceholderOptions } from "@tiptap/extension-placeholder"; import { BubbleMenuProps, EditorOptions } from "@tiptap/react"; -import { isError } from "util"; type validationStatus = "success" | "warning" | "error"; From e37192d83723905465ecfd70346627235d8b0cb4 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Wed, 15 May 2024 10:35:49 +0200 Subject: [PATCH 05/24] refactor: removed useless state and imports --- src/stories/chat/parts/commentBox.tsx | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/stories/chat/parts/commentBox.tsx b/src/stories/chat/parts/commentBox.tsx index 28626a98..8dd52409 100644 --- a/src/stories/chat/parts/commentBox.tsx +++ b/src/stories/chat/parts/commentBox.tsx @@ -24,10 +24,6 @@ import { CommentBar } from "./bar"; import { editorExtensions } from "./extensions"; import { EditorContainer } from "./containers"; import ThumbnailContainer from "./ThumbnailContainer"; -import { Lightbox } from "../../lightbox"; -import { Slider } from "../../slider"; -import { Player } from "../../player"; -import { Media } from "../../slider/index.stories"; import MediaLightBox from "./MediaLightbox"; const ChatBoxContainer = styled.div` @@ -66,7 +62,6 @@ export const CommentBox = ({ const { addToast } = useToast(); const [isOpen, setIsOpen] = useState(false); - const [selectedImage, setSelectedImage] = useState({} as File); const [selectedImageIndex, setSelectedImageIndex] = useState(0); const ext = editorExtensions({ placeholderOptions, mentionableUsers }); @@ -91,7 +86,6 @@ export const CommentBox = ({ const handleOpenLightbox = (file: File, index: number) => { if (!file) throw Error("Error with the image"); - setSelectedImage(file); setSelectedImageIndex(index); setIsOpen(true); }; @@ -152,7 +146,6 @@ export const CommentBox = ({ }, handlePaste: (view, event, slice) => { - if (!event.clipboardData || !event.clipboardData.items) return false; event.preventDefault(); @@ -189,7 +182,7 @@ export const CommentBox = ({ /^(image|video)\//.test(file.type) ); if (mediaFiles.length === 0) return false; - + addThumbnails({ files: mediaFiles }); return false; @@ -214,7 +207,7 @@ export const CommentBox = ({ <> Date: Wed, 15 May 2024 11:30:19 +0200 Subject: [PATCH 06/24] refactor: refactored handledrop and handlepaste media --- src/stories/chat/parts/commentBox.tsx | 120 +++++++++----------------- 1 file changed, 41 insertions(+), 79 deletions(-) diff --git a/src/stories/chat/parts/commentBox.tsx b/src/stories/chat/parts/commentBox.tsx index 8dd52409..24416d7f 100644 --- a/src/stories/chat/parts/commentBox.tsx +++ b/src/stories/chat/parts/commentBox.tsx @@ -66,6 +66,45 @@ export const CommentBox = ({ const ext = editorExtensions({ placeholderOptions, mentionableUsers }); + function handleEvent(data: DataTransfer | null) { + if (!data || !data.files) return; + addThumbnails({ files: createFiles(data.files) }); + } + function checkFiles(data: FileList): File[] { + const wrongFiles = Array.from(data).filter( + (file) => !/^(image|video)\//.test(file.type) + ); + if (wrongFiles.length > 0) { + for (const file of wrongFiles) { + addToast( + ({ close }) => ( + + ), + { placement: "top" } + ); + } + } + + return Array.from(data).filter((file) => + /^(image|video)\//.test(file.type) + ); + } + + function createFiles(data: FileList): FileItem[] { + const files = checkFiles(data); + return files.map((file) => { + return Object.assign(file, { + isLoadingMedia: false, + internal_id: uuidv4(), + }); + }); + } + const closeLightbox = () => { setIsOpen(false); }; @@ -102,90 +141,13 @@ export const CommentBox = ({ }, handleDrop: function (view, event, slice, moved) { - if (!event.dataTransfer || !event.dataTransfer.files) return false; - event.preventDefault(); - - const files: FileItem[] = Array.from(event.dataTransfer.files).map( - (file) => { - return Object.assign(file, { - isLoadingMedia: false, - internal_id: uuidv4(), - }); - } - ); - const wrongFiles = files.filter( - (file) => !/^(image|video)\//.test(file.type) - ); - - if (wrongFiles.length > 0) { - for (const file of wrongFiles) { - addToast( - ({ close }) => ( - - ), - { placement: "top" } - ); - } - } - - const mediaFiles: FileItem[] = files.filter((file) => - /^(image|video)\//.test(file.type) - ); - - if (mediaFiles.length === 0) return false; - - addThumbnails({ files: mediaFiles }); - - return false; + handleEvent(event.dataTransfer); }, handlePaste: (view, event, slice) => { - if (!event.clipboardData || !event.clipboardData.items) return false; - event.preventDefault(); - - const files: FileItem[] = Array.from(event.clipboardData.files).map( - (file) => { - return Object.assign(file, { - isLoadingMedia: false, - internal_id: uuidv4(), - }); - } - ); - const wrongFiles = files.filter( - (file) => !/^(image|video)\//.test(file.type) - ); - - if (wrongFiles.length > 0) { - for (const file of wrongFiles) { - addToast( - ({ close }) => ( - - ), - { placement: "top" } - ); - } - } - - const mediaFiles: FileItem[] = files.filter((file) => - /^(image|video)\//.test(file.type) - ); - if (mediaFiles.length === 0) return false; - - addThumbnails({ files: mediaFiles }); - - return false; + handleEvent(event.clipboardData); }, }, ...props, From b0722cbe71c9ca15c1f86e0c5ed0c75f5b7886bd Mon Sep 17 00:00:00 2001 From: Kariamos Date: Wed, 15 May 2024 11:38:33 +0200 Subject: [PATCH 07/24] refactor: refactored add media from clipper icon --- src/stories/chat/parts/bar.tsx | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/stories/chat/parts/bar.tsx b/src/stories/chat/parts/bar.tsx index 0c146683..985838c8 100644 --- a/src/stories/chat/parts/bar.tsx +++ b/src/stories/chat/parts/bar.tsx @@ -75,18 +75,15 @@ const CommentBar = ({ fileInput.click(); fileInput.onchange = () => { - const files = fileInput.files; - if (files) { - const mediaFiles: FileItem[] = Array.from(files).map((file) => { - return Object.assign(file, { - isLoadingMedia: false, - internal_id: uuidv4(), - }); + if (fileInput.files) { + addThumbnails({ + files: Array.from(fileInput.files).map((file) => { + return Object.assign(file, { + isLoadingMedia: false, + internal_id: uuidv4(), + }); + }), }); - - if (mediaFiles.length === 0) return; - - addThumbnails({ files: mediaFiles }); } }; return; From 57bf7a1c0f5dcef6c1a9504336bd1cfbdb281992 Mon Sep 17 00:00:00 2001 From: Iacopo Leardini Date: Wed, 15 May 2024 12:58:08 +0200 Subject: [PATCH 08/24] refactor: Improve thumbnail container and remove unused code --- .../ThumbnailContainer/DeleteThumbnailX.tsx | 1 + .../ThumbnailContainer/ImageThumbnail.tsx | 81 ----------- .../parts/ThumbnailContainer/Thumbnail.tsx | 129 ++++++++++++++++++ .../ThumbnailContainer/VideoThumbnail.tsx | 115 ---------------- .../chat/parts/ThumbnailContainer/index.tsx | 63 +++------ src/stories/chat/parts/comment.tsx | 51 ++----- 6 files changed, 164 insertions(+), 276 deletions(-) delete mode 100644 src/stories/chat/parts/ThumbnailContainer/ImageThumbnail.tsx create mode 100644 src/stories/chat/parts/ThumbnailContainer/Thumbnail.tsx delete mode 100644 src/stories/chat/parts/ThumbnailContainer/VideoThumbnail.tsx diff --git a/src/stories/chat/parts/ThumbnailContainer/DeleteThumbnailX.tsx b/src/stories/chat/parts/ThumbnailContainer/DeleteThumbnailX.tsx index bfe917a9..76ef6bf0 100644 --- a/src/stories/chat/parts/ThumbnailContainer/DeleteThumbnailX.tsx +++ b/src/stories/chat/parts/ThumbnailContainer/DeleteThumbnailX.tsx @@ -10,6 +10,7 @@ const StyledDeleteThumbnailX = styled.div` width: 32px; height: 32px; opacity: 0; + transition: opacity 0.2s; z-index: 2; `; diff --git a/src/stories/chat/parts/ThumbnailContainer/ImageThumbnail.tsx b/src/stories/chat/parts/ThumbnailContainer/ImageThumbnail.tsx deleted file mode 100644 index 856c88df..00000000 --- a/src/stories/chat/parts/ThumbnailContainer/ImageThumbnail.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import styled from "styled-components"; -import DeleteThumbnailX from "./DeleteThumbnailX"; -import { Spinner } from "@zendeskgarden/react-loaders"; -import { SpecialCard } from "../../../special-cards"; - -const ImageCard = styled(SpecialCard)` - padding: 0; - :hover .deleteThumbnail { - opacity: 1; - } -`; - -const Preview = styled.div<{ - url: string; -}>` - display: flex; - justify-content: center; - align-items: center; - height: 150px; - width: 100%; - background-image: url(${(props) => props.url}); - background-color: ${({ theme }) => theme.palette.grey[100]}; - background-size: contain; - background-position: center; - background-repeat: no-repeat; -`; - -interface Props { - src: string; - index?: number; - removeThumbnail?: (index: number) => void; - clickThumbnail: () => void; - showX?: boolean; - isLoadingMedia: boolean; - isError?: boolean; -} - -const ImageThumbnail = ({ - src, - index = 0, - removeThumbnail, - clickThumbnail, - showX = true, - isLoadingMedia = true, - isError = false, -}: Props) => { - const handleCancel = (e: any) => { - e.stopPropagation(); - if (removeThumbnail) removeThumbnail(index); - }; - - return ( - - {isLoadingMedia && ( - - - - )} - {isError && ( - // todo: add error icon - error uploading media - )} - {!isLoadingMedia && ( - - {showX && ( - handleCancel(e)} /> - )} - - )} - - ); -}; - -export default ImageThumbnail; diff --git a/src/stories/chat/parts/ThumbnailContainer/Thumbnail.tsx b/src/stories/chat/parts/ThumbnailContainer/Thumbnail.tsx new file mode 100644 index 00000000..68e5e6c5 --- /dev/null +++ b/src/stories/chat/parts/ThumbnailContainer/Thumbnail.tsx @@ -0,0 +1,129 @@ +import styled from "styled-components"; +import DeleteThumbnailX from "./DeleteThumbnailX"; +import { Spinner } from "@zendeskgarden/react-loaders"; +import { SpecialCard } from "../../../special-cards"; +import {ReactComponent as VideoPlayIcon} from "../../../../assets/icons/video-play-icon.svg"; + +const ImageCard = styled(SpecialCard)` + padding: 0; + position: relative; + overflow: hidden; + + &:before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: ${({ theme }) => theme.palette.grey[800]}; + opacity: 0; + transition: opacity 0.2s; + z-index: 1; + } + + &:hover { + .deleteThumbnail { + opacity: 1; + } + &:before { + opacity: 0.3; + } + } + + &.video{ + + svg { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 32px; + height: 32px; + z-index: 2; + } + } +`; + +const Preview = styled.div<{ + url?: string; +}>` + display: flex; + justify-content: center; + align-items: center; + height: 150px; + width: 100%; + + ${p => p.url && ` + background-image: url(${p.url}); + background-color: ${p.theme.palette.grey[100]}; + background-size: contain; + background-position: center; + background-repeat: no-repeat; + `} + + > video { + width: 100%; + height: 100%; + } +`; + +interface Props { + src: string; + type: string; + clickThumbnail?: () => void; + isLoadingMedia?: boolean; + removeThumbnail?: () => void; + showX?: boolean; + isError?: boolean; +} + +const Thumbnail = ({ + src, + type, + removeThumbnail, + clickThumbnail, + showX, + isLoadingMedia = true, + isError = false, +}: Props) => { + const handleCancel = (e: any) => { + e.stopPropagation(); + if (removeThumbnail) removeThumbnail(); + }; + + return ( + + {isError && ( + // todo: add error icon + error uploading media + )} + {isLoadingMedia ? ( + + + + ) : ( + + {showX && ( + handleCancel(e)} /> + )} + {type.includes('video') && <> + + + } + + )} + + ); +}; + +export default Thumbnail; diff --git a/src/stories/chat/parts/ThumbnailContainer/VideoThumbnail.tsx b/src/stories/chat/parts/ThumbnailContainer/VideoThumbnail.tsx deleted file mode 100644 index c2a78a5a..00000000 --- a/src/stories/chat/parts/ThumbnailContainer/VideoThumbnail.tsx +++ /dev/null @@ -1,115 +0,0 @@ -import styled from "styled-components"; -import DeleteThumbnailX from "./DeleteThumbnailX"; -import { Spinner } from "@zendeskgarden/react-loaders"; -import { SpecialCard } from "../../../special-cards"; -import { ReactComponent as VideoPlayIcon } from "../../../../assets/icons/video-play-icon.svg"; - -const VideoCard = styled(SpecialCard)` - padding: 0; - position: relative; - overflow: hidden; - - &:hover .deleteThumbnail { - opacity: 1; - z-index: 9999; - } - - &:before { - content: ""; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-color: ${({ theme }) => theme.palette.grey[800]}; - opacity: 0.3; - z-index: 1; - } - - > svg { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 32px; - height: 32px; - z-index: 2; - } -`; - -const Preview = styled.div` - padding: ${({ theme }) => theme.space.md}; - display: flex; - justify-content: center; - align-items: center; - height: 150px; - width: 100%; - - > video { - width: 100%; - height: 100%; - } -`; - -interface Props { - src: string; - index?: number; - removeThumbnail?: (index: number) => void; - clickThumbnail: () => void; - showX?: boolean; - isLoadingMedia: boolean; - isError?: boolean; -} - -const VideoThumbnail = ({ - src, - index = 0, - removeThumbnail, - clickThumbnail, - showX = true, - isLoadingMedia = true, - isError = false, -}: Props) => { - const handleCancel = (e: any) => { - e.stopPropagation(); - if (removeThumbnail) removeThumbnail(index); - }; - - return ( - - {isLoadingMedia && ( - - - - )} - {isError && ( - // todo: add error icon - error uploading media - )} - {!isLoadingMedia && ( - <> - {showX && ( - handleCancel(e)}/> - )} - - - - - - - )} - - - ); -}; - -export default VideoThumbnail; diff --git a/src/stories/chat/parts/ThumbnailContainer/index.tsx b/src/stories/chat/parts/ThumbnailContainer/index.tsx index 2dec11ab..4c98bf7e 100644 --- a/src/stories/chat/parts/ThumbnailContainer/index.tsx +++ b/src/stories/chat/parts/ThumbnailContainer/index.tsx @@ -1,5 +1,4 @@ -import ImageThumbnail from "./ImageThumbnail"; -import VideoThumbnail from "./VideoThumbnail"; +import Thumbnail from "./Thumbnail"; import { useChatContext } from "../../context/chatContext"; import { Grid } from "../../../grid/grid"; import { Row } from "../../../grid/row"; @@ -39,48 +38,24 @@ const ThumbnailContainer = ({ openLightbox }: Props) => { return ( - {mediaFiles.map((file, index) => { - // Check if item is an image or a video - if (file.fileType.includes("image")) - return ( - - { - removeThumbnail(index); - onDeleteThumbnail(file.internal_id); - }} - clickThumbnail={() => { - openLightbox(thumbnails[index], index); - }} - /> - - ); - if (file.fileType.includes("video")) - return ( - - { - removeThumbnail(index); - onDeleteThumbnail(file.internal_id); - }} - clickThumbnail={() => { - openLightbox(thumbnails[index], index); - }} - /> - - ); - return null; - })} + {mediaFiles.map((file, index) => ( + + { + removeThumbnail(index); + onDeleteThumbnail(file.internal_id); + }} + clickThumbnail={() => { + openLightbox(thumbnails[index], index); + }} + /> + + ))} ); diff --git a/src/stories/chat/parts/comment.tsx b/src/stories/chat/parts/comment.tsx index 95c815e9..622349a6 100644 --- a/src/stories/chat/parts/comment.tsx +++ b/src/stories/chat/parts/comment.tsx @@ -12,8 +12,7 @@ import { MD } from "@zendeskgarden/react-typography"; import { Grid } from "../../grid/grid"; import { Row } from "../../grid/row"; import { Col } from "../../grid/col"; -import ImageThumbnail from "./ThumbnailContainer/ImageThumbnail"; -import VideoThumbnail from "./ThumbnailContainer/VideoThumbnail"; +import Thumbnail from "./ThumbnailContainer/Thumbnail"; import MediaLightBox from "./MediaLightbox"; const CommentCard = styled(Card)` @@ -144,40 +143,20 @@ export const Comment = ({ - {media.map((file, index) => { - // Check if item is an image or a video - if (file.type.includes("image")) - return ( - - { - handleClickThumbnail(file, index); - }} - /> - - ); - if (file.type.includes("video")) - return ( - - { - handleClickThumbnail(file, index); - }} - /> - - ); - return null; - })} + {media.map((file, index) => ( + + { + handleClickThumbnail(file, index); + }} + /> + + ))} Date: Wed, 15 May 2024 15:03:32 +0200 Subject: [PATCH 09/24] fix: fixed error for one or multiple files not supported --- src/stories/chat/_types.tsx | 2 +- src/stories/chat/index.stories.tsx | 17 +++++++++--- src/stories/chat/parts/commentBox.tsx | 39 +++++++++++++++++---------- 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/src/stories/chat/_types.tsx b/src/stories/chat/_types.tsx index 555519e7..31130b96 100644 --- a/src/stories/chat/_types.tsx +++ b/src/stories/chat/_types.tsx @@ -8,7 +8,7 @@ export type SuggestedUser = { id: number; name: string; email: string }; export interface ChatEditorArgs extends Partial { author: Author; messageBadFileFormat: string; - + messageBadFileFormatMultiple: string; placeholderOptions?: Partial; hasFloatingMenu?: boolean; hasButtonsMenu?: boolean; diff --git a/src/stories/chat/index.stories.tsx b/src/stories/chat/index.stories.tsx index 39738071..dea1ec67 100644 --- a/src/stories/chat/index.stories.tsx +++ b/src/stories/chat/index.stories.tsx @@ -221,7 +221,11 @@ const defaultArgs: EditorStoryArgs = { arrayBuffer: function (): Promise { throw new Error("Function not implemented."); }, - slice: function (start?: number | undefined, end?: number | undefined, contentType?: string | undefined): Blob { + slice: function ( + start?: number | undefined, + end?: number | undefined, + contentType?: string | undefined + ): Blob { throw new Error("Function not implemented."); }, stream: function (): ReadableStream { @@ -229,7 +233,7 @@ const defaultArgs: EditorStoryArgs = { }, text: function (): Promise { throw new Error("Function not implemented."); - } + }, }, { url: "https://images.unsplash.com/photo-1544085311-11a028465b03?q=80&w=1932&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", @@ -243,7 +247,11 @@ const defaultArgs: EditorStoryArgs = { arrayBuffer: function (): Promise { throw new Error("Function not implemented."); }, - slice: function (start?: number | undefined, end?: number | undefined, contentType?: string | undefined): Blob { + slice: function ( + start?: number | undefined, + end?: number | undefined, + contentType?: string | undefined + ): Blob { throw new Error("Function not implemented."); }, stream: function (): ReadableStream { @@ -251,12 +259,13 @@ const defaultArgs: EditorStoryArgs = { }, text: function (): Promise { throw new Error("Function not implemented."); - } + }, }, ], }, ], messageBadFileFormat: "Format not supported, please upload video or image", + messageBadFileFormatMultiple: "Some uploaded files are not supported", }; export const Default = Template.bind({}); diff --git a/src/stories/chat/parts/commentBox.tsx b/src/stories/chat/parts/commentBox.tsx index 24416d7f..55951c01 100644 --- a/src/stories/chat/parts/commentBox.tsx +++ b/src/stories/chat/parts/commentBox.tsx @@ -74,20 +74,31 @@ export const CommentBox = ({ const wrongFiles = Array.from(data).filter( (file) => !/^(image|video)\//.test(file.type) ); - if (wrongFiles.length > 0) { - for (const file of wrongFiles) { - addToast( - ({ close }) => ( - - ), - { placement: "top" } - ); - } + if (wrongFiles.length === 1) { + addToast( + ({ close }) => ( + + ), + { placement: "top" } + ); + } + if (wrongFiles.length > 1) { + addToast( + ({ close }) => ( + + ), + { placement: "top" } + ); } return Array.from(data).filter((file) => From 02bde0a7d0d7cbdfa002313c57418f80989666bc Mon Sep 17 00:00:00 2001 From: Kariamos Date: Wed, 15 May 2024 15:19:26 +0200 Subject: [PATCH 10/24] refactor: refactored error message --- src/stories/chat/parts/commentBox.tsx | 28 ++++++++++----------------- 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/src/stories/chat/parts/commentBox.tsx b/src/stories/chat/parts/commentBox.tsx index 55951c01..bb932358 100644 --- a/src/stories/chat/parts/commentBox.tsx +++ b/src/stories/chat/parts/commentBox.tsx @@ -26,6 +26,8 @@ import { EditorContainer } from "./containers"; import ThumbnailContainer from "./ThumbnailContainer"; import MediaLightBox from "./MediaLightbox"; +export const acceptedMediaTypes = /^(image|video)\//; + const ChatBoxContainer = styled.div` display: flex; border-top: 1px solid ${({ theme }) => theme.palette.grey[200]}; @@ -72,37 +74,27 @@ export const CommentBox = ({ } function checkFiles(data: FileList): File[] { const wrongFiles = Array.from(data).filter( - (file) => !/^(image|video)\//.test(file.type) + (file) => !acceptedMediaTypes.test(file.type) ); - if (wrongFiles.length === 1) { + if (wrongFiles.length) { addToast( ({ close }) => ( ), { placement: "top" } ); } - if (wrongFiles.length > 1) { - addToast( - ({ close }) => ( - - ), - { placement: "top" } - ); - } - return Array.from(data).filter((file) => - /^(image|video)\//.test(file.type) + acceptedMediaTypes.test(file.type) ); } From ba608f9a69727ec0000fabed131f9c09566ed074 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Wed, 15 May 2024 15:49:24 +0200 Subject: [PATCH 11/24] refactor: changed name of method checkfiles to getValidMedia, removed unnecessary assignment of isloadingmedia = true --- src/stories/chat/context/chatContext.tsx | 11 +++++++---- src/stories/chat/parts/bar.tsx | 2 +- src/stories/chat/parts/commentBox.tsx | 7 +++---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/stories/chat/context/chatContext.tsx b/src/stories/chat/context/chatContext.tsx index 972a9e8d..90103e6a 100644 --- a/src/stories/chat/context/chatContext.tsx +++ b/src/stories/chat/context/chatContext.tsx @@ -1,5 +1,11 @@ import { Editor } from "@tiptap/react"; -import React, { createContext, useContext, useMemo, useState } from "react"; +import React, { + createContext, + useContext, + useEffect, + useMemo, + useState, +} from "react"; import { FileItem, SuggestedUser } from "../_types"; export type ChatContextType = { @@ -77,13 +83,11 @@ export const ChatContextProvider = ({ }, addThumbnails: ({ files }: { files: FileItem[] }) => { - files.forEach((file) => (file.isLoadingMedia = true)); setThumbnails((prev) => [...prev, ...files]); if (onFileUpload) { onFileUpload(files).then((data: Data) => { const failed = data.failed?.map((f) => f.name); - setThumbnails((prev) => { return prev.map((file) => { file.isLoadingMedia = false; @@ -103,7 +107,6 @@ export const ChatContextProvider = ({ editor.commands.clearContent(); } if (thumbnails.length > 0) setThumbnails([]); - }, onDeleteThumbnail: (id: string) => { diff --git a/src/stories/chat/parts/bar.tsx b/src/stories/chat/parts/bar.tsx index 985838c8..e35a649c 100644 --- a/src/stories/chat/parts/bar.tsx +++ b/src/stories/chat/parts/bar.tsx @@ -79,7 +79,7 @@ const CommentBar = ({ addThumbnails({ files: Array.from(fileInput.files).map((file) => { return Object.assign(file, { - isLoadingMedia: false, + isLoadingMedia: true, internal_id: uuidv4(), }); }), diff --git a/src/stories/chat/parts/commentBox.tsx b/src/stories/chat/parts/commentBox.tsx index bb932358..06634114 100644 --- a/src/stories/chat/parts/commentBox.tsx +++ b/src/stories/chat/parts/commentBox.tsx @@ -72,7 +72,7 @@ export const CommentBox = ({ if (!data || !data.files) return; addThumbnails({ files: createFiles(data.files) }); } - function checkFiles(data: FileList): File[] { + function getValidMedia(data: FileList): File[] { const wrongFiles = Array.from(data).filter( (file) => !acceptedMediaTypes.test(file.type) ); @@ -99,10 +99,9 @@ export const CommentBox = ({ } function createFiles(data: FileList): FileItem[] { - const files = checkFiles(data); - return files.map((file) => { + return getValidMedia(data).map((file) => { return Object.assign(file, { - isLoadingMedia: false, + isLoadingMedia: true, internal_id: uuidv4(), }); }); From f296ed03711f3166dd1aa33bc6d081a107f3228f Mon Sep 17 00:00:00 2001 From: Iacopo Leardini Date: Wed, 15 May 2024 16:19:01 +0200 Subject: [PATCH 12/24] refactor: hook to reuse media logic --- src/stories/chat/_types.tsx | 2 -- src/stories/chat/hooks/useMedia.tsx | 45 ++++++++++++++++++++++++ src/stories/chat/index.stories.tsx | 2 -- src/stories/chat/parts/bar.tsx | 15 +++----- src/stories/chat/parts/commentBox.tsx | 50 +++------------------------ 5 files changed, 53 insertions(+), 61 deletions(-) create mode 100644 src/stories/chat/hooks/useMedia.tsx diff --git a/src/stories/chat/_types.tsx b/src/stories/chat/_types.tsx index 31130b96..7264e19a 100644 --- a/src/stories/chat/_types.tsx +++ b/src/stories/chat/_types.tsx @@ -7,8 +7,6 @@ export type SuggestedUser = { id: number; name: string; email: string }; export interface ChatEditorArgs extends Partial { author: Author; - messageBadFileFormat: string; - messageBadFileFormatMultiple: string; placeholderOptions?: Partial; hasFloatingMenu?: boolean; hasButtonsMenu?: boolean; diff --git a/src/stories/chat/hooks/useMedia.tsx b/src/stories/chat/hooks/useMedia.tsx new file mode 100644 index 00000000..1f0f00e3 --- /dev/null +++ b/src/stories/chat/hooks/useMedia.tsx @@ -0,0 +1,45 @@ +import { useToast, Notification } from "../../notifications"; +import { FileItem } from "../_types"; +import { v4 as uuidv4 } from "uuid"; + +export const acceptedMediaTypes = /^(image|video)\//; + +export function useMedia() { + const { addToast } = useToast(); + function getValidMedia(data: FileList): File[] { + const wrongFiles = Array.from(data).filter( + (file) => !acceptedMediaTypes.test(file.type) + ); + if (wrongFiles.length) { + addToast( + ({ close }) => ( + + ), + { placement: "top" } + ); + } + return Array.from(data).filter((file) => + acceptedMediaTypes.test(file.type) + ); + } + + function getMedia(data: FileList): FileItem[] { + return getValidMedia(data).map((file) => { + return Object.assign(file, { + isLoadingMedia: true, + internal_id: uuidv4(), + }); + }); + } + + return { getMedia }; +} \ No newline at end of file diff --git a/src/stories/chat/index.stories.tsx b/src/stories/chat/index.stories.tsx index dea1ec67..79c94629 100644 --- a/src/stories/chat/index.stories.tsx +++ b/src/stories/chat/index.stories.tsx @@ -264,8 +264,6 @@ const defaultArgs: EditorStoryArgs = { ], }, ], - messageBadFileFormat: "Format not supported, please upload video or image", - messageBadFileFormatMultiple: "Some uploaded files are not supported", }; export const Default = Template.bind({}); diff --git a/src/stories/chat/parts/bar.tsx b/src/stories/chat/parts/bar.tsx index e35a649c..c06d2483 100644 --- a/src/stories/chat/parts/bar.tsx +++ b/src/stories/chat/parts/bar.tsx @@ -1,7 +1,6 @@ import styled from "styled-components"; -import { v4 as uuidv4 } from "uuid"; import { Tooltip } from "../../tooltip"; -import { ChatEditorArgs, FileItem } from "../_types"; +import { ChatEditorArgs } from "../_types"; import { Editor } from "@tiptap/react"; import { isMac } from "../../theme/utils"; import { ReactComponent as BoldIcon } from "../../../assets/icons/bold-stroke.svg"; @@ -10,6 +9,7 @@ import { ReactComponent as MentionIcon } from "../../../assets/icons/at-stroke.s import { ReactComponent as AttachmentIcon } from "../../../assets/icons/clipboard.svg"; import { IconButton } from "../../buttons/icon-button"; import { useChatContext } from "../context/chatContext"; +import { useMedia } from "../hooks/useMedia"; const MenuContainer = styled.div` padding: ${({ theme }) => theme.space.xs} 0; @@ -34,7 +34,7 @@ const CommentBar = ({ editor?: Editor; }) => { const { addThumbnails } = useChatContext(); - + const {getMedia} = useMedia(); if (!editor) return null; type MenuItem = { @@ -76,14 +76,7 @@ const CommentBar = ({ fileInput.onchange = () => { if (fileInput.files) { - addThumbnails({ - files: Array.from(fileInput.files).map((file) => { - return Object.assign(file, { - isLoadingMedia: true, - internal_id: uuidv4(), - }); - }), - }); + addThumbnails({ files: getMedia(fileInput.files) }); } }; return; diff --git a/src/stories/chat/parts/commentBox.tsx b/src/stories/chat/parts/commentBox.tsx index 06634114..ef3e3a8e 100644 --- a/src/stories/chat/parts/commentBox.tsx +++ b/src/stories/chat/parts/commentBox.tsx @@ -1,12 +1,11 @@ import styled from "styled-components"; -import { v4 as uuidv4 } from "uuid"; import { useEditor, EditorContent, Editor as TipTapEditor, Content, } from "@tiptap/react"; -import { ChatEditorArgs, FileItem } from "../_types"; +import { ChatEditorArgs } from "../_types"; import { KeyboardEvent as ReactKeyboardEvent, PropsWithChildren, @@ -14,10 +13,6 @@ import { useRef, useCallback, } from "react"; - -import { Notification } from "../../notifications"; -import { useToast } from "../../notifications"; - import { FloatingMenu } from "../../editor/floatingMenu"; import { useChatContext } from "../context/chatContext"; import { CommentBar } from "./bar"; @@ -25,8 +20,7 @@ import { editorExtensions } from "./extensions"; import { EditorContainer } from "./containers"; import ThumbnailContainer from "./ThumbnailContainer"; import MediaLightBox from "./MediaLightbox"; - -export const acceptedMediaTypes = /^(image|video)\//; +import { useMedia } from "../hooks/useMedia"; const ChatBoxContainer = styled.div` display: flex; @@ -61,50 +55,14 @@ export const CommentBox = ({ thumbnails, addThumbnails, } = useChatContext(); - - const { addToast } = useToast(); const [isOpen, setIsOpen] = useState(false); const [selectedImageIndex, setSelectedImageIndex] = useState(0); - + const {getMedia} = useMedia(); const ext = editorExtensions({ placeholderOptions, mentionableUsers }); function handleEvent(data: DataTransfer | null) { if (!data || !data.files) return; - addThumbnails({ files: createFiles(data.files) }); - } - function getValidMedia(data: FileList): File[] { - const wrongFiles = Array.from(data).filter( - (file) => !acceptedMediaTypes.test(file.type) - ); - if (wrongFiles.length) { - addToast( - ({ close }) => ( - - ), - { placement: "top" } - ); - } - return Array.from(data).filter((file) => - acceptedMediaTypes.test(file.type) - ); - } - - function createFiles(data: FileList): FileItem[] { - return getValidMedia(data).map((file) => { - return Object.assign(file, { - isLoadingMedia: true, - internal_id: uuidv4(), - }); - }); + addThumbnails({ files: getMedia(data.files) }); } const closeLightbox = () => { From 96826b98c6071a60b9ccacef8bceaad1763c88d9 Mon Sep 17 00:00:00 2001 From: Iacopo Leardini Date: Wed, 15 May 2024 16:26:59 +0200 Subject: [PATCH 13/24] refactor: Improve comment bar functionality and remove unused code --- src/stories/chat/parts/bar.tsx | 78 +++++++++++++--------------------- 1 file changed, 29 insertions(+), 49 deletions(-) diff --git a/src/stories/chat/parts/bar.tsx b/src/stories/chat/parts/bar.tsx index c06d2483..741a3b0b 100644 --- a/src/stories/chat/parts/bar.tsx +++ b/src/stories/chat/parts/bar.tsx @@ -37,52 +37,32 @@ const CommentBar = ({ const {getMedia} = useMedia(); if (!editor) return null; - type MenuItem = { - type: "bold" | "italic" | "mention" | "attachment"; + const handleBoldClick = () => { + editor.chain().focus().toggleBold().run(); }; - const getIcon = (type: MenuItem["type"]) => { - switch (type) { - case "bold": - return ; - case "italic": - return ; - case "mention": - return ; - case "attachment": - return ; - default: - return null; - } + const handleItalicClick = () => { + editor.chain().focus().toggleItalic().run(); }; - const handleClick = (type: MenuItem["type"]) => { - switch (type) { - case "bold": - return editor.chain().focus().toggleBold().run(); - case "italic": - return editor.chain().focus().toggleItalic().run(); - case "mention": - const { from } = editor.state.selection; - const char = from > 1 ? " @" : "@"; - return editor.chain().focus().insertContent(char).run(); - case "attachment": - //open a file browser to select one or more images - const fileInput = document.createElement("input"); - fileInput.type = "file"; - fileInput.accept = "image/*,video/*"; - fileInput.multiple = true; - fileInput.click(); + const handleMentionClick = () => { + const { from } = editor.state.selection; + const char = from > 1 ? " @" : "@"; + editor.chain().focus().insertContent(char).run(); + }; - fileInput.onchange = () => { - if (fileInput.files) { - addThumbnails({ files: getMedia(fileInput.files) }); - } - }; - return; - default: - return; - } + const handleAttachmentClick = () => { + const fileInput = document.createElement("input"); + fileInput.type = "file"; + fileInput.accept = "image/*,video/*"; + fileInput.multiple = true; + fileInput.click(); + + fileInput.onchange = () => { + if (fileInput.files) { + addThumbnails({ files: getMedia(fileInput.files) }); + } + }; }; return ( @@ -102,9 +82,9 @@ const CommentBar = ({ isBasic={!editor.isActive("bold")} isPrimary={editor.isActive("bold")} isPill={false} - onClick={() => handleClick("bold")} + onClick={handleBoldClick} > - {getIcon("bold")} + handleClick("italic")} + onClick={handleItalicClick} > - {getIcon("italic")} + @@ -139,9 +119,9 @@ const CommentBar = ({ isBasic={!editor.isActive("mention")} isPrimary={editor.isActive("mention")} isPill={false} - onClick={() => handleClick("mention")} + onClick={handleMentionClick} > - {getIcon("mention")} + handleClick("attachment")} + onClick={handleAttachmentClick} > - {getIcon("attachment")} + From 1f4db82c77cba0b062b83d01688d8165db9cfe65 Mon Sep 17 00:00:00 2001 From: Iacopo Leardini Date: Wed, 15 May 2024 16:27:50 +0200 Subject: [PATCH 14/24] refactor: use key in map --- src/stories/chat/parts/comment.tsx | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/stories/chat/parts/comment.tsx b/src/stories/chat/parts/comment.tsx index 622349a6..a51c3eeb 100644 --- a/src/stories/chat/parts/comment.tsx +++ b/src/stories/chat/parts/comment.tsx @@ -144,18 +144,17 @@ export const Comment = ({ {media.map((file, index) => ( - - { - handleClickThumbnail(file, index); - }} - /> - + + { + handleClickThumbnail(file, index); + }} + /> + ))} From 6b994a97d4227aaa5db68a155dcf88f62863203f Mon Sep 17 00:00:00 2001 From: Iacopo Leardini Date: Wed, 15 May 2024 16:30:11 +0200 Subject: [PATCH 15/24] refactor: fix comment key issue --- src/stories/chat/index.stories.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/stories/chat/index.stories.tsx b/src/stories/chat/index.stories.tsx index 79c94629..53d5b19e 100644 --- a/src/stories/chat/index.stories.tsx +++ b/src/stories/chat/index.stories.tsx @@ -43,9 +43,10 @@ const ChatPanel = ({ background, ...args }: EditorStoryArgs) => { Titolone - {args.comments?.map((comment) => ( + {args.comments?.map((comment, index) => ( <>altre cose @@ -154,9 +155,9 @@ const Template: StoryFn = ({ children, ...args }) => { console.log("internal_id - ", id); }} - /*setIsMediaUploading={function (value: boolean): void { - throw new Error("Function not implemented."); - }}*/ + /*setIsMediaUploading={function (value: boolean): void { + throw new Error("Function not implemented."); + }}*/ > @@ -170,11 +171,11 @@ const Template: StoryFn = ({ children, ...args }) => { const defaultArgs: EditorStoryArgs = { children: "

I'm a stupid editor!

", - onSave: (editor: TipTapEditor, mentions) => {}, + onSave: (editor: TipTapEditor, mentions) => { }, author: { avatar: "LC", }, - onUpdate: ({ editor }) => {}, + onUpdate: ({ editor }) => { }, comments: [ { message: "Hi, I'm a comment", From 8730026a17d7ea277ba6c17eaac480b4f0005921 Mon Sep 17 00:00:00 2001 From: Iacopo Leardini Date: Wed, 15 May 2024 16:37:08 +0200 Subject: [PATCH 16/24] refactor: add maxHeight style to MediaLightbox image --- src/stories/chat/parts/MediaLightbox.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/stories/chat/parts/MediaLightbox.tsx b/src/stories/chat/parts/MediaLightbox.tsx index c8a23f02..b8280077 100644 --- a/src/stories/chat/parts/MediaLightbox.tsx +++ b/src/stories/chat/parts/MediaLightbox.tsx @@ -35,6 +35,7 @@ const MediaLightBox = ({header, onClose, slideChange, selectedImageIndex, thumbn {`media )} {item.type.includes("video") && ( From afd9e9d5f5afb07dd913e3ff5a054428ce005967 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 16 May 2024 10:25:34 +0200 Subject: [PATCH 17/24] 3.1.106-attachments --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 306bacdf..f71dd24a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@appquality/unguess-design-system", - "version": "3.1.88", + "version": "3.1.106-attachments", "description": "", "main": "build/index.js", "types": "build/index.d.ts", From f888d4a12e641ba8a279fad5a386bcb2c9dc082c Mon Sep 17 00:00:00 2001 From: Iacopo Leardini Date: Thu, 16 May 2024 11:13:53 +0200 Subject: [PATCH 18/24] refactor: use CommentMedia type --- src/stories/chat/_types.tsx | 8 +-- src/stories/chat/context/chatContext.tsx | 16 +++--- src/stories/chat/hooks/useMedia.tsx | 7 +-- src/stories/chat/index.stories.tsx | 52 +++---------------- src/stories/chat/parts/MediaLightbox.tsx | 12 ++--- .../parts/ThumbnailContainer/Thumbnail.tsx | 2 +- .../chat/parts/ThumbnailContainer/index.tsx | 12 ++--- src/stories/chat/parts/comment.tsx | 12 ++--- src/stories/chat/parts/commentBox.tsx | 4 +- 9 files changed, 43 insertions(+), 82 deletions(-) diff --git a/src/stories/chat/_types.tsx b/src/stories/chat/_types.tsx index 7264e19a..49bb287d 100644 --- a/src/stories/chat/_types.tsx +++ b/src/stories/chat/_types.tsx @@ -40,10 +40,12 @@ export interface EditorHeaderArgs { validation?: validationStatus; } -export interface FileItem extends File { - isLoadingMedia: boolean; +export interface CommentMedia { + id: string; + type: string; + name?: string; + isLoadingMedia?: boolean; isError?: boolean; - internal_id: string; url?: string; } diff --git a/src/stories/chat/context/chatContext.tsx b/src/stories/chat/context/chatContext.tsx index 90103e6a..8b6a4fa6 100644 --- a/src/stories/chat/context/chatContext.tsx +++ b/src/stories/chat/context/chatContext.tsx @@ -6,15 +6,15 @@ import React, { useMemo, useState, } from "react"; -import { FileItem, SuggestedUser } from "../_types"; +import { CommentMedia, SuggestedUser } from "../_types"; export type ChatContextType = { triggerSave: () => void; editor?: Editor; setEditor: React.Dispatch>; - addThumbnails: (props: { files: FileItem[] }) => void; + addThumbnails: (props: { files: CommentMedia[] }) => void; removeThumbnail: (index: number) => void; - thumbnails: FileItem[]; + thumbnails: CommentMedia[]; mentionableUsers: (props: { query: string }) => SuggestedUser[]; afterUploadCallback: (failed: string[]) => void; clearInput: () => void; @@ -35,13 +35,13 @@ export const ChatContextProvider = ({ children, }: { onSave?: (editor: Editor, mentions: SuggestedUser[]) => void; - onFileUpload?: (files: FileItem[]) => Promise; + onFileUpload?: (files: CommentMedia[]) => Promise; onDeleteThumbnail: (id: string) => void; children: React.ReactNode; setMentionableUsers: (props: { query: string }) => SuggestedUser[]; }) => { const [editor, setEditor] = useState(); - const [thumbnails, setThumbnails] = useState([]); + const [thumbnails, setThumbnails] = useState([]); const getMentions = (editor: Editor) => { const result: SuggestedUser[] = []; @@ -70,7 +70,7 @@ export const ChatContextProvider = ({ afterUploadCallback: (failed: string[]) => { setThumbnails( thumbnails.map((file) => { - if (failed.includes(file.name)) { + if (failed.includes(file.id)) { file.isLoadingMedia = false; //file.isError = true; } else { @@ -82,7 +82,7 @@ export const ChatContextProvider = ({ ); }, - addThumbnails: ({ files }: { files: FileItem[] }) => { + addThumbnails: ({ files }: { files: CommentMedia[] }) => { setThumbnails((prev) => [...prev, ...files]); if (onFileUpload) { @@ -91,7 +91,7 @@ export const ChatContextProvider = ({ setThumbnails((prev) => { return prev.map((file) => { file.isLoadingMedia = false; - if (failed?.length && failed.includes(file.name)) { + if (failed?.length && failed.includes(file.id)) { file.isError = true; } else { file.isError = false; diff --git a/src/stories/chat/hooks/useMedia.tsx b/src/stories/chat/hooks/useMedia.tsx index 1f0f00e3..a13c0dce 100644 --- a/src/stories/chat/hooks/useMedia.tsx +++ b/src/stories/chat/hooks/useMedia.tsx @@ -1,5 +1,5 @@ import { useToast, Notification } from "../../notifications"; -import { FileItem } from "../_types"; +import { CommentMedia } from "../_types"; import { v4 as uuidv4 } from "uuid"; export const acceptedMediaTypes = /^(image|video)\//; @@ -32,11 +32,12 @@ export function useMedia() { ); } - function getMedia(data: FileList): FileItem[] { + function getMedia(data: FileList): CommentMedia[] { return getValidMedia(data).map((file) => { return Object.assign(file, { + url: URL.createObjectURL(file), isLoadingMedia: true, - internal_id: uuidv4(), + id: uuidv4(), }); }); } diff --git a/src/stories/chat/index.stories.tsx b/src/stories/chat/index.stories.tsx index 53d5b19e..932976d9 100644 --- a/src/stories/chat/index.stories.tsx +++ b/src/stories/chat/index.stories.tsx @@ -7,7 +7,7 @@ import { Button } from "../buttons/button"; import { Col } from "../grid/col"; import { Grid } from "../grid/grid"; import { Row } from "../grid/row"; -import { ChatEditorArgs, FileItem, SuggestedUser } from "./_types"; +import { ChatEditorArgs, CommentMedia, SuggestedUser } from "./_types"; import { Comment } from "./parts/comment"; import { theme } from "../theme"; import { Data } from "./context/chatContext"; @@ -27,12 +27,12 @@ interface EditorStoryArgs extends ChatEditorArgs { }; message: string; date: string; - media?: FileItem[]; + media?: CommentMedia[]; }[]; editorText?: string; background?: string; onSave: (editor: TipTapEditor, mentions: SuggestedUser[]) => void; - onFileUpload?: (files: FileItem[]) => Promise; + onFileUpload?: (files: CommentMedia[]) => Promise; placeholderOptions?: Partial; } @@ -213,54 +213,16 @@ const defaultArgs: EditorStoryArgs = { { url: "https://images.unsplash.com/photo-1638799692504-9b3c0093d54d?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", type: "image", - internal_id: "1", + id: "1", isLoadingMedia: false, - lastModified: 0, - name: "", - webkitRelativePath: "", - size: 0, - arrayBuffer: function (): Promise { - throw new Error("Function not implemented."); - }, - slice: function ( - start?: number | undefined, - end?: number | undefined, - contentType?: string | undefined - ): Blob { - throw new Error("Function not implemented."); - }, - stream: function (): ReadableStream { - throw new Error("Function not implemented."); - }, - text: function (): Promise { - throw new Error("Function not implemented."); - }, + name: "" }, { url: "https://images.unsplash.com/photo-1544085311-11a028465b03?q=80&w=1932&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", type: "image", - internal_id: "2", + id: "2", isLoadingMedia: false, - lastModified: 0, - name: "", - webkitRelativePath: "", - size: 0, - arrayBuffer: function (): Promise { - throw new Error("Function not implemented."); - }, - slice: function ( - start?: number | undefined, - end?: number | undefined, - contentType?: string | undefined - ): Blob { - throw new Error("Function not implemented."); - }, - stream: function (): ReadableStream { - throw new Error("Function not implemented."); - }, - text: function (): Promise { - throw new Error("Function not implemented."); - }, + name: "" }, ], }, diff --git a/src/stories/chat/parts/MediaLightbox.tsx b/src/stories/chat/parts/MediaLightbox.tsx index b8280077..c3a64e78 100644 --- a/src/stories/chat/parts/MediaLightbox.tsx +++ b/src/stories/chat/parts/MediaLightbox.tsx @@ -1,6 +1,6 @@ import { Lightbox } from "../../lightbox"; import { Slider } from "../../slider"; -import { FileItem } from "../_types"; +import { CommentMedia } from "../_types"; import { Player } from "../../player"; interface MediaLightBoxProps { @@ -9,7 +9,7 @@ interface MediaLightBoxProps { onClose: () => void; slideChange: (index: number) => void; selectedImageIndex: number; - thumbnails: FileItem[]; + thumbnails: CommentMedia[]; videoRefs: React.MutableRefObject>; details?: React.ReactNode; }; @@ -30,20 +30,20 @@ const MediaLightBox = ({header, onClose, slideChange, selectedImageIndex, thumbn initialSlide={selectedImageIndex} > {thumbnails.map((item) => ( - + {item.type.includes("image") && ( {`media )} - {item.type.includes("video") && ( + {item.type.includes("video") && item.url && ( { videoRefs.current.push(ref); }} - url={item.url || URL.createObjectURL(item)} + url={item.url} /> )} diff --git a/src/stories/chat/parts/ThumbnailContainer/Thumbnail.tsx b/src/stories/chat/parts/ThumbnailContainer/Thumbnail.tsx index 68e5e6c5..a1d50fef 100644 --- a/src/stories/chat/parts/ThumbnailContainer/Thumbnail.tsx +++ b/src/stories/chat/parts/ThumbnailContainer/Thumbnail.tsx @@ -69,7 +69,7 @@ const Preview = styled.div<{ `; interface Props { - src: string; + src?: string; type: string; clickThumbnail?: () => void; isLoadingMedia?: boolean; diff --git a/src/stories/chat/parts/ThumbnailContainer/index.tsx b/src/stories/chat/parts/ThumbnailContainer/index.tsx index 4c98bf7e..e51b431d 100644 --- a/src/stories/chat/parts/ThumbnailContainer/index.tsx +++ b/src/stories/chat/parts/ThumbnailContainer/index.tsx @@ -15,7 +15,7 @@ export interface FileElement { } interface Props { - openLightbox: (file: File, index: number) => void; + openLightbox: (index: number) => void; } const ThumbnailContainer = ({ openLightbox }: Props) => { @@ -25,8 +25,8 @@ const ThumbnailContainer = ({ openLightbox }: Props) => { return thumbnails.map((file) => ({ fileName: file.name, fileType: file.type, - previewUrl: URL.createObjectURL(file), - internal_id: file.internal_id, + previewUrl: file.url, + id: file.id, isLoadingMedia: file.isLoadingMedia, })); }, [thumbnails]); @@ -41,17 +41,17 @@ const ThumbnailContainer = ({ openLightbox }: Props) => { {mediaFiles.map((file, index) => ( { removeThumbnail(index); - onDeleteThumbnail(file.internal_id); + onDeleteThumbnail(file.id); }} clickThumbnail={() => { - openLightbox(thumbnails[index], index); + openLightbox(index); }} /> diff --git a/src/stories/chat/parts/comment.tsx b/src/stories/chat/parts/comment.tsx index a51c3eeb..60b57606 100644 --- a/src/stories/chat/parts/comment.tsx +++ b/src/stories/chat/parts/comment.tsx @@ -2,7 +2,7 @@ import { PropsWithChildren, useCallback, useRef, useState } from "react"; import { Title } from "../../title"; import { Card } from "../../cards"; import { styled } from "styled-components"; -import { Author, FileItem } from "../_types"; +import { Author, CommentMedia } from "../_types"; import { Avatar } from "../../avatar"; import { useChatContext } from "../context/chatContext"; import { Content, useEditor, EditorContent } from "@tiptap/react"; @@ -72,7 +72,7 @@ export const Comment = ({ author: Author; message: string; date: string; - media?: FileItem[]; + media?: CommentMedia[]; header: { title: string; message?: string; @@ -85,9 +85,7 @@ export const Comment = ({ const ext = editorExtensions({ mentionableUsers }); - const handleClickThumbnail = (file: FileItem, index: number) => { - if (!file) throw Error("Error with the image"); - + const handleClickThumbnail = (index: number) => { setSelectedImageIndex(index); setIsOpen(true); }; @@ -146,12 +144,12 @@ export const Comment = ({ {media.map((file, index) => ( { - handleClickThumbnail(file, index); + handleClickThumbnail(index); }} /> diff --git a/src/stories/chat/parts/commentBox.tsx b/src/stories/chat/parts/commentBox.tsx index ef3e3a8e..853886f2 100644 --- a/src/stories/chat/parts/commentBox.tsx +++ b/src/stories/chat/parts/commentBox.tsx @@ -82,9 +82,7 @@ export const CommentBox = ({ }, [videoRefs] ); - const handleOpenLightbox = (file: File, index: number) => { - if (!file) throw Error("Error with the image"); - + const handleOpenLightbox = (index: number) => { setSelectedImageIndex(index); setIsOpen(true); }; From f59d63dcef2581e2080a6968135a92416153c2b5 Mon Sep 17 00:00:00 2001 From: Iacopo Leardini Date: Thu, 16 May 2024 11:17:52 +0200 Subject: [PATCH 19/24] revert to main version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f71dd24a..306bacdf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@appquality/unguess-design-system", - "version": "3.1.106-attachments", + "version": "3.1.88", "description": "", "main": "build/index.js", "types": "build/index.d.ts", From 79a5eb469aeafabbf0f2d8049e927ad7422e18e4 Mon Sep 17 00:00:00 2001 From: Iacopo Leardini Date: Thu, 16 May 2024 11:37:58 +0200 Subject: [PATCH 20/24] feat: extend thumbnail type to include File to handle formData api upload --- src/stories/chat/context/chatContext.tsx | 7 +++---- src/stories/chat/hooks/useMedia.tsx | 2 +- src/stories/chat/index.stories.tsx | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/stories/chat/context/chatContext.tsx b/src/stories/chat/context/chatContext.tsx index 8b6a4fa6..901b8a5f 100644 --- a/src/stories/chat/context/chatContext.tsx +++ b/src/stories/chat/context/chatContext.tsx @@ -2,7 +2,6 @@ import { Editor } from "@tiptap/react"; import React, { createContext, useContext, - useEffect, useMemo, useState, } from "react"; @@ -12,7 +11,7 @@ export type ChatContextType = { triggerSave: () => void; editor?: Editor; setEditor: React.Dispatch>; - addThumbnails: (props: { files: CommentMedia[] }) => void; + addThumbnails: (props: { files: (File & CommentMedia)[] }) => void; removeThumbnail: (index: number) => void; thumbnails: CommentMedia[]; mentionableUsers: (props: { query: string }) => SuggestedUser[]; @@ -35,7 +34,7 @@ export const ChatContextProvider = ({ children, }: { onSave?: (editor: Editor, mentions: SuggestedUser[]) => void; - onFileUpload?: (files: CommentMedia[]) => Promise; + onFileUpload?: (files: File[]) => Promise; onDeleteThumbnail: (id: string) => void; children: React.ReactNode; setMentionableUsers: (props: { query: string }) => SuggestedUser[]; @@ -82,7 +81,7 @@ export const ChatContextProvider = ({ ); }, - addThumbnails: ({ files }: { files: CommentMedia[] }) => { + addThumbnails: ({ files }: { files: (File & CommentMedia)[] }) => { setThumbnails((prev) => [...prev, ...files]); if (onFileUpload) { diff --git a/src/stories/chat/hooks/useMedia.tsx b/src/stories/chat/hooks/useMedia.tsx index a13c0dce..33fe54b4 100644 --- a/src/stories/chat/hooks/useMedia.tsx +++ b/src/stories/chat/hooks/useMedia.tsx @@ -32,7 +32,7 @@ export function useMedia() { ); } - function getMedia(data: FileList): CommentMedia[] { + function getMedia(data: FileList) { return getValidMedia(data).map((file) => { return Object.assign(file, { url: URL.createObjectURL(file), diff --git a/src/stories/chat/index.stories.tsx b/src/stories/chat/index.stories.tsx index 932976d9..443094da 100644 --- a/src/stories/chat/index.stories.tsx +++ b/src/stories/chat/index.stories.tsx @@ -32,7 +32,7 @@ interface EditorStoryArgs extends ChatEditorArgs { editorText?: string; background?: string; onSave: (editor: TipTapEditor, mentions: SuggestedUser[]) => void; - onFileUpload?: (files: CommentMedia[]) => Promise; + onFileUpload?: (files: File[]) => Promise; placeholderOptions?: Partial; } From 885f128e5f8e40675e888f0fa3bf28d2e243d2c0 Mon Sep 17 00:00:00 2001 From: Iacopo Leardini Date: Thu, 16 May 2024 12:33:05 +0200 Subject: [PATCH 21/24] chore: Update onFileUpload parameter type --- src/stories/chat/context/chatContext.tsx | 2 +- src/stories/chat/index.stories.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stories/chat/context/chatContext.tsx b/src/stories/chat/context/chatContext.tsx index 901b8a5f..0e6654f6 100644 --- a/src/stories/chat/context/chatContext.tsx +++ b/src/stories/chat/context/chatContext.tsx @@ -34,7 +34,7 @@ export const ChatContextProvider = ({ children, }: { onSave?: (editor: Editor, mentions: SuggestedUser[]) => void; - onFileUpload?: (files: File[]) => Promise; + onFileUpload?: (files: (File & CommentMedia)[]) => Promise; onDeleteThumbnail: (id: string) => void; children: React.ReactNode; setMentionableUsers: (props: { query: string }) => SuggestedUser[]; diff --git a/src/stories/chat/index.stories.tsx b/src/stories/chat/index.stories.tsx index 443094da..3660ab85 100644 --- a/src/stories/chat/index.stories.tsx +++ b/src/stories/chat/index.stories.tsx @@ -32,7 +32,7 @@ interface EditorStoryArgs extends ChatEditorArgs { editorText?: string; background?: string; onSave: (editor: TipTapEditor, mentions: SuggestedUser[]) => void; - onFileUpload?: (files: File[]) => Promise; + onFileUpload?: (files: (File & CommentMedia)[]) => Promise; placeholderOptions?: Partial; } From 0c8b138c9aef31e71633f0c94a43d4046fd98347 Mon Sep 17 00:00:00 2001 From: Iacopo Leardini Date: Thu, 16 May 2024 12:43:25 +0200 Subject: [PATCH 22/24] refactor: Add key prop to ThumbnailContainer map function --- src/stories/chat/parts/ThumbnailContainer/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stories/chat/parts/ThumbnailContainer/index.tsx b/src/stories/chat/parts/ThumbnailContainer/index.tsx index e51b431d..603775f3 100644 --- a/src/stories/chat/parts/ThumbnailContainer/index.tsx +++ b/src/stories/chat/parts/ThumbnailContainer/index.tsx @@ -39,7 +39,7 @@ const ThumbnailContainer = ({ openLightbox }: Props) => { {mediaFiles.map((file, index) => ( - + Date: Thu, 16 May 2024 16:10:45 +0200 Subject: [PATCH 23/24] refactor: fixed thumbnails size and flex display --- .../parts/ThumbnailContainer/Thumbnail.tsx | 35 +++++++------ .../chat/parts/ThumbnailContainer/index.tsx | 50 +++++++++---------- 2 files changed, 46 insertions(+), 39 deletions(-) diff --git a/src/stories/chat/parts/ThumbnailContainer/Thumbnail.tsx b/src/stories/chat/parts/ThumbnailContainer/Thumbnail.tsx index a1d50fef..089c49e2 100644 --- a/src/stories/chat/parts/ThumbnailContainer/Thumbnail.tsx +++ b/src/stories/chat/parts/ThumbnailContainer/Thumbnail.tsx @@ -2,13 +2,14 @@ import styled from "styled-components"; import DeleteThumbnailX from "./DeleteThumbnailX"; import { Spinner } from "@zendeskgarden/react-loaders"; import { SpecialCard } from "../../../special-cards"; -import {ReactComponent as VideoPlayIcon} from "../../../../assets/icons/video-play-icon.svg"; +import { ReactComponent as VideoPlayIcon } from "../../../../assets/icons/video-play-icon.svg"; const ImageCard = styled(SpecialCard)` padding: 0; position: relative; overflow: hidden; - + min-width: 90px; + &:before { content: ""; position: absolute; @@ -31,8 +32,7 @@ const ImageCard = styled(SpecialCard)` } } - &.video{ - + &.video { svg { position: absolute; top: 50%; @@ -51,13 +51,15 @@ const Preview = styled.div<{ display: flex; justify-content: center; align-items: center; - height: 150px; + height: 100px; width: 100%; - ${p => p.url && ` + ${(p) => + p.url && + ` background-image: url(${p.url}); background-color: ${p.theme.palette.grey[100]}; - background-size: contain; + background-size: cover; background-position: center; background-repeat: no-repeat; `} @@ -93,7 +95,10 @@ const Thumbnail = ({ }; return ( - + {isError && ( // todo: add error icon error uploading media @@ -114,12 +119,14 @@ const Thumbnail = ({ {showX && ( handleCancel(e)} /> )} - {type.includes('video') && <> - - - } + {type.includes("video") && ( + <> + + + + )} )} diff --git a/src/stories/chat/parts/ThumbnailContainer/index.tsx b/src/stories/chat/parts/ThumbnailContainer/index.tsx index 603775f3..8e282d5f 100644 --- a/src/stories/chat/parts/ThumbnailContainer/index.tsx +++ b/src/stories/chat/parts/ThumbnailContainer/index.tsx @@ -1,9 +1,13 @@ import Thumbnail from "./Thumbnail"; import { useChatContext } from "../../context/chatContext"; -import { Grid } from "../../../grid/grid"; -import { Row } from "../../../grid/row"; -import { Col } from "../../../grid/col"; import { useMemo } from "react"; +import { styled } from "styled-components"; + +const FlexContainer = styled.div` + display: flex; + gap: ${({ theme }) => theme.space.xs}; + flex-wrap: wrap; +`; export interface FileElement { fileName: string; @@ -36,28 +40,24 @@ const ThumbnailContainer = ({ openLightbox }: Props) => { } return ( - - - {mediaFiles.map((file, index) => ( - - { - removeThumbnail(index); - onDeleteThumbnail(file.id); - }} - clickThumbnail={() => { - openLightbox(index); - }} - /> - - ))} - - + + {mediaFiles.map((file, index) => ( + { + removeThumbnail(index); + onDeleteThumbnail(file.id); + }} + clickThumbnail={() => { + openLightbox(index); + }} + /> + ))} + ); }; From 61740a704aa5f1fb1bde257ec1a7b20b0bb37993 Mon Sep 17 00:00:00 2001 From: Kariamos Date: Thu, 16 May 2024 16:20:19 +0200 Subject: [PATCH 24/24] refactor: updated attachment tooltip --- src/stories/chat/_types.tsx | 2 +- src/stories/chat/parts/bar.tsx | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/stories/chat/_types.tsx b/src/stories/chat/_types.tsx index 49bb287d..c96d2810 100644 --- a/src/stories/chat/_types.tsx +++ b/src/stories/chat/_types.tsx @@ -17,7 +17,7 @@ export interface ChatEditorArgs extends Partial { italic?: string; mention?: string; //react node - attachment?: string | React.ReactNode; + attachment?: React.ReactNode; }; mention?: { noResults?: string; diff --git a/src/stories/chat/parts/bar.tsx b/src/stories/chat/parts/bar.tsx index 741a3b0b..8462c92b 100644 --- a/src/stories/chat/parts/bar.tsx +++ b/src/stories/chat/parts/bar.tsx @@ -10,6 +10,7 @@ import { ReactComponent as AttachmentIcon } from "../../../assets/icons/clipboar import { IconButton } from "../../buttons/icon-button"; import { useChatContext } from "../context/chatContext"; import { useMedia } from "../hooks/useMedia"; +import { theme } from "../../theme"; const MenuContainer = styled.div` padding: ${({ theme }) => theme.space.xs} 0; @@ -34,7 +35,7 @@ const CommentBar = ({ editor?: Editor; }) => { const { addThumbnails } = useChatContext(); - const {getMedia} = useMedia(); + const { getMedia } = useMedia(); if (!editor) return null; const handleBoldClick = () => { @@ -126,7 +127,15 @@ const CommentBar = ({ + Upload images and video.{" "} + + {" "} +
Max size: 5GB{" "} +
+ + ) } placement="top" type="light"