2017-08-31 18:43:36 +02:00
|
|
|
const b64 = require('base64-js');
|
|
|
|
|
|
|
|
function arrayToB64(array) {
|
|
|
|
return b64
|
|
|
|
.fromByteArray(array)
|
|
|
|
.replace(/\+/g, '-')
|
|
|
|
.replace(/\//g, '_')
|
|
|
|
.replace(/=/g, '');
|
2017-06-02 05:59:27 +02:00
|
|
|
}
|
|
|
|
|
2017-08-31 18:43:36 +02:00
|
|
|
function b64ToArray(str) {
|
|
|
|
str = (str + '==='.slice((str.length + 3) % 4))
|
|
|
|
.replace(/-/g, '+')
|
|
|
|
.replace(/_/g, '/');
|
|
|
|
return b64.toByteArray(str);
|
2017-06-02 05:59:27 +02:00
|
|
|
}
|
|
|
|
|
2017-06-21 22:23:36 +02:00
|
|
|
function notify(str) {
|
2017-07-26 20:24:58 +02:00
|
|
|
return str;
|
|
|
|
/* TODO: enable once we have an opt-in ui element
|
2017-06-20 21:18:14 +02:00
|
|
|
if (!('Notification' in window)) {
|
2017-06-21 22:23:36 +02:00
|
|
|
return;
|
|
|
|
} else if (Notification.permission === 'granted') {
|
2017-06-21 23:31:21 +02:00
|
|
|
new Notification(str);
|
2017-06-21 22:23:36 +02:00
|
|
|
} else if (Notification.permission !== 'denied') {
|
|
|
|
Notification.requestPermission(function(permission) {
|
2017-06-21 23:31:21 +02:00
|
|
|
if (permission === 'granted') new Notification(str);
|
|
|
|
});
|
2017-06-21 22:23:36 +02:00
|
|
|
}
|
2017-07-26 20:24:58 +02:00
|
|
|
*/
|
2017-06-21 22:23:36 +02:00
|
|
|
}
|
|
|
|
|
2017-08-24 23:54:02 +02:00
|
|
|
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);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
async function canHasSend(polyfill) {
|
2017-07-10 22:27:01 +02:00
|
|
|
try {
|
2017-08-24 23:54:02 +02:00
|
|
|
const key = await window.crypto.subtle.generateKey(
|
|
|
|
{
|
|
|
|
name: 'AES-GCM',
|
|
|
|
length: 128
|
|
|
|
},
|
|
|
|
true,
|
|
|
|
['encrypt', 'decrypt']
|
|
|
|
);
|
|
|
|
|
|
|
|
await window.crypto.subtle.encrypt(
|
|
|
|
{
|
|
|
|
name: 'AES-GCM',
|
|
|
|
iv: window.crypto.getRandomValues(new Uint8Array(12)),
|
|
|
|
tagLength: 128
|
|
|
|
},
|
|
|
|
key,
|
|
|
|
new ArrayBuffer(8)
|
|
|
|
);
|
|
|
|
return true;
|
2017-07-12 19:53:29 +02:00
|
|
|
} catch (err) {
|
2017-08-24 23:54:02 +02:00
|
|
|
return loadShim(polyfill);
|
2017-07-10 22:27:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-21 01:06:06 +02:00
|
|
|
function isFile(id) {
|
2017-08-02 20:17:23 +02:00
|
|
|
return /^[0-9a-fA-F]{10}$/.test(id);
|
2017-07-21 01:06:06 +02:00
|
|
|
}
|
|
|
|
|
2017-08-04 05:13:17 +02:00
|
|
|
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 = window.getSelection();
|
|
|
|
sel.removeAllRanges();
|
|
|
|
sel.addRange(range);
|
|
|
|
aux.setSelectionRange(0, str.length);
|
2017-08-04 23:44:11 +02:00
|
|
|
} else {
|
2017-08-04 05:13:17 +02:00
|
|
|
aux.select();
|
|
|
|
}
|
2017-08-04 23:44:11 +02:00
|
|
|
const result = document.execCommand('copy');
|
2017-08-04 05:13:17 +02:00
|
|
|
document.body.removeChild(aux);
|
2017-08-04 23:44:11 +02:00
|
|
|
return result;
|
2017-08-04 05:13:17 +02:00
|
|
|
}
|
|
|
|
|
2017-08-06 03:06:43 +02:00
|
|
|
const LOCALIZE_NUMBERS = !!(
|
|
|
|
typeof Intl === 'object' &&
|
|
|
|
Intl &&
|
2017-08-24 23:54:02 +02:00
|
|
|
typeof Intl.NumberFormat === 'function' &&
|
|
|
|
typeof navigator === 'object'
|
2017-08-06 03:06:43 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
const UNITS = ['B', 'kB', 'MB', 'GB'];
|
|
|
|
function bytes(num) {
|
2017-08-31 18:43:36 +02:00
|
|
|
if (num < 1) {
|
|
|
|
return '0B';
|
|
|
|
}
|
2017-08-06 03:06:43 +02:00
|
|
|
const exponent = Math.min(Math.floor(Math.log10(num) / 3), UNITS.length - 1);
|
|
|
|
const n = Number(num / Math.pow(1000, exponent));
|
2017-11-09 22:58:20 +01:00
|
|
|
let nStr = n.toFixed(1);
|
|
|
|
if (LOCALIZE_NUMBERS) {
|
|
|
|
try {
|
2017-11-08 00:54:42 +01:00
|
|
|
const locale = document.querySelector('html').lang;
|
|
|
|
nStr = n.toLocaleString(locale, {
|
2017-08-06 03:06:43 +02:00
|
|
|
minimumFractionDigits: 1,
|
|
|
|
maximumFractionDigits: 1
|
2017-11-09 22:58:20 +01:00
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
// fall through
|
|
|
|
}
|
|
|
|
}
|
2017-08-06 03:06:43 +02:00
|
|
|
return `${nStr}${UNITS[exponent]}`;
|
|
|
|
}
|
|
|
|
|
2017-08-09 04:46:15 +02:00
|
|
|
function percent(ratio) {
|
2017-11-09 22:58:20 +01:00
|
|
|
if (LOCALIZE_NUMBERS) {
|
|
|
|
try {
|
2017-11-08 00:54:42 +01:00
|
|
|
const locale = document.querySelector('html').lang;
|
|
|
|
return ratio.toLocaleString(locale, { style: 'percent' });
|
2017-11-09 22:58:20 +01:00
|
|
|
} catch (e) {
|
|
|
|
// fall through
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return `${Math.floor(ratio * 100)}%`;
|
2017-08-09 04:46:15 +02:00
|
|
|
}
|
|
|
|
|
2017-08-11 04:01:39 +02:00
|
|
|
function allowedCopy() {
|
|
|
|
const support = !!document.queryCommandSupported;
|
|
|
|
return support ? document.queryCommandSupported('copy') : false;
|
|
|
|
}
|
|
|
|
|
2017-08-24 23:54:02 +02:00
|
|
|
function delay(delay = 100) {
|
|
|
|
return new Promise(resolve => setTimeout(resolve, delay));
|
|
|
|
}
|
|
|
|
|
|
|
|
function fadeOut(id) {
|
|
|
|
const classes = document.getElementById(id).classList;
|
|
|
|
classes.remove('fadeIn');
|
|
|
|
classes.add('fadeOut');
|
|
|
|
return delay(300);
|
|
|
|
}
|
|
|
|
|
2017-07-21 01:06:06 +02:00
|
|
|
const ONE_DAY_IN_MS = 86400000;
|
|
|
|
|
2017-08-24 23:54:02 +02:00
|
|
|
module.exports = {
|
|
|
|
fadeOut,
|
|
|
|
delay,
|
2017-08-11 04:01:39 +02:00
|
|
|
allowedCopy,
|
2017-08-06 03:06:43 +02:00
|
|
|
bytes,
|
2017-08-09 04:46:15 +02:00
|
|
|
percent,
|
2017-08-04 05:13:17 +02:00
|
|
|
copyToClipboard,
|
2017-08-31 18:43:36 +02:00
|
|
|
arrayToB64,
|
|
|
|
b64ToArray,
|
2017-07-10 22:27:01 +02:00
|
|
|
notify,
|
2017-08-24 23:54:02 +02:00
|
|
|
canHasSend,
|
2017-07-21 01:06:06 +02:00
|
|
|
isFile,
|
|
|
|
ONE_DAY_IN_MS
|
2017-06-02 05:59:27 +02:00
|
|
|
};
|