diff --git a/app/archive.js b/app/archive.js index 6cea76c7..6070799f 100644 --- a/app/archive.js +++ b/app/archive.js @@ -1,3 +1,4 @@ +/* global MAXFILESIZE */ import { blobStream, concatStream } from './streams'; export default class Archive { @@ -34,4 +35,21 @@ export default class Archive { get stream() { return concatStream(this.files.map(file => blobStream(file))); } + + addFiles(files) { + const newSize = files.reduce((total, file) => total + file.size, 0); + if (this.size + newSize > MAXFILESIZE) { + return false; + } + this.files = this.files.concat(files); + return true; + } + + checkSize() { + return this.size <= MAXFILESIZE; + } + + remove(index) { + this.files.splice(index, 1); + } } diff --git a/app/base.css b/app/base.css index 7a1bed43..f30d5c63 100644 --- a/app/base.css +++ b/app/base.css @@ -47,7 +47,7 @@ a { padding: 0 25px; box-sizing: border-box; min-height: 500px; - max-height: 630px; + max-height: 800px; height: 100px; } @@ -55,6 +55,7 @@ a { flex: none; position: relative; width: 400px; + margin-top: 32px; background-color: white; border-radius: 6px; box-shadow: 0 0 0 3px rgba(12, 12, 13, 0.2); @@ -147,10 +148,6 @@ a { border: none; } -.uploadCancel:hover { - text-decoration: underline; -} - .input { border: 1px solid var(--lightBorderColor); font-size: 20px; @@ -161,26 +158,10 @@ a { padding-right: 10px; } -.input--noBtn { - border-radius: 6px; -} - .input--error { border-color: var(--errorColor); } -.inputBtn.inputError { - background-color: var(--errorColor); -} - -.inputBtn.inputError:hover { - background-color: var(--errorColor); -} - -.cursor--pointer { - cursor: pointer; -} - .link { color: var(--linkColor); text-decoration: none; @@ -206,35 +187,11 @@ a { text-align: center; } -.progressSection { - margin: 0 auto; - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; - text-align: center; - font-size: 15px; -} - -.progressSection__text { - color: var(--lightTextColor); - letter-spacing: -0.4px; - margin-top: 24px; - margin-bottom: 74px; -} - .effect--fadeOut { opacity: 0; animation: fadeout 200ms linear; } -.goBackButton { - position: absolute; - top: 0; - left: 0; - margin: 18px; -} - @keyframes fadeout { 0% { opacity: 1; @@ -260,19 +217,26 @@ a { } } +.goBackButton { + position: absolute; + top: 0; + left: 0; + margin: 18px; +} + .error { color: var(--errorColor); font-weight: 600; } .title { - color: var(--textColor); - font-size: 33px; + color: var(--lightTextColor); + font-size: 18px; line-height: 40px; margin: 20px auto; - text-align: center; max-width: 520px; font-family: 'SF Pro Text', sans-serif; + font-weight: 700; word-wrap: break-word; } @@ -289,7 +253,7 @@ a { } .noDisplay { - display: none; + display: none !important; } .flexible { @@ -303,7 +267,7 @@ a { .main { flex-direction: column; - min-height: 700px; + height: 100%; } .spacer { @@ -312,7 +276,8 @@ a { } .stripedBox { - max-height: 550px; + margin-top: 72; + min-height: 400px; flex: 1; } diff --git a/app/dragManager.js b/app/dragManager.js index c4b1783e..3002e9c1 100644 --- a/app/dragManager.js +++ b/app/dragManager.js @@ -1,5 +1,3 @@ -import { checkSize } from './utils'; - export default function(state, emitter) { emitter.on('DOMContentLoaded', () => { document.body.addEventListener('dragover', event => { @@ -16,11 +14,9 @@ export default function(state, emitter) { .querySelector('.uploadArea') .classList.remove('uploadArea--dragging'); - const target = event.dataTransfer; + const files = Array.from(event.dataTransfer.files); - checkSize(target.files, state.files); - - emitter.emit('addFiles', { files: target.files }); + emitter.emit('addFiles', { files }); } }); }); diff --git a/app/fileManager.js b/app/fileManager.js index e66269c1..f294f199 100644 --- a/app/fileManager.js +++ b/app/fileManager.js @@ -1,14 +1,15 @@ +/* global MAXFILESIZE */ import FileSender from './fileSender'; import FileReceiver from './fileReceiver'; import { copyToClipboard, delay, openLinksInNewTab, percent } from './utils'; import * as metrics from './metrics'; import { hasPassword } from './api'; import Archive from './archive'; +import { bytes } from './utils'; export default function(state, emitter) { let lastRender = 0; let updateTitle = false; - state.files = []; function render() { emitter.emit('render'); @@ -61,14 +62,9 @@ export default function(state, emitter) { metrics.changedDownloadLimit(file); }); - emitter.on('removeUpload', async ({ file }) => { - for (let i = 0; i < state.files.length; i++) { - if (state.files[i] === file) { - state.files.splice(i, 1); - render(); - return; - } - } + emitter.on('removeUpload', async ({ index }) => { + state.archive.remove(index); + render(); }); emitter.on('delete', async ({ file, location }) => { @@ -93,18 +89,28 @@ export default function(state, emitter) { }); emitter.on('addFiles', async ({ files }) => { - for (let i = 0; i < files.length; i++) { - state.files.push(files[i]); + if (state.archive) { + if (!state.archive.addFiles(files)) { + // eslint-disable-next-line no-alert + alert(state.translate('fileTooBig', { size: bytes(MAXFILESIZE) })); + return; + } + } else { + const archive = new Archive(files); + if (!archive.checkSize()) { + // eslint-disable-next-line no-alert + alert(state.translate('fileTooBig', { size: bytes(MAXFILESIZE) })); + return; + } + state.archive = archive; } render(); }); - //TODO: hook up to multi-file upload functionality - emitter.on('upload', async ({ files, type, dlCount, password }) => { - const file = new Archive(files); - - const size = file.size; - const sender = new FileSender(file); + emitter.on('upload', async ({ type, dlCount, password }) => { + if (!state.archive) return; + const size = state.archive.size; + const sender = new FileSender(state.archive); sender.on('progress', updateProgress); sender.on('encrypting', render); sender.on('complete', render); diff --git a/app/pages/legal.js b/app/pages/legal.js index e045ab76..f18a926a 100644 --- a/app/pages/legal.js +++ b/app/pages/legal.js @@ -1,9 +1,15 @@ const html = require('choo/html'); const raw = require('choo/html/raw'); +const assets = require('../../common/assets'); +const title = require('../templates/title'); module.exports = function(state) { return html`