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(` +
+ + + + +