set styles for uploading files

Change-Id: I7d3f934ea4f31769d72d1f21c733ab0c16b325f6
diff --git a/client/src/pages/ChatInterface.tsx b/client/src/pages/ChatInterface.tsx
index 86f77da..4ad1830 100644
--- a/client/src/pages/ChatInterface.tsx
+++ b/client/src/pages/ChatInterface.tsx
@@ -15,15 +15,18 @@
  * License along with this program.  If not, see
  * <https://www.gnu.org/licenses/>.
  */
-import { Divider, Stack } from '@mui/material';
+import { Box, Divider, Stack } from '@mui/material';
 import { Account, ConversationMember, Message } from 'jami-web-common';
 import { useCallback, useContext, useEffect, useState } from 'react';
+import { useDropzone } from 'react-dropzone';
 
+import { FilePreviewRemovable } from '../components/FilePreview';
 import LoadingPage from '../components/Loading';
 import MessageList from '../components/MessageList';
 import SendMessageForm from '../components/SendMessageForm';
 import { SocketContext } from '../contexts/Socket';
 import { useMessagesQuery, useSendMessageMutation } from '../services/Conversation';
+import { FileHandler } from '../utils/files';
 
 type ChatInterfaceProps = {
   account: Account;
@@ -39,6 +42,34 @@
   const messagesQuery = useMessagesQuery(account.getId(), conversationId);
   const sendMessageMutation = useSendMessageMutation(account.getId(), conversationId);
 
+  const [fileHandlers, setFileHandlers] = useState<FileHandler[]>([]);
+
+  const onFilesDrop = useCallback(
+    (acceptedFiles: File[]) => {
+      const newFileHandlers = acceptedFiles.map((file) => new FileHandler(file));
+      setFileHandlers((oldFileHandlers) => [...oldFileHandlers, ...newFileHandlers]);
+    },
+    [setFileHandlers]
+  );
+
+  const removeFile = useCallback(
+    (fileId: string | number) => {
+      setFileHandlers((fileHandlers) => fileHandlers.filter((fileHandler) => fileHandler.id !== fileId));
+    },
+    [setFileHandlers]
+  );
+
+  const {
+    getRootProps,
+    getInputProps,
+    open: openFilePicker,
+    isDragActive,
+  } = useDropzone({
+    onDrop: onFilesDrop,
+    noClick: true,
+    noKeyboard: true,
+  });
+
   useEffect(() => {
     if (messagesQuery.isSuccess) {
       const sortedMessages = sortMessages(messagesQuery.data);
@@ -73,7 +104,21 @@
   }
 
   return (
-    <Stack flex={1} overflow="hidden">
+    <Stack flex={1} overflow="hidden" {...getRootProps()} paddingBottom="16px">
+      {isDragActive && (
+        // dark overlay when the user is dragging a file
+        <Box
+          sx={{
+            position: 'absolute',
+            width: '100%',
+            height: '100%',
+            backgroundColor: 'black',
+            opacity: '30%',
+            zIndex: 100,
+          }}
+        />
+      )}
+      <input {...getInputProps()} />
       <MessageList account={account} members={members} messages={messages} />
       <Divider
         sx={{
@@ -81,7 +126,37 @@
           borderTop: '1px solid #E5E5E5',
         }}
       />
-      <SendMessageForm account={account} members={members} onSend={sendMessage} />
+      <SendMessageForm account={account} members={members} onSend={sendMessage} openFilePicker={openFilePicker} />
+      {fileHandlers.length > 0 && <FilePreviewsList fileHandlers={fileHandlers} removeFile={removeFile} />}
+    </Stack>
+  );
+};
+
+interface FilePreviewsListProps {
+  fileHandlers: FileHandler[];
+  removeFile: (fileId: string | number) => void;
+}
+
+const FilePreviewsList = ({ fileHandlers, removeFile }: FilePreviewsListProps) => {
+  return (
+    <Stack
+      direction="row"
+      flexWrap="wrap"
+      gap="16px"
+      overflow="auto"
+      maxHeight="30%"
+      paddingX="16px"
+      marginTop="12px" // spacing with the component on top
+      paddingTop="4px" // spacing so "RemoveButton" are not cut
+    >
+      {fileHandlers.map((fileHandler) => (
+        <FilePreviewRemovable
+          key={fileHandler.id}
+          remove={() => removeFile(fileHandler.id)}
+          fileHandler={fileHandler}
+          borderColor={'#005699' /* Should be same color as message bubble */}
+        />
+      ))}
     </Stack>
   );
 };