diff --git a/app/base.css b/app/base.css new file mode 100644 index 00000000..cf0f0bf0 --- /dev/null +++ b/app/base.css @@ -0,0 +1,257 @@ +:root { + --pageBGColor: #fff; + --primaryControlBGColor: #0297f8; + --primaryControlFGColor: #fff; + --primaryControlHoverColor: #0287e8; + --inputTextColor: #737373; + --errorColor: #d70022; + --linkColor: #0094fb; + --textColor: #0c0c0d; + --lightTextColor: #737373; + --successControlBGColor: #05a700; + --successControlFGColor: #fff; +} + +html { + background: url('../assets/send_bg.svg'); + font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'segoe ui', + 'helvetica neue', helvetica, ubuntu, roboto, noto, arial, sans-serif; + font-weight: 200; + background-size: 110%; + background-repeat: no-repeat; + background-position: center top; + height: 100%; + margin: auto; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'segoe ui', + 'helvetica neue', helvetica, ubuntu, roboto, noto, arial, sans-serif; + display: flex; + flex-direction: column; + margin: 0; + min-height: 100vh; + position: relative; +} + +pre, +input, +select, +textarea, +button { + font-family: inherit; + margin: 0; +} + +pre { + font-family: monospace; + font-size: 18px; + font-weight: 600; + display: inline-block; +} + +a { + text-decoration: none; +} + +.all { + flex: 1; + display: flex; + flex-direction: column; + justify-content: flex-start; + max-width: 650px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; + width: 96%; +} + +.btn { + font-size: 15px; + font-weight: 500; + color: white; + cursor: pointer; + text-align: center; + background: var(--primaryControlBGColor); + border: 1px solid var(--primaryControlBGColor); + border-radius: 5px; +} + +.btn--cancel { + color: var(--errorColor); + background: var(--pageBGColor); + font-size: 15px; + border: 0; + cursor: pointer; + text-decoration: underline; +} + +.btn--cancel:disabled { + text-decoration: none; + cursor: auto; +} + +.input { + border: 1px solid var(--primaryControlBGColor); + border-radius: 6px 0 0 6px; + font-size: 20px; + color: var(--inputTextColor); + font-family: 'SF Pro Text', sans-serif; + letter-spacing: 0; + line-height: 23px; + font-weight: 300; + height: 46px; + padding-left: 10px; + padding-right: 10px; +} + +.input--noBtn { + border-radius: 6px; +} + +.inputBtn { + background: var(--primaryControlBGColor); + border-radius: 0 6px 6px 0; + border: 1px solid var(--primaryControlBGColor); + color: white; + cursor: pointer; + + /* Force flat button look */ + appearance: none; + font-size: 15px; + padding-bottom: 3px; + padding-left: 10px; + padding-right: 10px; + white-space: nowrap; +} + +.inputBtn:disabled { + cursor: auto; +} + +.inputBtn:hover { + background-color: var(--primaryControlHoverColor); +} + +.inputBtn--hidden { + display: none; +} + +.cursor--pointer { + cursor: pointer; +} + +.link { + color: var(--linkColor); + text-decoration: none; +} + +.link:focus, +.link:active, +.link:hover { + color: var(--primaryControlHoverColor); +} + +.link--action { + text-decoration: underline; + text-align: center; +} + +.page { + margin: 0 auto 30px; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + 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: rgba(0, 0, 0, 0.5); + letter-spacing: -0.4px; + margin-top: 24px; + margin-bottom: 74px; +} + +.effect--fadeOut { + opacity: 0; + animation: fadeout 200ms linear; +} + +@keyframes fadeout { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +.effect--fadeIn { + opacity: 1; + animation: fadein 200ms linear; +} + +@keyframes fadein { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +.title { + font-size: 33px; + line-height: 40px; + margin: 20px auto; + text-align: center; + max-width: 520px; + font-family: 'SF Pro Text', sans-serif; + word-wrap: break-word; +} + +.description { + font-size: 15px; + line-height: 23px; + max-width: 630px; + text-align: center; + margin: 0 auto 60px; + color: var(--textColor); + width: 92%; +} + +@media (max-device-width: 768px), (max-width: 768px) { + .description { + margin: 0 auto 25px; + } +} + +@media (max-device-width: 520px), (max-width: 520px) { + .input { + font-size: 22px; + padding: 10px 10px; + border-radius: 6px 6px 0 0; + } + + .inputBtn { + border-radius: 0 0 6px 6px; + flex: 0 1 65px; + } + + .input--noBtn { + border-radius: 6px; + } +} diff --git a/app/fileManager.js b/app/fileManager.js index 26da0fc6..7513d42d 100644 --- a/app/fileManager.js +++ b/app/fileManager.js @@ -108,7 +108,7 @@ export default function(state, emitter) { document.getElementById('cancel-upload').hidden = 'hidden'; await delay(1000); - await fadeOut('upload-progress'); + await fadeOut('.page'); openLinksInNewTab(links, false); emitter.emit('pushState', `/share/${ownedFile.id}`); } catch (err) { @@ -170,7 +170,7 @@ export default function(state, emitter) { const time = Date.now() - start; const speed = size / (time / 1000); await delay(1000); - await fadeOut('download-progress'); + await fadeOut('.page'); saveFile(f); state.storage.totalDownloads += 1; state.transfer.reset(); diff --git a/app/main.css b/app/main.css new file mode 100644 index 00000000..9c7c5dba --- /dev/null +++ b/app/main.css @@ -0,0 +1,19 @@ +@import './base.css'; +@import './templates/header/header.css'; +@import './templates/downloadButton/downloadButton.css'; +@import './templates/progress/progress.css'; +@import './templates/passwordInput/passwordInput.css'; +@import './templates/downloadPassword/downloadPassword.css'; +@import './templates/setPasswordSection/setPasswordSection.css'; +@import './templates/changePasswordSection/changePasswordSection.css'; +@import './templates/footer/footer.css'; +@import './templates/fxPromo/fxPromo.css'; +@import './templates/selectbox/selectbox.css'; +@import './templates/fileList/fileList.css'; +@import './templates/file/file.css'; +@import './templates/popup/popup.css'; +@import './pages/welcome/welcome.css'; +@import './pages/preview/preview.css'; +@import './pages/share/share.css'; +@import './pages/notFound/notFound.css'; +@import './pages/unsupported/unsupported.css'; diff --git a/app/pages/completed.js b/app/pages/completed.js deleted file mode 100644 index fa1fb896..00000000 --- a/app/pages/completed.js +++ /dev/null @@ -1,34 +0,0 @@ -const html = require('choo/html'); -const progress = require('../templates/progress'); -const { fadeOut } = require('../utils'); - -module.exports = function(state, emit) { - const div = html` -
-
-
-
- ${state.translate('downloadFinish')} -
-
- ${progress(1)} -
-
-
-
- ${state.translate('sendYourFilesLink')} -
-
- `; - - async function sendNew(e) { - e.preventDefault(); - await fadeOut('download'); - emit('pushState', '/'); - } - - return div; -}; diff --git a/app/pages/completed/index.js b/app/pages/completed/index.js new file mode 100644 index 00000000..88ba37e3 --- /dev/null +++ b/app/pages/completed/index.js @@ -0,0 +1,28 @@ +const html = require('choo/html'); +const progress = require('../../templates/progress'); +const { fadeOut } = require('../../utils'); + +module.exports = function(state, emit) { + const div = html` +
+
+ ${state.translate('downloadFinish')} +
+
+ ${progress(1)} +
+
+
+ ${state.translate('sendYourFilesLink')} +
`; + + async function sendNew(e) { + e.preventDefault(); + await fadeOut('.page'); + emit('pushState', '/'); + } + + return div; +}; diff --git a/app/pages/download.js b/app/pages/download.js deleted file mode 100644 index 4a415f17..00000000 --- a/app/pages/download.js +++ /dev/null @@ -1,46 +0,0 @@ -const html = require('choo/html'); -const progress = require('../templates/progress'); -const { bytes } = require('../utils'); - -module.exports = function(state, emit) { - const transfer = state.transfer; - const cancelBtn = html` - `; - - const div = html` -
-
-
-
- ${state.translate('downloadingPageProgress', { - filename: state.fileInfo.name, - size: bytes(state.fileInfo.size) - })} -
-
- ${state.translate('downloadingPageMessage')} -
- ${progress(transfer.progressRatio)} -
-
- ${state.translate(transfer.msg, transfer.sizes)} -
- ${transfer.state === 'downloading' ? cancelBtn : null} -
-
-
-
- `; - - function cancel() { - const btn = document.getElementById('cancel-upload'); - btn.remove(); - emit('cancel'); - } - return div; -}; diff --git a/app/pages/download/index.js b/app/pages/download/index.js new file mode 100644 index 00000000..f17cf5c7 --- /dev/null +++ b/app/pages/download/index.js @@ -0,0 +1,43 @@ +const html = require('choo/html'); +const progress = require('../../templates/progress'); +const { bytes } = require('../../utils'); + +module.exports = function(state, emit) { + const transfer = state.transfer; + const cancelBtn = html` + `; + + const div = html` +
+
+ ${state.translate('downloadingPageProgress', { + filename: state.fileInfo.name, + size: bytes(state.fileInfo.size) + })} +
+
+ ${state.translate('downloadingPageMessage')} +
+ ${progress(transfer.progressRatio)} +
+
+ ${state.translate(transfer.msg, transfer.sizes)} +
+ ${transfer.state === 'downloading' ? cancelBtn : null} +
+
+ `; + + function cancel() { + const btn = document.getElementById('cancel'); + btn.remove(); + emit('cancel'); + } + return div; +}; diff --git a/app/pages/error/error.css b/app/pages/error/error.css new file mode 100644 index 00000000..2bf8739c --- /dev/null +++ b/app/pages/error/error.css @@ -0,0 +1,11 @@ +.errorPage { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + text-align: center; +} + +.errorPage__img { + margin: 51px 0 71px; +} diff --git a/app/pages/error.js b/app/pages/error/index.js similarity index 51% rename from app/pages/error.js rename to app/pages/error/index.js index f7751faa..21446789 100644 --- a/app/pages/error.js +++ b/app/pages/error/index.js @@ -1,10 +1,10 @@ const html = require('choo/html'); -const assets = require('../../common/assets'); +const assets = require('../../../common/assets'); module.exports = function(state) { return html` -
+
${state.translate('errorPageHeader')}
- +
`; }; diff --git a/app/pages/legal.js b/app/pages/legal.js index 3b92b4d1..5b086ce7 100644 --- a/app/pages/legal.js +++ b/app/pages/legal.js @@ -12,23 +12,21 @@ function replaceLinks(str, urls) { module.exports = function(state) { const div = html` -
- + `; return div; diff --git a/app/pages/notFound.js b/app/pages/notFound/index.js similarity index 61% rename from app/pages/notFound.js rename to app/pages/notFound/index.js index 495b8b08..f8b32291 100644 --- a/app/pages/notFound.js +++ b/app/pages/notFound/index.js @@ -1,21 +1,19 @@ const html = require('choo/html'); -const assets = require('../../common/assets'); +const assets = require('../../../common/assets'); module.exports = function(state) { const div = html` -
-
+
${state.translate('expiredPageHeader')}
- `; +
`; return div; }; diff --git a/app/pages/notFound/notFound.css b/app/pages/notFound/notFound.css new file mode 100644 index 00000000..07bf0e15 --- /dev/null +++ b/app/pages/notFound/notFound.css @@ -0,0 +1,17 @@ +.notFoundPage { + margin: 0 auto 30px; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + text-align: center; +} + +.notFoundPage__img { + margin: 0 auto; + display: flex; + justify-content: center; + flex-direction: column; + width: 100%; + max-width: 640px; +} diff --git a/app/pages/preview.js b/app/pages/preview.js deleted file mode 100644 index 84e54f25..00000000 --- a/app/pages/preview.js +++ /dev/null @@ -1,44 +0,0 @@ -const html = require('choo/html'); -const assets = require('../../common/assets'); -const { bytes } = require('../utils'); - -module.exports = function(state, pageAction) { - const fileInfo = state.fileInfo; - - const size = fileInfo.size - ? state.translate('downloadFileSize', { size: bytes(fileInfo.size) }) - : ''; - - const title = fileInfo.name - ? state.translate('downloadFileName', { filename: fileInfo.name }) - : state.translate('downloadFileTitle'); - - const info = html` -
`; - if (!pageAction) { - return info; - } - const div = html` -
-
-
-
- ${title} - ${' ' + size} -
-
${state.translate('downloadMessage')}
- - ${pageAction} -
- ${state.translate('sendYourFilesLink')} -
- ${info} -
- `; - return div; -}; diff --git a/app/pages/preview/index.js b/app/pages/preview/index.js new file mode 100644 index 00000000..8c9f9d1d --- /dev/null +++ b/app/pages/preview/index.js @@ -0,0 +1,42 @@ +const html = require('choo/html'); +const assets = require('../../../common/assets'); +const { bytes } = require('../../utils'); + +module.exports = function(state, pageAction) { + const fileInfo = state.fileInfo; + + const size = fileInfo.size + ? state.translate('downloadFileSize', { size: bytes(fileInfo.size) }) + : ''; + + const title = fileInfo.name + ? state.translate('downloadFileName', { filename: fileInfo.name }) + : state.translate('downloadFileTitle'); + + const info = html` +
`; + if (!pageAction) { + return info; + } + const div = html` +
+
+ ${title} + ${' ' + size} +
+
${state.translate('downloadMessage')}
+ + ${pageAction} + + ${state.translate('sendYourFilesLink')} + + ${info} +
+ `; + return div; +}; diff --git a/app/pages/preview/preview.css b/app/pages/preview/preview.css new file mode 100644 index 00000000..83b1bc98 --- /dev/null +++ b/app/pages/preview/preview.css @@ -0,0 +1,4 @@ +.preview__img { + width: 283px; + height: 196px; +} diff --git a/app/pages/share.js b/app/pages/share/index.js similarity index 52% rename from app/pages/share.js rename to app/pages/share/index.js index aa16a8e5..1180b3cb 100644 --- a/app/pages/share.js +++ b/app/pages/share/index.js @@ -1,12 +1,13 @@ /* global EXPIRE_SECONDS */ const html = require('choo/html'); const raw = require('choo/html/raw'); -const assets = require('../../common/assets'); -const notFound = require('./notFound'); -const uploadPasswordSet = require('../templates/uploadPasswordSet'); -const uploadPasswordUnset = require('../templates/uploadPasswordUnset'); -const selectbox = require('../templates/selectbox'); -const { allowedCopy, delay, fadeOut } = require('../utils'); +const assets = require('../../../common/assets'); +const notFound = require('../notFound'); +const changePasswordSection = require('../../templates/changePasswordSection'); +const setPasswordSection = require('../../templates/setPasswordSection'); +const selectbox = require('../../templates/selectbox'); +const deletePopup = require('../../templates/popup'); +const { allowedCopy, delay, fadeOut } = require('../../utils'); function expireInfo(file, translate, emit) { const hours = Math.floor(EXPIRE_SECONDS / 60 / 60); @@ -34,44 +35,42 @@ module.exports = function(state, emit) { } const passwordSection = file.hasPassword - ? uploadPasswordSet(state, emit) - : uploadPasswordUnset(state, emit); + ? changePasswordSection(state, emit) + : setPasswordSection(state, emit); const div = html` -