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"