diff --git a/.gitignore b/.gitignore index 07da74f1e..7bce6cb2f 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,6 @@ /build/tmp /data .DS_Store -/tests/fix.php \ No newline at end of file +/tests/fix.php +/MULTIPLY +/include.php \ No newline at end of file diff --git a/dev/App/Abstract.jsx b/dev/App/Abstract.jsx index 6f26f78d5..b5149bceb 100644 --- a/dev/App/Abstract.jsx +++ b/dev/App/Abstract.jsx @@ -9,10 +9,10 @@ import { import {KeyState} from 'Common/Enums'; import {noop, isNormal, pString, inArray, microtime, timestamp, detectDropdownVisibility, windowResizeCallback} from 'Common/Utils'; -import Links from 'Common/Links'; -import Events from 'Common/Events'; +import * as Links from 'Common/Links'; +import * as Settings from 'Storage/Settings'; +import * as Events from 'Common/Events'; import Translator from 'Common/Translator'; -import Settings from 'Storage/Settings'; import {AbstractBoot} from 'Knoin/AbstractBoot'; diff --git a/dev/App/Admin.jsx b/dev/App/Admin.jsx index c767f7fd3..03fc70f12 100644 --- a/dev/App/Admin.jsx +++ b/dev/App/Admin.jsx @@ -3,12 +3,12 @@ import {window, _} from 'common'; import ko from 'ko'; import progressJs from 'progressJs'; -import Links from 'Common/Links'; +import * as Links from 'Common/Links'; import Translator from 'Common/Translator'; import {StorageResultType, Notification} from 'Common/Enums'; import {pInt, isNormal, isArray, inArray, isUnd} from 'Common/Utils'; -import Settings from 'Storage/Settings'; +import * as Settings from 'Storage/Settings'; import AppStore from 'Stores/Admin/App'; import DomainStore from 'Stores/Admin/Domain'; diff --git a/dev/App/User.jsx b/dev/App/User.jsx index 4813943f0..138fa5585 100644 --- a/dev/App/User.jsx +++ b/dev/App/User.jsx @@ -20,11 +20,11 @@ import { } from 'Common/Globals'; import {UNUSED_OPTION_VALUE} from 'Common/Consts'; -import Plugins from 'Common/Plugins'; -import Links from 'Common/Links'; -import Events from 'Common/Events'; +import * as Plugins from 'Common/Plugins'; +import * as Links from 'Common/Links'; +import * as Events from 'Common/Events'; +import * as Momentor from 'Common/Momentor'; import Translator from 'Common/Translator'; -import Momentor from 'Common/Momentor'; import Cache from 'Common/Cache'; import SocialStore from 'Stores/Social'; @@ -38,7 +38,7 @@ import MessageStore from 'Stores/User/Message'; import ContactStore from 'Stores/User/Contact'; import Local from 'Storage/Client'; -import Settings from 'Storage/Settings'; +import * as Settings from 'Storage/Settings'; import RainLoopStorage from 'Storage/RainLoop'; import Remote from 'Remote/User/Ajax'; diff --git a/dev/Common/Audio.jsx b/dev/Common/Audio.jsx index bcf8d82c3..f308d028e 100644 --- a/dev/Common/Audio.jsx +++ b/dev/Common/Audio.jsx @@ -1,8 +1,8 @@ import {window, $} from 'common'; import {bMobileDevice, bSafari} from 'Common/Globals'; -import Links from 'Common/Links'; -import Events from 'Common/Events'; +import * as Links from 'Common/Links'; +import * as Events from 'Common/Events'; import {trim} from 'Common/Utils'; class Audio diff --git a/dev/Common/Base64.jsx b/dev/Common/Base64.jsx index eab6cad4d..b669f67ed 100644 --- a/dev/Common/Base64.jsx +++ b/dev/Common/Base64.jsx @@ -163,7 +163,9 @@ const Base64 = { return string; } }; - -module.exports = Base64; /* jslint bitwise: false */ /* eslint-enable */ + +export const decode = Base64.decode; +export const encode = Base64.encode; +export const urlsafe_encode = Base64.urlsafe_encode; diff --git a/dev/Common/Cache.jsx b/dev/Common/Cache.jsx index 870eee9ab..0a61431d4 100644 --- a/dev/Common/Cache.jsx +++ b/dev/Common/Cache.jsx @@ -2,8 +2,8 @@ import {_} from 'common'; import {Capa, MessageSetAction} from 'Common/Enums'; import {trim, pInt, isArray} from 'Common/Utils'; -import Links from 'Common/Links'; -import Settings from 'Storage/Settings'; +import * as Links from 'Common/Links'; +import * as Settings from 'Storage/Settings'; class CacheUserStorage { diff --git a/dev/Common/ClientStorageDriver/Cookie.jsx b/dev/Common/ClientStorageDriver/Cookie.jsx index d69cbb380..fd4a2cd4d 100644 --- a/dev/Common/ClientStorageDriver/Cookie.jsx +++ b/dev/Common/ClientStorageDriver/Cookie.jsx @@ -22,10 +22,7 @@ class CookieDriver const storageValue = $.cookie(CLIENT_SIDE_STORAGE_INDEX_NAME); storageResult = null === storageValue ? null : JSON.parse(storageValue); } - catch (e) - { - // eslint-disable-line no-empty - } + catch (e) {/* eslint-disable-line no-empty */} (storageResult || (storageResult = {}))[key] = data; @@ -37,10 +34,7 @@ class CookieDriver result = true; } - catch (e) - { - // eslint-disable-line no-empty - } + catch (e) {/* eslint-disable-line no-empty */} return result; } @@ -62,10 +56,7 @@ class CookieDriver result = (storageResult && !isUnd(storageResult[key])) ? storageResult[key] : null; } - catch (e) - { - // eslint-disable-line no-empty - } + catch (e) {/* eslint-disable-line no-empty */} return result; } diff --git a/dev/Common/ClientStorageDriver/LocalStorage.jsx b/dev/Common/ClientStorageDriver/LocalStorage.jsx index 8ba2f2519..2061235d6 100644 --- a/dev/Common/ClientStorageDriver/LocalStorage.jsx +++ b/dev/Common/ClientStorageDriver/LocalStorage.jsx @@ -22,10 +22,7 @@ class LocalStorageDriver const storageValue = window.localStorage[CLIENT_SIDE_STORAGE_INDEX_NAME] || null; storageResult = null === storageValue ? null : JSON.parse(storageValue); } - catch (e) - { - // eslint-disable-line no-empty - } + catch (e) {/* eslint-disable-line no-empty */} (storageResult || (storageResult = {}))[key] = data; @@ -34,10 +31,7 @@ class LocalStorageDriver window.localStorage[CLIENT_SIDE_STORAGE_INDEX_NAME] = JSON.stringify(storageResult); result = true; } - catch (e) - { - // eslint-disable-line no-empty - } + catch (e) {/* eslint-disable-line no-empty */} return result; } @@ -59,10 +53,7 @@ class LocalStorageDriver result = (storageResult && !isUnd(storageResult[key])) ? storageResult[key] : null; } - catch (e) - { - // eslint-disable-line no-empty - } + catch (e) {/* eslint-disable-line no-empty */} return result; } diff --git a/dev/Common/Events.jsx b/dev/Common/Events.jsx index 2d03f1deb..3ce55f349 100644 --- a/dev/Common/Events.jsx +++ b/dev/Common/Events.jsx @@ -1,65 +1,52 @@ import {_} from 'common'; import {isObject, isUnd} from 'Common/Utils'; -import Plugins from 'Common/Plugins'; +import * as Plugins from 'Common/Plugins'; -class Events +const SUBS = {}; + +/** + * @param {string|Object} name + * @param {Function} func + * @param {Object=} context + */ +export function sub(name, func, context) { - subs = {}; + if (isObject(name)) + { + context = func || null; + func = null; - constructor() {} - - /** - * @param {string|Object} name - * @param {Function} func - * @param {Object=} context - * @return {Events} - */ - sub(name, func, context) { - - if (isObject(name)) - { - context = func || null; - func = null; - - _.each(name, (subFunc, subName) => { - this.sub(subName, subFunc, context); - }, this); - } - else - { - if (isUnd(this.subs[name])) - { - this.subs[name] = []; - } - - this.subs[name].push([func, context]); - } - - return this; + _.each(name, (subFunc, subName) => { + sub(subName, subFunc, context); + }); } - - /** - * @param {string} name - * @param {Array=} args - * @return {Events} - */ - pub(name, args) { - - Plugins.runHook('rl-pub', [name, args]); - - if (!isUnd(this.subs[name])) + else + { + if (isUnd(SUBS[name])) { - _.each(this.subs[name], (items) => { - if (items[0]) - { - items[0].apply(items[1] || null, args || []); - } - }); + SUBS[name] = []; } - return this; + SUBS[name].push([func, context]); } } -module.exports = new Events(); +/** + * @param {string} name + * @param {Array=} args + */ +export function pub(name, args) +{ + Plugins.runHook('rl-pub', [name, args]); + + if (!isUnd(SUBS[name])) + { + _.each(SUBS[name], (items) => { + if (items[0]) + { + items[0].apply(items[1] || null, args || []); + } + }); + } +} diff --git a/dev/Common/HtmlEditor.jsx b/dev/Common/HtmlEditor.jsx index e79f3d5b8..7d0daad33 100644 --- a/dev/Common/HtmlEditor.jsx +++ b/dev/Common/HtmlEditor.jsx @@ -1,7 +1,7 @@ import {window, _, $} from 'common'; import {oHtmlEditorDefaultConfig, oHtmlEditorLangsMap} from 'Common/Globals'; -import Settings from 'Storage/Settings'; +import * as Settings from 'Storage/Settings'; class HtmlEditor { diff --git a/dev/Common/Links.jsx b/dev/Common/Links.jsx index 2c6f5bb89..9b8aaa95a 100644 --- a/dev/Common/Links.jsx +++ b/dev/Common/Links.jsx @@ -1,390 +1,444 @@ import {window} from 'common'; import {pString, pInt, isUnd, isNormal, trim, encodeURIComponent} from 'Common/Utils'; -import Settings from 'Storage/Settings'; +import * as Settings from 'Storage/Settings'; -class Links +const ROOT = './'; +const HASH_PREFIX = '#/'; +const SERVER_PREFIX = './?'; +const SUB_QUERY_PREFIX = '&q[]='; + +const VERSION = Settings.appSettingsGet('version'); + +const WEB_PREFIX = Settings.appSettingsGet('webPath') || ''; +const VERSION_PREFIX = Settings.appSettingsGet('webVersionPath') || 'rainloop/v/' + VERSION + '/'; +const STATIC_PREFIX = VERSION_PREFIX + 'static/'; + +const ADMIN_HOST_USE = !!Settings.appSettingsGet('adminHostUse'); +const ADMIN_PATH = Settings.appSettingsGet('adminPath') || 'admin'; + +let AUTH_PREFIX = Settings.settingsGet('AuthAccountHash') || '0'; + +export function populateAuthSuffix() { - constructor() { - - this.sHashPrefix = '#/'; - this.sServerPrefix = './?'; - - this.sVersion = Settings.appSettingsGet('version'); - this.sWebPrefix = Settings.appSettingsGet('webPath') || ''; - this.sVersionPrefix = Settings.appSettingsGet('webVersionPath') || 'rainloop/v/' + this.sVersion + '/'; - this.bAminHostUse = !!Settings.appSettingsGet('adminHostUse'); - this.sAdminPath = Settings.appSettingsGet('adminPath') || 'admin'; - - this.sAuthSuffix = Settings.settingsGet('AuthAccountHash') || '0'; - - this.sStaticPrefix = this.sVersionPrefix + 'static/'; - } - - populateAuthSuffix() { - this.sAuthSuffix = Settings.settingsGet('AuthAccountHash') || '0'; - } - - /** - * @return {string} - */ - subQueryPrefix() { - return '&q[]='; - } - - /** - * @param {string=} startupUrl - * @return {string} - */ - root(startupUrl = '') { - return this.sHashPrefix + pString(startupUrl); - } - - /** - * @return {string} - */ - rootAdmin() { - return this.bAminHostUse ? './' : this.sServerPrefix + this.sAdminPath; - } - - /** - * @return {string} - */ - rootUser(mobile = false) { - return mobile ? './?/Mobile/' : './'; - } - - /** - * @param {string} type - * @param {string} download - * @param {string=} customSpecSuffix - * @return {string} - */ - attachmentRaw(type, download, customSpecSuffix) { - customSpecSuffix = isUnd(customSpecSuffix) ? this.sAuthSuffix : customSpecSuffix; - return this.sServerPrefix + '/Raw/' + this.subQueryPrefix() + '/' + customSpecSuffix + '/' + type + '/' + - this.subQueryPrefix() + '/' + download; - } - - /** - * @param {string} download - * @param {string=} customSpecSuffix - * @return {string} - */ - attachmentDownload(download, customSpecSuffix) { - return this.attachmentRaw('Download', download, customSpecSuffix); - } - - /** - * @param {string} download - * @param {string=} customSpecSuffix - * @return {string} - */ - attachmentPreview(download, customSpecSuffix) { - return this.attachmentRaw('View', download, customSpecSuffix); - } - - /** - * @param {string} download - * @param {string=} customSpecSuffix - * @return {string} - */ - attachmentThumbnailPreview(download, customSpecSuffix) { - return this.attachmentRaw('ViewThumbnail', download, customSpecSuffix); - } - - /** - * @param {string} download - * @param {string=} customSpecSuffix - * @return {string} - */ - attachmentPreviewAsPlain(download, customSpecSuffix) { - return this.attachmentRaw('ViewAsPlain', download, customSpecSuffix); - } - - /** - * @param {string} download - * @param {string=} customSpecSuffix - * @return {string} - */ - attachmentFramed(download, customSpecSuffix) { - return this.attachmentRaw('FramedView', download, customSpecSuffix); - } - - /** - * @return {string} - */ - upload() { - return this.sServerPrefix + '/Upload/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/'; - } - - /** - * @return {string} - */ - uploadContacts() { - return this.sServerPrefix + '/UploadContacts/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/'; - } - - /** - * @return {string} - */ - uploadBackground() { - return this.sServerPrefix + '/UploadBackground/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/'; - } - - /** - * @return {string} - */ - append() { - return this.sServerPrefix + '/Append/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/'; - } - - /** - * @param {string} email - * @return {string} - */ - change(email) { - return this.sServerPrefix + '/Change/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/' + encodeURIComponent(email) + '/'; - } - - /** - * @param {string} add - * @return {string} - */ - ajax(add) { - return this.sServerPrefix + '/Ajax/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/' + add; - } - - /** - * @param {string} requestHash - * @return {string} - */ - messageViewLink(requestHash) { - return this.sServerPrefix + '/Raw/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/ViewAsPlain/' + this.subQueryPrefix() + '/' + requestHash; - } - - /** - * @param {string} requestHash - * @return {string} - */ - messageDownloadLink(requestHash) { - return this.sServerPrefix + '/Raw/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/Download/' + this.subQueryPrefix() + '/' + requestHash; - } - - /** - * @param {string} email - * @return {string} - */ - avatarLink(email) { - return this.sServerPrefix + '/Raw/0/Avatar/' + encodeURIComponent(email) + '/'; - } - - /** - * @param {string} hash - * @return {string} - */ - publicLink(hash) { - return this.sServerPrefix + '/Raw/0/Public/' + hash + '/'; - } - - /** - * @param {string} hash - * @return {string} - */ - userBackground(hash) { - return this.sServerPrefix + '/Raw/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + - '/UserBackground/' + this.subQueryPrefix() + '/' + hash; - } - - /** - * @param {string} inboxFolderName = 'INBOX' - * @return {string} - */ - inbox(inboxFolderName = 'INBOX') { - return this.sHashPrefix + 'mailbox/' + inboxFolderName; - } - - /** - * @param {string=} screenName - * @return {string} - */ - settings(screenName = '') { - return this.sHashPrefix + 'settings' + (screenName ? '/' + screenName : ''); - } - - /** - * @return {string} - */ - about() { - return this.sHashPrefix + 'about'; - } - - /** - * @param {string} screenName - * @return {string} - */ - admin (screenName) { - let result = this.sHashPrefix; - switch (screenName) { - case 'AdminDomains': - result += 'domains'; - break; - case 'AdminSecurity': - result += 'security'; - break; - case 'AdminLicensing': - result += 'licensing'; - break; - } - - return result; - } - - /** - * @param {string} folder - * @param {number=} page = 1 - * @param {string=} search = '' - * @param {string=} threadUid = '' - * @return {string} - */ - mailBox(folder, page = 1, search = '', threadUid = '') { - - page = isNormal(page) ? pInt(page) : 1; - search = pString(search); - - let result = this.sHashPrefix + 'mailbox/'; - - if ('' !== folder) - { - const resultThreadUid = pInt(threadUid); - result += window.encodeURI(folder) + (0 < resultThreadUid ? '~' + resultThreadUid : ''); - } - - if (1 < page) - { - result = result.replace(/[\/]+$/, ''); - result += '/p' + page; - } - - if ('' !== search) - { - result = result.replace(/[\/]+$/, ''); - result += '/' + window.encodeURI(search); - } - - return result; - } - - /** - * @return {string} - */ - phpInfo() { - return this.sServerPrefix + 'Info'; - } - - /** - * @param {string} lang - * @param {boolean} admin - * @return {string} - */ - langLink(lang, admin) { - return this.sServerPrefix + '/Lang/0/' + (admin ? 'Admin' : 'App') + '/' + window.encodeURI(lang) + '/' + this.sVersion + '/'; - } - - /** - * @return {string} - */ - exportContactsVcf() { - return this.sServerPrefix + '/Raw/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/ContactsVcf/'; - } - - /** - * @return {string} - */ - exportContactsCsv() { - return this.sServerPrefix + '/Raw/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/ContactsCsv/'; - } - - /** - * @return {string} - */ - emptyContactPic() { - return this.sStaticPrefix + 'css/images/empty-contact.png'; - } - - /** - * @param {string} fileName - * @return {string} - */ - sound(fileName) { - return this.sStaticPrefix + 'sounds/' + fileName; - } - - /** - * @param {string} theme - * @return {string} - */ - themePreviewLink(theme) { - let prefix = this.sVersionPrefix; - if ('@custom' === theme.substr(-7)) - { - theme = trim(theme.substring(0, theme.length - 7)); - prefix = this.sWebPrefix; - } - - return prefix + 'themes/' + window.encodeURI(theme) + '/images/preview.png'; - } - - /** - * @return {string} - */ - notificationMailIcon() { - return this.sStaticPrefix + 'css/images/icom-message-notification.png'; - } - - /** - * @return {string} - */ - openPgpJs() { - return this.sStaticPrefix + 'js/min/openpgp.min.js'; - } - - /** - * @return {string} - */ - openPgpWorkerJs() { - return this.sStaticPrefix + 'js/min/openpgp.worker.min.js'; - } - - /** - * @return {string} - */ - openPgpWorkerPath() { - return this.sStaticPrefix + 'js/min/'; - } - - /** - * @param {boolean} xauth = false - * @return {string} - */ - socialGoogle(xauth = false) { - return this.sServerPrefix + 'SocialGoogle' + ('' !== this.sAuthSuffix ? '/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/' : '') + - (xauth ? '&xauth=1' : ''); - } - - /** - * @return {string} - */ - socialTwitter() { - return this.sServerPrefix + 'SocialTwitter' + ('' !== this.sAuthSuffix ? '/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/' : ''); - } - - /** - * @return {string} - */ - socialFacebook() { - return this.sServerPrefix + 'SocialFacebook' + ('' !== this.sAuthSuffix ? '/' + this.subQueryPrefix() + '/' + this.sAuthSuffix + '/' : ''); - } + AUTH_PREFIX = Settings.settingsGet('AuthAccountHash') || '0'; } -module.exports = new Links(); +/** + * @return {string} + */ +export function subQueryPrefix() +{ + return SUB_QUERY_PREFIX; +} + +/** + * @param {string=} startupUrl + * @return {string} + */ +export function root(startupUrl = '') +{ + return HASH_PREFIX + pString(startupUrl); +} + +/** + * @return {string} + */ +export function rootAdmin() +{ + return ADMIN_HOST_USE ? ROOT : SERVER_PREFIX + ADMIN_PATH; +} + +/** + * @param {boolean=} mobile = false + * @return {string} + */ +export function rootUser(mobile = false) +{ + return mobile ? SERVER_PREFIX + '/Mobile/' : ROOT; +} + +/** + * @param {string} type + * @param {string} download + * @param {string=} customSpecSuffix + * @return {string} + */ +export function attachmentRaw(type, download, customSpecSuffix) +{ + customSpecSuffix = isUnd(customSpecSuffix) ? AUTH_PREFIX : customSpecSuffix; + return SERVER_PREFIX + '/Raw/' + SUB_QUERY_PREFIX + '/' + customSpecSuffix + '/' + type + '/' + SUB_QUERY_PREFIX + '/' + download; +} + +/** + * @param {string} download + * @param {string=} customSpecSuffix + * @return {string} + */ +export function attachmentDownload(download, customSpecSuffix) +{ + return attachmentRaw('Download', download, customSpecSuffix); +} + +/** + * @param {string} download + * @param {string=} customSpecSuffix + * @return {string} + */ +export function attachmentPreview(download, customSpecSuffix) +{ + return attachmentRaw('View', download, customSpecSuffix); +} + +/** + * @param {string} download + * @param {string=} customSpecSuffix + * @return {string} + */ +export function attachmentThumbnailPreview(download, customSpecSuffix) +{ + return attachmentRaw('ViewThumbnail', download, customSpecSuffix); +} + +/** + * @param {string} download + * @param {string=} customSpecSuffix + * @return {string} + */ +export function attachmentPreviewAsPlain(download, customSpecSuffix) +{ + return attachmentRaw('ViewAsPlain', download, customSpecSuffix); +} + +/** + * @param {string} download + * @param {string=} customSpecSuffix + * @return {string} + */ +export function attachmentFramed(download, customSpecSuffix) +{ + return attachmentRaw('FramedView', download, customSpecSuffix); +} + +/** + * @param {string} type + * @return {string} + */ +export function serverRequest(type) +{ + return SERVER_PREFIX + '/' + type + '/' + SUB_QUERY_PREFIX + '/' + AUTH_PREFIX + '/'; +} + +/** + * @return {string} + */ +export function upload() +{ + return serverRequest('Upload'); +} + +/** + * @return {string} + */ +export function uploadContacts() +{ + return serverRequest('UploadContacts'); +} + +/** + * @return {string} + */ +export function uploadBackground() +{ + return serverRequest('UploadBackground'); +} + +/** + * @return {string} + */ +export function append() +{ + return serverRequest('Append'); +} + +/** + * @param {string} email + * @return {string} + */ +export function change(email) +{ + return serverRequest('Change') + encodeURIComponent(email) + '/'; +} + +/** + * @param {string} add + * @return {string} + */ +export function ajax(add) +{ + return serverRequest('Ajax') + add; +} + +/** + * @param {string} requestHash + * @return {string} + */ +export function messageViewLink(requestHash) +{ + return SERVER_PREFIX + '/Raw/' + SUB_QUERY_PREFIX + '/' + AUTH_PREFIX + '/ViewAsPlain/' + SUB_QUERY_PREFIX + '/' + requestHash; +} + +/** + * @param {string} requestHash + * @return {string} + */ +export function messageDownloadLink(requestHash) +{ + return SERVER_PREFIX + '/Raw/' + SUB_QUERY_PREFIX + '/' + AUTH_PREFIX + '/Download/' + SUB_QUERY_PREFIX + '/' + requestHash; +} + +/** + * @param {string} email + * @return {string} + */ +export function avatarLink(email) +{ + return SERVER_PREFIX + '/Raw/0/Avatar/' + encodeURIComponent(email) + '/'; +} + +/** + * @param {string} hash + * @return {string} + */ +export function publicLink(hash) +{ + return SERVER_PREFIX + '/Raw/0/Public/' + hash + '/'; +} + +/** + * @param {string} hash + * @return {string} + */ +export function userBackground(hash) +{ + return SERVER_PREFIX + '/Raw/' + SUB_QUERY_PREFIX + '/' + AUTH_PREFIX + '/UserBackground/' + SUB_QUERY_PREFIX + '/' + hash; +} + +/** + * @return {string} + */ +export function phpInfo() +{ + return SERVER_PREFIX + '/Info'; +} + +/** + * @param {string} lang + * @param {boolean} isAdmin + * @return {string} + */ +export function langLink(lang, isAdmin) +{ + return SERVER_PREFIX + '/Lang/0/' + (isAdmin ? 'Admin' : 'App') + '/' + window.encodeURI(lang) + '/' + VERSION + '/'; +} + +/** + * @return {string} + */ +export function exportContactsVcf() +{ + return SERVER_PREFIX + '/Raw/' + SUB_QUERY_PREFIX + '/' + AUTH_PREFIX + '/ContactsVcf/'; +} + +/** + * @return {string} + */ +export function exportContactsCsv() +{ + return SERVER_PREFIX + '/Raw/' + SUB_QUERY_PREFIX + '/' + AUTH_PREFIX + '/ContactsCsv/'; +} + +/** + * @param {boolean} xauth = false + * @return {string} + */ +export function socialGoogle(xauth = false) +{ + return SERVER_PREFIX + 'SocialGoogle' + + ('' !== AUTH_PREFIX ? '/' + SUB_QUERY_PREFIX + '/' + AUTH_PREFIX + '/' : '') + (xauth ? '&xauth=1' : ''); +} + +/** + * @return {string} + */ +export function socialTwitter() +{ + return SERVER_PREFIX + 'SocialTwitter' + + ('' !== AUTH_PREFIX ? '/' + SUB_QUERY_PREFIX + '/' + AUTH_PREFIX + '/' : ''); +} + +/** + * @return {string} + */ +export function socialFacebook() +{ + return SERVER_PREFIX + 'SocialFacebook' + + ('' !== AUTH_PREFIX ? '/' + SUB_QUERY_PREFIX + '/' + AUTH_PREFIX + '/' : ''); +} + +/** + * @param {string} path + * @return {string} + */ +export function staticPrefix(path) +{ + return STATIC_PREFIX + path; +} + +/** + * @return {string} + */ +export function emptyContactPic() +{ + return staticPrefix('css/images/empty-contact.png'); +} + +/** + * @param {string} fileName + * @return {string} + */ +export function sound(fileName) +{ + return staticPrefix('sounds/' + fileName); +} + +/** + * @return {string} + */ +export function notificationMailIcon() +{ + return staticPrefix('css/images/icom-message-notification.png'); +} + +/** + * @return {string} + */ +export function openPgpJs() +{ + return staticPrefix('js/min/openpgp.min.js'); +} + +/** + * @return {string} + */ +export function openPgpWorkerJs() +{ + return staticPrefix('js/min/openpgp.worker.min.js'); +} + +/** + * @return {string} + */ +export function openPgpWorkerPath() +{ + return staticPrefix('js/min/'); +} + +/** + * @param {string} theme + * @return {string} + */ +export function themePreviewLink(theme) +{ + let prefix = VERSION_PREFIX; + if ('@custom' === theme.substr(-7)) + { + theme = trim(theme.substring(0, theme.length - 7)); + prefix = WEB_PREFIX; + } + + return prefix + 'themes/' + window.encodeURI(theme) + '/images/preview.png'; +} + +/** + * @param {string} inboxFolderName = 'INBOX' + * @return {string} + */ +export function inbox(inboxFolderName = 'INBOX') +{ + return HASH_PREFIX + 'mailbox/' + inboxFolderName; +} + +/** + * @param {string=} screenName = '' + * @return {string} + */ +export function settings(screenName = '') +{ + return HASH_PREFIX + 'settings' + (screenName ? '/' + screenName : ''); +} + +/** + * @return {string} + */ +export function about() +{ + return HASH_PREFIX + 'about'; +} + +/** + * @param {string} screenName + * @return {string} + */ +export function admin(screenName) +{ + let result = HASH_PREFIX; + switch (screenName) { + case 'AdminDomains': + result += 'domains'; + break; + case 'AdminSecurity': + result += 'security'; + break; + case 'AdminLicensing': + result += 'licensing'; + break; + } + + return result; +} + +/** + * @param {string} folder + * @param {number=} page = 1 + * @param {string=} search = '' + * @param {string=} threadUid = '' + * @return {string} + */ +export function mailBox(folder, page = 1, search = '', threadUid = '') +{ + page = isNormal(page) ? pInt(page) : 1; + search = pString(search); + + let result = HASH_PREFIX + 'mailbox/'; + + if ('' !== folder) + { + const resultThreadUid = pInt(threadUid); + result += window.encodeURI(folder) + (0 < resultThreadUid ? '~' + resultThreadUid : ''); + } + + if (1 < page) + { + result = result.replace(/[\/]+$/, ''); + result += '/p' + page; + } + + if ('' !== search) + { + result = result.replace(/[\/]+$/, ''); + result += '/' + window.encodeURI(search); + } + + return result; +} diff --git a/dev/Common/Mime.jsx b/dev/Common/Mime.jsx index 9fc1a42eb..a0f3aae78 100644 --- a/dev/Common/Mime.jsx +++ b/dev/Common/Mime.jsx @@ -2,7 +2,7 @@ /* eslint key-spacing: 0 */ /* eslint quote-props: 0 */ -module.exports = { +const Mime = { 'eml' : 'message/rfc822', 'mime' : 'message/rfc822', 'txt' : 'text/plain', @@ -162,3 +162,5 @@ module.exports = { 'odt' : 'application/vnd.oasis.opendocument.text', 'ods' : 'application/vnd.oasis.opendocument.spreadsheet' }; + +export {Mime, Mime as default}; diff --git a/dev/Common/Momentor.jsx b/dev/Common/Momentor.jsx index 2a9a6003b..ae08c0ace 100644 --- a/dev/Common/Momentor.jsx +++ b/dev/Common/Momentor.jsx @@ -2,159 +2,147 @@ import {window, $, _, moment} from 'common'; import Translator from 'Common/Translator'; -class Momentor +let _moment = null; +let _momentNow = 0; + +const updateMomentNow = _.debounce(() => { + _moment = moment(); +}, 500, true); + +const updateMomentNowUnix = _.debounce(() => { + _momentNow = moment().unix(); +}, 500, true); + +export function momentNow() { - _moment = null; - _momentNow = 0; + updateMomentNow(); + return _moment || moment(); +} - constructor() +export function momentNowUnix() +{ + updateMomentNowUnix(); + return _momentNow || 0; +} + +/** + * @param {number} date + * @return {string} + */ +export function searchSubtractFormatDateHelper(date) +{ + momentNow().clone().subtract('days', date).format('YYYY.MM.DD'); +} + +/** + * @param {Object} m + * @return {string} + */ +function formatCustomShortDate(m) +{ + const now = momentNow(); + if (m && now) { - this.updateMomentNow = _.debounce(() => { - this._moment = moment(); - }, 500, true); - - this.updateMomentNowUnix = _.debounce(() => { - this._momentNow = moment().unix(); - }, 500, true); - - this.format = _.bind(this.format, this); - } - - momentNow() { - this.updateMomentNow(); - return this._moment || moment(); - } - - momentNowUnix() { - this.updateMomentNowUnix(); - return this._momentNow || 0; - } - - /** - * @param {number} date - * @return {string} - */ - searchSubtractFormatDateHelper(date) { - return this.momentNow().clone().subtract('days', date).format('YYYY.MM.DD'); - } - - /** - * @param {Object} m - * @return {string} - */ - formatCustomShortDate(m) { - - const now = this.momentNow(); - if (m && now) + switch(true) { - switch(true) - { - case 4 >= now.diff(m, 'hours'): - return m.fromNow(); - case now.format('L') === m.format('L'): - return Translator.i18n('MESSAGE_LIST/TODAY_AT', { - TIME: m.format('LT') - }); - case now.clone().subtract('days', 1).format('L') === m.format('L'): - return Translator.i18n('MESSAGE_LIST/YESTERDAY_AT', { - TIME: m.format('LT') - }); - case now.year() === m.year(): - return m.format('D MMM.'); - } - } - - return m ? m.format('LL') : ''; - } - - /** - * @param {number} timeStampInUTC - * @param {string} format - * @return {string} - */ - format(timeStampInUTC, format) { - - let - m = null, - result = '' - ; - - const now = this.momentNowUnix(); - - timeStampInUTC = 0 < timeStampInUTC ? timeStampInUTC : (0 === timeStampInUTC ? now : 0); - timeStampInUTC = now < timeStampInUTC ? now : timeStampInUTC; - - m = 0 < timeStampInUTC ? moment.unix(timeStampInUTC) : null; - - if (m && 1970 === m.year()) - { - m = null; - } - - if (m) - { - switch (format) - { - case 'FROMNOW': - result = m.fromNow(); - break; - case 'SHORT': - result = this.formatCustomShortDate(m); - break; - case 'FULL': - result = m.format('LLL'); - break; - default: - result = m.format(format); - break; - } - } - - return result; - } - - /** - * @param {Object} element - */ - momentToNode(element) { - - var - key = '', - time = 0, - $el = $(element) - ; - - time = $el.data('moment-time'); - if (time) - { - key = $el.data('moment-format'); - if (key) - { - $el.text(this.format(time, key)); - } - - key = $el.data('moment-format-title'); - if (key) - { - $el.attr('title', this.format(time, key)); - } + case 4 >= now.diff(m, 'hours'): + return m.fromNow(); + case now.format('L') === m.format('L'): + return Translator.i18n('MESSAGE_LIST/TODAY_AT', { + TIME: m.format('LT') + }); + case now.clone().subtract('days', 1).format('L') === m.format('L'): + return Translator.i18n('MESSAGE_LIST/YESTERDAY_AT', { + TIME: m.format('LT') + }); + case now.year() === m.year(): + return m.format('D MMM.'); } } - /** - * @param {Object} elements - */ - momentToNodes(elements) { - _.defer(() => { - $('.moment', elements).each((index, item) => { - this.momentToNode(item); - }); - }); + return m ? m.format('LL') : ''; +} + +/** + * @param {number} timeStampInUTC + * @param {string} formatStr + * @return {string} + */ +export function format(timeStampInUTC, formatStr) +{ + + let + m = null, + result = '' + ; + + const now = momentNowUnix(); + + timeStampInUTC = 0 < timeStampInUTC ? timeStampInUTC : (0 === timeStampInUTC ? now : 0); + timeStampInUTC = now < timeStampInUTC ? now : timeStampInUTC; + + m = 0 < timeStampInUTC ? moment.unix(timeStampInUTC) : null; + + if (m && 1970 === m.year()) + { + m = null; } - reload() { - this.momentToNodes(window.document); + if (m) + { + switch (formatStr) + { + case 'FROMNOW': + result = m.fromNow(); + break; + case 'SHORT': + result = formatCustomShortDate(m); + break; + case 'FULL': + result = m.format('LLL'); + break; + default: + result = m.format(formatStr); + break; + } + } + + return result; +} + +/** + * @param {Object} element + */ +export function momentToNode(element) +{ + var + key = '', + time = 0, + $el = $(element) + ; + + time = $el.data('moment-time'); + if (time) + { + key = $el.data('moment-format'); + if (key) + { + $el.text(format(time, key)); + } + + key = $el.data('moment-format-title'); + if (key) + { + $el.attr('title', format(time, key)); + } } } -module.exports = new Momentor(); +export function reload() +{ + _.defer(() => { + $('.moment', window.document).each((index, item) => { + momentToNode(item); + }); + }); +} diff --git a/dev/Common/Plugins.jsx b/dev/Common/Plugins.jsx index ee0719025..883d7cc29 100644 --- a/dev/Common/Plugins.jsx +++ b/dev/Common/Plugins.jsx @@ -2,106 +2,107 @@ import {_} from 'common'; import {isFunc, isArray, isUnd} from 'Common/Utils'; import {data as GlobalsData} from 'Common/Globals'; -import Settings from 'Storage/Settings'; +import * as Settings from 'Storage/Settings'; -class Plugins +const SIMPLE_HOOKS = {}; +const USER_VIEW_MODELS_HOOKS = []; +const ADMIN_VIEW_MODELS_HOOKS = []; + +/** + * @param {string} name + * @param {Function} callback + */ +export function addHook(name, callback) { - oSimpleHooks = {}; - aUserViewModelsHooks = []; - aAdminViewModelsHooks = []; - - constructor() {} - - /** - * @param {string} name - * @param {Function} callback - */ - addHook(name, callback) { - if (isFunc(callback)) + if (isFunc(callback)) + { + if (!isArray(SIMPLE_HOOKS[name])) { - if (!isArray(this.oSimpleHooks[name])) - { - this.oSimpleHooks[name] = []; - } - - this.oSimpleHooks[name].push(callback); + SIMPLE_HOOKS[name] = []; } - } - /** - * @param {string} name - * @param {Array=} args - */ - runHook(name, args = []) { - if (isArray(this.oSimpleHooks[name])) - { - _.each(this.oSimpleHooks[name], (callback) => { - callback.apply(null, args); - }); - } - } - - /** - * @param {string} name - * @return {?} - */ - mainSettingsGet(name) { - return Settings.settingsGet(name); - } - - /** - * @param {Function} callback - * @param {string} action - * @param {Object=} parameters - * @param {?number=} timeout - */ - remoteRequest(callback, action, parameters, timeout) { - if (GlobalsData.__APP__) - { - GlobalsData.__APP__.remote().defaultRequest(callback, 'Plugin' + action, parameters, timeout); - } - } - - /** - * @param {Function} SettingsViewModelClass - * @param {string} labelName - * @param {string} template - * @param {string} route - */ - addSettingsViewModel(SettingsViewModelClass, template, labelName, route) { - this.aUserViewModelsHooks.push([SettingsViewModelClass, template, labelName, route]); - } - - /** - * @param {Function} SettingsViewModelClass - * @param {string} labelName - * @param {string} template - * @param {string} route - */ - addSettingsViewModelForAdmin(SettingsViewModelClass, template, labelName, route) { - this.aAdminViewModelsHooks.push([SettingsViewModelClass, template, labelName, route]); - } - - /** - * @param {boolean} admin - */ - runSettingsViewModelHooks(admin) { - const Knoin = require('Knoin/Knoin'); - _.each(admin ? this.aAdminViewModelsHooks : this.aUserViewModelsHooks, (view) => { - Knoin.addSettingsViewModel(view[0], view[1], view[2], view[3]); - }); - } - - /** - * @param {string} pluginSection - * @param {string} name - * @return {?} - */ - settingsGet(pluginSection, name) { - let plugins = Settings.settingsGet('Plugins'); - plugins = plugins && !isUnd(plugins[pluginSection]) ? plugins[pluginSection] : null; - return plugins ? (isUnd(plugins[name]) ? null : plugins[name]) : null; + SIMPLE_HOOKS[name].push(callback); } } -module.exports = new Plugins(); +/** + * @param {string} name + * @param {Array=} args = [] + */ +export function runHook(name, args = []) +{ + if (isArray(SIMPLE_HOOKS[name])) + { + _.each(SIMPLE_HOOKS[name], (callback) => { + callback.apply(null, args); + }); + } +} + +/** + * @param {string} name + * @return {?} + */ +export function mainSettingsGet(name) +{ + return Settings.settingsGet(name); +} + +/** + * @param {Function} callback + * @param {string} action + * @param {Object=} parameters + * @param {?number=} timeout + */ +export function remoteRequest(callback, action, parameters, timeout) +{ + if (GlobalsData.__APP__) + { + GlobalsData.__APP__.remote().defaultRequest(callback, 'Plugin' + action, parameters, timeout); + } +} + +/** + * @param {Function} SettingsViewModelClass + * @param {string} labelName + * @param {string} template + * @param {string} route + */ +export function addSettingsViewModel(SettingsViewModelClass, template, labelName, route) +{ + USER_VIEW_MODELS_HOOKS.push([SettingsViewModelClass, template, labelName, route]); +} + +/** + * @param {Function} SettingsViewModelClass + * @param {string} labelName + * @param {string} template + * @param {string} route + */ +export function addSettingsViewModelForAdmin(SettingsViewModelClass, template, labelName, route) +{ + ADMIN_VIEW_MODELS_HOOKS.push([SettingsViewModelClass, template, labelName, route]); +} + +/** + * @param {boolean} admin + */ +export function runSettingsViewModelHooks(admin) +{ + const Knoin = require('Knoin/Knoin'); + _.each(admin ? ADMIN_VIEW_MODELS_HOOKS : USER_VIEW_MODELS_HOOKS, (view) => { + Knoin.addSettingsViewModel(view[0], view[1], view[2], view[3]); + }); +} + +/** + * @param {string} pluginSection + * @param {string} name + * @return {?} + */ +export function settingsGet(pluginSection, name) +{ + let plugins = Settings.settingsGet('Plugins'); + plugins = plugins && !isUnd(plugins[pluginSection]) ? plugins[pluginSection] : null; + return plugins ? (isUnd(plugins[name]) ? null : plugins[name]) : null; +} diff --git a/dev/Common/Translator.jsx b/dev/Common/Translator.jsx index 1da021564..b1295606f 100644 --- a/dev/Common/Translator.jsx +++ b/dev/Common/Translator.jsx @@ -2,7 +2,7 @@ import {window, $, _} from 'common'; import ko from 'ko'; import {Notification, UploadErrorCode} from 'Common/Enums'; -import {pInt, microtime, noop, inArray} from 'Common/Utils'; +import {pInt, isUnd, isNull, has, bind, microtime, noop, inArray} from 'Common/Utils'; import {$html, bAnimationSupported} from 'Common/Globals'; class Translator @@ -13,7 +13,7 @@ class Translator constructor() { this.data = window.rainloopI18N || {}; this.trigger = ko.observable(false); - this.i18n = _.bind(this.i18n, this); + this.i18n = bind(this.i18n, this); this.init(); } @@ -30,16 +30,16 @@ class Translator result = this.data[key] ; - if (_.isUndefined(result)) + if (isUnd(result)) { - result = _.isUndefined(defaulValue) ? key : defaulValue; + result = isUnd(defaulValue) ? key : defaulValue; } - if (!_.isUndefined(valueList) && !_.isNull(valueList)) + if (!isUnd(valueList) && !isNull(valueList)) { for (valueName in valueList) { - if (_.has(valueList, valueName)) + if (has(valueList, valueName)) { result = result.replace('%' + valueName + '%', valueList[valueName]); } @@ -244,8 +244,8 @@ class Translator } defCode = defCode ? (window.parseInt(defCode, 10)) || 0 : 0; - return _.isUndefined(this.notificationI18N[code]) ? ( - defCode && _.isUndefined(this.notificationI18N[defCode]) ? this.notificationI18N[defCode] : '' + return isUnd(this.notificationI18N[code]) ? ( + defCode && isUnd(this.notificationI18N[defCode]) ? this.notificationI18N[defCode] : '' ) : this.notificationI18N[code]; } diff --git a/dev/Common/Utils.jsx b/dev/Common/Utils.jsx index c10bee1ef..0ba3b83a1 100644 --- a/dev/Common/Utils.jsx +++ b/dev/Common/Utils.jsx @@ -5,10 +5,10 @@ import _ from '_'; import ko from 'ko'; import {$win, $div, dropdownVisibility, data as GlobalsData} from 'Common/Globals'; import {ComposeType, EventKeyCode, SaveSettingsStep, FolderType} from 'Common/Enums'; +import {Mime} from 'Common/Mime'; -const JSEncrypt = require('JSEncrypt'); -const Autolinker = require('Autolinker'); -const Mime = require('Common/Mime'); +import JSEncrypt from 'JSEncrypt'; +import Autolinker from 'Autolinker'; const trim = $.trim; const inArray = $.inArray; @@ -17,23 +17,20 @@ const isObject = _.isObject; const isFunc = _.isFunction; const isUnd = _.isUndefined; const isNull = _.isNull; +const has = _.has; +const bind = _.bind; const noop = () => {}; -export {trim, inArray, isArray, isObject, isFunc, isUnd, isNull, noop, noop as emptyFunction}; +export {trim, inArray, isArray, isObject, isFunc, isUnd, isNull, has, bind, noop, noop as emptyFunction}; /** * @param {Function} callback */ export function silentTryCatch(callback) { - try - { + try { callback(); - } - catch (e) - { - // eslint-disable-line no-empty - } + } catch (e) {/* eslint-disable-line no-empty */} } /** @@ -284,16 +281,6 @@ const timeOutActionSecond = (function () { export {timeOutAction, timeOutActionSecond}; -/** - * @param {(Object|null|undefined)} item - * @param {string} prop - * @return {boolean} - */ -export function hos(item, prop) -{ - return item && window.Object && window.Object.hasOwnProperty ? window.Object.hasOwnProperty.call(item, prop) : false; -} - /** * @return {boolean} */ @@ -326,9 +313,7 @@ export function removeInFocus(force) { window.document.activeElement.blur(); } - } catch (e) { - // eslint-disable-line no-empty - } + } catch (e) {/* eslint-disable-line no-empty */} } } @@ -347,9 +332,7 @@ export function removeSelection() { window.document.selection.empty(); } - } catch (e) { - // eslint-disable-line no-empty - } + } catch (e) {/* eslint-disable-line no-empty */} } /** @@ -626,6 +609,122 @@ export function defautOptionsAfterRender(domOption, item) } } +/** + * @param {string} title + * @param {Object} body + * @param {boolean} isHtml + * @param {boolean} print + */ +export function clearBqSwitcher(body) +{ + body.find('blockquote.rl-bq-switcher').removeClass('rl-bq-switcher hidden-bq'); + body.find('.rlBlockquoteSwitcher').off('.rlBlockquoteSwitcher').remove(); + body.find('[data-html-editor-font-wrapper]').removeAttr('data-html-editor-font-wrapper'); +} + +/** + * @param {string} title + * @param {Object} body + * @param {boolean} isHtml + * @param {boolean} print + */ +export function previewMessage(title, body, isHtml, print) +{ + const + win = window.open(''), + doc = win.document, + bodyClone = body.clone(), + bodyClass = isHtml ? 'html' : 'plain' + ; + + clearBqSwitcher(bodyClone); + + const html = bodyClone ? bodyClone.html() : ''; + + title = encodeHtml(title); + + doc.write(` + + + + + + ${title} + + +${html} +`); + + doc.close(); + + if (print) + { + window.setTimeout(() => win.print(), 100); + } +} + /** * @param {Object} viewModel * @param {string} templateID @@ -637,7 +736,7 @@ export function windowPopupKnockout(viewModel, templateID, title, fCallback = nu const win = window.open(''), doc = win.document, - func = '__OpenerApplyBindingsUid' + fakeMd5() + '__', + func = 'openerApplyBindingsUid' + fakeMd5(), template = $('#' + templateID) ; @@ -671,7 +770,6 @@ export function windowPopupKnockout(viewModel, templateID, title, fCallback = nu - @@ -684,7 +782,7 @@ export function windowPopupKnockout(viewModel, templateID, title, fCallback = nu const script = doc.createElement('script'); script.type = 'text/javascript'; - script.innerHTML = `if(window&&window.opener&&window.opener['${func}']){window.opener['${func}']();window.opener['${func}']=null}`; + script.innerHTML = `if(window&&window.opener&&window.opener['${func}']){window.opener['${func}']();}`; doc.getElementsByTagName('head')[0].appendChild(script); } @@ -1325,19 +1423,6 @@ export function triggerAutocompleteInputChange(delay = false) { } } -/** - * @param {Object} params - */ -export function setHeadViewport(params) -{ - let content = []; - _.each(params, (key, value) => { - content.push('' + key + '=' + value); - }); - - $('#app-head-viewport').attr('content', content.join(', ')); -} - /** * @param {string} fileName * @return {string} diff --git a/dev/Knoin/AbstractBoot.jsx b/dev/Knoin/AbstractBoot.jsx index 6dad3ce41..8e818a519 100644 --- a/dev/Knoin/AbstractBoot.jsx +++ b/dev/Knoin/AbstractBoot.jsx @@ -1,9 +1,7 @@ class AbstractBoot { - bootstart() { - // eslint-disable-line no-empty - } + bootstart() {/* eslint-disable-line no-empty */} } export {AbstractBoot, AbstractBoot as default}; diff --git a/dev/Model/Message.js b/dev/Model/Message.js index 7b247de35..c12e42504 100644 --- a/dev/Model/Message.js +++ b/dev/Model/Message.js @@ -4,7 +4,6 @@ 'use strict'; var - window = require('window'), _ = require('_'), $ = require('$'), ko = require('ko'), @@ -755,33 +754,8 @@ */ MessageModel.prototype.viewPopupMessage = function (bPrint) { - Utils.windowPopupKnockout(this.getDataForWindowPopup(), 'PopupsWindowSimpleMessage', - this.subject(), function (oPopupWin) - { - if (oPopupWin && oPopupWin.document && oPopupWin.document.body) - { - $('img.lazy', oPopupWin.document.body).each(function (iIndex, oImg) { - - var - $oImg = $(oImg), - sOrig = $oImg.data('original'), - sSrc = $oImg.attr('src') - ; - - if (0 <= iIndex && sOrig && !sSrc) - { - $oImg.attr('src', sOrig); - } - }); - - if (bPrint) - { - window.setTimeout(function () { - oPopupWin.print(); - }, 100); - } - } - }); + this.showLazyExternalImagesInBody(); + Utils.previewMessage(this.subject(), this.body, this.isHtml(), bPrint); }; MessageModel.prototype.printMessage = function () @@ -870,17 +844,26 @@ return this; }; + MessageModel.prototype.showLazyExternalImagesInBody = function () + { + if (this.body) + { + $('.lazy.lazy-inited[data-original]', this.body).each(function () { + $(this).attr('src', $(this).attr('data-original')).removeAttr('data-original'); + }); + } + }; + MessageModel.prototype.showExternalImages = function (bLazy) { if (this.body && this.body.data('rl-has-images')) { - var sAttr = ''; bLazy = Utils.isUnd(bLazy) ? false : bLazy; this.hasImages(false); this.body.data('rl-has-images', false); - sAttr = this.proxy ? 'data-x-additional-src' : 'data-x-src'; + var sAttr = this.proxy ? 'data-x-additional-src' : 'data-x-src'; $('[' + sAttr + ']', this.body).each(function () { if (bLazy && $(this).is('img')) { @@ -888,7 +871,7 @@ .addClass('lazy') .attr('data-original', $(this).attr(sAttr)) .removeAttr(sAttr) - ; + ; } else { diff --git a/dev/Storage/Settings.jsx b/dev/Storage/Settings.jsx index acb39c8a1..f1be4321f 100644 --- a/dev/Storage/Settings.jsx +++ b/dev/Storage/Settings.jsx @@ -2,51 +2,45 @@ import {window} from 'common'; import {isUnd, isNormal, isArray, inArray} from 'Common/Utils'; -class SettingsStorage +let SETTINGS = window.__rlah_data() || null; +SETTINGS = isNormal(SETTINGS) ? SETTINGS : {}; + +let APP_SETTINGS = SETTINGS.System || null; +APP_SETTINGS = isNormal(APP_SETTINGS) ? APP_SETTINGS : {}; + +/** + * @param {string} name + * @return {*} + */ +export function settingsGet(name) { - settings = {}; - appSettings = {}; - - constructor() { - this.settings = window.__rlah_data() || {}; - this.settings = isNormal(this.settings) ? this.settings : {}; - - this.appSettings = this.settings.System || null; - this.appSettings = isNormal(this.appSettings) ? this.appSettings : {}; - } - - /** - * @param {string} name - * @return {*} - */ - settingsGet(name) { - return isUnd(this.settings[name]) ? null : this.settings[name]; - } - - /** - * @param {string} name - * @param {*} value - */ - settingsSet(name, value) { - this.settings[name] = value; - } - - /** - * @param {string} name - * @return {*} - */ - appSettingsGet(name) { - return isUnd(this.appSettings[name]) ? null : this.appSettings[name]; - } - - /** - * @param {string} name - * @return {boolean} - */ - capa(name) { - const values = this.settingsGet('Capa'); - return isArray(values) && isNormal(name) && -1 < inArray(name, values); - } + return isUnd(SETTINGS[name]) ? null : SETTINGS[name]; } -module.exports = new SettingsStorage(); +/** + * @param {string} name + * @param {*} value + */ +export function settingsSet(name, value) +{ + SETTINGS[name] = value; +} + +/** + * @param {string} name + * @return {*} + */ +export function appSettingsGet(name) +{ + return isUnd(APP_SETTINGS[name]) ? null : APP_SETTINGS[name]; +} + +/** + * @param {string} name + * @return {boolean} + */ +export function capa(name) +{ + const values = settingsGet('Capa'); + return isArray(values) && isNormal(name) && -1 < inArray(name, values); +} diff --git a/dev/Stores/AbstractApp.jsx b/dev/Stores/AbstractApp.jsx index ca62b7cbf..d020cec19 100644 --- a/dev/Stores/AbstractApp.jsx +++ b/dev/Stores/AbstractApp.jsx @@ -1,7 +1,7 @@ import ko from 'ko'; import {$html, bMobileDevice} from 'Common/Globals'; -import Settings from 'Storage/Settings'; +import * as Settings from 'Storage/Settings'; class AbstractAppStore { diff --git a/dev/Stores/Admin/App.jsx b/dev/Stores/Admin/App.jsx index 3fa2c8820..fb6d952aa 100644 --- a/dev/Stores/Admin/App.jsx +++ b/dev/Stores/Admin/App.jsx @@ -1,6 +1,6 @@ import ko from 'ko'; -import Settings from 'Storage/Settings'; +import * as Settings from 'Storage/Settings'; import {AbstractAppStore} from 'Stores/AbstractApp'; diff --git a/dev/Stores/User/App.jsx b/dev/Stores/User/App.jsx index 6889234c9..1b261cf65 100644 --- a/dev/Stores/User/App.jsx +++ b/dev/Stores/User/App.jsx @@ -2,7 +2,7 @@ import ko from 'ko'; import {Focused, KeyState} from 'Common/Enums'; import {keyScope} from 'Common/Globals'; -import Settings from 'Storage/Settings'; +import * as Settings from 'Storage/Settings'; import {isNonEmptyArray} from 'Common/Utils'; import {AbstractAppStore} from 'Stores/AbstractApp'; diff --git a/dev/Styles/Animations.less b/dev/Styles/Animations.less index d0812a0cc..7654f8316 100644 --- a/dev/Styles/Animations.less +++ b/dev/Styles/Animations.less @@ -63,6 +63,14 @@ html.csstransitions.rl-started-delay { } } +html { + &.rgba.cssanimations.backgroundsize .e-strip-animation { + background-size: 60px 60px; + .rl-strip-animation(0, 0.1); + animation: animate-stripes 2s linear infinite; + } +} + html.rl-anim { &.cssanimations.csstransitions.no-mobile .b-login-content .errorAnimated { @@ -86,12 +94,6 @@ html.rl-anim { .transition(all 0.3s ease-out); } - &.rgba.cssanimations.backgroundsize .e-strip-animation { - background-size: 60px 60px; - .rl-strip-animation(0, 0.1); - animation: animate-stripes 2s linear infinite; - } - &.csstransitions .button-delete-transitions { .transition(all 0.2s linear); } diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js index 6900d42b3..441da46e5 100644 --- a/dev/View/Popup/Compose.js +++ b/dev/View/Popup/Compose.js @@ -1117,29 +1117,7 @@ oText = $(oMessage.body).clone(); if (oText) { - oText.find('blockquote.rl-bq-switcher').removeClass('rl-bq-switcher hidden-bq'); - oText.find('.rlBlockquoteSwitcher').off('.rlBlockquoteSwitcher').remove(); - oText.find('[data-html-editor-font-wrapper]').removeAttr('data-html-editor-font-wrapper'); - -// (function () { -// -// var oTmp = null, iLimit = 0; -// -// while (true) -// { -// iLimit++; -// -// oTmp = oText.children(); -// if (10 > iLimit && oTmp.is('div') && 1 === oTmp.length) -// { -// oTmp.children().unwrap(); -// continue; -// } -// -// break; -// } -// -// }()); + Utils.clearBqSwitcher(oText); sText = oText.html(); } diff --git a/dev/View/User/MailBox/MessageList.js b/dev/View/User/MailBox/MessageList.js index 0bd179536..27c1dd08c 100644 --- a/dev/View/User/MailBox/MessageList.js +++ b/dev/View/User/MailBox/MessageList.js @@ -289,43 +289,40 @@ this.goToUpUpOrDownDown(bV); }, this)); - Events - .sub('mailbox.message-list.selector.go-down', function (bSelect) { - this.selector.goDown(bSelect); - }, this) - .sub('mailbox.message-list.selector.go-up', function (bSelect) { - this.selector.goUp(bSelect); - }, this) - ; + Events.sub('mailbox.message-list.selector.go-down', function (bSelect) { + this.selector.goDown(bSelect); + }, this); - Events - .sub('mailbox.message.show', function (sFolder, sUid) { + Events.sub('mailbox.message-list.selector.go-up', function (bSelect) { + this.selector.goUp(bSelect); + }, this); - var oMessage = _.find(this.messageList(), function (oItem) { - return oItem && sFolder === oItem.folderFullNameRaw && sUid === oItem.uid; - }); + Events.sub('mailbox.message.show', function (sFolder, sUid) { - if ('INBOX' === sFolder) + var oMessage = _.find(this.messageList(), function (oItem) { + return oItem && sFolder === oItem.folderFullNameRaw && sUid === oItem.uid; + }); + + if ('INBOX' === sFolder) + { + kn.setHash(Links.mailBox(sFolder, 1)); + } + + if (oMessage) + { + this.selector.selectMessageItem(oMessage); + } + else + { + if ('INBOX' !== sFolder) { kn.setHash(Links.mailBox(sFolder, 1)); } - if (oMessage) - { - this.selector.selectMessageItem(oMessage); - } - else - { - if ('INBOX' !== sFolder) - { - kn.setHash(Links.mailBox(sFolder, 1)); - } + MessageStore.selectMessageByFolderAndUid(sFolder, sUid); + } - MessageStore.selectMessageByFolderAndUid(sFolder, sUid); - } - - }, this) - ; + }, this); MessageStore.messageListEndHash.subscribe(function () { this.selector.scrollToTop(); diff --git a/dev/bootstrap.jsx b/dev/bootstrap.jsx index 23b9bd30a..d39778df5 100644 --- a/dev/bootstrap.jsx +++ b/dev/bootstrap.jsx @@ -1,13 +1,12 @@ import window from 'window'; -import _ from '_'; import $ from '$'; import {kill_CtrlA_CtrlS, detectDropdownVisibility, createCommand} from 'Common/Utils'; import {$win, $html, data as GlobalsData, bMobileDevice} from 'Common/Globals'; -import Plugins from 'Common/Plugins'; +import * as Enums from 'Common/Enums'; +import * as Plugins from 'Common/Plugins'; import Translator from 'Common/Translator'; import EmailModel from 'Model/Email'; -import * as Enums from 'Common/Enums'; export default (App) => { @@ -29,17 +28,16 @@ export default (App) => { const rl = window.rl || {}; - rl.i18n = _.bind(Translator.i18n, Translator); - - rl.addHook = _.bind(Plugins.addHook, Plugins); - rl.settingsGet = _.bind(Plugins.mainSettingsGet, Plugins); + rl.i18n = Translator.i18n; rl.createCommand = createCommand; - rl.addSettingsViewModel = _.bind(Plugins.addSettingsViewModel, Plugins); - rl.addSettingsViewModelForAdmin = _.bind(Plugins.addSettingsViewModelForAdmin, Plugins); + rl.addSettingsViewModel = Plugins.addSettingsViewModel; + rl.addSettingsViewModelForAdmin = Plugins.addSettingsViewModelForAdmin; - rl.pluginRemoteRequest = _.bind(Plugins.remoteRequest, Plugins); - rl.pluginSettingsGet = _.bind(Plugins.settingsGet, Plugins); + rl.addHook = Plugins.addHook; + rl.settingsGet = Plugins.mainSettingsGet; + rl.pluginSettingsGet = Plugins.settingsGet; + rl.pluginRemoteRequest = Plugins.remoteRequest; rl.EmailModel = EmailModel; rl.Enums = Enums; @@ -50,21 +48,21 @@ export default (App) => { $(() => { - _.delay(() => { + window.setTimeout(() => { if (window.rainloopTEMPLATES && window.rainloopTEMPLATES[0]) { $('#rl-templates').html(window.rainloopTEMPLATES[0]); - _.delay(() => { - - App.bootstart(); + window.setTimeout(() => { $html .removeClass('no-js rl-booted-trigger') .addClass('rl-booted') ; + App.bootstart(); + }, 10); } else diff --git a/rainloop/v/0.0.0/app/templates/Index.html b/rainloop/v/0.0.0/app/templates/Index.html index 7f5914d92..0d1e95b72 100644 --- a/rainloop/v/0.0.0/app/templates/Index.html +++ b/rainloop/v/0.0.0/app/templates/Index.html @@ -9,7 +9,7 @@ - +