Stackedit/src/services/utils.js
2017-10-07 12:22:24 +01:00

140 lines
4.1 KiB
JavaScript

import yaml from 'js-yaml';
import defaultProperties from '../data/defaultFileProperties.yml';
const workspaceId = 'main';
const origin = `${location.protocol}//${location.host}`;
// For uid()
const uidLength = 16;
const crypto = window.crypto || window.msCrypto;
const alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
const radix = alphabet.length;
const array = new Uint32Array(uidLength);
// For isUserActive
const inactiveAfter = 2 * 60 * 1000; // 2 minutes
let lastActivity;
const setLastActivity = () => {
lastActivity = Date.now();
};
window.document.addEventListener('mousedown', setLastActivity);
window.document.addEventListener('keydown', setLastActivity);
window.document.addEventListener('touchstart', setLastActivity);
// For isWindowFocused
let lastFocus;
const lastFocusKey = `${workspaceId}/lastWindowFocus`;
const lastOpened = parseInt(localStorage[lastFocusKey], 10) || 0;
const setLastFocus = () => {
lastFocus = Date.now();
localStorage[lastFocusKey] = lastFocus;
setLastActivity();
};
setLastFocus();
window.addEventListener('focus', setLastFocus);
// For addQueryParams()
const urlParser = window.document.createElement('a');
export default {
workspaceId,
origin,
oauth2RedirectUri: `${origin}/oauth2/callback`,
lastOpened,
cleanTrashAfter: 7 * 1000, // 7 days
types: [
'contentState',
'syncedContent',
'content',
'file',
'folder',
'syncLocation',
'publishLocation',
'data',
],
deepCopy(obj) {
return obj == null ? obj : JSON.parse(JSON.stringify(obj));
},
serializeObject(obj) {
return obj === undefined ? obj : JSON.stringify(obj, (key, value) => {
if (Object.prototype.toString.call(value) !== '[object Object]') {
return value;
}
// Sort keys to have a predictable result
return Object.keys(value).sort().reduce((sorted, valueKey) => {
sorted[valueKey] = value[valueKey];
return sorted;
}, {});
});
},
uid() {
crypto.getRandomValues(array);
return array.cl_map(value => alphabet[value % radix]).join('');
},
hash(str) {
let hash = 0;
if (!str) return hash;
for (let i = 0; i < str.length; i += 1) {
const char = str.charCodeAt(i);
hash = ((hash << 5) - hash) + char; // eslint-disable-line no-bitwise
hash |= 0; // eslint-disable-line no-bitwise
}
return hash;
},
encodeBase64(str) {
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
(match, p1) => String.fromCharCode(`0x${p1}`)));
},
decodeBase64(str) {
return decodeURIComponent(atob(str).split('').map(
c => `%${`00${c.charCodeAt(0).toString(16)}`.slice(-2)}`).join(''));
},
computeProperties(yamlProperties) {
const customProperties = yaml.safeLoad(yamlProperties);
const properties = yaml.safeLoad(defaultProperties);
const override = (obj, opt) => {
const objType = Object.prototype.toString.call(obj);
const optType = Object.prototype.toString.call(opt);
if (objType !== optType) {
return obj;
} else if (objType !== '[object Object]') {
return opt === undefined ? obj : opt;
}
Object.keys({
...obj,
...opt,
}).forEach((key) => {
obj[key] = override(obj[key], opt[key]);
});
return obj;
};
return override(properties, customProperties);
},
randomize(value) {
return Math.floor((1 + (Math.random() * 0.2)) * value);
},
setInterval(func, interval) {
return setInterval(() => func(), this.randomize(interval));
},
isWindowFocused() {
return parseInt(localStorage[lastFocusKey], 10) === lastFocus;
},
isUserActive() {
return lastActivity > Date.now() - inactiveAfter && this.isWindowFocused();
},
addQueryParams(url = '', params = {}) {
const keys = Object.keys(params).filter(key => params[key] != null);
if (!keys.length) {
return url;
}
urlParser.href = url;
if (urlParser.search) {
urlParser.search += '&';
} else {
urlParser.search = '?';
}
urlParser.search += keys.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`).join('&');
return urlParser.href;
},
};