send/frontend/src/utils.js

145 lines
3.4 KiB
JavaScript
Raw Normal View History

2017-06-28 18:30:14 +00:00
function arrayToHex(iv) {
2017-06-02 03:59:27 +00:00
let hexStr = '';
// eslint-disable-next-line prefer-const
2017-07-27 14:46:28 +00:00
for (let i in iv) {
2017-06-02 03:59:27 +00:00
if (iv[i] < 16) {
hexStr += '0' + iv[i].toString(16);
} else {
hexStr += iv[i].toString(16);
}
}
return hexStr;
}
2017-06-28 18:30:14 +00:00
function hexToArray(str) {
const iv = new Uint8Array(str.length / 2);
2017-06-02 03:59:27 +00:00
for (let i = 0; i < str.length; i += 2) {
iv[i / 2] = parseInt(str.charAt(i) + str.charAt(i + 1), 16);
}
return iv;
}
2017-06-21 20:23:36 +00:00
function notify(str) {
2017-07-26 18:24:58 +00:00
return str;
/* TODO: enable once we have an opt-in ui element
if (!('Notification' in window)) {
2017-06-21 20:23:36 +00:00
return;
} else if (Notification.permission === 'granted') {
new Notification(str);
2017-06-21 20:23:36 +00:00
} else if (Notification.permission !== 'denied') {
Notification.requestPermission(function(permission) {
if (permission === 'granted') new Notification(str);
});
2017-06-21 20:23:36 +00:00
}
2017-07-26 18:24:58 +00:00
*/
2017-06-21 20:23:36 +00:00
}
function gcmCompliant() {
try {
2017-07-12 17:53:29 +00:00
return window.crypto.subtle
.generateKey(
{
name: 'AES-GCM',
2017-07-12 17:53:29 +00:00
length: 128
},
2017-07-12 17:53:29 +00:00
true,
['encrypt', 'decrypt']
)
2017-07-12 17:53:29 +00:00
.then(key => {
return window.crypto.subtle
.encrypt(
{
name: 'AES-GCM',
iv: window.crypto.getRandomValues(new Uint8Array(12)),
additionalData: window.crypto.getRandomValues(new Uint8Array(6)),
tagLength: 128
},
key,
new ArrayBuffer(8)
)
.then(() => {
return Promise.resolve();
});
})
.catch(err => {
return loadShim();
2017-07-12 17:53:29 +00:00
});
} catch (err) {
return loadShim();
}
function loadShim() {
return new Promise((resolve, reject) => {
const shim = document.createElement('script');
shim.src = '/cryptofill.js';
shim.addEventListener('load', resolve);
shim.addEventListener('error', reject);
document.head.appendChild(shim);
});
}
}
function isFile(id) {
return /^[0-9a-fA-F]{10}$/.test(id);
}
2017-08-04 03:13:17 +00: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);
} else {
2017-08-04 03:13:17 +00:00
aux.select();
}
const result = document.execCommand('copy');
2017-08-04 03:13:17 +00:00
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'
);
const UNITS = ['B', 'kB', 'MB', 'GB'];
function bytes(num) {
const exponent = Math.min(Math.floor(Math.log10(num) / 3), UNITS.length - 1);
const n = Number(num / Math.pow(1000, exponent));
const nStr = LOCALIZE_NUMBERS
? n.toLocaleString(navigator.languages, {
minimumFractionDigits: 1,
maximumFractionDigits: 1
})
: n.toFixed(1);
return `${nStr}${UNITS[exponent]}`;
}
function percent(ratio) {
return LOCALIZE_NUMBERS
? ratio.toLocaleString(navigator.languages, { style: 'percent' })
: `${Math.floor(ratio * 100)}%`;
}
const ONE_DAY_IN_MS = 86400000;
2017-08-10 17:02:13 +00:00
export {
2017-08-06 01:06:43 +00:00
bytes,
percent,
2017-08-04 03:13:17 +00:00
copyToClipboard,
2017-06-28 18:30:14 +00:00
arrayToHex,
hexToArray,
notify,
2017-07-20 22:16:00 +00:00
gcmCompliant,
isFile,
ONE_DAY_IN_MS
2017-06-02 03:59:27 +00:00
};