diff --git a/src/modules/GroupChannel/components/DragCover/index.tsx b/src/modules/GroupChannel/components/DragCover/index.tsx new file mode 100644 index 000000000..ff881b19e --- /dev/null +++ b/src/modules/GroupChannel/components/DragCover/index.tsx @@ -0,0 +1,73 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import Label from '../../../../ui/Label'; +import { Typography } from '../../../../ui/Label/types'; + +export interface DragCoverProps { + targetRef: React.RefObject; + onDrop: (files: File[]) => void; +} + +export const DragCover = (props: DragCoverProps) => { + const { + targetRef, + onDrop, + } = props; + + const [isShowing, setIsShowing] = useState(false); + + const onDragEnter = useCallback((e) => { + if (e.currentTarget.contains(e.relatedTarget)) return; + setIsShowing(true); + }, [targetRef]); + + const onDragOver = useCallback((e) => { + e.preventDefault(); + }, [targetRef]); + + const onDragLeave = useCallback((e) => { + if (e.currentTarget.contains(e.relatedTarget)) return; + setIsShowing(false); + }, [targetRef]); + + const _onDrop = useCallback((e) => { + e.preventDefault(); + setIsShowing(false); + onDrop(Array.from(e.dataTransfer.files)); + }, [targetRef]); + + useEffect(() => { + if (!targetRef) return; + + targetRef.current.addEventListener('dragenter', onDragEnter); + targetRef.current.addEventListener('dragover', onDragOver); + targetRef.current.addEventListener('dragleave', onDragLeave); + targetRef.current.addEventListener('drop', _onDrop); + + return () => { + targetRef.current.removeEventListener('dragenter', onDragEnter); + targetRef.current.removeEventListener('dragover', onDragOver); + targetRef.current.removeEventListener('dragleave', onDragLeave); + targetRef.current.removeEventListener('drop', _onDrop); + }; + + }, [targetRef]); + + return ( + isShowing + ?
+ +
+ : null + ); +}; diff --git a/src/modules/GroupChannel/components/GroupChannelUI/GroupChannelUIView.tsx b/src/modules/GroupChannel/components/GroupChannelUI/GroupChannelUIView.tsx index 1f490865f..80d0171f1 100644 --- a/src/modules/GroupChannel/components/GroupChannelUI/GroupChannelUIView.tsx +++ b/src/modules/GroupChannel/components/GroupChannelUI/GroupChannelUIView.tsx @@ -1,5 +1,5 @@ import './index.scss'; -import React from 'react'; +import React, { useRef } from 'react'; import TypingIndicator from '../TypingIndicator'; import { TypingIndicatorType } from '../../../../types'; @@ -13,6 +13,9 @@ import type { MessageContentProps } from '../../../../ui/MessageContent'; import { SuggestedRepliesProps } from '../SuggestedReplies'; import { deleteNullish } from '../../../../utils/utils'; import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird'; +import { useGroupChannel } from '../../context/hooks/useGroupChannel'; +import { useHandleUploadFiles } from '../MessageInputWrapper/useHandleUploadFiles'; +import { DragCover } from '../DragCover'; export interface GroupChannelUIBasicProps { // Components @@ -106,6 +109,24 @@ export const GroupChannelUIView = (props: GroupChannelUIViewProps) => { const { stores, config } = state; const sdkError = stores?.sdkStore?.error; const { logger, isOnline } = config; + const conversationRef = useRef(null); + + const { + state: { + quoteMessage, + }, + actions: { + sendFileMessage, + sendMultipleFilesMessage, + scrollToBottom, + }, + } = useGroupChannel(); + + const handleUploadFiles = useHandleUploadFiles({ + sendFileMessage, + sendMultipleFilesMessage, + quoteMessage, + }, { logger }); // Note: This is not a loading status of the message list. // It is just for custom props from the Channel module and is not used in the GroupChannel module. (We should remove this in v4) @@ -140,7 +161,7 @@ export const GroupChannelUIView = (props: GroupChannelUIViewProps) => { } return ( -
+
{renderChannelHeader?.({ className: 'sendbird-conversation__channel-header' })} {renderMessageList?.(props)}
@@ -153,6 +174,7 @@ export const GroupChannelUIView = (props: GroupChannelUIViewProps) => { {!isOnline && }
+ { handleUploadFiles(e).then(() => scrollToBottom()); }} />
); };