mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-09-03 22:47:03 +03:00
Replaced dev/Common/ClientStorageDriver/* with webstorage polyfill
Cleanup some other code
This commit is contained in:
parent
0e8bf13d5d
commit
b837013cfb
13 changed files with 201 additions and 594 deletions
|
|
@ -1,162 +0,0 @@
|
|||
import { CLIENT_SIDE_STORAGE_INDEX_NAME } from 'Common/Consts';
|
||||
|
||||
var Cookies = (() => {
|
||||
function extend (...args) {
|
||||
var result = {};
|
||||
args.forEach(attributes => {
|
||||
for (var key in attributes) {
|
||||
result[key] = attributes[key];
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function decode (s) {
|
||||
return s.replace(/(%[0-9A-Z]{2})+/g, decodeURIComponent);
|
||||
}
|
||||
|
||||
function set (key, value, attributes) {
|
||||
if (typeof document === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
attributes = extend({
|
||||
path: '/'
|
||||
}, attributes);
|
||||
|
||||
if (typeof attributes.expires === 'number') {
|
||||
attributes.expires = new Date(new Date() * 1 + attributes.expires * 864e+5);
|
||||
}
|
||||
|
||||
// We're using "expires" because "max-age" is not supported by IE
|
||||
attributes.expires = attributes.expires ? attributes.expires.toUTCString() : '';
|
||||
|
||||
try {
|
||||
var result = JSON.stringify(value);
|
||||
if (/^[{[]/.test(result)) {
|
||||
value = result;
|
||||
}
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
|
||||
value = encodeURIComponent(String(value))
|
||||
.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
|
||||
|
||||
key = encodeURIComponent(String(key))
|
||||
.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent)
|
||||
.replace(/[()]/g, escape);
|
||||
|
||||
var stringifiedAttributes = '';
|
||||
for (var attributeName in attributes) {
|
||||
if (!attributes[attributeName]) {
|
||||
continue;
|
||||
}
|
||||
stringifiedAttributes += '; ' + attributeName;
|
||||
if (attributes[attributeName] === true) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Considers RFC 6265 section 5.2:
|
||||
// ...
|
||||
// 3. If the remaining unparsed-attributes contains a %x3B (";")
|
||||
// character:
|
||||
// Consume the characters of the unparsed-attributes up to,
|
||||
// not including, the first %x3B (";") character.
|
||||
// ...
|
||||
stringifiedAttributes += '=' + attributes[attributeName].split(';')[0];
|
||||
}
|
||||
|
||||
return (document.cookie = key + '=' + value + stringifiedAttributes);
|
||||
}
|
||||
|
||||
function get (key) {
|
||||
if (typeof document === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
var jar = {};
|
||||
// To prevent the for loop in the first place assign an empty array
|
||||
// in case there are no cookies at all.
|
||||
var cookies = document.cookie ? document.cookie.split('; ') : [];
|
||||
var i = 0;
|
||||
|
||||
for (; i < cookies.length; i++) {
|
||||
var parts = cookies[i].split('=');
|
||||
var cookie = parts.slice(1).join('=');
|
||||
|
||||
try {
|
||||
var name = decode(parts[0]);
|
||||
cookie = decode(cookie);
|
||||
|
||||
try {
|
||||
cookie = JSON.parse(cookie);
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
|
||||
jar[name] = cookie;
|
||||
|
||||
if (key === name) {
|
||||
break;
|
||||
}
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
}
|
||||
|
||||
return key ? jar[key] : jar;
|
||||
}
|
||||
|
||||
return {
|
||||
set: set,
|
||||
getJSON: key => get(key)
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
class CookieDriver {
|
||||
/**
|
||||
* @param {string} key
|
||||
* @param {*} data
|
||||
* @returns {boolean}
|
||||
*/
|
||||
set(key, data) {
|
||||
let result = false,
|
||||
storageResult = null;
|
||||
|
||||
try {
|
||||
storageResult = Cookies.getJSON(CLIENT_SIDE_STORAGE_INDEX_NAME);
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
|
||||
(storageResult || (storageResult = {}))[key] = data;
|
||||
|
||||
try {
|
||||
Cookies.set(CLIENT_SIDE_STORAGE_INDEX_NAME, storageResult, {
|
||||
expires: 30
|
||||
});
|
||||
|
||||
result = true;
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} key
|
||||
* @returns {*}
|
||||
*/
|
||||
get(key) {
|
||||
let result = null;
|
||||
|
||||
try {
|
||||
const storageResult = Cookies.getJSON(CLIENT_SIDE_STORAGE_INDEX_NAME);
|
||||
result = storageResult && null != storageResult[key] ? storageResult[key] : null;
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
static supported() {
|
||||
return !!(navigator && navigator.cookieEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
export { CookieDriver, CookieDriver as default };
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
import { isStorageSupported } from 'Storage/RainLoop';
|
||||
import { CLIENT_SIDE_STORAGE_INDEX_NAME } from 'Common/Consts';
|
||||
|
||||
class LocalStorageDriver {
|
||||
s = null;
|
||||
|
||||
constructor() {
|
||||
this.s = window.localStorage || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} key
|
||||
* @param {*} data
|
||||
* @returns {boolean}
|
||||
*/
|
||||
set(key, data) {
|
||||
if (!this.s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let storageResult = null;
|
||||
try {
|
||||
const storageValue = this.s.getItem(CLIENT_SIDE_STORAGE_INDEX_NAME) || null;
|
||||
storageResult = null === storageValue ? null : JSON.parse(storageValue);
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
|
||||
(storageResult || (storageResult = {}))[key] = data;
|
||||
|
||||
try {
|
||||
this.s.setItem(CLIENT_SIDE_STORAGE_INDEX_NAME, JSON.stringify(storageResult));
|
||||
return true;
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} key
|
||||
* @returns {*}
|
||||
*/
|
||||
get(key) {
|
||||
if (!this.s) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const storageValue = this.s.getItem(CLIENT_SIDE_STORAGE_INDEX_NAME) || null,
|
||||
storageResult = null === storageValue ? null : JSON.parse(storageValue);
|
||||
|
||||
return storageResult && null != storageResult[key] ? storageResult[key] : null;
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
static supported() {
|
||||
return isStorageSupported('localStorage');
|
||||
}
|
||||
}
|
||||
|
||||
export { LocalStorageDriver, LocalStorageDriver as default };
|
||||
|
|
@ -90,7 +90,6 @@ class HtmlEditor {
|
|||
onModeChange = null;
|
||||
|
||||
element;
|
||||
$element;
|
||||
|
||||
resize;
|
||||
|
||||
|
|
@ -113,24 +112,18 @@ class HtmlEditor {
|
|||
}
|
||||
|
||||
runOnBlur() {
|
||||
if (this.onBlur) {
|
||||
this.onBlur();
|
||||
}
|
||||
this.onBlur && this.onBlur();
|
||||
}
|
||||
|
||||
blurTrigger() {
|
||||
if (this.onBlur) {
|
||||
clearTimeout(this.blurTimer);
|
||||
this.blurTimer = setTimeout(() => {
|
||||
this.runOnBlur();
|
||||
}, 200);
|
||||
this.blurTimer = setTimeout(() => this.runOnBlur(), 200);
|
||||
}
|
||||
}
|
||||
|
||||
focusTrigger() {
|
||||
if (this.onBlur) {
|
||||
clearTimeout(this.blurTimer);
|
||||
}
|
||||
this.onBlur && clearTimeout(this.blurTimer);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -175,9 +168,7 @@ class HtmlEditor {
|
|||
}
|
||||
|
||||
resetDirty() {
|
||||
if (this.editor) {
|
||||
this.editor.resetDirty();
|
||||
}
|
||||
this.editor && this.editor.resetDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -245,9 +236,7 @@ class HtmlEditor {
|
|||
this.editor.setData(html);
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
|
||||
if (focus) {
|
||||
this.focus();
|
||||
}
|
||||
focus && this.focus();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -272,9 +261,7 @@ class HtmlEditor {
|
|||
} catch (e) {} // eslint-disable-line no-empty
|
||||
}
|
||||
|
||||
if (focus) {
|
||||
this.focus();
|
||||
}
|
||||
focus && this.focus();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -308,28 +295,16 @@ class HtmlEditor {
|
|||
|
||||
this.editor = window.CKEDITOR.appendTo(this.element, config);
|
||||
|
||||
this.editor.on('key', (event) => {
|
||||
if (event && event.data && EventKeyCode.Tab === event.data.keyCode) {
|
||||
return false;
|
||||
}
|
||||
this.editor.on('key', event => !(event && event.data && EventKeyCode.Tab === event.data.keyCode));
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
this.editor.on('blur', () => {
|
||||
this.blurTrigger();
|
||||
});
|
||||
this.editor.on('blur', () => this.blurTrigger());
|
||||
|
||||
this.editor.on('mode', () => {
|
||||
this.blurTrigger();
|
||||
if (this.onModeChange) {
|
||||
this.onModeChange('plain' !== this.editor.mode);
|
||||
}
|
||||
this.onModeChange && this.onModeChange('plain' !== this.editor.mode);
|
||||
});
|
||||
|
||||
this.editor.on('focus', () => {
|
||||
this.focusTrigger();
|
||||
});
|
||||
this.editor.on('focus', () => this.focusTrigger());
|
||||
|
||||
if (window.FileReader) {
|
||||
this.editor.on('drop', (event) => {
|
||||
|
|
@ -366,9 +341,7 @@ class HtmlEditor {
|
|||
|
||||
this.resize();
|
||||
|
||||
if (this.onReady) {
|
||||
this.onReady();
|
||||
}
|
||||
this.onReady && this.onReady();
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -381,45 +354,35 @@ class HtmlEditor {
|
|||
}
|
||||
|
||||
focus() {
|
||||
if (this.editor) {
|
||||
try {
|
||||
this.editor.focus();
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
}
|
||||
try {
|
||||
this.editor && this.editor.focus();
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
}
|
||||
|
||||
hasFocus() {
|
||||
if (this.editor) {
|
||||
try {
|
||||
return !!this.editor.focusManager.hasFocus;
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
try {
|
||||
return this.editor && !!this.editor.focusManager.hasFocus;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
blur() {
|
||||
if (this.editor) {
|
||||
try {
|
||||
this.editor.focusManager.blur(true);
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
}
|
||||
try {
|
||||
this.editor && this.editor.focusManager.blur(true);
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
}
|
||||
|
||||
resizeEditor() {
|
||||
if (this.editor && this.__resizable) {
|
||||
try {
|
||||
this.editor.resize(this.element.clientWidth, this.element.clientHeight);
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
}
|
||||
try {
|
||||
this.editor && this.__resizable && this.editor.resize(this.element.clientWidth, this.element.clientHeight);
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
}
|
||||
|
||||
setReadOnly(value) {
|
||||
if (this.editor) {
|
||||
try {
|
||||
this.editor.setReadOnly(!!value);
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
}
|
||||
try {
|
||||
this.editor && this.editor.setReadOnly(!!value);
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
}
|
||||
|
||||
clear(focus) {
|
||||
|
|
|
|||
|
|
@ -305,7 +305,7 @@ export function openPgpWorkerPath() {
|
|||
export function themePreviewLink(theme) {
|
||||
let prefix = VERSION_PREFIX;
|
||||
if ('@custom' === theme.substr(-7)) {
|
||||
theme = theme.substring(0, theme.length - 7).trim();
|
||||
theme = theme.substr(0, theme.length - 7).trim();
|
||||
prefix = WEB_PREFIX;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@ class Selector {
|
|||
focusedItem;
|
||||
selectedItem;
|
||||
|
||||
itemSelectedThrottle;
|
||||
|
||||
selectedItemUseCallback = true;
|
||||
|
||||
iSelectNextHelper = 0;
|
||||
|
|
@ -51,7 +49,7 @@ class Selector {
|
|||
this.focusedItem = koFocusedItem || ko.observable(null);
|
||||
this.selectedItem = koSelectedItem || ko.observable(null);
|
||||
|
||||
this.itemSelectedThrottle = (item=>this.itemSelected(item)).debounce(300);
|
||||
const itemSelectedThrottle = (item => this.itemSelected(item)).debounce(300);
|
||||
|
||||
this.listChecked.subscribe((items) => {
|
||||
if (items.length) {
|
||||
|
|
@ -70,13 +68,11 @@ class Selector {
|
|||
this.selectedItem.subscribe((item) => {
|
||||
if (item) {
|
||||
if (this.isListChecked()) {
|
||||
this.listChecked().forEach(subItem => {
|
||||
subItem.checked(false);
|
||||
});
|
||||
this.listChecked().forEach(subItem => subItem.checked(false));
|
||||
}
|
||||
|
||||
if (this.selectedItemUseCallback) {
|
||||
this.itemSelectedThrottle(item);
|
||||
itemSelectedThrottle(item);
|
||||
}
|
||||
} else if (this.selectedItemUseCallback) {
|
||||
this.itemSelected(null);
|
||||
|
|
@ -91,11 +87,7 @@ class Selector {
|
|||
this.sItemCheckedSelector = sItemCheckedSelector;
|
||||
this.sItemFocusedSelector = sItemFocusedSelector;
|
||||
|
||||
this.focusedItem.subscribe((item) => {
|
||||
if (item) {
|
||||
this.sLastUid = this.getItemUid(item);
|
||||
}
|
||||
}, this);
|
||||
this.focusedItem.subscribe(item => item && (this.sLastUid = this.getItemUid(item)), this);
|
||||
|
||||
let aCache = [],
|
||||
aCheckedCache = [],
|
||||
|
|
@ -110,9 +102,7 @@ class Selector {
|
|||
const uid = this.getItemUid(item);
|
||||
|
||||
aCache.push(uid);
|
||||
if (item.checked()) {
|
||||
aCheckedCache.push(uid);
|
||||
}
|
||||
item.checked() && aCheckedCache.push(uid);
|
||||
if (null === mFocused && item.focused()) {
|
||||
mFocused = uid;
|
||||
}
|
||||
|
|
@ -178,7 +168,8 @@ class Selector {
|
|||
isNextFocused = aCache.find(sUid => {
|
||||
if (getNext && uids.includes(sUid)) {
|
||||
return sUid;
|
||||
} else if (isNextFocused === sUid) {
|
||||
}
|
||||
if (isNextFocused === sUid) {
|
||||
getNext = true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -346,13 +337,6 @@ class Selector {
|
|||
return !!(this.oCallbacks.onAutoSelect || (()=>true))();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {boolean} up
|
||||
*/
|
||||
doUpUpOrDownDown(up) {
|
||||
(this.oCallbacks.onUpUpOrDownDown || (()=>true))(!!up);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} oItem
|
||||
* @returns {string}
|
||||
|
|
@ -433,7 +417,7 @@ class Selector {
|
|||
});
|
||||
|
||||
if (!result && (EventKeyCode.Down === iEventKeyCode || EventKeyCode.Up === iEventKeyCode)) {
|
||||
this.doUpUpOrDownDown(EventKeyCode.Up === iEventKeyCode);
|
||||
(this.oCallbacks.onUpUpOrDownDown || (()=>true))(EventKeyCode.Up === iEventKeyCode);
|
||||
}
|
||||
} else if (EventKeyCode.Home === iEventKeyCode || EventKeyCode.End === iEventKeyCode) {
|
||||
if (EventKeyCode.Home === iEventKeyCode) {
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ export function splitPlainText(text, len = 100) {
|
|||
newLinePos = 0;
|
||||
|
||||
while (result.length > len) {
|
||||
subText = result.substring(0, len);
|
||||
subText = result.substr(0, len);
|
||||
spacePos = subText.lastIndexOf(' ');
|
||||
newLinePos = subText.lastIndexOf('\n');
|
||||
|
||||
|
|
@ -114,8 +114,8 @@ export function splitPlainText(text, len = 100) {
|
|||
spacePos = len;
|
||||
}
|
||||
|
||||
prefix += subText.substring(0, spacePos) + '\n';
|
||||
result = result.substring(spacePos + 1);
|
||||
prefix += subText.substr(0, spacePos) + '\n';
|
||||
result = result.substr(spacePos + 1);
|
||||
}
|
||||
|
||||
return prefix + result;
|
||||
|
|
@ -214,33 +214,14 @@ export function replySubjectAdd(prefix, subject) {
|
|||
return ((prefixIsRe ? 'Re: ' : 'Fwd: ') + (re ? 'Re: ' : '') + (fwd ? 'Fwd: ' : '') + parts.join(':').trim()).trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} num
|
||||
* @param {number} dec
|
||||
* @returns {number}
|
||||
*/
|
||||
export function roundNumber(num, dec) {
|
||||
return Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {(number|string)} sizeInBytes
|
||||
* @returns {string}
|
||||
*/
|
||||
export function friendlySize(sizeInBytes) {
|
||||
sizeInBytes = pInt(sizeInBytes);
|
||||
|
||||
switch (true) {
|
||||
case 1073741824 <= sizeInBytes:
|
||||
return roundNumber(sizeInBytes / 1073741824, 1) + 'GB';
|
||||
case 1048576 <= sizeInBytes:
|
||||
return roundNumber(sizeInBytes / 1048576, 1) + 'MB';
|
||||
case 1024 <= sizeInBytes:
|
||||
return roundNumber(sizeInBytes / 1024, 0) + 'KB';
|
||||
// no default
|
||||
}
|
||||
|
||||
return sizeInBytes + 'B';
|
||||
const sizes = ['B', 'KiB', 'MiB', 'GiB', 'TiB'], i = pInt(Math.floor(Math.log(sizeInBytes) / Math.log(1024)));
|
||||
return (sizeInBytes / Math.pow(1024, i)).toFixed(2>i ? 0 : 1) + sizes[i];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -249,14 +230,14 @@ export function friendlySize(sizeInBytes) {
|
|||
*/
|
||||
export const convertThemeName = theme => {
|
||||
if ('@custom' === theme.substr(-7)) {
|
||||
theme = theme.substring(0, theme.length - 7).trim();
|
||||
theme = theme.substr(0, theme.length - 7).trim();
|
||||
}
|
||||
|
||||
return theme
|
||||
.replace(/[^a-zA-Z0-9]+/g, ' ')
|
||||
.replace(/([A-Z])/g, ' $1')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim();
|
||||
.replace(/[^a-zA-Z0-9]+/g, ' ')
|
||||
.replace(/([A-Z])/g, ' $1')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -452,7 +433,7 @@ export function htmlToPlain(html) {
|
|||
iP3 = text.indexOf('__bq__end__', iP1 + 5);
|
||||
|
||||
if ((-1 === iP2 || iP3 < iP2) && iP1 < iP3) {
|
||||
text = text.substring(0, iP1) + convertBlockquote(text.substring(iP1 + 13, iP3)) + text.substring(iP3 + 11);
|
||||
text = text.substr(0, iP1) + convertBlockquote(text.substring(iP1 + 13, iP3)) + text.substr(iP3 + 11);
|
||||
pos = 0;
|
||||
} else if (-1 < iP2 && iP2 < iP3) {
|
||||
pos = iP2 - 1;
|
||||
|
|
@ -722,7 +703,7 @@ export function changeTheme(value, themeTrigger = ()=>{}) {
|
|||
.replace(/\/Css\/[^/]+\/User\//, '/Css/0/User/')
|
||||
.replace(/\/Hash\/[^/]+\//, '/Hash/-/');
|
||||
|
||||
if ('Json/' !== url.substring(url.length - 5, url.length)) {
|
||||
if ('Json/' !== url.substr(-5)) {
|
||||
url += 'Json/';
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue