Merge branch 'timvisee:master' into master
This commit is contained in:
commit
df9c7ea734
42 changed files with 23533 additions and 4150 deletions
|
@ -6,4 +6,4 @@ parserOptions:
|
|||
sourceType: module
|
||||
|
||||
rules:
|
||||
node/no-unsupported-features: off
|
||||
n/no-unsupported-features: off
|
||||
|
|
|
@ -45,13 +45,7 @@ async function checkCrypto() {
|
|||
);
|
||||
return true;
|
||||
} catch (err) {
|
||||
try {
|
||||
window.asmCrypto = await import('asmcrypto.js');
|
||||
await import('@dannycoates/webcrypto-liner/build/shim');
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,25 +60,12 @@ function checkStreams() {
|
|||
}
|
||||
}
|
||||
|
||||
async function polyfillStreams() {
|
||||
try {
|
||||
await import('@mattiasbuelens/web-streams-polyfill');
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export default async function getCapabilities() {
|
||||
const browser = browserName();
|
||||
const isMobile = /mobi|android/i.test(navigator.userAgent);
|
||||
const serviceWorker = 'serviceWorker' in navigator && browser !== 'edge';
|
||||
let crypto = await checkCrypto();
|
||||
const nativeStreams = checkStreams();
|
||||
let polyStreams = false;
|
||||
if (!nativeStreams) {
|
||||
polyStreams = await polyfillStreams();
|
||||
}
|
||||
let account = typeof AUTH_CONFIG !== 'undefined';
|
||||
try {
|
||||
account = account && !!localStorage;
|
||||
|
@ -106,10 +87,10 @@ export default async function getCapabilities() {
|
|||
account,
|
||||
crypto,
|
||||
serviceWorker,
|
||||
streamUpload: nativeStreams || polyStreams,
|
||||
streamUpload: nativeStreams,
|
||||
streamDownload:
|
||||
nativeStreams && serviceWorker && browser !== 'safari' && !mobileFirefox,
|
||||
multifile: nativeStreams || polyStreams,
|
||||
multifile: nativeStreams,
|
||||
share,
|
||||
standalone
|
||||
};
|
||||
|
|
|
@ -48,7 +48,7 @@ class ECETransformer {
|
|||
name: 'AES-GCM',
|
||||
length: 128
|
||||
},
|
||||
true, // Edge polyfill requires key to be extractable to encrypt :/
|
||||
false,
|
||||
['encrypt', 'decrypt']
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { FluentBundle } from '@fluent/bundle';
|
||||
import { FluentBundle, FluentResource } from '@fluent/bundle';
|
||||
|
||||
function makeBundle(locale, ftl) {
|
||||
const bundle = new FluentBundle(locale, { useIsolating: false });
|
||||
bundle.addMessages(ftl);
|
||||
bundle.addResource(new FluentResource(ftl));
|
||||
return bundle;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ export async function getTranslator(locale) {
|
|||
return function(id, data) {
|
||||
for (let bundle of bundles) {
|
||||
if (bundle.hasMessage(id)) {
|
||||
return bundle.format(bundle.getMessage(id), data);
|
||||
return bundle.formatPattern(bundle.getMessage(id).value, data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
41
app/main.css
41
app/main.css
|
@ -7,17 +7,14 @@ html {
|
|||
@tailwind components;
|
||||
|
||||
:not(input) {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
:root {
|
||||
--violet-gradient: linear-gradient(
|
||||
-180deg,
|
||||
rgba(144, 89, 255, 0.8) 0%,
|
||||
rgba(144, 89, 255, 0.4) 100%
|
||||
rgb(144 89 255 / 80%) 0%,
|
||||
rgb(144 89 255 / 40%) 100%
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -71,7 +68,7 @@ body {
|
|||
|
||||
.checkbox > label::before {
|
||||
/* @apply bg-grey-10; */
|
||||
@apply border;
|
||||
@apply border-default;
|
||||
@apply rounded-sm;
|
||||
|
||||
content: '';
|
||||
|
@ -204,19 +201,18 @@ progress::-webkit-progress-value {
|
|||
background-image: -webkit-linear-gradient(
|
||||
-45deg,
|
||||
transparent 20%,
|
||||
rgba(255, 255, 255, 0.4) 20%,
|
||||
rgba(255, 255, 255, 0.4) 40%,
|
||||
rgb(255 255 255 / 40%) 20%,
|
||||
rgb(255 255 255 / 40%) 40%,
|
||||
transparent 40%,
|
||||
transparent 60%,
|
||||
rgba(255, 255, 255, 0.4) 60%,
|
||||
rgba(255, 255, 255, 0.4) 80%,
|
||||
rgb(255 255 255 / 40%) 60%,
|
||||
rgb(255 255 255 / 40%) 80%,
|
||||
transparent 80%
|
||||
),
|
||||
-webkit-linear-gradient(left, var(--color-primary), var(--color-primary));
|
||||
/* stylelint-enable */
|
||||
border-radius: 2px;
|
||||
background-size: 21px 20px, 100% 100%, 100% 100%;
|
||||
-webkit-animation: animate-stripes 1s linear infinite;
|
||||
}
|
||||
|
||||
progress::-moz-progress-bar {
|
||||
|
@ -224,12 +220,12 @@ progress::-moz-progress-bar {
|
|||
background-image: -moz-linear-gradient(
|
||||
135deg,
|
||||
transparent 20%,
|
||||
rgba(255, 255, 255, 0.4) 20%,
|
||||
rgba(255, 255, 255, 0.4) 40%,
|
||||
rgb(255 255 255 / 40%) 20%,
|
||||
rgb(255 255 255 / 40%) 40%,
|
||||
transparent 40%,
|
||||
transparent 60%,
|
||||
rgba(255, 255, 255, 0.4) 60%,
|
||||
rgba(255, 255, 255, 0.4) 80%,
|
||||
rgb(255 255 255 / 40%) 60%,
|
||||
rgb(255 255 255 / 40%) 80%,
|
||||
transparent 80%
|
||||
),
|
||||
-moz-linear-gradient(left, var(--color-primary), var(--color-primary));
|
||||
|
@ -239,12 +235,6 @@ progress::-moz-progress-bar {
|
|||
animation: animate-stripes 1s linear infinite;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animate-stripes {
|
||||
100% {
|
||||
background-position: -21px 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animate-stripes {
|
||||
100% {
|
||||
background-position: -21px 0;
|
||||
|
@ -313,7 +303,7 @@ select {
|
|||
|
||||
@screen md {
|
||||
.main > section {
|
||||
@apply border;
|
||||
@apply border-default;
|
||||
@apply border-grey-80;
|
||||
}
|
||||
}
|
||||
|
@ -323,13 +313,12 @@ select {
|
|||
|
||||
@responsive {
|
||||
.shadow-light {
|
||||
box-shadow: 0 0 8px 0 rgba(12, 12, 13, 0.1);
|
||||
box-shadow: 0 0 8px 0 rgb(12 12 13 / 10%);
|
||||
}
|
||||
|
||||
.shadow-big {
|
||||
box-shadow: 0 12px 18px 2px rgba(34, 0, 51, 0.04),
|
||||
0 6px 22px 4px rgba(7, 48, 114, 0.12),
|
||||
0 6px 10px -4px rgba(14, 13, 26, 0.12);
|
||||
box-shadow: 0 12px 18px 2px rgb(34 0 51 / 4%),
|
||||
0 6px 22px 4px rgb(7 48 114 / 12%), 0 6px 10px -4px rgb(14 13 26 / 12%);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* global DEFAULTS LIMITS WEB_UI PREFS */
|
||||
import 'core-js';
|
||||
import 'fast-text-encoding'; // MS Edge support
|
||||
import 'intl-pluralrules';
|
||||
import choo from 'choo';
|
||||
import nanotiming from 'nanotiming';
|
||||
|
|
|
@ -110,7 +110,7 @@ class Storage {
|
|||
}
|
||||
|
||||
set user(info) {
|
||||
return this.engine.setItem('user', JSON.stringify(info));
|
||||
this.engine.setItem('user', JSON.stringify(info));
|
||||
}
|
||||
|
||||
getFileById(id) {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
/* global TransformStream */
|
||||
|
||||
export function transformStream(readable, transformer, oncancel) {
|
||||
try {
|
||||
return readable.pipeThrough(new TransformStream(transformer));
|
||||
|
|
|
@ -83,13 +83,13 @@ class Account extends Component {
|
|||
<input
|
||||
type="image"
|
||||
alt="${user.email}"
|
||||
class="w-8 h-8 rounded-full border text-primary md:text-white focus:outline"
|
||||
class="w-8 h-8 rounded-full border-default text-primary md:text-white focus:outline"
|
||||
src="${user.avatar}"
|
||||
onclick="${e => this.avatarClick(e)}"
|
||||
/>
|
||||
<ul
|
||||
id="accountMenu"
|
||||
class="invisible absolute top-0 right-0 mt-10 pt-2 pb-2 bg-white shadow-md whitespace-no-wrap outline-none z-50 dark:bg-grey-80"
|
||||
class="invisible absolute top-0 right-0 mt-10 pt-2 pb-2 bg-white shadow-md whitespace-nowrap outline-none z-50 dark:bg-grey-80"
|
||||
onblur="${e => this.hideMenu(e)}"
|
||||
>
|
||||
<li class="p-2 text-grey-60 dark:text-grey-50">${user.email}</li>
|
||||
|
|
|
@ -53,7 +53,7 @@ function password(state) {
|
|||
id="password-input"
|
||||
class="${state.archive.password
|
||||
? ''
|
||||
: 'invisible'} border rounded focus:border-primary leading-normal my-1 py-1 px-2 h-8 dark:bg-grey-80"
|
||||
: 'invisible'} border-default rounded-default focus:border-primary leading-normal my-1 py-1 px-2 h-8 dark:bg-grey-80"
|
||||
autocomplete="off"
|
||||
maxlength="${MAX_LENGTH}"
|
||||
type="password"
|
||||
|
@ -261,7 +261,7 @@ module.exports = function(state, emit, archive) {
|
|||
return html`
|
||||
<send-archive
|
||||
id="archive-${archive.id}"
|
||||
class="flex flex-col items-start rounded shadow-light bg-white p-4 w-full dark:bg-grey-90 dark:border dark:border-grey-70"
|
||||
class="flex flex-col items-start rounded-default shadow-light bg-white p-4 w-full dark:bg-grey-90 dark:border-default dark:border-grey-70"
|
||||
>
|
||||
${archiveInfo(
|
||||
archive,
|
||||
|
@ -335,7 +335,7 @@ module.exports.wip = function(state, emit) {
|
|||
fileInfo(f, remove(f, state.translate('deleteButtonHover')))
|
||||
),
|
||||
'flex-shrink bg-grey-10 rounded-t overflow-y-auto px-6 py-4 md:h-full md:max-h-half-screen dark:bg-black',
|
||||
'bg-white px-2 my-2 shadow-light rounded dark:bg-grey-90 dark:border dark:border-grey-80'
|
||||
'bg-white px-2 my-2 shadow-light rounded-default dark:bg-grey-90 dark:border-default dark:border-grey-80'
|
||||
)}
|
||||
<div
|
||||
class="flex-shrink-0 flex-grow flex items-end p-4 bg-grey-10 rounded-b mb-1 font-medium dark:bg-grey-90"
|
||||
|
@ -438,7 +438,7 @@ module.exports.uploading = function(state, emit) {
|
|||
return html`
|
||||
<send-upload-area
|
||||
id="${archive.id}"
|
||||
class="flex flex-col items-start rounded shadow-light bg-white p-4 w-full dark:bg-grey-90"
|
||||
class="flex flex-col items-start rounded-default shadow-light bg-white p-4 w-full dark:bg-grey-90"
|
||||
>
|
||||
${archiveInfo(archive)}
|
||||
<div class="text-xs opacity-75 w-full mt-2 mb-2">
|
||||
|
@ -488,7 +488,7 @@ module.exports.empty = function(state, emit) {
|
|||
`;
|
||||
return html`
|
||||
<send-upload-area
|
||||
class="flex flex-col items-center justify-center border-2 border-dashed border-grey-transparent rounded px-6 py-16 h-full w-full dark:border-grey-60"
|
||||
class="flex flex-col items-center justify-center border-2 border-dashed border-grey-transparent rounded-default px-6 py-16 h-full w-full dark:border-grey-60"
|
||||
onclick="${e => {
|
||||
if (e.target.tagName !== 'LABEL') {
|
||||
document.getElementById('file-upload').click();
|
||||
|
@ -563,7 +563,7 @@ module.exports.preview = function(state, emit) {
|
|||
<send-archive
|
||||
class="flex flex-col max-h-full bg-white p-4 w-full md:w-128 dark:bg-grey-90"
|
||||
>
|
||||
<div class="border rounded py-3 px-6 dark:border-grey-70">
|
||||
<div class="border-default rounded-default py-3 px-6 dark:border-grey-70">
|
||||
${archiveInfo(archive)} ${details}
|
||||
</div>
|
||||
<button
|
||||
|
@ -590,7 +590,7 @@ module.exports.downloading = function(state) {
|
|||
const progressPercent = percent(progress);
|
||||
return html`
|
||||
<send-archive
|
||||
class="flex flex-col bg-white rounded shadow-light p-4 w-full max-w-sm md:w-128 dark:bg-grey-90"
|
||||
class="flex flex-col bg-white rounded-default shadow-light p-4 w-full max-w-sm md:w-128 dark:bg-grey-90"
|
||||
>
|
||||
${archiveInfo(archive)}
|
||||
<div class="link-primary text-sm font-medium mt-2">
|
||||
|
|
|
@ -21,7 +21,7 @@ module.exports = function(name, url) {
|
|||
<input
|
||||
type="text"
|
||||
id="share-url"
|
||||
class="block w-full my-4 border rounded-lg leading-loose h-12 px-2 py-1 dark:bg-grey-80"
|
||||
class="block w-full my-4 border-default rounded-lg leading-loose h-12 px-2 py-1 dark:bg-grey-80"
|
||||
value="${url}"
|
||||
readonly="true"
|
||||
/>
|
||||
|
|
|
@ -17,7 +17,7 @@ module.exports = function(state, emit) {
|
|||
${state.translate('downloadDescription')}
|
||||
</p>
|
||||
<form
|
||||
class="flex flex-row flex-no-wrap w-full md:w-4/5"
|
||||
class="flex flex-row flex-nowrap w-full md:w-4/5"
|
||||
onsubmit="${checkPassword}"
|
||||
data-no-csrf
|
||||
>
|
||||
|
|
|
@ -12,12 +12,12 @@ module.exports = function(state, emit) {
|
|||
'downloadTitle'
|
||||
)}</h1>
|
||||
<p
|
||||
class="w-full p-2 border border-yellow-50 rounded md:w-4/5 text-orange-60 bg-yellow-40 text-center leading-normal"
|
||||
class="w-full p-2 border-default border-yellow-50 rounded-default md:w-4/5 text-orange-60 bg-yellow-40 text-center leading-normal"
|
||||
>
|
||||
⚠️ ${state.translate('noStreamsWarning')} ⚠️
|
||||
</p>
|
||||
<form class="md:w-128" onsubmit=${submit}>
|
||||
<fieldset class="border rounded p-4 my-4" onchange=${optionChanged}>
|
||||
<fieldset class="border-default rounded-default p-4 my-4" onchange=${optionChanged}>
|
||||
<div class="flex items-center mb-2">
|
||||
<svg class="h-8 w-6 mr-3 flex-shrink-0 text-primary">
|
||||
<use xlink:href="${assets.get('blue_file.svg')}#icon"/>
|
||||
|
|
|
@ -18,7 +18,7 @@ module.exports = function(selected, options, translate, changed, htmlId) {
|
|||
return html`
|
||||
<select
|
||||
id="${htmlId}"
|
||||
class="appearance-none cursor-pointer border rounded bg-grey-10 hover:border-primary focus:border-primary pl-1 pr-8 py-1 my-1 h-8 dark:bg-grey-80"
|
||||
class="appearance-none cursor-pointer border-default rounded-default bg-grey-10 hover:border-primary focus:border-primary pl-1 pr-8 py-1 my-1 h-8 dark:bg-grey-80"
|
||||
data-selected="${selected}"
|
||||
onchange="${choose}"
|
||||
>
|
||||
|
|
|
@ -18,7 +18,7 @@ module.exports = function(name, url) {
|
|||
<input
|
||||
type="text"
|
||||
id="share-url"
|
||||
class="w-full my-4 border rounded-lg leading-loose h-12 px-2 py-1 dark:bg-grey-80"
|
||||
class="w-full my-4 border-default rounded-lg leading-loose h-12 px-2 py-1 dark:bg-grey-80"
|
||||
value="${url}"
|
||||
readonly="true"
|
||||
/>
|
||||
|
|
|
@ -35,7 +35,7 @@ module.exports = function() {
|
|||
<input
|
||||
id="email-input"
|
||||
type="email"
|
||||
class="hidden border rounded-lg w-full px-2 py-1 h-12 mb-3 text-lg text-grey-70 leading-loose dark:bg-grey-80 dark:text-white"
|
||||
class="hidden border-default rounded-lg w-full px-2 py-1 h-12 mb-3 text-lg text-grey-70 leading-loose dark:bg-grey-80 dark:text-white"
|
||||
placeholder=${state.translate('emailPlaceholder')}
|
||||
/>
|
||||
<input
|
||||
|
|
|
@ -27,7 +27,7 @@ module.exports = function(state, emit) {
|
|||
<main class="main">
|
||||
${state.modal && modal(state, emit)}
|
||||
<section
|
||||
class="flex flex-col items-center justify-center text-center bg-white m-6 px-6 py-8 border border-grey-30 md:border-none md:px-12 md:py-16 shadow w-full md:h-full dark:bg-grey-90"
|
||||
class="flex flex-col items-center justify-center text-center bg-white m-6 px-6 py-8 border-default border-grey-30 md:border-none md:px-12 md:py-16 shadow-default w-full md:h-full dark:bg-grey-90"
|
||||
>
|
||||
<h1 class="text-3xl font-bold">${strings.header}</h1>
|
||||
<p class="mt-4 mb-8 max-w-md leading-normal">${strings.description}</p>
|
||||
|
|
52
app/utils.js
52
app/utils.js
|
@ -23,39 +23,34 @@ function locale() {
|
|||
return document.querySelector('html').lang;
|
||||
}
|
||||
|
||||
function loadShim(polyfill) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const shim = document.createElement('script');
|
||||
shim.src = polyfill;
|
||||
shim.addEventListener('load', () => resolve(true));
|
||||
shim.addEventListener('error', () => resolve(false));
|
||||
document.head.appendChild(shim);
|
||||
});
|
||||
}
|
||||
|
||||
function isFile(id) {
|
||||
return /^[0-9a-fA-F]{10,16}$/.test(id);
|
||||
}
|
||||
|
||||
function copyToClipboard(str) {
|
||||
const aux = document.createElement('input');
|
||||
aux.setAttribute('value', str);
|
||||
aux.contentEditable = true;
|
||||
aux.readOnly = true;
|
||||
document.body.appendChild(aux);
|
||||
if (navigator.userAgent.match(/iphone|ipad|ipod/i)) {
|
||||
const range = document.createRange();
|
||||
range.selectNodeContents(aux);
|
||||
const sel = getSelection();
|
||||
sel.removeAllRanges();
|
||||
sel.addRange(range);
|
||||
aux.setSelectionRange(0, str.length);
|
||||
} else {
|
||||
aux.select();
|
||||
async function copyToClipboard(str) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(str);
|
||||
} catch {
|
||||
// Older browsers or the clipboard API fails because of a missing permission
|
||||
const aux = document.createElement('input');
|
||||
aux.setAttribute('value', str);
|
||||
aux.contentEditable = true;
|
||||
aux.readOnly = true;
|
||||
document.body.appendChild(aux);
|
||||
if (navigator.userAgent.match(/iphone|ipad|ipod/i)) {
|
||||
const range = document.createRange();
|
||||
range.selectNodeContents(aux);
|
||||
const sel = getSelection();
|
||||
sel.removeAllRanges();
|
||||
sel.addRange(range);
|
||||
aux.setSelectionRange(0, str.length);
|
||||
} else {
|
||||
aux.select();
|
||||
}
|
||||
const result = document.execCommand('copy');
|
||||
document.body.removeChild(aux);
|
||||
return result;
|
||||
}
|
||||
const result = document.execCommand('copy');
|
||||
document.body.removeChild(aux);
|
||||
return result;
|
||||
}
|
||||
|
||||
const LOCALIZE_NUMBERS = !!(
|
||||
|
@ -287,7 +282,6 @@ module.exports = {
|
|||
copyToClipboard,
|
||||
arrayToB64,
|
||||
b64ToArray,
|
||||
loadShim,
|
||||
isFile,
|
||||
openLinksInNewTab,
|
||||
browserName,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue