diff --git a/package.json b/package.json
index 085cb0e94b14b8c492adf2cfe69a95e79428d54d..d739a386224c6db6a8f6938d695173e04be6465d 100644
--- a/package.json
+++ b/package.json
@@ -73,7 +73,7 @@
     "react-scroll": "^1.8.2",
     "react-tippy": "^1.4.0",
     "redux": "^4.1.0",
-    "revolt.js": "4.3.0",
+    "revolt.js": "4.3.1-alpha.0",
     "rimraf": "^3.0.2",
     "sass": "^1.35.1",
     "shade-blend-color": "^1.0.0",
diff --git a/src/components/common/messaging/MessageBox.tsx b/src/components/common/messaging/MessageBox.tsx
index e25ad13bfe14f8f62c1f64e1dfaf9305314b8a67..f678a2770808103c5fd49a80503c74decb670c78 100644
--- a/src/components/common/messaging/MessageBox.tsx
+++ b/src/components/common/messaging/MessageBox.tsx
@@ -50,6 +50,9 @@ const Action = styled.div`
     place-items: center;
 `;
 
+// ! FIXME: add to app config and load from app config
+export const CAN_UPLOAD_AT_ONCE = 5;
+
 function MessageBox({ channel, draft, dispatcher }: Props) {
     const [ uploadState, setUploadState ] = useState<UploadState>({ type: 'none' });
     const [typing, setTyping] = useState<boolean | number>(false);
@@ -133,7 +136,7 @@ function MessageBox({ channel, draft, dispatcher }: Props) {
 
     async function sendFile(content: string) {
         if (uploadState.type !== 'attached') return;
-        let attachments = [];
+        let attachments: string[] = [];
 
         const cancel = Axios.CancelToken.source();
         const files = uploadState.files;
@@ -141,8 +144,7 @@ function MessageBox({ channel, draft, dispatcher }: Props) {
         setUploadState({ type: "uploading", files, percent: 0, cancel });
 
         try {
-            for (let i=0;i<files.length;i++) {
-                if (i>0)continue; // ! FIXME: temp, allow multiple uploads on server
+            for (let i=0;i<files.length&&i<CAN_UPLOAD_AT_ONCE;i++) {
                 const file = files[i];
                 attachments.push(
                     await uploadFile(client.configuration!.features.autumn.url, 'attachments', file, {
@@ -150,7 +152,7 @@ function MessageBox({ channel, draft, dispatcher }: Props) {
                         setUploadState({
                             type: "uploading",
                             files,
-                            percent: Math.round(((i * 100) + (100 * e.loaded) / e.total) / (files.length)),
+                            percent: Math.round(((i * 100) + (100 * e.loaded) / e.total) / Math.min(files.length, CAN_UPLOAD_AT_ONCE)),
                             cancel
                         }),
                         cancelToken: cancel.token
@@ -184,7 +186,7 @@ function MessageBox({ channel, draft, dispatcher }: Props) {
             await client.channels.sendMessage(channel._id, {
                 content,
                 nonce,
-                attachment: attachments[0] // ! FIXME: temp, allow multiple uploads on server
+                attachments // ! FIXME: temp, allow multiple uploads on server
             });
         } catch (err) {
             setUploadState({
@@ -197,7 +199,15 @@ function MessageBox({ channel, draft, dispatcher }: Props) {
         }
 
         setMessage();
-        setUploadState({ type: "none" });
+
+        if (files.length > CAN_UPLOAD_AT_ONCE) {
+            setUploadState({
+                type: "attached",
+                files: files.slice(CAN_UPLOAD_AT_ONCE)
+            });
+        } else {
+            setUploadState({ type: "none" });
+        }
     }
     
     function startTyping() {
diff --git a/src/components/common/messaging/bars/FilePreview.tsx b/src/components/common/messaging/bars/FilePreview.tsx
index 605efbbbc77304856febde112ed976602af8b237..8bd55d3a6cac98027d4d22961ce296c00e4665b9 100644
--- a/src/components/common/messaging/bars/FilePreview.tsx
+++ b/src/components/common/messaging/bars/FilePreview.tsx
@@ -1,9 +1,9 @@
 import { Text } from "preact-i18n";
 import styled from "styled-components";
-import { UploadState } from "../MessageBox";
+import { CAN_UPLOAD_AT_ONCE, UploadState } from "../MessageBox";
 import { useEffect, useState } from 'preact/hooks';
-import { XCircle, Plus, Share, X } from "@styled-icons/feather";
 import { determineFileSize } from '../../../../lib/fileSize';
+import { XCircle, Plus, Share, X, FileText } from "@styled-icons/feather";
 
 interface Props {
     state: UploadState,
@@ -39,6 +39,10 @@ const Entry = styled.div`
         background: var(--secondary-background);
     }
 
+    &.fade {
+        opacity: 0.4;
+    }
+
     span.fn {
         margin: auto;
         font-size: .8em;
@@ -56,7 +60,7 @@ const Entry = styled.div`
         text-align: center;
     }
 
-    div {
+    div:first-child {
         position: relative;
         height: 0;
 
@@ -69,7 +73,7 @@ const Entry = styled.div`
             
             opacity: 0;
             transition: 0.1s ease opacity;
-            background: rgba(0, 0, 0, 0.5);
+            background: rgba(0, 0, 0, 0.8);
 
             &:hover {
                 opacity: 1;
@@ -86,6 +90,14 @@ const Description = styled.div`
     color: var(--secondary-foreground);
 `;
 
+const Divider = styled.div`
+    width: 4px;
+    height: 130px;
+    flex-shrink: 0;
+    border-radius: 4px;
+    background: var(--tertiary-background);
+`;
+
 const EmptyEntry = styled.div`
     width: 100px;
     height: 100px;
@@ -102,11 +114,13 @@ const EmptyEntry = styled.div`
     }
 `;
 
-function FileEntry({ file, remove }: { file: File, remove?: () => void }) {
+function FileEntry({ file, remove, index }: { file: File, remove?: () => void, index: number }) {
     if (!file.type.startsWith('image/')) return (
-        <Entry>
+        <Entry className={index >= CAN_UPLOAD_AT_ONCE ? 'fade' : ''}>
             <div><div onClick={remove}><XCircle size={36} /></div></div>
-            
+            <EmptyEntry>
+                <FileText size={36} />
+            </EmptyEntry>
             <span class="fn">{file.name}</span>
             <span class="size">{determineFileSize(file.size)}</span>
         </Entry>
@@ -121,7 +135,7 @@ function FileEntry({ file, remove }: { file: File, remove?: () => void }) {
     }, [ file ]);
 
     return (
-        <Entry>
+        <Entry className={index >= CAN_UPLOAD_AT_ONCE ? 'fade' : ''}>
             { remove && <div><div onClick={remove}><XCircle size={36} /></div></div> }
             <img src={url}
                  alt={file.name} />
@@ -137,10 +151,14 @@ export default function FilePreview({ state, addFile, removeFile }: Props) {
     return (
         <Container>
             <Carousel>
-                { state.files.map((file, index) => <FileEntry file={file} key={file.name} remove={state.type === 'attached' ? () => removeFile(index) : undefined} />) }
+                { state.files.map((file, index) =>
+                    <>
+                        { index === CAN_UPLOAD_AT_ONCE && <Divider /> }
+                        <FileEntry index={index} file={file} key={file.name} remove={state.type === 'attached' ? () => removeFile(index) : undefined} />
+                    </>
+                ) }
                 { state.type === 'attached' && <EmptyEntry onClick={addFile}><Plus size={48} /></EmptyEntry> }
             </Carousel>
-            { state.files.length > 1 && state.type === 'attached' && <Description>Warning: Only first file will be uploaded, this will be changed in a future update.</Description> }
             { state.type === 'uploading' && <Description>
                 <Share size={24} />
                 <Text id="app.main.channel.uploading_file" /> ({state.percent}%)
diff --git a/src/context/revoltjs/RevoltClient.tsx b/src/context/revoltjs/RevoltClient.tsx
index 8718ef41fc21276f878856bcc2ba551d2cc020d0..4de9d9362669a9990c584e9a63091e06fabcd858 100644
--- a/src/context/revoltjs/RevoltClient.tsx
+++ b/src/context/revoltjs/RevoltClient.tsx
@@ -114,11 +114,6 @@ function Context({ auth, sync, children, dispatcher }: Props) {
                 dispatcher({ type: "LOGOUT" });
 
                 delete client.user;
-                // ! FIXME: write procedure client.clear();
-                client.users.clear();
-                client.channels.clear();
-                client.servers.clear();
-                client.servers.members.clear();
                 dispatcher({ type: "RESET" });
 
                 openScreen({ id: "none" });
diff --git a/yarn.lock b/yarn.lock
index fbae6d6b60994eebe9481a9496cf8a244be84794..31f59fe461e7fe5ab18934d4dbe8fef213314e87 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3369,10 +3369,10 @@ reusify@^1.0.4:
   resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
   integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
 
-revolt.js@4.3.0:
-  version "4.3.0"
-  resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-4.3.0.tgz#dc396470da82dd58eac74150ed9e3d64f67c28db"
-  integrity sha512-QFD0KQMk6e6bOioZJSSSnzgtx76yJLFSp9LyM1fIIelP02vrMpU1wO7s89lE+7jljh7SVgJqyCfZmlshdyb7Ew==
+revolt.js@4.3.1-alpha.0:
+  version "4.3.1-alpha.0"
+  resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-4.3.1-alpha.0.tgz#21abb0706852468a0b7991a80d81093f547d25f3"
+  integrity sha512-YwDdDgioVYeBYkgZtgtXM37//96WmT18XVPJ7cBJzDQ3GWUKKPrw4VFjmi9FSh0ksfgfkSIrA7/hqmztZWbnVw==
   dependencies:
     "@insertish/mutable" "1.1.0"
     axios "^0.19.2"