fox-send/app/utils.js

302 lines
6.7 KiB
JavaScript
Raw Normal View History

2019-01-23 23:10:09 +00:00
/* global Android */
2019-11-06 04:37:44 +00:00
let html;
try {
html = require('choo/html');
} catch (e) {
// running in the service worker
}
const b64 = require('base64-js');
function arrayToB64(array) {
return b64
.fromByteArray(array)
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
2017-06-02 03:59:27 +00:00
}
function b64ToArray(str) {
2018-03-29 05:03:46 +00:00
return b64.toByteArray(str + '==='.slice((str.length + 3) % 4));
2017-06-02 03:59:27 +00:00
}
2019-04-26 20:30:33 +00:00
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) {
2019-03-26 16:58:04 +00:00
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();
2017-08-04 03:13:17 +00:00
}
const result = document.execCommand('copy');
document.body.removeChild(aux);
return result;
2017-08-04 03:13:17 +00:00
}
2017-08-06 01:06:43 +00:00
const LOCALIZE_NUMBERS = !!(
typeof Intl === 'object' &&
Intl &&
typeof Intl.NumberFormat === 'function' &&
typeof navigator === 'object'
2017-08-06 01:06:43 +00:00
);
2019-03-12 02:28:22 +00:00
const UNITS = ['bytes', 'kb', 'mb', 'gb'];
2019-03-01 00:31:37 +00:00
function bytes(num) {
if (num < 1) {
return '0B';
}
2017-08-06 01:06:43 +00:00
const exponent = Math.min(Math.floor(Math.log10(num) / 3), UNITS.length - 1);
const n = Number(num / Math.pow(1024, exponent));
2019-03-01 00:31:37 +00:00
const decimalDigits = Math.floor(n) === n ? 0 : 1;
let nStr = n.toFixed(decimalDigits);
2017-11-09 21:58:20 +00:00
if (LOCALIZE_NUMBERS) {
try {
2019-04-26 20:30:33 +00:00
nStr = n.toLocaleString(locale(), {
minimumFractionDigits: decimalDigits,
maximumFractionDigits: decimalDigits
2017-11-09 21:58:20 +00:00
});
} catch (e) {
// fall through
}
}
2019-03-12 02:28:22 +00:00
return translate('fileSize', {
num: nStr,
units: translate(UNITS[exponent])
});
2017-08-06 01:06:43 +00:00
}
function percent(ratio) {
2017-11-09 21:58:20 +00:00
if (LOCALIZE_NUMBERS) {
try {
2019-04-26 20:30:33 +00:00
return ratio.toLocaleString(locale(), { style: 'percent' });
2017-11-09 21:58:20 +00:00
} catch (e) {
// fall through
}
}
return `${Math.floor(ratio * 100)}%`;
}
2018-02-08 03:46:18 +00:00
function number(n) {
if (LOCALIZE_NUMBERS) {
2019-04-26 20:30:33 +00:00
return n.toLocaleString(locale());
2018-02-08 03:46:18 +00:00
}
return n.toString();
}
2017-08-11 02:01:39 +00:00
function allowedCopy() {
const support = !!document.queryCommandSupported;
return support ? document.queryCommandSupported('copy') : false;
}
function delay(delay = 100) {
return new Promise(resolve => setTimeout(resolve, delay));
}
function fadeOut(selector) {
const classes = document.querySelector(selector).classList;
classes.remove('effect--fadeIn');
classes.add('effect--fadeOut');
return delay(300);
}
2018-01-24 18:23:13 +00:00
function openLinksInNewTab(links, should = true) {
links = links || Array.from(document.querySelectorAll('a:not([target])'));
if (should) {
links.forEach(l => {
l.setAttribute('target', '_blank');
l.setAttribute('rel', 'noopener noreferrer');
});
} else {
links.forEach(l => {
l.removeAttribute('target');
l.removeAttribute('rel');
});
}
return links;
}
2018-08-03 19:24:41 +00:00
function browserName() {
try {
// order of these matters
2018-08-03 19:24:41 +00:00
if (/firefox/i.test(navigator.userAgent)) {
return 'firefox';
2018-07-31 18:09:18 +00:00
}
2018-08-03 19:24:41 +00:00
if (/edge/i.test(navigator.userAgent)) {
return 'edge';
}
if (/edg/i.test(navigator.userAgent)) {
return 'edgium';
}
2018-08-03 19:24:41 +00:00
if (/trident/i.test(navigator.userAgent)) {
return 'ie';
}
if (/chrome/i.test(navigator.userAgent)) {
return 'chrome';
}
if (/safari/i.test(navigator.userAgent)) {
return 'safari';
}
if (/send android/i.test(navigator.userAgent)) {
return 'android-app';
}
2018-08-03 19:24:41 +00:00
return 'other';
} catch (e) {
return 'unknown';
2018-07-31 18:09:18 +00:00
}
}
2018-08-07 22:40:17 +00:00
async function streamToArrayBuffer(stream, size) {
const reader = stream.getReader();
let state = await reader.read();
if (size) {
const result = new Uint8Array(size);
let offset = 0;
while (!state.done) {
result.set(state.value, offset);
offset += state.value.length;
state = await reader.read();
}
return result.buffer;
}
const parts = [];
let len = 0;
while (!state.done) {
parts.push(state.value);
len += state.value.length;
state = await reader.read();
}
let offset = 0;
const result = new Uint8Array(len);
for (const part of parts) {
result.set(part, offset);
offset += part.length;
}
return result.buffer;
}
2018-10-25 02:07:10 +00:00
function list(items, ulStyle = '', liStyle = '') {
2018-11-16 20:30:15 +00:00
const lis = items.map(
i =>
html`
<li class="${liStyle}">${i}</li>
`
);
return html`
<ul class="${ulStyle}">
${lis}
</ul>
`;
2018-10-25 02:07:10 +00:00
}
function secondsToL10nId(seconds) {
if (seconds < 3600) {
return { id: 'timespanMinutes', num: Math.floor(seconds / 60) };
} else if (seconds < 86400) {
return { id: 'timespanHours', num: Math.floor(seconds / 3600) };
} else {
return { id: 'timespanDays', num: Math.floor(seconds / 86400) };
}
}
function timeLeft(milliseconds) {
2018-11-16 20:30:15 +00:00
if (milliseconds < 1) {
return { id: 'linkExpiredAlt' };
}
2018-10-25 02:07:10 +00:00
const minutes = Math.floor(milliseconds / 1000 / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
if (days >= 1) {
return {
id: 'expiresDaysHoursMinutes',
days,
hours: hours % 24,
minutes: minutes % 60
};
}
if (hours >= 1) {
return {
id: 'expiresHoursMinutes',
hours,
minutes: minutes % 60
};
} else if (hours === 0) {
if (minutes === 0) {
return { id: 'expiresMinutes', minutes: '< 1' };
}
return { id: 'expiresMinutes', minutes };
}
return null;
}
2019-01-23 23:10:09 +00:00
function platform() {
if (typeof Android === 'object') {
return 'android';
}
return 'web';
}
const ECE_RECORD_SIZE = 1024 * 64;
const TAG_LENGTH = 16;
function encryptedSize(size, rs = ECE_RECORD_SIZE, tagLength = TAG_LENGTH) {
const chunk_meta = tagLength + 1; // Chunk metadata, tag and delimiter
return 21 + size + chunk_meta * Math.ceil(size / (rs - chunk_meta));
}
2019-03-12 02:28:22 +00:00
let translate = function() {
throw new Error('uninitialized translate function. call setTranslate first');
};
function setTranslate(t) {
translate = t;
}
module.exports = {
2019-04-26 20:30:33 +00:00
locale,
fadeOut,
delay,
2017-08-11 02:01:39 +00:00
allowedCopy,
2017-08-06 01:06:43 +00:00
bytes,
percent,
2018-02-08 03:46:18 +00:00
number,
2017-08-04 03:13:17 +00:00
copyToClipboard,
arrayToB64,
b64ToArray,
loadShim,
isFile,
2018-07-31 18:09:18 +00:00
openLinksInNewTab,
2018-08-07 22:40:17 +00:00
browserName,
2018-10-25 02:07:10 +00:00
streamToArrayBuffer,
list,
secondsToL10nId,
2019-01-23 23:10:09 +00:00
timeLeft,
platform,
2019-03-12 02:28:22 +00:00
encryptedSize,
setTranslate
2017-06-02 03:59:27 +00:00
};