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`
+ + + + ${title(state)}
${state.translate('legalHeader')}
${raw( replaceLinks(state.translate('legalNoticeTestPilot'), [ diff --git a/app/pages/preview/index.js b/app/pages/preview/index.js index 15951cf8..aa86d862 100644 --- a/app/pages/preview/index.js +++ b/app/pages/preview/index.js @@ -4,8 +4,7 @@ const downloadButton = require('../../templates/downloadButton'); const downloadedFiles = require('../../templates/uploadedFileList'); module.exports = function(state, emit) { - const storageFile = state.storage.getFileById(state.params.id); - const multifiles = Array.from(storageFile.manifest.files); + const ownedFile = state.storage.getFileById(state.params.id); const trySendLink = html` @@ -26,7 +25,7 @@ module.exports = function(state, emit) {
${titleSection(state)} - ${downloadedFiles(multifiles, state, emit)} + ${downloadedFiles(ownedFile, state, emit)}
${state.translate('downloadMessage2')}
${downloadButton(state, emit)} diff --git a/app/pages/share/index.js b/app/pages/share/index.js index 96718ae8..8d72729b 100644 --- a/app/pages/share/index.js +++ b/app/pages/share/index.js @@ -4,7 +4,7 @@ const raw = require('choo/html/raw'); const assets = require('../../../common/assets'); const notFound = require('../notFound'); const deletePopup = require('../../templates/popup'); -const uploadedFiles = require('../../templates/uploadedFileList'); +const uploadedFileList = require('../../templates/uploadedFileList'); const { allowedCopy, delay, fadeOut } = require('../../utils'); module.exports = function(state, emit) { @@ -17,8 +17,6 @@ module.exports = function(state, emit) { ? '' : 'passwordReminder--hidden'; - const multifiles = Array.from(file.manifest.files); - return html`
@@ -27,11 +25,10 @@ module.exports = function(state, emit) { ${expireInfo(file, state.translate)} - ${uploadedFiles(multifiles, state, emit)} - + ${uploadedFileList(file, state, emit)}
- ${state.translate('copyUrlFormLabelWithName', { filename: '' })} + ${state.translate('copyUrlLabel')}
(don't forget the password too)
@@ -60,14 +57,14 @@ module.exports = function(state, emit) {
`; - function showPopup() { + function showDeletePopup() { const popup = document.querySelector('.popup'); popup.classList.add('popup--show'); popup.focus(); diff --git a/app/pages/signin/index.js b/app/pages/signin/index.js index 652430b9..d69ae1b4 100644 --- a/app/pages/signin/index.js +++ b/app/pages/signin/index.js @@ -37,6 +37,7 @@ module.exports = function(state, emit) { ${state.translate('signInContinueMessage')}
`; + + function submitEmail(event) { + event.preventDefault(); + //TODO: hook up fxA onboarding + } }; diff --git a/app/pages/signin/signin.css b/app/pages/signin/signin.css index 6b94511a..85745267 100644 --- a/app/pages/signin/signin.css +++ b/app/pages/signin/signin.css @@ -6,7 +6,7 @@ .signIn__info { width: 308px; - margin: 16px auto 0; + margin: 12px auto 0; text-align: left; } @@ -26,7 +26,7 @@ height: 40px; border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 4px; - margin: 0; + margin: 8px 0; padding: 0 8px; font-size: 18px; color: var(--lightTextColor); diff --git a/app/pages/welcome/index.js b/app/pages/welcome/index.js index 2a9d98ad..c20a9965 100644 --- a/app/pages/welcome/index.js +++ b/app/pages/welcome/index.js @@ -1,6 +1,5 @@ const html = require('choo/html'); const assets = require('../../../common/assets'); -const { checkSize } = require('../../utils'); const title = require('../../templates/title'); const setPasswordSection = require('../../templates/setPasswordSection'); const uploadBox = require('../../templates/uploadedFileList'); @@ -9,14 +8,15 @@ const expireInfo = require('../../templates/expireInfo'); module.exports = function(state, emit) { // the page flickers if both the server and browser set 'effect--fadeIn' const fade = state.layout ? '' : 'effect--fadeIn'; - const files = state.files ? state.files : []; + + const hasAnUpload = state.archive && state.archive.numFiles > 0; const optionClass = state.uploading ? 'uploadOptions--faded' : ''; const btnUploading = state.uploading ? 'btn--stripes' : ''; const cancelVisible = state.uploading ? '' : 'noDisplay'; - const faded = files.length > 0 ? 'uploadArea--faded' : ''; - const selectFileClass = files.length > 0 ? 'btn--hidden' : ''; - const sendFileClass = files.length > 0 ? '' : 'btn--hidden'; + const faded = hasAnUpload ? 'uploadArea--faded' : ''; + const selectFileClass = hasAnUpload > 0 ? 'btn--hidden' : ''; + const sendFileClass = hasAnUpload > 0 ? '' : 'btn--hidden'; let btnText = ''; @@ -37,7 +37,7 @@ module.exports = function(state, emit) { ondragover=${dragover} ondragleave=${dragleave}> - ${uploadBox(files, state, emit)} + ${uploadBox(state.archive, state, emit)}
0) { - emit('upload', { - files, - type: 'click', - dlCount: state.downloadCount, - password: state.password - }); - } + emit('upload', { + type: 'click', + dlCount: state.downloadCount, + password: state.password + }); } }; diff --git a/app/pages/welcome/welcome.css b/app/pages/welcome/welcome.css index 5da03247..e6d1a653 100644 --- a/app/pages/welcome/welcome.css +++ b/app/pages/welcome/welcome.css @@ -91,3 +91,7 @@ .uploadCancel { margin: 6px 0 0; } + +.uploadCancel:hover { + text-decoration: underline; +} diff --git a/app/pasteManager.js b/app/pasteManager.js index 7fcaa1dc..482183cb 100644 --- a/app/pasteManager.js +++ b/app/pasteManager.js @@ -1,6 +1,3 @@ -/* global MAXFILESIZE */ -import { bytes } from './utils'; - export default function(state, emitter) { window.addEventListener('paste', event => { if (state.route !== '/' || state.uploading) return; @@ -12,14 +9,7 @@ export default function(state, emitter) { if (!file) continue; // Sometimes null - if (file.size > MAXFILESIZE) { - // eslint-disable-next-line no-alert - alert(state.translate('fileTooBig', { size: bytes(MAXFILESIZE) })); - continue; - } - - emitter.emit('upload', { file, type: 'paste' }); - return; // return here since only one file is allowed to be uploaded at a time + emitter.emit('addFiles', { files: [file] }); } }); } diff --git a/app/routes/home.js b/app/routes/home.js deleted file mode 100644 index 296f0c75..00000000 --- a/app/routes/home.js +++ /dev/null @@ -1,5 +0,0 @@ -const welcome = require('../pages/welcome'); - -module.exports = function(state, emit) { - return welcome(state, emit); -}; diff --git a/app/routes/index.js b/app/routes/index.js index 0f6c216d..20c7a0fa 100644 --- a/app/routes/index.js +++ b/app/routes/index.js @@ -2,7 +2,6 @@ const choo = require('choo'); const html = require('choo/html'); const nanotiming = require('nanotiming'); const download = require('./download'); -const header = require('../templates/header'); const footer = require('../templates/footer'); const fxPromo = require('../templates/fxPromo'); const signupPromo = require('../templates/signupPromo'); @@ -24,7 +23,6 @@ function body(template) { const b = html` ${banner(state, emit)} ${signupPromo(state)} - ${header(state)}