diff --git a/dev/Common/Utils.js b/dev/Common/Utils.js index 3ce98157a..373ca4ddd 100644 --- a/dev/Common/Utils.js +++ b/dev/Common/Utils.js @@ -1075,6 +1075,7 @@ Utils.setExpandedFolder = function (sFullNameHash, bExpanded) Utils.initLayoutResizer = function (sLeft, sRight, sClientSideKeyName) { var + iDisabledWidth = 65, iMinWidth = 155, oLeft = $(sLeft), oRight = $(sRight), @@ -1095,16 +1096,15 @@ Utils.initLayoutResizer = function (sLeft, sRight, sClientSideKeyName) }, fDisable = function (bDisable) { - var iWidth = 5; if (bDisable) { oLeft.resizable('disable'); - fSetWidth(iWidth); + fSetWidth(iDisabledWidth); } else { oLeft.resizable('enable'); - iWidth = Utils.pInt(RL.local().get(sClientSideKeyName)) || iMinWidth; + var iWidth = Utils.pInt(RL.local().get(sClientSideKeyName)) || iMinWidth; fSetWidth(iWidth > iMinWidth ? iWidth : iMinWidth); } }, @@ -1123,7 +1123,7 @@ Utils.initLayoutResizer = function (sLeft, sRight, sClientSideKeyName) if (null !== mLeftWidth) { - fSetWidth(mLeftWidth); + fSetWidth(mLeftWidth > iMinWidth ? mLeftWidth : iMinWidth); } oLeft.resizable({ diff --git a/dev/Styles/Animations.less b/dev/Styles/Animations.less index 37a5374d1..52875eb9c 100644 --- a/dev/Styles/Animations.less +++ b/dev/Styles/Animations.less @@ -154,6 +154,14 @@ html.rl-started-trigger.no-mobile #rl-content { animation: highlight-folder-row 0.5s linear; } + &.csstransitions .b-folders .btn.buttonContacts { + .transition(margin 0.3s linear); + } + + &.csstransitions .b-folders .b-content.opacity-on-panel-disabled { + .transition(opacity 0.3s linear); + } + &.csstransitions .messageList { .messageListItem { .transition(max-height 400ms ease); diff --git a/dev/Styles/Contacts.less b/dev/Styles/Contacts.less index 98c83732d..8532e84f2 100644 --- a/dev/Styles/Contacts.less +++ b/dev/Styles/Contacts.less @@ -58,7 +58,7 @@ }*/ } - .b-list-toopbar { + .b-list-toolbar { padding: 0; height: 45px; text-align: center; @@ -71,7 +71,7 @@ } } - .b-list-footer-toopbar { + .b-list-footer-toolbar { position: absolute; left: 0; bottom: 0; diff --git a/dev/Styles/FolderList.less b/dev/Styles/FolderList.less index cc21fc672..83d263b12 100644 --- a/dev/Styles/FolderList.less +++ b/dev/Styles/FolderList.less @@ -15,22 +15,23 @@ height: 30px; padding: 10px 10px 0 @rlLowMargin; color: #fff; + z-index: 101; } .b-footer { position: absolute; - bottom: 18px; + bottom: 20px; right: 0; left: 0; height: 20px; - padding: 0 10px 0 0; + padding: 0 10px 0 5px; z-index: 101; } .b-content { position: absolute; top: 50px + @rlLowMargin; - bottom: 30px + @rlLowMargin + @rlBottomMargin; + bottom: 32px + @rlLowMargin + @rlBottomMargin; // left: @rlLowMargin; left: 0; right: 0; @@ -161,3 +162,10 @@ padding-left: @subPadding * 3 + @folderItemPadding; } } + +html.rl-left-panel-disabled { + .btn.buttonContacts { + margin-top: 10px !important; + margin-left: 0 !important; + } +} \ No newline at end of file diff --git a/dev/Styles/Layout.less b/dev/Styles/Layout.less index 2927b77f8..3b060b5d3 100644 --- a/dev/Styles/Layout.less +++ b/dev/Styles/Layout.less @@ -36,7 +36,7 @@ .g-ui-absolute-reset; width: @rlLeftWidth; - min-width: 120px; + min-width: 60px; } #rl-right { @@ -147,10 +147,10 @@ html.ssm-state-tablet, html.ssm-state-mobile { } .b-contacts-content.modal { - .b-list-toopbar, .b-list-content, .b-list-footer-toopbar { + .b-list-toolbar, .b-list-content, .b-list-footer-toolbar { width: 150px; } - .b-list-toopbar .e-search { + .b-list-toolbar .e-search { width: 125px; } .b-view-content { @@ -173,10 +173,10 @@ html.ssm-state-tablet { } .b-contacts-content.modal { - .b-list-toopbar, .b-list-content, .b-list-footer-toopbar { + .b-list-toolbar, .b-list-content, .b-list-footer-toolbar { width: 200px; } - .b-list-toopbar .e-search { + .b-list-toolbar .e-search { width: 175px; } .b-view-content { @@ -188,15 +188,38 @@ html.ssm-state-tablet { } } +.show-on-panel-disabled { + display: none; +} + html.rl-left-panel-disabled { #rl-left { - width: 5px !important; - display: none; + width: 65px !important; + + .show-on-panel-disabled { + display: block; + } + + .opacity-on-panel-disabled { + .opacity(30); + } + + .visibility-hidden-on-panel-disabled { + visibility: hidden; + } + + .hide-on-panel-disabled { + display: none; + } + + &.ui-state-disabled { + .opacity(100); + } } #rl-right { - left: 5px !important; + left: 65px !important; } } diff --git a/dev/ViewModels/AdminMenuViewModel.js b/dev/ViewModels/AdminMenuViewModel.js index b8ab2e283..ce97bcb1c 100644 --- a/dev/ViewModels/AdminMenuViewModel.js +++ b/dev/ViewModels/AdminMenuViewModel.js @@ -10,6 +10,8 @@ function AdminMenuViewModel(oScreen) { KnoinAbstractViewModel.call(this, 'Left', 'AdminMenu'); + this.leftPanelDisabled = RL.data().leftPanelDisabled; + this.menu = oScreen.menu; Knoin.constructorEnd(this); diff --git a/dev/ViewModels/AdminPaneViewModel.js b/dev/ViewModels/AdminPaneViewModel.js index 260fe20d0..86b749ee3 100644 --- a/dev/ViewModels/AdminPaneViewModel.js +++ b/dev/ViewModels/AdminPaneViewModel.js @@ -12,7 +12,6 @@ function AdminPaneViewModel() this.version = ko.observable(RL.settingsGet('Version')); this.adminManLoadingVisibility = RL.data().adminManLoadingVisibility; - this.leftPanelDisabled = RL.data().leftPanelDisabled; Knoin.constructorEnd(this); } diff --git a/dev/ViewModels/MailBoxMessageListViewModel.js b/dev/ViewModels/MailBoxMessageListViewModel.js index b94d86cff..bababcf21 100644 --- a/dev/ViewModels/MailBoxMessageListViewModel.js +++ b/dev/ViewModels/MailBoxMessageListViewModel.js @@ -26,7 +26,6 @@ function MailBoxMessageListViewModel() this.folderMenuForMove = oData.folderMenuForMove; this.useCheckboxesInList = oData.useCheckboxesInList; - this.leftPanelDisabled = oData.leftPanelDisabled; this.mainMessageListSearch = oData.mainMessageListSearch; this.messageListEndFolder = oData.messageListEndFolder; diff --git a/dev/ViewModels/SettingsMenuViewModel.js b/dev/ViewModels/SettingsMenuViewModel.js index c28f2ccb4..fc8c894e8 100644 --- a/dev/ViewModels/SettingsMenuViewModel.js +++ b/dev/ViewModels/SettingsMenuViewModel.js @@ -10,6 +10,8 @@ function SettingsMenuViewModel(oScreen) { KnoinAbstractViewModel.call(this, 'Left', 'SettingsMenu'); + this.leftPanelDisabled = RL.data().leftPanelDisabled; + this.menu = oScreen.menu; Knoin.constructorEnd(this); diff --git a/dev/ViewModels/SettingsPaneViewModel.js b/dev/ViewModels/SettingsPaneViewModel.js index ba71c6b60..b6d5ee08c 100644 --- a/dev/ViewModels/SettingsPaneViewModel.js +++ b/dev/ViewModels/SettingsPaneViewModel.js @@ -8,8 +8,6 @@ function SettingsPaneViewModel() { KnoinAbstractViewModel.call(this, 'Right', 'SettingsPane'); - this.leftPanelDisabled = RL.data().leftPanelDisabled; - Knoin.constructorEnd(this); } diff --git a/package.json b/package.json index 848173d92..e5aa4e9c6 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "RainLoop", "title": "RainLoop Webmail", "version": "1.6.6", - "release": "921", + "release": "922", "description": "Simple, modern & fast web-based email client", "homepage": "http://rainloop.net", "main": "Gruntfile.js", diff --git a/rainloop/v/0.0.0/app/templates/Views/AdminMenu.html b/rainloop/v/0.0.0/app/templates/Views/AdminMenu.html index 6cec329de..d4cd5d1b2 100644 --- a/rainloop/v/0.0.0/app/templates/Views/AdminMenu.html +++ b/rainloop/v/0.0.0/app/templates/Views/AdminMenu.html @@ -1,6 +1,12 @@
]*>/gmi, '\n__bq__start__\n') - .replace(/<\/blockquote>/gmi, '\n__bq__end__\n') - .replace(/]*>(.|[\s\S\r\n]*)<\/a>/gmi, convertLinks) - .replace(/ /gi, ' ') - .replace(/<[^>]*>/gm, '') - .replace(/>/gi, '>') - .replace(/</gi, '<') - .replace(/&/gi, '&') - .replace(/&\w{2,6};/gi, '') - ; - - return sText - .replace(/\n[ \t]+/gm, '\n') - .replace(/[\n]{3,}/gm, '\n\n') - .replace(/__bq__start__(.|[\s\S\r\n]*)__bq__end__/gm, convertBlockquote) - .replace(/__bq__start__/gm, '') - .replace(/__bq__end__/gm, '') - ; -}; - -/** - * @param {string} sPlain - * @return {string} - */ -Utils.plainToHtml = function (sPlain) -{ - return sPlain.toString() - .replace(/&/g, '&').replace(/>/g, '>').replace(/'); -}; - -Utils.resizeAndCrop = function (sUrl, iValue, fCallback) -{ - var oTempImg = new window.Image(); - oTempImg.onload = function() { - - var - aDiff = [0, 0], - oCanvas = document.createElement('canvas'), - oCtx = oCanvas.getContext('2d') - ; - - oCanvas.width = iValue; - oCanvas.height = iValue; - - if (this.width > this.height) - { - aDiff = [this.width - this.height, 0]; - } - else - { - aDiff = [0, this.height - this.width]; - } - - oCtx.fillStyle = '#fff'; - oCtx.fillRect(0, 0, iValue, iValue); - oCtx.drawImage(this, aDiff[0] / 2, aDiff[1] / 2, this.width - aDiff[0], this.height - aDiff[1], 0, 0, iValue, iValue); - - fCallback(oCanvas.toDataURL('image/jpeg')); - }; - - oTempImg.src = sUrl; -}; - -Utils.computedPagenatorHelper = function (koCurrentPage, koPageCount) -{ - return function() { - var - iPrev = 0, - iNext = 0, - iLimit = 2, - aResult = [], - iCurrentPage = koCurrentPage(), - iPageCount = koPageCount(), - - /** - * @param {number} iIndex - * @param {boolean=} bPush - * @param {string=} sCustomName - */ - fAdd = function (iIndex, bPush, sCustomName) { - - var oData = { - 'current': iIndex === iCurrentPage, - 'name': Utils.isUnd(sCustomName) ? iIndex.toString() : sCustomName.toString(), - 'custom': Utils.isUnd(sCustomName) ? false : true, - 'title': Utils.isUnd(sCustomName) ? '' : iIndex.toString(), - 'value': iIndex.toString() - }; - - if (Utils.isUnd(bPush) ? true : !!bPush) - { - aResult.push(oData); - } - else - { - aResult.unshift(oData); - } - } - ; - - if (1 < iPageCount || (0 < iPageCount && iPageCount < iCurrentPage)) -// if (0 < iPageCount && 0 < iCurrentPage) - { - if (iPageCount < iCurrentPage) - { - fAdd(iPageCount); - iPrev = iPageCount; - iNext = iPageCount; - } - else - { - if (3 >= iCurrentPage || iPageCount - 2 <= iCurrentPage) - { - iLimit += 2; - } - - fAdd(iCurrentPage); - iPrev = iCurrentPage; - iNext = iCurrentPage; - } - - while (0 < iLimit) { - - iPrev -= 1; - iNext += 1; - - if (0 < iPrev) - { - fAdd(iPrev, false); - iLimit--; - } - - if (iPageCount >= iNext) - { - fAdd(iNext, true); - iLimit--; - } - else if (0 >= iPrev) - { - break; - } - } - - if (3 === iPrev) - { - fAdd(2, false); - } - else if (3 < iPrev) - { - fAdd(Math.round((iPrev - 1) / 2), false, '...'); - } - - if (iPageCount - 2 === iNext) - { - fAdd(iPageCount - 1, true); - } - else if (iPageCount - 2 > iNext) - { - fAdd(Math.round((iPageCount + iNext) / 2), true, '...'); - } - - // first and last - if (1 < iPrev) - { - fAdd(1, false); - } - - if (iPageCount > iNext) - { - fAdd(iPageCount, true); - } - } - - return aResult; - }; -}; - -Utils.selectElement = function (element) -{ - /* jshint onevar: false */ - if (window.getSelection) - { - var sel = window.getSelection(); - sel.removeAllRanges(); - var range = document.createRange(); - range.selectNodeContents(element); - sel.addRange(range); - } - else if (document.selection) - { - var textRange = document.body.createTextRange(); - textRange.moveToElementText(element); - textRange.select(); - } - /* jshint onevar: true */ -}; - -Utils.disableKeyFilter = function () -{ - if (window.key) - { - key.filter = function () { - return RL.data().useKeyboardShortcuts(); - }; - } -}; - -Utils.restoreKeyFilter = function () -{ - if (window.key) - { - key.filter = function (event) { - - if (RL.data().useKeyboardShortcuts()) - { - var - element = event.target || event.srcElement, - tagName = element ? element.tagName : '' - ; - - tagName = tagName.toUpperCase(); - return !(tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA' || - (element && tagName === 'DIV' && 'editorHtmlArea' === element.className && element.contentEditable) - ); - } - - return false; - }; - } -}; - -Utils.detectDropdownVisibility = _.debounce(function () { - Globals.dropdownVisibility(!!_.find(BootstrapDropdowns, function (oItem) { - return oItem.hasClass('open'); - })); +/** + * @type {?} + */ +Globals.langChangeTrigger = ko.observable(true); + +/** + * @type {number} + */ +Globals.iAjaxErrorCount = 0; + +/** + * @type {number} + */ +Globals.iTokenErrorCount = 0; + +/** + * @type {number} + */ +Globals.iMessageBodyCacheCount = 0; + +/** + * @type {boolean} + */ +Globals.bUnload = false; + +/** + * @type {string} + */ +Globals.sUserAgent = (navigator.userAgent || '').toLowerCase(); + +/** + * @type {boolean} + */ +Globals.bIsiOSDevice = -1 < Globals.sUserAgent.indexOf('iphone') || -1 < Globals.sUserAgent.indexOf('ipod') || -1 < Globals.sUserAgent.indexOf('ipad'); + +/** + * @type {boolean} + */ +Globals.bIsAndroidDevice = -1 < Globals.sUserAgent.indexOf('android'); + +/** + * @type {boolean} + */ +Globals.bMobileDevice = Globals.bIsiOSDevice || Globals.bIsAndroidDevice; + +/** + * @type {boolean} + */ +Globals.bDisableNanoScroll = Globals.bMobileDevice; + +/** + * @type {boolean} + */ +Globals.bAllowPdfPreview = !Globals.bMobileDevice; + +/** + * @type {boolean} + */ +Globals.bAnimationSupported = !Globals.bMobileDevice && $html.hasClass('csstransitions'); + +/** + * @type {string} + */ +Globals.sAnimationType = ''; + +/** + * @type {Object} + */ +Globals.oHtmlEditorDefaultConfig = { + 'title': false, + 'stylesSet': false, + 'customConfig': '', + 'contentsCss': '', + 'toolbarGroups': [ + {name: 'spec'}, + {name: 'styles'}, + {name: 'basicstyles', groups: ['basicstyles', 'cleanup']}, + {name: 'colors'}, + {name: 'paragraph', groups: ['list', 'indent', 'blocks', 'align']}, + {name: 'links'}, + {name: 'insert'}, + {name: 'others'} +// {name: 'document', groups: ['mode', 'document', 'doctools']} + ], + + 'removePlugins': 'contextmenu', //blockquote + 'removeButtons': 'Format,Undo,Redo,Cut,Copy,Paste,Anchor,Strike,Subscript,Superscript,Image,SelectAll', + 'removeDialogTabs': 'link:advanced;link:target;image:advanced', + + 'extraPlugins': 'plain', + + 'allowedContent': true, + 'autoParagraph': false, + + 'enterMode': window.CKEDITOR.ENTER_BR, + 'shiftEnterMode': window.CKEDITOR.ENTER_BR, + + 'font_defaultLabel': 'Arial', + 'fontSize_defaultLabel': '13', + 'fontSize_sizes': '10/10px;12/12px;13/13px;14/14px;16/16px;18/18px;20/20px;24/24px;28/28px;36/36px;48/48px' +}; + +/** + * @type {Object} + */ +Globals.oHtmlEditorLangsMap = { + 'de': 'de', + 'es': 'es', + 'fr': 'fr', + 'hu': 'hu', + 'is': 'is', + 'it': 'it', + 'ko': 'ko', + 'ko-kr': 'ko', + 'lv': 'lv', + 'nl': 'nl', + 'no': 'no', + 'pl': 'pl', + 'pt': 'pt', + 'pt-pt': 'pt', + 'pt-br': 'pt-br', + 'ru': 'ru', + 'ro': 'ro', + 'zh': 'zh', + 'zh-cn': 'zh-cn' +}; + +if (Globals.bAllowPdfPreview && navigator && navigator.mimeTypes) +{ + Globals.bAllowPdfPreview = !!_.find(navigator.mimeTypes, function (oType) { + return oType && 'application/pdf' === oType.type; + }); +} + +Consts.Defaults = {}; +Consts.Values = {}; +Consts.DataImages = {}; + +/** + * @const + * @type {number} + */ +Consts.Defaults.MessagesPerPage = 20; + +/** + * @const + * @type {number} + */ +Consts.Defaults.ContactsPerPage = 50; + +/** + * @const + * @type {Array} + */ +Consts.Defaults.MessagesPerPageArray = [10, 20, 30, 50, 100/*, 150, 200, 300*/]; + +/** + * @const + * @type {number} + */ +Consts.Defaults.DefaultAjaxTimeout = 30000; + +/** + * @const + * @type {number} + */ +Consts.Defaults.SearchAjaxTimeout = 300000; + +/** + * @const + * @type {number} + */ +Consts.Defaults.SendMessageAjaxTimeout = 300000; + +/** + * @const + * @type {number} + */ +Consts.Defaults.SaveMessageAjaxTimeout = 200000; + +/** + * @const + * @type {number} + */ +Consts.Defaults.ContactsSyncAjaxTimeout = 200000; + +/** + * @const + * @type {string} + */ +Consts.Values.UnuseOptionValue = '__UNUSE__'; + +/** + * @const + * @type {string} + */ +Consts.Values.ClientSideCookieIndexName = 'rlcsc'; + +/** + * @const + * @type {number} + */ +Consts.Values.ImapDefaulPort = 143; + +/** + * @const + * @type {number} + */ +Consts.Values.ImapDefaulSecurePort = 993; + +/** + * @const + * @type {number} + */ +Consts.Values.SmtpDefaulPort = 25; + +/** + * @const + * @type {number} + */ +Consts.Values.SmtpDefaulSecurePort = 465; + +/** + * @const + * @type {number} + */ +Consts.Values.MessageBodyCacheLimit = 15; + +/** + * @const + * @type {number} + */ +Consts.Values.AjaxErrorLimit = 7; + +/** + * @const + * @type {number} + */ +Consts.Values.TokenErrorLimit = 10; + +/** + * @const + * @type {string} + */ +Consts.DataImages.UserDotPic = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIW2P8DwQACgAD/il4QJ8AAAAASUVORK5CYII='; + +/** + * @const + * @type {string} + */ +Consts.DataImages.TranspPic = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIW2NkAAIAAAoAAggA9GkAAAAASUVORK5CYII='; + +/** + * @enum {string} + */ +Enums.StorageResultType = { + 'Success': 'success', + 'Abort': 'abort', + 'Error': 'error', + 'Unload': 'unload' +}; + +/** + * @enum {number} + */ +Enums.State = { + 'Empty': 10, + 'Login': 20, + 'Auth': 30 +}; + +/** + * @enum {number} + */ +Enums.StateType = { + 'Webmail': 0, + 'Admin': 1 +}; + +/** + * @enum {string} + */ +Enums.KeyState = { + 'All': 'all', + 'None': 'none', + 'ContactList': 'contact-list', + 'MessageList': 'message-list', + 'FolderList': 'folder-list', + 'MessageView': 'message-view', + 'Compose': 'compose', + 'Settings': 'settings', + 'Menu': 'menu', + 'PopupComposeOpenPGP': 'compose-open-pgp', + 'PopupKeyboardShortcutsHelp': 'popup-keyboard-shortcuts-help', + 'PopupAsk': 'popup-ask' +}; + +/** + * @enum {number} + */ +Enums.FolderType = { + 'Inbox': 10, + 'SentItems': 11, + 'Draft': 12, + 'Trash': 13, + 'Spam': 14, + 'Archive': 15, + 'NotSpam': 80, + 'User': 99 +}; + +/** + * @enum {string} + */ +Enums.LoginSignMeTypeAsString = { + 'DefaultOff': 'defaultoff', + 'DefaultOn': 'defaulton', + 'Unused': 'unused' +}; + +/** + * @enum {number} + */ +Enums.LoginSignMeType = { + 'DefaultOff': 0, + 'DefaultOn': 1, + 'Unused': 2 +}; + +/** + * @enum {string} + */ +Enums.ComposeType = { + 'Empty': 'empty', + 'Reply': 'reply', + 'ReplyAll': 'replyall', + 'Forward': 'forward', + 'ForwardAsAttachment': 'forward-as-attachment', + 'Draft': 'draft', + 'EditAsNew': 'editasnew' +}; + +/** + * @enum {number} + */ +Enums.UploadErrorCode = { + 'Normal': 0, + 'FileIsTooBig': 1, + 'FilePartiallyUploaded': 2, + 'FileNoUploaded': 3, + 'MissingTempFolder': 4, + 'FileOnSaveingError': 5, + 'FileType': 98, + 'Unknown': 99 +}; + +/** + * @enum {number} + */ +Enums.SetSystemFoldersNotification = { + 'None': 0, + 'Sent': 1, + 'Draft': 2, + 'Spam': 3, + 'Trash': 4, + 'Archive': 5 +}; + +/** + * @enum {number} + */ +Enums.ClientSideKeyName = { + 'FoldersLashHash': 0, + 'MessagesInboxLastHash': 1, + 'MailBoxListSize': 2, + 'ExpandedFolders': 3, + 'FolderListSize': 4 +}; + +/** + * @enum {number} + */ +Enums.EventKeyCode = { + 'Backspace': 8, + 'Tab': 9, + 'Enter': 13, + 'Esc': 27, + 'PageUp': 33, + 'PageDown': 34, + 'Left': 37, + 'Right': 39, + 'Up': 38, + 'Down': 40, + 'End': 35, + 'Home': 36, + 'Space': 32, + 'Insert': 45, + 'Delete': 46, + 'A': 65, + 'S': 83 +}; + +/** + * @enum {number} + */ +Enums.MessageSetAction = { + 'SetSeen': 0, + 'UnsetSeen': 1, + 'SetFlag': 2, + 'UnsetFlag': 3 +}; + +/** + * @enum {number} + */ +Enums.MessageSelectAction = { + 'All': 0, + 'None': 1, + 'Invert': 2, + 'Unseen': 3, + 'Seen': 4, + 'Flagged': 5, + 'Unflagged': 6 +}; + +/** + * @enum {number} + */ +Enums.DesktopNotifications = { + 'Allowed': 0, + 'NotAllowed': 1, + 'Denied': 2, + 'NotSupported': 9 +}; + +/** + * @enum {number} + */ +Enums.MessagePriority = { + 'Low': 5, + 'Normal': 3, + 'High': 1 +}; + +/** + * @enum {string} + */ +Enums.EditorDefaultType = { + 'Html': 'Html', + 'Plain': 'Plain' +}; + +/** + * @enum {string} + */ +Enums.CustomThemeType = { + 'Light': 'Light', + 'Dark': 'Dark' +}; + +/** + * @enum {number} + */ +Enums.ServerSecure = { + 'None': 0, + 'SSL': 1, + 'TLS': 2 +}; + +/** + * @enum {number} + */ +Enums.SearchDateType = { + 'All': -1, + 'Days3': 3, + 'Days7': 7, + 'Month': 30 +}; + +/** + * @enum {number} + */ +Enums.EmailType = { + 'Defailt': 0, + 'Facebook': 1, + 'Google': 2 +}; + +/** + * @enum {number} + */ +Enums.SaveSettingsStep = { + 'Animate': -2, + 'Idle': -1, + 'TrueResult': 1, + 'FalseResult': 0 +}; + +/** + * @enum {string} + */ +Enums.InterfaceAnimation = { + 'None': 'None', + 'Normal': 'Normal', + 'Full': 'Full' +}; + +/** + * @enum {number} + */ +Enums.Layout = { + 'NoPreview': 0, + 'SidePreview': 1, + 'BottomPreview': 2 +}; + +/** + * @enum {number} + */ +Enums.SignedVerifyStatus = { + 'UnknownPublicKeys': -4, + 'UnknownPrivateKey': -3, + 'Unverified': -2, + 'Error': -1, + 'None': 0, + 'Success': 1 +}; + +/** + * @enum {number} + */ +Enums.ContactPropertyType = { + + 'Unknown': 0, + + 'FullName': 10, + + 'FirstName': 15, + 'LastName': 16, + 'MiddleName': 16, + 'Nick': 18, + + 'NamePrefix': 20, + 'NameSuffix': 21, + + 'Email': 30, + 'Phone': 31, + 'Web': 32, + + 'Birthday': 40, + + 'Facebook': 90, + 'Skype': 91, + 'GitHub': 92, + + 'Note': 110, + + 'Custom': 250 +}; + +/** + * @enum {number} + */ +Enums.Notification = { + 'InvalidToken': 101, + 'AuthError': 102, + 'AccessError': 103, + 'ConnectionError': 104, + 'CaptchaError': 105, + 'SocialFacebookLoginAccessDisable': 106, + 'SocialTwitterLoginAccessDisable': 107, + 'SocialGoogleLoginAccessDisable': 108, + 'DomainNotAllowed': 109, + 'AccountNotAllowed': 110, + + 'AccountTwoFactorAuthRequired': 120, + 'AccountTwoFactorAuthError': 121, + + 'CouldNotSaveNewPassword': 130, + 'CurrentPasswordIncorrect': 131, + 'NewPasswordShort': 132, + 'NewPasswordWeak': 133, + 'NewPasswordForbidden': 134, + + 'ContactsSyncError': 140, + + 'CantGetMessageList': 201, + 'CantGetMessage': 202, + 'CantDeleteMessage': 203, + 'CantMoveMessage': 204, + 'CantCopyMessage': 205, + + 'CantSaveMessage': 301, + 'CantSendMessage': 302, + 'InvalidRecipients': 303, + + 'CantCreateFolder': 400, + 'CantRenameFolder': 401, + 'CantDeleteFolder': 402, + 'CantSubscribeFolder': 403, + 'CantUnsubscribeFolder': 404, + 'CantDeleteNonEmptyFolder': 405, + + 'CantSaveSettings': 501, + 'CantSavePluginSettings': 502, + + 'DomainAlreadyExists': 601, + + 'CantInstallPackage': 701, + 'CantDeletePackage': 702, + 'InvalidPluginPackage': 703, + 'UnsupportedPluginPackage': 704, + + 'LicensingServerIsUnavailable': 710, + 'LicensingExpired': 711, + 'LicensingBanned': 712, + + 'DemoSendMessageError': 750, + + 'AccountAlreadyExists': 801, + + 'MailServerError': 901, + 'ClientViewError': 902, + 'UnknownNotification': 999, + 'UnknownError': 999 +}; + +Utils.trim = $.trim; +Utils.inArray = $.inArray; +Utils.isArray = _.isArray; +Utils.isFunc = _.isFunction; +Utils.isUnd = _.isUndefined; +Utils.isNull = _.isNull; +Utils.emptyFunction = function () {}; + +/** + * @param {*} oValue + * @return {boolean} + */ +Utils.isNormal = function (oValue) +{ + return !Utils.isUnd(oValue) && !Utils.isNull(oValue); +}; + +Utils.windowResize = _.debounce(function (iTimeout) { + if (Utils.isUnd(iTimeout)) + { + $window.resize(); + } + else + { + window.setTimeout(function () { + $window.resize(); + }, iTimeout); + } }, 50); -// Base64 encode / decode -// http://www.webtoolkit.info/ - -Base64 = { - - // private property - _keyStr : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', - - // public method for urlsafe encoding - urlsafe_encode : function (input) { - return Base64.encode(input).replace(/[+]/g, '-').replace(/[\/]/g, '_').replace(/[=]/g, '.'); - }, - - // public method for encoding - encode : function (input) { - var - output = '', - chr1, chr2, chr3, enc1, enc2, enc3, enc4, - i = 0 - ; - - input = Base64._utf8_encode(input); - - while (i < input.length) - { - chr1 = input.charCodeAt(i++); - chr2 = input.charCodeAt(i++); - chr3 = input.charCodeAt(i++); - - enc1 = chr1 >> 2; - enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); - enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); - enc4 = chr3 & 63; - - if (isNaN(chr2)) - { - enc3 = enc4 = 64; - } - else if (isNaN(chr3)) - { - enc4 = 64; - } - - output = output + - this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + - this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4); - } - - return output; - }, - - // public method for decoding - decode : function (input) { - var - output = '', - chr1, chr2, chr3, enc1, enc2, enc3, enc4, - i = 0 - ; - - input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ''); - - while (i < input.length) - { - enc1 = this._keyStr.indexOf(input.charAt(i++)); - enc2 = this._keyStr.indexOf(input.charAt(i++)); - enc3 = this._keyStr.indexOf(input.charAt(i++)); - enc4 = this._keyStr.indexOf(input.charAt(i++)); - - chr1 = (enc1 << 2) | (enc2 >> 4); - chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); - chr3 = ((enc3 & 3) << 6) | enc4; - - output = output + String.fromCharCode(chr1); - - if (enc3 !== 64) - { - output = output + String.fromCharCode(chr2); - } - - if (enc4 !== 64) - { - output = output + String.fromCharCode(chr3); - } - } - - return Base64._utf8_decode(output); - }, - - // private method for UTF-8 encoding - _utf8_encode : function (string) { - - string = string.replace(/\r\n/g, "\n"); - - var - utftext = '', - n = 0, - l = string.length, - c = 0 - ; - - for (; n < l; n++) { - - c = string.charCodeAt(n); - - if (c < 128) - { - utftext += String.fromCharCode(c); - } - else if ((c > 127) && (c < 2048)) - { - utftext += String.fromCharCode((c >> 6) | 192); - utftext += String.fromCharCode((c & 63) | 128); - } - else - { - utftext += String.fromCharCode((c >> 12) | 224); - utftext += String.fromCharCode(((c >> 6) & 63) | 128); - utftext += String.fromCharCode((c & 63) | 128); - } - } - - return utftext; - }, - - // private method for UTF-8 decoding - _utf8_decode : function (utftext) { - var - string = '', - i = 0, - c = 0, - c2 = 0, - c3 = 0 - ; - - while ( i < utftext.length ) - { - c = utftext.charCodeAt(i); - - if (c < 128) - { - string += String.fromCharCode(c); - i++; - } - else if((c > 191) && (c < 224)) - { - c2 = utftext.charCodeAt(i+1); - string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); - i += 2; - } - else - { - c2 = utftext.charCodeAt(i+1); - c3 = utftext.charCodeAt(i+2); - string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); - i += 3; - } - } - - return string; - } -}; - + +/** + * @param {(string|number)} mValue + * @param {boolean=} bIncludeZero + * @return {boolean} + */ +Utils.isPosNumeric = function (mValue, bIncludeZero) +{ + return Utils.isNormal(mValue) ? + ((Utils.isUnd(bIncludeZero) ? true : !!bIncludeZero) ? + (/^[0-9]*$/).test(mValue.toString()) : + (/^[1-9]+[0-9]*$/).test(mValue.toString())) : + false; +}; + +/** + * @param {*} iValue + * @return {number} + */ +Utils.pInt = function (iValue) +{ + return Utils.isNormal(iValue) && '' !== iValue ? window.parseInt(iValue, 10) : 0; +}; + +/** + * @param {*} mValue + * @return {string} + */ +Utils.pString = function (mValue) +{ + return Utils.isNormal(mValue) ? '' + mValue : ''; +}; + +/** + * @param {*} aValue + * @return {boolean} + */ +Utils.isNonEmptyArray = function (aValue) +{ + return Utils.isArray(aValue) && 0 < aValue.length; +}; + +/** + * @param {string} sPath + * @param {*=} oObject + * @param {Object=} oObjectToExportTo + */ +Utils.exportPath = function (sPath, oObject, oObjectToExportTo) +{ + var + part = null, + parts = sPath.split('.'), + cur = oObjectToExportTo || window + ; + + for (; parts.length && (part = parts.shift());) + { + if (!parts.length && !Utils.isUnd(oObject)) + { + cur[part] = oObject; + } + else if (cur[part]) + { + cur = cur[part]; + } + else + { + cur = cur[part] = {}; + } + } +}; + +/** + * @param {Object} oObject + * @param {string} sName + * @param {*} mValue + */ +Utils.pImport = function (oObject, sName, mValue) +{ + oObject[sName] = mValue; +}; + +/** + * @param {Object} oObject + * @param {string} sName + * @param {*} mDefault + * @return {*} + */ +Utils.pExport = function (oObject, sName, mDefault) +{ + return Utils.isUnd(oObject[sName]) ? mDefault : oObject[sName]; +}; + +/** + * @param {string} sText + * @return {string} + */ +Utils.encodeHtml = function (sText) +{ + return Utils.isNormal(sText) ? sText.toString() + .replace(/&/g, '&').replace(//g, '>') + .replace(/"/g, '"').replace(/'/g, ''') : ''; +}; + +/** + * @param {string} sText + * @param {number=} iLen + * @return {string} + */ +Utils.splitPlainText = function (sText, iLen) +{ + var + sPrefix = '', + sSubText = '', + sResult = sText, + iSpacePos = 0, + iNewLinePos = 0 + ; + + iLen = Utils.isUnd(iLen) ? 100 : iLen; + + while (sResult.length > iLen) + { + sSubText = sResult.substring(0, iLen); + iSpacePos = sSubText.lastIndexOf(' '); + iNewLinePos = sSubText.lastIndexOf('\n'); + + if (-1 !== iNewLinePos) + { + iSpacePos = iNewLinePos; + } + + if (-1 === iSpacePos) + { + iSpacePos = iLen; + } + + sPrefix += sSubText.substring(0, iSpacePos) + '\n'; + sResult = sResult.substring(iSpacePos + 1); + } + + return sPrefix + sResult; +}; + +Utils.timeOutAction = (function () { + + var + oTimeOuts = {} + ; + + return function (sAction, fFunction, iTimeOut) + { + if (Utils.isUnd(oTimeOuts[sAction])) + { + oTimeOuts[sAction] = 0; + } + + window.clearTimeout(oTimeOuts[sAction]); + oTimeOuts[sAction] = window.setTimeout(fFunction, iTimeOut); + }; +}()); + +Utils.timeOutActionSecond = (function () { + + var + oTimeOuts = {} + ; + + return function (sAction, fFunction, iTimeOut) + { + if (!oTimeOuts[sAction]) + { + oTimeOuts[sAction] = window.setTimeout(function () { + fFunction(); + oTimeOuts[sAction] = 0; + }, iTimeOut); + } + }; +}()); + +Utils.audio = (function () { + + var + oAudio = false + ; + + return function (sMp3File, sOggFile) { + + if (false === oAudio) + { + if (Globals.bIsiOSDevice) + { + oAudio = null; + } + else + { + var + bCanPlayMp3 = false, + bCanPlayOgg = false, + oAudioLocal = window.Audio ? new window.Audio() : null + ; + + if (oAudioLocal && oAudioLocal.canPlayType && oAudioLocal.play) + { + bCanPlayMp3 = '' !== oAudioLocal.canPlayType('audio/mpeg; codecs="mp3"'); + if (!bCanPlayMp3) + { + bCanPlayOgg = '' !== oAudioLocal.canPlayType('audio/ogg; codecs="vorbis"'); + } + + if (bCanPlayMp3 || bCanPlayOgg) + { + oAudio = oAudioLocal; + oAudio.preload = 'none'; + oAudio.loop = false; + oAudio.autoplay = false; + oAudio.muted = false; + oAudio.src = bCanPlayMp3 ? sMp3File : sOggFile; + } + else + { + oAudio = null; + } + } + else + { + oAudio = null; + } + } + } + + return oAudio; + }; +}()); + +/** + * @param {(Object|null|undefined)} oObject + * @param {string} sProp + * @return {boolean} + */ +Utils.hos = function (oObject, sProp) +{ + return oObject && Object.hasOwnProperty ? Object.hasOwnProperty.call(oObject, sProp) : false; +}; + +/** + * @param {string} sKey + * @param {Object=} oValueList + * @param {string=} sDefaulValue + * @return {string} + */ +Utils.i18n = function (sKey, oValueList, sDefaulValue) +{ + var + sValueName = '', + sResult = Utils.isUnd(I18n[sKey]) ? (Utils.isUnd(sDefaulValue) ? sKey : sDefaulValue) : I18n[sKey] + ; + + if (!Utils.isUnd(oValueList) && !Utils.isNull(oValueList)) + { + for (sValueName in oValueList) + { + if (Utils.hos(oValueList, sValueName)) + { + sResult = sResult.replace('%' + sValueName + '%', oValueList[sValueName]); + } + } + } + + return sResult; +}; + +/** + * @param {Object} oElement + */ +Utils.i18nToNode = function (oElement) +{ + _.defer(function () { + $('.i18n', oElement).each(function () { + var + jqThis = $(this), + sKey = '' + ; + + sKey = jqThis.data('i18n-text'); + if (sKey) + { + jqThis.text(Utils.i18n(sKey)); + } + else + { + sKey = jqThis.data('i18n-html'); + if (sKey) + { + jqThis.html(Utils.i18n(sKey)); + } + + sKey = jqThis.data('i18n-placeholder'); + if (sKey) + { + jqThis.attr('placeholder', Utils.i18n(sKey)); + } + + sKey = jqThis.data('i18n-title'); + if (sKey) + { + jqThis.attr('title', Utils.i18n(sKey)); + } + } + }); + }); +}; + +Utils.i18nToDoc = function () +{ + if (window.rainloopI18N) + { + I18n = window.rainloopI18N || {}; + Utils.i18nToNode($document); + + Globals.langChangeTrigger(!Globals.langChangeTrigger()); + } + + window.rainloopI18N = {}; +}; + +/** + * @param {Function} fCallback + * @param {Object} oScope + * @param {Function=} fLangCallback + */ +Utils.initOnStartOrLangChange = function (fCallback, oScope, fLangCallback) +{ + if (fCallback) + { + fCallback.call(oScope); + } + + if (fLangCallback) + { + Globals.langChangeTrigger.subscribe(function () { + if (fCallback) + { + fCallback.call(oScope); + } + + fLangCallback.call(oScope); + }); + } + else if (fCallback) + { + Globals.langChangeTrigger.subscribe(fCallback, oScope); + } +}; + +/** + * @return {boolean} + */ +Utils.inFocus = function () +{ + var oActiveObj = document.activeElement; + return (oActiveObj && ('INPUT' === oActiveObj.tagName || + 'TEXTAREA' === oActiveObj.tagName || + 'IFRAME' === oActiveObj.tagName || + ('DIV' === oActiveObj.tagName && 'editorHtmlArea' === oActiveObj.className && oActiveObj.contentEditable))); +}; + +Utils.removeInFocus = function () +{ + if (document && document.activeElement && document.activeElement.blur) + { + var oA = $(document.activeElement); + if (oA.is('input') || oA.is('textarea')) + { + document.activeElement.blur(); + } + } +}; + +Utils.removeSelection = function () +{ + if (window && window.getSelection) + { + var oSel = window.getSelection(); + if (oSel && oSel.removeAllRanges) + { + oSel.removeAllRanges(); + } + } + else if (document && document.selection && document.selection.empty) + { + document.selection.empty(); + } +}; + +/** + * @param {string} sPrefix + * @param {string} sSubject + * @param {boolean=} bFixLongSubject = true + * @return {string} + */ +Utils.replySubjectAdd = function (sPrefix, sSubject, bFixLongSubject) +{ + var + oMatch = null, + sResult = Utils.trim(sSubject) + ; + + if (null !== (oMatch = (new window.RegExp('^' + sPrefix + '[\\s]?\\:(.*)$', 'gi')).exec(sSubject)) && !Utils.isUnd(oMatch[1])) + { + sResult = sPrefix + '[2]: ' + oMatch[1]; + } + else if (null !== (oMatch = (new window.RegExp('^(' + sPrefix + '[\\s]?[\\[\\(]?)([\\d]+)([\\]\\)]?[\\s]?\\:.*)$', 'gi')).exec(sSubject)) && + !Utils.isUnd(oMatch[1]) && !Utils.isUnd(oMatch[2]) && !Utils.isUnd(oMatch[3])) + { + sResult = oMatch[1] + (Utils.pInt(oMatch[2]) + 1) + oMatch[3]; + } + else + { + sResult = sPrefix + ': ' + sSubject; + } + + sResult = sResult.replace(/[\s]+/g, ' '); + sResult = (Utils.isUnd(bFixLongSubject) ? true : bFixLongSubject) ? Utils.fixLongSubject(sResult) : sResult; +// sResult = sResult.replace(/^(Re|Fwd)[\s]?\[[\d]+\]:/ig, '$1:'); + return sResult; +}; + +/** + * @param {string} sSubject + * @return {string} + */ +Utils.fixLongSubject = function (sSubject) +{ + var + iCounter = 0, + oMatch = null + ; + + sSubject = Utils.trim(sSubject.replace(/[\s]+/, ' ')); + + do + { + oMatch = /^Re(\[([\d]+)\]|):[\s]{0,3}Re(\[([\d]+)\]|):/ig.exec(sSubject); + if (!oMatch || Utils.isUnd(oMatch[0])) + { + oMatch = null; + } + + if (oMatch) + { + iCounter = 0; + iCounter += Utils.isUnd(oMatch[2]) ? 1 : 0 + Utils.pInt(oMatch[2]); + iCounter += Utils.isUnd(oMatch[4]) ? 1 : 0 + Utils.pInt(oMatch[4]); + + sSubject = sSubject.replace(/^Re(\[[\d]+\]|):[\s]{0,3}Re(\[[\d]+\]|):/gi, 'Re' + (0 < iCounter ? '[' + iCounter + ']' : '') + ':'); + } + + } + while (oMatch); + + sSubject = sSubject.replace(/[\s]+/, ' '); + return sSubject; +}; + +/** + * @param {number} iNum + * @param {number} iDec + * @return {number} + */ +Utils.roundNumber = function (iNum, iDec) +{ + return Math.round(iNum * Math.pow(10, iDec)) / Math.pow(10, iDec); +}; + +/** + * @param {(number|string)} iSizeInBytes + * @return {string} + */ +Utils.friendlySize = function (iSizeInBytes) +{ + iSizeInBytes = Utils.pInt(iSizeInBytes); + + if (iSizeInBytes >= 1073741824) + { + return Utils.roundNumber(iSizeInBytes / 1073741824, 1) + 'GB'; + } + else if (iSizeInBytes >= 1048576) + { + return Utils.roundNumber(iSizeInBytes / 1048576, 1) + 'MB'; + } + else if (iSizeInBytes >= 1024) + { + return Utils.roundNumber(iSizeInBytes / 1024, 0) + 'KB'; + } + + return iSizeInBytes + 'B'; +}; + +/** + * @param {string} sDesc + */ +Utils.log = function (sDesc) +{ + if (window.console && window.console.log) + { + window.console.log(sDesc); + } +}; + +/** + * @param {number} iCode + * @param {*=} mMessage = '' + * @return {string} + */ +Utils.getNotification = function (iCode, mMessage) +{ + iCode = Utils.pInt(iCode); + if (Enums.Notification.ClientViewError === iCode && mMessage) + { + return mMessage; + } + + return Utils.isUnd(NotificationI18N[iCode]) ? '' : NotificationI18N[iCode]; +}; + +Utils.initNotificationLanguage = function () +{ + NotificationI18N[Enums.Notification.InvalidToken] = Utils.i18n('NOTIFICATIONS/INVALID_TOKEN'); + NotificationI18N[Enums.Notification.AuthError] = Utils.i18n('NOTIFICATIONS/AUTH_ERROR'); + NotificationI18N[Enums.Notification.AccessError] = Utils.i18n('NOTIFICATIONS/ACCESS_ERROR'); + NotificationI18N[Enums.Notification.ConnectionError] = Utils.i18n('NOTIFICATIONS/CONNECTION_ERROR'); + NotificationI18N[Enums.Notification.CaptchaError] = Utils.i18n('NOTIFICATIONS/CAPTCHA_ERROR'); + NotificationI18N[Enums.Notification.SocialFacebookLoginAccessDisable] = Utils.i18n('NOTIFICATIONS/SOCIAL_FACEBOOK_LOGIN_ACCESS_DISABLE'); + NotificationI18N[Enums.Notification.SocialTwitterLoginAccessDisable] = Utils.i18n('NOTIFICATIONS/SOCIAL_TWITTER_LOGIN_ACCESS_DISABLE'); + NotificationI18N[Enums.Notification.SocialGoogleLoginAccessDisable] = Utils.i18n('NOTIFICATIONS/SOCIAL_GOOGLE_LOGIN_ACCESS_DISABLE'); + NotificationI18N[Enums.Notification.DomainNotAllowed] = Utils.i18n('NOTIFICATIONS/DOMAIN_NOT_ALLOWED'); + NotificationI18N[Enums.Notification.AccountNotAllowed] = Utils.i18n('NOTIFICATIONS/ACCOUNT_NOT_ALLOWED'); + + NotificationI18N[Enums.Notification.AccountTwoFactorAuthRequired] = Utils.i18n('NOTIFICATIONS/ACCOUNT_TWO_FACTOR_AUTH_REQUIRED'); + NotificationI18N[Enums.Notification.AccountTwoFactorAuthError] = Utils.i18n('NOTIFICATIONS/ACCOUNT_TWO_FACTOR_AUTH_ERROR'); + + NotificationI18N[Enums.Notification.CouldNotSaveNewPassword] = Utils.i18n('NOTIFICATIONS/COULD_NOT_SAVE_NEW_PASSWORD'); + NotificationI18N[Enums.Notification.CurrentPasswordIncorrect] = Utils.i18n('NOTIFICATIONS/CURRENT_PASSWORD_INCORRECT'); + NotificationI18N[Enums.Notification.NewPasswordShort] = Utils.i18n('NOTIFICATIONS/NEW_PASSWORD_SHORT'); + NotificationI18N[Enums.Notification.NewPasswordWeak] = Utils.i18n('NOTIFICATIONS/NEW_PASSWORD_WEAK'); + NotificationI18N[Enums.Notification.NewPasswordForbidden] = Utils.i18n('NOTIFICATIONS/NEW_PASSWORD_FORBIDDENT'); + + NotificationI18N[Enums.Notification.ContactsSyncError] = Utils.i18n('NOTIFICATIONS/CONTACTS_SYNC_ERROR'); + + NotificationI18N[Enums.Notification.CantGetMessageList] = Utils.i18n('NOTIFICATIONS/CANT_GET_MESSAGE_LIST'); + NotificationI18N[Enums.Notification.CantGetMessage] = Utils.i18n('NOTIFICATIONS/CANT_GET_MESSAGE'); + NotificationI18N[Enums.Notification.CantDeleteMessage] = Utils.i18n('NOTIFICATIONS/CANT_DELETE_MESSAGE'); + NotificationI18N[Enums.Notification.CantMoveMessage] = Utils.i18n('NOTIFICATIONS/CANT_MOVE_MESSAGE'); + NotificationI18N[Enums.Notification.CantCopyMessage] = Utils.i18n('NOTIFICATIONS/CANT_MOVE_MESSAGE'); + + NotificationI18N[Enums.Notification.CantSaveMessage] = Utils.i18n('NOTIFICATIONS/CANT_SAVE_MESSAGE'); + NotificationI18N[Enums.Notification.CantSendMessage] = Utils.i18n('NOTIFICATIONS/CANT_SEND_MESSAGE'); + NotificationI18N[Enums.Notification.InvalidRecipients] = Utils.i18n('NOTIFICATIONS/INVALID_RECIPIENTS'); + + NotificationI18N[Enums.Notification.CantCreateFolder] = Utils.i18n('NOTIFICATIONS/CANT_CREATE_FOLDER'); + NotificationI18N[Enums.Notification.CantRenameFolder] = Utils.i18n('NOTIFICATIONS/CANT_RENAME_FOLDER'); + NotificationI18N[Enums.Notification.CantDeleteFolder] = Utils.i18n('NOTIFICATIONS/CANT_DELETE_FOLDER'); + NotificationI18N[Enums.Notification.CantDeleteNonEmptyFolder] = Utils.i18n('NOTIFICATIONS/CANT_DELETE_NON_EMPTY_FOLDER'); + NotificationI18N[Enums.Notification.CantSubscribeFolder] = Utils.i18n('NOTIFICATIONS/CANT_SUBSCRIBE_FOLDER'); + NotificationI18N[Enums.Notification.CantUnsubscribeFolder] = Utils.i18n('NOTIFICATIONS/CANT_UNSUBSCRIBE_FOLDER'); + + NotificationI18N[Enums.Notification.CantSaveSettings] = Utils.i18n('NOTIFICATIONS/CANT_SAVE_SETTINGS'); + NotificationI18N[Enums.Notification.CantSavePluginSettings] = Utils.i18n('NOTIFICATIONS/CANT_SAVE_PLUGIN_SETTINGS'); + + NotificationI18N[Enums.Notification.DomainAlreadyExists] = Utils.i18n('NOTIFICATIONS/DOMAIN_ALREADY_EXISTS'); + + NotificationI18N[Enums.Notification.CantInstallPackage] = Utils.i18n('NOTIFICATIONS/CANT_INSTALL_PACKAGE'); + NotificationI18N[Enums.Notification.CantDeletePackage] = Utils.i18n('NOTIFICATIONS/CANT_DELETE_PACKAGE'); + NotificationI18N[Enums.Notification.InvalidPluginPackage] = Utils.i18n('NOTIFICATIONS/INVALID_PLUGIN_PACKAGE'); + NotificationI18N[Enums.Notification.UnsupportedPluginPackage] = Utils.i18n('NOTIFICATIONS/UNSUPPORTED_PLUGIN_PACKAGE'); + + NotificationI18N[Enums.Notification.LicensingServerIsUnavailable] = Utils.i18n('NOTIFICATIONS/LICENSING_SERVER_IS_UNAVAILABLE'); + NotificationI18N[Enums.Notification.LicensingExpired] = Utils.i18n('NOTIFICATIONS/LICENSING_EXPIRED'); + NotificationI18N[Enums.Notification.LicensingBanned] = Utils.i18n('NOTIFICATIONS/LICENSING_BANNED'); + + NotificationI18N[Enums.Notification.DemoSendMessageError] = Utils.i18n('NOTIFICATIONS/DEMO_SEND_MESSAGE_ERROR'); + + NotificationI18N[Enums.Notification.AccountAlreadyExists] = Utils.i18n('NOTIFICATIONS/ACCOUNT_ALREADY_EXISTS'); + + NotificationI18N[Enums.Notification.MailServerError] = Utils.i18n('NOTIFICATIONS/MAIL_SERVER_ERROR'); + NotificationI18N[Enums.Notification.UnknownNotification] = Utils.i18n('NOTIFICATIONS/UNKNOWN_ERROR'); + NotificationI18N[Enums.Notification.UnknownError] = Utils.i18n('NOTIFICATIONS/UNKNOWN_ERROR'); +}; + +/** + * @param {*} mCode + * @return {string} + */ +Utils.getUploadErrorDescByCode = function (mCode) +{ + var sResult = ''; + switch (Utils.pInt(mCode)) { + case Enums.UploadErrorCode.FileIsTooBig: + sResult = Utils.i18n('UPLOAD/ERROR_FILE_IS_TOO_BIG'); + break; + case Enums.UploadErrorCode.FilePartiallyUploaded: + sResult = Utils.i18n('UPLOAD/ERROR_FILE_PARTIALLY_UPLOADED'); + break; + case Enums.UploadErrorCode.FileNoUploaded: + sResult = Utils.i18n('UPLOAD/ERROR_NO_FILE_UPLOADED'); + break; + case Enums.UploadErrorCode.MissingTempFolder: + sResult = Utils.i18n('UPLOAD/ERROR_MISSING_TEMP_FOLDER'); + break; + case Enums.UploadErrorCode.FileOnSaveingError: + sResult = Utils.i18n('UPLOAD/ERROR_ON_SAVING_FILE'); + break; + case Enums.UploadErrorCode.FileType: + sResult = Utils.i18n('UPLOAD/ERROR_FILE_TYPE'); + break; + default: + sResult = Utils.i18n('UPLOAD/ERROR_UNKNOWN'); + break; + } + + return sResult; +}; + +/** + * @param {?} oObject + * @param {string} sMethodName + * @param {Array=} aParameters + * @param {number=} nDelay + */ +Utils.delegateRun = function (oObject, sMethodName, aParameters, nDelay) +{ + if (oObject && oObject[sMethodName]) + { + nDelay = Utils.pInt(nDelay); + if (0 >= nDelay) + { + oObject[sMethodName].apply(oObject, Utils.isArray(aParameters) ? aParameters : []); + } + else + { + _.delay(function () { + oObject[sMethodName].apply(oObject, Utils.isArray(aParameters) ? aParameters : []); + }, nDelay); + } + } +}; + +/** + * @param {?} oEvent + */ +Utils.killCtrlAandS = function (oEvent) +{ + oEvent = oEvent || window.event; + if (oEvent && oEvent.ctrlKey && !oEvent.shiftKey && !oEvent.altKey) + { + var + oSender = oEvent.target || oEvent.srcElement, + iKey = oEvent.keyCode || oEvent.which + ; + + if (iKey === Enums.EventKeyCode.S) + { + oEvent.preventDefault(); + return; + } + + if (oSender && oSender.tagName && oSender.tagName.match(/INPUT|TEXTAREA/i)) + { + return; + } + + if (iKey === Enums.EventKeyCode.A) + { + if (window.getSelection) + { + window.getSelection().removeAllRanges(); + } + else if (window.document.selection && window.document.selection.clear) + { + window.document.selection.clear(); + } + + oEvent.preventDefault(); + } + } +}; + +/** + * @param {(Object|null|undefined)} oContext + * @param {Function} fExecute + * @param {(Function|boolean|null)=} fCanExecute + * @return {Function} + */ +Utils.createCommand = function (oContext, fExecute, fCanExecute) +{ + var + fResult = fExecute ? function () { + if (fResult.canExecute && fResult.canExecute()) + { + fExecute.apply(oContext, Array.prototype.slice.call(arguments)); + } + return false; + } : function () {} + ; + + fResult.enabled = ko.observable(true); + + fCanExecute = Utils.isUnd(fCanExecute) ? true : fCanExecute; + if (Utils.isFunc(fCanExecute)) + { + fResult.canExecute = ko.computed(function () { + return fResult.enabled() && fCanExecute.call(oContext); + }); + } + else + { + fResult.canExecute = ko.computed(function () { + return fResult.enabled() && !!fCanExecute; + }); + } + + return fResult; +}; + +/** + * @param {Object} oData + */ +Utils.initDataConstructorBySettings = function (oData) +{ + oData.editorDefaultType = ko.observable(Enums.EditorDefaultType.Html); + oData.showImages = ko.observable(false); + oData.interfaceAnimation = ko.observable(Enums.InterfaceAnimation.Full); + oData.contactsAutosave = ko.observable(false); + + Globals.sAnimationType = Enums.InterfaceAnimation.Full; + + oData.allowThemes = ko.observable(true); + oData.allowCustomLogin = ko.observable(false); + oData.allowLanguagesOnSettings = ko.observable(true); + oData.allowLanguagesOnLogin = ko.observable(true); + + oData.desktopNotifications = ko.observable(false); + oData.useThreads = ko.observable(true); + oData.replySameFolder = ko.observable(true); + oData.useCheckboxesInList = ko.observable(true); + + oData.layout = ko.observable(Enums.Layout.SidePreview); + oData.usePreviewPane = ko.computed(function () { + return Enums.Layout.NoPreview !== oData.layout(); + }); + + oData.interfaceAnimation.subscribe(function (sValue) { + if (Globals.bMobileDevice || sValue === Enums.InterfaceAnimation.None) + { + $html.removeClass('rl-anim rl-anim-full').addClass('no-rl-anim'); + + Globals.sAnimationType = Enums.InterfaceAnimation.None; + } + else + { + switch (sValue) + { + case Enums.InterfaceAnimation.Full: + $html.removeClass('no-rl-anim').addClass('rl-anim rl-anim-full'); + Globals.sAnimationType = sValue; + break; + case Enums.InterfaceAnimation.Normal: + $html.removeClass('no-rl-anim rl-anim-full').addClass('rl-anim'); + Globals.sAnimationType = sValue; + break; + } + } + }); + + oData.interfaceAnimation.valueHasMutated(); + + oData.desktopNotificationsPermisions = ko.computed(function () { + oData.desktopNotifications(); + var iResult = Enums.DesktopNotifications.NotSupported; + if (NotificationClass && NotificationClass.permission) + { + switch (NotificationClass.permission.toLowerCase()) + { + case 'granted': + iResult = Enums.DesktopNotifications.Allowed; + break; + case 'denied': + iResult = Enums.DesktopNotifications.Denied; + break; + case 'default': + iResult = Enums.DesktopNotifications.NotAllowed; + break; + } + } + else if (window.webkitNotifications && window.webkitNotifications.checkPermission) + { + iResult = window.webkitNotifications.checkPermission(); + } + + return iResult; + }); + + oData.useDesktopNotifications = ko.computed({ + 'read': function () { + return oData.desktopNotifications() && + Enums.DesktopNotifications.Allowed === oData.desktopNotificationsPermisions(); + }, + 'write': function (bValue) { + if (bValue) + { + var iPermission = oData.desktopNotificationsPermisions(); + if (Enums.DesktopNotifications.Allowed === iPermission) + { + oData.desktopNotifications(true); + } + else if (Enums.DesktopNotifications.NotAllowed === iPermission) + { + NotificationClass.requestPermission(function () { + oData.desktopNotifications.valueHasMutated(); + if (Enums.DesktopNotifications.Allowed === oData.desktopNotificationsPermisions()) + { + if (oData.desktopNotifications()) + { + oData.desktopNotifications.valueHasMutated(); + } + else + { + oData.desktopNotifications(true); + } + } + else + { + if (oData.desktopNotifications()) + { + oData.desktopNotifications(false); + } + else + { + oData.desktopNotifications.valueHasMutated(); + } + } + }); + } + else + { + oData.desktopNotifications(false); + } + } + else + { + oData.desktopNotifications(false); + } + } + }); + + oData.language = ko.observable(''); + oData.languages = ko.observableArray([]); + + oData.mainLanguage = ko.computed({ + 'read': oData.language, + 'write': function (sValue) { + if (sValue !== oData.language()) + { + if (-1 < Utils.inArray(sValue, oData.languages())) + { + oData.language(sValue); + } + else if (0 < oData.languages().length) + { + oData.language(oData.languages()[0]); + } + } + else + { + oData.language.valueHasMutated(); + } + } + }); + + oData.theme = ko.observable(''); + oData.themes = ko.observableArray([]); + + oData.mainTheme = ko.computed({ + 'read': oData.theme, + 'write': function (sValue) { + if (sValue !== oData.theme()) + { + var aThemes = oData.themes(); + if (-1 < Utils.inArray(sValue, aThemes)) + { + oData.theme(sValue); + } + else if (0 < aThemes.length) + { + oData.theme(aThemes[0]); + } + } + else + { + oData.theme.valueHasMutated(); + } + } + }); + + oData.allowAdditionalAccounts = ko.observable(false); + oData.allowIdentities = ko.observable(false); + oData.allowGravatar = ko.observable(false); + oData.determineUserLanguage = ko.observable(false); + + oData.messagesPerPage = ko.observable(Consts.Defaults.MessagesPerPage);//.extend({'throttle': 200}); + + oData.mainMessagesPerPage = oData.messagesPerPage; + oData.mainMessagesPerPage = ko.computed({ + 'read': oData.messagesPerPage, + 'write': function (iValue) { + if (-1 < Utils.inArray(Utils.pInt(iValue), Consts.Defaults.MessagesPerPageArray)) + { + if (iValue !== oData.messagesPerPage()) + { + oData.messagesPerPage(iValue); + } + } + else + { + oData.messagesPerPage.valueHasMutated(); + } + } + }); + + oData.facebookEnable = ko.observable(false); + oData.facebookAppID = ko.observable(''); + oData.facebookAppSecret = ko.observable(''); + + oData.twitterEnable = ko.observable(false); + oData.twitterConsumerKey = ko.observable(''); + oData.twitterConsumerSecret = ko.observable(''); + + oData.googleEnable = ko.observable(false); + oData.googleClientID = ko.observable(''); + oData.googleClientSecret = ko.observable(''); + + oData.dropboxEnable = ko.observable(false); + oData.dropboxApiKey = ko.observable(''); + + oData.contactsIsAllowed = ko.observable(false); +}; + +/** + * @param {{moment:Function}} oObject + */ +Utils.createMomentDate = function (oObject) +{ + if (Utils.isUnd(oObject.moment)) + { + oObject.moment = ko.observable(moment()); + } + + return ko.computed(function () { + Globals.momentTrigger(); + return this.moment().fromNow(); + }, oObject); +}; + +/** + * @param {{moment:Function, momentDate:Function}} oObject + */ +Utils.createMomentShortDate = function (oObject) +{ + return ko.computed(function () { + + var + sResult = '', + oMomentNow = moment(), + oMoment = this.moment(), + sMomentDate = this.momentDate() + ; + + if (4 >= oMomentNow.diff(oMoment, 'hours')) + { + sResult = sMomentDate; + } + else if (oMomentNow.format('L') === oMoment.format('L')) + { + sResult = Utils.i18n('MESSAGE_LIST/TODAY_AT', { + 'TIME': oMoment.format('LT') + }); + } + else if (oMomentNow.clone().subtract('days', 1).format('L') === oMoment.format('L')) + { + sResult = Utils.i18n('MESSAGE_LIST/YESTERDAY_AT', { + 'TIME': oMoment.format('LT') + }); + } + else if (oMomentNow.year() === oMoment.year()) + { + sResult = oMoment.format('D MMM.'); + } + else + { + sResult = oMoment.format('LL'); + } + + return sResult; + + }, oObject); +}; + +/** + * @param {string} sFullNameHash + * @return {boolean} + */ +Utils.isFolderExpanded = function (sFullNameHash) +{ + var aExpandedList = /** @type {Array|null} */ RL.local().get(Enums.ClientSideKeyName.ExpandedFolders); + return _.isArray(aExpandedList) && -1 !== _.indexOf(aExpandedList, sFullNameHash); +}; + +/** + * @param {string} sFullNameHash + * @param {boolean} bExpanded + */ +Utils.setExpandedFolder = function (sFullNameHash, bExpanded) +{ + var aExpandedList = /** @type {Array|null} */ RL.local().get(Enums.ClientSideKeyName.ExpandedFolders); + if (!_.isArray(aExpandedList)) + { + aExpandedList = []; + } + + if (bExpanded) + { + aExpandedList.push(sFullNameHash); + aExpandedList = _.uniq(aExpandedList); + } + else + { + aExpandedList = _.without(aExpandedList, sFullNameHash); + } + + RL.local().set(Enums.ClientSideKeyName.ExpandedFolders, aExpandedList); +}; + +Utils.initLayoutResizer = function (sLeft, sRight, sClientSideKeyName) +{ + var + iDisabledWidth = 65, + iMinWidth = 155, + oLeft = $(sLeft), + oRight = $(sRight), + + mLeftWidth = RL.local().get(sClientSideKeyName) || null, + + fSetWidth = function (iWidth) { + if (iWidth) + { + oLeft.css({ + 'width': '' + iWidth + 'px' + }); + + oRight.css({ + 'left': '' + iWidth + 'px' + }); + } + }, + + fDisable = function (bDisable) { + if (bDisable) + { + oLeft.resizable('disable'); + fSetWidth(iDisabledWidth); + } + else + { + oLeft.resizable('enable'); + var iWidth = Utils.pInt(RL.local().get(sClientSideKeyName)) || iMinWidth; + fSetWidth(iWidth > iMinWidth ? iWidth : iMinWidth); + } + }, + + fResizeFunction = function (oEvent, oObject) { + if (oObject && oObject.size && oObject.size.width) + { + RL.local().set(sClientSideKeyName, oObject.size.width); + + oRight.css({ + 'left': '' + oObject.size.width + 'px' + }); + } + } + ; + + if (null !== mLeftWidth) + { + fSetWidth(mLeftWidth > iMinWidth ? mLeftWidth : iMinWidth); + } + + oLeft.resizable({ + 'helper': 'ui-resizable-helper', + 'minWidth': iMinWidth, + 'maxWidth': 350, + 'handles': 'e', + 'stop': fResizeFunction + }); + + RL.sub('left-panel.off', function () { + fDisable(true); + }); + + RL.sub('left-panel.on', function () { + fDisable(false); + }); +}; + +/** + * @param {Object} oMessageTextBody + */ +Utils.initBlockquoteSwitcher = function (oMessageTextBody) +{ + if (oMessageTextBody) + { + var $oList = $('blockquote:not(.rl-bq-switcher)', oMessageTextBody).filter(function () { + return 0 === $(this).parent().closest('blockquote', oMessageTextBody).length; + }); + + if ($oList && 0 < $oList.length) + { + $oList.each(function () { + var $self = $(this), iH = $self.height(); + if (0 === iH || 100 < iH) + { + $self.addClass('rl-bq-switcher hidden-bq'); + $('') + .insertBefore($self) + .click(function () { + $self.toggleClass('hidden-bq'); + Utils.windowResize(); + }) + .after('
') + .before('
') + ; + } + }); + } + } +}; + +/** + * @param {Object} oMessageTextBody + */ +Utils.removeBlockquoteSwitcher = function (oMessageTextBody) +{ + if (oMessageTextBody) + { + $(oMessageTextBody).find('blockquote.rl-bq-switcher').each(function () { + $(this).removeClass('rl-bq-switcher hidden-bq'); + }); + + $(oMessageTextBody).find('.rlBlockquoteSwitcher').each(function () { + $(this).remove(); + }); + } +}; + +/** + * @param {Object} oMessageTextBody + */ +Utils.toggleMessageBlockquote = function (oMessageTextBody) +{ + if (oMessageTextBody) + { + oMessageTextBody.find('.rlBlockquoteSwitcher').click(); + } +}; + +/** + * @param {string} sName + * @param {Function} ViewModelClass + * @param {Function=} AbstractViewModel = KnoinAbstractViewModel + */ +Utils.extendAsViewModel = function (sName, ViewModelClass, AbstractViewModel) +{ + if (ViewModelClass) + { + if (!AbstractViewModel) + { + AbstractViewModel = KnoinAbstractViewModel; + } + + ViewModelClass.__name = sName; + Plugins.regViewModelHook(sName, ViewModelClass); + _.extend(ViewModelClass.prototype, AbstractViewModel.prototype); + } +}; + +/** + * @param {Function} SettingsViewModelClass + * @param {string} sLabelName + * @param {string} sTemplate + * @param {string} sRoute + * @param {boolean=} bDefault + */ +Utils.addSettingsViewModel = function (SettingsViewModelClass, sTemplate, sLabelName, sRoute, bDefault) +{ + SettingsViewModelClass.__rlSettingsData = { + 'Label': sLabelName, + 'Template': sTemplate, + 'Route': sRoute, + 'IsDefault': !!bDefault + }; + + ViewModels['settings'].push(SettingsViewModelClass); +}; + +/** + * @param {Function} SettingsViewModelClass + */ +Utils.removeSettingsViewModel = function (SettingsViewModelClass) +{ + ViewModels['settings-removed'].push(SettingsViewModelClass); +}; + +/** + * @param {Function} SettingsViewModelClass + */ +Utils.disableSettingsViewModel = function (SettingsViewModelClass) +{ + ViewModels['settings-disabled'].push(SettingsViewModelClass); +}; + +Utils.convertThemeName = function (sTheme) +{ + if ('@custom' === sTheme.substr(-7)) + { + sTheme = Utils.trim(sTheme.substring(0, sTheme.length - 7)); + } + + return Utils.trim(sTheme.replace(/[^a-zA-Z]+/g, ' ').replace(/([A-Z])/g, ' $1').replace(/[\s]+/g, ' ')); +}; + +/** + * @param {string} sName + * @return {string} + */ +Utils.quoteName = function (sName) +{ + return sName.replace(/["]/g, '\\"'); +}; + +/** + * @return {number} + */ +Utils.microtime = function () +{ + return (new Date()).getTime(); +}; + +/** + * + * @param {string} sLanguage + * @param {boolean=} bEng = false + * @return {string} + */ +Utils.convertLangName = function (sLanguage, bEng) +{ + return Utils.i18n('LANGS_NAMES' + (true === bEng ? '_EN' : '') + '/LANG_' + + sLanguage.toUpperCase().replace(/[^a-zA-Z0-9]+/, '_'), null, sLanguage); +}; + +/** + * @param {number=} iLen + * @return {string} + */ +Utils.fakeMd5 = function(iLen) +{ + var + sResult = '', + sLine = '0123456789abcdefghijklmnopqrstuvwxyz' + ; + + iLen = Utils.isUnd(iLen) ? 32 : Utils.pInt(iLen); + + while (sResult.length < iLen) + { + sResult += sLine.substr(Math.round(Math.random() * sLine.length), 1); + } + + return sResult; +}; + +/* jshint ignore:start */ + +/** + * @param {string} s + * @return {string} + */ +Utils.md5 = function(s){function L(k,d){return(k<>>(32-d))}function K(G,k){var I,d,F,H,x;F=(G&2147483648);H=(k&2147483648);I=(G&1073741824);d=(k&1073741824);x=(G&1073741823)+(k&1073741823);if(I&d){return(x^2147483648^F^H)}if(I|d){if(x&1073741824){return(x^3221225472^F^H)}else{return(x^1073741824^F^H)}}else{return(x^F^H)}}function r(d,F,k){return(d&F)|((~d)&k)}function q(d,F,k){return(d&k)|(F&(~k))}function p(d,F,k){return(d^F^k)}function n(d,F,k){return(F^(d|(~k)))}function u(G,F,aa,Z,k,H,I){G=K(G,K(K(r(F,aa,Z),k),I));return K(L(G,H),F)}function f(G,F,aa,Z,k,H,I){G=K(G,K(K(q(F,aa,Z),k),I));return K(L(G,H),F)}function D(G,F,aa,Z,k,H,I){G=K(G,K(K(p(F,aa,Z),k),I));return K(L(G,H),F)}function t(G,F,aa,Z,k,H,I){G=K(G,K(K(n(F,aa,Z),k),I));return K(L(G,H),F)}function e(G){var Z;var F=G.length;var x=F+8;var k=(x-(x%64))/64;var I=(k+1)*16;var aa=Array(I-1);var d=0;var H=0;while(H >>29;return aa}function B(x){var k="",F="",G,d;for(d=0;d<=3;d++){G=(x>>>(d*8))&255;F="0"+G.toString(16);k=k+F.substr(F.length-2,2)}return k}function J(k){k=k.replace(/rn/g,"n");var d="";for(var F=0;F 127)&&(x<2048)){d+=String.fromCharCode((x>>6)|192);d+=String.fromCharCode((x&63)|128)}else{d+=String.fromCharCode((x>>12)|224);d+=String.fromCharCode(((x>>6)&63)|128);d+=String.fromCharCode((x&63)|128)}}}return d}var C=Array();var P,h,E,v,g,Y,X,W,V;var S=7,Q=12,N=17,M=22;var A=5,z=9,y=14,w=20;var o=4,m=11,l=16,j=23;var U=6,T=10,R=15,O=21;s=J(s);C=e(s);Y=1732584193;X=4023233417;W=2562383102;V=271733878;for(P=0;P /g, '>').replace(/'); +}; + +Utils.draggeblePlace = function () +{ + return $(' ').appendTo('#rl-hidden'); +}; + +Utils.defautOptionsAfterRender = function (oOption, oItem) +{ + if (oItem && !Utils.isUnd(oItem.disabled) && oOption) + { + $(oOption) + .toggleClass('disabled', oItem.disabled) + .prop('disabled', oItem.disabled) + ; + } +}; + +/** + * @param {Object} oViewModel + * @param {string} sTemplateID + * @param {string} sTitle + * @param {Function=} fCallback + */ +Utils.windowPopupKnockout = function (oViewModel, sTemplateID, sTitle, fCallback) +{ + var + oScript = null, + oWin = window.open(''), + sFunc = '__OpenerApplyBindingsUid' + Utils.fakeMd5() + '__', + oTemplate = $('#' + sTemplateID) + ; + + window[sFunc] = function () { + + if (oWin && oWin.document.body && oTemplate && oTemplate[0]) + { + var oBody = $(oWin.document.body); + + $('#rl-content', oBody).html(oTemplate.html()); + $('html', oWin.document).addClass('external ' + $('html').attr('class')); + + Utils.i18nToNode(oBody); + + Knoin.prototype.applyExternal(oViewModel, $('#rl-content', oBody)[0]); + + window[sFunc] = null; + + fCallback(oWin); + } + }; + + oWin.document.open(); + oWin.document.write('' + +'' + +'' + +'' + +'' + +'' + +'' + Utils.encodeHtml(sTitle) + ' ' + +''); + oWin.document.close(); + + oScript = oWin.document.createElement('script'); + oScript.type = 'text/javascript'; + oScript.innerHTML = 'if(window&&window.opener&&window.opener[\'' + sFunc + '\']){window.opener[\'' + sFunc + '\']();window.opener[\'' + sFunc + '\']=null}'; + oWin.document.getElementsByTagName('head')[0].appendChild(oScript); +}; + +Utils.settingsSaveHelperFunction = function (fCallback, koTrigger, oContext, iTimer) +{ + oContext = oContext || null; + iTimer = Utils.isUnd(iTimer) ? 1000 : Utils.pInt(iTimer); + return function (sType, mData, bCached, sRequestAction, oRequestParameters) { + koTrigger.call(oContext, mData && mData['Result'] ? Enums.SaveSettingsStep.TrueResult : Enums.SaveSettingsStep.FalseResult); + if (fCallback) + { + fCallback.call(oContext, sType, mData, bCached, sRequestAction, oRequestParameters); + } + _.delay(function () { + koTrigger.call(oContext, Enums.SaveSettingsStep.Idle); + }, iTimer); + }; +}; + +Utils.settingsSaveHelperSimpleFunction = function (koTrigger, oContext) +{ + return Utils.settingsSaveHelperFunction(null, koTrigger, oContext, 1000); +}; + + +/** + * @param {string} sHtml + * @return {string} + */ +Utils.htmlToPlain = function (sHtml) +{ + var + sText = '', + sQuoteChar = '> ', + + convertBlockquote = function () { + if (arguments && 1 < arguments.length) + { + var sText = $.trim(arguments[1]) + .replace(/__bq__start__(.|[\s\S\n\r]*)__bq__end__/gm, convertBlockquote) + ; + + sText = '\n' + sQuoteChar + $.trim(sText).replace(/\n/gm, '\n' + sQuoteChar) + '\n>\n'; + + return sText.replace(/\n([> ]+)/gm, function () { + return (arguments && 1 < arguments.length) ? '\n' + $.trim(arguments[1].replace(/[\s]/, '')) + ' ' : ''; + }); + } + + return ''; + }, + + convertDivs = function () { + if (arguments && 1 < arguments.length) + { + var sText = $.trim(arguments[1]); + if (0 < sText.length) + { + sText = sText.replace(/]*>(.|[\s\S\r\n]*)<\/div>/gmi, convertDivs); + sText = '\n' + $.trim(sText) + '\n'; + } + return sText; + } + return ''; + }, + + fixAttibuteValue = function () { + if (arguments && 1 < arguments.length) + { + return '' + arguments[1] + arguments[2].replace(//g, '>'); + } + + return ''; + }, + + convertLinks = function () { + if (arguments && 1 < arguments.length) + { + var + sName = $.trim(arguments[1]) +// sHref = $.trim(arguments[0].replace(//gmi, '$1')) + ; + + return sName; +// sName = (0 === trim(sName).length) ? '' : sName; +// sHref = ('mailto:' === sHref.substr(0, 7)) ? '' : sHref; +// sHref = ('http' === sHref.substr(0, 4)) ? sHref : ''; +// sHref = (sName === sHref) ? '' : sHref; +// sHref = (0 < sHref.length) ? ' (' + sHref + ') ' : ''; +// return (0 < sName.length) ? sName + sHref : sName; + } + return ''; + } + ; + + sText = sHtml + .replace(/[\s]+/gm, ' ') + .replace(/((?:href|data)\s?=\s?)("[^"]+?"|'[^']+?')/gmi, fixAttibuteValue) + .replace(/
/gmi, '\n') + .replace(/<\/h\d>/gi, '\n') + .replace(/<\/p>/gi, '\n\n') + .replace(/<\/li>/gi, '\n') + .replace(/<\/td>/gi, '\n') + .replace(/<\/tr>/gi, '\n') + .replace(/
]*>/gmi, '\n_______________________________\n\n') + .replace(/]*>/gmi, '') + .replace(/
]*>(.|[\s\S\r\n]*)<\/div>/gmi, convertDivs) + .replace(/]*>/gmi, '\n__bq__start__\n') + .replace(/<\/blockquote>/gmi, '\n__bq__end__\n') + .replace(/]*>(.|[\s\S\r\n]*)<\/a>/gmi, convertLinks) + .replace(/ /gi, ' ') + .replace(/<[^>]*>/gm, '') + .replace(/>/gi, '>') + .replace(/</gi, '<') + .replace(/&/gi, '&') + .replace(/&\w{2,6};/gi, '') + ; + + return sText + .replace(/\n[ \t]+/gm, '\n') + .replace(/[\n]{3,}/gm, '\n\n') + .replace(/__bq__start__(.|[\s\S\r\n]*)__bq__end__/gm, convertBlockquote) + .replace(/__bq__start__/gm, '') + .replace(/__bq__end__/gm, '') + ; +}; + +/** + * @param {string} sPlain + * @return {string} + */ +Utils.plainToHtml = function (sPlain) +{ + return sPlain.toString() + .replace(/&/g, '&').replace(/>/g, '>').replace(/'); +}; + +Utils.resizeAndCrop = function (sUrl, iValue, fCallback) +{ + var oTempImg = new window.Image(); + oTempImg.onload = function() { + + var + aDiff = [0, 0], + oCanvas = document.createElement('canvas'), + oCtx = oCanvas.getContext('2d') + ; + + oCanvas.width = iValue; + oCanvas.height = iValue; + + if (this.width > this.height) + { + aDiff = [this.width - this.height, 0]; + } + else + { + aDiff = [0, this.height - this.width]; + } + + oCtx.fillStyle = '#fff'; + oCtx.fillRect(0, 0, iValue, iValue); + oCtx.drawImage(this, aDiff[0] / 2, aDiff[1] / 2, this.width - aDiff[0], this.height - aDiff[1], 0, 0, iValue, iValue); + + fCallback(oCanvas.toDataURL('image/jpeg')); + }; + + oTempImg.src = sUrl; +}; + +Utils.computedPagenatorHelper = function (koCurrentPage, koPageCount) +{ + return function() { + var + iPrev = 0, + iNext = 0, + iLimit = 2, + aResult = [], + iCurrentPage = koCurrentPage(), + iPageCount = koPageCount(), + + /** + * @param {number} iIndex + * @param {boolean=} bPush + * @param {string=} sCustomName + */ + fAdd = function (iIndex, bPush, sCustomName) { + + var oData = { + 'current': iIndex === iCurrentPage, + 'name': Utils.isUnd(sCustomName) ? iIndex.toString() : sCustomName.toString(), + 'custom': Utils.isUnd(sCustomName) ? false : true, + 'title': Utils.isUnd(sCustomName) ? '' : iIndex.toString(), + 'value': iIndex.toString() + }; + + if (Utils.isUnd(bPush) ? true : !!bPush) + { + aResult.push(oData); + } + else + { + aResult.unshift(oData); + } + } + ; + + if (1 < iPageCount || (0 < iPageCount && iPageCount < iCurrentPage)) +// if (0 < iPageCount && 0 < iCurrentPage) + { + if (iPageCount < iCurrentPage) + { + fAdd(iPageCount); + iPrev = iPageCount; + iNext = iPageCount; + } + else + { + if (3 >= iCurrentPage || iPageCount - 2 <= iCurrentPage) + { + iLimit += 2; + } + + fAdd(iCurrentPage); + iPrev = iCurrentPage; + iNext = iCurrentPage; + } + + while (0 < iLimit) { + + iPrev -= 1; + iNext += 1; + + if (0 < iPrev) + { + fAdd(iPrev, false); + iLimit--; + } + + if (iPageCount >= iNext) + { + fAdd(iNext, true); + iLimit--; + } + else if (0 >= iPrev) + { + break; + } + } + + if (3 === iPrev) + { + fAdd(2, false); + } + else if (3 < iPrev) + { + fAdd(Math.round((iPrev - 1) / 2), false, '...'); + } + + if (iPageCount - 2 === iNext) + { + fAdd(iPageCount - 1, true); + } + else if (iPageCount - 2 > iNext) + { + fAdd(Math.round((iPageCount + iNext) / 2), true, '...'); + } + + // first and last + if (1 < iPrev) + { + fAdd(1, false); + } + + if (iPageCount > iNext) + { + fAdd(iPageCount, true); + } + } + + return aResult; + }; +}; + +Utils.selectElement = function (element) +{ + /* jshint onevar: false */ + if (window.getSelection) + { + var sel = window.getSelection(); + sel.removeAllRanges(); + var range = document.createRange(); + range.selectNodeContents(element); + sel.addRange(range); + } + else if (document.selection) + { + var textRange = document.body.createTextRange(); + textRange.moveToElementText(element); + textRange.select(); + } + /* jshint onevar: true */ +}; + +Utils.disableKeyFilter = function () +{ + if (window.key) + { + key.filter = function () { + return RL.data().useKeyboardShortcuts(); + }; + } +}; + +Utils.restoreKeyFilter = function () +{ + if (window.key) + { + key.filter = function (event) { + + if (RL.data().useKeyboardShortcuts()) + { + var + element = event.target || event.srcElement, + tagName = element ? element.tagName : '' + ; + + tagName = tagName.toUpperCase(); + return !(tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA' || + (element && tagName === 'DIV' && 'editorHtmlArea' === element.className && element.contentEditable) + ); + } + + return false; + }; + } +}; + +Utils.detectDropdownVisibility = _.debounce(function () { + Globals.dropdownVisibility(!!_.find(BootstrapDropdowns, function (oItem) { + return oItem.hasClass('open'); + })); +}, 50); +// Base64 encode / decode +// http://www.webtoolkit.info/ + +Base64 = { + + // private property + _keyStr : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', + + // public method for urlsafe encoding + urlsafe_encode : function (input) { + return Base64.encode(input).replace(/[+]/g, '-').replace(/[\/]/g, '_').replace(/[=]/g, '.'); + }, + + // public method for encoding + encode : function (input) { + var + output = '', + chr1, chr2, chr3, enc1, enc2, enc3, enc4, + i = 0 + ; + + input = Base64._utf8_encode(input); + + while (i < input.length) + { + chr1 = input.charCodeAt(i++); + chr2 = input.charCodeAt(i++); + chr3 = input.charCodeAt(i++); + + enc1 = chr1 >> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); + enc4 = chr3 & 63; + + if (isNaN(chr2)) + { + enc3 = enc4 = 64; + } + else if (isNaN(chr3)) + { + enc4 = 64; + } + + output = output + + this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + + this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4); + } + + return output; + }, + + // public method for decoding + decode : function (input) { + var + output = '', + chr1, chr2, chr3, enc1, enc2, enc3, enc4, + i = 0 + ; + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ''); + + while (i < input.length) + { + enc1 = this._keyStr.indexOf(input.charAt(i++)); + enc2 = this._keyStr.indexOf(input.charAt(i++)); + enc3 = this._keyStr.indexOf(input.charAt(i++)); + enc4 = this._keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output = output + String.fromCharCode(chr1); + + if (enc3 !== 64) + { + output = output + String.fromCharCode(chr2); + } + + if (enc4 !== 64) + { + output = output + String.fromCharCode(chr3); + } + } + + return Base64._utf8_decode(output); + }, + + // private method for UTF-8 encoding + _utf8_encode : function (string) { + + string = string.replace(/\r\n/g, "\n"); + + var + utftext = '', + n = 0, + l = string.length, + c = 0 + ; + + for (; n < l; n++) { + + c = string.charCodeAt(n); + + if (c < 128) + { + utftext += String.fromCharCode(c); + } + else if ((c > 127) && (c < 2048)) + { + utftext += String.fromCharCode((c >> 6) | 192); + utftext += String.fromCharCode((c & 63) | 128); + } + else + { + utftext += String.fromCharCode((c >> 12) | 224); + utftext += String.fromCharCode(((c >> 6) & 63) | 128); + utftext += String.fromCharCode((c & 63) | 128); + } + } + + return utftext; + }, + + // private method for UTF-8 decoding + _utf8_decode : function (utftext) { + var + string = '', + i = 0, + c = 0, + c2 = 0, + c3 = 0 + ; + + while ( i < utftext.length ) + { + c = utftext.charCodeAt(i); + + if (c < 128) + { + string += String.fromCharCode(c); + i++; + } + else if((c > 191) && (c < 224)) + { + c2 = utftext.charCodeAt(i+1); + string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); + i += 2; + } + else + { + c2 = utftext.charCodeAt(i+1); + c3 = utftext.charCodeAt(i+2); + string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + i += 3; + } + } + + return string; + } +}; + /*jslint bitwise: false*/ -ko.bindingHandlers.tooltip = { - 'init': function (oElement, fValueAccessor) { - if (!Globals.bMobileDevice) - { - var - $oEl = $(oElement), - sClass = $oEl.data('tooltip-class') || '', - sPlacement = $oEl.data('tooltip-placement') || 'top' - ; - - $oEl.tooltip({ - 'delay': { - 'show': 500, - 'hide': 100 - }, - 'html': true, - 'container': 'body', - 'placement': sPlacement, - 'trigger': 'hover', - 'title': function () { - return $oEl.is('.disabled') || Globals.dropdownVisibility() ? '' : '' + - Utils.i18n(ko.utils.unwrapObservable(fValueAccessor())) + ''; - } - }).click(function () { - $oEl.tooltip('hide'); - }); - - Globals.dropdownVisibility.subscribe(function (bValue) { - if (bValue) - { - $oEl.tooltip('hide'); - } - }); - } - } -}; - -ko.bindingHandlers.tooltip2 = { - 'init': function (oElement, fValueAccessor) { - var - $oEl = $(oElement), - sClass = $oEl.data('tooltip-class') || '', - sPlacement = $oEl.data('tooltip-placement') || 'top' - ; - - $oEl.tooltip({ - 'delay': { - 'show': 500, - 'hide': 100 - }, - 'html': true, - 'container': 'body', - 'placement': sPlacement, - 'title': function () { - return $oEl.is('.disabled') || Globals.dropdownVisibility() ? '' : - '' + fValueAccessor()() + ''; - } - }).click(function () { - $oEl.tooltip('hide'); - }); - - Globals.dropdownVisibility.subscribe(function (bValue) { - if (bValue) - { - $oEl.tooltip('hide'); - } - }); - } -}; - -ko.bindingHandlers.tooltip3 = { - 'init': function (oElement) { - - var $oEl = $(oElement); - - $oEl.tooltip({ - 'container': 'body', - 'trigger': 'hover manual', - 'title': function () { - return $oEl.data('tooltip3-data') || ''; - } - }); - - Globals.dropdownVisibility.subscribe(function (bValue) { - if (bValue) - { - $oEl.tooltip('hide'); - } - }); - - $document.click(function () { - $oEl.tooltip('hide'); - }); - - }, - 'update': function (oElement, fValueAccessor) { - var sValue = ko.utils.unwrapObservable(fValueAccessor()); - if ('' === sValue) - { - $(oElement).data('tooltip3-data', '').tooltip('hide'); - } - else - { - $(oElement).data('tooltip3-data', sValue).tooltip('show'); - } - } -}; - -ko.bindingHandlers.registrateBootstrapDropdown = { - 'init': function (oElement) { - BootstrapDropdowns.push($(oElement)); - } -}; - -ko.bindingHandlers.openDropdownTrigger = { - 'update': function (oElement, fValueAccessor) { - if (ko.utils.unwrapObservable(fValueAccessor())) - { - var $el = $(oElement); - if (!$el.hasClass('open')) - { - $el.find('.dropdown-toggle').dropdown('toggle'); - Utils.detectDropdownVisibility(); - } - - fValueAccessor()(false); - } - } -}; - -ko.bindingHandlers.dropdownCloser = { - 'init': function (oElement) { - $(oElement).closest('.dropdown').on('click', '.e-item', function () { - $(oElement).dropdown('toggle'); - }); - } -}; - -ko.bindingHandlers.popover = { - 'init': function (oElement, fValueAccessor) { - $(oElement).popover(ko.utils.unwrapObservable(fValueAccessor())); - } -}; - -ko.bindingHandlers.csstext = { - 'init': function (oElement, fValueAccessor) { - if (oElement && oElement.styleSheet && !Utils.isUnd(oElement.styleSheet.cssText)) - { - oElement.styleSheet.cssText = ko.utils.unwrapObservable(fValueAccessor()); - } - else - { - $(oElement).text(ko.utils.unwrapObservable(fValueAccessor())); - } - }, - 'update': function (oElement, fValueAccessor) { - if (oElement && oElement.styleSheet && !Utils.isUnd(oElement.styleSheet.cssText)) - { - oElement.styleSheet.cssText = ko.utils.unwrapObservable(fValueAccessor()); - } - else - { - $(oElement).text(ko.utils.unwrapObservable(fValueAccessor())); - } - } -}; - -ko.bindingHandlers.resizecrop = { - 'init': function (oElement) { - $(oElement).addClass('resizecrop').resizecrop({ - 'width': '100', - 'height': '100', - 'wrapperCSS': { - 'border-radius': '10px' - } - }); - }, - 'update': function (oElement, fValueAccessor) { - fValueAccessor()(); - $(oElement).resizecrop({ - 'width': '100', - 'height': '100' - }); - } -}; - -ko.bindingHandlers.onEnter = { - 'init': function (oElement, fValueAccessor, fAllBindingsAccessor, oViewModel) { - $(oElement).on('keypress', function (oEvent) { - if (oEvent && 13 === window.parseInt(oEvent.keyCode, 10)) - { - $(oElement).trigger('change'); - fValueAccessor().call(oViewModel); - } - }); - } -}; - -ko.bindingHandlers.onEsc = { - 'init': function (oElement, fValueAccessor, fAllBindingsAccessor, oViewModel) { - $(oElement).on('keypress', function (oEvent) { - if (oEvent && 27 === window.parseInt(oEvent.keyCode, 10)) - { - $(oElement).trigger('change'); - fValueAccessor().call(oViewModel); - } - }); - } -}; - -ko.bindingHandlers.clickOnTrue = { - 'update': function (oElement, fValueAccessor) { - if (ko.utils.unwrapObservable(fValueAccessor())) - { - $(oElement).click(); - } - } -}; - -ko.bindingHandlers.modal = { - 'init': function (oElement, fValueAccessor) { - - $(oElement).toggleClass('fade', !Globals.bMobileDevice).modal({ - 'keyboard': false, - 'show': ko.utils.unwrapObservable(fValueAccessor()) - }) - .on('shown', function () { - Utils.windowResize(); - }) - .find('.close').click(function () { - fValueAccessor()(false); - }); - }, - 'update': function (oElement, fValueAccessor) { - $(oElement).modal(ko.utils.unwrapObservable(fValueAccessor()) ? 'show' : 'hide'); - } -}; - -ko.bindingHandlers.i18nInit = { - 'init': function (oElement) { - Utils.i18nToNode(oElement); - } -}; - -ko.bindingHandlers.i18nUpdate = { - 'update': function (oElement, fValueAccessor) { - ko.utils.unwrapObservable(fValueAccessor()); - Utils.i18nToNode(oElement); - } -}; - -ko.bindingHandlers.link = { - 'update': function (oElement, fValueAccessor) { - $(oElement).attr('href', ko.utils.unwrapObservable(fValueAccessor())); - } -}; - -ko.bindingHandlers.title = { - 'update': function (oElement, fValueAccessor) { - $(oElement).attr('title', ko.utils.unwrapObservable(fValueAccessor())); - } -}; - -ko.bindingHandlers.textF = { - 'init': function (oElement, fValueAccessor) { - $(oElement).text(ko.utils.unwrapObservable(fValueAccessor())); - } -}; - -ko.bindingHandlers.initDom = { - 'init': function (oElement, fValueAccessor) { - fValueAccessor()(oElement); - } -}; - -ko.bindingHandlers.initResizeTrigger = { - 'init': function (oElement, fValueAccessor) { - var aValues = ko.utils.unwrapObservable(fValueAccessor()); - $(oElement).css({ - 'height': aValues[1], - 'min-height': aValues[1] - }); - }, - 'update': function (oElement, fValueAccessor) { - var - aValues = ko.utils.unwrapObservable(fValueAccessor()), - iValue = Utils.pInt(aValues[1]), - iSize = 0, - iOffset = $(oElement).offset().top - ; - - if (0 < iOffset) - { - iOffset += Utils.pInt(aValues[2]); - iSize = $window.height() - iOffset; - - if (iValue < iSize) - { - iValue = iSize; - } - - $(oElement).css({ - 'height': iValue, - 'min-height': iValue - }); - } - } -}; - -ko.bindingHandlers.appendDom = { - 'update': function (oElement, fValueAccessor) { - $(oElement).hide().empty().append(ko.utils.unwrapObservable(fValueAccessor())).show(); - } -}; - -ko.bindingHandlers.draggable = { - 'init': function (oElement, fValueAccessor, fAllBindingsAccessor) { - - if (!Globals.bMobileDevice) - { - var - iTriggerZone = 100, - iScrollSpeed = 3, - fAllValueFunc = fAllBindingsAccessor(), - sDroppableSelector = fAllValueFunc && fAllValueFunc['droppableSelector'] ? fAllValueFunc['droppableSelector'] : '', - oConf = { - 'distance': 20, - 'handle': '.dragHandle', - 'cursorAt': {'top': 22, 'left': 3}, - 'refreshPositions': true, - 'scroll': true - } - ; - - if (sDroppableSelector) - { - oConf['drag'] = function (oEvent) { - - $(sDroppableSelector).each(function () { - var - moveUp = null, - moveDown = null, - $this = $(this), - oOffset = $this.offset(), - bottomPos = oOffset.top + $this.height() - ; - - window.clearInterval($this.data('timerScroll')); - $this.data('timerScroll', false); - - if (oEvent.pageX >= oOffset.left && oEvent.pageX <= oOffset.left + $this.width()) - { - if (oEvent.pageY >= bottomPos - iTriggerZone && oEvent.pageY <= bottomPos) - { - moveUp = function() { - $this.scrollTop($this.scrollTop() + iScrollSpeed); - Utils.windowResize(); - }; - - $this.data('timerScroll', window.setInterval(moveUp, 10)); - moveUp(); - } - - if (oEvent.pageY >= oOffset.top && oEvent.pageY <= oOffset.top + iTriggerZone) - { - moveDown = function() { - $this.scrollTop($this.scrollTop() - iScrollSpeed); - Utils.windowResize(); - }; - - $this.data('timerScroll', window.setInterval(moveDown, 10)); - moveDown(); - } - } - }); - }; - - oConf['stop'] = function() { - $(sDroppableSelector).each(function () { - window.clearInterval($(this).data('timerScroll')); - $(this).data('timerScroll', false); - }); - }; - } - - oConf['helper'] = function (oEvent) { - return fValueAccessor()(oEvent && oEvent.target ? ko.dataFor(oEvent.target) : null); - }; - - $(oElement).draggable(oConf).on('mousedown', function () { - Utils.removeInFocus(); - }); - } - } -}; - -ko.bindingHandlers.droppable = { - 'init': function (oElement, fValueAccessor, fAllBindingsAccessor) { - - if (!Globals.bMobileDevice) - { - var - fValueFunc = fValueAccessor(), - fAllValueFunc = fAllBindingsAccessor(), - fOverCallback = fAllValueFunc && fAllValueFunc['droppableOver'] ? fAllValueFunc['droppableOver'] : null, - fOutCallback = fAllValueFunc && fAllValueFunc['droppableOut'] ? fAllValueFunc['droppableOut'] : null, - oConf = { - 'tolerance': 'pointer', - 'hoverClass': 'droppableHover' - } - ; - - if (fValueFunc) - { - oConf['drop'] = function (oEvent, oUi) { - fValueFunc(oEvent, oUi); - }; - - if (fOverCallback) - { - oConf['over'] = function (oEvent, oUi) { - fOverCallback(oEvent, oUi); - }; - } - - if (fOutCallback) - { - oConf['out'] = function (oEvent, oUi) { - fOutCallback(oEvent, oUi); - }; - } - - $(oElement).droppable(oConf); - } - } - } -}; - -ko.bindingHandlers.nano = { - 'init': function (oElement) { - if (!Globals.bDisableNanoScroll) - { - $(oElement) - .addClass('nano') - .nanoScroller({ - 'iOSNativeScrolling': false, - 'preventPageScrolling': true - }) - ; - } - } -}; - -ko.bindingHandlers.saveTrigger = { - 'init': function (oElement) { - - var $oEl = $(oElement); - - $oEl.data('save-trigger-type', $oEl.is('input[type=text],input[type=email],input[type=password],select,textarea') ? 'input' : 'custom'); - - if ('custom' === $oEl.data('save-trigger-type')) - { - $oEl.append( - ' ' - ).addClass('settings-saved-trigger'); - } - else - { - $oEl.addClass('settings-saved-trigger-input'); - } - }, - 'update': function (oElement, fValueAccessor) { - var - mValue = ko.utils.unwrapObservable(fValueAccessor()), - $oEl = $(oElement) - ; - - if ('custom' === $oEl.data('save-trigger-type')) - { - switch (mValue.toString()) - { - case '1': - $oEl - .find('.animated,.error').hide().removeClass('visible') - .end() - .find('.success').show().addClass('visible') - ; - break; - case '0': - $oEl - .find('.animated,.success').hide().removeClass('visible') - .end() - .find('.error').show().addClass('visible') - ; - break; - case '-2': - $oEl - .find('.error,.success').hide().removeClass('visible') - .end() - .find('.animated').show().addClass('visible') - ; - break; - default: - $oEl - .find('.animated').hide() - .end() - .find('.error,.success').removeClass('visible') - ; - break; - } - } - else - { - switch (mValue.toString()) - { - case '1': - $oEl.addClass('success').removeClass('error'); - break; - case '0': - $oEl.addClass('error').removeClass('success'); - break; - case '-2': -// $oEl; - break; - default: - $oEl.removeClass('error success'); - break; - } - } - } -}; - -ko.bindingHandlers.emailsTags = { - 'init': function(oElement, fValueAccessor) { - var - $oEl = $(oElement), - fValue = fValueAccessor() - ; - - $oEl.inputosaurus({ - 'parseOnBlur': true, - 'inputDelimiters': [',', ';'], - 'autoCompleteSource': function (oData, fResponse) { - RL.getAutocomplete(oData.term, function (aData) { - fResponse(_.map(aData, function (oEmailItem) { - return oEmailItem.toLine(false); - })); - }); - }, - 'parseHook': function (aInput) { - return _.map(aInput, function (sInputValue) { - - var - sValue = Utils.trim(sInputValue), - oEmail = null - ; - - if ('' !== sValue) - { - oEmail = new EmailModel(); - oEmail.mailsoParse(sValue); - oEmail.clearDuplicateName(); - return [oEmail.toLine(false), oEmail]; - } - - return [sValue, null]; - - }); - }, - 'change': _.bind(function (oEvent) { - $oEl.data('EmailsTagsValue', oEvent.target.value); - fValue(oEvent.target.value); - }, this) - }); - - fValue.subscribe(function (sValue) { - if ($oEl.data('EmailsTagsValue') !== sValue) - { - $oEl.val(sValue); - $oEl.data('EmailsTagsValue', sValue); - $oEl.inputosaurus('refresh'); - } - }); - - if (fValue.focusTrigger) - { - fValue.focusTrigger.subscribe(function () { - $oEl.inputosaurus('focus'); - }); - } - } -}; - -ko.bindingHandlers.command = { - 'init': function (oElement, fValueAccessor, fAllBindingsAccessor, oViewModel) { - var - jqElement = $(oElement), - oCommand = fValueAccessor() - ; - - if (!oCommand || !oCommand.enabled || !oCommand.canExecute) - { - throw new Error('You are not using command function'); - } - - jqElement.addClass('command'); - ko.bindingHandlers[jqElement.is('form') ? 'submit' : 'click'].init.apply(oViewModel, arguments); - }, - - 'update': function (oElement, fValueAccessor) { - - var - bResult = true, - jqElement = $(oElement), - oCommand = fValueAccessor() - ; - - bResult = oCommand.enabled(); - jqElement.toggleClass('command-not-enabled', !bResult); - - if (bResult) - { - bResult = oCommand.canExecute(); - jqElement.toggleClass('command-can-not-be-execute', !bResult); - } - - jqElement.toggleClass('command-disabled disable disabled', !bResult).toggleClass('no-disabled', !!bResult); - - if (jqElement.is('input') || jqElement.is('button')) - { - jqElement.prop('disabled', !bResult); - } - } -}; - -ko.extenders.trimmer = function (oTarget) -{ - var oResult = ko.computed({ - 'read': oTarget, - 'write': function (sNewValue) { - oTarget(Utils.trim(sNewValue.toString())); - }, - 'owner': this - }); - - oResult(oTarget()); - return oResult; -}; - -ko.extenders.reversible = function (oTarget) -{ - var mValue = oTarget(); - - oTarget.commit = function () - { - mValue = oTarget(); - }; - - oTarget.reverse = function () - { - oTarget(mValue); - }; - - oTarget.commitedValue = function () - { - return mValue; - }; - - return oTarget; -}; - -ko.extenders.toggleSubscribe = function (oTarget, oOptions) -{ - oTarget.subscribe(oOptions[1], oOptions[0], 'beforeChange'); - oTarget.subscribe(oOptions[2], oOptions[0]); - - return oTarget; -}; - -ko.extenders.falseTimeout = function (oTarget, iOption) -{ - oTarget.iTimeout = 0; - oTarget.subscribe(function (bValue) { - if (bValue) - { - window.clearTimeout(oTarget.iTimeout); - oTarget.iTimeout = window.setTimeout(function () { - oTarget(false); - oTarget.iTimeout = 0; - }, Utils.pInt(iOption)); - } - }); - - return oTarget; -}; - -ko.observable.fn.validateNone = function () -{ - this.hasError = ko.observable(false); - return this; -}; - -ko.observable.fn.validateEmail = function () -{ - this.hasError = ko.observable(false); - - this.subscribe(function (sValue) { - sValue = Utils.trim(sValue); - this.hasError('' !== sValue && !(/^[^@\s]+@[^@\s]+$/.test(sValue))); - }, this); - - this.valueHasMutated(); - return this; -}; - -ko.observable.fn.validateSimpleEmail = function () -{ - this.hasError = ko.observable(false); - - this.subscribe(function (sValue) { - sValue = Utils.trim(sValue); - this.hasError('' !== sValue && !(/^.+@.+$/.test(sValue))); - }, this); - - this.valueHasMutated(); - return this; -}; - -ko.observable.fn.validateFunc = function (fFunc) -{ - this.hasFuncError = ko.observable(false); - - if (Utils.isFunc(fFunc)) - { - this.subscribe(function (sValue) { - this.hasFuncError(!fFunc(sValue)); - }, this); - - this.valueHasMutated(); - } - - return this; -}; - +ko.bindingHandlers.tooltip = { + 'init': function (oElement, fValueAccessor) { + if (!Globals.bMobileDevice) + { + var + $oEl = $(oElement), + sClass = $oEl.data('tooltip-class') || '', + sPlacement = $oEl.data('tooltip-placement') || 'top' + ; -/** - * @constructor - */ -function LinkBuilder() -{ - this.sBase = '#/'; - this.sVersion = RL.settingsGet('Version'); - this.sSpecSuffix = RL.settingsGet('AuthAccountHash') || '0'; - this.sServer = (RL.settingsGet('IndexFile') || './') + '?'; -} - -/** - * @return {string} - */ -LinkBuilder.prototype.root = function () -{ - return this.sBase; -}; - -/** - * @param {string} sDownload - * @return {string} - */ -LinkBuilder.prototype.attachmentDownload = function (sDownload) -{ - return this.sServer + '/Raw/' + this.sSpecSuffix + '/Download/' + sDownload; -}; - -/** - * @param {string} sDownload - * @return {string} - */ -LinkBuilder.prototype.attachmentPreview = function (sDownload) -{ - return this.sServer + '/Raw/' + this.sSpecSuffix + '/View/' + sDownload; -}; - -/** - * @param {string} sDownload - * @return {string} - */ -LinkBuilder.prototype.attachmentPreviewAsPlain = function (sDownload) -{ - return this.sServer + '/Raw/' + this.sSpecSuffix + '/ViewAsPlain/' + sDownload; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.upload = function () -{ - return this.sServer + '/Upload/' + this.sSpecSuffix + '/'; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.uploadContacts = function () -{ - return this.sServer + '/UploadContacts/' + this.sSpecSuffix + '/'; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.uploadBackground = function () -{ - return this.sServer + '/UploadBackground/' + this.sSpecSuffix + '/'; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.append = function () -{ - return this.sServer + '/Append/' + this.sSpecSuffix + '/'; -}; - -/** - * @param {string} sEmail - * @return {string} - */ -LinkBuilder.prototype.change = function (sEmail) -{ - return this.sServer + '/Change/' + this.sSpecSuffix + '/' + window.encodeURIComponent(sEmail) + '/'; -}; - -/** - * @param {string=} sAdd - * @return {string} - */ -LinkBuilder.prototype.ajax = function (sAdd) -{ - return this.sServer + '/Ajax/' + this.sSpecSuffix + '/' + sAdd; -}; - -/** - * @param {string} sRequestHash - * @return {string} - */ -LinkBuilder.prototype.messageViewLink = function (sRequestHash) -{ - return this.sServer + '/Raw/' + this.sSpecSuffix + '/ViewAsPlain/' + sRequestHash; -}; - -/** - * @param {string} sRequestHash - * @return {string} - */ -LinkBuilder.prototype.messageDownloadLink = function (sRequestHash) -{ - return this.sServer + '/Raw/' + this.sSpecSuffix + '/Download/' + sRequestHash; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.inbox = function () -{ - return this.sBase + 'mailbox/Inbox'; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.messagePreview = function () -{ - return this.sBase + 'mailbox/message-preview'; -}; - -/** - * @param {string=} sScreenName - * @return {string} - */ -LinkBuilder.prototype.settings = function (sScreenName) -{ - var sResult = this.sBase + 'settings'; - if (!Utils.isUnd(sScreenName) && '' !== sScreenName) - { - sResult += '/' + sScreenName; - } - - return sResult; -}; - -/** - * @param {string} sScreenName - * @return {string} - */ -LinkBuilder.prototype.admin = function (sScreenName) -{ - var sResult = this.sBase; - switch (sScreenName) { - case 'AdminDomains': - sResult += 'domains'; - break; - case 'AdminSecurity': - sResult += 'security'; - break; - case 'AdminLicensing': - sResult += 'licensing'; - break; - } - - return sResult; -}; - -/** - * @param {string} sFolder - * @param {number=} iPage = 1 - * @param {string=} sSearch = '' - * @return {string} - */ -LinkBuilder.prototype.mailBox = function (sFolder, iPage, sSearch) -{ - iPage = Utils.isNormal(iPage) ? Utils.pInt(iPage) : 1; - sSearch = Utils.pString(sSearch); - - var sResult = this.sBase + 'mailbox/'; - if ('' !== sFolder) - { - sResult += encodeURI(sFolder); - } - if (1 < iPage) - { - sResult = sResult.replace(/[\/]+$/, ''); - sResult += '/p' + iPage; - } - if ('' !== sSearch) - { - sResult = sResult.replace(/[\/]+$/, ''); - sResult += '/' + encodeURI(sSearch); - } - - return sResult; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.phpInfo = function () -{ - return this.sServer + 'Info'; -}; - -/** - * @param {string} sLang - * @return {string} - */ -LinkBuilder.prototype.langLink = function (sLang) -{ - return this.sServer + '/Lang/0/' + encodeURI(sLang) + '/' + this.sVersion + '/'; -}; - -/** - * @param {string} sHash - * @return {string} - */ -LinkBuilder.prototype.getUserPicUrlFromHash = function (sHash) -{ - return this.sServer + '/Raw/' + this.sSpecSuffix + '/UserPic/' + sHash + '/' + this.sVersion + '/'; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.exportContactsVcf = function () -{ - return this.sServer + '/Raw/' + this.sSpecSuffix + '/ContactsVcf/'; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.exportContactsCsv = function () -{ - return this.sServer + '/Raw/' + this.sSpecSuffix + '/ContactsCsv/'; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.emptyContactPic = function () -{ - return 'rainloop/v/' + this.sVersion + '/static/css/images/empty-contact.png'; -}; - -/** - * @param {string} sFileName - * @return {string} - */ -LinkBuilder.prototype.sound = function (sFileName) -{ - return 'rainloop/v/' + this.sVersion + '/static/sounds/' + sFileName; -}; - -/** - * @param {string} sTheme - * @return {string} - */ -LinkBuilder.prototype.themePreviewLink = function (sTheme) -{ - var sPrefix = 'rainloop/v/' + this.sVersion + '/'; - if ('@custom' === sTheme.substr(-7)) - { - sTheme = Utils.trim(sTheme.substring(0, sTheme.length - 7)); - sPrefix = ''; - } - - return sPrefix + 'themes/' + encodeURI(sTheme) + '/images/preview.png'; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.notificationMailIcon = function () -{ - return 'rainloop/v/' + this.sVersion + '/static/css/images/icom-message-notification.png'; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.openPgpJs = function () -{ - return 'rainloop/v/' + this.sVersion + '/static/js/openpgp.min.js'; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.socialGoogle = function () -{ - return this.sServer + 'SocialGoogle' + ('' !== this.sSpecSuffix ? '/' + this.sSpecSuffix + '/' : ''); -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.socialTwitter = function () -{ - return this.sServer + 'SocialTwitter' + ('' !== this.sSpecSuffix ? '/' + this.sSpecSuffix + '/' : ''); -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.socialFacebook = function () -{ - return this.sServer + 'SocialFacebook' + ('' !== this.sSpecSuffix ? '/' + this.sSpecSuffix + '/' : ''); -}; + $oEl.tooltip({ + 'delay': { + 'show': 500, + 'hide': 100 + }, + 'html': true, + 'container': 'body', + 'placement': sPlacement, + 'trigger': 'hover', + 'title': function () { + return $oEl.is('.disabled') || Globals.dropdownVisibility() ? '' : '' + + Utils.i18n(ko.utils.unwrapObservable(fValueAccessor())) + ''; + } + }).click(function () { + $oEl.tooltip('hide'); + }); -/** - * @type {Object} - */ -Plugins.oViewModelsHooks = {}; - -/** - * @type {Object} - */ -Plugins.oSimpleHooks = {}; - -/** - * @param {string} sName - * @param {Function} ViewModel - */ -Plugins.regViewModelHook = function (sName, ViewModel) -{ - if (ViewModel) - { - ViewModel.__hookName = sName; - } -}; - -/** - * @param {string} sName - * @param {Function} fCallback - */ -Plugins.addHook = function (sName, fCallback) -{ - if (Utils.isFunc(fCallback)) - { - if (!Utils.isArray(Plugins.oSimpleHooks[sName])) - { - Plugins.oSimpleHooks[sName] = []; - } - - Plugins.oSimpleHooks[sName].push(fCallback); - } -}; - -/** - * @param {string} sName - * @param {Array=} aArguments - */ -Plugins.runHook = function (sName, aArguments) -{ - if (Utils.isArray(Plugins.oSimpleHooks[sName])) - { - aArguments = aArguments || []; - - _.each(Plugins.oSimpleHooks[sName], function (fCallback) { - fCallback.apply(null, aArguments); - }); - } -}; - -/** - * @param {string} sName - * @return {?} - */ -Plugins.mainSettingsGet = function (sName) -{ - return RL ? RL.settingsGet(sName) : null; -}; - -/** - * @param {Function} fCallback - * @param {string} sAction - * @param {Object=} oParameters - * @param {?number=} iTimeout - * @param {string=} sGetAdd = '' - * @param {Array=} aAbortActions = [] - */ -Plugins.remoteRequest = function (fCallback, sAction, oParameters, iTimeout, sGetAdd, aAbortActions) -{ - if (RL) - { - RL.remote().defaultRequest(fCallback, sAction, oParameters, iTimeout, sGetAdd, aAbortActions); - } -}; - -/** - * @param {string} sPluginSection - * @param {string} sName - * @return {?} - */ -Plugins.settingsGet = function (sPluginSection, sName) -{ - var oPlugin = Plugins.mainSettingsGet('Plugins'); - oPlugin = oPlugin && Utils.isUnd(oPlugin[sPluginSection]) ? null : oPlugin[sPluginSection]; - return oPlugin ? (Utils.isUnd(oPlugin[sName]) ? null : oPlugin[sName]) : null; -}; - - - -/** - * @constructor - */ -function CookieDriver() -{ - -} - -CookieDriver.supported = function () -{ - return true; -}; - -/** - * @param {string} sKey - * @param {*} mData - * @returns {boolean} - */ -CookieDriver.prototype.set = function (sKey, mData) -{ - var - mCokieValue = $.cookie(Consts.Values.ClientSideCookieIndexName), - bResult = false, - mResult = null - ; - - try - { - mResult = null === mCokieValue ? null : JSON.parse(mCokieValue); - if (!mResult) - { - mResult = {}; - } - - mResult[sKey] = mData; - $.cookie(Consts.Values.ClientSideCookieIndexName, JSON.stringify(mResult), { - 'expires': 30 - }); - - bResult = true; - } - catch (oException) {} - - return bResult; -}; - -/** - * @param {string} sKey - * @returns {*} - */ -CookieDriver.prototype.get = function (sKey) -{ - var - mCokieValue = $.cookie(Consts.Values.ClientSideCookieIndexName), - mResult = null - ; - - try - { - mResult = null === mCokieValue ? null : JSON.parse(mCokieValue); - if (mResult && !Utils.isUnd(mResult[sKey])) - { - mResult = mResult[sKey]; - } - else - { - mResult = null; - } - } - catch (oException) {} - - return mResult; -}; - -/** - * @constructor - */ -function LocalStorageDriver() -{ -} - -LocalStorageDriver.supported = function () -{ - return !!window.localStorage; -}; - -/** - * @param {string} sKey - * @param {*} mData - * @returns {boolean} - */ -LocalStorageDriver.prototype.set = function (sKey, mData) -{ - var - mCookieValue = window.localStorage[Consts.Values.ClientSideCookieIndexName] || null, - bResult = false, - mResult = null - ; - - try - { - mResult = null === mCookieValue ? null : JSON.parse(mCookieValue); - if (!mResult) - { - mResult = {}; - } - - mResult[sKey] = mData; - window.localStorage[Consts.Values.ClientSideCookieIndexName] = JSON.stringify(mResult); - - bResult = true; - } - catch (oException) {} - - return bResult; -}; - -/** - * @param {string} sKey - * @returns {*} - */ -LocalStorageDriver.prototype.get = function (sKey) -{ - var - mCokieValue = window.localStorage[Consts.Values.ClientSideCookieIndexName] || null, - mResult = null - ; - - try - { - mResult = null === mCokieValue ? null : JSON.parse(mCokieValue); - if (mResult && !Utils.isUnd(mResult[sKey])) - { - mResult = mResult[sKey]; - } - else - { - mResult = null; - } - } - catch (oException) {} - - return mResult; -}; - -/** - * @constructor - */ -function LocalStorage() -{ - var - sStorages = [ - LocalStorageDriver, - CookieDriver - ], - NextStorageDriver = _.find(sStorages, function (NextStorageDriver) { - return NextStorageDriver.supported(); - }) - ; - - if (NextStorageDriver) - { - NextStorageDriver = /** @type {?Function} */ NextStorageDriver; - this.oDriver = new NextStorageDriver(); - } -} - -LocalStorage.prototype.oDriver = null; - -/** - * @param {number} iKey - * @param {*} mData - * @return {boolean} - */ -LocalStorage.prototype.set = function (iKey, mData) -{ - return this.oDriver ? this.oDriver.set('p' + iKey, mData) : false; -}; - -/** - * @param {number} iKey - * @return {*} - */ -LocalStorage.prototype.get = function (iKey) -{ - return this.oDriver ? this.oDriver.get('p' + iKey) : null; -}; - -/** - * @constructor - */ -function KnoinAbstractBoot() -{ - -} - -KnoinAbstractBoot.prototype.bootstart = function () -{ - -}; - -/** - * @param {string=} sPosition = '' - * @param {string=} sTemplate = '' - * @constructor - */ -function KnoinAbstractViewModel(sPosition, sTemplate) -{ - this.bDisabeCloseOnEsc = false; - this.sPosition = Utils.pString(sPosition); - this.sTemplate = Utils.pString(sTemplate); - - this.sDefaultKeyScope = Enums.KeyState.None; - this.sCurrentKeyScope = this.sDefaultKeyScope; - - this.viewModelName = ''; - this.viewModelVisibility = ko.observable(false); - this.modalVisibility = ko.observable(false).extend({'rateLimit': 0}); - - this.viewModelDom = null; -} - -/** - * @type {string} - */ -KnoinAbstractViewModel.prototype.sPosition = ''; - -/** - * @type {string} - */ -KnoinAbstractViewModel.prototype.sTemplate = ''; - -/** - * @type {string} - */ -KnoinAbstractViewModel.prototype.viewModelName = ''; - -/** - * @type {?} - */ -KnoinAbstractViewModel.prototype.viewModelDom = null; - -/** - * @return {string} - */ -KnoinAbstractViewModel.prototype.viewModelTemplate = function () -{ - return this.sTemplate; -}; - -/** - * @return {string} - */ -KnoinAbstractViewModel.prototype.viewModelPosition = function () -{ - return this.sPosition; -}; - -KnoinAbstractViewModel.prototype.cancelCommand = KnoinAbstractViewModel.prototype.closeCommand = function () -{ -}; - -KnoinAbstractViewModel.prototype.storeAndSetKeyScope = function () -{ - this.sCurrentKeyScope = RL.data().keyScope(); - RL.data().keyScope(this.sDefaultKeyScope); -}; - -KnoinAbstractViewModel.prototype.restoreKeyScope = function () -{ - RL.data().keyScope(this.sCurrentKeyScope); -}; - -KnoinAbstractViewModel.prototype.registerPopupEscapeKey = function () -{ - var self = this; - $window.on('keydown', function (oEvent) { - if (oEvent && Enums.EventKeyCode.Esc === oEvent.keyCode && self.modalVisibility && self.modalVisibility()) - { - Utils.delegateRun(self, 'cancelCommand'); - return false; - } - - return true; - }); -}; - -/** - * @param {string} sScreenName - * @param {?=} aViewModels = [] - * @constructor - */ -function KnoinAbstractScreen(sScreenName, aViewModels) -{ - this.sScreenName = sScreenName; - this.aViewModels = Utils.isArray(aViewModels) ? aViewModels : []; -} - -/** - * @type {Array} - */ -KnoinAbstractScreen.prototype.oCross = null; - -/** - * @type {string} - */ -KnoinAbstractScreen.prototype.sScreenName = ''; - -/** - * @type {Array} - */ -KnoinAbstractScreen.prototype.aViewModels = []; - -/** - * @return {Array} - */ -KnoinAbstractScreen.prototype.viewModels = function () -{ - return this.aViewModels; -}; - -/** - * @return {string} - */ -KnoinAbstractScreen.prototype.screenName = function () -{ - return this.sScreenName; -}; - -KnoinAbstractScreen.prototype.routes = function () -{ - return null; -}; - -/** - * @return {?Object} - */ -KnoinAbstractScreen.prototype.__cross = function () -{ - return this.oCross; -}; - -KnoinAbstractScreen.prototype.__start = function () -{ - var - aRoutes = this.routes(), - oRoute = null, - fMatcher = null - ; - - if (Utils.isNonEmptyArray(aRoutes)) - { - fMatcher = _.bind(this.onRoute || Utils.emptyFunction, this); - oRoute = crossroads.create(); - - _.each(aRoutes, function (aItem) { - oRoute.addRoute(aItem[0], fMatcher).rules = aItem[1]; - }); - - this.oCross = oRoute; - } -}; - -/** - * @constructor - */ -function Knoin() -{ - this.sDefaultScreenName = ''; - this.oScreens = {}; - this.oBoot = null; - this.oCurrentScreen = null; -} - -/** - * @param {Object} thisObject - */ -Knoin.constructorEnd = function (thisObject) -{ - if (Utils.isFunc(thisObject['__constructor_end'])) - { - thisObject['__constructor_end'].call(thisObject); - } -}; - -Knoin.prototype.sDefaultScreenName = ''; -Knoin.prototype.oScreens = {}; -Knoin.prototype.oBoot = null; -Knoin.prototype.oCurrentScreen = null; - -Knoin.prototype.hideLoading = function () -{ - $('#rl-loading').hide(); -}; - -Knoin.prototype.routeOff = function () -{ - hasher.changed.active = false; -}; - -Knoin.prototype.routeOn = function () -{ - hasher.changed.active = true; -}; - -/** - * @param {Object} oBoot - * @return {Knoin} - */ -Knoin.prototype.setBoot = function (oBoot) -{ - if (Utils.isNormal(oBoot)) - { - this.oBoot = oBoot; - } - - return this; -}; - -/** - * @param {string} sScreenName - * @return {?Object} - */ -Knoin.prototype.screen = function (sScreenName) -{ - return ('' !== sScreenName && !Utils.isUnd(this.oScreens[sScreenName])) ? this.oScreens[sScreenName] : null; -}; - -/** - * @param {Function} ViewModelClass - * @param {Object=} oScreen - */ -Knoin.prototype.buildViewModel = function (ViewModelClass, oScreen) -{ - if (ViewModelClass && !ViewModelClass.__builded) - { - var - oViewModel = new ViewModelClass(oScreen), - sPosition = oViewModel.viewModelPosition(), - oViewModelPlace = $('#rl-content #rl-' + sPosition.toLowerCase()), - oViewModelDom = null - ; - - ViewModelClass.__builded = true; - ViewModelClass.__vm = oViewModel; - oViewModel.data = RL.data(); - - oViewModel.viewModelName = ViewModelClass.__name; - - if (oViewModelPlace && 1 === oViewModelPlace.length) - { - oViewModelDom = $('').addClass('rl-view-model').addClass('RL-' + oViewModel.viewModelTemplate()).hide().attr('data-bind', - 'template: {name: "' + oViewModel.viewModelTemplate() + '"}, i18nInit: true'); - - oViewModelDom.appendTo(oViewModelPlace); - oViewModel.viewModelDom = oViewModelDom; - ViewModelClass.__dom = oViewModelDom; - - if ('Popups' === sPosition) - { - oViewModel.cancelCommand = oViewModel.closeCommand = Utils.createCommand(oViewModel, function () { - kn.hideScreenPopup(ViewModelClass); - }); - - oViewModel.modalVisibility.subscribe(function (bValue) { - - var self = this; - if (bValue) - { - this.viewModelDom.show(); - this.storeAndSetKeyScope(); - - RL.popupVisibilityNames.push(this.viewModelName); - oViewModel.viewModelDom.css('z-index', 3000 + RL.popupVisibilityNames().length + 10); - - Utils.delegateRun(this, 'onFocus', [], 500); - } - else - { - Utils.delegateRun(this, 'onHide'); - this.restoreKeyScope(); - - RL.popupVisibilityNames.remove(this.viewModelName); - oViewModel.viewModelDom.css('z-index', 2000); - - _.delay(function () { - self.viewModelDom.hide(); - }, 300); - } - - }, oViewModel); - } - - Plugins.runHook('view-model-pre-build', [ViewModelClass.__name, oViewModel, oViewModelDom]); - - ko.applyBindings(oViewModel, oViewModelDom[0]); - Utils.delegateRun(oViewModel, 'onBuild', [oViewModelDom]); - if (oViewModel && 'Popups' === sPosition && !oViewModel.bDisabeCloseOnEsc) - { - oViewModel.registerPopupEscapeKey(); - } - - Plugins.runHook('view-model-post-build', [ViewModelClass.__name, oViewModel, oViewModelDom]); - } - else - { - Utils.log('Cannot find view model position: ' + sPosition); - } - } - - return ViewModelClass ? ViewModelClass.__vm : null; -}; - -/** - * @param {Object} oViewModel - * @param {Object} oViewModelDom - */ -Knoin.prototype.applyExternal = function (oViewModel, oViewModelDom) -{ - if (oViewModel && oViewModelDom) - { - ko.applyBindings(oViewModel, oViewModelDom); - } -}; - -/** - * @param {Function} ViewModelClassToHide - */ -Knoin.prototype.hideScreenPopup = function (ViewModelClassToHide) -{ - if (ViewModelClassToHide && ViewModelClassToHide.__vm && ViewModelClassToHide.__dom) - { - ViewModelClassToHide.__vm.modalVisibility(false); - Plugins.runHook('view-model-on-hide', [ViewModelClassToHide.__name, ViewModelClassToHide.__vm]); - } -}; - -/** - * @param {Function} ViewModelClassToShow - * @param {Array=} aParameters - */ -Knoin.prototype.showScreenPopup = function (ViewModelClassToShow, aParameters) -{ - if (ViewModelClassToShow) - { - this.buildViewModel(ViewModelClassToShow); - - if (ViewModelClassToShow.__vm && ViewModelClassToShow.__dom) - { - ViewModelClassToShow.__vm.modalVisibility(true); - Utils.delegateRun(ViewModelClassToShow.__vm, 'onShow', aParameters || []); - Plugins.runHook('view-model-on-show', [ViewModelClassToShow.__name, ViewModelClassToShow.__vm, aParameters || []]); - } - } -}; - -/** - * @param {string} sScreenName - * @param {string} sSubPart - */ -Knoin.prototype.screenOnRoute = function (sScreenName, sSubPart) -{ - var - self = this, - oScreen = null, - oCross = null - ; - - if ('' === Utils.pString(sScreenName)) - { - sScreenName = this.sDefaultScreenName; - } - - if ('' !== sScreenName) - { - oScreen = this.screen(sScreenName); - if (!oScreen) - { - oScreen = this.screen(this.sDefaultScreenName); - if (oScreen) - { - sSubPart = sScreenName + '/' + sSubPart; - sScreenName = this.sDefaultScreenName; - } - } - - if (oScreen && oScreen.__started) - { - if (!oScreen.__builded) - { - oScreen.__builded = true; - - if (Utils.isNonEmptyArray(oScreen.viewModels())) - { - _.each(oScreen.viewModels(), function (ViewModelClass) { - this.buildViewModel(ViewModelClass, oScreen); - }, this); - } - - Utils.delegateRun(oScreen, 'onBuild'); - } - - _.defer(function () { - - // hide screen - if (self.oCurrentScreen) - { - Utils.delegateRun(self.oCurrentScreen, 'onHide'); - - if (Utils.isNonEmptyArray(self.oCurrentScreen.viewModels())) - { - _.each(self.oCurrentScreen.viewModels(), function (ViewModelClass) { - - if (ViewModelClass.__vm && ViewModelClass.__dom && - 'Popups' !== ViewModelClass.__vm.viewModelPosition()) - { - ViewModelClass.__dom.hide(); - ViewModelClass.__vm.viewModelVisibility(false); - Utils.delegateRun(ViewModelClass.__vm, 'onHide'); - } - - }); - } - } - // -- - - self.oCurrentScreen = oScreen; - - // show screen - if (self.oCurrentScreen) - { - Utils.delegateRun(self.oCurrentScreen, 'onShow'); - - Plugins.runHook('screen-on-show', [self.oCurrentScreen.screenName(), self.oCurrentScreen]); - - if (Utils.isNonEmptyArray(self.oCurrentScreen.viewModels())) - { - _.each(self.oCurrentScreen.viewModels(), function (ViewModelClass) { - - if (ViewModelClass.__vm && ViewModelClass.__dom && - 'Popups' !== ViewModelClass.__vm.viewModelPosition()) - { - ViewModelClass.__dom.show(); - ViewModelClass.__vm.viewModelVisibility(true); - Utils.delegateRun(ViewModelClass.__vm, 'onShow'); - Utils.delegateRun(ViewModelClass.__vm, 'onFocus', [], 200); - - Plugins.runHook('view-model-on-show', [ViewModelClass.__name, ViewModelClass.__vm]); - } - - }, self); - } - } - // -- - - oCross = oScreen.__cross(); - if (oCross) - { - oCross.parse(sSubPart); - } - }); - } - } -}; - -/** - * @param {Array} aScreensClasses - */ -Knoin.prototype.startScreens = function (aScreensClasses) -{ - $('#rl-content').css({ - 'visibility': 'hidden' - }); - - _.each(aScreensClasses, function (CScreen) { - - var - oScreen = new CScreen(), - sScreenName = oScreen ? oScreen.screenName() : '' - ; - - if (oScreen && '' !== sScreenName) - { - if ('' === this.sDefaultScreenName) - { - this.sDefaultScreenName = sScreenName; - } - - this.oScreens[sScreenName] = oScreen; - } - - }, this); - - - _.each(this.oScreens, function (oScreen) { - if (oScreen && !oScreen.__started && oScreen.__start) - { - oScreen.__started = true; - oScreen.__start(); - - Plugins.runHook('screen-pre-start', [oScreen.screenName(), oScreen]); - Utils.delegateRun(oScreen, 'onStart'); - Plugins.runHook('screen-post-start', [oScreen.screenName(), oScreen]); - } - }, this); - - var oCross = crossroads.create(); - oCross.addRoute(/^([a-zA-Z0-9\-]*)\/?(.*)$/, _.bind(this.screenOnRoute, this)); - - hasher.initialized.add(oCross.parse, oCross); - hasher.changed.add(oCross.parse, oCross); - hasher.init(); - - $('#rl-content').css({ - 'visibility': 'visible' - }); - - _.delay(function () { - $html.removeClass('rl-started-trigger').addClass('rl-started'); - }, 50); -}; - -/** - * @param {string} sHash - * @param {boolean=} bSilence = false - * @param {boolean=} bReplace = false - */ -Knoin.prototype.setHash = function (sHash, bSilence, bReplace) -{ - sHash = '#' === sHash.substr(0, 1) ? sHash.substr(1) : sHash; - sHash = '/' === sHash.substr(0, 1) ? sHash.substr(1) : sHash; - - bReplace = Utils.isUnd(bReplace) ? false : !!bReplace; - - if (Utils.isUnd(bSilence) ? false : !!bSilence) - { - hasher.changed.active = false; - hasher[bReplace ? 'replaceHash' : 'setHash'](sHash); - hasher.changed.active = true; - } - else - { - hasher.changed.active = true; - hasher[bReplace ? 'replaceHash' : 'setHash'](sHash); - hasher.setHash(sHash); - } -}; - -/** - * @return {Knoin} - */ -Knoin.prototype.bootstart = function () -{ - if (this.oBoot && this.oBoot.bootstart) - { - this.oBoot.bootstart(); - } - - return this; -}; - -kn = new Knoin(); - -/** - * @param {string=} sEmail - * @param {string=} sName - * - * @constructor - */ -function EmailModel(sEmail, sName) -{ - this.email = sEmail || ''; - this.name = sName || ''; - this.privateType = null; - - this.clearDuplicateName(); -} - -/** - * @static - * @param {AjaxJsonEmail} oJsonEmail - * @return {?EmailModel} - */ -EmailModel.newInstanceFromJson = function (oJsonEmail) -{ - var oEmailModel = new EmailModel(); - return oEmailModel.initByJson(oJsonEmail) ? oEmailModel : null; -}; - -/** - * @type {string} - */ -EmailModel.prototype.name = ''; - -/** - * @type {string} - */ -EmailModel.prototype.email = ''; - -/** - * @type {(number|null)} - */ -EmailModel.prototype.privateType = null; - -EmailModel.prototype.clear = function () -{ - this.email = ''; - this.name = ''; - this.privateType = null; -}; - -/** - * @returns {boolean} - */ -EmailModel.prototype.validate = function () -{ - return '' !== this.name || '' !== this.email; -}; - -/** - * @param {boolean} bWithoutName = false - * @return {string} - */ -EmailModel.prototype.hash = function (bWithoutName) -{ - return '#' + (bWithoutName ? '' : this.name) + '#' + this.email + '#'; -}; - -EmailModel.prototype.clearDuplicateName = function () -{ - if (this.name === this.email) - { - this.name = ''; - } -}; - -/** - * @return {number} - */ -EmailModel.prototype.type = function () -{ - if (null === this.privateType) - { - if (this.email && '@facebook.com' === this.email.substr(-13)) - { - this.privateType = Enums.EmailType.Facebook; - } - - if (null === this.privateType) - { - this.privateType = Enums.EmailType.Default; - } - } - - return this.privateType; -}; - -/** - * @param {string} sQuery - * @return {boolean} - */ -EmailModel.prototype.search = function (sQuery) -{ - return -1 < (this.name + ' ' + this.email).toLowerCase().indexOf(sQuery.toLowerCase()); -}; - -/** - * @param {string} sString - */ -EmailModel.prototype.parse = function (sString) -{ - this.clear(); - - sString = Utils.trim(sString); - - var - mRegex = /(?:"([^"]+)")? ?(.*?@[^>,]+)>?,? ?/g, - mMatch = mRegex.exec(sString) - ; - - if (mMatch) - { - this.name = mMatch[1] || ''; - this.email = mMatch[2] || ''; - - this.clearDuplicateName(); - } - else if ((/^[^@]+@[^@]+$/).test(sString)) - { - this.name = ''; - this.email = sString; - } -}; - -/** - * @param {AjaxJsonEmail} oJsonEmail - * @return {boolean} - */ -EmailModel.prototype.initByJson = function (oJsonEmail) -{ - var bResult = false; - if (oJsonEmail && 'Object/Email' === oJsonEmail['@Object']) - { - this.name = Utils.trim(oJsonEmail.Name); - this.email = Utils.trim(oJsonEmail.Email); - - bResult = '' !== this.email; - this.clearDuplicateName(); - } - - return bResult; -}; - -/** - * @param {boolean} bFriendlyView - * @param {boolean=} bWrapWithLink = false - * @param {boolean=} bEncodeHtml = false - * @return {string} - */ -EmailModel.prototype.toLine = function (bFriendlyView, bWrapWithLink, bEncodeHtml) -{ - var sResult = ''; - if ('' !== this.email) - { - bWrapWithLink = Utils.isUnd(bWrapWithLink) ? false : !!bWrapWithLink; - bEncodeHtml = Utils.isUnd(bEncodeHtml) ? false : !!bEncodeHtml; - - if (bFriendlyView && '' !== this.name) - { - sResult = bWrapWithLink ? '') + - '" target="_blank" tabindex="-1">' + Utils.encodeHtml(this.name) + '' : - (bEncodeHtml ? Utils.encodeHtml(this.name) : this.name); - } - else - { - sResult = this.email; - if ('' !== this.name) - { - if (bWrapWithLink) - { - sResult = Utils.encodeHtml('"' + this.name + '" <') + - '') + '" target="_blank" tabindex="-1">' + Utils.encodeHtml(sResult) + '' + Utils.encodeHtml('>'); - } - else - { - sResult = '"' + this.name + '" <' + sResult + '>'; - if (bEncodeHtml) - { - sResult = Utils.encodeHtml(sResult); - } - } - } - else if (bWrapWithLink) - { - sResult = '' + Utils.encodeHtml(this.email) + ''; - } - } - } - - return sResult; -}; - -/** - * @param {string} $sEmailAddress - * @return {boolean} - */ -EmailModel.prototype.mailsoParse = function ($sEmailAddress) -{ - $sEmailAddress = Utils.trim($sEmailAddress); - if ('' === $sEmailAddress) - { - return false; - } - - var - substr = function (str, start, len) { - str += ''; - var end = str.length; - - if (start < 0) { - start += end; - } - - end = typeof len === 'undefined' ? end : (len < 0 ? len + end : len + start); - - return start >= str.length || start < 0 || start > end ? false : str.slice(start, end); - }, - - substr_replace = function (str, replace, start, length) { - if (start < 0) { - start = start + str.length; - } - length = length !== undefined ? length : str.length; - if (length < 0) { - length = length + str.length - start; - } - return str.slice(0, start) + replace.substr(0, length) + replace.slice(length) + str.slice(start + length); - }, - - $sName = '', - $sEmail = '', - $sComment = '', - - $bInName = false, - $bInAddress = false, - $bInComment = false, - - $aRegs = null, - - $iStartIndex = 0, - $iEndIndex = 0, - $iCurrentIndex = 0 - ; - - while ($iCurrentIndex < $sEmailAddress.length) - { - switch ($sEmailAddress.substr($iCurrentIndex, 1)) - { - case '"': - if ((!$bInName) && (!$bInAddress) && (!$bInComment)) - { - $bInName = true; - $iStartIndex = $iCurrentIndex; - } - else if ((!$bInAddress) && (!$bInComment)) - { - $iEndIndex = $iCurrentIndex; - $sName = substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1); - $sEmailAddress = substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1); - $iEndIndex = 0; - $iCurrentIndex = 0; - $iStartIndex = 0; - $bInName = false; - } - break; - case '<': - if ((!$bInName) && (!$bInAddress) && (!$bInComment)) - { - if ($iCurrentIndex > 0 && $sName.length === 0) - { - $sName = substr($sEmailAddress, 0, $iCurrentIndex); - } - - $bInAddress = true; - $iStartIndex = $iCurrentIndex; - } - break; - case '>': - if ($bInAddress) - { - $iEndIndex = $iCurrentIndex; - $sEmail = substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1); - $sEmailAddress = substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1); - $iEndIndex = 0; - $iCurrentIndex = 0; - $iStartIndex = 0; - $bInAddress = false; - } - break; - case '(': - if ((!$bInName) && (!$bInAddress) && (!$bInComment)) - { - $bInComment = true; - $iStartIndex = $iCurrentIndex; - } - break; - case ')': - if ($bInComment) - { - $iEndIndex = $iCurrentIndex; - $sComment = substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1); - $sEmailAddress = substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1); - $iEndIndex = 0; - $iCurrentIndex = 0; - $iStartIndex = 0; - $bInComment = false; - } - break; - case '\\': - $iCurrentIndex++; - break; - } - - $iCurrentIndex++; - } - - if ($sEmail.length === 0) - { - $aRegs = $sEmailAddress.match(/[^@\s]+@\S+/i); - if ($aRegs && $aRegs[0]) - { - $sEmail = $aRegs[0]; - } - else - { - $sName = $sEmailAddress; - } - } - - if ($sEmail.length > 0 && $sName.length === 0 && $sComment.length === 0) - { - $sName = $sEmailAddress.replace($sEmail, ''); - } - - $sEmail = Utils.trim($sEmail).replace(/^[<]+/, '').replace(/[>]+$/, ''); - $sName = Utils.trim($sName).replace(/^["']+/, '').replace(/["']+$/, ''); - $sComment = Utils.trim($sComment).replace(/^[(]+/, '').replace(/[)]+$/, ''); - - // Remove backslash - $sName = $sName.replace(/\\\\(.)/, '$1'); - $sComment = $sComment.replace(/\\\\(.)/, '$1'); - - this.name = $sName; - this.email = $sEmail; - - this.clearDuplicateName(); - return true; -}; - -/** - * @return {string} - */ -EmailModel.prototype.inputoTagLine = function () -{ - return 0 < this.name.length ? this.name + ' (' + this.email + ')' : this.email; -}; - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsDomainViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsDomain'); - - this.edit = ko.observable(false); - this.saving = ko.observable(false); - this.savingError = ko.observable(''); - this.whiteListPage = ko.observable(false); - - this.testing = ko.observable(false); - this.testingDone = ko.observable(false); - this.testingImapError = ko.observable(false); - this.testingSmtpError = ko.observable(false); - this.testingImapErrorDesc = ko.observable(''); - this.testingSmtpErrorDesc = ko.observable(''); - - this.testingImapError.subscribe(function (bValue) { - if (!bValue) - { - this.testingImapErrorDesc(''); - } - }, this); - - this.testingSmtpError.subscribe(function (bValue) { - if (!bValue) - { - this.testingSmtpErrorDesc(''); - } - }, this); - - this.testingImapErrorDesc = ko.observable(''); - this.testingSmtpErrorDesc = ko.observable(''); - - this.imapServerFocus = ko.observable(false); - this.smtpServerFocus = ko.observable(false); - - this.name = ko.observable(''); - this.name.focused = ko.observable(false); - - this.imapServer = ko.observable(''); - this.imapPort = ko.observable(Consts.Values.ImapDefaulPort); - this.imapSecure = ko.observable(Enums.ServerSecure.None); - this.imapShortLogin = ko.observable(false); - this.smtpServer = ko.observable(''); - this.smtpPort = ko.observable(Consts.Values.SmtpDefaulPort); - this.smtpSecure = ko.observable(Enums.ServerSecure.None); - this.smtpShortLogin = ko.observable(false); - this.smtpAuth = ko.observable(true); - this.whiteList = ko.observable(''); - - this.headerText = ko.computed(function () { - var sName = this.name(); - return this.edit() ? 'Edit Domain "' + sName + '"' : - 'Add Domain' + ('' === sName ? '' : ' "' + sName + '"'); - }, this); - - this.domainIsComputed = ko.computed(function () { - return '' !== this.name() && - '' !== this.imapServer() && - '' !== this.imapPort() && - '' !== this.smtpServer() && - '' !== this.smtpPort(); - }, this); - - this.canBeTested = ko.computed(function () { - return !this.testing() && this.domainIsComputed(); - }, this); - - this.canBeSaved = ko.computed(function () { - return !this.saving() && this.domainIsComputed(); - }, this); - - this.createOrAddCommand = Utils.createCommand(this, function () { - this.saving(true); - RL.remote().createOrUpdateDomain( - _.bind(this.onDomainCreateOrSaveResponse, this), - !this.edit(), - this.name(), - this.imapServer(), - this.imapPort(), - this.imapSecure(), - this.imapShortLogin(), - this.smtpServer(), - this.smtpPort(), - this.smtpSecure(), - this.smtpShortLogin(), - this.smtpAuth(), - this.whiteList() - ); - }, this.canBeSaved); - - this.testConnectionCommand = Utils.createCommand(this, function () { - this.whiteListPage(false); - this.testingDone(false); - this.testingImapError(false); - this.testingSmtpError(false); - this.testing(true); - RL.remote().testConnectionForDomain( - _.bind(this.onTestConnectionResponse, this), - this.name(), - this.imapServer(), - this.imapPort(), - this.imapSecure(), - this.smtpServer(), - this.smtpPort(), - this.smtpSecure(), - this.smtpAuth() - ); - }, this.canBeTested); - - this.whiteListCommand = Utils.createCommand(this, function () { - this.whiteListPage(!this.whiteListPage()); - }); - - // smart form improvements - this.imapServerFocus.subscribe(function (bValue) { - if (bValue && '' !== this.name() && '' === this.imapServer()) - { - this.imapServer(this.name().replace(/[.]?[*][.]?/g, '')); - } - }, this); - - this.smtpServerFocus.subscribe(function (bValue) { - if (bValue && '' !== this.imapServer() && '' === this.smtpServer()) - { - this.smtpServer(this.imapServer().replace(/imap/ig, 'smtp')); - } - }, this); - - this.imapSecure.subscribe(function (sValue) { - var iPort = Utils.pInt(this.imapPort()); - sValue = Utils.pString(sValue); - switch (sValue) - { - case '0': - if (993 === iPort) - { - this.imapPort(143); - } - break; - case '1': - if (143 === iPort) - { - this.imapPort(993); - } - break; - } - }, this); - - this.smtpSecure.subscribe(function (sValue) { - var iPort = Utils.pInt(this.smtpPort()); - sValue = Utils.pString(sValue); - switch (sValue) - { - case '0': - if (465 === iPort || 587 === iPort) - { - this.smtpPort(25); - } - break; - case '1': - if (25 === iPort || 587 === iPort) - { - this.smtpPort(465); - } - break; - case '2': - if (25 === iPort || 465 === iPort) - { - this.smtpPort(587); - } - break; - } - }, this); - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsDomainViewModel', PopupsDomainViewModel); - -PopupsDomainViewModel.prototype.onTestConnectionResponse = function (sResult, oData) -{ - this.testing(false); - if (Enums.StorageResultType.Success === sResult && oData.Result) - { - this.testingDone(true); - this.testingImapError(true !== oData.Result.Imap); - this.testingSmtpError(true !== oData.Result.Smtp); - - if (this.testingImapError() && oData.Result.Imap) - { - this.testingImapErrorDesc(oData.Result.Imap); - } - - if (this.testingSmtpError() && oData.Result.Smtp) - { - this.testingSmtpErrorDesc(oData.Result.Smtp); - } - } - else - { - this.testingImapError(true); - this.testingSmtpError(true); - } -}; - -PopupsDomainViewModel.prototype.onDomainCreateOrSaveResponse = function (sResult, oData) -{ - this.saving(false); - if (Enums.StorageResultType.Success === sResult && oData) - { - if (oData.Result) - { - RL.reloadDomainList(); - this.closeCommand(); - } - else if (Enums.Notification.DomainAlreadyExists === oData.ErrorCode) - { - this.savingError('Domain already exists'); - } - } - else - { - this.savingError('Unknown error'); - } -}; - -PopupsDomainViewModel.prototype.onHide = function () -{ - this.whiteListPage(false); -}; - -PopupsDomainViewModel.prototype.onShow = function (oDomain) -{ - this.saving(false); - this.whiteListPage(false); - - this.testing(false); - this.testingDone(false); - this.testingImapError(false); - this.testingSmtpError(false); - - this.clearForm(); - if (oDomain) - { - this.edit(true); - - this.name(Utils.trim(oDomain.Name)); - this.imapServer(Utils.trim(oDomain.IncHost)); - this.imapPort(Utils.pInt(oDomain.IncPort)); - this.imapSecure(Utils.trim(oDomain.IncSecure)); - this.imapShortLogin(!!oDomain.IncShortLogin); - this.smtpServer(Utils.trim(oDomain.OutHost)); - this.smtpPort(Utils.pInt(oDomain.OutPort)); - this.smtpSecure(Utils.trim(oDomain.OutSecure)); - this.smtpShortLogin(!!oDomain.OutShortLogin); - this.smtpAuth(!!oDomain.OutAuth); - this.whiteList(Utils.trim(oDomain.WhiteList)); - } -}; - -PopupsDomainViewModel.prototype.onFocus = function () -{ - if ('' === this.name()) - { - this.name.focused(true); - } -}; - -PopupsDomainViewModel.prototype.clearForm = function () -{ - this.edit(false); - this.whiteListPage(false); - - this.savingError(''); - - this.name(''); - this.name.focused(false); - - this.imapServer(''); - this.imapPort(Consts.Values.ImapDefaulPort); - this.imapSecure(Enums.ServerSecure.None); - this.imapShortLogin(false); - this.smtpServer(''); - this.smtpPort(Consts.Values.SmtpDefaulPort); - this.smtpSecure(Enums.ServerSecure.None); - this.smtpShortLogin(false); - this.smtpAuth(true); - this.whiteList(''); -}; - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsPluginViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsPlugin'); - - var self = this; - - this.onPluginSettingsUpdateResponse = _.bind(this.onPluginSettingsUpdateResponse, this); - - this.saveError = ko.observable(''); - - this.name = ko.observable(''); - this.readme = ko.observable(''); - - this.configures = ko.observableArray([]); - - this.hasReadme = ko.computed(function () { - return '' !== this.readme(); - }, this); - - this.hasConfiguration = ko.computed(function () { - return 0 < this.configures().length; - }, this); - - this.readmePopoverConf = { - 'placement': 'top', - 'trigger': 'hover', - 'title': 'About', - 'content': function () { - return self.readme(); - } - }; - - this.saveCommand = Utils.createCommand(this, function () { - - var oList = {}; - - oList['Name'] = this.name(); - - _.each(this.configures(), function (oItem) { - - var mValue = oItem.value(); - if (false === mValue || true === mValue) - { - mValue = mValue ? '1' : '0'; - } - - oList['_' + oItem['Name']] = mValue; - - }, this); - - this.saveError(''); - RL.remote().pluginSettingsUpdate(this.onPluginSettingsUpdateResponse, oList); - - }, this.hasConfiguration); - - this.bDisabeCloseOnEsc = true; - this.sDefaultKeyScope = Enums.KeyState.All; - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsPluginViewModel', PopupsPluginViewModel); - -PopupsPluginViewModel.prototype.onPluginSettingsUpdateResponse = function (sResult, oData) -{ - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - this.cancelCommand(); - } - else - { - this.saveError(''); - if (oData && oData.ErrorCode) - { - this.saveError(Utils.getNotification(oData.ErrorCode)); - } - else - { - this.saveError(Utils.getNotification(Enums.Notification.CantSavePluginSettings)); - } - } -}; - -PopupsPluginViewModel.prototype.onShow = function (oPlugin) -{ - this.name(); - this.readme(); - this.configures([]); - - if (oPlugin) - { - this.name(oPlugin['Name']); - this.readme(oPlugin['Readme']); - - var aConfig = oPlugin['Config']; - if (Utils.isNonEmptyArray(aConfig)) - { - this.configures(_.map(aConfig, function (aItem) { - return { - 'value': ko.observable(aItem[0]), - 'Name': aItem[1], - 'Type': aItem[2], - 'Label': aItem[3], - 'Default': aItem[4], - 'Desc': aItem[5] - }; - })); - } - } -}; - -PopupsPluginViewModel.prototype.tryToClosePopup = function () -{ - var self = this; - kn.showScreenPopup(PopupsAskViewModel, [Utils.i18n('POPUPS_ASK/DESC_WANT_CLOSE_THIS_WINDOW'), function () { - if (self.modalVisibility()) - { - Utils.delegateRun(self, 'cancelCommand'); - } - }]); -}; - -PopupsPluginViewModel.prototype.onBuild = function () -{ - key('esc', Enums.KeyState.All, _.bind(function () { - if (this.modalVisibility()) - { - this.tryToClosePopup(); - return false; - } - }, this)); -}; - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsActivateViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsActivate'); - - var self = this; - - this.domain = ko.observable(''); - this.key = ko.observable(''); - this.key.focus = ko.observable(false); - this.activationSuccessed = ko.observable(false); - - this.licenseTrigger = RL.data().licenseTrigger; - - this.activateProcess = ko.observable(false); - this.activateText = ko.observable(''); - this.activateText.isError = ko.observable(false); - - this.key.subscribe(function () { - this.activateText(''); - this.activateText.isError(false); - }, this); - - this.activationSuccessed.subscribe(function (bValue) { - if (bValue) - { - this.licenseTrigger(!this.licenseTrigger()); - } - }, this); - - this.activateCommand = Utils.createCommand(this, function () { - - this.activateProcess(true); - if (this.validateSubscriptionKey()) - { - RL.remote().licensingActivate(function (sResult, oData) { - - self.activateProcess(false); - if (Enums.StorageResultType.Success === sResult && oData.Result) - { - if (true === oData.Result) - { - self.activationSuccessed(true); - self.activateText('Subscription Key Activated Successfully'); - self.activateText.isError(false); - } - else - { - self.activateText(oData.Result); - self.activateText.isError(true); - self.key.focus(true); - } - } - else if (oData.ErrorCode) - { - self.activateText(Utils.getNotification(oData.ErrorCode)); - self.activateText.isError(true); - self.key.focus(true); - } - else - { - self.activateText(Utils.getNotification(Enums.Notification.UnknownError)); - self.activateText.isError(true); - self.key.focus(true); - } - - }, this.domain(), this.key()); - } - else - { - this.activateProcess(false); - this.activateText('Invalid Subscription Key'); - this.activateText.isError(true); - this.key.focus(true); - } - - }, function () { - return !this.activateProcess() && '' !== this.domain() && '' !== this.key() && !this.activationSuccessed(); - }); - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsActivateViewModel', PopupsActivateViewModel); - -PopupsActivateViewModel.prototype.onShow = function () -{ - this.domain(RL.settingsGet('AdminDomain')); - if (!this.activateProcess()) - { - this.key(''); - this.activateText(''); - this.activateText.isError(false); - this.activationSuccessed(false); - } -}; - -PopupsActivateViewModel.prototype.onFocus = function () -{ - if (!this.activateProcess()) - { - this.key.focus(true); - } -}; - -/** - * @returns {boolean} - */ -PopupsActivateViewModel.prototype.validateSubscriptionKey = function () -{ - var sValue = this.key(); - return '' === sValue || !!/^RL[\d]+-[A-Z0-9\-]+Z$/.test(Utils.trim(sValue)); + Globals.dropdownVisibility.subscribe(function (bValue) { + if (bValue) + { + $oEl.tooltip('hide'); + } + }); + } + } }; -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsLanguagesViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsLanguages'); - - this.exp = ko.observable(false); - - this.languages = ko.computed(function () { - return _.map(RL.data().languages(), function (sLanguage) { - return { - 'key': sLanguage, - 'selected': ko.observable(false), - 'fullName': Utils.convertLangName(sLanguage) - }; - }); - }); - - RL.data().mainLanguage.subscribe(function () { - this.resetMainLanguage(); - }, this); - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsLanguagesViewModel', PopupsLanguagesViewModel); - -PopupsLanguagesViewModel.prototype.languageEnName = function (sLanguage) -{ - return Utils.convertLangName(sLanguage, true); -}; - -PopupsLanguagesViewModel.prototype.resetMainLanguage = function () -{ - var sCurrent = RL.data().mainLanguage(); - _.each(this.languages(), function (oItem) { - oItem['selected'](oItem['key'] === sCurrent); - }); -}; - -PopupsLanguagesViewModel.prototype.onShow = function () -{ - this.exp(true); - - this.resetMainLanguage(); -}; - -PopupsLanguagesViewModel.prototype.onHide = function () -{ - this.exp(false); -}; - -PopupsLanguagesViewModel.prototype.changeLanguage = function (sLang) -{ - RL.data().mainLanguage(sLang); - this.cancelCommand(); -}; -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsAskViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsAsk'); - - this.askDesc = ko.observable(''); - this.yesButton = ko.observable(''); - this.noButton = ko.observable(''); - - this.yesFocus = ko.observable(false); - this.noFocus = ko.observable(false); - - this.fYesAction = null; - this.fNoAction = null; - - this.bDisabeCloseOnEsc = true; - this.sDefaultKeyScope = Enums.KeyState.PopupAsk; - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsAskViewModel', PopupsAskViewModel); - -PopupsAskViewModel.prototype.clearPopup = function () -{ - this.askDesc(''); - this.yesButton(Utils.i18n('POPUPS_ASK/BUTTON_YES')); - this.noButton(Utils.i18n('POPUPS_ASK/BUTTON_NO')); - - this.yesFocus(false); - this.noFocus(false); - - this.fYesAction = null; - this.fNoAction = null; -}; - -PopupsAskViewModel.prototype.yesClick = function () -{ - this.cancelCommand(); - - if (Utils.isFunc(this.fYesAction)) - { - this.fYesAction.call(null); - } -}; - -PopupsAskViewModel.prototype.noClick = function () -{ - this.cancelCommand(); - - if (Utils.isFunc(this.fNoAction)) - { - this.fNoAction.call(null); - } -}; - -/** - * @param {string} sAskDesc - * @param {Function=} fYesFunc - * @param {Function=} fNoFunc - * @param {string=} sYesButton - * @param {string=} sNoButton - */ -PopupsAskViewModel.prototype.onShow = function (sAskDesc, fYesFunc, fNoFunc, sYesButton, sNoButton) -{ - this.clearPopup(); - - this.fYesAction = fYesFunc || null; - this.fNoAction = fNoFunc || null; - - this.askDesc(sAskDesc || ''); - if (sYesButton) - { - this.yesButton(sYesButton); - } - - if (sYesButton) - { - this.yesButton(sNoButton); - } -}; - -PopupsAskViewModel.prototype.onFocus = function () -{ - this.yesFocus(true); -}; - -PopupsAskViewModel.prototype.onBuild = function () -{ - key('tab, shift+tab, right, left', Enums.KeyState.PopupAsk, _.bind(function () { - if (this.yesFocus()) - { - this.noFocus(true); - } - else - { - this.yesFocus(true); - } - return false; - }, this)); -}; - +ko.bindingHandlers.tooltip2 = { + 'init': function (oElement, fValueAccessor) { + var + $oEl = $(oElement), + sClass = $oEl.data('tooltip-class') || '', + sPlacement = $oEl.data('tooltip-placement') || 'top' + ; -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function AdminLoginViewModel() -{ - KnoinAbstractViewModel.call(this, 'Center', 'AdminLogin'); - - this.login = ko.observable(''); - this.password = ko.observable(''); - - this.loginError = ko.observable(false); - this.passwordError = ko.observable(false); - - this.loginFocus = ko.observable(false); - - this.login.subscribe(function () { - this.loginError(false); - }, this); - - this.password.subscribe(function () { - this.passwordError(false); - }, this); - - this.submitRequest = ko.observable(false); - this.submitError = ko.observable(''); - - this.submitCommand = Utils.createCommand(this, function () { - - this.loginError('' === Utils.trim(this.login())); - this.passwordError('' === Utils.trim(this.password())); - - if (this.loginError() || this.passwordError()) - { - return false; - } - - this.submitRequest(true); - - RL.remote().adminLogin(_.bind(function (sResult, oData) { - - if (Enums.StorageResultType.Success === sResult && oData && 'AdminLogin' === oData.Action) - { - if (oData.Result) - { - RL.loginAndLogoutReload(); - } - else if (oData.ErrorCode) - { - this.submitRequest(false); - this.submitError(Utils.getNotification(oData.ErrorCode)); - } - } - else - { - this.submitRequest(false); - this.submitError(Utils.getNotification(Enums.Notification.UnknownError)); - } - - }, this), this.login(), this.password()); - - return true; - - }, function () { - return !this.submitRequest(); - }); - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('AdminLoginViewModel', AdminLoginViewModel); - -AdminLoginViewModel.prototype.onShow = function () -{ - kn.routeOff(); - - _.delay(_.bind(function () { - this.loginFocus(true); - }, this), 100); - -}; - -AdminLoginViewModel.prototype.onHide = function () -{ - this.loginFocus(false); -}; + $oEl.tooltip({ + 'delay': { + 'show': 500, + 'hide': 100 + }, + 'html': true, + 'container': 'body', + 'placement': sPlacement, + 'title': function () { + return $oEl.is('.disabled') || Globals.dropdownVisibility() ? '' : + '' + fValueAccessor()() + ''; + } + }).click(function () { + $oEl.tooltip('hide'); + }); -/** - * @param {?} oScreen - * - * @constructor - * @extends KnoinAbstractViewModel - */ -function AdminMenuViewModel(oScreen) -{ - KnoinAbstractViewModel.call(this, 'Left', 'AdminMenu'); - - this.menu = oScreen.menu; - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('AdminMenuViewModel', AdminMenuViewModel); - -AdminMenuViewModel.prototype.link = function (sRoute) -{ - return '#/' + sRoute; -}; - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function AdminPaneViewModel() -{ - KnoinAbstractViewModel.call(this, 'Right', 'AdminPane'); - - this.adminDomain = ko.observable(RL.settingsGet('AdminDomain')); - this.version = ko.observable(RL.settingsGet('Version')); - - this.adminManLoadingVisibility = RL.data().adminManLoadingVisibility; - this.leftPanelDisabled = RL.data().leftPanelDisabled; - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('AdminPaneViewModel', AdminPaneViewModel); - -AdminPaneViewModel.prototype.logoutClick = function () -{ - RL.remote().adminLogout(function () { - RL.loginAndLogoutReload(); - }); + Globals.dropdownVisibility.subscribe(function (bValue) { + if (bValue) + { + $oEl.tooltip('hide'); + } + }); + } }; -/** - * @constructor - */ -function AdminGeneral() -{ - var oData = RL.data(); - - this.mainLanguage = oData.mainLanguage; - this.mainTheme = oData.mainTheme; - - this.language = oData.language; - this.theme = oData.theme; - - this.allowThemes = oData.allowThemes; - this.allowLanguagesOnSettings = oData.allowLanguagesOnSettings; - this.allowAdditionalAccounts = oData.allowAdditionalAccounts; - this.allowIdentities = oData.allowIdentities; - this.allowGravatar = oData.allowGravatar; - - this.themesOptions = ko.computed(function () { - return _.map(oData.themes(), function (sTheme) { - return { - 'optValue': sTheme, - 'optText': Utils.convertThemeName(sTheme) - }; - }); - }); - - this.mainLanguageFullName = ko.computed(function () { - return Utils.convertLangName(this.mainLanguage()); - }, this); - - this.weakPassword = !!RL.settingsGet('WeakPassword'); - - this.languageTrigger = ko.observable(Enums.SaveSettingsStep.Idle); - this.themeTrigger = ko.observable(Enums.SaveSettingsStep.Idle); -} - -Utils.addSettingsViewModel(AdminGeneral, 'AdminSettingsGeneral', 'General', 'general', true); - -AdminGeneral.prototype.onBuild = function () -{ - var self = this; - _.delay(function () { - - var - f2 = Utils.settingsSaveHelperSimpleFunction(self.languageTrigger, self), - f3 = Utils.settingsSaveHelperSimpleFunction(self.themeTrigger, self) - ; - - self.language.subscribe(function (sValue) { - RL.remote().saveAdminConfig(f2, { - 'Language': Utils.trim(sValue) - }); - }); - - self.theme.subscribe(function (sValue) { - RL.remote().saveAdminConfig(f3, { - 'Theme': Utils.trim(sValue) - }); - }); - - self.allowAdditionalAccounts.subscribe(function (bValue) { - RL.remote().saveAdminConfig(null, { - 'AllowAdditionalAccounts': bValue ? '1' : '0' - }); - }); - - self.allowIdentities.subscribe(function (bValue) { - RL.remote().saveAdminConfig(null, { - 'AllowIdentities': bValue ? '1' : '0' - }); - }); - - self.allowGravatar.subscribe(function (bValue) { - RL.remote().saveAdminConfig(null, { - 'AllowGravatar': bValue ? '1' : '0' - }); - }); - - self.allowThemes.subscribe(function (bValue) { - RL.remote().saveAdminConfig(null, { - 'AllowThemes': bValue ? '1' : '0' - }); - }); - - self.allowLanguagesOnSettings.subscribe(function (bValue) { - RL.remote().saveAdminConfig(null, { - 'AllowLanguagesOnSettings': bValue ? '1' : '0' - }); - }); - - }, 50); -}; - -AdminGeneral.prototype.selectLanguage = function () -{ - kn.showScreenPopup(PopupsLanguagesViewModel); -}; -/** - * @constructor - */ -function AdminLogin() -{ - var oData = RL.data(); - - this.allowCustomLogin = oData.allowCustomLogin; - this.determineUserLanguage = oData.determineUserLanguage; - - this.defaultDomain = ko.observable(RL.settingsGet('LoginDefaultDomain')); - - this.allowLanguagesOnLogin = oData.allowLanguagesOnLogin; - this.defaultDomainTrigger = ko.observable(Enums.SaveSettingsStep.Idle); -} - -Utils.addSettingsViewModel(AdminLogin, 'AdminSettingsLogin', 'Login', 'login'); - -AdminLogin.prototype.onBuild = function () -{ - var self = this; - _.delay(function () { - - var f1 = Utils.settingsSaveHelperSimpleFunction(self.defaultDomainTrigger, self); - - self.determineUserLanguage.subscribe(function (bValue) { - RL.remote().saveAdminConfig(null, { - 'DetermineUserLanguage': bValue ? '1' : '0' - }); - }); - - self.allowCustomLogin.subscribe(function (bValue) { - RL.remote().saveAdminConfig(null, { - 'AllowCustomLogin': bValue ? '1' : '0' - }); - }); - - self.allowLanguagesOnLogin.subscribe(function (bValue) { - RL.remote().saveAdminConfig(null, { - 'AllowLanguagesOnLogin': bValue ? '1' : '0' - }); - }); - - self.defaultDomain.subscribe(function (sValue) { - RL.remote().saveAdminConfig(f1, { - 'LoginDefaultDomain': Utils.trim(sValue) - }); - }); - - }, 50); -}; +ko.bindingHandlers.tooltip3 = { + 'init': function (oElement) { -/** - * @constructor - */ -function AdminBranding() -{ - this.title = ko.observable(RL.settingsGet('Title')); - this.title.trigger = ko.observable(Enums.SaveSettingsStep.Idle); - - this.loadingDesc = ko.observable(RL.settingsGet('LoadingDescription')); - this.loadingDesc.trigger = ko.observable(Enums.SaveSettingsStep.Idle); - - this.loginLogo = ko.observable(RL.settingsGet('LoginLogo')); - this.loginLogo.trigger = ko.observable(Enums.SaveSettingsStep.Idle); - - this.loginDescription = ko.observable(RL.settingsGet('LoginDescription')); - this.loginDescription.trigger = ko.observable(Enums.SaveSettingsStep.Idle); - - this.loginCss = ko.observable(RL.settingsGet('LoginCss')); - this.loginCss.trigger = ko.observable(Enums.SaveSettingsStep.Idle); -} - -Utils.addSettingsViewModel(AdminBranding, 'AdminSettingsBranding', 'Branding', 'branding'); - -AdminBranding.prototype.onBuild = function () -{ - var self = this; - _.delay(function () { - - var - f1 = Utils.settingsSaveHelperSimpleFunction(self.title.trigger, self), - f2 = Utils.settingsSaveHelperSimpleFunction(self.loadingDesc.trigger, self), - f3 = Utils.settingsSaveHelperSimpleFunction(self.loginLogo.trigger, self), - f4 = Utils.settingsSaveHelperSimpleFunction(self.loginDescription.trigger, self), - f5 = Utils.settingsSaveHelperSimpleFunction(self.loginCss.trigger, self) - ; - - self.title.subscribe(function (sValue) { - RL.remote().saveAdminConfig(f1, { - 'Title': Utils.trim(sValue) - }); - }); - - self.loadingDesc.subscribe(function (sValue) { - RL.remote().saveAdminConfig(f2, { - 'LoadingDescription': Utils.trim(sValue) - }); - }); - - self.loginLogo.subscribe(function (sValue) { - RL.remote().saveAdminConfig(f3, { - 'LoginLogo': Utils.trim(sValue) - }); - }); - - self.loginDescription.subscribe(function (sValue) { - RL.remote().saveAdminConfig(f4, { - 'LoginDescription': Utils.trim(sValue) - }); - }); - - self.loginCss.subscribe(function (sValue) { - RL.remote().saveAdminConfig(f5, { - 'LoginCss': Utils.trim(sValue) - }); - }); - - }, 50); -}; + var $oEl = $(oElement); + + $oEl.tooltip({ + 'container': 'body', + 'trigger': 'hover manual', + 'title': function () { + return $oEl.data('tooltip3-data') || ''; + } + }); -/** - * @constructor - */ -function AdminContacts() -{ -// var oData = RL.data(); - - this.defautOptionsAfterRender = Utils.defautOptionsAfterRender; - this.enableContacts = ko.observable(!!RL.settingsGet('ContactsEnable')); - this.contactsSharing = ko.observable(!!RL.settingsGet('ContactsSharing')); - this.contactsSync = ko.observable(!!RL.settingsGet('ContactsSync')); - - var - aTypes = ['sqlite', 'mysql', 'pgsql'], - aSupportedTypes = [], - getTypeName = function(sName) { - switch (sName) - { - case 'sqlite': - sName = 'SQLite'; - break; - case 'mysql': - sName = 'MySQL'; - break; - case 'pgsql': - sName = 'PostgreSQL'; - break; - } - - return sName; - } - ; - - if (!!RL.settingsGet('SQLiteIsSupported')) - { - aSupportedTypes.push('sqlite'); - } - if (!!RL.settingsGet('MySqlIsSupported')) - { - aSupportedTypes.push('mysql'); - } - if (!!RL.settingsGet('PostgreSqlIsSupported')) - { - aSupportedTypes.push('pgsql'); - } - - this.contactsSupported = 0 < aSupportedTypes.length; - - this.contactsTypes = ko.observableArray([]); - this.contactsTypesOptions = this.contactsTypes.map(function (sValue) { - var bDisabled = -1 === Utils.inArray(sValue, aSupportedTypes); - return { - 'id': sValue, - 'name': getTypeName(sValue) + (bDisabled ? ' (not supported)' : ''), - 'disabled': bDisabled - }; - }); - - this.contactsTypes(aTypes); - this.contactsType = ko.observable(''); - - this.mainContactsType = ko.computed({ - 'owner': this, - 'read': this.contactsType, - 'write': function (sValue) { - if (sValue !== this.contactsType()) - { - if (-1 < Utils.inArray(sValue, aSupportedTypes)) - { - this.contactsType(sValue); - } - else if (0 < aSupportedTypes.length) - { - this.contactsType(''); - } - } - else - { - this.contactsType.valueHasMutated(); - } - } - }); - - this.contactsType.subscribe(function () { - this.testContactsSuccess(false); - this.testContactsError(false); - this.testContactsErrorMessage(''); - }, this); - - this.pdoDsn = ko.observable(RL.settingsGet('ContactsPdoDsn')); - this.pdoUser = ko.observable(RL.settingsGet('ContactsPdoUser')); - this.pdoPassword = ko.observable(RL.settingsGet('ContactsPdoPassword')); - - this.pdoDsnTrigger = ko.observable(Enums.SaveSettingsStep.Idle); - this.pdoUserTrigger = ko.observable(Enums.SaveSettingsStep.Idle); - this.pdoPasswordTrigger = ko.observable(Enums.SaveSettingsStep.Idle); - this.contactsTypeTrigger = ko.observable(Enums.SaveSettingsStep.Idle); - - this.testing = ko.observable(false); - this.testContactsSuccess = ko.observable(false); - this.testContactsError = ko.observable(false); - this.testContactsErrorMessage = ko.observable(''); - - this.testContactsCommand = Utils.createCommand(this, function () { - - this.testContactsSuccess(false); - this.testContactsError(false); - this.testContactsErrorMessage(''); - this.testing(true); - - RL.remote().testContacts(this.onTestContactsResponse, { - 'ContactsPdoType': this.contactsType(), - 'ContactsPdoDsn': this.pdoDsn(), - 'ContactsPdoUser': this.pdoUser(), - 'ContactsPdoPassword': this.pdoPassword() - }); - - }, function () { - return '' !== this.pdoDsn() && '' !== this.pdoUser(); - }); - - this.contactsType(RL.settingsGet('ContactsPdoType')); - - this.onTestContactsResponse = _.bind(this.onTestContactsResponse, this); -} - -Utils.addSettingsViewModel(AdminContacts, 'AdminSettingsContacts', 'Contacts', 'contacts'); - -AdminContacts.prototype.onTestContactsResponse = function (sResult, oData) -{ - this.testContactsSuccess(false); - this.testContactsError(false); - this.testContactsErrorMessage(''); - - if (Enums.StorageResultType.Success === sResult && oData && oData.Result && oData.Result.Result) - { - this.testContactsSuccess(true); - } - else - { - this.testContactsError(true); - if (oData && oData.Result) - { - this.testContactsErrorMessage(oData.Result.Message || ''); - } - else - { - this.testContactsErrorMessage(''); - } - } - - this.testing(false); -}; - -AdminContacts.prototype.onShow = function () -{ - this.testContactsSuccess(false); - this.testContactsError(false); - this.testContactsErrorMessage(''); -}; - -AdminContacts.prototype.onBuild = function () -{ - var self = this; - _.delay(function () { - - var - f1 = Utils.settingsSaveHelperSimpleFunction(self.pdoDsnTrigger, self), - f3 = Utils.settingsSaveHelperSimpleFunction(self.pdoUserTrigger, self), - f4 = Utils.settingsSaveHelperSimpleFunction(self.pdoPasswordTrigger, self), - f5 = Utils.settingsSaveHelperSimpleFunction(self.contactsTypeTrigger, self) - ; - - self.enableContacts.subscribe(function (bValue) { - RL.remote().saveAdminConfig(null, { - 'ContactsEnable': bValue ? '1' : '0' - }); - }); - - self.contactsSharing.subscribe(function (bValue) { - RL.remote().saveAdminConfig(null, { - 'ContactsSharing': bValue ? '1' : '0' - }); - }); - - self.contactsSync.subscribe(function (bValue) { - RL.remote().saveAdminConfig(null, { - 'ContactsSync': bValue ? '1' : '0' - }); - }); - - self.contactsType.subscribe(function (sValue) { - RL.remote().saveAdminConfig(f5, { - 'ContactsPdoType': sValue - }); - }); - - self.pdoDsn.subscribe(function (sValue) { - RL.remote().saveAdminConfig(f1, { - 'ContactsPdoDsn': Utils.trim(sValue) - }); - }); - - self.pdoUser.subscribe(function (sValue) { - RL.remote().saveAdminConfig(f3, { - 'ContactsPdoUser': Utils.trim(sValue) - }); - }); - - self.pdoPassword.subscribe(function (sValue) { - RL.remote().saveAdminConfig(f4, { - 'ContactsPdoPassword': Utils.trim(sValue) - }); - }); - - self.contactsType(RL.settingsGet('ContactsPdoType')); - - }, 50); -}; + Globals.dropdownVisibility.subscribe(function (bValue) { + if (bValue) + { + $oEl.tooltip('hide'); + } + }); -/** - * @constructor - */ -function AdminDomains() -{ - var oData = RL.data(); - - this.domains = oData.domains; - this.domainsLoading = oData.domainsLoading; - - this.iDomainForDeletionTimeout = 0; - - this.visibility = ko.computed(function () { - return oData.domainsLoading() ? 'visible' : 'hidden'; - }, this); - - this.domainForDeletion = ko.observable(null).extend({'toggleSubscribe': [this, - function (oPrev) { - if (oPrev) - { - oPrev.deleteAccess(false); - } - }, function (oNext) { - if (oNext) - { - oNext.deleteAccess(true); - this.startDomainForDeletionTimeout(); - } - } - ]}); -} - -Utils.addSettingsViewModel(AdminDomains, 'AdminSettingsDomains', 'Domains', 'domains'); - -AdminDomains.prototype.startDomainForDeletionTimeout = function () -{ - var self = this; - window.clearInterval(this.iDomainForDeletionTimeout); - this.iDomainForDeletionTimeout = window.setTimeout(function () { - self.domainForDeletion(null); - }, 1000 * 3); -}; - -AdminDomains.prototype.createDomain = function () -{ - kn.showScreenPopup(PopupsDomainViewModel); -}; - -AdminDomains.prototype.deleteDomain = function (oDomain) -{ - this.domains.remove(oDomain); - RL.remote().domainDelete(_.bind(this.onDomainListChangeRequest, this), oDomain.name); -}; - -AdminDomains.prototype.disableDomain = function (oDomain) -{ - oDomain.disabled(!oDomain.disabled()); - RL.remote().domainDisable(_.bind(this.onDomainListChangeRequest, this), oDomain.name, oDomain.disabled()); -}; - -AdminDomains.prototype.onBuild = function (oDom) -{ - var self = this; - oDom - .on('click', '.b-admin-domains-list-table .e-item .e-action', function () { - var oDomainItem = ko.dataFor(this); - if (oDomainItem) - { - RL.remote().domain(_.bind(self.onDomainLoadRequest, self), oDomainItem.name); - } - }) - ; - - RL.reloadDomainList(); -}; - -AdminDomains.prototype.onDomainLoadRequest = function (sResult, oData) -{ - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - kn.showScreenPopup(PopupsDomainViewModel, [oData.Result]); - } -}; - -AdminDomains.prototype.onDomainListChangeRequest = function () -{ - RL.reloadDomainList(); -}; - -/** - * @constructor - */ -function AdminSecurity() -{ - this.csrfProtection = ko.observable(!!RL.settingsGet('UseTokenProtection')); - this.openPGP = ko.observable(!!RL.settingsGet('OpenPGP')); - this.allowTwoFactorAuth = ko.observable(!!RL.settingsGet('AllowTwoFactorAuth')); - - this.adminLogin = ko.observable(RL.settingsGet('AdminLogin')); - this.adminPassword = ko.observable(''); - this.adminPasswordNew = ko.observable(''); - this.adminPasswordNew2 = ko.observable(''); - this.adminPasswordNewError = ko.observable(false); - - this.adminPasswordUpdateError = ko.observable(false); - this.adminPasswordUpdateSuccess = ko.observable(false); - - this.adminPassword.subscribe(function () { - this.adminPasswordUpdateError(false); - this.adminPasswordUpdateSuccess(false); - }, this); - - this.adminPasswordNew.subscribe(function () { - this.adminPasswordUpdateError(false); - this.adminPasswordUpdateSuccess(false); - this.adminPasswordNewError(false); - }, this); - - this.adminPasswordNew2.subscribe(function () { - this.adminPasswordUpdateError(false); - this.adminPasswordUpdateSuccess(false); - this.adminPasswordNewError(false); - }, this); - - this.saveNewAdminPasswordCommand = Utils.createCommand(this, function () { - - if (this.adminPasswordNew() !== this.adminPasswordNew2()) - { - this.adminPasswordNewError(true); - return false; - } - - this.adminPasswordUpdateError(false); - this.adminPasswordUpdateSuccess(false); - - RL.remote().saveNewAdminPassword(this.onNewAdminPasswordResponse, { - 'Password': this.adminPassword(), - 'NewPassword': this.adminPasswordNew() - }); - - }, function () { - return '' !== this.adminPassword() && '' !== this.adminPasswordNew() && '' !== this.adminPasswordNew2(); - }); - - this.onNewAdminPasswordResponse = _.bind(this.onNewAdminPasswordResponse, this); -} - -Utils.addSettingsViewModel(AdminSecurity, 'AdminSettingsSecurity', 'Security', 'security'); - -AdminSecurity.prototype.onNewAdminPasswordResponse = function (sResult, oData) -{ - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - this.adminPassword(''); - this.adminPasswordNew(''); - this.adminPasswordNew2(''); - - this.adminPasswordUpdateSuccess(true); - } - else - { - this.adminPasswordUpdateError(true); - } -}; - -AdminSecurity.prototype.onBuild = function () -{ - this.csrfProtection.subscribe(function (bValue) { - RL.remote().saveAdminConfig(Utils.emptyFunction, { - 'TokenProtection': bValue ? '1' : '0' - }); - }); - - this.openPGP.subscribe(function (bValue) { - RL.remote().saveAdminConfig(Utils.emptyFunction, { - 'OpenPGP': bValue ? '1' : '0' - }); - }); - - this.allowTwoFactorAuth.subscribe(function (bValue) { - RL.remote().saveAdminConfig(Utils.emptyFunction, { - 'AllowTwoFactorAuth': bValue ? '1' : '0' - }); - }); -}; - -AdminSecurity.prototype.onHide = function () -{ - this.adminPassword(''); - this.adminPasswordNew(''); - this.adminPasswordNew2(''); -}; - -/** - * @return {string} - */ -AdminSecurity.prototype.phpInfoLink = function () -{ - return RL.link().phpInfo(); -}; - -/** - * @constructor - */ -function AdminSocial() -{ - var oData = RL.data(); - - this.googleEnable = oData.googleEnable; - this.googleClientID = oData.googleClientID; - this.googleClientSecret = oData.googleClientSecret; - this.googleTrigger1 = ko.observable(Enums.SaveSettingsStep.Idle); - this.googleTrigger2 = ko.observable(Enums.SaveSettingsStep.Idle); - - this.facebookEnable = oData.facebookEnable; - this.facebookAppID = oData.facebookAppID; - this.facebookAppSecret = oData.facebookAppSecret; - this.facebookTrigger1 = ko.observable(Enums.SaveSettingsStep.Idle); - this.facebookTrigger2 = ko.observable(Enums.SaveSettingsStep.Idle); - - this.twitterEnable = oData.twitterEnable; - this.twitterConsumerKey = oData.twitterConsumerKey; - this.twitterConsumerSecret = oData.twitterConsumerSecret; - this.twitterTrigger1 = ko.observable(Enums.SaveSettingsStep.Idle); - this.twitterTrigger2 = ko.observable(Enums.SaveSettingsStep.Idle); - - this.dropboxEnable = oData.dropboxEnable; - this.dropboxApiKey = oData.dropboxApiKey; - this.dropboxTrigger1 = ko.observable(Enums.SaveSettingsStep.Idle); -} - -Utils.addSettingsViewModel(AdminSocial, 'AdminSettingsSocial', 'Social', 'social'); - -AdminSocial.prototype.onBuild = function () -{ - var self = this; - _.delay(function () { - - var - f1 = Utils.settingsSaveHelperSimpleFunction(self.facebookTrigger1, self), - f2 = Utils.settingsSaveHelperSimpleFunction(self.facebookTrigger2, self), - f3 = Utils.settingsSaveHelperSimpleFunction(self.twitterTrigger1, self), - f4 = Utils.settingsSaveHelperSimpleFunction(self.twitterTrigger2, self), - f5 = Utils.settingsSaveHelperSimpleFunction(self.googleTrigger1, self), - f6 = Utils.settingsSaveHelperSimpleFunction(self.googleTrigger2, self), - f7 = Utils.settingsSaveHelperSimpleFunction(self.dropboxTrigger1, self) - ; - - self.facebookEnable.subscribe(function (bValue) { - RL.remote().saveAdminConfig(Utils.emptyFunction, { - 'FacebookEnable': bValue ? '1' : '0' - }); - }); - - self.facebookAppID.subscribe(function (sValue) { - RL.remote().saveAdminConfig(f1, { - 'FacebookAppID': Utils.trim(sValue) - }); - }); - - self.facebookAppSecret.subscribe(function (sValue) { - RL.remote().saveAdminConfig(f2, { - 'FacebookAppSecret': Utils.trim(sValue) - }); - }); - - self.twitterEnable.subscribe(function (bValue) { - RL.remote().saveAdminConfig(Utils.emptyFunction, { - 'TwitterEnable': bValue ? '1' : '0' - }); - }); - - self.twitterConsumerKey.subscribe(function (sValue) { - RL.remote().saveAdminConfig(f3, { - 'TwitterConsumerKey': Utils.trim(sValue) - }); - }); - - self.twitterConsumerSecret.subscribe(function (sValue) { - RL.remote().saveAdminConfig(f4, { - 'TwitterConsumerSecret': Utils.trim(sValue) - }); - }); - - self.googleEnable.subscribe(function (bValue) { - RL.remote().saveAdminConfig(Utils.emptyFunction, { - 'GoogleEnable': bValue ? '1' : '0' - }); - }); - - self.googleClientID.subscribe(function (sValue) { - RL.remote().saveAdminConfig(f5, { - 'GoogleClientID': Utils.trim(sValue) - }); - }); - - self.googleClientSecret.subscribe(function (sValue) { - RL.remote().saveAdminConfig(f6, { - 'GoogleClientSecret': Utils.trim(sValue) - }); - }); - - self.dropboxEnable.subscribe(function (bValue) { - RL.remote().saveAdminConfig(Utils.emptyFunction, { - 'DropboxEnable': bValue ? '1' : '0' - }); - }); - - self.dropboxApiKey.subscribe(function (sValue) { - RL.remote().saveAdminConfig(f7, { - 'DropboxApiKey': Utils.trim(sValue) - }); - }); - - }, 50); -}; - -/** - * @constructor - */ -function AdminPlugins() -{ - var oData = RL.data(); - - this.enabledPlugins = ko.observable(!!RL.settingsGet('EnabledPlugins')); - - this.pluginsError = ko.observable(''); - - this.plugins = oData.plugins; - this.pluginsLoading = oData.pluginsLoading; - - this.visibility = ko.computed(function () { - return oData.pluginsLoading() ? 'visible' : 'hidden'; - }, this); - - this.onPluginLoadRequest = _.bind(this.onPluginLoadRequest, this); - this.onPluginDisableRequest = _.bind(this.onPluginDisableRequest, this); -} - -Utils.addSettingsViewModel(AdminPlugins, 'AdminSettingsPlugins', 'Plugins', 'plugins'); - -AdminPlugins.prototype.disablePlugin = function (oPlugin) -{ - oPlugin.disabled(!oPlugin.disabled()); - RL.remote().pluginDisable(this.onPluginDisableRequest, oPlugin.name, oPlugin.disabled()); -}; - -AdminPlugins.prototype.configurePlugin = function (oPlugin) -{ - RL.remote().plugin(this.onPluginLoadRequest, oPlugin.name); -}; - -AdminPlugins.prototype.onBuild = function (oDom) -{ - var self = this; - - oDom - .on('click', '.e-item .configure-plugin-action', function () { - var oPlugin = ko.dataFor(this); - if (oPlugin) - { - self.configurePlugin(oPlugin); - } - }) - .on('click', '.e-item .disabled-plugin', function () { - var oPlugin = ko.dataFor(this); - if (oPlugin) - { - self.disablePlugin(oPlugin); - } - }) - ; - - this.enabledPlugins.subscribe(function (bValue) { - RL.remote().saveAdminConfig(Utils.emptyFunction, { - 'EnabledPlugins': bValue ? '1' : '0' - }); - }); -}; - -AdminPlugins.prototype.onShow = function () -{ - this.pluginsError(''); - RL.reloadPluginList(); -}; - -AdminPlugins.prototype.onPluginLoadRequest = function (sResult, oData) -{ - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - kn.showScreenPopup(PopupsPluginViewModel, [oData.Result]); - } -}; - -AdminPlugins.prototype.onPluginDisableRequest = function (sResult, oData) -{ - if (Enums.StorageResultType.Success === sResult && oData) - { - if (!oData.Result && oData.ErrorCode) - { - if (Enums.Notification.UnsupportedPluginPackage === oData.ErrorCode && oData.ErrorMessage && '' !== oData.ErrorMessage) - { - this.pluginsError(oData.ErrorMessage); - } - else - { - this.pluginsError(Utils.getNotification(oData.ErrorCode)); - } - } - } - - RL.reloadPluginList(); -}; - -/** - * @constructor - */ -function AdminPackages() -{ - var oData = RL.data(); - - this.packagesError = ko.observable(''); - - this.packages = oData.packages; - this.packagesLoading = oData.packagesLoading; - this.packagesReal = oData.packagesReal; - this.packagesMainUpdatable = oData.packagesMainUpdatable; - - this.packagesCurrent = this.packages.filter(function (oItem) { - return oItem && '' !== oItem['installed'] && !oItem['compare']; - }); - - this.packagesAvailableForUpdate = this.packages.filter(function (oItem) { - return oItem && '' !== oItem['installed'] && !!oItem['compare']; - }); - - this.packagesAvailableForInstallation = this.packages.filter(function (oItem) { - return oItem && '' === oItem['installed']; - }); - - this.visibility = ko.computed(function () { - return oData.packagesLoading() ? 'visible' : 'hidden'; - }, this); -} - -Utils.addSettingsViewModel(AdminPackages, 'AdminSettingsPackages', 'Packages', 'packages'); - -AdminPackages.prototype.onShow = function () -{ - this.packagesError(''); -}; - -AdminPackages.prototype.onBuild = function () -{ - RL.reloadPackagesList(); -}; - -AdminPackages.prototype.requestHelper = function (oPackage, bInstall) -{ - var self = this; - return function (sResult, oData) { - - if (Enums.StorageResultType.Success !== sResult || !oData || !oData.Result) - { - if (oData && oData.ErrorCode) - { - self.packagesError(Utils.getNotification(oData.ErrorCode)); - } - else - { - self.packagesError(Utils.getNotification( - bInstall ? Enums.Notification.CantInstallPackage : Enums.Notification.CantDeletePackage)); - } - } - - _.each(RL.data().packages(), function (oItem) { - if (oItem && oPackage && oItem['loading']() && oPackage['file'] === oItem['file']) - { - oPackage['loading'](false); - oItem['loading'](false); - } - }); - - if (Enums.StorageResultType.Success === sResult && oData && oData.Result && oData.Result['Reload']) - { - window.location.reload(); - } - else - { - RL.reloadPackagesList(); - } - }; -}; - -AdminPackages.prototype.deletePackage = function (oPackage) -{ - if (oPackage) - { - oPackage['loading'](true); - RL.remote().packageDelete(this.requestHelper(oPackage, false), oPackage); - } -}; - -AdminPackages.prototype.installPackage = function (oPackage) -{ - if (oPackage) - { - oPackage['loading'](true); - RL.remote().packageInstall(this.requestHelper(oPackage, true), oPackage); - } -}; - -/** - * @constructor - */ -function AdminLicensing() -{ - this.licensing = RL.data().licensing; - this.licensingProcess = RL.data().licensingProcess; - this.licenseValid = RL.data().licenseValid; - this.licenseExpired = RL.data().licenseExpired; - this.licenseError = RL.data().licenseError; - this.licenseTrigger = RL.data().licenseTrigger; - - this.adminDomain = ko.observable(''); - this.subscriptionEnabled = ko.observable(!!RL.settingsGet('SubscriptionEnabled')); - - this.licenseTrigger.subscribe(function () { - if (this.subscriptionEnabled()) - { - RL.reloadLicensing(true); - } - }, this); -} - -Utils.addSettingsViewModel(AdminLicensing, 'AdminSettingsLicensing', 'Licensing', 'licensing'); - -AdminLicensing.prototype.onBuild = function () -{ - if (this.subscriptionEnabled()) - { - RL.reloadLicensing(false); - } -}; - -AdminLicensing.prototype.onShow = function () -{ - this.adminDomain(RL.settingsGet('AdminDomain')); -}; - -AdminLicensing.prototype.showActivationForm = function () -{ - kn.showScreenPopup(PopupsActivateViewModel); -}; - -/** - * @returns {string} - */ -AdminLicensing.prototype.licenseExpiredMomentValue = function () -{ - var oDate = moment.unix(this.licenseExpired()); - return oDate.format('LL') + ' (' + oDate.from(moment()) + ')'; + $document.click(function () { + $oEl.tooltip('hide'); + }); + + }, + 'update': function (oElement, fValueAccessor) { + var sValue = ko.utils.unwrapObservable(fValueAccessor()); + if ('' === sValue) + { + $(oElement).data('tooltip3-data', '').tooltip('hide'); + } + else + { + $(oElement).data('tooltip3-data', sValue).tooltip('show'); + } + } }; -/** - * @constructor - */ -function AbstractData() -{ - this.leftPanelDisabled = ko.observable(false); - this.useKeyboardShortcuts = ko.observable(true); - - this.keyScopeReal = ko.observable(Enums.KeyState.All); - this.keyScopeFake = ko.observable(Enums.KeyState.All); - - this.keyScope = ko.computed({ - 'owner': this, - 'read': function () { - return this.keyScopeFake(); - }, - 'write': function (sValue) { - - if (Enums.KeyState.Menu !== sValue) - { - if (Enums.KeyState.Compose === sValue) - { - Utils.disableKeyFilter(); - } - else - { - Utils.restoreKeyFilter(); - } - - this.keyScopeFake(sValue); - if (Globals.dropdownVisibility()) - { - sValue = Enums.KeyState.Menu; - } - } - - this.keyScopeReal(sValue); - } - }); - - this.keyScopeReal.subscribe(function (sValue) { -// window.console.log(sValue); - key.setScope(sValue); - }); - - this.leftPanelDisabled.subscribe(function (bValue) { - RL.pub('left-panel.' + (bValue ? 'off' : 'on')); - }); - - Globals.dropdownVisibility.subscribe(function (bValue) { - if (bValue) - { - this.keyScope(Enums.KeyState.Menu); - } - else if (Enums.KeyState.Menu === key.getScope()) - { - this.keyScope(this.keyScopeFake()); - } - }, this); - - Utils.initDataConstructorBySettings(this); -} - -AbstractData.prototype.populateDataOnStart = function() -{ - var - mLayout = Utils.pInt(RL.settingsGet('Layout')), - aLanguages = RL.settingsGet('Languages'), - aThemes = RL.settingsGet('Themes') - ; - - if (Utils.isArray(aLanguages)) - { - this.languages(aLanguages); - } - - if (Utils.isArray(aThemes)) - { - this.themes(aThemes); - } - - this.mainLanguage(RL.settingsGet('Language')); - this.mainTheme(RL.settingsGet('Theme')); - - this.allowAdditionalAccounts(!!RL.settingsGet('AllowAdditionalAccounts')); - this.allowIdentities(!!RL.settingsGet('AllowIdentities')); - this.allowGravatar(!!RL.settingsGet('AllowGravatar')); - this.determineUserLanguage(!!RL.settingsGet('DetermineUserLanguage')); - - this.allowThemes(!!RL.settingsGet('AllowThemes')); - this.allowCustomLogin(!!RL.settingsGet('AllowCustomLogin')); - this.allowLanguagesOnLogin(!!RL.settingsGet('AllowLanguagesOnLogin')); - this.allowLanguagesOnSettings(!!RL.settingsGet('AllowLanguagesOnSettings')); - - this.editorDefaultType(RL.settingsGet('EditorDefaultType')); - this.showImages(!!RL.settingsGet('ShowImages')); - this.contactsAutosave(!!RL.settingsGet('ContactsAutosave')); - this.interfaceAnimation(RL.settingsGet('InterfaceAnimation')); - - this.mainMessagesPerPage(RL.settingsGet('MPP')); - - this.desktopNotifications(!!RL.settingsGet('DesktopNotifications')); - this.useThreads(!!RL.settingsGet('UseThreads')); - this.replySameFolder(!!RL.settingsGet('ReplySameFolder')); - this.useCheckboxesInList(!!RL.settingsGet('UseCheckboxesInList')); - - this.layout(Enums.Layout.SidePreview); - if (-1 < Utils.inArray(mLayout, [Enums.Layout.NoPreview, Enums.Layout.SidePreview, Enums.Layout.BottomPreview])) - { - this.layout(mLayout); - } - - this.facebookEnable(!!RL.settingsGet('AllowFacebookSocial')); - this.facebookAppID(RL.settingsGet('FacebookAppID')); - this.facebookAppSecret(RL.settingsGet('FacebookAppSecret')); - - this.twitterEnable(!!RL.settingsGet('AllowTwitterSocial')); - this.twitterConsumerKey(RL.settingsGet('TwitterConsumerKey')); - this.twitterConsumerSecret(RL.settingsGet('TwitterConsumerSecret')); - - this.googleEnable(!!RL.settingsGet('AllowGoogleSocial')); - this.googleClientID(RL.settingsGet('GoogleClientID')); - this.googleClientSecret(RL.settingsGet('GoogleClientSecret')); - - this.dropboxEnable(!!RL.settingsGet('AllowDropboxSocial')); - this.dropboxApiKey(RL.settingsGet('DropboxApiKey')); - - this.contactsIsAllowed(!!RL.settingsGet('ContactsIsAllowed')); -}; -/** - * @constructor - * @extends AbstractData - */ -function AdminDataStorage() -{ - AbstractData.call(this); - - this.domainsLoading = ko.observable(false).extend({'throttle': 100}); - this.domains = ko.observableArray([]); - - this.pluginsLoading = ko.observable(false).extend({'throttle': 100}); - this.plugins = ko.observableArray([]); - - this.packagesReal = ko.observable(true); - this.packagesMainUpdatable = ko.observable(true); - this.packagesLoading = ko.observable(false).extend({'throttle': 100}); - this.packages = ko.observableArray([]); - - this.licensing = ko.observable(false); - this.licensingProcess = ko.observable(false); - this.licenseValid = ko.observable(false); - this.licenseExpired = ko.observable(0); - this.licenseError = ko.observable(''); - - this.licenseTrigger = ko.observable(false); - - this.adminManLoading = ko.computed(function () { - return '000' !== [this.domainsLoading() ? '1' : '0', this.pluginsLoading() ? '1' : '0', this.packagesLoading() ? '1' : '0'].join(''); - }, this); - - this.adminManLoadingVisibility = ko.computed(function () { - return this.adminManLoading() ? 'visible' : 'hidden'; - }, this).extend({'rateLimit': 300}); -} - -_.extend(AdminDataStorage.prototype, AbstractData.prototype); - -AdminDataStorage.prototype.populateDataOnStart = function() -{ - AbstractData.prototype.populateDataOnStart.call(this); +ko.bindingHandlers.registrateBootstrapDropdown = { + 'init': function (oElement) { + BootstrapDropdowns.push($(oElement)); + } }; -/** - * @constructor - */ -function AbstractAjaxRemoteStorage() -{ - this.oRequests = {}; -} - -AbstractAjaxRemoteStorage.prototype.oRequests = {}; - -/** - * @param {?Function} fCallback - * @param {string} sRequestAction - * @param {string} sType - * @param {?AjaxJsonDefaultResponse} oData - * @param {boolean} bCached - * @param {*=} oRequestParameters - */ -AbstractAjaxRemoteStorage.prototype.defaultResponse = function (fCallback, sRequestAction, sType, oData, bCached, oRequestParameters) -{ - var - fCall = function () { - if (Enums.StorageResultType.Success !== sType && Globals.bUnload) - { - sType = Enums.StorageResultType.Unload; - } - - if (Enums.StorageResultType.Success === sType && oData && !oData.Result) - { - if (oData && -1 < Utils.inArray(oData.ErrorCode, [ - Enums.Notification.AuthError, Enums.Notification.AccessError, - Enums.Notification.ConnectionError, Enums.Notification.DomainNotAllowed, Enums.Notification.AccountNotAllowed, - Enums.Notification.MailServerError, Enums.Notification.UnknownNotification, Enums.Notification.UnknownError - ])) - { - Globals.iAjaxErrorCount++; - } - - if (oData && Enums.Notification.InvalidToken === oData.ErrorCode) - { - Globals.iTokenErrorCount++; - } - - if (Consts.Values.TokenErrorLimit < Globals.iTokenErrorCount) - { - RL.loginAndLogoutReload(true); - } - - if (oData.Logout || Consts.Values.AjaxErrorLimit < Globals.iAjaxErrorCount) - { - if (window.__rlah_clear) - { - window.__rlah_clear(); - } - - RL.loginAndLogoutReload(true); - } - } - else if (Enums.StorageResultType.Success === sType && oData && oData.Result) - { - Globals.iAjaxErrorCount = 0; - Globals.iTokenErrorCount = 0; - } - - if (fCallback) - { - Plugins.runHook('ajax-default-response', [sRequestAction, Enums.StorageResultType.Success === sType ? oData : null, sType, bCached, oRequestParameters]); - - fCallback( - sType, - Enums.StorageResultType.Success === sType ? oData : null, - bCached, - sRequestAction, - oRequestParameters - ); - } - } - ; - - switch (sType) - { - case 'success': - sType = Enums.StorageResultType.Success; - break; - case 'abort': - sType = Enums.StorageResultType.Abort; - break; - default: - sType = Enums.StorageResultType.Error; - break; - } - - if (Enums.StorageResultType.Error === sType) - { - _.delay(fCall, 300); - } - else - { - fCall(); - } -}; - -/** - * @param {?Function} fResultCallback - * @param {Object} oParameters - * @param {?number=} iTimeOut = 20000 - * @param {string=} sGetAdd = '' - * @param {Array=} aAbortActions = [] - * @return {jQuery.jqXHR} - */ -AbstractAjaxRemoteStorage.prototype.ajaxRequest = function (fResultCallback, oParameters, iTimeOut, sGetAdd, aAbortActions) -{ - var - self = this, - bPost = '' === sGetAdd, - oHeaders = {}, - iStart = (new window.Date()).getTime(), - oDefAjax = null, - sAction = '' - ; - - oParameters = oParameters || {}; - iTimeOut = Utils.isNormal(iTimeOut) ? iTimeOut : 20000; - sGetAdd = Utils.isUnd(sGetAdd) ? '' : Utils.pString(sGetAdd); - aAbortActions = Utils.isArray(aAbortActions) ? aAbortActions : []; - - sAction = oParameters.Action || ''; - - if (sAction && 0 < aAbortActions.length) - { - _.each(aAbortActions, function (sActionToAbort) { - if (self.oRequests[sActionToAbort]) - { - self.oRequests[sActionToAbort].__aborted = true; - if (self.oRequests[sActionToAbort].abort) - { - self.oRequests[sActionToAbort].abort(); - } - self.oRequests[sActionToAbort] = null; - } - }); - } - - if (bPost) - { - oParameters['XToken'] = RL.settingsGet('Token'); - } - - oDefAjax = $.ajax({ - 'type': bPost ? 'POST' : 'GET', - 'url': RL.link().ajax(sGetAdd) , - 'async': true, - 'dataType': 'json', - 'data': bPost ? oParameters : {}, - 'headers': oHeaders, - 'timeout': iTimeOut, - 'global': true - }); - - oDefAjax.always(function (oData, sType) { - - var bCached = false; - if (oData && oData['Time']) - { - bCached = Utils.pInt(oData['Time']) > (new window.Date()).getTime() - iStart; - } - - if (sAction && self.oRequests[sAction]) - { - if (self.oRequests[sAction].__aborted) - { - sType = 'abort'; - } - - self.oRequests[sAction] = null; - } - - self.defaultResponse(fResultCallback, sAction, sType, oData, bCached, oParameters); - }); - - if (sAction && 0 < aAbortActions.length && -1 < Utils.inArray(sAction, aAbortActions)) - { - if (this.oRequests[sAction]) - { - this.oRequests[sAction].__aborted = true; - if (this.oRequests[sAction].abort) - { - this.oRequests[sAction].abort(); - } - this.oRequests[sAction] = null; - } - - this.oRequests[sAction] = oDefAjax; - } - - return oDefAjax; -}; - -/** - * @param {?Function} fCallback - * @param {string} sAction - * @param {Object=} oParameters - * @param {?number=} iTimeout - * @param {string=} sGetAdd = '' - * @param {Array=} aAbortActions = [] - */ -AbstractAjaxRemoteStorage.prototype.defaultRequest = function (fCallback, sAction, oParameters, iTimeout, sGetAdd, aAbortActions) -{ - oParameters = oParameters || {}; - oParameters.Action = sAction; - - sGetAdd = Utils.pString(sGetAdd); - - Plugins.runHook('ajax-default-request', [sAction, oParameters, sGetAdd]); - - this.ajaxRequest(fCallback, oParameters, - Utils.isUnd(iTimeout) ? Consts.Defaults.DefaultAjaxTimeout : Utils.pInt(iTimeout), sGetAdd, aAbortActions); -}; - -/** - * @param {?Function} fCallback - */ -AbstractAjaxRemoteStorage.prototype.noop = function (fCallback) -{ - this.defaultRequest(fCallback, 'Noop'); -}; - -/** - * @param {?Function} fCallback - * @param {string} sMessage - * @param {string} sFileName - * @param {number} iLineNo - * @param {string} sLocation - * @param {string} sHtmlCapa - * @param {number} iTime - */ -AbstractAjaxRemoteStorage.prototype.jsError = function (fCallback, sMessage, sFileName, iLineNo, sLocation, sHtmlCapa, iTime) -{ - this.defaultRequest(fCallback, 'JsError', { - 'Message': sMessage, - 'FileName': sFileName, - 'LineNo': iLineNo, - 'Location': sLocation, - 'HtmlCapa': sHtmlCapa, - 'TimeOnPage': iTime - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sType - * @param {Array=} mData = null - * @param {boolean=} bIsError = false - */ -AbstractAjaxRemoteStorage.prototype.jsInfo = function (fCallback, sType, mData, bIsError) -{ - this.defaultRequest(fCallback, 'JsInfo', { - 'Type': sType, - 'Data': mData, - 'IsError': (Utils.isUnd(bIsError) ? false : !!bIsError) ? '1' : '0' - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sVersion - */ -AbstractAjaxRemoteStorage.prototype.jsVersion = function (fCallback, sVersion) -{ - this.defaultRequest(fCallback, 'Version', { - 'Version': sVersion - }); -}; -/** - * @constructor - * @extends AbstractAjaxRemoteStorage - */ -function AdminAjaxRemoteStorage() -{ - AbstractAjaxRemoteStorage.call(this); - - this.oRequests = {}; -} - -_.extend(AdminAjaxRemoteStorage.prototype, AbstractAjaxRemoteStorage.prototype); - -/** - * @param {?Function} fCallback - * @param {string} sLogin - * @param {string} sPassword - */ -AdminAjaxRemoteStorage.prototype.adminLogin = function (fCallback, sLogin, sPassword) -{ - this.defaultRequest(fCallback, 'AdminLogin', { - 'Login': sLogin, - 'Password': sPassword - }); -}; - -/** - * @param {?Function} fCallback - */ -AdminAjaxRemoteStorage.prototype.adminLogout = function (fCallback) -{ - this.defaultRequest(fCallback, 'AdminLogout'); -}; - -/** - * @param {?Function} fCallback - * @param {?} oData - */ -AdminAjaxRemoteStorage.prototype.saveAdminConfig = function (fCallback, oData) -{ - this.defaultRequest(fCallback, 'AdminSettingsUpdate', oData); -}; - -/** - * @param {?Function} fCallback - */ -AdminAjaxRemoteStorage.prototype.domainList = function (fCallback) -{ - this.defaultRequest(fCallback, 'AdminDomainList'); -}; - -/** - * @param {?Function} fCallback - */ -AdminAjaxRemoteStorage.prototype.pluginList = function (fCallback) -{ - this.defaultRequest(fCallback, 'AdminPluginList'); -}; - -/** - * @param {?Function} fCallback - */ -AdminAjaxRemoteStorage.prototype.packagesList = function (fCallback) -{ - this.defaultRequest(fCallback, 'AdminPackagesList'); -}; - -/** - * @param {?Function} fCallback - * @param {Object} oPackage - */ -AdminAjaxRemoteStorage.prototype.packageInstall = function (fCallback, oPackage) -{ - this.defaultRequest(fCallback, 'AdminPackageInstall', { - 'Id': oPackage.id, - 'Type': oPackage.type, - 'File': oPackage.file - }, 60000); -}; - -/** - * @param {?Function} fCallback - * @param {Object} oPackage - */ -AdminAjaxRemoteStorage.prototype.packageDelete = function (fCallback, oPackage) -{ - this.defaultRequest(fCallback, 'AdminPackageDelete', { - 'Id': oPackage.id - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sName - */ -AdminAjaxRemoteStorage.prototype.domain = function (fCallback, sName) -{ - this.defaultRequest(fCallback, 'AdminDomainLoad', { - 'Name': sName - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sName - */ -AdminAjaxRemoteStorage.prototype.plugin = function (fCallback, sName) -{ - this.defaultRequest(fCallback, 'AdminPluginLoad', { - 'Name': sName - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sName - */ -AdminAjaxRemoteStorage.prototype.domainDelete = function (fCallback, sName) -{ - this.defaultRequest(fCallback, 'AdminDomainDelete', { - 'Name': sName - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sName - * @param {boolean} bDisabled - */ -AdminAjaxRemoteStorage.prototype.domainDisable = function (fCallback, sName, bDisabled) -{ - return this.defaultRequest(fCallback, 'AdminDomainDisable', { - 'Name': sName, - 'Disabled': !!bDisabled ? '1' : '0' - }); -}; - -/** - * @param {?Function} fCallback - * @param {Object} oConfig - */ -AdminAjaxRemoteStorage.prototype.pluginSettingsUpdate = function (fCallback, oConfig) -{ - return this.defaultRequest(fCallback, 'AdminPluginSettingsUpdate', oConfig); -}; - -/** - * @param {?Function} fCallback - * @param {boolean} bForce - */ -AdminAjaxRemoteStorage.prototype.licensing = function (fCallback, bForce) -{ - return this.defaultRequest(fCallback, 'AdminLicensing', { - 'Force' : bForce ? '1' : '0' - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sDomain - * @param {string} sKey - */ -AdminAjaxRemoteStorage.prototype.licensingActivate = function (fCallback, sDomain, sKey) -{ - return this.defaultRequest(fCallback, 'AdminLicensingActivate', { - 'Domain' : sDomain, - 'Key' : sKey - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sName - * @param {boolean} bDisabled - */ -AdminAjaxRemoteStorage.prototype.pluginDisable = function (fCallback, sName, bDisabled) -{ - return this.defaultRequest(fCallback, 'AdminPluginDisable', { - 'Name': sName, - 'Disabled': !!bDisabled ? '1' : '0' - }); -}; - -AdminAjaxRemoteStorage.prototype.createOrUpdateDomain = function (fCallback, - bCreate, sName, sIncHost, iIncPort, sIncSecure, bIncShortLogin, - sOutHost, iOutPort, sOutSecure, bOutShortLogin, bOutAuth, sWhiteList) -{ - this.defaultRequest(fCallback, 'AdminDomainSave', { - 'Create': bCreate ? '1' : '0', - 'Name': sName, - 'IncHost': sIncHost, - 'IncPort': iIncPort, - 'IncSecure': sIncSecure, - 'IncShortLogin': bIncShortLogin ? '1' : '0', - 'OutHost': sOutHost, - 'OutPort': iOutPort, - 'OutSecure': sOutSecure, - 'OutShortLogin': bOutShortLogin ? '1' : '0', - 'OutAuth': bOutAuth ? '1' : '0', - 'WhiteList': sWhiteList - }); -}; - -AdminAjaxRemoteStorage.prototype.testConnectionForDomain = function (fCallback, sName, - sIncHost, iIncPort, sIncSecure, - sOutHost, iOutPort, sOutSecure, bOutAuth) -{ - this.defaultRequest(fCallback, 'AdminDomainTest', { - 'Name': sName, - 'IncHost': sIncHost, - 'IncPort': iIncPort, - 'IncSecure': sIncSecure, - 'OutHost': sOutHost, - 'OutPort': iOutPort, - 'OutSecure': sOutSecure, - 'OutAuth': bOutAuth ? '1' : '0' - }); -}; - -/** - * @param {?Function} fCallback - * @param {?} oData - */ -AdminAjaxRemoteStorage.prototype.testContacts = function (fCallback, oData) -{ - this.defaultRequest(fCallback, 'AdminContactsTest', oData); -}; - -/** - * @param {?Function} fCallback - * @param {?} oData - */ -AdminAjaxRemoteStorage.prototype.saveNewAdminPassword = function (fCallback, oData) -{ - this.defaultRequest(fCallback, 'AdminPasswordUpdate', oData); -}; - -/** - * @param {?Function} fCallback - */ -AdminAjaxRemoteStorage.prototype.adminPing = function (fCallback) -{ - this.defaultRequest(fCallback, 'AdminPing'); -}; - -/** - * @constructor - */ -function AbstractCacheStorage() -{ - this.oEmailsPicsHashes = {}; - this.oServices = {}; - this.bAllowGravatar = !!RL.settingsGet('AllowGravatar'); -} - -/** - * @type {Object} - */ -AbstractCacheStorage.prototype.oEmailsPicsHashes = {}; - -/** - * @type {Object} - */ -AbstractCacheStorage.prototype.oServices = {}; - -/** - * @type {boolean} - */ -AbstractCacheStorage.prototype.bAllowGravatar = false; - -AbstractCacheStorage.prototype.clear = function () -{ - this.oServices = {}; - this.oEmailsPicsHashes = {}; -}; - -/** - * @param {string} sEmail - * @return {string} - */ -AbstractCacheStorage.prototype.getUserPic = function (sEmail, fCallback) -{ - sEmail = Utils.trim(sEmail); - - var - sUrl = '', - sService = '', - sEmailLower = sEmail.toLowerCase(), - sPicHash = Utils.isUnd(this.oEmailsPicsHashes[sEmailLower]) ? '' : this.oEmailsPicsHashes[sEmailLower] - ; - - if ('' !== sPicHash) - { - sUrl = RL.link().getUserPicUrlFromHash(sPicHash); - } - else - { - sService = sEmailLower.substr(sEmail.indexOf('@') + 1); - sUrl = '' !== sService && this.oServices[sService] ? this.oServices[sService] : ''; - } - - - if (this.bAllowGravatar && '' === sUrl) - { - fCallback('//secure.gravatar.com/avatar/' + Utils.md5(sEmailLower) + '.jpg?s=80&d=mm', sEmail); - } - else - { - fCallback(sUrl, sEmail); - } -}; - -/** - * @param {Object} oData - */ -AbstractCacheStorage.prototype.setServicesData = function (oData) -{ - this.oServices = oData; -}; - -/** - * @param {Object} oData - */ -AbstractCacheStorage.prototype.setEmailsPicsHashesData = function (oData) -{ - this.oEmailsPicsHashes = oData; -}; - -/** - * @constructor - * @extends AbstractCacheStorage - */ -function AdminCacheStorage() -{ - AbstractCacheStorage.call(this); -} - -_.extend(AdminCacheStorage.prototype, AbstractCacheStorage.prototype); - -/** - * @param {Array} aViewModels - * @constructor - * @extends KnoinAbstractScreen - */ -function AbstractSettings(aViewModels) -{ - KnoinAbstractScreen.call(this, 'settings', aViewModels); - - this.menu = ko.observableArray([]); - - this.oCurrentSubScreen = null; - this.oViewModelPlace = null; -} - -_.extend(AbstractSettings.prototype, KnoinAbstractScreen.prototype); - -AbstractSettings.prototype.onRoute = function (sSubName) -{ - var - self = this, - oSettingsScreen = null, - RoutedSettingsViewModel = null, - oViewModelPlace = null, - oViewModelDom = null - ; - - RoutedSettingsViewModel = _.find(ViewModels['settings'], function (SettingsViewModel) { - return SettingsViewModel && SettingsViewModel.__rlSettingsData && - sSubName === SettingsViewModel.__rlSettingsData.Route; - }); - - if (RoutedSettingsViewModel) - { - if (_.find(ViewModels['settings-removed'], function (DisabledSettingsViewModel) { - return DisabledSettingsViewModel && DisabledSettingsViewModel === RoutedSettingsViewModel; - })) - { - RoutedSettingsViewModel = null; - } - - if (RoutedSettingsViewModel && _.find(ViewModels['settings-disabled'], function (DisabledSettingsViewModel) { - return DisabledSettingsViewModel && DisabledSettingsViewModel === RoutedSettingsViewModel; - })) - { - RoutedSettingsViewModel = null; - } - } - - if (RoutedSettingsViewModel) - { - if (RoutedSettingsViewModel.__builded && RoutedSettingsViewModel.__vm) - { - oSettingsScreen = RoutedSettingsViewModel.__vm; - } - else - { - oViewModelPlace = this.oViewModelPlace; - if (oViewModelPlace && 1 === oViewModelPlace.length) - { - RoutedSettingsViewModel = /** @type {?Function} */ RoutedSettingsViewModel; - oSettingsScreen = new RoutedSettingsViewModel(); - - oViewModelDom = $('').addClass('rl-settings-view-model').hide().attr('data-bind', - 'template: {name: "' + RoutedSettingsViewModel.__rlSettingsData.Template + '"}, i18nInit: true'); - - oViewModelDom.appendTo(oViewModelPlace); - - oSettingsScreen.data = RL.data(); - oSettingsScreen.viewModelDom = oViewModelDom; - - oSettingsScreen.__rlSettingsData = RoutedSettingsViewModel.__rlSettingsData; - - RoutedSettingsViewModel.__dom = oViewModelDom; - RoutedSettingsViewModel.__builded = true; - RoutedSettingsViewModel.__vm = oSettingsScreen; - - ko.applyBindings(oSettingsScreen, oViewModelDom[0]); - Utils.delegateRun(oSettingsScreen, 'onBuild', [oViewModelDom]); - } - else - { - Utils.log('Cannot find sub settings view model position: SettingsSubScreen'); - } - } - - if (oSettingsScreen) - { - _.defer(function () { - // hide - if (self.oCurrentSubScreen) - { - Utils.delegateRun(self.oCurrentSubScreen, 'onHide'); - self.oCurrentSubScreen.viewModelDom.hide(); - } - // -- - - self.oCurrentSubScreen = oSettingsScreen; - - // show - if (self.oCurrentSubScreen) - { - self.oCurrentSubScreen.viewModelDom.show(); - Utils.delegateRun(self.oCurrentSubScreen, 'onShow'); - Utils.delegateRun(self.oCurrentSubScreen, 'onFocus', [], 200); - - _.each(self.menu(), function (oItem) { - oItem.selected(oSettingsScreen && oSettingsScreen.__rlSettingsData && oItem.route === oSettingsScreen.__rlSettingsData.Route); - }); - - $('#rl-content .b-settings .b-content .content').scrollTop(0); - } - // -- - - Utils.windowResize(); - }); - } - } - else - { - kn.setHash(RL.link().settings(), false, true); - } -}; - -AbstractSettings.prototype.onHide = function () -{ - if (this.oCurrentSubScreen && this.oCurrentSubScreen.viewModelDom) - { - Utils.delegateRun(this.oCurrentSubScreen, 'onHide'); - this.oCurrentSubScreen.viewModelDom.hide(); - } -}; - -AbstractSettings.prototype.onBuild = function () -{ - _.each(ViewModels['settings'], function (SettingsViewModel) { - if (SettingsViewModel && SettingsViewModel.__rlSettingsData && - !_.find(ViewModels['settings-removed'], function (RemoveSettingsViewModel) { - return RemoveSettingsViewModel && RemoveSettingsViewModel === SettingsViewModel; - })) - { - this.menu.push({ - 'route': SettingsViewModel.__rlSettingsData.Route, - 'label': SettingsViewModel.__rlSettingsData.Label, - 'selected': ko.observable(false), - 'disabled': !!_.find(ViewModels['settings-disabled'], function (DisabledSettingsViewModel) { - return DisabledSettingsViewModel && DisabledSettingsViewModel === SettingsViewModel; - }) - }); - } - }, this); - - this.oViewModelPlace = $('#rl-content #rl-settings-subscreen'); -}; - -AbstractSettings.prototype.routes = function () -{ - var - DefaultViewModel = _.find(ViewModels['settings'], function (SettingsViewModel) { - return SettingsViewModel && SettingsViewModel.__rlSettingsData && SettingsViewModel.__rlSettingsData['IsDefault']; - }), - sDefaultRoute = DefaultViewModel ? DefaultViewModel.__rlSettingsData['Route'] : 'general', - oRules = { - 'subname': /^(.*)$/, - 'normalize_': function (oRequest, oVals) { - oVals.subname = Utils.isUnd(oVals.subname) ? sDefaultRoute : Utils.pString(oVals.subname); - return [oVals.subname]; - } - } - ; - - return [ - ['{subname}/', oRules], - ['{subname}', oRules], - ['', oRules] - ]; -}; - -/** - * @constructor - * @extends KnoinAbstractScreen - */ -function AdminLoginScreen() -{ - KnoinAbstractScreen.call(this, 'login', [AdminLoginViewModel]); -} - -_.extend(AdminLoginScreen.prototype, KnoinAbstractScreen.prototype); - -AdminLoginScreen.prototype.onShow = function () -{ - RL.setTitle(''); +ko.bindingHandlers.openDropdownTrigger = { + 'update': function (oElement, fValueAccessor) { + if (ko.utils.unwrapObservable(fValueAccessor())) + { + var $el = $(oElement); + if (!$el.hasClass('open')) + { + $el.find('.dropdown-toggle').dropdown('toggle'); + Utils.detectDropdownVisibility(); + } + + fValueAccessor()(false); + } + } }; -/** - * @constructor - * @extends AbstractSettings - */ -function AdminSettingsScreen() -{ - AbstractSettings.call(this, [ - AdminMenuViewModel, - AdminPaneViewModel - ]); -} - -_.extend(AdminSettingsScreen.prototype, AbstractSettings.prototype); - -AdminSettingsScreen.prototype.onShow = function () -{ -// AbstractSettings.prototype.onShow.call(this); - - RL.setTitle(''); + +ko.bindingHandlers.dropdownCloser = { + 'init': function (oElement) { + $(oElement).closest('.dropdown').on('click', '.e-item', function () { + $(oElement).dropdown('toggle'); + }); + } }; -/** - * @constructor - * @extends KnoinAbstractBoot - */ -function AbstractApp() -{ - KnoinAbstractBoot.call(this); - - this.oSettings = null; - this.oPlugins = null; - this.oLocal = null; - this.oLink = null; - this.oSubs = {}; - - this.isLocalAutocomplete = true; - - this.popupVisibilityNames = ko.observableArray([]); - - this.popupVisibility = ko.computed(function () { - return 0 < this.popupVisibilityNames().length; - }, this); - - this.iframe = $('').appendTo('body'); - - $window.on('error', function (oEvent) { - if (RL && oEvent && oEvent.originalEvent && oEvent.originalEvent.message && - -1 === Utils.inArray(oEvent.originalEvent.message, [ - 'Script error.', 'Uncaught Error: Error calling method on NPObject.' - ])) - { - RL.remote().jsError( - Utils.emptyFunction, - oEvent.originalEvent.message, - oEvent.originalEvent.filename, - oEvent.originalEvent.lineno, - location && location.toString ? location.toString() : '', - $html.attr('class'), - Utils.microtime() - Globals.now - ); - } - }); - - $document.on('keydown', function (oEvent) { - if (oEvent && oEvent.ctrlKey) - { - $html.addClass('rl-ctrl-key-pressed'); - } - }).on('keyup', function (oEvent) { - if (oEvent && !oEvent.ctrlKey) - { - $html.removeClass('rl-ctrl-key-pressed'); - } - }); -} - -_.extend(AbstractApp.prototype, KnoinAbstractBoot.prototype); - -AbstractApp.prototype.oSettings = null; -AbstractApp.prototype.oPlugins = null; -AbstractApp.prototype.oLocal = null; -AbstractApp.prototype.oLink = null; -AbstractApp.prototype.oSubs = {}; - -/** - * @param {string} sLink - * @return {boolean} - */ -AbstractApp.prototype.download = function (sLink) -{ - var - oLink = null, - oE = null, - sUserAgent = navigator.userAgent.toLowerCase() - ; - - if (sUserAgent && (sUserAgent.indexOf('chrome') > -1 || sUserAgent.indexOf('chrome') > -1)) - { - oLink = document.createElement('a'); - oLink['href'] = sLink; - - if (document['createEvent']) - { - oE = document['createEvent']('MouseEvents'); - if (oE && oE['initEvent'] && oLink['dispatchEvent']) - { - oE['initEvent']('click', true, true); - oLink['dispatchEvent'](oE); - return true; - } - } - } - - if (Globals.bMobileDevice) - { - window.open(sLink, '_self'); - window.focus(); - } - else - { - this.iframe.attr('src', sLink); -// window.document.location.href = sLink; - } - - return true; -}; - -/** - * @return {LinkBuilder} - */ -AbstractApp.prototype.link = function () -{ - if (null === this.oLink) - { - this.oLink = new LinkBuilder(); - } - - return this.oLink; -}; - -/** - * @return {LocalStorage} - */ -AbstractApp.prototype.local = function () -{ - if (null === this.oLocal) - { - this.oLocal = new LocalStorage(); - } - - return this.oLocal; -}; - -/** - * @param {string} sName - * @return {?} - */ -AbstractApp.prototype.settingsGet = function (sName) -{ - if (null === this.oSettings) - { - this.oSettings = Utils.isNormal(AppData) ? AppData : {}; - } - - return Utils.isUnd(this.oSettings[sName]) ? null : this.oSettings[sName]; -}; - -/** - * @param {string} sName - * @param {?} mValue - */ -AbstractApp.prototype.settingsSet = function (sName, mValue) -{ - if (null === this.oSettings) - { - this.oSettings = Utils.isNormal(AppData) ? AppData : {}; - } - - this.oSettings[sName] = mValue; -}; - -AbstractApp.prototype.setTitle = function (sTitle) -{ - sTitle = ((Utils.isNormal(sTitle) && 0 < sTitle.length) ? sTitle + ' - ' : '') + - RL.settingsGet('Title') || ''; - - window.document.title = '_'; - window.document.title = sTitle; -}; - -/** - * @param {boolean=} bLogout = false - * @param {boolean=} bClose = false - */ -AbstractApp.prototype.loginAndLogoutReload = function (bLogout, bClose) -{ - var - sCustomLogoutLink = Utils.pString(RL.settingsGet('CustomLogoutLink')), - bInIframe = !!RL.settingsGet('InIframe') - ; - - bLogout = Utils.isUnd(bLogout) ? false : !!bLogout; - bClose = Utils.isUnd(bClose) ? false : !!bClose; - - if (bLogout && bClose && window.close) - { - window.close(); - } - - if (bLogout && '' !== sCustomLogoutLink && window.location.href !== sCustomLogoutLink) - { - _.delay(function () { - if (bInIframe && window.parent) - { - window.parent.location.href = sCustomLogoutLink; - } - else - { - window.location.href = sCustomLogoutLink; - } - }, 100); - } - else - { - kn.routeOff(); - kn.setHash(RL.link().root(), true); - kn.routeOff(); - - _.delay(function () { - if (bInIframe && window.parent) - { - window.parent.location.reload(); - } - else - { - window.location.reload(); - } - }, 100); - } -}; - -AbstractApp.prototype.historyBack = function () -{ - window.history.back(); -}; - -/** - * @param {string} sQuery - * @param {Function} fCallback - */ -AbstractApp.prototype.getAutocomplete = function (sQuery, fCallback) -{ - fCallback([], sQuery); -}; - -/** - * @param {string} sName - * @param {Function} fFunc - * @param {Object=} oContext - * @return {AbstractApp} - */ -AbstractApp.prototype.sub = function (sName, fFunc, oContext) -{ - if (Utils.isUnd(this.oSubs[sName])) - { - this.oSubs[sName] = []; - } - - this.oSubs[sName].push([fFunc, oContext]); - - return this; -}; - -/** - * @param {string} sName - * @param {Array=} aArgs - * @return {AbstractApp} - */ -AbstractApp.prototype.pub = function (sName, aArgs) -{ - Plugins.runHook('rl-pub', [sName, aArgs]); - if (!Utils.isUnd(this.oSubs[sName])) - { - _.each(this.oSubs[sName], function (aItem) { - if (aItem[0]) - { - aItem[0].apply(aItem[1] || null, aArgs || []); - } - }); - } - - return this; -}; - -AbstractApp.prototype.bootstart = function () -{ - var self = this; - - Utils.initOnStartOrLangChange(function () { - Utils.initNotificationLanguage(); - }, null); - - _.delay(function () { - Utils.windowResize(); - }, 1000); - - ssm.addState({ - 'id': 'mobile', - 'maxWidth': 767, - 'onEnter': function() { - $html.addClass('ssm-state-mobile'); - self.pub('ssm.mobile-enter'); - }, - 'onLeave': function() { - $html.removeClass('ssm-state-mobile'); - self.pub('ssm.mobile-leave'); - } - }); - - ssm.addState({ - 'id': 'tablet', - 'minWidth': 768, - 'maxWidth': 999, - 'onEnter': function() { - $html.addClass('ssm-state-tablet'); - }, - 'onLeave': function() { - $html.removeClass('ssm-state-tablet'); - } - }); - - ssm.addState({ - 'id': 'desktop', - 'minWidth': 1000, - 'maxWidth': 1400, - 'onEnter': function() { - $html.addClass('ssm-state-desktop'); - }, - 'onLeave': function() { - $html.removeClass('ssm-state-desktop'); - } - }); - - ssm.addState({ - 'id': 'desktop-large', - 'minWidth': 1400, - 'onEnter': function() { - $html.addClass('ssm-state-desktop-large'); - }, - 'onLeave': function() { - $html.removeClass('ssm-state-desktop-large'); - } - }); - - RL.sub('ssm.mobile-enter', function () { - RL.data().leftPanelDisabled(true); - }); - - RL.sub('ssm.mobile-leave', function () { - RL.data().leftPanelDisabled(false); - }); - - RL.data().leftPanelDisabled.subscribe(function (bValue) { - $html.toggleClass('rl-left-panel-disabled', bValue); - }); - - ssm.ready(); -}; -/** - * @constructor - * @extends AbstractApp - */ -function AdminApp() -{ - AbstractApp.call(this); - - this.oData = null; - this.oRemote = null; - this.oCache = null; -} - -_.extend(AdminApp.prototype, AbstractApp.prototype); - -AdminApp.prototype.oData = null; -AdminApp.prototype.oRemote = null; -AdminApp.prototype.oCache = null; - -/** - * @return {AdminDataStorage} - */ -AdminApp.prototype.data = function () -{ - if (null === this.oData) - { - this.oData = new AdminDataStorage(); - } - - return this.oData; -}; - -/** - * @return {AdminAjaxRemoteStorage} - */ -AdminApp.prototype.remote = function () -{ - if (null === this.oRemote) - { - this.oRemote = new AdminAjaxRemoteStorage(); - } - - return this.oRemote; -}; - -/** - * @return {AdminCacheStorage} - */ -AdminApp.prototype.cache = function () -{ - if (null === this.oCache) - { - this.oCache = new AdminCacheStorage(); - } - - return this.oCache; -}; - -AdminApp.prototype.reloadDomainList = function () -{ - RL.data().domainsLoading(true); - RL.remote().domainList(function (sResult, oData) { - RL.data().domainsLoading(false); - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - var aList = _.map(oData.Result, function (bEnabled, sName) { - return { - 'name': sName, - 'disabled': ko.observable(!bEnabled), - 'deleteAccess': ko.observable(false) - }; - }, this); - - RL.data().domains(aList); - } - }); -}; - -AdminApp.prototype.reloadPluginList = function () -{ - RL.data().pluginsLoading(true); - RL.remote().pluginList(function (sResult, oData) { - RL.data().pluginsLoading(false); - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - var aList = _.map(oData.Result, function (oItem) { - return { - 'name': oItem['Name'], - 'disabled': ko.observable(!oItem['Enabled']), - 'configured': ko.observable(!!oItem['Configured']) - }; - }, this); - - RL.data().plugins(aList); - } - }); -}; - -AdminApp.prototype.reloadPackagesList = function () -{ - RL.data().packagesLoading(true); - RL.data().packagesReal(true); - - RL.remote().packagesList(function (sResult, oData) { - - RL.data().packagesLoading(false); - - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - RL.data().packagesReal(!!oData.Result.Real); - RL.data().packagesMainUpdatable(!!oData.Result.MainUpdatable); - - var - aList = [], - aLoading = {} - ; - - _.each(RL.data().packages(), function (oItem) { - if (oItem && oItem['loading']()) - { - aLoading[oItem['file']] = oItem; - } - }); - - if (Utils.isArray(oData.Result.List)) - { - aList = _.compact(_.map(oData.Result.List, function (oItem) { - if (oItem) - { - oItem['loading'] = ko.observable(!Utils.isUnd(aLoading[oItem['file']])); - return 'core' === oItem['type'] && !oItem['canBeInstalled'] ? null : oItem; - } - return null; - })); - } - - RL.data().packages(aList); - } - else - { - RL.data().packagesReal(false); - } - }); -}; - -/** - * - * @param {boolean=} bForce = false - */ -AdminApp.prototype.reloadLicensing = function (bForce) -{ - bForce = Utils.isUnd(bForce) ? false : !!bForce; - - RL.data().licensingProcess(true); - RL.data().licenseError(''); - - RL.remote().licensing(function (sResult, oData) { - RL.data().licensingProcess(false); - if (Enums.StorageResultType.Success === sResult && oData && oData.Result && Utils.isNormal(oData.Result['Expired'])) - { - RL.data().licenseValid(true); - RL.data().licenseExpired(Utils.pInt(oData.Result['Expired'])); - RL.data().licenseError(''); - - RL.data().licensing(true); - } - else - { - if (oData && oData.ErrorCode && -1 < Utils.inArray(Utils.pInt(oData.ErrorCode), [ - Enums.Notification.LicensingServerIsUnavailable, - Enums.Notification.LicensingExpired - ])) - { - RL.data().licenseError(Utils.getNotification(Utils.pInt(oData.ErrorCode))); - RL.data().licensing(true); - } - else - { - if (Enums.StorageResultType.Abort === sResult) - { - RL.data().licenseError(Utils.getNotification(Enums.Notification.LicensingServerIsUnavailable)); - RL.data().licensing(true); - } - else - { - RL.data().licensing(false); - } - } - } - }, bForce); -}; - -AdminApp.prototype.bootstart = function () -{ - AbstractApp.prototype.bootstart.call(this); - - RL.data().populateDataOnStart(); - - kn.hideLoading(); - - if (!RL.settingsGet('AllowAdminPanel')) - { - kn.routeOff(); - kn.setHash(RL.link().root(), true); - kn.routeOff(); - - _.defer(function () { - window.location.href = '/'; - }); - } - else - { - if (!!RL.settingsGet('Auth')) - { -// TODO -// if (!RL.settingsGet('AllowPackages') && AdminPackages) -// { -// Utils.disableSettingsViewModel(AdminPackages); -// } - - kn.startScreens([AdminSettingsScreen]); - } - else - { - kn.startScreens([AdminLoginScreen]); - } - } - - if (window.SimplePace) - { - window.SimplePace.set(100); - } -}; - -/** - * @type {AdminApp} - */ -RL = new AdminApp(); +ko.bindingHandlers.popover = { + 'init': function (oElement, fValueAccessor) { + $(oElement).popover(ko.utils.unwrapObservable(fValueAccessor())); + } +}; -$html.addClass(Globals.bMobileDevice ? 'mobile' : 'no-mobile'); - -$window.keydown(Utils.killCtrlAandS).keyup(Utils.killCtrlAandS); -$window.unload(function () { - Globals.bUnload = true; -}); - -$html.on('click.dropdown.data-api', function () { - Utils.detectDropdownVisibility(); -}); - -// export -window['rl'] = window['rl'] || {}; -window['rl']['addHook'] = Plugins.addHook; -window['rl']['settingsGet'] = Plugins.mainSettingsGet; -window['rl']['remoteRequest'] = Plugins.remoteRequest; -window['rl']['pluginSettingsGet'] = Plugins.settingsGet; -window['rl']['addSettingsViewModel'] = Utils.addSettingsViewModel; -window['rl']['createCommand'] = Utils.createCommand; - -window['rl']['EmailModel'] = EmailModel; -window['rl']['Enums'] = Enums; - -window['__RLBOOT'] = function (fCall) { - - // boot - $(function () { - - if (window['rainloopTEMPLATES'] && window['rainloopTEMPLATES'][0]) - { - $('#rl-templates').html(window['rainloopTEMPLATES'][0]); - - _.delay(function () { - window['rainloopAppData'] = {}; - window['rainloopI18N'] = {}; - window['rainloopTEMPLATES'] = {}; - - kn.setBoot(RL).bootstart(); - $html.removeClass('no-js rl-booted-trigger').addClass('rl-booted'); - - }, 50); - } - else - { - fCall(false); - } - - window['__RLBOOT'] = null; - }); -}; +ko.bindingHandlers.csstext = { + 'init': function (oElement, fValueAccessor) { + if (oElement && oElement.styleSheet && !Utils.isUnd(oElement.styleSheet.cssText)) + { + oElement.styleSheet.cssText = ko.utils.unwrapObservable(fValueAccessor()); + } + else + { + $(oElement).text(ko.utils.unwrapObservable(fValueAccessor())); + } + }, + 'update': function (oElement, fValueAccessor) { + if (oElement && oElement.styleSheet && !Utils.isUnd(oElement.styleSheet.cssText)) + { + oElement.styleSheet.cssText = ko.utils.unwrapObservable(fValueAccessor()); + } + else + { + $(oElement).text(ko.utils.unwrapObservable(fValueAccessor())); + } + } +}; -if (window.SimplePace) { - window.SimplePace.add(10); +ko.bindingHandlers.resizecrop = { + 'init': function (oElement) { + $(oElement).addClass('resizecrop').resizecrop({ + 'width': '100', + 'height': '100', + 'wrapperCSS': { + 'border-radius': '10px' + } + }); + }, + 'update': function (oElement, fValueAccessor) { + fValueAccessor()(); + $(oElement).resizecrop({ + 'width': '100', + 'height': '100' + }); + } +}; + +ko.bindingHandlers.onEnter = { + 'init': function (oElement, fValueAccessor, fAllBindingsAccessor, oViewModel) { + $(oElement).on('keypress', function (oEvent) { + if (oEvent && 13 === window.parseInt(oEvent.keyCode, 10)) + { + $(oElement).trigger('change'); + fValueAccessor().call(oViewModel); + } + }); + } +}; + +ko.bindingHandlers.onEsc = { + 'init': function (oElement, fValueAccessor, fAllBindingsAccessor, oViewModel) { + $(oElement).on('keypress', function (oEvent) { + if (oEvent && 27 === window.parseInt(oEvent.keyCode, 10)) + { + $(oElement).trigger('change'); + fValueAccessor().call(oViewModel); + } + }); + } +}; + +ko.bindingHandlers.clickOnTrue = { + 'update': function (oElement, fValueAccessor) { + if (ko.utils.unwrapObservable(fValueAccessor())) + { + $(oElement).click(); + } + } +}; + +ko.bindingHandlers.modal = { + 'init': function (oElement, fValueAccessor) { + + $(oElement).toggleClass('fade', !Globals.bMobileDevice).modal({ + 'keyboard': false, + 'show': ko.utils.unwrapObservable(fValueAccessor()) + }) + .on('shown', function () { + Utils.windowResize(); + }) + .find('.close').click(function () { + fValueAccessor()(false); + }); + }, + 'update': function (oElement, fValueAccessor) { + $(oElement).modal(ko.utils.unwrapObservable(fValueAccessor()) ? 'show' : 'hide'); + } +}; + +ko.bindingHandlers.i18nInit = { + 'init': function (oElement) { + Utils.i18nToNode(oElement); + } +}; + +ko.bindingHandlers.i18nUpdate = { + 'update': function (oElement, fValueAccessor) { + ko.utils.unwrapObservable(fValueAccessor()); + Utils.i18nToNode(oElement); + } +}; + +ko.bindingHandlers.link = { + 'update': function (oElement, fValueAccessor) { + $(oElement).attr('href', ko.utils.unwrapObservable(fValueAccessor())); + } +}; + +ko.bindingHandlers.title = { + 'update': function (oElement, fValueAccessor) { + $(oElement).attr('title', ko.utils.unwrapObservable(fValueAccessor())); + } +}; + +ko.bindingHandlers.textF = { + 'init': function (oElement, fValueAccessor) { + $(oElement).text(ko.utils.unwrapObservable(fValueAccessor())); + } +}; + +ko.bindingHandlers.initDom = { + 'init': function (oElement, fValueAccessor) { + fValueAccessor()(oElement); + } +}; + +ko.bindingHandlers.initResizeTrigger = { + 'init': function (oElement, fValueAccessor) { + var aValues = ko.utils.unwrapObservable(fValueAccessor()); + $(oElement).css({ + 'height': aValues[1], + 'min-height': aValues[1] + }); + }, + 'update': function (oElement, fValueAccessor) { + var + aValues = ko.utils.unwrapObservable(fValueAccessor()), + iValue = Utils.pInt(aValues[1]), + iSize = 0, + iOffset = $(oElement).offset().top + ; + + if (0 < iOffset) + { + iOffset += Utils.pInt(aValues[2]); + iSize = $window.height() - iOffset; + + if (iValue < iSize) + { + iValue = iSize; + } + + $(oElement).css({ + 'height': iValue, + 'min-height': iValue + }); + } + } +}; + +ko.bindingHandlers.appendDom = { + 'update': function (oElement, fValueAccessor) { + $(oElement).hide().empty().append(ko.utils.unwrapObservable(fValueAccessor())).show(); + } +}; + +ko.bindingHandlers.draggable = { + 'init': function (oElement, fValueAccessor, fAllBindingsAccessor) { + + if (!Globals.bMobileDevice) + { + var + iTriggerZone = 100, + iScrollSpeed = 3, + fAllValueFunc = fAllBindingsAccessor(), + sDroppableSelector = fAllValueFunc && fAllValueFunc['droppableSelector'] ? fAllValueFunc['droppableSelector'] : '', + oConf = { + 'distance': 20, + 'handle': '.dragHandle', + 'cursorAt': {'top': 22, 'left': 3}, + 'refreshPositions': true, + 'scroll': true + } + ; + + if (sDroppableSelector) + { + oConf['drag'] = function (oEvent) { + + $(sDroppableSelector).each(function () { + var + moveUp = null, + moveDown = null, + $this = $(this), + oOffset = $this.offset(), + bottomPos = oOffset.top + $this.height() + ; + + window.clearInterval($this.data('timerScroll')); + $this.data('timerScroll', false); + + if (oEvent.pageX >= oOffset.left && oEvent.pageX <= oOffset.left + $this.width()) + { + if (oEvent.pageY >= bottomPos - iTriggerZone && oEvent.pageY <= bottomPos) + { + moveUp = function() { + $this.scrollTop($this.scrollTop() + iScrollSpeed); + Utils.windowResize(); + }; + + $this.data('timerScroll', window.setInterval(moveUp, 10)); + moveUp(); + } + + if (oEvent.pageY >= oOffset.top && oEvent.pageY <= oOffset.top + iTriggerZone) + { + moveDown = function() { + $this.scrollTop($this.scrollTop() - iScrollSpeed); + Utils.windowResize(); + }; + + $this.data('timerScroll', window.setInterval(moveDown, 10)); + moveDown(); + } + } + }); + }; + + oConf['stop'] = function() { + $(sDroppableSelector).each(function () { + window.clearInterval($(this).data('timerScroll')); + $(this).data('timerScroll', false); + }); + }; + } + + oConf['helper'] = function (oEvent) { + return fValueAccessor()(oEvent && oEvent.target ? ko.dataFor(oEvent.target) : null); + }; + + $(oElement).draggable(oConf).on('mousedown', function () { + Utils.removeInFocus(); + }); + } + } +}; + +ko.bindingHandlers.droppable = { + 'init': function (oElement, fValueAccessor, fAllBindingsAccessor) { + + if (!Globals.bMobileDevice) + { + var + fValueFunc = fValueAccessor(), + fAllValueFunc = fAllBindingsAccessor(), + fOverCallback = fAllValueFunc && fAllValueFunc['droppableOver'] ? fAllValueFunc['droppableOver'] : null, + fOutCallback = fAllValueFunc && fAllValueFunc['droppableOut'] ? fAllValueFunc['droppableOut'] : null, + oConf = { + 'tolerance': 'pointer', + 'hoverClass': 'droppableHover' + } + ; + + if (fValueFunc) + { + oConf['drop'] = function (oEvent, oUi) { + fValueFunc(oEvent, oUi); + }; + + if (fOverCallback) + { + oConf['over'] = function (oEvent, oUi) { + fOverCallback(oEvent, oUi); + }; + } + + if (fOutCallback) + { + oConf['out'] = function (oEvent, oUi) { + fOutCallback(oEvent, oUi); + }; + } + + $(oElement).droppable(oConf); + } + } + } +}; + +ko.bindingHandlers.nano = { + 'init': function (oElement) { + if (!Globals.bDisableNanoScroll) + { + $(oElement) + .addClass('nano') + .nanoScroller({ + 'iOSNativeScrolling': false, + 'preventPageScrolling': true + }) + ; + } + } +}; + +ko.bindingHandlers.saveTrigger = { + 'init': function (oElement) { + + var $oEl = $(oElement); + + $oEl.data('save-trigger-type', $oEl.is('input[type=text],input[type=email],input[type=password],select,textarea') ? 'input' : 'custom'); + + if ('custom' === $oEl.data('save-trigger-type')) + { + $oEl.append( + ' ' + ).addClass('settings-saved-trigger'); + } + else + { + $oEl.addClass('settings-saved-trigger-input'); + } + }, + 'update': function (oElement, fValueAccessor) { + var + mValue = ko.utils.unwrapObservable(fValueAccessor()), + $oEl = $(oElement) + ; + + if ('custom' === $oEl.data('save-trigger-type')) + { + switch (mValue.toString()) + { + case '1': + $oEl + .find('.animated,.error').hide().removeClass('visible') + .end() + .find('.success').show().addClass('visible') + ; + break; + case '0': + $oEl + .find('.animated,.success').hide().removeClass('visible') + .end() + .find('.error').show().addClass('visible') + ; + break; + case '-2': + $oEl + .find('.error,.success').hide().removeClass('visible') + .end() + .find('.animated').show().addClass('visible') + ; + break; + default: + $oEl + .find('.animated').hide() + .end() + .find('.error,.success').removeClass('visible') + ; + break; + } + } + else + { + switch (mValue.toString()) + { + case '1': + $oEl.addClass('success').removeClass('error'); + break; + case '0': + $oEl.addClass('error').removeClass('success'); + break; + case '-2': +// $oEl; + break; + default: + $oEl.removeClass('error success'); + break; + } + } + } +}; + +ko.bindingHandlers.emailsTags = { + 'init': function(oElement, fValueAccessor) { + var + $oEl = $(oElement), + fValue = fValueAccessor() + ; + + $oEl.inputosaurus({ + 'parseOnBlur': true, + 'inputDelimiters': [',', ';'], + 'autoCompleteSource': function (oData, fResponse) { + RL.getAutocomplete(oData.term, function (aData) { + fResponse(_.map(aData, function (oEmailItem) { + return oEmailItem.toLine(false); + })); + }); + }, + 'parseHook': function (aInput) { + return _.map(aInput, function (sInputValue) { + + var + sValue = Utils.trim(sInputValue), + oEmail = null + ; + + if ('' !== sValue) + { + oEmail = new EmailModel(); + oEmail.mailsoParse(sValue); + oEmail.clearDuplicateName(); + return [oEmail.toLine(false), oEmail]; + } + + return [sValue, null]; + + }); + }, + 'change': _.bind(function (oEvent) { + $oEl.data('EmailsTagsValue', oEvent.target.value); + fValue(oEvent.target.value); + }, this) + }); + + fValue.subscribe(function (sValue) { + if ($oEl.data('EmailsTagsValue') !== sValue) + { + $oEl.val(sValue); + $oEl.data('EmailsTagsValue', sValue); + $oEl.inputosaurus('refresh'); + } + }); + + if (fValue.focusTrigger) + { + fValue.focusTrigger.subscribe(function () { + $oEl.inputosaurus('focus'); + }); + } + } +}; + +ko.bindingHandlers.command = { + 'init': function (oElement, fValueAccessor, fAllBindingsAccessor, oViewModel) { + var + jqElement = $(oElement), + oCommand = fValueAccessor() + ; + + if (!oCommand || !oCommand.enabled || !oCommand.canExecute) + { + throw new Error('You are not using command function'); + } + + jqElement.addClass('command'); + ko.bindingHandlers[jqElement.is('form') ? 'submit' : 'click'].init.apply(oViewModel, arguments); + }, + + 'update': function (oElement, fValueAccessor) { + + var + bResult = true, + jqElement = $(oElement), + oCommand = fValueAccessor() + ; + + bResult = oCommand.enabled(); + jqElement.toggleClass('command-not-enabled', !bResult); + + if (bResult) + { + bResult = oCommand.canExecute(); + jqElement.toggleClass('command-can-not-be-execute', !bResult); + } + + jqElement.toggleClass('command-disabled disable disabled', !bResult).toggleClass('no-disabled', !!bResult); + + if (jqElement.is('input') || jqElement.is('button')) + { + jqElement.prop('disabled', !bResult); + } + } +}; + +ko.extenders.trimmer = function (oTarget) +{ + var oResult = ko.computed({ + 'read': oTarget, + 'write': function (sNewValue) { + oTarget(Utils.trim(sNewValue.toString())); + }, + 'owner': this + }); + + oResult(oTarget()); + return oResult; +}; + +ko.extenders.reversible = function (oTarget) +{ + var mValue = oTarget(); + + oTarget.commit = function () + { + mValue = oTarget(); + }; + + oTarget.reverse = function () + { + oTarget(mValue); + }; + + oTarget.commitedValue = function () + { + return mValue; + }; + + return oTarget; +}; + +ko.extenders.toggleSubscribe = function (oTarget, oOptions) +{ + oTarget.subscribe(oOptions[1], oOptions[0], 'beforeChange'); + oTarget.subscribe(oOptions[2], oOptions[0]); + + return oTarget; +}; + +ko.extenders.falseTimeout = function (oTarget, iOption) +{ + oTarget.iTimeout = 0; + oTarget.subscribe(function (bValue) { + if (bValue) + { + window.clearTimeout(oTarget.iTimeout); + oTarget.iTimeout = window.setTimeout(function () { + oTarget(false); + oTarget.iTimeout = 0; + }, Utils.pInt(iOption)); + } + }); + + return oTarget; +}; + +ko.observable.fn.validateNone = function () +{ + this.hasError = ko.observable(false); + return this; +}; + +ko.observable.fn.validateEmail = function () +{ + this.hasError = ko.observable(false); + + this.subscribe(function (sValue) { + sValue = Utils.trim(sValue); + this.hasError('' !== sValue && !(/^[^@\s]+@[^@\s]+$/.test(sValue))); + }, this); + + this.valueHasMutated(); + return this; +}; + +ko.observable.fn.validateSimpleEmail = function () +{ + this.hasError = ko.observable(false); + + this.subscribe(function (sValue) { + sValue = Utils.trim(sValue); + this.hasError('' !== sValue && !(/^.+@.+$/.test(sValue))); + }, this); + + this.valueHasMutated(); + return this; +}; + +ko.observable.fn.validateFunc = function (fFunc) +{ + this.hasFuncError = ko.observable(false); + + if (Utils.isFunc(fFunc)) + { + this.subscribe(function (sValue) { + this.hasFuncError(!fFunc(sValue)); + }, this); + + this.valueHasMutated(); + } + + return this; +}; + + +/** + * @constructor + */ +function LinkBuilder() +{ + this.sBase = '#/'; + this.sVersion = RL.settingsGet('Version'); + this.sSpecSuffix = RL.settingsGet('AuthAccountHash') || '0'; + this.sServer = (RL.settingsGet('IndexFile') || './') + '?'; +} + +/** + * @return {string} + */ +LinkBuilder.prototype.root = function () +{ + return this.sBase; +}; + +/** + * @param {string} sDownload + * @return {string} + */ +LinkBuilder.prototype.attachmentDownload = function (sDownload) +{ + return this.sServer + '/Raw/' + this.sSpecSuffix + '/Download/' + sDownload; +}; + +/** + * @param {string} sDownload + * @return {string} + */ +LinkBuilder.prototype.attachmentPreview = function (sDownload) +{ + return this.sServer + '/Raw/' + this.sSpecSuffix + '/View/' + sDownload; +}; + +/** + * @param {string} sDownload + * @return {string} + */ +LinkBuilder.prototype.attachmentPreviewAsPlain = function (sDownload) +{ + return this.sServer + '/Raw/' + this.sSpecSuffix + '/ViewAsPlain/' + sDownload; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.upload = function () +{ + return this.sServer + '/Upload/' + this.sSpecSuffix + '/'; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.uploadContacts = function () +{ + return this.sServer + '/UploadContacts/' + this.sSpecSuffix + '/'; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.uploadBackground = function () +{ + return this.sServer + '/UploadBackground/' + this.sSpecSuffix + '/'; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.append = function () +{ + return this.sServer + '/Append/' + this.sSpecSuffix + '/'; +}; + +/** + * @param {string} sEmail + * @return {string} + */ +LinkBuilder.prototype.change = function (sEmail) +{ + return this.sServer + '/Change/' + this.sSpecSuffix + '/' + window.encodeURIComponent(sEmail) + '/'; +}; + +/** + * @param {string=} sAdd + * @return {string} + */ +LinkBuilder.prototype.ajax = function (sAdd) +{ + return this.sServer + '/Ajax/' + this.sSpecSuffix + '/' + sAdd; +}; + +/** + * @param {string} sRequestHash + * @return {string} + */ +LinkBuilder.prototype.messageViewLink = function (sRequestHash) +{ + return this.sServer + '/Raw/' + this.sSpecSuffix + '/ViewAsPlain/' + sRequestHash; +}; + +/** + * @param {string} sRequestHash + * @return {string} + */ +LinkBuilder.prototype.messageDownloadLink = function (sRequestHash) +{ + return this.sServer + '/Raw/' + this.sSpecSuffix + '/Download/' + sRequestHash; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.inbox = function () +{ + return this.sBase + 'mailbox/Inbox'; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.messagePreview = function () +{ + return this.sBase + 'mailbox/message-preview'; +}; + +/** + * @param {string=} sScreenName + * @return {string} + */ +LinkBuilder.prototype.settings = function (sScreenName) +{ + var sResult = this.sBase + 'settings'; + if (!Utils.isUnd(sScreenName) && '' !== sScreenName) + { + sResult += '/' + sScreenName; + } + + return sResult; +}; + +/** + * @param {string} sScreenName + * @return {string} + */ +LinkBuilder.prototype.admin = function (sScreenName) +{ + var sResult = this.sBase; + switch (sScreenName) { + case 'AdminDomains': + sResult += 'domains'; + break; + case 'AdminSecurity': + sResult += 'security'; + break; + case 'AdminLicensing': + sResult += 'licensing'; + break; + } + + return sResult; +}; + +/** + * @param {string} sFolder + * @param {number=} iPage = 1 + * @param {string=} sSearch = '' + * @return {string} + */ +LinkBuilder.prototype.mailBox = function (sFolder, iPage, sSearch) +{ + iPage = Utils.isNormal(iPage) ? Utils.pInt(iPage) : 1; + sSearch = Utils.pString(sSearch); + + var sResult = this.sBase + 'mailbox/'; + if ('' !== sFolder) + { + sResult += encodeURI(sFolder); + } + if (1 < iPage) + { + sResult = sResult.replace(/[\/]+$/, ''); + sResult += '/p' + iPage; + } + if ('' !== sSearch) + { + sResult = sResult.replace(/[\/]+$/, ''); + sResult += '/' + encodeURI(sSearch); + } + + return sResult; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.phpInfo = function () +{ + return this.sServer + 'Info'; +}; + +/** + * @param {string} sLang + * @return {string} + */ +LinkBuilder.prototype.langLink = function (sLang) +{ + return this.sServer + '/Lang/0/' + encodeURI(sLang) + '/' + this.sVersion + '/'; +}; + +/** + * @param {string} sHash + * @return {string} + */ +LinkBuilder.prototype.getUserPicUrlFromHash = function (sHash) +{ + return this.sServer + '/Raw/' + this.sSpecSuffix + '/UserPic/' + sHash + '/' + this.sVersion + '/'; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.exportContactsVcf = function () +{ + return this.sServer + '/Raw/' + this.sSpecSuffix + '/ContactsVcf/'; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.exportContactsCsv = function () +{ + return this.sServer + '/Raw/' + this.sSpecSuffix + '/ContactsCsv/'; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.emptyContactPic = function () +{ + return 'rainloop/v/' + this.sVersion + '/static/css/images/empty-contact.png'; +}; + +/** + * @param {string} sFileName + * @return {string} + */ +LinkBuilder.prototype.sound = function (sFileName) +{ + return 'rainloop/v/' + this.sVersion + '/static/sounds/' + sFileName; +}; + +/** + * @param {string} sTheme + * @return {string} + */ +LinkBuilder.prototype.themePreviewLink = function (sTheme) +{ + var sPrefix = 'rainloop/v/' + this.sVersion + '/'; + if ('@custom' === sTheme.substr(-7)) + { + sTheme = Utils.trim(sTheme.substring(0, sTheme.length - 7)); + sPrefix = ''; + } + + return sPrefix + 'themes/' + encodeURI(sTheme) + '/images/preview.png'; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.notificationMailIcon = function () +{ + return 'rainloop/v/' + this.sVersion + '/static/css/images/icom-message-notification.png'; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.openPgpJs = function () +{ + return 'rainloop/v/' + this.sVersion + '/static/js/openpgp.min.js'; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.socialGoogle = function () +{ + return this.sServer + 'SocialGoogle' + ('' !== this.sSpecSuffix ? '/' + this.sSpecSuffix + '/' : ''); +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.socialTwitter = function () +{ + return this.sServer + 'SocialTwitter' + ('' !== this.sSpecSuffix ? '/' + this.sSpecSuffix + '/' : ''); +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.socialFacebook = function () +{ + return this.sServer + 'SocialFacebook' + ('' !== this.sSpecSuffix ? '/' + this.sSpecSuffix + '/' : ''); +}; + +/** + * @type {Object} + */ +Plugins.oViewModelsHooks = {}; + +/** + * @type {Object} + */ +Plugins.oSimpleHooks = {}; + +/** + * @param {string} sName + * @param {Function} ViewModel + */ +Plugins.regViewModelHook = function (sName, ViewModel) +{ + if (ViewModel) + { + ViewModel.__hookName = sName; + } +}; + +/** + * @param {string} sName + * @param {Function} fCallback + */ +Plugins.addHook = function (sName, fCallback) +{ + if (Utils.isFunc(fCallback)) + { + if (!Utils.isArray(Plugins.oSimpleHooks[sName])) + { + Plugins.oSimpleHooks[sName] = []; + } + + Plugins.oSimpleHooks[sName].push(fCallback); + } +}; + +/** + * @param {string} sName + * @param {Array=} aArguments + */ +Plugins.runHook = function (sName, aArguments) +{ + if (Utils.isArray(Plugins.oSimpleHooks[sName])) + { + aArguments = aArguments || []; + + _.each(Plugins.oSimpleHooks[sName], function (fCallback) { + fCallback.apply(null, aArguments); + }); + } +}; + +/** + * @param {string} sName + * @return {?} + */ +Plugins.mainSettingsGet = function (sName) +{ + return RL ? RL.settingsGet(sName) : null; +}; + +/** + * @param {Function} fCallback + * @param {string} sAction + * @param {Object=} oParameters + * @param {?number=} iTimeout + * @param {string=} sGetAdd = '' + * @param {Array=} aAbortActions = [] + */ +Plugins.remoteRequest = function (fCallback, sAction, oParameters, iTimeout, sGetAdd, aAbortActions) +{ + if (RL) + { + RL.remote().defaultRequest(fCallback, sAction, oParameters, iTimeout, sGetAdd, aAbortActions); + } +}; + +/** + * @param {string} sPluginSection + * @param {string} sName + * @return {?} + */ +Plugins.settingsGet = function (sPluginSection, sName) +{ + var oPlugin = Plugins.mainSettingsGet('Plugins'); + oPlugin = oPlugin && Utils.isUnd(oPlugin[sPluginSection]) ? null : oPlugin[sPluginSection]; + return oPlugin ? (Utils.isUnd(oPlugin[sName]) ? null : oPlugin[sName]) : null; +}; + + + +/** + * @constructor + */ +function CookieDriver() +{ + +} + +CookieDriver.supported = function () +{ + return true; +}; + +/** + * @param {string} sKey + * @param {*} mData + * @returns {boolean} + */ +CookieDriver.prototype.set = function (sKey, mData) +{ + var + mCokieValue = $.cookie(Consts.Values.ClientSideCookieIndexName), + bResult = false, + mResult = null + ; + + try + { + mResult = null === mCokieValue ? null : JSON.parse(mCokieValue); + if (!mResult) + { + mResult = {}; + } + + mResult[sKey] = mData; + $.cookie(Consts.Values.ClientSideCookieIndexName, JSON.stringify(mResult), { + 'expires': 30 + }); + + bResult = true; + } + catch (oException) {} + + return bResult; +}; + +/** + * @param {string} sKey + * @returns {*} + */ +CookieDriver.prototype.get = function (sKey) +{ + var + mCokieValue = $.cookie(Consts.Values.ClientSideCookieIndexName), + mResult = null + ; + + try + { + mResult = null === mCokieValue ? null : JSON.parse(mCokieValue); + if (mResult && !Utils.isUnd(mResult[sKey])) + { + mResult = mResult[sKey]; + } + else + { + mResult = null; + } + } + catch (oException) {} + + return mResult; +}; + +/** + * @constructor + */ +function LocalStorageDriver() +{ +} + +LocalStorageDriver.supported = function () +{ + return !!window.localStorage; +}; + +/** + * @param {string} sKey + * @param {*} mData + * @returns {boolean} + */ +LocalStorageDriver.prototype.set = function (sKey, mData) +{ + var + mCookieValue = window.localStorage[Consts.Values.ClientSideCookieIndexName] || null, + bResult = false, + mResult = null + ; + + try + { + mResult = null === mCookieValue ? null : JSON.parse(mCookieValue); + if (!mResult) + { + mResult = {}; + } + + mResult[sKey] = mData; + window.localStorage[Consts.Values.ClientSideCookieIndexName] = JSON.stringify(mResult); + + bResult = true; + } + catch (oException) {} + + return bResult; +}; + +/** + * @param {string} sKey + * @returns {*} + */ +LocalStorageDriver.prototype.get = function (sKey) +{ + var + mCokieValue = window.localStorage[Consts.Values.ClientSideCookieIndexName] || null, + mResult = null + ; + + try + { + mResult = null === mCokieValue ? null : JSON.parse(mCokieValue); + if (mResult && !Utils.isUnd(mResult[sKey])) + { + mResult = mResult[sKey]; + } + else + { + mResult = null; + } + } + catch (oException) {} + + return mResult; +}; + +/** + * @constructor + */ +function LocalStorage() +{ + var + sStorages = [ + LocalStorageDriver, + CookieDriver + ], + NextStorageDriver = _.find(sStorages, function (NextStorageDriver) { + return NextStorageDriver.supported(); + }) + ; + + if (NextStorageDriver) + { + NextStorageDriver = /** @type {?Function} */ NextStorageDriver; + this.oDriver = new NextStorageDriver(); + } +} + +LocalStorage.prototype.oDriver = null; + +/** + * @param {number} iKey + * @param {*} mData + * @return {boolean} + */ +LocalStorage.prototype.set = function (iKey, mData) +{ + return this.oDriver ? this.oDriver.set('p' + iKey, mData) : false; +}; + +/** + * @param {number} iKey + * @return {*} + */ +LocalStorage.prototype.get = function (iKey) +{ + return this.oDriver ? this.oDriver.get('p' + iKey) : null; +}; + +/** + * @constructor + */ +function KnoinAbstractBoot() +{ + +} + +KnoinAbstractBoot.prototype.bootstart = function () +{ + +}; + +/** + * @param {string=} sPosition = '' + * @param {string=} sTemplate = '' + * @constructor + */ +function KnoinAbstractViewModel(sPosition, sTemplate) +{ + this.bDisabeCloseOnEsc = false; + this.sPosition = Utils.pString(sPosition); + this.sTemplate = Utils.pString(sTemplate); + + this.sDefaultKeyScope = Enums.KeyState.None; + this.sCurrentKeyScope = this.sDefaultKeyScope; + + this.viewModelName = ''; + this.viewModelVisibility = ko.observable(false); + this.modalVisibility = ko.observable(false).extend({'rateLimit': 0}); + + this.viewModelDom = null; +} + +/** + * @type {string} + */ +KnoinAbstractViewModel.prototype.sPosition = ''; + +/** + * @type {string} + */ +KnoinAbstractViewModel.prototype.sTemplate = ''; + +/** + * @type {string} + */ +KnoinAbstractViewModel.prototype.viewModelName = ''; + +/** + * @type {?} + */ +KnoinAbstractViewModel.prototype.viewModelDom = null; + +/** + * @return {string} + */ +KnoinAbstractViewModel.prototype.viewModelTemplate = function () +{ + return this.sTemplate; +}; + +/** + * @return {string} + */ +KnoinAbstractViewModel.prototype.viewModelPosition = function () +{ + return this.sPosition; +}; + +KnoinAbstractViewModel.prototype.cancelCommand = KnoinAbstractViewModel.prototype.closeCommand = function () +{ +}; + +KnoinAbstractViewModel.prototype.storeAndSetKeyScope = function () +{ + this.sCurrentKeyScope = RL.data().keyScope(); + RL.data().keyScope(this.sDefaultKeyScope); +}; + +KnoinAbstractViewModel.prototype.restoreKeyScope = function () +{ + RL.data().keyScope(this.sCurrentKeyScope); +}; + +KnoinAbstractViewModel.prototype.registerPopupEscapeKey = function () +{ + var self = this; + $window.on('keydown', function (oEvent) { + if (oEvent && Enums.EventKeyCode.Esc === oEvent.keyCode && self.modalVisibility && self.modalVisibility()) + { + Utils.delegateRun(self, 'cancelCommand'); + return false; + } + + return true; + }); +}; + +/** + * @param {string} sScreenName + * @param {?=} aViewModels = [] + * @constructor + */ +function KnoinAbstractScreen(sScreenName, aViewModels) +{ + this.sScreenName = sScreenName; + this.aViewModels = Utils.isArray(aViewModels) ? aViewModels : []; +} + +/** + * @type {Array} + */ +KnoinAbstractScreen.prototype.oCross = null; + +/** + * @type {string} + */ +KnoinAbstractScreen.prototype.sScreenName = ''; + +/** + * @type {Array} + */ +KnoinAbstractScreen.prototype.aViewModels = []; + +/** + * @return {Array} + */ +KnoinAbstractScreen.prototype.viewModels = function () +{ + return this.aViewModels; +}; + +/** + * @return {string} + */ +KnoinAbstractScreen.prototype.screenName = function () +{ + return this.sScreenName; +}; + +KnoinAbstractScreen.prototype.routes = function () +{ + return null; +}; + +/** + * @return {?Object} + */ +KnoinAbstractScreen.prototype.__cross = function () +{ + return this.oCross; +}; + +KnoinAbstractScreen.prototype.__start = function () +{ + var + aRoutes = this.routes(), + oRoute = null, + fMatcher = null + ; + + if (Utils.isNonEmptyArray(aRoutes)) + { + fMatcher = _.bind(this.onRoute || Utils.emptyFunction, this); + oRoute = crossroads.create(); + + _.each(aRoutes, function (aItem) { + oRoute.addRoute(aItem[0], fMatcher).rules = aItem[1]; + }); + + this.oCross = oRoute; + } +}; + +/** + * @constructor + */ +function Knoin() +{ + this.sDefaultScreenName = ''; + this.oScreens = {}; + this.oBoot = null; + this.oCurrentScreen = null; +} + +/** + * @param {Object} thisObject + */ +Knoin.constructorEnd = function (thisObject) +{ + if (Utils.isFunc(thisObject['__constructor_end'])) + { + thisObject['__constructor_end'].call(thisObject); + } +}; + +Knoin.prototype.sDefaultScreenName = ''; +Knoin.prototype.oScreens = {}; +Knoin.prototype.oBoot = null; +Knoin.prototype.oCurrentScreen = null; + +Knoin.prototype.hideLoading = function () +{ + $('#rl-loading').hide(); +}; + +Knoin.prototype.routeOff = function () +{ + hasher.changed.active = false; +}; + +Knoin.prototype.routeOn = function () +{ + hasher.changed.active = true; +}; + +/** + * @param {Object} oBoot + * @return {Knoin} + */ +Knoin.prototype.setBoot = function (oBoot) +{ + if (Utils.isNormal(oBoot)) + { + this.oBoot = oBoot; + } + + return this; +}; + +/** + * @param {string} sScreenName + * @return {?Object} + */ +Knoin.prototype.screen = function (sScreenName) +{ + return ('' !== sScreenName && !Utils.isUnd(this.oScreens[sScreenName])) ? this.oScreens[sScreenName] : null; +}; + +/** + * @param {Function} ViewModelClass + * @param {Object=} oScreen + */ +Knoin.prototype.buildViewModel = function (ViewModelClass, oScreen) +{ + if (ViewModelClass && !ViewModelClass.__builded) + { + var + oViewModel = new ViewModelClass(oScreen), + sPosition = oViewModel.viewModelPosition(), + oViewModelPlace = $('#rl-content #rl-' + sPosition.toLowerCase()), + oViewModelDom = null + ; + + ViewModelClass.__builded = true; + ViewModelClass.__vm = oViewModel; + oViewModel.data = RL.data(); + + oViewModel.viewModelName = ViewModelClass.__name; + + if (oViewModelPlace && 1 === oViewModelPlace.length) + { + oViewModelDom = $('').addClass('rl-view-model').addClass('RL-' + oViewModel.viewModelTemplate()).hide().attr('data-bind', + 'template: {name: "' + oViewModel.viewModelTemplate() + '"}, i18nInit: true'); + + oViewModelDom.appendTo(oViewModelPlace); + oViewModel.viewModelDom = oViewModelDom; + ViewModelClass.__dom = oViewModelDom; + + if ('Popups' === sPosition) + { + oViewModel.cancelCommand = oViewModel.closeCommand = Utils.createCommand(oViewModel, function () { + kn.hideScreenPopup(ViewModelClass); + }); + + oViewModel.modalVisibility.subscribe(function (bValue) { + + var self = this; + if (bValue) + { + this.viewModelDom.show(); + this.storeAndSetKeyScope(); + + RL.popupVisibilityNames.push(this.viewModelName); + oViewModel.viewModelDom.css('z-index', 3000 + RL.popupVisibilityNames().length + 10); + + Utils.delegateRun(this, 'onFocus', [], 500); + } + else + { + Utils.delegateRun(this, 'onHide'); + this.restoreKeyScope(); + + RL.popupVisibilityNames.remove(this.viewModelName); + oViewModel.viewModelDom.css('z-index', 2000); + + _.delay(function () { + self.viewModelDom.hide(); + }, 300); + } + + }, oViewModel); + } + + Plugins.runHook('view-model-pre-build', [ViewModelClass.__name, oViewModel, oViewModelDom]); + + ko.applyBindings(oViewModel, oViewModelDom[0]); + Utils.delegateRun(oViewModel, 'onBuild', [oViewModelDom]); + if (oViewModel && 'Popups' === sPosition && !oViewModel.bDisabeCloseOnEsc) + { + oViewModel.registerPopupEscapeKey(); + } + + Plugins.runHook('view-model-post-build', [ViewModelClass.__name, oViewModel, oViewModelDom]); + } + else + { + Utils.log('Cannot find view model position: ' + sPosition); + } + } + + return ViewModelClass ? ViewModelClass.__vm : null; +}; + +/** + * @param {Object} oViewModel + * @param {Object} oViewModelDom + */ +Knoin.prototype.applyExternal = function (oViewModel, oViewModelDom) +{ + if (oViewModel && oViewModelDom) + { + ko.applyBindings(oViewModel, oViewModelDom); + } +}; + +/** + * @param {Function} ViewModelClassToHide + */ +Knoin.prototype.hideScreenPopup = function (ViewModelClassToHide) +{ + if (ViewModelClassToHide && ViewModelClassToHide.__vm && ViewModelClassToHide.__dom) + { + ViewModelClassToHide.__vm.modalVisibility(false); + Plugins.runHook('view-model-on-hide', [ViewModelClassToHide.__name, ViewModelClassToHide.__vm]); + } +}; + +/** + * @param {Function} ViewModelClassToShow + * @param {Array=} aParameters + */ +Knoin.prototype.showScreenPopup = function (ViewModelClassToShow, aParameters) +{ + if (ViewModelClassToShow) + { + this.buildViewModel(ViewModelClassToShow); + + if (ViewModelClassToShow.__vm && ViewModelClassToShow.__dom) + { + ViewModelClassToShow.__vm.modalVisibility(true); + Utils.delegateRun(ViewModelClassToShow.__vm, 'onShow', aParameters || []); + Plugins.runHook('view-model-on-show', [ViewModelClassToShow.__name, ViewModelClassToShow.__vm, aParameters || []]); + } + } +}; + +/** + * @param {string} sScreenName + * @param {string} sSubPart + */ +Knoin.prototype.screenOnRoute = function (sScreenName, sSubPart) +{ + var + self = this, + oScreen = null, + oCross = null + ; + + if ('' === Utils.pString(sScreenName)) + { + sScreenName = this.sDefaultScreenName; + } + + if ('' !== sScreenName) + { + oScreen = this.screen(sScreenName); + if (!oScreen) + { + oScreen = this.screen(this.sDefaultScreenName); + if (oScreen) + { + sSubPart = sScreenName + '/' + sSubPart; + sScreenName = this.sDefaultScreenName; + } + } + + if (oScreen && oScreen.__started) + { + if (!oScreen.__builded) + { + oScreen.__builded = true; + + if (Utils.isNonEmptyArray(oScreen.viewModels())) + { + _.each(oScreen.viewModels(), function (ViewModelClass) { + this.buildViewModel(ViewModelClass, oScreen); + }, this); + } + + Utils.delegateRun(oScreen, 'onBuild'); + } + + _.defer(function () { + + // hide screen + if (self.oCurrentScreen) + { + Utils.delegateRun(self.oCurrentScreen, 'onHide'); + + if (Utils.isNonEmptyArray(self.oCurrentScreen.viewModels())) + { + _.each(self.oCurrentScreen.viewModels(), function (ViewModelClass) { + + if (ViewModelClass.__vm && ViewModelClass.__dom && + 'Popups' !== ViewModelClass.__vm.viewModelPosition()) + { + ViewModelClass.__dom.hide(); + ViewModelClass.__vm.viewModelVisibility(false); + Utils.delegateRun(ViewModelClass.__vm, 'onHide'); + } + + }); + } + } + // -- + + self.oCurrentScreen = oScreen; + + // show screen + if (self.oCurrentScreen) + { + Utils.delegateRun(self.oCurrentScreen, 'onShow'); + + Plugins.runHook('screen-on-show', [self.oCurrentScreen.screenName(), self.oCurrentScreen]); + + if (Utils.isNonEmptyArray(self.oCurrentScreen.viewModels())) + { + _.each(self.oCurrentScreen.viewModels(), function (ViewModelClass) { + + if (ViewModelClass.__vm && ViewModelClass.__dom && + 'Popups' !== ViewModelClass.__vm.viewModelPosition()) + { + ViewModelClass.__dom.show(); + ViewModelClass.__vm.viewModelVisibility(true); + Utils.delegateRun(ViewModelClass.__vm, 'onShow'); + Utils.delegateRun(ViewModelClass.__vm, 'onFocus', [], 200); + + Plugins.runHook('view-model-on-show', [ViewModelClass.__name, ViewModelClass.__vm]); + } + + }, self); + } + } + // -- + + oCross = oScreen.__cross(); + if (oCross) + { + oCross.parse(sSubPart); + } + }); + } + } +}; + +/** + * @param {Array} aScreensClasses + */ +Knoin.prototype.startScreens = function (aScreensClasses) +{ + $('#rl-content').css({ + 'visibility': 'hidden' + }); + + _.each(aScreensClasses, function (CScreen) { + + var + oScreen = new CScreen(), + sScreenName = oScreen ? oScreen.screenName() : '' + ; + + if (oScreen && '' !== sScreenName) + { + if ('' === this.sDefaultScreenName) + { + this.sDefaultScreenName = sScreenName; + } + + this.oScreens[sScreenName] = oScreen; + } + + }, this); + + + _.each(this.oScreens, function (oScreen) { + if (oScreen && !oScreen.__started && oScreen.__start) + { + oScreen.__started = true; + oScreen.__start(); + + Plugins.runHook('screen-pre-start', [oScreen.screenName(), oScreen]); + Utils.delegateRun(oScreen, 'onStart'); + Plugins.runHook('screen-post-start', [oScreen.screenName(), oScreen]); + } + }, this); + + var oCross = crossroads.create(); + oCross.addRoute(/^([a-zA-Z0-9\-]*)\/?(.*)$/, _.bind(this.screenOnRoute, this)); + + hasher.initialized.add(oCross.parse, oCross); + hasher.changed.add(oCross.parse, oCross); + hasher.init(); + + $('#rl-content').css({ + 'visibility': 'visible' + }); + + _.delay(function () { + $html.removeClass('rl-started-trigger').addClass('rl-started'); + }, 50); +}; + +/** + * @param {string} sHash + * @param {boolean=} bSilence = false + * @param {boolean=} bReplace = false + */ +Knoin.prototype.setHash = function (sHash, bSilence, bReplace) +{ + sHash = '#' === sHash.substr(0, 1) ? sHash.substr(1) : sHash; + sHash = '/' === sHash.substr(0, 1) ? sHash.substr(1) : sHash; + + bReplace = Utils.isUnd(bReplace) ? false : !!bReplace; + + if (Utils.isUnd(bSilence) ? false : !!bSilence) + { + hasher.changed.active = false; + hasher[bReplace ? 'replaceHash' : 'setHash'](sHash); + hasher.changed.active = true; + } + else + { + hasher.changed.active = true; + hasher[bReplace ? 'replaceHash' : 'setHash'](sHash); + hasher.setHash(sHash); + } +}; + +/** + * @return {Knoin} + */ +Knoin.prototype.bootstart = function () +{ + if (this.oBoot && this.oBoot.bootstart) + { + this.oBoot.bootstart(); + } + + return this; +}; + +kn = new Knoin(); + +/** + * @param {string=} sEmail + * @param {string=} sName + * + * @constructor + */ +function EmailModel(sEmail, sName) +{ + this.email = sEmail || ''; + this.name = sName || ''; + this.privateType = null; + + this.clearDuplicateName(); +} + +/** + * @static + * @param {AjaxJsonEmail} oJsonEmail + * @return {?EmailModel} + */ +EmailModel.newInstanceFromJson = function (oJsonEmail) +{ + var oEmailModel = new EmailModel(); + return oEmailModel.initByJson(oJsonEmail) ? oEmailModel : null; +}; + +/** + * @type {string} + */ +EmailModel.prototype.name = ''; + +/** + * @type {string} + */ +EmailModel.prototype.email = ''; + +/** + * @type {(number|null)} + */ +EmailModel.prototype.privateType = null; + +EmailModel.prototype.clear = function () +{ + this.email = ''; + this.name = ''; + this.privateType = null; +}; + +/** + * @returns {boolean} + */ +EmailModel.prototype.validate = function () +{ + return '' !== this.name || '' !== this.email; +}; + +/** + * @param {boolean} bWithoutName = false + * @return {string} + */ +EmailModel.prototype.hash = function (bWithoutName) +{ + return '#' + (bWithoutName ? '' : this.name) + '#' + this.email + '#'; +}; + +EmailModel.prototype.clearDuplicateName = function () +{ + if (this.name === this.email) + { + this.name = ''; + } +}; + +/** + * @return {number} + */ +EmailModel.prototype.type = function () +{ + if (null === this.privateType) + { + if (this.email && '@facebook.com' === this.email.substr(-13)) + { + this.privateType = Enums.EmailType.Facebook; + } + + if (null === this.privateType) + { + this.privateType = Enums.EmailType.Default; + } + } + + return this.privateType; +}; + +/** + * @param {string} sQuery + * @return {boolean} + */ +EmailModel.prototype.search = function (sQuery) +{ + return -1 < (this.name + ' ' + this.email).toLowerCase().indexOf(sQuery.toLowerCase()); +}; + +/** + * @param {string} sString + */ +EmailModel.prototype.parse = function (sString) +{ + this.clear(); + + sString = Utils.trim(sString); + + var + mRegex = /(?:"([^"]+)")? ?(.*?@[^>,]+)>?,? ?/g, + mMatch = mRegex.exec(sString) + ; + + if (mMatch) + { + this.name = mMatch[1] || ''; + this.email = mMatch[2] || ''; + + this.clearDuplicateName(); + } + else if ((/^[^@]+@[^@]+$/).test(sString)) + { + this.name = ''; + this.email = sString; + } +}; + +/** + * @param {AjaxJsonEmail} oJsonEmail + * @return {boolean} + */ +EmailModel.prototype.initByJson = function (oJsonEmail) +{ + var bResult = false; + if (oJsonEmail && 'Object/Email' === oJsonEmail['@Object']) + { + this.name = Utils.trim(oJsonEmail.Name); + this.email = Utils.trim(oJsonEmail.Email); + + bResult = '' !== this.email; + this.clearDuplicateName(); + } + + return bResult; +}; + +/** + * @param {boolean} bFriendlyView + * @param {boolean=} bWrapWithLink = false + * @param {boolean=} bEncodeHtml = false + * @return {string} + */ +EmailModel.prototype.toLine = function (bFriendlyView, bWrapWithLink, bEncodeHtml) +{ + var sResult = ''; + if ('' !== this.email) + { + bWrapWithLink = Utils.isUnd(bWrapWithLink) ? false : !!bWrapWithLink; + bEncodeHtml = Utils.isUnd(bEncodeHtml) ? false : !!bEncodeHtml; + + if (bFriendlyView && '' !== this.name) + { + sResult = bWrapWithLink ? '') + + '" target="_blank" tabindex="-1">' + Utils.encodeHtml(this.name) + '' : + (bEncodeHtml ? Utils.encodeHtml(this.name) : this.name); + } + else + { + sResult = this.email; + if ('' !== this.name) + { + if (bWrapWithLink) + { + sResult = Utils.encodeHtml('"' + this.name + '" <') + + '') + '" target="_blank" tabindex="-1">' + Utils.encodeHtml(sResult) + '' + Utils.encodeHtml('>'); + } + else + { + sResult = '"' + this.name + '" <' + sResult + '>'; + if (bEncodeHtml) + { + sResult = Utils.encodeHtml(sResult); + } + } + } + else if (bWrapWithLink) + { + sResult = '' + Utils.encodeHtml(this.email) + ''; + } + } + } + + return sResult; +}; + +/** + * @param {string} $sEmailAddress + * @return {boolean} + */ +EmailModel.prototype.mailsoParse = function ($sEmailAddress) +{ + $sEmailAddress = Utils.trim($sEmailAddress); + if ('' === $sEmailAddress) + { + return false; + } + + var + substr = function (str, start, len) { + str += ''; + var end = str.length; + + if (start < 0) { + start += end; + } + + end = typeof len === 'undefined' ? end : (len < 0 ? len + end : len + start); + + return start >= str.length || start < 0 || start > end ? false : str.slice(start, end); + }, + + substr_replace = function (str, replace, start, length) { + if (start < 0) { + start = start + str.length; + } + length = length !== undefined ? length : str.length; + if (length < 0) { + length = length + str.length - start; + } + return str.slice(0, start) + replace.substr(0, length) + replace.slice(length) + str.slice(start + length); + }, + + $sName = '', + $sEmail = '', + $sComment = '', + + $bInName = false, + $bInAddress = false, + $bInComment = false, + + $aRegs = null, + + $iStartIndex = 0, + $iEndIndex = 0, + $iCurrentIndex = 0 + ; + + while ($iCurrentIndex < $sEmailAddress.length) + { + switch ($sEmailAddress.substr($iCurrentIndex, 1)) + { + case '"': + if ((!$bInName) && (!$bInAddress) && (!$bInComment)) + { + $bInName = true; + $iStartIndex = $iCurrentIndex; + } + else if ((!$bInAddress) && (!$bInComment)) + { + $iEndIndex = $iCurrentIndex; + $sName = substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1); + $sEmailAddress = substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1); + $iEndIndex = 0; + $iCurrentIndex = 0; + $iStartIndex = 0; + $bInName = false; + } + break; + case '<': + if ((!$bInName) && (!$bInAddress) && (!$bInComment)) + { + if ($iCurrentIndex > 0 && $sName.length === 0) + { + $sName = substr($sEmailAddress, 0, $iCurrentIndex); + } + + $bInAddress = true; + $iStartIndex = $iCurrentIndex; + } + break; + case '>': + if ($bInAddress) + { + $iEndIndex = $iCurrentIndex; + $sEmail = substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1); + $sEmailAddress = substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1); + $iEndIndex = 0; + $iCurrentIndex = 0; + $iStartIndex = 0; + $bInAddress = false; + } + break; + case '(': + if ((!$bInName) && (!$bInAddress) && (!$bInComment)) + { + $bInComment = true; + $iStartIndex = $iCurrentIndex; + } + break; + case ')': + if ($bInComment) + { + $iEndIndex = $iCurrentIndex; + $sComment = substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1); + $sEmailAddress = substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1); + $iEndIndex = 0; + $iCurrentIndex = 0; + $iStartIndex = 0; + $bInComment = false; + } + break; + case '\\': + $iCurrentIndex++; + break; + } + + $iCurrentIndex++; + } + + if ($sEmail.length === 0) + { + $aRegs = $sEmailAddress.match(/[^@\s]+@\S+/i); + if ($aRegs && $aRegs[0]) + { + $sEmail = $aRegs[0]; + } + else + { + $sName = $sEmailAddress; + } + } + + if ($sEmail.length > 0 && $sName.length === 0 && $sComment.length === 0) + { + $sName = $sEmailAddress.replace($sEmail, ''); + } + + $sEmail = Utils.trim($sEmail).replace(/^[<]+/, '').replace(/[>]+$/, ''); + $sName = Utils.trim($sName).replace(/^["']+/, '').replace(/["']+$/, ''); + $sComment = Utils.trim($sComment).replace(/^[(]+/, '').replace(/[)]+$/, ''); + + // Remove backslash + $sName = $sName.replace(/\\\\(.)/, '$1'); + $sComment = $sComment.replace(/\\\\(.)/, '$1'); + + this.name = $sName; + this.email = $sEmail; + + this.clearDuplicateName(); + return true; +}; + +/** + * @return {string} + */ +EmailModel.prototype.inputoTagLine = function () +{ + return 0 < this.name.length ? this.name + ' (' + this.email + ')' : this.email; +}; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsDomainViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsDomain'); + + this.edit = ko.observable(false); + this.saving = ko.observable(false); + this.savingError = ko.observable(''); + this.whiteListPage = ko.observable(false); + + this.testing = ko.observable(false); + this.testingDone = ko.observable(false); + this.testingImapError = ko.observable(false); + this.testingSmtpError = ko.observable(false); + this.testingImapErrorDesc = ko.observable(''); + this.testingSmtpErrorDesc = ko.observable(''); + + this.testingImapError.subscribe(function (bValue) { + if (!bValue) + { + this.testingImapErrorDesc(''); + } + }, this); + + this.testingSmtpError.subscribe(function (bValue) { + if (!bValue) + { + this.testingSmtpErrorDesc(''); + } + }, this); + + this.testingImapErrorDesc = ko.observable(''); + this.testingSmtpErrorDesc = ko.observable(''); + + this.imapServerFocus = ko.observable(false); + this.smtpServerFocus = ko.observable(false); + + this.name = ko.observable(''); + this.name.focused = ko.observable(false); + + this.imapServer = ko.observable(''); + this.imapPort = ko.observable(Consts.Values.ImapDefaulPort); + this.imapSecure = ko.observable(Enums.ServerSecure.None); + this.imapShortLogin = ko.observable(false); + this.smtpServer = ko.observable(''); + this.smtpPort = ko.observable(Consts.Values.SmtpDefaulPort); + this.smtpSecure = ko.observable(Enums.ServerSecure.None); + this.smtpShortLogin = ko.observable(false); + this.smtpAuth = ko.observable(true); + this.whiteList = ko.observable(''); + + this.headerText = ko.computed(function () { + var sName = this.name(); + return this.edit() ? 'Edit Domain "' + sName + '"' : + 'Add Domain' + ('' === sName ? '' : ' "' + sName + '"'); + }, this); + + this.domainIsComputed = ko.computed(function () { + return '' !== this.name() && + '' !== this.imapServer() && + '' !== this.imapPort() && + '' !== this.smtpServer() && + '' !== this.smtpPort(); + }, this); + + this.canBeTested = ko.computed(function () { + return !this.testing() && this.domainIsComputed(); + }, this); + + this.canBeSaved = ko.computed(function () { + return !this.saving() && this.domainIsComputed(); + }, this); + + this.createOrAddCommand = Utils.createCommand(this, function () { + this.saving(true); + RL.remote().createOrUpdateDomain( + _.bind(this.onDomainCreateOrSaveResponse, this), + !this.edit(), + this.name(), + this.imapServer(), + this.imapPort(), + this.imapSecure(), + this.imapShortLogin(), + this.smtpServer(), + this.smtpPort(), + this.smtpSecure(), + this.smtpShortLogin(), + this.smtpAuth(), + this.whiteList() + ); + }, this.canBeSaved); + + this.testConnectionCommand = Utils.createCommand(this, function () { + this.whiteListPage(false); + this.testingDone(false); + this.testingImapError(false); + this.testingSmtpError(false); + this.testing(true); + RL.remote().testConnectionForDomain( + _.bind(this.onTestConnectionResponse, this), + this.name(), + this.imapServer(), + this.imapPort(), + this.imapSecure(), + this.smtpServer(), + this.smtpPort(), + this.smtpSecure(), + this.smtpAuth() + ); + }, this.canBeTested); + + this.whiteListCommand = Utils.createCommand(this, function () { + this.whiteListPage(!this.whiteListPage()); + }); + + // smart form improvements + this.imapServerFocus.subscribe(function (bValue) { + if (bValue && '' !== this.name() && '' === this.imapServer()) + { + this.imapServer(this.name().replace(/[.]?[*][.]?/g, '')); + } + }, this); + + this.smtpServerFocus.subscribe(function (bValue) { + if (bValue && '' !== this.imapServer() && '' === this.smtpServer()) + { + this.smtpServer(this.imapServer().replace(/imap/ig, 'smtp')); + } + }, this); + + this.imapSecure.subscribe(function (sValue) { + var iPort = Utils.pInt(this.imapPort()); + sValue = Utils.pString(sValue); + switch (sValue) + { + case '0': + if (993 === iPort) + { + this.imapPort(143); + } + break; + case '1': + if (143 === iPort) + { + this.imapPort(993); + } + break; + } + }, this); + + this.smtpSecure.subscribe(function (sValue) { + var iPort = Utils.pInt(this.smtpPort()); + sValue = Utils.pString(sValue); + switch (sValue) + { + case '0': + if (465 === iPort || 587 === iPort) + { + this.smtpPort(25); + } + break; + case '1': + if (25 === iPort || 587 === iPort) + { + this.smtpPort(465); + } + break; + case '2': + if (25 === iPort || 465 === iPort) + { + this.smtpPort(587); + } + break; + } + }, this); + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsDomainViewModel', PopupsDomainViewModel); + +PopupsDomainViewModel.prototype.onTestConnectionResponse = function (sResult, oData) +{ + this.testing(false); + if (Enums.StorageResultType.Success === sResult && oData.Result) + { + this.testingDone(true); + this.testingImapError(true !== oData.Result.Imap); + this.testingSmtpError(true !== oData.Result.Smtp); + + if (this.testingImapError() && oData.Result.Imap) + { + this.testingImapErrorDesc(oData.Result.Imap); + } + + if (this.testingSmtpError() && oData.Result.Smtp) + { + this.testingSmtpErrorDesc(oData.Result.Smtp); + } + } + else + { + this.testingImapError(true); + this.testingSmtpError(true); + } +}; + +PopupsDomainViewModel.prototype.onDomainCreateOrSaveResponse = function (sResult, oData) +{ + this.saving(false); + if (Enums.StorageResultType.Success === sResult && oData) + { + if (oData.Result) + { + RL.reloadDomainList(); + this.closeCommand(); + } + else if (Enums.Notification.DomainAlreadyExists === oData.ErrorCode) + { + this.savingError('Domain already exists'); + } + } + else + { + this.savingError('Unknown error'); + } +}; + +PopupsDomainViewModel.prototype.onHide = function () +{ + this.whiteListPage(false); +}; + +PopupsDomainViewModel.prototype.onShow = function (oDomain) +{ + this.saving(false); + this.whiteListPage(false); + + this.testing(false); + this.testingDone(false); + this.testingImapError(false); + this.testingSmtpError(false); + + this.clearForm(); + if (oDomain) + { + this.edit(true); + + this.name(Utils.trim(oDomain.Name)); + this.imapServer(Utils.trim(oDomain.IncHost)); + this.imapPort(Utils.pInt(oDomain.IncPort)); + this.imapSecure(Utils.trim(oDomain.IncSecure)); + this.imapShortLogin(!!oDomain.IncShortLogin); + this.smtpServer(Utils.trim(oDomain.OutHost)); + this.smtpPort(Utils.pInt(oDomain.OutPort)); + this.smtpSecure(Utils.trim(oDomain.OutSecure)); + this.smtpShortLogin(!!oDomain.OutShortLogin); + this.smtpAuth(!!oDomain.OutAuth); + this.whiteList(Utils.trim(oDomain.WhiteList)); + } +}; + +PopupsDomainViewModel.prototype.onFocus = function () +{ + if ('' === this.name()) + { + this.name.focused(true); + } +}; + +PopupsDomainViewModel.prototype.clearForm = function () +{ + this.edit(false); + this.whiteListPage(false); + + this.savingError(''); + + this.name(''); + this.name.focused(false); + + this.imapServer(''); + this.imapPort(Consts.Values.ImapDefaulPort); + this.imapSecure(Enums.ServerSecure.None); + this.imapShortLogin(false); + this.smtpServer(''); + this.smtpPort(Consts.Values.SmtpDefaulPort); + this.smtpSecure(Enums.ServerSecure.None); + this.smtpShortLogin(false); + this.smtpAuth(true); + this.whiteList(''); +}; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsPluginViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsPlugin'); + + var self = this; + + this.onPluginSettingsUpdateResponse = _.bind(this.onPluginSettingsUpdateResponse, this); + + this.saveError = ko.observable(''); + + this.name = ko.observable(''); + this.readme = ko.observable(''); + + this.configures = ko.observableArray([]); + + this.hasReadme = ko.computed(function () { + return '' !== this.readme(); + }, this); + + this.hasConfiguration = ko.computed(function () { + return 0 < this.configures().length; + }, this); + + this.readmePopoverConf = { + 'placement': 'top', + 'trigger': 'hover', + 'title': 'About', + 'content': function () { + return self.readme(); + } + }; + + this.saveCommand = Utils.createCommand(this, function () { + + var oList = {}; + + oList['Name'] = this.name(); + + _.each(this.configures(), function (oItem) { + + var mValue = oItem.value(); + if (false === mValue || true === mValue) + { + mValue = mValue ? '1' : '0'; + } + + oList['_' + oItem['Name']] = mValue; + + }, this); + + this.saveError(''); + RL.remote().pluginSettingsUpdate(this.onPluginSettingsUpdateResponse, oList); + + }, this.hasConfiguration); + + this.bDisabeCloseOnEsc = true; + this.sDefaultKeyScope = Enums.KeyState.All; + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsPluginViewModel', PopupsPluginViewModel); + +PopupsPluginViewModel.prototype.onPluginSettingsUpdateResponse = function (sResult, oData) +{ + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + this.cancelCommand(); + } + else + { + this.saveError(''); + if (oData && oData.ErrorCode) + { + this.saveError(Utils.getNotification(oData.ErrorCode)); + } + else + { + this.saveError(Utils.getNotification(Enums.Notification.CantSavePluginSettings)); + } + } +}; + +PopupsPluginViewModel.prototype.onShow = function (oPlugin) +{ + this.name(); + this.readme(); + this.configures([]); + + if (oPlugin) + { + this.name(oPlugin['Name']); + this.readme(oPlugin['Readme']); + + var aConfig = oPlugin['Config']; + if (Utils.isNonEmptyArray(aConfig)) + { + this.configures(_.map(aConfig, function (aItem) { + return { + 'value': ko.observable(aItem[0]), + 'Name': aItem[1], + 'Type': aItem[2], + 'Label': aItem[3], + 'Default': aItem[4], + 'Desc': aItem[5] + }; + })); + } + } +}; + +PopupsPluginViewModel.prototype.tryToClosePopup = function () +{ + var self = this; + kn.showScreenPopup(PopupsAskViewModel, [Utils.i18n('POPUPS_ASK/DESC_WANT_CLOSE_THIS_WINDOW'), function () { + if (self.modalVisibility()) + { + Utils.delegateRun(self, 'cancelCommand'); + } + }]); +}; + +PopupsPluginViewModel.prototype.onBuild = function () +{ + key('esc', Enums.KeyState.All, _.bind(function () { + if (this.modalVisibility()) + { + this.tryToClosePopup(); + return false; + } + }, this)); +}; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsActivateViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsActivate'); + + var self = this; + + this.domain = ko.observable(''); + this.key = ko.observable(''); + this.key.focus = ko.observable(false); + this.activationSuccessed = ko.observable(false); + + this.licenseTrigger = RL.data().licenseTrigger; + + this.activateProcess = ko.observable(false); + this.activateText = ko.observable(''); + this.activateText.isError = ko.observable(false); + + this.key.subscribe(function () { + this.activateText(''); + this.activateText.isError(false); + }, this); + + this.activationSuccessed.subscribe(function (bValue) { + if (bValue) + { + this.licenseTrigger(!this.licenseTrigger()); + } + }, this); + + this.activateCommand = Utils.createCommand(this, function () { + + this.activateProcess(true); + if (this.validateSubscriptionKey()) + { + RL.remote().licensingActivate(function (sResult, oData) { + + self.activateProcess(false); + if (Enums.StorageResultType.Success === sResult && oData.Result) + { + if (true === oData.Result) + { + self.activationSuccessed(true); + self.activateText('Subscription Key Activated Successfully'); + self.activateText.isError(false); + } + else + { + self.activateText(oData.Result); + self.activateText.isError(true); + self.key.focus(true); + } + } + else if (oData.ErrorCode) + { + self.activateText(Utils.getNotification(oData.ErrorCode)); + self.activateText.isError(true); + self.key.focus(true); + } + else + { + self.activateText(Utils.getNotification(Enums.Notification.UnknownError)); + self.activateText.isError(true); + self.key.focus(true); + } + + }, this.domain(), this.key()); + } + else + { + this.activateProcess(false); + this.activateText('Invalid Subscription Key'); + this.activateText.isError(true); + this.key.focus(true); + } + + }, function () { + return !this.activateProcess() && '' !== this.domain() && '' !== this.key() && !this.activationSuccessed(); + }); + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsActivateViewModel', PopupsActivateViewModel); + +PopupsActivateViewModel.prototype.onShow = function () +{ + this.domain(RL.settingsGet('AdminDomain')); + if (!this.activateProcess()) + { + this.key(''); + this.activateText(''); + this.activateText.isError(false); + this.activationSuccessed(false); + } +}; + +PopupsActivateViewModel.prototype.onFocus = function () +{ + if (!this.activateProcess()) + { + this.key.focus(true); + } +}; + +/** + * @returns {boolean} + */ +PopupsActivateViewModel.prototype.validateSubscriptionKey = function () +{ + var sValue = this.key(); + return '' === sValue || !!/^RL[\d]+-[A-Z0-9\-]+Z$/.test(Utils.trim(sValue)); +}; +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsLanguagesViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsLanguages'); + + this.exp = ko.observable(false); + + this.languages = ko.computed(function () { + return _.map(RL.data().languages(), function (sLanguage) { + return { + 'key': sLanguage, + 'selected': ko.observable(false), + 'fullName': Utils.convertLangName(sLanguage) + }; + }); + }); + + RL.data().mainLanguage.subscribe(function () { + this.resetMainLanguage(); + }, this); + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsLanguagesViewModel', PopupsLanguagesViewModel); + +PopupsLanguagesViewModel.prototype.languageEnName = function (sLanguage) +{ + return Utils.convertLangName(sLanguage, true); +}; + +PopupsLanguagesViewModel.prototype.resetMainLanguage = function () +{ + var sCurrent = RL.data().mainLanguage(); + _.each(this.languages(), function (oItem) { + oItem['selected'](oItem['key'] === sCurrent); + }); +}; + +PopupsLanguagesViewModel.prototype.onShow = function () +{ + this.exp(true); + + this.resetMainLanguage(); +}; + +PopupsLanguagesViewModel.prototype.onHide = function () +{ + this.exp(false); +}; + +PopupsLanguagesViewModel.prototype.changeLanguage = function (sLang) +{ + RL.data().mainLanguage(sLang); + this.cancelCommand(); +}; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsAskViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsAsk'); + + this.askDesc = ko.observable(''); + this.yesButton = ko.observable(''); + this.noButton = ko.observable(''); + + this.yesFocus = ko.observable(false); + this.noFocus = ko.observable(false); + + this.fYesAction = null; + this.fNoAction = null; + + this.bDisabeCloseOnEsc = true; + this.sDefaultKeyScope = Enums.KeyState.PopupAsk; + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsAskViewModel', PopupsAskViewModel); + +PopupsAskViewModel.prototype.clearPopup = function () +{ + this.askDesc(''); + this.yesButton(Utils.i18n('POPUPS_ASK/BUTTON_YES')); + this.noButton(Utils.i18n('POPUPS_ASK/BUTTON_NO')); + + this.yesFocus(false); + this.noFocus(false); + + this.fYesAction = null; + this.fNoAction = null; +}; + +PopupsAskViewModel.prototype.yesClick = function () +{ + this.cancelCommand(); + + if (Utils.isFunc(this.fYesAction)) + { + this.fYesAction.call(null); + } +}; + +PopupsAskViewModel.prototype.noClick = function () +{ + this.cancelCommand(); + + if (Utils.isFunc(this.fNoAction)) + { + this.fNoAction.call(null); + } +}; + +/** + * @param {string} sAskDesc + * @param {Function=} fYesFunc + * @param {Function=} fNoFunc + * @param {string=} sYesButton + * @param {string=} sNoButton + */ +PopupsAskViewModel.prototype.onShow = function (sAskDesc, fYesFunc, fNoFunc, sYesButton, sNoButton) +{ + this.clearPopup(); + + this.fYesAction = fYesFunc || null; + this.fNoAction = fNoFunc || null; + + this.askDesc(sAskDesc || ''); + if (sYesButton) + { + this.yesButton(sYesButton); + } + + if (sYesButton) + { + this.yesButton(sNoButton); + } +}; + +PopupsAskViewModel.prototype.onFocus = function () +{ + this.yesFocus(true); +}; + +PopupsAskViewModel.prototype.onBuild = function () +{ + key('tab, shift+tab, right, left', Enums.KeyState.PopupAsk, _.bind(function () { + if (this.yesFocus()) + { + this.noFocus(true); + } + else + { + this.yesFocus(true); + } + return false; + }, this)); +}; + + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function AdminLoginViewModel() +{ + KnoinAbstractViewModel.call(this, 'Center', 'AdminLogin'); + + this.login = ko.observable(''); + this.password = ko.observable(''); + + this.loginError = ko.observable(false); + this.passwordError = ko.observable(false); + + this.loginFocus = ko.observable(false); + + this.login.subscribe(function () { + this.loginError(false); + }, this); + + this.password.subscribe(function () { + this.passwordError(false); + }, this); + + this.submitRequest = ko.observable(false); + this.submitError = ko.observable(''); + + this.submitCommand = Utils.createCommand(this, function () { + + this.loginError('' === Utils.trim(this.login())); + this.passwordError('' === Utils.trim(this.password())); + + if (this.loginError() || this.passwordError()) + { + return false; + } + + this.submitRequest(true); + + RL.remote().adminLogin(_.bind(function (sResult, oData) { + + if (Enums.StorageResultType.Success === sResult && oData && 'AdminLogin' === oData.Action) + { + if (oData.Result) + { + RL.loginAndLogoutReload(); + } + else if (oData.ErrorCode) + { + this.submitRequest(false); + this.submitError(Utils.getNotification(oData.ErrorCode)); + } + } + else + { + this.submitRequest(false); + this.submitError(Utils.getNotification(Enums.Notification.UnknownError)); + } + + }, this), this.login(), this.password()); + + return true; + + }, function () { + return !this.submitRequest(); + }); + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('AdminLoginViewModel', AdminLoginViewModel); + +AdminLoginViewModel.prototype.onShow = function () +{ + kn.routeOff(); + + _.delay(_.bind(function () { + this.loginFocus(true); + }, this), 100); + +}; + +AdminLoginViewModel.prototype.onHide = function () +{ + this.loginFocus(false); +}; + +/** + * @param {?} oScreen + * + * @constructor + * @extends KnoinAbstractViewModel + */ +function AdminMenuViewModel(oScreen) +{ + KnoinAbstractViewModel.call(this, 'Left', 'AdminMenu'); + + this.leftPanelDisabled = RL.data().leftPanelDisabled; + + this.menu = oScreen.menu; + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('AdminMenuViewModel', AdminMenuViewModel); + +AdminMenuViewModel.prototype.link = function (sRoute) +{ + return '#/' + sRoute; +}; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function AdminPaneViewModel() +{ + KnoinAbstractViewModel.call(this, 'Right', 'AdminPane'); + + this.adminDomain = ko.observable(RL.settingsGet('AdminDomain')); + this.version = ko.observable(RL.settingsGet('Version')); + + this.adminManLoadingVisibility = RL.data().adminManLoadingVisibility; + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('AdminPaneViewModel', AdminPaneViewModel); + +AdminPaneViewModel.prototype.logoutClick = function () +{ + RL.remote().adminLogout(function () { + RL.loginAndLogoutReload(); + }); +}; +/** + * @constructor + */ +function AdminGeneral() +{ + var oData = RL.data(); + + this.mainLanguage = oData.mainLanguage; + this.mainTheme = oData.mainTheme; + + this.language = oData.language; + this.theme = oData.theme; + + this.allowThemes = oData.allowThemes; + this.allowLanguagesOnSettings = oData.allowLanguagesOnSettings; + this.allowAdditionalAccounts = oData.allowAdditionalAccounts; + this.allowIdentities = oData.allowIdentities; + this.allowGravatar = oData.allowGravatar; + + this.themesOptions = ko.computed(function () { + return _.map(oData.themes(), function (sTheme) { + return { + 'optValue': sTheme, + 'optText': Utils.convertThemeName(sTheme) + }; + }); + }); + + this.mainLanguageFullName = ko.computed(function () { + return Utils.convertLangName(this.mainLanguage()); + }, this); + + this.weakPassword = !!RL.settingsGet('WeakPassword'); + + this.languageTrigger = ko.observable(Enums.SaveSettingsStep.Idle); + this.themeTrigger = ko.observable(Enums.SaveSettingsStep.Idle); +} + +Utils.addSettingsViewModel(AdminGeneral, 'AdminSettingsGeneral', 'General', 'general', true); + +AdminGeneral.prototype.onBuild = function () +{ + var self = this; + _.delay(function () { + + var + f2 = Utils.settingsSaveHelperSimpleFunction(self.languageTrigger, self), + f3 = Utils.settingsSaveHelperSimpleFunction(self.themeTrigger, self) + ; + + self.language.subscribe(function (sValue) { + RL.remote().saveAdminConfig(f2, { + 'Language': Utils.trim(sValue) + }); + }); + + self.theme.subscribe(function (sValue) { + RL.remote().saveAdminConfig(f3, { + 'Theme': Utils.trim(sValue) + }); + }); + + self.allowAdditionalAccounts.subscribe(function (bValue) { + RL.remote().saveAdminConfig(null, { + 'AllowAdditionalAccounts': bValue ? '1' : '0' + }); + }); + + self.allowIdentities.subscribe(function (bValue) { + RL.remote().saveAdminConfig(null, { + 'AllowIdentities': bValue ? '1' : '0' + }); + }); + + self.allowGravatar.subscribe(function (bValue) { + RL.remote().saveAdminConfig(null, { + 'AllowGravatar': bValue ? '1' : '0' + }); + }); + + self.allowThemes.subscribe(function (bValue) { + RL.remote().saveAdminConfig(null, { + 'AllowThemes': bValue ? '1' : '0' + }); + }); + + self.allowLanguagesOnSettings.subscribe(function (bValue) { + RL.remote().saveAdminConfig(null, { + 'AllowLanguagesOnSettings': bValue ? '1' : '0' + }); + }); + + }, 50); +}; + +AdminGeneral.prototype.selectLanguage = function () +{ + kn.showScreenPopup(PopupsLanguagesViewModel); +}; + +/** + * @constructor + */ +function AdminLogin() +{ + var oData = RL.data(); + + this.allowCustomLogin = oData.allowCustomLogin; + this.determineUserLanguage = oData.determineUserLanguage; + + this.defaultDomain = ko.observable(RL.settingsGet('LoginDefaultDomain')); + + this.allowLanguagesOnLogin = oData.allowLanguagesOnLogin; + this.defaultDomainTrigger = ko.observable(Enums.SaveSettingsStep.Idle); +} + +Utils.addSettingsViewModel(AdminLogin, 'AdminSettingsLogin', 'Login', 'login'); + +AdminLogin.prototype.onBuild = function () +{ + var self = this; + _.delay(function () { + + var f1 = Utils.settingsSaveHelperSimpleFunction(self.defaultDomainTrigger, self); + + self.determineUserLanguage.subscribe(function (bValue) { + RL.remote().saveAdminConfig(null, { + 'DetermineUserLanguage': bValue ? '1' : '0' + }); + }); + + self.allowCustomLogin.subscribe(function (bValue) { + RL.remote().saveAdminConfig(null, { + 'AllowCustomLogin': bValue ? '1' : '0' + }); + }); + + self.allowLanguagesOnLogin.subscribe(function (bValue) { + RL.remote().saveAdminConfig(null, { + 'AllowLanguagesOnLogin': bValue ? '1' : '0' + }); + }); + + self.defaultDomain.subscribe(function (sValue) { + RL.remote().saveAdminConfig(f1, { + 'LoginDefaultDomain': Utils.trim(sValue) + }); + }); + + }, 50); +}; + +/** + * @constructor + */ +function AdminBranding() +{ + this.title = ko.observable(RL.settingsGet('Title')); + this.title.trigger = ko.observable(Enums.SaveSettingsStep.Idle); + + this.loadingDesc = ko.observable(RL.settingsGet('LoadingDescription')); + this.loadingDesc.trigger = ko.observable(Enums.SaveSettingsStep.Idle); + + this.loginLogo = ko.observable(RL.settingsGet('LoginLogo')); + this.loginLogo.trigger = ko.observable(Enums.SaveSettingsStep.Idle); + + this.loginDescription = ko.observable(RL.settingsGet('LoginDescription')); + this.loginDescription.trigger = ko.observable(Enums.SaveSettingsStep.Idle); + + this.loginCss = ko.observable(RL.settingsGet('LoginCss')); + this.loginCss.trigger = ko.observable(Enums.SaveSettingsStep.Idle); +} + +Utils.addSettingsViewModel(AdminBranding, 'AdminSettingsBranding', 'Branding', 'branding'); + +AdminBranding.prototype.onBuild = function () +{ + var self = this; + _.delay(function () { + + var + f1 = Utils.settingsSaveHelperSimpleFunction(self.title.trigger, self), + f2 = Utils.settingsSaveHelperSimpleFunction(self.loadingDesc.trigger, self), + f3 = Utils.settingsSaveHelperSimpleFunction(self.loginLogo.trigger, self), + f4 = Utils.settingsSaveHelperSimpleFunction(self.loginDescription.trigger, self), + f5 = Utils.settingsSaveHelperSimpleFunction(self.loginCss.trigger, self) + ; + + self.title.subscribe(function (sValue) { + RL.remote().saveAdminConfig(f1, { + 'Title': Utils.trim(sValue) + }); + }); + + self.loadingDesc.subscribe(function (sValue) { + RL.remote().saveAdminConfig(f2, { + 'LoadingDescription': Utils.trim(sValue) + }); + }); + + self.loginLogo.subscribe(function (sValue) { + RL.remote().saveAdminConfig(f3, { + 'LoginLogo': Utils.trim(sValue) + }); + }); + + self.loginDescription.subscribe(function (sValue) { + RL.remote().saveAdminConfig(f4, { + 'LoginDescription': Utils.trim(sValue) + }); + }); + + self.loginCss.subscribe(function (sValue) { + RL.remote().saveAdminConfig(f5, { + 'LoginCss': Utils.trim(sValue) + }); + }); + + }, 50); +}; + +/** + * @constructor + */ +function AdminContacts() +{ +// var oData = RL.data(); + + this.defautOptionsAfterRender = Utils.defautOptionsAfterRender; + this.enableContacts = ko.observable(!!RL.settingsGet('ContactsEnable')); + this.contactsSharing = ko.observable(!!RL.settingsGet('ContactsSharing')); + this.contactsSync = ko.observable(!!RL.settingsGet('ContactsSync')); + + var + aTypes = ['sqlite', 'mysql', 'pgsql'], + aSupportedTypes = [], + getTypeName = function(sName) { + switch (sName) + { + case 'sqlite': + sName = 'SQLite'; + break; + case 'mysql': + sName = 'MySQL'; + break; + case 'pgsql': + sName = 'PostgreSQL'; + break; + } + + return sName; + } + ; + + if (!!RL.settingsGet('SQLiteIsSupported')) + { + aSupportedTypes.push('sqlite'); + } + if (!!RL.settingsGet('MySqlIsSupported')) + { + aSupportedTypes.push('mysql'); + } + if (!!RL.settingsGet('PostgreSqlIsSupported')) + { + aSupportedTypes.push('pgsql'); + } + + this.contactsSupported = 0 < aSupportedTypes.length; + + this.contactsTypes = ko.observableArray([]); + this.contactsTypesOptions = this.contactsTypes.map(function (sValue) { + var bDisabled = -1 === Utils.inArray(sValue, aSupportedTypes); + return { + 'id': sValue, + 'name': getTypeName(sValue) + (bDisabled ? ' (not supported)' : ''), + 'disabled': bDisabled + }; + }); + + this.contactsTypes(aTypes); + this.contactsType = ko.observable(''); + + this.mainContactsType = ko.computed({ + 'owner': this, + 'read': this.contactsType, + 'write': function (sValue) { + if (sValue !== this.contactsType()) + { + if (-1 < Utils.inArray(sValue, aSupportedTypes)) + { + this.contactsType(sValue); + } + else if (0 < aSupportedTypes.length) + { + this.contactsType(''); + } + } + else + { + this.contactsType.valueHasMutated(); + } + } + }); + + this.contactsType.subscribe(function () { + this.testContactsSuccess(false); + this.testContactsError(false); + this.testContactsErrorMessage(''); + }, this); + + this.pdoDsn = ko.observable(RL.settingsGet('ContactsPdoDsn')); + this.pdoUser = ko.observable(RL.settingsGet('ContactsPdoUser')); + this.pdoPassword = ko.observable(RL.settingsGet('ContactsPdoPassword')); + + this.pdoDsnTrigger = ko.observable(Enums.SaveSettingsStep.Idle); + this.pdoUserTrigger = ko.observable(Enums.SaveSettingsStep.Idle); + this.pdoPasswordTrigger = ko.observable(Enums.SaveSettingsStep.Idle); + this.contactsTypeTrigger = ko.observable(Enums.SaveSettingsStep.Idle); + + this.testing = ko.observable(false); + this.testContactsSuccess = ko.observable(false); + this.testContactsError = ko.observable(false); + this.testContactsErrorMessage = ko.observable(''); + + this.testContactsCommand = Utils.createCommand(this, function () { + + this.testContactsSuccess(false); + this.testContactsError(false); + this.testContactsErrorMessage(''); + this.testing(true); + + RL.remote().testContacts(this.onTestContactsResponse, { + 'ContactsPdoType': this.contactsType(), + 'ContactsPdoDsn': this.pdoDsn(), + 'ContactsPdoUser': this.pdoUser(), + 'ContactsPdoPassword': this.pdoPassword() + }); + + }, function () { + return '' !== this.pdoDsn() && '' !== this.pdoUser(); + }); + + this.contactsType(RL.settingsGet('ContactsPdoType')); + + this.onTestContactsResponse = _.bind(this.onTestContactsResponse, this); +} + +Utils.addSettingsViewModel(AdminContacts, 'AdminSettingsContacts', 'Contacts', 'contacts'); + +AdminContacts.prototype.onTestContactsResponse = function (sResult, oData) +{ + this.testContactsSuccess(false); + this.testContactsError(false); + this.testContactsErrorMessage(''); + + if (Enums.StorageResultType.Success === sResult && oData && oData.Result && oData.Result.Result) + { + this.testContactsSuccess(true); + } + else + { + this.testContactsError(true); + if (oData && oData.Result) + { + this.testContactsErrorMessage(oData.Result.Message || ''); + } + else + { + this.testContactsErrorMessage(''); + } + } + + this.testing(false); +}; + +AdminContacts.prototype.onShow = function () +{ + this.testContactsSuccess(false); + this.testContactsError(false); + this.testContactsErrorMessage(''); +}; + +AdminContacts.prototype.onBuild = function () +{ + var self = this; + _.delay(function () { + + var + f1 = Utils.settingsSaveHelperSimpleFunction(self.pdoDsnTrigger, self), + f3 = Utils.settingsSaveHelperSimpleFunction(self.pdoUserTrigger, self), + f4 = Utils.settingsSaveHelperSimpleFunction(self.pdoPasswordTrigger, self), + f5 = Utils.settingsSaveHelperSimpleFunction(self.contactsTypeTrigger, self) + ; + + self.enableContacts.subscribe(function (bValue) { + RL.remote().saveAdminConfig(null, { + 'ContactsEnable': bValue ? '1' : '0' + }); + }); + + self.contactsSharing.subscribe(function (bValue) { + RL.remote().saveAdminConfig(null, { + 'ContactsSharing': bValue ? '1' : '0' + }); + }); + + self.contactsSync.subscribe(function (bValue) { + RL.remote().saveAdminConfig(null, { + 'ContactsSync': bValue ? '1' : '0' + }); + }); + + self.contactsType.subscribe(function (sValue) { + RL.remote().saveAdminConfig(f5, { + 'ContactsPdoType': sValue + }); + }); + + self.pdoDsn.subscribe(function (sValue) { + RL.remote().saveAdminConfig(f1, { + 'ContactsPdoDsn': Utils.trim(sValue) + }); + }); + + self.pdoUser.subscribe(function (sValue) { + RL.remote().saveAdminConfig(f3, { + 'ContactsPdoUser': Utils.trim(sValue) + }); + }); + + self.pdoPassword.subscribe(function (sValue) { + RL.remote().saveAdminConfig(f4, { + 'ContactsPdoPassword': Utils.trim(sValue) + }); + }); + + self.contactsType(RL.settingsGet('ContactsPdoType')); + + }, 50); +}; + +/** + * @constructor + */ +function AdminDomains() +{ + var oData = RL.data(); + + this.domains = oData.domains; + this.domainsLoading = oData.domainsLoading; + + this.iDomainForDeletionTimeout = 0; + + this.visibility = ko.computed(function () { + return oData.domainsLoading() ? 'visible' : 'hidden'; + }, this); + + this.domainForDeletion = ko.observable(null).extend({'toggleSubscribe': [this, + function (oPrev) { + if (oPrev) + { + oPrev.deleteAccess(false); + } + }, function (oNext) { + if (oNext) + { + oNext.deleteAccess(true); + this.startDomainForDeletionTimeout(); + } + } + ]}); +} + +Utils.addSettingsViewModel(AdminDomains, 'AdminSettingsDomains', 'Domains', 'domains'); + +AdminDomains.prototype.startDomainForDeletionTimeout = function () +{ + var self = this; + window.clearInterval(this.iDomainForDeletionTimeout); + this.iDomainForDeletionTimeout = window.setTimeout(function () { + self.domainForDeletion(null); + }, 1000 * 3); +}; + +AdminDomains.prototype.createDomain = function () +{ + kn.showScreenPopup(PopupsDomainViewModel); +}; + +AdminDomains.prototype.deleteDomain = function (oDomain) +{ + this.domains.remove(oDomain); + RL.remote().domainDelete(_.bind(this.onDomainListChangeRequest, this), oDomain.name); +}; + +AdminDomains.prototype.disableDomain = function (oDomain) +{ + oDomain.disabled(!oDomain.disabled()); + RL.remote().domainDisable(_.bind(this.onDomainListChangeRequest, this), oDomain.name, oDomain.disabled()); +}; + +AdminDomains.prototype.onBuild = function (oDom) +{ + var self = this; + oDom + .on('click', '.b-admin-domains-list-table .e-item .e-action', function () { + var oDomainItem = ko.dataFor(this); + if (oDomainItem) + { + RL.remote().domain(_.bind(self.onDomainLoadRequest, self), oDomainItem.name); + } + }) + ; + + RL.reloadDomainList(); +}; + +AdminDomains.prototype.onDomainLoadRequest = function (sResult, oData) +{ + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + kn.showScreenPopup(PopupsDomainViewModel, [oData.Result]); + } +}; + +AdminDomains.prototype.onDomainListChangeRequest = function () +{ + RL.reloadDomainList(); +}; + +/** + * @constructor + */ +function AdminSecurity() +{ + this.csrfProtection = ko.observable(!!RL.settingsGet('UseTokenProtection')); + this.openPGP = ko.observable(!!RL.settingsGet('OpenPGP')); + this.allowTwoFactorAuth = ko.observable(!!RL.settingsGet('AllowTwoFactorAuth')); + + this.adminLogin = ko.observable(RL.settingsGet('AdminLogin')); + this.adminPassword = ko.observable(''); + this.adminPasswordNew = ko.observable(''); + this.adminPasswordNew2 = ko.observable(''); + this.adminPasswordNewError = ko.observable(false); + + this.adminPasswordUpdateError = ko.observable(false); + this.adminPasswordUpdateSuccess = ko.observable(false); + + this.adminPassword.subscribe(function () { + this.adminPasswordUpdateError(false); + this.adminPasswordUpdateSuccess(false); + }, this); + + this.adminPasswordNew.subscribe(function () { + this.adminPasswordUpdateError(false); + this.adminPasswordUpdateSuccess(false); + this.adminPasswordNewError(false); + }, this); + + this.adminPasswordNew2.subscribe(function () { + this.adminPasswordUpdateError(false); + this.adminPasswordUpdateSuccess(false); + this.adminPasswordNewError(false); + }, this); + + this.saveNewAdminPasswordCommand = Utils.createCommand(this, function () { + + if (this.adminPasswordNew() !== this.adminPasswordNew2()) + { + this.adminPasswordNewError(true); + return false; + } + + this.adminPasswordUpdateError(false); + this.adminPasswordUpdateSuccess(false); + + RL.remote().saveNewAdminPassword(this.onNewAdminPasswordResponse, { + 'Password': this.adminPassword(), + 'NewPassword': this.adminPasswordNew() + }); + + }, function () { + return '' !== this.adminPassword() && '' !== this.adminPasswordNew() && '' !== this.adminPasswordNew2(); + }); + + this.onNewAdminPasswordResponse = _.bind(this.onNewAdminPasswordResponse, this); +} + +Utils.addSettingsViewModel(AdminSecurity, 'AdminSettingsSecurity', 'Security', 'security'); + +AdminSecurity.prototype.onNewAdminPasswordResponse = function (sResult, oData) +{ + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + this.adminPassword(''); + this.adminPasswordNew(''); + this.adminPasswordNew2(''); + + this.adminPasswordUpdateSuccess(true); + } + else + { + this.adminPasswordUpdateError(true); + } +}; + +AdminSecurity.prototype.onBuild = function () +{ + this.csrfProtection.subscribe(function (bValue) { + RL.remote().saveAdminConfig(Utils.emptyFunction, { + 'TokenProtection': bValue ? '1' : '0' + }); + }); + + this.openPGP.subscribe(function (bValue) { + RL.remote().saveAdminConfig(Utils.emptyFunction, { + 'OpenPGP': bValue ? '1' : '0' + }); + }); + + this.allowTwoFactorAuth.subscribe(function (bValue) { + RL.remote().saveAdminConfig(Utils.emptyFunction, { + 'AllowTwoFactorAuth': bValue ? '1' : '0' + }); + }); +}; + +AdminSecurity.prototype.onHide = function () +{ + this.adminPassword(''); + this.adminPasswordNew(''); + this.adminPasswordNew2(''); +}; + +/** + * @return {string} + */ +AdminSecurity.prototype.phpInfoLink = function () +{ + return RL.link().phpInfo(); +}; + +/** + * @constructor + */ +function AdminSocial() +{ + var oData = RL.data(); + + this.googleEnable = oData.googleEnable; + this.googleClientID = oData.googleClientID; + this.googleClientSecret = oData.googleClientSecret; + this.googleTrigger1 = ko.observable(Enums.SaveSettingsStep.Idle); + this.googleTrigger2 = ko.observable(Enums.SaveSettingsStep.Idle); + + this.facebookEnable = oData.facebookEnable; + this.facebookAppID = oData.facebookAppID; + this.facebookAppSecret = oData.facebookAppSecret; + this.facebookTrigger1 = ko.observable(Enums.SaveSettingsStep.Idle); + this.facebookTrigger2 = ko.observable(Enums.SaveSettingsStep.Idle); + + this.twitterEnable = oData.twitterEnable; + this.twitterConsumerKey = oData.twitterConsumerKey; + this.twitterConsumerSecret = oData.twitterConsumerSecret; + this.twitterTrigger1 = ko.observable(Enums.SaveSettingsStep.Idle); + this.twitterTrigger2 = ko.observable(Enums.SaveSettingsStep.Idle); + + this.dropboxEnable = oData.dropboxEnable; + this.dropboxApiKey = oData.dropboxApiKey; + this.dropboxTrigger1 = ko.observable(Enums.SaveSettingsStep.Idle); +} + +Utils.addSettingsViewModel(AdminSocial, 'AdminSettingsSocial', 'Social', 'social'); + +AdminSocial.prototype.onBuild = function () +{ + var self = this; + _.delay(function () { + + var + f1 = Utils.settingsSaveHelperSimpleFunction(self.facebookTrigger1, self), + f2 = Utils.settingsSaveHelperSimpleFunction(self.facebookTrigger2, self), + f3 = Utils.settingsSaveHelperSimpleFunction(self.twitterTrigger1, self), + f4 = Utils.settingsSaveHelperSimpleFunction(self.twitterTrigger2, self), + f5 = Utils.settingsSaveHelperSimpleFunction(self.googleTrigger1, self), + f6 = Utils.settingsSaveHelperSimpleFunction(self.googleTrigger2, self), + f7 = Utils.settingsSaveHelperSimpleFunction(self.dropboxTrigger1, self) + ; + + self.facebookEnable.subscribe(function (bValue) { + RL.remote().saveAdminConfig(Utils.emptyFunction, { + 'FacebookEnable': bValue ? '1' : '0' + }); + }); + + self.facebookAppID.subscribe(function (sValue) { + RL.remote().saveAdminConfig(f1, { + 'FacebookAppID': Utils.trim(sValue) + }); + }); + + self.facebookAppSecret.subscribe(function (sValue) { + RL.remote().saveAdminConfig(f2, { + 'FacebookAppSecret': Utils.trim(sValue) + }); + }); + + self.twitterEnable.subscribe(function (bValue) { + RL.remote().saveAdminConfig(Utils.emptyFunction, { + 'TwitterEnable': bValue ? '1' : '0' + }); + }); + + self.twitterConsumerKey.subscribe(function (sValue) { + RL.remote().saveAdminConfig(f3, { + 'TwitterConsumerKey': Utils.trim(sValue) + }); + }); + + self.twitterConsumerSecret.subscribe(function (sValue) { + RL.remote().saveAdminConfig(f4, { + 'TwitterConsumerSecret': Utils.trim(sValue) + }); + }); + + self.googleEnable.subscribe(function (bValue) { + RL.remote().saveAdminConfig(Utils.emptyFunction, { + 'GoogleEnable': bValue ? '1' : '0' + }); + }); + + self.googleClientID.subscribe(function (sValue) { + RL.remote().saveAdminConfig(f5, { + 'GoogleClientID': Utils.trim(sValue) + }); + }); + + self.googleClientSecret.subscribe(function (sValue) { + RL.remote().saveAdminConfig(f6, { + 'GoogleClientSecret': Utils.trim(sValue) + }); + }); + + self.dropboxEnable.subscribe(function (bValue) { + RL.remote().saveAdminConfig(Utils.emptyFunction, { + 'DropboxEnable': bValue ? '1' : '0' + }); + }); + + self.dropboxApiKey.subscribe(function (sValue) { + RL.remote().saveAdminConfig(f7, { + 'DropboxApiKey': Utils.trim(sValue) + }); + }); + + }, 50); +}; + +/** + * @constructor + */ +function AdminPlugins() +{ + var oData = RL.data(); + + this.enabledPlugins = ko.observable(!!RL.settingsGet('EnabledPlugins')); + + this.pluginsError = ko.observable(''); + + this.plugins = oData.plugins; + this.pluginsLoading = oData.pluginsLoading; + + this.visibility = ko.computed(function () { + return oData.pluginsLoading() ? 'visible' : 'hidden'; + }, this); + + this.onPluginLoadRequest = _.bind(this.onPluginLoadRequest, this); + this.onPluginDisableRequest = _.bind(this.onPluginDisableRequest, this); +} + +Utils.addSettingsViewModel(AdminPlugins, 'AdminSettingsPlugins', 'Plugins', 'plugins'); + +AdminPlugins.prototype.disablePlugin = function (oPlugin) +{ + oPlugin.disabled(!oPlugin.disabled()); + RL.remote().pluginDisable(this.onPluginDisableRequest, oPlugin.name, oPlugin.disabled()); +}; + +AdminPlugins.prototype.configurePlugin = function (oPlugin) +{ + RL.remote().plugin(this.onPluginLoadRequest, oPlugin.name); +}; + +AdminPlugins.prototype.onBuild = function (oDom) +{ + var self = this; + + oDom + .on('click', '.e-item .configure-plugin-action', function () { + var oPlugin = ko.dataFor(this); + if (oPlugin) + { + self.configurePlugin(oPlugin); + } + }) + .on('click', '.e-item .disabled-plugin', function () { + var oPlugin = ko.dataFor(this); + if (oPlugin) + { + self.disablePlugin(oPlugin); + } + }) + ; + + this.enabledPlugins.subscribe(function (bValue) { + RL.remote().saveAdminConfig(Utils.emptyFunction, { + 'EnabledPlugins': bValue ? '1' : '0' + }); + }); +}; + +AdminPlugins.prototype.onShow = function () +{ + this.pluginsError(''); + RL.reloadPluginList(); +}; + +AdminPlugins.prototype.onPluginLoadRequest = function (sResult, oData) +{ + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + kn.showScreenPopup(PopupsPluginViewModel, [oData.Result]); + } +}; + +AdminPlugins.prototype.onPluginDisableRequest = function (sResult, oData) +{ + if (Enums.StorageResultType.Success === sResult && oData) + { + if (!oData.Result && oData.ErrorCode) + { + if (Enums.Notification.UnsupportedPluginPackage === oData.ErrorCode && oData.ErrorMessage && '' !== oData.ErrorMessage) + { + this.pluginsError(oData.ErrorMessage); + } + else + { + this.pluginsError(Utils.getNotification(oData.ErrorCode)); + } + } + } + + RL.reloadPluginList(); +}; + +/** + * @constructor + */ +function AdminPackages() +{ + var oData = RL.data(); + + this.packagesError = ko.observable(''); + + this.packages = oData.packages; + this.packagesLoading = oData.packagesLoading; + this.packagesReal = oData.packagesReal; + this.packagesMainUpdatable = oData.packagesMainUpdatable; + + this.packagesCurrent = this.packages.filter(function (oItem) { + return oItem && '' !== oItem['installed'] && !oItem['compare']; + }); + + this.packagesAvailableForUpdate = this.packages.filter(function (oItem) { + return oItem && '' !== oItem['installed'] && !!oItem['compare']; + }); + + this.packagesAvailableForInstallation = this.packages.filter(function (oItem) { + return oItem && '' === oItem['installed']; + }); + + this.visibility = ko.computed(function () { + return oData.packagesLoading() ? 'visible' : 'hidden'; + }, this); +} + +Utils.addSettingsViewModel(AdminPackages, 'AdminSettingsPackages', 'Packages', 'packages'); + +AdminPackages.prototype.onShow = function () +{ + this.packagesError(''); +}; + +AdminPackages.prototype.onBuild = function () +{ + RL.reloadPackagesList(); +}; + +AdminPackages.prototype.requestHelper = function (oPackage, bInstall) +{ + var self = this; + return function (sResult, oData) { + + if (Enums.StorageResultType.Success !== sResult || !oData || !oData.Result) + { + if (oData && oData.ErrorCode) + { + self.packagesError(Utils.getNotification(oData.ErrorCode)); + } + else + { + self.packagesError(Utils.getNotification( + bInstall ? Enums.Notification.CantInstallPackage : Enums.Notification.CantDeletePackage)); + } + } + + _.each(RL.data().packages(), function (oItem) { + if (oItem && oPackage && oItem['loading']() && oPackage['file'] === oItem['file']) + { + oPackage['loading'](false); + oItem['loading'](false); + } + }); + + if (Enums.StorageResultType.Success === sResult && oData && oData.Result && oData.Result['Reload']) + { + window.location.reload(); + } + else + { + RL.reloadPackagesList(); + } + }; +}; + +AdminPackages.prototype.deletePackage = function (oPackage) +{ + if (oPackage) + { + oPackage['loading'](true); + RL.remote().packageDelete(this.requestHelper(oPackage, false), oPackage); + } +}; + +AdminPackages.prototype.installPackage = function (oPackage) +{ + if (oPackage) + { + oPackage['loading'](true); + RL.remote().packageInstall(this.requestHelper(oPackage, true), oPackage); + } +}; + +/** + * @constructor + */ +function AdminLicensing() +{ + this.licensing = RL.data().licensing; + this.licensingProcess = RL.data().licensingProcess; + this.licenseValid = RL.data().licenseValid; + this.licenseExpired = RL.data().licenseExpired; + this.licenseError = RL.data().licenseError; + this.licenseTrigger = RL.data().licenseTrigger; + + this.adminDomain = ko.observable(''); + this.subscriptionEnabled = ko.observable(!!RL.settingsGet('SubscriptionEnabled')); + + this.licenseTrigger.subscribe(function () { + if (this.subscriptionEnabled()) + { + RL.reloadLicensing(true); + } + }, this); +} + +Utils.addSettingsViewModel(AdminLicensing, 'AdminSettingsLicensing', 'Licensing', 'licensing'); + +AdminLicensing.prototype.onBuild = function () +{ + if (this.subscriptionEnabled()) + { + RL.reloadLicensing(false); + } +}; + +AdminLicensing.prototype.onShow = function () +{ + this.adminDomain(RL.settingsGet('AdminDomain')); +}; + +AdminLicensing.prototype.showActivationForm = function () +{ + kn.showScreenPopup(PopupsActivateViewModel); +}; + +/** + * @returns {string} + */ +AdminLicensing.prototype.licenseExpiredMomentValue = function () +{ + var oDate = moment.unix(this.licenseExpired()); + return oDate.format('LL') + ' (' + oDate.from(moment()) + ')'; +}; +/** + * @constructor + */ +function AbstractData() +{ + this.leftPanelDisabled = ko.observable(false); + this.useKeyboardShortcuts = ko.observable(true); + + this.keyScopeReal = ko.observable(Enums.KeyState.All); + this.keyScopeFake = ko.observable(Enums.KeyState.All); + + this.keyScope = ko.computed({ + 'owner': this, + 'read': function () { + return this.keyScopeFake(); + }, + 'write': function (sValue) { + + if (Enums.KeyState.Menu !== sValue) + { + if (Enums.KeyState.Compose === sValue) + { + Utils.disableKeyFilter(); + } + else + { + Utils.restoreKeyFilter(); + } + + this.keyScopeFake(sValue); + if (Globals.dropdownVisibility()) + { + sValue = Enums.KeyState.Menu; + } + } + + this.keyScopeReal(sValue); + } + }); + + this.keyScopeReal.subscribe(function (sValue) { +// window.console.log(sValue); + key.setScope(sValue); + }); + + this.leftPanelDisabled.subscribe(function (bValue) { + RL.pub('left-panel.' + (bValue ? 'off' : 'on')); + }); + + Globals.dropdownVisibility.subscribe(function (bValue) { + if (bValue) + { + this.keyScope(Enums.KeyState.Menu); + } + else if (Enums.KeyState.Menu === key.getScope()) + { + this.keyScope(this.keyScopeFake()); + } + }, this); + + Utils.initDataConstructorBySettings(this); +} + +AbstractData.prototype.populateDataOnStart = function() +{ + var + mLayout = Utils.pInt(RL.settingsGet('Layout')), + aLanguages = RL.settingsGet('Languages'), + aThemes = RL.settingsGet('Themes') + ; + + if (Utils.isArray(aLanguages)) + { + this.languages(aLanguages); + } + + if (Utils.isArray(aThemes)) + { + this.themes(aThemes); + } + + this.mainLanguage(RL.settingsGet('Language')); + this.mainTheme(RL.settingsGet('Theme')); + + this.allowAdditionalAccounts(!!RL.settingsGet('AllowAdditionalAccounts')); + this.allowIdentities(!!RL.settingsGet('AllowIdentities')); + this.allowGravatar(!!RL.settingsGet('AllowGravatar')); + this.determineUserLanguage(!!RL.settingsGet('DetermineUserLanguage')); + + this.allowThemes(!!RL.settingsGet('AllowThemes')); + this.allowCustomLogin(!!RL.settingsGet('AllowCustomLogin')); + this.allowLanguagesOnLogin(!!RL.settingsGet('AllowLanguagesOnLogin')); + this.allowLanguagesOnSettings(!!RL.settingsGet('AllowLanguagesOnSettings')); + + this.editorDefaultType(RL.settingsGet('EditorDefaultType')); + this.showImages(!!RL.settingsGet('ShowImages')); + this.contactsAutosave(!!RL.settingsGet('ContactsAutosave')); + this.interfaceAnimation(RL.settingsGet('InterfaceAnimation')); + + this.mainMessagesPerPage(RL.settingsGet('MPP')); + + this.desktopNotifications(!!RL.settingsGet('DesktopNotifications')); + this.useThreads(!!RL.settingsGet('UseThreads')); + this.replySameFolder(!!RL.settingsGet('ReplySameFolder')); + this.useCheckboxesInList(!!RL.settingsGet('UseCheckboxesInList')); + + this.layout(Enums.Layout.SidePreview); + if (-1 < Utils.inArray(mLayout, [Enums.Layout.NoPreview, Enums.Layout.SidePreview, Enums.Layout.BottomPreview])) + { + this.layout(mLayout); + } + + this.facebookEnable(!!RL.settingsGet('AllowFacebookSocial')); + this.facebookAppID(RL.settingsGet('FacebookAppID')); + this.facebookAppSecret(RL.settingsGet('FacebookAppSecret')); + + this.twitterEnable(!!RL.settingsGet('AllowTwitterSocial')); + this.twitterConsumerKey(RL.settingsGet('TwitterConsumerKey')); + this.twitterConsumerSecret(RL.settingsGet('TwitterConsumerSecret')); + + this.googleEnable(!!RL.settingsGet('AllowGoogleSocial')); + this.googleClientID(RL.settingsGet('GoogleClientID')); + this.googleClientSecret(RL.settingsGet('GoogleClientSecret')); + + this.dropboxEnable(!!RL.settingsGet('AllowDropboxSocial')); + this.dropboxApiKey(RL.settingsGet('DropboxApiKey')); + + this.contactsIsAllowed(!!RL.settingsGet('ContactsIsAllowed')); +}; + +/** + * @constructor + * @extends AbstractData + */ +function AdminDataStorage() +{ + AbstractData.call(this); + + this.domainsLoading = ko.observable(false).extend({'throttle': 100}); + this.domains = ko.observableArray([]); + + this.pluginsLoading = ko.observable(false).extend({'throttle': 100}); + this.plugins = ko.observableArray([]); + + this.packagesReal = ko.observable(true); + this.packagesMainUpdatable = ko.observable(true); + this.packagesLoading = ko.observable(false).extend({'throttle': 100}); + this.packages = ko.observableArray([]); + + this.licensing = ko.observable(false); + this.licensingProcess = ko.observable(false); + this.licenseValid = ko.observable(false); + this.licenseExpired = ko.observable(0); + this.licenseError = ko.observable(''); + + this.licenseTrigger = ko.observable(false); + + this.adminManLoading = ko.computed(function () { + return '000' !== [this.domainsLoading() ? '1' : '0', this.pluginsLoading() ? '1' : '0', this.packagesLoading() ? '1' : '0'].join(''); + }, this); + + this.adminManLoadingVisibility = ko.computed(function () { + return this.adminManLoading() ? 'visible' : 'hidden'; + }, this).extend({'rateLimit': 300}); +} + +_.extend(AdminDataStorage.prototype, AbstractData.prototype); + +AdminDataStorage.prototype.populateDataOnStart = function() +{ + AbstractData.prototype.populateDataOnStart.call(this); +}; +/** + * @constructor + */ +function AbstractAjaxRemoteStorage() +{ + this.oRequests = {}; +} + +AbstractAjaxRemoteStorage.prototype.oRequests = {}; + +/** + * @param {?Function} fCallback + * @param {string} sRequestAction + * @param {string} sType + * @param {?AjaxJsonDefaultResponse} oData + * @param {boolean} bCached + * @param {*=} oRequestParameters + */ +AbstractAjaxRemoteStorage.prototype.defaultResponse = function (fCallback, sRequestAction, sType, oData, bCached, oRequestParameters) +{ + var + fCall = function () { + if (Enums.StorageResultType.Success !== sType && Globals.bUnload) + { + sType = Enums.StorageResultType.Unload; + } + + if (Enums.StorageResultType.Success === sType && oData && !oData.Result) + { + if (oData && -1 < Utils.inArray(oData.ErrorCode, [ + Enums.Notification.AuthError, Enums.Notification.AccessError, + Enums.Notification.ConnectionError, Enums.Notification.DomainNotAllowed, Enums.Notification.AccountNotAllowed, + Enums.Notification.MailServerError, Enums.Notification.UnknownNotification, Enums.Notification.UnknownError + ])) + { + Globals.iAjaxErrorCount++; + } + + if (oData && Enums.Notification.InvalidToken === oData.ErrorCode) + { + Globals.iTokenErrorCount++; + } + + if (Consts.Values.TokenErrorLimit < Globals.iTokenErrorCount) + { + RL.loginAndLogoutReload(true); + } + + if (oData.Logout || Consts.Values.AjaxErrorLimit < Globals.iAjaxErrorCount) + { + if (window.__rlah_clear) + { + window.__rlah_clear(); + } + + RL.loginAndLogoutReload(true); + } + } + else if (Enums.StorageResultType.Success === sType && oData && oData.Result) + { + Globals.iAjaxErrorCount = 0; + Globals.iTokenErrorCount = 0; + } + + if (fCallback) + { + Plugins.runHook('ajax-default-response', [sRequestAction, Enums.StorageResultType.Success === sType ? oData : null, sType, bCached, oRequestParameters]); + + fCallback( + sType, + Enums.StorageResultType.Success === sType ? oData : null, + bCached, + sRequestAction, + oRequestParameters + ); + } + } + ; + + switch (sType) + { + case 'success': + sType = Enums.StorageResultType.Success; + break; + case 'abort': + sType = Enums.StorageResultType.Abort; + break; + default: + sType = Enums.StorageResultType.Error; + break; + } + + if (Enums.StorageResultType.Error === sType) + { + _.delay(fCall, 300); + } + else + { + fCall(); + } +}; + +/** + * @param {?Function} fResultCallback + * @param {Object} oParameters + * @param {?number=} iTimeOut = 20000 + * @param {string=} sGetAdd = '' + * @param {Array=} aAbortActions = [] + * @return {jQuery.jqXHR} + */ +AbstractAjaxRemoteStorage.prototype.ajaxRequest = function (fResultCallback, oParameters, iTimeOut, sGetAdd, aAbortActions) +{ + var + self = this, + bPost = '' === sGetAdd, + oHeaders = {}, + iStart = (new window.Date()).getTime(), + oDefAjax = null, + sAction = '' + ; + + oParameters = oParameters || {}; + iTimeOut = Utils.isNormal(iTimeOut) ? iTimeOut : 20000; + sGetAdd = Utils.isUnd(sGetAdd) ? '' : Utils.pString(sGetAdd); + aAbortActions = Utils.isArray(aAbortActions) ? aAbortActions : []; + + sAction = oParameters.Action || ''; + + if (sAction && 0 < aAbortActions.length) + { + _.each(aAbortActions, function (sActionToAbort) { + if (self.oRequests[sActionToAbort]) + { + self.oRequests[sActionToAbort].__aborted = true; + if (self.oRequests[sActionToAbort].abort) + { + self.oRequests[sActionToAbort].abort(); + } + self.oRequests[sActionToAbort] = null; + } + }); + } + + if (bPost) + { + oParameters['XToken'] = RL.settingsGet('Token'); + } + + oDefAjax = $.ajax({ + 'type': bPost ? 'POST' : 'GET', + 'url': RL.link().ajax(sGetAdd) , + 'async': true, + 'dataType': 'json', + 'data': bPost ? oParameters : {}, + 'headers': oHeaders, + 'timeout': iTimeOut, + 'global': true + }); + + oDefAjax.always(function (oData, sType) { + + var bCached = false; + if (oData && oData['Time']) + { + bCached = Utils.pInt(oData['Time']) > (new window.Date()).getTime() - iStart; + } + + if (sAction && self.oRequests[sAction]) + { + if (self.oRequests[sAction].__aborted) + { + sType = 'abort'; + } + + self.oRequests[sAction] = null; + } + + self.defaultResponse(fResultCallback, sAction, sType, oData, bCached, oParameters); + }); + + if (sAction && 0 < aAbortActions.length && -1 < Utils.inArray(sAction, aAbortActions)) + { + if (this.oRequests[sAction]) + { + this.oRequests[sAction].__aborted = true; + if (this.oRequests[sAction].abort) + { + this.oRequests[sAction].abort(); + } + this.oRequests[sAction] = null; + } + + this.oRequests[sAction] = oDefAjax; + } + + return oDefAjax; +}; + +/** + * @param {?Function} fCallback + * @param {string} sAction + * @param {Object=} oParameters + * @param {?number=} iTimeout + * @param {string=} sGetAdd = '' + * @param {Array=} aAbortActions = [] + */ +AbstractAjaxRemoteStorage.prototype.defaultRequest = function (fCallback, sAction, oParameters, iTimeout, sGetAdd, aAbortActions) +{ + oParameters = oParameters || {}; + oParameters.Action = sAction; + + sGetAdd = Utils.pString(sGetAdd); + + Plugins.runHook('ajax-default-request', [sAction, oParameters, sGetAdd]); + + this.ajaxRequest(fCallback, oParameters, + Utils.isUnd(iTimeout) ? Consts.Defaults.DefaultAjaxTimeout : Utils.pInt(iTimeout), sGetAdd, aAbortActions); +}; + +/** + * @param {?Function} fCallback + */ +AbstractAjaxRemoteStorage.prototype.noop = function (fCallback) +{ + this.defaultRequest(fCallback, 'Noop'); +}; + +/** + * @param {?Function} fCallback + * @param {string} sMessage + * @param {string} sFileName + * @param {number} iLineNo + * @param {string} sLocation + * @param {string} sHtmlCapa + * @param {number} iTime + */ +AbstractAjaxRemoteStorage.prototype.jsError = function (fCallback, sMessage, sFileName, iLineNo, sLocation, sHtmlCapa, iTime) +{ + this.defaultRequest(fCallback, 'JsError', { + 'Message': sMessage, + 'FileName': sFileName, + 'LineNo': iLineNo, + 'Location': sLocation, + 'HtmlCapa': sHtmlCapa, + 'TimeOnPage': iTime + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sType + * @param {Array=} mData = null + * @param {boolean=} bIsError = false + */ +AbstractAjaxRemoteStorage.prototype.jsInfo = function (fCallback, sType, mData, bIsError) +{ + this.defaultRequest(fCallback, 'JsInfo', { + 'Type': sType, + 'Data': mData, + 'IsError': (Utils.isUnd(bIsError) ? false : !!bIsError) ? '1' : '0' + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sVersion + */ +AbstractAjaxRemoteStorage.prototype.jsVersion = function (fCallback, sVersion) +{ + this.defaultRequest(fCallback, 'Version', { + 'Version': sVersion + }); +}; + +/** + * @constructor + * @extends AbstractAjaxRemoteStorage + */ +function AdminAjaxRemoteStorage() +{ + AbstractAjaxRemoteStorage.call(this); + + this.oRequests = {}; +} + +_.extend(AdminAjaxRemoteStorage.prototype, AbstractAjaxRemoteStorage.prototype); + +/** + * @param {?Function} fCallback + * @param {string} sLogin + * @param {string} sPassword + */ +AdminAjaxRemoteStorage.prototype.adminLogin = function (fCallback, sLogin, sPassword) +{ + this.defaultRequest(fCallback, 'AdminLogin', { + 'Login': sLogin, + 'Password': sPassword + }); +}; + +/** + * @param {?Function} fCallback + */ +AdminAjaxRemoteStorage.prototype.adminLogout = function (fCallback) +{ + this.defaultRequest(fCallback, 'AdminLogout'); +}; + +/** + * @param {?Function} fCallback + * @param {?} oData + */ +AdminAjaxRemoteStorage.prototype.saveAdminConfig = function (fCallback, oData) +{ + this.defaultRequest(fCallback, 'AdminSettingsUpdate', oData); +}; + +/** + * @param {?Function} fCallback + */ +AdminAjaxRemoteStorage.prototype.domainList = function (fCallback) +{ + this.defaultRequest(fCallback, 'AdminDomainList'); +}; + +/** + * @param {?Function} fCallback + */ +AdminAjaxRemoteStorage.prototype.pluginList = function (fCallback) +{ + this.defaultRequest(fCallback, 'AdminPluginList'); +}; + +/** + * @param {?Function} fCallback + */ +AdminAjaxRemoteStorage.prototype.packagesList = function (fCallback) +{ + this.defaultRequest(fCallback, 'AdminPackagesList'); +}; + +/** + * @param {?Function} fCallback + * @param {Object} oPackage + */ +AdminAjaxRemoteStorage.prototype.packageInstall = function (fCallback, oPackage) +{ + this.defaultRequest(fCallback, 'AdminPackageInstall', { + 'Id': oPackage.id, + 'Type': oPackage.type, + 'File': oPackage.file + }, 60000); +}; + +/** + * @param {?Function} fCallback + * @param {Object} oPackage + */ +AdminAjaxRemoteStorage.prototype.packageDelete = function (fCallback, oPackage) +{ + this.defaultRequest(fCallback, 'AdminPackageDelete', { + 'Id': oPackage.id + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sName + */ +AdminAjaxRemoteStorage.prototype.domain = function (fCallback, sName) +{ + this.defaultRequest(fCallback, 'AdminDomainLoad', { + 'Name': sName + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sName + */ +AdminAjaxRemoteStorage.prototype.plugin = function (fCallback, sName) +{ + this.defaultRequest(fCallback, 'AdminPluginLoad', { + 'Name': sName + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sName + */ +AdminAjaxRemoteStorage.prototype.domainDelete = function (fCallback, sName) +{ + this.defaultRequest(fCallback, 'AdminDomainDelete', { + 'Name': sName + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sName + * @param {boolean} bDisabled + */ +AdminAjaxRemoteStorage.prototype.domainDisable = function (fCallback, sName, bDisabled) +{ + return this.defaultRequest(fCallback, 'AdminDomainDisable', { + 'Name': sName, + 'Disabled': !!bDisabled ? '1' : '0' + }); +}; + +/** + * @param {?Function} fCallback + * @param {Object} oConfig + */ +AdminAjaxRemoteStorage.prototype.pluginSettingsUpdate = function (fCallback, oConfig) +{ + return this.defaultRequest(fCallback, 'AdminPluginSettingsUpdate', oConfig); +}; + +/** + * @param {?Function} fCallback + * @param {boolean} bForce + */ +AdminAjaxRemoteStorage.prototype.licensing = function (fCallback, bForce) +{ + return this.defaultRequest(fCallback, 'AdminLicensing', { + 'Force' : bForce ? '1' : '0' + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sDomain + * @param {string} sKey + */ +AdminAjaxRemoteStorage.prototype.licensingActivate = function (fCallback, sDomain, sKey) +{ + return this.defaultRequest(fCallback, 'AdminLicensingActivate', { + 'Domain' : sDomain, + 'Key' : sKey + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sName + * @param {boolean} bDisabled + */ +AdminAjaxRemoteStorage.prototype.pluginDisable = function (fCallback, sName, bDisabled) +{ + return this.defaultRequest(fCallback, 'AdminPluginDisable', { + 'Name': sName, + 'Disabled': !!bDisabled ? '1' : '0' + }); +}; + +AdminAjaxRemoteStorage.prototype.createOrUpdateDomain = function (fCallback, + bCreate, sName, sIncHost, iIncPort, sIncSecure, bIncShortLogin, + sOutHost, iOutPort, sOutSecure, bOutShortLogin, bOutAuth, sWhiteList) +{ + this.defaultRequest(fCallback, 'AdminDomainSave', { + 'Create': bCreate ? '1' : '0', + 'Name': sName, + 'IncHost': sIncHost, + 'IncPort': iIncPort, + 'IncSecure': sIncSecure, + 'IncShortLogin': bIncShortLogin ? '1' : '0', + 'OutHost': sOutHost, + 'OutPort': iOutPort, + 'OutSecure': sOutSecure, + 'OutShortLogin': bOutShortLogin ? '1' : '0', + 'OutAuth': bOutAuth ? '1' : '0', + 'WhiteList': sWhiteList + }); +}; + +AdminAjaxRemoteStorage.prototype.testConnectionForDomain = function (fCallback, sName, + sIncHost, iIncPort, sIncSecure, + sOutHost, iOutPort, sOutSecure, bOutAuth) +{ + this.defaultRequest(fCallback, 'AdminDomainTest', { + 'Name': sName, + 'IncHost': sIncHost, + 'IncPort': iIncPort, + 'IncSecure': sIncSecure, + 'OutHost': sOutHost, + 'OutPort': iOutPort, + 'OutSecure': sOutSecure, + 'OutAuth': bOutAuth ? '1' : '0' + }); +}; + +/** + * @param {?Function} fCallback + * @param {?} oData + */ +AdminAjaxRemoteStorage.prototype.testContacts = function (fCallback, oData) +{ + this.defaultRequest(fCallback, 'AdminContactsTest', oData); +}; + +/** + * @param {?Function} fCallback + * @param {?} oData + */ +AdminAjaxRemoteStorage.prototype.saveNewAdminPassword = function (fCallback, oData) +{ + this.defaultRequest(fCallback, 'AdminPasswordUpdate', oData); +}; + +/** + * @param {?Function} fCallback + */ +AdminAjaxRemoteStorage.prototype.adminPing = function (fCallback) +{ + this.defaultRequest(fCallback, 'AdminPing'); +}; + +/** + * @constructor + */ +function AbstractCacheStorage() +{ + this.oEmailsPicsHashes = {}; + this.oServices = {}; + this.bAllowGravatar = !!RL.settingsGet('AllowGravatar'); +} + +/** + * @type {Object} + */ +AbstractCacheStorage.prototype.oEmailsPicsHashes = {}; + +/** + * @type {Object} + */ +AbstractCacheStorage.prototype.oServices = {}; + +/** + * @type {boolean} + */ +AbstractCacheStorage.prototype.bAllowGravatar = false; + +AbstractCacheStorage.prototype.clear = function () +{ + this.oServices = {}; + this.oEmailsPicsHashes = {}; +}; + +/** + * @param {string} sEmail + * @return {string} + */ +AbstractCacheStorage.prototype.getUserPic = function (sEmail, fCallback) +{ + sEmail = Utils.trim(sEmail); + + var + sUrl = '', + sService = '', + sEmailLower = sEmail.toLowerCase(), + sPicHash = Utils.isUnd(this.oEmailsPicsHashes[sEmailLower]) ? '' : this.oEmailsPicsHashes[sEmailLower] + ; + + if ('' !== sPicHash) + { + sUrl = RL.link().getUserPicUrlFromHash(sPicHash); + } + else + { + sService = sEmailLower.substr(sEmail.indexOf('@') + 1); + sUrl = '' !== sService && this.oServices[sService] ? this.oServices[sService] : ''; + } + + + if (this.bAllowGravatar && '' === sUrl) + { + fCallback('//secure.gravatar.com/avatar/' + Utils.md5(sEmailLower) + '.jpg?s=80&d=mm', sEmail); + } + else + { + fCallback(sUrl, sEmail); + } +}; + +/** + * @param {Object} oData + */ +AbstractCacheStorage.prototype.setServicesData = function (oData) +{ + this.oServices = oData; +}; + +/** + * @param {Object} oData + */ +AbstractCacheStorage.prototype.setEmailsPicsHashesData = function (oData) +{ + this.oEmailsPicsHashes = oData; +}; + +/** + * @constructor + * @extends AbstractCacheStorage + */ +function AdminCacheStorage() +{ + AbstractCacheStorage.call(this); +} + +_.extend(AdminCacheStorage.prototype, AbstractCacheStorage.prototype); + +/** + * @param {Array} aViewModels + * @constructor + * @extends KnoinAbstractScreen + */ +function AbstractSettings(aViewModels) +{ + KnoinAbstractScreen.call(this, 'settings', aViewModels); + + this.menu = ko.observableArray([]); + + this.oCurrentSubScreen = null; + this.oViewModelPlace = null; +} + +_.extend(AbstractSettings.prototype, KnoinAbstractScreen.prototype); + +AbstractSettings.prototype.onRoute = function (sSubName) +{ + var + self = this, + oSettingsScreen = null, + RoutedSettingsViewModel = null, + oViewModelPlace = null, + oViewModelDom = null + ; + + RoutedSettingsViewModel = _.find(ViewModels['settings'], function (SettingsViewModel) { + return SettingsViewModel && SettingsViewModel.__rlSettingsData && + sSubName === SettingsViewModel.__rlSettingsData.Route; + }); + + if (RoutedSettingsViewModel) + { + if (_.find(ViewModels['settings-removed'], function (DisabledSettingsViewModel) { + return DisabledSettingsViewModel && DisabledSettingsViewModel === RoutedSettingsViewModel; + })) + { + RoutedSettingsViewModel = null; + } + + if (RoutedSettingsViewModel && _.find(ViewModels['settings-disabled'], function (DisabledSettingsViewModel) { + return DisabledSettingsViewModel && DisabledSettingsViewModel === RoutedSettingsViewModel; + })) + { + RoutedSettingsViewModel = null; + } + } + + if (RoutedSettingsViewModel) + { + if (RoutedSettingsViewModel.__builded && RoutedSettingsViewModel.__vm) + { + oSettingsScreen = RoutedSettingsViewModel.__vm; + } + else + { + oViewModelPlace = this.oViewModelPlace; + if (oViewModelPlace && 1 === oViewModelPlace.length) + { + RoutedSettingsViewModel = /** @type {?Function} */ RoutedSettingsViewModel; + oSettingsScreen = new RoutedSettingsViewModel(); + + oViewModelDom = $('').addClass('rl-settings-view-model').hide().attr('data-bind', + 'template: {name: "' + RoutedSettingsViewModel.__rlSettingsData.Template + '"}, i18nInit: true'); + + oViewModelDom.appendTo(oViewModelPlace); + + oSettingsScreen.data = RL.data(); + oSettingsScreen.viewModelDom = oViewModelDom; + + oSettingsScreen.__rlSettingsData = RoutedSettingsViewModel.__rlSettingsData; + + RoutedSettingsViewModel.__dom = oViewModelDom; + RoutedSettingsViewModel.__builded = true; + RoutedSettingsViewModel.__vm = oSettingsScreen; + + ko.applyBindings(oSettingsScreen, oViewModelDom[0]); + Utils.delegateRun(oSettingsScreen, 'onBuild', [oViewModelDom]); + } + else + { + Utils.log('Cannot find sub settings view model position: SettingsSubScreen'); + } + } + + if (oSettingsScreen) + { + _.defer(function () { + // hide + if (self.oCurrentSubScreen) + { + Utils.delegateRun(self.oCurrentSubScreen, 'onHide'); + self.oCurrentSubScreen.viewModelDom.hide(); + } + // -- + + self.oCurrentSubScreen = oSettingsScreen; + + // show + if (self.oCurrentSubScreen) + { + self.oCurrentSubScreen.viewModelDom.show(); + Utils.delegateRun(self.oCurrentSubScreen, 'onShow'); + Utils.delegateRun(self.oCurrentSubScreen, 'onFocus', [], 200); + + _.each(self.menu(), function (oItem) { + oItem.selected(oSettingsScreen && oSettingsScreen.__rlSettingsData && oItem.route === oSettingsScreen.__rlSettingsData.Route); + }); + + $('#rl-content .b-settings .b-content .content').scrollTop(0); + } + // -- + + Utils.windowResize(); + }); + } + } + else + { + kn.setHash(RL.link().settings(), false, true); + } +}; + +AbstractSettings.prototype.onHide = function () +{ + if (this.oCurrentSubScreen && this.oCurrentSubScreen.viewModelDom) + { + Utils.delegateRun(this.oCurrentSubScreen, 'onHide'); + this.oCurrentSubScreen.viewModelDom.hide(); + } +}; + +AbstractSettings.prototype.onBuild = function () +{ + _.each(ViewModels['settings'], function (SettingsViewModel) { + if (SettingsViewModel && SettingsViewModel.__rlSettingsData && + !_.find(ViewModels['settings-removed'], function (RemoveSettingsViewModel) { + return RemoveSettingsViewModel && RemoveSettingsViewModel === SettingsViewModel; + })) + { + this.menu.push({ + 'route': SettingsViewModel.__rlSettingsData.Route, + 'label': SettingsViewModel.__rlSettingsData.Label, + 'selected': ko.observable(false), + 'disabled': !!_.find(ViewModels['settings-disabled'], function (DisabledSettingsViewModel) { + return DisabledSettingsViewModel && DisabledSettingsViewModel === SettingsViewModel; + }) + }); + } + }, this); + + this.oViewModelPlace = $('#rl-content #rl-settings-subscreen'); +}; + +AbstractSettings.prototype.routes = function () +{ + var + DefaultViewModel = _.find(ViewModels['settings'], function (SettingsViewModel) { + return SettingsViewModel && SettingsViewModel.__rlSettingsData && SettingsViewModel.__rlSettingsData['IsDefault']; + }), + sDefaultRoute = DefaultViewModel ? DefaultViewModel.__rlSettingsData['Route'] : 'general', + oRules = { + 'subname': /^(.*)$/, + 'normalize_': function (oRequest, oVals) { + oVals.subname = Utils.isUnd(oVals.subname) ? sDefaultRoute : Utils.pString(oVals.subname); + return [oVals.subname]; + } + } + ; + + return [ + ['{subname}/', oRules], + ['{subname}', oRules], + ['', oRules] + ]; +}; + +/** + * @constructor + * @extends KnoinAbstractScreen + */ +function AdminLoginScreen() +{ + KnoinAbstractScreen.call(this, 'login', [AdminLoginViewModel]); +} + +_.extend(AdminLoginScreen.prototype, KnoinAbstractScreen.prototype); + +AdminLoginScreen.prototype.onShow = function () +{ + RL.setTitle(''); +}; +/** + * @constructor + * @extends AbstractSettings + */ +function AdminSettingsScreen() +{ + AbstractSettings.call(this, [ + AdminMenuViewModel, + AdminPaneViewModel + ]); +} + +_.extend(AdminSettingsScreen.prototype, AbstractSettings.prototype); + +AdminSettingsScreen.prototype.onShow = function () +{ +// AbstractSettings.prototype.onShow.call(this); + + RL.setTitle(''); +}; +/** + * @constructor + * @extends KnoinAbstractBoot + */ +function AbstractApp() +{ + KnoinAbstractBoot.call(this); + + this.oSettings = null; + this.oPlugins = null; + this.oLocal = null; + this.oLink = null; + this.oSubs = {}; + + this.isLocalAutocomplete = true; + + this.popupVisibilityNames = ko.observableArray([]); + + this.popupVisibility = ko.computed(function () { + return 0 < this.popupVisibilityNames().length; + }, this); + + this.iframe = $('').appendTo('body'); + + $window.on('error', function (oEvent) { + if (RL && oEvent && oEvent.originalEvent && oEvent.originalEvent.message && + -1 === Utils.inArray(oEvent.originalEvent.message, [ + 'Script error.', 'Uncaught Error: Error calling method on NPObject.' + ])) + { + RL.remote().jsError( + Utils.emptyFunction, + oEvent.originalEvent.message, + oEvent.originalEvent.filename, + oEvent.originalEvent.lineno, + location && location.toString ? location.toString() : '', + $html.attr('class'), + Utils.microtime() - Globals.now + ); + } + }); + + $document.on('keydown', function (oEvent) { + if (oEvent && oEvent.ctrlKey) + { + $html.addClass('rl-ctrl-key-pressed'); + } + }).on('keyup', function (oEvent) { + if (oEvent && !oEvent.ctrlKey) + { + $html.removeClass('rl-ctrl-key-pressed'); + } + }); +} + +_.extend(AbstractApp.prototype, KnoinAbstractBoot.prototype); + +AbstractApp.prototype.oSettings = null; +AbstractApp.prototype.oPlugins = null; +AbstractApp.prototype.oLocal = null; +AbstractApp.prototype.oLink = null; +AbstractApp.prototype.oSubs = {}; + +/** + * @param {string} sLink + * @return {boolean} + */ +AbstractApp.prototype.download = function (sLink) +{ + var + oLink = null, + oE = null, + sUserAgent = navigator.userAgent.toLowerCase() + ; + + if (sUserAgent && (sUserAgent.indexOf('chrome') > -1 || sUserAgent.indexOf('chrome') > -1)) + { + oLink = document.createElement('a'); + oLink['href'] = sLink; + + if (document['createEvent']) + { + oE = document['createEvent']('MouseEvents'); + if (oE && oE['initEvent'] && oLink['dispatchEvent']) + { + oE['initEvent']('click', true, true); + oLink['dispatchEvent'](oE); + return true; + } + } + } + + if (Globals.bMobileDevice) + { + window.open(sLink, '_self'); + window.focus(); + } + else + { + this.iframe.attr('src', sLink); +// window.document.location.href = sLink; + } + + return true; +}; + +/** + * @return {LinkBuilder} + */ +AbstractApp.prototype.link = function () +{ + if (null === this.oLink) + { + this.oLink = new LinkBuilder(); + } + + return this.oLink; +}; + +/** + * @return {LocalStorage} + */ +AbstractApp.prototype.local = function () +{ + if (null === this.oLocal) + { + this.oLocal = new LocalStorage(); + } + + return this.oLocal; +}; + +/** + * @param {string} sName + * @return {?} + */ +AbstractApp.prototype.settingsGet = function (sName) +{ + if (null === this.oSettings) + { + this.oSettings = Utils.isNormal(AppData) ? AppData : {}; + } + + return Utils.isUnd(this.oSettings[sName]) ? null : this.oSettings[sName]; +}; + +/** + * @param {string} sName + * @param {?} mValue + */ +AbstractApp.prototype.settingsSet = function (sName, mValue) +{ + if (null === this.oSettings) + { + this.oSettings = Utils.isNormal(AppData) ? AppData : {}; + } + + this.oSettings[sName] = mValue; +}; + +AbstractApp.prototype.setTitle = function (sTitle) +{ + sTitle = ((Utils.isNormal(sTitle) && 0 < sTitle.length) ? sTitle + ' - ' : '') + + RL.settingsGet('Title') || ''; + + window.document.title = '_'; + window.document.title = sTitle; +}; + +/** + * @param {boolean=} bLogout = false + * @param {boolean=} bClose = false + */ +AbstractApp.prototype.loginAndLogoutReload = function (bLogout, bClose) +{ + var + sCustomLogoutLink = Utils.pString(RL.settingsGet('CustomLogoutLink')), + bInIframe = !!RL.settingsGet('InIframe') + ; + + bLogout = Utils.isUnd(bLogout) ? false : !!bLogout; + bClose = Utils.isUnd(bClose) ? false : !!bClose; + + if (bLogout && bClose && window.close) + { + window.close(); + } + + if (bLogout && '' !== sCustomLogoutLink && window.location.href !== sCustomLogoutLink) + { + _.delay(function () { + if (bInIframe && window.parent) + { + window.parent.location.href = sCustomLogoutLink; + } + else + { + window.location.href = sCustomLogoutLink; + } + }, 100); + } + else + { + kn.routeOff(); + kn.setHash(RL.link().root(), true); + kn.routeOff(); + + _.delay(function () { + if (bInIframe && window.parent) + { + window.parent.location.reload(); + } + else + { + window.location.reload(); + } + }, 100); + } +}; + +AbstractApp.prototype.historyBack = function () +{ + window.history.back(); +}; + +/** + * @param {string} sQuery + * @param {Function} fCallback + */ +AbstractApp.prototype.getAutocomplete = function (sQuery, fCallback) +{ + fCallback([], sQuery); +}; + +/** + * @param {string} sName + * @param {Function} fFunc + * @param {Object=} oContext + * @return {AbstractApp} + */ +AbstractApp.prototype.sub = function (sName, fFunc, oContext) +{ + if (Utils.isUnd(this.oSubs[sName])) + { + this.oSubs[sName] = []; + } + + this.oSubs[sName].push([fFunc, oContext]); + + return this; +}; + +/** + * @param {string} sName + * @param {Array=} aArgs + * @return {AbstractApp} + */ +AbstractApp.prototype.pub = function (sName, aArgs) +{ + Plugins.runHook('rl-pub', [sName, aArgs]); + if (!Utils.isUnd(this.oSubs[sName])) + { + _.each(this.oSubs[sName], function (aItem) { + if (aItem[0]) + { + aItem[0].apply(aItem[1] || null, aArgs || []); + } + }); + } + + return this; +}; + +AbstractApp.prototype.bootstart = function () +{ + var self = this; + + Utils.initOnStartOrLangChange(function () { + Utils.initNotificationLanguage(); + }, null); + + _.delay(function () { + Utils.windowResize(); + }, 1000); + + ssm.addState({ + 'id': 'mobile', + 'maxWidth': 767, + 'onEnter': function() { + $html.addClass('ssm-state-mobile'); + self.pub('ssm.mobile-enter'); + }, + 'onLeave': function() { + $html.removeClass('ssm-state-mobile'); + self.pub('ssm.mobile-leave'); + } + }); + + ssm.addState({ + 'id': 'tablet', + 'minWidth': 768, + 'maxWidth': 999, + 'onEnter': function() { + $html.addClass('ssm-state-tablet'); + }, + 'onLeave': function() { + $html.removeClass('ssm-state-tablet'); + } + }); + + ssm.addState({ + 'id': 'desktop', + 'minWidth': 1000, + 'maxWidth': 1400, + 'onEnter': function() { + $html.addClass('ssm-state-desktop'); + }, + 'onLeave': function() { + $html.removeClass('ssm-state-desktop'); + } + }); + + ssm.addState({ + 'id': 'desktop-large', + 'minWidth': 1400, + 'onEnter': function() { + $html.addClass('ssm-state-desktop-large'); + }, + 'onLeave': function() { + $html.removeClass('ssm-state-desktop-large'); + } + }); + + RL.sub('ssm.mobile-enter', function () { + RL.data().leftPanelDisabled(true); + }); + + RL.sub('ssm.mobile-leave', function () { + RL.data().leftPanelDisabled(false); + }); + + RL.data().leftPanelDisabled.subscribe(function (bValue) { + $html.toggleClass('rl-left-panel-disabled', bValue); + }); + + ssm.ready(); +}; + +/** + * @constructor + * @extends AbstractApp + */ +function AdminApp() +{ + AbstractApp.call(this); + + this.oData = null; + this.oRemote = null; + this.oCache = null; +} + +_.extend(AdminApp.prototype, AbstractApp.prototype); + +AdminApp.prototype.oData = null; +AdminApp.prototype.oRemote = null; +AdminApp.prototype.oCache = null; + +/** + * @return {AdminDataStorage} + */ +AdminApp.prototype.data = function () +{ + if (null === this.oData) + { + this.oData = new AdminDataStorage(); + } + + return this.oData; +}; + +/** + * @return {AdminAjaxRemoteStorage} + */ +AdminApp.prototype.remote = function () +{ + if (null === this.oRemote) + { + this.oRemote = new AdminAjaxRemoteStorage(); + } + + return this.oRemote; +}; + +/** + * @return {AdminCacheStorage} + */ +AdminApp.prototype.cache = function () +{ + if (null === this.oCache) + { + this.oCache = new AdminCacheStorage(); + } + + return this.oCache; +}; + +AdminApp.prototype.reloadDomainList = function () +{ + RL.data().domainsLoading(true); + RL.remote().domainList(function (sResult, oData) { + RL.data().domainsLoading(false); + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + var aList = _.map(oData.Result, function (bEnabled, sName) { + return { + 'name': sName, + 'disabled': ko.observable(!bEnabled), + 'deleteAccess': ko.observable(false) + }; + }, this); + + RL.data().domains(aList); + } + }); +}; + +AdminApp.prototype.reloadPluginList = function () +{ + RL.data().pluginsLoading(true); + RL.remote().pluginList(function (sResult, oData) { + RL.data().pluginsLoading(false); + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + var aList = _.map(oData.Result, function (oItem) { + return { + 'name': oItem['Name'], + 'disabled': ko.observable(!oItem['Enabled']), + 'configured': ko.observable(!!oItem['Configured']) + }; + }, this); + + RL.data().plugins(aList); + } + }); +}; + +AdminApp.prototype.reloadPackagesList = function () +{ + RL.data().packagesLoading(true); + RL.data().packagesReal(true); + + RL.remote().packagesList(function (sResult, oData) { + + RL.data().packagesLoading(false); + + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + RL.data().packagesReal(!!oData.Result.Real); + RL.data().packagesMainUpdatable(!!oData.Result.MainUpdatable); + + var + aList = [], + aLoading = {} + ; + + _.each(RL.data().packages(), function (oItem) { + if (oItem && oItem['loading']()) + { + aLoading[oItem['file']] = oItem; + } + }); + + if (Utils.isArray(oData.Result.List)) + { + aList = _.compact(_.map(oData.Result.List, function (oItem) { + if (oItem) + { + oItem['loading'] = ko.observable(!Utils.isUnd(aLoading[oItem['file']])); + return 'core' === oItem['type'] && !oItem['canBeInstalled'] ? null : oItem; + } + return null; + })); + } + + RL.data().packages(aList); + } + else + { + RL.data().packagesReal(false); + } + }); +}; + +/** + * + * @param {boolean=} bForce = false + */ +AdminApp.prototype.reloadLicensing = function (bForce) +{ + bForce = Utils.isUnd(bForce) ? false : !!bForce; + + RL.data().licensingProcess(true); + RL.data().licenseError(''); + + RL.remote().licensing(function (sResult, oData) { + RL.data().licensingProcess(false); + if (Enums.StorageResultType.Success === sResult && oData && oData.Result && Utils.isNormal(oData.Result['Expired'])) + { + RL.data().licenseValid(true); + RL.data().licenseExpired(Utils.pInt(oData.Result['Expired'])); + RL.data().licenseError(''); + + RL.data().licensing(true); + } + else + { + if (oData && oData.ErrorCode && -1 < Utils.inArray(Utils.pInt(oData.ErrorCode), [ + Enums.Notification.LicensingServerIsUnavailable, + Enums.Notification.LicensingExpired + ])) + { + RL.data().licenseError(Utils.getNotification(Utils.pInt(oData.ErrorCode))); + RL.data().licensing(true); + } + else + { + if (Enums.StorageResultType.Abort === sResult) + { + RL.data().licenseError(Utils.getNotification(Enums.Notification.LicensingServerIsUnavailable)); + RL.data().licensing(true); + } + else + { + RL.data().licensing(false); + } + } + } + }, bForce); +}; + +AdminApp.prototype.bootstart = function () +{ + AbstractApp.prototype.bootstart.call(this); + + RL.data().populateDataOnStart(); + + kn.hideLoading(); + + if (!RL.settingsGet('AllowAdminPanel')) + { + kn.routeOff(); + kn.setHash(RL.link().root(), true); + kn.routeOff(); + + _.defer(function () { + window.location.href = '/'; + }); + } + else + { + if (!!RL.settingsGet('Auth')) + { +// TODO +// if (!RL.settingsGet('AllowPackages') && AdminPackages) +// { +// Utils.disableSettingsViewModel(AdminPackages); +// } + + kn.startScreens([AdminSettingsScreen]); + } + else + { + kn.startScreens([AdminLoginScreen]); + } + } + + if (window.SimplePace) + { + window.SimplePace.set(100); + } +}; + +/** + * @type {AdminApp} + */ +RL = new AdminApp(); + +$html.addClass(Globals.bMobileDevice ? 'mobile' : 'no-mobile'); + +$window.keydown(Utils.killCtrlAandS).keyup(Utils.killCtrlAandS); +$window.unload(function () { + Globals.bUnload = true; +}); + +$html.on('click.dropdown.data-api', function () { + Utils.detectDropdownVisibility(); +}); + +// export +window['rl'] = window['rl'] || {}; +window['rl']['addHook'] = Plugins.addHook; +window['rl']['settingsGet'] = Plugins.mainSettingsGet; +window['rl']['remoteRequest'] = Plugins.remoteRequest; +window['rl']['pluginSettingsGet'] = Plugins.settingsGet; +window['rl']['addSettingsViewModel'] = Utils.addSettingsViewModel; +window['rl']['createCommand'] = Utils.createCommand; + +window['rl']['EmailModel'] = EmailModel; +window['rl']['Enums'] = Enums; + +window['__RLBOOT'] = function (fCall) { + + // boot + $(function () { + + if (window['rainloopTEMPLATES'] && window['rainloopTEMPLATES'][0]) + { + $('#rl-templates').html(window['rainloopTEMPLATES'][0]); + + _.delay(function () { + window['rainloopAppData'] = {}; + window['rainloopI18N'] = {}; + window['rainloopTEMPLATES'] = {}; + + kn.setBoot(RL).bootstart(); + $html.removeClass('no-js rl-booted-trigger').addClass('rl-booted'); + + }, 50); + } + else + { + fCall(false); + } + + window['__RLBOOT'] = null; + }); +}; + +if (window.SimplePace) { + window.SimplePace.add(10); } }(window, jQuery, ko, crossroads, hasher, _)); \ No newline at end of file diff --git a/rainloop/v/0.0.0/static/js/admin.min.js b/rainloop/v/0.0.0/static/js/admin.min.js index 9c7f6b6b8..7dcbe9460 100644 --- a/rainloop/v/0.0.0/static/js/admin.min.js +++ b/rainloop/v/0.0.0/static/js/admin.min.js @@ -1,5 +1,5 @@ /*! RainLoop Webmail Admin Module (c) RainLoop Team | Licensed under CC BY-NC-SA 3.0 */ -!function(a,b,c,d,e,f){"use strict";function g(){this.sBase="#/",this.sVersion=gb.settingsGet("Version"),this.sSpecSuffix=gb.settingsGet("AuthAccountHash")||"0",this.sServer=(gb.settingsGet("IndexFile")||"./")+"?"}function h(){}function i(){}function j(){var a=[i,h],b=f.find(a,function(a){return a.supported()});b&&(b=b,this.oDriver=new b)}function k(){}function l(a,b){this.bDisabeCloseOnEsc=!1,this.sPosition=V.pString(a),this.sTemplate=V.pString(b),this.sDefaultKeyScope=T.KeyState.None,this.sCurrentKeyScope=this.sDefaultKeyScope,this.viewModelName="",this.viewModelVisibility=c.observable(!1),this.modalVisibility=c.observable(!1).extend({rateLimit:0}),this.viewModelDom=null}function m(a,b){this.sScreenName=a,this.aViewModels=V.isArray(b)?b:[]}function n(){this.sDefaultScreenName="",this.oScreens={},this.oBoot=null,this.oCurrentScreen=null}function o(a,b){this.email=a||"",this.name=b||"",this.privateType=null,this.clearDuplicateName()}function p(){l.call(this,"Popups","PopupsDomain"),this.edit=c.observable(!1),this.saving=c.observable(!1),this.savingError=c.observable(""),this.whiteListPage=c.observable(!1),this.testing=c.observable(!1),this.testingDone=c.observable(!1),this.testingImapError=c.observable(!1),this.testingSmtpError=c.observable(!1),this.testingImapErrorDesc=c.observable(""),this.testingSmtpErrorDesc=c.observable(""),this.testingImapError.subscribe(function(a){a||this.testingImapErrorDesc("")},this),this.testingSmtpError.subscribe(function(a){a||this.testingSmtpErrorDesc("")},this),this.testingImapErrorDesc=c.observable(""),this.testingSmtpErrorDesc=c.observable(""),this.imapServerFocus=c.observable(!1),this.smtpServerFocus=c.observable(!1),this.name=c.observable(""),this.name.focused=c.observable(!1),this.imapServer=c.observable(""),this.imapPort=c.observable(S.Values.ImapDefaulPort),this.imapSecure=c.observable(T.ServerSecure.None),this.imapShortLogin=c.observable(!1),this.smtpServer=c.observable(""),this.smtpPort=c.observable(S.Values.SmtpDefaulPort),this.smtpSecure=c.observable(T.ServerSecure.None),this.smtpShortLogin=c.observable(!1),this.smtpAuth=c.observable(!0),this.whiteList=c.observable(""),this.headerText=c.computed(function(){var a=this.name();return this.edit()?'Edit Domain "'+a+'"':"Add Domain"+(""===a?"":' "'+a+'"')},this),this.domainIsComputed=c.computed(function(){return""!==this.name()&&""!==this.imapServer()&&""!==this.imapPort()&&""!==this.smtpServer()&&""!==this.smtpPort()},this),this.canBeTested=c.computed(function(){return!this.testing()&&this.domainIsComputed()},this),this.canBeSaved=c.computed(function(){return!this.saving()&&this.domainIsComputed()},this),this.createOrAddCommand=V.createCommand(this,function(){this.saving(!0),gb.remote().createOrUpdateDomain(f.bind(this.onDomainCreateOrSaveResponse,this),!this.edit(),this.name(),this.imapServer(),this.imapPort(),this.imapSecure(),this.imapShortLogin(),this.smtpServer(),this.smtpPort(),this.smtpSecure(),this.smtpShortLogin(),this.smtpAuth(),this.whiteList())},this.canBeSaved),this.testConnectionCommand=V.createCommand(this,function(){this.whiteListPage(!1),this.testingDone(!1),this.testingImapError(!1),this.testingSmtpError(!1),this.testing(!0),gb.remote().testConnectionForDomain(f.bind(this.onTestConnectionResponse,this),this.name(),this.imapServer(),this.imapPort(),this.imapSecure(),this.smtpServer(),this.smtpPort(),this.smtpSecure(),this.smtpAuth())},this.canBeTested),this.whiteListCommand=V.createCommand(this,function(){this.whiteListPage(!this.whiteListPage())}),this.imapServerFocus.subscribe(function(a){a&&""!==this.name()&&""===this.imapServer()&&this.imapServer(this.name().replace(/[.]?[*][.]?/g,""))},this),this.smtpServerFocus.subscribe(function(a){a&&""!==this.imapServer()&&""===this.smtpServer()&&this.smtpServer(this.imapServer().replace(/imap/gi,"smtp"))},this),this.imapSecure.subscribe(function(a){var b=V.pInt(this.imapPort());switch(a=V.pString(a)){case"0":993===b&&this.imapPort(143);break;case"1":143===b&&this.imapPort(993)}},this),this.smtpSecure.subscribe(function(a){var b=V.pInt(this.smtpPort());switch(a=V.pString(a)){case"0":(465===b||587===b)&&this.smtpPort(25);break;case"1":(25===b||587===b)&&this.smtpPort(465);break;case"2":(25===b||465===b)&&this.smtpPort(587)}},this),n.constructorEnd(this)}function q(){l.call(this,"Popups","PopupsPlugin");var a=this;this.onPluginSettingsUpdateResponse=f.bind(this.onPluginSettingsUpdateResponse,this),this.saveError=c.observable(""),this.name=c.observable(""),this.readme=c.observable(""),this.configures=c.observableArray([]),this.hasReadme=c.computed(function(){return""!==this.readme()},this),this.hasConfiguration=c.computed(function(){return 0').appendTo("body"),db.on("error",function(a){gb&&a&&a.originalEvent&&a.originalEvent.message&&-1===V.inArray(a.originalEvent.message,["Script error.","Uncaught Error: Error calling method on NPObject."])&&gb.remote().jsError(V.emptyFunction,a.originalEvent.message,a.originalEvent.filename,a.originalEvent.lineno,location&&location.toString?location.toString():"",cb.attr("class"),V.microtime()-Y.now)}),eb.on("keydown",function(a){a&&a.ctrlKey&&cb.addClass("rl-ctrl-key-pressed")}).on("keyup",function(a){a&&!a.ctrlKey&&cb.removeClass("rl-ctrl-key-pressed")})}function R(){Q.call(this),this.oData=null,this.oRemote=null,this.oCache=null}var S={},T={},U={},V={},W={},X={},Y={},Z={settings:[],"settings-removed":[],"settings-disabled":[]},$=[],_=null,ab=a.rainloopAppData||{},bb=a.rainloopI18N||{},cb=b("html"),db=b(a),eb=b(a.document),fb=a.Notification&&a.Notification.requestPermission?a.Notification:null,gb=null;Y.now=(new Date).getTime(),Y.momentTrigger=c.observable(!0),Y.dropdownVisibility=c.observable(!1).extend({rateLimit:0}),Y.langChangeTrigger=c.observable(!0),Y.iAjaxErrorCount=0,Y.iTokenErrorCount=0,Y.iMessageBodyCacheCount=0,Y.bUnload=!1,Y.sUserAgent=(navigator.userAgent||"").toLowerCase(),Y.bIsiOSDevice=-1 /g,">").replace(/"/g,""").replace(/'/g,"'"):""},V.splitPlainText=function(a,b){var c="",d="",e=a,f=0,g=0;for(b=V.isUnd(b)?100:b;e.length>b;)d=e.substring(0,b),f=d.lastIndexOf(" "),g=d.lastIndexOf("\n"),-1!==g&&(f=g),-1===f&&(f=b),c+=d.substring(0,f)+"\n",e=e.substring(f+1);return c+e},V.timeOutAction=function(){var b={};return function(c,d,e){V.isUnd(b[c])&&(b[c]=0),a.clearTimeout(b[c]),b[c]=a.setTimeout(d,e)}}(),V.timeOutActionSecond=function(){var b={};return function(c,d,e){b[c]||(b[c]=a.setTimeout(function(){d(),b[c]=0},e))}}(),V.audio=function(){var b=!1;return function(c,d){if(!1===b)if(Y.bIsiOSDevice)b=null;else{var e=!1,f=!1,g=a.Audio?new a.Audio:null;g&&g.canPlayType&&g.play?(e=""!==g.canPlayType('audio/mpeg; codecs="mp3"'),e||(f=""!==g.canPlayType('audio/ogg; codecs="vorbis"')),e||f?(b=g,b.preload="none",b.loop=!1,b.autoplay=!1,b.muted=!1,b.src=e?c:d):b=null):b=null}return b}}(),V.hos=function(a,b){return a&&Object.hasOwnProperty?Object.hasOwnProperty.call(a,b):!1},V.i18n=function(a,b,c){var d="",e=V.isUnd(bb[a])?V.isUnd(c)?a:c:bb[a];if(!V.isUnd(b)&&!V.isNull(b))for(d in b)V.hos(b,d)&&(e=e.replace("%"+d+"%",b[d]));return e},V.i18nToNode=function(a){f.defer(function(){b(".i18n",a).each(function(){var a=b(this),c="";c=a.data("i18n-text"),c?a.text(V.i18n(c)):(c=a.data("i18n-html"),c&&a.html(V.i18n(c)),c=a.data("i18n-placeholder"),c&&a.attr("placeholder",V.i18n(c)),c=a.data("i18n-title"),c&&a.attr("title",V.i18n(c)))})})},V.i18nToDoc=function(){a.rainloopI18N&&(bb=a.rainloopI18N||{},V.i18nToNode(eb),Y.langChangeTrigger(!Y.langChangeTrigger())),a.rainloopI18N={}},V.initOnStartOrLangChange=function(a,b,c){a&&a.call(b),c?Y.langChangeTrigger.subscribe(function(){a&&a.call(b),c.call(b)}):a&&Y.langChangeTrigger.subscribe(a,b)},V.inFocus=function(){var a=document.activeElement;return a&&("INPUT"===a.tagName||"TEXTAREA"===a.tagName||"IFRAME"===a.tagName||"DIV"===a.tagName&&"editorHtmlArea"===a.className&&a.contentEditable)},V.removeInFocus=function(){if(document&&document.activeElement&&document.activeElement.blur){var a=b(document.activeElement);(a.is("input")||a.is("textarea"))&&document.activeElement.blur()}},V.removeSelection=function(){if(a&&a.getSelection){var b=a.getSelection();b&&b.removeAllRanges&&b.removeAllRanges()}else document&&document.selection&&document.selection.empty&&document.selection.empty()},V.replySubjectAdd=function(b,c,d){var e=null,f=V.trim(c);return f=null===(e=new a.RegExp("^"+b+"[\\s]?\\:(.*)$","gi").exec(c))||V.isUnd(e[1])?null===(e=new a.RegExp("^("+b+"[\\s]?[\\[\\(]?)([\\d]+)([\\]\\)]?[\\s]?\\:.*)$","gi").exec(c))||V.isUnd(e[1])||V.isUnd(e[2])||V.isUnd(e[3])?b+": "+c:e[1]+(V.pInt(e[2])+1)+e[3]:b+"[2]: "+e[1],f=f.replace(/[\s]+/g," "),f=(V.isUnd(d)?!0:d)?V.fixLongSubject(f):f},V.fixLongSubject=function(a){var b=0,c=null;a=V.trim(a.replace(/[\s]+/," "));do c=/^Re(\[([\d]+)\]|):[\s]{0,3}Re(\[([\d]+)\]|):/gi.exec(a),(!c||V.isUnd(c[0]))&&(c=null),c&&(b=0,b+=V.isUnd(c[2])?1:0+V.pInt(c[2]),b+=V.isUnd(c[4])?1:0+V.pInt(c[4]),a=a.replace(/^Re(\[[\d]+\]|):[\s]{0,3}Re(\[[\d]+\]|):/gi,"Re"+(b>0?"["+b+"]":"")+":"));while(c);return a=a.replace(/[\s]+/," ")},V.roundNumber=function(a,b){return Math.round(a*Math.pow(10,b))/Math.pow(10,b)},V.friendlySize=function(a){return a=V.pInt(a),a>=1073741824?V.roundNumber(a/1073741824,1)+"GB":a>=1048576?V.roundNumber(a/1048576,1)+"MB":a>=1024?V.roundNumber(a/1024,0)+"KB":a+"B"},V.log=function(b){a.console&&a.console.log&&a.console.log(b)},V.getNotification=function(a,b){return a=V.pInt(a),T.Notification.ClientViewError===a&&b?b:V.isUnd(U[a])?"":U[a]},V.initNotificationLanguage=function(){U[T.Notification.InvalidToken]=V.i18n("NOTIFICATIONS/INVALID_TOKEN"),U[T.Notification.AuthError]=V.i18n("NOTIFICATIONS/AUTH_ERROR"),U[T.Notification.AccessError]=V.i18n("NOTIFICATIONS/ACCESS_ERROR"),U[T.Notification.ConnectionError]=V.i18n("NOTIFICATIONS/CONNECTION_ERROR"),U[T.Notification.CaptchaError]=V.i18n("NOTIFICATIONS/CAPTCHA_ERROR"),U[T.Notification.SocialFacebookLoginAccessDisable]=V.i18n("NOTIFICATIONS/SOCIAL_FACEBOOK_LOGIN_ACCESS_DISABLE"),U[T.Notification.SocialTwitterLoginAccessDisable]=V.i18n("NOTIFICATIONS/SOCIAL_TWITTER_LOGIN_ACCESS_DISABLE"),U[T.Notification.SocialGoogleLoginAccessDisable]=V.i18n("NOTIFICATIONS/SOCIAL_GOOGLE_LOGIN_ACCESS_DISABLE"),U[T.Notification.DomainNotAllowed]=V.i18n("NOTIFICATIONS/DOMAIN_NOT_ALLOWED"),U[T.Notification.AccountNotAllowed]=V.i18n("NOTIFICATIONS/ACCOUNT_NOT_ALLOWED"),U[T.Notification.AccountTwoFactorAuthRequired]=V.i18n("NOTIFICATIONS/ACCOUNT_TWO_FACTOR_AUTH_REQUIRED"),U[T.Notification.AccountTwoFactorAuthError]=V.i18n("NOTIFICATIONS/ACCOUNT_TWO_FACTOR_AUTH_ERROR"),U[T.Notification.CouldNotSaveNewPassword]=V.i18n("NOTIFICATIONS/COULD_NOT_SAVE_NEW_PASSWORD"),U[T.Notification.CurrentPasswordIncorrect]=V.i18n("NOTIFICATIONS/CURRENT_PASSWORD_INCORRECT"),U[T.Notification.NewPasswordShort]=V.i18n("NOTIFICATIONS/NEW_PASSWORD_SHORT"),U[T.Notification.NewPasswordWeak]=V.i18n("NOTIFICATIONS/NEW_PASSWORD_WEAK"),U[T.Notification.NewPasswordForbidden]=V.i18n("NOTIFICATIONS/NEW_PASSWORD_FORBIDDENT"),U[T.Notification.ContactsSyncError]=V.i18n("NOTIFICATIONS/CONTACTS_SYNC_ERROR"),U[T.Notification.CantGetMessageList]=V.i18n("NOTIFICATIONS/CANT_GET_MESSAGE_LIST"),U[T.Notification.CantGetMessage]=V.i18n("NOTIFICATIONS/CANT_GET_MESSAGE"),U[T.Notification.CantDeleteMessage]=V.i18n("NOTIFICATIONS/CANT_DELETE_MESSAGE"),U[T.Notification.CantMoveMessage]=V.i18n("NOTIFICATIONS/CANT_MOVE_MESSAGE"),U[T.Notification.CantCopyMessage]=V.i18n("NOTIFICATIONS/CANT_MOVE_MESSAGE"),U[T.Notification.CantSaveMessage]=V.i18n("NOTIFICATIONS/CANT_SAVE_MESSAGE"),U[T.Notification.CantSendMessage]=V.i18n("NOTIFICATIONS/CANT_SEND_MESSAGE"),U[T.Notification.InvalidRecipients]=V.i18n("NOTIFICATIONS/INVALID_RECIPIENTS"),U[T.Notification.CantCreateFolder]=V.i18n("NOTIFICATIONS/CANT_CREATE_FOLDER"),U[T.Notification.CantRenameFolder]=V.i18n("NOTIFICATIONS/CANT_RENAME_FOLDER"),U[T.Notification.CantDeleteFolder]=V.i18n("NOTIFICATIONS/CANT_DELETE_FOLDER"),U[T.Notification.CantDeleteNonEmptyFolder]=V.i18n("NOTIFICATIONS/CANT_DELETE_NON_EMPTY_FOLDER"),U[T.Notification.CantSubscribeFolder]=V.i18n("NOTIFICATIONS/CANT_SUBSCRIBE_FOLDER"),U[T.Notification.CantUnsubscribeFolder]=V.i18n("NOTIFICATIONS/CANT_UNSUBSCRIBE_FOLDER"),U[T.Notification.CantSaveSettings]=V.i18n("NOTIFICATIONS/CANT_SAVE_SETTINGS"),U[T.Notification.CantSavePluginSettings]=V.i18n("NOTIFICATIONS/CANT_SAVE_PLUGIN_SETTINGS"),U[T.Notification.DomainAlreadyExists]=V.i18n("NOTIFICATIONS/DOMAIN_ALREADY_EXISTS"),U[T.Notification.CantInstallPackage]=V.i18n("NOTIFICATIONS/CANT_INSTALL_PACKAGE"),U[T.Notification.CantDeletePackage]=V.i18n("NOTIFICATIONS/CANT_DELETE_PACKAGE"),U[T.Notification.InvalidPluginPackage]=V.i18n("NOTIFICATIONS/INVALID_PLUGIN_PACKAGE"),U[T.Notification.UnsupportedPluginPackage]=V.i18n("NOTIFICATIONS/UNSUPPORTED_PLUGIN_PACKAGE"),U[T.Notification.LicensingServerIsUnavailable]=V.i18n("NOTIFICATIONS/LICENSING_SERVER_IS_UNAVAILABLE"),U[T.Notification.LicensingExpired]=V.i18n("NOTIFICATIONS/LICENSING_EXPIRED"),U[T.Notification.LicensingBanned]=V.i18n("NOTIFICATIONS/LICENSING_BANNED"),U[T.Notification.DemoSendMessageError]=V.i18n("NOTIFICATIONS/DEMO_SEND_MESSAGE_ERROR"),U[T.Notification.AccountAlreadyExists]=V.i18n("NOTIFICATIONS/ACCOUNT_ALREADY_EXISTS"),U[T.Notification.MailServerError]=V.i18n("NOTIFICATIONS/MAIL_SERVER_ERROR"),U[T.Notification.UnknownNotification]=V.i18n("NOTIFICATIONS/UNKNOWN_ERROR"),U[T.Notification.UnknownError]=V.i18n("NOTIFICATIONS/UNKNOWN_ERROR") -},V.getUploadErrorDescByCode=function(a){var b="";switch(V.pInt(a)){case T.UploadErrorCode.FileIsTooBig:b=V.i18n("UPLOAD/ERROR_FILE_IS_TOO_BIG");break;case T.UploadErrorCode.FilePartiallyUploaded:b=V.i18n("UPLOAD/ERROR_FILE_PARTIALLY_UPLOADED");break;case T.UploadErrorCode.FileNoUploaded:b=V.i18n("UPLOAD/ERROR_NO_FILE_UPLOADED");break;case T.UploadErrorCode.MissingTempFolder:b=V.i18n("UPLOAD/ERROR_MISSING_TEMP_FOLDER");break;case T.UploadErrorCode.FileOnSaveingError:b=V.i18n("UPLOAD/ERROR_ON_SAVING_FILE");break;case T.UploadErrorCode.FileType:b=V.i18n("UPLOAD/ERROR_FILE_TYPE");break;default:b=V.i18n("UPLOAD/ERROR_UNKNOWN")}return b},V.delegateRun=function(a,b,c,d){a&&a[b]&&(d=V.pInt(d),0>=d?a[b].apply(a,V.isArray(c)?c:[]):f.delay(function(){a[b].apply(a,V.isArray(c)?c:[])},d))},V.killCtrlAandS=function(b){if(b=b||a.event,b&&b.ctrlKey&&!b.shiftKey&&!b.altKey){var c=b.target||b.srcElement,d=b.keyCode||b.which;if(d===T.EventKeyCode.S)return b.preventDefault(),void 0;if(c&&c.tagName&&c.tagName.match(/INPUT|TEXTAREA/i))return;d===T.EventKeyCode.A&&(a.getSelection?a.getSelection().removeAllRanges():a.document.selection&&a.document.selection.clear&&a.document.selection.clear(),b.preventDefault())}},V.createCommand=function(a,b,d){var e=b?function(){return e.canExecute&&e.canExecute()&&b.apply(a,Array.prototype.slice.call(arguments)),!1}:function(){};return e.enabled=c.observable(!0),d=V.isUnd(d)?!0:d,e.canExecute=V.isFunc(d)?c.computed(function(){return e.enabled()&&d.call(a)}):c.computed(function(){return e.enabled()&&!!d}),e},V.initDataConstructorBySettings=function(b){b.editorDefaultType=c.observable(T.EditorDefaultType.Html),b.showImages=c.observable(!1),b.interfaceAnimation=c.observable(T.InterfaceAnimation.Full),b.contactsAutosave=c.observable(!1),Y.sAnimationType=T.InterfaceAnimation.Full,b.allowThemes=c.observable(!0),b.allowCustomLogin=c.observable(!1),b.allowLanguagesOnSettings=c.observable(!0),b.allowLanguagesOnLogin=c.observable(!0),b.desktopNotifications=c.observable(!1),b.useThreads=c.observable(!0),b.replySameFolder=c.observable(!0),b.useCheckboxesInList=c.observable(!0),b.layout=c.observable(T.Layout.SidePreview),b.usePreviewPane=c.computed(function(){return T.Layout.NoPreview!==b.layout()}),b.interfaceAnimation.subscribe(function(a){if(Y.bMobileDevice||a===T.InterfaceAnimation.None)cb.removeClass("rl-anim rl-anim-full").addClass("no-rl-anim"),Y.sAnimationType=T.InterfaceAnimation.None;else switch(a){case T.InterfaceAnimation.Full:cb.removeClass("no-rl-anim").addClass("rl-anim rl-anim-full"),Y.sAnimationType=a;break;case T.InterfaceAnimation.Normal:cb.removeClass("no-rl-anim rl-anim-full").addClass("rl-anim"),Y.sAnimationType=a}}),b.interfaceAnimation.valueHasMutated(),b.desktopNotificationsPermisions=c.computed(function(){b.desktopNotifications();var c=T.DesktopNotifications.NotSupported;if(fb&&fb.permission)switch(fb.permission.toLowerCase()){case"granted":c=T.DesktopNotifications.Allowed;break;case"denied":c=T.DesktopNotifications.Denied;break;case"default":c=T.DesktopNotifications.NotAllowed}else a.webkitNotifications&&a.webkitNotifications.checkPermission&&(c=a.webkitNotifications.checkPermission());return c}),b.useDesktopNotifications=c.computed({read:function(){return b.desktopNotifications()&&T.DesktopNotifications.Allowed===b.desktopNotificationsPermisions()},write:function(a){if(a){var c=b.desktopNotificationsPermisions();T.DesktopNotifications.Allowed===c?b.desktopNotifications(!0):T.DesktopNotifications.NotAllowed===c?fb.requestPermission(function(){b.desktopNotifications.valueHasMutated(),T.DesktopNotifications.Allowed===b.desktopNotificationsPermisions()?b.desktopNotifications()?b.desktopNotifications.valueHasMutated():b.desktopNotifications(!0):b.desktopNotifications()?b.desktopNotifications(!1):b.desktopNotifications.valueHasMutated()}):b.desktopNotifications(!1)}else b.desktopNotifications(!1)}}),b.language=c.observable(""),b.languages=c.observableArray([]),b.mainLanguage=c.computed({read:b.language,write:function(a){a!==b.language()?-1 =b.diff(c,"hours")?d:b.format("L")===c.format("L")?V.i18n("MESSAGE_LIST/TODAY_AT",{TIME:c.format("LT")}):b.clone().subtract("days",1).format("L")===c.format("L")?V.i18n("MESSAGE_LIST/YESTERDAY_AT",{TIME:c.format("LT")}):b.year()===c.year()?c.format("D MMM."):c.format("LL")},a)},V.isFolderExpanded=function(a){var b=gb.local().get(T.ClientSideKeyName.ExpandedFolders);return f.isArray(b)&&-1!==f.indexOf(b,a)},V.setExpandedFolder=function(a,b){var c=gb.local().get(T.ClientSideKeyName.ExpandedFolders);f.isArray(c)||(c=[]),b?(c.push(a),c=f.uniq(c)):c=f.without(c,a),gb.local().set(T.ClientSideKeyName.ExpandedFolders,c)},V.initLayoutResizer=function(a,c,d){var e=155,f=b(a),g=b(c),h=gb.local().get(d)||null,i=function(a){a&&(f.css({width:""+a+"px"}),g.css({left:""+a+"px"}))},j=function(a){var b=5;a?(f.resizable("disable"),i(b)):(f.resizable("enable"),b=V.pInt(gb.local().get(d))||e,i(b>e?b:e))},k=function(a,b){b&&b.size&&b.size.width&&(gb.local().set(d,b.size.width),g.css({left:""+b.size.width+"px"}))};null!==h&&i(h),f.resizable({helper:"ui-resizable-helper",minWidth:e,maxWidth:350,handles:"e",stop:k}),gb.sub("left-panel.off",function(){j(!0)}),gb.sub("left-panel.on",function(){j(!1)})},V.initBlockquoteSwitcher=function(a){if(a){var c=b("blockquote:not(.rl-bq-switcher)",a).filter(function(){return 0===b(this).parent().closest("blockquote",a).length});c&&0 100)&&(a.addClass("rl-bq-switcher hidden-bq"),b('').insertBefore(a).click(function(){a.toggleClass("hidden-bq"),V.windowResize()}).after("
").before("
"))})}},V.removeBlockquoteSwitcher=function(a){a&&(b(a).find("blockquote.rl-bq-switcher").each(function(){b(this).removeClass("rl-bq-switcher hidden-bq")}),b(a).find(".rlBlockquoteSwitcher").each(function(){b(this).remove()}))},V.toggleMessageBlockquote=function(a){a&&a.find(".rlBlockquoteSwitcher").click()},V.extendAsViewModel=function(a,b,c){b&&(c||(c=l),b.__name=a,W.regViewModelHook(a,b),f.extend(b.prototype,c.prototype))},V.addSettingsViewModel=function(a,b,c,d,e){a.__rlSettingsData={Label:c,Template:b,Route:d,IsDefault:!!e},Z.settings.push(a)},V.removeSettingsViewModel=function(a){Z["settings-removed"].push(a)},V.disableSettingsViewModel=function(a){Z["settings-disabled"].push(a)},V.convertThemeName=function(a){return"@custom"===a.substr(-7)&&(a=V.trim(a.substring(0,a.length-7))),V.trim(a.replace(/[^a-zA-Z]+/g," ").replace(/([A-Z])/g," $1").replace(/[\s]+/g," "))},V.quoteName=function(a){return a.replace(/["]/g,'\\"')},V.microtime=function(){return(new Date).getTime()},V.convertLangName=function(a,b){return V.i18n("LANGS_NAMES"+(!0===b?"_EN":"")+"/LANG_"+a.toUpperCase().replace(/[^a-zA-Z0-9]+/,"_"),null,a)},V.fakeMd5=function(a){var b="",c="0123456789abcdefghijklmnopqrstuvwxyz";for(a=V.isUnd(a)?32:V.pInt(a);b.length>>32-b}function c(a,b){var c,d,e,f,g;return e=2147483648&a,f=2147483648&b,c=1073741824&a,d=1073741824&b,g=(1073741823&a)+(1073741823&b),c&d?2147483648^g^e^f:c|d?1073741824&g?3221225472^g^e^f:1073741824^g^e^f:g^e^f}function d(a,b,c){return a&b|~a&c}function e(a,b,c){return a&c|b&~c}function f(a,b,c){return a^b^c}function g(a,b,c){return b^(a|~c)}function h(a,e,f,g,h,i,j){return a=c(a,c(c(d(e,f,g),h),j)),c(b(a,i),e)}function i(a,d,f,g,h,i,j){return a=c(a,c(c(e(d,f,g),h),j)),c(b(a,i),d)}function j(a,d,e,g,h,i,j){return a=c(a,c(c(f(d,e,g),h),j)),c(b(a,i),d)}function k(a,d,e,f,h,i,j){return a=c(a,c(c(g(d,e,f),h),j)),c(b(a,i),d)}function l(a){for(var b,c=a.length,d=c+8,e=(d-d%64)/64,f=16*(e+1),g=Array(f-1),h=0,i=0;c>i;)b=(i-i%4)/4,h=i%4*8,g[b]=g[b]|a.charCodeAt(i)<>>29,g}function m(a){var b,c,d="",e="";for(c=0;3>=c;c++)b=a>>>8*c&255,e="0"+b.toString(16),d+=e.substr(e.length-2,2);return d}function n(a){a=a.replace(/rn/g,"n");for(var b="",c=0;c d?b+=String.fromCharCode(d):d>127&&2048>d?(b+=String.fromCharCode(d>>6|192),b+=String.fromCharCode(63&d|128)):(b+=String.fromCharCode(d>>12|224),b+=String.fromCharCode(d>>6&63|128),b+=String.fromCharCode(63&d|128))}return b}var o,p,q,r,s,t,u,v,w,x=Array(),y=7,z=12,A=17,B=22,C=5,D=9,E=14,F=20,G=4,H=11,I=16,J=23,K=6,L=10,M=15,N=21;for(a=n(a),x=l(a),t=1732584193,u=4023233417,v=2562383102,w=271733878,o=0;o /g,">").replace(/")},V.draggeblePlace=function(){return b(' ').appendTo("#rl-hidden")},V.defautOptionsAfterRender=function(a,c){c&&!V.isUnd(c.disabled)&&a&&b(a).toggleClass("disabled",c.disabled).prop("disabled",c.disabled)},V.windowPopupKnockout=function(c,d,e,f){var g=null,h=a.open(""),i="__OpenerApplyBindingsUid"+V.fakeMd5()+"__",j=b("#"+d);a[i]=function(){if(h&&h.document.body&&j&&j[0]){var d=b(h.document.body);b("#rl-content",d).html(j.html()),b("html",h.document).addClass("external "+b("html").attr("class")),V.i18nToNode(d),n.prototype.applyExternal(c,b("#rl-content",d)[0]),a[i]=null,f(h)}},h.document.open(),h.document.write(''+V.encodeHtml(e)+' '),h.document.close(),g=h.document.createElement("script"),g.type="text/javascript",g.innerHTML="if(window&&window.opener&&window.opener['"+i+"']){window.opener['"+i+"']();window.opener['"+i+"']=null}",h.document.getElementsByTagName("head")[0].appendChild(g)},V.settingsSaveHelperFunction=function(a,b,c,d){return c=c||null,d=V.isUnd(d)?1e3:V.pInt(d),function(e,g,h,i,j){b.call(c,g&&g.Result?T.SaveSettingsStep.TrueResult:T.SaveSettingsStep.FalseResult),a&&a.call(c,e,g,h,i,j),f.delay(function(){b.call(c,T.SaveSettingsStep.Idle)},d)}},V.settingsSaveHelperSimpleFunction=function(a,b){return V.settingsSaveHelperFunction(null,a,b,1e3)},V.htmlToPlain=function(a){var c="",d="> ",e=function(){if(arguments&&1\n",a.replace(/\n([> ]+)/gm,function(){return arguments&&1 ]*>(.|[\s\S\r\n]*)<\/div>/gim,f),a="\n"+b.trim(a)+"\n"),a}return""},g=function(){return arguments&&1 /g,">"):""},h=function(){if(arguments&&1 /gim,"\n").replace(/<\/h\d>/gi,"\n").replace(/<\/p>/gi,"\n\n").replace(/<\/li>/gi,"\n").replace(/<\/td>/gi,"\n").replace(/<\/tr>/gi,"\n").replace(/
]*>/gim,"\n_______________________________\n\n").replace(/]*>/gim,"").replace(/
]*>(.|[\s\S\r\n]*)<\/div>/gim,f).replace(/]*>/gim,"\n__bq__start__\n").replace(/<\/blockquote>/gim,"\n__bq__end__\n").replace(/]*>(.|[\s\S\r\n]*)<\/a>/gim,h).replace(/ /gi," ").replace(/<[^>]*>/gm,"").replace(/>/gi,">").replace(/</gi,"<").replace(/&/gi,"&").replace(/&\w{2,6};/gi,""),c.replace(/\n[ \t]+/gm,"\n").replace(/[\n]{3,}/gm,"\n\n").replace(/__bq__start__(.|[\s\S\r\n]*)__bq__end__/gm,e).replace(/__bq__start__/gm,"").replace(/__bq__end__/gm,"")},V.plainToHtml=function(a){return a.toString().replace(/&/g,"&").replace(/>/g,">").replace(/")},V.resizeAndCrop=function(b,c,d){var e=new a.Image;e.onload=function(){var a=[0,0],b=document.createElement("canvas"),e=b.getContext("2d");b.width=c,b.height=c,a=this.width>this.height?[this.width-this.height,0]:[0,this.height-this.width],e.fillStyle="#fff",e.fillRect(0,0,c,c),e.drawImage(this,a[0]/2,a[1]/2,this.width-a[0],this.height-a[1],0,0,c,c),d(b.toDataURL("image/jpeg"))},e.src=b},V.computedPagenatorHelper=function(a,b){return function(){var c=0,d=0,e=2,f=[],g=a(),h=b(),i=function(a,b,c){var d={current:a===g,name:V.isUnd(c)?a.toString():c.toString(),custom:V.isUnd(c)?!1:!0,title:V.isUnd(c)?"":a.toString(),value:a.toString()};(V.isUnd(b)?0:!b)?f.unshift(d):f.push(d)};if(h>1||h>0&&g>h){for(g>h?(i(h),c=h,d=h):((3>=g||g>=h-2)&&(e+=2),i(g),c=g,d=g);e>0;)if(c-=1,d+=1,c>0&&(i(c,!1),e--),h>=d)i(d,!0),e--;else if(0>=c)break;3===c?i(2,!1):c>3&&i(Math.round((c-1)/2),!1,"..."),h-2===d?i(h-1,!0):h-2>d&&i(Math.round((h+d)/2),!0,"..."),c>1&&i(1,!1),h>d&&i(h,!0)}return f}},V.selectElement=function(b){if(a.getSelection){var c=a.getSelection();c.removeAllRanges();var d=document.createRange();d.selectNodeContents(b),c.addRange(d)}else if(document.selection){var e=document.body.createTextRange();e.moveToElementText(b),e.select()}},V.disableKeyFilter=function(){a.key&&(key.filter=function(){return gb.data().useKeyboardShortcuts()})},V.restoreKeyFilter=function(){a.key&&(key.filter=function(a){if(gb.data().useKeyboardShortcuts()){var b=a.target||a.srcElement,c=b?b.tagName:"";return c=c.toUpperCase(),!("INPUT"===c||"SELECT"===c||"TEXTAREA"===c||b&&"DIV"===c&&"editorHtmlArea"===b.className&&b.contentEditable)}return!1})},V.detectDropdownVisibility=f.debounce(function(){Y.dropdownVisibility(!!f.find($,function(a){return a.hasClass("open")}))},50),X={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",urlsafe_encode:function(a){return X.encode(a).replace(/[+]/g,"-").replace(/[\/]/g,"_").replace(/[=]/g,".")},encode:function(a){var b,c,d,e,f,g,h,i="",j=0;for(a=X._utf8_encode(a);j>2,f=(3&b)<<4|c>>4,g=(15&c)<<2|d>>6,h=63&d,isNaN(c)?g=h=64:isNaN(d)&&(h=64),i=i+this._keyStr.charAt(e)+this._keyStr.charAt(f)+this._keyStr.charAt(g)+this._keyStr.charAt(h);return i},decode:function(a){var b,c,d,e,f,g,h,i="",j=0;for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");j >4,c=(15&f)<<4|g>>2,d=(3&g)<<6|h,i+=String.fromCharCode(b),64!==g&&(i+=String.fromCharCode(c)),64!==h&&(i+=String.fromCharCode(d));return X._utf8_decode(i)},_utf8_encode:function(a){a=a.replace(/\r\n/g,"\n");for(var b="",c=0,d=a.length,e=0;d>c;c++)e=a.charCodeAt(c),128>e?b+=String.fromCharCode(e):e>127&&2048>e?(b+=String.fromCharCode(e>>6|192),b+=String.fromCharCode(63&e|128)):(b+=String.fromCharCode(e>>12|224),b+=String.fromCharCode(e>>6&63|128),b+=String.fromCharCode(63&e|128));return b},_utf8_decode:function(a){for(var b="",c=0,d=0,e=0,f=0;c d?(b+=String.fromCharCode(d),c++):d>191&&224>d?(e=a.charCodeAt(c+1),b+=String.fromCharCode((31&d)<<6|63&e),c+=2):(e=a.charCodeAt(c+1),f=a.charCodeAt(c+2),b+=String.fromCharCode((15&d)<<12|(63&e)<<6|63&f),c+=3);return b}},c.bindingHandlers.tooltip={init:function(a,d){if(!Y.bMobileDevice){var e=b(a),f=e.data("tooltip-class")||"",g=e.data("tooltip-placement")||"top";e.tooltip({delay:{show:500,hide:100},html:!0,container:"body",placement:g,trigger:"hover",title:function(){return e.is(".disabled")||Y.dropdownVisibility()?"":''+V.i18n(c.utils.unwrapObservable(d()))+""}}).click(function(){e.tooltip("hide")}),Y.dropdownVisibility.subscribe(function(a){a&&e.tooltip("hide")})}}},c.bindingHandlers.tooltip2={init:function(a,c){var d=b(a),e=d.data("tooltip-class")||"",f=d.data("tooltip-placement")||"top";d.tooltip({delay:{show:500,hide:100},html:!0,container:"body",placement:f,title:function(){return d.is(".disabled")||Y.dropdownVisibility()?"":''+c()()+""}}).click(function(){d.tooltip("hide")}),Y.dropdownVisibility.subscribe(function(a){a&&d.tooltip("hide")})}},c.bindingHandlers.tooltip3={init:function(a){var c=b(a);c.tooltip({container:"body",trigger:"hover manual",title:function(){return c.data("tooltip3-data")||""}}),Y.dropdownVisibility.subscribe(function(a){a&&c.tooltip("hide")}),eb.click(function(){c.tooltip("hide")})},update:function(a,d){var e=c.utils.unwrapObservable(d());""===e?b(a).data("tooltip3-data","").tooltip("hide"):b(a).data("tooltip3-data",e).tooltip("show")}},c.bindingHandlers.registrateBootstrapDropdown={init:function(a){$.push(b(a))}},c.bindingHandlers.openDropdownTrigger={update:function(a,d){if(c.utils.unwrapObservable(d())){var e=b(a);e.hasClass("open")||(e.find(".dropdown-toggle").dropdown("toggle"),V.detectDropdownVisibility()),d()(!1)}}},c.bindingHandlers.dropdownCloser={init:function(a){b(a).closest(".dropdown").on("click",".e-item",function(){b(a).dropdown("toggle")})}},c.bindingHandlers.popover={init:function(a,d){b(a).popover(c.utils.unwrapObservable(d()))}},c.bindingHandlers.csstext={init:function(a,d){a&&a.styleSheet&&!V.isUnd(a.styleSheet.cssText)?a.styleSheet.cssText=c.utils.unwrapObservable(d()):b(a).text(c.utils.unwrapObservable(d()))},update:function(a,d){a&&a.styleSheet&&!V.isUnd(a.styleSheet.cssText)?a.styleSheet.cssText=c.utils.unwrapObservable(d()):b(a).text(c.utils.unwrapObservable(d()))}},c.bindingHandlers.resizecrop={init:function(a){b(a).addClass("resizecrop").resizecrop({width:"100",height:"100",wrapperCSS:{"border-radius":"10px"}})},update:function(a,c){c()(),b(a).resizecrop({width:"100",height:"100"})}},c.bindingHandlers.onEnter={init:function(c,d,e,f){b(c).on("keypress",function(e){e&&13===a.parseInt(e.keyCode,10)&&(b(c).trigger("change"),d().call(f))})}},c.bindingHandlers.onEsc={init:function(c,d,e,f){b(c).on("keypress",function(e){e&&27===a.parseInt(e.keyCode,10)&&(b(c).trigger("change"),d().call(f))})}},c.bindingHandlers.clickOnTrue={update:function(a,d){c.utils.unwrapObservable(d())&&b(a).click()}},c.bindingHandlers.modal={init:function(a,d){b(a).toggleClass("fade",!Y.bMobileDevice).modal({keyboard:!1,show:c.utils.unwrapObservable(d())}).on("shown",function(){V.windowResize()}).find(".close").click(function(){d()(!1)})},update:function(a,d){b(a).modal(c.utils.unwrapObservable(d())?"show":"hide")}},c.bindingHandlers.i18nInit={init:function(a){V.i18nToNode(a)}},c.bindingHandlers.i18nUpdate={update:function(a,b){c.utils.unwrapObservable(b()),V.i18nToNode(a)}},c.bindingHandlers.link={update:function(a,d){b(a).attr("href",c.utils.unwrapObservable(d()))}},c.bindingHandlers.title={update:function(a,d){b(a).attr("title",c.utils.unwrapObservable(d()))}},c.bindingHandlers.textF={init:function(a,d){b(a).text(c.utils.unwrapObservable(d()))}},c.bindingHandlers.initDom={init:function(a,b){b()(a)}},c.bindingHandlers.initResizeTrigger={init:function(a,d){var e=c.utils.unwrapObservable(d());b(a).css({height:e[1],"min-height":e[1]})},update:function(a,d){var e=c.utils.unwrapObservable(d()),f=V.pInt(e[1]),g=0,h=b(a).offset().top;h>0&&(h+=V.pInt(e[2]),g=db.height()-h,g>f&&(f=g),b(a).css({height:f,"min-height":f}))}},c.bindingHandlers.appendDom={update:function(a,d){b(a).hide().empty().append(c.utils.unwrapObservable(d())).show()}},c.bindingHandlers.draggable={init:function(d,e,f){if(!Y.bMobileDevice){var g=100,h=3,i=f(),j=i&&i.droppableSelector?i.droppableSelector:"",k={distance:20,handle:".dragHandle",cursorAt:{top:22,left:3},refreshPositions:!0,scroll:!0};j&&(k.drag=function(c){b(j).each(function(){var d=null,e=null,f=b(this),i=f.offset(),j=i.top+f.height();a.clearInterval(f.data("timerScroll")),f.data("timerScroll",!1),c.pageX>=i.left&&c.pageX<=i.left+f.width()&&(c.pageY>=j-g&&c.pageY<=j&&(d=function(){f.scrollTop(f.scrollTop()+h),V.windowResize()},f.data("timerScroll",a.setInterval(d,10)),d()),c.pageY>=i.top&&c.pageY<=i.top+g&&(e=function(){f.scrollTop(f.scrollTop()-h),V.windowResize()},f.data("timerScroll",a.setInterval(e,10)),e()))})},k.stop=function(){b(j).each(function(){a.clearInterval(b(this).data("timerScroll")),b(this).data("timerScroll",!1)})}),k.helper=function(a){return e()(a&&a.target?c.dataFor(a.target):null)},b(d).draggable(k).on("mousedown",function(){V.removeInFocus()})}}},c.bindingHandlers.droppable={init:function(a,c,d){if(!Y.bMobileDevice){var e=c(),f=d(),g=f&&f.droppableOver?f.droppableOver:null,h=f&&f.droppableOut?f.droppableOut:null,i={tolerance:"pointer",hoverClass:"droppableHover"};e&&(i.drop=function(a,b){e(a,b)},g&&(i.over=function(a,b){g(a,b)}),h&&(i.out=function(a,b){h(a,b)}),b(a).droppable(i))}}},c.bindingHandlers.nano={init:function(a){Y.bDisableNanoScroll||b(a).addClass("nano").nanoScroller({iOSNativeScrolling:!1,preventPageScrolling:!0})}},c.bindingHandlers.saveTrigger={init:function(a){var c=b(a);c.data("save-trigger-type",c.is("input[type=text],input[type=email],input[type=password],select,textarea")?"input":"custom"),"custom"===c.data("save-trigger-type")?c.append(' ').addClass("settings-saved-trigger"):c.addClass("settings-saved-trigger-input")},update:function(a,d){var e=c.utils.unwrapObservable(d()),f=b(a);if("custom"===f.data("save-trigger-type"))switch(e.toString()){case"1":f.find(".animated,.error").hide().removeClass("visible").end().find(".success").show().addClass("visible");break;case"0":f.find(".animated,.success").hide().removeClass("visible").end().find(".error").show().addClass("visible");break;case"-2":f.find(".error,.success").hide().removeClass("visible").end().find(".animated").show().addClass("visible");break;default:f.find(".animated").hide().end().find(".error,.success").removeClass("visible")}else switch(e.toString()){case"1":f.addClass("success").removeClass("error");break;case"0":f.addClass("error").removeClass("success");break;case"-2":break;default:f.removeClass("error success")}}},c.bindingHandlers.emailsTags={init:function(a,c){var d=b(a),e=c();d.inputosaurus({parseOnBlur:!0,inputDelimiters:[",",";"],autoCompleteSource:function(a,b){gb.getAutocomplete(a.term,function(a){b(f.map(a,function(a){return a.toLine(!1)}))})},parseHook:function(a){return f.map(a,function(a){var b=V.trim(a),c=null;return""!==b?(c=new o,c.mailsoParse(b),c.clearDuplicateName(),[c.toLine(!1),c]):[b,null]})},change:f.bind(function(a){d.data("EmailsTagsValue",a.target.value),e(a.target.value)},this)}),e.subscribe(function(a){d.data("EmailsTagsValue")!==a&&(d.val(a),d.data("EmailsTagsValue",a),d.inputosaurus("refresh"))}),e.focusTrigger&&e.focusTrigger.subscribe(function(){d.inputosaurus("focus")})}},c.bindingHandlers.command={init:function(a,d,e,f){var g=b(a),h=d();if(!h||!h.enabled||!h.canExecute)throw new Error("You are not using command function");g.addClass("command"),c.bindingHandlers[g.is("form")?"submit":"click"].init.apply(f,arguments)},update:function(a,c){var d=!0,e=b(a),f=c();d=f.enabled(),e.toggleClass("command-not-enabled",!d),d&&(d=f.canExecute(),e.toggleClass("command-can-not-be-execute",!d)),e.toggleClass("command-disabled disable disabled",!d).toggleClass("no-disabled",!!d),(e.is("input")||e.is("button"))&&e.prop("disabled",!d)}},c.extenders.trimmer=function(a){var b=c.computed({read:a,write:function(b){a(V.trim(b.toString()))},owner:this});return b(a()),b},c.extenders.reversible=function(a){var b=a();return a.commit=function(){b=a()},a.reverse=function(){a(b)},a.commitedValue=function(){return b},a},c.extenders.toggleSubscribe=function(a,b){return a.subscribe(b[1],b[0],"beforeChange"),a.subscribe(b[2],b[0]),a},c.extenders.falseTimeout=function(b,c){return b.iTimeout=0,b.subscribe(function(d){d&&(a.clearTimeout(b.iTimeout),b.iTimeout=a.setTimeout(function(){b(!1),b.iTimeout=0},V.pInt(c)))}),b},c.observable.fn.validateNone=function(){return this.hasError=c.observable(!1),this},c.observable.fn.validateEmail=function(){return this.hasError=c.observable(!1),this.subscribe(function(a){a=V.trim(a),this.hasError(""!==a&&!/^[^@\s]+@[^@\s]+$/.test(a))},this),this.valueHasMutated(),this},c.observable.fn.validateSimpleEmail=function(){return this.hasError=c.observable(!1),this.subscribe(function(a){a=V.trim(a),this.hasError(""!==a&&!/^.+@.+$/.test(a))},this),this.valueHasMutated(),this},c.observable.fn.validateFunc=function(a){return this.hasFuncError=c.observable(!1),V.isFunc(a)&&(this.subscribe(function(b){this.hasFuncError(!a(b))},this),this.valueHasMutated()),this},g.prototype.root=function(){return this.sBase},g.prototype.attachmentDownload=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/Download/"+a},g.prototype.attachmentPreview=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/View/"+a},g.prototype.attachmentPreviewAsPlain=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/ViewAsPlain/"+a},g.prototype.upload=function(){return this.sServer+"/Upload/"+this.sSpecSuffix+"/"},g.prototype.uploadContacts=function(){return this.sServer+"/UploadContacts/"+this.sSpecSuffix+"/"},g.prototype.uploadBackground=function(){return this.sServer+"/UploadBackground/"+this.sSpecSuffix+"/"},g.prototype.append=function(){return this.sServer+"/Append/"+this.sSpecSuffix+"/"},g.prototype.change=function(b){return this.sServer+"/Change/"+this.sSpecSuffix+"/"+a.encodeURIComponent(b)+"/"},g.prototype.ajax=function(a){return this.sServer+"/Ajax/"+this.sSpecSuffix+"/"+a},g.prototype.messageViewLink=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/ViewAsPlain/"+a},g.prototype.messageDownloadLink=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/Download/"+a},g.prototype.inbox=function(){return this.sBase+"mailbox/Inbox"},g.prototype.messagePreview=function(){return this.sBase+"mailbox/message-preview"},g.prototype.settings=function(a){var b=this.sBase+"settings";return V.isUnd(a)||""===a||(b+="/"+a),b},g.prototype.admin=function(a){var b=this.sBase;switch(a){case"AdminDomains":b+="domains";break;case"AdminSecurity":b+="security";break;case"AdminLicensing":b+="licensing"}return b},g.prototype.mailBox=function(a,b,c){b=V.isNormal(b)?V.pInt(b):1,c=V.pString(c);var d=this.sBase+"mailbox/";return""!==a&&(d+=encodeURI(a)),b>1&&(d=d.replace(/[\/]+$/,""),d+="/p"+b),""!==c&&(d=d.replace(/[\/]+$/,""),d+="/"+encodeURI(c)),d},g.prototype.phpInfo=function(){return this.sServer+"Info"},g.prototype.langLink=function(a){return this.sServer+"/Lang/0/"+encodeURI(a)+"/"+this.sVersion+"/"},g.prototype.getUserPicUrlFromHash=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/UserPic/"+a+"/"+this.sVersion+"/"},g.prototype.exportContactsVcf=function(){return this.sServer+"/Raw/"+this.sSpecSuffix+"/ContactsVcf/"},g.prototype.exportContactsCsv=function(){return this.sServer+"/Raw/"+this.sSpecSuffix+"/ContactsCsv/"},g.prototype.emptyContactPic=function(){return"rainloop/v/"+this.sVersion+"/static/css/images/empty-contact.png"},g.prototype.sound=function(a){return"rainloop/v/"+this.sVersion+"/static/sounds/"+a},g.prototype.themePreviewLink=function(a){var b="rainloop/v/"+this.sVersion+"/";return"@custom"===a.substr(-7)&&(a=V.trim(a.substring(0,a.length-7)),b=""),b+"themes/"+encodeURI(a)+"/images/preview.png"},g.prototype.notificationMailIcon=function(){return"rainloop/v/"+this.sVersion+"/static/css/images/icom-message-notification.png"},g.prototype.openPgpJs=function(){return"rainloop/v/"+this.sVersion+"/static/js/openpgp.min.js"},g.prototype.socialGoogle=function(){return this.sServer+"SocialGoogle"+(""!==this.sSpecSuffix?"/"+this.sSpecSuffix+"/":"")},g.prototype.socialTwitter=function(){return this.sServer+"SocialTwitter"+(""!==this.sSpecSuffix?"/"+this.sSpecSuffix+"/":"")},g.prototype.socialFacebook=function(){return this.sServer+"SocialFacebook"+(""!==this.sSpecSuffix?"/"+this.sSpecSuffix+"/":"")},W.oViewModelsHooks={},W.oSimpleHooks={},W.regViewModelHook=function(a,b){b&&(b.__hookName=a) -},W.addHook=function(a,b){V.isFunc(b)&&(V.isArray(W.oSimpleHooks[a])||(W.oSimpleHooks[a]=[]),W.oSimpleHooks[a].push(b))},W.runHook=function(a,b){V.isArray(W.oSimpleHooks[a])&&(b=b||[],f.each(W.oSimpleHooks[a],function(a){a.apply(null,b)}))},W.mainSettingsGet=function(a){return gb?gb.settingsGet(a):null},W.remoteRequest=function(a,b,c,d,e,f){gb&&gb.remote().defaultRequest(a,b,c,d,e,f)},W.settingsGet=function(a,b){var c=W.mainSettingsGet("Plugins");return c=c&&V.isUnd(c[a])?null:c[a],c?V.isUnd(c[b])?null:c[b]:null},h.supported=function(){return!0},h.prototype.set=function(a,c){var d=b.cookie(S.Values.ClientSideCookieIndexName),e=!1,f=null;try{f=null===d?null:JSON.parse(d),f||(f={}),f[a]=c,b.cookie(S.Values.ClientSideCookieIndexName,JSON.stringify(f),{expires:30}),e=!0}catch(g){}return e},h.prototype.get=function(a){var c=b.cookie(S.Values.ClientSideCookieIndexName),d=null;try{d=null===c?null:JSON.parse(c),d=d&&!V.isUnd(d[a])?d[a]:null}catch(e){}return d},i.supported=function(){return!!a.localStorage},i.prototype.set=function(b,c){var d=a.localStorage[S.Values.ClientSideCookieIndexName]||null,e=!1,f=null;try{f=null===d?null:JSON.parse(d),f||(f={}),f[b]=c,a.localStorage[S.Values.ClientSideCookieIndexName]=JSON.stringify(f),e=!0}catch(g){}return e},i.prototype.get=function(b){var c=a.localStorage[S.Values.ClientSideCookieIndexName]||null,d=null;try{d=null===c?null:JSON.parse(c),d=d&&!V.isUnd(d[b])?d[b]:null}catch(e){}return d},j.prototype.oDriver=null,j.prototype.set=function(a,b){return this.oDriver?this.oDriver.set("p"+a,b):!1},j.prototype.get=function(a){return this.oDriver?this.oDriver.get("p"+a):null},k.prototype.bootstart=function(){},l.prototype.sPosition="",l.prototype.sTemplate="",l.prototype.viewModelName="",l.prototype.viewModelDom=null,l.prototype.viewModelTemplate=function(){return this.sTemplate},l.prototype.viewModelPosition=function(){return this.sPosition},l.prototype.cancelCommand=l.prototype.closeCommand=function(){},l.prototype.storeAndSetKeyScope=function(){this.sCurrentKeyScope=gb.data().keyScope(),gb.data().keyScope(this.sDefaultKeyScope)},l.prototype.restoreKeyScope=function(){gb.data().keyScope(this.sCurrentKeyScope)},l.prototype.registerPopupEscapeKey=function(){var a=this;db.on("keydown",function(b){return b&&T.EventKeyCode.Esc===b.keyCode&&a.modalVisibility&&a.modalVisibility()?(V.delegateRun(a,"cancelCommand"),!1):!0})},m.prototype.oCross=null,m.prototype.sScreenName="",m.prototype.aViewModels=[],m.prototype.viewModels=function(){return this.aViewModels},m.prototype.screenName=function(){return this.sScreenName},m.prototype.routes=function(){return null},m.prototype.__cross=function(){return this.oCross},m.prototype.__start=function(){var a=this.routes(),b=null,c=null;V.isNonEmptyArray(a)&&(c=f.bind(this.onRoute||V.emptyFunction,this),b=d.create(),f.each(a,function(a){b.addRoute(a[0],c).rules=a[1]}),this.oCross=b)},n.constructorEnd=function(a){V.isFunc(a.__constructor_end)&&a.__constructor_end.call(a)},n.prototype.sDefaultScreenName="",n.prototype.oScreens={},n.prototype.oBoot=null,n.prototype.oCurrentScreen=null,n.prototype.hideLoading=function(){b("#rl-loading").hide()},n.prototype.routeOff=function(){e.changed.active=!1},n.prototype.routeOn=function(){e.changed.active=!0},n.prototype.setBoot=function(a){return V.isNormal(a)&&(this.oBoot=a),this},n.prototype.screen=function(a){return""===a||V.isUnd(this.oScreens[a])?null:this.oScreens[a]},n.prototype.buildViewModel=function(a,d){if(a&&!a.__builded){var e=new a(d),g=e.viewModelPosition(),h=b("#rl-content #rl-"+g.toLowerCase()),i=null;a.__builded=!0,a.__vm=e,e.data=gb.data(),e.viewModelName=a.__name,h&&1===h.length?(i=b(" ").addClass("rl-view-model").addClass("RL-"+e.viewModelTemplate()).hide().attr("data-bind",'template: {name: "'+e.viewModelTemplate()+'"}, i18nInit: true'),i.appendTo(h),e.viewModelDom=i,a.__dom=i,"Popups"===g&&(e.cancelCommand=e.closeCommand=V.createCommand(e,function(){_.hideScreenPopup(a)}),e.modalVisibility.subscribe(function(a){var b=this;a?(this.viewModelDom.show(),this.storeAndSetKeyScope(),gb.popupVisibilityNames.push(this.viewModelName),e.viewModelDom.css("z-index",3e3+gb.popupVisibilityNames().length+10),V.delegateRun(this,"onFocus",[],500)):(V.delegateRun(this,"onHide"),this.restoreKeyScope(),gb.popupVisibilityNames.remove(this.viewModelName),e.viewModelDom.css("z-index",2e3),f.delay(function(){b.viewModelDom.hide()},300))},e)),W.runHook("view-model-pre-build",[a.__name,e,i]),c.applyBindings(e,i[0]),V.delegateRun(e,"onBuild",[i]),e&&"Popups"===g&&!e.bDisabeCloseOnEsc&&e.registerPopupEscapeKey(),W.runHook("view-model-post-build",[a.__name,e,i])):V.log("Cannot find view model position: "+g)}return a?a.__vm:null},n.prototype.applyExternal=function(a,b){a&&b&&c.applyBindings(a,b)},n.prototype.hideScreenPopup=function(a){a&&a.__vm&&a.__dom&&(a.__vm.modalVisibility(!1),W.runHook("view-model-on-hide",[a.__name,a.__vm]))},n.prototype.showScreenPopup=function(a,b){a&&(this.buildViewModel(a),a.__vm&&a.__dom&&(a.__vm.modalVisibility(!0),V.delegateRun(a.__vm,"onShow",b||[]),W.runHook("view-model-on-show",[a.__name,a.__vm,b||[]])))},n.prototype.screenOnRoute=function(a,b){var c=this,d=null,e=null;""===V.pString(a)&&(a=this.sDefaultScreenName),""!==a&&(d=this.screen(a),d||(d=this.screen(this.sDefaultScreenName),d&&(b=a+"/"+b,a=this.sDefaultScreenName)),d&&d.__started&&(d.__builded||(d.__builded=!0,V.isNonEmptyArray(d.viewModels())&&f.each(d.viewModels(),function(a){this.buildViewModel(a,d)},this),V.delegateRun(d,"onBuild")),f.defer(function(){c.oCurrentScreen&&(V.delegateRun(c.oCurrentScreen,"onHide"),V.isNonEmptyArray(c.oCurrentScreen.viewModels())&&f.each(c.oCurrentScreen.viewModels(),function(a){a.__vm&&a.__dom&&"Popups"!==a.__vm.viewModelPosition()&&(a.__dom.hide(),a.__vm.viewModelVisibility(!1),V.delegateRun(a.__vm,"onHide"))})),c.oCurrentScreen=d,c.oCurrentScreen&&(V.delegateRun(c.oCurrentScreen,"onShow"),W.runHook("screen-on-show",[c.oCurrentScreen.screenName(),c.oCurrentScreen]),V.isNonEmptyArray(c.oCurrentScreen.viewModels())&&f.each(c.oCurrentScreen.viewModels(),function(a){a.__vm&&a.__dom&&"Popups"!==a.__vm.viewModelPosition()&&(a.__dom.show(),a.__vm.viewModelVisibility(!0),V.delegateRun(a.__vm,"onShow"),V.delegateRun(a.__vm,"onFocus",[],200),W.runHook("view-model-on-show",[a.__name,a.__vm]))},c)),e=d.__cross(),e&&e.parse(b)})))},n.prototype.startScreens=function(a){b("#rl-content").css({visibility:"hidden"}),f.each(a,function(a){var b=new a,c=b?b.screenName():"";b&&""!==c&&(""===this.sDefaultScreenName&&(this.sDefaultScreenName=c),this.oScreens[c]=b)},this),f.each(this.oScreens,function(a){a&&!a.__started&&a.__start&&(a.__started=!0,a.__start(),W.runHook("screen-pre-start",[a.screenName(),a]),V.delegateRun(a,"onStart"),W.runHook("screen-post-start",[a.screenName(),a]))},this);var c=d.create();c.addRoute(/^([a-zA-Z0-9\-]*)\/?(.*)$/,f.bind(this.screenOnRoute,this)),e.initialized.add(c.parse,c),e.changed.add(c.parse,c),e.init(),b("#rl-content").css({visibility:"visible"}),f.delay(function(){cb.removeClass("rl-started-trigger").addClass("rl-started")},50)},n.prototype.setHash=function(a,b,c){a="#"===a.substr(0,1)?a.substr(1):a,a="/"===a.substr(0,1)?a.substr(1):a,c=V.isUnd(c)?!1:!!c,(V.isUnd(b)?1:!b)?(e.changed.active=!0,e[c?"replaceHash":"setHash"](a),e.setHash(a)):(e.changed.active=!1,e[c?"replaceHash":"setHash"](a),e.changed.active=!0)},n.prototype.bootstart=function(){return this.oBoot&&this.oBoot.bootstart&&this.oBoot.bootstart(),this},_=new n,o.newInstanceFromJson=function(a){var b=new o;return b.initByJson(a)?b:null},o.prototype.name="",o.prototype.email="",o.prototype.privateType=null,o.prototype.clear=function(){this.email="",this.name="",this.privateType=null},o.prototype.validate=function(){return""!==this.name||""!==this.email},o.prototype.hash=function(a){return"#"+(a?"":this.name)+"#"+this.email+"#"},o.prototype.clearDuplicateName=function(){this.name===this.email&&(this.name="")},o.prototype.type=function(){return null===this.privateType&&(this.email&&"@facebook.com"===this.email.substr(-13)&&(this.privateType=T.EmailType.Facebook),null===this.privateType&&(this.privateType=T.EmailType.Default)),this.privateType},o.prototype.search=function(a){return-1<(this.name+" "+this.email).toLowerCase().indexOf(a.toLowerCase())},o.prototype.parse=function(a){this.clear(),a=V.trim(a);var b=/(?:"([^"]+)")? ?(.*?@[^>,]+)>?,? ?/g,c=b.exec(a);c?(this.name=c[1]||"",this.email=c[2]||"",this.clearDuplicateName()):/^[^@]+@[^@]+$/.test(a)&&(this.name="",this.email=a)},o.prototype.initByJson=function(a){var b=!1;return a&&"Object/Email"===a["@Object"]&&(this.name=V.trim(a.Name),this.email=V.trim(a.Email),b=""!==this.email,this.clearDuplicateName()),b},o.prototype.toLine=function(a,b,c){var d="";return""!==this.email&&(b=V.isUnd(b)?!1:!!b,c=V.isUnd(c)?!1:!!c,a&&""!==this.name?d=b?'")+'" target="_blank" tabindex="-1">'+V.encodeHtml(this.name)+"":c?V.encodeHtml(this.name):this.name:(d=this.email,""!==this.name?b?d=V.encodeHtml('"'+this.name+'" <')+'")+'" target="_blank" tabindex="-1">'+V.encodeHtml(d)+""+V.encodeHtml(">"):(d='"'+this.name+'" <'+d+">",c&&(d=V.encodeHtml(d))):b&&(d=''+V.encodeHtml(this.email)+""))),d},o.prototype.mailsoParse=function(a){if(a=V.trim(a),""===a)return!1;for(var b=function(a,b,c){a+="";var d=a.length;return 0>b&&(b+=d),d="undefined"==typeof c?d:0>c?c+d:c+b,b>=a.length||0>b||b>d?!1:a.slice(b,d)},c=function(a,b,c,d){return 0>c&&(c+=a.length),d=void 0!==d?d:a.length,0>d&&(d=d+a.length-c),a.slice(0,c)+b.substr(0,d)+b.slice(d)+a.slice(c+d)},d="",e="",f="",g=!1,h=!1,i=!1,j=null,k=0,l=0,m=0;m").addClass("rl-settings-view-model").hide().attr("data-bind",'template: {name: "'+g.__rlSettingsData.Template+'"}, i18nInit: true'),i.appendTo(h),e.data=gb.data(),e.viewModelDom=i,e.__rlSettingsData=g.__rlSettingsData,g.__dom=i,g.__builded=!0,g.__vm=e,c.applyBindings(e,i[0]),V.delegateRun(e,"onBuild",[i])):V.log("Cannot find sub settings view model position: SettingsSubScreen")),e&&f.defer(function(){d.oCurrentSubScreen&&(V.delegateRun(d.oCurrentSubScreen,"onHide"),d.oCurrentSubScreen.viewModelDom.hide()),d.oCurrentSubScreen=e,d.oCurrentSubScreen&&(d.oCurrentSubScreen.viewModelDom.show(),V.delegateRun(d.oCurrentSubScreen,"onShow"),V.delegateRun(d.oCurrentSubScreen,"onFocus",[],200),f.each(d.menu(),function(a){a.selected(e&&e.__rlSettingsData&&a.route===e.__rlSettingsData.Route)}),b("#rl-content .b-settings .b-content .content").scrollTop(0)),V.windowResize()})):_.setHash(gb.link().settings(),!1,!0)},N.prototype.onHide=function(){this.oCurrentSubScreen&&this.oCurrentSubScreen.viewModelDom&&(V.delegateRun(this.oCurrentSubScreen,"onHide"),this.oCurrentSubScreen.viewModelDom.hide())},N.prototype.onBuild=function(){f.each(Z.settings,function(a){a&&a.__rlSettingsData&&!f.find(Z["settings-removed"],function(b){return b&&b===a})&&this.menu.push({route:a.__rlSettingsData.Route,label:a.__rlSettingsData.Label,selected:c.observable(!1),disabled:!!f.find(Z["settings-disabled"],function(b){return b&&b===a})})},this),this.oViewModelPlace=b("#rl-content #rl-settings-subscreen")},N.prototype.routes=function(){var a=f.find(Z.settings,function(a){return a&&a.__rlSettingsData&&a.__rlSettingsData.IsDefault}),b=a?a.__rlSettingsData.Route:"general",c={subname:/^(.*)$/,normalize_:function(a,c){return c.subname=V.isUnd(c.subname)?b:V.pString(c.subname),[c.subname]}};return[["{subname}/",c],["{subname}",c],["",c]]},f.extend(O.prototype,m.prototype),O.prototype.onShow=function(){gb.setTitle("")},f.extend(P.prototype,N.prototype),P.prototype.onShow=function(){gb.setTitle("")},f.extend(Q.prototype,k.prototype),Q.prototype.oSettings=null,Q.prototype.oPlugins=null,Q.prototype.oLocal=null,Q.prototype.oLink=null,Q.prototype.oSubs={},Q.prototype.download=function(b){var c=null,d=null,e=navigator.userAgent.toLowerCase();return e&&(e.indexOf("chrome")>-1||e.indexOf("chrome")>-1)&&(c=document.createElement("a"),c.href=b,document.createEvent&&(d=document.createEvent("MouseEvents"),d&&d.initEvent&&c.dispatchEvent))?(d.initEvent("click",!0,!0),c.dispatchEvent(d),!0):(Y.bMobileDevice?(a.open(b,"_self"),a.focus()):this.iframe.attr("src",b),!0)},Q.prototype.link=function(){return null===this.oLink&&(this.oLink=new g),this.oLink},Q.prototype.local=function(){return null===this.oLocal&&(this.oLocal=new j),this.oLocal},Q.prototype.settingsGet=function(a){return null===this.oSettings&&(this.oSettings=V.isNormal(ab)?ab:{}),V.isUnd(this.oSettings[a])?null:this.oSettings[a]},Q.prototype.settingsSet=function(a,b){null===this.oSettings&&(this.oSettings=V.isNormal(ab)?ab:{}),this.oSettings[a]=b},Q.prototype.setTitle=function(b){b=(V.isNormal(b)&&00&&0===d.length&&(d=b(a,0,m)),h=!0,k=m);break;case">":h&&(l=m,e=b(a,k+1,l-k-1),a=c(a,"",k,l-k+1),l=0,m=0,k=0,h=!1);break;case"(":g||h||i||(i=!0,k=m);break;case")":i&&(l=m,f=b(a,k+1,l-k-1),a=c(a,"",k,l-k+1),l=0,m=0,k=0,i=!1);break;case"\\":m++}m++}return 0===e.length&&(j=a.match(/[^@\s]+@\S+/i),j&&j[0]?e=j[0]:d=a),e.length>0&&0===d.length&&0===f.length&&(d=a.replace(e,"")),e=V.trim(e).replace(/^[<]+/,"").replace(/[>]+$/,""),d=V.trim(d).replace(/^["']+/,"").replace(/["']+$/,""),f=V.trim(f).replace(/^[(]+/,"").replace(/[)]+$/,""),d=d.replace(/\\\\(.)/,"$1"),f=f.replace(/\\\\(.)/,"$1"),this.name=d,this.email=e,this.clearDuplicateName(),!0},o.prototype.inputoTagLine=function(){return 0 (new a.Date).getTime()-l),n&&i.oRequests[n]&&(i.oRequests[n].__aborted&&(e="abort"),i.oRequests[n]=null),i.defaultResponse(c,n,e,b,f,d)}),n&&0 ').appendTo("body"),db.on("error",function(a){gb&&a&&a.originalEvent&&a.originalEvent.message&&-1===V.inArray(a.originalEvent.message,["Script error.","Uncaught Error: Error calling method on NPObject."])&&gb.remote().jsError(V.emptyFunction,a.originalEvent.message,a.originalEvent.filename,a.originalEvent.lineno,location&&location.toString?location.toString():"",cb.attr("class"),V.microtime()-Y.now)}),eb.on("keydown",function(a){a&&a.ctrlKey&&cb.addClass("rl-ctrl-key-pressed")}).on("keyup",function(a){a&&!a.ctrlKey&&cb.removeClass("rl-ctrl-key-pressed")})}function R(){Q.call(this),this.oData=null,this.oRemote=null,this.oCache=null}var S={},T={},U={},V={},W={},X={},Y={},Z={settings:[],"settings-removed":[],"settings-disabled":[]},$=[],_=null,ab=a.rainloopAppData||{},bb=a.rainloopI18N||{},cb=b("html"),db=b(a),eb=b(a.document),fb=a.Notification&&a.Notification.requestPermission?a.Notification:null,gb=null;Y.now=(new Date).getTime(),Y.momentTrigger=c.observable(!0),Y.dropdownVisibility=c.observable(!1).extend({rateLimit:0}),Y.langChangeTrigger=c.observable(!0),Y.iAjaxErrorCount=0,Y.iTokenErrorCount=0,Y.iMessageBodyCacheCount=0,Y.bUnload=!1,Y.sUserAgent=(navigator.userAgent||"").toLowerCase(),Y.bIsiOSDevice=-1 /g,">").replace(/"/g,""").replace(/'/g,"'"):""},V.splitPlainText=function(a,b){var c="",d="",e=a,f=0,g=0;for(b=V.isUnd(b)?100:b;e.length>b;)d=e.substring(0,b),f=d.lastIndexOf(" "),g=d.lastIndexOf("\n"),-1!==g&&(f=g),-1===f&&(f=b),c+=d.substring(0,f)+"\n",e=e.substring(f+1);return c+e},V.timeOutAction=function(){var b={};return function(c,d,e){V.isUnd(b[c])&&(b[c]=0),a.clearTimeout(b[c]),b[c]=a.setTimeout(d,e)}}(),V.timeOutActionSecond=function(){var b={};return function(c,d,e){b[c]||(b[c]=a.setTimeout(function(){d(),b[c]=0},e))}}(),V.audio=function(){var b=!1;return function(c,d){if(!1===b)if(Y.bIsiOSDevice)b=null;else{var e=!1,f=!1,g=a.Audio?new a.Audio:null;g&&g.canPlayType&&g.play?(e=""!==g.canPlayType('audio/mpeg; codecs="mp3"'),e||(f=""!==g.canPlayType('audio/ogg; codecs="vorbis"')),e||f?(b=g,b.preload="none",b.loop=!1,b.autoplay=!1,b.muted=!1,b.src=e?c:d):b=null):b=null}return b}}(),V.hos=function(a,b){return a&&Object.hasOwnProperty?Object.hasOwnProperty.call(a,b):!1},V.i18n=function(a,b,c){var d="",e=V.isUnd(bb[a])?V.isUnd(c)?a:c:bb[a];if(!V.isUnd(b)&&!V.isNull(b))for(d in b)V.hos(b,d)&&(e=e.replace("%"+d+"%",b[d]));return e},V.i18nToNode=function(a){f.defer(function(){b(".i18n",a).each(function(){var a=b(this),c="";c=a.data("i18n-text"),c?a.text(V.i18n(c)):(c=a.data("i18n-html"),c&&a.html(V.i18n(c)),c=a.data("i18n-placeholder"),c&&a.attr("placeholder",V.i18n(c)),c=a.data("i18n-title"),c&&a.attr("title",V.i18n(c)))})})},V.i18nToDoc=function(){a.rainloopI18N&&(bb=a.rainloopI18N||{},V.i18nToNode(eb),Y.langChangeTrigger(!Y.langChangeTrigger())),a.rainloopI18N={}},V.initOnStartOrLangChange=function(a,b,c){a&&a.call(b),c?Y.langChangeTrigger.subscribe(function(){a&&a.call(b),c.call(b)}):a&&Y.langChangeTrigger.subscribe(a,b)},V.inFocus=function(){var a=document.activeElement;return a&&("INPUT"===a.tagName||"TEXTAREA"===a.tagName||"IFRAME"===a.tagName||"DIV"===a.tagName&&"editorHtmlArea"===a.className&&a.contentEditable)},V.removeInFocus=function(){if(document&&document.activeElement&&document.activeElement.blur){var a=b(document.activeElement);(a.is("input")||a.is("textarea"))&&document.activeElement.blur()}},V.removeSelection=function(){if(a&&a.getSelection){var b=a.getSelection();b&&b.removeAllRanges&&b.removeAllRanges()}else document&&document.selection&&document.selection.empty&&document.selection.empty()},V.replySubjectAdd=function(b,c,d){var e=null,f=V.trim(c);return f=null===(e=new a.RegExp("^"+b+"[\\s]?\\:(.*)$","gi").exec(c))||V.isUnd(e[1])?null===(e=new a.RegExp("^("+b+"[\\s]?[\\[\\(]?)([\\d]+)([\\]\\)]?[\\s]?\\:.*)$","gi").exec(c))||V.isUnd(e[1])||V.isUnd(e[2])||V.isUnd(e[3])?b+": "+c:e[1]+(V.pInt(e[2])+1)+e[3]:b+"[2]: "+e[1],f=f.replace(/[\s]+/g," "),f=(V.isUnd(d)?!0:d)?V.fixLongSubject(f):f},V.fixLongSubject=function(a){var b=0,c=null;a=V.trim(a.replace(/[\s]+/," "));do c=/^Re(\[([\d]+)\]|):[\s]{0,3}Re(\[([\d]+)\]|):/gi.exec(a),(!c||V.isUnd(c[0]))&&(c=null),c&&(b=0,b+=V.isUnd(c[2])?1:0+V.pInt(c[2]),b+=V.isUnd(c[4])?1:0+V.pInt(c[4]),a=a.replace(/^Re(\[[\d]+\]|):[\s]{0,3}Re(\[[\d]+\]|):/gi,"Re"+(b>0?"["+b+"]":"")+":"));while(c);return a=a.replace(/[\s]+/," ")},V.roundNumber=function(a,b){return Math.round(a*Math.pow(10,b))/Math.pow(10,b)},V.friendlySize=function(a){return a=V.pInt(a),a>=1073741824?V.roundNumber(a/1073741824,1)+"GB":a>=1048576?V.roundNumber(a/1048576,1)+"MB":a>=1024?V.roundNumber(a/1024,0)+"KB":a+"B"},V.log=function(b){a.console&&a.console.log&&a.console.log(b)},V.getNotification=function(a,b){return a=V.pInt(a),T.Notification.ClientViewError===a&&b?b:V.isUnd(U[a])?"":U[a]},V.initNotificationLanguage=function(){U[T.Notification.InvalidToken]=V.i18n("NOTIFICATIONS/INVALID_TOKEN"),U[T.Notification.AuthError]=V.i18n("NOTIFICATIONS/AUTH_ERROR"),U[T.Notification.AccessError]=V.i18n("NOTIFICATIONS/ACCESS_ERROR"),U[T.Notification.ConnectionError]=V.i18n("NOTIFICATIONS/CONNECTION_ERROR"),U[T.Notification.CaptchaError]=V.i18n("NOTIFICATIONS/CAPTCHA_ERROR"),U[T.Notification.SocialFacebookLoginAccessDisable]=V.i18n("NOTIFICATIONS/SOCIAL_FACEBOOK_LOGIN_ACCESS_DISABLE"),U[T.Notification.SocialTwitterLoginAccessDisable]=V.i18n("NOTIFICATIONS/SOCIAL_TWITTER_LOGIN_ACCESS_DISABLE"),U[T.Notification.SocialGoogleLoginAccessDisable]=V.i18n("NOTIFICATIONS/SOCIAL_GOOGLE_LOGIN_ACCESS_DISABLE"),U[T.Notification.DomainNotAllowed]=V.i18n("NOTIFICATIONS/DOMAIN_NOT_ALLOWED"),U[T.Notification.AccountNotAllowed]=V.i18n("NOTIFICATIONS/ACCOUNT_NOT_ALLOWED"),U[T.Notification.AccountTwoFactorAuthRequired]=V.i18n("NOTIFICATIONS/ACCOUNT_TWO_FACTOR_AUTH_REQUIRED"),U[T.Notification.AccountTwoFactorAuthError]=V.i18n("NOTIFICATIONS/ACCOUNT_TWO_FACTOR_AUTH_ERROR"),U[T.Notification.CouldNotSaveNewPassword]=V.i18n("NOTIFICATIONS/COULD_NOT_SAVE_NEW_PASSWORD"),U[T.Notification.CurrentPasswordIncorrect]=V.i18n("NOTIFICATIONS/CURRENT_PASSWORD_INCORRECT"),U[T.Notification.NewPasswordShort]=V.i18n("NOTIFICATIONS/NEW_PASSWORD_SHORT"),U[T.Notification.NewPasswordWeak]=V.i18n("NOTIFICATIONS/NEW_PASSWORD_WEAK"),U[T.Notification.NewPasswordForbidden]=V.i18n("NOTIFICATIONS/NEW_PASSWORD_FORBIDDENT"),U[T.Notification.ContactsSyncError]=V.i18n("NOTIFICATIONS/CONTACTS_SYNC_ERROR"),U[T.Notification.CantGetMessageList]=V.i18n("NOTIFICATIONS/CANT_GET_MESSAGE_LIST"),U[T.Notification.CantGetMessage]=V.i18n("NOTIFICATIONS/CANT_GET_MESSAGE"),U[T.Notification.CantDeleteMessage]=V.i18n("NOTIFICATIONS/CANT_DELETE_MESSAGE"),U[T.Notification.CantMoveMessage]=V.i18n("NOTIFICATIONS/CANT_MOVE_MESSAGE"),U[T.Notification.CantCopyMessage]=V.i18n("NOTIFICATIONS/CANT_MOVE_MESSAGE"),U[T.Notification.CantSaveMessage]=V.i18n("NOTIFICATIONS/CANT_SAVE_MESSAGE"),U[T.Notification.CantSendMessage]=V.i18n("NOTIFICATIONS/CANT_SEND_MESSAGE"),U[T.Notification.InvalidRecipients]=V.i18n("NOTIFICATIONS/INVALID_RECIPIENTS"),U[T.Notification.CantCreateFolder]=V.i18n("NOTIFICATIONS/CANT_CREATE_FOLDER"),U[T.Notification.CantRenameFolder]=V.i18n("NOTIFICATIONS/CANT_RENAME_FOLDER"),U[T.Notification.CantDeleteFolder]=V.i18n("NOTIFICATIONS/CANT_DELETE_FOLDER"),U[T.Notification.CantDeleteNonEmptyFolder]=V.i18n("NOTIFICATIONS/CANT_DELETE_NON_EMPTY_FOLDER"),U[T.Notification.CantSubscribeFolder]=V.i18n("NOTIFICATIONS/CANT_SUBSCRIBE_FOLDER"),U[T.Notification.CantUnsubscribeFolder]=V.i18n("NOTIFICATIONS/CANT_UNSUBSCRIBE_FOLDER"),U[T.Notification.CantSaveSettings]=V.i18n("NOTIFICATIONS/CANT_SAVE_SETTINGS"),U[T.Notification.CantSavePluginSettings]=V.i18n("NOTIFICATIONS/CANT_SAVE_PLUGIN_SETTINGS"),U[T.Notification.DomainAlreadyExists]=V.i18n("NOTIFICATIONS/DOMAIN_ALREADY_EXISTS"),U[T.Notification.CantInstallPackage]=V.i18n("NOTIFICATIONS/CANT_INSTALL_PACKAGE"),U[T.Notification.CantDeletePackage]=V.i18n("NOTIFICATIONS/CANT_DELETE_PACKAGE"),U[T.Notification.InvalidPluginPackage]=V.i18n("NOTIFICATIONS/INVALID_PLUGIN_PACKAGE"),U[T.Notification.UnsupportedPluginPackage]=V.i18n("NOTIFICATIONS/UNSUPPORTED_PLUGIN_PACKAGE"),U[T.Notification.LicensingServerIsUnavailable]=V.i18n("NOTIFICATIONS/LICENSING_SERVER_IS_UNAVAILABLE"),U[T.Notification.LicensingExpired]=V.i18n("NOTIFICATIONS/LICENSING_EXPIRED"),U[T.Notification.LicensingBanned]=V.i18n("NOTIFICATIONS/LICENSING_BANNED"),U[T.Notification.DemoSendMessageError]=V.i18n("NOTIFICATIONS/DEMO_SEND_MESSAGE_ERROR"),U[T.Notification.AccountAlreadyExists]=V.i18n("NOTIFICATIONS/ACCOUNT_ALREADY_EXISTS"),U[T.Notification.MailServerError]=V.i18n("NOTIFICATIONS/MAIL_SERVER_ERROR"),U[T.Notification.UnknownNotification]=V.i18n("NOTIFICATIONS/UNKNOWN_ERROR"),U[T.Notification.UnknownError]=V.i18n("NOTIFICATIONS/UNKNOWN_ERROR") +},V.getUploadErrorDescByCode=function(a){var b="";switch(V.pInt(a)){case T.UploadErrorCode.FileIsTooBig:b=V.i18n("UPLOAD/ERROR_FILE_IS_TOO_BIG");break;case T.UploadErrorCode.FilePartiallyUploaded:b=V.i18n("UPLOAD/ERROR_FILE_PARTIALLY_UPLOADED");break;case T.UploadErrorCode.FileNoUploaded:b=V.i18n("UPLOAD/ERROR_NO_FILE_UPLOADED");break;case T.UploadErrorCode.MissingTempFolder:b=V.i18n("UPLOAD/ERROR_MISSING_TEMP_FOLDER");break;case T.UploadErrorCode.FileOnSaveingError:b=V.i18n("UPLOAD/ERROR_ON_SAVING_FILE");break;case T.UploadErrorCode.FileType:b=V.i18n("UPLOAD/ERROR_FILE_TYPE");break;default:b=V.i18n("UPLOAD/ERROR_UNKNOWN")}return b},V.delegateRun=function(a,b,c,d){a&&a[b]&&(d=V.pInt(d),0>=d?a[b].apply(a,V.isArray(c)?c:[]):f.delay(function(){a[b].apply(a,V.isArray(c)?c:[])},d))},V.killCtrlAandS=function(b){if(b=b||a.event,b&&b.ctrlKey&&!b.shiftKey&&!b.altKey){var c=b.target||b.srcElement,d=b.keyCode||b.which;if(d===T.EventKeyCode.S)return void b.preventDefault();if(c&&c.tagName&&c.tagName.match(/INPUT|TEXTAREA/i))return;d===T.EventKeyCode.A&&(a.getSelection?a.getSelection().removeAllRanges():a.document.selection&&a.document.selection.clear&&a.document.selection.clear(),b.preventDefault())}},V.createCommand=function(a,b,d){var e=b?function(){return e.canExecute&&e.canExecute()&&b.apply(a,Array.prototype.slice.call(arguments)),!1}:function(){};return e.enabled=c.observable(!0),d=V.isUnd(d)?!0:d,e.canExecute=c.computed(V.isFunc(d)?function(){return e.enabled()&&d.call(a)}:function(){return e.enabled()&&!!d}),e},V.initDataConstructorBySettings=function(b){b.editorDefaultType=c.observable(T.EditorDefaultType.Html),b.showImages=c.observable(!1),b.interfaceAnimation=c.observable(T.InterfaceAnimation.Full),b.contactsAutosave=c.observable(!1),Y.sAnimationType=T.InterfaceAnimation.Full,b.allowThemes=c.observable(!0),b.allowCustomLogin=c.observable(!1),b.allowLanguagesOnSettings=c.observable(!0),b.allowLanguagesOnLogin=c.observable(!0),b.desktopNotifications=c.observable(!1),b.useThreads=c.observable(!0),b.replySameFolder=c.observable(!0),b.useCheckboxesInList=c.observable(!0),b.layout=c.observable(T.Layout.SidePreview),b.usePreviewPane=c.computed(function(){return T.Layout.NoPreview!==b.layout()}),b.interfaceAnimation.subscribe(function(a){if(Y.bMobileDevice||a===T.InterfaceAnimation.None)cb.removeClass("rl-anim rl-anim-full").addClass("no-rl-anim"),Y.sAnimationType=T.InterfaceAnimation.None;else switch(a){case T.InterfaceAnimation.Full:cb.removeClass("no-rl-anim").addClass("rl-anim rl-anim-full"),Y.sAnimationType=a;break;case T.InterfaceAnimation.Normal:cb.removeClass("no-rl-anim rl-anim-full").addClass("rl-anim"),Y.sAnimationType=a}}),b.interfaceAnimation.valueHasMutated(),b.desktopNotificationsPermisions=c.computed(function(){b.desktopNotifications();var c=T.DesktopNotifications.NotSupported;if(fb&&fb.permission)switch(fb.permission.toLowerCase()){case"granted":c=T.DesktopNotifications.Allowed;break;case"denied":c=T.DesktopNotifications.Denied;break;case"default":c=T.DesktopNotifications.NotAllowed}else a.webkitNotifications&&a.webkitNotifications.checkPermission&&(c=a.webkitNotifications.checkPermission());return c}),b.useDesktopNotifications=c.computed({read:function(){return b.desktopNotifications()&&T.DesktopNotifications.Allowed===b.desktopNotificationsPermisions()},write:function(a){if(a){var c=b.desktopNotificationsPermisions();T.DesktopNotifications.Allowed===c?b.desktopNotifications(!0):T.DesktopNotifications.NotAllowed===c?fb.requestPermission(function(){b.desktopNotifications.valueHasMutated(),T.DesktopNotifications.Allowed===b.desktopNotificationsPermisions()?b.desktopNotifications()?b.desktopNotifications.valueHasMutated():b.desktopNotifications(!0):b.desktopNotifications()?b.desktopNotifications(!1):b.desktopNotifications.valueHasMutated()}):b.desktopNotifications(!1)}else b.desktopNotifications(!1)}}),b.language=c.observable(""),b.languages=c.observableArray([]),b.mainLanguage=c.computed({read:b.language,write:function(a){a!==b.language()?-1 =b.diff(c,"hours")?d:b.format("L")===c.format("L")?V.i18n("MESSAGE_LIST/TODAY_AT",{TIME:c.format("LT")}):b.clone().subtract("days",1).format("L")===c.format("L")?V.i18n("MESSAGE_LIST/YESTERDAY_AT",{TIME:c.format("LT")}):c.format(b.year()===c.year()?"D MMM.":"LL")},a)},V.isFolderExpanded=function(a){var b=gb.local().get(T.ClientSideKeyName.ExpandedFolders);return f.isArray(b)&&-1!==f.indexOf(b,a)},V.setExpandedFolder=function(a,b){var c=gb.local().get(T.ClientSideKeyName.ExpandedFolders);f.isArray(c)||(c=[]),b?(c.push(a),c=f.uniq(c)):c=f.without(c,a),gb.local().set(T.ClientSideKeyName.ExpandedFolders,c)},V.initLayoutResizer=function(a,c,d){var e=65,f=155,g=b(a),h=b(c),i=gb.local().get(d)||null,j=function(a){a&&(g.css({width:""+a+"px"}),h.css({left:""+a+"px"}))},k=function(a){if(a)g.resizable("disable"),j(e);else{g.resizable("enable");var b=V.pInt(gb.local().get(d))||f;j(b>f?b:f)}},l=function(a,b){b&&b.size&&b.size.width&&(gb.local().set(d,b.size.width),h.css({left:""+b.size.width+"px"}))};null!==i&&j(i>f?i:f),g.resizable({helper:"ui-resizable-helper",minWidth:f,maxWidth:350,handles:"e",stop:l}),gb.sub("left-panel.off",function(){k(!0)}),gb.sub("left-panel.on",function(){k(!1)})},V.initBlockquoteSwitcher=function(a){if(a){var c=b("blockquote:not(.rl-bq-switcher)",a).filter(function(){return 0===b(this).parent().closest("blockquote",a).length});c&&0 100)&&(a.addClass("rl-bq-switcher hidden-bq"),b('').insertBefore(a).click(function(){a.toggleClass("hidden-bq"),V.windowResize()}).after("
").before("
"))})}},V.removeBlockquoteSwitcher=function(a){a&&(b(a).find("blockquote.rl-bq-switcher").each(function(){b(this).removeClass("rl-bq-switcher hidden-bq")}),b(a).find(".rlBlockquoteSwitcher").each(function(){b(this).remove()}))},V.toggleMessageBlockquote=function(a){a&&a.find(".rlBlockquoteSwitcher").click()},V.extendAsViewModel=function(a,b,c){b&&(c||(c=l),b.__name=a,W.regViewModelHook(a,b),f.extend(b.prototype,c.prototype))},V.addSettingsViewModel=function(a,b,c,d,e){a.__rlSettingsData={Label:c,Template:b,Route:d,IsDefault:!!e},Z.settings.push(a)},V.removeSettingsViewModel=function(a){Z["settings-removed"].push(a)},V.disableSettingsViewModel=function(a){Z["settings-disabled"].push(a)},V.convertThemeName=function(a){return"@custom"===a.substr(-7)&&(a=V.trim(a.substring(0,a.length-7))),V.trim(a.replace(/[^a-zA-Z]+/g," ").replace(/([A-Z])/g," $1").replace(/[\s]+/g," "))},V.quoteName=function(a){return a.replace(/["]/g,'\\"')},V.microtime=function(){return(new Date).getTime()},V.convertLangName=function(a,b){return V.i18n("LANGS_NAMES"+(!0===b?"_EN":"")+"/LANG_"+a.toUpperCase().replace(/[^a-zA-Z0-9]+/,"_"),null,a)},V.fakeMd5=function(a){var b="",c="0123456789abcdefghijklmnopqrstuvwxyz";for(a=V.isUnd(a)?32:V.pInt(a);b.length>>32-b}function c(a,b){var c,d,e,f,g;return e=2147483648&a,f=2147483648&b,c=1073741824&a,d=1073741824&b,g=(1073741823&a)+(1073741823&b),c&d?2147483648^g^e^f:c|d?1073741824&g?3221225472^g^e^f:1073741824^g^e^f:g^e^f}function d(a,b,c){return a&b|~a&c}function e(a,b,c){return a&c|b&~c}function f(a,b,c){return a^b^c}function g(a,b,c){return b^(a|~c)}function h(a,e,f,g,h,i,j){return a=c(a,c(c(d(e,f,g),h),j)),c(b(a,i),e)}function i(a,d,f,g,h,i,j){return a=c(a,c(c(e(d,f,g),h),j)),c(b(a,i),d)}function j(a,d,e,g,h,i,j){return a=c(a,c(c(f(d,e,g),h),j)),c(b(a,i),d)}function k(a,d,e,f,h,i,j){return a=c(a,c(c(g(d,e,f),h),j)),c(b(a,i),d)}function l(a){for(var b,c=a.length,d=c+8,e=(d-d%64)/64,f=16*(e+1),g=Array(f-1),h=0,i=0;c>i;)b=(i-i%4)/4,h=i%4*8,g[b]=g[b]|a.charCodeAt(i)<>>29,g}function m(a){var b,c,d="",e="";for(c=0;3>=c;c++)b=a>>>8*c&255,e="0"+b.toString(16),d+=e.substr(e.length-2,2);return d}function n(a){a=a.replace(/rn/g,"n");for(var b="",c=0;c d?b+=String.fromCharCode(d):d>127&&2048>d?(b+=String.fromCharCode(d>>6|192),b+=String.fromCharCode(63&d|128)):(b+=String.fromCharCode(d>>12|224),b+=String.fromCharCode(d>>6&63|128),b+=String.fromCharCode(63&d|128))}return b}var o,p,q,r,s,t,u,v,w,x=Array(),y=7,z=12,A=17,B=22,C=5,D=9,E=14,F=20,G=4,H=11,I=16,J=23,K=6,L=10,M=15,N=21;for(a=n(a),x=l(a),t=1732584193,u=4023233417,v=2562383102,w=271733878,o=0;o /g,">").replace(/")},V.draggeblePlace=function(){return b(' ').appendTo("#rl-hidden")},V.defautOptionsAfterRender=function(a,c){c&&!V.isUnd(c.disabled)&&a&&b(a).toggleClass("disabled",c.disabled).prop("disabled",c.disabled)},V.windowPopupKnockout=function(c,d,e,f){var g=null,h=a.open(""),i="__OpenerApplyBindingsUid"+V.fakeMd5()+"__",j=b("#"+d);a[i]=function(){if(h&&h.document.body&&j&&j[0]){var d=b(h.document.body);b("#rl-content",d).html(j.html()),b("html",h.document).addClass("external "+b("html").attr("class")),V.i18nToNode(d),n.prototype.applyExternal(c,b("#rl-content",d)[0]),a[i]=null,f(h)}},h.document.open(),h.document.write(''+V.encodeHtml(e)+' '),h.document.close(),g=h.document.createElement("script"),g.type="text/javascript",g.innerHTML="if(window&&window.opener&&window.opener['"+i+"']){window.opener['"+i+"']();window.opener['"+i+"']=null}",h.document.getElementsByTagName("head")[0].appendChild(g)},V.settingsSaveHelperFunction=function(a,b,c,d){return c=c||null,d=V.isUnd(d)?1e3:V.pInt(d),function(e,g,h,i,j){b.call(c,g&&g.Result?T.SaveSettingsStep.TrueResult:T.SaveSettingsStep.FalseResult),a&&a.call(c,e,g,h,i,j),f.delay(function(){b.call(c,T.SaveSettingsStep.Idle)},d)}},V.settingsSaveHelperSimpleFunction=function(a,b){return V.settingsSaveHelperFunction(null,a,b,1e3)},V.htmlToPlain=function(a){var c="",d="> ",e=function(){if(arguments&&1\n",a.replace(/\n([> ]+)/gm,function(){return arguments&&1 ]*>(.|[\s\S\r\n]*)<\/div>/gim,f),a="\n"+b.trim(a)+"\n"),a}return""},g=function(){return arguments&&1 /g,">"):""},h=function(){if(arguments&&1 /gim,"\n").replace(/<\/h\d>/gi,"\n").replace(/<\/p>/gi,"\n\n").replace(/<\/li>/gi,"\n").replace(/<\/td>/gi,"\n").replace(/<\/tr>/gi,"\n").replace(/
]*>/gim,"\n_______________________________\n\n").replace(/]*>/gim,"").replace(/
]*>(.|[\s\S\r\n]*)<\/div>/gim,f).replace(/]*>/gim,"\n__bq__start__\n").replace(/<\/blockquote>/gim,"\n__bq__end__\n").replace(/]*>(.|[\s\S\r\n]*)<\/a>/gim,h).replace(/ /gi," ").replace(/<[^>]*>/gm,"").replace(/>/gi,">").replace(/</gi,"<").replace(/&/gi,"&").replace(/&\w{2,6};/gi,""),c.replace(/\n[ \t]+/gm,"\n").replace(/[\n]{3,}/gm,"\n\n").replace(/__bq__start__(.|[\s\S\r\n]*)__bq__end__/gm,e).replace(/__bq__start__/gm,"").replace(/__bq__end__/gm,"")},V.plainToHtml=function(a){return a.toString().replace(/&/g,"&").replace(/>/g,">").replace(/")},V.resizeAndCrop=function(b,c,d){var e=new a.Image;e.onload=function(){var a=[0,0],b=document.createElement("canvas"),e=b.getContext("2d");b.width=c,b.height=c,a=this.width>this.height?[this.width-this.height,0]:[0,this.height-this.width],e.fillStyle="#fff",e.fillRect(0,0,c,c),e.drawImage(this,a[0]/2,a[1]/2,this.width-a[0],this.height-a[1],0,0,c,c),d(b.toDataURL("image/jpeg"))},e.src=b},V.computedPagenatorHelper=function(a,b){return function(){var c=0,d=0,e=2,f=[],g=a(),h=b(),i=function(a,b,c){var d={current:a===g,name:V.isUnd(c)?a.toString():c.toString(),custom:V.isUnd(c)?!1:!0,title:V.isUnd(c)?"":a.toString(),value:a.toString()};(V.isUnd(b)?0:!b)?f.unshift(d):f.push(d)};if(h>1||h>0&&g>h){for(g>h?(i(h),c=h,d=h):((3>=g||g>=h-2)&&(e+=2),i(g),c=g,d=g);e>0;)if(c-=1,d+=1,c>0&&(i(c,!1),e--),h>=d)i(d,!0),e--;else if(0>=c)break;3===c?i(2,!1):c>3&&i(Math.round((c-1)/2),!1,"..."),h-2===d?i(h-1,!0):h-2>d&&i(Math.round((h+d)/2),!0,"..."),c>1&&i(1,!1),h>d&&i(h,!0)}return f}},V.selectElement=function(b){if(a.getSelection){var c=a.getSelection();c.removeAllRanges();var d=document.createRange();d.selectNodeContents(b),c.addRange(d)}else if(document.selection){var e=document.body.createTextRange();e.moveToElementText(b),e.select()}},V.disableKeyFilter=function(){a.key&&(key.filter=function(){return gb.data().useKeyboardShortcuts()})},V.restoreKeyFilter=function(){a.key&&(key.filter=function(a){if(gb.data().useKeyboardShortcuts()){var b=a.target||a.srcElement,c=b?b.tagName:"";return c=c.toUpperCase(),!("INPUT"===c||"SELECT"===c||"TEXTAREA"===c||b&&"DIV"===c&&"editorHtmlArea"===b.className&&b.contentEditable)}return!1})},V.detectDropdownVisibility=f.debounce(function(){Y.dropdownVisibility(!!f.find($,function(a){return a.hasClass("open")}))},50),X={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",urlsafe_encode:function(a){return X.encode(a).replace(/[+]/g,"-").replace(/[\/]/g,"_").replace(/[=]/g,".")},encode:function(a){var b,c,d,e,f,g,h,i="",j=0;for(a=X._utf8_encode(a);j>2,f=(3&b)<<4|c>>4,g=(15&c)<<2|d>>6,h=63&d,isNaN(c)?g=h=64:isNaN(d)&&(h=64),i=i+this._keyStr.charAt(e)+this._keyStr.charAt(f)+this._keyStr.charAt(g)+this._keyStr.charAt(h);return i},decode:function(a){var b,c,d,e,f,g,h,i="",j=0;for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");j >4,c=(15&f)<<4|g>>2,d=(3&g)<<6|h,i+=String.fromCharCode(b),64!==g&&(i+=String.fromCharCode(c)),64!==h&&(i+=String.fromCharCode(d));return X._utf8_decode(i)},_utf8_encode:function(a){a=a.replace(/\r\n/g,"\n");for(var b="",c=0,d=a.length,e=0;d>c;c++)e=a.charCodeAt(c),128>e?b+=String.fromCharCode(e):e>127&&2048>e?(b+=String.fromCharCode(e>>6|192),b+=String.fromCharCode(63&e|128)):(b+=String.fromCharCode(e>>12|224),b+=String.fromCharCode(e>>6&63|128),b+=String.fromCharCode(63&e|128));return b},_utf8_decode:function(a){for(var b="",c=0,d=0,e=0,f=0;c d?(b+=String.fromCharCode(d),c++):d>191&&224>d?(e=a.charCodeAt(c+1),b+=String.fromCharCode((31&d)<<6|63&e),c+=2):(e=a.charCodeAt(c+1),f=a.charCodeAt(c+2),b+=String.fromCharCode((15&d)<<12|(63&e)<<6|63&f),c+=3);return b}},c.bindingHandlers.tooltip={init:function(a,d){if(!Y.bMobileDevice){var e=b(a),f=e.data("tooltip-class")||"",g=e.data("tooltip-placement")||"top";e.tooltip({delay:{show:500,hide:100},html:!0,container:"body",placement:g,trigger:"hover",title:function(){return e.is(".disabled")||Y.dropdownVisibility()?"":''+V.i18n(c.utils.unwrapObservable(d()))+""}}).click(function(){e.tooltip("hide")}),Y.dropdownVisibility.subscribe(function(a){a&&e.tooltip("hide")})}}},c.bindingHandlers.tooltip2={init:function(a,c){var d=b(a),e=d.data("tooltip-class")||"",f=d.data("tooltip-placement")||"top";d.tooltip({delay:{show:500,hide:100},html:!0,container:"body",placement:f,title:function(){return d.is(".disabled")||Y.dropdownVisibility()?"":''+c()()+""}}).click(function(){d.tooltip("hide")}),Y.dropdownVisibility.subscribe(function(a){a&&d.tooltip("hide")})}},c.bindingHandlers.tooltip3={init:function(a){var c=b(a);c.tooltip({container:"body",trigger:"hover manual",title:function(){return c.data("tooltip3-data")||""}}),Y.dropdownVisibility.subscribe(function(a){a&&c.tooltip("hide")}),eb.click(function(){c.tooltip("hide")})},update:function(a,d){var e=c.utils.unwrapObservable(d());""===e?b(a).data("tooltip3-data","").tooltip("hide"):b(a).data("tooltip3-data",e).tooltip("show")}},c.bindingHandlers.registrateBootstrapDropdown={init:function(a){$.push(b(a))}},c.bindingHandlers.openDropdownTrigger={update:function(a,d){if(c.utils.unwrapObservable(d())){var e=b(a);e.hasClass("open")||(e.find(".dropdown-toggle").dropdown("toggle"),V.detectDropdownVisibility()),d()(!1)}}},c.bindingHandlers.dropdownCloser={init:function(a){b(a).closest(".dropdown").on("click",".e-item",function(){b(a).dropdown("toggle")})}},c.bindingHandlers.popover={init:function(a,d){b(a).popover(c.utils.unwrapObservable(d()))}},c.bindingHandlers.csstext={init:function(a,d){a&&a.styleSheet&&!V.isUnd(a.styleSheet.cssText)?a.styleSheet.cssText=c.utils.unwrapObservable(d()):b(a).text(c.utils.unwrapObservable(d()))},update:function(a,d){a&&a.styleSheet&&!V.isUnd(a.styleSheet.cssText)?a.styleSheet.cssText=c.utils.unwrapObservable(d()):b(a).text(c.utils.unwrapObservable(d()))}},c.bindingHandlers.resizecrop={init:function(a){b(a).addClass("resizecrop").resizecrop({width:"100",height:"100",wrapperCSS:{"border-radius":"10px"}})},update:function(a,c){c()(),b(a).resizecrop({width:"100",height:"100"})}},c.bindingHandlers.onEnter={init:function(c,d,e,f){b(c).on("keypress",function(e){e&&13===a.parseInt(e.keyCode,10)&&(b(c).trigger("change"),d().call(f))})}},c.bindingHandlers.onEsc={init:function(c,d,e,f){b(c).on("keypress",function(e){e&&27===a.parseInt(e.keyCode,10)&&(b(c).trigger("change"),d().call(f))})}},c.bindingHandlers.clickOnTrue={update:function(a,d){c.utils.unwrapObservable(d())&&b(a).click()}},c.bindingHandlers.modal={init:function(a,d){b(a).toggleClass("fade",!Y.bMobileDevice).modal({keyboard:!1,show:c.utils.unwrapObservable(d())}).on("shown",function(){V.windowResize()}).find(".close").click(function(){d()(!1)})},update:function(a,d){b(a).modal(c.utils.unwrapObservable(d())?"show":"hide")}},c.bindingHandlers.i18nInit={init:function(a){V.i18nToNode(a)}},c.bindingHandlers.i18nUpdate={update:function(a,b){c.utils.unwrapObservable(b()),V.i18nToNode(a)}},c.bindingHandlers.link={update:function(a,d){b(a).attr("href",c.utils.unwrapObservable(d()))}},c.bindingHandlers.title={update:function(a,d){b(a).attr("title",c.utils.unwrapObservable(d()))}},c.bindingHandlers.textF={init:function(a,d){b(a).text(c.utils.unwrapObservable(d()))}},c.bindingHandlers.initDom={init:function(a,b){b()(a)}},c.bindingHandlers.initResizeTrigger={init:function(a,d){var e=c.utils.unwrapObservable(d());b(a).css({height:e[1],"min-height":e[1]})},update:function(a,d){var e=c.utils.unwrapObservable(d()),f=V.pInt(e[1]),g=0,h=b(a).offset().top;h>0&&(h+=V.pInt(e[2]),g=db.height()-h,g>f&&(f=g),b(a).css({height:f,"min-height":f}))}},c.bindingHandlers.appendDom={update:function(a,d){b(a).hide().empty().append(c.utils.unwrapObservable(d())).show()}},c.bindingHandlers.draggable={init:function(d,e,f){if(!Y.bMobileDevice){var g=100,h=3,i=f(),j=i&&i.droppableSelector?i.droppableSelector:"",k={distance:20,handle:".dragHandle",cursorAt:{top:22,left:3},refreshPositions:!0,scroll:!0};j&&(k.drag=function(c){b(j).each(function(){var d=null,e=null,f=b(this),i=f.offset(),j=i.top+f.height();a.clearInterval(f.data("timerScroll")),f.data("timerScroll",!1),c.pageX>=i.left&&c.pageX<=i.left+f.width()&&(c.pageY>=j-g&&c.pageY<=j&&(d=function(){f.scrollTop(f.scrollTop()+h),V.windowResize()},f.data("timerScroll",a.setInterval(d,10)),d()),c.pageY>=i.top&&c.pageY<=i.top+g&&(e=function(){f.scrollTop(f.scrollTop()-h),V.windowResize()},f.data("timerScroll",a.setInterval(e,10)),e()))})},k.stop=function(){b(j).each(function(){a.clearInterval(b(this).data("timerScroll")),b(this).data("timerScroll",!1)})}),k.helper=function(a){return e()(a&&a.target?c.dataFor(a.target):null)},b(d).draggable(k).on("mousedown",function(){V.removeInFocus()})}}},c.bindingHandlers.droppable={init:function(a,c,d){if(!Y.bMobileDevice){var e=c(),f=d(),g=f&&f.droppableOver?f.droppableOver:null,h=f&&f.droppableOut?f.droppableOut:null,i={tolerance:"pointer",hoverClass:"droppableHover"};e&&(i.drop=function(a,b){e(a,b)},g&&(i.over=function(a,b){g(a,b)}),h&&(i.out=function(a,b){h(a,b)}),b(a).droppable(i))}}},c.bindingHandlers.nano={init:function(a){Y.bDisableNanoScroll||b(a).addClass("nano").nanoScroller({iOSNativeScrolling:!1,preventPageScrolling:!0})}},c.bindingHandlers.saveTrigger={init:function(a){var c=b(a);c.data("save-trigger-type",c.is("input[type=text],input[type=email],input[type=password],select,textarea")?"input":"custom"),"custom"===c.data("save-trigger-type")?c.append(' ').addClass("settings-saved-trigger"):c.addClass("settings-saved-trigger-input")},update:function(a,d){var e=c.utils.unwrapObservable(d()),f=b(a);if("custom"===f.data("save-trigger-type"))switch(e.toString()){case"1":f.find(".animated,.error").hide().removeClass("visible").end().find(".success").show().addClass("visible");break;case"0":f.find(".animated,.success").hide().removeClass("visible").end().find(".error").show().addClass("visible");break;case"-2":f.find(".error,.success").hide().removeClass("visible").end().find(".animated").show().addClass("visible");break;default:f.find(".animated").hide().end().find(".error,.success").removeClass("visible")}else switch(e.toString()){case"1":f.addClass("success").removeClass("error");break;case"0":f.addClass("error").removeClass("success");break;case"-2":break;default:f.removeClass("error success")}}},c.bindingHandlers.emailsTags={init:function(a,c){var d=b(a),e=c();d.inputosaurus({parseOnBlur:!0,inputDelimiters:[",",";"],autoCompleteSource:function(a,b){gb.getAutocomplete(a.term,function(a){b(f.map(a,function(a){return a.toLine(!1)}))})},parseHook:function(a){return f.map(a,function(a){var b=V.trim(a),c=null;return""!==b?(c=new o,c.mailsoParse(b),c.clearDuplicateName(),[c.toLine(!1),c]):[b,null]})},change:f.bind(function(a){d.data("EmailsTagsValue",a.target.value),e(a.target.value)},this)}),e.subscribe(function(a){d.data("EmailsTagsValue")!==a&&(d.val(a),d.data("EmailsTagsValue",a),d.inputosaurus("refresh"))}),e.focusTrigger&&e.focusTrigger.subscribe(function(){d.inputosaurus("focus")})}},c.bindingHandlers.command={init:function(a,d,e,f){var g=b(a),h=d();if(!h||!h.enabled||!h.canExecute)throw new Error("You are not using command function");g.addClass("command"),c.bindingHandlers[g.is("form")?"submit":"click"].init.apply(f,arguments)},update:function(a,c){var d=!0,e=b(a),f=c();d=f.enabled(),e.toggleClass("command-not-enabled",!d),d&&(d=f.canExecute(),e.toggleClass("command-can-not-be-execute",!d)),e.toggleClass("command-disabled disable disabled",!d).toggleClass("no-disabled",!!d),(e.is("input")||e.is("button"))&&e.prop("disabled",!d)}},c.extenders.trimmer=function(a){var b=c.computed({read:a,write:function(b){a(V.trim(b.toString()))},owner:this});return b(a()),b},c.extenders.reversible=function(a){var b=a();return a.commit=function(){b=a()},a.reverse=function(){a(b)},a.commitedValue=function(){return b},a},c.extenders.toggleSubscribe=function(a,b){return a.subscribe(b[1],b[0],"beforeChange"),a.subscribe(b[2],b[0]),a},c.extenders.falseTimeout=function(b,c){return b.iTimeout=0,b.subscribe(function(d){d&&(a.clearTimeout(b.iTimeout),b.iTimeout=a.setTimeout(function(){b(!1),b.iTimeout=0},V.pInt(c)))}),b},c.observable.fn.validateNone=function(){return this.hasError=c.observable(!1),this},c.observable.fn.validateEmail=function(){return this.hasError=c.observable(!1),this.subscribe(function(a){a=V.trim(a),this.hasError(""!==a&&!/^[^@\s]+@[^@\s]+$/.test(a))},this),this.valueHasMutated(),this},c.observable.fn.validateSimpleEmail=function(){return this.hasError=c.observable(!1),this.subscribe(function(a){a=V.trim(a),this.hasError(""!==a&&!/^.+@.+$/.test(a))},this),this.valueHasMutated(),this},c.observable.fn.validateFunc=function(a){return this.hasFuncError=c.observable(!1),V.isFunc(a)&&(this.subscribe(function(b){this.hasFuncError(!a(b))},this),this.valueHasMutated()),this},g.prototype.root=function(){return this.sBase},g.prototype.attachmentDownload=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/Download/"+a},g.prototype.attachmentPreview=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/View/"+a},g.prototype.attachmentPreviewAsPlain=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/ViewAsPlain/"+a},g.prototype.upload=function(){return this.sServer+"/Upload/"+this.sSpecSuffix+"/"},g.prototype.uploadContacts=function(){return this.sServer+"/UploadContacts/"+this.sSpecSuffix+"/"},g.prototype.uploadBackground=function(){return this.sServer+"/UploadBackground/"+this.sSpecSuffix+"/"},g.prototype.append=function(){return this.sServer+"/Append/"+this.sSpecSuffix+"/"},g.prototype.change=function(b){return this.sServer+"/Change/"+this.sSpecSuffix+"/"+a.encodeURIComponent(b)+"/"},g.prototype.ajax=function(a){return this.sServer+"/Ajax/"+this.sSpecSuffix+"/"+a},g.prototype.messageViewLink=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/ViewAsPlain/"+a},g.prototype.messageDownloadLink=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/Download/"+a},g.prototype.inbox=function(){return this.sBase+"mailbox/Inbox"},g.prototype.messagePreview=function(){return this.sBase+"mailbox/message-preview"},g.prototype.settings=function(a){var b=this.sBase+"settings";return V.isUnd(a)||""===a||(b+="/"+a),b},g.prototype.admin=function(a){var b=this.sBase;switch(a){case"AdminDomains":b+="domains";break;case"AdminSecurity":b+="security";break;case"AdminLicensing":b+="licensing"}return b},g.prototype.mailBox=function(a,b,c){b=V.isNormal(b)?V.pInt(b):1,c=V.pString(c);var d=this.sBase+"mailbox/";return""!==a&&(d+=encodeURI(a)),b>1&&(d=d.replace(/[\/]+$/,""),d+="/p"+b),""!==c&&(d=d.replace(/[\/]+$/,""),d+="/"+encodeURI(c)),d},g.prototype.phpInfo=function(){return this.sServer+"Info"},g.prototype.langLink=function(a){return this.sServer+"/Lang/0/"+encodeURI(a)+"/"+this.sVersion+"/"},g.prototype.getUserPicUrlFromHash=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/UserPic/"+a+"/"+this.sVersion+"/"},g.prototype.exportContactsVcf=function(){return this.sServer+"/Raw/"+this.sSpecSuffix+"/ContactsVcf/"},g.prototype.exportContactsCsv=function(){return this.sServer+"/Raw/"+this.sSpecSuffix+"/ContactsCsv/"},g.prototype.emptyContactPic=function(){return"rainloop/v/"+this.sVersion+"/static/css/images/empty-contact.png"},g.prototype.sound=function(a){return"rainloop/v/"+this.sVersion+"/static/sounds/"+a},g.prototype.themePreviewLink=function(a){var b="rainloop/v/"+this.sVersion+"/";return"@custom"===a.substr(-7)&&(a=V.trim(a.substring(0,a.length-7)),b=""),b+"themes/"+encodeURI(a)+"/images/preview.png"},g.prototype.notificationMailIcon=function(){return"rainloop/v/"+this.sVersion+"/static/css/images/icom-message-notification.png"},g.prototype.openPgpJs=function(){return"rainloop/v/"+this.sVersion+"/static/js/openpgp.min.js"},g.prototype.socialGoogle=function(){return this.sServer+"SocialGoogle"+(""!==this.sSpecSuffix?"/"+this.sSpecSuffix+"/":"")},g.prototype.socialTwitter=function(){return this.sServer+"SocialTwitter"+(""!==this.sSpecSuffix?"/"+this.sSpecSuffix+"/":"")},g.prototype.socialFacebook=function(){return this.sServer+"SocialFacebook"+(""!==this.sSpecSuffix?"/"+this.sSpecSuffix+"/":"")},W.oViewModelsHooks={},W.oSimpleHooks={},W.regViewModelHook=function(a,b){b&&(b.__hookName=a) +},W.addHook=function(a,b){V.isFunc(b)&&(V.isArray(W.oSimpleHooks[a])||(W.oSimpleHooks[a]=[]),W.oSimpleHooks[a].push(b))},W.runHook=function(a,b){V.isArray(W.oSimpleHooks[a])&&(b=b||[],f.each(W.oSimpleHooks[a],function(a){a.apply(null,b)}))},W.mainSettingsGet=function(a){return gb?gb.settingsGet(a):null},W.remoteRequest=function(a,b,c,d,e,f){gb&&gb.remote().defaultRequest(a,b,c,d,e,f)},W.settingsGet=function(a,b){var c=W.mainSettingsGet("Plugins");return c=c&&V.isUnd(c[a])?null:c[a],c?V.isUnd(c[b])?null:c[b]:null},h.supported=function(){return!0},h.prototype.set=function(a,c){var d=b.cookie(S.Values.ClientSideCookieIndexName),e=!1,f=null;try{f=null===d?null:JSON.parse(d),f||(f={}),f[a]=c,b.cookie(S.Values.ClientSideCookieIndexName,JSON.stringify(f),{expires:30}),e=!0}catch(g){}return e},h.prototype.get=function(a){var c=b.cookie(S.Values.ClientSideCookieIndexName),d=null;try{d=null===c?null:JSON.parse(c),d=d&&!V.isUnd(d[a])?d[a]:null}catch(e){}return d},i.supported=function(){return!!a.localStorage},i.prototype.set=function(b,c){var d=a.localStorage[S.Values.ClientSideCookieIndexName]||null,e=!1,f=null;try{f=null===d?null:JSON.parse(d),f||(f={}),f[b]=c,a.localStorage[S.Values.ClientSideCookieIndexName]=JSON.stringify(f),e=!0}catch(g){}return e},i.prototype.get=function(b){var c=a.localStorage[S.Values.ClientSideCookieIndexName]||null,d=null;try{d=null===c?null:JSON.parse(c),d=d&&!V.isUnd(d[b])?d[b]:null}catch(e){}return d},j.prototype.oDriver=null,j.prototype.set=function(a,b){return this.oDriver?this.oDriver.set("p"+a,b):!1},j.prototype.get=function(a){return this.oDriver?this.oDriver.get("p"+a):null},k.prototype.bootstart=function(){},l.prototype.sPosition="",l.prototype.sTemplate="",l.prototype.viewModelName="",l.prototype.viewModelDom=null,l.prototype.viewModelTemplate=function(){return this.sTemplate},l.prototype.viewModelPosition=function(){return this.sPosition},l.prototype.cancelCommand=l.prototype.closeCommand=function(){},l.prototype.storeAndSetKeyScope=function(){this.sCurrentKeyScope=gb.data().keyScope(),gb.data().keyScope(this.sDefaultKeyScope)},l.prototype.restoreKeyScope=function(){gb.data().keyScope(this.sCurrentKeyScope)},l.prototype.registerPopupEscapeKey=function(){var a=this;db.on("keydown",function(b){return b&&T.EventKeyCode.Esc===b.keyCode&&a.modalVisibility&&a.modalVisibility()?(V.delegateRun(a,"cancelCommand"),!1):!0})},m.prototype.oCross=null,m.prototype.sScreenName="",m.prototype.aViewModels=[],m.prototype.viewModels=function(){return this.aViewModels},m.prototype.screenName=function(){return this.sScreenName},m.prototype.routes=function(){return null},m.prototype.__cross=function(){return this.oCross},m.prototype.__start=function(){var a=this.routes(),b=null,c=null;V.isNonEmptyArray(a)&&(c=f.bind(this.onRoute||V.emptyFunction,this),b=d.create(),f.each(a,function(a){b.addRoute(a[0],c).rules=a[1]}),this.oCross=b)},n.constructorEnd=function(a){V.isFunc(a.__constructor_end)&&a.__constructor_end.call(a)},n.prototype.sDefaultScreenName="",n.prototype.oScreens={},n.prototype.oBoot=null,n.prototype.oCurrentScreen=null,n.prototype.hideLoading=function(){b("#rl-loading").hide()},n.prototype.routeOff=function(){e.changed.active=!1},n.prototype.routeOn=function(){e.changed.active=!0},n.prototype.setBoot=function(a){return V.isNormal(a)&&(this.oBoot=a),this},n.prototype.screen=function(a){return""===a||V.isUnd(this.oScreens[a])?null:this.oScreens[a]},n.prototype.buildViewModel=function(a,d){if(a&&!a.__builded){var e=new a(d),g=e.viewModelPosition(),h=b("#rl-content #rl-"+g.toLowerCase()),i=null;a.__builded=!0,a.__vm=e,e.data=gb.data(),e.viewModelName=a.__name,h&&1===h.length?(i=b(" ").addClass("rl-view-model").addClass("RL-"+e.viewModelTemplate()).hide().attr("data-bind",'template: {name: "'+e.viewModelTemplate()+'"}, i18nInit: true'),i.appendTo(h),e.viewModelDom=i,a.__dom=i,"Popups"===g&&(e.cancelCommand=e.closeCommand=V.createCommand(e,function(){_.hideScreenPopup(a)}),e.modalVisibility.subscribe(function(a){var b=this;a?(this.viewModelDom.show(),this.storeAndSetKeyScope(),gb.popupVisibilityNames.push(this.viewModelName),e.viewModelDom.css("z-index",3e3+gb.popupVisibilityNames().length+10),V.delegateRun(this,"onFocus",[],500)):(V.delegateRun(this,"onHide"),this.restoreKeyScope(),gb.popupVisibilityNames.remove(this.viewModelName),e.viewModelDom.css("z-index",2e3),f.delay(function(){b.viewModelDom.hide()},300))},e)),W.runHook("view-model-pre-build",[a.__name,e,i]),c.applyBindings(e,i[0]),V.delegateRun(e,"onBuild",[i]),e&&"Popups"===g&&!e.bDisabeCloseOnEsc&&e.registerPopupEscapeKey(),W.runHook("view-model-post-build",[a.__name,e,i])):V.log("Cannot find view model position: "+g)}return a?a.__vm:null},n.prototype.applyExternal=function(a,b){a&&b&&c.applyBindings(a,b)},n.prototype.hideScreenPopup=function(a){a&&a.__vm&&a.__dom&&(a.__vm.modalVisibility(!1),W.runHook("view-model-on-hide",[a.__name,a.__vm]))},n.prototype.showScreenPopup=function(a,b){a&&(this.buildViewModel(a),a.__vm&&a.__dom&&(a.__vm.modalVisibility(!0),V.delegateRun(a.__vm,"onShow",b||[]),W.runHook("view-model-on-show",[a.__name,a.__vm,b||[]])))},n.prototype.screenOnRoute=function(a,b){var c=this,d=null,e=null;""===V.pString(a)&&(a=this.sDefaultScreenName),""!==a&&(d=this.screen(a),d||(d=this.screen(this.sDefaultScreenName),d&&(b=a+"/"+b,a=this.sDefaultScreenName)),d&&d.__started&&(d.__builded||(d.__builded=!0,V.isNonEmptyArray(d.viewModels())&&f.each(d.viewModels(),function(a){this.buildViewModel(a,d)},this),V.delegateRun(d,"onBuild")),f.defer(function(){c.oCurrentScreen&&(V.delegateRun(c.oCurrentScreen,"onHide"),V.isNonEmptyArray(c.oCurrentScreen.viewModels())&&f.each(c.oCurrentScreen.viewModels(),function(a){a.__vm&&a.__dom&&"Popups"!==a.__vm.viewModelPosition()&&(a.__dom.hide(),a.__vm.viewModelVisibility(!1),V.delegateRun(a.__vm,"onHide"))})),c.oCurrentScreen=d,c.oCurrentScreen&&(V.delegateRun(c.oCurrentScreen,"onShow"),W.runHook("screen-on-show",[c.oCurrentScreen.screenName(),c.oCurrentScreen]),V.isNonEmptyArray(c.oCurrentScreen.viewModels())&&f.each(c.oCurrentScreen.viewModels(),function(a){a.__vm&&a.__dom&&"Popups"!==a.__vm.viewModelPosition()&&(a.__dom.show(),a.__vm.viewModelVisibility(!0),V.delegateRun(a.__vm,"onShow"),V.delegateRun(a.__vm,"onFocus",[],200),W.runHook("view-model-on-show",[a.__name,a.__vm]))},c)),e=d.__cross(),e&&e.parse(b)})))},n.prototype.startScreens=function(a){b("#rl-content").css({visibility:"hidden"}),f.each(a,function(a){var b=new a,c=b?b.screenName():"";b&&""!==c&&(""===this.sDefaultScreenName&&(this.sDefaultScreenName=c),this.oScreens[c]=b)},this),f.each(this.oScreens,function(a){a&&!a.__started&&a.__start&&(a.__started=!0,a.__start(),W.runHook("screen-pre-start",[a.screenName(),a]),V.delegateRun(a,"onStart"),W.runHook("screen-post-start",[a.screenName(),a]))},this);var c=d.create();c.addRoute(/^([a-zA-Z0-9\-]*)\/?(.*)$/,f.bind(this.screenOnRoute,this)),e.initialized.add(c.parse,c),e.changed.add(c.parse,c),e.init(),b("#rl-content").css({visibility:"visible"}),f.delay(function(){cb.removeClass("rl-started-trigger").addClass("rl-started")},50)},n.prototype.setHash=function(a,b,c){a="#"===a.substr(0,1)?a.substr(1):a,a="/"===a.substr(0,1)?a.substr(1):a,c=V.isUnd(c)?!1:!!c,(V.isUnd(b)?1:!b)?(e.changed.active=!0,e[c?"replaceHash":"setHash"](a),e.setHash(a)):(e.changed.active=!1,e[c?"replaceHash":"setHash"](a),e.changed.active=!0)},n.prototype.bootstart=function(){return this.oBoot&&this.oBoot.bootstart&&this.oBoot.bootstart(),this},_=new n,o.newInstanceFromJson=function(a){var b=new o;return b.initByJson(a)?b:null},o.prototype.name="",o.prototype.email="",o.prototype.privateType=null,o.prototype.clear=function(){this.email="",this.name="",this.privateType=null},o.prototype.validate=function(){return""!==this.name||""!==this.email},o.prototype.hash=function(a){return"#"+(a?"":this.name)+"#"+this.email+"#"},o.prototype.clearDuplicateName=function(){this.name===this.email&&(this.name="")},o.prototype.type=function(){return null===this.privateType&&(this.email&&"@facebook.com"===this.email.substr(-13)&&(this.privateType=T.EmailType.Facebook),null===this.privateType&&(this.privateType=T.EmailType.Default)),this.privateType},o.prototype.search=function(a){return-1<(this.name+" "+this.email).toLowerCase().indexOf(a.toLowerCase())},o.prototype.parse=function(a){this.clear(),a=V.trim(a);var b=/(?:"([^"]+)")? ?(.*?@[^>,]+)>?,? ?/g,c=b.exec(a);c?(this.name=c[1]||"",this.email=c[2]||"",this.clearDuplicateName()):/^[^@]+@[^@]+$/.test(a)&&(this.name="",this.email=a)},o.prototype.initByJson=function(a){var b=!1;return a&&"Object/Email"===a["@Object"]&&(this.name=V.trim(a.Name),this.email=V.trim(a.Email),b=""!==this.email,this.clearDuplicateName()),b},o.prototype.toLine=function(a,b,c){var d="";return""!==this.email&&(b=V.isUnd(b)?!1:!!b,c=V.isUnd(c)?!1:!!c,a&&""!==this.name?d=b?'")+'" target="_blank" tabindex="-1">'+V.encodeHtml(this.name)+"":c?V.encodeHtml(this.name):this.name:(d=this.email,""!==this.name?b?d=V.encodeHtml('"'+this.name+'" <')+'")+'" target="_blank" tabindex="-1">'+V.encodeHtml(d)+""+V.encodeHtml(">"):(d='"'+this.name+'" <'+d+">",c&&(d=V.encodeHtml(d))):b&&(d=''+V.encodeHtml(this.email)+""))),d},o.prototype.mailsoParse=function(a){if(a=V.trim(a),""===a)return!1;for(var b=function(a,b,c){a+="";var d=a.length;return 0>b&&(b+=d),d="undefined"==typeof c?d:0>c?c+d:c+b,b>=a.length||0>b||b>d?!1:a.slice(b,d)},c=function(a,b,c,d){return 0>c&&(c+=a.length),d=void 0!==d?d:a.length,0>d&&(d=d+a.length-c),a.slice(0,c)+b.substr(0,d)+b.slice(d)+a.slice(c+d)},d="",e="",f="",g=!1,h=!1,i=!1,j=null,k=0,l=0,m=0;m").addClass("rl-settings-view-model").hide().attr("data-bind",'template: {name: "'+g.__rlSettingsData.Template+'"}, i18nInit: true'),i.appendTo(h),e.data=gb.data(),e.viewModelDom=i,e.__rlSettingsData=g.__rlSettingsData,g.__dom=i,g.__builded=!0,g.__vm=e,c.applyBindings(e,i[0]),V.delegateRun(e,"onBuild",[i])):V.log("Cannot find sub settings view model position: SettingsSubScreen")),e&&f.defer(function(){d.oCurrentSubScreen&&(V.delegateRun(d.oCurrentSubScreen,"onHide"),d.oCurrentSubScreen.viewModelDom.hide()),d.oCurrentSubScreen=e,d.oCurrentSubScreen&&(d.oCurrentSubScreen.viewModelDom.show(),V.delegateRun(d.oCurrentSubScreen,"onShow"),V.delegateRun(d.oCurrentSubScreen,"onFocus",[],200),f.each(d.menu(),function(a){a.selected(e&&e.__rlSettingsData&&a.route===e.__rlSettingsData.Route)}),b("#rl-content .b-settings .b-content .content").scrollTop(0)),V.windowResize()})):_.setHash(gb.link().settings(),!1,!0)},N.prototype.onHide=function(){this.oCurrentSubScreen&&this.oCurrentSubScreen.viewModelDom&&(V.delegateRun(this.oCurrentSubScreen,"onHide"),this.oCurrentSubScreen.viewModelDom.hide())},N.prototype.onBuild=function(){f.each(Z.settings,function(a){a&&a.__rlSettingsData&&!f.find(Z["settings-removed"],function(b){return b&&b===a})&&this.menu.push({route:a.__rlSettingsData.Route,label:a.__rlSettingsData.Label,selected:c.observable(!1),disabled:!!f.find(Z["settings-disabled"],function(b){return b&&b===a})})},this),this.oViewModelPlace=b("#rl-content #rl-settings-subscreen")},N.prototype.routes=function(){var a=f.find(Z.settings,function(a){return a&&a.__rlSettingsData&&a.__rlSettingsData.IsDefault}),b=a?a.__rlSettingsData.Route:"general",c={subname:/^(.*)$/,normalize_:function(a,c){return c.subname=V.isUnd(c.subname)?b:V.pString(c.subname),[c.subname]}};return[["{subname}/",c],["{subname}",c],["",c]]},f.extend(O.prototype,m.prototype),O.prototype.onShow=function(){gb.setTitle("")},f.extend(P.prototype,N.prototype),P.prototype.onShow=function(){gb.setTitle("")},f.extend(Q.prototype,k.prototype),Q.prototype.oSettings=null,Q.prototype.oPlugins=null,Q.prototype.oLocal=null,Q.prototype.oLink=null,Q.prototype.oSubs={},Q.prototype.download=function(b){var c=null,d=null,e=navigator.userAgent.toLowerCase();return e&&(e.indexOf("chrome")>-1||e.indexOf("chrome")>-1)&&(c=document.createElement("a"),c.href=b,document.createEvent&&(d=document.createEvent("MouseEvents"),d&&d.initEvent&&c.dispatchEvent))?(d.initEvent("click",!0,!0),c.dispatchEvent(d),!0):(Y.bMobileDevice?(a.open(b,"_self"),a.focus()):this.iframe.attr("src",b),!0)},Q.prototype.link=function(){return null===this.oLink&&(this.oLink=new g),this.oLink},Q.prototype.local=function(){return null===this.oLocal&&(this.oLocal=new j),this.oLocal},Q.prototype.settingsGet=function(a){return null===this.oSettings&&(this.oSettings=V.isNormal(ab)?ab:{}),V.isUnd(this.oSettings[a])?null:this.oSettings[a]},Q.prototype.settingsSet=function(a,b){null===this.oSettings&&(this.oSettings=V.isNormal(ab)?ab:{}),this.oSettings[a]=b},Q.prototype.setTitle=function(b){b=(V.isNormal(b)&&00&&0===d.length&&(d=b(a,0,m)),h=!0,k=m);break;case">":h&&(l=m,e=b(a,k+1,l-k-1),a=c(a,"",k,l-k+1),l=0,m=0,k=0,h=!1);break;case"(":g||h||i||(i=!0,k=m);break;case")":i&&(l=m,f=b(a,k+1,l-k-1),a=c(a,"",k,l-k+1),l=0,m=0,k=0,i=!1);break;case"\\":m++}m++}return 0===e.length&&(j=a.match(/[^@\s]+@\S+/i),j&&j[0]?e=j[0]:d=a),e.length>0&&0===d.length&&0===f.length&&(d=a.replace(e,"")),e=V.trim(e).replace(/^[<]+/,"").replace(/[>]+$/,""),d=V.trim(d).replace(/^["']+/,"").replace(/["']+$/,""),f=V.trim(f).replace(/^[(]+/,"").replace(/[)]+$/,""),d=d.replace(/\\\\(.)/,"$1"),f=f.replace(/\\\\(.)/,"$1"),this.name=d,this.email=e,this.clearDuplicateName(),!0},o.prototype.inputoTagLine=function(){return 0 (new a.Date).getTime()-l),n&&i.oRequests[n]&&(i.oRequests[n].__aborted&&(e="abort"),i.oRequests[n]=null),i.defaultResponse(c,n,e,b,f,d)}),n&&0 } - */ - Utils = {}, - - /** - * @type {Object. } - */ - Plugins = {}, - - /** - * @type {Object. } - */ - Base64 = {}, - - /** - * @type {Object} - */ - Globals = {}, - - /** - * @type {Object} - */ - ViewModels = { - 'settings': [], - 'settings-removed': [], - 'settings-disabled': [] - }, - - /** - * @type {Array} - */ - BootstrapDropdowns = [], - - /** - * @type {*} - */ - kn = null, - - /** - * @type {Object} - */ - AppData = window['rainloopAppData'] || {}, - - /** - * @type {Object} - */ - I18n = window['rainloopI18N'] || {}, - - $html = $('html'), - -// $body = $('body'), - - $window = $(window), - - $document = $(window.document), - - NotificationClass = window.Notification && window.Notification.requestPermission ? window.Notification : null + +'use strict'; + +var + /** + * @type {Object} + */ + Consts = {}, + + /** + * @type {Object} + */ + Enums = {}, + + /** + * @type {Object} + */ + NotificationI18N = {}, + + /** + * @type {Object. } + */ + Utils = {}, + + /** + * @type {Object. } + */ + Plugins = {}, + + /** + * @type {Object. } + */ + Base64 = {}, + + /** + * @type {Object} + */ + Globals = {}, + + /** + * @type {Object} + */ + ViewModels = { + 'settings': [], + 'settings-removed': [], + 'settings-disabled': [] + }, + + /** + * @type {Array} + */ + BootstrapDropdowns = [], + + /** + * @type {*} + */ + kn = null, + + /** + * @type {Object} + */ + AppData = window['rainloopAppData'] || {}, + + /** + * @type {Object} + */ + I18n = window['rainloopI18N'] || {}, + + $html = $('html'), + +// $body = $('body'), + + $window = $(window), + + $document = $(window.document), + + NotificationClass = window.Notification && window.Notification.requestPermission ? window.Notification : null ; -/*jshint onevar: false*/ -/** - * @type {?RainLoopApp} - */ -var - RL = null, - - $proxyDiv = $('') -; -/*jshint onevar: true*/ +/*jshint onevar: false*/ +/** + * @type {?RainLoopApp} + */ +var + RL = null, + + $proxyDiv = $('') +; +/*jshint onevar: true*/ -/** - * @type {?} - */ -Globals.now = (new Date()).getTime(); - -/** - * @type {?} - */ -Globals.momentTrigger = ko.observable(true); - -/** - * @type {?} - */ -Globals.dropdownVisibility = ko.observable(false).extend({'rateLimit': 0}); - -/** - * @type {?} - */ -Globals.langChangeTrigger = ko.observable(true); - -/** - * @type {number} - */ -Globals.iAjaxErrorCount = 0; - -/** - * @type {number} - */ -Globals.iTokenErrorCount = 0; - -/** - * @type {number} - */ -Globals.iMessageBodyCacheCount = 0; - -/** - * @type {boolean} - */ -Globals.bUnload = false; - -/** - * @type {string} - */ -Globals.sUserAgent = (navigator.userAgent || '').toLowerCase(); - -/** - * @type {boolean} - */ -Globals.bIsiOSDevice = -1 < Globals.sUserAgent.indexOf('iphone') || -1 < Globals.sUserAgent.indexOf('ipod') || -1 < Globals.sUserAgent.indexOf('ipad'); - -/** - * @type {boolean} - */ -Globals.bIsAndroidDevice = -1 < Globals.sUserAgent.indexOf('android'); - -/** - * @type {boolean} - */ -Globals.bMobileDevice = Globals.bIsiOSDevice || Globals.bIsAndroidDevice; - -/** - * @type {boolean} - */ -Globals.bDisableNanoScroll = Globals.bMobileDevice; - -/** - * @type {boolean} - */ -Globals.bAllowPdfPreview = !Globals.bMobileDevice; - -/** - * @type {boolean} - */ -Globals.bAnimationSupported = !Globals.bMobileDevice && $html.hasClass('csstransitions'); - -/** - * @type {string} - */ -Globals.sAnimationType = ''; - -/** - * @type {Object} - */ -Globals.oHtmlEditorDefaultConfig = { - 'title': false, - 'stylesSet': false, - 'customConfig': '', - 'contentsCss': '', - 'toolbarGroups': [ - {name: 'spec'}, - {name: 'styles'}, - {name: 'basicstyles', groups: ['basicstyles', 'cleanup']}, - {name: 'colors'}, - {name: 'paragraph', groups: ['list', 'indent', 'blocks', 'align']}, - {name: 'links'}, - {name: 'insert'}, - {name: 'others'} -// {name: 'document', groups: ['mode', 'document', 'doctools']} - ], - - 'removePlugins': 'contextmenu', //blockquote - 'removeButtons': 'Format,Undo,Redo,Cut,Copy,Paste,Anchor,Strike,Subscript,Superscript,Image,SelectAll', - 'removeDialogTabs': 'link:advanced;link:target;image:advanced', - - 'extraPlugins': 'plain', - - 'allowedContent': true, - 'autoParagraph': false, - - 'enterMode': window.CKEDITOR.ENTER_BR, - 'shiftEnterMode': window.CKEDITOR.ENTER_BR, - - 'font_defaultLabel': 'Arial', - 'fontSize_defaultLabel': '13', - 'fontSize_sizes': '10/10px;12/12px;13/13px;14/14px;16/16px;18/18px;20/20px;24/24px;28/28px;36/36px;48/48px' -}; - -/** - * @type {Object} - */ -Globals.oHtmlEditorLangsMap = { - 'de': 'de', - 'es': 'es', - 'fr': 'fr', - 'hu': 'hu', - 'is': 'is', - 'it': 'it', - 'ko': 'ko', - 'ko-kr': 'ko', - 'lv': 'lv', - 'nl': 'nl', - 'no': 'no', - 'pl': 'pl', - 'pt': 'pt', - 'pt-pt': 'pt', - 'pt-br': 'pt-br', - 'ru': 'ru', - 'ro': 'ro', - 'zh': 'zh', - 'zh-cn': 'zh-cn' -}; - -if (Globals.bAllowPdfPreview && navigator && navigator.mimeTypes) -{ - Globals.bAllowPdfPreview = !!_.find(navigator.mimeTypes, function (oType) { - return oType && 'application/pdf' === oType.type; - }); -} +/** + * @type {?} + */ +Globals.now = (new Date()).getTime(); -Consts.Defaults = {}; -Consts.Values = {}; -Consts.DataImages = {}; - -/** - * @const - * @type {number} - */ -Consts.Defaults.MessagesPerPage = 20; - -/** - * @const - * @type {number} - */ -Consts.Defaults.ContactsPerPage = 50; - -/** - * @const - * @type {Array} - */ -Consts.Defaults.MessagesPerPageArray = [10, 20, 30, 50, 100/*, 150, 200, 300*/]; - -/** - * @const - * @type {number} - */ -Consts.Defaults.DefaultAjaxTimeout = 30000; - -/** - * @const - * @type {number} - */ -Consts.Defaults.SearchAjaxTimeout = 300000; - -/** - * @const - * @type {number} - */ -Consts.Defaults.SendMessageAjaxTimeout = 300000; - -/** - * @const - * @type {number} - */ -Consts.Defaults.SaveMessageAjaxTimeout = 200000; - -/** - * @const - * @type {number} - */ -Consts.Defaults.ContactsSyncAjaxTimeout = 200000; - -/** - * @const - * @type {string} - */ -Consts.Values.UnuseOptionValue = '__UNUSE__'; - -/** - * @const - * @type {string} - */ -Consts.Values.ClientSideCookieIndexName = 'rlcsc'; - -/** - * @const - * @type {number} - */ -Consts.Values.ImapDefaulPort = 143; - -/** - * @const - * @type {number} - */ -Consts.Values.ImapDefaulSecurePort = 993; - -/** - * @const - * @type {number} - */ -Consts.Values.SmtpDefaulPort = 25; - -/** - * @const - * @type {number} - */ -Consts.Values.SmtpDefaulSecurePort = 465; - -/** - * @const - * @type {number} - */ -Consts.Values.MessageBodyCacheLimit = 15; - -/** - * @const - * @type {number} - */ -Consts.Values.AjaxErrorLimit = 7; - -/** - * @const - * @type {number} - */ -Consts.Values.TokenErrorLimit = 10; - -/** - * @const - * @type {string} - */ -Consts.DataImages.UserDotPic = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIW2P8DwQACgAD/il4QJ8AAAAASUVORK5CYII='; - -/** - * @const - * @type {string} - */ -Consts.DataImages.TranspPic = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIW2NkAAIAAAoAAggA9GkAAAAASUVORK5CYII='; +/** + * @type {?} + */ +Globals.momentTrigger = ko.observable(true); -/** - * @enum {string} - */ -Enums.StorageResultType = { - 'Success': 'success', - 'Abort': 'abort', - 'Error': 'error', - 'Unload': 'unload' -}; - -/** - * @enum {number} - */ -Enums.State = { - 'Empty': 10, - 'Login': 20, - 'Auth': 30 -}; - -/** - * @enum {number} - */ -Enums.StateType = { - 'Webmail': 0, - 'Admin': 1 -}; - -/** - * @enum {string} - */ -Enums.KeyState = { - 'All': 'all', - 'None': 'none', - 'ContactList': 'contact-list', - 'MessageList': 'message-list', - 'FolderList': 'folder-list', - 'MessageView': 'message-view', - 'Compose': 'compose', - 'Settings': 'settings', - 'Menu': 'menu', - 'PopupComposeOpenPGP': 'compose-open-pgp', - 'PopupKeyboardShortcutsHelp': 'popup-keyboard-shortcuts-help', - 'PopupAsk': 'popup-ask' -}; - -/** - * @enum {number} - */ -Enums.FolderType = { - 'Inbox': 10, - 'SentItems': 11, - 'Draft': 12, - 'Trash': 13, - 'Spam': 14, - 'Archive': 15, - 'NotSpam': 80, - 'User': 99 -}; - -/** - * @enum {string} - */ -Enums.LoginSignMeTypeAsString = { - 'DefaultOff': 'defaultoff', - 'DefaultOn': 'defaulton', - 'Unused': 'unused' -}; - -/** - * @enum {number} - */ -Enums.LoginSignMeType = { - 'DefaultOff': 0, - 'DefaultOn': 1, - 'Unused': 2 -}; - -/** - * @enum {string} - */ -Enums.ComposeType = { - 'Empty': 'empty', - 'Reply': 'reply', - 'ReplyAll': 'replyall', - 'Forward': 'forward', - 'ForwardAsAttachment': 'forward-as-attachment', - 'Draft': 'draft', - 'EditAsNew': 'editasnew' -}; - -/** - * @enum {number} - */ -Enums.UploadErrorCode = { - 'Normal': 0, - 'FileIsTooBig': 1, - 'FilePartiallyUploaded': 2, - 'FileNoUploaded': 3, - 'MissingTempFolder': 4, - 'FileOnSaveingError': 5, - 'FileType': 98, - 'Unknown': 99 -}; - -/** - * @enum {number} - */ -Enums.SetSystemFoldersNotification = { - 'None': 0, - 'Sent': 1, - 'Draft': 2, - 'Spam': 3, - 'Trash': 4, - 'Archive': 5 -}; - -/** - * @enum {number} - */ -Enums.ClientSideKeyName = { - 'FoldersLashHash': 0, - 'MessagesInboxLastHash': 1, - 'MailBoxListSize': 2, - 'ExpandedFolders': 3, - 'FolderListSize': 4 -}; - -/** - * @enum {number} - */ -Enums.EventKeyCode = { - 'Backspace': 8, - 'Tab': 9, - 'Enter': 13, - 'Esc': 27, - 'PageUp': 33, - 'PageDown': 34, - 'Left': 37, - 'Right': 39, - 'Up': 38, - 'Down': 40, - 'End': 35, - 'Home': 36, - 'Space': 32, - 'Insert': 45, - 'Delete': 46, - 'A': 65, - 'S': 83 -}; - -/** - * @enum {number} - */ -Enums.MessageSetAction = { - 'SetSeen': 0, - 'UnsetSeen': 1, - 'SetFlag': 2, - 'UnsetFlag': 3 -}; - -/** - * @enum {number} - */ -Enums.MessageSelectAction = { - 'All': 0, - 'None': 1, - 'Invert': 2, - 'Unseen': 3, - 'Seen': 4, - 'Flagged': 5, - 'Unflagged': 6 -}; - -/** - * @enum {number} - */ -Enums.DesktopNotifications = { - 'Allowed': 0, - 'NotAllowed': 1, - 'Denied': 2, - 'NotSupported': 9 -}; - -/** - * @enum {number} - */ -Enums.MessagePriority = { - 'Low': 5, - 'Normal': 3, - 'High': 1 -}; - -/** - * @enum {string} - */ -Enums.EditorDefaultType = { - 'Html': 'Html', - 'Plain': 'Plain' -}; - -/** - * @enum {string} - */ -Enums.CustomThemeType = { - 'Light': 'Light', - 'Dark': 'Dark' -}; - -/** - * @enum {number} - */ -Enums.ServerSecure = { - 'None': 0, - 'SSL': 1, - 'TLS': 2 -}; - -/** - * @enum {number} - */ -Enums.SearchDateType = { - 'All': -1, - 'Days3': 3, - 'Days7': 7, - 'Month': 30 -}; - -/** - * @enum {number} - */ -Enums.EmailType = { - 'Defailt': 0, - 'Facebook': 1, - 'Google': 2 -}; - -/** - * @enum {number} - */ -Enums.SaveSettingsStep = { - 'Animate': -2, - 'Idle': -1, - 'TrueResult': 1, - 'FalseResult': 0 -}; - -/** - * @enum {string} - */ -Enums.InterfaceAnimation = { - 'None': 'None', - 'Normal': 'Normal', - 'Full': 'Full' -}; - -/** - * @enum {number} - */ -Enums.Layout = { - 'NoPreview': 0, - 'SidePreview': 1, - 'BottomPreview': 2 -}; - -/** - * @enum {number} - */ -Enums.SignedVerifyStatus = { - 'UnknownPublicKeys': -4, - 'UnknownPrivateKey': -3, - 'Unverified': -2, - 'Error': -1, - 'None': 0, - 'Success': 1 -}; - -/** - * @enum {number} - */ -Enums.ContactPropertyType = { - - 'Unknown': 0, - - 'FullName': 10, - - 'FirstName': 15, - 'LastName': 16, - 'MiddleName': 16, - 'Nick': 18, - - 'NamePrefix': 20, - 'NameSuffix': 21, - - 'Email': 30, - 'Phone': 31, - 'Web': 32, - - 'Birthday': 40, - - 'Facebook': 90, - 'Skype': 91, - 'GitHub': 92, - - 'Note': 110, - - 'Custom': 250 -}; - -/** - * @enum {number} - */ -Enums.Notification = { - 'InvalidToken': 101, - 'AuthError': 102, - 'AccessError': 103, - 'ConnectionError': 104, - 'CaptchaError': 105, - 'SocialFacebookLoginAccessDisable': 106, - 'SocialTwitterLoginAccessDisable': 107, - 'SocialGoogleLoginAccessDisable': 108, - 'DomainNotAllowed': 109, - 'AccountNotAllowed': 110, - - 'AccountTwoFactorAuthRequired': 120, - 'AccountTwoFactorAuthError': 121, - - 'CouldNotSaveNewPassword': 130, - 'CurrentPasswordIncorrect': 131, - 'NewPasswordShort': 132, - 'NewPasswordWeak': 133, - 'NewPasswordForbidden': 134, - - 'ContactsSyncError': 140, - - 'CantGetMessageList': 201, - 'CantGetMessage': 202, - 'CantDeleteMessage': 203, - 'CantMoveMessage': 204, - 'CantCopyMessage': 205, - - 'CantSaveMessage': 301, - 'CantSendMessage': 302, - 'InvalidRecipients': 303, - - 'CantCreateFolder': 400, - 'CantRenameFolder': 401, - 'CantDeleteFolder': 402, - 'CantSubscribeFolder': 403, - 'CantUnsubscribeFolder': 404, - 'CantDeleteNonEmptyFolder': 405, - - 'CantSaveSettings': 501, - 'CantSavePluginSettings': 502, - - 'DomainAlreadyExists': 601, - - 'CantInstallPackage': 701, - 'CantDeletePackage': 702, - 'InvalidPluginPackage': 703, - 'UnsupportedPluginPackage': 704, - - 'LicensingServerIsUnavailable': 710, - 'LicensingExpired': 711, - 'LicensingBanned': 712, - - 'DemoSendMessageError': 750, - - 'AccountAlreadyExists': 801, - - 'MailServerError': 901, - 'ClientViewError': 902, - 'UnknownNotification': 999, - 'UnknownError': 999 -}; +/** + * @type {?} + */ +Globals.dropdownVisibility = ko.observable(false).extend({'rateLimit': 0}); -Utils.trim = $.trim; -Utils.inArray = $.inArray; -Utils.isArray = _.isArray; -Utils.isFunc = _.isFunction; -Utils.isUnd = _.isUndefined; -Utils.isNull = _.isNull; -Utils.emptyFunction = function () {}; - -/** - * @param {*} oValue - * @return {boolean} - */ -Utils.isNormal = function (oValue) -{ - return !Utils.isUnd(oValue) && !Utils.isNull(oValue); -}; - -Utils.windowResize = _.debounce(function (iTimeout) { - if (Utils.isUnd(iTimeout)) - { - $window.resize(); - } - else - { - window.setTimeout(function () { - $window.resize(); - }, iTimeout); - } -}, 50); - -/** - * @param {(string|number)} mValue - * @param {boolean=} bIncludeZero - * @return {boolean} - */ -Utils.isPosNumeric = function (mValue, bIncludeZero) -{ - return Utils.isNormal(mValue) ? - ((Utils.isUnd(bIncludeZero) ? true : !!bIncludeZero) ? - (/^[0-9]*$/).test(mValue.toString()) : - (/^[1-9]+[0-9]*$/).test(mValue.toString())) : - false; -}; - -/** - * @param {*} iValue - * @return {number} - */ -Utils.pInt = function (iValue) -{ - return Utils.isNormal(iValue) && '' !== iValue ? window.parseInt(iValue, 10) : 0; -}; - -/** - * @param {*} mValue - * @return {string} - */ -Utils.pString = function (mValue) -{ - return Utils.isNormal(mValue) ? '' + mValue : ''; -}; - -/** - * @param {*} aValue - * @return {boolean} - */ -Utils.isNonEmptyArray = function (aValue) -{ - return Utils.isArray(aValue) && 0 < aValue.length; -}; - -/** - * @param {string} sPath - * @param {*=} oObject - * @param {Object=} oObjectToExportTo - */ -Utils.exportPath = function (sPath, oObject, oObjectToExportTo) -{ - var - part = null, - parts = sPath.split('.'), - cur = oObjectToExportTo || window - ; - - for (; parts.length && (part = parts.shift());) - { - if (!parts.length && !Utils.isUnd(oObject)) - { - cur[part] = oObject; - } - else if (cur[part]) - { - cur = cur[part]; - } - else - { - cur = cur[part] = {}; - } - } -}; - -/** - * @param {Object} oObject - * @param {string} sName - * @param {*} mValue - */ -Utils.pImport = function (oObject, sName, mValue) -{ - oObject[sName] = mValue; -}; - -/** - * @param {Object} oObject - * @param {string} sName - * @param {*} mDefault - * @return {*} - */ -Utils.pExport = function (oObject, sName, mDefault) -{ - return Utils.isUnd(oObject[sName]) ? mDefault : oObject[sName]; -}; - -/** - * @param {string} sText - * @return {string} - */ -Utils.encodeHtml = function (sText) -{ - return Utils.isNormal(sText) ? sText.toString() - .replace(/&/g, '&').replace(//g, '>') - .replace(/"/g, '"').replace(/'/g, ''') : ''; -}; - -/** - * @param {string} sText - * @param {number=} iLen - * @return {string} - */ -Utils.splitPlainText = function (sText, iLen) -{ - var - sPrefix = '', - sSubText = '', - sResult = sText, - iSpacePos = 0, - iNewLinePos = 0 - ; - - iLen = Utils.isUnd(iLen) ? 100 : iLen; - - while (sResult.length > iLen) - { - sSubText = sResult.substring(0, iLen); - iSpacePos = sSubText.lastIndexOf(' '); - iNewLinePos = sSubText.lastIndexOf('\n'); - - if (-1 !== iNewLinePos) - { - iSpacePos = iNewLinePos; - } - - if (-1 === iSpacePos) - { - iSpacePos = iLen; - } - - sPrefix += sSubText.substring(0, iSpacePos) + '\n'; - sResult = sResult.substring(iSpacePos + 1); - } - - return sPrefix + sResult; -}; - -Utils.timeOutAction = (function () { - - var - oTimeOuts = {} - ; - - return function (sAction, fFunction, iTimeOut) - { - if (Utils.isUnd(oTimeOuts[sAction])) - { - oTimeOuts[sAction] = 0; - } - - window.clearTimeout(oTimeOuts[sAction]); - oTimeOuts[sAction] = window.setTimeout(fFunction, iTimeOut); - }; -}()); - -Utils.timeOutActionSecond = (function () { - - var - oTimeOuts = {} - ; - - return function (sAction, fFunction, iTimeOut) - { - if (!oTimeOuts[sAction]) - { - oTimeOuts[sAction] = window.setTimeout(function () { - fFunction(); - oTimeOuts[sAction] = 0; - }, iTimeOut); - } - }; -}()); - -Utils.audio = (function () { - - var - oAudio = false - ; - - return function (sMp3File, sOggFile) { - - if (false === oAudio) - { - if (Globals.bIsiOSDevice) - { - oAudio = null; - } - else - { - var - bCanPlayMp3 = false, - bCanPlayOgg = false, - oAudioLocal = window.Audio ? new window.Audio() : null - ; - - if (oAudioLocal && oAudioLocal.canPlayType && oAudioLocal.play) - { - bCanPlayMp3 = '' !== oAudioLocal.canPlayType('audio/mpeg; codecs="mp3"'); - if (!bCanPlayMp3) - { - bCanPlayOgg = '' !== oAudioLocal.canPlayType('audio/ogg; codecs="vorbis"'); - } - - if (bCanPlayMp3 || bCanPlayOgg) - { - oAudio = oAudioLocal; - oAudio.preload = 'none'; - oAudio.loop = false; - oAudio.autoplay = false; - oAudio.muted = false; - oAudio.src = bCanPlayMp3 ? sMp3File : sOggFile; - } - else - { - oAudio = null; - } - } - else - { - oAudio = null; - } - } - } - - return oAudio; - }; -}()); - -/** - * @param {(Object|null|undefined)} oObject - * @param {string} sProp - * @return {boolean} - */ -Utils.hos = function (oObject, sProp) -{ - return oObject && Object.hasOwnProperty ? Object.hasOwnProperty.call(oObject, sProp) : false; -}; - -/** - * @param {string} sKey - * @param {Object=} oValueList - * @param {string=} sDefaulValue - * @return {string} - */ -Utils.i18n = function (sKey, oValueList, sDefaulValue) -{ - var - sValueName = '', - sResult = Utils.isUnd(I18n[sKey]) ? (Utils.isUnd(sDefaulValue) ? sKey : sDefaulValue) : I18n[sKey] - ; - - if (!Utils.isUnd(oValueList) && !Utils.isNull(oValueList)) - { - for (sValueName in oValueList) - { - if (Utils.hos(oValueList, sValueName)) - { - sResult = sResult.replace('%' + sValueName + '%', oValueList[sValueName]); - } - } - } - - return sResult; -}; - -/** - * @param {Object} oElement - */ -Utils.i18nToNode = function (oElement) -{ - _.defer(function () { - $('.i18n', oElement).each(function () { - var - jqThis = $(this), - sKey = '' - ; - - sKey = jqThis.data('i18n-text'); - if (sKey) - { - jqThis.text(Utils.i18n(sKey)); - } - else - { - sKey = jqThis.data('i18n-html'); - if (sKey) - { - jqThis.html(Utils.i18n(sKey)); - } - - sKey = jqThis.data('i18n-placeholder'); - if (sKey) - { - jqThis.attr('placeholder', Utils.i18n(sKey)); - } - - sKey = jqThis.data('i18n-title'); - if (sKey) - { - jqThis.attr('title', Utils.i18n(sKey)); - } - } - }); - }); -}; - -Utils.i18nToDoc = function () -{ - if (window.rainloopI18N) - { - I18n = window.rainloopI18N || {}; - Utils.i18nToNode($document); - - Globals.langChangeTrigger(!Globals.langChangeTrigger()); - } - - window.rainloopI18N = {}; -}; - -/** - * @param {Function} fCallback - * @param {Object} oScope - * @param {Function=} fLangCallback - */ -Utils.initOnStartOrLangChange = function (fCallback, oScope, fLangCallback) -{ - if (fCallback) - { - fCallback.call(oScope); - } - - if (fLangCallback) - { - Globals.langChangeTrigger.subscribe(function () { - if (fCallback) - { - fCallback.call(oScope); - } - - fLangCallback.call(oScope); - }); - } - else if (fCallback) - { - Globals.langChangeTrigger.subscribe(fCallback, oScope); - } -}; - -/** - * @return {boolean} - */ -Utils.inFocus = function () -{ - var oActiveObj = document.activeElement; - return (oActiveObj && ('INPUT' === oActiveObj.tagName || - 'TEXTAREA' === oActiveObj.tagName || - 'IFRAME' === oActiveObj.tagName || - ('DIV' === oActiveObj.tagName && 'editorHtmlArea' === oActiveObj.className && oActiveObj.contentEditable))); -}; - -Utils.removeInFocus = function () -{ - if (document && document.activeElement && document.activeElement.blur) - { - var oA = $(document.activeElement); - if (oA.is('input') || oA.is('textarea')) - { - document.activeElement.blur(); - } - } -}; - -Utils.removeSelection = function () -{ - if (window && window.getSelection) - { - var oSel = window.getSelection(); - if (oSel && oSel.removeAllRanges) - { - oSel.removeAllRanges(); - } - } - else if (document && document.selection && document.selection.empty) - { - document.selection.empty(); - } -}; - -/** - * @param {string} sPrefix - * @param {string} sSubject - * @param {boolean=} bFixLongSubject = true - * @return {string} - */ -Utils.replySubjectAdd = function (sPrefix, sSubject, bFixLongSubject) -{ - var - oMatch = null, - sResult = Utils.trim(sSubject) - ; - - if (null !== (oMatch = (new window.RegExp('^' + sPrefix + '[\\s]?\\:(.*)$', 'gi')).exec(sSubject)) && !Utils.isUnd(oMatch[1])) - { - sResult = sPrefix + '[2]: ' + oMatch[1]; - } - else if (null !== (oMatch = (new window.RegExp('^(' + sPrefix + '[\\s]?[\\[\\(]?)([\\d]+)([\\]\\)]?[\\s]?\\:.*)$', 'gi')).exec(sSubject)) && - !Utils.isUnd(oMatch[1]) && !Utils.isUnd(oMatch[2]) && !Utils.isUnd(oMatch[3])) - { - sResult = oMatch[1] + (Utils.pInt(oMatch[2]) + 1) + oMatch[3]; - } - else - { - sResult = sPrefix + ': ' + sSubject; - } - - sResult = sResult.replace(/[\s]+/g, ' '); - sResult = (Utils.isUnd(bFixLongSubject) ? true : bFixLongSubject) ? Utils.fixLongSubject(sResult) : sResult; -// sResult = sResult.replace(/^(Re|Fwd)[\s]?\[[\d]+\]:/ig, '$1:'); - return sResult; -}; - -/** - * @param {string} sSubject - * @return {string} - */ -Utils.fixLongSubject = function (sSubject) -{ - var - iCounter = 0, - oMatch = null - ; - - sSubject = Utils.trim(sSubject.replace(/[\s]+/, ' ')); - - do - { - oMatch = /^Re(\[([\d]+)\]|):[\s]{0,3}Re(\[([\d]+)\]|):/ig.exec(sSubject); - if (!oMatch || Utils.isUnd(oMatch[0])) - { - oMatch = null; - } - - if (oMatch) - { - iCounter = 0; - iCounter += Utils.isUnd(oMatch[2]) ? 1 : 0 + Utils.pInt(oMatch[2]); - iCounter += Utils.isUnd(oMatch[4]) ? 1 : 0 + Utils.pInt(oMatch[4]); - - sSubject = sSubject.replace(/^Re(\[[\d]+\]|):[\s]{0,3}Re(\[[\d]+\]|):/gi, 'Re' + (0 < iCounter ? '[' + iCounter + ']' : '') + ':'); - } - - } - while (oMatch); - - sSubject = sSubject.replace(/[\s]+/, ' '); - return sSubject; -}; - -/** - * @param {number} iNum - * @param {number} iDec - * @return {number} - */ -Utils.roundNumber = function (iNum, iDec) -{ - return Math.round(iNum * Math.pow(10, iDec)) / Math.pow(10, iDec); -}; - -/** - * @param {(number|string)} iSizeInBytes - * @return {string} - */ -Utils.friendlySize = function (iSizeInBytes) -{ - iSizeInBytes = Utils.pInt(iSizeInBytes); - - if (iSizeInBytes >= 1073741824) - { - return Utils.roundNumber(iSizeInBytes / 1073741824, 1) + 'GB'; - } - else if (iSizeInBytes >= 1048576) - { - return Utils.roundNumber(iSizeInBytes / 1048576, 1) + 'MB'; - } - else if (iSizeInBytes >= 1024) - { - return Utils.roundNumber(iSizeInBytes / 1024, 0) + 'KB'; - } - - return iSizeInBytes + 'B'; -}; - -/** - * @param {string} sDesc - */ -Utils.log = function (sDesc) -{ - if (window.console && window.console.log) - { - window.console.log(sDesc); - } -}; - -/** - * @param {number} iCode - * @param {*=} mMessage = '' - * @return {string} - */ -Utils.getNotification = function (iCode, mMessage) -{ - iCode = Utils.pInt(iCode); - if (Enums.Notification.ClientViewError === iCode && mMessage) - { - return mMessage; - } - - return Utils.isUnd(NotificationI18N[iCode]) ? '' : NotificationI18N[iCode]; -}; - -Utils.initNotificationLanguage = function () -{ - NotificationI18N[Enums.Notification.InvalidToken] = Utils.i18n('NOTIFICATIONS/INVALID_TOKEN'); - NotificationI18N[Enums.Notification.AuthError] = Utils.i18n('NOTIFICATIONS/AUTH_ERROR'); - NotificationI18N[Enums.Notification.AccessError] = Utils.i18n('NOTIFICATIONS/ACCESS_ERROR'); - NotificationI18N[Enums.Notification.ConnectionError] = Utils.i18n('NOTIFICATIONS/CONNECTION_ERROR'); - NotificationI18N[Enums.Notification.CaptchaError] = Utils.i18n('NOTIFICATIONS/CAPTCHA_ERROR'); - NotificationI18N[Enums.Notification.SocialFacebookLoginAccessDisable] = Utils.i18n('NOTIFICATIONS/SOCIAL_FACEBOOK_LOGIN_ACCESS_DISABLE'); - NotificationI18N[Enums.Notification.SocialTwitterLoginAccessDisable] = Utils.i18n('NOTIFICATIONS/SOCIAL_TWITTER_LOGIN_ACCESS_DISABLE'); - NotificationI18N[Enums.Notification.SocialGoogleLoginAccessDisable] = Utils.i18n('NOTIFICATIONS/SOCIAL_GOOGLE_LOGIN_ACCESS_DISABLE'); - NotificationI18N[Enums.Notification.DomainNotAllowed] = Utils.i18n('NOTIFICATIONS/DOMAIN_NOT_ALLOWED'); - NotificationI18N[Enums.Notification.AccountNotAllowed] = Utils.i18n('NOTIFICATIONS/ACCOUNT_NOT_ALLOWED'); - - NotificationI18N[Enums.Notification.AccountTwoFactorAuthRequired] = Utils.i18n('NOTIFICATIONS/ACCOUNT_TWO_FACTOR_AUTH_REQUIRED'); - NotificationI18N[Enums.Notification.AccountTwoFactorAuthError] = Utils.i18n('NOTIFICATIONS/ACCOUNT_TWO_FACTOR_AUTH_ERROR'); - - NotificationI18N[Enums.Notification.CouldNotSaveNewPassword] = Utils.i18n('NOTIFICATIONS/COULD_NOT_SAVE_NEW_PASSWORD'); - NotificationI18N[Enums.Notification.CurrentPasswordIncorrect] = Utils.i18n('NOTIFICATIONS/CURRENT_PASSWORD_INCORRECT'); - NotificationI18N[Enums.Notification.NewPasswordShort] = Utils.i18n('NOTIFICATIONS/NEW_PASSWORD_SHORT'); - NotificationI18N[Enums.Notification.NewPasswordWeak] = Utils.i18n('NOTIFICATIONS/NEW_PASSWORD_WEAK'); - NotificationI18N[Enums.Notification.NewPasswordForbidden] = Utils.i18n('NOTIFICATIONS/NEW_PASSWORD_FORBIDDENT'); - - NotificationI18N[Enums.Notification.ContactsSyncError] = Utils.i18n('NOTIFICATIONS/CONTACTS_SYNC_ERROR'); - - NotificationI18N[Enums.Notification.CantGetMessageList] = Utils.i18n('NOTIFICATIONS/CANT_GET_MESSAGE_LIST'); - NotificationI18N[Enums.Notification.CantGetMessage] = Utils.i18n('NOTIFICATIONS/CANT_GET_MESSAGE'); - NotificationI18N[Enums.Notification.CantDeleteMessage] = Utils.i18n('NOTIFICATIONS/CANT_DELETE_MESSAGE'); - NotificationI18N[Enums.Notification.CantMoveMessage] = Utils.i18n('NOTIFICATIONS/CANT_MOVE_MESSAGE'); - NotificationI18N[Enums.Notification.CantCopyMessage] = Utils.i18n('NOTIFICATIONS/CANT_MOVE_MESSAGE'); - - NotificationI18N[Enums.Notification.CantSaveMessage] = Utils.i18n('NOTIFICATIONS/CANT_SAVE_MESSAGE'); - NotificationI18N[Enums.Notification.CantSendMessage] = Utils.i18n('NOTIFICATIONS/CANT_SEND_MESSAGE'); - NotificationI18N[Enums.Notification.InvalidRecipients] = Utils.i18n('NOTIFICATIONS/INVALID_RECIPIENTS'); - - NotificationI18N[Enums.Notification.CantCreateFolder] = Utils.i18n('NOTIFICATIONS/CANT_CREATE_FOLDER'); - NotificationI18N[Enums.Notification.CantRenameFolder] = Utils.i18n('NOTIFICATIONS/CANT_RENAME_FOLDER'); - NotificationI18N[Enums.Notification.CantDeleteFolder] = Utils.i18n('NOTIFICATIONS/CANT_DELETE_FOLDER'); - NotificationI18N[Enums.Notification.CantDeleteNonEmptyFolder] = Utils.i18n('NOTIFICATIONS/CANT_DELETE_NON_EMPTY_FOLDER'); - NotificationI18N[Enums.Notification.CantSubscribeFolder] = Utils.i18n('NOTIFICATIONS/CANT_SUBSCRIBE_FOLDER'); - NotificationI18N[Enums.Notification.CantUnsubscribeFolder] = Utils.i18n('NOTIFICATIONS/CANT_UNSUBSCRIBE_FOLDER'); - - NotificationI18N[Enums.Notification.CantSaveSettings] = Utils.i18n('NOTIFICATIONS/CANT_SAVE_SETTINGS'); - NotificationI18N[Enums.Notification.CantSavePluginSettings] = Utils.i18n('NOTIFICATIONS/CANT_SAVE_PLUGIN_SETTINGS'); - - NotificationI18N[Enums.Notification.DomainAlreadyExists] = Utils.i18n('NOTIFICATIONS/DOMAIN_ALREADY_EXISTS'); - - NotificationI18N[Enums.Notification.CantInstallPackage] = Utils.i18n('NOTIFICATIONS/CANT_INSTALL_PACKAGE'); - NotificationI18N[Enums.Notification.CantDeletePackage] = Utils.i18n('NOTIFICATIONS/CANT_DELETE_PACKAGE'); - NotificationI18N[Enums.Notification.InvalidPluginPackage] = Utils.i18n('NOTIFICATIONS/INVALID_PLUGIN_PACKAGE'); - NotificationI18N[Enums.Notification.UnsupportedPluginPackage] = Utils.i18n('NOTIFICATIONS/UNSUPPORTED_PLUGIN_PACKAGE'); - - NotificationI18N[Enums.Notification.LicensingServerIsUnavailable] = Utils.i18n('NOTIFICATIONS/LICENSING_SERVER_IS_UNAVAILABLE'); - NotificationI18N[Enums.Notification.LicensingExpired] = Utils.i18n('NOTIFICATIONS/LICENSING_EXPIRED'); - NotificationI18N[Enums.Notification.LicensingBanned] = Utils.i18n('NOTIFICATIONS/LICENSING_BANNED'); - - NotificationI18N[Enums.Notification.DemoSendMessageError] = Utils.i18n('NOTIFICATIONS/DEMO_SEND_MESSAGE_ERROR'); - - NotificationI18N[Enums.Notification.AccountAlreadyExists] = Utils.i18n('NOTIFICATIONS/ACCOUNT_ALREADY_EXISTS'); - - NotificationI18N[Enums.Notification.MailServerError] = Utils.i18n('NOTIFICATIONS/MAIL_SERVER_ERROR'); - NotificationI18N[Enums.Notification.UnknownNotification] = Utils.i18n('NOTIFICATIONS/UNKNOWN_ERROR'); - NotificationI18N[Enums.Notification.UnknownError] = Utils.i18n('NOTIFICATIONS/UNKNOWN_ERROR'); -}; - -/** - * @param {*} mCode - * @return {string} - */ -Utils.getUploadErrorDescByCode = function (mCode) -{ - var sResult = ''; - switch (Utils.pInt(mCode)) { - case Enums.UploadErrorCode.FileIsTooBig: - sResult = Utils.i18n('UPLOAD/ERROR_FILE_IS_TOO_BIG'); - break; - case Enums.UploadErrorCode.FilePartiallyUploaded: - sResult = Utils.i18n('UPLOAD/ERROR_FILE_PARTIALLY_UPLOADED'); - break; - case Enums.UploadErrorCode.FileNoUploaded: - sResult = Utils.i18n('UPLOAD/ERROR_NO_FILE_UPLOADED'); - break; - case Enums.UploadErrorCode.MissingTempFolder: - sResult = Utils.i18n('UPLOAD/ERROR_MISSING_TEMP_FOLDER'); - break; - case Enums.UploadErrorCode.FileOnSaveingError: - sResult = Utils.i18n('UPLOAD/ERROR_ON_SAVING_FILE'); - break; - case Enums.UploadErrorCode.FileType: - sResult = Utils.i18n('UPLOAD/ERROR_FILE_TYPE'); - break; - default: - sResult = Utils.i18n('UPLOAD/ERROR_UNKNOWN'); - break; - } - - return sResult; -}; - -/** - * @param {?} oObject - * @param {string} sMethodName - * @param {Array=} aParameters - * @param {number=} nDelay - */ -Utils.delegateRun = function (oObject, sMethodName, aParameters, nDelay) -{ - if (oObject && oObject[sMethodName]) - { - nDelay = Utils.pInt(nDelay); - if (0 >= nDelay) - { - oObject[sMethodName].apply(oObject, Utils.isArray(aParameters) ? aParameters : []); - } - else - { - _.delay(function () { - oObject[sMethodName].apply(oObject, Utils.isArray(aParameters) ? aParameters : []); - }, nDelay); - } - } -}; - -/** - * @param {?} oEvent - */ -Utils.killCtrlAandS = function (oEvent) -{ - oEvent = oEvent || window.event; - if (oEvent && oEvent.ctrlKey && !oEvent.shiftKey && !oEvent.altKey) - { - var - oSender = oEvent.target || oEvent.srcElement, - iKey = oEvent.keyCode || oEvent.which - ; - - if (iKey === Enums.EventKeyCode.S) - { - oEvent.preventDefault(); - return; - } - - if (oSender && oSender.tagName && oSender.tagName.match(/INPUT|TEXTAREA/i)) - { - return; - } - - if (iKey === Enums.EventKeyCode.A) - { - if (window.getSelection) - { - window.getSelection().removeAllRanges(); - } - else if (window.document.selection && window.document.selection.clear) - { - window.document.selection.clear(); - } - - oEvent.preventDefault(); - } - } -}; - -/** - * @param {(Object|null|undefined)} oContext - * @param {Function} fExecute - * @param {(Function|boolean|null)=} fCanExecute - * @return {Function} - */ -Utils.createCommand = function (oContext, fExecute, fCanExecute) -{ - var - fResult = fExecute ? function () { - if (fResult.canExecute && fResult.canExecute()) - { - fExecute.apply(oContext, Array.prototype.slice.call(arguments)); - } - return false; - } : function () {} - ; - - fResult.enabled = ko.observable(true); - - fCanExecute = Utils.isUnd(fCanExecute) ? true : fCanExecute; - if (Utils.isFunc(fCanExecute)) - { - fResult.canExecute = ko.computed(function () { - return fResult.enabled() && fCanExecute.call(oContext); - }); - } - else - { - fResult.canExecute = ko.computed(function () { - return fResult.enabled() && !!fCanExecute; - }); - } - - return fResult; -}; - -/** - * @param {Object} oData - */ -Utils.initDataConstructorBySettings = function (oData) -{ - oData.editorDefaultType = ko.observable(Enums.EditorDefaultType.Html); - oData.showImages = ko.observable(false); - oData.interfaceAnimation = ko.observable(Enums.InterfaceAnimation.Full); - oData.contactsAutosave = ko.observable(false); - - Globals.sAnimationType = Enums.InterfaceAnimation.Full; - - oData.allowThemes = ko.observable(true); - oData.allowCustomLogin = ko.observable(false); - oData.allowLanguagesOnSettings = ko.observable(true); - oData.allowLanguagesOnLogin = ko.observable(true); - - oData.desktopNotifications = ko.observable(false); - oData.useThreads = ko.observable(true); - oData.replySameFolder = ko.observable(true); - oData.useCheckboxesInList = ko.observable(true); - - oData.layout = ko.observable(Enums.Layout.SidePreview); - oData.usePreviewPane = ko.computed(function () { - return Enums.Layout.NoPreview !== oData.layout(); - }); - - oData.interfaceAnimation.subscribe(function (sValue) { - if (Globals.bMobileDevice || sValue === Enums.InterfaceAnimation.None) - { - $html.removeClass('rl-anim rl-anim-full').addClass('no-rl-anim'); - - Globals.sAnimationType = Enums.InterfaceAnimation.None; - } - else - { - switch (sValue) - { - case Enums.InterfaceAnimation.Full: - $html.removeClass('no-rl-anim').addClass('rl-anim rl-anim-full'); - Globals.sAnimationType = sValue; - break; - case Enums.InterfaceAnimation.Normal: - $html.removeClass('no-rl-anim rl-anim-full').addClass('rl-anim'); - Globals.sAnimationType = sValue; - break; - } - } - }); - - oData.interfaceAnimation.valueHasMutated(); - - oData.desktopNotificationsPermisions = ko.computed(function () { - oData.desktopNotifications(); - var iResult = Enums.DesktopNotifications.NotSupported; - if (NotificationClass && NotificationClass.permission) - { - switch (NotificationClass.permission.toLowerCase()) - { - case 'granted': - iResult = Enums.DesktopNotifications.Allowed; - break; - case 'denied': - iResult = Enums.DesktopNotifications.Denied; - break; - case 'default': - iResult = Enums.DesktopNotifications.NotAllowed; - break; - } - } - else if (window.webkitNotifications && window.webkitNotifications.checkPermission) - { - iResult = window.webkitNotifications.checkPermission(); - } - - return iResult; - }); - - oData.useDesktopNotifications = ko.computed({ - 'read': function () { - return oData.desktopNotifications() && - Enums.DesktopNotifications.Allowed === oData.desktopNotificationsPermisions(); - }, - 'write': function (bValue) { - if (bValue) - { - var iPermission = oData.desktopNotificationsPermisions(); - if (Enums.DesktopNotifications.Allowed === iPermission) - { - oData.desktopNotifications(true); - } - else if (Enums.DesktopNotifications.NotAllowed === iPermission) - { - NotificationClass.requestPermission(function () { - oData.desktopNotifications.valueHasMutated(); - if (Enums.DesktopNotifications.Allowed === oData.desktopNotificationsPermisions()) - { - if (oData.desktopNotifications()) - { - oData.desktopNotifications.valueHasMutated(); - } - else - { - oData.desktopNotifications(true); - } - } - else - { - if (oData.desktopNotifications()) - { - oData.desktopNotifications(false); - } - else - { - oData.desktopNotifications.valueHasMutated(); - } - } - }); - } - else - { - oData.desktopNotifications(false); - } - } - else - { - oData.desktopNotifications(false); - } - } - }); - - oData.language = ko.observable(''); - oData.languages = ko.observableArray([]); - - oData.mainLanguage = ko.computed({ - 'read': oData.language, - 'write': function (sValue) { - if (sValue !== oData.language()) - { - if (-1 < Utils.inArray(sValue, oData.languages())) - { - oData.language(sValue); - } - else if (0 < oData.languages().length) - { - oData.language(oData.languages()[0]); - } - } - else - { - oData.language.valueHasMutated(); - } - } - }); - - oData.theme = ko.observable(''); - oData.themes = ko.observableArray([]); - - oData.mainTheme = ko.computed({ - 'read': oData.theme, - 'write': function (sValue) { - if (sValue !== oData.theme()) - { - var aThemes = oData.themes(); - if (-1 < Utils.inArray(sValue, aThemes)) - { - oData.theme(sValue); - } - else if (0 < aThemes.length) - { - oData.theme(aThemes[0]); - } - } - else - { - oData.theme.valueHasMutated(); - } - } - }); - - oData.allowAdditionalAccounts = ko.observable(false); - oData.allowIdentities = ko.observable(false); - oData.allowGravatar = ko.observable(false); - oData.determineUserLanguage = ko.observable(false); - - oData.messagesPerPage = ko.observable(Consts.Defaults.MessagesPerPage);//.extend({'throttle': 200}); - - oData.mainMessagesPerPage = oData.messagesPerPage; - oData.mainMessagesPerPage = ko.computed({ - 'read': oData.messagesPerPage, - 'write': function (iValue) { - if (-1 < Utils.inArray(Utils.pInt(iValue), Consts.Defaults.MessagesPerPageArray)) - { - if (iValue !== oData.messagesPerPage()) - { - oData.messagesPerPage(iValue); - } - } - else - { - oData.messagesPerPage.valueHasMutated(); - } - } - }); - - oData.facebookEnable = ko.observable(false); - oData.facebookAppID = ko.observable(''); - oData.facebookAppSecret = ko.observable(''); - - oData.twitterEnable = ko.observable(false); - oData.twitterConsumerKey = ko.observable(''); - oData.twitterConsumerSecret = ko.observable(''); - - oData.googleEnable = ko.observable(false); - oData.googleClientID = ko.observable(''); - oData.googleClientSecret = ko.observable(''); - - oData.dropboxEnable = ko.observable(false); - oData.dropboxApiKey = ko.observable(''); - - oData.contactsIsAllowed = ko.observable(false); -}; - -/** - * @param {{moment:Function}} oObject - */ -Utils.createMomentDate = function (oObject) -{ - if (Utils.isUnd(oObject.moment)) - { - oObject.moment = ko.observable(moment()); - } - - return ko.computed(function () { - Globals.momentTrigger(); - return this.moment().fromNow(); - }, oObject); -}; - -/** - * @param {{moment:Function, momentDate:Function}} oObject - */ -Utils.createMomentShortDate = function (oObject) -{ - return ko.computed(function () { - - var - sResult = '', - oMomentNow = moment(), - oMoment = this.moment(), - sMomentDate = this.momentDate() - ; - - if (4 >= oMomentNow.diff(oMoment, 'hours')) - { - sResult = sMomentDate; - } - else if (oMomentNow.format('L') === oMoment.format('L')) - { - sResult = Utils.i18n('MESSAGE_LIST/TODAY_AT', { - 'TIME': oMoment.format('LT') - }); - } - else if (oMomentNow.clone().subtract('days', 1).format('L') === oMoment.format('L')) - { - sResult = Utils.i18n('MESSAGE_LIST/YESTERDAY_AT', { - 'TIME': oMoment.format('LT') - }); - } - else if (oMomentNow.year() === oMoment.year()) - { - sResult = oMoment.format('D MMM.'); - } - else - { - sResult = oMoment.format('LL'); - } - - return sResult; - - }, oObject); -}; - -/** - * @param {string} sFullNameHash - * @return {boolean} - */ -Utils.isFolderExpanded = function (sFullNameHash) -{ - var aExpandedList = /** @type {Array|null} */ RL.local().get(Enums.ClientSideKeyName.ExpandedFolders); - return _.isArray(aExpandedList) && -1 !== _.indexOf(aExpandedList, sFullNameHash); -}; - -/** - * @param {string} sFullNameHash - * @param {boolean} bExpanded - */ -Utils.setExpandedFolder = function (sFullNameHash, bExpanded) -{ - var aExpandedList = /** @type {Array|null} */ RL.local().get(Enums.ClientSideKeyName.ExpandedFolders); - if (!_.isArray(aExpandedList)) - { - aExpandedList = []; - } - - if (bExpanded) - { - aExpandedList.push(sFullNameHash); - aExpandedList = _.uniq(aExpandedList); - } - else - { - aExpandedList = _.without(aExpandedList, sFullNameHash); - } - - RL.local().set(Enums.ClientSideKeyName.ExpandedFolders, aExpandedList); -}; - -Utils.initLayoutResizer = function (sLeft, sRight, sClientSideKeyName) -{ - var - iMinWidth = 155, - oLeft = $(sLeft), - oRight = $(sRight), - - mLeftWidth = RL.local().get(sClientSideKeyName) || null, - - fSetWidth = function (iWidth) { - if (iWidth) - { - oLeft.css({ - 'width': '' + iWidth + 'px' - }); - - oRight.css({ - 'left': '' + iWidth + 'px' - }); - } - }, - - fDisable = function (bDisable) { - var iWidth = 5; - if (bDisable) - { - oLeft.resizable('disable'); - fSetWidth(iWidth); - } - else - { - oLeft.resizable('enable'); - iWidth = Utils.pInt(RL.local().get(sClientSideKeyName)) || iMinWidth; - fSetWidth(iWidth > iMinWidth ? iWidth : iMinWidth); - } - }, - - fResizeFunction = function (oEvent, oObject) { - if (oObject && oObject.size && oObject.size.width) - { - RL.local().set(sClientSideKeyName, oObject.size.width); - - oRight.css({ - 'left': '' + oObject.size.width + 'px' - }); - } - } - ; - - if (null !== mLeftWidth) - { - fSetWidth(mLeftWidth); - } - - oLeft.resizable({ - 'helper': 'ui-resizable-helper', - 'minWidth': iMinWidth, - 'maxWidth': 350, - 'handles': 'e', - 'stop': fResizeFunction - }); - - RL.sub('left-panel.off', function () { - fDisable(true); - }); - - RL.sub('left-panel.on', function () { - fDisable(false); - }); -}; - -/** - * @param {Object} oMessageTextBody - */ -Utils.initBlockquoteSwitcher = function (oMessageTextBody) -{ - if (oMessageTextBody) - { - var $oList = $('blockquote:not(.rl-bq-switcher)', oMessageTextBody).filter(function () { - return 0 === $(this).parent().closest('blockquote', oMessageTextBody).length; - }); - - if ($oList && 0 < $oList.length) - { - $oList.each(function () { - var $self = $(this), iH = $self.height(); - if (0 === iH || 100 < iH) - { - $self.addClass('rl-bq-switcher hidden-bq'); - $('') - .insertBefore($self) - .click(function () { - $self.toggleClass('hidden-bq'); - Utils.windowResize(); - }) - .after('
') - .before('
') - ; - } - }); - } - } -}; - -/** - * @param {Object} oMessageTextBody - */ -Utils.removeBlockquoteSwitcher = function (oMessageTextBody) -{ - if (oMessageTextBody) - { - $(oMessageTextBody).find('blockquote.rl-bq-switcher').each(function () { - $(this).removeClass('rl-bq-switcher hidden-bq'); - }); - - $(oMessageTextBody).find('.rlBlockquoteSwitcher').each(function () { - $(this).remove(); - }); - } -}; - -/** - * @param {Object} oMessageTextBody - */ -Utils.toggleMessageBlockquote = function (oMessageTextBody) -{ - if (oMessageTextBody) - { - oMessageTextBody.find('.rlBlockquoteSwitcher').click(); - } -}; - -/** - * @param {string} sName - * @param {Function} ViewModelClass - * @param {Function=} AbstractViewModel = KnoinAbstractViewModel - */ -Utils.extendAsViewModel = function (sName, ViewModelClass, AbstractViewModel) -{ - if (ViewModelClass) - { - if (!AbstractViewModel) - { - AbstractViewModel = KnoinAbstractViewModel; - } - - ViewModelClass.__name = sName; - Plugins.regViewModelHook(sName, ViewModelClass); - _.extend(ViewModelClass.prototype, AbstractViewModel.prototype); - } -}; - -/** - * @param {Function} SettingsViewModelClass - * @param {string} sLabelName - * @param {string} sTemplate - * @param {string} sRoute - * @param {boolean=} bDefault - */ -Utils.addSettingsViewModel = function (SettingsViewModelClass, sTemplate, sLabelName, sRoute, bDefault) -{ - SettingsViewModelClass.__rlSettingsData = { - 'Label': sLabelName, - 'Template': sTemplate, - 'Route': sRoute, - 'IsDefault': !!bDefault - }; - - ViewModels['settings'].push(SettingsViewModelClass); -}; - -/** - * @param {Function} SettingsViewModelClass - */ -Utils.removeSettingsViewModel = function (SettingsViewModelClass) -{ - ViewModels['settings-removed'].push(SettingsViewModelClass); -}; - -/** - * @param {Function} SettingsViewModelClass - */ -Utils.disableSettingsViewModel = function (SettingsViewModelClass) -{ - ViewModels['settings-disabled'].push(SettingsViewModelClass); -}; - -Utils.convertThemeName = function (sTheme) -{ - if ('@custom' === sTheme.substr(-7)) - { - sTheme = Utils.trim(sTheme.substring(0, sTheme.length - 7)); - } - - return Utils.trim(sTheme.replace(/[^a-zA-Z]+/g, ' ').replace(/([A-Z])/g, ' $1').replace(/[\s]+/g, ' ')); -}; - -/** - * @param {string} sName - * @return {string} - */ -Utils.quoteName = function (sName) -{ - return sName.replace(/["]/g, '\\"'); -}; - -/** - * @return {number} - */ -Utils.microtime = function () -{ - return (new Date()).getTime(); -}; - -/** - * - * @param {string} sLanguage - * @param {boolean=} bEng = false - * @return {string} - */ -Utils.convertLangName = function (sLanguage, bEng) -{ - return Utils.i18n('LANGS_NAMES' + (true === bEng ? '_EN' : '') + '/LANG_' + - sLanguage.toUpperCase().replace(/[^a-zA-Z0-9]+/, '_'), null, sLanguage); -}; - -/** - * @param {number=} iLen - * @return {string} - */ -Utils.fakeMd5 = function(iLen) -{ - var - sResult = '', - sLine = '0123456789abcdefghijklmnopqrstuvwxyz' - ; - - iLen = Utils.isUnd(iLen) ? 32 : Utils.pInt(iLen); - - while (sResult.length < iLen) - { - sResult += sLine.substr(Math.round(Math.random() * sLine.length), 1); - } - - return sResult; -}; - -/* jshint ignore:start */ - -/** - * @param {string} s - * @return {string} - */ -Utils.md5 = function(s){function L(k,d){return(k<>>(32-d))}function K(G,k){var I,d,F,H,x;F=(G&2147483648);H=(k&2147483648);I=(G&1073741824);d=(k&1073741824);x=(G&1073741823)+(k&1073741823);if(I&d){return(x^2147483648^F^H)}if(I|d){if(x&1073741824){return(x^3221225472^F^H)}else{return(x^1073741824^F^H)}}else{return(x^F^H)}}function r(d,F,k){return(d&F)|((~d)&k)}function q(d,F,k){return(d&k)|(F&(~k))}function p(d,F,k){return(d^F^k)}function n(d,F,k){return(F^(d|(~k)))}function u(G,F,aa,Z,k,H,I){G=K(G,K(K(r(F,aa,Z),k),I));return K(L(G,H),F)}function f(G,F,aa,Z,k,H,I){G=K(G,K(K(q(F,aa,Z),k),I));return K(L(G,H),F)}function D(G,F,aa,Z,k,H,I){G=K(G,K(K(p(F,aa,Z),k),I));return K(L(G,H),F)}function t(G,F,aa,Z,k,H,I){G=K(G,K(K(n(F,aa,Z),k),I));return K(L(G,H),F)}function e(G){var Z;var F=G.length;var x=F+8;var k=(x-(x%64))/64;var I=(k+1)*16;var aa=Array(I-1);var d=0;var H=0;while(H >>29;return aa}function B(x){var k="",F="",G,d;for(d=0;d<=3;d++){G=(x>>>(d*8))&255;F="0"+G.toString(16);k=k+F.substr(F.length-2,2)}return k}function J(k){k=k.replace(/rn/g,"n");var d="";for(var F=0;F 127)&&(x<2048)){d+=String.fromCharCode((x>>6)|192);d+=String.fromCharCode((x&63)|128)}else{d+=String.fromCharCode((x>>12)|224);d+=String.fromCharCode(((x>>6)&63)|128);d+=String.fromCharCode((x&63)|128)}}}return d}var C=Array();var P,h,E,v,g,Y,X,W,V;var S=7,Q=12,N=17,M=22;var A=5,z=9,y=14,w=20;var o=4,m=11,l=16,j=23;var U=6,T=10,R=15,O=21;s=J(s);C=e(s);Y=1732584193;X=4023233417;W=2562383102;V=271733878;for(P=0;P /g, '>').replace(/'); -}; - -Utils.draggeblePlace = function () -{ - return $(' ').appendTo('#rl-hidden'); -}; - -Utils.defautOptionsAfterRender = function (oOption, oItem) -{ - if (oItem && !Utils.isUnd(oItem.disabled) && oOption) - { - $(oOption) - .toggleClass('disabled', oItem.disabled) - .prop('disabled', oItem.disabled) - ; - } -}; - -/** - * @param {Object} oViewModel - * @param {string} sTemplateID - * @param {string} sTitle - * @param {Function=} fCallback - */ -Utils.windowPopupKnockout = function (oViewModel, sTemplateID, sTitle, fCallback) -{ - var - oScript = null, - oWin = window.open(''), - sFunc = '__OpenerApplyBindingsUid' + Utils.fakeMd5() + '__', - oTemplate = $('#' + sTemplateID) - ; - - window[sFunc] = function () { - - if (oWin && oWin.document.body && oTemplate && oTemplate[0]) - { - var oBody = $(oWin.document.body); - - $('#rl-content', oBody).html(oTemplate.html()); - $('html', oWin.document).addClass('external ' + $('html').attr('class')); - - Utils.i18nToNode(oBody); - - Knoin.prototype.applyExternal(oViewModel, $('#rl-content', oBody)[0]); - - window[sFunc] = null; - - fCallback(oWin); - } - }; - - oWin.document.open(); - oWin.document.write('' + -'' + -'' + -'' + -'' + -'' + -'' + Utils.encodeHtml(sTitle) + ' ' + -''); - oWin.document.close(); - - oScript = oWin.document.createElement('script'); - oScript.type = 'text/javascript'; - oScript.innerHTML = 'if(window&&window.opener&&window.opener[\'' + sFunc + '\']){window.opener[\'' + sFunc + '\']();window.opener[\'' + sFunc + '\']=null}'; - oWin.document.getElementsByTagName('head')[0].appendChild(oScript); -}; - -Utils.settingsSaveHelperFunction = function (fCallback, koTrigger, oContext, iTimer) -{ - oContext = oContext || null; - iTimer = Utils.isUnd(iTimer) ? 1000 : Utils.pInt(iTimer); - return function (sType, mData, bCached, sRequestAction, oRequestParameters) { - koTrigger.call(oContext, mData && mData['Result'] ? Enums.SaveSettingsStep.TrueResult : Enums.SaveSettingsStep.FalseResult); - if (fCallback) - { - fCallback.call(oContext, sType, mData, bCached, sRequestAction, oRequestParameters); - } - _.delay(function () { - koTrigger.call(oContext, Enums.SaveSettingsStep.Idle); - }, iTimer); - }; -}; - -Utils.settingsSaveHelperSimpleFunction = function (koTrigger, oContext) -{ - return Utils.settingsSaveHelperFunction(null, koTrigger, oContext, 1000); -}; - - -/** - * @param {string} sHtml - * @return {string} - */ -Utils.htmlToPlain = function (sHtml) -{ - var - sText = '', - sQuoteChar = '> ', - - convertBlockquote = function () { - if (arguments && 1 < arguments.length) - { - var sText = $.trim(arguments[1]) - .replace(/__bq__start__(.|[\s\S\n\r]*)__bq__end__/gm, convertBlockquote) - ; - - sText = '\n' + sQuoteChar + $.trim(sText).replace(/\n/gm, '\n' + sQuoteChar) + '\n>\n'; - - return sText.replace(/\n([> ]+)/gm, function () { - return (arguments && 1 < arguments.length) ? '\n' + $.trim(arguments[1].replace(/[\s]/, '')) + ' ' : ''; - }); - } - - return ''; - }, - - convertDivs = function () { - if (arguments && 1 < arguments.length) - { - var sText = $.trim(arguments[1]); - if (0 < sText.length) - { - sText = sText.replace(/]*>(.|[\s\S\r\n]*)<\/div>/gmi, convertDivs); - sText = '\n' + $.trim(sText) + '\n'; - } - return sText; - } - return ''; - }, - - fixAttibuteValue = function () { - if (arguments && 1 < arguments.length) - { - return '' + arguments[1] + arguments[2].replace(//g, '>'); - } - - return ''; - }, - - convertLinks = function () { - if (arguments && 1 < arguments.length) - { - var - sName = $.trim(arguments[1]) -// sHref = $.trim(arguments[0].replace(//gmi, '$1')) - ; - - return sName; -// sName = (0 === trim(sName).length) ? '' : sName; -// sHref = ('mailto:' === sHref.substr(0, 7)) ? '' : sHref; -// sHref = ('http' === sHref.substr(0, 4)) ? sHref : ''; -// sHref = (sName === sHref) ? '' : sHref; -// sHref = (0 < sHref.length) ? ' (' + sHref + ') ' : ''; -// return (0 < sName.length) ? sName + sHref : sName; - } - return ''; - } - ; - - sText = sHtml - .replace(/[\s]+/gm, ' ') - .replace(/((?:href|data)\s?=\s?)("[^"]+?"|'[^']+?')/gmi, fixAttibuteValue) - .replace(/
/gmi, '\n') - .replace(/<\/h\d>/gi, '\n') - .replace(/<\/p>/gi, '\n\n') - .replace(/<\/li>/gi, '\n') - .replace(/<\/td>/gi, '\n') - .replace(/<\/tr>/gi, '\n') - .replace(/
]*>/gmi, '\n_______________________________\n\n') - .replace(/]*>/gmi, '') - .replace(/
]*>(.|[\s\S\r\n]*)<\/div>/gmi, convertDivs) - .replace(/]*>/gmi, '\n__bq__start__\n') - .replace(/<\/blockquote>/gmi, '\n__bq__end__\n') - .replace(/]*>(.|[\s\S\r\n]*)<\/a>/gmi, convertLinks) - .replace(/ /gi, ' ') - .replace(/<[^>]*>/gm, '') - .replace(/>/gi, '>') - .replace(/</gi, '<') - .replace(/&/gi, '&') - .replace(/&\w{2,6};/gi, '') - ; - - return sText - .replace(/\n[ \t]+/gm, '\n') - .replace(/[\n]{3,}/gm, '\n\n') - .replace(/__bq__start__(.|[\s\S\r\n]*)__bq__end__/gm, convertBlockquote) - .replace(/__bq__start__/gm, '') - .replace(/__bq__end__/gm, '') - ; -}; - -/** - * @param {string} sPlain - * @return {string} - */ -Utils.plainToHtml = function (sPlain) -{ - return sPlain.toString() - .replace(/&/g, '&').replace(/>/g, '>').replace(/'); -}; - -Utils.resizeAndCrop = function (sUrl, iValue, fCallback) -{ - var oTempImg = new window.Image(); - oTempImg.onload = function() { - - var - aDiff = [0, 0], - oCanvas = document.createElement('canvas'), - oCtx = oCanvas.getContext('2d') - ; - - oCanvas.width = iValue; - oCanvas.height = iValue; - - if (this.width > this.height) - { - aDiff = [this.width - this.height, 0]; - } - else - { - aDiff = [0, this.height - this.width]; - } - - oCtx.fillStyle = '#fff'; - oCtx.fillRect(0, 0, iValue, iValue); - oCtx.drawImage(this, aDiff[0] / 2, aDiff[1] / 2, this.width - aDiff[0], this.height - aDiff[1], 0, 0, iValue, iValue); - - fCallback(oCanvas.toDataURL('image/jpeg')); - }; - - oTempImg.src = sUrl; -}; - -Utils.computedPagenatorHelper = function (koCurrentPage, koPageCount) -{ - return function() { - var - iPrev = 0, - iNext = 0, - iLimit = 2, - aResult = [], - iCurrentPage = koCurrentPage(), - iPageCount = koPageCount(), - - /** - * @param {number} iIndex - * @param {boolean=} bPush - * @param {string=} sCustomName - */ - fAdd = function (iIndex, bPush, sCustomName) { - - var oData = { - 'current': iIndex === iCurrentPage, - 'name': Utils.isUnd(sCustomName) ? iIndex.toString() : sCustomName.toString(), - 'custom': Utils.isUnd(sCustomName) ? false : true, - 'title': Utils.isUnd(sCustomName) ? '' : iIndex.toString(), - 'value': iIndex.toString() - }; - - if (Utils.isUnd(bPush) ? true : !!bPush) - { - aResult.push(oData); - } - else - { - aResult.unshift(oData); - } - } - ; - - if (1 < iPageCount || (0 < iPageCount && iPageCount < iCurrentPage)) -// if (0 < iPageCount && 0 < iCurrentPage) - { - if (iPageCount < iCurrentPage) - { - fAdd(iPageCount); - iPrev = iPageCount; - iNext = iPageCount; - } - else - { - if (3 >= iCurrentPage || iPageCount - 2 <= iCurrentPage) - { - iLimit += 2; - } - - fAdd(iCurrentPage); - iPrev = iCurrentPage; - iNext = iCurrentPage; - } - - while (0 < iLimit) { - - iPrev -= 1; - iNext += 1; - - if (0 < iPrev) - { - fAdd(iPrev, false); - iLimit--; - } - - if (iPageCount >= iNext) - { - fAdd(iNext, true); - iLimit--; - } - else if (0 >= iPrev) - { - break; - } - } - - if (3 === iPrev) - { - fAdd(2, false); - } - else if (3 < iPrev) - { - fAdd(Math.round((iPrev - 1) / 2), false, '...'); - } - - if (iPageCount - 2 === iNext) - { - fAdd(iPageCount - 1, true); - } - else if (iPageCount - 2 > iNext) - { - fAdd(Math.round((iPageCount + iNext) / 2), true, '...'); - } - - // first and last - if (1 < iPrev) - { - fAdd(1, false); - } - - if (iPageCount > iNext) - { - fAdd(iPageCount, true); - } - } - - return aResult; - }; -}; - -Utils.selectElement = function (element) -{ - /* jshint onevar: false */ - if (window.getSelection) - { - var sel = window.getSelection(); - sel.removeAllRanges(); - var range = document.createRange(); - range.selectNodeContents(element); - sel.addRange(range); - } - else if (document.selection) - { - var textRange = document.body.createTextRange(); - textRange.moveToElementText(element); - textRange.select(); - } - /* jshint onevar: true */ -}; - -Utils.disableKeyFilter = function () -{ - if (window.key) - { - key.filter = function () { - return RL.data().useKeyboardShortcuts(); - }; - } -}; - -Utils.restoreKeyFilter = function () -{ - if (window.key) - { - key.filter = function (event) { - - if (RL.data().useKeyboardShortcuts()) - { - var - element = event.target || event.srcElement, - tagName = element ? element.tagName : '' - ; - - tagName = tagName.toUpperCase(); - return !(tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA' || - (element && tagName === 'DIV' && 'editorHtmlArea' === element.className && element.contentEditable) - ); - } - - return false; - }; - } -}; - -Utils.detectDropdownVisibility = _.debounce(function () { - Globals.dropdownVisibility(!!_.find(BootstrapDropdowns, function (oItem) { - return oItem.hasClass('open'); - })); +/** + * @type {?} + */ +Globals.langChangeTrigger = ko.observable(true); + +/** + * @type {number} + */ +Globals.iAjaxErrorCount = 0; + +/** + * @type {number} + */ +Globals.iTokenErrorCount = 0; + +/** + * @type {number} + */ +Globals.iMessageBodyCacheCount = 0; + +/** + * @type {boolean} + */ +Globals.bUnload = false; + +/** + * @type {string} + */ +Globals.sUserAgent = (navigator.userAgent || '').toLowerCase(); + +/** + * @type {boolean} + */ +Globals.bIsiOSDevice = -1 < Globals.sUserAgent.indexOf('iphone') || -1 < Globals.sUserAgent.indexOf('ipod') || -1 < Globals.sUserAgent.indexOf('ipad'); + +/** + * @type {boolean} + */ +Globals.bIsAndroidDevice = -1 < Globals.sUserAgent.indexOf('android'); + +/** + * @type {boolean} + */ +Globals.bMobileDevice = Globals.bIsiOSDevice || Globals.bIsAndroidDevice; + +/** + * @type {boolean} + */ +Globals.bDisableNanoScroll = Globals.bMobileDevice; + +/** + * @type {boolean} + */ +Globals.bAllowPdfPreview = !Globals.bMobileDevice; + +/** + * @type {boolean} + */ +Globals.bAnimationSupported = !Globals.bMobileDevice && $html.hasClass('csstransitions'); + +/** + * @type {string} + */ +Globals.sAnimationType = ''; + +/** + * @type {Object} + */ +Globals.oHtmlEditorDefaultConfig = { + 'title': false, + 'stylesSet': false, + 'customConfig': '', + 'contentsCss': '', + 'toolbarGroups': [ + {name: 'spec'}, + {name: 'styles'}, + {name: 'basicstyles', groups: ['basicstyles', 'cleanup']}, + {name: 'colors'}, + {name: 'paragraph', groups: ['list', 'indent', 'blocks', 'align']}, + {name: 'links'}, + {name: 'insert'}, + {name: 'others'} +// {name: 'document', groups: ['mode', 'document', 'doctools']} + ], + + 'removePlugins': 'contextmenu', //blockquote + 'removeButtons': 'Format,Undo,Redo,Cut,Copy,Paste,Anchor,Strike,Subscript,Superscript,Image,SelectAll', + 'removeDialogTabs': 'link:advanced;link:target;image:advanced', + + 'extraPlugins': 'plain', + + 'allowedContent': true, + 'autoParagraph': false, + + 'enterMode': window.CKEDITOR.ENTER_BR, + 'shiftEnterMode': window.CKEDITOR.ENTER_BR, + + 'font_defaultLabel': 'Arial', + 'fontSize_defaultLabel': '13', + 'fontSize_sizes': '10/10px;12/12px;13/13px;14/14px;16/16px;18/18px;20/20px;24/24px;28/28px;36/36px;48/48px' +}; + +/** + * @type {Object} + */ +Globals.oHtmlEditorLangsMap = { + 'de': 'de', + 'es': 'es', + 'fr': 'fr', + 'hu': 'hu', + 'is': 'is', + 'it': 'it', + 'ko': 'ko', + 'ko-kr': 'ko', + 'lv': 'lv', + 'nl': 'nl', + 'no': 'no', + 'pl': 'pl', + 'pt': 'pt', + 'pt-pt': 'pt', + 'pt-br': 'pt-br', + 'ru': 'ru', + 'ro': 'ro', + 'zh': 'zh', + 'zh-cn': 'zh-cn' +}; + +if (Globals.bAllowPdfPreview && navigator && navigator.mimeTypes) +{ + Globals.bAllowPdfPreview = !!_.find(navigator.mimeTypes, function (oType) { + return oType && 'application/pdf' === oType.type; + }); +} + +Consts.Defaults = {}; +Consts.Values = {}; +Consts.DataImages = {}; + +/** + * @const + * @type {number} + */ +Consts.Defaults.MessagesPerPage = 20; + +/** + * @const + * @type {number} + */ +Consts.Defaults.ContactsPerPage = 50; + +/** + * @const + * @type {Array} + */ +Consts.Defaults.MessagesPerPageArray = [10, 20, 30, 50, 100/*, 150, 200, 300*/]; + +/** + * @const + * @type {number} + */ +Consts.Defaults.DefaultAjaxTimeout = 30000; + +/** + * @const + * @type {number} + */ +Consts.Defaults.SearchAjaxTimeout = 300000; + +/** + * @const + * @type {number} + */ +Consts.Defaults.SendMessageAjaxTimeout = 300000; + +/** + * @const + * @type {number} + */ +Consts.Defaults.SaveMessageAjaxTimeout = 200000; + +/** + * @const + * @type {number} + */ +Consts.Defaults.ContactsSyncAjaxTimeout = 200000; + +/** + * @const + * @type {string} + */ +Consts.Values.UnuseOptionValue = '__UNUSE__'; + +/** + * @const + * @type {string} + */ +Consts.Values.ClientSideCookieIndexName = 'rlcsc'; + +/** + * @const + * @type {number} + */ +Consts.Values.ImapDefaulPort = 143; + +/** + * @const + * @type {number} + */ +Consts.Values.ImapDefaulSecurePort = 993; + +/** + * @const + * @type {number} + */ +Consts.Values.SmtpDefaulPort = 25; + +/** + * @const + * @type {number} + */ +Consts.Values.SmtpDefaulSecurePort = 465; + +/** + * @const + * @type {number} + */ +Consts.Values.MessageBodyCacheLimit = 15; + +/** + * @const + * @type {number} + */ +Consts.Values.AjaxErrorLimit = 7; + +/** + * @const + * @type {number} + */ +Consts.Values.TokenErrorLimit = 10; + +/** + * @const + * @type {string} + */ +Consts.DataImages.UserDotPic = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIW2P8DwQACgAD/il4QJ8AAAAASUVORK5CYII='; + +/** + * @const + * @type {string} + */ +Consts.DataImages.TranspPic = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQIW2NkAAIAAAoAAggA9GkAAAAASUVORK5CYII='; + +/** + * @enum {string} + */ +Enums.StorageResultType = { + 'Success': 'success', + 'Abort': 'abort', + 'Error': 'error', + 'Unload': 'unload' +}; + +/** + * @enum {number} + */ +Enums.State = { + 'Empty': 10, + 'Login': 20, + 'Auth': 30 +}; + +/** + * @enum {number} + */ +Enums.StateType = { + 'Webmail': 0, + 'Admin': 1 +}; + +/** + * @enum {string} + */ +Enums.KeyState = { + 'All': 'all', + 'None': 'none', + 'ContactList': 'contact-list', + 'MessageList': 'message-list', + 'FolderList': 'folder-list', + 'MessageView': 'message-view', + 'Compose': 'compose', + 'Settings': 'settings', + 'Menu': 'menu', + 'PopupComposeOpenPGP': 'compose-open-pgp', + 'PopupKeyboardShortcutsHelp': 'popup-keyboard-shortcuts-help', + 'PopupAsk': 'popup-ask' +}; + +/** + * @enum {number} + */ +Enums.FolderType = { + 'Inbox': 10, + 'SentItems': 11, + 'Draft': 12, + 'Trash': 13, + 'Spam': 14, + 'Archive': 15, + 'NotSpam': 80, + 'User': 99 +}; + +/** + * @enum {string} + */ +Enums.LoginSignMeTypeAsString = { + 'DefaultOff': 'defaultoff', + 'DefaultOn': 'defaulton', + 'Unused': 'unused' +}; + +/** + * @enum {number} + */ +Enums.LoginSignMeType = { + 'DefaultOff': 0, + 'DefaultOn': 1, + 'Unused': 2 +}; + +/** + * @enum {string} + */ +Enums.ComposeType = { + 'Empty': 'empty', + 'Reply': 'reply', + 'ReplyAll': 'replyall', + 'Forward': 'forward', + 'ForwardAsAttachment': 'forward-as-attachment', + 'Draft': 'draft', + 'EditAsNew': 'editasnew' +}; + +/** + * @enum {number} + */ +Enums.UploadErrorCode = { + 'Normal': 0, + 'FileIsTooBig': 1, + 'FilePartiallyUploaded': 2, + 'FileNoUploaded': 3, + 'MissingTempFolder': 4, + 'FileOnSaveingError': 5, + 'FileType': 98, + 'Unknown': 99 +}; + +/** + * @enum {number} + */ +Enums.SetSystemFoldersNotification = { + 'None': 0, + 'Sent': 1, + 'Draft': 2, + 'Spam': 3, + 'Trash': 4, + 'Archive': 5 +}; + +/** + * @enum {number} + */ +Enums.ClientSideKeyName = { + 'FoldersLashHash': 0, + 'MessagesInboxLastHash': 1, + 'MailBoxListSize': 2, + 'ExpandedFolders': 3, + 'FolderListSize': 4 +}; + +/** + * @enum {number} + */ +Enums.EventKeyCode = { + 'Backspace': 8, + 'Tab': 9, + 'Enter': 13, + 'Esc': 27, + 'PageUp': 33, + 'PageDown': 34, + 'Left': 37, + 'Right': 39, + 'Up': 38, + 'Down': 40, + 'End': 35, + 'Home': 36, + 'Space': 32, + 'Insert': 45, + 'Delete': 46, + 'A': 65, + 'S': 83 +}; + +/** + * @enum {number} + */ +Enums.MessageSetAction = { + 'SetSeen': 0, + 'UnsetSeen': 1, + 'SetFlag': 2, + 'UnsetFlag': 3 +}; + +/** + * @enum {number} + */ +Enums.MessageSelectAction = { + 'All': 0, + 'None': 1, + 'Invert': 2, + 'Unseen': 3, + 'Seen': 4, + 'Flagged': 5, + 'Unflagged': 6 +}; + +/** + * @enum {number} + */ +Enums.DesktopNotifications = { + 'Allowed': 0, + 'NotAllowed': 1, + 'Denied': 2, + 'NotSupported': 9 +}; + +/** + * @enum {number} + */ +Enums.MessagePriority = { + 'Low': 5, + 'Normal': 3, + 'High': 1 +}; + +/** + * @enum {string} + */ +Enums.EditorDefaultType = { + 'Html': 'Html', + 'Plain': 'Plain' +}; + +/** + * @enum {string} + */ +Enums.CustomThemeType = { + 'Light': 'Light', + 'Dark': 'Dark' +}; + +/** + * @enum {number} + */ +Enums.ServerSecure = { + 'None': 0, + 'SSL': 1, + 'TLS': 2 +}; + +/** + * @enum {number} + */ +Enums.SearchDateType = { + 'All': -1, + 'Days3': 3, + 'Days7': 7, + 'Month': 30 +}; + +/** + * @enum {number} + */ +Enums.EmailType = { + 'Defailt': 0, + 'Facebook': 1, + 'Google': 2 +}; + +/** + * @enum {number} + */ +Enums.SaveSettingsStep = { + 'Animate': -2, + 'Idle': -1, + 'TrueResult': 1, + 'FalseResult': 0 +}; + +/** + * @enum {string} + */ +Enums.InterfaceAnimation = { + 'None': 'None', + 'Normal': 'Normal', + 'Full': 'Full' +}; + +/** + * @enum {number} + */ +Enums.Layout = { + 'NoPreview': 0, + 'SidePreview': 1, + 'BottomPreview': 2 +}; + +/** + * @enum {number} + */ +Enums.SignedVerifyStatus = { + 'UnknownPublicKeys': -4, + 'UnknownPrivateKey': -3, + 'Unverified': -2, + 'Error': -1, + 'None': 0, + 'Success': 1 +}; + +/** + * @enum {number} + */ +Enums.ContactPropertyType = { + + 'Unknown': 0, + + 'FullName': 10, + + 'FirstName': 15, + 'LastName': 16, + 'MiddleName': 16, + 'Nick': 18, + + 'NamePrefix': 20, + 'NameSuffix': 21, + + 'Email': 30, + 'Phone': 31, + 'Web': 32, + + 'Birthday': 40, + + 'Facebook': 90, + 'Skype': 91, + 'GitHub': 92, + + 'Note': 110, + + 'Custom': 250 +}; + +/** + * @enum {number} + */ +Enums.Notification = { + 'InvalidToken': 101, + 'AuthError': 102, + 'AccessError': 103, + 'ConnectionError': 104, + 'CaptchaError': 105, + 'SocialFacebookLoginAccessDisable': 106, + 'SocialTwitterLoginAccessDisable': 107, + 'SocialGoogleLoginAccessDisable': 108, + 'DomainNotAllowed': 109, + 'AccountNotAllowed': 110, + + 'AccountTwoFactorAuthRequired': 120, + 'AccountTwoFactorAuthError': 121, + + 'CouldNotSaveNewPassword': 130, + 'CurrentPasswordIncorrect': 131, + 'NewPasswordShort': 132, + 'NewPasswordWeak': 133, + 'NewPasswordForbidden': 134, + + 'ContactsSyncError': 140, + + 'CantGetMessageList': 201, + 'CantGetMessage': 202, + 'CantDeleteMessage': 203, + 'CantMoveMessage': 204, + 'CantCopyMessage': 205, + + 'CantSaveMessage': 301, + 'CantSendMessage': 302, + 'InvalidRecipients': 303, + + 'CantCreateFolder': 400, + 'CantRenameFolder': 401, + 'CantDeleteFolder': 402, + 'CantSubscribeFolder': 403, + 'CantUnsubscribeFolder': 404, + 'CantDeleteNonEmptyFolder': 405, + + 'CantSaveSettings': 501, + 'CantSavePluginSettings': 502, + + 'DomainAlreadyExists': 601, + + 'CantInstallPackage': 701, + 'CantDeletePackage': 702, + 'InvalidPluginPackage': 703, + 'UnsupportedPluginPackage': 704, + + 'LicensingServerIsUnavailable': 710, + 'LicensingExpired': 711, + 'LicensingBanned': 712, + + 'DemoSendMessageError': 750, + + 'AccountAlreadyExists': 801, + + 'MailServerError': 901, + 'ClientViewError': 902, + 'UnknownNotification': 999, + 'UnknownError': 999 +}; + +Utils.trim = $.trim; +Utils.inArray = $.inArray; +Utils.isArray = _.isArray; +Utils.isFunc = _.isFunction; +Utils.isUnd = _.isUndefined; +Utils.isNull = _.isNull; +Utils.emptyFunction = function () {}; + +/** + * @param {*} oValue + * @return {boolean} + */ +Utils.isNormal = function (oValue) +{ + return !Utils.isUnd(oValue) && !Utils.isNull(oValue); +}; + +Utils.windowResize = _.debounce(function (iTimeout) { + if (Utils.isUnd(iTimeout)) + { + $window.resize(); + } + else + { + window.setTimeout(function () { + $window.resize(); + }, iTimeout); + } }, 50); -// Base64 encode / decode -// http://www.webtoolkit.info/ - -Base64 = { - - // private property - _keyStr : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', - - // public method for urlsafe encoding - urlsafe_encode : function (input) { - return Base64.encode(input).replace(/[+]/g, '-').replace(/[\/]/g, '_').replace(/[=]/g, '.'); - }, - - // public method for encoding - encode : function (input) { - var - output = '', - chr1, chr2, chr3, enc1, enc2, enc3, enc4, - i = 0 - ; - - input = Base64._utf8_encode(input); - - while (i < input.length) - { - chr1 = input.charCodeAt(i++); - chr2 = input.charCodeAt(i++); - chr3 = input.charCodeAt(i++); - - enc1 = chr1 >> 2; - enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); - enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); - enc4 = chr3 & 63; - - if (isNaN(chr2)) - { - enc3 = enc4 = 64; - } - else if (isNaN(chr3)) - { - enc4 = 64; - } - - output = output + - this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + - this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4); - } - - return output; - }, - - // public method for decoding - decode : function (input) { - var - output = '', - chr1, chr2, chr3, enc1, enc2, enc3, enc4, - i = 0 - ; - - input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ''); - - while (i < input.length) - { - enc1 = this._keyStr.indexOf(input.charAt(i++)); - enc2 = this._keyStr.indexOf(input.charAt(i++)); - enc3 = this._keyStr.indexOf(input.charAt(i++)); - enc4 = this._keyStr.indexOf(input.charAt(i++)); - - chr1 = (enc1 << 2) | (enc2 >> 4); - chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); - chr3 = ((enc3 & 3) << 6) | enc4; - - output = output + String.fromCharCode(chr1); - - if (enc3 !== 64) - { - output = output + String.fromCharCode(chr2); - } - - if (enc4 !== 64) - { - output = output + String.fromCharCode(chr3); - } - } - - return Base64._utf8_decode(output); - }, - - // private method for UTF-8 encoding - _utf8_encode : function (string) { - - string = string.replace(/\r\n/g, "\n"); - - var - utftext = '', - n = 0, - l = string.length, - c = 0 - ; - - for (; n < l; n++) { - - c = string.charCodeAt(n); - - if (c < 128) - { - utftext += String.fromCharCode(c); - } - else if ((c > 127) && (c < 2048)) - { - utftext += String.fromCharCode((c >> 6) | 192); - utftext += String.fromCharCode((c & 63) | 128); - } - else - { - utftext += String.fromCharCode((c >> 12) | 224); - utftext += String.fromCharCode(((c >> 6) & 63) | 128); - utftext += String.fromCharCode((c & 63) | 128); - } - } - - return utftext; - }, - - // private method for UTF-8 decoding - _utf8_decode : function (utftext) { - var - string = '', - i = 0, - c = 0, - c2 = 0, - c3 = 0 - ; - - while ( i < utftext.length ) - { - c = utftext.charCodeAt(i); - - if (c < 128) - { - string += String.fromCharCode(c); - i++; - } - else if((c > 191) && (c < 224)) - { - c2 = utftext.charCodeAt(i+1); - string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); - i += 2; - } - else - { - c2 = utftext.charCodeAt(i+1); - c3 = utftext.charCodeAt(i+2); - string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); - i += 3; - } - } - - return string; - } -}; - + +/** + * @param {(string|number)} mValue + * @param {boolean=} bIncludeZero + * @return {boolean} + */ +Utils.isPosNumeric = function (mValue, bIncludeZero) +{ + return Utils.isNormal(mValue) ? + ((Utils.isUnd(bIncludeZero) ? true : !!bIncludeZero) ? + (/^[0-9]*$/).test(mValue.toString()) : + (/^[1-9]+[0-9]*$/).test(mValue.toString())) : + false; +}; + +/** + * @param {*} iValue + * @return {number} + */ +Utils.pInt = function (iValue) +{ + return Utils.isNormal(iValue) && '' !== iValue ? window.parseInt(iValue, 10) : 0; +}; + +/** + * @param {*} mValue + * @return {string} + */ +Utils.pString = function (mValue) +{ + return Utils.isNormal(mValue) ? '' + mValue : ''; +}; + +/** + * @param {*} aValue + * @return {boolean} + */ +Utils.isNonEmptyArray = function (aValue) +{ + return Utils.isArray(aValue) && 0 < aValue.length; +}; + +/** + * @param {string} sPath + * @param {*=} oObject + * @param {Object=} oObjectToExportTo + */ +Utils.exportPath = function (sPath, oObject, oObjectToExportTo) +{ + var + part = null, + parts = sPath.split('.'), + cur = oObjectToExportTo || window + ; + + for (; parts.length && (part = parts.shift());) + { + if (!parts.length && !Utils.isUnd(oObject)) + { + cur[part] = oObject; + } + else if (cur[part]) + { + cur = cur[part]; + } + else + { + cur = cur[part] = {}; + } + } +}; + +/** + * @param {Object} oObject + * @param {string} sName + * @param {*} mValue + */ +Utils.pImport = function (oObject, sName, mValue) +{ + oObject[sName] = mValue; +}; + +/** + * @param {Object} oObject + * @param {string} sName + * @param {*} mDefault + * @return {*} + */ +Utils.pExport = function (oObject, sName, mDefault) +{ + return Utils.isUnd(oObject[sName]) ? mDefault : oObject[sName]; +}; + +/** + * @param {string} sText + * @return {string} + */ +Utils.encodeHtml = function (sText) +{ + return Utils.isNormal(sText) ? sText.toString() + .replace(/&/g, '&').replace(//g, '>') + .replace(/"/g, '"').replace(/'/g, ''') : ''; +}; + +/** + * @param {string} sText + * @param {number=} iLen + * @return {string} + */ +Utils.splitPlainText = function (sText, iLen) +{ + var + sPrefix = '', + sSubText = '', + sResult = sText, + iSpacePos = 0, + iNewLinePos = 0 + ; + + iLen = Utils.isUnd(iLen) ? 100 : iLen; + + while (sResult.length > iLen) + { + sSubText = sResult.substring(0, iLen); + iSpacePos = sSubText.lastIndexOf(' '); + iNewLinePos = sSubText.lastIndexOf('\n'); + + if (-1 !== iNewLinePos) + { + iSpacePos = iNewLinePos; + } + + if (-1 === iSpacePos) + { + iSpacePos = iLen; + } + + sPrefix += sSubText.substring(0, iSpacePos) + '\n'; + sResult = sResult.substring(iSpacePos + 1); + } + + return sPrefix + sResult; +}; + +Utils.timeOutAction = (function () { + + var + oTimeOuts = {} + ; + + return function (sAction, fFunction, iTimeOut) + { + if (Utils.isUnd(oTimeOuts[sAction])) + { + oTimeOuts[sAction] = 0; + } + + window.clearTimeout(oTimeOuts[sAction]); + oTimeOuts[sAction] = window.setTimeout(fFunction, iTimeOut); + }; +}()); + +Utils.timeOutActionSecond = (function () { + + var + oTimeOuts = {} + ; + + return function (sAction, fFunction, iTimeOut) + { + if (!oTimeOuts[sAction]) + { + oTimeOuts[sAction] = window.setTimeout(function () { + fFunction(); + oTimeOuts[sAction] = 0; + }, iTimeOut); + } + }; +}()); + +Utils.audio = (function () { + + var + oAudio = false + ; + + return function (sMp3File, sOggFile) { + + if (false === oAudio) + { + if (Globals.bIsiOSDevice) + { + oAudio = null; + } + else + { + var + bCanPlayMp3 = false, + bCanPlayOgg = false, + oAudioLocal = window.Audio ? new window.Audio() : null + ; + + if (oAudioLocal && oAudioLocal.canPlayType && oAudioLocal.play) + { + bCanPlayMp3 = '' !== oAudioLocal.canPlayType('audio/mpeg; codecs="mp3"'); + if (!bCanPlayMp3) + { + bCanPlayOgg = '' !== oAudioLocal.canPlayType('audio/ogg; codecs="vorbis"'); + } + + if (bCanPlayMp3 || bCanPlayOgg) + { + oAudio = oAudioLocal; + oAudio.preload = 'none'; + oAudio.loop = false; + oAudio.autoplay = false; + oAudio.muted = false; + oAudio.src = bCanPlayMp3 ? sMp3File : sOggFile; + } + else + { + oAudio = null; + } + } + else + { + oAudio = null; + } + } + } + + return oAudio; + }; +}()); + +/** + * @param {(Object|null|undefined)} oObject + * @param {string} sProp + * @return {boolean} + */ +Utils.hos = function (oObject, sProp) +{ + return oObject && Object.hasOwnProperty ? Object.hasOwnProperty.call(oObject, sProp) : false; +}; + +/** + * @param {string} sKey + * @param {Object=} oValueList + * @param {string=} sDefaulValue + * @return {string} + */ +Utils.i18n = function (sKey, oValueList, sDefaulValue) +{ + var + sValueName = '', + sResult = Utils.isUnd(I18n[sKey]) ? (Utils.isUnd(sDefaulValue) ? sKey : sDefaulValue) : I18n[sKey] + ; + + if (!Utils.isUnd(oValueList) && !Utils.isNull(oValueList)) + { + for (sValueName in oValueList) + { + if (Utils.hos(oValueList, sValueName)) + { + sResult = sResult.replace('%' + sValueName + '%', oValueList[sValueName]); + } + } + } + + return sResult; +}; + +/** + * @param {Object} oElement + */ +Utils.i18nToNode = function (oElement) +{ + _.defer(function () { + $('.i18n', oElement).each(function () { + var + jqThis = $(this), + sKey = '' + ; + + sKey = jqThis.data('i18n-text'); + if (sKey) + { + jqThis.text(Utils.i18n(sKey)); + } + else + { + sKey = jqThis.data('i18n-html'); + if (sKey) + { + jqThis.html(Utils.i18n(sKey)); + } + + sKey = jqThis.data('i18n-placeholder'); + if (sKey) + { + jqThis.attr('placeholder', Utils.i18n(sKey)); + } + + sKey = jqThis.data('i18n-title'); + if (sKey) + { + jqThis.attr('title', Utils.i18n(sKey)); + } + } + }); + }); +}; + +Utils.i18nToDoc = function () +{ + if (window.rainloopI18N) + { + I18n = window.rainloopI18N || {}; + Utils.i18nToNode($document); + + Globals.langChangeTrigger(!Globals.langChangeTrigger()); + } + + window.rainloopI18N = {}; +}; + +/** + * @param {Function} fCallback + * @param {Object} oScope + * @param {Function=} fLangCallback + */ +Utils.initOnStartOrLangChange = function (fCallback, oScope, fLangCallback) +{ + if (fCallback) + { + fCallback.call(oScope); + } + + if (fLangCallback) + { + Globals.langChangeTrigger.subscribe(function () { + if (fCallback) + { + fCallback.call(oScope); + } + + fLangCallback.call(oScope); + }); + } + else if (fCallback) + { + Globals.langChangeTrigger.subscribe(fCallback, oScope); + } +}; + +/** + * @return {boolean} + */ +Utils.inFocus = function () +{ + var oActiveObj = document.activeElement; + return (oActiveObj && ('INPUT' === oActiveObj.tagName || + 'TEXTAREA' === oActiveObj.tagName || + 'IFRAME' === oActiveObj.tagName || + ('DIV' === oActiveObj.tagName && 'editorHtmlArea' === oActiveObj.className && oActiveObj.contentEditable))); +}; + +Utils.removeInFocus = function () +{ + if (document && document.activeElement && document.activeElement.blur) + { + var oA = $(document.activeElement); + if (oA.is('input') || oA.is('textarea')) + { + document.activeElement.blur(); + } + } +}; + +Utils.removeSelection = function () +{ + if (window && window.getSelection) + { + var oSel = window.getSelection(); + if (oSel && oSel.removeAllRanges) + { + oSel.removeAllRanges(); + } + } + else if (document && document.selection && document.selection.empty) + { + document.selection.empty(); + } +}; + +/** + * @param {string} sPrefix + * @param {string} sSubject + * @param {boolean=} bFixLongSubject = true + * @return {string} + */ +Utils.replySubjectAdd = function (sPrefix, sSubject, bFixLongSubject) +{ + var + oMatch = null, + sResult = Utils.trim(sSubject) + ; + + if (null !== (oMatch = (new window.RegExp('^' + sPrefix + '[\\s]?\\:(.*)$', 'gi')).exec(sSubject)) && !Utils.isUnd(oMatch[1])) + { + sResult = sPrefix + '[2]: ' + oMatch[1]; + } + else if (null !== (oMatch = (new window.RegExp('^(' + sPrefix + '[\\s]?[\\[\\(]?)([\\d]+)([\\]\\)]?[\\s]?\\:.*)$', 'gi')).exec(sSubject)) && + !Utils.isUnd(oMatch[1]) && !Utils.isUnd(oMatch[2]) && !Utils.isUnd(oMatch[3])) + { + sResult = oMatch[1] + (Utils.pInt(oMatch[2]) + 1) + oMatch[3]; + } + else + { + sResult = sPrefix + ': ' + sSubject; + } + + sResult = sResult.replace(/[\s]+/g, ' '); + sResult = (Utils.isUnd(bFixLongSubject) ? true : bFixLongSubject) ? Utils.fixLongSubject(sResult) : sResult; +// sResult = sResult.replace(/^(Re|Fwd)[\s]?\[[\d]+\]:/ig, '$1:'); + return sResult; +}; + +/** + * @param {string} sSubject + * @return {string} + */ +Utils.fixLongSubject = function (sSubject) +{ + var + iCounter = 0, + oMatch = null + ; + + sSubject = Utils.trim(sSubject.replace(/[\s]+/, ' ')); + + do + { + oMatch = /^Re(\[([\d]+)\]|):[\s]{0,3}Re(\[([\d]+)\]|):/ig.exec(sSubject); + if (!oMatch || Utils.isUnd(oMatch[0])) + { + oMatch = null; + } + + if (oMatch) + { + iCounter = 0; + iCounter += Utils.isUnd(oMatch[2]) ? 1 : 0 + Utils.pInt(oMatch[2]); + iCounter += Utils.isUnd(oMatch[4]) ? 1 : 0 + Utils.pInt(oMatch[4]); + + sSubject = sSubject.replace(/^Re(\[[\d]+\]|):[\s]{0,3}Re(\[[\d]+\]|):/gi, 'Re' + (0 < iCounter ? '[' + iCounter + ']' : '') + ':'); + } + + } + while (oMatch); + + sSubject = sSubject.replace(/[\s]+/, ' '); + return sSubject; +}; + +/** + * @param {number} iNum + * @param {number} iDec + * @return {number} + */ +Utils.roundNumber = function (iNum, iDec) +{ + return Math.round(iNum * Math.pow(10, iDec)) / Math.pow(10, iDec); +}; + +/** + * @param {(number|string)} iSizeInBytes + * @return {string} + */ +Utils.friendlySize = function (iSizeInBytes) +{ + iSizeInBytes = Utils.pInt(iSizeInBytes); + + if (iSizeInBytes >= 1073741824) + { + return Utils.roundNumber(iSizeInBytes / 1073741824, 1) + 'GB'; + } + else if (iSizeInBytes >= 1048576) + { + return Utils.roundNumber(iSizeInBytes / 1048576, 1) + 'MB'; + } + else if (iSizeInBytes >= 1024) + { + return Utils.roundNumber(iSizeInBytes / 1024, 0) + 'KB'; + } + + return iSizeInBytes + 'B'; +}; + +/** + * @param {string} sDesc + */ +Utils.log = function (sDesc) +{ + if (window.console && window.console.log) + { + window.console.log(sDesc); + } +}; + +/** + * @param {number} iCode + * @param {*=} mMessage = '' + * @return {string} + */ +Utils.getNotification = function (iCode, mMessage) +{ + iCode = Utils.pInt(iCode); + if (Enums.Notification.ClientViewError === iCode && mMessage) + { + return mMessage; + } + + return Utils.isUnd(NotificationI18N[iCode]) ? '' : NotificationI18N[iCode]; +}; + +Utils.initNotificationLanguage = function () +{ + NotificationI18N[Enums.Notification.InvalidToken] = Utils.i18n('NOTIFICATIONS/INVALID_TOKEN'); + NotificationI18N[Enums.Notification.AuthError] = Utils.i18n('NOTIFICATIONS/AUTH_ERROR'); + NotificationI18N[Enums.Notification.AccessError] = Utils.i18n('NOTIFICATIONS/ACCESS_ERROR'); + NotificationI18N[Enums.Notification.ConnectionError] = Utils.i18n('NOTIFICATIONS/CONNECTION_ERROR'); + NotificationI18N[Enums.Notification.CaptchaError] = Utils.i18n('NOTIFICATIONS/CAPTCHA_ERROR'); + NotificationI18N[Enums.Notification.SocialFacebookLoginAccessDisable] = Utils.i18n('NOTIFICATIONS/SOCIAL_FACEBOOK_LOGIN_ACCESS_DISABLE'); + NotificationI18N[Enums.Notification.SocialTwitterLoginAccessDisable] = Utils.i18n('NOTIFICATIONS/SOCIAL_TWITTER_LOGIN_ACCESS_DISABLE'); + NotificationI18N[Enums.Notification.SocialGoogleLoginAccessDisable] = Utils.i18n('NOTIFICATIONS/SOCIAL_GOOGLE_LOGIN_ACCESS_DISABLE'); + NotificationI18N[Enums.Notification.DomainNotAllowed] = Utils.i18n('NOTIFICATIONS/DOMAIN_NOT_ALLOWED'); + NotificationI18N[Enums.Notification.AccountNotAllowed] = Utils.i18n('NOTIFICATIONS/ACCOUNT_NOT_ALLOWED'); + + NotificationI18N[Enums.Notification.AccountTwoFactorAuthRequired] = Utils.i18n('NOTIFICATIONS/ACCOUNT_TWO_FACTOR_AUTH_REQUIRED'); + NotificationI18N[Enums.Notification.AccountTwoFactorAuthError] = Utils.i18n('NOTIFICATIONS/ACCOUNT_TWO_FACTOR_AUTH_ERROR'); + + NotificationI18N[Enums.Notification.CouldNotSaveNewPassword] = Utils.i18n('NOTIFICATIONS/COULD_NOT_SAVE_NEW_PASSWORD'); + NotificationI18N[Enums.Notification.CurrentPasswordIncorrect] = Utils.i18n('NOTIFICATIONS/CURRENT_PASSWORD_INCORRECT'); + NotificationI18N[Enums.Notification.NewPasswordShort] = Utils.i18n('NOTIFICATIONS/NEW_PASSWORD_SHORT'); + NotificationI18N[Enums.Notification.NewPasswordWeak] = Utils.i18n('NOTIFICATIONS/NEW_PASSWORD_WEAK'); + NotificationI18N[Enums.Notification.NewPasswordForbidden] = Utils.i18n('NOTIFICATIONS/NEW_PASSWORD_FORBIDDENT'); + + NotificationI18N[Enums.Notification.ContactsSyncError] = Utils.i18n('NOTIFICATIONS/CONTACTS_SYNC_ERROR'); + + NotificationI18N[Enums.Notification.CantGetMessageList] = Utils.i18n('NOTIFICATIONS/CANT_GET_MESSAGE_LIST'); + NotificationI18N[Enums.Notification.CantGetMessage] = Utils.i18n('NOTIFICATIONS/CANT_GET_MESSAGE'); + NotificationI18N[Enums.Notification.CantDeleteMessage] = Utils.i18n('NOTIFICATIONS/CANT_DELETE_MESSAGE'); + NotificationI18N[Enums.Notification.CantMoveMessage] = Utils.i18n('NOTIFICATIONS/CANT_MOVE_MESSAGE'); + NotificationI18N[Enums.Notification.CantCopyMessage] = Utils.i18n('NOTIFICATIONS/CANT_MOVE_MESSAGE'); + + NotificationI18N[Enums.Notification.CantSaveMessage] = Utils.i18n('NOTIFICATIONS/CANT_SAVE_MESSAGE'); + NotificationI18N[Enums.Notification.CantSendMessage] = Utils.i18n('NOTIFICATIONS/CANT_SEND_MESSAGE'); + NotificationI18N[Enums.Notification.InvalidRecipients] = Utils.i18n('NOTIFICATIONS/INVALID_RECIPIENTS'); + + NotificationI18N[Enums.Notification.CantCreateFolder] = Utils.i18n('NOTIFICATIONS/CANT_CREATE_FOLDER'); + NotificationI18N[Enums.Notification.CantRenameFolder] = Utils.i18n('NOTIFICATIONS/CANT_RENAME_FOLDER'); + NotificationI18N[Enums.Notification.CantDeleteFolder] = Utils.i18n('NOTIFICATIONS/CANT_DELETE_FOLDER'); + NotificationI18N[Enums.Notification.CantDeleteNonEmptyFolder] = Utils.i18n('NOTIFICATIONS/CANT_DELETE_NON_EMPTY_FOLDER'); + NotificationI18N[Enums.Notification.CantSubscribeFolder] = Utils.i18n('NOTIFICATIONS/CANT_SUBSCRIBE_FOLDER'); + NotificationI18N[Enums.Notification.CantUnsubscribeFolder] = Utils.i18n('NOTIFICATIONS/CANT_UNSUBSCRIBE_FOLDER'); + + NotificationI18N[Enums.Notification.CantSaveSettings] = Utils.i18n('NOTIFICATIONS/CANT_SAVE_SETTINGS'); + NotificationI18N[Enums.Notification.CantSavePluginSettings] = Utils.i18n('NOTIFICATIONS/CANT_SAVE_PLUGIN_SETTINGS'); + + NotificationI18N[Enums.Notification.DomainAlreadyExists] = Utils.i18n('NOTIFICATIONS/DOMAIN_ALREADY_EXISTS'); + + NotificationI18N[Enums.Notification.CantInstallPackage] = Utils.i18n('NOTIFICATIONS/CANT_INSTALL_PACKAGE'); + NotificationI18N[Enums.Notification.CantDeletePackage] = Utils.i18n('NOTIFICATIONS/CANT_DELETE_PACKAGE'); + NotificationI18N[Enums.Notification.InvalidPluginPackage] = Utils.i18n('NOTIFICATIONS/INVALID_PLUGIN_PACKAGE'); + NotificationI18N[Enums.Notification.UnsupportedPluginPackage] = Utils.i18n('NOTIFICATIONS/UNSUPPORTED_PLUGIN_PACKAGE'); + + NotificationI18N[Enums.Notification.LicensingServerIsUnavailable] = Utils.i18n('NOTIFICATIONS/LICENSING_SERVER_IS_UNAVAILABLE'); + NotificationI18N[Enums.Notification.LicensingExpired] = Utils.i18n('NOTIFICATIONS/LICENSING_EXPIRED'); + NotificationI18N[Enums.Notification.LicensingBanned] = Utils.i18n('NOTIFICATIONS/LICENSING_BANNED'); + + NotificationI18N[Enums.Notification.DemoSendMessageError] = Utils.i18n('NOTIFICATIONS/DEMO_SEND_MESSAGE_ERROR'); + + NotificationI18N[Enums.Notification.AccountAlreadyExists] = Utils.i18n('NOTIFICATIONS/ACCOUNT_ALREADY_EXISTS'); + + NotificationI18N[Enums.Notification.MailServerError] = Utils.i18n('NOTIFICATIONS/MAIL_SERVER_ERROR'); + NotificationI18N[Enums.Notification.UnknownNotification] = Utils.i18n('NOTIFICATIONS/UNKNOWN_ERROR'); + NotificationI18N[Enums.Notification.UnknownError] = Utils.i18n('NOTIFICATIONS/UNKNOWN_ERROR'); +}; + +/** + * @param {*} mCode + * @return {string} + */ +Utils.getUploadErrorDescByCode = function (mCode) +{ + var sResult = ''; + switch (Utils.pInt(mCode)) { + case Enums.UploadErrorCode.FileIsTooBig: + sResult = Utils.i18n('UPLOAD/ERROR_FILE_IS_TOO_BIG'); + break; + case Enums.UploadErrorCode.FilePartiallyUploaded: + sResult = Utils.i18n('UPLOAD/ERROR_FILE_PARTIALLY_UPLOADED'); + break; + case Enums.UploadErrorCode.FileNoUploaded: + sResult = Utils.i18n('UPLOAD/ERROR_NO_FILE_UPLOADED'); + break; + case Enums.UploadErrorCode.MissingTempFolder: + sResult = Utils.i18n('UPLOAD/ERROR_MISSING_TEMP_FOLDER'); + break; + case Enums.UploadErrorCode.FileOnSaveingError: + sResult = Utils.i18n('UPLOAD/ERROR_ON_SAVING_FILE'); + break; + case Enums.UploadErrorCode.FileType: + sResult = Utils.i18n('UPLOAD/ERROR_FILE_TYPE'); + break; + default: + sResult = Utils.i18n('UPLOAD/ERROR_UNKNOWN'); + break; + } + + return sResult; +}; + +/** + * @param {?} oObject + * @param {string} sMethodName + * @param {Array=} aParameters + * @param {number=} nDelay + */ +Utils.delegateRun = function (oObject, sMethodName, aParameters, nDelay) +{ + if (oObject && oObject[sMethodName]) + { + nDelay = Utils.pInt(nDelay); + if (0 >= nDelay) + { + oObject[sMethodName].apply(oObject, Utils.isArray(aParameters) ? aParameters : []); + } + else + { + _.delay(function () { + oObject[sMethodName].apply(oObject, Utils.isArray(aParameters) ? aParameters : []); + }, nDelay); + } + } +}; + +/** + * @param {?} oEvent + */ +Utils.killCtrlAandS = function (oEvent) +{ + oEvent = oEvent || window.event; + if (oEvent && oEvent.ctrlKey && !oEvent.shiftKey && !oEvent.altKey) + { + var + oSender = oEvent.target || oEvent.srcElement, + iKey = oEvent.keyCode || oEvent.which + ; + + if (iKey === Enums.EventKeyCode.S) + { + oEvent.preventDefault(); + return; + } + + if (oSender && oSender.tagName && oSender.tagName.match(/INPUT|TEXTAREA/i)) + { + return; + } + + if (iKey === Enums.EventKeyCode.A) + { + if (window.getSelection) + { + window.getSelection().removeAllRanges(); + } + else if (window.document.selection && window.document.selection.clear) + { + window.document.selection.clear(); + } + + oEvent.preventDefault(); + } + } +}; + +/** + * @param {(Object|null|undefined)} oContext + * @param {Function} fExecute + * @param {(Function|boolean|null)=} fCanExecute + * @return {Function} + */ +Utils.createCommand = function (oContext, fExecute, fCanExecute) +{ + var + fResult = fExecute ? function () { + if (fResult.canExecute && fResult.canExecute()) + { + fExecute.apply(oContext, Array.prototype.slice.call(arguments)); + } + return false; + } : function () {} + ; + + fResult.enabled = ko.observable(true); + + fCanExecute = Utils.isUnd(fCanExecute) ? true : fCanExecute; + if (Utils.isFunc(fCanExecute)) + { + fResult.canExecute = ko.computed(function () { + return fResult.enabled() && fCanExecute.call(oContext); + }); + } + else + { + fResult.canExecute = ko.computed(function () { + return fResult.enabled() && !!fCanExecute; + }); + } + + return fResult; +}; + +/** + * @param {Object} oData + */ +Utils.initDataConstructorBySettings = function (oData) +{ + oData.editorDefaultType = ko.observable(Enums.EditorDefaultType.Html); + oData.showImages = ko.observable(false); + oData.interfaceAnimation = ko.observable(Enums.InterfaceAnimation.Full); + oData.contactsAutosave = ko.observable(false); + + Globals.sAnimationType = Enums.InterfaceAnimation.Full; + + oData.allowThemes = ko.observable(true); + oData.allowCustomLogin = ko.observable(false); + oData.allowLanguagesOnSettings = ko.observable(true); + oData.allowLanguagesOnLogin = ko.observable(true); + + oData.desktopNotifications = ko.observable(false); + oData.useThreads = ko.observable(true); + oData.replySameFolder = ko.observable(true); + oData.useCheckboxesInList = ko.observable(true); + + oData.layout = ko.observable(Enums.Layout.SidePreview); + oData.usePreviewPane = ko.computed(function () { + return Enums.Layout.NoPreview !== oData.layout(); + }); + + oData.interfaceAnimation.subscribe(function (sValue) { + if (Globals.bMobileDevice || sValue === Enums.InterfaceAnimation.None) + { + $html.removeClass('rl-anim rl-anim-full').addClass('no-rl-anim'); + + Globals.sAnimationType = Enums.InterfaceAnimation.None; + } + else + { + switch (sValue) + { + case Enums.InterfaceAnimation.Full: + $html.removeClass('no-rl-anim').addClass('rl-anim rl-anim-full'); + Globals.sAnimationType = sValue; + break; + case Enums.InterfaceAnimation.Normal: + $html.removeClass('no-rl-anim rl-anim-full').addClass('rl-anim'); + Globals.sAnimationType = sValue; + break; + } + } + }); + + oData.interfaceAnimation.valueHasMutated(); + + oData.desktopNotificationsPermisions = ko.computed(function () { + oData.desktopNotifications(); + var iResult = Enums.DesktopNotifications.NotSupported; + if (NotificationClass && NotificationClass.permission) + { + switch (NotificationClass.permission.toLowerCase()) + { + case 'granted': + iResult = Enums.DesktopNotifications.Allowed; + break; + case 'denied': + iResult = Enums.DesktopNotifications.Denied; + break; + case 'default': + iResult = Enums.DesktopNotifications.NotAllowed; + break; + } + } + else if (window.webkitNotifications && window.webkitNotifications.checkPermission) + { + iResult = window.webkitNotifications.checkPermission(); + } + + return iResult; + }); + + oData.useDesktopNotifications = ko.computed({ + 'read': function () { + return oData.desktopNotifications() && + Enums.DesktopNotifications.Allowed === oData.desktopNotificationsPermisions(); + }, + 'write': function (bValue) { + if (bValue) + { + var iPermission = oData.desktopNotificationsPermisions(); + if (Enums.DesktopNotifications.Allowed === iPermission) + { + oData.desktopNotifications(true); + } + else if (Enums.DesktopNotifications.NotAllowed === iPermission) + { + NotificationClass.requestPermission(function () { + oData.desktopNotifications.valueHasMutated(); + if (Enums.DesktopNotifications.Allowed === oData.desktopNotificationsPermisions()) + { + if (oData.desktopNotifications()) + { + oData.desktopNotifications.valueHasMutated(); + } + else + { + oData.desktopNotifications(true); + } + } + else + { + if (oData.desktopNotifications()) + { + oData.desktopNotifications(false); + } + else + { + oData.desktopNotifications.valueHasMutated(); + } + } + }); + } + else + { + oData.desktopNotifications(false); + } + } + else + { + oData.desktopNotifications(false); + } + } + }); + + oData.language = ko.observable(''); + oData.languages = ko.observableArray([]); + + oData.mainLanguage = ko.computed({ + 'read': oData.language, + 'write': function (sValue) { + if (sValue !== oData.language()) + { + if (-1 < Utils.inArray(sValue, oData.languages())) + { + oData.language(sValue); + } + else if (0 < oData.languages().length) + { + oData.language(oData.languages()[0]); + } + } + else + { + oData.language.valueHasMutated(); + } + } + }); + + oData.theme = ko.observable(''); + oData.themes = ko.observableArray([]); + + oData.mainTheme = ko.computed({ + 'read': oData.theme, + 'write': function (sValue) { + if (sValue !== oData.theme()) + { + var aThemes = oData.themes(); + if (-1 < Utils.inArray(sValue, aThemes)) + { + oData.theme(sValue); + } + else if (0 < aThemes.length) + { + oData.theme(aThemes[0]); + } + } + else + { + oData.theme.valueHasMutated(); + } + } + }); + + oData.allowAdditionalAccounts = ko.observable(false); + oData.allowIdentities = ko.observable(false); + oData.allowGravatar = ko.observable(false); + oData.determineUserLanguage = ko.observable(false); + + oData.messagesPerPage = ko.observable(Consts.Defaults.MessagesPerPage);//.extend({'throttle': 200}); + + oData.mainMessagesPerPage = oData.messagesPerPage; + oData.mainMessagesPerPage = ko.computed({ + 'read': oData.messagesPerPage, + 'write': function (iValue) { + if (-1 < Utils.inArray(Utils.pInt(iValue), Consts.Defaults.MessagesPerPageArray)) + { + if (iValue !== oData.messagesPerPage()) + { + oData.messagesPerPage(iValue); + } + } + else + { + oData.messagesPerPage.valueHasMutated(); + } + } + }); + + oData.facebookEnable = ko.observable(false); + oData.facebookAppID = ko.observable(''); + oData.facebookAppSecret = ko.observable(''); + + oData.twitterEnable = ko.observable(false); + oData.twitterConsumerKey = ko.observable(''); + oData.twitterConsumerSecret = ko.observable(''); + + oData.googleEnable = ko.observable(false); + oData.googleClientID = ko.observable(''); + oData.googleClientSecret = ko.observable(''); + + oData.dropboxEnable = ko.observable(false); + oData.dropboxApiKey = ko.observable(''); + + oData.contactsIsAllowed = ko.observable(false); +}; + +/** + * @param {{moment:Function}} oObject + */ +Utils.createMomentDate = function (oObject) +{ + if (Utils.isUnd(oObject.moment)) + { + oObject.moment = ko.observable(moment()); + } + + return ko.computed(function () { + Globals.momentTrigger(); + return this.moment().fromNow(); + }, oObject); +}; + +/** + * @param {{moment:Function, momentDate:Function}} oObject + */ +Utils.createMomentShortDate = function (oObject) +{ + return ko.computed(function () { + + var + sResult = '', + oMomentNow = moment(), + oMoment = this.moment(), + sMomentDate = this.momentDate() + ; + + if (4 >= oMomentNow.diff(oMoment, 'hours')) + { + sResult = sMomentDate; + } + else if (oMomentNow.format('L') === oMoment.format('L')) + { + sResult = Utils.i18n('MESSAGE_LIST/TODAY_AT', { + 'TIME': oMoment.format('LT') + }); + } + else if (oMomentNow.clone().subtract('days', 1).format('L') === oMoment.format('L')) + { + sResult = Utils.i18n('MESSAGE_LIST/YESTERDAY_AT', { + 'TIME': oMoment.format('LT') + }); + } + else if (oMomentNow.year() === oMoment.year()) + { + sResult = oMoment.format('D MMM.'); + } + else + { + sResult = oMoment.format('LL'); + } + + return sResult; + + }, oObject); +}; + +/** + * @param {string} sFullNameHash + * @return {boolean} + */ +Utils.isFolderExpanded = function (sFullNameHash) +{ + var aExpandedList = /** @type {Array|null} */ RL.local().get(Enums.ClientSideKeyName.ExpandedFolders); + return _.isArray(aExpandedList) && -1 !== _.indexOf(aExpandedList, sFullNameHash); +}; + +/** + * @param {string} sFullNameHash + * @param {boolean} bExpanded + */ +Utils.setExpandedFolder = function (sFullNameHash, bExpanded) +{ + var aExpandedList = /** @type {Array|null} */ RL.local().get(Enums.ClientSideKeyName.ExpandedFolders); + if (!_.isArray(aExpandedList)) + { + aExpandedList = []; + } + + if (bExpanded) + { + aExpandedList.push(sFullNameHash); + aExpandedList = _.uniq(aExpandedList); + } + else + { + aExpandedList = _.without(aExpandedList, sFullNameHash); + } + + RL.local().set(Enums.ClientSideKeyName.ExpandedFolders, aExpandedList); +}; + +Utils.initLayoutResizer = function (sLeft, sRight, sClientSideKeyName) +{ + var + iDisabledWidth = 65, + iMinWidth = 155, + oLeft = $(sLeft), + oRight = $(sRight), + + mLeftWidth = RL.local().get(sClientSideKeyName) || null, + + fSetWidth = function (iWidth) { + if (iWidth) + { + oLeft.css({ + 'width': '' + iWidth + 'px' + }); + + oRight.css({ + 'left': '' + iWidth + 'px' + }); + } + }, + + fDisable = function (bDisable) { + if (bDisable) + { + oLeft.resizable('disable'); + fSetWidth(iDisabledWidth); + } + else + { + oLeft.resizable('enable'); + var iWidth = Utils.pInt(RL.local().get(sClientSideKeyName)) || iMinWidth; + fSetWidth(iWidth > iMinWidth ? iWidth : iMinWidth); + } + }, + + fResizeFunction = function (oEvent, oObject) { + if (oObject && oObject.size && oObject.size.width) + { + RL.local().set(sClientSideKeyName, oObject.size.width); + + oRight.css({ + 'left': '' + oObject.size.width + 'px' + }); + } + } + ; + + if (null !== mLeftWidth) + { + fSetWidth(mLeftWidth > iMinWidth ? mLeftWidth : iMinWidth); + } + + oLeft.resizable({ + 'helper': 'ui-resizable-helper', + 'minWidth': iMinWidth, + 'maxWidth': 350, + 'handles': 'e', + 'stop': fResizeFunction + }); + + RL.sub('left-panel.off', function () { + fDisable(true); + }); + + RL.sub('left-panel.on', function () { + fDisable(false); + }); +}; + +/** + * @param {Object} oMessageTextBody + */ +Utils.initBlockquoteSwitcher = function (oMessageTextBody) +{ + if (oMessageTextBody) + { + var $oList = $('blockquote:not(.rl-bq-switcher)', oMessageTextBody).filter(function () { + return 0 === $(this).parent().closest('blockquote', oMessageTextBody).length; + }); + + if ($oList && 0 < $oList.length) + { + $oList.each(function () { + var $self = $(this), iH = $self.height(); + if (0 === iH || 100 < iH) + { + $self.addClass('rl-bq-switcher hidden-bq'); + $('') + .insertBefore($self) + .click(function () { + $self.toggleClass('hidden-bq'); + Utils.windowResize(); + }) + .after('
') + .before('
') + ; + } + }); + } + } +}; + +/** + * @param {Object} oMessageTextBody + */ +Utils.removeBlockquoteSwitcher = function (oMessageTextBody) +{ + if (oMessageTextBody) + { + $(oMessageTextBody).find('blockquote.rl-bq-switcher').each(function () { + $(this).removeClass('rl-bq-switcher hidden-bq'); + }); + + $(oMessageTextBody).find('.rlBlockquoteSwitcher').each(function () { + $(this).remove(); + }); + } +}; + +/** + * @param {Object} oMessageTextBody + */ +Utils.toggleMessageBlockquote = function (oMessageTextBody) +{ + if (oMessageTextBody) + { + oMessageTextBody.find('.rlBlockquoteSwitcher').click(); + } +}; + +/** + * @param {string} sName + * @param {Function} ViewModelClass + * @param {Function=} AbstractViewModel = KnoinAbstractViewModel + */ +Utils.extendAsViewModel = function (sName, ViewModelClass, AbstractViewModel) +{ + if (ViewModelClass) + { + if (!AbstractViewModel) + { + AbstractViewModel = KnoinAbstractViewModel; + } + + ViewModelClass.__name = sName; + Plugins.regViewModelHook(sName, ViewModelClass); + _.extend(ViewModelClass.prototype, AbstractViewModel.prototype); + } +}; + +/** + * @param {Function} SettingsViewModelClass + * @param {string} sLabelName + * @param {string} sTemplate + * @param {string} sRoute + * @param {boolean=} bDefault + */ +Utils.addSettingsViewModel = function (SettingsViewModelClass, sTemplate, sLabelName, sRoute, bDefault) +{ + SettingsViewModelClass.__rlSettingsData = { + 'Label': sLabelName, + 'Template': sTemplate, + 'Route': sRoute, + 'IsDefault': !!bDefault + }; + + ViewModels['settings'].push(SettingsViewModelClass); +}; + +/** + * @param {Function} SettingsViewModelClass + */ +Utils.removeSettingsViewModel = function (SettingsViewModelClass) +{ + ViewModels['settings-removed'].push(SettingsViewModelClass); +}; + +/** + * @param {Function} SettingsViewModelClass + */ +Utils.disableSettingsViewModel = function (SettingsViewModelClass) +{ + ViewModels['settings-disabled'].push(SettingsViewModelClass); +}; + +Utils.convertThemeName = function (sTheme) +{ + if ('@custom' === sTheme.substr(-7)) + { + sTheme = Utils.trim(sTheme.substring(0, sTheme.length - 7)); + } + + return Utils.trim(sTheme.replace(/[^a-zA-Z]+/g, ' ').replace(/([A-Z])/g, ' $1').replace(/[\s]+/g, ' ')); +}; + +/** + * @param {string} sName + * @return {string} + */ +Utils.quoteName = function (sName) +{ + return sName.replace(/["]/g, '\\"'); +}; + +/** + * @return {number} + */ +Utils.microtime = function () +{ + return (new Date()).getTime(); +}; + +/** + * + * @param {string} sLanguage + * @param {boolean=} bEng = false + * @return {string} + */ +Utils.convertLangName = function (sLanguage, bEng) +{ + return Utils.i18n('LANGS_NAMES' + (true === bEng ? '_EN' : '') + '/LANG_' + + sLanguage.toUpperCase().replace(/[^a-zA-Z0-9]+/, '_'), null, sLanguage); +}; + +/** + * @param {number=} iLen + * @return {string} + */ +Utils.fakeMd5 = function(iLen) +{ + var + sResult = '', + sLine = '0123456789abcdefghijklmnopqrstuvwxyz' + ; + + iLen = Utils.isUnd(iLen) ? 32 : Utils.pInt(iLen); + + while (sResult.length < iLen) + { + sResult += sLine.substr(Math.round(Math.random() * sLine.length), 1); + } + + return sResult; +}; + +/* jshint ignore:start */ + +/** + * @param {string} s + * @return {string} + */ +Utils.md5 = function(s){function L(k,d){return(k<>>(32-d))}function K(G,k){var I,d,F,H,x;F=(G&2147483648);H=(k&2147483648);I=(G&1073741824);d=(k&1073741824);x=(G&1073741823)+(k&1073741823);if(I&d){return(x^2147483648^F^H)}if(I|d){if(x&1073741824){return(x^3221225472^F^H)}else{return(x^1073741824^F^H)}}else{return(x^F^H)}}function r(d,F,k){return(d&F)|((~d)&k)}function q(d,F,k){return(d&k)|(F&(~k))}function p(d,F,k){return(d^F^k)}function n(d,F,k){return(F^(d|(~k)))}function u(G,F,aa,Z,k,H,I){G=K(G,K(K(r(F,aa,Z),k),I));return K(L(G,H),F)}function f(G,F,aa,Z,k,H,I){G=K(G,K(K(q(F,aa,Z),k),I));return K(L(G,H),F)}function D(G,F,aa,Z,k,H,I){G=K(G,K(K(p(F,aa,Z),k),I));return K(L(G,H),F)}function t(G,F,aa,Z,k,H,I){G=K(G,K(K(n(F,aa,Z),k),I));return K(L(G,H),F)}function e(G){var Z;var F=G.length;var x=F+8;var k=(x-(x%64))/64;var I=(k+1)*16;var aa=Array(I-1);var d=0;var H=0;while(H >>29;return aa}function B(x){var k="",F="",G,d;for(d=0;d<=3;d++){G=(x>>>(d*8))&255;F="0"+G.toString(16);k=k+F.substr(F.length-2,2)}return k}function J(k){k=k.replace(/rn/g,"n");var d="";for(var F=0;F 127)&&(x<2048)){d+=String.fromCharCode((x>>6)|192);d+=String.fromCharCode((x&63)|128)}else{d+=String.fromCharCode((x>>12)|224);d+=String.fromCharCode(((x>>6)&63)|128);d+=String.fromCharCode((x&63)|128)}}}return d}var C=Array();var P,h,E,v,g,Y,X,W,V;var S=7,Q=12,N=17,M=22;var A=5,z=9,y=14,w=20;var o=4,m=11,l=16,j=23;var U=6,T=10,R=15,O=21;s=J(s);C=e(s);Y=1732584193;X=4023233417;W=2562383102;V=271733878;for(P=0;P /g, '>').replace(/'); +}; + +Utils.draggeblePlace = function () +{ + return $(' ').appendTo('#rl-hidden'); +}; + +Utils.defautOptionsAfterRender = function (oOption, oItem) +{ + if (oItem && !Utils.isUnd(oItem.disabled) && oOption) + { + $(oOption) + .toggleClass('disabled', oItem.disabled) + .prop('disabled', oItem.disabled) + ; + } +}; + +/** + * @param {Object} oViewModel + * @param {string} sTemplateID + * @param {string} sTitle + * @param {Function=} fCallback + */ +Utils.windowPopupKnockout = function (oViewModel, sTemplateID, sTitle, fCallback) +{ + var + oScript = null, + oWin = window.open(''), + sFunc = '__OpenerApplyBindingsUid' + Utils.fakeMd5() + '__', + oTemplate = $('#' + sTemplateID) + ; + + window[sFunc] = function () { + + if (oWin && oWin.document.body && oTemplate && oTemplate[0]) + { + var oBody = $(oWin.document.body); + + $('#rl-content', oBody).html(oTemplate.html()); + $('html', oWin.document).addClass('external ' + $('html').attr('class')); + + Utils.i18nToNode(oBody); + + Knoin.prototype.applyExternal(oViewModel, $('#rl-content', oBody)[0]); + + window[sFunc] = null; + + fCallback(oWin); + } + }; + + oWin.document.open(); + oWin.document.write('' + +'' + +'' + +'' + +'' + +'' + +'' + Utils.encodeHtml(sTitle) + ' ' + +''); + oWin.document.close(); + + oScript = oWin.document.createElement('script'); + oScript.type = 'text/javascript'; + oScript.innerHTML = 'if(window&&window.opener&&window.opener[\'' + sFunc + '\']){window.opener[\'' + sFunc + '\']();window.opener[\'' + sFunc + '\']=null}'; + oWin.document.getElementsByTagName('head')[0].appendChild(oScript); +}; + +Utils.settingsSaveHelperFunction = function (fCallback, koTrigger, oContext, iTimer) +{ + oContext = oContext || null; + iTimer = Utils.isUnd(iTimer) ? 1000 : Utils.pInt(iTimer); + return function (sType, mData, bCached, sRequestAction, oRequestParameters) { + koTrigger.call(oContext, mData && mData['Result'] ? Enums.SaveSettingsStep.TrueResult : Enums.SaveSettingsStep.FalseResult); + if (fCallback) + { + fCallback.call(oContext, sType, mData, bCached, sRequestAction, oRequestParameters); + } + _.delay(function () { + koTrigger.call(oContext, Enums.SaveSettingsStep.Idle); + }, iTimer); + }; +}; + +Utils.settingsSaveHelperSimpleFunction = function (koTrigger, oContext) +{ + return Utils.settingsSaveHelperFunction(null, koTrigger, oContext, 1000); +}; + + +/** + * @param {string} sHtml + * @return {string} + */ +Utils.htmlToPlain = function (sHtml) +{ + var + sText = '', + sQuoteChar = '> ', + + convertBlockquote = function () { + if (arguments && 1 < arguments.length) + { + var sText = $.trim(arguments[1]) + .replace(/__bq__start__(.|[\s\S\n\r]*)__bq__end__/gm, convertBlockquote) + ; + + sText = '\n' + sQuoteChar + $.trim(sText).replace(/\n/gm, '\n' + sQuoteChar) + '\n>\n'; + + return sText.replace(/\n([> ]+)/gm, function () { + return (arguments && 1 < arguments.length) ? '\n' + $.trim(arguments[1].replace(/[\s]/, '')) + ' ' : ''; + }); + } + + return ''; + }, + + convertDivs = function () { + if (arguments && 1 < arguments.length) + { + var sText = $.trim(arguments[1]); + if (0 < sText.length) + { + sText = sText.replace(/]*>(.|[\s\S\r\n]*)<\/div>/gmi, convertDivs); + sText = '\n' + $.trim(sText) + '\n'; + } + return sText; + } + return ''; + }, + + fixAttibuteValue = function () { + if (arguments && 1 < arguments.length) + { + return '' + arguments[1] + arguments[2].replace(//g, '>'); + } + + return ''; + }, + + convertLinks = function () { + if (arguments && 1 < arguments.length) + { + var + sName = $.trim(arguments[1]) +// sHref = $.trim(arguments[0].replace(//gmi, '$1')) + ; + + return sName; +// sName = (0 === trim(sName).length) ? '' : sName; +// sHref = ('mailto:' === sHref.substr(0, 7)) ? '' : sHref; +// sHref = ('http' === sHref.substr(0, 4)) ? sHref : ''; +// sHref = (sName === sHref) ? '' : sHref; +// sHref = (0 < sHref.length) ? ' (' + sHref + ') ' : ''; +// return (0 < sName.length) ? sName + sHref : sName; + } + return ''; + } + ; + + sText = sHtml + .replace(/[\s]+/gm, ' ') + .replace(/((?:href|data)\s?=\s?)("[^"]+?"|'[^']+?')/gmi, fixAttibuteValue) + .replace(/
/gmi, '\n') + .replace(/<\/h\d>/gi, '\n') + .replace(/<\/p>/gi, '\n\n') + .replace(/<\/li>/gi, '\n') + .replace(/<\/td>/gi, '\n') + .replace(/<\/tr>/gi, '\n') + .replace(/
]*>/gmi, '\n_______________________________\n\n') + .replace(/]*>/gmi, '') + .replace(/
]*>(.|[\s\S\r\n]*)<\/div>/gmi, convertDivs) + .replace(/]*>/gmi, '\n__bq__start__\n') + .replace(/<\/blockquote>/gmi, '\n__bq__end__\n') + .replace(/]*>(.|[\s\S\r\n]*)<\/a>/gmi, convertLinks) + .replace(/ /gi, ' ') + .replace(/<[^>]*>/gm, '') + .replace(/>/gi, '>') + .replace(/</gi, '<') + .replace(/&/gi, '&') + .replace(/&\w{2,6};/gi, '') + ; + + return sText + .replace(/\n[ \t]+/gm, '\n') + .replace(/[\n]{3,}/gm, '\n\n') + .replace(/__bq__start__(.|[\s\S\r\n]*)__bq__end__/gm, convertBlockquote) + .replace(/__bq__start__/gm, '') + .replace(/__bq__end__/gm, '') + ; +}; + +/** + * @param {string} sPlain + * @return {string} + */ +Utils.plainToHtml = function (sPlain) +{ + return sPlain.toString() + .replace(/&/g, '&').replace(/>/g, '>').replace(/'); +}; + +Utils.resizeAndCrop = function (sUrl, iValue, fCallback) +{ + var oTempImg = new window.Image(); + oTempImg.onload = function() { + + var + aDiff = [0, 0], + oCanvas = document.createElement('canvas'), + oCtx = oCanvas.getContext('2d') + ; + + oCanvas.width = iValue; + oCanvas.height = iValue; + + if (this.width > this.height) + { + aDiff = [this.width - this.height, 0]; + } + else + { + aDiff = [0, this.height - this.width]; + } + + oCtx.fillStyle = '#fff'; + oCtx.fillRect(0, 0, iValue, iValue); + oCtx.drawImage(this, aDiff[0] / 2, aDiff[1] / 2, this.width - aDiff[0], this.height - aDiff[1], 0, 0, iValue, iValue); + + fCallback(oCanvas.toDataURL('image/jpeg')); + }; + + oTempImg.src = sUrl; +}; + +Utils.computedPagenatorHelper = function (koCurrentPage, koPageCount) +{ + return function() { + var + iPrev = 0, + iNext = 0, + iLimit = 2, + aResult = [], + iCurrentPage = koCurrentPage(), + iPageCount = koPageCount(), + + /** + * @param {number} iIndex + * @param {boolean=} bPush + * @param {string=} sCustomName + */ + fAdd = function (iIndex, bPush, sCustomName) { + + var oData = { + 'current': iIndex === iCurrentPage, + 'name': Utils.isUnd(sCustomName) ? iIndex.toString() : sCustomName.toString(), + 'custom': Utils.isUnd(sCustomName) ? false : true, + 'title': Utils.isUnd(sCustomName) ? '' : iIndex.toString(), + 'value': iIndex.toString() + }; + + if (Utils.isUnd(bPush) ? true : !!bPush) + { + aResult.push(oData); + } + else + { + aResult.unshift(oData); + } + } + ; + + if (1 < iPageCount || (0 < iPageCount && iPageCount < iCurrentPage)) +// if (0 < iPageCount && 0 < iCurrentPage) + { + if (iPageCount < iCurrentPage) + { + fAdd(iPageCount); + iPrev = iPageCount; + iNext = iPageCount; + } + else + { + if (3 >= iCurrentPage || iPageCount - 2 <= iCurrentPage) + { + iLimit += 2; + } + + fAdd(iCurrentPage); + iPrev = iCurrentPage; + iNext = iCurrentPage; + } + + while (0 < iLimit) { + + iPrev -= 1; + iNext += 1; + + if (0 < iPrev) + { + fAdd(iPrev, false); + iLimit--; + } + + if (iPageCount >= iNext) + { + fAdd(iNext, true); + iLimit--; + } + else if (0 >= iPrev) + { + break; + } + } + + if (3 === iPrev) + { + fAdd(2, false); + } + else if (3 < iPrev) + { + fAdd(Math.round((iPrev - 1) / 2), false, '...'); + } + + if (iPageCount - 2 === iNext) + { + fAdd(iPageCount - 1, true); + } + else if (iPageCount - 2 > iNext) + { + fAdd(Math.round((iPageCount + iNext) / 2), true, '...'); + } + + // first and last + if (1 < iPrev) + { + fAdd(1, false); + } + + if (iPageCount > iNext) + { + fAdd(iPageCount, true); + } + } + + return aResult; + }; +}; + +Utils.selectElement = function (element) +{ + /* jshint onevar: false */ + if (window.getSelection) + { + var sel = window.getSelection(); + sel.removeAllRanges(); + var range = document.createRange(); + range.selectNodeContents(element); + sel.addRange(range); + } + else if (document.selection) + { + var textRange = document.body.createTextRange(); + textRange.moveToElementText(element); + textRange.select(); + } + /* jshint onevar: true */ +}; + +Utils.disableKeyFilter = function () +{ + if (window.key) + { + key.filter = function () { + return RL.data().useKeyboardShortcuts(); + }; + } +}; + +Utils.restoreKeyFilter = function () +{ + if (window.key) + { + key.filter = function (event) { + + if (RL.data().useKeyboardShortcuts()) + { + var + element = event.target || event.srcElement, + tagName = element ? element.tagName : '' + ; + + tagName = tagName.toUpperCase(); + return !(tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA' || + (element && tagName === 'DIV' && 'editorHtmlArea' === element.className && element.contentEditable) + ); + } + + return false; + }; + } +}; + +Utils.detectDropdownVisibility = _.debounce(function () { + Globals.dropdownVisibility(!!_.find(BootstrapDropdowns, function (oItem) { + return oItem.hasClass('open'); + })); +}, 50); +// Base64 encode / decode +// http://www.webtoolkit.info/ + +Base64 = { + + // private property + _keyStr : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', + + // public method for urlsafe encoding + urlsafe_encode : function (input) { + return Base64.encode(input).replace(/[+]/g, '-').replace(/[\/]/g, '_').replace(/[=]/g, '.'); + }, + + // public method for encoding + encode : function (input) { + var + output = '', + chr1, chr2, chr3, enc1, enc2, enc3, enc4, + i = 0 + ; + + input = Base64._utf8_encode(input); + + while (i < input.length) + { + chr1 = input.charCodeAt(i++); + chr2 = input.charCodeAt(i++); + chr3 = input.charCodeAt(i++); + + enc1 = chr1 >> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); + enc4 = chr3 & 63; + + if (isNaN(chr2)) + { + enc3 = enc4 = 64; + } + else if (isNaN(chr3)) + { + enc4 = 64; + } + + output = output + + this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + + this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4); + } + + return output; + }, + + // public method for decoding + decode : function (input) { + var + output = '', + chr1, chr2, chr3, enc1, enc2, enc3, enc4, + i = 0 + ; + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ''); + + while (i < input.length) + { + enc1 = this._keyStr.indexOf(input.charAt(i++)); + enc2 = this._keyStr.indexOf(input.charAt(i++)); + enc3 = this._keyStr.indexOf(input.charAt(i++)); + enc4 = this._keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output = output + String.fromCharCode(chr1); + + if (enc3 !== 64) + { + output = output + String.fromCharCode(chr2); + } + + if (enc4 !== 64) + { + output = output + String.fromCharCode(chr3); + } + } + + return Base64._utf8_decode(output); + }, + + // private method for UTF-8 encoding + _utf8_encode : function (string) { + + string = string.replace(/\r\n/g, "\n"); + + var + utftext = '', + n = 0, + l = string.length, + c = 0 + ; + + for (; n < l; n++) { + + c = string.charCodeAt(n); + + if (c < 128) + { + utftext += String.fromCharCode(c); + } + else if ((c > 127) && (c < 2048)) + { + utftext += String.fromCharCode((c >> 6) | 192); + utftext += String.fromCharCode((c & 63) | 128); + } + else + { + utftext += String.fromCharCode((c >> 12) | 224); + utftext += String.fromCharCode(((c >> 6) & 63) | 128); + utftext += String.fromCharCode((c & 63) | 128); + } + } + + return utftext; + }, + + // private method for UTF-8 decoding + _utf8_decode : function (utftext) { + var + string = '', + i = 0, + c = 0, + c2 = 0, + c3 = 0 + ; + + while ( i < utftext.length ) + { + c = utftext.charCodeAt(i); + + if (c < 128) + { + string += String.fromCharCode(c); + i++; + } + else if((c > 191) && (c < 224)) + { + c2 = utftext.charCodeAt(i+1); + string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); + i += 2; + } + else + { + c2 = utftext.charCodeAt(i+1); + c3 = utftext.charCodeAt(i+2); + string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + i += 3; + } + } + + return string; + } +}; + /*jslint bitwise: false*/ -ko.bindingHandlers.tooltip = { - 'init': function (oElement, fValueAccessor) { - if (!Globals.bMobileDevice) - { - var - $oEl = $(oElement), - sClass = $oEl.data('tooltip-class') || '', - sPlacement = $oEl.data('tooltip-placement') || 'top' - ; - - $oEl.tooltip({ - 'delay': { - 'show': 500, - 'hide': 100 - }, - 'html': true, - 'container': 'body', - 'placement': sPlacement, - 'trigger': 'hover', - 'title': function () { - return $oEl.is('.disabled') || Globals.dropdownVisibility() ? '' : '' + - Utils.i18n(ko.utils.unwrapObservable(fValueAccessor())) + ''; - } - }).click(function () { - $oEl.tooltip('hide'); - }); - - Globals.dropdownVisibility.subscribe(function (bValue) { - if (bValue) - { - $oEl.tooltip('hide'); - } - }); - } - } -}; - -ko.bindingHandlers.tooltip2 = { - 'init': function (oElement, fValueAccessor) { - var - $oEl = $(oElement), - sClass = $oEl.data('tooltip-class') || '', - sPlacement = $oEl.data('tooltip-placement') || 'top' - ; - - $oEl.tooltip({ - 'delay': { - 'show': 500, - 'hide': 100 - }, - 'html': true, - 'container': 'body', - 'placement': sPlacement, - 'title': function () { - return $oEl.is('.disabled') || Globals.dropdownVisibility() ? '' : - '' + fValueAccessor()() + ''; - } - }).click(function () { - $oEl.tooltip('hide'); - }); - - Globals.dropdownVisibility.subscribe(function (bValue) { - if (bValue) - { - $oEl.tooltip('hide'); - } - }); - } -}; - -ko.bindingHandlers.tooltip3 = { - 'init': function (oElement) { - - var $oEl = $(oElement); - - $oEl.tooltip({ - 'container': 'body', - 'trigger': 'hover manual', - 'title': function () { - return $oEl.data('tooltip3-data') || ''; - } - }); - - Globals.dropdownVisibility.subscribe(function (bValue) { - if (bValue) - { - $oEl.tooltip('hide'); - } - }); - - $document.click(function () { - $oEl.tooltip('hide'); - }); - - }, - 'update': function (oElement, fValueAccessor) { - var sValue = ko.utils.unwrapObservable(fValueAccessor()); - if ('' === sValue) - { - $(oElement).data('tooltip3-data', '').tooltip('hide'); - } - else - { - $(oElement).data('tooltip3-data', sValue).tooltip('show'); - } - } -}; - -ko.bindingHandlers.registrateBootstrapDropdown = { - 'init': function (oElement) { - BootstrapDropdowns.push($(oElement)); - } -}; - -ko.bindingHandlers.openDropdownTrigger = { - 'update': function (oElement, fValueAccessor) { - if (ko.utils.unwrapObservable(fValueAccessor())) - { - var $el = $(oElement); - if (!$el.hasClass('open')) - { - $el.find('.dropdown-toggle').dropdown('toggle'); - Utils.detectDropdownVisibility(); - } - - fValueAccessor()(false); - } - } -}; - -ko.bindingHandlers.dropdownCloser = { - 'init': function (oElement) { - $(oElement).closest('.dropdown').on('click', '.e-item', function () { - $(oElement).dropdown('toggle'); - }); - } -}; - -ko.bindingHandlers.popover = { - 'init': function (oElement, fValueAccessor) { - $(oElement).popover(ko.utils.unwrapObservable(fValueAccessor())); - } -}; - -ko.bindingHandlers.csstext = { - 'init': function (oElement, fValueAccessor) { - if (oElement && oElement.styleSheet && !Utils.isUnd(oElement.styleSheet.cssText)) - { - oElement.styleSheet.cssText = ko.utils.unwrapObservable(fValueAccessor()); - } - else - { - $(oElement).text(ko.utils.unwrapObservable(fValueAccessor())); - } - }, - 'update': function (oElement, fValueAccessor) { - if (oElement && oElement.styleSheet && !Utils.isUnd(oElement.styleSheet.cssText)) - { - oElement.styleSheet.cssText = ko.utils.unwrapObservable(fValueAccessor()); - } - else - { - $(oElement).text(ko.utils.unwrapObservable(fValueAccessor())); - } - } -}; - -ko.bindingHandlers.resizecrop = { - 'init': function (oElement) { - $(oElement).addClass('resizecrop').resizecrop({ - 'width': '100', - 'height': '100', - 'wrapperCSS': { - 'border-radius': '10px' - } - }); - }, - 'update': function (oElement, fValueAccessor) { - fValueAccessor()(); - $(oElement).resizecrop({ - 'width': '100', - 'height': '100' - }); - } -}; - -ko.bindingHandlers.onEnter = { - 'init': function (oElement, fValueAccessor, fAllBindingsAccessor, oViewModel) { - $(oElement).on('keypress', function (oEvent) { - if (oEvent && 13 === window.parseInt(oEvent.keyCode, 10)) - { - $(oElement).trigger('change'); - fValueAccessor().call(oViewModel); - } - }); - } -}; - -ko.bindingHandlers.onEsc = { - 'init': function (oElement, fValueAccessor, fAllBindingsAccessor, oViewModel) { - $(oElement).on('keypress', function (oEvent) { - if (oEvent && 27 === window.parseInt(oEvent.keyCode, 10)) - { - $(oElement).trigger('change'); - fValueAccessor().call(oViewModel); - } - }); - } -}; - -ko.bindingHandlers.clickOnTrue = { - 'update': function (oElement, fValueAccessor) { - if (ko.utils.unwrapObservable(fValueAccessor())) - { - $(oElement).click(); - } - } -}; - -ko.bindingHandlers.modal = { - 'init': function (oElement, fValueAccessor) { - - $(oElement).toggleClass('fade', !Globals.bMobileDevice).modal({ - 'keyboard': false, - 'show': ko.utils.unwrapObservable(fValueAccessor()) - }) - .on('shown', function () { - Utils.windowResize(); - }) - .find('.close').click(function () { - fValueAccessor()(false); - }); - }, - 'update': function (oElement, fValueAccessor) { - $(oElement).modal(ko.utils.unwrapObservable(fValueAccessor()) ? 'show' : 'hide'); - } -}; - -ko.bindingHandlers.i18nInit = { - 'init': function (oElement) { - Utils.i18nToNode(oElement); - } -}; - -ko.bindingHandlers.i18nUpdate = { - 'update': function (oElement, fValueAccessor) { - ko.utils.unwrapObservable(fValueAccessor()); - Utils.i18nToNode(oElement); - } -}; - -ko.bindingHandlers.link = { - 'update': function (oElement, fValueAccessor) { - $(oElement).attr('href', ko.utils.unwrapObservable(fValueAccessor())); - } -}; - -ko.bindingHandlers.title = { - 'update': function (oElement, fValueAccessor) { - $(oElement).attr('title', ko.utils.unwrapObservable(fValueAccessor())); - } -}; - -ko.bindingHandlers.textF = { - 'init': function (oElement, fValueAccessor) { - $(oElement).text(ko.utils.unwrapObservable(fValueAccessor())); - } -}; - -ko.bindingHandlers.initDom = { - 'init': function (oElement, fValueAccessor) { - fValueAccessor()(oElement); - } -}; - -ko.bindingHandlers.initResizeTrigger = { - 'init': function (oElement, fValueAccessor) { - var aValues = ko.utils.unwrapObservable(fValueAccessor()); - $(oElement).css({ - 'height': aValues[1], - 'min-height': aValues[1] - }); - }, - 'update': function (oElement, fValueAccessor) { - var - aValues = ko.utils.unwrapObservable(fValueAccessor()), - iValue = Utils.pInt(aValues[1]), - iSize = 0, - iOffset = $(oElement).offset().top - ; - - if (0 < iOffset) - { - iOffset += Utils.pInt(aValues[2]); - iSize = $window.height() - iOffset; - - if (iValue < iSize) - { - iValue = iSize; - } - - $(oElement).css({ - 'height': iValue, - 'min-height': iValue - }); - } - } -}; - -ko.bindingHandlers.appendDom = { - 'update': function (oElement, fValueAccessor) { - $(oElement).hide().empty().append(ko.utils.unwrapObservable(fValueAccessor())).show(); - } -}; - -ko.bindingHandlers.draggable = { - 'init': function (oElement, fValueAccessor, fAllBindingsAccessor) { - - if (!Globals.bMobileDevice) - { - var - iTriggerZone = 100, - iScrollSpeed = 3, - fAllValueFunc = fAllBindingsAccessor(), - sDroppableSelector = fAllValueFunc && fAllValueFunc['droppableSelector'] ? fAllValueFunc['droppableSelector'] : '', - oConf = { - 'distance': 20, - 'handle': '.dragHandle', - 'cursorAt': {'top': 22, 'left': 3}, - 'refreshPositions': true, - 'scroll': true - } - ; - - if (sDroppableSelector) - { - oConf['drag'] = function (oEvent) { - - $(sDroppableSelector).each(function () { - var - moveUp = null, - moveDown = null, - $this = $(this), - oOffset = $this.offset(), - bottomPos = oOffset.top + $this.height() - ; - - window.clearInterval($this.data('timerScroll')); - $this.data('timerScroll', false); - - if (oEvent.pageX >= oOffset.left && oEvent.pageX <= oOffset.left + $this.width()) - { - if (oEvent.pageY >= bottomPos - iTriggerZone && oEvent.pageY <= bottomPos) - { - moveUp = function() { - $this.scrollTop($this.scrollTop() + iScrollSpeed); - Utils.windowResize(); - }; - - $this.data('timerScroll', window.setInterval(moveUp, 10)); - moveUp(); - } - - if (oEvent.pageY >= oOffset.top && oEvent.pageY <= oOffset.top + iTriggerZone) - { - moveDown = function() { - $this.scrollTop($this.scrollTop() - iScrollSpeed); - Utils.windowResize(); - }; - - $this.data('timerScroll', window.setInterval(moveDown, 10)); - moveDown(); - } - } - }); - }; - - oConf['stop'] = function() { - $(sDroppableSelector).each(function () { - window.clearInterval($(this).data('timerScroll')); - $(this).data('timerScroll', false); - }); - }; - } - - oConf['helper'] = function (oEvent) { - return fValueAccessor()(oEvent && oEvent.target ? ko.dataFor(oEvent.target) : null); - }; - - $(oElement).draggable(oConf).on('mousedown', function () { - Utils.removeInFocus(); - }); - } - } -}; - -ko.bindingHandlers.droppable = { - 'init': function (oElement, fValueAccessor, fAllBindingsAccessor) { - - if (!Globals.bMobileDevice) - { - var - fValueFunc = fValueAccessor(), - fAllValueFunc = fAllBindingsAccessor(), - fOverCallback = fAllValueFunc && fAllValueFunc['droppableOver'] ? fAllValueFunc['droppableOver'] : null, - fOutCallback = fAllValueFunc && fAllValueFunc['droppableOut'] ? fAllValueFunc['droppableOut'] : null, - oConf = { - 'tolerance': 'pointer', - 'hoverClass': 'droppableHover' - } - ; - - if (fValueFunc) - { - oConf['drop'] = function (oEvent, oUi) { - fValueFunc(oEvent, oUi); - }; - - if (fOverCallback) - { - oConf['over'] = function (oEvent, oUi) { - fOverCallback(oEvent, oUi); - }; - } - - if (fOutCallback) - { - oConf['out'] = function (oEvent, oUi) { - fOutCallback(oEvent, oUi); - }; - } - - $(oElement).droppable(oConf); - } - } - } -}; - -ko.bindingHandlers.nano = { - 'init': function (oElement) { - if (!Globals.bDisableNanoScroll) - { - $(oElement) - .addClass('nano') - .nanoScroller({ - 'iOSNativeScrolling': false, - 'preventPageScrolling': true - }) - ; - } - } -}; - -ko.bindingHandlers.saveTrigger = { - 'init': function (oElement) { - - var $oEl = $(oElement); - - $oEl.data('save-trigger-type', $oEl.is('input[type=text],input[type=email],input[type=password],select,textarea') ? 'input' : 'custom'); - - if ('custom' === $oEl.data('save-trigger-type')) - { - $oEl.append( - ' ' - ).addClass('settings-saved-trigger'); - } - else - { - $oEl.addClass('settings-saved-trigger-input'); - } - }, - 'update': function (oElement, fValueAccessor) { - var - mValue = ko.utils.unwrapObservable(fValueAccessor()), - $oEl = $(oElement) - ; - - if ('custom' === $oEl.data('save-trigger-type')) - { - switch (mValue.toString()) - { - case '1': - $oEl - .find('.animated,.error').hide().removeClass('visible') - .end() - .find('.success').show().addClass('visible') - ; - break; - case '0': - $oEl - .find('.animated,.success').hide().removeClass('visible') - .end() - .find('.error').show().addClass('visible') - ; - break; - case '-2': - $oEl - .find('.error,.success').hide().removeClass('visible') - .end() - .find('.animated').show().addClass('visible') - ; - break; - default: - $oEl - .find('.animated').hide() - .end() - .find('.error,.success').removeClass('visible') - ; - break; - } - } - else - { - switch (mValue.toString()) - { - case '1': - $oEl.addClass('success').removeClass('error'); - break; - case '0': - $oEl.addClass('error').removeClass('success'); - break; - case '-2': -// $oEl; - break; - default: - $oEl.removeClass('error success'); - break; - } - } - } -}; - -ko.bindingHandlers.emailsTags = { - 'init': function(oElement, fValueAccessor) { - var - $oEl = $(oElement), - fValue = fValueAccessor() - ; - - $oEl.inputosaurus({ - 'parseOnBlur': true, - 'inputDelimiters': [',', ';'], - 'autoCompleteSource': function (oData, fResponse) { - RL.getAutocomplete(oData.term, function (aData) { - fResponse(_.map(aData, function (oEmailItem) { - return oEmailItem.toLine(false); - })); - }); - }, - 'parseHook': function (aInput) { - return _.map(aInput, function (sInputValue) { - - var - sValue = Utils.trim(sInputValue), - oEmail = null - ; - - if ('' !== sValue) - { - oEmail = new EmailModel(); - oEmail.mailsoParse(sValue); - oEmail.clearDuplicateName(); - return [oEmail.toLine(false), oEmail]; - } - - return [sValue, null]; - - }); - }, - 'change': _.bind(function (oEvent) { - $oEl.data('EmailsTagsValue', oEvent.target.value); - fValue(oEvent.target.value); - }, this) - }); - - fValue.subscribe(function (sValue) { - if ($oEl.data('EmailsTagsValue') !== sValue) - { - $oEl.val(sValue); - $oEl.data('EmailsTagsValue', sValue); - $oEl.inputosaurus('refresh'); - } - }); - - if (fValue.focusTrigger) - { - fValue.focusTrigger.subscribe(function () { - $oEl.inputosaurus('focus'); - }); - } - } -}; - -ko.bindingHandlers.command = { - 'init': function (oElement, fValueAccessor, fAllBindingsAccessor, oViewModel) { - var - jqElement = $(oElement), - oCommand = fValueAccessor() - ; - - if (!oCommand || !oCommand.enabled || !oCommand.canExecute) - { - throw new Error('You are not using command function'); - } - - jqElement.addClass('command'); - ko.bindingHandlers[jqElement.is('form') ? 'submit' : 'click'].init.apply(oViewModel, arguments); - }, - - 'update': function (oElement, fValueAccessor) { - - var - bResult = true, - jqElement = $(oElement), - oCommand = fValueAccessor() - ; - - bResult = oCommand.enabled(); - jqElement.toggleClass('command-not-enabled', !bResult); - - if (bResult) - { - bResult = oCommand.canExecute(); - jqElement.toggleClass('command-can-not-be-execute', !bResult); - } - - jqElement.toggleClass('command-disabled disable disabled', !bResult).toggleClass('no-disabled', !!bResult); - - if (jqElement.is('input') || jqElement.is('button')) - { - jqElement.prop('disabled', !bResult); - } - } -}; - -ko.extenders.trimmer = function (oTarget) -{ - var oResult = ko.computed({ - 'read': oTarget, - 'write': function (sNewValue) { - oTarget(Utils.trim(sNewValue.toString())); - }, - 'owner': this - }); - - oResult(oTarget()); - return oResult; -}; - -ko.extenders.reversible = function (oTarget) -{ - var mValue = oTarget(); - - oTarget.commit = function () - { - mValue = oTarget(); - }; - - oTarget.reverse = function () - { - oTarget(mValue); - }; - - oTarget.commitedValue = function () - { - return mValue; - }; - - return oTarget; -}; - -ko.extenders.toggleSubscribe = function (oTarget, oOptions) -{ - oTarget.subscribe(oOptions[1], oOptions[0], 'beforeChange'); - oTarget.subscribe(oOptions[2], oOptions[0]); - - return oTarget; -}; - -ko.extenders.falseTimeout = function (oTarget, iOption) -{ - oTarget.iTimeout = 0; - oTarget.subscribe(function (bValue) { - if (bValue) - { - window.clearTimeout(oTarget.iTimeout); - oTarget.iTimeout = window.setTimeout(function () { - oTarget(false); - oTarget.iTimeout = 0; - }, Utils.pInt(iOption)); - } - }); - - return oTarget; -}; - -ko.observable.fn.validateNone = function () -{ - this.hasError = ko.observable(false); - return this; -}; - -ko.observable.fn.validateEmail = function () -{ - this.hasError = ko.observable(false); - - this.subscribe(function (sValue) { - sValue = Utils.trim(sValue); - this.hasError('' !== sValue && !(/^[^@\s]+@[^@\s]+$/.test(sValue))); - }, this); - - this.valueHasMutated(); - return this; -}; - -ko.observable.fn.validateSimpleEmail = function () -{ - this.hasError = ko.observable(false); - - this.subscribe(function (sValue) { - sValue = Utils.trim(sValue); - this.hasError('' !== sValue && !(/^.+@.+$/.test(sValue))); - }, this); - - this.valueHasMutated(); - return this; -}; - -ko.observable.fn.validateFunc = function (fFunc) -{ - this.hasFuncError = ko.observable(false); - - if (Utils.isFunc(fFunc)) - { - this.subscribe(function (sValue) { - this.hasFuncError(!fFunc(sValue)); - }, this); - - this.valueHasMutated(); - } - - return this; -}; - +ko.bindingHandlers.tooltip = { + 'init': function (oElement, fValueAccessor) { + if (!Globals.bMobileDevice) + { + var + $oEl = $(oElement), + sClass = $oEl.data('tooltip-class') || '', + sPlacement = $oEl.data('tooltip-placement') || 'top' + ; -/** - * @constructor - */ -function LinkBuilder() -{ - this.sBase = '#/'; - this.sVersion = RL.settingsGet('Version'); - this.sSpecSuffix = RL.settingsGet('AuthAccountHash') || '0'; - this.sServer = (RL.settingsGet('IndexFile') || './') + '?'; -} - -/** - * @return {string} - */ -LinkBuilder.prototype.root = function () -{ - return this.sBase; -}; - -/** - * @param {string} sDownload - * @return {string} - */ -LinkBuilder.prototype.attachmentDownload = function (sDownload) -{ - return this.sServer + '/Raw/' + this.sSpecSuffix + '/Download/' + sDownload; -}; - -/** - * @param {string} sDownload - * @return {string} - */ -LinkBuilder.prototype.attachmentPreview = function (sDownload) -{ - return this.sServer + '/Raw/' + this.sSpecSuffix + '/View/' + sDownload; -}; - -/** - * @param {string} sDownload - * @return {string} - */ -LinkBuilder.prototype.attachmentPreviewAsPlain = function (sDownload) -{ - return this.sServer + '/Raw/' + this.sSpecSuffix + '/ViewAsPlain/' + sDownload; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.upload = function () -{ - return this.sServer + '/Upload/' + this.sSpecSuffix + '/'; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.uploadContacts = function () -{ - return this.sServer + '/UploadContacts/' + this.sSpecSuffix + '/'; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.uploadBackground = function () -{ - return this.sServer + '/UploadBackground/' + this.sSpecSuffix + '/'; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.append = function () -{ - return this.sServer + '/Append/' + this.sSpecSuffix + '/'; -}; - -/** - * @param {string} sEmail - * @return {string} - */ -LinkBuilder.prototype.change = function (sEmail) -{ - return this.sServer + '/Change/' + this.sSpecSuffix + '/' + window.encodeURIComponent(sEmail) + '/'; -}; - -/** - * @param {string=} sAdd - * @return {string} - */ -LinkBuilder.prototype.ajax = function (sAdd) -{ - return this.sServer + '/Ajax/' + this.sSpecSuffix + '/' + sAdd; -}; - -/** - * @param {string} sRequestHash - * @return {string} - */ -LinkBuilder.prototype.messageViewLink = function (sRequestHash) -{ - return this.sServer + '/Raw/' + this.sSpecSuffix + '/ViewAsPlain/' + sRequestHash; -}; - -/** - * @param {string} sRequestHash - * @return {string} - */ -LinkBuilder.prototype.messageDownloadLink = function (sRequestHash) -{ - return this.sServer + '/Raw/' + this.sSpecSuffix + '/Download/' + sRequestHash; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.inbox = function () -{ - return this.sBase + 'mailbox/Inbox'; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.messagePreview = function () -{ - return this.sBase + 'mailbox/message-preview'; -}; - -/** - * @param {string=} sScreenName - * @return {string} - */ -LinkBuilder.prototype.settings = function (sScreenName) -{ - var sResult = this.sBase + 'settings'; - if (!Utils.isUnd(sScreenName) && '' !== sScreenName) - { - sResult += '/' + sScreenName; - } - - return sResult; -}; - -/** - * @param {string} sScreenName - * @return {string} - */ -LinkBuilder.prototype.admin = function (sScreenName) -{ - var sResult = this.sBase; - switch (sScreenName) { - case 'AdminDomains': - sResult += 'domains'; - break; - case 'AdminSecurity': - sResult += 'security'; - break; - case 'AdminLicensing': - sResult += 'licensing'; - break; - } - - return sResult; -}; - -/** - * @param {string} sFolder - * @param {number=} iPage = 1 - * @param {string=} sSearch = '' - * @return {string} - */ -LinkBuilder.prototype.mailBox = function (sFolder, iPage, sSearch) -{ - iPage = Utils.isNormal(iPage) ? Utils.pInt(iPage) : 1; - sSearch = Utils.pString(sSearch); - - var sResult = this.sBase + 'mailbox/'; - if ('' !== sFolder) - { - sResult += encodeURI(sFolder); - } - if (1 < iPage) - { - sResult = sResult.replace(/[\/]+$/, ''); - sResult += '/p' + iPage; - } - if ('' !== sSearch) - { - sResult = sResult.replace(/[\/]+$/, ''); - sResult += '/' + encodeURI(sSearch); - } - - return sResult; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.phpInfo = function () -{ - return this.sServer + 'Info'; -}; - -/** - * @param {string} sLang - * @return {string} - */ -LinkBuilder.prototype.langLink = function (sLang) -{ - return this.sServer + '/Lang/0/' + encodeURI(sLang) + '/' + this.sVersion + '/'; -}; - -/** - * @param {string} sHash - * @return {string} - */ -LinkBuilder.prototype.getUserPicUrlFromHash = function (sHash) -{ - return this.sServer + '/Raw/' + this.sSpecSuffix + '/UserPic/' + sHash + '/' + this.sVersion + '/'; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.exportContactsVcf = function () -{ - return this.sServer + '/Raw/' + this.sSpecSuffix + '/ContactsVcf/'; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.exportContactsCsv = function () -{ - return this.sServer + '/Raw/' + this.sSpecSuffix + '/ContactsCsv/'; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.emptyContactPic = function () -{ - return 'rainloop/v/' + this.sVersion + '/static/css/images/empty-contact.png'; -}; - -/** - * @param {string} sFileName - * @return {string} - */ -LinkBuilder.prototype.sound = function (sFileName) -{ - return 'rainloop/v/' + this.sVersion + '/static/sounds/' + sFileName; -}; - -/** - * @param {string} sTheme - * @return {string} - */ -LinkBuilder.prototype.themePreviewLink = function (sTheme) -{ - var sPrefix = 'rainloop/v/' + this.sVersion + '/'; - if ('@custom' === sTheme.substr(-7)) - { - sTheme = Utils.trim(sTheme.substring(0, sTheme.length - 7)); - sPrefix = ''; - } - - return sPrefix + 'themes/' + encodeURI(sTheme) + '/images/preview.png'; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.notificationMailIcon = function () -{ - return 'rainloop/v/' + this.sVersion + '/static/css/images/icom-message-notification.png'; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.openPgpJs = function () -{ - return 'rainloop/v/' + this.sVersion + '/static/js/openpgp.min.js'; -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.socialGoogle = function () -{ - return this.sServer + 'SocialGoogle' + ('' !== this.sSpecSuffix ? '/' + this.sSpecSuffix + '/' : ''); -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.socialTwitter = function () -{ - return this.sServer + 'SocialTwitter' + ('' !== this.sSpecSuffix ? '/' + this.sSpecSuffix + '/' : ''); -}; - -/** - * @return {string} - */ -LinkBuilder.prototype.socialFacebook = function () -{ - return this.sServer + 'SocialFacebook' + ('' !== this.sSpecSuffix ? '/' + this.sSpecSuffix + '/' : ''); -}; + $oEl.tooltip({ + 'delay': { + 'show': 500, + 'hide': 100 + }, + 'html': true, + 'container': 'body', + 'placement': sPlacement, + 'trigger': 'hover', + 'title': function () { + return $oEl.is('.disabled') || Globals.dropdownVisibility() ? '' : '' + + Utils.i18n(ko.utils.unwrapObservable(fValueAccessor())) + ''; + } + }).click(function () { + $oEl.tooltip('hide'); + }); -/** - * @type {Object} - */ -Plugins.oViewModelsHooks = {}; - -/** - * @type {Object} - */ -Plugins.oSimpleHooks = {}; - -/** - * @param {string} sName - * @param {Function} ViewModel - */ -Plugins.regViewModelHook = function (sName, ViewModel) -{ - if (ViewModel) - { - ViewModel.__hookName = sName; - } -}; - -/** - * @param {string} sName - * @param {Function} fCallback - */ -Plugins.addHook = function (sName, fCallback) -{ - if (Utils.isFunc(fCallback)) - { - if (!Utils.isArray(Plugins.oSimpleHooks[sName])) - { - Plugins.oSimpleHooks[sName] = []; - } - - Plugins.oSimpleHooks[sName].push(fCallback); - } -}; - -/** - * @param {string} sName - * @param {Array=} aArguments - */ -Plugins.runHook = function (sName, aArguments) -{ - if (Utils.isArray(Plugins.oSimpleHooks[sName])) - { - aArguments = aArguments || []; - - _.each(Plugins.oSimpleHooks[sName], function (fCallback) { - fCallback.apply(null, aArguments); - }); - } -}; - -/** - * @param {string} sName - * @return {?} - */ -Plugins.mainSettingsGet = function (sName) -{ - return RL ? RL.settingsGet(sName) : null; -}; - -/** - * @param {Function} fCallback - * @param {string} sAction - * @param {Object=} oParameters - * @param {?number=} iTimeout - * @param {string=} sGetAdd = '' - * @param {Array=} aAbortActions = [] - */ -Plugins.remoteRequest = function (fCallback, sAction, oParameters, iTimeout, sGetAdd, aAbortActions) -{ - if (RL) - { - RL.remote().defaultRequest(fCallback, sAction, oParameters, iTimeout, sGetAdd, aAbortActions); - } -}; - -/** - * @param {string} sPluginSection - * @param {string} sName - * @return {?} - */ -Plugins.settingsGet = function (sPluginSection, sName) -{ - var oPlugin = Plugins.mainSettingsGet('Plugins'); - oPlugin = oPlugin && Utils.isUnd(oPlugin[sPluginSection]) ? null : oPlugin[sPluginSection]; - return oPlugin ? (Utils.isUnd(oPlugin[sName]) ? null : oPlugin[sName]) : null; -}; - - - -function NewHtmlEditorWrapper(oElement, fOnBlur, fOnReady, fOnModeChange) -{ - var self = this; - self.editor = null; - self.iBlurTimer = 0; - self.fOnBlur = fOnBlur || null; - self.fOnReady = fOnReady || null; - self.fOnModeChange = fOnModeChange || null; - - self.$element = $(oElement); - - self.init(); -} - -NewHtmlEditorWrapper.prototype.blurTrigger = function () -{ - if (this.fOnBlur) - { - var self = this; - window.clearTimeout(self.iBlurTimer); - self.iBlurTimer = window.setTimeout(function () { - self.fOnBlur(); - }, 200); - } -}; - -NewHtmlEditorWrapper.prototype.focusTrigger = function () -{ - if (this.fOnBlur) - { - window.clearTimeout(this.iBlurTimer); - } -}; - -/** - * @return {boolean} - */ -NewHtmlEditorWrapper.prototype.isHtml = function () -{ - return this.editor ? 'wysiwyg' === this.editor.mode : false; -}; - -/** - * @return {boolean} - */ -NewHtmlEditorWrapper.prototype.checkDirty = function () -{ - return this.editor ? this.editor.checkDirty() : false; -}; - -NewHtmlEditorWrapper.prototype.resetDirty = function () -{ - if (this.editor) - { - this.editor.resetDirty(); - } -}; - -/** - * @return {string} - */ -NewHtmlEditorWrapper.prototype.getData = function () -{ - if (this.editor) - { - if ('plain' === this.editor.mode && this.editor.plugins.plain && this.editor.__plain) - { - return this.editor.__plain.getRawData(); - } - - return this.editor.getData(); - } - - return ''; -}; - -NewHtmlEditorWrapper.prototype.modeToggle = function (bPlain) -{ - if (this.editor) - { - if (bPlain) - { - if ('plain' === this.editor.mode) - { - this.editor.setMode('wysiwyg'); - } - } - else - { - if ('wysiwyg' === this.editor.mode) - { - this.editor.setMode('plain'); - } - } - } -}; - -NewHtmlEditorWrapper.prototype.setHtml = function (sHtml, bFocus) -{ - if (this.editor) - { - this.modeToggle(true); - this.editor.setData(sHtml); - - if (bFocus) - { - this.focus(); - } - } -}; - -NewHtmlEditorWrapper.prototype.setPlain = function (sPlain, bFocus) -{ - if (this.editor) - { - this.modeToggle(false); - if ('plain' === this.editor.mode && this.editor.plugins.plain && this.editor.__plain) - { - return this.editor.__plain.setRawData(sPlain); - } - else - { - this.editor.setData(sPlain); - } - - if (bFocus) - { - this.focus(); - } - } -}; - -NewHtmlEditorWrapper.prototype.init = function () -{ - if (this.$element && this.$element[0]) - { - var - self = this, - oConfig = Globals.oHtmlEditorDefaultConfig, - sLanguage = RL.settingsGet('Language'), - bSource = !!RL.settingsGet('AllowHtmlEditorSourceButton') - ; - - if (bSource && oConfig.toolbarGroups && !oConfig.toolbarGroups.__SourceInited) - { - oConfig.toolbarGroups.__SourceInited = true; - oConfig.toolbarGroups.push({name: 'document', groups: ['mode', 'document', 'doctools']}); - } - - oConfig.language = Globals.oHtmlEditorLangsMap[sLanguage] || 'en'; - self.editor = window.CKEDITOR.appendTo(self.$element[0], oConfig); - - self.editor.on('key', function(oEvent) { - if (oEvent && oEvent.data && 9 === oEvent.data.keyCode) - { - return false; - } - }); - - self.editor.on('blur', function() { - self.blurTrigger(); - }); - - self.editor.on('mode', function() { - self.blurTrigger(); - - if (self.fOnModeChange) - { - self.fOnModeChange('plain' !== self.editor.mode); - } - }); - - self.editor.on('focus', function() { - self.focusTrigger(); - }); - - if (self.fOnReady) - { - self.editor.on('instanceReady', function () { - - self.editor.setKeystroke(window.CKEDITOR.CTRL + 65 /* A */, 'selectAll'); - - self.fOnReady(); - self.__resizable = true; - self.resize(); - }); - } - } -}; - -NewHtmlEditorWrapper.prototype.focus = function () -{ - if (this.editor) - { - this.editor.focus(); - } -}; - -NewHtmlEditorWrapper.prototype.blur = function () -{ - if (this.editor) - { - this.editor.focusManager.blur(true); - } -}; - -NewHtmlEditorWrapper.prototype.resize = function () -{ - if (this.editor && this.__resizable) - { - this.editor.resize(this.$element.width(), this.$element.innerHeight()); - } -}; - -NewHtmlEditorWrapper.prototype.clear = function (bFocus) -{ - this.setHtml('', bFocus); -}; - - -/** - * @constructor - * @param {koProperty} oKoList - * @param {koProperty} oKoSelectedItem - * @param {string} sItemSelector - * @param {string} sItemSelectedSelector - * @param {string} sItemCheckedSelector - * @param {string} sItemFocusedSelector - */ -function Selector(oKoList, oKoSelectedItem, - sItemSelector, sItemSelectedSelector, sItemCheckedSelector, sItemFocusedSelector) -{ - this.list = oKoList; - - this.listChecked = ko.computed(function () { - return _.filter(this.list(), function (oItem) { - return oItem.checked(); - }); - }, this).extend({'rateLimit': 0}); - - this.isListChecked = ko.computed(function () { - return 0 < this.listChecked().length; - }, this); - - this.focusedItem = ko.observable(null); - this.selectedItem = oKoSelectedItem; - this.selectedItemUseCallback = true; - - this.itemSelectedThrottle = _.debounce(_.bind(this.itemSelected, this), 300); - - this.listChecked.subscribe(function (aItems) { - if (0 < aItems.length) - { - if (null === this.selectedItem()) - { - this.selectedItem.valueHasMutated(); - } - else - { - this.selectedItem(null); - } - } - else if (this.bAutoSelect && this.focusedItem()) - { - this.selectedItem(this.focusedItem()); - } - }, this); - - this.selectedItem.subscribe(function (oItem) { - - if (oItem) - { - if (this.isListChecked()) - { - _.each(this.listChecked(), function (oSubItem) { - oSubItem.checked(false); - }); - } - - if (this.selectedItemUseCallback) - { - this.itemSelectedThrottle(oItem); - } - } - else if (this.selectedItemUseCallback) - { - this.itemSelected(null); - } - - }, this); - - this.selectedItem.extend({'toggleSubscribe': [null, - function (oPrev) { - if (oPrev) - { - oPrev.selected(false); - } - }, function (oNext) { - if (oNext) - { - oNext.selected(true); - } - } - ]}); - - this.focusedItem.extend({'toggleSubscribe': [null, - function (oPrev) { - if (oPrev) - { - oPrev.focused(false); - } - }, function (oNext) { - if (oNext) - { - oNext.focused(true); - } - } - ]}); - - this.oContentVisible = null; - this.oContentScrollable = null; - - this.sItemSelector = sItemSelector; - this.sItemSelectedSelector = sItemSelectedSelector; - this.sItemCheckedSelector = sItemCheckedSelector; - this.sItemFocusedSelector = sItemFocusedSelector; - - this.sLastUid = ''; - this.bAutoSelect = true; - this.oCallbacks = {}; - - this.emptyFunction = function () {}; - - this.focusedItem.subscribe(function (oItem) { - if (oItem) - { - this.sLastUid = this.getItemUid(oItem); - } - }, this); - - var - aCache = [], - aCheckedCache = [], - mFocused = null, - mSelected = null - ; - - this.list.subscribe(function (aItems) { - - var self = this; - if (Utils.isArray(aItems)) - { - _.each(aItems, function (oItem) { - if (oItem) - { - var sUid = self.getItemUid(oItem); - - aCache.push(sUid); - if (oItem.checked()) - { - aCheckedCache.push(sUid); - } - if (null === mFocused && oItem.focused()) - { - mFocused = sUid; - } - if (null === mSelected && oItem.selected()) - { - mSelected = sUid; - } - } - }); - } - }, this, 'beforeChange'); - - this.list.subscribe(function (aItems) { - - var - self = this, - oTemp = null, - bGetNext = false, - aUids = [], - mNextFocused = mFocused, - bChecked = false, - bSelected = false, - iLen = 0 - ; - - this.selectedItemUseCallback = false; - - this.focusedItem(null); - this.selectedItem(null); - - if (Utils.isArray(aItems)) - { - iLen = aCheckedCache.length; - - _.each(aItems, function (oItem) { - - var sUid = self.getItemUid(oItem); - aUids.push(sUid); - - if (null !== mFocused && mFocused === sUid) - { - self.focusedItem(oItem); - mFocused = null; - } - - if (0 < iLen && -1 < Utils.inArray(sUid, aCheckedCache)) - { - bChecked = true; - oItem.checked(true); - iLen--; - } - - if (!bChecked && null !== mSelected && mSelected === sUid) - { - bSelected = true; - self.selectedItem(oItem); - mSelected = null; - } - }); - - this.selectedItemUseCallback = true; - - if (!bChecked && !bSelected && this.bAutoSelect) - { - if (self.focusedItem()) - { - self.selectedItem(self.focusedItem()); - } - else if (0 < aItems.length) - { - if (null !== mNextFocused) - { - bGetNext = false; - mNextFocused = _.find(aCache, function (sUid) { - if (bGetNext && -1 < Utils.inArray(sUid, aUids)) - { - return sUid; - } - else if (mNextFocused === sUid) - { - bGetNext = true; - } - return false; - }); - - if (mNextFocused) - { - oTemp = _.find(aItems, function (oItem) { - return mNextFocused === self.getItemUid(oItem); - }); - } - } - - self.selectedItem(oTemp || null); - self.focusedItem(self.selectedItem()); - } - } - } - - aCache = []; - aCheckedCache = []; - mFocused = null; - mSelected = null; - - }, this); -} - -Selector.prototype.itemSelected = function (oItem) -{ - if (this.isListChecked()) - { - if (!oItem) - { - (this.oCallbacks['onItemSelect'] || this.emptyFunction)(oItem || null); - } - } - else - { - if (oItem) - { - (this.oCallbacks['onItemSelect'] || this.emptyFunction)(oItem); - } - } -}; - -Selector.prototype.goDown = function (bForceSelect) -{ - this.newSelectPosition(Enums.EventKeyCode.Down, false, bForceSelect); -}; - -Selector.prototype.goUp = function (bForceSelect) -{ - this.newSelectPosition(Enums.EventKeyCode.Up, false, bForceSelect); -}; - -Selector.prototype.init = function (oContentVisible, oContentScrollable, sKeyScope) -{ - this.oContentVisible = oContentVisible; - this.oContentScrollable = oContentScrollable; - - sKeyScope = sKeyScope || 'all'; - - if (this.oContentVisible && this.oContentScrollable) - { - var - self = this - ; - - $(this.oContentVisible) - .on('selectstart', function (oEvent) { - if (oEvent && oEvent.preventDefault) - { - oEvent.preventDefault(); - } - }) - .on('click', this.sItemSelector, function (oEvent) { - self.actionClick(ko.dataFor(this), oEvent); - }) - .on('click', this.sItemCheckedSelector, function (oEvent) { - var oItem = ko.dataFor(this); - if (oItem) - { - if (oEvent && oEvent.shiftKey) - { - self.actionClick(oItem, oEvent); - } - else - { - self.focusedItem(oItem); - oItem.checked(!oItem.checked()); - } - } - }) - ; - - key('enter', sKeyScope, function () { - if (self.focusedItem() && !self.focusedItem().selected()) - { - self.actionClick(self.focusedItem()); - return false; - } - - return true; - }); - - key('ctrl+up, command+up, ctrl+down, command+down', sKeyScope, function () { - return false; - }); - - key('up, shift+up, down, shift+down, home, end, pageup, pagedown, insert, space', sKeyScope, function (event, handler) { - if (event && handler && handler.shortcut) - { - // TODO - var iKey = 0; - switch (handler.shortcut) - { - case 'up': - case 'shift+up': - iKey = Enums.EventKeyCode.Up; - break; - case 'down': - case 'shift+down': - iKey = Enums.EventKeyCode.Down; - break; - case 'insert': - iKey = Enums.EventKeyCode.Insert; - break; - case 'space': - iKey = Enums.EventKeyCode.Space; - break; - case 'home': - iKey = Enums.EventKeyCode.Home; - break; - case 'end': - iKey = Enums.EventKeyCode.End; - break; - case 'pageup': - iKey = Enums.EventKeyCode.PageUp; - break; - case 'pagedown': - iKey = Enums.EventKeyCode.PageDown; - break; - } - - if (0 < iKey) - { - self.newSelectPosition(iKey, key.shift); - return false; - } - } - }); - } -}; - -Selector.prototype.autoSelect = function (bValue) -{ - this.bAutoSelect = !!bValue; -}; - -/** - * @param {Object} oItem - * @returns {string} - */ -Selector.prototype.getItemUid = function (oItem) -{ - var - sUid = '', - fGetItemUidCallback = this.oCallbacks['onItemGetUid'] || null - ; - - if (fGetItemUidCallback && oItem) - { - sUid = fGetItemUidCallback(oItem); - } - - return sUid.toString(); -}; - -/** - * @param {number} iEventKeyCode - * @param {boolean} bShiftKey - * @param {boolean=} bForceSelect = false - */ -Selector.prototype.newSelectPosition = function (iEventKeyCode, bShiftKey, bForceSelect) -{ - var - iIndex = 0, - iPageStep = 10, - bNext = false, - bStop = false, - oResult = null, - aList = this.list(), - iListLen = aList ? aList.length : 0, - oFocused = this.focusedItem() - ; - - if (0 < iListLen) - { - if (!oFocused) - { - if (Enums.EventKeyCode.Down === iEventKeyCode || Enums.EventKeyCode.Insert === iEventKeyCode || Enums.EventKeyCode.Space === iEventKeyCode || Enums.EventKeyCode.Home === iEventKeyCode || Enums.EventKeyCode.PageUp === iEventKeyCode) - { - oResult = aList[0]; - } - else if (Enums.EventKeyCode.Up === iEventKeyCode || Enums.EventKeyCode.End === iEventKeyCode || Enums.EventKeyCode.PageDown === iEventKeyCode) - { - oResult = aList[aList.length - 1]; - } - } - else if (oFocused) - { - if (Enums.EventKeyCode.Down === iEventKeyCode || Enums.EventKeyCode.Up === iEventKeyCode || Enums.EventKeyCode.Insert === iEventKeyCode || Enums.EventKeyCode.Space === iEventKeyCode) - { - _.each(aList, function (oItem) { - if (!bStop) - { - switch (iEventKeyCode) { - case Enums.EventKeyCode.Up: - if (oFocused === oItem) - { - bStop = true; - } - else - { - oResult = oItem; - } - break; - case Enums.EventKeyCode.Down: - case Enums.EventKeyCode.Insert: - if (bNext) - { - oResult = oItem; - bStop = true; - } - else if (oFocused === oItem) - { - bNext = true; - } - break; - } - } - }); - } - else if (Enums.EventKeyCode.Home === iEventKeyCode || Enums.EventKeyCode.End === iEventKeyCode) - { - if (Enums.EventKeyCode.Home === iEventKeyCode) - { - oResult = aList[0]; - } - else if (Enums.EventKeyCode.End === iEventKeyCode) - { - oResult = aList[aList.length - 1]; - } - } - else if (Enums.EventKeyCode.PageDown === iEventKeyCode) - { - for (; iIndex < iListLen; iIndex++) - { - if (oFocused === aList[iIndex]) - { - iIndex += iPageStep; - iIndex = iListLen - 1 < iIndex ? iListLen - 1 : iIndex; - oResult = aList[iIndex]; - break; - } - } - } - else if (Enums.EventKeyCode.PageUp === iEventKeyCode) - { - for (iIndex = iListLen; iIndex >= 0; iIndex--) - { - if (oFocused === aList[iIndex]) - { - iIndex -= iPageStep; - iIndex = 0 > iIndex ? 0 : iIndex; - oResult = aList[iIndex]; - break; - } - } - } - } - } - - if (oResult) - { - this.focusedItem(oResult); - - if (oFocused) - { - if (bShiftKey) - { - if (Enums.EventKeyCode.Up === iEventKeyCode || Enums.EventKeyCode.Down === iEventKeyCode) - { - oFocused.checked(!oFocused.checked()); - } - } - else if (Enums.EventKeyCode.Insert === iEventKeyCode || Enums.EventKeyCode.Space === iEventKeyCode) - { - oFocused.checked(!oFocused.checked()); - } - } - - if ((this.bAutoSelect || !!bForceSelect) && - !this.isListChecked() && Enums.EventKeyCode.Space !== iEventKeyCode) - { - this.selectedItem(oResult); - } - - this.scrollToFocused(); - } - else if (oFocused) - { - if (bShiftKey && (Enums.EventKeyCode.Up === iEventKeyCode || Enums.EventKeyCode.Down === iEventKeyCode)) - { - oFocused.checked(!oFocused.checked()); - } - else if (Enums.EventKeyCode.Insert === iEventKeyCode || Enums.EventKeyCode.Space === iEventKeyCode) - { - oFocused.checked(!oFocused.checked()); - } - - this.focusedItem(oFocused); - } -}; - -/** - * @return {boolean} - */ -Selector.prototype.scrollToFocused = function () -{ - if (!this.oContentVisible || !this.oContentScrollable) - { - return false; - } - - var - iOffset = 20, - oFocused = $(this.sItemFocusedSelector, this.oContentScrollable), - oPos = oFocused.position(), - iVisibleHeight = this.oContentVisible.height(), - iFocusedHeight = oFocused.outerHeight() - ; - - if (oPos && (oPos.top < 0 || oPos.top + iFocusedHeight > iVisibleHeight)) - { - if (oPos.top < 0) - { - this.oContentScrollable.scrollTop(this.oContentScrollable.scrollTop() + oPos.top - iOffset); - } - else - { - this.oContentScrollable.scrollTop(this.oContentScrollable.scrollTop() + oPos.top - iVisibleHeight + iFocusedHeight + iOffset); - } - - return true; - } - - return false; -}; - -/** - * @param {boolean=} bFast = false - * @return {boolean} - */ -Selector.prototype.scrollToTop = function (bFast) -{ - if (!this.oContentVisible || !this.oContentScrollable) - { - return false; - } - - if (bFast) - { - this.oContentScrollable.scrollTop(0); - } - else - { - this.oContentScrollable.stop().animate({'scrollTop': 0}, 200); - } - - return true; -}; - -Selector.prototype.eventClickFunction = function (oItem, oEvent) -{ - var - sUid = this.getItemUid(oItem), - iIndex = 0, - iLength = 0, - oListItem = null, - sLineUid = '', - bChangeRange = false, - bIsInRange = false, - aList = [], - bChecked = false - ; - - if (oEvent && oEvent.shiftKey) - { - if ('' !== sUid && '' !== this.sLastUid && sUid !== this.sLastUid) - { - aList = this.list(); - bChecked = oItem.checked(); - - for (iIndex = 0, iLength = aList.length; iIndex < iLength; iIndex++) - { - oListItem = aList[iIndex]; - sLineUid = this.getItemUid(oListItem); - - bChangeRange = false; - if (sLineUid === this.sLastUid || sLineUid === sUid) - { - bChangeRange = true; - } - - if (bChangeRange) - { - bIsInRange = !bIsInRange; - } - - if (bIsInRange || bChangeRange) - { - oListItem.checked(bChecked); - } - } - } - } - - this.sLastUid = '' === sUid ? '' : sUid; -}; - -/** - * @param {Object} oItem - * @param {Object=} oEvent - */ -Selector.prototype.actionClick = function (oItem, oEvent) -{ - if (oItem) - { - var - bClick = true, - sUid = this.getItemUid(oItem) - ; - - if (oEvent) - { - if (oEvent.shiftKey && !oEvent.ctrlKey && !oEvent.altKey) - { - bClick = false; - if ('' === this.sLastUid) - { - this.sLastUid = sUid; - } - - oItem.checked(!oItem.checked()); - this.eventClickFunction(oItem, oEvent); - - this.focusedItem(oItem); - } - else if (oEvent.ctrlKey && !oEvent.shiftKey && !oEvent.altKey) - { - bClick = false; - this.focusedItem(oItem); - - if (this.selectedItem() && oItem !== this.selectedItem()) - { - this.selectedItem().checked(true); - } - - oItem.checked(!oItem.checked()); - } - } - - if (bClick) - { - this.focusedItem(oItem); - this.selectedItem(oItem); - } - } -}; - -Selector.prototype.on = function (sEventName, fCallback) -{ - this.oCallbacks[sEventName] = fCallback; -}; - -/** - * @constructor - */ -function CookieDriver() -{ - -} - -CookieDriver.supported = function () -{ - return true; -}; - -/** - * @param {string} sKey - * @param {*} mData - * @returns {boolean} - */ -CookieDriver.prototype.set = function (sKey, mData) -{ - var - mCokieValue = $.cookie(Consts.Values.ClientSideCookieIndexName), - bResult = false, - mResult = null - ; - - try - { - mResult = null === mCokieValue ? null : JSON.parse(mCokieValue); - if (!mResult) - { - mResult = {}; - } - - mResult[sKey] = mData; - $.cookie(Consts.Values.ClientSideCookieIndexName, JSON.stringify(mResult), { - 'expires': 30 - }); - - bResult = true; - } - catch (oException) {} - - return bResult; -}; - -/** - * @param {string} sKey - * @returns {*} - */ -CookieDriver.prototype.get = function (sKey) -{ - var - mCokieValue = $.cookie(Consts.Values.ClientSideCookieIndexName), - mResult = null - ; - - try - { - mResult = null === mCokieValue ? null : JSON.parse(mCokieValue); - if (mResult && !Utils.isUnd(mResult[sKey])) - { - mResult = mResult[sKey]; - } - else - { - mResult = null; - } - } - catch (oException) {} - - return mResult; -}; - -/** - * @constructor - */ -function LocalStorageDriver() -{ -} - -LocalStorageDriver.supported = function () -{ - return !!window.localStorage; -}; - -/** - * @param {string} sKey - * @param {*} mData - * @returns {boolean} - */ -LocalStorageDriver.prototype.set = function (sKey, mData) -{ - var - mCookieValue = window.localStorage[Consts.Values.ClientSideCookieIndexName] || null, - bResult = false, - mResult = null - ; - - try - { - mResult = null === mCookieValue ? null : JSON.parse(mCookieValue); - if (!mResult) - { - mResult = {}; - } - - mResult[sKey] = mData; - window.localStorage[Consts.Values.ClientSideCookieIndexName] = JSON.stringify(mResult); - - bResult = true; - } - catch (oException) {} - - return bResult; -}; - -/** - * @param {string} sKey - * @returns {*} - */ -LocalStorageDriver.prototype.get = function (sKey) -{ - var - mCokieValue = window.localStorage[Consts.Values.ClientSideCookieIndexName] || null, - mResult = null - ; - - try - { - mResult = null === mCokieValue ? null : JSON.parse(mCokieValue); - if (mResult && !Utils.isUnd(mResult[sKey])) - { - mResult = mResult[sKey]; - } - else - { - mResult = null; - } - } - catch (oException) {} - - return mResult; -}; - -/** - * @constructor - */ -function LocalStorage() -{ - var - sStorages = [ - LocalStorageDriver, - CookieDriver - ], - NextStorageDriver = _.find(sStorages, function (NextStorageDriver) { - return NextStorageDriver.supported(); - }) - ; - - if (NextStorageDriver) - { - NextStorageDriver = /** @type {?Function} */ NextStorageDriver; - this.oDriver = new NextStorageDriver(); - } -} - -LocalStorage.prototype.oDriver = null; - -/** - * @param {number} iKey - * @param {*} mData - * @return {boolean} - */ -LocalStorage.prototype.set = function (iKey, mData) -{ - return this.oDriver ? this.oDriver.set('p' + iKey, mData) : false; -}; - -/** - * @param {number} iKey - * @return {*} - */ -LocalStorage.prototype.get = function (iKey) -{ - return this.oDriver ? this.oDriver.get('p' + iKey) : null; -}; - -/** - * @constructor - */ -function KnoinAbstractBoot() -{ - -} - -KnoinAbstractBoot.prototype.bootstart = function () -{ - -}; - -/** - * @param {string=} sPosition = '' - * @param {string=} sTemplate = '' - * @constructor - */ -function KnoinAbstractViewModel(sPosition, sTemplate) -{ - this.bDisabeCloseOnEsc = false; - this.sPosition = Utils.pString(sPosition); - this.sTemplate = Utils.pString(sTemplate); - - this.sDefaultKeyScope = Enums.KeyState.None; - this.sCurrentKeyScope = this.sDefaultKeyScope; - - this.viewModelName = ''; - this.viewModelVisibility = ko.observable(false); - this.modalVisibility = ko.observable(false).extend({'rateLimit': 0}); - - this.viewModelDom = null; -} - -/** - * @type {string} - */ -KnoinAbstractViewModel.prototype.sPosition = ''; - -/** - * @type {string} - */ -KnoinAbstractViewModel.prototype.sTemplate = ''; - -/** - * @type {string} - */ -KnoinAbstractViewModel.prototype.viewModelName = ''; - -/** - * @type {?} - */ -KnoinAbstractViewModel.prototype.viewModelDom = null; - -/** - * @return {string} - */ -KnoinAbstractViewModel.prototype.viewModelTemplate = function () -{ - return this.sTemplate; -}; - -/** - * @return {string} - */ -KnoinAbstractViewModel.prototype.viewModelPosition = function () -{ - return this.sPosition; -}; - -KnoinAbstractViewModel.prototype.cancelCommand = KnoinAbstractViewModel.prototype.closeCommand = function () -{ -}; - -KnoinAbstractViewModel.prototype.storeAndSetKeyScope = function () -{ - this.sCurrentKeyScope = RL.data().keyScope(); - RL.data().keyScope(this.sDefaultKeyScope); -}; - -KnoinAbstractViewModel.prototype.restoreKeyScope = function () -{ - RL.data().keyScope(this.sCurrentKeyScope); -}; - -KnoinAbstractViewModel.prototype.registerPopupEscapeKey = function () -{ - var self = this; - $window.on('keydown', function (oEvent) { - if (oEvent && Enums.EventKeyCode.Esc === oEvent.keyCode && self.modalVisibility && self.modalVisibility()) - { - Utils.delegateRun(self, 'cancelCommand'); - return false; - } - - return true; - }); -}; - -/** - * @param {string} sScreenName - * @param {?=} aViewModels = [] - * @constructor - */ -function KnoinAbstractScreen(sScreenName, aViewModels) -{ - this.sScreenName = sScreenName; - this.aViewModels = Utils.isArray(aViewModels) ? aViewModels : []; -} - -/** - * @type {Array} - */ -KnoinAbstractScreen.prototype.oCross = null; - -/** - * @type {string} - */ -KnoinAbstractScreen.prototype.sScreenName = ''; - -/** - * @type {Array} - */ -KnoinAbstractScreen.prototype.aViewModels = []; - -/** - * @return {Array} - */ -KnoinAbstractScreen.prototype.viewModels = function () -{ - return this.aViewModels; -}; - -/** - * @return {string} - */ -KnoinAbstractScreen.prototype.screenName = function () -{ - return this.sScreenName; -}; - -KnoinAbstractScreen.prototype.routes = function () -{ - return null; -}; - -/** - * @return {?Object} - */ -KnoinAbstractScreen.prototype.__cross = function () -{ - return this.oCross; -}; - -KnoinAbstractScreen.prototype.__start = function () -{ - var - aRoutes = this.routes(), - oRoute = null, - fMatcher = null - ; - - if (Utils.isNonEmptyArray(aRoutes)) - { - fMatcher = _.bind(this.onRoute || Utils.emptyFunction, this); - oRoute = crossroads.create(); - - _.each(aRoutes, function (aItem) { - oRoute.addRoute(aItem[0], fMatcher).rules = aItem[1]; - }); - - this.oCross = oRoute; - } -}; - -/** - * @constructor - */ -function Knoin() -{ - this.sDefaultScreenName = ''; - this.oScreens = {}; - this.oBoot = null; - this.oCurrentScreen = null; -} - -/** - * @param {Object} thisObject - */ -Knoin.constructorEnd = function (thisObject) -{ - if (Utils.isFunc(thisObject['__constructor_end'])) - { - thisObject['__constructor_end'].call(thisObject); - } -}; - -Knoin.prototype.sDefaultScreenName = ''; -Knoin.prototype.oScreens = {}; -Knoin.prototype.oBoot = null; -Knoin.prototype.oCurrentScreen = null; - -Knoin.prototype.hideLoading = function () -{ - $('#rl-loading').hide(); -}; - -Knoin.prototype.routeOff = function () -{ - hasher.changed.active = false; -}; - -Knoin.prototype.routeOn = function () -{ - hasher.changed.active = true; -}; - -/** - * @param {Object} oBoot - * @return {Knoin} - */ -Knoin.prototype.setBoot = function (oBoot) -{ - if (Utils.isNormal(oBoot)) - { - this.oBoot = oBoot; - } - - return this; -}; - -/** - * @param {string} sScreenName - * @return {?Object} - */ -Knoin.prototype.screen = function (sScreenName) -{ - return ('' !== sScreenName && !Utils.isUnd(this.oScreens[sScreenName])) ? this.oScreens[sScreenName] : null; -}; - -/** - * @param {Function} ViewModelClass - * @param {Object=} oScreen - */ -Knoin.prototype.buildViewModel = function (ViewModelClass, oScreen) -{ - if (ViewModelClass && !ViewModelClass.__builded) - { - var - oViewModel = new ViewModelClass(oScreen), - sPosition = oViewModel.viewModelPosition(), - oViewModelPlace = $('#rl-content #rl-' + sPosition.toLowerCase()), - oViewModelDom = null - ; - - ViewModelClass.__builded = true; - ViewModelClass.__vm = oViewModel; - oViewModel.data = RL.data(); - - oViewModel.viewModelName = ViewModelClass.__name; - - if (oViewModelPlace && 1 === oViewModelPlace.length) - { - oViewModelDom = $('').addClass('rl-view-model').addClass('RL-' + oViewModel.viewModelTemplate()).hide().attr('data-bind', - 'template: {name: "' + oViewModel.viewModelTemplate() + '"}, i18nInit: true'); - - oViewModelDom.appendTo(oViewModelPlace); - oViewModel.viewModelDom = oViewModelDom; - ViewModelClass.__dom = oViewModelDom; - - if ('Popups' === sPosition) - { - oViewModel.cancelCommand = oViewModel.closeCommand = Utils.createCommand(oViewModel, function () { - kn.hideScreenPopup(ViewModelClass); - }); - - oViewModel.modalVisibility.subscribe(function (bValue) { - - var self = this; - if (bValue) - { - this.viewModelDom.show(); - this.storeAndSetKeyScope(); - - RL.popupVisibilityNames.push(this.viewModelName); - oViewModel.viewModelDom.css('z-index', 3000 + RL.popupVisibilityNames().length + 10); - - Utils.delegateRun(this, 'onFocus', [], 500); - } - else - { - Utils.delegateRun(this, 'onHide'); - this.restoreKeyScope(); - - RL.popupVisibilityNames.remove(this.viewModelName); - oViewModel.viewModelDom.css('z-index', 2000); - - _.delay(function () { - self.viewModelDom.hide(); - }, 300); - } - - }, oViewModel); - } - - Plugins.runHook('view-model-pre-build', [ViewModelClass.__name, oViewModel, oViewModelDom]); - - ko.applyBindings(oViewModel, oViewModelDom[0]); - Utils.delegateRun(oViewModel, 'onBuild', [oViewModelDom]); - if (oViewModel && 'Popups' === sPosition && !oViewModel.bDisabeCloseOnEsc) - { - oViewModel.registerPopupEscapeKey(); - } - - Plugins.runHook('view-model-post-build', [ViewModelClass.__name, oViewModel, oViewModelDom]); - } - else - { - Utils.log('Cannot find view model position: ' + sPosition); - } - } - - return ViewModelClass ? ViewModelClass.__vm : null; -}; - -/** - * @param {Object} oViewModel - * @param {Object} oViewModelDom - */ -Knoin.prototype.applyExternal = function (oViewModel, oViewModelDom) -{ - if (oViewModel && oViewModelDom) - { - ko.applyBindings(oViewModel, oViewModelDom); - } -}; - -/** - * @param {Function} ViewModelClassToHide - */ -Knoin.prototype.hideScreenPopup = function (ViewModelClassToHide) -{ - if (ViewModelClassToHide && ViewModelClassToHide.__vm && ViewModelClassToHide.__dom) - { - ViewModelClassToHide.__vm.modalVisibility(false); - Plugins.runHook('view-model-on-hide', [ViewModelClassToHide.__name, ViewModelClassToHide.__vm]); - } -}; - -/** - * @param {Function} ViewModelClassToShow - * @param {Array=} aParameters - */ -Knoin.prototype.showScreenPopup = function (ViewModelClassToShow, aParameters) -{ - if (ViewModelClassToShow) - { - this.buildViewModel(ViewModelClassToShow); - - if (ViewModelClassToShow.__vm && ViewModelClassToShow.__dom) - { - ViewModelClassToShow.__vm.modalVisibility(true); - Utils.delegateRun(ViewModelClassToShow.__vm, 'onShow', aParameters || []); - Plugins.runHook('view-model-on-show', [ViewModelClassToShow.__name, ViewModelClassToShow.__vm, aParameters || []]); - } - } -}; - -/** - * @param {string} sScreenName - * @param {string} sSubPart - */ -Knoin.prototype.screenOnRoute = function (sScreenName, sSubPart) -{ - var - self = this, - oScreen = null, - oCross = null - ; - - if ('' === Utils.pString(sScreenName)) - { - sScreenName = this.sDefaultScreenName; - } - - if ('' !== sScreenName) - { - oScreen = this.screen(sScreenName); - if (!oScreen) - { - oScreen = this.screen(this.sDefaultScreenName); - if (oScreen) - { - sSubPart = sScreenName + '/' + sSubPart; - sScreenName = this.sDefaultScreenName; - } - } - - if (oScreen && oScreen.__started) - { - if (!oScreen.__builded) - { - oScreen.__builded = true; - - if (Utils.isNonEmptyArray(oScreen.viewModels())) - { - _.each(oScreen.viewModels(), function (ViewModelClass) { - this.buildViewModel(ViewModelClass, oScreen); - }, this); - } - - Utils.delegateRun(oScreen, 'onBuild'); - } - - _.defer(function () { - - // hide screen - if (self.oCurrentScreen) - { - Utils.delegateRun(self.oCurrentScreen, 'onHide'); - - if (Utils.isNonEmptyArray(self.oCurrentScreen.viewModels())) - { - _.each(self.oCurrentScreen.viewModels(), function (ViewModelClass) { - - if (ViewModelClass.__vm && ViewModelClass.__dom && - 'Popups' !== ViewModelClass.__vm.viewModelPosition()) - { - ViewModelClass.__dom.hide(); - ViewModelClass.__vm.viewModelVisibility(false); - Utils.delegateRun(ViewModelClass.__vm, 'onHide'); - } - - }); - } - } - // -- - - self.oCurrentScreen = oScreen; - - // show screen - if (self.oCurrentScreen) - { - Utils.delegateRun(self.oCurrentScreen, 'onShow'); - - Plugins.runHook('screen-on-show', [self.oCurrentScreen.screenName(), self.oCurrentScreen]); - - if (Utils.isNonEmptyArray(self.oCurrentScreen.viewModels())) - { - _.each(self.oCurrentScreen.viewModels(), function (ViewModelClass) { - - if (ViewModelClass.__vm && ViewModelClass.__dom && - 'Popups' !== ViewModelClass.__vm.viewModelPosition()) - { - ViewModelClass.__dom.show(); - ViewModelClass.__vm.viewModelVisibility(true); - Utils.delegateRun(ViewModelClass.__vm, 'onShow'); - Utils.delegateRun(ViewModelClass.__vm, 'onFocus', [], 200); - - Plugins.runHook('view-model-on-show', [ViewModelClass.__name, ViewModelClass.__vm]); - } - - }, self); - } - } - // -- - - oCross = oScreen.__cross(); - if (oCross) - { - oCross.parse(sSubPart); - } - }); - } - } -}; - -/** - * @param {Array} aScreensClasses - */ -Knoin.prototype.startScreens = function (aScreensClasses) -{ - $('#rl-content').css({ - 'visibility': 'hidden' - }); - - _.each(aScreensClasses, function (CScreen) { - - var - oScreen = new CScreen(), - sScreenName = oScreen ? oScreen.screenName() : '' - ; - - if (oScreen && '' !== sScreenName) - { - if ('' === this.sDefaultScreenName) - { - this.sDefaultScreenName = sScreenName; - } - - this.oScreens[sScreenName] = oScreen; - } - - }, this); - - - _.each(this.oScreens, function (oScreen) { - if (oScreen && !oScreen.__started && oScreen.__start) - { - oScreen.__started = true; - oScreen.__start(); - - Plugins.runHook('screen-pre-start', [oScreen.screenName(), oScreen]); - Utils.delegateRun(oScreen, 'onStart'); - Plugins.runHook('screen-post-start', [oScreen.screenName(), oScreen]); - } - }, this); - - var oCross = crossroads.create(); - oCross.addRoute(/^([a-zA-Z0-9\-]*)\/?(.*)$/, _.bind(this.screenOnRoute, this)); - - hasher.initialized.add(oCross.parse, oCross); - hasher.changed.add(oCross.parse, oCross); - hasher.init(); - - $('#rl-content').css({ - 'visibility': 'visible' - }); - - _.delay(function () { - $html.removeClass('rl-started-trigger').addClass('rl-started'); - }, 50); -}; - -/** - * @param {string} sHash - * @param {boolean=} bSilence = false - * @param {boolean=} bReplace = false - */ -Knoin.prototype.setHash = function (sHash, bSilence, bReplace) -{ - sHash = '#' === sHash.substr(0, 1) ? sHash.substr(1) : sHash; - sHash = '/' === sHash.substr(0, 1) ? sHash.substr(1) : sHash; - - bReplace = Utils.isUnd(bReplace) ? false : !!bReplace; - - if (Utils.isUnd(bSilence) ? false : !!bSilence) - { - hasher.changed.active = false; - hasher[bReplace ? 'replaceHash' : 'setHash'](sHash); - hasher.changed.active = true; - } - else - { - hasher.changed.active = true; - hasher[bReplace ? 'replaceHash' : 'setHash'](sHash); - hasher.setHash(sHash); - } -}; - -/** - * @return {Knoin} - */ -Knoin.prototype.bootstart = function () -{ - if (this.oBoot && this.oBoot.bootstart) - { - this.oBoot.bootstart(); - } - - return this; -}; - -kn = new Knoin(); - -/** - * @param {string=} sEmail - * @param {string=} sName - * - * @constructor - */ -function EmailModel(sEmail, sName) -{ - this.email = sEmail || ''; - this.name = sName || ''; - this.privateType = null; - - this.clearDuplicateName(); -} - -/** - * @static - * @param {AjaxJsonEmail} oJsonEmail - * @return {?EmailModel} - */ -EmailModel.newInstanceFromJson = function (oJsonEmail) -{ - var oEmailModel = new EmailModel(); - return oEmailModel.initByJson(oJsonEmail) ? oEmailModel : null; -}; - -/** - * @type {string} - */ -EmailModel.prototype.name = ''; - -/** - * @type {string} - */ -EmailModel.prototype.email = ''; - -/** - * @type {(number|null)} - */ -EmailModel.prototype.privateType = null; - -EmailModel.prototype.clear = function () -{ - this.email = ''; - this.name = ''; - this.privateType = null; -}; - -/** - * @returns {boolean} - */ -EmailModel.prototype.validate = function () -{ - return '' !== this.name || '' !== this.email; -}; - -/** - * @param {boolean} bWithoutName = false - * @return {string} - */ -EmailModel.prototype.hash = function (bWithoutName) -{ - return '#' + (bWithoutName ? '' : this.name) + '#' + this.email + '#'; -}; - -EmailModel.prototype.clearDuplicateName = function () -{ - if (this.name === this.email) - { - this.name = ''; - } -}; - -/** - * @return {number} - */ -EmailModel.prototype.type = function () -{ - if (null === this.privateType) - { - if (this.email && '@facebook.com' === this.email.substr(-13)) - { - this.privateType = Enums.EmailType.Facebook; - } - - if (null === this.privateType) - { - this.privateType = Enums.EmailType.Default; - } - } - - return this.privateType; -}; - -/** - * @param {string} sQuery - * @return {boolean} - */ -EmailModel.prototype.search = function (sQuery) -{ - return -1 < (this.name + ' ' + this.email).toLowerCase().indexOf(sQuery.toLowerCase()); -}; - -/** - * @param {string} sString - */ -EmailModel.prototype.parse = function (sString) -{ - this.clear(); - - sString = Utils.trim(sString); - - var - mRegex = /(?:"([^"]+)")? ?(.*?@[^>,]+)>?,? ?/g, - mMatch = mRegex.exec(sString) - ; - - if (mMatch) - { - this.name = mMatch[1] || ''; - this.email = mMatch[2] || ''; - - this.clearDuplicateName(); - } - else if ((/^[^@]+@[^@]+$/).test(sString)) - { - this.name = ''; - this.email = sString; - } -}; - -/** - * @param {AjaxJsonEmail} oJsonEmail - * @return {boolean} - */ -EmailModel.prototype.initByJson = function (oJsonEmail) -{ - var bResult = false; - if (oJsonEmail && 'Object/Email' === oJsonEmail['@Object']) - { - this.name = Utils.trim(oJsonEmail.Name); - this.email = Utils.trim(oJsonEmail.Email); - - bResult = '' !== this.email; - this.clearDuplicateName(); - } - - return bResult; -}; - -/** - * @param {boolean} bFriendlyView - * @param {boolean=} bWrapWithLink = false - * @param {boolean=} bEncodeHtml = false - * @return {string} - */ -EmailModel.prototype.toLine = function (bFriendlyView, bWrapWithLink, bEncodeHtml) -{ - var sResult = ''; - if ('' !== this.email) - { - bWrapWithLink = Utils.isUnd(bWrapWithLink) ? false : !!bWrapWithLink; - bEncodeHtml = Utils.isUnd(bEncodeHtml) ? false : !!bEncodeHtml; - - if (bFriendlyView && '' !== this.name) - { - sResult = bWrapWithLink ? '') + - '" target="_blank" tabindex="-1">' + Utils.encodeHtml(this.name) + '' : - (bEncodeHtml ? Utils.encodeHtml(this.name) : this.name); - } - else - { - sResult = this.email; - if ('' !== this.name) - { - if (bWrapWithLink) - { - sResult = Utils.encodeHtml('"' + this.name + '" <') + - '') + '" target="_blank" tabindex="-1">' + Utils.encodeHtml(sResult) + '' + Utils.encodeHtml('>'); - } - else - { - sResult = '"' + this.name + '" <' + sResult + '>'; - if (bEncodeHtml) - { - sResult = Utils.encodeHtml(sResult); - } - } - } - else if (bWrapWithLink) - { - sResult = '' + Utils.encodeHtml(this.email) + ''; - } - } - } - - return sResult; -}; - -/** - * @param {string} $sEmailAddress - * @return {boolean} - */ -EmailModel.prototype.mailsoParse = function ($sEmailAddress) -{ - $sEmailAddress = Utils.trim($sEmailAddress); - if ('' === $sEmailAddress) - { - return false; - } - - var - substr = function (str, start, len) { - str += ''; - var end = str.length; - - if (start < 0) { - start += end; - } - - end = typeof len === 'undefined' ? end : (len < 0 ? len + end : len + start); - - return start >= str.length || start < 0 || start > end ? false : str.slice(start, end); - }, - - substr_replace = function (str, replace, start, length) { - if (start < 0) { - start = start + str.length; - } - length = length !== undefined ? length : str.length; - if (length < 0) { - length = length + str.length - start; - } - return str.slice(0, start) + replace.substr(0, length) + replace.slice(length) + str.slice(start + length); - }, - - $sName = '', - $sEmail = '', - $sComment = '', - - $bInName = false, - $bInAddress = false, - $bInComment = false, - - $aRegs = null, - - $iStartIndex = 0, - $iEndIndex = 0, - $iCurrentIndex = 0 - ; - - while ($iCurrentIndex < $sEmailAddress.length) - { - switch ($sEmailAddress.substr($iCurrentIndex, 1)) - { - case '"': - if ((!$bInName) && (!$bInAddress) && (!$bInComment)) - { - $bInName = true; - $iStartIndex = $iCurrentIndex; - } - else if ((!$bInAddress) && (!$bInComment)) - { - $iEndIndex = $iCurrentIndex; - $sName = substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1); - $sEmailAddress = substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1); - $iEndIndex = 0; - $iCurrentIndex = 0; - $iStartIndex = 0; - $bInName = false; - } - break; - case '<': - if ((!$bInName) && (!$bInAddress) && (!$bInComment)) - { - if ($iCurrentIndex > 0 && $sName.length === 0) - { - $sName = substr($sEmailAddress, 0, $iCurrentIndex); - } - - $bInAddress = true; - $iStartIndex = $iCurrentIndex; - } - break; - case '>': - if ($bInAddress) - { - $iEndIndex = $iCurrentIndex; - $sEmail = substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1); - $sEmailAddress = substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1); - $iEndIndex = 0; - $iCurrentIndex = 0; - $iStartIndex = 0; - $bInAddress = false; - } - break; - case '(': - if ((!$bInName) && (!$bInAddress) && (!$bInComment)) - { - $bInComment = true; - $iStartIndex = $iCurrentIndex; - } - break; - case ')': - if ($bInComment) - { - $iEndIndex = $iCurrentIndex; - $sComment = substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1); - $sEmailAddress = substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1); - $iEndIndex = 0; - $iCurrentIndex = 0; - $iStartIndex = 0; - $bInComment = false; - } - break; - case '\\': - $iCurrentIndex++; - break; - } - - $iCurrentIndex++; - } - - if ($sEmail.length === 0) - { - $aRegs = $sEmailAddress.match(/[^@\s]+@\S+/i); - if ($aRegs && $aRegs[0]) - { - $sEmail = $aRegs[0]; - } - else - { - $sName = $sEmailAddress; - } - } - - if ($sEmail.length > 0 && $sName.length === 0 && $sComment.length === 0) - { - $sName = $sEmailAddress.replace($sEmail, ''); - } - - $sEmail = Utils.trim($sEmail).replace(/^[<]+/, '').replace(/[>]+$/, ''); - $sName = Utils.trim($sName).replace(/^["']+/, '').replace(/["']+$/, ''); - $sComment = Utils.trim($sComment).replace(/^[(]+/, '').replace(/[)]+$/, ''); - - // Remove backslash - $sName = $sName.replace(/\\\\(.)/, '$1'); - $sComment = $sComment.replace(/\\\\(.)/, '$1'); - - this.name = $sName; - this.email = $sEmail; - - this.clearDuplicateName(); - return true; -}; - -/** - * @return {string} - */ -EmailModel.prototype.inputoTagLine = function () -{ - return 0 < this.name.length ? this.name + ' (' + this.email + ')' : this.email; -}; - -/** - * @constructor - */ -function ContactModel() -{ - this.idContact = 0; - this.display = ''; - this.properties = []; - this.readOnly = false; - - this.focused = ko.observable(false); - this.selected = ko.observable(false); - this.checked = ko.observable(false); - this.deleted = ko.observable(false); -} - -/** - * @return {Array|null} - */ -ContactModel.prototype.getNameAndEmailHelper = function () -{ - var - sName = '', - sEmail = '' - ; - - if (Utils.isNonEmptyArray(this.properties)) - { - _.each(this.properties, function (aProperty) { - if (aProperty) - { - if (Enums.ContactPropertyType.FirstName === aProperty[0]) - { - sName = Utils.trim(aProperty[1] + ' ' + sName); - } - else if (Enums.ContactPropertyType.LastName === aProperty[0]) - { - sName = Utils.trim(sName + ' ' + aProperty[1]); - } - else if ('' === sEmail && Enums.ContactPropertyType.Email === aProperty[0]) - { - sEmail = aProperty[1]; - } - } - }, this); - } - - return '' === sEmail ? null : [sEmail, sName]; -}; - -ContactModel.prototype.parse = function (oItem) -{ - var bResult = false; - if (oItem && 'Object/Contact' === oItem['@Object']) - { - this.idContact = Utils.pInt(oItem['IdContact']); - this.display = Utils.pString(oItem['Display']); - this.readOnly = !!oItem['ReadOnly']; - - if (Utils.isNonEmptyArray(oItem['Properties'])) - { - _.each(oItem['Properties'], function (oProperty) { - if (oProperty && oProperty['Type'] && Utils.isNormal(oProperty['Value']) && Utils.isNormal(oProperty['TypeStr'])) - { - this.properties.push([Utils.pInt(oProperty['Type']), Utils.pString(oProperty['Value']), Utils.pString(oProperty['TypeStr'])]); - } - }, this); - } - - bResult = true; - } - - return bResult; -}; - -/** - * @return {string} - */ -ContactModel.prototype.srcAttr = function () -{ - return RL.link().emptyContactPic(); -}; - -/** - * @return {string} - */ -ContactModel.prototype.generateUid = function () -{ - return '' + this.idContact; -}; - -/** - * @return string - */ -ContactModel.prototype.lineAsCcc = function () -{ - var aResult = []; - if (this.deleted()) - { - aResult.push('deleted'); - } - if (this.selected()) - { - aResult.push('selected'); - } - if (this.checked()) - { - aResult.push('checked'); - } - if (this.focused()) - { - aResult.push('focused'); - } - - return aResult.join(' '); -}; - -/** - * @param {number=} iType = Enums.ContactPropertyType.Unknown - * @param {string=} sTypeStr = '' - * @param {string=} sValue = '' - * @param {boolean=} bFocused = false - * @param {string=} sPlaceholder = '' - * - * @constructor - */ -function ContactPropertyModel(iType, sTypeStr, sValue, bFocused, sPlaceholder) -{ - this.type = ko.observable(Utils.isUnd(iType) ? Enums.ContactPropertyType.Unknown : iType); - this.typeStr = ko.observable(Utils.isUnd(sTypeStr) ? '' : sTypeStr); - this.focused = ko.observable(Utils.isUnd(bFocused) ? false : !!bFocused); - this.value = ko.observable(Utils.pString(sValue)); - - this.placeholder = ko.observable(sPlaceholder || ''); - - this.placeholderValue = ko.computed(function () { - var sPlaceholder = this.placeholder(); - return sPlaceholder ? Utils.i18n(sPlaceholder) : ''; - }, this); - - this.largeValue = ko.computed(function () { - return Enums.ContactPropertyType.Note === this.type(); - }, this); - -} - -/** - * @constructor - */ -function AttachmentModel() -{ - this.mimeType = ''; - this.fileName = ''; - this.estimatedSize = 0; - this.friendlySize = ''; - this.isInline = false; - this.isLinked = false; - this.cid = ''; - this.cidWithOutTags = ''; - this.contentLocation = ''; - this.download = ''; - this.folder = ''; - this.uid = ''; - this.mimeIndex = ''; -} - -/** - * @static - * @param {AjaxJsonAttachment} oJsonAttachment - * @return {?AttachmentModel} - */ -AttachmentModel.newInstanceFromJson = function (oJsonAttachment) -{ - var oAttachmentModel = new AttachmentModel(); - return oAttachmentModel.initByJson(oJsonAttachment) ? oAttachmentModel : null; -}; - -AttachmentModel.prototype.mimeType = ''; -AttachmentModel.prototype.fileName = ''; -AttachmentModel.prototype.estimatedSize = 0; -AttachmentModel.prototype.friendlySize = ''; -AttachmentModel.prototype.isInline = false; -AttachmentModel.prototype.isLinked = false; -AttachmentModel.prototype.cid = ''; -AttachmentModel.prototype.cidWithOutTags = ''; -AttachmentModel.prototype.contentLocation = ''; -AttachmentModel.prototype.download = ''; -AttachmentModel.prototype.folder = ''; -AttachmentModel.prototype.uid = ''; -AttachmentModel.prototype.mimeIndex = ''; - -/** - * @param {AjaxJsonAttachment} oJsonAttachment - */ -AttachmentModel.prototype.initByJson = function (oJsonAttachment) -{ - var bResult = false; - if (oJsonAttachment && 'Object/Attachment' === oJsonAttachment['@Object']) - { - this.mimeType = (oJsonAttachment.MimeType || '').toLowerCase(); - this.fileName = oJsonAttachment.FileName; - this.estimatedSize = Utils.pInt(oJsonAttachment.EstimatedSize); - this.isInline = !!oJsonAttachment.IsInline; - this.isLinked = !!oJsonAttachment.IsLinked; - this.cid = oJsonAttachment.CID; - this.contentLocation = oJsonAttachment.ContentLocation; - this.download = oJsonAttachment.Download; - - this.folder = oJsonAttachment.Folder; - this.uid = oJsonAttachment.Uid; - this.mimeIndex = oJsonAttachment.MimeIndex; - - this.friendlySize = Utils.friendlySize(this.estimatedSize); - this.cidWithOutTags = this.cid.replace(/^<+/, '').replace(/>+$/, ''); - - bResult = true; - } - - return bResult; -}; - -/** - * @return {boolean} - */ -AttachmentModel.prototype.isImage = function () -{ - return -1 < Utils.inArray(this.mimeType.toLowerCase(), - ['image/png', 'image/jpg', 'image/jpeg', 'image/gif'] - ); -}; - -/** - * @return {boolean} - */ -AttachmentModel.prototype.isText = function () -{ - return 'text/' === this.mimeType.substr(0, 5) && - -1 === Utils.inArray(this.mimeType, ['text/html']); -}; - -/** - * @return {boolean} - */ -AttachmentModel.prototype.isPdf = function () -{ - return Globals.bAllowPdfPreview && 'application/pdf' === this.mimeType; -}; - -/** - * @return {string} - */ -AttachmentModel.prototype.linkDownload = function () -{ - return RL.link().attachmentDownload(this.download); -}; - -/** - * @return {string} - */ -AttachmentModel.prototype.linkPreview = function () -{ - return RL.link().attachmentPreview(this.download); -}; - -/** - * @return {string} - */ -AttachmentModel.prototype.linkPreviewAsPlain = function () -{ - return RL.link().attachmentPreviewAsPlain(this.download); -}; - -/** - * @return {string} - */ -AttachmentModel.prototype.generateTransferDownloadUrl = function () -{ - var sLink = this.linkDownload(); - if ('http' !== sLink.substr(0, 4)) - { - sLink = window.location.protocol + '//' + window.location.host + window.location.pathname + sLink; - } - - return this.mimeType + ':' + this.fileName + ':' + sLink; -}; - -/** - * @param {AttachmentModel} oAttachment - * @param {*} oEvent - * @return {boolean} - */ -AttachmentModel.prototype.eventDragStart = function (oAttachment, oEvent) -{ - var oLocalEvent = oEvent.originalEvent || oEvent; - if (oAttachment && oLocalEvent && oLocalEvent.dataTransfer && oLocalEvent.dataTransfer.setData) - { - oLocalEvent.dataTransfer.setData('DownloadURL', this.generateTransferDownloadUrl()); - } - - return true; -}; - -AttachmentModel.prototype.iconClass = function () -{ - var - aParts = this.mimeType.toLocaleString().split('/'), - sClass = 'icon-file' - ; - - if (aParts && aParts[1]) - { - if ('image' === aParts[0]) - { - sClass = 'icon-file-image'; - } - else if ('text' === aParts[0]) - { - sClass = 'icon-file-text'; - } - else if ('audio' === aParts[0]) - { - sClass = 'icon-file-music'; - } - else if ('video' === aParts[0]) - { - sClass = 'icon-file-movie'; - } - else if (-1 < Utils.inArray(aParts[1], - ['zip', '7z', 'tar', 'rar', 'gzip', 'bzip', 'bzip2', 'x-zip', 'x-7z', 'x-rar', 'x-tar', 'x-gzip', 'x-bzip', 'x-bzip2', 'x-zip-compressed', 'x-7z-compressed', 'x-rar-compressed'])) - { - sClass = 'icon-file-zip'; - } -// else if (-1 < Utils.inArray(aParts[1], -// ['pdf', 'x-pdf'])) -// { -// sClass = 'icon-file-pdf'; -// } -// else if (-1 < Utils.inArray(aParts[1], [ -// 'exe', 'x-exe', 'x-winexe', 'bat' -// ])) -// { -// sClass = 'icon-console'; -// } - else if (-1 < Utils.inArray(aParts[1], [ - 'rtf', 'msword', 'vnd.msword', 'vnd.openxmlformats-officedocument.wordprocessingml.document', - 'vnd.openxmlformats-officedocument.wordprocessingml.template', - 'vnd.ms-word.document.macroEnabled.12', - 'vnd.ms-word.template.macroEnabled.12' - ])) - { - sClass = 'icon-file-text'; - } - else if (-1 < Utils.inArray(aParts[1], [ - 'excel', 'ms-excel', 'vnd.ms-excel', - 'vnd.openxmlformats-officedocument.spreadsheetml.sheet', - 'vnd.openxmlformats-officedocument.spreadsheetml.template', - 'vnd.ms-excel.sheet.macroEnabled.12', - 'vnd.ms-excel.template.macroEnabled.12', - 'vnd.ms-excel.addin.macroEnabled.12', - 'vnd.ms-excel.sheet.binary.macroEnabled.12' - ])) - { - sClass = 'icon-file-excel'; - } - else if (-1 < Utils.inArray(aParts[1], [ - 'powerpoint', 'ms-powerpoint', 'vnd.ms-powerpoint', - 'vnd.openxmlformats-officedocument.presentationml.presentation', - 'vnd.openxmlformats-officedocument.presentationml.template', - 'vnd.openxmlformats-officedocument.presentationml.slideshow', - 'vnd.ms-powerpoint.addin.macroEnabled.12', - 'vnd.ms-powerpoint.presentation.macroEnabled.12', - 'vnd.ms-powerpoint.template.macroEnabled.12', - 'vnd.ms-powerpoint.slideshow.macroEnabled.12' - ])) - { - sClass = 'icon-file-chart-graph'; - } - } - - return sClass; -}; - -/** - * @constructor - * @param {string} sId - * @param {string} sFileName - * @param {?number=} nSize - * @param {boolean=} bInline - * @param {boolean=} bLinked - * @param {string=} sCID - * @param {string=} sContentLocation - */ -function ComposeAttachmentModel(sId, sFileName, nSize, bInline, bLinked, sCID, sContentLocation) -{ - this.id = sId; - this.isInline = Utils.isUnd(bInline) ? false : !!bInline; - this.isLinked = Utils.isUnd(bLinked) ? false : !!bLinked; - this.CID = Utils.isUnd(sCID) ? '' : sCID; - this.contentLocation = Utils.isUnd(sContentLocation) ? '' : sContentLocation; - this.fromMessage = false; - - this.fileName = ko.observable(sFileName); - this.size = ko.observable(Utils.isUnd(nSize) ? null : nSize); - this.tempName = ko.observable(''); - - this.progress = ko.observable(''); - this.error = ko.observable(''); - this.waiting = ko.observable(true); - this.uploading = ko.observable(false); - this.enabled = ko.observable(true); - - this.friendlySize = ko.computed(function () { - var mSize = this.size(); - return null === mSize ? '' : Utils.friendlySize(this.size()); - }, this); -} - -ComposeAttachmentModel.prototype.id = ''; -ComposeAttachmentModel.prototype.isInline = false; -ComposeAttachmentModel.prototype.isLinked = false; -ComposeAttachmentModel.prototype.CID = ''; -ComposeAttachmentModel.prototype.contentLocation = ''; -ComposeAttachmentModel.prototype.fromMessage = false; -ComposeAttachmentModel.prototype.cancel = Utils.emptyFunction; - -/** - * @param {AjaxJsonComposeAttachment} oJsonAttachment - */ -ComposeAttachmentModel.prototype.initByUploadJson = function (oJsonAttachment) -{ - var bResult = false; - if (oJsonAttachment) - { - this.fileName(oJsonAttachment.Name); - this.size(Utils.isUnd(oJsonAttachment.Size) ? 0 : Utils.pInt(oJsonAttachment.Size)); - this.tempName(Utils.isUnd(oJsonAttachment.TempName) ? '' : oJsonAttachment.TempName); - this.isInline = false; - - bResult = true; - } - - return bResult; + Globals.dropdownVisibility.subscribe(function (bValue) { + if (bValue) + { + $oEl.tooltip('hide'); + } + }); + } + } }; -/** - * @constructor - */ -function MessageModel() -{ - this.folderFullNameRaw = ''; - this.uid = ''; - this.hash = ''; - this.requestHash = ''; - this.subject = ko.observable(''); - this.size = ko.observable(0); - this.dateTimeStampInUTC = ko.observable(0); - this.priority = ko.observable(Enums.MessagePriority.Normal); - - this.fromEmailString = ko.observable(''); - this.toEmailsString = ko.observable(''); - this.senderEmailsString = ko.observable(''); - - this.emails = []; - - this.from = []; - this.to = []; - this.cc = []; - this.bcc = []; - this.replyTo = []; - - this.newForAnimation = ko.observable(false); - - this.deleted = ko.observable(false); - this.unseen = ko.observable(false); - this.flagged = ko.observable(false); - this.answered = ko.observable(false); - this.forwarded = ko.observable(false); - this.isReadReceipt = ko.observable(false); - - this.focused = ko.observable(false); - this.selected = ko.observable(false); - this.checked = ko.observable(false); - this.hasAttachments = ko.observable(false); - this.attachmentsMainType = ko.observable(''); - - this.moment = ko.observable(moment()); - - this.attachmentIconClass = ko.computed(function () { - var sClass = ''; - if (this.hasAttachments()) - { - sClass = 'icon-attachment'; - switch (this.attachmentsMainType()) - { - case 'image': - sClass = 'icon-image'; - break; - case 'archive': - sClass = 'icon-file-zip'; - break; - case 'doc': - sClass = 'icon-file-text'; - break; -// case 'pdf': -// sClass = 'icon-file-pdf'; -// break; - } - } - return sClass; - }, this); - - this.fullFormatDateValue = ko.computed(function () { - return MessageModel.calculateFullFromatDateValue(this.dateTimeStampInUTC()); - }, this); - - this.fullFormatDateValue = ko.computed(function () { - return MessageModel.calculateFullFromatDateValue(this.dateTimeStampInUTC()); - }, this); - - this.momentDate = Utils.createMomentDate(this); - this.momentShortDate = Utils.createMomentShortDate(this); - - this.dateTimeStampInUTC.subscribe(function (iValue) { - var iNow = moment().unix(); - this.moment(moment.unix(iNow < iValue ? iNow : iValue)); - }, this); - - this.body = null; - this.plainRaw = ''; - this.isRtl = ko.observable(false); - this.isHtml = ko.observable(false); - this.hasImages = ko.observable(false); - this.attachments = ko.observableArray([]); - - this.isPgpSigned = ko.observable(false); - this.isPgpEncrypted = ko.observable(false); - this.pgpSignedVerifyStatus = ko.observable(Enums.SignedVerifyStatus.None); - this.pgpSignedVerifyUser = ko.observable(''); - - this.priority = ko.observable(Enums.MessagePriority.Normal); - this.readReceipt = ko.observable(''); - - this.aDraftInfo = []; - this.sMessageId = ''; - this.sInReplyTo = ''; - this.sReferences = ''; - - this.parentUid = ko.observable(0); - this.threads = ko.observableArray([]); - this.threadsLen = ko.observable(0); - this.hasUnseenSubMessage = ko.observable(false); - this.hasFlaggedSubMessage = ko.observable(false); - - this.lastInCollapsedThread = ko.observable(false); - this.lastInCollapsedThreadLoading = ko.observable(false); - - this.threadsLenResult = ko.computed(function () { - var iCount = this.threadsLen(); - return 0 === this.parentUid() && 0 < iCount ? iCount + 1 : ''; - }, this); -} - -/** - * @static - * @param {AjaxJsonMessage} oJsonMessage - * @return {?MessageModel} - */ -MessageModel.newInstanceFromJson = function (oJsonMessage) -{ - var oMessageModel = new MessageModel(); - return oMessageModel.initByJson(oJsonMessage) ? oMessageModel : null; -}; - -/** - * @static - * @param {number} iTimeStampInUTC - * @return {string} - */ -MessageModel.calculateFullFromatDateValue = function (iTimeStampInUTC) -{ - return moment.unix(iTimeStampInUTC).format('LLL'); -}; - -/** - * @static - * @param {Array} aEmail - * @param {boolean=} bFriendlyView - * @param {boolean=} bWrapWithLink = false - * @return {string} - */ -MessageModel.emailsToLine = function (aEmail, bFriendlyView, bWrapWithLink) -{ - var - aResult = [], - iIndex = 0, - iLen = 0 - ; - - if (Utils.isNonEmptyArray(aEmail)) - { - for (iIndex = 0, iLen = aEmail.length; iIndex < iLen; iIndex++) - { - aResult.push(aEmail[iIndex].toLine(bFriendlyView, bWrapWithLink)); - } - } - - return aResult.join(', '); -}; - -/** - * @static - * @param {?Array} aJsonEmails - * @return {Array} - */ -MessageModel.initEmailsFromJson = function (aJsonEmails) -{ - var - iIndex = 0, - iLen = 0, - oEmailModel = null, - aResult = [] - ; - - if (Utils.isNonEmptyArray(aJsonEmails)) - { - for (iIndex = 0, iLen = aJsonEmails.length; iIndex < iLen; iIndex++) - { - oEmailModel = EmailModel.newInstanceFromJson(aJsonEmails[iIndex]); - if (oEmailModel) - { - aResult.push(oEmailModel); - } - } - } - - return aResult; -}; - -/** - * @static - * @param {Array.} aMessageEmails - * @param {Object} oLocalUnic - * @param {Array} aLocalEmails - */ -MessageModel.replyHelper = function (aMessageEmails, oLocalUnic, aLocalEmails) -{ - if (aMessageEmails && 0 < aMessageEmails.length) - { - var - iIndex = 0, - iLen = aMessageEmails.length - ; - - for (; iIndex < iLen; iIndex++) - { - if (Utils.isUnd(oLocalUnic[aMessageEmails[iIndex].email])) - { - oLocalUnic[aMessageEmails[iIndex].email] = true; - aLocalEmails.push(aMessageEmails[iIndex]); - } - } - } -}; - -MessageModel.prototype.clear = function () -{ - this.folderFullNameRaw = ''; - this.uid = ''; - this.hash = ''; - this.requestHash = ''; - this.subject(''); - this.size(0); - this.dateTimeStampInUTC(0); - this.priority(Enums.MessagePriority.Normal); - - this.fromEmailString(''); - this.toEmailsString(''); - this.senderEmailsString(''); - - this.emails = []; - - this.from = []; - this.to = []; - this.cc = []; - this.bcc = []; - this.replyTo = []; - - this.newForAnimation(false); - - this.deleted(false); - this.unseen(false); - this.flagged(false); - this.answered(false); - this.forwarded(false); - this.isReadReceipt(false); - - this.selected(false); - this.checked(false); - this.hasAttachments(false); - this.attachmentsMainType(''); - - this.body = null; - this.isRtl(false); - this.isHtml(false); - this.hasImages(false); - this.attachments([]); - - this.isPgpSigned(false); - this.isPgpEncrypted(false); - this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.None); - this.pgpSignedVerifyUser(''); - - this.priority(Enums.MessagePriority.Normal); - this.readReceipt(''); - this.aDraftInfo = []; - this.sMessageId = ''; - this.sInReplyTo = ''; - this.sReferences = ''; - - this.parentUid(0); - this.threads([]); - this.threadsLen(0); - this.hasUnseenSubMessage(false); - this.hasFlaggedSubMessage(false); - - this.lastInCollapsedThread(false); - this.lastInCollapsedThreadLoading(false); -}; - -MessageModel.prototype.computeSenderEmail = function () -{ - var - sSent = RL.data().sentFolder(), - sDraft = RL.data().draftFolder() - ; - - this.senderEmailsString(this.folderFullNameRaw === sSent || this.folderFullNameRaw === sDraft ? - this.toEmailsString() : this.fromEmailString()); -}; - -/** - * @param {AjaxJsonMessage} oJsonMessage - * @return {boolean} - */ -MessageModel.prototype.initByJson = function (oJsonMessage) -{ - var bResult = false; - if (oJsonMessage && 'Object/Message' === oJsonMessage['@Object']) - { - this.folderFullNameRaw = oJsonMessage.Folder; - this.uid = oJsonMessage.Uid; - this.hash = oJsonMessage.Hash; - this.requestHash = oJsonMessage.RequestHash; - - this.size(Utils.pInt(oJsonMessage.Size)); - - this.from = MessageModel.initEmailsFromJson(oJsonMessage.From); - this.to = MessageModel.initEmailsFromJson(oJsonMessage.To); - this.cc = MessageModel.initEmailsFromJson(oJsonMessage.Cc); - this.bcc = MessageModel.initEmailsFromJson(oJsonMessage.Bcc); - this.replyTo = MessageModel.initEmailsFromJson(oJsonMessage.ReplyTo); - - this.subject(oJsonMessage.Subject); - this.dateTimeStampInUTC(Utils.pInt(oJsonMessage.DateTimeStampInUTC)); - this.hasAttachments(!!oJsonMessage.HasAttachments); - this.attachmentsMainType(oJsonMessage.AttachmentsMainType); - - this.fromEmailString(MessageModel.emailsToLine(this.from, true)); - this.toEmailsString(MessageModel.emailsToLine(this.to, true)); - - this.parentUid(Utils.pInt(oJsonMessage.ParentThread)); - this.threads(Utils.isArray(oJsonMessage.Threads) ? oJsonMessage.Threads : []); - this.threadsLen(Utils.pInt(oJsonMessage.ThreadsLen)); - - this.initFlagsByJson(oJsonMessage); - this.computeSenderEmail(); - - bResult = true; - } - - return bResult; -}; - -/** - * @param {AjaxJsonMessage} oJsonMessage - * @return {boolean} - */ -MessageModel.prototype.initUpdateByMessageJson = function (oJsonMessage) -{ - var - bResult = false, - iPriority = Enums.MessagePriority.Normal - ; - - if (oJsonMessage && 'Object/Message' === oJsonMessage['@Object']) - { - iPriority = Utils.pInt(oJsonMessage.Priority); - this.priority(-1 < Utils.inArray(iPriority, [Enums.MessagePriority.High, Enums.MessagePriority.Low]) ? - iPriority : Enums.MessagePriority.Normal); - - this.aDraftInfo = oJsonMessage.DraftInfo; - - this.sMessageId = oJsonMessage.MessageId; - this.sInReplyTo = oJsonMessage.InReplyTo; - this.sReferences = oJsonMessage.References; - - if (RL.data().allowOpenPGP()) - { - this.isPgpSigned(!!oJsonMessage.PgpSigned); - this.isPgpEncrypted(!!oJsonMessage.PgpEncrypted); - } - - this.hasAttachments(!!oJsonMessage.HasAttachments); - this.attachmentsMainType(oJsonMessage.AttachmentsMainType); - - this.foundedCIDs = Utils.isArray(oJsonMessage.FoundedCIDs) ? oJsonMessage.FoundedCIDs : []; - this.attachments(this.initAttachmentsFromJson(oJsonMessage.Attachments)); - - this.readReceipt(oJsonMessage.ReadReceipt || ''); - - this.computeSenderEmail(); - - bResult = true; - } - - return bResult; -}; - -/** - * @param {(AjaxJsonAttachment|null)} oJsonAttachments - * @return {Array} - */ -MessageModel.prototype.initAttachmentsFromJson = function (oJsonAttachments) -{ - var - iIndex = 0, - iLen = 0, - oAttachmentModel = null, - aResult = [] - ; - - if (oJsonAttachments && 'Collection/AttachmentCollection' === oJsonAttachments['@Object'] && - Utils.isNonEmptyArray(oJsonAttachments['@Collection'])) - { - for (iIndex = 0, iLen = oJsonAttachments['@Collection'].length; iIndex < iLen; iIndex++) - { - oAttachmentModel = AttachmentModel.newInstanceFromJson(oJsonAttachments['@Collection'][iIndex]); - if (oAttachmentModel) - { - if ('' !== oAttachmentModel.cidWithOutTags && 0 < this.foundedCIDs.length && - 0 <= Utils.inArray(oAttachmentModel.cidWithOutTags, this.foundedCIDs)) - { - oAttachmentModel.isLinked = true; - } - - aResult.push(oAttachmentModel); - } - } - } - - return aResult; -}; - -/** - * @param {AjaxJsonMessage} oJsonMessage - * @return {boolean} - */ -MessageModel.prototype.initFlagsByJson = function (oJsonMessage) -{ - var bResult = false; - - if (oJsonMessage && 'Object/Message' === oJsonMessage['@Object']) - { - this.unseen(!oJsonMessage.IsSeen); - this.flagged(!!oJsonMessage.IsFlagged); - this.answered(!!oJsonMessage.IsAnswered); - this.forwarded(!!oJsonMessage.IsForwarded); - this.isReadReceipt(!!oJsonMessage.IsReadReceipt); - - bResult = true; - } - - return bResult; -}; - -/** - * @param {boolean} bFriendlyView - * @param {boolean=} bWrapWithLink = false - * @return {string} - */ -MessageModel.prototype.fromToLine = function (bFriendlyView, bWrapWithLink) -{ - return MessageModel.emailsToLine(this.from, bFriendlyView, bWrapWithLink); -}; - -/** - * @param {boolean} bFriendlyView - * @param {boolean=} bWrapWithLink = false - * @return {string} - */ -MessageModel.prototype.toToLine = function (bFriendlyView, bWrapWithLink) -{ - return MessageModel.emailsToLine(this.to, bFriendlyView, bWrapWithLink); -}; - -/** - * @param {boolean} bFriendlyView - * @param {boolean=} bWrapWithLink = false - * @return {string} - */ -MessageModel.prototype.ccToLine = function (bFriendlyView, bWrapWithLink) -{ - return MessageModel.emailsToLine(this.cc, bFriendlyView, bWrapWithLink); -}; - -/** - * @param {boolean} bFriendlyView - * @param {boolean=} bWrapWithLink = false - * @return {string} - */ -MessageModel.prototype.bccToLine = function (bFriendlyView, bWrapWithLink) -{ - return MessageModel.emailsToLine(this.bcc, bFriendlyView, bWrapWithLink); -}; - -/** - * @return string - */ -MessageModel.prototype.lineAsCcc = function () -{ - var aResult = []; - if (this.deleted()) - { - aResult.push('deleted'); - } - if (this.selected()) - { - aResult.push('selected'); - } - if (this.checked()) - { - aResult.push('checked'); - } - if (this.flagged()) - { - aResult.push('flagged'); - } - if (this.unseen()) - { - aResult.push('unseen'); - } - if (this.answered()) - { - aResult.push('answered'); - } - if (this.forwarded()) - { - aResult.push('forwarded'); - } - if (this.focused()) - { - aResult.push('focused'); - } - if (this.hasAttachments()) - { - aResult.push('withAttachments'); - switch (this.attachmentsMainType()) - { - case 'image': - aResult.push('imageOnlyAttachments'); - break; - case 'archive': - aResult.push('archiveOnlyAttachments'); - break; - } - } - if (this.newForAnimation()) - { - aResult.push('new'); - } - if ('' === this.subject()) - { - aResult.push('emptySubject'); - } - if (0 < this.parentUid()) - { - aResult.push('hasParentMessage'); - } - if (0 < this.threadsLen() && 0 === this.parentUid()) - { - aResult.push('hasChildrenMessage'); - } - if (this.hasUnseenSubMessage()) - { - aResult.push('hasUnseenSubMessage'); - } - if (this.hasFlaggedSubMessage()) - { - aResult.push('hasFlaggedSubMessage'); - } - - return aResult.join(' '); -}; - -/** - * @return {boolean} - */ -MessageModel.prototype.hasVisibleAttachments = function () -{ - return !!_.find(this.attachments(), function (oAttachment) { - return !oAttachment.isLinked; - }); -// return 0 < this.attachments().length; -}; - -/** - * @param {string} sCid - * @return {*} - */ -MessageModel.prototype.findAttachmentByCid = function (sCid) -{ - var - oResult = null, - aAttachments = this.attachments() - ; - - if (Utils.isNonEmptyArray(aAttachments)) - { - sCid = sCid.replace(/^<+/, '').replace(/>+$/, ''); - oResult = _.find(aAttachments, function (oAttachment) { - return sCid === oAttachment.cidWithOutTags; - }); - } - - return oResult || null; -}; - -/** - * @param {string} sContentLocation - * @return {*} - */ -MessageModel.prototype.findAttachmentByContentLocation = function (sContentLocation) -{ - var - oResult = null, - aAttachments = this.attachments() - ; - - if (Utils.isNonEmptyArray(aAttachments)) - { - oResult = _.find(aAttachments, function (oAttachment) { - return sContentLocation === oAttachment.contentLocation; - }); - } - - return oResult || null; -}; - - -/** - * @return {string} - */ -MessageModel.prototype.messageId = function () -{ - return this.sMessageId; -}; - -/** - * @return {string} - */ -MessageModel.prototype.inReplyTo = function () -{ - return this.sInReplyTo; -}; - -/** - * @return {string} - */ -MessageModel.prototype.references = function () -{ - return this.sReferences; -}; - -/** - * @return {string} - */ -MessageModel.prototype.fromAsSingleEmail = function () -{ - return Utils.isArray(this.from) && this.from[0] ? this.from[0].email : ''; -}; - -/** - * @return {string} - */ -MessageModel.prototype.viewLink = function () -{ - return RL.link().messageViewLink(this.requestHash); -}; - -/** - * @return {string} - */ -MessageModel.prototype.downloadLink = function () -{ - return RL.link().messageDownloadLink(this.requestHash); -}; - -/** - * @param {Object} oExcludeEmails - * @return {Array} - */ -MessageModel.prototype.replyEmails = function (oExcludeEmails) -{ - var - aResult = [], - oUnic = Utils.isUnd(oExcludeEmails) ? {} : oExcludeEmails - ; - - MessageModel.replyHelper(this.replyTo, oUnic, aResult); - if (0 === aResult.length) - { - MessageModel.replyHelper(this.from, oUnic, aResult); - } - - return aResult; -}; - -/** - * @param {Object} oExcludeEmails - * @return {Array. } - */ -MessageModel.prototype.replyAllEmails = function (oExcludeEmails) -{ - var - aToResult = [], - aCcResult = [], - oUnic = Utils.isUnd(oExcludeEmails) ? {} : oExcludeEmails - ; - - MessageModel.replyHelper(this.replyTo, oUnic, aToResult); - if (0 === aToResult.length) - { - MessageModel.replyHelper(this.from, oUnic, aToResult); - } - - MessageModel.replyHelper(this.to, oUnic, aToResult); - MessageModel.replyHelper(this.cc, oUnic, aCcResult); - - return [aToResult, aCcResult]; -}; - -/** - * @return {string} - */ -MessageModel.prototype.textBodyToString = function () -{ - return this.body ? this.body.html() : ''; -}; - -/** - * @return {string} - */ -MessageModel.prototype.attachmentsToStringLine = function () -{ - var aAttachLines = _.map(this.attachments(), function (oItem) { - return oItem.fileName + ' (' + oItem.friendlySize + ')'; - }); - - return aAttachLines && 0 < aAttachLines.length ? aAttachLines.join(', ') : ''; -}; - -/** - * @return {Object} - */ -MessageModel.prototype.getDataForWindowPopup = function () -{ - return { - 'popupFrom': this.fromToLine(false), - 'popupTo': this.toToLine(false), - 'popupCc': this.ccToLine(false), - 'popupBcc': this.bccToLine(false), - 'popupSubject': this.subject(), - 'popupDate': this.fullFormatDateValue(), - 'popupAttachments': this.attachmentsToStringLine(), - 'popupBody': this.textBodyToString() - }; -}; - -/** - * @param {boolean=} bPrint = false - */ -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); - } - } - }); -}; - -MessageModel.prototype.printMessage = function () -{ - this.viewPopupMessage(true); -}; - -/** - * @returns {string} - */ -MessageModel.prototype.generateUid = function () -{ - return this.folderFullNameRaw + '/' + this.uid; -}; - -/** - * @param {MessageModel} oMessage - * @return {MessageModel} - */ -MessageModel.prototype.populateByMessageListItem = function (oMessage) -{ - this.folderFullNameRaw = oMessage.folderFullNameRaw; - this.uid = oMessage.uid; - this.hash = oMessage.hash; - this.requestHash = oMessage.requestHash; - this.subject(oMessage.subject()); - this.size(oMessage.size()); - this.dateTimeStampInUTC(oMessage.dateTimeStampInUTC()); - this.priority(oMessage.priority()); - - this.fromEmailString(oMessage.fromEmailString()); - this.toEmailsString(oMessage.toEmailsString()); - - this.emails = oMessage.emails; - - this.from = oMessage.from; - this.to = oMessage.to; - this.cc = oMessage.cc; - this.bcc = oMessage.bcc; - this.replyTo = oMessage.replyTo; - - this.unseen(oMessage.unseen()); - this.flagged(oMessage.flagged()); - this.answered(oMessage.answered()); - this.forwarded(oMessage.forwarded()); - this.isReadReceipt(oMessage.isReadReceipt()); - - this.selected(oMessage.selected()); - this.checked(oMessage.checked()); - this.hasAttachments(oMessage.hasAttachments()); - this.attachmentsMainType(oMessage.attachmentsMainType()); - - this.moment(oMessage.moment()); - - this.body = null; -// this.isRtl(oMessage.isRtl()); -// this.isHtml(false); -// this.hasImages(false); -// this.attachments([]); - -// this.isPgpSigned(false); -// this.isPgpEncrypted(false); - - this.priority(Enums.MessagePriority.Normal); - this.aDraftInfo = []; - this.sMessageId = ''; - this.sInReplyTo = ''; - this.sReferences = ''; - - this.parentUid(oMessage.parentUid()); - this.threads(oMessage.threads()); - this.threadsLen(oMessage.threadsLen()); - - this.computeSenderEmail(); - - return this; -}; - -MessageModel.prototype.showExternalImages = function (bLazy) -{ - if (this.body && this.body.data('rl-has-images')) - { - bLazy = Utils.isUnd(bLazy) ? false : bLazy; - - this.hasImages(false); - this.body.data('rl-has-images', false); - - $('[data-x-src]', this.body).each(function () { - if (bLazy && $(this).is('img')) - { - $(this) - .addClass('lazy') - .attr('data-original', $(this).attr('data-x-src')) - .removeAttr('data-x-src') - ; - } - else - { - $(this).attr('src', $(this).attr('data-x-src')).removeAttr('data-x-src'); - } - }); - - $('[data-x-style-url]', this.body).each(function () { - var sStyle = Utils.trim($(this).attr('style')); - sStyle = '' === sStyle ? '' : (';' === sStyle.substr(-1) ? sStyle + ' ' : sStyle + '; '); - $(this).attr('style', sStyle + $(this).attr('data-x-style-url')).removeAttr('data-x-style-url'); - }); - - if (bLazy) - { - $('img.lazy', this.body).addClass('lazy-inited').lazyload({ - 'threshold' : 400, - 'effect' : 'fadeIn', - 'skip_invisible' : false, - 'container': $('.RL-MailMessageView .messageView .messageItem .content')[0] - }); - - $window.resize(); - } - - Utils.windowResize(500); - } -}; - -MessageModel.prototype.showInternalImages = function (bLazy) -{ - if (this.body && !this.body.data('rl-init-internal-images')) - { - this.body.data('rl-init-internal-images', true); - - bLazy = Utils.isUnd(bLazy) ? false : bLazy; - - var self = this; - - $('[data-x-src-cid]', this.body).each(function () { - - var oAttachment = self.findAttachmentByCid($(this).attr('data-x-src-cid')); - if (oAttachment && oAttachment.download) - { - if (bLazy && $(this).is('img')) - { - $(this) - .addClass('lazy') - .attr('data-original', oAttachment.linkPreview()); - } - else - { - $(this).attr('src', oAttachment.linkPreview()); - } - } - }); - - $('[data-x-src-location]', this.body).each(function () { - - var oAttachment = self.findAttachmentByContentLocation($(this).attr('data-x-src-location')); - if (!oAttachment) - { - oAttachment = self.findAttachmentByCid($(this).attr('data-x-src-location')); - } - - if (oAttachment && oAttachment.download) - { - if (bLazy && $(this).is('img')) - { - $(this) - .addClass('lazy') - .attr('data-original', oAttachment.linkPreview()); - } - else - { - $(this).attr('src', oAttachment.linkPreview()); - } - } - }); - - $('[data-x-style-cid]', this.body).each(function () { - - var - sStyle = '', - sName = '', - oAttachment = self.findAttachmentByCid($(this).attr('data-x-style-cid')) - ; - - if (oAttachment && oAttachment.linkPreview) - { - sName = $(this).attr('data-x-style-cid-name'); - if ('' !== sName) - { - sStyle = Utils.trim($(this).attr('style')); - sStyle = '' === sStyle ? '' : (';' === sStyle.substr(-1) ? sStyle + ' ' : sStyle + '; '); - $(this).attr('style', sStyle + sName + ': url(\'' + oAttachment.linkPreview() + '\')'); - } - } - }); - - if (bLazy) - { - (function ($oImg, oContainer) { - _.delay(function () { - $oImg.addClass('lazy-inited').lazyload({ - 'threshold' : 400, - 'effect' : 'fadeIn', - 'skip_invisible' : false, - 'container': oContainer - }); - }, 300); - }($('img.lazy', self.body), $('.RL-MailMessageView .messageView .messageItem .content')[0])); - } - - Utils.windowResize(500); - } -}; - -MessageModel.prototype.storeDataToDom = function () -{ - if (this.body) - { - this.body.data('rl-is-rtl', !!this.isRtl()); - this.body.data('rl-is-html', !!this.isHtml()); - this.body.data('rl-has-images', !!this.hasImages()); - - this.body.data('rl-plain-raw', this.plainRaw); - - if (RL.data().allowOpenPGP()) - { - this.body.data('rl-plain-pgp-signed', !!this.isPgpSigned()); - this.body.data('rl-plain-pgp-encrypted', !!this.isPgpEncrypted()); - this.body.data('rl-pgp-verify-status', this.pgpSignedVerifyStatus()); - this.body.data('rl-pgp-verify-user', this.pgpSignedVerifyUser()); - } - } -}; - -MessageModel.prototype.storePgpVerifyDataToDom = function () -{ - if (this.body && RL.data().allowOpenPGP()) - { - this.body.data('rl-pgp-verify-status', this.pgpSignedVerifyStatus()); - this.body.data('rl-pgp-verify-user', this.pgpSignedVerifyUser()); - } -}; - -MessageModel.prototype.fetchDataToDom = function () -{ - if (this.body) - { - this.isRtl(!!this.body.data('rl-is-rtl')); - this.isHtml(!!this.body.data('rl-is-html')); - this.hasImages(!!this.body.data('rl-has-images')); - - this.plainRaw = Utils.pString(this.body.data('rl-plain-raw')); - - if (RL.data().allowOpenPGP()) - { - this.isPgpSigned(!!this.body.data('rl-plain-pgp-signed')); - this.isPgpEncrypted(!!this.body.data('rl-plain-pgp-encrypted')); - this.pgpSignedVerifyStatus(this.body.data('rl-pgp-verify-status')); - this.pgpSignedVerifyUser(this.body.data('rl-pgp-verify-user')); - } - else - { - this.isPgpSigned(false); - this.isPgpEncrypted(false); - this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.None); - this.pgpSignedVerifyUser(''); - } - } -}; - -MessageModel.prototype.verifyPgpSignedClearMessage = function () -{ - if (this.isPgpSigned()) - { - var - aRes = [], - mPgpMessage = null, - sFrom = this.from && this.from[0] && this.from[0].email ? this.from[0].email : '', - aPublicKeys = RL.data().findPublicKeysByEmail(sFrom), - oValidKey = null, - oValidSysKey = null, - sPlain = '' - ; - - this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Error); - this.pgpSignedVerifyUser(''); - - try - { - mPgpMessage = window.openpgp.cleartext.readArmored(this.plainRaw); - if (mPgpMessage && mPgpMessage.getText) - { - this.pgpSignedVerifyStatus( - aPublicKeys.length ? Enums.SignedVerifyStatus.Unverified : Enums.SignedVerifyStatus.UnknownPublicKeys); - - aRes = mPgpMessage.verify(aPublicKeys); - if (aRes && 0 < aRes.length) - { - oValidKey = _.find(aRes, function (oItem) { - return oItem && oItem.keyid && oItem.valid; - }); - - if (oValidKey) - { - oValidSysKey = RL.data().findPublicKeyByHex(oValidKey.keyid.toHex()); - if (oValidSysKey) - { - sPlain = mPgpMessage.getText(); - - this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Success); - this.pgpSignedVerifyUser(oValidSysKey.user); - - sPlain = - $proxyDiv.empty().append( - $('').text(sPlain) - ).html() - ; - - $proxyDiv.empty(); - - this.replacePlaneTextBody(sPlain); - } - } - } - } - } - catch (oExc) {} - - this.storePgpVerifyDataToDom(); - } -}; - -MessageModel.prototype.decryptPgpEncryptedMessage = function (sPassword) -{ - if (this.isPgpEncrypted()) - { - var - aRes = [], - mPgpMessage = null, - mPgpMessageDecrypted = null, - sFrom = this.from && this.from[0] && this.from[0].email ? this.from[0].email : '', - aPublicKey = RL.data().findPublicKeysByEmail(sFrom), - oPrivateKey = RL.data().findSelfPrivateKey(sPassword), - oValidKey = null, - oValidSysKey = null, - sPlain = '' - ; - - this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Error); - this.pgpSignedVerifyUser(''); - - if (!oPrivateKey) - { - this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.UnknownPrivateKey); - } - - try - { - mPgpMessage = window.openpgp.message.readArmored(this.plainRaw); - if (mPgpMessage && oPrivateKey && mPgpMessage.decrypt) - { - this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Unverified); - - mPgpMessageDecrypted = mPgpMessage.decrypt(oPrivateKey); - if (mPgpMessageDecrypted) - { - aRes = mPgpMessageDecrypted.verify(aPublicKey); - if (aRes && 0 < aRes.length) - { - oValidKey = _.find(aRes, function (oItem) { - return oItem && oItem.keyid && oItem.valid; - }); - - if (oValidKey) - { - oValidSysKey = RL.data().findPublicKeyByHex(oValidKey.keyid.toHex()); - if (oValidSysKey) - { - this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Success); - this.pgpSignedVerifyUser(oValidSysKey.user); - } - } - } - - sPlain = mPgpMessageDecrypted.getText(); - - sPlain = - $proxyDiv.empty().append( - $('').text(sPlain) - ).html() - ; - - $proxyDiv.empty(); - - this.replacePlaneTextBody(sPlain); - } - } - } - catch (oExc) {} - - this.storePgpVerifyDataToDom(); - } -}; - -MessageModel.prototype.replacePlaneTextBody = function (sPlain) -{ - if (this.body) - { - this.body.html(sPlain).addClass('b-text-part plain'); - } -}; - -/** - * @return {string} - */ -MessageModel.prototype.flagHash = function () -{ - return [this.deleted(), this.unseen(), this.flagged(), this.answered(), this.forwarded(), - this.isReadReceipt()].join(''); -}; -/** - * @constructor - */ -function FolderModel() -{ - this.name = ko.observable(''); - this.fullName = ''; - this.fullNameRaw = ''; - this.fullNameHash = ''; - this.delimiter = ''; - this.namespace = ''; - this.deep = 0; - this.interval = 0; - - this.selectable = false; - this.existen = true; - - this.type = ko.observable(Enums.FolderType.User); - - this.focused = ko.observable(false); - this.selected = ko.observable(false); - this.edited = ko.observable(false); - this.collapsed = ko.observable(true); - this.subScribed = ko.observable(true); - this.subFolders = ko.observableArray([]); - this.deleteAccess = ko.observable(false); - this.actionBlink = ko.observable(false).extend({'falseTimeout': 1000}); - - this.nameForEdit = ko.observable(''); - - this.name.subscribe(function (sValue) { - this.nameForEdit(sValue); - }, this); - - this.edited.subscribe(function (bValue) { - if (bValue) - { - this.nameForEdit(this.name()); - } - }, this); - - this.privateMessageCountAll = ko.observable(0); - this.privateMessageCountUnread = ko.observable(0); - - this.collapsedPrivate = ko.observable(true); -} - -/** - * @static - * @param {AjaxJsonFolder} oJsonFolder - * @return {?FolderModel} - */ -FolderModel.newInstanceFromJson = function (oJsonFolder) -{ - var oFolderModel = new FolderModel(); - return oFolderModel.initByJson(oJsonFolder) ? oFolderModel.initComputed() : null; -}; - -/** - * @return {FolderModel} - */ -FolderModel.prototype.initComputed = function () -{ - this.hasSubScribedSubfolders = ko.computed(function () { - return !!_.find(this.subFolders(), function (oFolder) { - return oFolder.subScribed() && !oFolder.isSystemFolder(); - }); - }, this); - - this.canBeEdited = ko.computed(function () { - return Enums.FolderType.User === this.type() && this.existen && this.selectable; - }, this); - - this.visible = ko.computed(function () { - var - bSubScribed = this.subScribed(), - bSubFolders = this.hasSubScribedSubfolders() - ; - - return (bSubScribed || (bSubFolders && (!this.existen || !this.selectable))); - }, this); - - this.isSystemFolder = ko.computed(function () { - return Enums.FolderType.User !== this.type(); - }, this); - - this.hidden = ko.computed(function () { - var - bSystem = this.isSystemFolder(), - bSubFolders = this.hasSubScribedSubfolders() - ; - - return (bSystem && !bSubFolders) || (!this.selectable && !bSubFolders); - - }, this); - - this.selectableForFolderList = ko.computed(function () { - return !this.isSystemFolder() && this.selectable; - }, this); - - this.messageCountAll = ko.computed({ - 'read': this.privateMessageCountAll, - 'write': function (iValue) { - if (Utils.isPosNumeric(iValue, true)) - { - this.privateMessageCountAll(iValue); - } - else - { - this.privateMessageCountAll.valueHasMutated(); - } - }, - 'owner': this - }); - - this.messageCountUnread = ko.computed({ - 'read': this.privateMessageCountUnread, - 'write': function (iValue) { - if (Utils.isPosNumeric(iValue, true)) - { - this.privateMessageCountUnread(iValue); - } - else - { - this.privateMessageCountUnread.valueHasMutated(); - } - }, - 'owner': this - }); - - this.printableUnreadCount = ko.computed(function () { - var - iCount = this.messageCountAll(), - iUnread = this.messageCountUnread(), - iType = this.type() - ; - - if (Enums.FolderType.Inbox === iType) - { - RL.data().foldersInboxUnreadCount(iUnread); - } - - if (0 < iCount) - { - if (Enums.FolderType.Draft === iType) - { - return '' + iCount; - } - else if (0 < iUnread && Enums.FolderType.Trash !== iType && Enums.FolderType.Archive !== iType && Enums.FolderType.SentItems !== iType) - { - return '' + iUnread; - } - } - - return ''; - - }, this); - - this.canBeDeleted = ko.computed(function () { - var - bSystem = this.isSystemFolder() - ; - return !bSystem && 0 === this.subFolders().length && 'INBOX' !== this.fullNameRaw; - }, this); - - this.canBeSubScribed = ko.computed(function () { - return !this.isSystemFolder() && this.selectable && 'INBOX' !== this.fullNameRaw; - }, this); - - this.visible.subscribe(function () { - Utils.timeOutAction('folder-list-folder-visibility-change', function () { - $window.trigger('folder-list-folder-visibility-change'); - }, 100); - }); - - this.localName = ko.computed(function () { - - Globals.langChangeTrigger(); - - var - iType = this.type(), - sName = this.name() - ; - - if (this.isSystemFolder()) - { - switch (iType) - { - case Enums.FolderType.Inbox: - sName = Utils.i18n('FOLDER_LIST/INBOX_NAME'); - break; - case Enums.FolderType.SentItems: - sName = Utils.i18n('FOLDER_LIST/SENT_NAME'); - break; - case Enums.FolderType.Draft: - sName = Utils.i18n('FOLDER_LIST/DRAFTS_NAME'); - break; - case Enums.FolderType.Spam: - sName = Utils.i18n('FOLDER_LIST/SPAM_NAME'); - break; - case Enums.FolderType.Trash: - sName = Utils.i18n('FOLDER_LIST/TRASH_NAME'); - break; - case Enums.FolderType.Archive: - sName = Utils.i18n('FOLDER_LIST/ARCHIVE_NAME'); - break; - } - } - - return sName; - - }, this); - - this.manageFolderSystemName = ko.computed(function () { - - Globals.langChangeTrigger(); - - var - sSuffix = '', - iType = this.type(), - sName = this.name() - ; - - if (this.isSystemFolder()) - { - switch (iType) - { - case Enums.FolderType.Inbox: - sSuffix = '(' + Utils.i18n('FOLDER_LIST/INBOX_NAME') + ')'; - break; - case Enums.FolderType.SentItems: - sSuffix = '(' + Utils.i18n('FOLDER_LIST/SENT_NAME') + ')'; - break; - case Enums.FolderType.Draft: - sSuffix = '(' + Utils.i18n('FOLDER_LIST/DRAFTS_NAME') + ')'; - break; - case Enums.FolderType.Spam: - sSuffix = '(' + Utils.i18n('FOLDER_LIST/SPAM_NAME') + ')'; - break; - case Enums.FolderType.Trash: - sSuffix = '(' + Utils.i18n('FOLDER_LIST/TRASH_NAME') + ')'; - break; - case Enums.FolderType.Archive: - sSuffix = '(' + Utils.i18n('FOLDER_LIST/ARCHIVE_NAME') + ')'; - break; - } - } - - if ('' !== sSuffix && '(' + sName + ')' === sSuffix || '(inbox)' === sSuffix.toLowerCase()) - { - sSuffix = ''; - } - - return sSuffix; - - }, this); - - this.collapsed = ko.computed({ - 'read': function () { - return !this.hidden() && this.collapsedPrivate(); - }, - 'write': function (mValue) { - this.collapsedPrivate(mValue); - }, - 'owner': this - }); - - this.hasUnreadMessages = ko.computed(function () { - return 0 < this.messageCountUnread(); - }, this); - - this.hasSubScribedUnreadMessagesSubfolders = ko.computed(function () { - return !!_.find(this.subFolders(), function (oFolder) { - return oFolder.hasUnreadMessages() || oFolder.hasSubScribedUnreadMessagesSubfolders(); - }); - }, this); - - return this; -}; - -FolderModel.prototype.fullName = ''; -FolderModel.prototype.fullNameRaw = ''; -FolderModel.prototype.fullNameHash = ''; -FolderModel.prototype.delimiter = ''; -FolderModel.prototype.namespace = ''; -FolderModel.prototype.deep = 0; -FolderModel.prototype.interval = 0; - -/** - * @return {string} - */ -FolderModel.prototype.collapsedCss = function () -{ - return this.hasSubScribedSubfolders() ? - (this.collapsed() ? 'icon-right-mini e-collapsed-sign' : 'icon-down-mini e-collapsed-sign') : 'icon-none e-collapsed-sign'; -}; - -/** - * @param {AjaxJsonFolder} oJsonFolder - * @return {boolean} - */ -FolderModel.prototype.initByJson = function (oJsonFolder) -{ - var bResult = false; - if (oJsonFolder && 'Object/Folder' === oJsonFolder['@Object']) - { - this.name(oJsonFolder.Name); - this.delimiter = oJsonFolder.Delimiter; - this.fullName = oJsonFolder.FullName; - this.fullNameRaw = oJsonFolder.FullNameRaw; - this.fullNameHash = oJsonFolder.FullNameHash; - this.deep = oJsonFolder.FullNameRaw.split(this.delimiter).length - 1; - this.selectable = !!oJsonFolder.IsSelectable; - this.existen = !!oJsonFolder.IsExisten; - - this.subScribed(!!oJsonFolder.IsSubscribed); - this.type('INBOX' === this.fullNameRaw ? Enums.FolderType.Inbox : Enums.FolderType.User); - - bResult = true; - } - - return bResult; -}; - -/** - * @return {string} - */ -FolderModel.prototype.printableFullName = function () -{ - return this.fullName.split(this.delimiter).join(' / '); -}; +ko.bindingHandlers.tooltip2 = { + 'init': function (oElement, fValueAccessor) { + var + $oEl = $(oElement), + sClass = $oEl.data('tooltip-class') || '', + sPlacement = $oEl.data('tooltip-placement') || 'top' + ; -/** - * @param {string} sEmail - * @param {boolean=} bCanBeDelete = true - * @constructor - */ -function AccountModel(sEmail, bCanBeDelete) -{ - this.email = sEmail; - this.deleteAccess = ko.observable(false); - this.canBeDalete = ko.observable(bCanBeDelete); -} - -AccountModel.prototype.email = ''; - -/** - * @return {string} - */ -AccountModel.prototype.changeAccountLink = function () -{ - return RL.link().change(this.email); + $oEl.tooltip({ + 'delay': { + 'show': 500, + 'hide': 100 + }, + 'html': true, + 'container': 'body', + 'placement': sPlacement, + 'title': function () { + return $oEl.is('.disabled') || Globals.dropdownVisibility() ? '' : + '' + fValueAccessor()() + ''; + } + }).click(function () { + $oEl.tooltip('hide'); + }); + + Globals.dropdownVisibility.subscribe(function (bValue) { + if (bValue) + { + $oEl.tooltip('hide'); + } + }); + } }; -/** - * @param {string} sId - * @param {string} sEmail - * @param {boolean=} bCanBeDelete = true - * @constructor - */ -function IdentityModel(sId, sEmail, bCanBeDelete) -{ - this.id = sId; - this.email = ko.observable(sEmail); - this.name = ko.observable(''); - this.replyTo = ko.observable(''); - this.bcc = ko.observable(''); - - this.deleteAccess = ko.observable(false); - this.canBeDalete = ko.observable(bCanBeDelete); -} - -IdentityModel.prototype.formattedName = function () -{ - var sName = this.name(); - return '' === sName ? this.email() : sName + ' <' + this.email() + '>'; -}; - -IdentityModel.prototype.formattedNameForCompose = function () -{ - var sName = this.name(); - return '' === sName ? this.email() : sName + ' (' + this.email() + ')'; -}; - -IdentityModel.prototype.formattedNameForEmail = function () -{ - var sName = this.name(); - return '' === sName ? this.email() : '"' + Utils.quoteName(sName) + '" <' + this.email() + '>'; -}; -/** - * @param {string} iIndex - * @param {string} sGuID - * @param {string} sID - * @param {string} sUserID - * @param {string} sEmail - * @param {boolean} bIsPrivate - * @param {string} sArmor - * @constructor - */ -function OpenPgpKeyModel(iIndex, sGuID, sID, sUserID, sEmail, bIsPrivate, sArmor) -{ - this.index = iIndex; - this.id = sID; - this.guid = sGuID; - this.user = sUserID; - this.email = sEmail; - this.armor = sArmor; - this.isPrivate = !!bIsPrivate; - - this.deleteAccess = ko.observable(false); -} - -OpenPgpKeyModel.prototype.index = 0; -OpenPgpKeyModel.prototype.id = ''; -OpenPgpKeyModel.prototype.guid = ''; -OpenPgpKeyModel.prototype.user = ''; -OpenPgpKeyModel.prototype.email = ''; -OpenPgpKeyModel.prototype.armor = ''; -OpenPgpKeyModel.prototype.isPrivate = false; +ko.bindingHandlers.tooltip3 = { + 'init': function (oElement) { -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsFolderClearViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsFolderClear'); - - this.selectedFolder = ko.observable(null); - this.clearingProcess = ko.observable(false); - this.clearingError = ko.observable(''); - - this.folderFullNameForClear = ko.computed(function () { - var oFolder = this.selectedFolder(); - return oFolder ? oFolder.printableFullName() : ''; - }, this); - - this.folderNameForClear = ko.computed(function () { - var oFolder = this.selectedFolder(); - return oFolder ? oFolder.localName() : ''; - }, this); - - this.dangerDescHtml = ko.computed(function () { - return Utils.i18n('POPUPS_CLEAR_FOLDER/DANGER_DESC_HTML_1', { - 'FOLDER': this.folderNameForClear() - }); - }, this); - - this.clearCommand = Utils.createCommand(this, function () { - - var - self = this, - oFolderToClear = this.selectedFolder() - ; - - if (oFolderToClear) - { - RL.data().message(null); - RL.data().messageList([]); - - this.clearingProcess(true); - - RL.cache().setFolderHash(oFolderToClear.fullNameRaw, ''); - RL.remote().folderClear(function (sResult, oData) { - - self.clearingProcess(false); - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - RL.reloadMessageList(true); - self.cancelCommand(); - } - else - { - if (oData && oData.ErrorCode) - { - self.clearingError(Utils.getNotification(oData.ErrorCode)); - } - else - { - self.clearingError(Utils.getNotification(Enums.Notification.MailServerError)); - } - } - }, oFolderToClear.fullNameRaw); - } - - }, function () { - - var - oFolder = this.selectedFolder(), - bIsClearing = this.clearingProcess() - ; - - return !bIsClearing && null !== oFolder; - - }); - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsFolderClearViewModel', PopupsFolderClearViewModel); - -PopupsFolderClearViewModel.prototype.clearPopup = function () -{ - this.clearingProcess(false); - this.selectedFolder(null); -}; - -PopupsFolderClearViewModel.prototype.onShow = function (oFolder) -{ - this.clearPopup(); - if (oFolder) - { - this.selectedFolder(oFolder); - } -}; + var $oEl = $(oElement); + + $oEl.tooltip({ + 'container': 'body', + 'trigger': 'hover manual', + 'title': function () { + return $oEl.data('tooltip3-data') || ''; + } + }); -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsFolderCreateViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsFolderCreate'); - - Utils.initOnStartOrLangChange(function () { - this.sNoParentText = Utils.i18n('POPUPS_CREATE_FOLDER/SELECT_NO_PARENT'); - }, this); - - this.folderName = ko.observable(''); - this.folderName.focused = ko.observable(false); - - this.selectedParentValue = ko.observable(Consts.Values.UnuseOptionValue); - - this.parentFolderSelectList = ko.computed(function () { - - var - oData = RL.data(), - aTop = [], - fDisableCallback = null, - fVisibleCallback = null, - aList = oData.folderList(), - fRenameCallback = function (oItem) { - return oItem ? (oItem.isSystemFolder() ? oItem.name() + ' ' + oItem.manageFolderSystemName() : oItem.name()) : ''; - } - ; - - aTop.push(['', this.sNoParentText]); - - if ('' !== oData.namespace) - { - fDisableCallback = function (oItem) - { - return oData.namespace !== oItem.fullNameRaw.substr(0, oData.namespace.length); - }; - } - - return RL.folderListOptionsBuilder([], aList, [], aTop, null, fDisableCallback, fVisibleCallback, fRenameCallback); - - }, this); - - // commands - this.createFolder = Utils.createCommand(this, function () { - - var - oData = RL.data(), - sParentFolderName = this.selectedParentValue() - ; - - if ('' === sParentFolderName && 1 < oData.namespace.length) - { - sParentFolderName = oData.namespace.substr(0, oData.namespace.length - 1); - } - - oData.foldersCreating(true); - RL.remote().folderCreate(function (sResult, oData) { - - RL.data().foldersCreating(false); - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - RL.folders(); - } - else - { - RL.data().foldersListError( - oData && oData.ErrorCode ? Utils.getNotification(oData.ErrorCode) : Utils.i18n('NOTIFICATIONS/CANT_CREATE_FOLDER')); - } - - }, this.folderName(), sParentFolderName); - - this.cancelCommand(); - - }, function () { - return this.simpleFolderNameValidation(this.folderName()); - }); - - this.defautOptionsAfterRender = Utils.defautOptionsAfterRender; - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsFolderCreateViewModel', PopupsFolderCreateViewModel); - -PopupsFolderCreateViewModel.prototype.sNoParentText = ''; - -PopupsFolderCreateViewModel.prototype.simpleFolderNameValidation = function (sName) -{ - return (/^[^\\\/]+$/g).test(Utils.trim(sName)); -}; - -PopupsFolderCreateViewModel.prototype.clearPopup = function () -{ - this.folderName(''); - this.selectedParentValue(''); - this.folderName.focused(false); -}; - -PopupsFolderCreateViewModel.prototype.onShow = function () -{ - this.clearPopup(); -}; - -PopupsFolderCreateViewModel.prototype.onFocus = function () -{ - this.folderName.focused(true); -}; + Globals.dropdownVisibility.subscribe(function (bValue) { + if (bValue) + { + $oEl.tooltip('hide'); + } + }); -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsFolderSystemViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsFolderSystem'); - - Utils.initOnStartOrLangChange(function () { - this.sChooseOnText = Utils.i18n('POPUPS_SYSTEM_FOLDERS/SELECT_CHOOSE_ONE'); - this.sUnuseText = Utils.i18n('POPUPS_SYSTEM_FOLDERS/SELECT_UNUSE_NAME'); - }, this); - - this.notification = ko.observable(''); - - this.folderSelectList = ko.computed(function () { - return RL.folderListOptionsBuilder([], RL.data().folderList(), RL.data().folderListSystemNames(), [ - ['', this.sChooseOnText], - [Consts.Values.UnuseOptionValue, this.sUnuseText] - ]); - }, this); - - var - oData = RL.data(), - self = this, - fSaveSystemFolders = null, - fCallback = null - ; - - this.sentFolder = oData.sentFolder; - this.draftFolder = oData.draftFolder; - this.spamFolder = oData.spamFolder; - this.trashFolder = oData.trashFolder; - this.archiveFolder = oData.archiveFolder; - - fSaveSystemFolders = _.debounce(function () { - - RL.settingsSet('SentFolder', self.sentFolder()); - RL.settingsSet('DraftFolder', self.draftFolder()); - RL.settingsSet('SpamFolder', self.spamFolder()); - RL.settingsSet('TrashFolder', self.trashFolder()); - RL.settingsSet('ArchiveFolder', self.archiveFolder()); - - RL.remote().saveSystemFolders(Utils.emptyFunction, { - 'SentFolder': self.sentFolder(), - 'DraftFolder': self.draftFolder(), - 'SpamFolder': self.spamFolder(), - 'TrashFolder': self.trashFolder(), - 'ArchiveFolder': self.archiveFolder(), - 'NullFolder': 'NullFolder' - }); - - }, 1000); - - fCallback = function () { - - RL.settingsSet('SentFolder', self.sentFolder()); - RL.settingsSet('DraftFolder', self.draftFolder()); - RL.settingsSet('SpamFolder', self.spamFolder()); - RL.settingsSet('TrashFolder', self.trashFolder()); - RL.settingsSet('ArchiveFolder', self.archiveFolder()); - - fSaveSystemFolders(); - }; - - this.sentFolder.subscribe(fCallback); - this.draftFolder.subscribe(fCallback); - this.spamFolder.subscribe(fCallback); - this.trashFolder.subscribe(fCallback); - this.archiveFolder.subscribe(fCallback); - - this.defautOptionsAfterRender = Utils.defautOptionsAfterRender; - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsFolderSystemViewModel', PopupsFolderSystemViewModel); - -PopupsFolderSystemViewModel.prototype.sChooseOnText = ''; -PopupsFolderSystemViewModel.prototype.sUnuseText = ''; - -/** - * @param {number=} iNotificationType = Enums.SetSystemFoldersNotification.None - */ -PopupsFolderSystemViewModel.prototype.onShow = function (iNotificationType) -{ - var sNotification = ''; - - iNotificationType = Utils.isUnd(iNotificationType) ? Enums.SetSystemFoldersNotification.None : iNotificationType; - - switch (iNotificationType) - { - case Enums.SetSystemFoldersNotification.Sent: - sNotification = Utils.i18n('POPUPS_SYSTEM_FOLDERS/NOTIFICATION_SENT'); - break; - case Enums.SetSystemFoldersNotification.Draft: - sNotification = Utils.i18n('POPUPS_SYSTEM_FOLDERS/NOTIFICATION_DRAFTS'); - break; - case Enums.SetSystemFoldersNotification.Spam: - sNotification = Utils.i18n('POPUPS_SYSTEM_FOLDERS/NOTIFICATION_SPAM'); - break; - case Enums.SetSystemFoldersNotification.Trash: - sNotification = Utils.i18n('POPUPS_SYSTEM_FOLDERS/NOTIFICATION_TRASH'); - break; - case Enums.SetSystemFoldersNotification.Archive: - sNotification = Utils.i18n('POPUPS_SYSTEM_FOLDERS/NOTIFICATION_ARCHIVE'); - break; - } - - this.notification(sNotification); -}; - - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsComposeViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsCompose'); - - this.oEditor = null; - this.aDraftInfo = null; - this.sInReplyTo = ''; - this.bFromDraft = false; - this.bSkipNext = false; - this.sReferences = ''; - - this.bAllowIdentities = RL.settingsGet('AllowIdentities'); - - var - self = this, - oRainLoopData = RL.data(), - fCcAndBccCheckHelper = function (aValue) { - if (false === self.showCcAndBcc() && 0 < aValue.length) - { - self.showCcAndBcc(true); - } - } - ; - - this.allowOpenPGP = oRainLoopData.allowOpenPGP; - - this.resizer = ko.observable(false).extend({'throttle': 50}); - - this.identitiesDropdownTrigger = ko.observable(false); - - this.to = ko.observable(''); - this.to.focusTrigger = ko.observable(false); - this.cc = ko.observable(''); - this.bcc = ko.observable(''); - - this.replyTo = ko.observable(''); - this.subject = ko.observable(''); - this.isHtml = ko.observable(false); - - this.requestReadReceipt = ko.observable(false); - - this.sendError = ko.observable(false); - this.sendSuccessButSaveError = ko.observable(false); - this.savedError = ko.observable(false); - - this.savedTime = ko.observable(0); - this.savedOrSendingText = ko.observable(''); - - this.emptyToError = ko.observable(false); - this.showCcAndBcc = ko.observable(false); - - this.cc.subscribe(fCcAndBccCheckHelper, this); - this.bcc.subscribe(fCcAndBccCheckHelper, this); - - this.draftFolder = ko.observable(''); - this.draftUid = ko.observable(''); - this.sending = ko.observable(false); - this.saving = ko.observable(false); - this.attachments = ko.observableArray([]); - - this.attachmentsInProcess = this.attachments.filter(function (oItem) { - return oItem && '' === oItem.tempName(); - }); - - this.attachmentsInReady = this.attachments.filter(function (oItem) { - return oItem && '' !== oItem.tempName(); - }); - - this.attachments.subscribe(function () { - this.triggerForResize(); - }, this); - - this.isDraftFolderMessage = ko.computed(function () { - return '' !== this.draftFolder() && '' !== this.draftUid(); - }, this); - - this.composeUploaderButton = ko.observable(null); - this.composeUploaderDropPlace = ko.observable(null); - this.dragAndDropEnabled = ko.observable(false); - this.dragAndDropOver = ko.observable(false).extend({'throttle': 1}); - this.dragAndDropVisible = ko.observable(false).extend({'throttle': 1}); - this.attacheMultipleAllowed = ko.observable(false); - this.addAttachmentEnabled = ko.observable(false); - - this.composeEditorArea = ko.observable(null); - - this.identities = RL.data().identities; - - this.currentIdentityID = ko.observable(''); - - this.currentIdentityString = ko.observable(''); - this.currentIdentityResultEmail = ko.observable(''); - - this.identitiesOptions = ko.computed(function () { - - var aList = [{ - 'optValue': oRainLoopData.accountEmail(), - 'optText': this.formattedFrom(false) - }]; - - _.each(oRainLoopData.identities(), function (oItem) { - aList.push({ - 'optValue': oItem.id, - 'optText': oItem.formattedNameForCompose() - }); - }); - - return aList; - - }, this); - - ko.computed(function () { - - var - sResult = '', - sResultEmail = '', - oItem = null, - aList = this.identities(), - sID = this.currentIdentityID() - ; - - if (this.bAllowIdentities && sID && sID !== RL.data().accountEmail()) - { - oItem = _.find(aList, function (oItem) { - return oItem && sID === oItem['id']; - }); - - sResult = oItem ? oItem.formattedNameForCompose() : ''; - sResultEmail = oItem ? oItem.formattedNameForEmail() : ''; - - if ('' === sResult && aList[0]) - { - this.currentIdentityID(aList[0]['id']); - return ''; - } - } - - if ('' === sResult) - { - sResult = this.formattedFrom(false); - sResultEmail = this.formattedFrom(true); - } - - this.currentIdentityString(sResult); - this.currentIdentityResultEmail(sResultEmail); - - return sResult; - - }, this); - - this.to.subscribe(function (sValue) { - if (this.emptyToError() && 0 < sValue.length) - { - this.emptyToError(false); - } - }, this); - - this.editorResizeThrottle = _.throttle(_.bind(this.editorResize, this), 100); - - this.resizer.subscribe(function () { - this.editorResizeThrottle(); - }, this); - - this.canBeSended = ko.computed(function () { - return !this.sending() && - !this.saving() && - 0 === this.attachmentsInProcess().length && - 0 < this.to().length - ; - }, this); - - this.canBeSendedOrSaved = ko.computed(function () { - return !this.sending() && !this.saving(); - }, this); - - this.deleteCommand = Utils.createCommand(this, function () { - - RL.deleteMessagesFromFolderWithoutCheck(this.draftFolder(), [this.draftUid()]); - kn.hideScreenPopup(PopupsComposeViewModel); - - }, function () { - return this.isDraftFolderMessage(); - }); - - this.sendMessageResponse = _.bind(this.sendMessageResponse, this); - this.saveMessageResponse = _.bind(this.saveMessageResponse, this); - - this.sendCommand = Utils.createCommand(this, function () { - var - sTo = Utils.trim(this.to()), - sSentFolder = RL.data().sentFolder(), - aFlagsCache = [] - ; - - if (0 === sTo.length) - { - this.emptyToError(true); - } - else - { - if (RL.data().replySameFolder()) - { - if (Utils.isArray(this.aDraftInfo) && 3 === this.aDraftInfo.length && Utils.isNormal(this.aDraftInfo[2]) && 0 < this.aDraftInfo[2].length) - { - sSentFolder = this.aDraftInfo[2]; - } - } - - if ('' === sSentFolder) - { - kn.showScreenPopup(PopupsFolderSystemViewModel, [Enums.SetSystemFoldersNotification.Sent]); - } - else - { - this.sendError(false); - this.sending(true); - - if (Utils.isArray(this.aDraftInfo) && 3 === this.aDraftInfo.length) - { - aFlagsCache = RL.cache().getMessageFlagsFromCache(this.aDraftInfo[2], this.aDraftInfo[1]); - if (aFlagsCache) - { - if ('forward' === this.aDraftInfo[0]) - { - aFlagsCache[3] = true; - } - else - { - aFlagsCache[2] = true; - } - - RL.cache().setMessageFlagsToCache(this.aDraftInfo[2], this.aDraftInfo[1], aFlagsCache); - RL.reloadFlagsCurrentMessageListAndMessageFromCache(); - RL.cache().setFolderHash(this.aDraftInfo[2], ''); - } - } - - sSentFolder = Consts.Values.UnuseOptionValue === sSentFolder ? '' : sSentFolder; - - RL.cache().setFolderHash(this.draftFolder(), ''); - RL.cache().setFolderHash(sSentFolder, ''); - - RL.remote().sendMessage( - this.sendMessageResponse, - this.draftFolder(), - this.draftUid(), - sSentFolder, - this.currentIdentityResultEmail(), - sTo, - this.cc(), - this.bcc(), - this.subject(), - this.oEditor ? this.oEditor.isHtml() : false, - this.oEditor ? this.oEditor.getData() : '', - this.prepearAttachmentsForSendOrSave(), - this.aDraftInfo, - this.sInReplyTo, - this.sReferences, - this.requestReadReceipt() - ); - } - } - }, this.canBeSendedOrSaved); - - this.saveCommand = Utils.createCommand(this, function () { - - if (RL.data().draftFolderNotEnabled()) - { - kn.showScreenPopup(PopupsFolderSystemViewModel, [Enums.SetSystemFoldersNotification.Draft]); - } - else - { - this.savedError(false); - this.saving(true); - - this.bSkipNext = true; - - RL.cache().setFolderHash(RL.data().draftFolder(), ''); - - RL.remote().saveMessage( - this.saveMessageResponse, - this.draftFolder(), - this.draftUid(), - RL.data().draftFolder(), - this.currentIdentityResultEmail(), - this.to(), - this.cc(), - this.bcc(), - this.subject(), - this.oEditor ? this.oEditor.isHtml() : false, - this.oEditor ? this.oEditor.getData() : '', - this.prepearAttachmentsForSendOrSave(), - this.aDraftInfo, - this.sInReplyTo, - this.sReferences - ); - } - - }, this.canBeSendedOrSaved); - - RL.sub('interval.1m', function () { - if (this.modalVisibility() && !RL.data().draftFolderNotEnabled() && !this.isEmptyForm(false) && - !this.bSkipNext && !this.saving() && !this.sending() && !this.savedError()) - { - this.bSkipNext = false; - this.saveCommand(); - } - }, this); - - this.showCcAndBcc.subscribe(function () { - this.triggerForResize(); - }, this); - - this.dropboxEnabled = ko.observable(RL.settingsGet('DropboxApiKey') ? true : false); - - this.dropboxCommand = Utils.createCommand(this, function () { - - if (window.Dropbox) - { - window.Dropbox.choose({ - //'iframe': true, - 'success': function(aFiles) { - - if (aFiles && aFiles[0] && aFiles[0]['link']) - { - self.addDropboxAttachment(aFiles[0]); - } - }, - 'linkType': "direct", - 'multiselect': false - }); - } - - return true; - - }, function () { - return this.dropboxEnabled(); - }); - - this.driveEnabled = ko.observable(false); - - this.driveCommand = Utils.createCommand(this, function () { - -// this.driveOpenPopup(); - return true; - - }, function () { - return this.driveEnabled(); - }); - -// this.driveCallback = _.bind(this.driveCallback, this); - - this.bDisabeCloseOnEsc = true; - this.sDefaultKeyScope = Enums.KeyState.Compose; - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsComposeViewModel', PopupsComposeViewModel); - -PopupsComposeViewModel.prototype.openOpenPgpPopup = function () -{ - if (this.allowOpenPGP() && this.oEditor && !this.oEditor.isHtml()) - { - var self = this; - kn.showScreenPopup(PopupsComposeOpenPgpViewModel, [ - function (sResult) { - self.editor(function (oEditor) { - oEditor.setPlain(sResult); - }); - }, - this.oEditor.getData(), - this.currentIdentityResultEmail(), - this.to(), - this.cc(), - this.bcc() - ]); - } -}; - -PopupsComposeViewModel.prototype.reloadDraftFolder = function () -{ - var sDraftFolder = RL.data().draftFolder(); - if ('' !== sDraftFolder) - { - RL.cache().setFolderHash(sDraftFolder, ''); - if (RL.data().currentFolderFullNameRaw() === sDraftFolder) - { - RL.reloadMessageList(true); - } - else - { - RL.folderInformation(sDraftFolder); - } - } -}; - -PopupsComposeViewModel.prototype.findIdentityIdByMessage = function (sComposeType, oMessage) -{ - var - oIDs = {}, - sResult = '', - fFindHelper = function (oItem) { - if (oItem && oItem.email && oIDs[oItem.email]) - { - sResult = oIDs[oItem.email]; - return true; - } - - return false; - } - ; - - if (this.bAllowIdentities) - { - _.each(this.identities(), function (oItem) { - oIDs[oItem.email()] = oItem['id']; - }); - } - - oIDs[RL.data().accountEmail()] = RL.data().accountEmail(); - - if (oMessage) - { - switch (sComposeType) - { - case Enums.ComposeType.Empty: - sResult = RL.data().accountEmail(); - break; - case Enums.ComposeType.Reply: - case Enums.ComposeType.ReplyAll: - case Enums.ComposeType.Forward: - case Enums.ComposeType.ForwardAsAttachment: - _.find(_.union(oMessage.to, oMessage.cc, oMessage.bcc), fFindHelper); - break; - case Enums.ComposeType.Draft: - _.find(_.union(oMessage.from, oMessage.replyTo), fFindHelper); - break; - } - } - else - { - sResult = RL.data().accountEmail(); - } - - return sResult; -}; - -PopupsComposeViewModel.prototype.selectIdentity = function (oIdentity) -{ - if (oIdentity) - { - this.currentIdentityID(oIdentity.optValue); - } -}; - -/** - * - * @param {boolean=} bHeaderResult = false - * @returns {string} - */ -PopupsComposeViewModel.prototype.formattedFrom = function (bHeaderResult) -{ - var - sDisplayName = RL.data().displayName(), - sEmail = RL.data().accountEmail() - ; - - return '' === sDisplayName ? sEmail : - ((Utils.isUnd(bHeaderResult) ? false : !!bHeaderResult) ? - '"' + Utils.quoteName(sDisplayName) + '" <' + sEmail + '>' : - sDisplayName + ' (' + sEmail + ')') - ; -}; - -PopupsComposeViewModel.prototype.sendMessageResponse = function (sResult, oData) -{ - var - bResult = false, - sMessage = '' - ; - - this.sending(false); - - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - bResult = true; - if (this.modalVisibility()) - { - Utils.delegateRun(this, 'closeCommand'); - } - } - - if (this.modalVisibility() && !bResult) - { - if (oData && Enums.Notification.CantSaveMessage === oData.ErrorCode) - { - this.sendSuccessButSaveError(true); - window.alert(Utils.trim(Utils.i18n('COMPOSE/SAVED_ERROR_ON_SEND'))); - } - else - { - sMessage = Utils.getNotification(oData && oData.ErrorCode ? oData.ErrorCode : Enums.Notification.CantSendMessage, - oData && oData.ErrorMessage ? oData.ErrorMessage : ''); - - this.sendError(true); - window.alert(sMessage || Utils.getNotification(Enums.Notification.CantSendMessage)); - } - } - - this.reloadDraftFolder(); -}; - -PopupsComposeViewModel.prototype.saveMessageResponse = function (sResult, oData) -{ - var - bResult = false, - oMessage = null - ; - - this.saving(false); - - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - if (oData.Result.NewFolder && oData.Result.NewUid) - { - if (this.bFromDraft) - { - oMessage = RL.data().message(); - if (oMessage && this.draftFolder() === oMessage.folderFullNameRaw && this.draftUid() === oMessage.uid) - { - RL.data().message(null); - } - } - - this.draftFolder(oData.Result.NewFolder); - this.draftUid(oData.Result.NewUid); - - if (this.modalVisibility()) - { - this.savedTime(Math.round((new window.Date()).getTime() / 1000)); - - this.savedOrSendingText( - 0 < this.savedTime() ? Utils.i18n('COMPOSE/SAVED_TIME', { - 'TIME': moment.unix(this.savedTime() - 1).format('LT') - }) : '' - ); - - bResult = true; - - if (this.bFromDraft) - { - RL.cache().setFolderHash(this.draftFolder(), ''); - } - } - } - } - - if (!this.modalVisibility() && !bResult) - { - this.savedError(true); - this.savedOrSendingText(Utils.getNotification(Enums.Notification.CantSaveMessage)); - } - - this.reloadDraftFolder(); -}; - -PopupsComposeViewModel.prototype.onHide = function () -{ - this.reset(); - kn.routeOn(); -}; - -/** - * @param {string} sSignature - * @param {string=} sFrom - * @return {string} - */ -PopupsComposeViewModel.prototype.convertSignature = function (sSignature, sFrom) -{ - if ('' !== sSignature) - { - var bHtml = false; - if (':HTML:' === sSignature.substr(0, 6)) - { - bHtml = true; - sSignature = sSignature.substr(6); - } - - sSignature = sSignature.replace(/[\r]/, ''); - - sFrom = Utils.pString(sFrom); - if ('' !== sFrom) - { - sSignature = sSignature.replace(/{{FROM}}/, sFrom); - } - - sSignature = sSignature.replace(/[\s]{1,2}{{FROM}}/, '{{FROM}}'); - - sSignature = sSignature.replace(/{{FROM}}/, ''); - sSignature = sSignature.replace(/{{DATE}}/, moment().format('llll')); - - if (!bHtml) - { - sSignature = Utils.convertPlainTextToHtml(sSignature); - } - } - - return sSignature; -}; - -PopupsComposeViewModel.prototype.editor = function (fOnInit) -{ - if (fOnInit) - { - var self = this; - if (!this.oEditor && this.composeEditorArea()) - { - _.delay(function () { - self.oEditor = new NewHtmlEditorWrapper(self.composeEditorArea(), null, function () { - fOnInit(self.oEditor); - }, function (bHtml) { - self.isHtml(!!bHtml); - }); - }, 300); - } - else if (this.oEditor) - { - fOnInit(this.oEditor); - } - } -}; - -/** - * @param {string=} sType = Enums.ComposeType.Empty - * @param {?MessageModel|Array=} oMessageOrArray = null - * @param {Array=} aToEmails = null - */ -PopupsComposeViewModel.prototype.onShow = function (sType, oMessageOrArray, aToEmails) -{ - kn.routeOff(); - - var - self = this, - sFrom = '', - sTo = '', - sCc = '', - sDate = '', - sSubject = '', - oText = null, - sText = '', - sReplyTitle = '', - aResplyAllParts = [], - oExcludeEmail = {}, - mEmail = RL.data().accountEmail(), - sSignature = RL.data().signature(), - bSignatureToAll = RL.data().signatureToAll(), - aDownloads = [], - aDraftInfo = null, - oMessage = null, - sComposeType = sType || Enums.ComposeType.Empty, - fEmailArrayToStringLineHelper = function (aList, bFriendly) { - - var - iIndex = 0, - iLen = aList.length, - aResult = [] - ; - - for (; iIndex < iLen; iIndex++) - { - aResult.push(aList[iIndex].toLine(!!bFriendly)); - } - - return aResult.join(', '); - } - ; - - oMessageOrArray = oMessageOrArray || null; - if (oMessageOrArray && Utils.isNormal(oMessageOrArray)) - { - oMessage = Utils.isArray(oMessageOrArray) && 1 === oMessageOrArray.length ? oMessageOrArray[0] : - (!Utils.isArray(oMessageOrArray) ? oMessageOrArray : null); - } - - if (null !== mEmail) - { - oExcludeEmail[mEmail] = true; - this.currentIdentityID(this.findIdentityIdByMessage(sComposeType, oMessage)); - } - - this.reset(); - - if (Utils.isNonEmptyArray(aToEmails)) - { - this.to(fEmailArrayToStringLineHelper(aToEmails)); - } - - if ('' !== sComposeType && oMessage) - { - sDate = oMessage.fullFormatDateValue(); - sSubject = oMessage.subject(); - aDraftInfo = oMessage.aDraftInfo; - - oText = $(oMessage.body).clone(); - Utils.removeBlockquoteSwitcher(oText); - sText = oText.html(); - - switch (sComposeType) - { - case Enums.ComposeType.Empty: - break; - - case Enums.ComposeType.Reply: - this.to(fEmailArrayToStringLineHelper(oMessage.replyEmails(oExcludeEmail))); - this.subject(Utils.replySubjectAdd('Re', sSubject)); - this.prepearMessageAttachments(oMessage, sComposeType); - this.aDraftInfo = ['reply', oMessage.uid, oMessage.folderFullNameRaw]; - this.sInReplyTo = oMessage.sMessageId; - this.sReferences = Utils.trim(this.sInReplyTo + ' ' + oMessage.sReferences); - break; - - case Enums.ComposeType.ReplyAll: - aResplyAllParts = oMessage.replyAllEmails(oExcludeEmail); - this.to(fEmailArrayToStringLineHelper(aResplyAllParts[0])); - this.cc(fEmailArrayToStringLineHelper(aResplyAllParts[1])); - this.subject(Utils.replySubjectAdd('Re', sSubject)); - this.prepearMessageAttachments(oMessage, sComposeType); - this.aDraftInfo = ['reply', oMessage.uid, oMessage.folderFullNameRaw]; - this.sInReplyTo = oMessage.sMessageId; - this.sReferences = Utils.trim(this.sInReplyTo + ' ' + oMessage.references()); - break; - - case Enums.ComposeType.Forward: - this.subject(Utils.replySubjectAdd('Fwd', sSubject)); - this.prepearMessageAttachments(oMessage, sComposeType); - this.aDraftInfo = ['forward', oMessage.uid, oMessage.folderFullNameRaw]; - this.sInReplyTo = oMessage.sMessageId; - this.sReferences = Utils.trim(this.sInReplyTo + ' ' + oMessage.sReferences); - break; - - case Enums.ComposeType.ForwardAsAttachment: - this.subject(Utils.replySubjectAdd('Fwd', sSubject)); - this.prepearMessageAttachments(oMessage, sComposeType); - this.aDraftInfo = ['forward', oMessage.uid, oMessage.folderFullNameRaw]; - this.sInReplyTo = oMessage.sMessageId; - this.sReferences = Utils.trim(this.sInReplyTo + ' ' + oMessage.sReferences); - break; - - case Enums.ComposeType.Draft: - this.to(fEmailArrayToStringLineHelper(oMessage.to)); - this.cc(fEmailArrayToStringLineHelper(oMessage.cc)); - this.bcc(fEmailArrayToStringLineHelper(oMessage.bcc)); - - this.bFromDraft = true; - - this.draftFolder(oMessage.folderFullNameRaw); - this.draftUid(oMessage.uid); - - this.subject(sSubject); - this.prepearMessageAttachments(oMessage, sComposeType); - - this.aDraftInfo = Utils.isNonEmptyArray(aDraftInfo) && 3 === aDraftInfo.length ? aDraftInfo : null; - this.sInReplyTo = oMessage.sInReplyTo; - this.sReferences = oMessage.sReferences; - break; - - case Enums.ComposeType.EditAsNew: - this.to(fEmailArrayToStringLineHelper(oMessage.to)); - this.cc(fEmailArrayToStringLineHelper(oMessage.cc)); - this.bcc(fEmailArrayToStringLineHelper(oMessage.bcc)); - - this.subject(sSubject); - this.prepearMessageAttachments(oMessage, sComposeType); - - this.aDraftInfo = Utils.isNonEmptyArray(aDraftInfo) && 3 === aDraftInfo.length ? aDraftInfo : null; - this.sInReplyTo = oMessage.sInReplyTo; - this.sReferences = oMessage.sReferences; - break; - } - - switch (sComposeType) - { - case Enums.ComposeType.Reply: - case Enums.ComposeType.ReplyAll: - sFrom = oMessage.fromToLine(false, true); - sReplyTitle = Utils.i18n('COMPOSE/REPLY_MESSAGE_TITLE', { - 'DATETIME': sDate, - 'EMAIL': sFrom - }); - - sText = '
' + sReplyTitle + ':' + - ''; - - break; - - case Enums.ComposeType.Forward: - sFrom = oMessage.fromToLine(false, true); - sTo = oMessage.toToLine(false, true); - sCc = oMessage.ccToLine(false, true); - sText = '' + sText + '
' + Utils.i18n('COMPOSE/FORWARD_MESSAGE_TOP_TITLE') + - '
' + Utils.i18n('COMPOSE/FORWARD_MESSAGE_TOP_FROM') + ': ' + sFrom + - '
' + Utils.i18n('COMPOSE/FORWARD_MESSAGE_TOP_TO') + ': ' + sTo + - (0 < sCc.length ? '
' + Utils.i18n('COMPOSE/FORWARD_MESSAGE_TOP_CC') + ': ' + sCc : '') + - '
' + Utils.i18n('COMPOSE/FORWARD_MESSAGE_TOP_SENT') + ': ' + Utils.encodeHtml(sDate) + - '
' + Utils.i18n('COMPOSE/FORWARD_MESSAGE_TOP_SUBJECT') + ': ' + Utils.encodeHtml(sSubject) + - '
' + sText; - break; - case Enums.ComposeType.ForwardAsAttachment: - sText = ''; - break; - } - - if (bSignatureToAll && '' !== sSignature && - Enums.ComposeType.EditAsNew !== sComposeType && Enums.ComposeType.Draft !== sComposeType) - { - sText = this.convertSignature(sSignature, fEmailArrayToStringLineHelper(oMessage.from, true)) + '
' + sText; - } - - this.editor(function (oEditor) { - oEditor.setHtml(sText, false); - if (!oMessage.isHtml()) - { - oEditor.modeToggle(false); - } - }); - } - else if (Enums.ComposeType.Empty === sComposeType) - { - sText = this.convertSignature(sSignature); - this.editor(function (oEditor) { - oEditor.setHtml(sText, false); - if (Enums.EditorDefaultType.Html !== RL.data().editorDefaultType()) - { - oEditor.modeToggle(false); - } - }); - } - else if (Utils.isNonEmptyArray(oMessageOrArray)) - { - _.each(oMessageOrArray, function (oMessage) { - self.addMessageAsAttachment(oMessage); - }); - } - - aDownloads = this.getAttachmentsDownloadsForUpload(); - if (Utils.isNonEmptyArray(aDownloads)) - { - RL.remote().messageUploadAttachments(function (sResult, oData) { - - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - var - oAttachment = null, - sTempName = '' - ; - - if (!self.viewModelVisibility()) - { - for (sTempName in oData.Result) - { - if (oData.Result.hasOwnProperty(sTempName)) - { - oAttachment = self.getAttachmentById(oData.Result[sTempName]); - if (oAttachment) - { - oAttachment.tempName(sTempName); - } - } - } - } - } - else - { - self.setMessageAttachmentFailedDowbloadText(); - } - - }, aDownloads); - } - - this.triggerForResize(); -}; - -PopupsComposeViewModel.prototype.onFocus = function () -{ - if ('' === this.to()) - { - this.to.focusTrigger(!this.to.focusTrigger()); - } - else if (this.oEditor) - { - this.oEditor.focus(); - } - - this.triggerForResize(); -}; - -PopupsComposeViewModel.prototype.editorResize = function () -{ - if (this.oEditor) - { - this.oEditor.resize(); - } -}; - -PopupsComposeViewModel.prototype.tryToClosePopup = function () -{ - var self = this; - kn.showScreenPopup(PopupsAskViewModel, [Utils.i18n('POPUPS_ASK/DESC_WANT_CLOSE_THIS_WINDOW'), function () { - if (self.modalVisibility()) - { - Utils.delegateRun(self, 'closeCommand'); - } - }]); -}; - -PopupsComposeViewModel.prototype.onBuild = function () -{ - this.initUploader(); - - var - self = this, - oScript = null - ; - - key('ctrl+q, command+q', Enums.KeyState.Compose, function () { - self.identitiesDropdownTrigger(true); - return false; - }); - - key('ctrl+s, command+s', Enums.KeyState.Compose, function () { - self.saveCommand(); - return false; - }); - - key('ctrl+enter, command+enter', Enums.KeyState.Compose, function () { - self.sendCommand(); - return false; - }); - - key('esc', Enums.KeyState.Compose, function () { - self.tryToClosePopup(); - return false; - }); - - $window.on('resize', function () { - self.triggerForResize(); - }); - - if (this.dropboxEnabled()) - { - oScript = document.createElement('script'); - oScript.type = 'text/javascript'; - oScript.src = 'https://www.dropbox.com/static/api/1/dropins.js'; - $(oScript).attr('id', 'dropboxjs').attr('data-app-key', RL.settingsGet('DropboxApiKey')); - - document.body.appendChild(oScript); - } - -// TODO (Google Drive) -// if (false) -// { -// $.getScript('http://www.google.com/jsapi', function () { -// if (window.google) -// { -// window.google.load('picker', '1', { -// 'callback': Utils.emptyFunction -// }); -// } -// }); -// } -}; - -//PopupsComposeViewModel.prototype.driveCallback = function (oData) -//{ -// if (oData && window.google && oData['action'] === window.google.picker.Action.PICKED) -// { -// } -//}; -// -//PopupsComposeViewModel.prototype.driveOpenPopup = function () -//{ -// if (window.google) -// { -// var -// oPicker = new window.google.picker.PickerBuilder() -// .enableFeature(window.google.picker.Feature.NAV_HIDDEN) -// .addView(new window.google.picker.View(window.google.picker.ViewId.DOCS)) -// .setCallback(this.driveCallback).build() -// ; -// -// oPicker.setVisible(true); -// } -//}; - -/** - * @param {string} sId - * @return {?Object} - */ -PopupsComposeViewModel.prototype.getAttachmentById = function (sId) -{ - var - aAttachments = this.attachments(), - iIndex = 0, - iLen = aAttachments.length - ; - - for (; iIndex < iLen; iIndex++) - { - if (aAttachments[iIndex] && sId === aAttachments[iIndex].id) - { - return aAttachments[iIndex]; - } - } - - return null; -}; - -PopupsComposeViewModel.prototype.initUploader = function () -{ - if (this.composeUploaderButton()) - { - var - oUploadCache = {}, - iAttachmentSizeLimit = Utils.pInt(RL.settingsGet('AttachmentLimit')), - oJua = new Jua({ - 'action': RL.link().upload(), - 'name': 'uploader', - 'queueSize': 2, - 'multipleSizeLimit': 50, - 'disableFolderDragAndDrop': false, - 'clickElement': this.composeUploaderButton(), - 'dragAndDropElement': this.composeUploaderDropPlace() - }) - ; - - if (oJua) - { - oJua -// .on('onLimitReached', function (iLimit) { -// alert(iLimit); -// }) - .on('onDragEnter', _.bind(function () { - this.dragAndDropOver(true); - }, this)) - .on('onDragLeave', _.bind(function () { - this.dragAndDropOver(false); - }, this)) - .on('onBodyDragEnter', _.bind(function () { - this.dragAndDropVisible(true); - }, this)) - .on('onBodyDragLeave', _.bind(function () { - this.dragAndDropVisible(false); - }, this)) - .on('onProgress', _.bind(function (sId, iLoaded, iTotal) { - var oItem = null; - if (Utils.isUnd(oUploadCache[sId])) - { - oItem = this.getAttachmentById(sId); - if (oItem) - { - oUploadCache[sId] = oItem; - } - } - else - { - oItem = oUploadCache[sId]; - } - - if (oItem) - { - oItem.progress(' - ' + Math.floor(iLoaded / iTotal * 100) + '%'); - } - - }, this)) - .on('onSelect', _.bind(function (sId, oData) { - - this.dragAndDropOver(false); - - var - that = this, - sFileName = Utils.isUnd(oData.FileName) ? '' : oData.FileName.toString(), - mSize = Utils.isNormal(oData.Size) ? Utils.pInt(oData.Size) : null, - oAttachment = new ComposeAttachmentModel(sId, sFileName, mSize) - ; - - oAttachment.cancel = (function (sId) { - - return function () { - that.attachments.remove(function (oItem) { - return oItem && oItem.id === sId; - }); - - if (oJua) - { - oJua.cancel(sId); - } - }; - - }(sId)); - - this.attachments.push(oAttachment); - - if (0 < mSize && 0 < iAttachmentSizeLimit && iAttachmentSizeLimit < mSize) - { - oAttachment.error(Utils.i18n('UPLOAD/ERROR_FILE_IS_TOO_BIG')); - return false; - } - - return true; - - }, this)) - .on('onStart', _.bind(function (sId) { - - var - oItem = null - ; - - if (Utils.isUnd(oUploadCache[sId])) - { - oItem = this.getAttachmentById(sId); - if (oItem) - { - oUploadCache[sId] = oItem; - } - } - else - { - oItem = oUploadCache[sId]; - } - - if (oItem) - { - oItem.waiting(false); - oItem.uploading(true); - } - - }, this)) - .on('onComplete', _.bind(function (sId, bResult, oData) { - - var - sError = '', - mErrorCode = null, - oAttachmentJson = null, - oAttachment = this.getAttachmentById(sId) - ; - - oAttachmentJson = bResult && oData && oData.Result && oData.Result.Attachment ? oData.Result.Attachment : null; - mErrorCode = oData && oData.Result && oData.Result.ErrorCode ? oData.Result.ErrorCode : null; - - if (null !== mErrorCode) - { - sError = Utils.getUploadErrorDescByCode(mErrorCode); - } - else if (!oAttachmentJson) - { - sError = Utils.i18n('UPLOAD/ERROR_UNKNOWN'); - } - - if (oAttachment) - { - if ('' !== sError && 0 < sError.length) - { - oAttachment - .waiting(false) - .uploading(false) - .error(sError) - ; - } - else if (oAttachmentJson) - { - oAttachment - .waiting(false) - .uploading(false) - ; - - oAttachment.initByUploadJson(oAttachmentJson); - } - - if (Utils.isUnd(oUploadCache[sId])) - { - delete (oUploadCache[sId]); - } - } - - }, this)) - ; - - this - .addAttachmentEnabled(true) - .dragAndDropEnabled(oJua.isDragAndDropSupported()) - ; - } - else - { - this - .addAttachmentEnabled(false) - .dragAndDropEnabled(false) - ; - } - } -}; - -/** - * @return {Object} - */ -PopupsComposeViewModel.prototype.prepearAttachmentsForSendOrSave = function () -{ - var oResult = {}; - _.each(this.attachmentsInReady(), function (oItem) { - if (oItem && '' !== oItem.tempName() && oItem.enabled()) - { - oResult[oItem.tempName()] = [ - oItem.fileName(), - oItem.isInline ? '1' : '0', - oItem.CID, - oItem.contentLocation - ]; - } - }); - - return oResult; -}; - -/** - * @param {MessageModel} oMessage - */ -PopupsComposeViewModel.prototype.addMessageAsAttachment = function (oMessage) -{ - if (oMessage) - { - var - self = this, - oAttachment = null, - sTemp = oMessage.subject(), - fCancelFunc = function (sId) { - return function () { - self.attachments.remove(function (oItem) { - return oItem && oItem.id === sId; - }); - }; - } - ; - - sTemp = '.eml' === sTemp.substr(-4).toLowerCase() ? sTemp : sTemp + '.eml'; - oAttachment = new ComposeAttachmentModel( - oMessage.requestHash, sTemp, oMessage.size() - ); - - oAttachment.fromMessage = true; - oAttachment.cancel = fCancelFunc(oMessage.requestHash); - oAttachment.waiting(false).uploading(true); - - this.attachments.push(oAttachment); - } -}; - -/** - * @param {Object} oDropboxFile - * @return {boolean} - */ -PopupsComposeViewModel.prototype.addDropboxAttachment = function (oDropboxFile) -{ - var - self = this, - fCancelFunc = function (sId) { - return function () { - self.attachments.remove(function (oItem) { - return oItem && oItem.id === sId; - }); - }; - }, - iAttachmentSizeLimit = Utils.pInt(RL.settingsGet('AttachmentLimit')), - oAttachment = null, - mSize = oDropboxFile['bytes'] - ; - - oAttachment = new ComposeAttachmentModel( - oDropboxFile['link'], oDropboxFile['name'], mSize - ); - - oAttachment.fromMessage = false; - oAttachment.cancel = fCancelFunc(oDropboxFile['link']); - oAttachment.waiting(false).uploading(true); - - this.attachments.push(oAttachment); - - if (0 < mSize && 0 < iAttachmentSizeLimit && iAttachmentSizeLimit < mSize) - { - oAttachment.uploading(false); - oAttachment.error(Utils.i18n('UPLOAD/ERROR_FILE_IS_TOO_BIG')); - return false; - } - - RL.remote().composeUploadExternals(function (sResult, oData) { - - var bResult = false; - oAttachment.uploading(false); - - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - if (oData.Result[oAttachment.id]) - { - bResult = true; - oAttachment.tempName(oData.Result[oAttachment.id]); - } - } - - if (!bResult) - { - oAttachment.error(Utils.getUploadErrorDescByCode(Enums.UploadErrorCode.FileNoUploaded)); - } - - }, [oDropboxFile['link']]); - - return true; -}; - -/** - * @param {MessageModel} oMessage - * @param {string} sType - */ -PopupsComposeViewModel.prototype.prepearMessageAttachments = function (oMessage, sType) -{ - if (oMessage) - { - var - self = this, - aAttachments = Utils.isNonEmptyArray(oMessage.attachments()) ? oMessage.attachments() : [], - iIndex = 0, - iLen = aAttachments.length, - oAttachment = null, - oItem = null, - bAdd = false, - fCancelFunc = function (sId) { - return function () { - self.attachments.remove(function (oItem) { - return oItem && oItem.id === sId; - }); - }; - } - ; - - if (Enums.ComposeType.ForwardAsAttachment === sType) - { - this.addMessageAsAttachment(oMessage); - } - else - { - for (; iIndex < iLen; iIndex++) - { - oItem = aAttachments[iIndex]; - - bAdd = false; - switch (sType) { - case Enums.ComposeType.Reply: - case Enums.ComposeType.ReplyAll: - bAdd = oItem.isLinked; - break; - - case Enums.ComposeType.Forward: - case Enums.ComposeType.Draft: - case Enums.ComposeType.EditAsNew: - bAdd = true; - break; - } - - bAdd = true; - if (bAdd) - { - oAttachment = new ComposeAttachmentModel( - oItem.download, oItem.fileName, oItem.estimatedSize, - oItem.isInline, oItem.isLinked, oItem.cid, oItem.contentLocation - ); - - oAttachment.fromMessage = true; - oAttachment.cancel = fCancelFunc(oItem.download); - oAttachment.waiting(false).uploading(true); - - this.attachments.push(oAttachment); - } - } - } - } -}; - -PopupsComposeViewModel.prototype.removeLinkedAttachments = function () -{ - this.attachments.remove(function (oItem) { - return oItem && oItem.isLinked; - }); -}; - -PopupsComposeViewModel.prototype.setMessageAttachmentFailedDowbloadText = function () -{ - _.each(this.attachments(), function(oAttachment) { - if (oAttachment && oAttachment.fromMessage) - { - oAttachment - .waiting(false) - .uploading(false) - .error(Utils.getUploadErrorDescByCode(Enums.UploadErrorCode.FileNoUploaded)) - ; - } - }, this); -}; - -/** - * @param {boolean=} bIncludeAttachmentInProgress = true - * @return {boolean} - */ -PopupsComposeViewModel.prototype.isEmptyForm = function (bIncludeAttachmentInProgress) -{ - bIncludeAttachmentInProgress = Utils.isUnd(bIncludeAttachmentInProgress) ? true : !!bIncludeAttachmentInProgress; - var bAttach = bIncludeAttachmentInProgress ? - 0 === this.attachments().length : 0 === this.attachmentsInReady().length; - - return 0 === this.to().length && - 0 === this.cc().length && - 0 === this.bcc().length && - 0 === this.subject().length && - bAttach && - (!this.oEditor || '' === this.oEditor.getData()) - ; -}; - -PopupsComposeViewModel.prototype.reset = function () -{ - this.to(''); - this.cc(''); - this.bcc(''); - this.replyTo(''); - this.subject(''); - - this.requestReadReceipt(false); - - this.aDraftInfo = null; - this.sInReplyTo = ''; - this.bFromDraft = false; - this.sReferences = ''; - - this.sendError(false); - this.sendSuccessButSaveError(false); - this.savedError(false); - this.savedTime(0); - this.savedOrSendingText(''); - this.emptyToError(false); - this.showCcAndBcc(false); - - this.attachments([]); - this.dragAndDropOver(false); - this.dragAndDropVisible(false); - - this.draftFolder(''); - this.draftUid(''); - - this.sending(false); - this.saving(false); - - if (this.oEditor) - { - this.oEditor.clear(false); - } -}; - -/** - * @return {Array} - */ -PopupsComposeViewModel.prototype.getAttachmentsDownloadsForUpload = function () -{ - return _.map(_.filter(this.attachments(), function (oItem) { - return oItem && '' === oItem.tempName(); - }), function (oItem) { - return oItem.id; - }); -}; - -PopupsComposeViewModel.prototype.triggerForResize = function () -{ - this.resizer(!this.resizer()); - this.editorResizeThrottle(); -}; - - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsContactsViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsContacts'); - - var - self = this, - fFastClearEmptyListHelper = function (aList) { - if (aList && 0 < aList.length) { - self.viewProperties.removeAll(aList); - } - } - ; - - this.allowContactsSync = RL.data().allowContactsSync; - this.enableContactsSync = RL.data().enableContactsSync; - this.allowExport = !Globals.bMobileDevice; - - this.search = ko.observable(''); - this.contactsCount = ko.observable(0); - this.contacts = RL.data().contacts; - - this.currentContact = ko.observable(null); - - this.importUploaderButton = ko.observable(null); - - this.contactsPage = ko.observable(1); - this.contactsPageCount = ko.computed(function () { - var iPage = Math.ceil(this.contactsCount() / Consts.Defaults.ContactsPerPage); - return 0 >= iPage ? 1 : iPage; - }, this); - - this.contactsPagenator = ko.computed(Utils.computedPagenatorHelper(this.contactsPage, this.contactsPageCount)); - - this.emptySelection = ko.observable(true); - this.viewClearSearch = ko.observable(false); - - this.viewID = ko.observable(''); - this.viewReadOnly = ko.observable(false); - this.viewProperties = ko.observableArray([]); - - this.viewSaveTrigger = ko.observable(Enums.SaveSettingsStep.Idle); - - this.viewPropertiesNames = this.viewProperties.filter(function(oProperty) { - return -1 < Utils.inArray(oProperty.type(), [ - Enums.ContactPropertyType.FirstName, Enums.ContactPropertyType.LastName - ]); - }); - - this.viewPropertiesOther = this.viewProperties.filter(function(oProperty) { - return -1 < Utils.inArray(oProperty.type(), [ - Enums.ContactPropertyType.Note - ]); - }); - - this.viewPropertiesOther = ko.computed(function () { - - var aList = _.filter(this.viewProperties(), function (oProperty) { - return -1 < Utils.inArray(oProperty.type(), [ - Enums.ContactPropertyType.Nick - ]); - }); - - return _.sortBy(aList, function (oProperty) { - return oProperty.type(); - }); - - }, this); - - this.viewPropertiesEmails = this.viewProperties.filter(function(oProperty) { - return Enums.ContactPropertyType.Email === oProperty.type(); - }); - - this.viewPropertiesWeb = this.viewProperties.filter(function(oProperty) { - return Enums.ContactPropertyType.Web === oProperty.type(); - }); - - this.viewHasNonEmptyRequaredProperties = ko.computed(function() { - - var - aNames = this.viewPropertiesNames(), - aEmail = this.viewPropertiesEmails(), - fHelper = function (oProperty) { - return '' !== Utils.trim(oProperty.value()); - } - ; - - return !!(_.find(aNames, fHelper) || _.find(aEmail, fHelper)); - }, this); - - this.viewPropertiesPhones = this.viewProperties.filter(function(oProperty) { - return Enums.ContactPropertyType.Phone === oProperty.type(); - }); - - this.viewPropertiesEmailsNonEmpty = this.viewPropertiesNames.filter(function(oProperty) { - return '' !== Utils.trim(oProperty.value()); - }); - - this.viewPropertiesEmailsEmptyAndOnFocused = this.viewPropertiesEmails.filter(function(oProperty) { - var bF = oProperty.focused(); - return '' === Utils.trim(oProperty.value()) && !bF; - }); - - this.viewPropertiesPhonesEmptyAndOnFocused = this.viewPropertiesPhones.filter(function(oProperty) { - var bF = oProperty.focused(); - return '' === Utils.trim(oProperty.value()) && !bF; - }); - - this.viewPropertiesWebEmptyAndOnFocused = this.viewPropertiesWeb.filter(function(oProperty) { - var bF = oProperty.focused(); - return '' === Utils.trim(oProperty.value()) && !bF; - }); - - this.viewPropertiesOtherEmptyAndOnFocused = ko.computed(function () { - return _.filter(this.viewPropertiesOther(), function (oProperty) { - var bF = oProperty.focused(); - return '' === Utils.trim(oProperty.value()) && !bF; - }); - }, this); - - this.viewPropertiesEmailsEmptyAndOnFocused.subscribe(function(aList) { - fFastClearEmptyListHelper(aList); - }); - - this.viewPropertiesPhonesEmptyAndOnFocused.subscribe(function(aList) { - fFastClearEmptyListHelper(aList); - }); - - this.viewPropertiesWebEmptyAndOnFocused.subscribe(function(aList) { - fFastClearEmptyListHelper(aList); - }); - - this.viewPropertiesOtherEmptyAndOnFocused.subscribe(function(aList) { - fFastClearEmptyListHelper(aList); - }); - - this.viewSaving = ko.observable(false); - - this.useCheckboxesInList = RL.data().useCheckboxesInList; - - this.search.subscribe(function () { - this.reloadContactList(); - }, this); - - this.contacts.subscribe(function () { - Utils.windowResize(); - }, this); - - this.viewProperties.subscribe(function () { - Utils.windowResize(); - }, this); - - this.contactsChecked = ko.computed(function () { - return _.filter(this.contacts(), function (oItem) { - return oItem.checked(); - }); - }, this); - - this.contactsCheckedOrSelected = ko.computed(function () { - - var - aChecked = this.contactsChecked(), - oSelected = this.currentContact() - ; - - return _.union(aChecked, oSelected ? [oSelected] : []); - - }, this); - - this.contactsCheckedOrSelectedUids = ko.computed(function () { - return _.map(this.contactsCheckedOrSelected(), function (oContact) { - return oContact.idContact; - }); - }, this); - - this.selector = new Selector(this.contacts, this.currentContact, - '.e-contact-item .actionHandle', '.e-contact-item.selected', '.e-contact-item .checkboxItem', - '.e-contact-item.focused'); - - this.selector.on('onItemSelect', _.bind(function (oContact) { - this.populateViewContact(oContact ? oContact : null); - if (!oContact) - { - this.emptySelection(true); - } - }, this)); - - this.selector.on('onItemGetUid', function (oContact) { - return oContact ? oContact.generateUid() : ''; - }); - - this.newCommand = Utils.createCommand(this, function () { - this.populateViewContact(null); - this.currentContact(null); - }); - - this.deleteCommand = Utils.createCommand(this, function () { - this.deleteSelectedContacts(); - this.emptySelection(true); - }, function () { - return 0 < this.contactsCheckedOrSelected().length; - }); - - this.newMessageCommand = Utils.createCommand(this, function () { - var aC = this.contactsCheckedOrSelected(), aE = []; - if (Utils.isNonEmptyArray(aC)) - { - aE = _.map(aC, function (oItem) { - if (oItem) - { - var - aData = oItem.getNameAndEmailHelper(), - oEmail = aData ? new EmailModel(aData[0], aData[1]) : null - ; - - if (oEmail && oEmail.validate()) - { - return oEmail; - } - } - - return null; - }); - - aE = _.compact(aE); - } - - if (Utils.isNonEmptyArray(aE)) - { - kn.hideScreenPopup(PopupsContactsViewModel); - kn.showScreenPopup(PopupsComposeViewModel, [Enums.ComposeType.Empty, null, aE]); - } - - }, function () { - return 0 < this.contactsCheckedOrSelected().length; - }); - - this.clearCommand = Utils.createCommand(this, function () { - this.search(''); - }); - - this.saveCommand = Utils.createCommand(this, function () { - - this.viewSaving(true); - this.viewSaveTrigger(Enums.SaveSettingsStep.Animate); - - var - sRequestUid = Utils.fakeMd5(), - aProperties = [] - ; - - _.each(this.viewProperties(), function (oItem) { - if (oItem.type() && '' !== Utils.trim(oItem.value())) - { - aProperties.push([oItem.type(), oItem.value(), oItem.typeStr()]); - } - }); - - RL.remote().contactSave(function (sResult, oData) { - - var bRes = false; - self.viewSaving(false); - - if (Enums.StorageResultType.Success === sResult && oData && oData.Result && - oData.Result.RequestUid === sRequestUid && 0 < Utils.pInt(oData.Result.ResultID)) - { - if ('' === self.viewID()) - { - self.viewID(Utils.pInt(oData.Result.ResultID)); - } - - self.reloadContactList(); - bRes = true; - } - - _.delay(function () { - self.viewSaveTrigger(bRes ? Enums.SaveSettingsStep.TrueResult : Enums.SaveSettingsStep.FalseResult); - }, 300); - - if (bRes) - { - self.watchDirty(false); - - _.delay(function () { - self.viewSaveTrigger(Enums.SaveSettingsStep.Idle); - }, 1000); - } - - }, sRequestUid, this.viewID(), aProperties); - - }, function () { - var - bV = this.viewHasNonEmptyRequaredProperties(), - bReadOnly = this.viewReadOnly() - ; - return !this.viewSaving() && bV && !bReadOnly; - }); - - this.syncCommand = Utils.createCommand(this, function () { - - var self = this; - RL.contactsSync(function (sResult, oData) { - if (Enums.StorageResultType.Success !== sResult || !oData || !oData.Result) - { - window.alert(Utils.getNotification( - oData && oData.ErrorCode ? oData.ErrorCode : Enums.Notification.ContactsSyncError)); - } - - self.reloadContactList(true); - }); - - }, function () { - return !this.contacts.syncing() && !this.contacts.importing(); - }); - - this.bDropPageAfterDelete = false; - - this.watchDirty = ko.observable(false); - this.watchHash = ko.observable(false); - - this.viewHash = ko.computed(function () { - return '' + _.map(self.viewProperties(), function (oItem) { - return oItem.value(); - }).join(''); - }); - -// this.saveCommandDebounce = _.debounce(_.bind(this.saveCommand, this), 1000); - - this.viewHash.subscribe(function () { - if (this.watchHash() && !this.viewReadOnly() && !this.watchDirty()) - { - this.watchDirty(true); - } - }, this); - - this.sDefaultKeyScope = Enums.KeyState.ContactList; - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsContactsViewModel', PopupsContactsViewModel); - -PopupsContactsViewModel.prototype.getPropertyPlceholder = function (sType) -{ - var sResult = ''; - switch (sType) - { - case Enums.ContactPropertyType.LastName: - sResult = 'CONTACTS/PLACEHOLDER_ENTER_LAST_NAME'; - break; - case Enums.ContactPropertyType.FirstName: - sResult = 'CONTACTS/PLACEHOLDER_ENTER_FIRST_NAME'; - break; - case Enums.ContactPropertyType.Nick: - sResult = 'CONTACTS/PLACEHOLDER_ENTER_NICK_NAME'; - break; - } - - return sResult; -}; - -PopupsContactsViewModel.prototype.addNewProperty = function (sType, sTypeStr) -{ - this.viewProperties.push(new ContactPropertyModel(sType, sTypeStr || '', '', true, this.getPropertyPlceholder(sType))); -}; - -PopupsContactsViewModel.prototype.addNewOrFocusProperty = function (sType, sTypeStr) -{ - var oItem = _.find(this.viewProperties(), function (oItem) { - return sType === oItem.type(); - }); - - if (oItem) - { - oItem.focused(true); - } - else - { - this.addNewProperty(sType, sTypeStr); - } -}; - -PopupsContactsViewModel.prototype.addNewEmail = function () -{ - this.addNewProperty(Enums.ContactPropertyType.Email, 'Home'); -}; - -PopupsContactsViewModel.prototype.addNewPhone = function () -{ - this.addNewProperty(Enums.ContactPropertyType.Phone, 'Mobile'); -}; - -PopupsContactsViewModel.prototype.addNewWeb = function () -{ - this.addNewProperty(Enums.ContactPropertyType.Web); -}; - -PopupsContactsViewModel.prototype.addNewNickname = function () -{ - this.addNewOrFocusProperty(Enums.ContactPropertyType.Nick); -}; - -PopupsContactsViewModel.prototype.addNewNotes = function () -{ - this.addNewOrFocusProperty(Enums.ContactPropertyType.Note); -}; - -PopupsContactsViewModel.prototype.addNewBirthday = function () -{ - this.addNewOrFocusProperty(Enums.ContactPropertyType.Birthday); -}; - -//PopupsContactsViewModel.prototype.addNewAddress = function () -//{ -//}; - -PopupsContactsViewModel.prototype.exportVcf = function () -{ - RL.download(RL.link().exportContactsVcf()); -}; - -PopupsContactsViewModel.prototype.exportCsv = function () -{ - RL.download(RL.link().exportContactsCsv()); -}; - -PopupsContactsViewModel.prototype.initUploader = function () -{ - if (this.importUploaderButton()) - { - var - oJua = new Jua({ - 'action': RL.link().uploadContacts(), - 'name': 'uploader', - 'queueSize': 1, - 'multipleSizeLimit': 1, - 'disableFolderDragAndDrop': true, - 'disableDragAndDrop': true, - 'disableMultiple': true, - 'disableDocumentDropPrevent': true, - 'clickElement': this.importUploaderButton() - }) - ; - - if (oJua) - { - oJua - .on('onStart', _.bind(function () { - this.contacts.importing(true); - }, this)) - .on('onComplete', _.bind(function (sId, bResult, oData) { - - this.contacts.importing(false); - this.reloadContactList(); - - if (!sId || !bResult || !oData || !oData.Result) - { - window.alert(Utils.i18n('CONTACTS/ERROR_IMPORT_FILE')); - } - - }, this)) - ; - } - } -}; - -PopupsContactsViewModel.prototype.removeCheckedOrSelectedContactsFromList = function () -{ - var - self = this, - oKoContacts = this.contacts, - oCurrentContact = this.currentContact(), - iCount = this.contacts().length, - aContacts = this.contactsCheckedOrSelected() - ; - - if (0 < aContacts.length) - { - _.each(aContacts, function (oContact) { - - if (oCurrentContact && oCurrentContact.idContact === oContact.idContact) - { - oCurrentContact = null; - self.currentContact(null); - } - - oContact.deleted(true); - iCount--; - }); - - if (iCount <= 0) - { - this.bDropPageAfterDelete = true; - } - - _.delay(function () { - - _.each(aContacts, function (oContact) { - oKoContacts.remove(oContact); - }); - - }, 500); - } -}; - -PopupsContactsViewModel.prototype.deleteSelectedContacts = function () -{ - if (0 < this.contactsCheckedOrSelected().length) - { - RL.remote().contactsDelete( - _.bind(this.deleteResponse, this), - this.contactsCheckedOrSelectedUids() - ); - - this.removeCheckedOrSelectedContactsFromList(); - } -}; - -/** - * @param {string} sResult - * @param {AjaxJsonDefaultResponse} oData - */ -PopupsContactsViewModel.prototype.deleteResponse = function (sResult, oData) -{ - if (500 < (Enums.StorageResultType.Success === sResult && oData && oData.Time ? Utils.pInt(oData.Time) : 0)) - { - this.reloadContactList(this.bDropPageAfterDelete); - } - else - { - _.delay((function (self) { - return function () { - self.reloadContactList(self.bDropPageAfterDelete); - }; - }(this)), 500); - } -}; - -PopupsContactsViewModel.prototype.removeProperty = function (oProp) -{ - this.viewProperties.remove(oProp); -}; - -/** - * @param {?ContactModel} oContact - */ -PopupsContactsViewModel.prototype.populateViewContact = function (oContact) -{ - var - sId = '', - sLastName = '', - sFirstName = '', - aList = [] - ; - - this.watchHash(false); - - this.emptySelection(false); - this.viewReadOnly(false); - - if (oContact) - { - sId = oContact.idContact; - if (Utils.isNonEmptyArray(oContact.properties)) - { - _.each(oContact.properties, function (aProperty) { - if (aProperty && aProperty[0]) - { - if (Enums.ContactPropertyType.LastName === aProperty[0]) - { - sLastName = aProperty[1]; - } - else if (Enums.ContactPropertyType.FirstName === aProperty[0]) - { - sFirstName = aProperty[1]; - } - else - { - aList.push(new ContactPropertyModel(aProperty[0], aProperty[2] || '', aProperty[1])); - } - } - }); - } - - this.viewReadOnly(!!oContact.readOnly); - } - - aList.unshift(new ContactPropertyModel(Enums.ContactPropertyType.LastName, '', sLastName, false, - this.getPropertyPlceholder(Enums.ContactPropertyType.LastName))); - - aList.unshift(new ContactPropertyModel(Enums.ContactPropertyType.FirstName, '', sFirstName, !oContact, - this.getPropertyPlceholder(Enums.ContactPropertyType.FirstName))); - - this.viewID(sId); - this.viewProperties([]); - this.viewProperties(aList); - - this.watchDirty(false); - this.watchHash(true); -}; - -/** - * @param {boolean=} bDropPagePosition = false - */ -PopupsContactsViewModel.prototype.reloadContactList = function (bDropPagePosition) -{ - var - self = this, - iOffset = (this.contactsPage() - 1) * Consts.Defaults.ContactsPerPage - ; - - this.bDropPageAfterDelete = false; - - if (Utils.isUnd(bDropPagePosition) ? false : !!bDropPagePosition) - { - this.contactsPage(1); - iOffset = 0; - } - - this.contacts.loading(true); - RL.remote().contacts(function (sResult, oData) { - var - iCount = 0, - aList = [] - ; - - if (Enums.StorageResultType.Success === sResult && oData && oData.Result && oData.Result.List) - { - if (Utils.isNonEmptyArray(oData.Result.List)) - { - aList = _.map(oData.Result.List, function (oItem) { - var oContact = new ContactModel(); - return oContact.parse(oItem) ? oContact : null; - }); - - aList = _.compact(aList); - - iCount = Utils.pInt(oData.Result.Count); - iCount = 0 < iCount ? iCount : 0; - } - } - - self.contactsCount(iCount); - - self.contacts(aList); - self.viewClearSearch('' !== self.search()); - self.contacts.loading(false); - - }, iOffset, Consts.Defaults.ContactsPerPage, this.search()); -}; - -PopupsContactsViewModel.prototype.onBuild = function (oDom) -{ - this.oContentVisible = $('.b-list-content', oDom); - this.oContentScrollable = $('.content', this.oContentVisible); - - this.selector.init(this.oContentVisible, this.oContentScrollable, Enums.KeyState.ContactList); - - var self = this; - - key('delete', Enums.KeyState.ContactList, function () { - self.deleteCommand(); - return false; - }); - - oDom - .on('click', '.e-pagenator .e-page', function () { - var oPage = ko.dataFor(this); - if (oPage) - { - self.contactsPage(Utils.pInt(oPage.value)); - self.reloadContactList(); - } - }) - ; - - this.initUploader(); -}; - -PopupsContactsViewModel.prototype.onShow = function () -{ - kn.routeOff(); - this.reloadContactList(true); -}; - -PopupsContactsViewModel.prototype.onHide = function () -{ - kn.routeOn(); - this.currentContact(null); - this.emptySelection(true); - this.search(''); - - _.each(this.contacts(), function (oItem) { - oItem.checked(false); - }); -}; - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsAdvancedSearchViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsAdvancedSearch'); - - this.fromFocus = ko.observable(false); - - this.from = ko.observable(''); - this.to = ko.observable(''); - this.subject = ko.observable(''); - this.text = ko.observable(''); - this.selectedDateValue = ko.observable(-1); - - this.hasAttachment = ko.observable(false); - this.starred = ko.observable(false); - this.unseen = ko.observable(false); - - this.searchCommand = Utils.createCommand(this, function () { - - var sSearch = this.buildSearchString(); - if ('' !== sSearch) - { - RL.data().mainMessageListSearch(sSearch); - } - - this.cancelCommand(); - }); - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsAdvancedSearchViewModel', PopupsAdvancedSearchViewModel); - -PopupsAdvancedSearchViewModel.prototype.buildSearchStringValue = function (sValue) -{ - if (-1 < sValue.indexOf(' ')) - { - sValue = '"' + sValue + '"'; - } - - return sValue; -}; - -PopupsAdvancedSearchViewModel.prototype.buildSearchString = function () -{ - var - aResult = [], - sFrom = Utils.trim(this.from()), - sTo = Utils.trim(this.to()), - sSubject = Utils.trim(this.subject()), - sText = Utils.trim(this.text()), - aIs = [], - aHas = [] - ; - - if (sFrom && '' !== sFrom) - { - aResult.push('from:' + this.buildSearchStringValue(sFrom)); - } - - if (sTo && '' !== sTo) - { - aResult.push('to:' + this.buildSearchStringValue(sTo)); - } - - if (sSubject && '' !== sSubject) - { - aResult.push('subject:' + this.buildSearchStringValue(sSubject)); - } - - if (this.hasAttachment()) - { - aHas.push('attachment'); - } - - if (this.unseen()) - { - aIs.push('unseen'); - } - - if (this.starred()) - { - aIs.push('flagged'); - } - - if (0 < aHas.length) - { - aResult.push('has:' + aHas.join(',')); - } - - if (0 < aIs.length) - { - aResult.push('is:' + aIs.join(',')); - } - - if (-1 < this.selectedDateValue()) - { - aResult.push('date:' + moment().subtract('days', this.selectedDateValue()).format('YYYY.MM.DD') + '/'); - } - - if (sText && '' !== sText) - { - aResult.push('text:' + this.buildSearchStringValue(sText)); - } - - return Utils.trim(aResult.join(' ')); -}; - -PopupsAdvancedSearchViewModel.prototype.clearPopup = function () -{ - this.from(''); - this.to(''); - this.subject(''); - this.text(''); - - this.selectedDateValue(-1); - this.hasAttachment(false); - this.starred(false); - this.unseen(false); - - this.fromFocus(true); -}; - -PopupsAdvancedSearchViewModel.prototype.onShow = function () -{ - this.clearPopup(); -}; - -PopupsAdvancedSearchViewModel.prototype.onFocus = function () -{ - this.fromFocus(true); -}; - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsAddAccountViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsAddAccount'); - - this.email = ko.observable(''); - this.login = ko.observable(''); - this.password = ko.observable(''); - - this.emailError = ko.observable(false); - this.loginError = ko.observable(false); - this.passwordError = ko.observable(false); - - this.email.subscribe(function () { - this.emailError(false); - }, this); - - this.login.subscribe(function () { - this.loginError(false); - }, this); - - this.password.subscribe(function () { - this.passwordError(false); - }, this); - - this.allowCustomLogin = RL.data().allowCustomLogin; - - this.submitRequest = ko.observable(false); - this.submitError = ko.observable(''); - - this.emailFocus = ko.observable(false); - this.loginFocus = ko.observable(false); - - this.addAccountCommand = Utils.createCommand(this, function () { - - this.emailError('' === Utils.trim(this.email())); - this.passwordError('' === Utils.trim(this.password())); - - if (this.emailError() || this.passwordError()) - { - return false; - } - - this.submitRequest(true); - - RL.remote().accountAdd(_.bind(function (sResult, oData) { - - this.submitRequest(false); - if (Enums.StorageResultType.Success === sResult && oData && 'AccountAdd' === oData.Action) - { - if (oData.Result) - { - RL.accountsAndIdentities(); - this.cancelCommand(); - } - else if (oData.ErrorCode) - { - this.submitError(Utils.getNotification(oData.ErrorCode)); - } - } - else - { - this.submitError(Utils.getNotification(Enums.Notification.UnknownError)); - } - - }, this), this.email(), this.allowCustomLogin() ? this.login() : '', this.password()); - - return true; - - }, function () { - return !this.submitRequest(); - }); - - this.loginFocus.subscribe(function (bValue) { - if (bValue && '' === this.login() && '' !== this.email()) - { - this.login(this.email()); - } - }, this); - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsAddAccountViewModel', PopupsAddAccountViewModel); - -PopupsAddAccountViewModel.prototype.clearPopup = function () -{ - this.email(''); - this.login(''); - this.password(''); - - this.emailError(false); - this.loginError(false); - this.passwordError(false); - - this.submitRequest(false); - this.submitError(''); -}; - -PopupsAddAccountViewModel.prototype.onShow = function () -{ - this.clearPopup(); -}; - -PopupsAddAccountViewModel.prototype.onFocus = function () -{ - this.emailFocus(true); -}; - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsAddOpenPgpKeyViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsAddOpenPgpKey'); - - this.key = ko.observable(''); - this.key.error = ko.observable(false); - this.key.focus = ko.observable(false); - - this.key.subscribe(function () { - this.key.error(false); - }, this); - - this.addOpenPgpKeyCommand = Utils.createCommand(this, function () { - - var - iCount = 30, - aMatch = null, - sKey = Utils.trim(this.key()), - oReg = /[\-]{3,6}BEGIN PGP (PRIVATE|PUBLIC) KEY BLOCK[\-]{3,6}[\s\S]+[\-]{3,6}END PGP (PRIVATE|PUBLIC) KEY BLOCK[\-]{3,6}/gi, - oOpenpgpKeyring = RL.data().openpgpKeyring - ; - - this.key.error('' === sKey); - - if (!oOpenpgpKeyring || this.key.error()) - { - return false; - } - - do - { - aMatch = oReg.exec(sKey); - if (!aMatch || 0 > iCount) - { - break; - } - - if (aMatch[0] && aMatch[1] && aMatch[2] && aMatch[1] === aMatch[2]) - { - if ('PRIVATE' === aMatch[1]) - { - oOpenpgpKeyring.privateKeys.importKey(aMatch[0]); - } - else if ('PUBLIC' === aMatch[1]) - { - oOpenpgpKeyring.publicKeys.importKey(aMatch[0]); - } - } - - iCount--; - } - while (true); - - oOpenpgpKeyring.store(); - - RL.reloadOpenPgpKeys(); - Utils.delegateRun(this, 'cancelCommand'); - - return true; - }); - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsAddOpenPgpKeyViewModel', PopupsAddOpenPgpKeyViewModel); - -PopupsAddOpenPgpKeyViewModel.prototype.clearPopup = function () -{ - this.key(''); - this.key.error(false); -}; - -PopupsAddOpenPgpKeyViewModel.prototype.onShow = function () -{ - this.clearPopup(); -}; - -PopupsAddOpenPgpKeyViewModel.prototype.onFocus = function () -{ - this.key.focus(true); -}; - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsViewOpenPgpKeyViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsViewOpenPgpKey'); - - this.key = ko.observable(''); - this.keyDom = ko.observable(null); - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsViewOpenPgpKeyViewModel', PopupsViewOpenPgpKeyViewModel); - -PopupsViewOpenPgpKeyViewModel.prototype.clearPopup = function () -{ - this.key(''); -}; - -PopupsViewOpenPgpKeyViewModel.prototype.selectKey = function () -{ - var oEl = this.keyDom(); - if (oEl) - { - Utils.selectElement(oEl); - } -}; - -PopupsViewOpenPgpKeyViewModel.prototype.onShow = function (oOpenPgpKey) -{ - this.clearPopup(); - - if (oOpenPgpKey) - { - this.key(oOpenPgpKey.armor); - } -}; - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsGenerateNewOpenPgpKeyViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsGenerateNewOpenPgpKey'); - - this.email = ko.observable(''); - this.email.focus = ko.observable(''); - this.email.error = ko.observable(false); - - this.name = ko.observable(''); - this.password = ko.observable(''); - this.keyBitLength = ko.observable(2048); - - this.submitRequest = ko.observable(false); - - this.email.subscribe(function () { - this.email.error(false); - }, this); - - this.generateOpenPgpKeyCommand = Utils.createCommand(this, function () { - - var - self = this, - sUserID = '', - mKeyPair = null, - oOpenpgpKeyring = RL.data().openpgpKeyring - ; - - this.email.error('' === Utils.trim(this.email())); - if (!oOpenpgpKeyring || this.email.error()) - { - return false; - } - - sUserID = this.email(); - if ('' !== this.name()) - { - sUserID = this.name() + ' <' + sUserID + '>'; - } - - this.submitRequest(true); - - _.delay(function () { - mKeyPair = window.openpgp.generateKeyPair(1, Utils.pInt(self.keyBitLength()), sUserID, Utils.trim(self.password())); - if (mKeyPair && mKeyPair.privateKeyArmored) - { - oOpenpgpKeyring.privateKeys.importKey(mKeyPair.privateKeyArmored); - oOpenpgpKeyring.publicKeys.importKey(mKeyPair.publicKeyArmored); - oOpenpgpKeyring.store(); - - RL.reloadOpenPgpKeys(); - Utils.delegateRun(self, 'cancelCommand'); - } - - self.submitRequest(false); - }, 100); - - return true; - }); - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsGenerateNewOpenPgpKeyViewModel', PopupsGenerateNewOpenPgpKeyViewModel); - -PopupsGenerateNewOpenPgpKeyViewModel.prototype.clearPopup = function () -{ - this.name(''); - this.password(''); - - this.email(''); - this.email.error(false); - this.keyBitLength(2048); -}; - -PopupsGenerateNewOpenPgpKeyViewModel.prototype.onShow = function () -{ - this.clearPopup(); -}; - -PopupsGenerateNewOpenPgpKeyViewModel.prototype.onFocus = function () -{ - this.email.focus(true); -}; - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsComposeOpenPgpViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsComposeOpenPgp'); - - this.notification = ko.observable(''); - - this.sign = ko.observable(true); - this.encrypt = ko.observable(true); - - this.password = ko.observable(''); - this.password.focus = ko.observable(false); - this.buttonFocus = ko.observable(false); - - this.from = ko.observable(''); - this.to = ko.observableArray([]); - this.text = ko.observable(''); - - this.resultCallback = null; - - this.submitRequest = ko.observable(false); - - // commands - this.doCommand = Utils.createCommand(this, function () { - - var - self = this, - bResult = true, - oData = RL.data(), - oPrivateKey = null, - aPublicKeys = [] - ; - - this.submitRequest(true); - - if (bResult && this.sign() && '' === this.from()) - { - this.notification(Utils.i18n('PGP_NOTIFICATIONS/SPECIFY_FROM_EMAIL')); - bResult = false; - } - - if (bResult && this.sign()) - { - oPrivateKey = oData.findPrivateKeyByEmail(this.from(), this.password()); - if (!oPrivateKey) - { - this.notification(Utils.i18n('PGP_NOTIFICATIONS/NO_PRIVATE_KEY_FOUND_FOR', { - 'EMAIL': this.from() - })); - - bResult = false; - } - } - - if (bResult && this.encrypt() && 0 === this.to().length) - { - this.notification(Utils.i18n('PGP_NOTIFICATIONS/SPECIFY_AT_LEAST_ONE_RECIPIENT')); - bResult = false; - } - - if (bResult && this.encrypt()) - { - aPublicKeys = []; - _.each(this.to(), function (sEmail) { - var aKeys = oData.findPublicKeysByEmail(sEmail); - if (0 === aKeys.length && bResult) - { - self.notification(Utils.i18n('PGP_NOTIFICATIONS/NO_PUBLIC_KEYS_FOUND_FOR', { - 'EMAIL': sEmail - })); - - bResult = false; - } - - aPublicKeys = aPublicKeys.concat(aKeys); - }); - - if (bResult && (0 === aPublicKeys.length || this.to().length !== aPublicKeys.length)) - { - bResult = false; - } - } - - _.delay(function () { - - if (self.resultCallback && bResult) - { - try { - - if (oPrivateKey && 0 === aPublicKeys.length) - { - self.resultCallback( - window.openpgp.signClearMessage([oPrivateKey], self.text()) - ); - } - else if (oPrivateKey && 0 < aPublicKeys.length) - { - self.resultCallback( - window.openpgp.signAndEncryptMessage(aPublicKeys, oPrivateKey, self.text()) - ); - } - else if (!oPrivateKey && 0 < aPublicKeys.length) - { - self.resultCallback( - window.openpgp.encryptMessage(aPublicKeys, self.text()) - ); - } - } - catch (e) - { - self.notification(Utils.i18n('PGP_NOTIFICATIONS/PGP_ERROR', { - 'ERROR': '' + e - })); - - bResult = false; - } - } - - if (bResult) - { - self.cancelCommand(); - } - - self.submitRequest(false); - - }, 10); - - }, function () { - return !this.submitRequest() && (this.sign() || this.encrypt()); - }); - - this.sDefaultKeyScope = Enums.KeyState.PopupComposeOpenPGP; - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsComposeOpenPgpViewModel', PopupsComposeOpenPgpViewModel); - -PopupsComposeOpenPgpViewModel.prototype.clearPopup = function () -{ - this.notification(''); - - this.password(''); - this.password.focus(false); - this.buttonFocus(false); - - this.from(''); - this.to([]); - this.text(''); - - this.submitRequest(false); - - this.resultCallback = null; -}; - -PopupsComposeOpenPgpViewModel.prototype.onBuild = function () -{ - key('tab,shift+tab', Enums.KeyState.PopupComposeOpenPGP, _.bind(function () { - - switch (true) - { - case this.password.focus(): - this.buttonFocus(true); - break; - case this.buttonFocus(): - this.password.focus(true); - break; - } - - return false; - - }, this)); -}; - -PopupsComposeOpenPgpViewModel.prototype.onHide = function () -{ - this.clearPopup(); -}; - -PopupsComposeOpenPgpViewModel.prototype.onFocus = function () -{ - if (this.sign()) - { - this.password.focus(true); - } - else - { - this.buttonFocus(true); - } -}; - -PopupsComposeOpenPgpViewModel.prototype.onShow = function (fCallback, sText, sFromEmail, sTo, sCc, sBcc) -{ - this.clearPopup(); - - var - oEmail = new EmailModel(), - sResultFromEmail = '', - aRec = [] - ; - - this.resultCallback = fCallback; - - oEmail.clear(); - oEmail.mailsoParse(sFromEmail); - if ('' !== oEmail.email) - { - sResultFromEmail = oEmail.email; - } - - if ('' !== sTo) - { - aRec.push(sTo); - } - - if ('' !== sCc) - { - aRec.push(sCc); - } - - if ('' !== sBcc) - { - aRec.push(sBcc); - } - - aRec = aRec.join(', ').split(','); - aRec = _.compact(_.map(aRec, function (sValue) { - oEmail.clear(); - oEmail.mailsoParse(Utils.trim(sValue)); - return '' === oEmail.email ? false : oEmail.email; - })); - - this.from(sResultFromEmail); - this.to(aRec); - this.text(sText); -}; - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsIdentityViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsIdentity'); - - this.id = ''; - this.edit = ko.observable(false); - this.owner = ko.observable(false); - - this.email = ko.observable('').validateEmail(); - this.email.focused = ko.observable(false); - this.name = ko.observable(''); - this.name.focused = ko.observable(false); - this.replyTo = ko.observable('').validateSimpleEmail(); - this.replyTo.focused = ko.observable(false); - this.bcc = ko.observable('').validateSimpleEmail(); - this.bcc.focused = ko.observable(false); - -// this.email.subscribe(function () { -// this.email.hasError(false); -// }, this); - - this.submitRequest = ko.observable(false); - this.submitError = ko.observable(''); - - this.addOrEditIdentityCommand = Utils.createCommand(this, function () { - - if (!this.email.hasError()) - { - this.email.hasError('' === Utils.trim(this.email())); - } - - if (this.email.hasError()) - { - if (!this.owner()) - { - this.email.focused(true); - } - - return false; - } - - if (this.replyTo.hasError()) - { - this.replyTo.focused(true); - return false; - } - - if (this.bcc.hasError()) - { - this.bcc.focused(true); - return false; - } - - this.submitRequest(true); - - RL.remote().identityUpdate(_.bind(function (sResult, oData) { - - this.submitRequest(false); - if (Enums.StorageResultType.Success === sResult && oData) - { - if (oData.Result) - { - RL.accountsAndIdentities(); - this.cancelCommand(); - } - else if (oData.ErrorCode) - { - this.submitError(Utils.getNotification(oData.ErrorCode)); - } - } - else - { - this.submitError(Utils.getNotification(Enums.Notification.UnknownError)); - } - - }, this), this.id, this.email(), this.name(), this.replyTo(), this.bcc()); - - return true; - - }, function () { - return !this.submitRequest(); - }); - - this.label = ko.computed(function () { - return Utils.i18n('POPUPS_IDENTITIES/' + (this.edit() ? 'TITLE_UPDATE_IDENTITY': 'TITLE_ADD_IDENTITY')); - }, this); - - this.button = ko.computed(function () { - return Utils.i18n('POPUPS_IDENTITIES/' + (this.edit() ? 'BUTTON_UPDATE_IDENTITY': 'BUTTON_ADD_IDENTITY')); - }, this); - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsIdentityViewModel', PopupsIdentityViewModel); - -PopupsIdentityViewModel.prototype.clearPopup = function () -{ - this.id = ''; - this.edit(false); - this.owner(false); - - this.name(''); - this.email(''); - this.replyTo(''); - this.bcc(''); - - this.email.hasError(false); - this.replyTo.hasError(false); - this.bcc.hasError(false); - - this.submitRequest(false); - this.submitError(''); -}; - -/** - * @param {?IdentityModel} oIdentity - */ -PopupsIdentityViewModel.prototype.onShow = function (oIdentity) -{ - this.clearPopup(); - - if (oIdentity) - { - this.edit(true); - - this.id = oIdentity.id; - this.name(oIdentity.name()); - this.email(oIdentity.email()); - this.replyTo(oIdentity.replyTo()); - this.bcc(oIdentity.bcc()); - - this.owner(this.id === RL.data().accountEmail()); - } -}; - -PopupsIdentityViewModel.prototype.onFocus = function () -{ - if (!this.owner()) - { - this.email.focused(true); - } -}; - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsLanguagesViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsLanguages'); - - this.exp = ko.observable(false); - - this.languages = ko.computed(function () { - return _.map(RL.data().languages(), function (sLanguage) { - return { - 'key': sLanguage, - 'selected': ko.observable(false), - 'fullName': Utils.convertLangName(sLanguage) - }; - }); - }); - - RL.data().mainLanguage.subscribe(function () { - this.resetMainLanguage(); - }, this); - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsLanguagesViewModel', PopupsLanguagesViewModel); - -PopupsLanguagesViewModel.prototype.languageEnName = function (sLanguage) -{ - return Utils.convertLangName(sLanguage, true); -}; - -PopupsLanguagesViewModel.prototype.resetMainLanguage = function () -{ - var sCurrent = RL.data().mainLanguage(); - _.each(this.languages(), function (oItem) { - oItem['selected'](oItem['key'] === sCurrent); - }); -}; - -PopupsLanguagesViewModel.prototype.onShow = function () -{ - this.exp(true); - - this.resetMainLanguage(); -}; - -PopupsLanguagesViewModel.prototype.onHide = function () -{ - this.exp(false); -}; - -PopupsLanguagesViewModel.prototype.changeLanguage = function (sLang) -{ - RL.data().mainLanguage(sLang); - this.cancelCommand(); -}; - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsTwoFactorTestViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsTwoFactorTest'); - - var self = this; - - this.code = ko.observable(''); - this.code.focused = ko.observable(false); - this.code.status = ko.observable(null); - - this.testing = ko.observable(false); - - // commands - this.testCode = Utils.createCommand(this, function () { - - this.testing(true); - RL.remote().testTwoFactor(function (sResult, oData) { - - self.testing(false); - self.code.status(Enums.StorageResultType.Success === sResult && oData && oData.Result ? true : false); - - }, this.code()); - - }, function () { - return '' !== this.code() && !this.testing(); - }); - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsTwoFactorTestViewModel', PopupsTwoFactorTestViewModel); - -PopupsTwoFactorTestViewModel.prototype.clearPopup = function () -{ - this.code(''); - this.code.focused(false); - this.code.status(null); - this.testing(false); -}; - -PopupsTwoFactorTestViewModel.prototype.onShow = function () -{ - this.clearPopup(); -}; - -PopupsTwoFactorTestViewModel.prototype.onFocus = function () -{ - this.code.focused(true); -}; - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsAskViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsAsk'); - - this.askDesc = ko.observable(''); - this.yesButton = ko.observable(''); - this.noButton = ko.observable(''); - - this.yesFocus = ko.observable(false); - this.noFocus = ko.observable(false); - - this.fYesAction = null; - this.fNoAction = null; - - this.bDisabeCloseOnEsc = true; - this.sDefaultKeyScope = Enums.KeyState.PopupAsk; - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsAskViewModel', PopupsAskViewModel); - -PopupsAskViewModel.prototype.clearPopup = function () -{ - this.askDesc(''); - this.yesButton(Utils.i18n('POPUPS_ASK/BUTTON_YES')); - this.noButton(Utils.i18n('POPUPS_ASK/BUTTON_NO')); - - this.yesFocus(false); - this.noFocus(false); - - this.fYesAction = null; - this.fNoAction = null; -}; - -PopupsAskViewModel.prototype.yesClick = function () -{ - this.cancelCommand(); - - if (Utils.isFunc(this.fYesAction)) - { - this.fYesAction.call(null); - } -}; - -PopupsAskViewModel.prototype.noClick = function () -{ - this.cancelCommand(); - - if (Utils.isFunc(this.fNoAction)) - { - this.fNoAction.call(null); - } -}; - -/** - * @param {string} sAskDesc - * @param {Function=} fYesFunc - * @param {Function=} fNoFunc - * @param {string=} sYesButton - * @param {string=} sNoButton - */ -PopupsAskViewModel.prototype.onShow = function (sAskDesc, fYesFunc, fNoFunc, sYesButton, sNoButton) -{ - this.clearPopup(); - - this.fYesAction = fYesFunc || null; - this.fNoAction = fNoFunc || null; - - this.askDesc(sAskDesc || ''); - if (sYesButton) - { - this.yesButton(sYesButton); - } - - if (sYesButton) - { - this.yesButton(sNoButton); - } -}; - -PopupsAskViewModel.prototype.onFocus = function () -{ - this.yesFocus(true); -}; - -PopupsAskViewModel.prototype.onBuild = function () -{ - key('tab, shift+tab, right, left', Enums.KeyState.PopupAsk, _.bind(function () { - if (this.yesFocus()) - { - this.noFocus(true); - } - else - { - this.yesFocus(true); - } - return false; - }, this)); -}; - - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function PopupsKeyboardShortcutsHelpViewModel() -{ - KnoinAbstractViewModel.call(this, 'Popups', 'PopupsKeyboardShortcutsHelp'); - - this.sDefaultKeyScope = Enums.KeyState.PopupKeyboardShortcutsHelp; - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('PopupsKeyboardShortcutsHelpViewModel', PopupsKeyboardShortcutsHelpViewModel); - -PopupsKeyboardShortcutsHelpViewModel.prototype.onBuild = function (oDom) -{ - key('tab, shift+tab, left, right', Enums.KeyState.PopupKeyboardShortcutsHelp, _.bind(function (event, handler) { - if (event && handler) - { - var - $tabs = oDom.find('.nav.nav-tabs > li'), - bNext = handler && ('tab' === handler.shortcut || 'right' === handler.shortcut), - iIndex = $tabs.index($tabs.filter('.active')) - ; - - if (!bNext && iIndex > 0) - { - iIndex--; - } - else if (bNext && iIndex < $tabs.length - 1) - { - iIndex++; - } - else - { - iIndex = bNext ? 0 : $tabs.length - 1; - } - - $tabs.eq(iIndex).find('a[data-toggle="tab"]').tab('show'); - return false; - } - }, this)); -}; - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function LoginViewModel() -{ - KnoinAbstractViewModel.call(this, 'Center', 'Login'); - - var oData = RL.data(); - - this.email = ko.observable(''); - this.login = ko.observable(''); - this.password = ko.observable(''); - this.signMe = ko.observable(false); - - this.additionalCode = ko.observable(''); - this.additionalCode.error = ko.observable(false); - this.additionalCode.focused = ko.observable(false); - this.additionalCode.visibility = ko.observable(false); - this.additionalCodeSignMe = ko.observable(false); - - this.logoImg = Utils.trim(RL.settingsGet('LoginLogo')); - this.loginDescription = Utils.trim(RL.settingsGet('LoginDescription')); - this.logoCss = Utils.trim(RL.settingsGet('LoginCss')); - - this.emailError = ko.observable(false); - this.loginError = ko.observable(false); - this.passwordError = ko.observable(false); - - this.emailFocus = ko.observable(false); - this.loginFocus = ko.observable(false); - this.submitFocus = ko.observable(false); - - this.email.subscribe(function () { - this.emailError(false); - this.additionalCode(''); - this.additionalCode.visibility(false); - }, this); - - this.login.subscribe(function () { - this.loginError(false); - }, this); - - this.password.subscribe(function () { - this.passwordError(false); - }, this); - - this.additionalCode.subscribe(function () { - this.additionalCode.error(false); - }, this); - - this.additionalCode.visibility.subscribe(function () { - this.additionalCode.error(false); - }, this); - - this.submitRequest = ko.observable(false); - this.submitError = ko.observable(''); - - this.allowCustomLogin = oData.allowCustomLogin; - this.allowLanguagesOnLogin = oData.allowLanguagesOnLogin; - - this.langRequest = ko.observable(false); - this.mainLanguage = oData.mainLanguage; - this.bSendLanguage = false; - - this.mainLanguageFullName = ko.computed(function () { - return Utils.convertLangName(this.mainLanguage()); - }, this); - - this.signMeType = ko.observable(Enums.LoginSignMeType.Unused); - - this.signMeType.subscribe(function (iValue) { - this.signMe(Enums.LoginSignMeType.DefaultOn === iValue); - }, this); - - this.signMeVisibility = ko.computed(function () { - return Enums.LoginSignMeType.Unused !== this.signMeType(); - }, this); - - this.submitCommand = Utils.createCommand(this, function () { - - this.emailError('' === Utils.trim(this.email())); - this.passwordError('' === Utils.trim(this.password())); - - if (this.additionalCode.visibility()) - { - this.additionalCode.error('' === Utils.trim(this.additionalCode())); - } - - if (this.emailError() || this.passwordError() || this.additionalCode.error()) - { - return false; - } - - this.submitRequest(true); - - RL.remote().login(_.bind(function (sResult, oData) { - - if (Enums.StorageResultType.Success === sResult && oData && 'Login' === oData.Action) - { - if (oData.Result) - { - if (oData.TwoFactorAuth) - { - this.additionalCode(''); - this.additionalCode.visibility(true); - this.additionalCode.focused(true); - - this.submitRequest(false); - } - else - { - RL.loginAndLogoutReload(); - } - } - else if (oData.ErrorCode) - { - this.submitRequest(false); - this.submitError(Utils.getNotification(oData.ErrorCode)); - - if ('' === this.submitError()) - { - this.submitError(Utils.getNotification(Enums.Notification.UnknownError)); - } - } - else - { - this.submitRequest(false); - } - } - else - { - this.submitRequest(false); - this.submitError(Utils.getNotification(Enums.Notification.UnknownError)); - } - - }, this), this.email(), this.allowCustomLogin() ? this.login() : '', this.password(), !!this.signMe(), - this.bSendLanguage ? this.mainLanguage() : '', - this.additionalCode.visibility() ? this.additionalCode() : '', - this.additionalCode.visibility() ? !!this.additionalCodeSignMe() : false - ); - - return true; - - }, function () { - return !this.submitRequest(); - }); - - this.facebookLoginEnabled = ko.observable(false); - - this.facebookCommand = Utils.createCommand(this, function () { - - window.open(RL.link().socialFacebook(), 'Facebook', 'left=200,top=100,width=650,height=335,menubar=no,status=no,resizable=yes,scrollbars=yes'); - return true; - - }, function () { - return !this.submitRequest() && this.facebookLoginEnabled(); - }); - - this.googleLoginEnabled = ko.observable(false); - - this.googleCommand = Utils.createCommand(this, function () { - - window.open(RL.link().socialGoogle(), 'Google', 'left=200,top=100,width=650,height=335,menubar=no,status=no,resizable=yes,scrollbars=yes'); - return true; - - }, function () { - return !this.submitRequest() && this.googleLoginEnabled(); - }); - - this.twitterLoginEnabled = ko.observable(false); - - this.twitterCommand = Utils.createCommand(this, function () { - - window.open(RL.link().socialTwitter(), 'Twitter', 'left=200,top=100,width=650,height=335,menubar=no,status=no,resizable=yes,scrollbars=yes'); - return true; - - }, function () { - return !this.submitRequest() && this.twitterLoginEnabled(); - }); - - this.loginFocus.subscribe(function (bValue) { - if (bValue && '' === this.login() && '' !== this.email()) - { - this.login(this.email()); - } - }, this); - - this.socialLoginEnabled = ko.computed(function () { - - var - bF = this.facebookLoginEnabled(), - bG = this.googleLoginEnabled(), - bT = this.twitterLoginEnabled() - ; - - return bF || bG || bT; - }, this); - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('LoginViewModel', LoginViewModel); - -LoginViewModel.prototype.onShow = function () -{ - kn.routeOff(); - - _.delay(_.bind(function () { - if ('' !== this.email() && '' !== this.password()) - { - this.submitFocus(true); - } - else - { - this.emailFocus(true); - } - - if (RL.settingsGet('UserLanguage')) - { - $.cookie('rllang', RL.data().language(), {'expires': 30}); - } - - }, this), 100); -}; - -LoginViewModel.prototype.onHide = function () -{ - this.submitFocus(false); - this.emailFocus(false); -}; - -LoginViewModel.prototype.onBuild = function () -{ - var - self = this, - sJsHash = RL.settingsGet('JsHash'), - fSocial = function (iErrorCode) { - iErrorCode = Utils.pInt(iErrorCode); - if (0 === iErrorCode) - { - self.submitRequest(true); - RL.loginAndLogoutReload(); - } - else - { - self.submitError(Utils.getNotification(iErrorCode)); - } - } - ; - - this.facebookLoginEnabled(!!RL.settingsGet('AllowFacebookSocial')); - this.twitterLoginEnabled(!!RL.settingsGet('AllowTwitterSocial')); - this.googleLoginEnabled(!!RL.settingsGet('AllowGoogleSocial')); - - switch ((RL.settingsGet('SignMe') || 'unused').toLowerCase()) - { - case Enums.LoginSignMeTypeAsString.DefaultOff: - this.signMeType(Enums.LoginSignMeType.DefaultOff); - break; - case Enums.LoginSignMeTypeAsString.DefaultOn: - this.signMeType(Enums.LoginSignMeType.DefaultOn); - break; - default: - case Enums.LoginSignMeTypeAsString.Unused: - this.signMeType(Enums.LoginSignMeType.Unused); - break; - } - - this.email(RL.data().devEmail); - this.login(RL.data().devLogin); - this.password(RL.data().devPassword); - - if (this.googleLoginEnabled()) - { - window['rl_' + sJsHash + '_google_login_service'] = fSocial; - } - - if (this.facebookLoginEnabled()) - { - window['rl_' + sJsHash + '_facebook_login_service'] = fSocial; - } - - if (this.twitterLoginEnabled()) - { - window['rl_' + sJsHash + '_twitter_login_service'] = fSocial; - } - - _.delay(function () { - RL.data().language.subscribe(function (sValue) { - self.langRequest(true); - $.ajax({ - 'url': RL.link().langLink(sValue), - 'dataType': 'script', - 'cache': true - }).done(function() { - self.bSendLanguage = true; - Utils.i18nToDoc(); - $.cookie('rllang', RL.data().language(), {'expires': 30}); - }).always(function() { - self.langRequest(false); - }); - }); - }, 50); -}; - -LoginViewModel.prototype.selectLanguage = function () -{ - kn.showScreenPopup(PopupsLanguagesViewModel); -}; - - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function AbstractSystemDropDownViewModel() -{ - KnoinAbstractViewModel.call(this, 'Right', 'SystemDropDown'); - - var oData = RL.data(); - - this.accounts = oData.accounts; - this.accountEmail = oData.accountEmail; - this.accountsLoading = oData.accountsLoading; - - this.accountMenuDropdownTrigger = ko.observable(false); - - this.allowAddAccount = RL.settingsGet('AllowAdditionalAccounts'); - - this.loading = ko.computed(function () { - return this.accountsLoading(); - }, this); - - this.accountClick = _.bind(this.accountClick, this); -} - -_.extend(AbstractSystemDropDownViewModel.prototype, KnoinAbstractViewModel.prototype); - -AbstractSystemDropDownViewModel.prototype.accountClick = function (oAccount, oEvent) -{ - if (oAccount && oEvent && !Utils.isUnd(oEvent.which) && 1 === oEvent.which) - { - var self = this; - this.accountsLoading(true); - _.delay(function () { - self.accountsLoading(false); - }, 1000); - } - - return true; -}; - -AbstractSystemDropDownViewModel.prototype.emailTitle = function () -{ - return RL.data().accountEmail(); -}; - -AbstractSystemDropDownViewModel.prototype.settingsClick = function () -{ - kn.setHash(RL.link().settings()); -}; - -AbstractSystemDropDownViewModel.prototype.settingsHelp = function () -{ - kn.showScreenPopup(PopupsKeyboardShortcutsHelpViewModel); -}; - -AbstractSystemDropDownViewModel.prototype.addAccountClick = function () -{ - if (this.allowAddAccount) - { - kn.showScreenPopup(PopupsAddAccountViewModel); - } -}; - -AbstractSystemDropDownViewModel.prototype.logoutClick = function () -{ - RL.remote().logout(function () { - if (window.__rlah_clear) - { - window.__rlah_clear(); - } - - RL.loginAndLogoutReload(true, RL.settingsGet('ParentEmail') && 0 < RL.settingsGet('ParentEmail').length); - }); -}; - -AbstractSystemDropDownViewModel.prototype.onBuild = function () -{ - var self = this; - key('`', [Enums.KeyState.MessageList, Enums.KeyState.MessageView, Enums.KeyState.Settings], function () { - if (self.viewModelVisibility()) - { - self.accountMenuDropdownTrigger(true); - } - }); - - // shortcuts help - key('shift+/', [Enums.KeyState.MessageList, Enums.KeyState.MessageView, Enums.KeyState.Settings], function () { - if (self.viewModelVisibility()) - { - kn.showScreenPopup(PopupsKeyboardShortcutsHelpViewModel); - return false; - } - }); -}; - -/** - * @constructor - * @extends AbstractSystemDropDownViewModel - */ -function MailBoxSystemDropDownViewModel() -{ - AbstractSystemDropDownViewModel.call(this); - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('MailBoxSystemDropDownViewModel', MailBoxSystemDropDownViewModel, AbstractSystemDropDownViewModel); - -/** - * @constructor - * @extends AbstractSystemDropDownViewModel - */ -function SettingsSystemDropDownViewModel() -{ - AbstractSystemDropDownViewModel.call(this); - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('SettingsSystemDropDownViewModel', SettingsSystemDropDownViewModel, AbstractSystemDropDownViewModel); - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function MailBoxFolderListViewModel() -{ - KnoinAbstractViewModel.call(this, 'Left', 'MailFolderList'); - - var oData = RL.data(); - - this.messageList = oData.messageList; - this.folderList = oData.folderList; - this.folderListSystem = oData.folderListSystem; - this.foldersChanging = oData.foldersChanging; - - this.leftPanelDisabled = oData.leftPanelDisabled; - - this.iDropOverTimer = 0; - - this.allowContacts = !!RL.settingsGet('ContactsIsAllowed'); - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('MailBoxFolderListViewModel', MailBoxFolderListViewModel); - -MailBoxFolderListViewModel.prototype.onBuild = function (oDom) -{ - var self = this; - - oDom - .on('click', '.b-folders .e-item .e-link .e-collapsed-sign', function (oEvent) { - - var - oFolder = ko.dataFor(this), - bCollapsed = false - ; - - if (oFolder && oEvent) - { - bCollapsed = oFolder.collapsed(); - Utils.setExpandedFolder(oFolder.fullNameHash, bCollapsed); - - oFolder.collapsed(!bCollapsed); - oEvent.preventDefault(); - oEvent.stopPropagation(); - } - }) - .on('click', '.b-folders .e-item .e-link.selectable', function (oEvent) { - - oEvent.preventDefault(); - - var - oData = RL.data(), - oFolder = ko.dataFor(this) - ; - - if (oFolder) - { - if (Enums.Layout.NoPreview === oData.layout()) - { - oData.message(null); - } - - if (oFolder.fullNameRaw === oData.currentFolderFullNameRaw()) - { - RL.cache().setFolderHash(oFolder.fullNameRaw, ''); - } - - kn.setHash(RL.link().mailBox(oFolder.fullNameHash)); - } - }) - ; - - key('up, down', Enums.KeyState.FolderList, function (event, handler) { - - var - iIndex = -1, - iKeyCode = handler && 'up' === handler.shortcut ? 38 : 40, - $items = $('.b-folders .e-item .e-link:not(.hidden):visible', oDom) - ; - - if (event && $items.length) - { - iIndex = $items.index($items.filter('.focused')); - if (-1 < iIndex) - { - $items.eq(iIndex).removeClass('focused'); - } - - if (iKeyCode === 38 && iIndex > 0) - { - iIndex--; - } - else if (iKeyCode === 40 && iIndex < $items.length - 1) - { - iIndex++; - } - - $items.eq(iIndex).addClass('focused'); - } - - return false; - }); - - key('enter', Enums.KeyState.FolderList, function () { - var $items = $('.b-folders .e-item .e-link:not(.hidden).focused', oDom); - if ($items.length && $items[0]) - { - self.folderList.focused(false); - $items.click(); - } - - return false; - }); - - key('space', Enums.KeyState.FolderList, function () { - var bCollapsed = true, oFolder = null, $items = $('.b-folders .e-item .e-link:not(.hidden).focused', oDom); - if ($items.length && $items[0]) - { - oFolder = ko.dataFor($items[0]); - if (oFolder) - { - bCollapsed = oFolder.collapsed(); - Utils.setExpandedFolder(oFolder.fullNameHash, bCollapsed); - oFolder.collapsed(!bCollapsed); - } - } - - return false; - }); - - key('esc, tab, shift+tab, right', Enums.KeyState.FolderList, function () { - self.folderList.focused(false); - return false; - }); - - self.folderList.focused.subscribe(function (bValue) { - $('.b-folders .e-item .e-link.focused', oDom).removeClass('focused'); - if (bValue) - { - $('.b-folders .e-item .e-link.selected', oDom).addClass('focused'); - } - }); -}; - -MailBoxFolderListViewModel.prototype.messagesDropOver = function (oFolder) -{ - window.clearTimeout(this.iDropOverTimer); - if (oFolder && oFolder.collapsed()) - { - this.iDropOverTimer = window.setTimeout(function () { - oFolder.collapsed(false); - Utils.setExpandedFolder(oFolder.fullNameHash, true); - Utils.windowResize(); - }, 500); - } -}; - -MailBoxFolderListViewModel.prototype.messagesDropOut = function () -{ - window.clearTimeout(this.iDropOverTimer); -}; - -/** - * - * @param {FolderModel} oToFolder - * @param {{helper:jQuery}} oUi - */ -MailBoxFolderListViewModel.prototype.messagesDrop = function (oToFolder, oUi) -{ - if (oToFolder && oUi && oUi.helper) - { - var - sFromFolderFullNameRaw = oUi.helper.data('rl-folder'), - bCopy = $html.hasClass('rl-ctrl-key-pressed'), - aUids = oUi.helper.data('rl-uids') - ; - - if (Utils.isNormal(sFromFolderFullNameRaw) && '' !== sFromFolderFullNameRaw && Utils.isArray(aUids)) - { - RL.moveMessagesToFolder(sFromFolderFullNameRaw, aUids, oToFolder.fullNameRaw, bCopy); - } - } -}; - -MailBoxFolderListViewModel.prototype.composeClick = function () -{ - kn.showScreenPopup(PopupsComposeViewModel); -}; - -MailBoxFolderListViewModel.prototype.createFolder = function () -{ - kn.showScreenPopup(PopupsFolderCreateViewModel); -}; - -MailBoxFolderListViewModel.prototype.configureFolders = function () -{ - kn.setHash(RL.link().settings('folders')); -}; - -MailBoxFolderListViewModel.prototype.contactsClick = function () -{ - if (this.allowContacts) - { - kn.showScreenPopup(PopupsContactsViewModel); - } -}; - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function MailBoxMessageListViewModel() -{ - KnoinAbstractViewModel.call(this, 'Right', 'MailMessageList'); - - this.sLastUid = null; - this.bPrefetch = false; - this.emptySubjectValue = ''; - - var oData = RL.data(); - - this.popupVisibility = RL.popupVisibility; - - this.message = oData.message; - this.messageList = oData.messageList; - this.folderList = oData.folderList; - this.currentMessage = oData.currentMessage; - this.isMessageSelected = oData.isMessageSelected; - this.messageListSearch = oData.messageListSearch; - this.messageListError = oData.messageListError; - this.folderMenuForMove = oData.folderMenuForMove; - - this.useCheckboxesInList = oData.useCheckboxesInList; - this.leftPanelDisabled = oData.leftPanelDisabled; - - this.mainMessageListSearch = oData.mainMessageListSearch; - this.messageListEndFolder = oData.messageListEndFolder; - - this.messageListChecked = oData.messageListChecked; - this.messageListCheckedOrSelected = oData.messageListCheckedOrSelected; - this.messageListCheckedOrSelectedUidsWithSubMails = oData.messageListCheckedOrSelectedUidsWithSubMails; - this.messageListCompleteLoadingThrottle = oData.messageListCompleteLoadingThrottle; - - Utils.initOnStartOrLangChange(function () { - this.emptySubjectValue = Utils.i18n('MESSAGE_LIST/EMPTY_SUBJECT_TEXT'); - }, this); - - this.userQuota = oData.userQuota; - this.userUsageSize = oData.userUsageSize; - this.userUsageProc = oData.userUsageProc; - - this.moveDropdownTrigger = ko.observable(false); - this.moreDropdownTrigger = ko.observable(false); - - // append drag and drop - this.dragOver = ko.observable(false).extend({'throttle': 1}); - this.dragOverEnter = ko.observable(false).extend({'throttle': 1}); - this.dragOverArea = ko.observable(null); - this.dragOverBodyArea = ko.observable(null); - - this.messageListItemTemplate = ko.computed(function () { - return Enums.Layout.NoPreview !== oData.layout() ? - 'MailMessageListItem' : 'MailMessageListItemNoPreviewPane'; - }); - - this.messageListSearchDesc = ko.computed(function () { - var sValue = oData.messageListEndSearch(); - return '' === sValue ? '' : Utils.i18n('MESSAGE_LIST/SEARCH_RESULT_FOR', {'SEARCH': sValue}); - }); - - this.messageListPagenator = ko.computed(Utils.computedPagenatorHelper(oData.messageListPage, oData.messageListPageCount)); - - this.checkAll = ko.computed({ - 'read': function () { - return 0 < RL.data().messageListChecked().length; - }, - - 'write': function (bValue) { - bValue = !!bValue; - _.each(RL.data().messageList(), function (oMessage) { - oMessage.checked(bValue); - }); - } - }); - - this.inputMessageListSearchFocus = ko.observable(false); - - this.sLastSearchValue = ''; - this.inputProxyMessageListSearch = ko.computed({ - 'read': this.mainMessageListSearch, - 'write': function (sValue) { - this.sLastSearchValue = sValue; - }, - 'owner': this - }); - - this.isIncompleteChecked = ko.computed(function () { - var - iM = RL.data().messageList().length, - iC = RL.data().messageListChecked().length - ; - return 0 < iM && 0 < iC && iM > iC; - }, this); - - this.hasMessages = ko.computed(function () { - return 0 < this.messageList().length; - }, this); - - this.hasCheckedOrSelectedLines = ko.computed(function () { - return 0 < this.messageListCheckedOrSelected().length; - }, this); - - this.isSpamFolder = ko.computed(function () { - return oData.spamFolder() === this.messageListEndFolder() && - '' !== oData.spamFolder(); - }, this); - - this.isSpamDisabled = ko.computed(function () { - return Consts.Values.UnuseOptionValue === oData.spamFolder(); - }, this); - - this.isTrashFolder = ko.computed(function () { - return oData.trashFolder() === this.messageListEndFolder() && - '' !== oData.trashFolder(); - }, this); - - this.isDraftFolder = ko.computed(function () { - return oData.draftFolder() === this.messageListEndFolder() && - '' !== oData.draftFolder(); - }, this); - - this.isSentFolder = ko.computed(function () { - return oData.sentFolder() === this.messageListEndFolder() && - '' !== oData.sentFolder(); - }, this); - - this.isArchiveFolder = ko.computed(function () { - return oData.archiveFolder() === this.messageListEndFolder() && - '' !== oData.archiveFolder(); - }, this); - - this.isArchiveDisabled = ko.computed(function () { - return Consts.Values.UnuseOptionValue === RL.data().archiveFolder(); - }, this); - - this.canBeMoved = this.hasCheckedOrSelectedLines; - - this.clearCommand = Utils.createCommand(this, function () { - kn.showScreenPopup(PopupsFolderClearViewModel, [RL.data().currentFolder()]); - }); - - this.multyForwardCommand = Utils.createCommand(this, function () { - kn.showScreenPopup(PopupsComposeViewModel, [Enums.ComposeType.ForwardAsAttachment, RL.data().messageListCheckedOrSelected()]); - }, this.canBeMoved); - - this.deleteWithoutMoveCommand = Utils.createCommand(this, function () { - RL.deleteMessagesFromFolder(Enums.FolderType.Trash, - RL.data().currentFolderFullNameRaw(), - RL.data().messageListCheckedOrSelectedUidsWithSubMails(), false); - }, this.canBeMoved); - - this.deleteCommand = Utils.createCommand(this, function () { - RL.deleteMessagesFromFolder(Enums.FolderType.Trash, - RL.data().currentFolderFullNameRaw(), - RL.data().messageListCheckedOrSelectedUidsWithSubMails(), true); - }, this.canBeMoved); - - this.archiveCommand = Utils.createCommand(this, function () { - RL.deleteMessagesFromFolder(Enums.FolderType.Archive, - RL.data().currentFolderFullNameRaw(), - RL.data().messageListCheckedOrSelectedUidsWithSubMails(), true); - }, this.canBeMoved); - - this.spamCommand = Utils.createCommand(this, function () { - RL.deleteMessagesFromFolder(Enums.FolderType.Spam, - RL.data().currentFolderFullNameRaw(), - RL.data().messageListCheckedOrSelectedUidsWithSubMails(), true); - }, this.canBeMoved); - - this.notSpamCommand = Utils.createCommand(this, function () { - RL.deleteMessagesFromFolder(Enums.FolderType.NotSpam, - RL.data().currentFolderFullNameRaw(), - RL.data().messageListCheckedOrSelectedUidsWithSubMails(), true); - }, this.canBeMoved); - - this.moveCommand = Utils.createCommand(this, Utils.emptyFunction, this.canBeMoved); - - this.reloadCommand = Utils.createCommand(this, function () { - if (!RL.data().messageListCompleteLoadingThrottle()) - { - RL.reloadMessageList(false, true); - } - }); - - this.quotaTooltip = _.bind(this.quotaTooltip, this); - - this.selector = new Selector(this.messageList, this.currentMessage, - '.messageListItem .actionHandle', '.messageListItem.selected', '.messageListItem .checkboxMessage', - '.messageListItem.focused'); - - this.selector.on('onItemSelect', _.bind(function (oMessage) { - if (oMessage) - { - oData.message(oData.staticMessageList.populateByMessageListItem(oMessage)); - this.populateMessageBody(oData.message()); - - if (Enums.Layout.NoPreview === oData.layout()) - { - kn.setHash(RL.link().messagePreview(), true); - oData.message.focused(true); - } - } - else - { - oData.message(null); - } - }, this)); - - this.selector.on('onItemGetUid', function (oMessage) { - return oMessage ? oMessage.generateUid() : ''; - }); - - oData.messageListEndHash.subscribe(function () { - this.selector.scrollToTop(); - }, this); - - oData.layout.subscribe(function (mValue) { - this.selector.autoSelect(Enums.Layout.NoPreview !== mValue); - }, this); - - oData.layout.valueHasMutated(); - - RL - .sub('mailbox.message-list.selector.go-down', function () { - this.selector.goDown(true); - }, this) - .sub('mailbox.message-list.selector.go-up', function () { - this.selector.goUp(true); - }, this) - ; - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('MailBoxMessageListViewModel', MailBoxMessageListViewModel); - -/** - * @type {string} - */ -MailBoxMessageListViewModel.prototype.emptySubjectValue = ''; - -MailBoxMessageListViewModel.prototype.searchEnterAction = function () -{ - this.mainMessageListSearch(this.sLastSearchValue); - this.inputMessageListSearchFocus(false); -}; - -/** - * @returns {string} - */ -MailBoxMessageListViewModel.prototype.printableMessageCountForDeletion = function () -{ - var iCnt = this.messageListCheckedOrSelectedUidsWithSubMails().length; - return 1 < iCnt ? ' (' + (100 > iCnt ? iCnt : '99+') + ')' : ''; -}; - -MailBoxMessageListViewModel.prototype.cancelSearch = function () -{ - this.mainMessageListSearch(''); - this.inputMessageListSearchFocus(false); -}; - -/** - * @param {string} sToFolderFullNameRaw - * @return {boolean} - */ -MailBoxMessageListViewModel.prototype.moveSelectedMessagesToFolder = function (sToFolderFullNameRaw, bCopy) -{ - if (this.canBeMoved()) - { - RL.moveMessagesToFolder( - RL.data().currentFolderFullNameRaw(), - RL.data().messageListCheckedOrSelectedUidsWithSubMails(), sToFolderFullNameRaw, bCopy); - } - - return false; -}; - -MailBoxMessageListViewModel.prototype.dragAndDronHelper = function (oMessageListItem) -{ - if (oMessageListItem) - { - oMessageListItem.checked(true); - } - - var - oEl = Utils.draggeblePlace(), - aUids = RL.data().messageListCheckedOrSelectedUidsWithSubMails() - ; - - oEl.data('rl-folder', RL.data().currentFolderFullNameRaw()); - oEl.data('rl-uids', aUids); - oEl.find('.text').text('' + aUids.length); - - _.defer(function () { - var aUids = RL.data().messageListCheckedOrSelectedUidsWithSubMails(); - - oEl.data('rl-uids', aUids); - oEl.find('.text').text('' + aUids.length); - }); - - return oEl; -}; - -/** - * @param {string} sResult - * @param {AjaxJsonDefaultResponse} oData - * @param {boolean} bCached - */ -MailBoxMessageListViewModel.prototype.onMessageResponse = function (sResult, oData, bCached) -{ - var oRainLoopData = RL.data(); - - oRainLoopData.hideMessageBodies(); - oRainLoopData.messageLoading(false); - - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - oRainLoopData.setMessage(oData, bCached); - } - else if (Enums.StorageResultType.Unload === sResult) - { - oRainLoopData.message(null); - oRainLoopData.messageError(''); - } - else if (Enums.StorageResultType.Abort !== sResult) - { - oRainLoopData.message(null); - oRainLoopData.messageError((oData && oData.ErrorCode ? - Utils.getNotification(oData.ErrorCode) : - Utils.getNotification(Enums.Notification.UnknownError))); - } -}; - -MailBoxMessageListViewModel.prototype.populateMessageBody = function (oMessage) -{ - if (oMessage) - { - if (RL.remote().message(this.onMessageResponse, oMessage.folderFullNameRaw, oMessage.uid)) - { - RL.data().messageLoading(true); - } - else - { - Utils.log('Error: Unknown message request: ' + oMessage.folderFullNameRaw + ' ~ ' + oMessage.uid + ' [e-101]'); - } - } -}; - -/** - * @param {string} sFolderFullNameRaw - * @param {number} iSetAction - * @param {Array=} aMessages = null - */ -MailBoxMessageListViewModel.prototype.setAction = function (sFolderFullNameRaw, iSetAction, aMessages) -{ - var - aUids = [], - oFolder = null, - oCache = RL.cache(), - iAlreadyUnread = 0 - ; - - if (Utils.isUnd(aMessages)) - { - aMessages = RL.data().messageListChecked(); - } - - aUids = _.map(aMessages, function (oMessage) { - return oMessage.uid; - }); - - if ('' !== sFolderFullNameRaw && 0 < aUids.length) - { - switch (iSetAction) { - case Enums.MessageSetAction.SetSeen: - _.each(aMessages, function (oMessage) { - if (oMessage.unseen()) - { - iAlreadyUnread++; - } - - oMessage.unseen(false); - oCache.storeMessageFlagsToCache(oMessage); - }); - - oFolder = oCache.getFolderFromCacheList(sFolderFullNameRaw); - if (oFolder) - { - oFolder.messageCountUnread(oFolder.messageCountUnread() - iAlreadyUnread); - } - - RL.remote().messageSetSeen(Utils.emptyFunction, sFolderFullNameRaw, aUids, true); - break; - case Enums.MessageSetAction.UnsetSeen: - _.each(aMessages, function (oMessage) { - if (oMessage.unseen()) - { - iAlreadyUnread++; - } - - oMessage.unseen(true); - oCache.storeMessageFlagsToCache(oMessage); - }); - - oFolder = oCache.getFolderFromCacheList(sFolderFullNameRaw); - if (oFolder) - { - oFolder.messageCountUnread(oFolder.messageCountUnread() - iAlreadyUnread + aUids.length); - } - RL.remote().messageSetSeen(Utils.emptyFunction, sFolderFullNameRaw, aUids, false); - break; - case Enums.MessageSetAction.SetFlag: - _.each(aMessages, function (oMessage) { - oMessage.flagged(true); - oCache.storeMessageFlagsToCache(oMessage); - }); - RL.remote().messageSetFlagged(Utils.emptyFunction, sFolderFullNameRaw, aUids, true); - break; - case Enums.MessageSetAction.UnsetFlag: - _.each(aMessages, function (oMessage) { - oMessage.flagged(false); - oCache.storeMessageFlagsToCache(oMessage); - }); - RL.remote().messageSetFlagged(Utils.emptyFunction, sFolderFullNameRaw, aUids, false); - break; - } - - RL.reloadFlagsCurrentMessageListAndMessageFromCache(); - } -}; - -/** - * @param {string} sFolderFullNameRaw - * @param {number} iSetAction - */ -MailBoxMessageListViewModel.prototype.setActionForAll = function (sFolderFullNameRaw, iSetAction) -{ - var - oFolder = null, - aMessages = RL.data().messageList(), - oCache = RL.cache() - ; - - if ('' !== sFolderFullNameRaw) - { - oFolder = oCache.getFolderFromCacheList(sFolderFullNameRaw); - - if (oFolder) - { - switch (iSetAction) { - case Enums.MessageSetAction.SetSeen: - oFolder = oCache.getFolderFromCacheList(sFolderFullNameRaw); - if (oFolder) - { - _.each(aMessages, function (oMessage) { - oMessage.unseen(false); - }); - - oFolder.messageCountUnread(0); - oCache.clearMessageFlagsFromCacheByFolder(sFolderFullNameRaw); - } - - RL.remote().messageSetSeenToAll(Utils.emptyFunction, sFolderFullNameRaw, true); - break; - case Enums.MessageSetAction.UnsetSeen: - oFolder = oCache.getFolderFromCacheList(sFolderFullNameRaw); - if (oFolder) - { - _.each(aMessages, function (oMessage) { - oMessage.unseen(true); - }); - - oFolder.messageCountUnread(oFolder.messageCountAll()); - oCache.clearMessageFlagsFromCacheByFolder(sFolderFullNameRaw); - } - RL.remote().messageSetSeenToAll(Utils.emptyFunction, sFolderFullNameRaw, false); - break; - } - - RL.reloadFlagsCurrentMessageListAndMessageFromCache(); - } - } -}; - -MailBoxMessageListViewModel.prototype.listSetSeen = function () -{ - this.setAction(RL.data().currentFolderFullNameRaw(), Enums.MessageSetAction.SetSeen, RL.data().messageListCheckedOrSelected()); -}; - -MailBoxMessageListViewModel.prototype.listSetAllSeen = function () -{ - this.setActionForAll(RL.data().currentFolderFullNameRaw(), Enums.MessageSetAction.SetSeen); -}; - -MailBoxMessageListViewModel.prototype.listUnsetSeen = function () -{ - this.setAction(RL.data().currentFolderFullNameRaw(), Enums.MessageSetAction.UnsetSeen, RL.data().messageListCheckedOrSelected()); -}; - -MailBoxMessageListViewModel.prototype.listSetFlags = function () -{ - this.setAction(RL.data().currentFolderFullNameRaw(), Enums.MessageSetAction.SetFlag, RL.data().messageListCheckedOrSelected()); -}; - -MailBoxMessageListViewModel.prototype.listUnsetFlags = function () -{ - this.setAction(RL.data().currentFolderFullNameRaw(), Enums.MessageSetAction.UnsetFlag, RL.data().messageListCheckedOrSelected()); -}; - -MailBoxMessageListViewModel.prototype.flagMessages = function (oCurrentMessage) -{ - var - aChecked = this.messageListCheckedOrSelected(), - aCheckedUids = [] - ; - - if (oCurrentMessage) - { - if (0 < aChecked.length) - { - aCheckedUids = _.map(aChecked, function (oMessage) { - return oMessage.uid; - }); - } - - if (0 < aCheckedUids.length && -1 < Utils.inArray(oCurrentMessage.uid, aCheckedUids)) - { - this.setAction(oCurrentMessage.folderFullNameRaw, oCurrentMessage.flagged() ? - Enums.MessageSetAction.UnsetFlag : Enums.MessageSetAction.SetFlag, aChecked); - } - else - { - this.setAction(oCurrentMessage.folderFullNameRaw, oCurrentMessage.flagged() ? - Enums.MessageSetAction.UnsetFlag : Enums.MessageSetAction.SetFlag, [oCurrentMessage]); - } - } -}; - -MailBoxMessageListViewModel.prototype.flagMessagesFast = function (bFlag) -{ - var - aChecked = this.messageListCheckedOrSelected(), - aFlagged = [] - ; - - if (0 < aChecked.length) - { - aFlagged = _.filter(aChecked, function (oMessage) { - return oMessage.flagged(); - }); - - if (Utils.isUnd(bFlag)) - { - this.setAction(aChecked[0].folderFullNameRaw, - aChecked.length === aFlagged.length ? Enums.MessageSetAction.UnsetFlag : Enums.MessageSetAction.SetFlag, aChecked); - } - else - { - this.setAction(aChecked[0].folderFullNameRaw, - !bFlag ? Enums.MessageSetAction.UnsetFlag : Enums.MessageSetAction.SetFlag, aChecked); - } - } -}; - -MailBoxMessageListViewModel.prototype.seenMessagesFast = function (bSeen) -{ - var - aChecked = this.messageListCheckedOrSelected(), - aUnseen = [] - ; - - if (0 < aChecked.length) - { - aUnseen = _.filter(aChecked, function (oMessage) { - return oMessage.unseen(); - }); - - if (Utils.isUnd(bSeen)) - { - this.setAction(aChecked[0].folderFullNameRaw, - 0 < aUnseen.length ? Enums.MessageSetAction.SetSeen : Enums.MessageSetAction.UnsetSeen, aChecked); - } - else - { - this.setAction(aChecked[0].folderFullNameRaw, - bSeen ? Enums.MessageSetAction.SetSeen : Enums.MessageSetAction.UnsetSeen, aChecked); - } - } -}; - -MailBoxMessageListViewModel.prototype.onBuild = function (oDom) -{ - var - self = this, - oData = RL.data() - ; - - this.oContentVisible = $('.b-content', oDom); - this.oContentScrollable = $('.content', this.oContentVisible); - - this.oContentVisible.on('click', '.fullThreadHandle', function () { - var - aList = [], - oMessage = ko.dataFor(this) - ; - - if (oMessage && !oMessage.lastInCollapsedThreadLoading()) - { - RL.data().messageListThreadFolder(oMessage.folderFullNameRaw); - - aList = RL.data().messageListThreadUids(); - - if (oMessage.lastInCollapsedThread()) - { - aList.push(0 < oMessage.parentUid() ? oMessage.parentUid() : oMessage.uid); - } - else - { - aList = _.without(aList, 0 < oMessage.parentUid() ? oMessage.parentUid() : oMessage.uid); - } - - RL.data().messageListThreadUids(_.uniq(aList)); - - oMessage.lastInCollapsedThreadLoading(true); - oMessage.lastInCollapsedThread(!oMessage.lastInCollapsedThread()); - RL.reloadMessageList(); - } - - return false; - }); - - this.selector.init(this.oContentVisible, this.oContentScrollable, Enums.KeyState.MessageList); - - oDom - .on('click', '.messageList .b-message-list-wrapper', function () { - if (self.message.focused()) - { - self.message.focused(false); - } - }) - .on('click', '.e-pagenator .e-page', function () { - var oPage = ko.dataFor(this); - if (oPage) - { - kn.setHash(RL.link().mailBox( - oData.currentFolderFullNameHash(), - oPage.value, - oData.messageListSearch() - )); - } - }) - .on('click', '.messageList .checkboxCkeckAll', function () { - self.checkAll(!self.checkAll()); - }) - .on('click', '.messageList .messageListItem .flagParent', function () { - self.flagMessages(ko.dataFor(this)); - }) - ; - - this.initUploaderForAppend(); - this.initShortcuts(); - - if (!Globals.bMobileDevice && !!RL.settingsGet('AllowPrefetch') && ifvisible) - { - ifvisible.setIdleDuration(10); - - ifvisible.idle(function () { - self.prefetchNextTick(); - }); - } -}; - -MailBoxMessageListViewModel.prototype.initShortcuts = function () -{ - var self = this; - - // disable print - key('ctrl+p, command+p', Enums.KeyState.MessageList, function () { - return false; - }); - - // TODO // more toggle -// key('', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { -// self.moreDropdownTrigger(true); -// return false; -// }); - - // archive (zip) - key('z', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - self.archiveCommand(); - return false; - }); - - // delete - key('delete, shift+delete', Enums.KeyState.MessageList, function (event, handler) { - if (event) - { - if (0 < RL.data().messageListCheckedOrSelected().length) - { - if (handler && 'shift+delete' === handler.shortcut) - { - self.deleteWithoutMoveCommand(); - } - else - { - self.deleteCommand(); - } - } - - return false; - } - }); - - // check all - key('ctrl+a, command+a', Enums.KeyState.MessageList, function () { - self.checkAll(!(self.checkAll() && !self.isIncompleteChecked())); - return false; - }); - - // write/compose (open compose popup) - key('w,c', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - kn.showScreenPopup(PopupsComposeViewModel); - return false; - }); - - // important - star/flag messages - key('i', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - self.flagMessagesFast(); - return false; - }); - - // move - key('m', Enums.KeyState.MessageList, function () { - self.moveDropdownTrigger(true); - return false; - }); - - // read - key('q', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - self.seenMessagesFast(true); - return false; - }); - - // unread - key('u', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - self.seenMessagesFast(false); - return false; - }); - - key('shift+f', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - self.multyForwardCommand(); - return false; - }); - - // search input focus - key('/', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - self.inputMessageListSearchFocus(true); - return false; - }); - - // cancel search - key('esc', Enums.KeyState.MessageList, function () { - if ('' !== self.messageListSearchDesc()) - { - self.cancelSearch(); - return false; - } - }); - - // change focused state - key('tab, shift+tab, left, right', Enums.KeyState.MessageList, function (event, handler) { - if (event && handler && 'shift+tab' === handler.shortcut || 'left' === handler.shortcut) - { - self.folderList.focused(true); - } - else if (self.message()) - { - self.message.focused(true); - } - - return false; - }); - - // TODO - key('ctrl+left, command+left', Enums.KeyState.MessageView, function () { - return false; - }); - - // TODO - key('ctrl+right, command+right', Enums.KeyState.MessageView, function () { - return false; - }); -}; - -MailBoxMessageListViewModel.prototype.prefetchNextTick = function () -{ - if (!this.bPrefetch && !ifvisible.now() && this.viewModelVisibility()) - { - var - self = this, - oCache = RL.cache(), - oMessage = _.find(this.messageList(), function (oMessage) { - return oMessage && - !oCache.hasRequestedMessage(oMessage.folderFullNameRaw, oMessage.uid); - }) - ; - - if (oMessage) - { - this.bPrefetch = true; - - RL.cache().addRequestedMessage(oMessage.folderFullNameRaw, oMessage.uid); - - RL.remote().message(function (sResult, oData) { - - var bNext = !!(Enums.StorageResultType.Success === sResult && oData && oData.Result); - - _.delay(function () { - self.bPrefetch = false; - if (bNext) - { - self.prefetchNextTick(); - } - }, 1000); - - }, oMessage.folderFullNameRaw, oMessage.uid); - } - } -}; - -MailBoxMessageListViewModel.prototype.composeClick = function () -{ - kn.showScreenPopup(PopupsComposeViewModel); -}; - -MailBoxMessageListViewModel.prototype.advancedSearchClick = function () -{ - kn.showScreenPopup(PopupsAdvancedSearchViewModel); -}; - -MailBoxMessageListViewModel.prototype.quotaTooltip = function () -{ - return Utils.i18n('MESSAGE_LIST/QUOTA_SIZE', { - 'SIZE': Utils.friendlySize(this.userUsageSize()), - 'PROC': this.userUsageProc(), - 'LIMIT': Utils.friendlySize(this.userQuota()) - }); -}; - -MailBoxMessageListViewModel.prototype.initUploaderForAppend = function () -{ - if (!RL.settingsGet('AllowAppendMessage') || !this.dragOverArea()) - { - return false; - } - - var oJua = new Jua({ - 'action': RL.link().append(), - 'name': 'AppendFile', - 'queueSize': 1, - 'multipleSizeLimit': 1, - 'disableFolderDragAndDrop': true, - 'hidden': { - 'Folder': function () { - return RL.data().currentFolderFullNameRaw(); - } - }, - 'dragAndDropElement': this.dragOverArea(), - 'dragAndDropBodyElement': this.dragOverBodyArea() - }); - - oJua - .on('onDragEnter', _.bind(function () { - this.dragOverEnter(true); - }, this)) - .on('onDragLeave', _.bind(function () { - this.dragOverEnter(false); - }, this)) - .on('onBodyDragEnter', _.bind(function () { - this.dragOver(true); - }, this)) - .on('onBodyDragLeave', _.bind(function () { - this.dragOver(false); - }, this)) - .on('onSelect', _.bind(function (sUid, oData) { - if (sUid && oData && 'message/rfc822' === oData['Type']) - { - RL.data().messageListLoading(true); - return true; - } - - return false; - }, this)) - .on('onComplete', _.bind(function () { - RL.reloadMessageList(true, true); - }, this)) - ; - - return !!oJua; + $document.click(function () { + $oEl.tooltip('hide'); + }); + + }, + 'update': function (oElement, fValueAccessor) { + var sValue = ko.utils.unwrapObservable(fValueAccessor()); + if ('' === sValue) + { + $(oElement).data('tooltip3-data', '').tooltip('hide'); + } + else + { + $(oElement).data('tooltip3-data', sValue).tooltip('show'); + } + } }; -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function MailBoxMessageViewViewModel() -{ - KnoinAbstractViewModel.call(this, 'Right', 'MailMessageView'); - - var - self = this, - sLastEmail = '', - oData = RL.data(), - createCommandHelper = function (sType) { - return Utils.createCommand(self, function () { - this.replyOrforward(sType); - }, self.canBeRepliedOrForwarded); - } - ; - - this.oMessageScrollerDom = null; - - this.keyScope = oData.keyScope; - this.message = oData.message; - this.currentMessage = oData.currentMessage; - this.messageListChecked = oData.messageListChecked; - this.hasCheckedMessages = oData.hasCheckedMessages; - this.messageListCheckedOrSelectedUidsWithSubMails = oData.messageListCheckedOrSelectedUidsWithSubMails; - this.messageLoading = oData.messageLoading; - this.messageLoadingThrottle = oData.messageLoadingThrottle; - this.messagesBodiesDom = oData.messagesBodiesDom; - this.useThreads = oData.useThreads; - this.replySameFolder = oData.replySameFolder; - this.layout = oData.layout; - this.usePreviewPane = oData.usePreviewPane; - this.isMessageSelected = oData.isMessageSelected; - this.messageActiveDom = oData.messageActiveDom; - this.messageError = oData.messageError; - - this.fullScreenMode = oData.messageFullScreenMode; - - this.showFullInfo = ko.observable(false); - this.moreDropdownTrigger = ko.observable(false); - this.messageDomFocused = ko.observable(false).extend({'rateLimit': 0}); - - this.messageVisibility = ko.computed(function () { - return !this.messageLoadingThrottle() && !!this.message(); - }, this); - - this.message.subscribe(function (oMessage) { - if (!oMessage) - { - this.currentMessage(null); - } - }, this); - - this.canBeRepliedOrForwarded = this.messageVisibility; - - // commands - this.closeMessage = Utils.createCommand(this, function () { - oData.message(null); - }); - - this.replyCommand = createCommandHelper(Enums.ComposeType.Reply); - this.replyAllCommand = createCommandHelper(Enums.ComposeType.ReplyAll); - this.forwardCommand = createCommandHelper(Enums.ComposeType.Forward); - this.forwardAsAttachmentCommand = createCommandHelper(Enums.ComposeType.ForwardAsAttachment); - this.editAsNewCommand = createCommandHelper(Enums.ComposeType.EditAsNew); - - this.messageVisibilityCommand = Utils.createCommand(this, Utils.emptyFunction, this.messageVisibility); - - this.messageEditCommand = Utils.createCommand(this, function () { - this.editMessage(); - }, this.messageVisibility); - - this.deleteCommand = Utils.createCommand(this, function () { - if (this.message()) - { - RL.deleteMessagesFromFolder(Enums.FolderType.Trash, - this.message().folderFullNameRaw, - [this.message().uid], true); - } - }, this.messageVisibility); - - this.deleteWithoutMoveCommand = Utils.createCommand(this, function () { - if (this.message()) - { - RL.deleteMessagesFromFolder(Enums.FolderType.Trash, - RL.data().currentFolderFullNameRaw(), - [this.message().uid], false); - } - }, this.messageVisibility); - - this.archiveCommand = Utils.createCommand(this, function () { - if (this.message()) - { - RL.deleteMessagesFromFolder(Enums.FolderType.Archive, - this.message().folderFullNameRaw, - [this.message().uid], true); - } - }, this.messageVisibility); - - this.spamCommand = Utils.createCommand(this, function () { - if (this.message()) - { - RL.deleteMessagesFromFolder(Enums.FolderType.Spam, - this.message().folderFullNameRaw, - [this.message().uid], true); - } - }, this.messageVisibility); - - this.notSpamCommand = Utils.createCommand(this, function () { - if (this.message()) - { - RL.deleteMessagesFromFolder(Enums.FolderType.NotSpam, - this.message().folderFullNameRaw, - [this.message().uid], true); - } - }, this.messageVisibility); - - // viewer - this.viewSubject = ko.observable(''); - this.viewFromShort = ko.observable(''); - this.viewToShort = ko.observable(''); - this.viewFrom = ko.observable(''); - this.viewTo = ko.observable(''); - this.viewCc = ko.observable(''); - this.viewBcc = ko.observable(''); - this.viewDate = ko.observable(''); - this.viewMoment = ko.observable(''); - this.viewLineAsCcc = ko.observable(''); - this.viewViewLink = ko.observable(''); - this.viewDownloadLink = ko.observable(''); - this.viewUserPic = ko.observable(Consts.DataImages.UserDotPic); - this.viewUserPicVisible = ko.observable(false); - - this.viewPgpPassword = ko.observable(''); - this.viewPgpSignedVerifyStatus = ko.computed(function () { - return this.message() ? this.message().pgpSignedVerifyStatus() : Enums.SignedVerifyStatus.None; - }, this); - - this.viewPgpSignedVerifyUser = ko.computed(function () { - return this.message() ? this.message().pgpSignedVerifyUser() : ''; - }, this); - - this.message.subscribe(function (oMessage) { - - this.messageActiveDom(null); - - this.viewPgpPassword(''); - - if (oMessage) - { - this.viewSubject(oMessage.subject()); - this.viewFromShort(oMessage.fromToLine(true, true)); - this.viewToShort(oMessage.toToLine(true, true)); - this.viewFrom(oMessage.fromToLine(false)); - this.viewTo(oMessage.toToLine(false)); - this.viewCc(oMessage.ccToLine(false)); - this.viewBcc(oMessage.bccToLine(false)); - this.viewDate(oMessage.fullFormatDateValue()); - this.viewMoment(oMessage.momentDate()); - this.viewLineAsCcc(oMessage.lineAsCcc()); - this.viewViewLink(oMessage.viewLink()); - this.viewDownloadLink(oMessage.downloadLink()); - - sLastEmail = oMessage.fromAsSingleEmail(); - RL.cache().getUserPic(sLastEmail, function (sPic, $sEmail) { - if (sPic !== self.viewUserPic() && sLastEmail === $sEmail) - { - self.viewUserPicVisible(false); - self.viewUserPic(Consts.DataImages.UserDotPic); - if ('' !== sPic) - { - self.viewUserPicVisible(true); - self.viewUserPic(sPic); - } - } - }); - } - - }, this); - - this.fullScreenMode.subscribe(function (bValue) { - if (bValue) - { - $html.addClass('rl-message-fullscreen'); - } - else - { - $html.removeClass('rl-message-fullscreen'); - } - - Utils.windowResize(); - }); - - this.messageLoadingThrottle.subscribe(function (bV) { - if (bV) - { - Utils.windowResize(); - } - }); - - this.messageActiveDom.subscribe(function () { - this.scrollMessageToTop(); - }, this); - - this.goUpCommand = Utils.createCommand(this, function () { - RL.pub('mailbox.message-list.selector.go-up'); - }); - - this.goDownCommand = Utils.createCommand(this, function () { - RL.pub('mailbox.message-list.selector.go-down'); - }); - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('MailBoxMessageViewViewModel', MailBoxMessageViewViewModel); - -MailBoxMessageViewViewModel.prototype.isPgpActionVisible = function () -{ - return Enums.SignedVerifyStatus.Success !== this.viewPgpSignedVerifyStatus(); -}; - -MailBoxMessageViewViewModel.prototype.isPgpStatusVerifyVisible = function () -{ - return Enums.SignedVerifyStatus.None !== this.viewPgpSignedVerifyStatus(); -}; - -MailBoxMessageViewViewModel.prototype.isPgpStatusVerifySuccess = function () -{ - return Enums.SignedVerifyStatus.Success === this.viewPgpSignedVerifyStatus(); -}; - -MailBoxMessageViewViewModel.prototype.pgpStatusVerifyMessage = function () -{ - var sResult = ''; - switch (this.viewPgpSignedVerifyStatus()) - { - case Enums.SignedVerifyStatus.UnknownPublicKeys: - sResult = Utils.i18n('PGP_NOTIFICATIONS/NO_PUBLIC_KEYS_FOUND'); - break; - case Enums.SignedVerifyStatus.UnknownPrivateKey: - sResult = Utils.i18n('PGP_NOTIFICATIONS/NO_PRIVATE_KEY_FOUND'); - break; - case Enums.SignedVerifyStatus.Unverified: - sResult = Utils.i18n('PGP_NOTIFICATIONS/UNVERIFIRED_SIGNATURE'); - break; - case Enums.SignedVerifyStatus.Error: - sResult = Utils.i18n('PGP_NOTIFICATIONS/DECRYPTION_ERROR'); - break; - case Enums.SignedVerifyStatus.Success: - sResult = Utils.i18n('PGP_NOTIFICATIONS/GOOD_SIGNATURE', { - 'USER': this.viewPgpSignedVerifyUser() - }); - break; - } - - return sResult; -}; - -MailBoxMessageViewViewModel.prototype.scrollToTop = function () -{ - var oCont = $('.messageItem.nano .content', this.viewModelDom); - if (oCont && oCont[0]) - { -// oCont.animate({'scrollTop': 0}, 300); - oCont.scrollTop(0); - } - else - { -// $('.messageItem', this.viewModelDom).animate({'scrollTop': 0}, 300); - $('.messageItem', this.viewModelDom).scrollTop(0); - } - - Utils.windowResize(); -}; - -MailBoxMessageViewViewModel.prototype.fullScreen = function () -{ - this.fullScreenMode(true); - Utils.windowResize(); -}; - -MailBoxMessageViewViewModel.prototype.unFullScreen = function () -{ - this.fullScreenMode(false); - Utils.windowResize(); -}; - -MailBoxMessageViewViewModel.prototype.toggleFullScreen = function () -{ - Utils.removeSelection(); - - this.fullScreenMode(!this.fullScreenMode()); - Utils.windowResize(); -}; - -/** - * @param {string} sType - */ -MailBoxMessageViewViewModel.prototype.replyOrforward = function (sType) -{ - kn.showScreenPopup(PopupsComposeViewModel, [sType, RL.data().message()]); -}; - -MailBoxMessageViewViewModel.prototype.onBuild = function (oDom) -{ - var - self = this, - oData = RL.data() - ; - - this.fullScreenMode.subscribe(function (bValue) { - if (bValue) - { - self.message.focused(true); - } - }, this); - - $('.attachmentsPlace', oDom).magnificPopup({ - 'delegate': '.magnificPopupImage:visible', - 'type': 'image', - 'gallery': { - 'enabled': true, - 'preload': [1, 1], - 'navigateByImgClick': true - }, - 'callbacks': { - 'open': function() { - oData.useKeyboardShortcuts(false); - }, - 'close': function() { - oData.useKeyboardShortcuts(true); - } - }, - 'mainClass': 'mfp-fade', - 'removalDelay': 400 - }); - - oDom - .on('click', '.messageView .messageItem .messageItemHeader', function () { - if (oData.useKeyboardShortcuts() && self.message()) - { - self.message.focused(true); - } - }) - .on('mousedown', 'a', function (oEvent) { - // setup maito protocol - return !(oEvent && 3 !== oEvent['which'] && RL.mailToHelper($(this).attr('href'))); - }) - .on('click', '.attachmentsPlace .attachmentPreview', function (oEvent) { - if (oEvent && oEvent.stopPropagation) - { - oEvent.stopPropagation(); - } - }) - .on('click', '.attachmentsPlace .attachmentItem', function () { - - var - oAttachment = ko.dataFor(this) - ; - - if (oAttachment && oAttachment.download) - { - RL.download(oAttachment.linkDownload()); - } - }) - ; - - this.message.focused.subscribe(function (bValue) { - if (bValue && !Utils.inFocus()) { - this.messageDomFocused(true); - } else { - this.messageDomFocused(false); - } - }, this); - - this.messageDomFocused.subscribe(function (bValue) { - if (!bValue && Enums.KeyState.MessageView === this.keyScope()) - { - this.message.focused(false); - } - }, this); - - this.keyScope.subscribe(function (sValue) { - if (Enums.KeyState.MessageView === sValue && this.message.focused()) - { - this.messageDomFocused(true); - } - }, this); - - this.oMessageScrollerDom = oDom.find('.messageItem .content'); - this.oMessageScrollerDom = this.oMessageScrollerDom && this.oMessageScrollerDom[0] ? this.oMessageScrollerDom : null; - - this.initShortcuts(); -}; - -/** - * @return {boolean} - */ -MailBoxMessageViewViewModel.prototype.escShortcuts = function () -{ - if (this.viewModelVisibility() && this.message()) - { - if (this.fullScreenMode()) - { - this.fullScreenMode(false); - } - else if (Enums.Layout.NoPreview === RL.data().layout()) - { - this.message(null); - } - else - { - this.message.focused(false); - } - - return false; - } -}; - -MailBoxMessageViewViewModel.prototype.initShortcuts = function () -{ - var - self = this, - oData = RL.data() - ; - - // exit fullscreen, back - key('esc', Enums.KeyState.MessageView, _.bind(this.escShortcuts, this)); - - // fullscreen - key('enter', Enums.KeyState.MessageView, function () { - self.toggleFullScreen(); - return false; - }); - - key('enter', Enums.KeyState.MessageList, function () { - if (Enums.Layout.NoPreview !== oData.layout() && self.message()) - { - self.toggleFullScreen(); - return false; - } - }); - - // TODO // more toggle -// key('', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { -// self.moreDropdownTrigger(true); -// return false; -// }); - - // reply - key('r', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - if (oData.message()) - { - self.replyCommand(); - return false; - } - }); - - // replaAll - key('a', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - if (oData.message()) - { - self.replyAllCommand(); - return false; - } - }); - - // forward - key('f', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - if (oData.message()) - { - self.forwardCommand(); - return false; - } - }); - - // message information -// key('i', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { -// if (oData.message()) -// { -// self.showFullInfo(!self.showFullInfo()); -// return false; -// } -// }); - - // toggle message blockquotes - key('b', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - if (oData.message() && oData.message().body) - { - Utils.toggleMessageBlockquote(oData.message().body); - return false; - } - }); - - key('ctrl+left, command+left, ctrl+up, command+up', Enums.KeyState.MessageView, function () { - self.goUpCommand(); - return false; - }); - - key('ctrl+right, command+right, ctrl+down, command+down', Enums.KeyState.MessageView, function () { - self.goDownCommand(); - return false; - }); - - // print - key('ctrl+p, command+p', Enums.KeyState.MessageView, function () { - if (self.message()) - { - self.message().printMessage(); - } - - return false; - }); - - // delete - key('delete, shift+delete', Enums.KeyState.MessageView, function (event, handler) { - if (event) - { - if (handler && 'shift+delete' === handler.shortcut) - { - self.deleteWithoutMoveCommand(); - } - else - { - self.deleteCommand(); - } - - return false; - } - }); - - // change focused state - key('tab, shift+tab, left', Enums.KeyState.MessageView, function () { - if (!self.fullScreenMode() && self.message() && Enums.Layout.NoPreview !== oData.layout()) - { - self.message.focused(false); - } - - return false; - }); -}; - -/** - * @return {boolean} - */ -MailBoxMessageViewViewModel.prototype.isDraftFolder = function () -{ - return RL.data().message() && RL.data().draftFolder() === RL.data().message().folderFullNameRaw; -}; - -/** - * @return {boolean} - */ -MailBoxMessageViewViewModel.prototype.isSentFolder = function () -{ - return RL.data().message() && RL.data().sentFolder() === RL.data().message().folderFullNameRaw; -}; - -/** - * @return {boolean} - */ -MailBoxMessageViewViewModel.prototype.isSpamFolder = function () -{ - return RL.data().message() && RL.data().spamFolder() === RL.data().message().folderFullNameRaw; -}; - -/** - * @return {boolean} - */ -MailBoxMessageViewViewModel.prototype.isSpamDisabled = function () -{ - return RL.data().message() && RL.data().spamFolder() === Consts.Values.UnuseOptionValue; -}; - -/** - * @return {boolean} - */ -MailBoxMessageViewViewModel.prototype.isArchiveFolder = function () -{ - return RL.data().message() && RL.data().archiveFolder() === RL.data().message().folderFullNameRaw; -}; - -/** - * @return {boolean} - */ -MailBoxMessageViewViewModel.prototype.isArchiveDisabled = function () -{ - return RL.data().message() && RL.data().archiveFolder() === Consts.Values.UnuseOptionValue; -}; - -/** - * @return {boolean} - */ -MailBoxMessageViewViewModel.prototype.isDraftOrSentFolder = function () -{ - return this.isDraftFolder() || this.isSentFolder(); -}; - -MailBoxMessageViewViewModel.prototype.composeClick = function () -{ - kn.showScreenPopup(PopupsComposeViewModel); -}; - -MailBoxMessageViewViewModel.prototype.editMessage = function () -{ - if (RL.data().message()) - { - kn.showScreenPopup(PopupsComposeViewModel, [Enums.ComposeType.Draft, RL.data().message()]); - } -}; - -MailBoxMessageViewViewModel.prototype.scrollMessageToTop = function () -{ - if (this.oMessageScrollerDom) - { - this.oMessageScrollerDom.scrollTop(0); - } -}; - -/** - * @param {MessageModel} oMessage - */ -MailBoxMessageViewViewModel.prototype.showImages = function (oMessage) -{ - if (oMessage && oMessage.showExternalImages) - { - oMessage.showExternalImages(true); - } -}; - -/** - * @returns {string} - */ -MailBoxMessageViewViewModel.prototype.printableCheckedMessageCount = function () -{ - var iCnt = this.messageListCheckedOrSelectedUidsWithSubMails().length; - return 0 < iCnt ? (100 > iCnt ? iCnt : '99+') : ''; -}; - - -/** - * @param {MessageModel} oMessage - */ -MailBoxMessageViewViewModel.prototype.verifyPgpSignedClearMessage = function (oMessage) -{ - if (oMessage) - { - oMessage.verifyPgpSignedClearMessage(); - } -}; - -/** - * @param {MessageModel} oMessage - */ -MailBoxMessageViewViewModel.prototype.decryptPgpEncryptedMessage = function (oMessage) -{ - if (oMessage) - { - oMessage.decryptPgpEncryptedMessage(this.viewPgpPassword()); - } -}; - -/** - * @param {MessageModel} oMessage - */ -MailBoxMessageViewViewModel.prototype.readReceipt = function (oMessage) -{ - if (oMessage && '' !== oMessage.readReceipt()) - { - RL.remote().sendReadReceiptMessage(Utils.emptyFunction, oMessage.folderFullNameRaw, oMessage.uid, - oMessage.readReceipt(), - Utils.i18n('READ_RECEIPT/SUBJECT', {'SUBJECT': oMessage.subject()}), - Utils.i18n('READ_RECEIPT/BODY', {'READ-RECEIPT': RL.data().accountEmail()})); - - oMessage.isReadReceipt(true); - - RL.cache().storeMessageFlagsToCache(oMessage); - RL.reloadFlagsCurrentMessageListAndMessageFromCache(); - } -}; -/** - * @param {?} oScreen - * - * @constructor - * @extends KnoinAbstractViewModel - */ -function SettingsMenuViewModel(oScreen) -{ - KnoinAbstractViewModel.call(this, 'Left', 'SettingsMenu'); - - this.menu = oScreen.menu; - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('SettingsMenuViewModel', SettingsMenuViewModel); - -SettingsMenuViewModel.prototype.link = function (sRoute) -{ - return RL.link().settings(sRoute); -}; - -SettingsMenuViewModel.prototype.backToMailBoxClick = function () -{ - kn.setHash(RL.link().inbox()); -}; - -/** - * @constructor - * @extends KnoinAbstractViewModel - */ -function SettingsPaneViewModel() -{ - KnoinAbstractViewModel.call(this, 'Right', 'SettingsPane'); - - this.leftPanelDisabled = RL.data().leftPanelDisabled; - - Knoin.constructorEnd(this); -} - -Utils.extendAsViewModel('SettingsPaneViewModel', SettingsPaneViewModel); - -SettingsPaneViewModel.prototype.onBuild = function () -{ - var self = this; - key('esc', Enums.KeyState.Settings, function () { - self.backToMailBoxClick(); - }); -}; - -SettingsPaneViewModel.prototype.onShow = function () -{ - RL.data().message(null); -}; - -SettingsPaneViewModel.prototype.backToMailBoxClick = function () -{ - kn.setHash(RL.link().inbox()); -}; - -/** - * @constructor - */ -function SettingsGeneral() -{ - var oData = RL.data(); - - this.mainLanguage = oData.mainLanguage; - this.mainMessagesPerPage = oData.mainMessagesPerPage; - this.mainMessagesPerPageArray = Consts.Defaults.MessagesPerPageArray; - this.editorDefaultType = oData.editorDefaultType; - this.showImages = oData.showImages; - this.interfaceAnimation = oData.interfaceAnimation; - this.useDesktopNotifications = oData.useDesktopNotifications; - this.threading = oData.threading; - this.useThreads = oData.useThreads; - this.replySameFolder = oData.replySameFolder; - this.layout = oData.layout; - this.usePreviewPane = oData.usePreviewPane; - this.useCheckboxesInList = oData.useCheckboxesInList; - this.allowLanguagesOnSettings = oData.allowLanguagesOnSettings; - - this.isDesktopNotificationsSupported = ko.computed(function () { - return Enums.DesktopNotifications.NotSupported !== oData.desktopNotificationsPermisions(); - }); - - this.isDesktopNotificationsDenied = ko.computed(function () { - return Enums.DesktopNotifications.NotSupported === oData.desktopNotificationsPermisions() || - Enums.DesktopNotifications.Denied === oData.desktopNotificationsPermisions(); - }); - - this.mainLanguageFullName = ko.computed(function () { - return Utils.convertLangName(this.mainLanguage()); - }, this); - - this.languageTrigger = ko.observable(Enums.SaveSettingsStep.Idle).extend({'throttle': 100}); - this.mppTrigger = ko.observable(Enums.SaveSettingsStep.Idle); - - this.isAnimationSupported = Globals.bAnimationSupported; -} - -Utils.addSettingsViewModel(SettingsGeneral, 'SettingsGeneral', 'SETTINGS_LABELS/LABEL_GENERAL_NAME', 'general', true); - -SettingsGeneral.prototype.toggleLayout = function () -{ - this.layout(Enums.Layout.NoPreview === this.layout() ? Enums.Layout.SidePreview : Enums.Layout.NoPreview); -}; - -SettingsGeneral.prototype.onBuild = function () -{ - var self = this; - - _.delay(function () { - - var - oData = RL.data(), - f1 = Utils.settingsSaveHelperSimpleFunction(self.mppTrigger, self) - ; - - oData.language.subscribe(function (sValue) { - - self.languageTrigger(Enums.SaveSettingsStep.Animate); - - $.ajax({ - 'url': RL.link().langLink(sValue), - 'dataType': 'script', - 'cache': true - }).done(function() { - Utils.i18nToDoc(); - self.languageTrigger(Enums.SaveSettingsStep.TrueResult); - }).fail(function() { - self.languageTrigger(Enums.SaveSettingsStep.FalseResult); - }).always(function() { - _.delay(function () { - self.languageTrigger(Enums.SaveSettingsStep.Idle); - }, 1000); - }); - - RL.remote().saveSettings(Utils.emptyFunction, { - 'Language': sValue - }); - }); - - oData.editorDefaultType.subscribe(function (sValue) { - RL.remote().saveSettings(Utils.emptyFunction, { - 'EditorDefaultType': sValue - }); - }); - - oData.messagesPerPage.subscribe(function (iValue) { - RL.remote().saveSettings(f1, { - 'MPP': iValue - }); - }); - - oData.showImages.subscribe(function (bValue) { - RL.remote().saveSettings(Utils.emptyFunction, { - 'ShowImages': bValue ? '1' : '0' - }); - }); - - oData.interfaceAnimation.subscribe(function (sValue) { - RL.remote().saveSettings(Utils.emptyFunction, { - 'InterfaceAnimation': sValue - }); - }); - - oData.useDesktopNotifications.subscribe(function (bValue) { - Utils.timeOutAction('SaveDesktopNotifications', function () { - RL.remote().saveSettings(Utils.emptyFunction, { - 'DesktopNotifications': bValue ? '1' : '0' - }); - }, 3000); - }); - - oData.replySameFolder.subscribe(function (bValue) { - Utils.timeOutAction('SaveReplySameFolder', function () { - RL.remote().saveSettings(Utils.emptyFunction, { - 'ReplySameFolder': bValue ? '1' : '0' - }); - }, 3000); - }); - - oData.useThreads.subscribe(function (bValue) { - - oData.messageList([]); - - RL.remote().saveSettings(Utils.emptyFunction, { - 'UseThreads': bValue ? '1' : '0' - }); - }); - - oData.layout.subscribe(function (nValue) { - - oData.messageList([]); - - RL.remote().saveSettings(Utils.emptyFunction, { - 'Layout': nValue - }); - }); - - oData.useCheckboxesInList.subscribe(function (bValue) { - RL.remote().saveSettings(Utils.emptyFunction, { - 'UseCheckboxesInList': bValue ? '1' : '0' - }); - }); - - }, 50); -}; - -SettingsGeneral.prototype.onShow = function () -{ - RL.data().desktopNotifications.valueHasMutated(); -}; - -SettingsGeneral.prototype.selectLanguage = function () -{ - kn.showScreenPopup(PopupsLanguagesViewModel); -}; - -/** - * @constructor - */ -function SettingsContacts() -{ - var oData = RL.data(); - - this.contactsAutosave = oData.contactsAutosave; - - this.allowContactsSync = oData.allowContactsSync; - this.enableContactsSync = oData.enableContactsSync; - this.contactsSyncUrl = oData.contactsSyncUrl; - this.contactsSyncUser = oData.contactsSyncUser; - this.contactsSyncPass = oData.contactsSyncPass; - - this.saveTrigger = ko.computed(function () { - return [ - this.enableContactsSync() ? '1' : '0', - this.contactsSyncUrl(), - this.contactsSyncUser(), - this.contactsSyncPass() - ].join('|'); - }, this).extend({'throttle': 500}); - - this.saveTrigger.subscribe(function () { - RL.remote().saveContactsSyncData(null, - this.enableContactsSync(), - this.contactsSyncUrl(), - this.contactsSyncUser(), - this.contactsSyncPass() - ); - }, this); -} - -Utils.addSettingsViewModel(SettingsContacts, 'SettingsContacts', 'SETTINGS_LABELS/LABEL_CONTACTS_NAME', 'contacts'); - -SettingsContacts.prototype.onBuild = function () -{ - RL.data().contactsAutosave.subscribe(function (bValue) { - RL.remote().saveSettings(Utils.emptyFunction, { - 'ContactsAutosave': bValue ? '1' : '0' - }); - }); -}; - -//SettingsContacts.prototype.onShow = function () -//{ -// -//}; - -/** - * @constructor - */ -function SettingsAccounts() -{ - var oData = RL.data(); - - this.accounts = oData.accounts; - - this.processText = ko.computed(function () { - return oData.accountsLoading() ? Utils.i18n('SETTINGS_ACCOUNTS/LOADING_PROCESS') : ''; - }, this); - - this.visibility = ko.computed(function () { - return '' === this.processText() ? 'hidden' : 'visible'; - }, this); - - this.accountForDeletion = ko.observable(null).extend({'falseTimeout': 3000}).extend({'toggleSubscribe': [this, - function (oPrev) { - if (oPrev) - { - oPrev.deleteAccess(false); - } - }, function (oNext) { - if (oNext) - { - oNext.deleteAccess(true); - } - } - ]}); -} - -Utils.addSettingsViewModel(SettingsAccounts, 'SettingsAccounts', 'SETTINGS_LABELS/LABEL_ACCOUNTS_NAME', 'accounts'); - -SettingsAccounts.prototype.addNewAccount = function () -{ - kn.showScreenPopup(PopupsAddAccountViewModel); -}; - -/** - * @param {AccountModel} oAccountToRemove - */ -SettingsAccounts.prototype.deleteAccount = function (oAccountToRemove) -{ - if (oAccountToRemove && oAccountToRemove.deleteAccess()) - { - this.accountForDeletion(null); - - var - fRemoveAccount = function (oAccount) { - return oAccountToRemove === oAccount; - } - ; - - if (oAccountToRemove) - { - this.accounts.remove(fRemoveAccount); - - RL.remote().accountDelete(function (sResult, oData) { - - if (Enums.StorageResultType.Success === sResult && oData && - oData.Result && oData.Reload) - { - kn.routeOff(); - kn.setHash(RL.link().root(), true); - kn.routeOff(); - - _.defer(function () { - window.location.reload(); - }); - } - else - { - RL.accountsAndIdentities(); - } - - }, oAccountToRemove.email); - } - } -}; - -/** - * @constructor - */ -function SettingsIdentity() -{ - var oData = RL.data(); - - this.editor = null; - - this.displayName = oData.displayName; - this.signature = oData.signature; - this.signatureToAll = oData.signatureToAll; - this.replyTo = oData.replyTo; - - this.signatureDom = ko.observable(null); - - this.displayNameTrigger = ko.observable(Enums.SaveSettingsStep.Idle); - this.replyTrigger = ko.observable(Enums.SaveSettingsStep.Idle); - this.signatureTrigger = ko.observable(Enums.SaveSettingsStep.Idle); -} - -Utils.addSettingsViewModel(SettingsIdentity, 'SettingsIdentity', 'SETTINGS_LABELS/LABEL_IDENTITY_NAME', 'identity'); - -SettingsIdentity.prototype.onFocus = function () -{ - if (!this.editor && this.signatureDom()) - { - var - self = this, - sSignature = RL.data().signature() - ; - - this.editor = new NewHtmlEditorWrapper(self.signatureDom(), function () { - RL.data().signature( - (self.editor.isHtml() ? ':HTML:' : '') + self.editor.getData() - ); - }, function () { - if (':HTML:' === sSignature.substr(0, 6)) - { - self.editor.setHtml(sSignature.substr(6), false); - } - else - { - self.editor.setPlain(sSignature, false); - } - }); - } -}; - -SettingsIdentity.prototype.onBuild = function () -{ - var self = this; - _.delay(function () { - - var - oData = RL.data(), - f1 = Utils.settingsSaveHelperSimpleFunction(self.displayNameTrigger, self), - f2 = Utils.settingsSaveHelperSimpleFunction(self.replyTrigger, self), - f3 = Utils.settingsSaveHelperSimpleFunction(self.signatureTrigger, self) - ; - - oData.displayName.subscribe(function (sValue) { - RL.remote().saveSettings(f1, { - 'DisplayName': sValue - }); - }); - - oData.replyTo.subscribe(function (sValue) { - RL.remote().saveSettings(f2, { - 'ReplyTo': sValue - }); - }); - - oData.signature.subscribe(function (sValue) { - RL.remote().saveSettings(f3, { - 'Signature': sValue - }); - }); - - oData.signatureToAll.subscribe(function (bValue) { - RL.remote().saveSettings(null, { - 'SignatureToAll': bValue ? '1' : '0' - }); - }); - - }, 50); -}; - -/** - * @constructor - */ -function SettingsIdentities() -{ - var oData = RL.data(); - - this.editor = null; - - this.displayName = oData.displayName; - this.signature = oData.signature; - this.signatureToAll = oData.signatureToAll; - this.replyTo = oData.replyTo; - - this.signatureDom = ko.observable(null); - - this.displayNameTrigger = ko.observable(Enums.SaveSettingsStep.Idle); - this.replyTrigger = ko.observable(Enums.SaveSettingsStep.Idle); - this.signatureTrigger = ko.observable(Enums.SaveSettingsStep.Idle); - - this.identities = oData.identities; - - this.processText = ko.computed(function () { - return oData.identitiesLoading() ? Utils.i18n('SETTINGS_IDENTITIES/LOADING_PROCESS') : ''; - }, this); - - this.visibility = ko.computed(function () { - return '' === this.processText() ? 'hidden' : 'visible'; - }, this); - - this.identityForDeletion = ko.observable(null).extend({'falseTimeout': 3000}).extend({'toggleSubscribe': [this, - function (oPrev) { - if (oPrev) - { - oPrev.deleteAccess(false); - } - }, function (oNext) { - if (oNext) - { - oNext.deleteAccess(true); - } - } - ]}); -} - -Utils.addSettingsViewModel(SettingsIdentities, 'SettingsIdentities', 'SETTINGS_LABELS/LABEL_IDENTITIES_NAME', 'identities'); - -SettingsIdentities.prototype.addNewIdentity = function () -{ - kn.showScreenPopup(PopupsIdentityViewModel); -}; - -SettingsIdentities.prototype.editIdentity = function (oIdentity) -{ - kn.showScreenPopup(PopupsIdentityViewModel, [oIdentity]); -}; - -/** - * @param {IdentityModel} oIdentityToRemove - */ -SettingsIdentities.prototype.deleteIdentity = function (oIdentityToRemove) -{ - if (oIdentityToRemove && oIdentityToRemove.deleteAccess()) - { - this.identityForDeletion(null); - - var - fRemoveFolder = function (oIdentity) { - return oIdentityToRemove === oIdentity; - } - ; - - if (oIdentityToRemove) - { - this.identities.remove(fRemoveFolder); - - RL.remote().identityDelete(function () { - RL.accountsAndIdentities(); - }, oIdentityToRemove.id); - } - } -}; - -SettingsIdentities.prototype.onFocus = function () -{ - if (!this.editor && this.signatureDom()) - { - var - self = this, - sSignature = RL.data().signature() - ; - - this.editor = new NewHtmlEditorWrapper(self.signatureDom(), function () { - RL.data().signature( - (self.editor.isHtml() ? ':HTML:' : '') + self.editor.getData() - ); - }, function () { - if (':HTML:' === sSignature.substr(0, 6)) - { - self.editor.setHtml(sSignature.substr(6), false); - } - else - { - self.editor.setPlain(sSignature, false); - } - }); - } -}; - -SettingsIdentities.prototype.onBuild = function (oDom) -{ - var self = this; - - oDom - .on('click', '.identity-item .e-action', function () { - var oIdentityItem = ko.dataFor(this); - if (oIdentityItem) - { - self.editIdentity(oIdentityItem); - } - }) - ; - - _.delay(function () { - - var - oData = RL.data(), - f1 = Utils.settingsSaveHelperSimpleFunction(self.displayNameTrigger, self), - f2 = Utils.settingsSaveHelperSimpleFunction(self.replyTrigger, self), - f3 = Utils.settingsSaveHelperSimpleFunction(self.signatureTrigger, self) - ; - - oData.displayName.subscribe(function (sValue) { - RL.remote().saveSettings(f1, { - 'DisplayName': sValue - }); - }); - - oData.replyTo.subscribe(function (sValue) { - RL.remote().saveSettings(f2, { - 'ReplyTo': sValue - }); - }); - - oData.signature.subscribe(function (sValue) { - RL.remote().saveSettings(f3, { - 'Signature': sValue - }); - }); - - oData.signatureToAll.subscribe(function (bValue) { - RL.remote().saveSettings(null, { - 'SignatureToAll': bValue ? '1' : '0' - }); - }); - - }, 50); +ko.bindingHandlers.registrateBootstrapDropdown = { + 'init': function (oElement) { + BootstrapDropdowns.push($(oElement)); + } }; -/** - * @constructor - */ -function SettingsSecurity() -{ - this.processing = ko.observable(false); - this.clearing = ko.observable(false); - this.secreting = ko.observable(false); - - this.viewUser = ko.observable(''); - this.viewEnable = ko.observable(false); - this.viewEnable.subs = true; - this.twoFactorStatus = ko.observable(false); - - this.viewSecret = ko.observable(''); - this.viewBackupCodes = ko.observable(''); - this.viewUrl = ko.observable(''); - - this.bFirst = true; - - this.viewTwoFactorStatus = ko.computed(function () { - Globals.langChangeTrigger(); - return Utils.i18n( - this.twoFactorStatus() ? - 'SETTINGS_SECURITY/TWO_FACTOR_SECRET_CONFIGURED_DESC' : - 'SETTINGS_SECURITY/TWO_FACTOR_SECRET_NOT_CONFIGURED_DESC' - ); - }, this); - - this.onResult = _.bind(this.onResult, this); - this.onSecretResult = _.bind(this.onSecretResult, this); -} - -Utils.addSettingsViewModel(SettingsSecurity, 'SettingsSecurity', 'SETTINGS_LABELS/LABEL_SECURITY_NAME', 'security'); - -SettingsSecurity.prototype.showSecret = function () -{ - this.secreting(true); - RL.remote().showTwoFactorSecret(this.onSecretResult); -}; - -SettingsSecurity.prototype.hideSecret = function () -{ - this.viewSecret(''); - this.viewBackupCodes(''); - this.viewUrl(''); -}; - -SettingsSecurity.prototype.createTwoFactor = function () -{ - this.processing(true); - RL.remote().createTwoFactor(this.onResult); -}; - -SettingsSecurity.prototype.enableTwoFactor = function () -{ - this.processing(true); - RL.remote().enableTwoFactor(this.onResult, this.viewEnable()); -}; - -SettingsSecurity.prototype.testTwoFactor = function () -{ - kn.showScreenPopup(PopupsTwoFactorTestViewModel); -}; - -SettingsSecurity.prototype.clearTwoFactor = function () -{ - this.viewSecret(''); - this.viewBackupCodes(''); - this.viewUrl(''); - - this.clearing(true); - RL.remote().clearTwoFactor(this.onResult); -}; - -SettingsSecurity.prototype.onShow = function () -{ - this.viewSecret(''); - this.viewBackupCodes(''); - this.viewUrl(''); -}; - -SettingsSecurity.prototype.onResult = function (sResult, oData) -{ - this.processing(false); - this.clearing(false); - - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - this.viewUser(Utils.pString(oData.Result.User)); - this.viewEnable(!!oData.Result.Enable); - this.twoFactorStatus(!!oData.Result.IsSet); - - this.viewSecret(Utils.pString(oData.Result.Secret)); - this.viewBackupCodes(Utils.pString(oData.Result.BackupCodes).replace(/[\s]+/g, ' ')); - this.viewUrl(Utils.pString(oData.Result.Url)); - } - else - { - this.viewUser(''); - this.viewEnable(false); - this.twoFactorStatus(false); - - this.viewSecret(''); - this.viewBackupCodes(''); - this.viewUrl(''); - } - - if (this.bFirst) - { - this.bFirst = false; - var self = this; - this.viewEnable.subscribe(function (bValue) { - if (this.viewEnable.subs) - { - RL.remote().enableTwoFactor(function (sResult, oData) { - if (Enums.StorageResultType.Success !== sResult || !oData || !oData.Result) - { - self.viewEnable.subs = false; - self.viewEnable(false); - self.viewEnable.subs = true; - } - }, bValue); - } - }, this); - } -}; - -SettingsSecurity.prototype.onSecretResult = function (sResult, oData) -{ - this.secreting(false); - - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - this.viewSecret(Utils.pString(oData.Result.Secret)); - this.viewUrl(Utils.pString(oData.Result.Url)); - } - else - { - this.viewSecret(''); - this.viewUrl(''); - } -}; - -SettingsSecurity.prototype.onBuild = function () -{ - this.processing(true); - RL.remote().getTwoFactor(this.onResult); -}; -/** - * @constructor - */ -function SettingsSocialScreen() -{ - var oData = RL.data(); - - this.googleEnable = oData.googleEnable; - - this.googleActions = oData.googleActions; - this.googleLoggined = oData.googleLoggined; - this.googleUserName = oData.googleUserName; - - this.facebookEnable = oData.facebookEnable; - - this.facebookActions = oData.facebookActions; - this.facebookLoggined = oData.facebookLoggined; - this.facebookUserName = oData.facebookUserName; - - this.twitterEnable = oData.twitterEnable; - - this.twitterActions = oData.twitterActions; - this.twitterLoggined = oData.twitterLoggined; - this.twitterUserName = oData.twitterUserName; - - this.connectGoogle = Utils.createCommand(this, function () { - if (!this.googleLoggined()) - { - RL.googleConnect(); - } - }, function () { - return !this.googleLoggined() && !this.googleActions(); - }); - - this.disconnectGoogle = Utils.createCommand(this, function () { - RL.googleDisconnect(); - }); - - this.connectFacebook = Utils.createCommand(this, function () { - if (!this.facebookLoggined()) - { - RL.facebookConnect(); - } - }, function () { - return !this.facebookLoggined() && !this.facebookActions(); - }); - - this.disconnectFacebook = Utils.createCommand(this, function () { - RL.facebookDisconnect(); - }); - - this.connectTwitter = Utils.createCommand(this, function () { - if (!this.twitterLoggined()) - { - RL.twitterConnect(); - } - }, function () { - return !this.twitterLoggined() && !this.twitterActions(); - }); - - this.disconnectTwitter = Utils.createCommand(this, function () { - RL.twitterDisconnect(); - }); -} - -Utils.addSettingsViewModel(SettingsSocialScreen, 'SettingsSocial', 'SETTINGS_LABELS/LABEL_SOCIAL_NAME', 'social'); - -/** - * @constructor - */ -function SettingsChangePasswordScreen() -{ - this.changeProcess = ko.observable(false); - - this.errorDescription = ko.observable(''); - this.passwordMismatch = ko.observable(false); - this.passwordUpdateError = ko.observable(false); - this.passwordUpdateSuccess = ko.observable(false); - - this.currentPassword = ko.observable(''); - this.currentPassword.error = ko.observable(false); - this.newPassword = ko.observable(''); - this.newPassword2 = ko.observable(''); - - this.currentPassword.subscribe(function () { - this.passwordUpdateError(false); - this.passwordUpdateSuccess(false); - this.currentPassword.error(false); - }, this); - - this.newPassword.subscribe(function () { - this.passwordUpdateError(false); - this.passwordUpdateSuccess(false); - this.passwordMismatch(false); - }, this); - - this.newPassword2.subscribe(function () { - this.passwordUpdateError(false); - this.passwordUpdateSuccess(false); - this.passwordMismatch(false); - }, this); - - this.saveNewPasswordCommand = Utils.createCommand(this, function () { - - if (this.newPassword() !== this.newPassword2()) - { - this.passwordMismatch(true); - this.errorDescription(Utils.i18n('SETTINGS_CHANGE_PASSWORD/ERROR_PASSWORD_MISMATCH')); - } - else - { - this.changeProcess(true); - - this.passwordUpdateError(false); - this.passwordUpdateSuccess(false); - this.currentPassword.error(false); - this.passwordMismatch(false); - this.errorDescription(''); - - RL.remote().changePassword(this.onChangePasswordResponse, this.currentPassword(), this.newPassword()); - } - - }, function () { - return !this.changeProcess() && '' !== this.currentPassword() && - '' !== this.newPassword() && '' !== this.newPassword2(); - }); - - this.onChangePasswordResponse = _.bind(this.onChangePasswordResponse, this); -} - -Utils.addSettingsViewModel(SettingsChangePasswordScreen, 'SettingsChangePassword', 'SETTINGS_LABELS/LABEL_CHANGE_PASSWORD_NAME', 'change-password'); - -SettingsChangePasswordScreen.prototype.onHide = function () -{ - this.changeProcess(false); - this.currentPassword(''); - this.newPassword(''); - this.newPassword2(''); - this.errorDescription(''); - this.passwordMismatch(false); - this.currentPassword.error(false); -}; - -SettingsChangePasswordScreen.prototype.onChangePasswordResponse = function (sResult, oData) -{ - this.changeProcess(false); - this.passwordMismatch(false); - this.errorDescription(''); - this.currentPassword.error(false); - - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - this.currentPassword(''); - this.newPassword(''); - this.newPassword2(''); - - this.passwordUpdateSuccess(true); - this.currentPassword.error(false); - } - else - { - if (oData && Enums.Notification.CurrentPasswordIncorrect === oData.ErrorCode) - { - this.currentPassword.error(true); - } - - this.passwordUpdateError(true); - this.errorDescription(oData && oData.ErrorCode ? Utils.getNotification(oData.ErrorCode) : - Utils.getNotification(Enums.Notification.CouldNotSaveNewPassword)); - } -}; - -/** - * @constructor - */ -function SettingsFolders() -{ - var oData = RL.data(); - - this.foldersListError = oData.foldersListError; - this.folderList = oData.folderList; - - this.processText = ko.computed(function () { - - var - oData = RL.data(), - bLoading = oData.foldersLoading(), - bCreating = oData.foldersCreating(), - bDeleting = oData.foldersDeleting(), - bRenaming = oData.foldersRenaming() - ; - - if (bCreating) - { - return Utils.i18n('SETTINGS_FOLDERS/CREATING_PROCESS'); - } - else if (bDeleting) - { - return Utils.i18n('SETTINGS_FOLDERS/DELETING_PROCESS'); - } - else if (bRenaming) - { - return Utils.i18n('SETTINGS_FOLDERS/RENAMING_PROCESS'); - } - else if (bLoading) - { - return Utils.i18n('SETTINGS_FOLDERS/LOADING_PROCESS'); - } - - return ''; - - }, this); - - this.visibility = ko.computed(function () { - return '' === this.processText() ? 'hidden' : 'visible'; - }, this); - - this.folderForDeletion = ko.observable(null).extend({'falseTimeout': 3000}).extend({'toggleSubscribe': [this, - function (oPrev) { - if (oPrev) - { - oPrev.deleteAccess(false); - } - }, function (oNext) { - if (oNext) - { - oNext.deleteAccess(true); - } - } - ]}); - - this.folderForEdit = ko.observable(null).extend({'toggleSubscribe': [this, - function (oPrev) { - if (oPrev) - { - oPrev.edited(false); - } - }, function (oNext) { - if (oNext && oNext.canBeEdited()) - { - oNext.edited(true); - } - } - ]}); - - this.useImapSubscribe = !!RL.settingsGet('UseImapSubscribe'); -} - -Utils.addSettingsViewModel(SettingsFolders, 'SettingsFolders', 'SETTINGS_LABELS/LABEL_FOLDERS_NAME', 'folders'); - -SettingsFolders.prototype.folderEditOnEnter = function (oFolder) -{ - var sEditName = oFolder ? Utils.trim(oFolder.nameForEdit()) : ''; - if ('' !== sEditName && oFolder.name() !== sEditName) - { - RL.local().set(Enums.ClientSideKeyName.FoldersLashHash, ''); - - RL.data().foldersRenaming(true); - RL.remote().folderRename(function (sResult, oData) { - - RL.data().foldersRenaming(false); - if (Enums.StorageResultType.Success !== sResult || !oData || !oData.Result) - { - RL.data().foldersListError( - oData && oData.ErrorCode ? Utils.getNotification(oData.ErrorCode) : Utils.i18n('NOTIFICATIONS/CANT_RENAME_FOLDER')); - } - - RL.folders(); - - }, oFolder.fullNameRaw, sEditName); - - RL.cache().removeFolderFromCacheList(oFolder.fullNameRaw); - - oFolder.name(sEditName); - } - - oFolder.edited(false); -}; - -SettingsFolders.prototype.folderEditOnEsc = function (oFolder) -{ - if (oFolder) - { - oFolder.edited(false); - } -}; - -SettingsFolders.prototype.onShow = function () -{ - RL.data().foldersListError(''); -}; - -SettingsFolders.prototype.createFolder = function () -{ - kn.showScreenPopup(PopupsFolderCreateViewModel); -}; - -SettingsFolders.prototype.systemFolder = function () -{ - kn.showScreenPopup(PopupsFolderSystemViewModel); -}; - -SettingsFolders.prototype.deleteFolder = function (oFolderToRemove) -{ - if (oFolderToRemove && oFolderToRemove.canBeDeleted() && oFolderToRemove.deleteAccess() && - 0 === oFolderToRemove.privateMessageCountAll()) - { - this.folderForDeletion(null); - - var - fRemoveFolder = function (oFolder) { - - if (oFolderToRemove === oFolder) - { - return true; - } - - oFolder.subFolders.remove(fRemoveFolder); - return false; - } - ; - - if (oFolderToRemove) - { - RL.local().set(Enums.ClientSideKeyName.FoldersLashHash, ''); - - RL.data().folderList.remove(fRemoveFolder); - - RL.data().foldersDeleting(true); - RL.remote().folderDelete(function (sResult, oData) { - - RL.data().foldersDeleting(false); - if (Enums.StorageResultType.Success !== sResult || !oData || !oData.Result) - { - RL.data().foldersListError( - oData && oData.ErrorCode ? Utils.getNotification(oData.ErrorCode) : Utils.i18n('NOTIFICATIONS/CANT_DELETE_FOLDER')); - } - - RL.folders(); - - }, oFolderToRemove.fullNameRaw); - - RL.cache().removeFolderFromCacheList(oFolderToRemove.fullNameRaw); - } - } - else if (0 < oFolderToRemove.privateMessageCountAll()) - { - RL.data().foldersListError(Utils.getNotification(Enums.Notification.CantDeleteNonEmptyFolder)); - } -}; - -SettingsFolders.prototype.subscribeFolder = function (oFolder) -{ - RL.local().set(Enums.ClientSideKeyName.FoldersLashHash, ''); - RL.remote().folderSetSubscribe(Utils.emptyFunction, oFolder.fullNameRaw, true); - - oFolder.subScribed(true); -}; - -SettingsFolders.prototype.unSubscribeFolder = function (oFolder) -{ - RL.local().set(Enums.ClientSideKeyName.FoldersLashHash, ''); - RL.remote().folderSetSubscribe(Utils.emptyFunction, oFolder.fullNameRaw, false); - - oFolder.subScribed(false); -}; - -/** - * @constructor - */ -function SettingsThemes() -{ - var - self = this, - oData = RL.data() - ; - - this.mainTheme = oData.mainTheme; - this.themesObjects = ko.observableArray([]); - - this.themeTrigger = ko.observable(Enums.SaveSettingsStep.Idle).extend({'throttle': 100}); - - this.oLastAjax = null; - this.iTimer = 0; - - RL.data().theme.subscribe(function (sValue) { - - _.each(this.themesObjects(), function (oTheme) { - oTheme.selected(sValue === oTheme.name); - }); - - var - oThemeLink = $('#rlThemeLink'), - oThemeStyle = $('#rlThemeStyle'), - sUrl = oThemeLink.attr('href') - ; - - if (!sUrl) - { - sUrl = oThemeStyle.attr('data-href'); - } - - if (sUrl) - { - sUrl = sUrl.toString().replace(/\/-\/[^\/]+\/\-\//, '/-/' + sValue + '/-/'); - sUrl = sUrl.toString().replace(/\/Css\/[^\/]+\/User\//, '/Css/0/User/'); - - if ('Json/' !== sUrl.substring(sUrl.length - 5, sUrl.length)) - { - sUrl += 'Json/'; - } - - window.clearTimeout(self.iTimer); - self.themeTrigger(Enums.SaveSettingsStep.Animate); - - if (this.oLastAjax && this.oLastAjax.abort) - { - this.oLastAjax.abort(); - } - - this.oLastAjax = $.ajax({ - 'url': sUrl, - 'dataType': 'json' - }).done(function(aData) { - if (aData && Utils.isArray(aData) && 2 === aData.length) - { - if (oThemeLink && oThemeLink[0] && (!oThemeStyle || !oThemeStyle[0])) - { - oThemeStyle = $(''); - oThemeLink.after(oThemeStyle); - oThemeLink.remove(); - } - - if (oThemeStyle && oThemeStyle[0]) - { - oThemeStyle.attr('data-href', sUrl).attr('data-theme', aData[0]); - if (oThemeStyle && oThemeStyle[0] && oThemeStyle[0].styleSheet && !Utils.isUnd(oThemeStyle[0].styleSheet.cssText)) - { - oThemeStyle[0].styleSheet.cssText = aData[1]; - } - else - { - oThemeStyle.text(aData[1]); - } - } - - self.themeTrigger(Enums.SaveSettingsStep.TrueResult); - } - - }).always(function() { - - self.iTimer = window.setTimeout(function () { - self.themeTrigger(Enums.SaveSettingsStep.Idle); - }, 1000); - - self.oLastAjax = null; - }); - } - - RL.remote().saveSettings(null, { - 'Theme': sValue - }); - - }, this); -} - -Utils.addSettingsViewModel(SettingsThemes, 'SettingsThemes', 'SETTINGS_LABELS/LABEL_THEMES_NAME', 'themes'); - -SettingsThemes.prototype.onBuild = function () -{ - var sCurrentTheme = RL.data().theme(); - this.themesObjects(_.map(RL.data().themes(), function (sTheme) { - return { - 'name': sTheme, - 'nameDisplay': Utils.convertThemeName(sTheme), - 'selected': ko.observable(sTheme === sCurrentTheme), - 'themePreviewSrc': RL.link().themePreviewLink(sTheme) - }; - })); -}; - -/** - * @constructor - */ -function SettingsOpenPGP() -{ - this.openpgpkeys = RL.data().openpgpkeys; - this.openpgpkeysPublic = RL.data().openpgpkeysPublic; - this.openpgpkeysPrivate = RL.data().openpgpkeysPrivate; - - this.openPgpKeyForDeletion = ko.observable(null).extend({'falseTimeout': 3000}).extend({'toggleSubscribe': [this, - function (oPrev) { - if (oPrev) - { - oPrev.deleteAccess(false); - } - }, function (oNext) { - if (oNext) - { - oNext.deleteAccess(true); - } - } - ]}); -} - -Utils.addSettingsViewModel(SettingsOpenPGP, 'SettingsOpenPGP', 'SETTINGS_LABELS/LABEL_OPEN_PGP_NAME', 'openpgp'); - -SettingsOpenPGP.prototype.addOpenPgpKey = function () -{ - kn.showScreenPopup(PopupsAddOpenPgpKeyViewModel); -}; - -SettingsOpenPGP.prototype.generateOpenPgpKey = function () -{ - kn.showScreenPopup(PopupsGenerateNewOpenPgpKeyViewModel); -}; - -SettingsOpenPGP.prototype.viewOpenPgpKey = function (oOpenPgpKey) -{ - if (oOpenPgpKey) - { - kn.showScreenPopup(PopupsViewOpenPgpKeyViewModel, [oOpenPgpKey]); - } -}; - -/** - * @param {OpenPgpKeyModel} oOpenPgpKeyToRemove - */ -SettingsOpenPGP.prototype.deleteOpenPgpKey = function (oOpenPgpKeyToRemove) -{ - if (oOpenPgpKeyToRemove && oOpenPgpKeyToRemove.deleteAccess()) - { - this.openPgpKeyForDeletion(null); - - if (oOpenPgpKeyToRemove && RL.data().openpgpKeyring) - { - this.openpgpkeys.remove(function (oOpenPgpKey) { - return oOpenPgpKeyToRemove === oOpenPgpKey; - }); - - RL.data().openpgpKeyring[oOpenPgpKeyToRemove.isPrivate ? 'privateKeys' : 'publicKeys'] - .removeForId(oOpenPgpKeyToRemove.guid); - - RL.data().openpgpKeyring.store(); - - RL.reloadOpenPgpKeys(); - } - } +ko.bindingHandlers.openDropdownTrigger = { + 'update': function (oElement, fValueAccessor) { + if (ko.utils.unwrapObservable(fValueAccessor())) + { + var $el = $(oElement); + if (!$el.hasClass('open')) + { + $el.find('.dropdown-toggle').dropdown('toggle'); + Utils.detectDropdownVisibility(); + } + + fValueAccessor()(false); + } + } }; -/** - * @constructor - */ -function AbstractData() -{ - this.leftPanelDisabled = ko.observable(false); - this.useKeyboardShortcuts = ko.observable(true); - - this.keyScopeReal = ko.observable(Enums.KeyState.All); - this.keyScopeFake = ko.observable(Enums.KeyState.All); - - this.keyScope = ko.computed({ - 'owner': this, - 'read': function () { - return this.keyScopeFake(); - }, - 'write': function (sValue) { - - if (Enums.KeyState.Menu !== sValue) - { - if (Enums.KeyState.Compose === sValue) - { - Utils.disableKeyFilter(); - } - else - { - Utils.restoreKeyFilter(); - } - - this.keyScopeFake(sValue); - if (Globals.dropdownVisibility()) - { - sValue = Enums.KeyState.Menu; - } - } - - this.keyScopeReal(sValue); - } - }); - - this.keyScopeReal.subscribe(function (sValue) { -// window.console.log(sValue); - key.setScope(sValue); - }); - - this.leftPanelDisabled.subscribe(function (bValue) { - RL.pub('left-panel.' + (bValue ? 'off' : 'on')); - }); - - Globals.dropdownVisibility.subscribe(function (bValue) { - if (bValue) - { - this.keyScope(Enums.KeyState.Menu); - } - else if (Enums.KeyState.Menu === key.getScope()) - { - this.keyScope(this.keyScopeFake()); - } - }, this); - - Utils.initDataConstructorBySettings(this); -} - -AbstractData.prototype.populateDataOnStart = function() -{ - var - mLayout = Utils.pInt(RL.settingsGet('Layout')), - aLanguages = RL.settingsGet('Languages'), - aThemes = RL.settingsGet('Themes') - ; - - if (Utils.isArray(aLanguages)) - { - this.languages(aLanguages); - } - - if (Utils.isArray(aThemes)) - { - this.themes(aThemes); - } - - this.mainLanguage(RL.settingsGet('Language')); - this.mainTheme(RL.settingsGet('Theme')); - - this.allowAdditionalAccounts(!!RL.settingsGet('AllowAdditionalAccounts')); - this.allowIdentities(!!RL.settingsGet('AllowIdentities')); - this.allowGravatar(!!RL.settingsGet('AllowGravatar')); - this.determineUserLanguage(!!RL.settingsGet('DetermineUserLanguage')); - - this.allowThemes(!!RL.settingsGet('AllowThemes')); - this.allowCustomLogin(!!RL.settingsGet('AllowCustomLogin')); - this.allowLanguagesOnLogin(!!RL.settingsGet('AllowLanguagesOnLogin')); - this.allowLanguagesOnSettings(!!RL.settingsGet('AllowLanguagesOnSettings')); - - this.editorDefaultType(RL.settingsGet('EditorDefaultType')); - this.showImages(!!RL.settingsGet('ShowImages')); - this.contactsAutosave(!!RL.settingsGet('ContactsAutosave')); - this.interfaceAnimation(RL.settingsGet('InterfaceAnimation')); - - this.mainMessagesPerPage(RL.settingsGet('MPP')); - - this.desktopNotifications(!!RL.settingsGet('DesktopNotifications')); - this.useThreads(!!RL.settingsGet('UseThreads')); - this.replySameFolder(!!RL.settingsGet('ReplySameFolder')); - this.useCheckboxesInList(!!RL.settingsGet('UseCheckboxesInList')); - - this.layout(Enums.Layout.SidePreview); - if (-1 < Utils.inArray(mLayout, [Enums.Layout.NoPreview, Enums.Layout.SidePreview, Enums.Layout.BottomPreview])) - { - this.layout(mLayout); - } - - this.facebookEnable(!!RL.settingsGet('AllowFacebookSocial')); - this.facebookAppID(RL.settingsGet('FacebookAppID')); - this.facebookAppSecret(RL.settingsGet('FacebookAppSecret')); - - this.twitterEnable(!!RL.settingsGet('AllowTwitterSocial')); - this.twitterConsumerKey(RL.settingsGet('TwitterConsumerKey')); - this.twitterConsumerSecret(RL.settingsGet('TwitterConsumerSecret')); - - this.googleEnable(!!RL.settingsGet('AllowGoogleSocial')); - this.googleClientID(RL.settingsGet('GoogleClientID')); - this.googleClientSecret(RL.settingsGet('GoogleClientSecret')); - - this.dropboxEnable(!!RL.settingsGet('AllowDropboxSocial')); - this.dropboxApiKey(RL.settingsGet('DropboxApiKey')); - - this.contactsIsAllowed(!!RL.settingsGet('ContactsIsAllowed')); -}; -/** - * @constructor - * @extends AbstractData - */ -function WebMailDataStorage() -{ - AbstractData.call(this); - - var - fRemoveSystemFolderType = function (observable) { - return function () { - var oFolder = RL.cache().getFolderFromCacheList(observable()); - if (oFolder) - { - oFolder.type(Enums.FolderType.User); - } - }; - }, - fSetSystemFolderType = function (iType) { - return function (sValue) { - var oFolder = RL.cache().getFolderFromCacheList(sValue); - if (oFolder) - { - oFolder.type(iType); - } - }; - } - ; - - this.devEmail = ''; - this.devLogin = ''; - this.devPassword = ''; - - this.accountEmail = ko.observable(''); - this.accountIncLogin = ko.observable(''); - this.accountOutLogin = ko.observable(''); - this.projectHash = ko.observable(''); - this.threading = ko.observable(false); - - this.lastFoldersHash = ''; - this.remoteSuggestions = false; - - // system folders - this.sentFolder = ko.observable(''); - this.draftFolder = ko.observable(''); - this.spamFolder = ko.observable(''); - this.trashFolder = ko.observable(''); - this.archiveFolder = ko.observable(''); - - this.sentFolder.subscribe(fRemoveSystemFolderType(this.sentFolder), this, 'beforeChange'); - this.draftFolder.subscribe(fRemoveSystemFolderType(this.draftFolder), this, 'beforeChange'); - this.spamFolder.subscribe(fRemoveSystemFolderType(this.spamFolder), this, 'beforeChange'); - this.trashFolder.subscribe(fRemoveSystemFolderType(this.trashFolder), this, 'beforeChange'); - this.archiveFolder.subscribe(fRemoveSystemFolderType(this.archiveFolder), this, 'beforeChange'); - - this.sentFolder.subscribe(fSetSystemFolderType(Enums.FolderType.SentItems), this); - this.draftFolder.subscribe(fSetSystemFolderType(Enums.FolderType.Draft), this); - this.spamFolder.subscribe(fSetSystemFolderType(Enums.FolderType.Spam), this); - this.trashFolder.subscribe(fSetSystemFolderType(Enums.FolderType.Trash), this); - this.archiveFolder.subscribe(fSetSystemFolderType(Enums.FolderType.Archive), this); - - this.draftFolderNotEnabled = ko.computed(function () { - return '' === this.draftFolder() || Consts.Values.UnuseOptionValue === this.draftFolder(); - }, this); - - // personal - this.displayName = ko.observable(''); - this.signature = ko.observable(''); - this.signatureToAll = ko.observable(false); - this.replyTo = ko.observable(''); - - // security - this.enableTwoFactor = ko.observable(false); - - // accounts - this.accounts = ko.observableArray([]); - this.accountsLoading = ko.observable(false).extend({'throttle': 100}); - - // identities - this.identities = ko.observableArray([]); - this.identitiesLoading = ko.observable(false).extend({'throttle': 100}); - - // contacts - this.contacts = ko.observableArray([]); - this.contacts.loading = ko.observable(false).extend({'throttle': 200}); - this.contacts.importing = ko.observable(false).extend({'throttle': 200}); - this.contacts.syncing = ko.observable(false).extend({'throttle': 200}); - this.contacts.exportingVcf = ko.observable(false).extend({'throttle': 200}); - this.contacts.exportingCsv = ko.observable(false).extend({'throttle': 200}); - - this.allowContactsSync = ko.observable(false); - this.enableContactsSync = ko.observable(false); - this.contactsSyncUrl = ko.observable(''); - this.contactsSyncUser = ko.observable(''); - this.contactsSyncPass = ko.observable(''); - - this.allowContactsSync = ko.observable(!!RL.settingsGet('ContactsSyncIsAllowed')); - this.enableContactsSync = ko.observable(!!RL.settingsGet('EnableContactsSync')); - this.contactsSyncUrl = ko.observable(RL.settingsGet('ContactsSyncUrl')); - this.contactsSyncUser = ko.observable(RL.settingsGet('ContactsSyncUser')); - this.contactsSyncPass = ko.observable(RL.settingsGet('ContactsSyncPassword')); - - // folders - this.namespace = ''; - this.folderList = ko.observableArray([]); - this.folderList.focused = ko.observable(false); - - this.foldersListError = ko.observable(''); - - this.foldersLoading = ko.observable(false); - this.foldersCreating = ko.observable(false); - this.foldersDeleting = ko.observable(false); - this.foldersRenaming = ko.observable(false); - - this.foldersChanging = ko.computed(function () { - var - bLoading = this.foldersLoading(), - bCreating = this.foldersCreating(), - bDeleting = this.foldersDeleting(), - bRenaming = this.foldersRenaming() - ; - return bLoading || bCreating || bDeleting || bRenaming; - }, this); - - this.foldersInboxUnreadCount = ko.observable(0); - - this.currentFolder = ko.observable(null).extend({'toggleSubscribe': [null, - function (oPrev) { - if (oPrev) - { - oPrev.selected(false); - } - }, function (oNext) { - if (oNext) - { - oNext.selected(true); - } - } - ]}); - - this.currentFolderFullNameRaw = ko.computed(function () { - return this.currentFolder() ? this.currentFolder().fullNameRaw : ''; - }, this); - - this.currentFolderFullName = ko.computed(function () { - return this.currentFolder() ? this.currentFolder().fullName : ''; - }, this); - - this.currentFolderFullNameHash = ko.computed(function () { - return this.currentFolder() ? this.currentFolder().fullNameHash : ''; - }, this); - - this.currentFolderName = ko.computed(function () { - return this.currentFolder() ? this.currentFolder().name() : ''; - }, this); - - this.folderListSystemNames = ko.computed(function () { - - var - aList = ['INBOX'], - aFolders = this.folderList(), - sSentFolder = this.sentFolder(), - sDraftFolder = this.draftFolder(), - sSpamFolder = this.spamFolder(), - sTrashFolder = this.trashFolder(), - sArchiveFolder = this.archiveFolder() - ; - - if (Utils.isArray(aFolders) && 0 < aFolders.length) - { - if ('' !== sSentFolder && Consts.Values.UnuseOptionValue !== sSentFolder) - { - aList.push(sSentFolder); - } - if ('' !== sDraftFolder && Consts.Values.UnuseOptionValue !== sDraftFolder) - { - aList.push(sDraftFolder); - } - if ('' !== sSpamFolder && Consts.Values.UnuseOptionValue !== sSpamFolder) - { - aList.push(sSpamFolder); - } - if ('' !== sTrashFolder && Consts.Values.UnuseOptionValue !== sTrashFolder) - { - aList.push(sTrashFolder); - } - if ('' !== sArchiveFolder && Consts.Values.UnuseOptionValue !== sArchiveFolder) - { - aList.push(sArchiveFolder); - } - } - - return aList; - - }, this); - - this.folderListSystem = ko.computed(function () { - return _.compact(_.map(this.folderListSystemNames(), function (sName) { - return RL.cache().getFolderFromCacheList(sName); - })); - }, this); - - this.folderMenuForMove = ko.computed(function () { - return RL.folderListOptionsBuilder(this.folderListSystem(), this.folderList(), [ - this.currentFolderFullNameRaw() - ], null, null, null, null, function (oItem) { - return oItem ? oItem.localName() : ''; - }); - }, this); - - // message list - this.staticMessageList = []; - - this.messageList = ko.observableArray([]).extend({'rateLimit': 0}); - - this.messageListCount = ko.observable(0); - this.messageListSearch = ko.observable(''); - this.messageListPage = ko.observable(1); - - this.messageListThreadFolder = ko.observable(''); - this.messageListThreadUids = ko.observableArray([]); - - this.messageListThreadFolder.subscribe(function () { - this.messageListThreadUids([]); - }, this); - - this.messageListEndFolder = ko.observable(''); - this.messageListEndSearch = ko.observable(''); - this.messageListEndPage = ko.observable(1); - - this.messageListEndHash = ko.computed(function () { - return this.messageListEndFolder() + '|' + this.messageListEndSearch() + '|' + this.messageListEndPage(); - }, this); - - this.messageListPageCount = ko.computed(function () { - var iPage = Math.ceil(this.messageListCount() / this.messagesPerPage()); - return 0 >= iPage ? 1 : iPage; - }, this); - - this.mainMessageListSearch = ko.computed({ - 'read': this.messageListSearch, - 'write': function (sValue) { - kn.setHash(RL.link().mailBox( - this.currentFolderFullNameHash(), 1, Utils.trim(sValue.toString()) - )); - }, - 'owner': this - }); - - this.messageListError = ko.observable(''); - - this.messageListLoading = ko.observable(false); - this.messageListIsNotCompleted = ko.observable(false); - this.messageListCompleteLoadingThrottle = ko.observable(false).extend({'throttle': 200}); - - this.messageListCompleteLoading = ko.computed(function () { - var - bOne = this.messageListLoading(), - bTwo = this.messageListIsNotCompleted() - ; - return bOne || bTwo; - }, this); - - this.messageListCompleteLoading.subscribe(function (bValue) { - this.messageListCompleteLoadingThrottle(bValue); - }, this); - - this.messageList.subscribe(_.debounce(function (aList) { - _.each(aList, function (oItem) { - if (oItem.newForAnimation()) - { - oItem.newForAnimation(false); - } - }); - }, 500)); - - // message preview - this.staticMessageList = new MessageModel(); - this.message = ko.observable(null); - this.messageLoading = ko.observable(false); - this.messageLoadingThrottle = ko.observable(false).extend({'throttle': 50}); - - this.message.focused = ko.observable(false); - - this.message.subscribe(function (oMessage) { - if (!oMessage) - { - this.message.focused(false); - this.hideMessageBodies(); - - if (Enums.Layout.NoPreview === RL.data().layout() && - -1 < window.location.hash.indexOf('message-preview')) - { - RL.historyBack(); - } - } - else if (Enums.Layout.NoPreview === this.layout()) - { - this.message.focused(true); - } - }, this); - - this.message.focused.subscribe(function (bValue) { - if (bValue) - { - RL.data().folderList.focused(false); - RL.data().keyScope(Enums.KeyState.MessageView); - } - else if (Enums.KeyState.MessageView === RL.data().keyScope()) - { - RL.data().keyScope(Enums.KeyState.MessageList); - } - }); - - this.folderList.focused.subscribe(function (bValue) { - if (bValue) - { - RL.data().keyScope(Enums.KeyState.FolderList); - } - else if (Enums.KeyState.FolderList === RL.data().keyScope()) - { - RL.data().keyScope(Enums.KeyState.MessageList); - } - }); - - this.messageLoading.subscribe(function (bValue) { - this.messageLoadingThrottle(bValue); - }, this); - - this.messageFullScreenMode = ko.observable(false); - - this.messageError = ko.observable(''); - - this.messagesBodiesDom = ko.observable(null); - - this.messagesBodiesDom.subscribe(function (oDom) { - if (oDom && !(oDom instanceof jQuery)) - { - this.messagesBodiesDom($(oDom)); - } - }, this); - - this.messageActiveDom = ko.observable(null); - - this.isMessageSelected = ko.computed(function () { - return null !== this.message(); - }, this); - - this.currentMessage = ko.observable(null); - - this.messageListChecked = ko.computed(function () { - return _.filter(this.messageList(), function (oItem) { - return oItem.checked(); - }); - }, this).extend({'rateLimit': 0}); - - this.hasCheckedMessages = ko.computed(function () { - return 0 < this.messageListChecked().length; - }, this).extend({'rateLimit': 0}); - - this.messageListCheckedOrSelected = ko.computed(function () { - - var - aChecked = this.messageListChecked(), - oSelectedMessage = this.currentMessage() - ; - - return _.union(aChecked, oSelectedMessage ? [oSelectedMessage] : []); - - }, this); - - this.messageListCheckedOrSelectedUidsWithSubMails = ko.computed(function () { - var aList = []; - _.each(this.messageListCheckedOrSelected(), function (oMessage) { - if (oMessage) - { - aList.push(oMessage.uid); - if (0 < oMessage.threadsLen() && 0 === oMessage.parentUid() && oMessage.lastInCollapsedThread()) - { - aList = _.union(aList, oMessage.threads()); - } - } - }); - return aList; - }, this); - - // quota - this.userQuota = ko.observable(0); - this.userUsageSize = ko.observable(0); - this.userUsageProc = ko.computed(function () { - - var - iQuota = this.userQuota(), - iUsed = this.userUsageSize() - ; - - return 0 < iQuota ? Math.ceil((iUsed / iQuota) * 100) : 0; - - }, this); - - // other - this.allowOpenPGP = ko.observable(false); - this.openpgpkeys = ko.observableArray([]); - this.openpgpKeyring = null; - - this.openpgpkeysPublic = this.openpgpkeys.filter(function (oItem) { - return !!(oItem && !oItem.isPrivate); - }); - - this.openpgpkeysPrivate = this.openpgpkeys.filter(function (oItem) { - return !!(oItem && oItem.isPrivate); - }); - - // google - this.googleActions = ko.observable(false); - this.googleLoggined = ko.observable(false); - this.googleUserName = ko.observable(''); - - // facebook - this.facebookActions = ko.observable(false); - this.facebookLoggined = ko.observable(false); - this.facebookUserName = ko.observable(''); - - // twitter - this.twitterActions = ko.observable(false); - this.twitterLoggined = ko.observable(false); - this.twitterUserName = ko.observable(''); - - this.customThemeType = ko.observable(Enums.CustomThemeType.Light); - - this.purgeMessageBodyCacheThrottle = _.throttle(this.purgeMessageBodyCache, 1000 * 30); -} - -_.extend(WebMailDataStorage.prototype, AbstractData.prototype); - -WebMailDataStorage.prototype.purgeMessageBodyCache = function() -{ - var - iCount = 0, - oMessagesBodiesDom = null, - iEnd = Globals.iMessageBodyCacheCount - Consts.Values.MessageBodyCacheLimit - ; - - if (0 < iEnd) - { - oMessagesBodiesDom = this.messagesBodiesDom(); - if (oMessagesBodiesDom) - { - oMessagesBodiesDom.find('.rl-cache-class').each(function () { - var oItem = $(this); - if (iEnd > oItem.data('rl-cache-count')) - { - oItem.addClass('rl-cache-purge'); - iCount++; - } - }); - - if (0 < iCount) - { - _.delay(function () { - oMessagesBodiesDom.find('.rl-cache-purge').remove(); - }, 300); - } - } - } -}; - -WebMailDataStorage.prototype.populateDataOnStart = function() -{ - AbstractData.prototype.populateDataOnStart.call(this); - - this.accountEmail(RL.settingsGet('Email')); - this.accountIncLogin(RL.settingsGet('IncLogin')); - this.accountOutLogin(RL.settingsGet('OutLogin')); - this.projectHash(RL.settingsGet('ProjectHash')); - - this.displayName(RL.settingsGet('DisplayName')); - this.replyTo(RL.settingsGet('ReplyTo')); - this.signature(RL.settingsGet('Signature')); - this.signatureToAll(!!RL.settingsGet('SignatureToAll')); - this.enableTwoFactor(!!RL.settingsGet('EnableTwoFactor')); - - this.lastFoldersHash = RL.local().get(Enums.ClientSideKeyName.FoldersLashHash) || ''; - - this.remoteSuggestions = !!RL.settingsGet('RemoteSuggestions'); - - this.devEmail = RL.settingsGet('DevEmail'); - this.devLogin = RL.settingsGet('DevLogin'); - this.devPassword = RL.settingsGet('DevPassword'); -}; - -WebMailDataStorage.prototype.initUidNextAndNewMessages = function (sFolder, sUidNext, aNewMessages) -{ - if ('INBOX' === sFolder && Utils.isNormal(sUidNext) && sUidNext !== '') - { - if (Utils.isArray(aNewMessages) && 0 < aNewMessages.length) - { - var - oCache = RL.cache(), - iIndex = 0, - iLen = aNewMessages.length, - fNotificationHelper = function (sImageSrc, sTitle, sText) - { - var oNotification = null; - if (NotificationClass && RL.data().useDesktopNotifications()) - { - oNotification = new NotificationClass(sTitle, { - 'body': sText, - 'icon': sImageSrc - }); - - if (oNotification) - { - if (oNotification.show) - { - oNotification.show(); - } - - window.setTimeout((function (oLocalNotifications) { - return function () { - if (oLocalNotifications.cancel) - { - oLocalNotifications.cancel(); - } - else if (oLocalNotifications.close) - { - oLocalNotifications.close(); - } - }; - }(oNotification)), 7000); - } - } - } - ; - - _.each(aNewMessages, function (oItem) { - oCache.addNewMessageCache(sFolder, oItem.Uid); - }); - - if (3 < iLen) - { - fNotificationHelper( - RL.link().notificationMailIcon(), - RL.data().accountEmail(), - Utils.i18n('MESSAGE_LIST/NEW_MESSAGE_NOTIFICATION', { - 'COUNT': iLen - }) - ); - } - else - { - for (; iIndex < iLen; iIndex++) - { - fNotificationHelper( - RL.link().notificationMailIcon(), - MessageModel.emailsToLine(MessageModel.initEmailsFromJson(aNewMessages[iIndex].From), false), - aNewMessages[iIndex].Subject - ); - } - } - } - - RL.cache().setFolderUidNext(sFolder, sUidNext); - } -}; - -/** - * @param {string} sNamespace - * @param {Array} aFolders - * @return {Array} - */ -WebMailDataStorage.prototype.folderResponseParseRec = function (sNamespace, aFolders) -{ - var - iIndex = 0, - iLen = 0, - oFolder = null, - oCacheFolder = null, - sFolderFullNameRaw = '', - aSubFolders = [], - aList = [] - ; - - for (iIndex = 0, iLen = aFolders.length; iIndex < iLen; iIndex++) - { - oFolder = aFolders[iIndex]; - if (oFolder) - { - sFolderFullNameRaw = oFolder.FullNameRaw; - - oCacheFolder = RL.cache().getFolderFromCacheList(sFolderFullNameRaw); - if (!oCacheFolder) - { - oCacheFolder = FolderModel.newInstanceFromJson(oFolder); - if (oCacheFolder) - { - RL.cache().setFolderToCacheList(sFolderFullNameRaw, oCacheFolder); - RL.cache().setFolderFullNameRaw(oCacheFolder.fullNameHash, sFolderFullNameRaw); - } - } - - if (oCacheFolder) - { - oCacheFolder.collapsed(!Utils.isFolderExpanded(oCacheFolder.fullNameHash)); - - if (oFolder.Extended) - { - if (oFolder.Extended.Hash) - { - RL.cache().setFolderHash(oCacheFolder.fullNameRaw, oFolder.Extended.Hash); - } - - if (Utils.isNormal(oFolder.Extended.MessageCount)) - { - oCacheFolder.messageCountAll(oFolder.Extended.MessageCount); - } - - if (Utils.isNormal(oFolder.Extended.MessageUnseenCount)) - { - oCacheFolder.messageCountUnread(oFolder.Extended.MessageUnseenCount); - } - } - - aSubFolders = oFolder['SubFolders']; - if (aSubFolders && 'Collection/FolderCollection' === aSubFolders['@Object'] && - aSubFolders['@Collection'] && Utils.isArray(aSubFolders['@Collection'])) - { - oCacheFolder.subFolders( - this.folderResponseParseRec(sNamespace, aSubFolders['@Collection'])); - } - - aList.push(oCacheFolder); - } - } - } - - return aList; -}; - -/** - * @param {*} oData - */ -WebMailDataStorage.prototype.setFolders = function (oData) -{ - var - aList = [], - bUpdate = false, - oRLData = RL.data(), - fNormalizeFolder = function (sFolderFullNameRaw) { - return ('' === sFolderFullNameRaw || Consts.Values.UnuseOptionValue === sFolderFullNameRaw || - null !== RL.cache().getFolderFromCacheList(sFolderFullNameRaw)) ? sFolderFullNameRaw : ''; - } - ; - - if (oData && oData.Result && 'Collection/FolderCollection' === oData.Result['@Object'] && - oData.Result['@Collection'] && Utils.isArray(oData.Result['@Collection'])) - { - if (!Utils.isUnd(oData.Result.Namespace)) - { - oRLData.namespace = oData.Result.Namespace; - } - - this.threading(!!RL.settingsGet('UseImapThread') && oData.Result.IsThreadsSupported && true); - - aList = this.folderResponseParseRec(oRLData.namespace, oData.Result['@Collection']); - oRLData.folderList(aList); - - if (oData.Result['SystemFolders'] && - '' === '' + RL.settingsGet('SentFolder') + RL.settingsGet('DraftFolder') + - RL.settingsGet('SpamFolder') + RL.settingsGet('TrashFolder') + RL.settingsGet('ArchiveFolder') + - RL.settingsGet('NullFolder')) - { - // TODO Magic Numbers - RL.settingsSet('SentFolder', oData.Result['SystemFolders'][2] || null); - RL.settingsSet('DraftFolder', oData.Result['SystemFolders'][3] || null); - RL.settingsSet('SpamFolder', oData.Result['SystemFolders'][4] || null); - RL.settingsSet('TrashFolder', oData.Result['SystemFolders'][5] || null); - RL.settingsSet('ArchiveFolder', oData.Result['SystemFolders'][12] || null); - - bUpdate = true; - } - - oRLData.sentFolder(fNormalizeFolder(RL.settingsGet('SentFolder'))); - oRLData.draftFolder(fNormalizeFolder(RL.settingsGet('DraftFolder'))); - oRLData.spamFolder(fNormalizeFolder(RL.settingsGet('SpamFolder'))); - oRLData.trashFolder(fNormalizeFolder(RL.settingsGet('TrashFolder'))); - oRLData.archiveFolder(fNormalizeFolder(RL.settingsGet('ArchiveFolder'))); - - if (bUpdate) - { - RL.remote().saveSystemFolders(Utils.emptyFunction, { - 'SentFolder': oRLData.sentFolder(), - 'DraftFolder': oRLData.draftFolder(), - 'SpamFolder': oRLData.spamFolder(), - 'TrashFolder': oRLData.trashFolder(), - 'ArchiveFolder': oRLData.archiveFolder(), - 'NullFolder': 'NullFolder' - }); - } - - RL.local().set(Enums.ClientSideKeyName.FoldersLashHash, oData.Result.FoldersHash); - } -}; - -WebMailDataStorage.prototype.hideMessageBodies = function () -{ - var oMessagesBodiesDom = this.messagesBodiesDom(); - if (oMessagesBodiesDom) - { - oMessagesBodiesDom.find('.b-text-part').hide(); - } -}; - -/** - * @param {boolean=} bBoot = false - * @returns {Array} - */ -WebMailDataStorage.prototype.getNextFolderNames = function (bBoot) -{ - bBoot = Utils.isUnd(bBoot) ? false : !!bBoot; - - var - aResult = [], - iLimit = 10, - iUtc = moment().unix(), - iTimeout = iUtc - 60 * 5, - aTimeouts = [], - fSearchFunction = function (aList) { - _.each(aList, function (oFolder) { - if (oFolder && 'INBOX' !== oFolder.fullNameRaw && - oFolder.selectable && oFolder.existen && - iTimeout > oFolder.interval && - (!bBoot || oFolder.subScribed())) - { - aTimeouts.push([oFolder.interval, oFolder.fullNameRaw]); - } - - if (oFolder && 0 < oFolder.subFolders().length) - { - fSearchFunction(oFolder.subFolders()); - } - }); - } - ; - - fSearchFunction(this.folderList()); - - aTimeouts.sort(function(a, b) { - if (a[0] < b[0]) - { - return -1; - } - else if (a[0] > b[0]) - { - return 1; - } - - return 0; - }); - - _.find(aTimeouts, function (aItem) { - var oFolder = RL.cache().getFolderFromCacheList(aItem[1]); - if (oFolder) - { - oFolder.interval = iUtc; - aResult.push(aItem[1]); - } - - return iLimit <= aResult.length; - }); - - return _.uniq(aResult); -}; - -/** - * @param {string} sFromFolderFullNameRaw - * @param {Array} aUidForRemove - * @param {string=} sToFolderFullNameRaw = '' - * @param {bCopy=} bCopy = false - */ -WebMailDataStorage.prototype.removeMessagesFromList = function ( - sFromFolderFullNameRaw, aUidForRemove, sToFolderFullNameRaw, bCopy) -{ - sToFolderFullNameRaw = Utils.isNormal(sToFolderFullNameRaw) ? sToFolderFullNameRaw : ''; - bCopy = Utils.isUnd(bCopy) ? false : !!bCopy; - - aUidForRemove = _.map(aUidForRemove, function (mValue) { - return Utils.pInt(mValue); - }); - - var - iUnseenCount = 0, - oData = RL.data(), - oCache = RL.cache(), - aMessageList = oData.messageList(), - oFromFolder = RL.cache().getFolderFromCacheList(sFromFolderFullNameRaw), - oToFolder = '' === sToFolderFullNameRaw ? null : oCache.getFolderFromCacheList(sToFolderFullNameRaw || ''), - sCurrentFolderFullNameRaw = oData.currentFolderFullNameRaw(), - oCurrentMessage = oData.message(), - aMessages = sCurrentFolderFullNameRaw === sFromFolderFullNameRaw ? _.filter(aMessageList, function (oMessage) { - return oMessage && -1 < Utils.inArray(Utils.pInt(oMessage.uid), aUidForRemove); - }) : [] - ; - - _.each(aMessages, function (oMessage) { - if (oMessage && oMessage.unseen()) - { - iUnseenCount++; - } - }); - - if (oFromFolder && !bCopy) - { - oFromFolder.messageCountAll(0 <= oFromFolder.messageCountAll() - aUidForRemove.length ? - oFromFolder.messageCountAll() - aUidForRemove.length : 0); - - if (0 < iUnseenCount) - { - oFromFolder.messageCountUnread(0 <= oFromFolder.messageCountUnread() - iUnseenCount ? - oFromFolder.messageCountUnread() - iUnseenCount : 0); - } - } - - if (oToFolder) - { - oToFolder.messageCountAll(oToFolder.messageCountAll() + aUidForRemove.length); - if (0 < iUnseenCount) - { - oToFolder.messageCountUnread(oToFolder.messageCountUnread() + iUnseenCount); - } - - oToFolder.actionBlink(true); - } - - if (0 < aMessages.length) - { - if (bCopy) - { - _.each(aMessages, function (oMessage) { - oMessage.checked(false); - }); - } - else - { - oData.messageListIsNotCompleted(true); - - _.each(aMessages, function (oMessage) { - if (oCurrentMessage && oCurrentMessage.hash === oMessage.hash) - { - oCurrentMessage = null; - oData.message(null); - } - - oMessage.deleted(true); - }); - - _.delay(function () { - _.each(aMessages, function (oMessage) { - oData.messageList.remove(oMessage); - }); - }, 400); - } - } - - if ('' !== sFromFolderFullNameRaw) - { - oCache.setFolderHash(sFromFolderFullNameRaw, ''); - } - - if ('' !== sToFolderFullNameRaw) - { - oCache.setFolderHash(sToFolderFullNameRaw, ''); - } -}; - -WebMailDataStorage.prototype.setMessage = function (oData, bCached) -{ - var - bIsHtml = false, - bHasExternals = false, - bHasInternals = false, - oBody = null, - oTextBody = null, - sId = '', - sPlain = '', - bPgpSigned = false, - bPgpEncrypted = false, - oMessagesBodiesDom = this.messagesBodiesDom(), - oMessage = this.message() - ; - - if (oData && oMessage && oData.Result && 'Object/Message' === oData.Result['@Object'] && - oMessage.folderFullNameRaw === oData.Result.Folder && oMessage.uid === oData.Result.Uid) - { - this.messageError(''); - - oMessage.initUpdateByMessageJson(oData.Result); - RL.cache().addRequestedMessage(oMessage.folderFullNameRaw, oMessage.uid); - - if (!bCached) - { - oMessage.initFlagsByJson(oData.Result); - } - - oMessagesBodiesDom = oMessagesBodiesDom && oMessagesBodiesDom[0] ? oMessagesBodiesDom : null; - if (oMessagesBodiesDom) - { - sId = 'rl-mgs-' + oMessage.hash.replace(/[^a-zA-Z0-9]/g, ''); - oTextBody = oMessagesBodiesDom.find('#' + sId); - if (!oTextBody || !oTextBody[0]) - { - bHasExternals = !!oData.Result.HasExternals; - bHasInternals = !!oData.Result.HasInternals; - - oBody = $('').hide().addClass('rl-cache-class'); - oBody.data('rl-cache-count', ++Globals.iMessageBodyCacheCount); - - if (Utils.isNormal(oData.Result.Html) && '' !== oData.Result.Html) - { - bIsHtml = true; - oBody.html(oData.Result.Html.toString()).addClass('b-text-part html'); - } - else if (Utils.isNormal(oData.Result.Plain) && '' !== oData.Result.Plain) - { - bIsHtml = false; - sPlain = oData.Result.Plain.toString(); - - if ((oMessage.isPgpSigned() || oMessage.isPgpEncrypted()) && - RL.data().allowOpenPGP() && - Utils.isNormal(oData.Result.PlainRaw)) - { - oMessage.plainRaw = Utils.pString(oData.Result.PlainRaw); - - bPgpEncrypted = /---BEGIN PGP MESSAGE---/.test(oMessage.plainRaw); - if (!bPgpEncrypted) - { - bPgpSigned = /-----BEGIN PGP SIGNED MESSAGE-----/.test(oMessage.plainRaw) && - /-----BEGIN PGP SIGNATURE-----/.test(oMessage.plainRaw); - } - - $proxyDiv.empty(); - if (bPgpSigned && oMessage.isPgpSigned()) - { - sPlain = - $proxyDiv.append( - $('').text(oMessage.plainRaw) - ).html() - ; - } - else if (bPgpEncrypted && oMessage.isPgpEncrypted()) - { - sPlain = - $proxyDiv.append( - $('').text(oMessage.plainRaw) - ).html() - ; - } - - $proxyDiv.empty(); - - oMessage.isPgpSigned(bPgpSigned); - oMessage.isPgpEncrypted(bPgpEncrypted); - } - - oBody.html(sPlain).addClass('b-text-part plain'); - } - else - { - bIsHtml = false; - } - - oMessage.isHtml(!!bIsHtml); - oMessage.hasImages(!!bHasExternals); - oMessage.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.None); - oMessage.pgpSignedVerifyUser(''); - - if (oData.Result.Rtl) - { - oMessage.isRtl(true); - oBody.addClass('rtl-text-part'); - } - - oMessage.body = oBody; - if (oMessage.body) - { - oMessagesBodiesDom.append(oMessage.body); - } - - oMessage.storeDataToDom(); - - if (bHasInternals) - { - oMessage.showInternalImages(true); - } - - if (oMessage.hasImages() && this.showImages()) - { - oMessage.showExternalImages(true); - } - - this.purgeMessageBodyCacheThrottle(); - } - else - { - oMessage.body = oTextBody; - if (oMessage.body) - { - oMessage.body.data('rl-cache-count', ++Globals.iMessageBodyCacheCount); - oMessage.fetchDataToDom(); - } - } - - this.messageActiveDom(oMessage.body); - - this.hideMessageBodies(); - oMessage.body.show(); - - if (oBody) - { - Utils.initBlockquoteSwitcher(oBody); - } - } - - RL.cache().initMessageFlagsFromCache(oMessage); - if (oMessage.unseen()) - { - RL.setMessageSeen(oMessage); - } - - Utils.windowResize(); - } -}; - -/** - * @param {Array} aList - * @returns {string} - */ -WebMailDataStorage.prototype.calculateMessageListHash = function (aList) -{ - return _.map(aList, function (oMessage) { - return '' + oMessage.hash + '_' + oMessage.threadsLen() + '_' + oMessage.flagHash(); - }).join('|'); -}; - -WebMailDataStorage.prototype.setMessageList = function (oData, bCached) -{ - if (oData && oData.Result && 'Collection/MessageCollection' === oData.Result['@Object'] && - oData.Result['@Collection'] && Utils.isArray(oData.Result['@Collection'])) - { - var - oRainLoopData = RL.data(), - oCache = RL.cache(), - mLastCollapsedThreadUids = null, - iIndex = 0, - iLen = 0, - iCount = 0, - iOffset = 0, - aList = [], - iUtc = moment().unix(), - aStaticList = oRainLoopData.staticMessageList, - oJsonMessage = null, - oMessage = null, - oFolder = null, - iNewCount = 0, - bUnreadCountChange = false - ; - - iCount = Utils.pInt(oData.Result.MessageResultCount); - iOffset = Utils.pInt(oData.Result.Offset); - - if (Utils.isNonEmptyArray(oData.Result.LastCollapsedThreadUids)) - { - mLastCollapsedThreadUids = oData.Result.LastCollapsedThreadUids; - } - - oFolder = RL.cache().getFolderFromCacheList( - Utils.isNormal(oData.Result.Folder) ? oData.Result.Folder : ''); - - if (oFolder && !bCached) - { - oFolder.interval = iUtc; - - RL.cache().setFolderHash(oData.Result.Folder, oData.Result.FolderHash); - - if (Utils.isNormal(oData.Result.MessageCount)) - { - oFolder.messageCountAll(oData.Result.MessageCount); - } - - if (Utils.isNormal(oData.Result.MessageUnseenCount)) - { - if (Utils.pInt(oFolder.messageCountUnread()) !== Utils.pInt(oData.Result.MessageUnseenCount)) - { - bUnreadCountChange = true; - } - - oFolder.messageCountUnread(oData.Result.MessageUnseenCount); - } - - this.initUidNextAndNewMessages(oFolder.fullNameRaw, oData.Result.UidNext, oData.Result.NewMessages); - } - - if (bUnreadCountChange && oFolder) - { - RL.cache().clearMessageFlagsFromCacheByFolder(oFolder.fullNameRaw); - } - - for (iIndex = 0, iLen = oData.Result['@Collection'].length; iIndex < iLen; iIndex++) - { - oJsonMessage = oData.Result['@Collection'][iIndex]; - if (oJsonMessage && 'Object/Message' === oJsonMessage['@Object']) - { - oMessage = aStaticList[iIndex]; - if (!oMessage || !oMessage.initByJson(oJsonMessage)) - { - oMessage = MessageModel.newInstanceFromJson(oJsonMessage); - } - - if (oMessage) - { - if (oCache.hasNewMessageAndRemoveFromCache(oMessage.folderFullNameRaw, oMessage.uid) && 5 >= iNewCount) - { - iNewCount++; - oMessage.newForAnimation(true); - } - - oMessage.deleted(false); - - if (bCached) - { - RL.cache().initMessageFlagsFromCache(oMessage); - } - else - { - RL.cache().storeMessageFlagsToCache(oMessage); - } - - oMessage.lastInCollapsedThread(mLastCollapsedThreadUids && -1 < Utils.inArray(Utils.pInt(oMessage.uid), mLastCollapsedThreadUids) ? true : false); - - aList.push(oMessage); - } - } - } - - oRainLoopData.messageListCount(iCount); - oRainLoopData.messageListSearch(Utils.isNormal(oData.Result.Search) ? oData.Result.Search : ''); - oRainLoopData.messageListPage(Math.ceil((iOffset / oRainLoopData.messagesPerPage()) + 1)); - oRainLoopData.messageListEndFolder(Utils.isNormal(oData.Result.Folder) ? oData.Result.Folder : ''); - oRainLoopData.messageListEndSearch(Utils.isNormal(oData.Result.Search) ? oData.Result.Search : ''); - oRainLoopData.messageListEndPage(oRainLoopData.messageListPage()); - - oRainLoopData.messageList(aList); - oRainLoopData.messageListIsNotCompleted(false); - - if (aStaticList.length < aList.length) - { - oRainLoopData.staticMessageList = aList; - } - - oCache.clearNewMessageCache(); - - if (oFolder && (bCached || bUnreadCountChange || RL.data().useThreads())) - { - RL.folderInformation(oFolder.fullNameRaw, aList); - } - } - else - { - RL.data().messageListCount(0); - RL.data().messageList([]); - RL.data().messageListError(Utils.getNotification( - oData && oData.ErrorCode ? oData.ErrorCode : Enums.Notification.CantGetMessageList - )); - } -}; - -WebMailDataStorage.prototype.findPublicKeyByHex = function (sHash) -{ - return _.find(this.openpgpkeysPublic(), function (oItem) { - return oItem && sHash === oItem.id; - }); -}; - -WebMailDataStorage.prototype.findPublicKeysByEmail = function (sEmail) -{ - return _.compact(_.map(this.openpgpkeysPublic(), function (oItem) { - - var oKey = null; - if (oItem && sEmail === oItem.email) - { - try - { - oKey = window.openpgp.key.readArmored(oItem.armor); - if (oKey && !oKey.err && oKey.keys && oKey.keys[0]) - { - return oKey.keys[0]; - } - } - catch (e) {} - } - - return null; - - })); -}; - -/** - * @param {string} sEmail - * @param {string=} sPassword - * @returns {?} - */ -WebMailDataStorage.prototype.findPrivateKeyByEmail = function (sEmail, sPassword) -{ - var - oPrivateKey = null, - oKey = _.find(this.openpgpkeysPrivate(), function (oItem) { - return oItem && sEmail === oItem.email; - }) - ; - - if (oKey) - { - try - { - oPrivateKey = window.openpgp.key.readArmored(oKey.armor); - if (oPrivateKey && !oPrivateKey.err && oPrivateKey.keys && oPrivateKey.keys[0]) - { - oPrivateKey = oPrivateKey.keys[0]; - oPrivateKey.decrypt(Utils.pString(sPassword)); - } - else - { - oPrivateKey = null; - } - } - catch (e) - { - oPrivateKey = null; - } - } - - return oPrivateKey; -}; - -/** - * @param {string=} sPassword - * @returns {?} - */ -WebMailDataStorage.prototype.findSelfPrivateKey = function (sPassword) -{ - return this.findPrivateKeyByEmail(this.accountEmail(), sPassword); -}; - -/** - * @constructor - */ -function AbstractAjaxRemoteStorage() -{ - this.oRequests = {}; -} - -AbstractAjaxRemoteStorage.prototype.oRequests = {}; - -/** - * @param {?Function} fCallback - * @param {string} sRequestAction - * @param {string} sType - * @param {?AjaxJsonDefaultResponse} oData - * @param {boolean} bCached - * @param {*=} oRequestParameters - */ -AbstractAjaxRemoteStorage.prototype.defaultResponse = function (fCallback, sRequestAction, sType, oData, bCached, oRequestParameters) -{ - var - fCall = function () { - if (Enums.StorageResultType.Success !== sType && Globals.bUnload) - { - sType = Enums.StorageResultType.Unload; - } - - if (Enums.StorageResultType.Success === sType && oData && !oData.Result) - { - if (oData && -1 < Utils.inArray(oData.ErrorCode, [ - Enums.Notification.AuthError, Enums.Notification.AccessError, - Enums.Notification.ConnectionError, Enums.Notification.DomainNotAllowed, Enums.Notification.AccountNotAllowed, - Enums.Notification.MailServerError, Enums.Notification.UnknownNotification, Enums.Notification.UnknownError - ])) - { - Globals.iAjaxErrorCount++; - } - - if (oData && Enums.Notification.InvalidToken === oData.ErrorCode) - { - Globals.iTokenErrorCount++; - } - - if (Consts.Values.TokenErrorLimit < Globals.iTokenErrorCount) - { - RL.loginAndLogoutReload(true); - } - - if (oData.Logout || Consts.Values.AjaxErrorLimit < Globals.iAjaxErrorCount) - { - if (window.__rlah_clear) - { - window.__rlah_clear(); - } - - RL.loginAndLogoutReload(true); - } - } - else if (Enums.StorageResultType.Success === sType && oData && oData.Result) - { - Globals.iAjaxErrorCount = 0; - Globals.iTokenErrorCount = 0; - } - - if (fCallback) - { - Plugins.runHook('ajax-default-response', [sRequestAction, Enums.StorageResultType.Success === sType ? oData : null, sType, bCached, oRequestParameters]); - - fCallback( - sType, - Enums.StorageResultType.Success === sType ? oData : null, - bCached, - sRequestAction, - oRequestParameters - ); - } - } - ; - - switch (sType) - { - case 'success': - sType = Enums.StorageResultType.Success; - break; - case 'abort': - sType = Enums.StorageResultType.Abort; - break; - default: - sType = Enums.StorageResultType.Error; - break; - } - - if (Enums.StorageResultType.Error === sType) - { - _.delay(fCall, 300); - } - else - { - fCall(); - } -}; - -/** - * @param {?Function} fResultCallback - * @param {Object} oParameters - * @param {?number=} iTimeOut = 20000 - * @param {string=} sGetAdd = '' - * @param {Array=} aAbortActions = [] - * @return {jQuery.jqXHR} - */ -AbstractAjaxRemoteStorage.prototype.ajaxRequest = function (fResultCallback, oParameters, iTimeOut, sGetAdd, aAbortActions) -{ - var - self = this, - bPost = '' === sGetAdd, - oHeaders = {}, - iStart = (new window.Date()).getTime(), - oDefAjax = null, - sAction = '' - ; - - oParameters = oParameters || {}; - iTimeOut = Utils.isNormal(iTimeOut) ? iTimeOut : 20000; - sGetAdd = Utils.isUnd(sGetAdd) ? '' : Utils.pString(sGetAdd); - aAbortActions = Utils.isArray(aAbortActions) ? aAbortActions : []; - - sAction = oParameters.Action || ''; - - if (sAction && 0 < aAbortActions.length) - { - _.each(aAbortActions, function (sActionToAbort) { - if (self.oRequests[sActionToAbort]) - { - self.oRequests[sActionToAbort].__aborted = true; - if (self.oRequests[sActionToAbort].abort) - { - self.oRequests[sActionToAbort].abort(); - } - self.oRequests[sActionToAbort] = null; - } - }); - } - - if (bPost) - { - oParameters['XToken'] = RL.settingsGet('Token'); - } - - oDefAjax = $.ajax({ - 'type': bPost ? 'POST' : 'GET', - 'url': RL.link().ajax(sGetAdd) , - 'async': true, - 'dataType': 'json', - 'data': bPost ? oParameters : {}, - 'headers': oHeaders, - 'timeout': iTimeOut, - 'global': true - }); - - oDefAjax.always(function (oData, sType) { - - var bCached = false; - if (oData && oData['Time']) - { - bCached = Utils.pInt(oData['Time']) > (new window.Date()).getTime() - iStart; - } - - if (sAction && self.oRequests[sAction]) - { - if (self.oRequests[sAction].__aborted) - { - sType = 'abort'; - } - - self.oRequests[sAction] = null; - } - - self.defaultResponse(fResultCallback, sAction, sType, oData, bCached, oParameters); - }); - - if (sAction && 0 < aAbortActions.length && -1 < Utils.inArray(sAction, aAbortActions)) - { - if (this.oRequests[sAction]) - { - this.oRequests[sAction].__aborted = true; - if (this.oRequests[sAction].abort) - { - this.oRequests[sAction].abort(); - } - this.oRequests[sAction] = null; - } - - this.oRequests[sAction] = oDefAjax; - } - - return oDefAjax; -}; - -/** - * @param {?Function} fCallback - * @param {string} sAction - * @param {Object=} oParameters - * @param {?number=} iTimeout - * @param {string=} sGetAdd = '' - * @param {Array=} aAbortActions = [] - */ -AbstractAjaxRemoteStorage.prototype.defaultRequest = function (fCallback, sAction, oParameters, iTimeout, sGetAdd, aAbortActions) -{ - oParameters = oParameters || {}; - oParameters.Action = sAction; - - sGetAdd = Utils.pString(sGetAdd); - - Plugins.runHook('ajax-default-request', [sAction, oParameters, sGetAdd]); - - this.ajaxRequest(fCallback, oParameters, - Utils.isUnd(iTimeout) ? Consts.Defaults.DefaultAjaxTimeout : Utils.pInt(iTimeout), sGetAdd, aAbortActions); -}; - -/** - * @param {?Function} fCallback - */ -AbstractAjaxRemoteStorage.prototype.noop = function (fCallback) -{ - this.defaultRequest(fCallback, 'Noop'); -}; - -/** - * @param {?Function} fCallback - * @param {string} sMessage - * @param {string} sFileName - * @param {number} iLineNo - * @param {string} sLocation - * @param {string} sHtmlCapa - * @param {number} iTime - */ -AbstractAjaxRemoteStorage.prototype.jsError = function (fCallback, sMessage, sFileName, iLineNo, sLocation, sHtmlCapa, iTime) -{ - this.defaultRequest(fCallback, 'JsError', { - 'Message': sMessage, - 'FileName': sFileName, - 'LineNo': iLineNo, - 'Location': sLocation, - 'HtmlCapa': sHtmlCapa, - 'TimeOnPage': iTime - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sType - * @param {Array=} mData = null - * @param {boolean=} bIsError = false - */ -AbstractAjaxRemoteStorage.prototype.jsInfo = function (fCallback, sType, mData, bIsError) -{ - this.defaultRequest(fCallback, 'JsInfo', { - 'Type': sType, - 'Data': mData, - 'IsError': (Utils.isUnd(bIsError) ? false : !!bIsError) ? '1' : '0' - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sVersion - */ -AbstractAjaxRemoteStorage.prototype.jsVersion = function (fCallback, sVersion) -{ - this.defaultRequest(fCallback, 'Version', { - 'Version': sVersion - }); -}; - -/** - * @constructor - * @extends AbstractAjaxRemoteStorage - */ -function WebMailAjaxRemoteStorage() -{ - AbstractAjaxRemoteStorage.call(this); - - this.oRequests = {}; -} - -_.extend(WebMailAjaxRemoteStorage.prototype, AbstractAjaxRemoteStorage.prototype); - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.folders = function (fCallback) -{ - this.defaultRequest(fCallback, 'Folders', { - 'SentFolder': RL.settingsGet('SentFolder'), - 'DraftFolder': RL.settingsGet('DraftFolder'), - 'SpamFolder': RL.settingsGet('SpamFolder'), - 'TrashFolder': RL.settingsGet('TrashFolder'), - 'ArchiveFolder': RL.settingsGet('ArchiveFolder') - }, null, '', ['Folders']); -}; - -/** - * @param {?Function} fCallback - * @param {string} sEmail - * @param {string} sLogin - * @param {string} sPassword - * @param {boolean} bSignMe - * @param {string=} sLanguage - * @param {string=} sAdditionalCode - * @param {boolean=} bAdditionalCodeSignMe - */ -WebMailAjaxRemoteStorage.prototype.login = function (fCallback, sEmail, sLogin, sPassword, bSignMe, sLanguage, sAdditionalCode, bAdditionalCodeSignMe) -{ - this.defaultRequest(fCallback, 'Login', { - 'Email': sEmail, - 'Login': sLogin, - 'Password': sPassword, - 'Language': sLanguage || '', - 'AdditionalCode': sAdditionalCode || '', - 'AdditionalCodeSignMe': bAdditionalCodeSignMe ? '1' : '0', - 'SignMe': bSignMe ? '1' : '0' - }); -}; - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.getTwoFactor = function (fCallback) -{ - this.defaultRequest(fCallback, 'GetTwoFactorInfo'); -}; - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.createTwoFactor = function (fCallback) -{ - this.defaultRequest(fCallback, 'CreateTwoFactorSecret'); -}; - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.clearTwoFactor = function (fCallback) -{ - this.defaultRequest(fCallback, 'ClearTwoFactorInfo'); -}; - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.showTwoFactorSecret = function (fCallback) -{ - this.defaultRequest(fCallback, 'ShowTwoFactorSecret'); -}; - -/** - * @param {?Function} fCallback - * @param {string} sCode - */ -WebMailAjaxRemoteStorage.prototype.testTwoFactor = function (fCallback, sCode) -{ - this.defaultRequest(fCallback, 'TestTwoFactorInfo', { - 'Code': sCode - }); -}; - -/** - * @param {?Function} fCallback - * @param {boolean} bEnable - */ -WebMailAjaxRemoteStorage.prototype.enableTwoFactor = function (fCallback, bEnable) -{ - this.defaultRequest(fCallback, 'EnableTwoFactor', { - 'Enable': bEnable ? '1' : '0' - }); -}; - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.clearTwoFactorInfo = function (fCallback) -{ - this.defaultRequest(fCallback, 'ClearTwoFactorInfo'); -}; - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.contactsSync = function (fCallback) -{ - this.defaultRequest(fCallback, 'ContactsSync', null, Consts.Defaults.ContactsSyncAjaxTimeout); -}; - -/** - * @param {?Function} fCallback - * @param {boolean} bEnable - * @param {string} sUrl - * @param {string} sUser - * @param {string} sPassword - */ -WebMailAjaxRemoteStorage.prototype.saveContactsSyncData = function (fCallback, bEnable, sUrl, sUser, sPassword) -{ - this.defaultRequest(fCallback, 'SaveContactsSyncData', { - 'Enable': bEnable ? '1' : '0', - 'Url': sUrl, - 'User': sUser, - 'Password': sPassword - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sEmail - * @param {string} sLogin - * @param {string} sPassword - */ -WebMailAjaxRemoteStorage.prototype.accountAdd = function (fCallback, sEmail, sLogin, sPassword) -{ - this.defaultRequest(fCallback, 'AccountAdd', { - 'Email': sEmail, - 'Login': sLogin, - 'Password': sPassword - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sEmailToDelete - */ -WebMailAjaxRemoteStorage.prototype.accountDelete = function (fCallback, sEmailToDelete) -{ - this.defaultRequest(fCallback, 'AccountDelete', { - 'EmailToDelete': sEmailToDelete - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sId - * @param {string} sEmail - * @param {string} sName - * @param {string} sReplyTo - * @param {string} sBcc - */ -WebMailAjaxRemoteStorage.prototype.identityUpdate = function (fCallback, sId, sEmail, sName, sReplyTo, sBcc) -{ - this.defaultRequest(fCallback, 'IdentityUpdate', { - 'Id': sId, - 'Email': sEmail, - 'Name': sName, - 'ReplyTo': sReplyTo, - 'Bcc': sBcc - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sIdToDelete - */ -WebMailAjaxRemoteStorage.prototype.identityDelete = function (fCallback, sIdToDelete) -{ - this.defaultRequest(fCallback, 'IdentityDelete', { - 'IdToDelete': sIdToDelete - }); -}; - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.accountsAndIdentities = function (fCallback) -{ - this.defaultRequest(fCallback, 'AccountsAndIdentities'); -}; - -/** - * @param {?Function} fCallback - * @param {string} sFolderFullNameRaw - * @param {number=} iOffset = 0 - * @param {number=} iLimit = 20 - * @param {string=} sSearch = '' - * @param {boolean=} bSilent = false - */ -WebMailAjaxRemoteStorage.prototype.messageList = function (fCallback, sFolderFullNameRaw, iOffset, iLimit, sSearch, bSilent) -{ - sFolderFullNameRaw = Utils.pString(sFolderFullNameRaw); - - var - oData = RL.data(), - sFolderHash = RL.cache().getFolderHash(sFolderFullNameRaw) - ; - - bSilent = Utils.isUnd(bSilent) ? false : !!bSilent; - iOffset = Utils.isUnd(iOffset) ? 0 : Utils.pInt(iOffset); - iLimit = Utils.isUnd(iOffset) ? 20 : Utils.pInt(iLimit); - sSearch = Utils.pString(sSearch); - - if ('' !== sFolderHash && ('' === sSearch || -1 === sSearch.indexOf('has:'))) - { - this.defaultRequest(fCallback, 'MessageList', {}, - '' === sSearch ? Consts.Defaults.DefaultAjaxTimeout : Consts.Defaults.SearchAjaxTimeout, - 'MessageList/' + Base64.urlsafe_encode([ - sFolderFullNameRaw, - iOffset, - iLimit, - sSearch, - oData.projectHash(), - sFolderHash, - 'INBOX' === sFolderFullNameRaw ? RL.cache().getFolderUidNext(sFolderFullNameRaw) : '', - oData.threading() && oData.useThreads() ? '1' : '0', - oData.threading() && sFolderFullNameRaw === oData.messageListThreadFolder() ? oData.messageListThreadUids().join(',') : '' - ].join(String.fromCharCode(0))), bSilent ? [] : ['MessageList']); - } - else - { - this.defaultRequest(fCallback, 'MessageList', { - 'Folder': sFolderFullNameRaw, - 'Offset': iOffset, - 'Limit': iLimit, - 'Search': sSearch, - 'UidNext': 'INBOX' === sFolderFullNameRaw ? RL.cache().getFolderUidNext(sFolderFullNameRaw) : '', - 'UseThreads': RL.data().threading() && RL.data().useThreads() ? '1' : '0', - 'ExpandedThreadUid': oData.threading() && sFolderFullNameRaw === oData.messageListThreadFolder() ? oData.messageListThreadUids().join(',') : '' - }, '' === sSearch ? Consts.Defaults.DefaultAjaxTimeout : Consts.Defaults.SearchAjaxTimeout, '', bSilent ? [] : ['MessageList']); - } -}; - -/** - * @param {?Function} fCallback - * @param {Array} aDownloads - */ -WebMailAjaxRemoteStorage.prototype.messageUploadAttachments = function (fCallback, aDownloads) -{ - this.defaultRequest(fCallback, 'MessageUploadAttachments', { - 'Attachments': aDownloads - }, 999000); -}; - -/** - * @param {?Function} fCallback - * @param {string} sFolderFullNameRaw - * @param {number} iUid - * @return {boolean} - */ -WebMailAjaxRemoteStorage.prototype.message = function (fCallback, sFolderFullNameRaw, iUid) -{ - sFolderFullNameRaw = Utils.pString(sFolderFullNameRaw); - iUid = Utils.pInt(iUid); - - if (RL.cache().getFolderFromCacheList(sFolderFullNameRaw) && 0 < iUid) - { - this.defaultRequest(fCallback, 'Message', {}, null, - 'Message/' + Base64.urlsafe_encode([ - sFolderFullNameRaw, - iUid, - RL.data().projectHash(), - RL.data().threading() && RL.data().useThreads() ? '1' : '0' - ].join(String.fromCharCode(0))), ['Message']); - - return true; - } - - return false; -}; - -/** - * @param {?Function} fCallback - * @param {Array} aExternals - */ -WebMailAjaxRemoteStorage.prototype.composeUploadExternals = function (fCallback, aExternals) -{ - this.defaultRequest(fCallback, 'ComposeUploadExternals', { - 'Externals': aExternals - }, 999000); -}; - -/** - * @param {?Function} fCallback - * @param {string} sFolder - * @param {Array=} aList = [] - */ -WebMailAjaxRemoteStorage.prototype.folderInformation = function (fCallback, sFolder, aList) -{ - var - bRequest = true, - oCache = RL.cache(), - aUids = [] - ; - - if (Utils.isArray(aList) && 0 < aList.length) - { - bRequest = false; - _.each(aList, function (oMessageListItem) { - if (!oCache.getMessageFlagsFromCache(oMessageListItem.folderFullNameRaw, oMessageListItem.uid)) - { - aUids.push(oMessageListItem.uid); - } - - if (0 < oMessageListItem.threads().length) - { - _.each(oMessageListItem.threads(), function (sUid) { - if (!oCache.getMessageFlagsFromCache(oMessageListItem.folderFullNameRaw, sUid)) - { - aUids.push(sUid); - } - }); - } - }); - - if (0 < aUids.length) - { - bRequest = true; - } - } - - if (bRequest) - { - this.defaultRequest(fCallback, 'FolderInformation', { - 'Folder': sFolder, - 'FlagsUids': Utils.isArray(aUids) ? aUids.join(',') : '', - 'UidNext': 'INBOX' === sFolder ? RL.cache().getFolderUidNext(sFolder) : '' - }); - } - else if (RL.data().useThreads()) - { - RL.reloadFlagsCurrentMessageListAndMessageFromCache(); - } -}; - -/** - * @param {?Function} fCallback - * @param {Array} aFolders - */ -WebMailAjaxRemoteStorage.prototype.folderInformationMultiply = function (fCallback, aFolders) -{ - this.defaultRequest(fCallback, 'FolderInformationMultiply', { - 'Folders': aFolders - }); -}; - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.logout = function (fCallback) -{ - this.defaultRequest(fCallback, 'Logout'); -}; - -/** - * @param {?Function} fCallback - * @param {string} sFolderFullNameRaw - * @param {Array} aUids - * @param {boolean} bSetFlagged - */ -WebMailAjaxRemoteStorage.prototype.messageSetFlagged = function (fCallback, sFolderFullNameRaw, aUids, bSetFlagged) -{ - this.defaultRequest(fCallback, 'MessageSetFlagged', { - 'Folder': sFolderFullNameRaw, - 'Uids': aUids.join(','), - 'SetAction': bSetFlagged ? '1' : '0' - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sFolderFullNameRaw - * @param {Array} aUids - * @param {boolean} bSetSeen - */ -WebMailAjaxRemoteStorage.prototype.messageSetSeen = function (fCallback, sFolderFullNameRaw, aUids, bSetSeen) -{ - this.defaultRequest(fCallback, 'MessageSetSeen', { - 'Folder': sFolderFullNameRaw, - 'Uids': aUids.join(','), - 'SetAction': bSetSeen ? '1' : '0' - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sFolderFullNameRaw - * @param {boolean} bSetSeen - */ -WebMailAjaxRemoteStorage.prototype.messageSetSeenToAll = function (fCallback, sFolderFullNameRaw, bSetSeen) -{ - this.defaultRequest(fCallback, 'MessageSetSeenToAll', { - 'Folder': sFolderFullNameRaw, - 'SetAction': bSetSeen ? '1' : '0' - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sMessageFolder - * @param {string} sMessageUid - * @param {string} sDraftFolder - * @param {string} sFrom - * @param {string} sTo - * @param {string} sCc - * @param {string} sBcc - * @param {string} sSubject - * @param {boolean} bTextIsHtml - * @param {string} sText - * @param {Array} aAttachments - * @param {(Array|null)} aDraftInfo - * @param {string} sInReplyTo - * @param {string} sReferences - */ -WebMailAjaxRemoteStorage.prototype.saveMessage = function (fCallback, sMessageFolder, sMessageUid, sDraftFolder, - sFrom, sTo, sCc, sBcc, sSubject, bTextIsHtml, sText, aAttachments, aDraftInfo, sInReplyTo, sReferences) -{ - this.defaultRequest(fCallback, 'SaveMessage', { - 'MessageFolder': sMessageFolder, - 'MessageUid': sMessageUid, - 'DraftFolder': sDraftFolder, - 'From': sFrom, - 'To': sTo, - 'Cc': sCc, - 'Bcc': sBcc, - 'Subject': sSubject, - 'TextIsHtml': bTextIsHtml ? '1' : '0', - 'Text': sText, - 'DraftInfo': aDraftInfo, - 'InReplyTo': sInReplyTo, - 'References': sReferences, - 'Attachments': aAttachments - }, Consts.Defaults.SaveMessageAjaxTimeout); -}; - - -/** - * @param {?Function} fCallback - * @param {string} sMessageFolder - * @param {string} sMessageUid - * @param {string} sReadReceipt - * @param {string} sSubject - * @param {string} sText - */ -WebMailAjaxRemoteStorage.prototype.sendReadReceiptMessage = function (fCallback, sMessageFolder, sMessageUid, sReadReceipt, sSubject, sText) -{ - this.defaultRequest(fCallback, 'SendReadReceiptMessage', { - 'MessageFolder': sMessageFolder, - 'MessageUid': sMessageUid, - 'ReadReceipt': sReadReceipt, - 'Subject': sSubject, - 'Text': sText - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sMessageFolder - * @param {string} sMessageUid - * @param {string} sSentFolder - * @param {string} sFrom - * @param {string} sTo - * @param {string} sCc - * @param {string} sBcc - * @param {string} sSubject - * @param {boolean} bTextIsHtml - * @param {string} sText - * @param {Array} aAttachments - * @param {(Array|null)} aDraftInfo - * @param {string} sInReplyTo - * @param {string} sReferences - * @param {boolean} bRequestReadReceipt - */ -WebMailAjaxRemoteStorage.prototype.sendMessage = function (fCallback, sMessageFolder, sMessageUid, sSentFolder, - sFrom, sTo, sCc, sBcc, sSubject, bTextIsHtml, sText, aAttachments, aDraftInfo, sInReplyTo, sReferences, bRequestReadReceipt) -{ - this.defaultRequest(fCallback, 'SendMessage', { - 'MessageFolder': sMessageFolder, - 'MessageUid': sMessageUid, - 'SentFolder': sSentFolder, - 'From': sFrom, - 'To': sTo, - 'Cc': sCc, - 'Bcc': sBcc, - 'Subject': sSubject, - 'TextIsHtml': bTextIsHtml ? '1' : '0', - 'Text': sText, - 'DraftInfo': aDraftInfo, - 'InReplyTo': sInReplyTo, - 'References': sReferences, - 'ReadReceiptRequest': bRequestReadReceipt ? '1' : '0', - 'Attachments': aAttachments - }, Consts.Defaults.SendMessageAjaxTimeout); -}; - -/** - * @param {?Function} fCallback - * @param {Object} oData - */ -WebMailAjaxRemoteStorage.prototype.saveSystemFolders = function (fCallback, oData) -{ - this.defaultRequest(fCallback, 'SystemFoldersUpdate', oData); -}; - -/** - * @param {?Function} fCallback - * @param {Object} oData - */ -WebMailAjaxRemoteStorage.prototype.saveSettings = function (fCallback, oData) -{ - this.defaultRequest(fCallback, 'SettingsUpdate', oData); -}; - -/** - * @param {?Function} fCallback - * @param {string} sPrevPassword - * @param {string} sNewPassword - */ -WebMailAjaxRemoteStorage.prototype.changePassword = function (fCallback, sPrevPassword, sNewPassword) -{ - this.defaultRequest(fCallback, 'ChangePassword', { - 'PrevPassword': sPrevPassword, - 'NewPassword': sNewPassword - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sNewFolderName - * @param {string} sParentName - */ -WebMailAjaxRemoteStorage.prototype.folderCreate = function (fCallback, sNewFolderName, sParentName) -{ - this.defaultRequest(fCallback, 'FolderCreate', { - 'Folder': sNewFolderName, - 'Parent': sParentName - }, null, '', ['Folders']); -}; - -/** - * @param {?Function} fCallback - * @param {string} sFolderFullNameRaw - */ -WebMailAjaxRemoteStorage.prototype.folderDelete = function (fCallback, sFolderFullNameRaw) -{ - this.defaultRequest(fCallback, 'FolderDelete', { - 'Folder': sFolderFullNameRaw - }, null, '', ['Folders']); -}; - -/** - * @param {?Function} fCallback - * @param {string} sPrevFolderFullNameRaw - * @param {string} sNewFolderName - */ -WebMailAjaxRemoteStorage.prototype.folderRename = function (fCallback, sPrevFolderFullNameRaw, sNewFolderName) -{ - this.defaultRequest(fCallback, 'FolderRename', { - 'Folder': sPrevFolderFullNameRaw, - 'NewFolderName': sNewFolderName - }, null, '', ['Folders']); -}; - -/** - * @param {?Function} fCallback - * @param {string} sFolderFullNameRaw - */ -WebMailAjaxRemoteStorage.prototype.folderClear = function (fCallback, sFolderFullNameRaw) -{ - this.defaultRequest(fCallback, 'FolderClear', { - 'Folder': sFolderFullNameRaw - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sFolderFullNameRaw - * @param {boolean} bSubscribe - */ -WebMailAjaxRemoteStorage.prototype.folderSetSubscribe = function (fCallback, sFolderFullNameRaw, bSubscribe) -{ - this.defaultRequest(fCallback, 'FolderSubscribe', { - 'Folder': sFolderFullNameRaw, - 'Subscribe': bSubscribe ? '1' : '0' - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sFolder - * @param {string} sToFolder - * @param {Array} aUids - * @param {string=} sLearning - */ -WebMailAjaxRemoteStorage.prototype.messagesMove = function (fCallback, sFolder, sToFolder, aUids, sLearning) -{ - this.defaultRequest(fCallback, 'MessageMove', { - 'FromFolder': sFolder, - 'ToFolder': sToFolder, - 'Uids': aUids.join(','), - 'Learning': sLearning || '' - }, null, '', ['MessageList']); -}; - -/** - * @param {?Function} fCallback - * @param {string} sFolder - * @param {string} sToFolder - * @param {Array} aUids - */ -WebMailAjaxRemoteStorage.prototype.messagesCopy = function (fCallback, sFolder, sToFolder, aUids) -{ - this.defaultRequest(fCallback, 'MessageCopy', { - 'FromFolder': sFolder, - 'ToFolder': sToFolder, - 'Uids': aUids.join(',') - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sFolder - * @param {Array} aUids - */ -WebMailAjaxRemoteStorage.prototype.messagesDelete = function (fCallback, sFolder, aUids) -{ - this.defaultRequest(fCallback, 'MessageDelete', { - 'Folder': sFolder, - 'Uids': aUids.join(',') - }, null, '', ['MessageList']); -}; - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.appDelayStart = function (fCallback) -{ - this.defaultRequest(fCallback, 'AppDelayStart'); -}; - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.quota = function (fCallback) -{ - this.defaultRequest(fCallback, 'Quota'); -}; - -/** - * @param {?Function} fCallback - * @param {number} iOffset - * @param {number} iLimit - * @param {string} sSearch - */ -WebMailAjaxRemoteStorage.prototype.contacts = function (fCallback, iOffset, iLimit, sSearch) -{ - this.defaultRequest(fCallback, 'Contacts', { - 'Offset': iOffset, - 'Limit': iLimit, - 'Search': sSearch - }, null, '', ['Contacts']); -}; - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.contactSave = function (fCallback, sRequestUid, sUid, aProperties) -{ - this.defaultRequest(fCallback, 'ContactSave', { - 'RequestUid': sRequestUid, - 'Uid': Utils.trim(sUid), - 'Properties': aProperties - }); -}; - -/** - * @param {?Function} fCallback - * @param {Array} aUids - */ -WebMailAjaxRemoteStorage.prototype.contactsDelete = function (fCallback, aUids) -{ - this.defaultRequest(fCallback, 'ContactsDelete', { - 'Uids': aUids.join(',') - }); -}; - -/** - * @param {?Function} fCallback - * @param {string} sQuery - * @param {number} iPage - */ -WebMailAjaxRemoteStorage.prototype.suggestions = function (fCallback, sQuery, iPage) -{ - this.defaultRequest(fCallback, 'Suggestions', { - 'Query': sQuery, - 'Page': iPage - }, null, '', ['Suggestions']); -}; - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.servicesPics = function (fCallback) -{ - this.defaultRequest(fCallback, 'ServicesPics'); -}; - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.emailsPicsHashes = function (fCallback) -{ - this.defaultRequest(fCallback, 'EmailsPicsHashes'); -}; - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.facebookUser = function (fCallback) -{ - this.defaultRequest(fCallback, 'SocialFacebookUserInformation'); -}; - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.facebookDisconnect = function (fCallback) -{ - this.defaultRequest(fCallback, 'SocialFacebookDisconnect'); -}; - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.twitterUser = function (fCallback) -{ - this.defaultRequest(fCallback, 'SocialTwitterUserInformation'); -}; - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.twitterDisconnect = function (fCallback) -{ - this.defaultRequest(fCallback, 'SocialTwitterDisconnect'); -}; - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.googleUser = function (fCallback) -{ - this.defaultRequest(fCallback, 'SocialGoogleUserInformation'); -}; - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.googleDisconnect = function (fCallback) -{ - this.defaultRequest(fCallback, 'SocialGoogleDisconnect'); -}; - -/** - * @param {?Function} fCallback - */ -WebMailAjaxRemoteStorage.prototype.socialUsers = function (fCallback) -{ - this.defaultRequest(fCallback, 'SocialUsers'); -}; - - -/** - * @constructor - */ -function AbstractCacheStorage() -{ - this.oEmailsPicsHashes = {}; - this.oServices = {}; - this.bAllowGravatar = !!RL.settingsGet('AllowGravatar'); -} - -/** - * @type {Object} - */ -AbstractCacheStorage.prototype.oEmailsPicsHashes = {}; - -/** - * @type {Object} - */ -AbstractCacheStorage.prototype.oServices = {}; - -/** - * @type {boolean} - */ -AbstractCacheStorage.prototype.bAllowGravatar = false; - -AbstractCacheStorage.prototype.clear = function () -{ - this.oServices = {}; - this.oEmailsPicsHashes = {}; -}; - -/** - * @param {string} sEmail - * @return {string} - */ -AbstractCacheStorage.prototype.getUserPic = function (sEmail, fCallback) -{ - sEmail = Utils.trim(sEmail); - - var - sUrl = '', - sService = '', - sEmailLower = sEmail.toLowerCase(), - sPicHash = Utils.isUnd(this.oEmailsPicsHashes[sEmailLower]) ? '' : this.oEmailsPicsHashes[sEmailLower] - ; - - if ('' !== sPicHash) - { - sUrl = RL.link().getUserPicUrlFromHash(sPicHash); - } - else - { - sService = sEmailLower.substr(sEmail.indexOf('@') + 1); - sUrl = '' !== sService && this.oServices[sService] ? this.oServices[sService] : ''; - } - - - if (this.bAllowGravatar && '' === sUrl) - { - fCallback('//secure.gravatar.com/avatar/' + Utils.md5(sEmailLower) + '.jpg?s=80&d=mm', sEmail); - } - else - { - fCallback(sUrl, sEmail); - } -}; - -/** - * @param {Object} oData - */ -AbstractCacheStorage.prototype.setServicesData = function (oData) -{ - this.oServices = oData; -}; - -/** - * @param {Object} oData - */ -AbstractCacheStorage.prototype.setEmailsPicsHashesData = function (oData) -{ - this.oEmailsPicsHashes = oData; -}; - -/** - * @constructor - * @extends AbstractCacheStorage - */ -function WebMailCacheStorage() -{ - AbstractCacheStorage.call(this); - - this.oFoldersCache = {}; - this.oFoldersNamesCache = {}; - this.oFolderHashCache = {}; - this.oFolderUidNextCache = {}; - this.oMessageListHashCache = {}; - this.oMessageFlagsCache = {}; - this.oNewMessage = {}; - this.oRequestedMessage = {}; -} - -_.extend(WebMailCacheStorage.prototype, AbstractCacheStorage.prototype); - -/** - * @type {Object} - */ -WebMailCacheStorage.prototype.oFoldersCache = {}; - -/** - * @type {Object} - */ -WebMailCacheStorage.prototype.oFoldersNamesCache = {}; - -/** - * @type {Object} - */ -WebMailCacheStorage.prototype.oFolderHashCache = {}; - -/** - * @type {Object} - */ -WebMailCacheStorage.prototype.oFolderUidNextCache = {}; - -/** - * @type {Object} - */ -WebMailCacheStorage.prototype.oMessageListHashCache = {}; - -/** - * @type {Object} - */ -WebMailCacheStorage.prototype.oMessageFlagsCache = {}; - -/** - * @type {Object} - */ -WebMailCacheStorage.prototype.oBodies = {}; - -/** - * @type {Object} - */ -WebMailCacheStorage.prototype.oNewMessage = {}; - -/** - * @type {Object} - */ -WebMailCacheStorage.prototype.oRequestedMessage = {}; - -WebMailCacheStorage.prototype.clear = function () -{ - AbstractCacheStorage.prototype.clear.call(this); - - this.oFoldersCache = {}; - this.oFoldersNamesCache = {}; - this.oFolderHashCache = {}; - this.oFolderUidNextCache = {}; - this.oMessageListHashCache = {}; - this.oMessageFlagsCache = {}; - this.oBodies = {}; -}; - -/** - * @param {string} sFolderFullNameRaw - * @param {string} sUid - * @return {string} - */ -WebMailCacheStorage.prototype.getMessageKey = function (sFolderFullNameRaw, sUid) -{ - return sFolderFullNameRaw + '#' + sUid; -}; - -/** - * @param {string} sFolder - * @param {string} sUid - */ -WebMailCacheStorage.prototype.addRequestedMessage = function (sFolder, sUid) -{ - this.oRequestedMessage[this.getMessageKey(sFolder, sUid)] = true; -}; - -/** - * @param {string} sFolder - * @param {string} sUid - * @return {boolean} - */ -WebMailCacheStorage.prototype.hasRequestedMessage = function (sFolder, sUid) -{ - return true === this.oRequestedMessage[this.getMessageKey(sFolder, sUid)]; -}; - -/** - * @param {string} sFolderFullNameRaw - * @param {string} sUid - */ -WebMailCacheStorage.prototype.addNewMessageCache = function (sFolderFullNameRaw, sUid) -{ - this.oNewMessage[this.getMessageKey(sFolderFullNameRaw, sUid)] = true; -}; - -/** - * @param {string} sFolderFullNameRaw - * @param {string} sUid - */ -WebMailCacheStorage.prototype.hasNewMessageAndRemoveFromCache = function (sFolderFullNameRaw, sUid) -{ - if (this.oNewMessage[this.getMessageKey(sFolderFullNameRaw, sUid)]) - { - this.oNewMessage[this.getMessageKey(sFolderFullNameRaw, sUid)] = null; - return true; - } - - return false; -}; - -WebMailCacheStorage.prototype.clearNewMessageCache = function () -{ - this.oNewMessage = {}; -}; - -/** - * @param {string} sFolderHash - * @return {string} - */ -WebMailCacheStorage.prototype.getFolderFullNameRaw = function (sFolderHash) -{ - return '' !== sFolderHash && this.oFoldersNamesCache[sFolderHash] ? this.oFoldersNamesCache[sFolderHash] : ''; -}; - -/** - * @param {string} sFolderHash - * @param {string} sFolderFullNameRaw - */ -WebMailCacheStorage.prototype.setFolderFullNameRaw = function (sFolderHash, sFolderFullNameRaw) -{ - this.oFoldersNamesCache[sFolderHash] = sFolderFullNameRaw; -}; - -/** - * @param {string} sFolderFullNameRaw - * @return {string} - */ -WebMailCacheStorage.prototype.getFolderHash = function (sFolderFullNameRaw) -{ - return '' !== sFolderFullNameRaw && this.oFolderHashCache[sFolderFullNameRaw] ? this.oFolderHashCache[sFolderFullNameRaw] : ''; -}; - -/** - * @param {string} sFolderFullNameRaw - * @param {string} sFolderHash - */ -WebMailCacheStorage.prototype.setFolderHash = function (sFolderFullNameRaw, sFolderHash) -{ - this.oFolderHashCache[sFolderFullNameRaw] = sFolderHash; -}; - -/** - * @param {string} sFolderFullNameRaw - * @return {string} - */ -WebMailCacheStorage.prototype.getFolderUidNext = function (sFolderFullNameRaw) -{ - return '' !== sFolderFullNameRaw && this.oFolderUidNextCache[sFolderFullNameRaw] ? this.oFolderUidNextCache[sFolderFullNameRaw] : ''; -}; - -/** - * @param {string} sFolderFullNameRaw - * @param {string} sUidNext - */ -WebMailCacheStorage.prototype.setFolderUidNext = function (sFolderFullNameRaw, sUidNext) -{ - this.oFolderUidNextCache[sFolderFullNameRaw] = sUidNext; -}; - -/** - * @param {string} sFolderFullNameRaw - * @return {?FolderModel} - */ -WebMailCacheStorage.prototype.getFolderFromCacheList = function (sFolderFullNameRaw) -{ - return '' !== sFolderFullNameRaw && this.oFoldersCache[sFolderFullNameRaw] ? this.oFoldersCache[sFolderFullNameRaw] : null; -}; - -/** - * @param {string} sFolderFullNameRaw - * @param {?FolderModel} oFolder - */ -WebMailCacheStorage.prototype.setFolderToCacheList = function (sFolderFullNameRaw, oFolder) -{ - this.oFoldersCache[sFolderFullNameRaw] = oFolder; -}; - -/** - * @param {string} sFolderFullNameRaw - */ -WebMailCacheStorage.prototype.removeFolderFromCacheList = function (sFolderFullNameRaw) -{ - this.setFolderToCacheList(sFolderFullNameRaw, null); -}; - -/** - * @param {string} sFolderFullName - * @param {string} sUid - * @return {?Array} - */ -WebMailCacheStorage.prototype.getMessageFlagsFromCache = function (sFolderFullName, sUid) -{ - return this.oMessageFlagsCache[sFolderFullName] && this.oMessageFlagsCache[sFolderFullName][sUid] ? - this.oMessageFlagsCache[sFolderFullName][sUid] : null; -}; - -/** - * @param {string} sFolderFullName - * @param {string} sUid - * @param {Array} aFlagsCache - */ -WebMailCacheStorage.prototype.setMessageFlagsToCache = function (sFolderFullName, sUid, aFlagsCache) -{ - if (!this.oMessageFlagsCache[sFolderFullName]) - { - this.oMessageFlagsCache[sFolderFullName] = {}; - } - - this.oMessageFlagsCache[sFolderFullName][sUid] = aFlagsCache; -}; - -/** - * @param {string} sFolderFullName - */ -WebMailCacheStorage.prototype.clearMessageFlagsFromCacheByFolder = function (sFolderFullName) -{ - this.oMessageFlagsCache[sFolderFullName] = {}; -}; - -/** - * @param {(MessageModel|null)} oMessage - */ -WebMailCacheStorage.prototype.initMessageFlagsFromCache = function (oMessage) -{ - if (oMessage) - { - var - self = this, - aFlags = this.getMessageFlagsFromCache(oMessage.folderFullNameRaw, oMessage.uid), - mUnseenSubUid = null, - mFlaggedSubUid = null - ; - - if (aFlags && 0 < aFlags.length) - { - oMessage.unseen(!!aFlags[0]); - oMessage.flagged(!!aFlags[1]); - oMessage.answered(!!aFlags[2]); - oMessage.forwarded(!!aFlags[3]); - oMessage.isReadReceipt(!!aFlags[4]); - } - - if (0 < oMessage.threads().length) - { - mUnseenSubUid = _.find(oMessage.threads(), function (iSubUid) { - var aFlags = self.getMessageFlagsFromCache(oMessage.folderFullNameRaw, iSubUid); - return aFlags && 0 < aFlags.length && !!aFlags[0]; - }); - - mFlaggedSubUid = _.find(oMessage.threads(), function (iSubUid) { - var aFlags = self.getMessageFlagsFromCache(oMessage.folderFullNameRaw, iSubUid); - return aFlags && 0 < aFlags.length && !!aFlags[1]; - }); - - oMessage.hasUnseenSubMessage(mUnseenSubUid && 0 < Utils.pInt(mUnseenSubUid)); - oMessage.hasFlaggedSubMessage(mFlaggedSubUid && 0 < Utils.pInt(mFlaggedSubUid)); - } - } -}; - -/** - * @param {(MessageModel|null)} oMessage - */ -WebMailCacheStorage.prototype.storeMessageFlagsToCache = function (oMessage) -{ - if (oMessage) - { - this.setMessageFlagsToCache( - oMessage.folderFullNameRaw, - oMessage.uid, - [oMessage.unseen(), oMessage.flagged(), oMessage.answered(), oMessage.forwarded(), oMessage.isReadReceipt()] - ); - } -}; -/** - * @param {string} sFolder - * @param {string} sUid - * @param {Array} aFlags - */ -WebMailCacheStorage.prototype.storeMessageFlagsToCacheByFolderAndUid = function (sFolder, sUid, aFlags) -{ - if (Utils.isArray(aFlags) && 0 < aFlags.length) - { - this.setMessageFlagsToCache(sFolder, sUid, aFlags); - } -}; - -/** - * @param {Array} aViewModels - * @constructor - * @extends KnoinAbstractScreen - */ -function AbstractSettings(aViewModels) -{ - KnoinAbstractScreen.call(this, 'settings', aViewModels); - - this.menu = ko.observableArray([]); - - this.oCurrentSubScreen = null; - this.oViewModelPlace = null; -} - -_.extend(AbstractSettings.prototype, KnoinAbstractScreen.prototype); - -AbstractSettings.prototype.onRoute = function (sSubName) -{ - var - self = this, - oSettingsScreen = null, - RoutedSettingsViewModel = null, - oViewModelPlace = null, - oViewModelDom = null - ; - - RoutedSettingsViewModel = _.find(ViewModels['settings'], function (SettingsViewModel) { - return SettingsViewModel && SettingsViewModel.__rlSettingsData && - sSubName === SettingsViewModel.__rlSettingsData.Route; - }); - - if (RoutedSettingsViewModel) - { - if (_.find(ViewModels['settings-removed'], function (DisabledSettingsViewModel) { - return DisabledSettingsViewModel && DisabledSettingsViewModel === RoutedSettingsViewModel; - })) - { - RoutedSettingsViewModel = null; - } - - if (RoutedSettingsViewModel && _.find(ViewModels['settings-disabled'], function (DisabledSettingsViewModel) { - return DisabledSettingsViewModel && DisabledSettingsViewModel === RoutedSettingsViewModel; - })) - { - RoutedSettingsViewModel = null; - } - } - - if (RoutedSettingsViewModel) - { - if (RoutedSettingsViewModel.__builded && RoutedSettingsViewModel.__vm) - { - oSettingsScreen = RoutedSettingsViewModel.__vm; - } - else - { - oViewModelPlace = this.oViewModelPlace; - if (oViewModelPlace && 1 === oViewModelPlace.length) - { - RoutedSettingsViewModel = /** @type {?Function} */ RoutedSettingsViewModel; - oSettingsScreen = new RoutedSettingsViewModel(); - - oViewModelDom = $('').addClass('rl-settings-view-model').hide().attr('data-bind', - 'template: {name: "' + RoutedSettingsViewModel.__rlSettingsData.Template + '"}, i18nInit: true'); - - oViewModelDom.appendTo(oViewModelPlace); - - oSettingsScreen.data = RL.data(); - oSettingsScreen.viewModelDom = oViewModelDom; - - oSettingsScreen.__rlSettingsData = RoutedSettingsViewModel.__rlSettingsData; - - RoutedSettingsViewModel.__dom = oViewModelDom; - RoutedSettingsViewModel.__builded = true; - RoutedSettingsViewModel.__vm = oSettingsScreen; - - ko.applyBindings(oSettingsScreen, oViewModelDom[0]); - Utils.delegateRun(oSettingsScreen, 'onBuild', [oViewModelDom]); - } - else - { - Utils.log('Cannot find sub settings view model position: SettingsSubScreen'); - } - } - - if (oSettingsScreen) - { - _.defer(function () { - // hide - if (self.oCurrentSubScreen) - { - Utils.delegateRun(self.oCurrentSubScreen, 'onHide'); - self.oCurrentSubScreen.viewModelDom.hide(); - } - // -- - - self.oCurrentSubScreen = oSettingsScreen; - - // show - if (self.oCurrentSubScreen) - { - self.oCurrentSubScreen.viewModelDom.show(); - Utils.delegateRun(self.oCurrentSubScreen, 'onShow'); - Utils.delegateRun(self.oCurrentSubScreen, 'onFocus', [], 200); - - _.each(self.menu(), function (oItem) { - oItem.selected(oSettingsScreen && oSettingsScreen.__rlSettingsData && oItem.route === oSettingsScreen.__rlSettingsData.Route); - }); - - $('#rl-content .b-settings .b-content .content').scrollTop(0); - } - // -- - - Utils.windowResize(); - }); - } - } - else - { - kn.setHash(RL.link().settings(), false, true); - } -}; - -AbstractSettings.prototype.onHide = function () -{ - if (this.oCurrentSubScreen && this.oCurrentSubScreen.viewModelDom) - { - Utils.delegateRun(this.oCurrentSubScreen, 'onHide'); - this.oCurrentSubScreen.viewModelDom.hide(); - } -}; - -AbstractSettings.prototype.onBuild = function () -{ - _.each(ViewModels['settings'], function (SettingsViewModel) { - if (SettingsViewModel && SettingsViewModel.__rlSettingsData && - !_.find(ViewModels['settings-removed'], function (RemoveSettingsViewModel) { - return RemoveSettingsViewModel && RemoveSettingsViewModel === SettingsViewModel; - })) - { - this.menu.push({ - 'route': SettingsViewModel.__rlSettingsData.Route, - 'label': SettingsViewModel.__rlSettingsData.Label, - 'selected': ko.observable(false), - 'disabled': !!_.find(ViewModels['settings-disabled'], function (DisabledSettingsViewModel) { - return DisabledSettingsViewModel && DisabledSettingsViewModel === SettingsViewModel; - }) - }); - } - }, this); - - this.oViewModelPlace = $('#rl-content #rl-settings-subscreen'); -}; - -AbstractSettings.prototype.routes = function () -{ - var - DefaultViewModel = _.find(ViewModels['settings'], function (SettingsViewModel) { - return SettingsViewModel && SettingsViewModel.__rlSettingsData && SettingsViewModel.__rlSettingsData['IsDefault']; - }), - sDefaultRoute = DefaultViewModel ? DefaultViewModel.__rlSettingsData['Route'] : 'general', - oRules = { - 'subname': /^(.*)$/, - 'normalize_': function (oRequest, oVals) { - oVals.subname = Utils.isUnd(oVals.subname) ? sDefaultRoute : Utils.pString(oVals.subname); - return [oVals.subname]; - } - } - ; - - return [ - ['{subname}/', oRules], - ['{subname}', oRules], - ['', oRules] - ]; -}; - -/** - * @constructor - * @extends KnoinAbstractScreen - */ -function LoginScreen() -{ - KnoinAbstractScreen.call(this, 'login', [LoginViewModel]); -} - -_.extend(LoginScreen.prototype, KnoinAbstractScreen.prototype); - -LoginScreen.prototype.onShow = function () -{ - RL.setTitle(''); +ko.bindingHandlers.dropdownCloser = { + 'init': function (oElement) { + $(oElement).closest('.dropdown').on('click', '.e-item', function () { + $(oElement).dropdown('toggle'); + }); + } }; -/** - * @constructor - * @extends KnoinAbstractScreen - */ -function MailBoxScreen() -{ - KnoinAbstractScreen.call(this, 'mailbox', [ - MailBoxSystemDropDownViewModel, - MailBoxFolderListViewModel, - MailBoxMessageListViewModel, - MailBoxMessageViewViewModel - ]); - - this.oLastRoute = {}; -} - -_.extend(MailBoxScreen.prototype, KnoinAbstractScreen.prototype); - -/** - * @type {Object} - */ -MailBoxScreen.prototype.oLastRoute = {}; - -MailBoxScreen.prototype.setNewTitle = function () -{ - var - sEmail = RL.data().accountEmail(), - ifoldersInboxUnreadCount = RL.data().foldersInboxUnreadCount() - ; - - RL.setTitle(('' === sEmail ? '' : - (0 < ifoldersInboxUnreadCount ? '(' + ifoldersInboxUnreadCount + ') ' : ' ') + sEmail + ' - ') + Utils.i18n('TITLES/MAILBOX')); -}; - -MailBoxScreen.prototype.onShow = function () -{ - this.setNewTitle(); - RL.data().keyScope(Enums.KeyState.MessageList); -}; - -/** - * @param {string} sFolderHash - * @param {number} iPage - * @param {string} sSearch - * @param {boolean=} bPreview = false - */ -MailBoxScreen.prototype.onRoute = function (sFolderHash, iPage, sSearch, bPreview) -{ - if (Utils.isUnd(bPreview) ? false : !!bPreview) - { - if (Enums.Layout.NoPreview === RL.data().layout() && !RL.data().message()) - { - RL.historyBack(); - } - } - else - { - var - oData = RL.data(), - sFolderFullNameRaw = RL.cache().getFolderFullNameRaw(sFolderHash), - oFolder = RL.cache().getFolderFromCacheList(sFolderFullNameRaw) - ; - - if (oFolder) - { - oData - .currentFolder(oFolder) - .messageListPage(iPage) - .messageListSearch(sSearch) - ; - - if (Enums.Layout.NoPreview === oData.layout() && oData.message()) - { - oData.message(null); - oData.messageFullScreenMode(false); - } - - RL.reloadMessageList(); - } - } -}; - -MailBoxScreen.prototype.onStart = function () -{ - var - oData = RL.data(), - fResizeFunction = function () { - Utils.windowResize(); - } - ; - - if (RL.settingsGet('AllowAdditionalAccounts') || RL.settingsGet('AllowIdentities')) - { - RL.accountsAndIdentities(); - } - - _.delay(function () { - if ('INBOX' !== oData.currentFolderFullNameRaw()) - { - RL.folderInformation('INBOX'); - } - }, 1000); - - _.delay(function () { - RL.quota(); - }, 5000); - - _.delay(function () { - RL.remote().appDelayStart(Utils.emptyFunction); - }, 35000); - - $html.toggleClass('rl-no-preview-pane', Enums.Layout.NoPreview === oData.layout()); - - oData.folderList.subscribe(fResizeFunction); - oData.messageList.subscribe(fResizeFunction); - oData.message.subscribe(fResizeFunction); - - oData.layout.subscribe(function (nValue) { - $html.toggleClass('rl-no-preview-pane', Enums.Layout.NoPreview === nValue); - }); - - oData.foldersInboxUnreadCount.subscribe(function () { - this.setNewTitle(); - }, this); -}; - -/** - * @return {Array} - */ -MailBoxScreen.prototype.routes = function () -{ - var - fNormP = function () { - return ['Inbox', 1, '', true]; - }, - fNormS = function (oRequest, oVals) { - oVals[0] = Utils.pString(oVals[0]); - oVals[1] = Utils.pInt(oVals[1]); - oVals[1] = 0 >= oVals[1] ? 1 : oVals[1]; - oVals[2] = Utils.pString(oVals[2]); - - if ('' === oRequest) - { - oVals[0] = 'Inbox'; - oVals[1] = 1; - } - - return [decodeURI(oVals[0]), oVals[1], decodeURI(oVals[2]), false]; - }, - fNormD = function (oRequest, oVals) { - oVals[0] = Utils.pString(oVals[0]); - oVals[1] = Utils.pString(oVals[1]); - - if ('' === oRequest) - { - oVals[0] = 'Inbox'; - } - - return [decodeURI(oVals[0]), 1, decodeURI(oVals[1]), false]; - } - ; - - return [ - [/^([a-zA-Z0-9]+)\/p([1-9][0-9]*)\/(.+)\/?$/, {'normalize_': fNormS}], - [/^([a-zA-Z0-9]+)\/p([1-9][0-9]*)$/, {'normalize_': fNormS}], - [/^([a-zA-Z0-9]+)\/(.+)\/?$/, {'normalize_': fNormD}], - [/^message-preview$/, {'normalize_': fNormP}], - [/^([^\/]*)$/, {'normalize_': fNormS}] - ]; -}; -/** - * @constructor - * @extends AbstractSettings - */ -function SettingsScreen() -{ - AbstractSettings.call(this, [ - SettingsSystemDropDownViewModel, - SettingsMenuViewModel, - SettingsPaneViewModel - ]); - - Utils.initOnStartOrLangChange(function () { - this.sSettingsTitle = Utils.i18n('TITLES/SETTINGS'); - }, this, function () { - RL.setTitle(this.sSettingsTitle); - }); -} - -_.extend(SettingsScreen.prototype, AbstractSettings.prototype); - -SettingsScreen.prototype.onShow = function () -{ -// AbstractSettings.prototype.onShow.call(this); - - RL.setTitle(this.sSettingsTitle); - RL.data().keyScope(Enums.KeyState.Settings); -}; +ko.bindingHandlers.popover = { + 'init': function (oElement, fValueAccessor) { + $(oElement).popover(ko.utils.unwrapObservable(fValueAccessor())); + } +}; -/** - * @constructor - * @extends KnoinAbstractBoot - */ -function AbstractApp() -{ - KnoinAbstractBoot.call(this); - - this.oSettings = null; - this.oPlugins = null; - this.oLocal = null; - this.oLink = null; - this.oSubs = {}; - - this.isLocalAutocomplete = true; - - this.popupVisibilityNames = ko.observableArray([]); - - this.popupVisibility = ko.computed(function () { - return 0 < this.popupVisibilityNames().length; - }, this); - - this.iframe = $('').appendTo('body'); - - $window.on('error', function (oEvent) { - if (RL && oEvent && oEvent.originalEvent && oEvent.originalEvent.message && - -1 === Utils.inArray(oEvent.originalEvent.message, [ - 'Script error.', 'Uncaught Error: Error calling method on NPObject.' - ])) - { - RL.remote().jsError( - Utils.emptyFunction, - oEvent.originalEvent.message, - oEvent.originalEvent.filename, - oEvent.originalEvent.lineno, - location && location.toString ? location.toString() : '', - $html.attr('class'), - Utils.microtime() - Globals.now - ); - } - }); - - $document.on('keydown', function (oEvent) { - if (oEvent && oEvent.ctrlKey) - { - $html.addClass('rl-ctrl-key-pressed'); - } - }).on('keyup', function (oEvent) { - if (oEvent && !oEvent.ctrlKey) - { - $html.removeClass('rl-ctrl-key-pressed'); - } - }); -} - -_.extend(AbstractApp.prototype, KnoinAbstractBoot.prototype); - -AbstractApp.prototype.oSettings = null; -AbstractApp.prototype.oPlugins = null; -AbstractApp.prototype.oLocal = null; -AbstractApp.prototype.oLink = null; -AbstractApp.prototype.oSubs = {}; - -/** - * @param {string} sLink - * @return {boolean} - */ -AbstractApp.prototype.download = function (sLink) -{ - var - oLink = null, - oE = null, - sUserAgent = navigator.userAgent.toLowerCase() - ; - - if (sUserAgent && (sUserAgent.indexOf('chrome') > -1 || sUserAgent.indexOf('chrome') > -1)) - { - oLink = document.createElement('a'); - oLink['href'] = sLink; - - if (document['createEvent']) - { - oE = document['createEvent']('MouseEvents'); - if (oE && oE['initEvent'] && oLink['dispatchEvent']) - { - oE['initEvent']('click', true, true); - oLink['dispatchEvent'](oE); - return true; - } - } - } - - if (Globals.bMobileDevice) - { - window.open(sLink, '_self'); - window.focus(); - } - else - { - this.iframe.attr('src', sLink); -// window.document.location.href = sLink; - } - - return true; -}; - -/** - * @return {LinkBuilder} - */ -AbstractApp.prototype.link = function () -{ - if (null === this.oLink) - { - this.oLink = new LinkBuilder(); - } - - return this.oLink; -}; - -/** - * @return {LocalStorage} - */ -AbstractApp.prototype.local = function () -{ - if (null === this.oLocal) - { - this.oLocal = new LocalStorage(); - } - - return this.oLocal; -}; - -/** - * @param {string} sName - * @return {?} - */ -AbstractApp.prototype.settingsGet = function (sName) -{ - if (null === this.oSettings) - { - this.oSettings = Utils.isNormal(AppData) ? AppData : {}; - } - - return Utils.isUnd(this.oSettings[sName]) ? null : this.oSettings[sName]; -}; - -/** - * @param {string} sName - * @param {?} mValue - */ -AbstractApp.prototype.settingsSet = function (sName, mValue) -{ - if (null === this.oSettings) - { - this.oSettings = Utils.isNormal(AppData) ? AppData : {}; - } - - this.oSettings[sName] = mValue; -}; - -AbstractApp.prototype.setTitle = function (sTitle) -{ - sTitle = ((Utils.isNormal(sTitle) && 0 < sTitle.length) ? sTitle + ' - ' : '') + - RL.settingsGet('Title') || ''; - - window.document.title = '_'; - window.document.title = sTitle; -}; - -/** - * @param {boolean=} bLogout = false - * @param {boolean=} bClose = false - */ -AbstractApp.prototype.loginAndLogoutReload = function (bLogout, bClose) -{ - var - sCustomLogoutLink = Utils.pString(RL.settingsGet('CustomLogoutLink')), - bInIframe = !!RL.settingsGet('InIframe') - ; - - bLogout = Utils.isUnd(bLogout) ? false : !!bLogout; - bClose = Utils.isUnd(bClose) ? false : !!bClose; - - if (bLogout && bClose && window.close) - { - window.close(); - } - - if (bLogout && '' !== sCustomLogoutLink && window.location.href !== sCustomLogoutLink) - { - _.delay(function () { - if (bInIframe && window.parent) - { - window.parent.location.href = sCustomLogoutLink; - } - else - { - window.location.href = sCustomLogoutLink; - } - }, 100); - } - else - { - kn.routeOff(); - kn.setHash(RL.link().root(), true); - kn.routeOff(); - - _.delay(function () { - if (bInIframe && window.parent) - { - window.parent.location.reload(); - } - else - { - window.location.reload(); - } - }, 100); - } -}; - -AbstractApp.prototype.historyBack = function () -{ - window.history.back(); -}; - -/** - * @param {string} sQuery - * @param {Function} fCallback - */ -AbstractApp.prototype.getAutocomplete = function (sQuery, fCallback) -{ - fCallback([], sQuery); -}; - -/** - * @param {string} sName - * @param {Function} fFunc - * @param {Object=} oContext - * @return {AbstractApp} - */ -AbstractApp.prototype.sub = function (sName, fFunc, oContext) -{ - if (Utils.isUnd(this.oSubs[sName])) - { - this.oSubs[sName] = []; - } - - this.oSubs[sName].push([fFunc, oContext]); - - return this; -}; - -/** - * @param {string} sName - * @param {Array=} aArgs - * @return {AbstractApp} - */ -AbstractApp.prototype.pub = function (sName, aArgs) -{ - Plugins.runHook('rl-pub', [sName, aArgs]); - if (!Utils.isUnd(this.oSubs[sName])) - { - _.each(this.oSubs[sName], function (aItem) { - if (aItem[0]) - { - aItem[0].apply(aItem[1] || null, aArgs || []); - } - }); - } - - return this; -}; - -AbstractApp.prototype.bootstart = function () -{ - var self = this; - - Utils.initOnStartOrLangChange(function () { - Utils.initNotificationLanguage(); - }, null); - - _.delay(function () { - Utils.windowResize(); - }, 1000); - - ssm.addState({ - 'id': 'mobile', - 'maxWidth': 767, - 'onEnter': function() { - $html.addClass('ssm-state-mobile'); - self.pub('ssm.mobile-enter'); - }, - 'onLeave': function() { - $html.removeClass('ssm-state-mobile'); - self.pub('ssm.mobile-leave'); - } - }); - - ssm.addState({ - 'id': 'tablet', - 'minWidth': 768, - 'maxWidth': 999, - 'onEnter': function() { - $html.addClass('ssm-state-tablet'); - }, - 'onLeave': function() { - $html.removeClass('ssm-state-tablet'); - } - }); - - ssm.addState({ - 'id': 'desktop', - 'minWidth': 1000, - 'maxWidth': 1400, - 'onEnter': function() { - $html.addClass('ssm-state-desktop'); - }, - 'onLeave': function() { - $html.removeClass('ssm-state-desktop'); - } - }); - - ssm.addState({ - 'id': 'desktop-large', - 'minWidth': 1400, - 'onEnter': function() { - $html.addClass('ssm-state-desktop-large'); - }, - 'onLeave': function() { - $html.removeClass('ssm-state-desktop-large'); - } - }); - - RL.sub('ssm.mobile-enter', function () { - RL.data().leftPanelDisabled(true); - }); - - RL.sub('ssm.mobile-leave', function () { - RL.data().leftPanelDisabled(false); - }); - - RL.data().leftPanelDisabled.subscribe(function (bValue) { - $html.toggleClass('rl-left-panel-disabled', bValue); - }); - - ssm.ready(); -}; +ko.bindingHandlers.csstext = { + 'init': function (oElement, fValueAccessor) { + if (oElement && oElement.styleSheet && !Utils.isUnd(oElement.styleSheet.cssText)) + { + oElement.styleSheet.cssText = ko.utils.unwrapObservable(fValueAccessor()); + } + else + { + $(oElement).text(ko.utils.unwrapObservable(fValueAccessor())); + } + }, + 'update': function (oElement, fValueAccessor) { + if (oElement && oElement.styleSheet && !Utils.isUnd(oElement.styleSheet.cssText)) + { + oElement.styleSheet.cssText = ko.utils.unwrapObservable(fValueAccessor()); + } + else + { + $(oElement).text(ko.utils.unwrapObservable(fValueAccessor())); + } + } +}; -/** - * @constructor - * @extends AbstractApp - */ -function RainLoopApp() -{ - AbstractApp.call(this); - - this.oData = null; - this.oRemote = null; - this.oCache = null; - this.oMoveCache = {}; - - this.quotaDebounce = _.debounce(this.quota, 1000 * 30); - this.moveOrDeleteResponseHelper = _.bind(this.moveOrDeleteResponseHelper, this); - - this.messagesMoveTrigger = _.debounce(this.messagesMoveTrigger, 500); - - window.setInterval(function () { - RL.pub('interval.30s'); - }, 30000); - - window.setInterval(function () { - RL.pub('interval.1m'); - }, 60000); - - window.setInterval(function () { - RL.pub('interval.2m'); - }, 60000 * 2); - - window.setInterval(function () { - RL.pub('interval.3m'); - }, 60000 * 3); - - window.setInterval(function () { - RL.pub('interval.5m'); - }, 60000 * 5); - - window.setInterval(function () { - RL.pub('interval.10m'); - }, 60000 * 10); - - window.setTimeout(function () { - window.setInterval(function () { - RL.pub('interval.10m-after5m'); - }, 60000 * 10); - }, 60000 * 5); - - $.wakeUp(function () { - RL.remote().jsVersion(function (sResult, oData) { - if (Enums.StorageResultType.Success === sResult && oData && !oData.Result) - { - if (window.parent && !!RL.settingsGet('InIframe')) - { - window.parent.location.reload(); - } - else - { - window.location.reload(); - } - } - }, RL.settingsGet('Version')); - }, {}, 60 * 60 * 1000); -} - -_.extend(RainLoopApp.prototype, AbstractApp.prototype); - -RainLoopApp.prototype.oData = null; -RainLoopApp.prototype.oRemote = null; -RainLoopApp.prototype.oCache = null; - -/** - * @return {WebMailDataStorage} - */ -RainLoopApp.prototype.data = function () -{ - if (null === this.oData) - { - this.oData = new WebMailDataStorage(); - } - - return this.oData; -}; - -/** - * @return {WebMailAjaxRemoteStorage} - */ -RainLoopApp.prototype.remote = function () -{ - if (null === this.oRemote) - { - this.oRemote = new WebMailAjaxRemoteStorage(); - } - - return this.oRemote; -}; - -/** - * @return {WebMailCacheStorage} - */ -RainLoopApp.prototype.cache = function () -{ - if (null === this.oCache) - { - this.oCache = new WebMailCacheStorage(); - } - - return this.oCache; -}; - -RainLoopApp.prototype.reloadFlagsCurrentMessageListAndMessageFromCache = function () -{ - var oCache = RL.cache(); - _.each(RL.data().messageList(), function (oMessage) { - oCache.initMessageFlagsFromCache(oMessage); - }); - - oCache.initMessageFlagsFromCache(RL.data().message()); -}; - -/** - * @param {boolean=} bDropPagePosition = false - * @param {boolean=} bDropCurrenFolderCache = false - */ -RainLoopApp.prototype.reloadMessageList = function (bDropPagePosition, bDropCurrenFolderCache) -{ - var - oRLData = RL.data(), - iOffset = (oRLData.messageListPage() - 1) * oRLData.messagesPerPage() - ; - - if (Utils.isUnd(bDropCurrenFolderCache) ? false : !!bDropCurrenFolderCache) - { - RL.cache().setFolderHash(oRLData.currentFolderFullNameRaw(), ''); - } - - if (Utils.isUnd(bDropPagePosition) ? false : !!bDropPagePosition) - { - oRLData.messageListPage(1); - iOffset = 0; - } - - oRLData.messageListLoading(true); - RL.remote().messageList(function (sResult, oData, bCached) { - - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - oRLData.messageListError(''); - oRLData.messageListLoading(false); - oRLData.setMessageList(oData, bCached); - } - else if (Enums.StorageResultType.Unload === sResult) - { - oRLData.messageListError(''); - oRLData.messageListLoading(false); - } - else if (Enums.StorageResultType.Abort !== sResult) - { - oRLData.messageList([]); - oRLData.messageListLoading(false); - oRLData.messageListError(oData && oData.ErrorCode ? - Utils.getNotification(oData.ErrorCode) : Utils.i18n('NOTIFICATIONS/CANT_GET_MESSAGE_LIST') - ); - } - - }, oRLData.currentFolderFullNameRaw(), iOffset, oRLData.messagesPerPage(), oRLData.messageListSearch()); -}; - -RainLoopApp.prototype.recacheInboxMessageList = function () -{ - RL.remote().messageList(Utils.emptyFunction, 'INBOX', 0, RL.data().messagesPerPage(), '', true); -}; - -RainLoopApp.prototype.reloadMessageListHelper = function (bEmptyList) -{ - RL.reloadMessageList(bEmptyList); -}; - -/** - * @param {Function} fResultFunc - * @returns {boolean} - */ -RainLoopApp.prototype.contactsSync = function (fResultFunc) -{ - var oContacts = RL.data().contacts; - if (oContacts.importing() || oContacts.syncing() || !RL.data().enableContactsSync() || !RL.data().allowContactsSync()) - { - return false; - } - - oContacts.syncing(true); - - RL.remote().contactsSync(function (sResult, oData) { - - oContacts.syncing(false); - - if (fResultFunc) - { - fResultFunc(sResult, oData); - } - }); - - return true; -}; - -RainLoopApp.prototype.messagesMoveTrigger = function () -{ - var - self = this, - sSpamFolder = RL.data().spamFolder() - ; - - _.each(this.oMoveCache, function (oItem) { - - var - bSpam = sSpamFolder === oItem['To'], - bHam = !bSpam && sSpamFolder === oItem['From'] && 'INBOX' === oItem['To'] - ; - - RL.remote().messagesMove(self.moveOrDeleteResponseHelper, oItem['From'], oItem['To'], oItem['Uid'], - bSpam ? 'SPAM' : (bHam ? 'HAM' : '')); - }); - - this.oMoveCache = {}; -}; - -RainLoopApp.prototype.messagesMoveHelper = function (sFromFolderFullNameRaw, sToFolderFullNameRaw, aUidForMove) -{ - var sH = '$$' + sFromFolderFullNameRaw + '$$' + sToFolderFullNameRaw + '$$'; - if (!this.oMoveCache[sH]) - { - this.oMoveCache[sH] = { - 'From': sFromFolderFullNameRaw, - 'To': sToFolderFullNameRaw, - 'Uid': [] - }; - } - - this.oMoveCache[sH]['Uid'] = _.union(this.oMoveCache[sH]['Uid'], aUidForMove); - this.messagesMoveTrigger(); -}; - -RainLoopApp.prototype.messagesCopyHelper = function (sFromFolderFullNameRaw, sToFolderFullNameRaw, aUidForCopy) -{ - RL.remote().messagesCopy( - this.moveOrDeleteResponseHelper, - sFromFolderFullNameRaw, - sToFolderFullNameRaw, - aUidForCopy - ); -}; - -RainLoopApp.prototype.messagesDeleteHelper = function (sFromFolderFullNameRaw, aUidForRemove) -{ - RL.remote().messagesDelete( - this.moveOrDeleteResponseHelper, - sFromFolderFullNameRaw, - aUidForRemove - ); -}; - -RainLoopApp.prototype.moveOrDeleteResponseHelper = function (sResult, oData) -{ - if (Enums.StorageResultType.Success === sResult && RL.data().currentFolder()) - { - if (oData && Utils.isArray(oData.Result) && 2 === oData.Result.length) - { - RL.cache().setFolderHash(oData.Result[0], oData.Result[1]); - } - else - { - RL.cache().setFolderHash(RL.data().currentFolderFullNameRaw(), ''); - - if (oData && -1 < Utils.inArray(oData.ErrorCode, - [Enums.Notification.CantMoveMessage, Enums.Notification.CantCopyMessage])) - { - window.alert(Utils.getNotification(oData.ErrorCode)); - } - } - - RL.reloadMessageListHelper(0 === RL.data().messageList().length); - RL.quotaDebounce(); - } -}; - -/** - * @param {string} sFromFolderFullNameRaw - * @param {Array} aUidForRemove - */ -RainLoopApp.prototype.deleteMessagesFromFolderWithoutCheck = function (sFromFolderFullNameRaw, aUidForRemove) -{ - this.messagesDeleteHelper(sFromFolderFullNameRaw, aUidForRemove); - RL.data().removeMessagesFromList(sFromFolderFullNameRaw, aUidForRemove); -}; - -/** - * @param {number} iDeleteType - * @param {string} sFromFolderFullNameRaw - * @param {Array} aUidForRemove - * @param {boolean=} bUseFolder = true - */ -RainLoopApp.prototype.deleteMessagesFromFolder = function (iDeleteType, sFromFolderFullNameRaw, aUidForRemove, bUseFolder) -{ - var - self = this, - oData = RL.data(), - oCache = RL.cache(), - oMoveFolder = null, - nSetSystemFoldersNotification = null - ; - - switch (iDeleteType) - { - case Enums.FolderType.Spam: - oMoveFolder = oCache.getFolderFromCacheList(oData.spamFolder()); - nSetSystemFoldersNotification = Enums.SetSystemFoldersNotification.Spam; - break; - case Enums.FolderType.NotSpam: - oMoveFolder = oCache.getFolderFromCacheList('INBOX'); - break; - case Enums.FolderType.Trash: - oMoveFolder = oCache.getFolderFromCacheList(oData.trashFolder()); - nSetSystemFoldersNotification = Enums.SetSystemFoldersNotification.Trash; - break; - case Enums.FolderType.Archive: - oMoveFolder = oCache.getFolderFromCacheList(oData.archiveFolder()); - nSetSystemFoldersNotification = Enums.SetSystemFoldersNotification.Archive; - break; - } - - bUseFolder = Utils.isUnd(bUseFolder) ? true : !!bUseFolder; - if (bUseFolder) - { - if ((Enums.FolderType.Spam === iDeleteType && Consts.Values.UnuseOptionValue === oData.spamFolder()) || - (Enums.FolderType.Trash === iDeleteType && Consts.Values.UnuseOptionValue === oData.trashFolder()) || - (Enums.FolderType.Archive === iDeleteType && Consts.Values.UnuseOptionValue === oData.archiveFolder())) - { - bUseFolder = false; - } - } - - if (!oMoveFolder && bUseFolder) - { - kn.showScreenPopup(PopupsFolderSystemViewModel, [nSetSystemFoldersNotification]); - } - else if (!bUseFolder || (Enums.FolderType.Trash === iDeleteType && - (sFromFolderFullNameRaw === oData.spamFolder() || sFromFolderFullNameRaw === oData.trashFolder()))) - { - kn.showScreenPopup(PopupsAskViewModel, [Utils.i18n('POPUPS_ASK/DESC_WANT_DELETE_MESSAGES'), function () { - - self.messagesDeleteHelper(sFromFolderFullNameRaw, aUidForRemove); - oData.removeMessagesFromList(sFromFolderFullNameRaw, aUidForRemove); - - }]); - } - else if (oMoveFolder) - { - this.messagesMoveHelper(sFromFolderFullNameRaw, oMoveFolder.fullNameRaw, aUidForRemove); - oData.removeMessagesFromList(sFromFolderFullNameRaw, aUidForRemove, oMoveFolder.fullNameRaw); - } -}; - -/** - * @param {string} sFromFolderFullNameRaw - * @param {Array} aUidForMove - * @param {string} sToFolderFullNameRaw - * @param {boolean=} bCopy = false - */ -RainLoopApp.prototype.moveMessagesToFolder = function (sFromFolderFullNameRaw, aUidForMove, sToFolderFullNameRaw, bCopy) -{ - if (sFromFolderFullNameRaw !== sToFolderFullNameRaw && Utils.isArray(aUidForMove) && 0 < aUidForMove.length) - { - var - oFromFolder = RL.cache().getFolderFromCacheList(sFromFolderFullNameRaw), - oToFolder = RL.cache().getFolderFromCacheList(sToFolderFullNameRaw) - ; - - if (oFromFolder && oToFolder) - { - if (Utils.isUnd(bCopy) ? false : !!bCopy) - { - this.messagesCopyHelper(oFromFolder.fullNameRaw, oToFolder.fullNameRaw, aUidForMove); - } - else - { - this.messagesMoveHelper(oFromFolder.fullNameRaw, oToFolder.fullNameRaw, aUidForMove); - } - - RL.data().removeMessagesFromList(oFromFolder.fullNameRaw, aUidForMove, oToFolder.fullNameRaw, bCopy); - return true; - } - } - - return false; -}; - -/** - * @param {Function=} fCallback - */ -RainLoopApp.prototype.folders = function (fCallback) -{ - this.data().foldersLoading(true); - this.remote().folders(_.bind(function (sResult, oData) { - - RL.data().foldersLoading(false); - if (Enums.StorageResultType.Success === sResult) - { - this.data().setFolders(oData); - if (fCallback) - { - fCallback(true); - } - } - else - { - if (fCallback) - { - fCallback(false); - } - } - }, this)); -}; - -RainLoopApp.prototype.reloadOpenPgpKeys = function () -{ - if (RL.data().allowOpenPGP()) - { - var - aKeys = [], - oEmail = new EmailModel(), - oOpenpgpKeyring = RL.data().openpgpKeyring, - oOpenpgpKeys = oOpenpgpKeyring ? oOpenpgpKeyring.getAllKeys() : [] - ; - - _.each(oOpenpgpKeys, function (oItem, iIndex) { - if (oItem && oItem.primaryKey) - { - var - - oPrimaryUser = oItem.getPrimaryUser(), - sUser = (oPrimaryUser && oPrimaryUser.user) ? oPrimaryUser.user.userId.userid - : (oItem.users && oItem.users[0] ? oItem.users[0].userId.userid : '') - ; - - oEmail.clear(); - oEmail.mailsoParse(sUser); - - if (oEmail.validate()) - { - aKeys.push(new OpenPgpKeyModel( - iIndex, - oItem.primaryKey.getFingerprint(), - oItem.primaryKey.getKeyId().toHex().toLowerCase(), - sUser, - oEmail.email, - oItem.isPrivate(), - oItem.armor()) - ); - } - } - }); - - RL.data().openpgpkeys(aKeys); - } -}; - -RainLoopApp.prototype.accountsAndIdentities = function () -{ - var oRainLoopData = RL.data(); - - oRainLoopData.accountsLoading(true); - oRainLoopData.identitiesLoading(true); - - RL.remote().accountsAndIdentities(function (sResult, oData) { - - oRainLoopData.accountsLoading(false); - oRainLoopData.identitiesLoading(false); - - if (Enums.StorageResultType.Success === sResult && oData.Result) - { - var - sParentEmail = RL.settingsGet('ParentEmail'), - sAccountEmail = oRainLoopData.accountEmail() - ; - - sParentEmail = '' === sParentEmail ? sAccountEmail : sParentEmail; - - if (Utils.isArray(oData.Result['Accounts'])) - { - oRainLoopData.accounts(_.map(oData.Result['Accounts'], function (sValue) { - return new AccountModel(sValue, sValue !== sParentEmail); - })); - } - - if (Utils.isArray(oData.Result['Identities'])) - { - oRainLoopData.identities(_.map(oData.Result['Identities'], function (oIdentityData) { - - var - sId = Utils.pString(oIdentityData['Id']), - sEmail = Utils.pString(oIdentityData['Email']), - oIdentity = new IdentityModel(sId, sEmail, sId !== sAccountEmail) - ; - - oIdentity.name(Utils.pString(oIdentityData['Name'])); - oIdentity.replyTo(Utils.pString(oIdentityData['ReplyTo'])); - oIdentity.bcc(Utils.pString(oIdentityData['Bcc'])); - - return oIdentity; - })); - } - } - }); -}; - -RainLoopApp.prototype.quota = function () -{ - this.remote().quota(function (sResult, oData) { - if (Enums.StorageResultType.Success === sResult && oData && oData.Result && - Utils.isArray(oData.Result) && 1 < oData.Result.length && - Utils.isPosNumeric(oData.Result[0], true) && Utils.isPosNumeric(oData.Result[1], true)) - { - RL.data().userQuota(Utils.pInt(oData.Result[1]) * 1024); - RL.data().userUsageSize(Utils.pInt(oData.Result[0]) * 1024); - } - }); -}; - -/** - * @param {string} sFolder - * @param {Array=} aList = [] - */ -RainLoopApp.prototype.folderInformation = function (sFolder, aList) -{ - if ('' !== Utils.trim(sFolder)) - { - this.remote().folderInformation(function (sResult, oData) { - if (Enums.StorageResultType.Success === sResult) - { - if (oData && oData.Result && oData.Result.Hash && oData.Result.Folder) - { - var - iUtc = moment().unix(), - sHash = RL.cache().getFolderHash(oData.Result.Folder), - oFolder = RL.cache().getFolderFromCacheList(oData.Result.Folder), - bCheck = false, - sUid = '', - aList = [], - bUnreadCountChange = false, - oFlags = null - ; - - if (oFolder) - { - oFolder.interval = iUtc; - - if (oData.Result.Hash) - { - RL.cache().setFolderHash(oData.Result.Folder, oData.Result.Hash); - } - - if (Utils.isNormal(oData.Result.MessageCount)) - { - oFolder.messageCountAll(oData.Result.MessageCount); - } - - if (Utils.isNormal(oData.Result.MessageUnseenCount)) - { - if (Utils.pInt(oFolder.messageCountUnread()) !== Utils.pInt(oData.Result.MessageUnseenCount)) - { - bUnreadCountChange = true; - } - - oFolder.messageCountUnread(oData.Result.MessageUnseenCount); - } - - if (bUnreadCountChange) - { - RL.cache().clearMessageFlagsFromCacheByFolder(oFolder.fullNameRaw); - } - - if (oData.Result.Flags) - { - for (sUid in oData.Result.Flags) - { - if (oData.Result.Flags.hasOwnProperty(sUid)) - { - bCheck = true; - oFlags = oData.Result.Flags[sUid]; - RL.cache().storeMessageFlagsToCacheByFolderAndUid(oFolder.fullNameRaw, sUid.toString(), [ - !oFlags['IsSeen'], !!oFlags['IsFlagged'], !!oFlags['IsAnswered'], !!oFlags['IsForwarded'], !!oFlags['IsReadReceipt'] - ]); - } - } - - if (bCheck) - { - RL.reloadFlagsCurrentMessageListAndMessageFromCache(); - } - } - - RL.data().initUidNextAndNewMessages(oFolder.fullNameRaw, oData.Result.UidNext, oData.Result.NewMessages); - - if (oData.Result.Hash !== sHash || '' === sHash) - { - if (oFolder.fullNameRaw === RL.data().currentFolderFullNameRaw()) - { - RL.reloadMessageList(); - } - else if ('INBOX' === oFolder.fullNameRaw) - { - RL.recacheInboxMessageList(); - } - } - else if (bUnreadCountChange) - { - if (oFolder.fullNameRaw === RL.data().currentFolderFullNameRaw()) - { - aList = RL.data().messageList(); - if (Utils.isNonEmptyArray(aList)) - { - RL.folderInformation(oFolder.fullNameRaw, aList); - } - } - } - } - } - } - }, sFolder, aList); - } -}; - -/** - * @param {boolean=} bBoot = false - */ -RainLoopApp.prototype.folderInformationMultiply = function (bBoot) -{ - bBoot = Utils.isUnd(bBoot) ? false : !!bBoot; - - var - iUtc = moment().unix(), - aFolders = RL.data().getNextFolderNames(bBoot) - ; - - if (Utils.isNonEmptyArray(aFolders)) - { - this.remote().folderInformationMultiply(function (sResult, oData) { - if (Enums.StorageResultType.Success === sResult) - { - if (oData && oData.Result && oData.Result.List && Utils.isNonEmptyArray(oData.Result.List)) - { - _.each(oData.Result.List, function (oItem) { - - var - aList = [], - sHash = RL.cache().getFolderHash(oItem.Folder), - oFolder = RL.cache().getFolderFromCacheList(oItem.Folder), - bUnreadCountChange = false - ; - - if (oFolder) - { - oFolder.interval = iUtc; - - if (oItem.Hash) - { - RL.cache().setFolderHash(oItem.Folder, oItem.Hash); - } - - if (Utils.isNormal(oItem.MessageCount)) - { - oFolder.messageCountAll(oItem.MessageCount); - } - - if (Utils.isNormal(oItem.MessageUnseenCount)) - { - if (Utils.pInt(oFolder.messageCountUnread()) !== Utils.pInt(oItem.MessageUnseenCount)) - { - bUnreadCountChange = true; - } - - oFolder.messageCountUnread(oItem.MessageUnseenCount); - } - - if (bUnreadCountChange) - { - RL.cache().clearMessageFlagsFromCacheByFolder(oFolder.fullNameRaw); - } - - if (oItem.Hash !== sHash || '' === sHash) - { - if (oFolder.fullNameRaw === RL.data().currentFolderFullNameRaw()) - { - RL.reloadMessageList(); - } - } - else if (bUnreadCountChange) - { - if (oFolder.fullNameRaw === RL.data().currentFolderFullNameRaw()) - { - aList = RL.data().messageList(); - if (Utils.isNonEmptyArray(aList)) - { - RL.folderInformation(oFolder.fullNameRaw, aList); - } - } - } - } - }); - - if (bBoot) - { - RL.folderInformationMultiply(true); - } - } - } - }, aFolders); - } -}; - -RainLoopApp.prototype.setMessageSeen = function (oMessage) -{ - if (oMessage.unseen()) - { - oMessage.unseen(false); - - var oFolder = RL.cache().getFolderFromCacheList(oMessage.folderFullNameRaw); - if (oFolder) - { - oFolder.messageCountUnread(0 <= oFolder.messageCountUnread() - 1 ? - oFolder.messageCountUnread() - 1 : 0); - } - - RL.cache().storeMessageFlagsToCache(oMessage); - RL.reloadFlagsCurrentMessageListAndMessageFromCache(); - } - - RL.remote().messageSetSeen(Utils.emptyFunction, oMessage.folderFullNameRaw, [oMessage.uid], true); -}; - -RainLoopApp.prototype.googleConnect = function () -{ - window.open(RL.link().socialGoogle(), 'Google', 'left=200,top=100,width=650,height=600,menubar=no,status=no,resizable=yes,scrollbars=yes'); -}; - -RainLoopApp.prototype.twitterConnect = function () -{ - window.open(RL.link().socialTwitter(), 'Twitter', 'left=200,top=100,width=650,height=350,menubar=no,status=no,resizable=yes,scrollbars=yes'); -}; - -RainLoopApp.prototype.facebookConnect = function () -{ - window.open(RL.link().socialFacebook(), 'Facebook', 'left=200,top=100,width=650,height=335,menubar=no,status=no,resizable=yes,scrollbars=yes'); -}; - -/** - * @param {boolean=} bFireAllActions - */ -RainLoopApp.prototype.socialUsers = function (bFireAllActions) -{ - var oRainLoopData = RL.data(); - - if (bFireAllActions) - { - oRainLoopData.googleActions(true); - oRainLoopData.facebookActions(true); - oRainLoopData.twitterActions(true); - } - - RL.remote().socialUsers(function (sResult, oData) { - - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - oRainLoopData.googleUserName(oData.Result['Google'] || ''); - oRainLoopData.facebookUserName(oData.Result['Facebook'] || ''); - oRainLoopData.twitterUserName(oData.Result['Twitter'] || ''); - } - else - { - oRainLoopData.googleUserName(''); - oRainLoopData.facebookUserName(''); - oRainLoopData.twitterUserName(''); - } - - oRainLoopData.googleLoggined('' !== oRainLoopData.googleUserName()); - oRainLoopData.facebookLoggined('' !== oRainLoopData.facebookUserName()); - oRainLoopData.twitterLoggined('' !== oRainLoopData.twitterUserName()); - - oRainLoopData.googleActions(false); - oRainLoopData.facebookActions(false); - oRainLoopData.twitterActions(false); - }); -}; - -RainLoopApp.prototype.googleDisconnect = function () -{ - RL.data().googleActions(true); - RL.remote().googleDisconnect(function () { - RL.socialUsers(); - }); -}; - -RainLoopApp.prototype.facebookDisconnect = function () -{ - RL.data().facebookActions(true); - RL.remote().facebookDisconnect(function () { - RL.socialUsers(); - }); -}; - -RainLoopApp.prototype.twitterDisconnect = function () -{ - RL.data().twitterActions(true); - RL.remote().twitterDisconnect(function () { - RL.socialUsers(); - }); -}; - -/** - * @param {Array} aSystem - * @param {Array} aList - * @param {Array=} aDisabled - * @param {Array=} aHeaderLines - * @param {?number=} iUnDeep - * @param {Function=} fDisableCallback - * @param {Function=} fVisibleCallback - * @param {Function=} fRenameCallback - * @param {boolean=} bSystem - * @param {boolean=} bBuildUnvisible - * @return {Array} - */ -RainLoopApp.prototype.folderListOptionsBuilder = function (aSystem, aList, aDisabled, aHeaderLines, iUnDeep, fDisableCallback, fVisibleCallback, fRenameCallback, bSystem, bBuildUnvisible) -{ - var - iIndex = 0, - iLen = 0, - /** - * @type {?FolderModel} - */ - oItem = null, - bSep = false, - sDeepPrefix = '\u00A0\u00A0\u00A0', - aResult = [] - ; - - bSystem = !Utils.isNormal(bSystem) ? 0 < aSystem.length : bSystem; - bBuildUnvisible = Utils.isUnd(bBuildUnvisible) ? false : !!bBuildUnvisible; - iUnDeep = !Utils.isNormal(iUnDeep) ? 0 : iUnDeep; - fDisableCallback = Utils.isNormal(fDisableCallback) ? fDisableCallback : null; - fVisibleCallback = Utils.isNormal(fVisibleCallback) ? fVisibleCallback : null; - fRenameCallback = Utils.isNormal(fRenameCallback) ? fRenameCallback : null; - - if (!Utils.isArray(aDisabled)) - { - aDisabled = []; - } - - if (!Utils.isArray(aHeaderLines)) - { - aHeaderLines = []; - } - - for (iIndex = 0, iLen = aHeaderLines.length; iIndex < iLen; iIndex++) - { - aResult.push({ - 'id': aHeaderLines[iIndex][0], - 'name': aHeaderLines[iIndex][1], - 'system': false, - 'seporator': false, - 'disabled': false - }); - } - - bSep = true; - for (iIndex = 0, iLen = aSystem.length; iIndex < iLen; iIndex++) - { - oItem = aSystem[iIndex]; - if (fVisibleCallback ? fVisibleCallback.call(null, oItem) : true) - { - if (bSep && 0 < aResult.length) - { - aResult.push({ - 'id': '---', - 'name': '---', - 'system': false, - 'seporator': true, - 'disabled': true - }); - } - - bSep = false; - aResult.push({ - 'id': oItem.fullNameRaw, - 'name': fRenameCallback ? fRenameCallback.call(null, oItem) : oItem.name(), - 'system': true, - 'seporator': false, - 'disabled': !oItem.selectable || -1 < Utils.inArray(oItem.fullNameRaw, aDisabled) || - (fDisableCallback ? fDisableCallback.call(null, oItem) : false) - }); - } - } - - bSep = true; - for (iIndex = 0, iLen = aList.length; iIndex < iLen; iIndex++) - { - oItem = aList[iIndex]; - if (oItem.subScribed() || !oItem.existen) - { - if (fVisibleCallback ? fVisibleCallback.call(null, oItem) : true) - { - if (Enums.FolderType.User === oItem.type() || !bSystem || 0 < oItem.subFolders().length) - { - if (bSep && 0 < aResult.length) - { - aResult.push({ - 'id': '---', - 'name': '---', - 'system': false, - 'seporator': true, - 'disabled': true - }); - } - - bSep = false; - aResult.push({ - 'id': oItem.fullNameRaw, - 'name': (new window.Array(oItem.deep + 1 - iUnDeep)).join(sDeepPrefix) + - (fRenameCallback ? fRenameCallback.call(null, oItem) : oItem.name()), - 'system': false, - 'seporator': false, - 'disabled': !oItem.selectable || -1 < Utils.inArray(oItem.fullNameRaw, aDisabled) || - (fDisableCallback ? fDisableCallback.call(null, oItem) : false) - }); - } - } - } - - if (oItem.subScribed() && 0 < oItem.subFolders().length) - { - aResult = aResult.concat(RL.folderListOptionsBuilder([], oItem.subFolders(), aDisabled, [], - iUnDeep, fDisableCallback, fVisibleCallback, fRenameCallback, bSystem, bBuildUnvisible)); - } - } - - return aResult; -}; - -/** - * @param {string} sQuery - * @param {Function} fCallback - */ -RainLoopApp.prototype.getAutocomplete = function (sQuery, fCallback) -{ - var - aData = [] - ; - - RL.remote().suggestions(function (sResult, oData) { - if (Enums.StorageResultType.Success === sResult && oData && Utils.isArray(oData.Result)) - { - aData = _.map(oData.Result, function (aItem) { - return aItem && aItem[0] ? new EmailModel(aItem[0], aItem[1]) : null; - }); - - fCallback(_.compact(aData)); - } - else if (Enums.StorageResultType.Abort !== sResult) - { - fCallback([]); - } - - }, sQuery); -}; - -RainLoopApp.prototype.emailsPicsHashes = function () -{ - RL.remote().emailsPicsHashes(function (sResult, oData) { - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - RL.cache().setEmailsPicsHashesData(oData.Result); - } - }); -}; - -/** - * @param {string} sMailToUrl - * @returns {boolean} - */ -RainLoopApp.prototype.mailToHelper = function (sMailToUrl) -{ - if (sMailToUrl && 'mailto:' === sMailToUrl.toString().toLowerCase().substr(0, 7)) - { - var oEmailModel = null; - oEmailModel = new EmailModel(); - oEmailModel.parse(window.decodeURI(sMailToUrl.toString().substr(7).replace(/\?.+$/, ''))); - - if (oEmailModel && oEmailModel.email) - { - kn.showScreenPopup(PopupsComposeViewModel, [Enums.ComposeType.Empty, null, [oEmailModel]]); - return true; - } - } - - return false; -}; - -RainLoopApp.prototype.bootstart = function () -{ - RL.pub('rl.bootstart'); - AbstractApp.prototype.bootstart.call(this); - - RL.data().populateDataOnStart(); - - var - sCustomLoginLink = '', - sJsHash = RL.settingsGet('JsHash'), - iContactsSyncInterval = Utils.pInt(RL.settingsGet('ContactsSyncInterval')), - bGoogle = RL.settingsGet('AllowGoogleSocial'), - bFacebook = RL.settingsGet('AllowFacebookSocial'), - bTwitter = RL.settingsGet('AllowTwitterSocial') - ; - - if (!RL.settingsGet('ChangePasswordIsAllowed')) - { - Utils.removeSettingsViewModel(SettingsChangePasswordScreen); - } - - if (!RL.settingsGet('ContactsIsAllowed')) - { - Utils.removeSettingsViewModel(SettingsContacts); - } - - if (!RL.settingsGet('AllowAdditionalAccounts')) - { - Utils.removeSettingsViewModel(SettingsAccounts); - } - - if (RL.settingsGet('AllowIdentities')) - { - Utils.removeSettingsViewModel(SettingsIdentity); - } - else - { - Utils.removeSettingsViewModel(SettingsIdentities); - } - - if (!RL.settingsGet('OpenPGP')) - { - Utils.removeSettingsViewModel(SettingsOpenPGP); - } - - if (!RL.settingsGet('AllowTwoFactorAuth')) - { - Utils.removeSettingsViewModel(SettingsSecurity); - } - - if (!bGoogle && !bFacebook && !bTwitter) - { - Utils.removeSettingsViewModel(SettingsSocialScreen); - } - - if (!RL.settingsGet('AllowThemes')) - { - Utils.removeSettingsViewModel(SettingsThemes); - } - - Utils.initOnStartOrLangChange(function () { - - $.extend(true, $.magnificPopup.defaults, { - 'tClose': Utils.i18n('MAGNIFIC_POPUP/CLOSE'), - 'tLoading': Utils.i18n('MAGNIFIC_POPUP/LOADING'), - 'gallery': { - 'tPrev': Utils.i18n('MAGNIFIC_POPUP/GALLERY_PREV'), - 'tNext': Utils.i18n('MAGNIFIC_POPUP/GALLERY_NEXT'), - 'tCounter': Utils.i18n('MAGNIFIC_POPUP/GALLERY_COUNTER') - }, - 'image': { - 'tError': Utils.i18n('MAGNIFIC_POPUP/IMAGE_ERROR') - }, - 'ajax': { - 'tError': Utils.i18n('MAGNIFIC_POPUP/AJAX_ERROR') - } - }); - - }, this); - - if (window.SimplePace) - { - window.SimplePace.set(70); - window.SimplePace.sleep(); - } - - if (!!RL.settingsGet('Auth')) - { - this.setTitle(Utils.i18n('TITLES/LOADING')); - - this.folders(_.bind(function (bValue) { - - kn.hideLoading(); - - if (bValue) - { - if (window.crypto && window.crypto.getRandomValues && RL.settingsGet('OpenPGP')) - { - $.ajax({ - 'url': RL.link().openPgpJs(), - 'dataType': 'script', - 'cache': true, - 'success': function () { - if (window.openpgp) - { - RL.data().openpgpKeyring = new window.openpgp.Keyring(); - RL.data().allowOpenPGP(true); - - RL.pub('openpgp.init'); - - RL.reloadOpenPgpKeys(); - } - } - }); - } - else - { - RL.data().allowOpenPGP(false); - } - - kn.startScreens([MailBoxScreen, SettingsScreen]); - - if (bGoogle || bFacebook || bTwitter) - { - RL.socialUsers(true); - } - - RL.sub('interval.2m', function () { - RL.folderInformation('INBOX'); - }); - - RL.sub('interval.2m', function () { - var sF = RL.data().currentFolderFullNameRaw(); - if ('INBOX' !== sF) - { - RL.folderInformation(sF); - } - }); - - RL.sub('interval.3m', function () { - RL.folderInformationMultiply(); - }); - - RL.sub('interval.5m', function () { - RL.quota(); - }); - - RL.sub('interval.10m', function () { - RL.folders(); - }); - - iContactsSyncInterval = 5 <= iContactsSyncInterval ? iContactsSyncInterval : 20; - iContactsSyncInterval = 320 >= iContactsSyncInterval ? iContactsSyncInterval : 320; - - window.setInterval(function () { - RL.contactsSync(); - }, iContactsSyncInterval * 60000 + 5000); - - _.delay(function () { - RL.contactsSync(); - }, 5000); - - _.delay(function () { - RL.folderInformationMultiply(true); - }, 500); - - _.delay(function () { - - RL.emailsPicsHashes(); - - RL.remote().servicesPics(function (sResult, oData) { - if (Enums.StorageResultType.Success === sResult && oData && oData.Result) - { - RL.cache().setServicesData(oData.Result); - } - }); - - }, 2000); - - Plugins.runHook('rl-start-user-screens'); - RL.pub('rl.bootstart-user-screens'); - - if (!!RL.settingsGet('AccountSignMe') && window.navigator.registerProtocolHandler) - { - _.delay(function () { - try { - window.navigator.registerProtocolHandler('mailto', - window.location.protocol + '//' + window.location.host + window.location.pathname + '?mailto&to=%s', - '' + (RL.settingsGet('Title') || 'RainLoop')); - } catch(e) {} - - if (RL.settingsGet('MailToEmail')) - { - RL.mailToHelper(RL.settingsGet('MailToEmail')); - } - }, 500); - } - } - else - { - kn.startScreens([LoginScreen]); - - Plugins.runHook('rl-start-login-screens'); - RL.pub('rl.bootstart-login-screens'); - } - - if (window.SimplePace) - { - window.SimplePace.set(100); - } - - if (!Globals.bMobileDevice) - { - _.defer(function () { - Utils.initLayoutResizer('#rl-left', '#rl-right', Enums.ClientSideKeyName.FolderListSize); - }); - } - - }, this)); - } - else - { - sCustomLoginLink = Utils.pString(RL.settingsGet('CustomLoginLink')); - if (!sCustomLoginLink) - { - kn.hideLoading(); - kn.startScreens([LoginScreen]); - - Plugins.runHook('rl-start-login-screens'); - RL.pub('rl.bootstart-login-screens'); - - if (window.SimplePace) - { - window.SimplePace.set(100); - } - } - else - { - kn.routeOff(); - kn.setHash(RL.link().root(), true); - kn.routeOff(); - - _.defer(function () { - window.location.href = sCustomLoginLink; - }); - } - } - - if (bGoogle) - { - window['rl_' + sJsHash + '_google_service'] = function () { - RL.data().googleActions(true); - RL.socialUsers(); - }; - } - - if (bFacebook) - { - window['rl_' + sJsHash + '_facebook_service'] = function () { - RL.data().facebookActions(true); - RL.socialUsers(); - }; - } - - if (bTwitter) - { - window['rl_' + sJsHash + '_twitter_service'] = function () { - RL.data().twitterActions(true); - RL.socialUsers(); - }; - } - - RL.sub('interval.1m', function () { - Globals.momentTrigger(!Globals.momentTrigger()); - }); - - Plugins.runHook('rl-start-screens'); - RL.pub('rl.bootstart-end'); -}; - -/** - * @type {RainLoopApp} - */ -RL = new RainLoopApp(); +ko.bindingHandlers.resizecrop = { + 'init': function (oElement) { + $(oElement).addClass('resizecrop').resizecrop({ + 'width': '100', + 'height': '100', + 'wrapperCSS': { + 'border-radius': '10px' + } + }); + }, + 'update': function (oElement, fValueAccessor) { + fValueAccessor()(); + $(oElement).resizecrop({ + 'width': '100', + 'height': '100' + }); + } +}; -$html.addClass(Globals.bMobileDevice ? 'mobile' : 'no-mobile'); - -$window.keydown(Utils.killCtrlAandS).keyup(Utils.killCtrlAandS); -$window.unload(function () { - Globals.bUnload = true; -}); - -$html.on('click.dropdown.data-api', function () { - Utils.detectDropdownVisibility(); -}); - -// export -window['rl'] = window['rl'] || {}; -window['rl']['addHook'] = Plugins.addHook; -window['rl']['settingsGet'] = Plugins.mainSettingsGet; -window['rl']['remoteRequest'] = Plugins.remoteRequest; -window['rl']['pluginSettingsGet'] = Plugins.settingsGet; -window['rl']['addSettingsViewModel'] = Utils.addSettingsViewModel; -window['rl']['createCommand'] = Utils.createCommand; - -window['rl']['EmailModel'] = EmailModel; -window['rl']['Enums'] = Enums; - -window['__RLBOOT'] = function (fCall) { - - // boot - $(function () { - - if (window['rainloopTEMPLATES'] && window['rainloopTEMPLATES'][0]) - { - $('#rl-templates').html(window['rainloopTEMPLATES'][0]); - - _.delay(function () { - window['rainloopAppData'] = {}; - window['rainloopI18N'] = {}; - window['rainloopTEMPLATES'] = {}; - - kn.setBoot(RL).bootstart(); - $html.removeClass('no-js rl-booted-trigger').addClass('rl-booted'); - - }, 50); - } - else - { - fCall(false); - } - - window['__RLBOOT'] = null; - }); -}; +ko.bindingHandlers.onEnter = { + 'init': function (oElement, fValueAccessor, fAllBindingsAccessor, oViewModel) { + $(oElement).on('keypress', function (oEvent) { + if (oEvent && 13 === window.parseInt(oEvent.keyCode, 10)) + { + $(oElement).trigger('change'); + fValueAccessor().call(oViewModel); + } + }); + } +}; -if (window.SimplePace) { - window.SimplePace.add(10); +ko.bindingHandlers.onEsc = { + 'init': function (oElement, fValueAccessor, fAllBindingsAccessor, oViewModel) { + $(oElement).on('keypress', function (oEvent) { + if (oEvent && 27 === window.parseInt(oEvent.keyCode, 10)) + { + $(oElement).trigger('change'); + fValueAccessor().call(oViewModel); + } + }); + } +}; + +ko.bindingHandlers.clickOnTrue = { + 'update': function (oElement, fValueAccessor) { + if (ko.utils.unwrapObservable(fValueAccessor())) + { + $(oElement).click(); + } + } +}; + +ko.bindingHandlers.modal = { + 'init': function (oElement, fValueAccessor) { + + $(oElement).toggleClass('fade', !Globals.bMobileDevice).modal({ + 'keyboard': false, + 'show': ko.utils.unwrapObservable(fValueAccessor()) + }) + .on('shown', function () { + Utils.windowResize(); + }) + .find('.close').click(function () { + fValueAccessor()(false); + }); + }, + 'update': function (oElement, fValueAccessor) { + $(oElement).modal(ko.utils.unwrapObservable(fValueAccessor()) ? 'show' : 'hide'); + } +}; + +ko.bindingHandlers.i18nInit = { + 'init': function (oElement) { + Utils.i18nToNode(oElement); + } +}; + +ko.bindingHandlers.i18nUpdate = { + 'update': function (oElement, fValueAccessor) { + ko.utils.unwrapObservable(fValueAccessor()); + Utils.i18nToNode(oElement); + } +}; + +ko.bindingHandlers.link = { + 'update': function (oElement, fValueAccessor) { + $(oElement).attr('href', ko.utils.unwrapObservable(fValueAccessor())); + } +}; + +ko.bindingHandlers.title = { + 'update': function (oElement, fValueAccessor) { + $(oElement).attr('title', ko.utils.unwrapObservable(fValueAccessor())); + } +}; + +ko.bindingHandlers.textF = { + 'init': function (oElement, fValueAccessor) { + $(oElement).text(ko.utils.unwrapObservable(fValueAccessor())); + } +}; + +ko.bindingHandlers.initDom = { + 'init': function (oElement, fValueAccessor) { + fValueAccessor()(oElement); + } +}; + +ko.bindingHandlers.initResizeTrigger = { + 'init': function (oElement, fValueAccessor) { + var aValues = ko.utils.unwrapObservable(fValueAccessor()); + $(oElement).css({ + 'height': aValues[1], + 'min-height': aValues[1] + }); + }, + 'update': function (oElement, fValueAccessor) { + var + aValues = ko.utils.unwrapObservable(fValueAccessor()), + iValue = Utils.pInt(aValues[1]), + iSize = 0, + iOffset = $(oElement).offset().top + ; + + if (0 < iOffset) + { + iOffset += Utils.pInt(aValues[2]); + iSize = $window.height() - iOffset; + + if (iValue < iSize) + { + iValue = iSize; + } + + $(oElement).css({ + 'height': iValue, + 'min-height': iValue + }); + } + } +}; + +ko.bindingHandlers.appendDom = { + 'update': function (oElement, fValueAccessor) { + $(oElement).hide().empty().append(ko.utils.unwrapObservable(fValueAccessor())).show(); + } +}; + +ko.bindingHandlers.draggable = { + 'init': function (oElement, fValueAccessor, fAllBindingsAccessor) { + + if (!Globals.bMobileDevice) + { + var + iTriggerZone = 100, + iScrollSpeed = 3, + fAllValueFunc = fAllBindingsAccessor(), + sDroppableSelector = fAllValueFunc && fAllValueFunc['droppableSelector'] ? fAllValueFunc['droppableSelector'] : '', + oConf = { + 'distance': 20, + 'handle': '.dragHandle', + 'cursorAt': {'top': 22, 'left': 3}, + 'refreshPositions': true, + 'scroll': true + } + ; + + if (sDroppableSelector) + { + oConf['drag'] = function (oEvent) { + + $(sDroppableSelector).each(function () { + var + moveUp = null, + moveDown = null, + $this = $(this), + oOffset = $this.offset(), + bottomPos = oOffset.top + $this.height() + ; + + window.clearInterval($this.data('timerScroll')); + $this.data('timerScroll', false); + + if (oEvent.pageX >= oOffset.left && oEvent.pageX <= oOffset.left + $this.width()) + { + if (oEvent.pageY >= bottomPos - iTriggerZone && oEvent.pageY <= bottomPos) + { + moveUp = function() { + $this.scrollTop($this.scrollTop() + iScrollSpeed); + Utils.windowResize(); + }; + + $this.data('timerScroll', window.setInterval(moveUp, 10)); + moveUp(); + } + + if (oEvent.pageY >= oOffset.top && oEvent.pageY <= oOffset.top + iTriggerZone) + { + moveDown = function() { + $this.scrollTop($this.scrollTop() - iScrollSpeed); + Utils.windowResize(); + }; + + $this.data('timerScroll', window.setInterval(moveDown, 10)); + moveDown(); + } + } + }); + }; + + oConf['stop'] = function() { + $(sDroppableSelector).each(function () { + window.clearInterval($(this).data('timerScroll')); + $(this).data('timerScroll', false); + }); + }; + } + + oConf['helper'] = function (oEvent) { + return fValueAccessor()(oEvent && oEvent.target ? ko.dataFor(oEvent.target) : null); + }; + + $(oElement).draggable(oConf).on('mousedown', function () { + Utils.removeInFocus(); + }); + } + } +}; + +ko.bindingHandlers.droppable = { + 'init': function (oElement, fValueAccessor, fAllBindingsAccessor) { + + if (!Globals.bMobileDevice) + { + var + fValueFunc = fValueAccessor(), + fAllValueFunc = fAllBindingsAccessor(), + fOverCallback = fAllValueFunc && fAllValueFunc['droppableOver'] ? fAllValueFunc['droppableOver'] : null, + fOutCallback = fAllValueFunc && fAllValueFunc['droppableOut'] ? fAllValueFunc['droppableOut'] : null, + oConf = { + 'tolerance': 'pointer', + 'hoverClass': 'droppableHover' + } + ; + + if (fValueFunc) + { + oConf['drop'] = function (oEvent, oUi) { + fValueFunc(oEvent, oUi); + }; + + if (fOverCallback) + { + oConf['over'] = function (oEvent, oUi) { + fOverCallback(oEvent, oUi); + }; + } + + if (fOutCallback) + { + oConf['out'] = function (oEvent, oUi) { + fOutCallback(oEvent, oUi); + }; + } + + $(oElement).droppable(oConf); + } + } + } +}; + +ko.bindingHandlers.nano = { + 'init': function (oElement) { + if (!Globals.bDisableNanoScroll) + { + $(oElement) + .addClass('nano') + .nanoScroller({ + 'iOSNativeScrolling': false, + 'preventPageScrolling': true + }) + ; + } + } +}; + +ko.bindingHandlers.saveTrigger = { + 'init': function (oElement) { + + var $oEl = $(oElement); + + $oEl.data('save-trigger-type', $oEl.is('input[type=text],input[type=email],input[type=password],select,textarea') ? 'input' : 'custom'); + + if ('custom' === $oEl.data('save-trigger-type')) + { + $oEl.append( + ' ' + ).addClass('settings-saved-trigger'); + } + else + { + $oEl.addClass('settings-saved-trigger-input'); + } + }, + 'update': function (oElement, fValueAccessor) { + var + mValue = ko.utils.unwrapObservable(fValueAccessor()), + $oEl = $(oElement) + ; + + if ('custom' === $oEl.data('save-trigger-type')) + { + switch (mValue.toString()) + { + case '1': + $oEl + .find('.animated,.error').hide().removeClass('visible') + .end() + .find('.success').show().addClass('visible') + ; + break; + case '0': + $oEl + .find('.animated,.success').hide().removeClass('visible') + .end() + .find('.error').show().addClass('visible') + ; + break; + case '-2': + $oEl + .find('.error,.success').hide().removeClass('visible') + .end() + .find('.animated').show().addClass('visible') + ; + break; + default: + $oEl + .find('.animated').hide() + .end() + .find('.error,.success').removeClass('visible') + ; + break; + } + } + else + { + switch (mValue.toString()) + { + case '1': + $oEl.addClass('success').removeClass('error'); + break; + case '0': + $oEl.addClass('error').removeClass('success'); + break; + case '-2': +// $oEl; + break; + default: + $oEl.removeClass('error success'); + break; + } + } + } +}; + +ko.bindingHandlers.emailsTags = { + 'init': function(oElement, fValueAccessor) { + var + $oEl = $(oElement), + fValue = fValueAccessor() + ; + + $oEl.inputosaurus({ + 'parseOnBlur': true, + 'inputDelimiters': [',', ';'], + 'autoCompleteSource': function (oData, fResponse) { + RL.getAutocomplete(oData.term, function (aData) { + fResponse(_.map(aData, function (oEmailItem) { + return oEmailItem.toLine(false); + })); + }); + }, + 'parseHook': function (aInput) { + return _.map(aInput, function (sInputValue) { + + var + sValue = Utils.trim(sInputValue), + oEmail = null + ; + + if ('' !== sValue) + { + oEmail = new EmailModel(); + oEmail.mailsoParse(sValue); + oEmail.clearDuplicateName(); + return [oEmail.toLine(false), oEmail]; + } + + return [sValue, null]; + + }); + }, + 'change': _.bind(function (oEvent) { + $oEl.data('EmailsTagsValue', oEvent.target.value); + fValue(oEvent.target.value); + }, this) + }); + + fValue.subscribe(function (sValue) { + if ($oEl.data('EmailsTagsValue') !== sValue) + { + $oEl.val(sValue); + $oEl.data('EmailsTagsValue', sValue); + $oEl.inputosaurus('refresh'); + } + }); + + if (fValue.focusTrigger) + { + fValue.focusTrigger.subscribe(function () { + $oEl.inputosaurus('focus'); + }); + } + } +}; + +ko.bindingHandlers.command = { + 'init': function (oElement, fValueAccessor, fAllBindingsAccessor, oViewModel) { + var + jqElement = $(oElement), + oCommand = fValueAccessor() + ; + + if (!oCommand || !oCommand.enabled || !oCommand.canExecute) + { + throw new Error('You are not using command function'); + } + + jqElement.addClass('command'); + ko.bindingHandlers[jqElement.is('form') ? 'submit' : 'click'].init.apply(oViewModel, arguments); + }, + + 'update': function (oElement, fValueAccessor) { + + var + bResult = true, + jqElement = $(oElement), + oCommand = fValueAccessor() + ; + + bResult = oCommand.enabled(); + jqElement.toggleClass('command-not-enabled', !bResult); + + if (bResult) + { + bResult = oCommand.canExecute(); + jqElement.toggleClass('command-can-not-be-execute', !bResult); + } + + jqElement.toggleClass('command-disabled disable disabled', !bResult).toggleClass('no-disabled', !!bResult); + + if (jqElement.is('input') || jqElement.is('button')) + { + jqElement.prop('disabled', !bResult); + } + } +}; + +ko.extenders.trimmer = function (oTarget) +{ + var oResult = ko.computed({ + 'read': oTarget, + 'write': function (sNewValue) { + oTarget(Utils.trim(sNewValue.toString())); + }, + 'owner': this + }); + + oResult(oTarget()); + return oResult; +}; + +ko.extenders.reversible = function (oTarget) +{ + var mValue = oTarget(); + + oTarget.commit = function () + { + mValue = oTarget(); + }; + + oTarget.reverse = function () + { + oTarget(mValue); + }; + + oTarget.commitedValue = function () + { + return mValue; + }; + + return oTarget; +}; + +ko.extenders.toggleSubscribe = function (oTarget, oOptions) +{ + oTarget.subscribe(oOptions[1], oOptions[0], 'beforeChange'); + oTarget.subscribe(oOptions[2], oOptions[0]); + + return oTarget; +}; + +ko.extenders.falseTimeout = function (oTarget, iOption) +{ + oTarget.iTimeout = 0; + oTarget.subscribe(function (bValue) { + if (bValue) + { + window.clearTimeout(oTarget.iTimeout); + oTarget.iTimeout = window.setTimeout(function () { + oTarget(false); + oTarget.iTimeout = 0; + }, Utils.pInt(iOption)); + } + }); + + return oTarget; +}; + +ko.observable.fn.validateNone = function () +{ + this.hasError = ko.observable(false); + return this; +}; + +ko.observable.fn.validateEmail = function () +{ + this.hasError = ko.observable(false); + + this.subscribe(function (sValue) { + sValue = Utils.trim(sValue); + this.hasError('' !== sValue && !(/^[^@\s]+@[^@\s]+$/.test(sValue))); + }, this); + + this.valueHasMutated(); + return this; +}; + +ko.observable.fn.validateSimpleEmail = function () +{ + this.hasError = ko.observable(false); + + this.subscribe(function (sValue) { + sValue = Utils.trim(sValue); + this.hasError('' !== sValue && !(/^.+@.+$/.test(sValue))); + }, this); + + this.valueHasMutated(); + return this; +}; + +ko.observable.fn.validateFunc = function (fFunc) +{ + this.hasFuncError = ko.observable(false); + + if (Utils.isFunc(fFunc)) + { + this.subscribe(function (sValue) { + this.hasFuncError(!fFunc(sValue)); + }, this); + + this.valueHasMutated(); + } + + return this; +}; + + +/** + * @constructor + */ +function LinkBuilder() +{ + this.sBase = '#/'; + this.sVersion = RL.settingsGet('Version'); + this.sSpecSuffix = RL.settingsGet('AuthAccountHash') || '0'; + this.sServer = (RL.settingsGet('IndexFile') || './') + '?'; +} + +/** + * @return {string} + */ +LinkBuilder.prototype.root = function () +{ + return this.sBase; +}; + +/** + * @param {string} sDownload + * @return {string} + */ +LinkBuilder.prototype.attachmentDownload = function (sDownload) +{ + return this.sServer + '/Raw/' + this.sSpecSuffix + '/Download/' + sDownload; +}; + +/** + * @param {string} sDownload + * @return {string} + */ +LinkBuilder.prototype.attachmentPreview = function (sDownload) +{ + return this.sServer + '/Raw/' + this.sSpecSuffix + '/View/' + sDownload; +}; + +/** + * @param {string} sDownload + * @return {string} + */ +LinkBuilder.prototype.attachmentPreviewAsPlain = function (sDownload) +{ + return this.sServer + '/Raw/' + this.sSpecSuffix + '/ViewAsPlain/' + sDownload; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.upload = function () +{ + return this.sServer + '/Upload/' + this.sSpecSuffix + '/'; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.uploadContacts = function () +{ + return this.sServer + '/UploadContacts/' + this.sSpecSuffix + '/'; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.uploadBackground = function () +{ + return this.sServer + '/UploadBackground/' + this.sSpecSuffix + '/'; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.append = function () +{ + return this.sServer + '/Append/' + this.sSpecSuffix + '/'; +}; + +/** + * @param {string} sEmail + * @return {string} + */ +LinkBuilder.prototype.change = function (sEmail) +{ + return this.sServer + '/Change/' + this.sSpecSuffix + '/' + window.encodeURIComponent(sEmail) + '/'; +}; + +/** + * @param {string=} sAdd + * @return {string} + */ +LinkBuilder.prototype.ajax = function (sAdd) +{ + return this.sServer + '/Ajax/' + this.sSpecSuffix + '/' + sAdd; +}; + +/** + * @param {string} sRequestHash + * @return {string} + */ +LinkBuilder.prototype.messageViewLink = function (sRequestHash) +{ + return this.sServer + '/Raw/' + this.sSpecSuffix + '/ViewAsPlain/' + sRequestHash; +}; + +/** + * @param {string} sRequestHash + * @return {string} + */ +LinkBuilder.prototype.messageDownloadLink = function (sRequestHash) +{ + return this.sServer + '/Raw/' + this.sSpecSuffix + '/Download/' + sRequestHash; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.inbox = function () +{ + return this.sBase + 'mailbox/Inbox'; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.messagePreview = function () +{ + return this.sBase + 'mailbox/message-preview'; +}; + +/** + * @param {string=} sScreenName + * @return {string} + */ +LinkBuilder.prototype.settings = function (sScreenName) +{ + var sResult = this.sBase + 'settings'; + if (!Utils.isUnd(sScreenName) && '' !== sScreenName) + { + sResult += '/' + sScreenName; + } + + return sResult; +}; + +/** + * @param {string} sScreenName + * @return {string} + */ +LinkBuilder.prototype.admin = function (sScreenName) +{ + var sResult = this.sBase; + switch (sScreenName) { + case 'AdminDomains': + sResult += 'domains'; + break; + case 'AdminSecurity': + sResult += 'security'; + break; + case 'AdminLicensing': + sResult += 'licensing'; + break; + } + + return sResult; +}; + +/** + * @param {string} sFolder + * @param {number=} iPage = 1 + * @param {string=} sSearch = '' + * @return {string} + */ +LinkBuilder.prototype.mailBox = function (sFolder, iPage, sSearch) +{ + iPage = Utils.isNormal(iPage) ? Utils.pInt(iPage) : 1; + sSearch = Utils.pString(sSearch); + + var sResult = this.sBase + 'mailbox/'; + if ('' !== sFolder) + { + sResult += encodeURI(sFolder); + } + if (1 < iPage) + { + sResult = sResult.replace(/[\/]+$/, ''); + sResult += '/p' + iPage; + } + if ('' !== sSearch) + { + sResult = sResult.replace(/[\/]+$/, ''); + sResult += '/' + encodeURI(sSearch); + } + + return sResult; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.phpInfo = function () +{ + return this.sServer + 'Info'; +}; + +/** + * @param {string} sLang + * @return {string} + */ +LinkBuilder.prototype.langLink = function (sLang) +{ + return this.sServer + '/Lang/0/' + encodeURI(sLang) + '/' + this.sVersion + '/'; +}; + +/** + * @param {string} sHash + * @return {string} + */ +LinkBuilder.prototype.getUserPicUrlFromHash = function (sHash) +{ + return this.sServer + '/Raw/' + this.sSpecSuffix + '/UserPic/' + sHash + '/' + this.sVersion + '/'; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.exportContactsVcf = function () +{ + return this.sServer + '/Raw/' + this.sSpecSuffix + '/ContactsVcf/'; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.exportContactsCsv = function () +{ + return this.sServer + '/Raw/' + this.sSpecSuffix + '/ContactsCsv/'; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.emptyContactPic = function () +{ + return 'rainloop/v/' + this.sVersion + '/static/css/images/empty-contact.png'; +}; + +/** + * @param {string} sFileName + * @return {string} + */ +LinkBuilder.prototype.sound = function (sFileName) +{ + return 'rainloop/v/' + this.sVersion + '/static/sounds/' + sFileName; +}; + +/** + * @param {string} sTheme + * @return {string} + */ +LinkBuilder.prototype.themePreviewLink = function (sTheme) +{ + var sPrefix = 'rainloop/v/' + this.sVersion + '/'; + if ('@custom' === sTheme.substr(-7)) + { + sTheme = Utils.trim(sTheme.substring(0, sTheme.length - 7)); + sPrefix = ''; + } + + return sPrefix + 'themes/' + encodeURI(sTheme) + '/images/preview.png'; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.notificationMailIcon = function () +{ + return 'rainloop/v/' + this.sVersion + '/static/css/images/icom-message-notification.png'; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.openPgpJs = function () +{ + return 'rainloop/v/' + this.sVersion + '/static/js/openpgp.min.js'; +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.socialGoogle = function () +{ + return this.sServer + 'SocialGoogle' + ('' !== this.sSpecSuffix ? '/' + this.sSpecSuffix + '/' : ''); +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.socialTwitter = function () +{ + return this.sServer + 'SocialTwitter' + ('' !== this.sSpecSuffix ? '/' + this.sSpecSuffix + '/' : ''); +}; + +/** + * @return {string} + */ +LinkBuilder.prototype.socialFacebook = function () +{ + return this.sServer + 'SocialFacebook' + ('' !== this.sSpecSuffix ? '/' + this.sSpecSuffix + '/' : ''); +}; + +/** + * @type {Object} + */ +Plugins.oViewModelsHooks = {}; + +/** + * @type {Object} + */ +Plugins.oSimpleHooks = {}; + +/** + * @param {string} sName + * @param {Function} ViewModel + */ +Plugins.regViewModelHook = function (sName, ViewModel) +{ + if (ViewModel) + { + ViewModel.__hookName = sName; + } +}; + +/** + * @param {string} sName + * @param {Function} fCallback + */ +Plugins.addHook = function (sName, fCallback) +{ + if (Utils.isFunc(fCallback)) + { + if (!Utils.isArray(Plugins.oSimpleHooks[sName])) + { + Plugins.oSimpleHooks[sName] = []; + } + + Plugins.oSimpleHooks[sName].push(fCallback); + } +}; + +/** + * @param {string} sName + * @param {Array=} aArguments + */ +Plugins.runHook = function (sName, aArguments) +{ + if (Utils.isArray(Plugins.oSimpleHooks[sName])) + { + aArguments = aArguments || []; + + _.each(Plugins.oSimpleHooks[sName], function (fCallback) { + fCallback.apply(null, aArguments); + }); + } +}; + +/** + * @param {string} sName + * @return {?} + */ +Plugins.mainSettingsGet = function (sName) +{ + return RL ? RL.settingsGet(sName) : null; +}; + +/** + * @param {Function} fCallback + * @param {string} sAction + * @param {Object=} oParameters + * @param {?number=} iTimeout + * @param {string=} sGetAdd = '' + * @param {Array=} aAbortActions = [] + */ +Plugins.remoteRequest = function (fCallback, sAction, oParameters, iTimeout, sGetAdd, aAbortActions) +{ + if (RL) + { + RL.remote().defaultRequest(fCallback, sAction, oParameters, iTimeout, sGetAdd, aAbortActions); + } +}; + +/** + * @param {string} sPluginSection + * @param {string} sName + * @return {?} + */ +Plugins.settingsGet = function (sPluginSection, sName) +{ + var oPlugin = Plugins.mainSettingsGet('Plugins'); + oPlugin = oPlugin && Utils.isUnd(oPlugin[sPluginSection]) ? null : oPlugin[sPluginSection]; + return oPlugin ? (Utils.isUnd(oPlugin[sName]) ? null : oPlugin[sName]) : null; +}; + + + +function NewHtmlEditorWrapper(oElement, fOnBlur, fOnReady, fOnModeChange) +{ + var self = this; + self.editor = null; + self.iBlurTimer = 0; + self.fOnBlur = fOnBlur || null; + self.fOnReady = fOnReady || null; + self.fOnModeChange = fOnModeChange || null; + + self.$element = $(oElement); + + self.init(); +} + +NewHtmlEditorWrapper.prototype.blurTrigger = function () +{ + if (this.fOnBlur) + { + var self = this; + window.clearTimeout(self.iBlurTimer); + self.iBlurTimer = window.setTimeout(function () { + self.fOnBlur(); + }, 200); + } +}; + +NewHtmlEditorWrapper.prototype.focusTrigger = function () +{ + if (this.fOnBlur) + { + window.clearTimeout(this.iBlurTimer); + } +}; + +/** + * @return {boolean} + */ +NewHtmlEditorWrapper.prototype.isHtml = function () +{ + return this.editor ? 'wysiwyg' === this.editor.mode : false; +}; + +/** + * @return {boolean} + */ +NewHtmlEditorWrapper.prototype.checkDirty = function () +{ + return this.editor ? this.editor.checkDirty() : false; +}; + +NewHtmlEditorWrapper.prototype.resetDirty = function () +{ + if (this.editor) + { + this.editor.resetDirty(); + } +}; + +/** + * @return {string} + */ +NewHtmlEditorWrapper.prototype.getData = function () +{ + if (this.editor) + { + if ('plain' === this.editor.mode && this.editor.plugins.plain && this.editor.__plain) + { + return this.editor.__plain.getRawData(); + } + + return this.editor.getData(); + } + + return ''; +}; + +NewHtmlEditorWrapper.prototype.modeToggle = function (bPlain) +{ + if (this.editor) + { + if (bPlain) + { + if ('plain' === this.editor.mode) + { + this.editor.setMode('wysiwyg'); + } + } + else + { + if ('wysiwyg' === this.editor.mode) + { + this.editor.setMode('plain'); + } + } + } +}; + +NewHtmlEditorWrapper.prototype.setHtml = function (sHtml, bFocus) +{ + if (this.editor) + { + this.modeToggle(true); + this.editor.setData(sHtml); + + if (bFocus) + { + this.focus(); + } + } +}; + +NewHtmlEditorWrapper.prototype.setPlain = function (sPlain, bFocus) +{ + if (this.editor) + { + this.modeToggle(false); + if ('plain' === this.editor.mode && this.editor.plugins.plain && this.editor.__plain) + { + return this.editor.__plain.setRawData(sPlain); + } + else + { + this.editor.setData(sPlain); + } + + if (bFocus) + { + this.focus(); + } + } +}; + +NewHtmlEditorWrapper.prototype.init = function () +{ + if (this.$element && this.$element[0]) + { + var + self = this, + oConfig = Globals.oHtmlEditorDefaultConfig, + sLanguage = RL.settingsGet('Language'), + bSource = !!RL.settingsGet('AllowHtmlEditorSourceButton') + ; + + if (bSource && oConfig.toolbarGroups && !oConfig.toolbarGroups.__SourceInited) + { + oConfig.toolbarGroups.__SourceInited = true; + oConfig.toolbarGroups.push({name: 'document', groups: ['mode', 'document', 'doctools']}); + } + + oConfig.language = Globals.oHtmlEditorLangsMap[sLanguage] || 'en'; + self.editor = window.CKEDITOR.appendTo(self.$element[0], oConfig); + + self.editor.on('key', function(oEvent) { + if (oEvent && oEvent.data && 9 === oEvent.data.keyCode) + { + return false; + } + }); + + self.editor.on('blur', function() { + self.blurTrigger(); + }); + + self.editor.on('mode', function() { + self.blurTrigger(); + + if (self.fOnModeChange) + { + self.fOnModeChange('plain' !== self.editor.mode); + } + }); + + self.editor.on('focus', function() { + self.focusTrigger(); + }); + + if (self.fOnReady) + { + self.editor.on('instanceReady', function () { + + self.editor.setKeystroke(window.CKEDITOR.CTRL + 65 /* A */, 'selectAll'); + + self.fOnReady(); + self.__resizable = true; + self.resize(); + }); + } + } +}; + +NewHtmlEditorWrapper.prototype.focus = function () +{ + if (this.editor) + { + this.editor.focus(); + } +}; + +NewHtmlEditorWrapper.prototype.blur = function () +{ + if (this.editor) + { + this.editor.focusManager.blur(true); + } +}; + +NewHtmlEditorWrapper.prototype.resize = function () +{ + if (this.editor && this.__resizable) + { + this.editor.resize(this.$element.width(), this.$element.innerHeight()); + } +}; + +NewHtmlEditorWrapper.prototype.clear = function (bFocus) +{ + this.setHtml('', bFocus); +}; + + +/** + * @constructor + * @param {koProperty} oKoList + * @param {koProperty} oKoSelectedItem + * @param {string} sItemSelector + * @param {string} sItemSelectedSelector + * @param {string} sItemCheckedSelector + * @param {string} sItemFocusedSelector + */ +function Selector(oKoList, oKoSelectedItem, + sItemSelector, sItemSelectedSelector, sItemCheckedSelector, sItemFocusedSelector) +{ + this.list = oKoList; + + this.listChecked = ko.computed(function () { + return _.filter(this.list(), function (oItem) { + return oItem.checked(); + }); + }, this).extend({'rateLimit': 0}); + + this.isListChecked = ko.computed(function () { + return 0 < this.listChecked().length; + }, this); + + this.focusedItem = ko.observable(null); + this.selectedItem = oKoSelectedItem; + this.selectedItemUseCallback = true; + + this.itemSelectedThrottle = _.debounce(_.bind(this.itemSelected, this), 300); + + this.listChecked.subscribe(function (aItems) { + if (0 < aItems.length) + { + if (null === this.selectedItem()) + { + this.selectedItem.valueHasMutated(); + } + else + { + this.selectedItem(null); + } + } + else if (this.bAutoSelect && this.focusedItem()) + { + this.selectedItem(this.focusedItem()); + } + }, this); + + this.selectedItem.subscribe(function (oItem) { + + if (oItem) + { + if (this.isListChecked()) + { + _.each(this.listChecked(), function (oSubItem) { + oSubItem.checked(false); + }); + } + + if (this.selectedItemUseCallback) + { + this.itemSelectedThrottle(oItem); + } + } + else if (this.selectedItemUseCallback) + { + this.itemSelected(null); + } + + }, this); + + this.selectedItem.extend({'toggleSubscribe': [null, + function (oPrev) { + if (oPrev) + { + oPrev.selected(false); + } + }, function (oNext) { + if (oNext) + { + oNext.selected(true); + } + } + ]}); + + this.focusedItem.extend({'toggleSubscribe': [null, + function (oPrev) { + if (oPrev) + { + oPrev.focused(false); + } + }, function (oNext) { + if (oNext) + { + oNext.focused(true); + } + } + ]}); + + this.oContentVisible = null; + this.oContentScrollable = null; + + this.sItemSelector = sItemSelector; + this.sItemSelectedSelector = sItemSelectedSelector; + this.sItemCheckedSelector = sItemCheckedSelector; + this.sItemFocusedSelector = sItemFocusedSelector; + + this.sLastUid = ''; + this.bAutoSelect = true; + this.oCallbacks = {}; + + this.emptyFunction = function () {}; + + this.focusedItem.subscribe(function (oItem) { + if (oItem) + { + this.sLastUid = this.getItemUid(oItem); + } + }, this); + + var + aCache = [], + aCheckedCache = [], + mFocused = null, + mSelected = null + ; + + this.list.subscribe(function (aItems) { + + var self = this; + if (Utils.isArray(aItems)) + { + _.each(aItems, function (oItem) { + if (oItem) + { + var sUid = self.getItemUid(oItem); + + aCache.push(sUid); + if (oItem.checked()) + { + aCheckedCache.push(sUid); + } + if (null === mFocused && oItem.focused()) + { + mFocused = sUid; + } + if (null === mSelected && oItem.selected()) + { + mSelected = sUid; + } + } + }); + } + }, this, 'beforeChange'); + + this.list.subscribe(function (aItems) { + + var + self = this, + oTemp = null, + bGetNext = false, + aUids = [], + mNextFocused = mFocused, + bChecked = false, + bSelected = false, + iLen = 0 + ; + + this.selectedItemUseCallback = false; + + this.focusedItem(null); + this.selectedItem(null); + + if (Utils.isArray(aItems)) + { + iLen = aCheckedCache.length; + + _.each(aItems, function (oItem) { + + var sUid = self.getItemUid(oItem); + aUids.push(sUid); + + if (null !== mFocused && mFocused === sUid) + { + self.focusedItem(oItem); + mFocused = null; + } + + if (0 < iLen && -1 < Utils.inArray(sUid, aCheckedCache)) + { + bChecked = true; + oItem.checked(true); + iLen--; + } + + if (!bChecked && null !== mSelected && mSelected === sUid) + { + bSelected = true; + self.selectedItem(oItem); + mSelected = null; + } + }); + + this.selectedItemUseCallback = true; + + if (!bChecked && !bSelected && this.bAutoSelect) + { + if (self.focusedItem()) + { + self.selectedItem(self.focusedItem()); + } + else if (0 < aItems.length) + { + if (null !== mNextFocused) + { + bGetNext = false; + mNextFocused = _.find(aCache, function (sUid) { + if (bGetNext && -1 < Utils.inArray(sUid, aUids)) + { + return sUid; + } + else if (mNextFocused === sUid) + { + bGetNext = true; + } + return false; + }); + + if (mNextFocused) + { + oTemp = _.find(aItems, function (oItem) { + return mNextFocused === self.getItemUid(oItem); + }); + } + } + + self.selectedItem(oTemp || null); + self.focusedItem(self.selectedItem()); + } + } + } + + aCache = []; + aCheckedCache = []; + mFocused = null; + mSelected = null; + + }, this); +} + +Selector.prototype.itemSelected = function (oItem) +{ + if (this.isListChecked()) + { + if (!oItem) + { + (this.oCallbacks['onItemSelect'] || this.emptyFunction)(oItem || null); + } + } + else + { + if (oItem) + { + (this.oCallbacks['onItemSelect'] || this.emptyFunction)(oItem); + } + } +}; + +Selector.prototype.goDown = function (bForceSelect) +{ + this.newSelectPosition(Enums.EventKeyCode.Down, false, bForceSelect); +}; + +Selector.prototype.goUp = function (bForceSelect) +{ + this.newSelectPosition(Enums.EventKeyCode.Up, false, bForceSelect); +}; + +Selector.prototype.init = function (oContentVisible, oContentScrollable, sKeyScope) +{ + this.oContentVisible = oContentVisible; + this.oContentScrollable = oContentScrollable; + + sKeyScope = sKeyScope || 'all'; + + if (this.oContentVisible && this.oContentScrollable) + { + var + self = this + ; + + $(this.oContentVisible) + .on('selectstart', function (oEvent) { + if (oEvent && oEvent.preventDefault) + { + oEvent.preventDefault(); + } + }) + .on('click', this.sItemSelector, function (oEvent) { + self.actionClick(ko.dataFor(this), oEvent); + }) + .on('click', this.sItemCheckedSelector, function (oEvent) { + var oItem = ko.dataFor(this); + if (oItem) + { + if (oEvent && oEvent.shiftKey) + { + self.actionClick(oItem, oEvent); + } + else + { + self.focusedItem(oItem); + oItem.checked(!oItem.checked()); + } + } + }) + ; + + key('enter', sKeyScope, function () { + if (self.focusedItem() && !self.focusedItem().selected()) + { + self.actionClick(self.focusedItem()); + return false; + } + + return true; + }); + + key('ctrl+up, command+up, ctrl+down, command+down', sKeyScope, function () { + return false; + }); + + key('up, shift+up, down, shift+down, home, end, pageup, pagedown, insert, space', sKeyScope, function (event, handler) { + if (event && handler && handler.shortcut) + { + // TODO + var iKey = 0; + switch (handler.shortcut) + { + case 'up': + case 'shift+up': + iKey = Enums.EventKeyCode.Up; + break; + case 'down': + case 'shift+down': + iKey = Enums.EventKeyCode.Down; + break; + case 'insert': + iKey = Enums.EventKeyCode.Insert; + break; + case 'space': + iKey = Enums.EventKeyCode.Space; + break; + case 'home': + iKey = Enums.EventKeyCode.Home; + break; + case 'end': + iKey = Enums.EventKeyCode.End; + break; + case 'pageup': + iKey = Enums.EventKeyCode.PageUp; + break; + case 'pagedown': + iKey = Enums.EventKeyCode.PageDown; + break; + } + + if (0 < iKey) + { + self.newSelectPosition(iKey, key.shift); + return false; + } + } + }); + } +}; + +Selector.prototype.autoSelect = function (bValue) +{ + this.bAutoSelect = !!bValue; +}; + +/** + * @param {Object} oItem + * @returns {string} + */ +Selector.prototype.getItemUid = function (oItem) +{ + var + sUid = '', + fGetItemUidCallback = this.oCallbacks['onItemGetUid'] || null + ; + + if (fGetItemUidCallback && oItem) + { + sUid = fGetItemUidCallback(oItem); + } + + return sUid.toString(); +}; + +/** + * @param {number} iEventKeyCode + * @param {boolean} bShiftKey + * @param {boolean=} bForceSelect = false + */ +Selector.prototype.newSelectPosition = function (iEventKeyCode, bShiftKey, bForceSelect) +{ + var + iIndex = 0, + iPageStep = 10, + bNext = false, + bStop = false, + oResult = null, + aList = this.list(), + iListLen = aList ? aList.length : 0, + oFocused = this.focusedItem() + ; + + if (0 < iListLen) + { + if (!oFocused) + { + if (Enums.EventKeyCode.Down === iEventKeyCode || Enums.EventKeyCode.Insert === iEventKeyCode || Enums.EventKeyCode.Space === iEventKeyCode || Enums.EventKeyCode.Home === iEventKeyCode || Enums.EventKeyCode.PageUp === iEventKeyCode) + { + oResult = aList[0]; + } + else if (Enums.EventKeyCode.Up === iEventKeyCode || Enums.EventKeyCode.End === iEventKeyCode || Enums.EventKeyCode.PageDown === iEventKeyCode) + { + oResult = aList[aList.length - 1]; + } + } + else if (oFocused) + { + if (Enums.EventKeyCode.Down === iEventKeyCode || Enums.EventKeyCode.Up === iEventKeyCode || Enums.EventKeyCode.Insert === iEventKeyCode || Enums.EventKeyCode.Space === iEventKeyCode) + { + _.each(aList, function (oItem) { + if (!bStop) + { + switch (iEventKeyCode) { + case Enums.EventKeyCode.Up: + if (oFocused === oItem) + { + bStop = true; + } + else + { + oResult = oItem; + } + break; + case Enums.EventKeyCode.Down: + case Enums.EventKeyCode.Insert: + if (bNext) + { + oResult = oItem; + bStop = true; + } + else if (oFocused === oItem) + { + bNext = true; + } + break; + } + } + }); + } + else if (Enums.EventKeyCode.Home === iEventKeyCode || Enums.EventKeyCode.End === iEventKeyCode) + { + if (Enums.EventKeyCode.Home === iEventKeyCode) + { + oResult = aList[0]; + } + else if (Enums.EventKeyCode.End === iEventKeyCode) + { + oResult = aList[aList.length - 1]; + } + } + else if (Enums.EventKeyCode.PageDown === iEventKeyCode) + { + for (; iIndex < iListLen; iIndex++) + { + if (oFocused === aList[iIndex]) + { + iIndex += iPageStep; + iIndex = iListLen - 1 < iIndex ? iListLen - 1 : iIndex; + oResult = aList[iIndex]; + break; + } + } + } + else if (Enums.EventKeyCode.PageUp === iEventKeyCode) + { + for (iIndex = iListLen; iIndex >= 0; iIndex--) + { + if (oFocused === aList[iIndex]) + { + iIndex -= iPageStep; + iIndex = 0 > iIndex ? 0 : iIndex; + oResult = aList[iIndex]; + break; + } + } + } + } + } + + if (oResult) + { + this.focusedItem(oResult); + + if (oFocused) + { + if (bShiftKey) + { + if (Enums.EventKeyCode.Up === iEventKeyCode || Enums.EventKeyCode.Down === iEventKeyCode) + { + oFocused.checked(!oFocused.checked()); + } + } + else if (Enums.EventKeyCode.Insert === iEventKeyCode || Enums.EventKeyCode.Space === iEventKeyCode) + { + oFocused.checked(!oFocused.checked()); + } + } + + if ((this.bAutoSelect || !!bForceSelect) && + !this.isListChecked() && Enums.EventKeyCode.Space !== iEventKeyCode) + { + this.selectedItem(oResult); + } + + this.scrollToFocused(); + } + else if (oFocused) + { + if (bShiftKey && (Enums.EventKeyCode.Up === iEventKeyCode || Enums.EventKeyCode.Down === iEventKeyCode)) + { + oFocused.checked(!oFocused.checked()); + } + else if (Enums.EventKeyCode.Insert === iEventKeyCode || Enums.EventKeyCode.Space === iEventKeyCode) + { + oFocused.checked(!oFocused.checked()); + } + + this.focusedItem(oFocused); + } +}; + +/** + * @return {boolean} + */ +Selector.prototype.scrollToFocused = function () +{ + if (!this.oContentVisible || !this.oContentScrollable) + { + return false; + } + + var + iOffset = 20, + oFocused = $(this.sItemFocusedSelector, this.oContentScrollable), + oPos = oFocused.position(), + iVisibleHeight = this.oContentVisible.height(), + iFocusedHeight = oFocused.outerHeight() + ; + + if (oPos && (oPos.top < 0 || oPos.top + iFocusedHeight > iVisibleHeight)) + { + if (oPos.top < 0) + { + this.oContentScrollable.scrollTop(this.oContentScrollable.scrollTop() + oPos.top - iOffset); + } + else + { + this.oContentScrollable.scrollTop(this.oContentScrollable.scrollTop() + oPos.top - iVisibleHeight + iFocusedHeight + iOffset); + } + + return true; + } + + return false; +}; + +/** + * @param {boolean=} bFast = false + * @return {boolean} + */ +Selector.prototype.scrollToTop = function (bFast) +{ + if (!this.oContentVisible || !this.oContentScrollable) + { + return false; + } + + if (bFast) + { + this.oContentScrollable.scrollTop(0); + } + else + { + this.oContentScrollable.stop().animate({'scrollTop': 0}, 200); + } + + return true; +}; + +Selector.prototype.eventClickFunction = function (oItem, oEvent) +{ + var + sUid = this.getItemUid(oItem), + iIndex = 0, + iLength = 0, + oListItem = null, + sLineUid = '', + bChangeRange = false, + bIsInRange = false, + aList = [], + bChecked = false + ; + + if (oEvent && oEvent.shiftKey) + { + if ('' !== sUid && '' !== this.sLastUid && sUid !== this.sLastUid) + { + aList = this.list(); + bChecked = oItem.checked(); + + for (iIndex = 0, iLength = aList.length; iIndex < iLength; iIndex++) + { + oListItem = aList[iIndex]; + sLineUid = this.getItemUid(oListItem); + + bChangeRange = false; + if (sLineUid === this.sLastUid || sLineUid === sUid) + { + bChangeRange = true; + } + + if (bChangeRange) + { + bIsInRange = !bIsInRange; + } + + if (bIsInRange || bChangeRange) + { + oListItem.checked(bChecked); + } + } + } + } + + this.sLastUid = '' === sUid ? '' : sUid; +}; + +/** + * @param {Object} oItem + * @param {Object=} oEvent + */ +Selector.prototype.actionClick = function (oItem, oEvent) +{ + if (oItem) + { + var + bClick = true, + sUid = this.getItemUid(oItem) + ; + + if (oEvent) + { + if (oEvent.shiftKey && !oEvent.ctrlKey && !oEvent.altKey) + { + bClick = false; + if ('' === this.sLastUid) + { + this.sLastUid = sUid; + } + + oItem.checked(!oItem.checked()); + this.eventClickFunction(oItem, oEvent); + + this.focusedItem(oItem); + } + else if (oEvent.ctrlKey && !oEvent.shiftKey && !oEvent.altKey) + { + bClick = false; + this.focusedItem(oItem); + + if (this.selectedItem() && oItem !== this.selectedItem()) + { + this.selectedItem().checked(true); + } + + oItem.checked(!oItem.checked()); + } + } + + if (bClick) + { + this.focusedItem(oItem); + this.selectedItem(oItem); + } + } +}; + +Selector.prototype.on = function (sEventName, fCallback) +{ + this.oCallbacks[sEventName] = fCallback; +}; + +/** + * @constructor + */ +function CookieDriver() +{ + +} + +CookieDriver.supported = function () +{ + return true; +}; + +/** + * @param {string} sKey + * @param {*} mData + * @returns {boolean} + */ +CookieDriver.prototype.set = function (sKey, mData) +{ + var + mCokieValue = $.cookie(Consts.Values.ClientSideCookieIndexName), + bResult = false, + mResult = null + ; + + try + { + mResult = null === mCokieValue ? null : JSON.parse(mCokieValue); + if (!mResult) + { + mResult = {}; + } + + mResult[sKey] = mData; + $.cookie(Consts.Values.ClientSideCookieIndexName, JSON.stringify(mResult), { + 'expires': 30 + }); + + bResult = true; + } + catch (oException) {} + + return bResult; +}; + +/** + * @param {string} sKey + * @returns {*} + */ +CookieDriver.prototype.get = function (sKey) +{ + var + mCokieValue = $.cookie(Consts.Values.ClientSideCookieIndexName), + mResult = null + ; + + try + { + mResult = null === mCokieValue ? null : JSON.parse(mCokieValue); + if (mResult && !Utils.isUnd(mResult[sKey])) + { + mResult = mResult[sKey]; + } + else + { + mResult = null; + } + } + catch (oException) {} + + return mResult; +}; + +/** + * @constructor + */ +function LocalStorageDriver() +{ +} + +LocalStorageDriver.supported = function () +{ + return !!window.localStorage; +}; + +/** + * @param {string} sKey + * @param {*} mData + * @returns {boolean} + */ +LocalStorageDriver.prototype.set = function (sKey, mData) +{ + var + mCookieValue = window.localStorage[Consts.Values.ClientSideCookieIndexName] || null, + bResult = false, + mResult = null + ; + + try + { + mResult = null === mCookieValue ? null : JSON.parse(mCookieValue); + if (!mResult) + { + mResult = {}; + } + + mResult[sKey] = mData; + window.localStorage[Consts.Values.ClientSideCookieIndexName] = JSON.stringify(mResult); + + bResult = true; + } + catch (oException) {} + + return bResult; +}; + +/** + * @param {string} sKey + * @returns {*} + */ +LocalStorageDriver.prototype.get = function (sKey) +{ + var + mCokieValue = window.localStorage[Consts.Values.ClientSideCookieIndexName] || null, + mResult = null + ; + + try + { + mResult = null === mCokieValue ? null : JSON.parse(mCokieValue); + if (mResult && !Utils.isUnd(mResult[sKey])) + { + mResult = mResult[sKey]; + } + else + { + mResult = null; + } + } + catch (oException) {} + + return mResult; +}; + +/** + * @constructor + */ +function LocalStorage() +{ + var + sStorages = [ + LocalStorageDriver, + CookieDriver + ], + NextStorageDriver = _.find(sStorages, function (NextStorageDriver) { + return NextStorageDriver.supported(); + }) + ; + + if (NextStorageDriver) + { + NextStorageDriver = /** @type {?Function} */ NextStorageDriver; + this.oDriver = new NextStorageDriver(); + } +} + +LocalStorage.prototype.oDriver = null; + +/** + * @param {number} iKey + * @param {*} mData + * @return {boolean} + */ +LocalStorage.prototype.set = function (iKey, mData) +{ + return this.oDriver ? this.oDriver.set('p' + iKey, mData) : false; +}; + +/** + * @param {number} iKey + * @return {*} + */ +LocalStorage.prototype.get = function (iKey) +{ + return this.oDriver ? this.oDriver.get('p' + iKey) : null; +}; + +/** + * @constructor + */ +function KnoinAbstractBoot() +{ + +} + +KnoinAbstractBoot.prototype.bootstart = function () +{ + +}; + +/** + * @param {string=} sPosition = '' + * @param {string=} sTemplate = '' + * @constructor + */ +function KnoinAbstractViewModel(sPosition, sTemplate) +{ + this.bDisabeCloseOnEsc = false; + this.sPosition = Utils.pString(sPosition); + this.sTemplate = Utils.pString(sTemplate); + + this.sDefaultKeyScope = Enums.KeyState.None; + this.sCurrentKeyScope = this.sDefaultKeyScope; + + this.viewModelName = ''; + this.viewModelVisibility = ko.observable(false); + this.modalVisibility = ko.observable(false).extend({'rateLimit': 0}); + + this.viewModelDom = null; +} + +/** + * @type {string} + */ +KnoinAbstractViewModel.prototype.sPosition = ''; + +/** + * @type {string} + */ +KnoinAbstractViewModel.prototype.sTemplate = ''; + +/** + * @type {string} + */ +KnoinAbstractViewModel.prototype.viewModelName = ''; + +/** + * @type {?} + */ +KnoinAbstractViewModel.prototype.viewModelDom = null; + +/** + * @return {string} + */ +KnoinAbstractViewModel.prototype.viewModelTemplate = function () +{ + return this.sTemplate; +}; + +/** + * @return {string} + */ +KnoinAbstractViewModel.prototype.viewModelPosition = function () +{ + return this.sPosition; +}; + +KnoinAbstractViewModel.prototype.cancelCommand = KnoinAbstractViewModel.prototype.closeCommand = function () +{ +}; + +KnoinAbstractViewModel.prototype.storeAndSetKeyScope = function () +{ + this.sCurrentKeyScope = RL.data().keyScope(); + RL.data().keyScope(this.sDefaultKeyScope); +}; + +KnoinAbstractViewModel.prototype.restoreKeyScope = function () +{ + RL.data().keyScope(this.sCurrentKeyScope); +}; + +KnoinAbstractViewModel.prototype.registerPopupEscapeKey = function () +{ + var self = this; + $window.on('keydown', function (oEvent) { + if (oEvent && Enums.EventKeyCode.Esc === oEvent.keyCode && self.modalVisibility && self.modalVisibility()) + { + Utils.delegateRun(self, 'cancelCommand'); + return false; + } + + return true; + }); +}; + +/** + * @param {string} sScreenName + * @param {?=} aViewModels = [] + * @constructor + */ +function KnoinAbstractScreen(sScreenName, aViewModels) +{ + this.sScreenName = sScreenName; + this.aViewModels = Utils.isArray(aViewModels) ? aViewModels : []; +} + +/** + * @type {Array} + */ +KnoinAbstractScreen.prototype.oCross = null; + +/** + * @type {string} + */ +KnoinAbstractScreen.prototype.sScreenName = ''; + +/** + * @type {Array} + */ +KnoinAbstractScreen.prototype.aViewModels = []; + +/** + * @return {Array} + */ +KnoinAbstractScreen.prototype.viewModels = function () +{ + return this.aViewModels; +}; + +/** + * @return {string} + */ +KnoinAbstractScreen.prototype.screenName = function () +{ + return this.sScreenName; +}; + +KnoinAbstractScreen.prototype.routes = function () +{ + return null; +}; + +/** + * @return {?Object} + */ +KnoinAbstractScreen.prototype.__cross = function () +{ + return this.oCross; +}; + +KnoinAbstractScreen.prototype.__start = function () +{ + var + aRoutes = this.routes(), + oRoute = null, + fMatcher = null + ; + + if (Utils.isNonEmptyArray(aRoutes)) + { + fMatcher = _.bind(this.onRoute || Utils.emptyFunction, this); + oRoute = crossroads.create(); + + _.each(aRoutes, function (aItem) { + oRoute.addRoute(aItem[0], fMatcher).rules = aItem[1]; + }); + + this.oCross = oRoute; + } +}; + +/** + * @constructor + */ +function Knoin() +{ + this.sDefaultScreenName = ''; + this.oScreens = {}; + this.oBoot = null; + this.oCurrentScreen = null; +} + +/** + * @param {Object} thisObject + */ +Knoin.constructorEnd = function (thisObject) +{ + if (Utils.isFunc(thisObject['__constructor_end'])) + { + thisObject['__constructor_end'].call(thisObject); + } +}; + +Knoin.prototype.sDefaultScreenName = ''; +Knoin.prototype.oScreens = {}; +Knoin.prototype.oBoot = null; +Knoin.prototype.oCurrentScreen = null; + +Knoin.prototype.hideLoading = function () +{ + $('#rl-loading').hide(); +}; + +Knoin.prototype.routeOff = function () +{ + hasher.changed.active = false; +}; + +Knoin.prototype.routeOn = function () +{ + hasher.changed.active = true; +}; + +/** + * @param {Object} oBoot + * @return {Knoin} + */ +Knoin.prototype.setBoot = function (oBoot) +{ + if (Utils.isNormal(oBoot)) + { + this.oBoot = oBoot; + } + + return this; +}; + +/** + * @param {string} sScreenName + * @return {?Object} + */ +Knoin.prototype.screen = function (sScreenName) +{ + return ('' !== sScreenName && !Utils.isUnd(this.oScreens[sScreenName])) ? this.oScreens[sScreenName] : null; +}; + +/** + * @param {Function} ViewModelClass + * @param {Object=} oScreen + */ +Knoin.prototype.buildViewModel = function (ViewModelClass, oScreen) +{ + if (ViewModelClass && !ViewModelClass.__builded) + { + var + oViewModel = new ViewModelClass(oScreen), + sPosition = oViewModel.viewModelPosition(), + oViewModelPlace = $('#rl-content #rl-' + sPosition.toLowerCase()), + oViewModelDom = null + ; + + ViewModelClass.__builded = true; + ViewModelClass.__vm = oViewModel; + oViewModel.data = RL.data(); + + oViewModel.viewModelName = ViewModelClass.__name; + + if (oViewModelPlace && 1 === oViewModelPlace.length) + { + oViewModelDom = $('').addClass('rl-view-model').addClass('RL-' + oViewModel.viewModelTemplate()).hide().attr('data-bind', + 'template: {name: "' + oViewModel.viewModelTemplate() + '"}, i18nInit: true'); + + oViewModelDom.appendTo(oViewModelPlace); + oViewModel.viewModelDom = oViewModelDom; + ViewModelClass.__dom = oViewModelDom; + + if ('Popups' === sPosition) + { + oViewModel.cancelCommand = oViewModel.closeCommand = Utils.createCommand(oViewModel, function () { + kn.hideScreenPopup(ViewModelClass); + }); + + oViewModel.modalVisibility.subscribe(function (bValue) { + + var self = this; + if (bValue) + { + this.viewModelDom.show(); + this.storeAndSetKeyScope(); + + RL.popupVisibilityNames.push(this.viewModelName); + oViewModel.viewModelDom.css('z-index', 3000 + RL.popupVisibilityNames().length + 10); + + Utils.delegateRun(this, 'onFocus', [], 500); + } + else + { + Utils.delegateRun(this, 'onHide'); + this.restoreKeyScope(); + + RL.popupVisibilityNames.remove(this.viewModelName); + oViewModel.viewModelDom.css('z-index', 2000); + + _.delay(function () { + self.viewModelDom.hide(); + }, 300); + } + + }, oViewModel); + } + + Plugins.runHook('view-model-pre-build', [ViewModelClass.__name, oViewModel, oViewModelDom]); + + ko.applyBindings(oViewModel, oViewModelDom[0]); + Utils.delegateRun(oViewModel, 'onBuild', [oViewModelDom]); + if (oViewModel && 'Popups' === sPosition && !oViewModel.bDisabeCloseOnEsc) + { + oViewModel.registerPopupEscapeKey(); + } + + Plugins.runHook('view-model-post-build', [ViewModelClass.__name, oViewModel, oViewModelDom]); + } + else + { + Utils.log('Cannot find view model position: ' + sPosition); + } + } + + return ViewModelClass ? ViewModelClass.__vm : null; +}; + +/** + * @param {Object} oViewModel + * @param {Object} oViewModelDom + */ +Knoin.prototype.applyExternal = function (oViewModel, oViewModelDom) +{ + if (oViewModel && oViewModelDom) + { + ko.applyBindings(oViewModel, oViewModelDom); + } +}; + +/** + * @param {Function} ViewModelClassToHide + */ +Knoin.prototype.hideScreenPopup = function (ViewModelClassToHide) +{ + if (ViewModelClassToHide && ViewModelClassToHide.__vm && ViewModelClassToHide.__dom) + { + ViewModelClassToHide.__vm.modalVisibility(false); + Plugins.runHook('view-model-on-hide', [ViewModelClassToHide.__name, ViewModelClassToHide.__vm]); + } +}; + +/** + * @param {Function} ViewModelClassToShow + * @param {Array=} aParameters + */ +Knoin.prototype.showScreenPopup = function (ViewModelClassToShow, aParameters) +{ + if (ViewModelClassToShow) + { + this.buildViewModel(ViewModelClassToShow); + + if (ViewModelClassToShow.__vm && ViewModelClassToShow.__dom) + { + ViewModelClassToShow.__vm.modalVisibility(true); + Utils.delegateRun(ViewModelClassToShow.__vm, 'onShow', aParameters || []); + Plugins.runHook('view-model-on-show', [ViewModelClassToShow.__name, ViewModelClassToShow.__vm, aParameters || []]); + } + } +}; + +/** + * @param {string} sScreenName + * @param {string} sSubPart + */ +Knoin.prototype.screenOnRoute = function (sScreenName, sSubPart) +{ + var + self = this, + oScreen = null, + oCross = null + ; + + if ('' === Utils.pString(sScreenName)) + { + sScreenName = this.sDefaultScreenName; + } + + if ('' !== sScreenName) + { + oScreen = this.screen(sScreenName); + if (!oScreen) + { + oScreen = this.screen(this.sDefaultScreenName); + if (oScreen) + { + sSubPart = sScreenName + '/' + sSubPart; + sScreenName = this.sDefaultScreenName; + } + } + + if (oScreen && oScreen.__started) + { + if (!oScreen.__builded) + { + oScreen.__builded = true; + + if (Utils.isNonEmptyArray(oScreen.viewModels())) + { + _.each(oScreen.viewModels(), function (ViewModelClass) { + this.buildViewModel(ViewModelClass, oScreen); + }, this); + } + + Utils.delegateRun(oScreen, 'onBuild'); + } + + _.defer(function () { + + // hide screen + if (self.oCurrentScreen) + { + Utils.delegateRun(self.oCurrentScreen, 'onHide'); + + if (Utils.isNonEmptyArray(self.oCurrentScreen.viewModels())) + { + _.each(self.oCurrentScreen.viewModels(), function (ViewModelClass) { + + if (ViewModelClass.__vm && ViewModelClass.__dom && + 'Popups' !== ViewModelClass.__vm.viewModelPosition()) + { + ViewModelClass.__dom.hide(); + ViewModelClass.__vm.viewModelVisibility(false); + Utils.delegateRun(ViewModelClass.__vm, 'onHide'); + } + + }); + } + } + // -- + + self.oCurrentScreen = oScreen; + + // show screen + if (self.oCurrentScreen) + { + Utils.delegateRun(self.oCurrentScreen, 'onShow'); + + Plugins.runHook('screen-on-show', [self.oCurrentScreen.screenName(), self.oCurrentScreen]); + + if (Utils.isNonEmptyArray(self.oCurrentScreen.viewModels())) + { + _.each(self.oCurrentScreen.viewModels(), function (ViewModelClass) { + + if (ViewModelClass.__vm && ViewModelClass.__dom && + 'Popups' !== ViewModelClass.__vm.viewModelPosition()) + { + ViewModelClass.__dom.show(); + ViewModelClass.__vm.viewModelVisibility(true); + Utils.delegateRun(ViewModelClass.__vm, 'onShow'); + Utils.delegateRun(ViewModelClass.__vm, 'onFocus', [], 200); + + Plugins.runHook('view-model-on-show', [ViewModelClass.__name, ViewModelClass.__vm]); + } + + }, self); + } + } + // -- + + oCross = oScreen.__cross(); + if (oCross) + { + oCross.parse(sSubPart); + } + }); + } + } +}; + +/** + * @param {Array} aScreensClasses + */ +Knoin.prototype.startScreens = function (aScreensClasses) +{ + $('#rl-content').css({ + 'visibility': 'hidden' + }); + + _.each(aScreensClasses, function (CScreen) { + + var + oScreen = new CScreen(), + sScreenName = oScreen ? oScreen.screenName() : '' + ; + + if (oScreen && '' !== sScreenName) + { + if ('' === this.sDefaultScreenName) + { + this.sDefaultScreenName = sScreenName; + } + + this.oScreens[sScreenName] = oScreen; + } + + }, this); + + + _.each(this.oScreens, function (oScreen) { + if (oScreen && !oScreen.__started && oScreen.__start) + { + oScreen.__started = true; + oScreen.__start(); + + Plugins.runHook('screen-pre-start', [oScreen.screenName(), oScreen]); + Utils.delegateRun(oScreen, 'onStart'); + Plugins.runHook('screen-post-start', [oScreen.screenName(), oScreen]); + } + }, this); + + var oCross = crossroads.create(); + oCross.addRoute(/^([a-zA-Z0-9\-]*)\/?(.*)$/, _.bind(this.screenOnRoute, this)); + + hasher.initialized.add(oCross.parse, oCross); + hasher.changed.add(oCross.parse, oCross); + hasher.init(); + + $('#rl-content').css({ + 'visibility': 'visible' + }); + + _.delay(function () { + $html.removeClass('rl-started-trigger').addClass('rl-started'); + }, 50); +}; + +/** + * @param {string} sHash + * @param {boolean=} bSilence = false + * @param {boolean=} bReplace = false + */ +Knoin.prototype.setHash = function (sHash, bSilence, bReplace) +{ + sHash = '#' === sHash.substr(0, 1) ? sHash.substr(1) : sHash; + sHash = '/' === sHash.substr(0, 1) ? sHash.substr(1) : sHash; + + bReplace = Utils.isUnd(bReplace) ? false : !!bReplace; + + if (Utils.isUnd(bSilence) ? false : !!bSilence) + { + hasher.changed.active = false; + hasher[bReplace ? 'replaceHash' : 'setHash'](sHash); + hasher.changed.active = true; + } + else + { + hasher.changed.active = true; + hasher[bReplace ? 'replaceHash' : 'setHash'](sHash); + hasher.setHash(sHash); + } +}; + +/** + * @return {Knoin} + */ +Knoin.prototype.bootstart = function () +{ + if (this.oBoot && this.oBoot.bootstart) + { + this.oBoot.bootstart(); + } + + return this; +}; + +kn = new Knoin(); + +/** + * @param {string=} sEmail + * @param {string=} sName + * + * @constructor + */ +function EmailModel(sEmail, sName) +{ + this.email = sEmail || ''; + this.name = sName || ''; + this.privateType = null; + + this.clearDuplicateName(); +} + +/** + * @static + * @param {AjaxJsonEmail} oJsonEmail + * @return {?EmailModel} + */ +EmailModel.newInstanceFromJson = function (oJsonEmail) +{ + var oEmailModel = new EmailModel(); + return oEmailModel.initByJson(oJsonEmail) ? oEmailModel : null; +}; + +/** + * @type {string} + */ +EmailModel.prototype.name = ''; + +/** + * @type {string} + */ +EmailModel.prototype.email = ''; + +/** + * @type {(number|null)} + */ +EmailModel.prototype.privateType = null; + +EmailModel.prototype.clear = function () +{ + this.email = ''; + this.name = ''; + this.privateType = null; +}; + +/** + * @returns {boolean} + */ +EmailModel.prototype.validate = function () +{ + return '' !== this.name || '' !== this.email; +}; + +/** + * @param {boolean} bWithoutName = false + * @return {string} + */ +EmailModel.prototype.hash = function (bWithoutName) +{ + return '#' + (bWithoutName ? '' : this.name) + '#' + this.email + '#'; +}; + +EmailModel.prototype.clearDuplicateName = function () +{ + if (this.name === this.email) + { + this.name = ''; + } +}; + +/** + * @return {number} + */ +EmailModel.prototype.type = function () +{ + if (null === this.privateType) + { + if (this.email && '@facebook.com' === this.email.substr(-13)) + { + this.privateType = Enums.EmailType.Facebook; + } + + if (null === this.privateType) + { + this.privateType = Enums.EmailType.Default; + } + } + + return this.privateType; +}; + +/** + * @param {string} sQuery + * @return {boolean} + */ +EmailModel.prototype.search = function (sQuery) +{ + return -1 < (this.name + ' ' + this.email).toLowerCase().indexOf(sQuery.toLowerCase()); +}; + +/** + * @param {string} sString + */ +EmailModel.prototype.parse = function (sString) +{ + this.clear(); + + sString = Utils.trim(sString); + + var + mRegex = /(?:"([^"]+)")? ?(.*?@[^>,]+)>?,? ?/g, + mMatch = mRegex.exec(sString) + ; + + if (mMatch) + { + this.name = mMatch[1] || ''; + this.email = mMatch[2] || ''; + + this.clearDuplicateName(); + } + else if ((/^[^@]+@[^@]+$/).test(sString)) + { + this.name = ''; + this.email = sString; + } +}; + +/** + * @param {AjaxJsonEmail} oJsonEmail + * @return {boolean} + */ +EmailModel.prototype.initByJson = function (oJsonEmail) +{ + var bResult = false; + if (oJsonEmail && 'Object/Email' === oJsonEmail['@Object']) + { + this.name = Utils.trim(oJsonEmail.Name); + this.email = Utils.trim(oJsonEmail.Email); + + bResult = '' !== this.email; + this.clearDuplicateName(); + } + + return bResult; +}; + +/** + * @param {boolean} bFriendlyView + * @param {boolean=} bWrapWithLink = false + * @param {boolean=} bEncodeHtml = false + * @return {string} + */ +EmailModel.prototype.toLine = function (bFriendlyView, bWrapWithLink, bEncodeHtml) +{ + var sResult = ''; + if ('' !== this.email) + { + bWrapWithLink = Utils.isUnd(bWrapWithLink) ? false : !!bWrapWithLink; + bEncodeHtml = Utils.isUnd(bEncodeHtml) ? false : !!bEncodeHtml; + + if (bFriendlyView && '' !== this.name) + { + sResult = bWrapWithLink ? '') + + '" target="_blank" tabindex="-1">' + Utils.encodeHtml(this.name) + '' : + (bEncodeHtml ? Utils.encodeHtml(this.name) : this.name); + } + else + { + sResult = this.email; + if ('' !== this.name) + { + if (bWrapWithLink) + { + sResult = Utils.encodeHtml('"' + this.name + '" <') + + '') + '" target="_blank" tabindex="-1">' + Utils.encodeHtml(sResult) + '' + Utils.encodeHtml('>'); + } + else + { + sResult = '"' + this.name + '" <' + sResult + '>'; + if (bEncodeHtml) + { + sResult = Utils.encodeHtml(sResult); + } + } + } + else if (bWrapWithLink) + { + sResult = '' + Utils.encodeHtml(this.email) + ''; + } + } + } + + return sResult; +}; + +/** + * @param {string} $sEmailAddress + * @return {boolean} + */ +EmailModel.prototype.mailsoParse = function ($sEmailAddress) +{ + $sEmailAddress = Utils.trim($sEmailAddress); + if ('' === $sEmailAddress) + { + return false; + } + + var + substr = function (str, start, len) { + str += ''; + var end = str.length; + + if (start < 0) { + start += end; + } + + end = typeof len === 'undefined' ? end : (len < 0 ? len + end : len + start); + + return start >= str.length || start < 0 || start > end ? false : str.slice(start, end); + }, + + substr_replace = function (str, replace, start, length) { + if (start < 0) { + start = start + str.length; + } + length = length !== undefined ? length : str.length; + if (length < 0) { + length = length + str.length - start; + } + return str.slice(0, start) + replace.substr(0, length) + replace.slice(length) + str.slice(start + length); + }, + + $sName = '', + $sEmail = '', + $sComment = '', + + $bInName = false, + $bInAddress = false, + $bInComment = false, + + $aRegs = null, + + $iStartIndex = 0, + $iEndIndex = 0, + $iCurrentIndex = 0 + ; + + while ($iCurrentIndex < $sEmailAddress.length) + { + switch ($sEmailAddress.substr($iCurrentIndex, 1)) + { + case '"': + if ((!$bInName) && (!$bInAddress) && (!$bInComment)) + { + $bInName = true; + $iStartIndex = $iCurrentIndex; + } + else if ((!$bInAddress) && (!$bInComment)) + { + $iEndIndex = $iCurrentIndex; + $sName = substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1); + $sEmailAddress = substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1); + $iEndIndex = 0; + $iCurrentIndex = 0; + $iStartIndex = 0; + $bInName = false; + } + break; + case '<': + if ((!$bInName) && (!$bInAddress) && (!$bInComment)) + { + if ($iCurrentIndex > 0 && $sName.length === 0) + { + $sName = substr($sEmailAddress, 0, $iCurrentIndex); + } + + $bInAddress = true; + $iStartIndex = $iCurrentIndex; + } + break; + case '>': + if ($bInAddress) + { + $iEndIndex = $iCurrentIndex; + $sEmail = substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1); + $sEmailAddress = substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1); + $iEndIndex = 0; + $iCurrentIndex = 0; + $iStartIndex = 0; + $bInAddress = false; + } + break; + case '(': + if ((!$bInName) && (!$bInAddress) && (!$bInComment)) + { + $bInComment = true; + $iStartIndex = $iCurrentIndex; + } + break; + case ')': + if ($bInComment) + { + $iEndIndex = $iCurrentIndex; + $sComment = substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1); + $sEmailAddress = substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1); + $iEndIndex = 0; + $iCurrentIndex = 0; + $iStartIndex = 0; + $bInComment = false; + } + break; + case '\\': + $iCurrentIndex++; + break; + } + + $iCurrentIndex++; + } + + if ($sEmail.length === 0) + { + $aRegs = $sEmailAddress.match(/[^@\s]+@\S+/i); + if ($aRegs && $aRegs[0]) + { + $sEmail = $aRegs[0]; + } + else + { + $sName = $sEmailAddress; + } + } + + if ($sEmail.length > 0 && $sName.length === 0 && $sComment.length === 0) + { + $sName = $sEmailAddress.replace($sEmail, ''); + } + + $sEmail = Utils.trim($sEmail).replace(/^[<]+/, '').replace(/[>]+$/, ''); + $sName = Utils.trim($sName).replace(/^["']+/, '').replace(/["']+$/, ''); + $sComment = Utils.trim($sComment).replace(/^[(]+/, '').replace(/[)]+$/, ''); + + // Remove backslash + $sName = $sName.replace(/\\\\(.)/, '$1'); + $sComment = $sComment.replace(/\\\\(.)/, '$1'); + + this.name = $sName; + this.email = $sEmail; + + this.clearDuplicateName(); + return true; +}; + +/** + * @return {string} + */ +EmailModel.prototype.inputoTagLine = function () +{ + return 0 < this.name.length ? this.name + ' (' + this.email + ')' : this.email; +}; + +/** + * @constructor + */ +function ContactModel() +{ + this.idContact = 0; + this.display = ''; + this.properties = []; + this.readOnly = false; + + this.focused = ko.observable(false); + this.selected = ko.observable(false); + this.checked = ko.observable(false); + this.deleted = ko.observable(false); +} + +/** + * @return {Array|null} + */ +ContactModel.prototype.getNameAndEmailHelper = function () +{ + var + sName = '', + sEmail = '' + ; + + if (Utils.isNonEmptyArray(this.properties)) + { + _.each(this.properties, function (aProperty) { + if (aProperty) + { + if (Enums.ContactPropertyType.FirstName === aProperty[0]) + { + sName = Utils.trim(aProperty[1] + ' ' + sName); + } + else if (Enums.ContactPropertyType.LastName === aProperty[0]) + { + sName = Utils.trim(sName + ' ' + aProperty[1]); + } + else if ('' === sEmail && Enums.ContactPropertyType.Email === aProperty[0]) + { + sEmail = aProperty[1]; + } + } + }, this); + } + + return '' === sEmail ? null : [sEmail, sName]; +}; + +ContactModel.prototype.parse = function (oItem) +{ + var bResult = false; + if (oItem && 'Object/Contact' === oItem['@Object']) + { + this.idContact = Utils.pInt(oItem['IdContact']); + this.display = Utils.pString(oItem['Display']); + this.readOnly = !!oItem['ReadOnly']; + + if (Utils.isNonEmptyArray(oItem['Properties'])) + { + _.each(oItem['Properties'], function (oProperty) { + if (oProperty && oProperty['Type'] && Utils.isNormal(oProperty['Value']) && Utils.isNormal(oProperty['TypeStr'])) + { + this.properties.push([Utils.pInt(oProperty['Type']), Utils.pString(oProperty['Value']), Utils.pString(oProperty['TypeStr'])]); + } + }, this); + } + + bResult = true; + } + + return bResult; +}; + +/** + * @return {string} + */ +ContactModel.prototype.srcAttr = function () +{ + return RL.link().emptyContactPic(); +}; + +/** + * @return {string} + */ +ContactModel.prototype.generateUid = function () +{ + return '' + this.idContact; +}; + +/** + * @return string + */ +ContactModel.prototype.lineAsCcc = function () +{ + var aResult = []; + if (this.deleted()) + { + aResult.push('deleted'); + } + if (this.selected()) + { + aResult.push('selected'); + } + if (this.checked()) + { + aResult.push('checked'); + } + if (this.focused()) + { + aResult.push('focused'); + } + + return aResult.join(' '); +}; + +/** + * @param {number=} iType = Enums.ContactPropertyType.Unknown + * @param {string=} sTypeStr = '' + * @param {string=} sValue = '' + * @param {boolean=} bFocused = false + * @param {string=} sPlaceholder = '' + * + * @constructor + */ +function ContactPropertyModel(iType, sTypeStr, sValue, bFocused, sPlaceholder) +{ + this.type = ko.observable(Utils.isUnd(iType) ? Enums.ContactPropertyType.Unknown : iType); + this.typeStr = ko.observable(Utils.isUnd(sTypeStr) ? '' : sTypeStr); + this.focused = ko.observable(Utils.isUnd(bFocused) ? false : !!bFocused); + this.value = ko.observable(Utils.pString(sValue)); + + this.placeholder = ko.observable(sPlaceholder || ''); + + this.placeholderValue = ko.computed(function () { + var sPlaceholder = this.placeholder(); + return sPlaceholder ? Utils.i18n(sPlaceholder) : ''; + }, this); + + this.largeValue = ko.computed(function () { + return Enums.ContactPropertyType.Note === this.type(); + }, this); + +} + +/** + * @constructor + */ +function AttachmentModel() +{ + this.mimeType = ''; + this.fileName = ''; + this.estimatedSize = 0; + this.friendlySize = ''; + this.isInline = false; + this.isLinked = false; + this.cid = ''; + this.cidWithOutTags = ''; + this.contentLocation = ''; + this.download = ''; + this.folder = ''; + this.uid = ''; + this.mimeIndex = ''; +} + +/** + * @static + * @param {AjaxJsonAttachment} oJsonAttachment + * @return {?AttachmentModel} + */ +AttachmentModel.newInstanceFromJson = function (oJsonAttachment) +{ + var oAttachmentModel = new AttachmentModel(); + return oAttachmentModel.initByJson(oJsonAttachment) ? oAttachmentModel : null; +}; + +AttachmentModel.prototype.mimeType = ''; +AttachmentModel.prototype.fileName = ''; +AttachmentModel.prototype.estimatedSize = 0; +AttachmentModel.prototype.friendlySize = ''; +AttachmentModel.prototype.isInline = false; +AttachmentModel.prototype.isLinked = false; +AttachmentModel.prototype.cid = ''; +AttachmentModel.prototype.cidWithOutTags = ''; +AttachmentModel.prototype.contentLocation = ''; +AttachmentModel.prototype.download = ''; +AttachmentModel.prototype.folder = ''; +AttachmentModel.prototype.uid = ''; +AttachmentModel.prototype.mimeIndex = ''; + +/** + * @param {AjaxJsonAttachment} oJsonAttachment + */ +AttachmentModel.prototype.initByJson = function (oJsonAttachment) +{ + var bResult = false; + if (oJsonAttachment && 'Object/Attachment' === oJsonAttachment['@Object']) + { + this.mimeType = (oJsonAttachment.MimeType || '').toLowerCase(); + this.fileName = oJsonAttachment.FileName; + this.estimatedSize = Utils.pInt(oJsonAttachment.EstimatedSize); + this.isInline = !!oJsonAttachment.IsInline; + this.isLinked = !!oJsonAttachment.IsLinked; + this.cid = oJsonAttachment.CID; + this.contentLocation = oJsonAttachment.ContentLocation; + this.download = oJsonAttachment.Download; + + this.folder = oJsonAttachment.Folder; + this.uid = oJsonAttachment.Uid; + this.mimeIndex = oJsonAttachment.MimeIndex; + + this.friendlySize = Utils.friendlySize(this.estimatedSize); + this.cidWithOutTags = this.cid.replace(/^<+/, '').replace(/>+$/, ''); + + bResult = true; + } + + return bResult; +}; + +/** + * @return {boolean} + */ +AttachmentModel.prototype.isImage = function () +{ + return -1 < Utils.inArray(this.mimeType.toLowerCase(), + ['image/png', 'image/jpg', 'image/jpeg', 'image/gif'] + ); +}; + +/** + * @return {boolean} + */ +AttachmentModel.prototype.isText = function () +{ + return 'text/' === this.mimeType.substr(0, 5) && + -1 === Utils.inArray(this.mimeType, ['text/html']); +}; + +/** + * @return {boolean} + */ +AttachmentModel.prototype.isPdf = function () +{ + return Globals.bAllowPdfPreview && 'application/pdf' === this.mimeType; +}; + +/** + * @return {string} + */ +AttachmentModel.prototype.linkDownload = function () +{ + return RL.link().attachmentDownload(this.download); +}; + +/** + * @return {string} + */ +AttachmentModel.prototype.linkPreview = function () +{ + return RL.link().attachmentPreview(this.download); +}; + +/** + * @return {string} + */ +AttachmentModel.prototype.linkPreviewAsPlain = function () +{ + return RL.link().attachmentPreviewAsPlain(this.download); +}; + +/** + * @return {string} + */ +AttachmentModel.prototype.generateTransferDownloadUrl = function () +{ + var sLink = this.linkDownload(); + if ('http' !== sLink.substr(0, 4)) + { + sLink = window.location.protocol + '//' + window.location.host + window.location.pathname + sLink; + } + + return this.mimeType + ':' + this.fileName + ':' + sLink; +}; + +/** + * @param {AttachmentModel} oAttachment + * @param {*} oEvent + * @return {boolean} + */ +AttachmentModel.prototype.eventDragStart = function (oAttachment, oEvent) +{ + var oLocalEvent = oEvent.originalEvent || oEvent; + if (oAttachment && oLocalEvent && oLocalEvent.dataTransfer && oLocalEvent.dataTransfer.setData) + { + oLocalEvent.dataTransfer.setData('DownloadURL', this.generateTransferDownloadUrl()); + } + + return true; +}; + +AttachmentModel.prototype.iconClass = function () +{ + var + aParts = this.mimeType.toLocaleString().split('/'), + sClass = 'icon-file' + ; + + if (aParts && aParts[1]) + { + if ('image' === aParts[0]) + { + sClass = 'icon-file-image'; + } + else if ('text' === aParts[0]) + { + sClass = 'icon-file-text'; + } + else if ('audio' === aParts[0]) + { + sClass = 'icon-file-music'; + } + else if ('video' === aParts[0]) + { + sClass = 'icon-file-movie'; + } + else if (-1 < Utils.inArray(aParts[1], + ['zip', '7z', 'tar', 'rar', 'gzip', 'bzip', 'bzip2', 'x-zip', 'x-7z', 'x-rar', 'x-tar', 'x-gzip', 'x-bzip', 'x-bzip2', 'x-zip-compressed', 'x-7z-compressed', 'x-rar-compressed'])) + { + sClass = 'icon-file-zip'; + } +// else if (-1 < Utils.inArray(aParts[1], +// ['pdf', 'x-pdf'])) +// { +// sClass = 'icon-file-pdf'; +// } +// else if (-1 < Utils.inArray(aParts[1], [ +// 'exe', 'x-exe', 'x-winexe', 'bat' +// ])) +// { +// sClass = 'icon-console'; +// } + else if (-1 < Utils.inArray(aParts[1], [ + 'rtf', 'msword', 'vnd.msword', 'vnd.openxmlformats-officedocument.wordprocessingml.document', + 'vnd.openxmlformats-officedocument.wordprocessingml.template', + 'vnd.ms-word.document.macroEnabled.12', + 'vnd.ms-word.template.macroEnabled.12' + ])) + { + sClass = 'icon-file-text'; + } + else if (-1 < Utils.inArray(aParts[1], [ + 'excel', 'ms-excel', 'vnd.ms-excel', + 'vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'vnd.openxmlformats-officedocument.spreadsheetml.template', + 'vnd.ms-excel.sheet.macroEnabled.12', + 'vnd.ms-excel.template.macroEnabled.12', + 'vnd.ms-excel.addin.macroEnabled.12', + 'vnd.ms-excel.sheet.binary.macroEnabled.12' + ])) + { + sClass = 'icon-file-excel'; + } + else if (-1 < Utils.inArray(aParts[1], [ + 'powerpoint', 'ms-powerpoint', 'vnd.ms-powerpoint', + 'vnd.openxmlformats-officedocument.presentationml.presentation', + 'vnd.openxmlformats-officedocument.presentationml.template', + 'vnd.openxmlformats-officedocument.presentationml.slideshow', + 'vnd.ms-powerpoint.addin.macroEnabled.12', + 'vnd.ms-powerpoint.presentation.macroEnabled.12', + 'vnd.ms-powerpoint.template.macroEnabled.12', + 'vnd.ms-powerpoint.slideshow.macroEnabled.12' + ])) + { + sClass = 'icon-file-chart-graph'; + } + } + + return sClass; +}; + +/** + * @constructor + * @param {string} sId + * @param {string} sFileName + * @param {?number=} nSize + * @param {boolean=} bInline + * @param {boolean=} bLinked + * @param {string=} sCID + * @param {string=} sContentLocation + */ +function ComposeAttachmentModel(sId, sFileName, nSize, bInline, bLinked, sCID, sContentLocation) +{ + this.id = sId; + this.isInline = Utils.isUnd(bInline) ? false : !!bInline; + this.isLinked = Utils.isUnd(bLinked) ? false : !!bLinked; + this.CID = Utils.isUnd(sCID) ? '' : sCID; + this.contentLocation = Utils.isUnd(sContentLocation) ? '' : sContentLocation; + this.fromMessage = false; + + this.fileName = ko.observable(sFileName); + this.size = ko.observable(Utils.isUnd(nSize) ? null : nSize); + this.tempName = ko.observable(''); + + this.progress = ko.observable(''); + this.error = ko.observable(''); + this.waiting = ko.observable(true); + this.uploading = ko.observable(false); + this.enabled = ko.observable(true); + + this.friendlySize = ko.computed(function () { + var mSize = this.size(); + return null === mSize ? '' : Utils.friendlySize(this.size()); + }, this); +} + +ComposeAttachmentModel.prototype.id = ''; +ComposeAttachmentModel.prototype.isInline = false; +ComposeAttachmentModel.prototype.isLinked = false; +ComposeAttachmentModel.prototype.CID = ''; +ComposeAttachmentModel.prototype.contentLocation = ''; +ComposeAttachmentModel.prototype.fromMessage = false; +ComposeAttachmentModel.prototype.cancel = Utils.emptyFunction; + +/** + * @param {AjaxJsonComposeAttachment} oJsonAttachment + */ +ComposeAttachmentModel.prototype.initByUploadJson = function (oJsonAttachment) +{ + var bResult = false; + if (oJsonAttachment) + { + this.fileName(oJsonAttachment.Name); + this.size(Utils.isUnd(oJsonAttachment.Size) ? 0 : Utils.pInt(oJsonAttachment.Size)); + this.tempName(Utils.isUnd(oJsonAttachment.TempName) ? '' : oJsonAttachment.TempName); + this.isInline = false; + + bResult = true; + } + + return bResult; +}; +/** + * @constructor + */ +function MessageModel() +{ + this.folderFullNameRaw = ''; + this.uid = ''; + this.hash = ''; + this.requestHash = ''; + this.subject = ko.observable(''); + this.size = ko.observable(0); + this.dateTimeStampInUTC = ko.observable(0); + this.priority = ko.observable(Enums.MessagePriority.Normal); + + this.fromEmailString = ko.observable(''); + this.toEmailsString = ko.observable(''); + this.senderEmailsString = ko.observable(''); + + this.emails = []; + + this.from = []; + this.to = []; + this.cc = []; + this.bcc = []; + this.replyTo = []; + + this.newForAnimation = ko.observable(false); + + this.deleted = ko.observable(false); + this.unseen = ko.observable(false); + this.flagged = ko.observable(false); + this.answered = ko.observable(false); + this.forwarded = ko.observable(false); + this.isReadReceipt = ko.observable(false); + + this.focused = ko.observable(false); + this.selected = ko.observable(false); + this.checked = ko.observable(false); + this.hasAttachments = ko.observable(false); + this.attachmentsMainType = ko.observable(''); + + this.moment = ko.observable(moment()); + + this.attachmentIconClass = ko.computed(function () { + var sClass = ''; + if (this.hasAttachments()) + { + sClass = 'icon-attachment'; + switch (this.attachmentsMainType()) + { + case 'image': + sClass = 'icon-image'; + break; + case 'archive': + sClass = 'icon-file-zip'; + break; + case 'doc': + sClass = 'icon-file-text'; + break; +// case 'pdf': +// sClass = 'icon-file-pdf'; +// break; + } + } + return sClass; + }, this); + + this.fullFormatDateValue = ko.computed(function () { + return MessageModel.calculateFullFromatDateValue(this.dateTimeStampInUTC()); + }, this); + + this.fullFormatDateValue = ko.computed(function () { + return MessageModel.calculateFullFromatDateValue(this.dateTimeStampInUTC()); + }, this); + + this.momentDate = Utils.createMomentDate(this); + this.momentShortDate = Utils.createMomentShortDate(this); + + this.dateTimeStampInUTC.subscribe(function (iValue) { + var iNow = moment().unix(); + this.moment(moment.unix(iNow < iValue ? iNow : iValue)); + }, this); + + this.body = null; + this.plainRaw = ''; + this.isRtl = ko.observable(false); + this.isHtml = ko.observable(false); + this.hasImages = ko.observable(false); + this.attachments = ko.observableArray([]); + + this.isPgpSigned = ko.observable(false); + this.isPgpEncrypted = ko.observable(false); + this.pgpSignedVerifyStatus = ko.observable(Enums.SignedVerifyStatus.None); + this.pgpSignedVerifyUser = ko.observable(''); + + this.priority = ko.observable(Enums.MessagePriority.Normal); + this.readReceipt = ko.observable(''); + + this.aDraftInfo = []; + this.sMessageId = ''; + this.sInReplyTo = ''; + this.sReferences = ''; + + this.parentUid = ko.observable(0); + this.threads = ko.observableArray([]); + this.threadsLen = ko.observable(0); + this.hasUnseenSubMessage = ko.observable(false); + this.hasFlaggedSubMessage = ko.observable(false); + + this.lastInCollapsedThread = ko.observable(false); + this.lastInCollapsedThreadLoading = ko.observable(false); + + this.threadsLenResult = ko.computed(function () { + var iCount = this.threadsLen(); + return 0 === this.parentUid() && 0 < iCount ? iCount + 1 : ''; + }, this); +} + +/** + * @static + * @param {AjaxJsonMessage} oJsonMessage + * @return {?MessageModel} + */ +MessageModel.newInstanceFromJson = function (oJsonMessage) +{ + var oMessageModel = new MessageModel(); + return oMessageModel.initByJson(oJsonMessage) ? oMessageModel : null; +}; + +/** + * @static + * @param {number} iTimeStampInUTC + * @return {string} + */ +MessageModel.calculateFullFromatDateValue = function (iTimeStampInUTC) +{ + return moment.unix(iTimeStampInUTC).format('LLL'); +}; + +/** + * @static + * @param {Array} aEmail + * @param {boolean=} bFriendlyView + * @param {boolean=} bWrapWithLink = false + * @return {string} + */ +MessageModel.emailsToLine = function (aEmail, bFriendlyView, bWrapWithLink) +{ + var + aResult = [], + iIndex = 0, + iLen = 0 + ; + + if (Utils.isNonEmptyArray(aEmail)) + { + for (iIndex = 0, iLen = aEmail.length; iIndex < iLen; iIndex++) + { + aResult.push(aEmail[iIndex].toLine(bFriendlyView, bWrapWithLink)); + } + } + + return aResult.join(', '); +}; + +/** + * @static + * @param {?Array} aJsonEmails + * @return {Array} + */ +MessageModel.initEmailsFromJson = function (aJsonEmails) +{ + var + iIndex = 0, + iLen = 0, + oEmailModel = null, + aResult = [] + ; + + if (Utils.isNonEmptyArray(aJsonEmails)) + { + for (iIndex = 0, iLen = aJsonEmails.length; iIndex < iLen; iIndex++) + { + oEmailModel = EmailModel.newInstanceFromJson(aJsonEmails[iIndex]); + if (oEmailModel) + { + aResult.push(oEmailModel); + } + } + } + + return aResult; +}; + +/** + * @static + * @param {Array.} aMessageEmails + * @param {Object} oLocalUnic + * @param {Array} aLocalEmails + */ +MessageModel.replyHelper = function (aMessageEmails, oLocalUnic, aLocalEmails) +{ + if (aMessageEmails && 0 < aMessageEmails.length) + { + var + iIndex = 0, + iLen = aMessageEmails.length + ; + + for (; iIndex < iLen; iIndex++) + { + if (Utils.isUnd(oLocalUnic[aMessageEmails[iIndex].email])) + { + oLocalUnic[aMessageEmails[iIndex].email] = true; + aLocalEmails.push(aMessageEmails[iIndex]); + } + } + } +}; + +MessageModel.prototype.clear = function () +{ + this.folderFullNameRaw = ''; + this.uid = ''; + this.hash = ''; + this.requestHash = ''; + this.subject(''); + this.size(0); + this.dateTimeStampInUTC(0); + this.priority(Enums.MessagePriority.Normal); + + this.fromEmailString(''); + this.toEmailsString(''); + this.senderEmailsString(''); + + this.emails = []; + + this.from = []; + this.to = []; + this.cc = []; + this.bcc = []; + this.replyTo = []; + + this.newForAnimation(false); + + this.deleted(false); + this.unseen(false); + this.flagged(false); + this.answered(false); + this.forwarded(false); + this.isReadReceipt(false); + + this.selected(false); + this.checked(false); + this.hasAttachments(false); + this.attachmentsMainType(''); + + this.body = null; + this.isRtl(false); + this.isHtml(false); + this.hasImages(false); + this.attachments([]); + + this.isPgpSigned(false); + this.isPgpEncrypted(false); + this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.None); + this.pgpSignedVerifyUser(''); + + this.priority(Enums.MessagePriority.Normal); + this.readReceipt(''); + this.aDraftInfo = []; + this.sMessageId = ''; + this.sInReplyTo = ''; + this.sReferences = ''; + + this.parentUid(0); + this.threads([]); + this.threadsLen(0); + this.hasUnseenSubMessage(false); + this.hasFlaggedSubMessage(false); + + this.lastInCollapsedThread(false); + this.lastInCollapsedThreadLoading(false); +}; + +MessageModel.prototype.computeSenderEmail = function () +{ + var + sSent = RL.data().sentFolder(), + sDraft = RL.data().draftFolder() + ; + + this.senderEmailsString(this.folderFullNameRaw === sSent || this.folderFullNameRaw === sDraft ? + this.toEmailsString() : this.fromEmailString()); +}; + +/** + * @param {AjaxJsonMessage} oJsonMessage + * @return {boolean} + */ +MessageModel.prototype.initByJson = function (oJsonMessage) +{ + var bResult = false; + if (oJsonMessage && 'Object/Message' === oJsonMessage['@Object']) + { + this.folderFullNameRaw = oJsonMessage.Folder; + this.uid = oJsonMessage.Uid; + this.hash = oJsonMessage.Hash; + this.requestHash = oJsonMessage.RequestHash; + + this.size(Utils.pInt(oJsonMessage.Size)); + + this.from = MessageModel.initEmailsFromJson(oJsonMessage.From); + this.to = MessageModel.initEmailsFromJson(oJsonMessage.To); + this.cc = MessageModel.initEmailsFromJson(oJsonMessage.Cc); + this.bcc = MessageModel.initEmailsFromJson(oJsonMessage.Bcc); + this.replyTo = MessageModel.initEmailsFromJson(oJsonMessage.ReplyTo); + + this.subject(oJsonMessage.Subject); + this.dateTimeStampInUTC(Utils.pInt(oJsonMessage.DateTimeStampInUTC)); + this.hasAttachments(!!oJsonMessage.HasAttachments); + this.attachmentsMainType(oJsonMessage.AttachmentsMainType); + + this.fromEmailString(MessageModel.emailsToLine(this.from, true)); + this.toEmailsString(MessageModel.emailsToLine(this.to, true)); + + this.parentUid(Utils.pInt(oJsonMessage.ParentThread)); + this.threads(Utils.isArray(oJsonMessage.Threads) ? oJsonMessage.Threads : []); + this.threadsLen(Utils.pInt(oJsonMessage.ThreadsLen)); + + this.initFlagsByJson(oJsonMessage); + this.computeSenderEmail(); + + bResult = true; + } + + return bResult; +}; + +/** + * @param {AjaxJsonMessage} oJsonMessage + * @return {boolean} + */ +MessageModel.prototype.initUpdateByMessageJson = function (oJsonMessage) +{ + var + bResult = false, + iPriority = Enums.MessagePriority.Normal + ; + + if (oJsonMessage && 'Object/Message' === oJsonMessage['@Object']) + { + iPriority = Utils.pInt(oJsonMessage.Priority); + this.priority(-1 < Utils.inArray(iPriority, [Enums.MessagePriority.High, Enums.MessagePriority.Low]) ? + iPriority : Enums.MessagePriority.Normal); + + this.aDraftInfo = oJsonMessage.DraftInfo; + + this.sMessageId = oJsonMessage.MessageId; + this.sInReplyTo = oJsonMessage.InReplyTo; + this.sReferences = oJsonMessage.References; + + if (RL.data().allowOpenPGP()) + { + this.isPgpSigned(!!oJsonMessage.PgpSigned); + this.isPgpEncrypted(!!oJsonMessage.PgpEncrypted); + } + + this.hasAttachments(!!oJsonMessage.HasAttachments); + this.attachmentsMainType(oJsonMessage.AttachmentsMainType); + + this.foundedCIDs = Utils.isArray(oJsonMessage.FoundedCIDs) ? oJsonMessage.FoundedCIDs : []; + this.attachments(this.initAttachmentsFromJson(oJsonMessage.Attachments)); + + this.readReceipt(oJsonMessage.ReadReceipt || ''); + + this.computeSenderEmail(); + + bResult = true; + } + + return bResult; +}; + +/** + * @param {(AjaxJsonAttachment|null)} oJsonAttachments + * @return {Array} + */ +MessageModel.prototype.initAttachmentsFromJson = function (oJsonAttachments) +{ + var + iIndex = 0, + iLen = 0, + oAttachmentModel = null, + aResult = [] + ; + + if (oJsonAttachments && 'Collection/AttachmentCollection' === oJsonAttachments['@Object'] && + Utils.isNonEmptyArray(oJsonAttachments['@Collection'])) + { + for (iIndex = 0, iLen = oJsonAttachments['@Collection'].length; iIndex < iLen; iIndex++) + { + oAttachmentModel = AttachmentModel.newInstanceFromJson(oJsonAttachments['@Collection'][iIndex]); + if (oAttachmentModel) + { + if ('' !== oAttachmentModel.cidWithOutTags && 0 < this.foundedCIDs.length && + 0 <= Utils.inArray(oAttachmentModel.cidWithOutTags, this.foundedCIDs)) + { + oAttachmentModel.isLinked = true; + } + + aResult.push(oAttachmentModel); + } + } + } + + return aResult; +}; + +/** + * @param {AjaxJsonMessage} oJsonMessage + * @return {boolean} + */ +MessageModel.prototype.initFlagsByJson = function (oJsonMessage) +{ + var bResult = false; + + if (oJsonMessage && 'Object/Message' === oJsonMessage['@Object']) + { + this.unseen(!oJsonMessage.IsSeen); + this.flagged(!!oJsonMessage.IsFlagged); + this.answered(!!oJsonMessage.IsAnswered); + this.forwarded(!!oJsonMessage.IsForwarded); + this.isReadReceipt(!!oJsonMessage.IsReadReceipt); + + bResult = true; + } + + return bResult; +}; + +/** + * @param {boolean} bFriendlyView + * @param {boolean=} bWrapWithLink = false + * @return {string} + */ +MessageModel.prototype.fromToLine = function (bFriendlyView, bWrapWithLink) +{ + return MessageModel.emailsToLine(this.from, bFriendlyView, bWrapWithLink); +}; + +/** + * @param {boolean} bFriendlyView + * @param {boolean=} bWrapWithLink = false + * @return {string} + */ +MessageModel.prototype.toToLine = function (bFriendlyView, bWrapWithLink) +{ + return MessageModel.emailsToLine(this.to, bFriendlyView, bWrapWithLink); +}; + +/** + * @param {boolean} bFriendlyView + * @param {boolean=} bWrapWithLink = false + * @return {string} + */ +MessageModel.prototype.ccToLine = function (bFriendlyView, bWrapWithLink) +{ + return MessageModel.emailsToLine(this.cc, bFriendlyView, bWrapWithLink); +}; + +/** + * @param {boolean} bFriendlyView + * @param {boolean=} bWrapWithLink = false + * @return {string} + */ +MessageModel.prototype.bccToLine = function (bFriendlyView, bWrapWithLink) +{ + return MessageModel.emailsToLine(this.bcc, bFriendlyView, bWrapWithLink); +}; + +/** + * @return string + */ +MessageModel.prototype.lineAsCcc = function () +{ + var aResult = []; + if (this.deleted()) + { + aResult.push('deleted'); + } + if (this.selected()) + { + aResult.push('selected'); + } + if (this.checked()) + { + aResult.push('checked'); + } + if (this.flagged()) + { + aResult.push('flagged'); + } + if (this.unseen()) + { + aResult.push('unseen'); + } + if (this.answered()) + { + aResult.push('answered'); + } + if (this.forwarded()) + { + aResult.push('forwarded'); + } + if (this.focused()) + { + aResult.push('focused'); + } + if (this.hasAttachments()) + { + aResult.push('withAttachments'); + switch (this.attachmentsMainType()) + { + case 'image': + aResult.push('imageOnlyAttachments'); + break; + case 'archive': + aResult.push('archiveOnlyAttachments'); + break; + } + } + if (this.newForAnimation()) + { + aResult.push('new'); + } + if ('' === this.subject()) + { + aResult.push('emptySubject'); + } + if (0 < this.parentUid()) + { + aResult.push('hasParentMessage'); + } + if (0 < this.threadsLen() && 0 === this.parentUid()) + { + aResult.push('hasChildrenMessage'); + } + if (this.hasUnseenSubMessage()) + { + aResult.push('hasUnseenSubMessage'); + } + if (this.hasFlaggedSubMessage()) + { + aResult.push('hasFlaggedSubMessage'); + } + + return aResult.join(' '); +}; + +/** + * @return {boolean} + */ +MessageModel.prototype.hasVisibleAttachments = function () +{ + return !!_.find(this.attachments(), function (oAttachment) { + return !oAttachment.isLinked; + }); +// return 0 < this.attachments().length; +}; + +/** + * @param {string} sCid + * @return {*} + */ +MessageModel.prototype.findAttachmentByCid = function (sCid) +{ + var + oResult = null, + aAttachments = this.attachments() + ; + + if (Utils.isNonEmptyArray(aAttachments)) + { + sCid = sCid.replace(/^<+/, '').replace(/>+$/, ''); + oResult = _.find(aAttachments, function (oAttachment) { + return sCid === oAttachment.cidWithOutTags; + }); + } + + return oResult || null; +}; + +/** + * @param {string} sContentLocation + * @return {*} + */ +MessageModel.prototype.findAttachmentByContentLocation = function (sContentLocation) +{ + var + oResult = null, + aAttachments = this.attachments() + ; + + if (Utils.isNonEmptyArray(aAttachments)) + { + oResult = _.find(aAttachments, function (oAttachment) { + return sContentLocation === oAttachment.contentLocation; + }); + } + + return oResult || null; +}; + + +/** + * @return {string} + */ +MessageModel.prototype.messageId = function () +{ + return this.sMessageId; +}; + +/** + * @return {string} + */ +MessageModel.prototype.inReplyTo = function () +{ + return this.sInReplyTo; +}; + +/** + * @return {string} + */ +MessageModel.prototype.references = function () +{ + return this.sReferences; +}; + +/** + * @return {string} + */ +MessageModel.prototype.fromAsSingleEmail = function () +{ + return Utils.isArray(this.from) && this.from[0] ? this.from[0].email : ''; +}; + +/** + * @return {string} + */ +MessageModel.prototype.viewLink = function () +{ + return RL.link().messageViewLink(this.requestHash); +}; + +/** + * @return {string} + */ +MessageModel.prototype.downloadLink = function () +{ + return RL.link().messageDownloadLink(this.requestHash); +}; + +/** + * @param {Object} oExcludeEmails + * @return {Array} + */ +MessageModel.prototype.replyEmails = function (oExcludeEmails) +{ + var + aResult = [], + oUnic = Utils.isUnd(oExcludeEmails) ? {} : oExcludeEmails + ; + + MessageModel.replyHelper(this.replyTo, oUnic, aResult); + if (0 === aResult.length) + { + MessageModel.replyHelper(this.from, oUnic, aResult); + } + + return aResult; +}; + +/** + * @param {Object} oExcludeEmails + * @return {Array. } + */ +MessageModel.prototype.replyAllEmails = function (oExcludeEmails) +{ + var + aToResult = [], + aCcResult = [], + oUnic = Utils.isUnd(oExcludeEmails) ? {} : oExcludeEmails + ; + + MessageModel.replyHelper(this.replyTo, oUnic, aToResult); + if (0 === aToResult.length) + { + MessageModel.replyHelper(this.from, oUnic, aToResult); + } + + MessageModel.replyHelper(this.to, oUnic, aToResult); + MessageModel.replyHelper(this.cc, oUnic, aCcResult); + + return [aToResult, aCcResult]; +}; + +/** + * @return {string} + */ +MessageModel.prototype.textBodyToString = function () +{ + return this.body ? this.body.html() : ''; +}; + +/** + * @return {string} + */ +MessageModel.prototype.attachmentsToStringLine = function () +{ + var aAttachLines = _.map(this.attachments(), function (oItem) { + return oItem.fileName + ' (' + oItem.friendlySize + ')'; + }); + + return aAttachLines && 0 < aAttachLines.length ? aAttachLines.join(', ') : ''; +}; + +/** + * @return {Object} + */ +MessageModel.prototype.getDataForWindowPopup = function () +{ + return { + 'popupFrom': this.fromToLine(false), + 'popupTo': this.toToLine(false), + 'popupCc': this.ccToLine(false), + 'popupBcc': this.bccToLine(false), + 'popupSubject': this.subject(), + 'popupDate': this.fullFormatDateValue(), + 'popupAttachments': this.attachmentsToStringLine(), + 'popupBody': this.textBodyToString() + }; +}; + +/** + * @param {boolean=} bPrint = false + */ +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); + } + } + }); +}; + +MessageModel.prototype.printMessage = function () +{ + this.viewPopupMessage(true); +}; + +/** + * @returns {string} + */ +MessageModel.prototype.generateUid = function () +{ + return this.folderFullNameRaw + '/' + this.uid; +}; + +/** + * @param {MessageModel} oMessage + * @return {MessageModel} + */ +MessageModel.prototype.populateByMessageListItem = function (oMessage) +{ + this.folderFullNameRaw = oMessage.folderFullNameRaw; + this.uid = oMessage.uid; + this.hash = oMessage.hash; + this.requestHash = oMessage.requestHash; + this.subject(oMessage.subject()); + this.size(oMessage.size()); + this.dateTimeStampInUTC(oMessage.dateTimeStampInUTC()); + this.priority(oMessage.priority()); + + this.fromEmailString(oMessage.fromEmailString()); + this.toEmailsString(oMessage.toEmailsString()); + + this.emails = oMessage.emails; + + this.from = oMessage.from; + this.to = oMessage.to; + this.cc = oMessage.cc; + this.bcc = oMessage.bcc; + this.replyTo = oMessage.replyTo; + + this.unseen(oMessage.unseen()); + this.flagged(oMessage.flagged()); + this.answered(oMessage.answered()); + this.forwarded(oMessage.forwarded()); + this.isReadReceipt(oMessage.isReadReceipt()); + + this.selected(oMessage.selected()); + this.checked(oMessage.checked()); + this.hasAttachments(oMessage.hasAttachments()); + this.attachmentsMainType(oMessage.attachmentsMainType()); + + this.moment(oMessage.moment()); + + this.body = null; +// this.isRtl(oMessage.isRtl()); +// this.isHtml(false); +// this.hasImages(false); +// this.attachments([]); + +// this.isPgpSigned(false); +// this.isPgpEncrypted(false); + + this.priority(Enums.MessagePriority.Normal); + this.aDraftInfo = []; + this.sMessageId = ''; + this.sInReplyTo = ''; + this.sReferences = ''; + + this.parentUid(oMessage.parentUid()); + this.threads(oMessage.threads()); + this.threadsLen(oMessage.threadsLen()); + + this.computeSenderEmail(); + + return this; +}; + +MessageModel.prototype.showExternalImages = function (bLazy) +{ + if (this.body && this.body.data('rl-has-images')) + { + bLazy = Utils.isUnd(bLazy) ? false : bLazy; + + this.hasImages(false); + this.body.data('rl-has-images', false); + + $('[data-x-src]', this.body).each(function () { + if (bLazy && $(this).is('img')) + { + $(this) + .addClass('lazy') + .attr('data-original', $(this).attr('data-x-src')) + .removeAttr('data-x-src') + ; + } + else + { + $(this).attr('src', $(this).attr('data-x-src')).removeAttr('data-x-src'); + } + }); + + $('[data-x-style-url]', this.body).each(function () { + var sStyle = Utils.trim($(this).attr('style')); + sStyle = '' === sStyle ? '' : (';' === sStyle.substr(-1) ? sStyle + ' ' : sStyle + '; '); + $(this).attr('style', sStyle + $(this).attr('data-x-style-url')).removeAttr('data-x-style-url'); + }); + + if (bLazy) + { + $('img.lazy', this.body).addClass('lazy-inited').lazyload({ + 'threshold' : 400, + 'effect' : 'fadeIn', + 'skip_invisible' : false, + 'container': $('.RL-MailMessageView .messageView .messageItem .content')[0] + }); + + $window.resize(); + } + + Utils.windowResize(500); + } +}; + +MessageModel.prototype.showInternalImages = function (bLazy) +{ + if (this.body && !this.body.data('rl-init-internal-images')) + { + this.body.data('rl-init-internal-images', true); + + bLazy = Utils.isUnd(bLazy) ? false : bLazy; + + var self = this; + + $('[data-x-src-cid]', this.body).each(function () { + + var oAttachment = self.findAttachmentByCid($(this).attr('data-x-src-cid')); + if (oAttachment && oAttachment.download) + { + if (bLazy && $(this).is('img')) + { + $(this) + .addClass('lazy') + .attr('data-original', oAttachment.linkPreview()); + } + else + { + $(this).attr('src', oAttachment.linkPreview()); + } + } + }); + + $('[data-x-src-location]', this.body).each(function () { + + var oAttachment = self.findAttachmentByContentLocation($(this).attr('data-x-src-location')); + if (!oAttachment) + { + oAttachment = self.findAttachmentByCid($(this).attr('data-x-src-location')); + } + + if (oAttachment && oAttachment.download) + { + if (bLazy && $(this).is('img')) + { + $(this) + .addClass('lazy') + .attr('data-original', oAttachment.linkPreview()); + } + else + { + $(this).attr('src', oAttachment.linkPreview()); + } + } + }); + + $('[data-x-style-cid]', this.body).each(function () { + + var + sStyle = '', + sName = '', + oAttachment = self.findAttachmentByCid($(this).attr('data-x-style-cid')) + ; + + if (oAttachment && oAttachment.linkPreview) + { + sName = $(this).attr('data-x-style-cid-name'); + if ('' !== sName) + { + sStyle = Utils.trim($(this).attr('style')); + sStyle = '' === sStyle ? '' : (';' === sStyle.substr(-1) ? sStyle + ' ' : sStyle + '; '); + $(this).attr('style', sStyle + sName + ': url(\'' + oAttachment.linkPreview() + '\')'); + } + } + }); + + if (bLazy) + { + (function ($oImg, oContainer) { + _.delay(function () { + $oImg.addClass('lazy-inited').lazyload({ + 'threshold' : 400, + 'effect' : 'fadeIn', + 'skip_invisible' : false, + 'container': oContainer + }); + }, 300); + }($('img.lazy', self.body), $('.RL-MailMessageView .messageView .messageItem .content')[0])); + } + + Utils.windowResize(500); + } +}; + +MessageModel.prototype.storeDataToDom = function () +{ + if (this.body) + { + this.body.data('rl-is-rtl', !!this.isRtl()); + this.body.data('rl-is-html', !!this.isHtml()); + this.body.data('rl-has-images', !!this.hasImages()); + + this.body.data('rl-plain-raw', this.plainRaw); + + if (RL.data().allowOpenPGP()) + { + this.body.data('rl-plain-pgp-signed', !!this.isPgpSigned()); + this.body.data('rl-plain-pgp-encrypted', !!this.isPgpEncrypted()); + this.body.data('rl-pgp-verify-status', this.pgpSignedVerifyStatus()); + this.body.data('rl-pgp-verify-user', this.pgpSignedVerifyUser()); + } + } +}; + +MessageModel.prototype.storePgpVerifyDataToDom = function () +{ + if (this.body && RL.data().allowOpenPGP()) + { + this.body.data('rl-pgp-verify-status', this.pgpSignedVerifyStatus()); + this.body.data('rl-pgp-verify-user', this.pgpSignedVerifyUser()); + } +}; + +MessageModel.prototype.fetchDataToDom = function () +{ + if (this.body) + { + this.isRtl(!!this.body.data('rl-is-rtl')); + this.isHtml(!!this.body.data('rl-is-html')); + this.hasImages(!!this.body.data('rl-has-images')); + + this.plainRaw = Utils.pString(this.body.data('rl-plain-raw')); + + if (RL.data().allowOpenPGP()) + { + this.isPgpSigned(!!this.body.data('rl-plain-pgp-signed')); + this.isPgpEncrypted(!!this.body.data('rl-plain-pgp-encrypted')); + this.pgpSignedVerifyStatus(this.body.data('rl-pgp-verify-status')); + this.pgpSignedVerifyUser(this.body.data('rl-pgp-verify-user')); + } + else + { + this.isPgpSigned(false); + this.isPgpEncrypted(false); + this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.None); + this.pgpSignedVerifyUser(''); + } + } +}; + +MessageModel.prototype.verifyPgpSignedClearMessage = function () +{ + if (this.isPgpSigned()) + { + var + aRes = [], + mPgpMessage = null, + sFrom = this.from && this.from[0] && this.from[0].email ? this.from[0].email : '', + aPublicKeys = RL.data().findPublicKeysByEmail(sFrom), + oValidKey = null, + oValidSysKey = null, + sPlain = '' + ; + + this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Error); + this.pgpSignedVerifyUser(''); + + try + { + mPgpMessage = window.openpgp.cleartext.readArmored(this.plainRaw); + if (mPgpMessage && mPgpMessage.getText) + { + this.pgpSignedVerifyStatus( + aPublicKeys.length ? Enums.SignedVerifyStatus.Unverified : Enums.SignedVerifyStatus.UnknownPublicKeys); + + aRes = mPgpMessage.verify(aPublicKeys); + if (aRes && 0 < aRes.length) + { + oValidKey = _.find(aRes, function (oItem) { + return oItem && oItem.keyid && oItem.valid; + }); + + if (oValidKey) + { + oValidSysKey = RL.data().findPublicKeyByHex(oValidKey.keyid.toHex()); + if (oValidSysKey) + { + sPlain = mPgpMessage.getText(); + + this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Success); + this.pgpSignedVerifyUser(oValidSysKey.user); + + sPlain = + $proxyDiv.empty().append( + $('').text(sPlain) + ).html() + ; + + $proxyDiv.empty(); + + this.replacePlaneTextBody(sPlain); + } + } + } + } + } + catch (oExc) {} + + this.storePgpVerifyDataToDom(); + } +}; + +MessageModel.prototype.decryptPgpEncryptedMessage = function (sPassword) +{ + if (this.isPgpEncrypted()) + { + var + aRes = [], + mPgpMessage = null, + mPgpMessageDecrypted = null, + sFrom = this.from && this.from[0] && this.from[0].email ? this.from[0].email : '', + aPublicKey = RL.data().findPublicKeysByEmail(sFrom), + oPrivateKey = RL.data().findSelfPrivateKey(sPassword), + oValidKey = null, + oValidSysKey = null, + sPlain = '' + ; + + this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Error); + this.pgpSignedVerifyUser(''); + + if (!oPrivateKey) + { + this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.UnknownPrivateKey); + } + + try + { + mPgpMessage = window.openpgp.message.readArmored(this.plainRaw); + if (mPgpMessage && oPrivateKey && mPgpMessage.decrypt) + { + this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Unverified); + + mPgpMessageDecrypted = mPgpMessage.decrypt(oPrivateKey); + if (mPgpMessageDecrypted) + { + aRes = mPgpMessageDecrypted.verify(aPublicKey); + if (aRes && 0 < aRes.length) + { + oValidKey = _.find(aRes, function (oItem) { + return oItem && oItem.keyid && oItem.valid; + }); + + if (oValidKey) + { + oValidSysKey = RL.data().findPublicKeyByHex(oValidKey.keyid.toHex()); + if (oValidSysKey) + { + this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Success); + this.pgpSignedVerifyUser(oValidSysKey.user); + } + } + } + + sPlain = mPgpMessageDecrypted.getText(); + + sPlain = + $proxyDiv.empty().append( + $('').text(sPlain) + ).html() + ; + + $proxyDiv.empty(); + + this.replacePlaneTextBody(sPlain); + } + } + } + catch (oExc) {} + + this.storePgpVerifyDataToDom(); + } +}; + +MessageModel.prototype.replacePlaneTextBody = function (sPlain) +{ + if (this.body) + { + this.body.html(sPlain).addClass('b-text-part plain'); + } +}; + +/** + * @return {string} + */ +MessageModel.prototype.flagHash = function () +{ + return [this.deleted(), this.unseen(), this.flagged(), this.answered(), this.forwarded(), + this.isReadReceipt()].join(''); +}; + +/** + * @constructor + */ +function FolderModel() +{ + this.name = ko.observable(''); + this.fullName = ''; + this.fullNameRaw = ''; + this.fullNameHash = ''; + this.delimiter = ''; + this.namespace = ''; + this.deep = 0; + this.interval = 0; + + this.selectable = false; + this.existen = true; + + this.type = ko.observable(Enums.FolderType.User); + + this.focused = ko.observable(false); + this.selected = ko.observable(false); + this.edited = ko.observable(false); + this.collapsed = ko.observable(true); + this.subScribed = ko.observable(true); + this.subFolders = ko.observableArray([]); + this.deleteAccess = ko.observable(false); + this.actionBlink = ko.observable(false).extend({'falseTimeout': 1000}); + + this.nameForEdit = ko.observable(''); + + this.name.subscribe(function (sValue) { + this.nameForEdit(sValue); + }, this); + + this.edited.subscribe(function (bValue) { + if (bValue) + { + this.nameForEdit(this.name()); + } + }, this); + + this.privateMessageCountAll = ko.observable(0); + this.privateMessageCountUnread = ko.observable(0); + + this.collapsedPrivate = ko.observable(true); +} + +/** + * @static + * @param {AjaxJsonFolder} oJsonFolder + * @return {?FolderModel} + */ +FolderModel.newInstanceFromJson = function (oJsonFolder) +{ + var oFolderModel = new FolderModel(); + return oFolderModel.initByJson(oJsonFolder) ? oFolderModel.initComputed() : null; +}; + +/** + * @return {FolderModel} + */ +FolderModel.prototype.initComputed = function () +{ + this.hasSubScribedSubfolders = ko.computed(function () { + return !!_.find(this.subFolders(), function (oFolder) { + return oFolder.subScribed() && !oFolder.isSystemFolder(); + }); + }, this); + + this.canBeEdited = ko.computed(function () { + return Enums.FolderType.User === this.type() && this.existen && this.selectable; + }, this); + + this.visible = ko.computed(function () { + var + bSubScribed = this.subScribed(), + bSubFolders = this.hasSubScribedSubfolders() + ; + + return (bSubScribed || (bSubFolders && (!this.existen || !this.selectable))); + }, this); + + this.isSystemFolder = ko.computed(function () { + return Enums.FolderType.User !== this.type(); + }, this); + + this.hidden = ko.computed(function () { + var + bSystem = this.isSystemFolder(), + bSubFolders = this.hasSubScribedSubfolders() + ; + + return (bSystem && !bSubFolders) || (!this.selectable && !bSubFolders); + + }, this); + + this.selectableForFolderList = ko.computed(function () { + return !this.isSystemFolder() && this.selectable; + }, this); + + this.messageCountAll = ko.computed({ + 'read': this.privateMessageCountAll, + 'write': function (iValue) { + if (Utils.isPosNumeric(iValue, true)) + { + this.privateMessageCountAll(iValue); + } + else + { + this.privateMessageCountAll.valueHasMutated(); + } + }, + 'owner': this + }); + + this.messageCountUnread = ko.computed({ + 'read': this.privateMessageCountUnread, + 'write': function (iValue) { + if (Utils.isPosNumeric(iValue, true)) + { + this.privateMessageCountUnread(iValue); + } + else + { + this.privateMessageCountUnread.valueHasMutated(); + } + }, + 'owner': this + }); + + this.printableUnreadCount = ko.computed(function () { + var + iCount = this.messageCountAll(), + iUnread = this.messageCountUnread(), + iType = this.type() + ; + + if (Enums.FolderType.Inbox === iType) + { + RL.data().foldersInboxUnreadCount(iUnread); + } + + if (0 < iCount) + { + if (Enums.FolderType.Draft === iType) + { + return '' + iCount; + } + else if (0 < iUnread && Enums.FolderType.Trash !== iType && Enums.FolderType.Archive !== iType && Enums.FolderType.SentItems !== iType) + { + return '' + iUnread; + } + } + + return ''; + + }, this); + + this.canBeDeleted = ko.computed(function () { + var + bSystem = this.isSystemFolder() + ; + return !bSystem && 0 === this.subFolders().length && 'INBOX' !== this.fullNameRaw; + }, this); + + this.canBeSubScribed = ko.computed(function () { + return !this.isSystemFolder() && this.selectable && 'INBOX' !== this.fullNameRaw; + }, this); + + this.visible.subscribe(function () { + Utils.timeOutAction('folder-list-folder-visibility-change', function () { + $window.trigger('folder-list-folder-visibility-change'); + }, 100); + }); + + this.localName = ko.computed(function () { + + Globals.langChangeTrigger(); + + var + iType = this.type(), + sName = this.name() + ; + + if (this.isSystemFolder()) + { + switch (iType) + { + case Enums.FolderType.Inbox: + sName = Utils.i18n('FOLDER_LIST/INBOX_NAME'); + break; + case Enums.FolderType.SentItems: + sName = Utils.i18n('FOLDER_LIST/SENT_NAME'); + break; + case Enums.FolderType.Draft: + sName = Utils.i18n('FOLDER_LIST/DRAFTS_NAME'); + break; + case Enums.FolderType.Spam: + sName = Utils.i18n('FOLDER_LIST/SPAM_NAME'); + break; + case Enums.FolderType.Trash: + sName = Utils.i18n('FOLDER_LIST/TRASH_NAME'); + break; + case Enums.FolderType.Archive: + sName = Utils.i18n('FOLDER_LIST/ARCHIVE_NAME'); + break; + } + } + + return sName; + + }, this); + + this.manageFolderSystemName = ko.computed(function () { + + Globals.langChangeTrigger(); + + var + sSuffix = '', + iType = this.type(), + sName = this.name() + ; + + if (this.isSystemFolder()) + { + switch (iType) + { + case Enums.FolderType.Inbox: + sSuffix = '(' + Utils.i18n('FOLDER_LIST/INBOX_NAME') + ')'; + break; + case Enums.FolderType.SentItems: + sSuffix = '(' + Utils.i18n('FOLDER_LIST/SENT_NAME') + ')'; + break; + case Enums.FolderType.Draft: + sSuffix = '(' + Utils.i18n('FOLDER_LIST/DRAFTS_NAME') + ')'; + break; + case Enums.FolderType.Spam: + sSuffix = '(' + Utils.i18n('FOLDER_LIST/SPAM_NAME') + ')'; + break; + case Enums.FolderType.Trash: + sSuffix = '(' + Utils.i18n('FOLDER_LIST/TRASH_NAME') + ')'; + break; + case Enums.FolderType.Archive: + sSuffix = '(' + Utils.i18n('FOLDER_LIST/ARCHIVE_NAME') + ')'; + break; + } + } + + if ('' !== sSuffix && '(' + sName + ')' === sSuffix || '(inbox)' === sSuffix.toLowerCase()) + { + sSuffix = ''; + } + + return sSuffix; + + }, this); + + this.collapsed = ko.computed({ + 'read': function () { + return !this.hidden() && this.collapsedPrivate(); + }, + 'write': function (mValue) { + this.collapsedPrivate(mValue); + }, + 'owner': this + }); + + this.hasUnreadMessages = ko.computed(function () { + return 0 < this.messageCountUnread(); + }, this); + + this.hasSubScribedUnreadMessagesSubfolders = ko.computed(function () { + return !!_.find(this.subFolders(), function (oFolder) { + return oFolder.hasUnreadMessages() || oFolder.hasSubScribedUnreadMessagesSubfolders(); + }); + }, this); + + return this; +}; + +FolderModel.prototype.fullName = ''; +FolderModel.prototype.fullNameRaw = ''; +FolderModel.prototype.fullNameHash = ''; +FolderModel.prototype.delimiter = ''; +FolderModel.prototype.namespace = ''; +FolderModel.prototype.deep = 0; +FolderModel.prototype.interval = 0; + +/** + * @return {string} + */ +FolderModel.prototype.collapsedCss = function () +{ + return this.hasSubScribedSubfolders() ? + (this.collapsed() ? 'icon-right-mini e-collapsed-sign' : 'icon-down-mini e-collapsed-sign') : 'icon-none e-collapsed-sign'; +}; + +/** + * @param {AjaxJsonFolder} oJsonFolder + * @return {boolean} + */ +FolderModel.prototype.initByJson = function (oJsonFolder) +{ + var bResult = false; + if (oJsonFolder && 'Object/Folder' === oJsonFolder['@Object']) + { + this.name(oJsonFolder.Name); + this.delimiter = oJsonFolder.Delimiter; + this.fullName = oJsonFolder.FullName; + this.fullNameRaw = oJsonFolder.FullNameRaw; + this.fullNameHash = oJsonFolder.FullNameHash; + this.deep = oJsonFolder.FullNameRaw.split(this.delimiter).length - 1; + this.selectable = !!oJsonFolder.IsSelectable; + this.existen = !!oJsonFolder.IsExisten; + + this.subScribed(!!oJsonFolder.IsSubscribed); + this.type('INBOX' === this.fullNameRaw ? Enums.FolderType.Inbox : Enums.FolderType.User); + + bResult = true; + } + + return bResult; +}; + +/** + * @return {string} + */ +FolderModel.prototype.printableFullName = function () +{ + return this.fullName.split(this.delimiter).join(' / '); +}; + +/** + * @param {string} sEmail + * @param {boolean=} bCanBeDelete = true + * @constructor + */ +function AccountModel(sEmail, bCanBeDelete) +{ + this.email = sEmail; + this.deleteAccess = ko.observable(false); + this.canBeDalete = ko.observable(bCanBeDelete); +} + +AccountModel.prototype.email = ''; + +/** + * @return {string} + */ +AccountModel.prototype.changeAccountLink = function () +{ + return RL.link().change(this.email); +}; +/** + * @param {string} sId + * @param {string} sEmail + * @param {boolean=} bCanBeDelete = true + * @constructor + */ +function IdentityModel(sId, sEmail, bCanBeDelete) +{ + this.id = sId; + this.email = ko.observable(sEmail); + this.name = ko.observable(''); + this.replyTo = ko.observable(''); + this.bcc = ko.observable(''); + + this.deleteAccess = ko.observable(false); + this.canBeDalete = ko.observable(bCanBeDelete); +} + +IdentityModel.prototype.formattedName = function () +{ + var sName = this.name(); + return '' === sName ? this.email() : sName + ' <' + this.email() + '>'; +}; + +IdentityModel.prototype.formattedNameForCompose = function () +{ + var sName = this.name(); + return '' === sName ? this.email() : sName + ' (' + this.email() + ')'; +}; + +IdentityModel.prototype.formattedNameForEmail = function () +{ + var sName = this.name(); + return '' === sName ? this.email() : '"' + Utils.quoteName(sName) + '" <' + this.email() + '>'; +}; + +/** + * @param {string} iIndex + * @param {string} sGuID + * @param {string} sID + * @param {string} sUserID + * @param {string} sEmail + * @param {boolean} bIsPrivate + * @param {string} sArmor + * @constructor + */ +function OpenPgpKeyModel(iIndex, sGuID, sID, sUserID, sEmail, bIsPrivate, sArmor) +{ + this.index = iIndex; + this.id = sID; + this.guid = sGuID; + this.user = sUserID; + this.email = sEmail; + this.armor = sArmor; + this.isPrivate = !!bIsPrivate; + + this.deleteAccess = ko.observable(false); +} + +OpenPgpKeyModel.prototype.index = 0; +OpenPgpKeyModel.prototype.id = ''; +OpenPgpKeyModel.prototype.guid = ''; +OpenPgpKeyModel.prototype.user = ''; +OpenPgpKeyModel.prototype.email = ''; +OpenPgpKeyModel.prototype.armor = ''; +OpenPgpKeyModel.prototype.isPrivate = false; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsFolderClearViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsFolderClear'); + + this.selectedFolder = ko.observable(null); + this.clearingProcess = ko.observable(false); + this.clearingError = ko.observable(''); + + this.folderFullNameForClear = ko.computed(function () { + var oFolder = this.selectedFolder(); + return oFolder ? oFolder.printableFullName() : ''; + }, this); + + this.folderNameForClear = ko.computed(function () { + var oFolder = this.selectedFolder(); + return oFolder ? oFolder.localName() : ''; + }, this); + + this.dangerDescHtml = ko.computed(function () { + return Utils.i18n('POPUPS_CLEAR_FOLDER/DANGER_DESC_HTML_1', { + 'FOLDER': this.folderNameForClear() + }); + }, this); + + this.clearCommand = Utils.createCommand(this, function () { + + var + self = this, + oFolderToClear = this.selectedFolder() + ; + + if (oFolderToClear) + { + RL.data().message(null); + RL.data().messageList([]); + + this.clearingProcess(true); + + RL.cache().setFolderHash(oFolderToClear.fullNameRaw, ''); + RL.remote().folderClear(function (sResult, oData) { + + self.clearingProcess(false); + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + RL.reloadMessageList(true); + self.cancelCommand(); + } + else + { + if (oData && oData.ErrorCode) + { + self.clearingError(Utils.getNotification(oData.ErrorCode)); + } + else + { + self.clearingError(Utils.getNotification(Enums.Notification.MailServerError)); + } + } + }, oFolderToClear.fullNameRaw); + } + + }, function () { + + var + oFolder = this.selectedFolder(), + bIsClearing = this.clearingProcess() + ; + + return !bIsClearing && null !== oFolder; + + }); + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsFolderClearViewModel', PopupsFolderClearViewModel); + +PopupsFolderClearViewModel.prototype.clearPopup = function () +{ + this.clearingProcess(false); + this.selectedFolder(null); +}; + +PopupsFolderClearViewModel.prototype.onShow = function (oFolder) +{ + this.clearPopup(); + if (oFolder) + { + this.selectedFolder(oFolder); + } +}; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsFolderCreateViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsFolderCreate'); + + Utils.initOnStartOrLangChange(function () { + this.sNoParentText = Utils.i18n('POPUPS_CREATE_FOLDER/SELECT_NO_PARENT'); + }, this); + + this.folderName = ko.observable(''); + this.folderName.focused = ko.observable(false); + + this.selectedParentValue = ko.observable(Consts.Values.UnuseOptionValue); + + this.parentFolderSelectList = ko.computed(function () { + + var + oData = RL.data(), + aTop = [], + fDisableCallback = null, + fVisibleCallback = null, + aList = oData.folderList(), + fRenameCallback = function (oItem) { + return oItem ? (oItem.isSystemFolder() ? oItem.name() + ' ' + oItem.manageFolderSystemName() : oItem.name()) : ''; + } + ; + + aTop.push(['', this.sNoParentText]); + + if ('' !== oData.namespace) + { + fDisableCallback = function (oItem) + { + return oData.namespace !== oItem.fullNameRaw.substr(0, oData.namespace.length); + }; + } + + return RL.folderListOptionsBuilder([], aList, [], aTop, null, fDisableCallback, fVisibleCallback, fRenameCallback); + + }, this); + + // commands + this.createFolder = Utils.createCommand(this, function () { + + var + oData = RL.data(), + sParentFolderName = this.selectedParentValue() + ; + + if ('' === sParentFolderName && 1 < oData.namespace.length) + { + sParentFolderName = oData.namespace.substr(0, oData.namespace.length - 1); + } + + oData.foldersCreating(true); + RL.remote().folderCreate(function (sResult, oData) { + + RL.data().foldersCreating(false); + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + RL.folders(); + } + else + { + RL.data().foldersListError( + oData && oData.ErrorCode ? Utils.getNotification(oData.ErrorCode) : Utils.i18n('NOTIFICATIONS/CANT_CREATE_FOLDER')); + } + + }, this.folderName(), sParentFolderName); + + this.cancelCommand(); + + }, function () { + return this.simpleFolderNameValidation(this.folderName()); + }); + + this.defautOptionsAfterRender = Utils.defautOptionsAfterRender; + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsFolderCreateViewModel', PopupsFolderCreateViewModel); + +PopupsFolderCreateViewModel.prototype.sNoParentText = ''; + +PopupsFolderCreateViewModel.prototype.simpleFolderNameValidation = function (sName) +{ + return (/^[^\\\/]+$/g).test(Utils.trim(sName)); +}; + +PopupsFolderCreateViewModel.prototype.clearPopup = function () +{ + this.folderName(''); + this.selectedParentValue(''); + this.folderName.focused(false); +}; + +PopupsFolderCreateViewModel.prototype.onShow = function () +{ + this.clearPopup(); +}; + +PopupsFolderCreateViewModel.prototype.onFocus = function () +{ + this.folderName.focused(true); +}; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsFolderSystemViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsFolderSystem'); + + Utils.initOnStartOrLangChange(function () { + this.sChooseOnText = Utils.i18n('POPUPS_SYSTEM_FOLDERS/SELECT_CHOOSE_ONE'); + this.sUnuseText = Utils.i18n('POPUPS_SYSTEM_FOLDERS/SELECT_UNUSE_NAME'); + }, this); + + this.notification = ko.observable(''); + + this.folderSelectList = ko.computed(function () { + return RL.folderListOptionsBuilder([], RL.data().folderList(), RL.data().folderListSystemNames(), [ + ['', this.sChooseOnText], + [Consts.Values.UnuseOptionValue, this.sUnuseText] + ]); + }, this); + + var + oData = RL.data(), + self = this, + fSaveSystemFolders = null, + fCallback = null + ; + + this.sentFolder = oData.sentFolder; + this.draftFolder = oData.draftFolder; + this.spamFolder = oData.spamFolder; + this.trashFolder = oData.trashFolder; + this.archiveFolder = oData.archiveFolder; + + fSaveSystemFolders = _.debounce(function () { + + RL.settingsSet('SentFolder', self.sentFolder()); + RL.settingsSet('DraftFolder', self.draftFolder()); + RL.settingsSet('SpamFolder', self.spamFolder()); + RL.settingsSet('TrashFolder', self.trashFolder()); + RL.settingsSet('ArchiveFolder', self.archiveFolder()); + + RL.remote().saveSystemFolders(Utils.emptyFunction, { + 'SentFolder': self.sentFolder(), + 'DraftFolder': self.draftFolder(), + 'SpamFolder': self.spamFolder(), + 'TrashFolder': self.trashFolder(), + 'ArchiveFolder': self.archiveFolder(), + 'NullFolder': 'NullFolder' + }); + + }, 1000); + + fCallback = function () { + + RL.settingsSet('SentFolder', self.sentFolder()); + RL.settingsSet('DraftFolder', self.draftFolder()); + RL.settingsSet('SpamFolder', self.spamFolder()); + RL.settingsSet('TrashFolder', self.trashFolder()); + RL.settingsSet('ArchiveFolder', self.archiveFolder()); + + fSaveSystemFolders(); + }; + + this.sentFolder.subscribe(fCallback); + this.draftFolder.subscribe(fCallback); + this.spamFolder.subscribe(fCallback); + this.trashFolder.subscribe(fCallback); + this.archiveFolder.subscribe(fCallback); + + this.defautOptionsAfterRender = Utils.defautOptionsAfterRender; + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsFolderSystemViewModel', PopupsFolderSystemViewModel); + +PopupsFolderSystemViewModel.prototype.sChooseOnText = ''; +PopupsFolderSystemViewModel.prototype.sUnuseText = ''; + +/** + * @param {number=} iNotificationType = Enums.SetSystemFoldersNotification.None + */ +PopupsFolderSystemViewModel.prototype.onShow = function (iNotificationType) +{ + var sNotification = ''; + + iNotificationType = Utils.isUnd(iNotificationType) ? Enums.SetSystemFoldersNotification.None : iNotificationType; + + switch (iNotificationType) + { + case Enums.SetSystemFoldersNotification.Sent: + sNotification = Utils.i18n('POPUPS_SYSTEM_FOLDERS/NOTIFICATION_SENT'); + break; + case Enums.SetSystemFoldersNotification.Draft: + sNotification = Utils.i18n('POPUPS_SYSTEM_FOLDERS/NOTIFICATION_DRAFTS'); + break; + case Enums.SetSystemFoldersNotification.Spam: + sNotification = Utils.i18n('POPUPS_SYSTEM_FOLDERS/NOTIFICATION_SPAM'); + break; + case Enums.SetSystemFoldersNotification.Trash: + sNotification = Utils.i18n('POPUPS_SYSTEM_FOLDERS/NOTIFICATION_TRASH'); + break; + case Enums.SetSystemFoldersNotification.Archive: + sNotification = Utils.i18n('POPUPS_SYSTEM_FOLDERS/NOTIFICATION_ARCHIVE'); + break; + } + + this.notification(sNotification); +}; + + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsComposeViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsCompose'); + + this.oEditor = null; + this.aDraftInfo = null; + this.sInReplyTo = ''; + this.bFromDraft = false; + this.bSkipNext = false; + this.sReferences = ''; + + this.bAllowIdentities = RL.settingsGet('AllowIdentities'); + + var + self = this, + oRainLoopData = RL.data(), + fCcAndBccCheckHelper = function (aValue) { + if (false === self.showCcAndBcc() && 0 < aValue.length) + { + self.showCcAndBcc(true); + } + } + ; + + this.allowOpenPGP = oRainLoopData.allowOpenPGP; + + this.resizer = ko.observable(false).extend({'throttle': 50}); + + this.identitiesDropdownTrigger = ko.observable(false); + + this.to = ko.observable(''); + this.to.focusTrigger = ko.observable(false); + this.cc = ko.observable(''); + this.bcc = ko.observable(''); + + this.replyTo = ko.observable(''); + this.subject = ko.observable(''); + this.isHtml = ko.observable(false); + + this.requestReadReceipt = ko.observable(false); + + this.sendError = ko.observable(false); + this.sendSuccessButSaveError = ko.observable(false); + this.savedError = ko.observable(false); + + this.savedTime = ko.observable(0); + this.savedOrSendingText = ko.observable(''); + + this.emptyToError = ko.observable(false); + this.showCcAndBcc = ko.observable(false); + + this.cc.subscribe(fCcAndBccCheckHelper, this); + this.bcc.subscribe(fCcAndBccCheckHelper, this); + + this.draftFolder = ko.observable(''); + this.draftUid = ko.observable(''); + this.sending = ko.observable(false); + this.saving = ko.observable(false); + this.attachments = ko.observableArray([]); + + this.attachmentsInProcess = this.attachments.filter(function (oItem) { + return oItem && '' === oItem.tempName(); + }); + + this.attachmentsInReady = this.attachments.filter(function (oItem) { + return oItem && '' !== oItem.tempName(); + }); + + this.attachments.subscribe(function () { + this.triggerForResize(); + }, this); + + this.isDraftFolderMessage = ko.computed(function () { + return '' !== this.draftFolder() && '' !== this.draftUid(); + }, this); + + this.composeUploaderButton = ko.observable(null); + this.composeUploaderDropPlace = ko.observable(null); + this.dragAndDropEnabled = ko.observable(false); + this.dragAndDropOver = ko.observable(false).extend({'throttle': 1}); + this.dragAndDropVisible = ko.observable(false).extend({'throttle': 1}); + this.attacheMultipleAllowed = ko.observable(false); + this.addAttachmentEnabled = ko.observable(false); + + this.composeEditorArea = ko.observable(null); + + this.identities = RL.data().identities; + + this.currentIdentityID = ko.observable(''); + + this.currentIdentityString = ko.observable(''); + this.currentIdentityResultEmail = ko.observable(''); + + this.identitiesOptions = ko.computed(function () { + + var aList = [{ + 'optValue': oRainLoopData.accountEmail(), + 'optText': this.formattedFrom(false) + }]; + + _.each(oRainLoopData.identities(), function (oItem) { + aList.push({ + 'optValue': oItem.id, + 'optText': oItem.formattedNameForCompose() + }); + }); + + return aList; + + }, this); + + ko.computed(function () { + + var + sResult = '', + sResultEmail = '', + oItem = null, + aList = this.identities(), + sID = this.currentIdentityID() + ; + + if (this.bAllowIdentities && sID && sID !== RL.data().accountEmail()) + { + oItem = _.find(aList, function (oItem) { + return oItem && sID === oItem['id']; + }); + + sResult = oItem ? oItem.formattedNameForCompose() : ''; + sResultEmail = oItem ? oItem.formattedNameForEmail() : ''; + + if ('' === sResult && aList[0]) + { + this.currentIdentityID(aList[0]['id']); + return ''; + } + } + + if ('' === sResult) + { + sResult = this.formattedFrom(false); + sResultEmail = this.formattedFrom(true); + } + + this.currentIdentityString(sResult); + this.currentIdentityResultEmail(sResultEmail); + + return sResult; + + }, this); + + this.to.subscribe(function (sValue) { + if (this.emptyToError() && 0 < sValue.length) + { + this.emptyToError(false); + } + }, this); + + this.editorResizeThrottle = _.throttle(_.bind(this.editorResize, this), 100); + + this.resizer.subscribe(function () { + this.editorResizeThrottle(); + }, this); + + this.canBeSended = ko.computed(function () { + return !this.sending() && + !this.saving() && + 0 === this.attachmentsInProcess().length && + 0 < this.to().length + ; + }, this); + + this.canBeSendedOrSaved = ko.computed(function () { + return !this.sending() && !this.saving(); + }, this); + + this.deleteCommand = Utils.createCommand(this, function () { + + RL.deleteMessagesFromFolderWithoutCheck(this.draftFolder(), [this.draftUid()]); + kn.hideScreenPopup(PopupsComposeViewModel); + + }, function () { + return this.isDraftFolderMessage(); + }); + + this.sendMessageResponse = _.bind(this.sendMessageResponse, this); + this.saveMessageResponse = _.bind(this.saveMessageResponse, this); + + this.sendCommand = Utils.createCommand(this, function () { + var + sTo = Utils.trim(this.to()), + sSentFolder = RL.data().sentFolder(), + aFlagsCache = [] + ; + + if (0 === sTo.length) + { + this.emptyToError(true); + } + else + { + if (RL.data().replySameFolder()) + { + if (Utils.isArray(this.aDraftInfo) && 3 === this.aDraftInfo.length && Utils.isNormal(this.aDraftInfo[2]) && 0 < this.aDraftInfo[2].length) + { + sSentFolder = this.aDraftInfo[2]; + } + } + + if ('' === sSentFolder) + { + kn.showScreenPopup(PopupsFolderSystemViewModel, [Enums.SetSystemFoldersNotification.Sent]); + } + else + { + this.sendError(false); + this.sending(true); + + if (Utils.isArray(this.aDraftInfo) && 3 === this.aDraftInfo.length) + { + aFlagsCache = RL.cache().getMessageFlagsFromCache(this.aDraftInfo[2], this.aDraftInfo[1]); + if (aFlagsCache) + { + if ('forward' === this.aDraftInfo[0]) + { + aFlagsCache[3] = true; + } + else + { + aFlagsCache[2] = true; + } + + RL.cache().setMessageFlagsToCache(this.aDraftInfo[2], this.aDraftInfo[1], aFlagsCache); + RL.reloadFlagsCurrentMessageListAndMessageFromCache(); + RL.cache().setFolderHash(this.aDraftInfo[2], ''); + } + } + + sSentFolder = Consts.Values.UnuseOptionValue === sSentFolder ? '' : sSentFolder; + + RL.cache().setFolderHash(this.draftFolder(), ''); + RL.cache().setFolderHash(sSentFolder, ''); + + RL.remote().sendMessage( + this.sendMessageResponse, + this.draftFolder(), + this.draftUid(), + sSentFolder, + this.currentIdentityResultEmail(), + sTo, + this.cc(), + this.bcc(), + this.subject(), + this.oEditor ? this.oEditor.isHtml() : false, + this.oEditor ? this.oEditor.getData() : '', + this.prepearAttachmentsForSendOrSave(), + this.aDraftInfo, + this.sInReplyTo, + this.sReferences, + this.requestReadReceipt() + ); + } + } + }, this.canBeSendedOrSaved); + + this.saveCommand = Utils.createCommand(this, function () { + + if (RL.data().draftFolderNotEnabled()) + { + kn.showScreenPopup(PopupsFolderSystemViewModel, [Enums.SetSystemFoldersNotification.Draft]); + } + else + { + this.savedError(false); + this.saving(true); + + this.bSkipNext = true; + + RL.cache().setFolderHash(RL.data().draftFolder(), ''); + + RL.remote().saveMessage( + this.saveMessageResponse, + this.draftFolder(), + this.draftUid(), + RL.data().draftFolder(), + this.currentIdentityResultEmail(), + this.to(), + this.cc(), + this.bcc(), + this.subject(), + this.oEditor ? this.oEditor.isHtml() : false, + this.oEditor ? this.oEditor.getData() : '', + this.prepearAttachmentsForSendOrSave(), + this.aDraftInfo, + this.sInReplyTo, + this.sReferences + ); + } + + }, this.canBeSendedOrSaved); + + RL.sub('interval.1m', function () { + if (this.modalVisibility() && !RL.data().draftFolderNotEnabled() && !this.isEmptyForm(false) && + !this.bSkipNext && !this.saving() && !this.sending() && !this.savedError()) + { + this.bSkipNext = false; + this.saveCommand(); + } + }, this); + + this.showCcAndBcc.subscribe(function () { + this.triggerForResize(); + }, this); + + this.dropboxEnabled = ko.observable(RL.settingsGet('DropboxApiKey') ? true : false); + + this.dropboxCommand = Utils.createCommand(this, function () { + + if (window.Dropbox) + { + window.Dropbox.choose({ + //'iframe': true, + 'success': function(aFiles) { + + if (aFiles && aFiles[0] && aFiles[0]['link']) + { + self.addDropboxAttachment(aFiles[0]); + } + }, + 'linkType': "direct", + 'multiselect': false + }); + } + + return true; + + }, function () { + return this.dropboxEnabled(); + }); + + this.driveEnabled = ko.observable(false); + + this.driveCommand = Utils.createCommand(this, function () { + +// this.driveOpenPopup(); + return true; + + }, function () { + return this.driveEnabled(); + }); + +// this.driveCallback = _.bind(this.driveCallback, this); + + this.bDisabeCloseOnEsc = true; + this.sDefaultKeyScope = Enums.KeyState.Compose; + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsComposeViewModel', PopupsComposeViewModel); + +PopupsComposeViewModel.prototype.openOpenPgpPopup = function () +{ + if (this.allowOpenPGP() && this.oEditor && !this.oEditor.isHtml()) + { + var self = this; + kn.showScreenPopup(PopupsComposeOpenPgpViewModel, [ + function (sResult) { + self.editor(function (oEditor) { + oEditor.setPlain(sResult); + }); + }, + this.oEditor.getData(), + this.currentIdentityResultEmail(), + this.to(), + this.cc(), + this.bcc() + ]); + } +}; + +PopupsComposeViewModel.prototype.reloadDraftFolder = function () +{ + var sDraftFolder = RL.data().draftFolder(); + if ('' !== sDraftFolder) + { + RL.cache().setFolderHash(sDraftFolder, ''); + if (RL.data().currentFolderFullNameRaw() === sDraftFolder) + { + RL.reloadMessageList(true); + } + else + { + RL.folderInformation(sDraftFolder); + } + } +}; + +PopupsComposeViewModel.prototype.findIdentityIdByMessage = function (sComposeType, oMessage) +{ + var + oIDs = {}, + sResult = '', + fFindHelper = function (oItem) { + if (oItem && oItem.email && oIDs[oItem.email]) + { + sResult = oIDs[oItem.email]; + return true; + } + + return false; + } + ; + + if (this.bAllowIdentities) + { + _.each(this.identities(), function (oItem) { + oIDs[oItem.email()] = oItem['id']; + }); + } + + oIDs[RL.data().accountEmail()] = RL.data().accountEmail(); + + if (oMessage) + { + switch (sComposeType) + { + case Enums.ComposeType.Empty: + sResult = RL.data().accountEmail(); + break; + case Enums.ComposeType.Reply: + case Enums.ComposeType.ReplyAll: + case Enums.ComposeType.Forward: + case Enums.ComposeType.ForwardAsAttachment: + _.find(_.union(oMessage.to, oMessage.cc, oMessage.bcc), fFindHelper); + break; + case Enums.ComposeType.Draft: + _.find(_.union(oMessage.from, oMessage.replyTo), fFindHelper); + break; + } + } + else + { + sResult = RL.data().accountEmail(); + } + + return sResult; +}; + +PopupsComposeViewModel.prototype.selectIdentity = function (oIdentity) +{ + if (oIdentity) + { + this.currentIdentityID(oIdentity.optValue); + } +}; + +/** + * + * @param {boolean=} bHeaderResult = false + * @returns {string} + */ +PopupsComposeViewModel.prototype.formattedFrom = function (bHeaderResult) +{ + var + sDisplayName = RL.data().displayName(), + sEmail = RL.data().accountEmail() + ; + + return '' === sDisplayName ? sEmail : + ((Utils.isUnd(bHeaderResult) ? false : !!bHeaderResult) ? + '"' + Utils.quoteName(sDisplayName) + '" <' + sEmail + '>' : + sDisplayName + ' (' + sEmail + ')') + ; +}; + +PopupsComposeViewModel.prototype.sendMessageResponse = function (sResult, oData) +{ + var + bResult = false, + sMessage = '' + ; + + this.sending(false); + + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + bResult = true; + if (this.modalVisibility()) + { + Utils.delegateRun(this, 'closeCommand'); + } + } + + if (this.modalVisibility() && !bResult) + { + if (oData && Enums.Notification.CantSaveMessage === oData.ErrorCode) + { + this.sendSuccessButSaveError(true); + window.alert(Utils.trim(Utils.i18n('COMPOSE/SAVED_ERROR_ON_SEND'))); + } + else + { + sMessage = Utils.getNotification(oData && oData.ErrorCode ? oData.ErrorCode : Enums.Notification.CantSendMessage, + oData && oData.ErrorMessage ? oData.ErrorMessage : ''); + + this.sendError(true); + window.alert(sMessage || Utils.getNotification(Enums.Notification.CantSendMessage)); + } + } + + this.reloadDraftFolder(); +}; + +PopupsComposeViewModel.prototype.saveMessageResponse = function (sResult, oData) +{ + var + bResult = false, + oMessage = null + ; + + this.saving(false); + + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + if (oData.Result.NewFolder && oData.Result.NewUid) + { + if (this.bFromDraft) + { + oMessage = RL.data().message(); + if (oMessage && this.draftFolder() === oMessage.folderFullNameRaw && this.draftUid() === oMessage.uid) + { + RL.data().message(null); + } + } + + this.draftFolder(oData.Result.NewFolder); + this.draftUid(oData.Result.NewUid); + + if (this.modalVisibility()) + { + this.savedTime(Math.round((new window.Date()).getTime() / 1000)); + + this.savedOrSendingText( + 0 < this.savedTime() ? Utils.i18n('COMPOSE/SAVED_TIME', { + 'TIME': moment.unix(this.savedTime() - 1).format('LT') + }) : '' + ); + + bResult = true; + + if (this.bFromDraft) + { + RL.cache().setFolderHash(this.draftFolder(), ''); + } + } + } + } + + if (!this.modalVisibility() && !bResult) + { + this.savedError(true); + this.savedOrSendingText(Utils.getNotification(Enums.Notification.CantSaveMessage)); + } + + this.reloadDraftFolder(); +}; + +PopupsComposeViewModel.prototype.onHide = function () +{ + this.reset(); + kn.routeOn(); +}; + +/** + * @param {string} sSignature + * @param {string=} sFrom + * @return {string} + */ +PopupsComposeViewModel.prototype.convertSignature = function (sSignature, sFrom) +{ + if ('' !== sSignature) + { + var bHtml = false; + if (':HTML:' === sSignature.substr(0, 6)) + { + bHtml = true; + sSignature = sSignature.substr(6); + } + + sSignature = sSignature.replace(/[\r]/, ''); + + sFrom = Utils.pString(sFrom); + if ('' !== sFrom) + { + sSignature = sSignature.replace(/{{FROM}}/, sFrom); + } + + sSignature = sSignature.replace(/[\s]{1,2}{{FROM}}/, '{{FROM}}'); + + sSignature = sSignature.replace(/{{FROM}}/, ''); + sSignature = sSignature.replace(/{{DATE}}/, moment().format('llll')); + + if (!bHtml) + { + sSignature = Utils.convertPlainTextToHtml(sSignature); + } + } + + return sSignature; +}; + +PopupsComposeViewModel.prototype.editor = function (fOnInit) +{ + if (fOnInit) + { + var self = this; + if (!this.oEditor && this.composeEditorArea()) + { + _.delay(function () { + self.oEditor = new NewHtmlEditorWrapper(self.composeEditorArea(), null, function () { + fOnInit(self.oEditor); + }, function (bHtml) { + self.isHtml(!!bHtml); + }); + }, 300); + } + else if (this.oEditor) + { + fOnInit(this.oEditor); + } + } +}; + +/** + * @param {string=} sType = Enums.ComposeType.Empty + * @param {?MessageModel|Array=} oMessageOrArray = null + * @param {Array=} aToEmails = null + */ +PopupsComposeViewModel.prototype.onShow = function (sType, oMessageOrArray, aToEmails) +{ + kn.routeOff(); + + var + self = this, + sFrom = '', + sTo = '', + sCc = '', + sDate = '', + sSubject = '', + oText = null, + sText = '', + sReplyTitle = '', + aResplyAllParts = [], + oExcludeEmail = {}, + mEmail = RL.data().accountEmail(), + sSignature = RL.data().signature(), + bSignatureToAll = RL.data().signatureToAll(), + aDownloads = [], + aDraftInfo = null, + oMessage = null, + sComposeType = sType || Enums.ComposeType.Empty, + fEmailArrayToStringLineHelper = function (aList, bFriendly) { + + var + iIndex = 0, + iLen = aList.length, + aResult = [] + ; + + for (; iIndex < iLen; iIndex++) + { + aResult.push(aList[iIndex].toLine(!!bFriendly)); + } + + return aResult.join(', '); + } + ; + + oMessageOrArray = oMessageOrArray || null; + if (oMessageOrArray && Utils.isNormal(oMessageOrArray)) + { + oMessage = Utils.isArray(oMessageOrArray) && 1 === oMessageOrArray.length ? oMessageOrArray[0] : + (!Utils.isArray(oMessageOrArray) ? oMessageOrArray : null); + } + + if (null !== mEmail) + { + oExcludeEmail[mEmail] = true; + this.currentIdentityID(this.findIdentityIdByMessage(sComposeType, oMessage)); + } + + this.reset(); + + if (Utils.isNonEmptyArray(aToEmails)) + { + this.to(fEmailArrayToStringLineHelper(aToEmails)); + } + + if ('' !== sComposeType && oMessage) + { + sDate = oMessage.fullFormatDateValue(); + sSubject = oMessage.subject(); + aDraftInfo = oMessage.aDraftInfo; + + oText = $(oMessage.body).clone(); + Utils.removeBlockquoteSwitcher(oText); + sText = oText.html(); + + switch (sComposeType) + { + case Enums.ComposeType.Empty: + break; + + case Enums.ComposeType.Reply: + this.to(fEmailArrayToStringLineHelper(oMessage.replyEmails(oExcludeEmail))); + this.subject(Utils.replySubjectAdd('Re', sSubject)); + this.prepearMessageAttachments(oMessage, sComposeType); + this.aDraftInfo = ['reply', oMessage.uid, oMessage.folderFullNameRaw]; + this.sInReplyTo = oMessage.sMessageId; + this.sReferences = Utils.trim(this.sInReplyTo + ' ' + oMessage.sReferences); + break; + + case Enums.ComposeType.ReplyAll: + aResplyAllParts = oMessage.replyAllEmails(oExcludeEmail); + this.to(fEmailArrayToStringLineHelper(aResplyAllParts[0])); + this.cc(fEmailArrayToStringLineHelper(aResplyAllParts[1])); + this.subject(Utils.replySubjectAdd('Re', sSubject)); + this.prepearMessageAttachments(oMessage, sComposeType); + this.aDraftInfo = ['reply', oMessage.uid, oMessage.folderFullNameRaw]; + this.sInReplyTo = oMessage.sMessageId; + this.sReferences = Utils.trim(this.sInReplyTo + ' ' + oMessage.references()); + break; + + case Enums.ComposeType.Forward: + this.subject(Utils.replySubjectAdd('Fwd', sSubject)); + this.prepearMessageAttachments(oMessage, sComposeType); + this.aDraftInfo = ['forward', oMessage.uid, oMessage.folderFullNameRaw]; + this.sInReplyTo = oMessage.sMessageId; + this.sReferences = Utils.trim(this.sInReplyTo + ' ' + oMessage.sReferences); + break; + + case Enums.ComposeType.ForwardAsAttachment: + this.subject(Utils.replySubjectAdd('Fwd', sSubject)); + this.prepearMessageAttachments(oMessage, sComposeType); + this.aDraftInfo = ['forward', oMessage.uid, oMessage.folderFullNameRaw]; + this.sInReplyTo = oMessage.sMessageId; + this.sReferences = Utils.trim(this.sInReplyTo + ' ' + oMessage.sReferences); + break; + + case Enums.ComposeType.Draft: + this.to(fEmailArrayToStringLineHelper(oMessage.to)); + this.cc(fEmailArrayToStringLineHelper(oMessage.cc)); + this.bcc(fEmailArrayToStringLineHelper(oMessage.bcc)); + + this.bFromDraft = true; + + this.draftFolder(oMessage.folderFullNameRaw); + this.draftUid(oMessage.uid); + + this.subject(sSubject); + this.prepearMessageAttachments(oMessage, sComposeType); + + this.aDraftInfo = Utils.isNonEmptyArray(aDraftInfo) && 3 === aDraftInfo.length ? aDraftInfo : null; + this.sInReplyTo = oMessage.sInReplyTo; + this.sReferences = oMessage.sReferences; + break; + + case Enums.ComposeType.EditAsNew: + this.to(fEmailArrayToStringLineHelper(oMessage.to)); + this.cc(fEmailArrayToStringLineHelper(oMessage.cc)); + this.bcc(fEmailArrayToStringLineHelper(oMessage.bcc)); + + this.subject(sSubject); + this.prepearMessageAttachments(oMessage, sComposeType); + + this.aDraftInfo = Utils.isNonEmptyArray(aDraftInfo) && 3 === aDraftInfo.length ? aDraftInfo : null; + this.sInReplyTo = oMessage.sInReplyTo; + this.sReferences = oMessage.sReferences; + break; + } + + switch (sComposeType) + { + case Enums.ComposeType.Reply: + case Enums.ComposeType.ReplyAll: + sFrom = oMessage.fromToLine(false, true); + sReplyTitle = Utils.i18n('COMPOSE/REPLY_MESSAGE_TITLE', { + 'DATETIME': sDate, + 'EMAIL': sFrom + }); + + sText = '
' + sReplyTitle + ':' + + ''; + + break; + + case Enums.ComposeType.Forward: + sFrom = oMessage.fromToLine(false, true); + sTo = oMessage.toToLine(false, true); + sCc = oMessage.ccToLine(false, true); + sText = '' + sText + '
' + Utils.i18n('COMPOSE/FORWARD_MESSAGE_TOP_TITLE') + + '
' + Utils.i18n('COMPOSE/FORWARD_MESSAGE_TOP_FROM') + ': ' + sFrom + + '
' + Utils.i18n('COMPOSE/FORWARD_MESSAGE_TOP_TO') + ': ' + sTo + + (0 < sCc.length ? '
' + Utils.i18n('COMPOSE/FORWARD_MESSAGE_TOP_CC') + ': ' + sCc : '') + + '
' + Utils.i18n('COMPOSE/FORWARD_MESSAGE_TOP_SENT') + ': ' + Utils.encodeHtml(sDate) + + '
' + Utils.i18n('COMPOSE/FORWARD_MESSAGE_TOP_SUBJECT') + ': ' + Utils.encodeHtml(sSubject) + + '
' + sText; + break; + case Enums.ComposeType.ForwardAsAttachment: + sText = ''; + break; + } + + if (bSignatureToAll && '' !== sSignature && + Enums.ComposeType.EditAsNew !== sComposeType && Enums.ComposeType.Draft !== sComposeType) + { + sText = this.convertSignature(sSignature, fEmailArrayToStringLineHelper(oMessage.from, true)) + '
' + sText; + } + + this.editor(function (oEditor) { + oEditor.setHtml(sText, false); + if (!oMessage.isHtml()) + { + oEditor.modeToggle(false); + } + }); + } + else if (Enums.ComposeType.Empty === sComposeType) + { + sText = this.convertSignature(sSignature); + this.editor(function (oEditor) { + oEditor.setHtml(sText, false); + if (Enums.EditorDefaultType.Html !== RL.data().editorDefaultType()) + { + oEditor.modeToggle(false); + } + }); + } + else if (Utils.isNonEmptyArray(oMessageOrArray)) + { + _.each(oMessageOrArray, function (oMessage) { + self.addMessageAsAttachment(oMessage); + }); + } + + aDownloads = this.getAttachmentsDownloadsForUpload(); + if (Utils.isNonEmptyArray(aDownloads)) + { + RL.remote().messageUploadAttachments(function (sResult, oData) { + + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + var + oAttachment = null, + sTempName = '' + ; + + if (!self.viewModelVisibility()) + { + for (sTempName in oData.Result) + { + if (oData.Result.hasOwnProperty(sTempName)) + { + oAttachment = self.getAttachmentById(oData.Result[sTempName]); + if (oAttachment) + { + oAttachment.tempName(sTempName); + } + } + } + } + } + else + { + self.setMessageAttachmentFailedDowbloadText(); + } + + }, aDownloads); + } + + this.triggerForResize(); +}; + +PopupsComposeViewModel.prototype.onFocus = function () +{ + if ('' === this.to()) + { + this.to.focusTrigger(!this.to.focusTrigger()); + } + else if (this.oEditor) + { + this.oEditor.focus(); + } + + this.triggerForResize(); +}; + +PopupsComposeViewModel.prototype.editorResize = function () +{ + if (this.oEditor) + { + this.oEditor.resize(); + } +}; + +PopupsComposeViewModel.prototype.tryToClosePopup = function () +{ + var self = this; + kn.showScreenPopup(PopupsAskViewModel, [Utils.i18n('POPUPS_ASK/DESC_WANT_CLOSE_THIS_WINDOW'), function () { + if (self.modalVisibility()) + { + Utils.delegateRun(self, 'closeCommand'); + } + }]); +}; + +PopupsComposeViewModel.prototype.onBuild = function () +{ + this.initUploader(); + + var + self = this, + oScript = null + ; + + key('ctrl+q, command+q', Enums.KeyState.Compose, function () { + self.identitiesDropdownTrigger(true); + return false; + }); + + key('ctrl+s, command+s', Enums.KeyState.Compose, function () { + self.saveCommand(); + return false; + }); + + key('ctrl+enter, command+enter', Enums.KeyState.Compose, function () { + self.sendCommand(); + return false; + }); + + key('esc', Enums.KeyState.Compose, function () { + self.tryToClosePopup(); + return false; + }); + + $window.on('resize', function () { + self.triggerForResize(); + }); + + if (this.dropboxEnabled()) + { + oScript = document.createElement('script'); + oScript.type = 'text/javascript'; + oScript.src = 'https://www.dropbox.com/static/api/1/dropins.js'; + $(oScript).attr('id', 'dropboxjs').attr('data-app-key', RL.settingsGet('DropboxApiKey')); + + document.body.appendChild(oScript); + } + +// TODO (Google Drive) +// if (false) +// { +// $.getScript('http://www.google.com/jsapi', function () { +// if (window.google) +// { +// window.google.load('picker', '1', { +// 'callback': Utils.emptyFunction +// }); +// } +// }); +// } +}; + +//PopupsComposeViewModel.prototype.driveCallback = function (oData) +//{ +// if (oData && window.google && oData['action'] === window.google.picker.Action.PICKED) +// { +// } +//}; +// +//PopupsComposeViewModel.prototype.driveOpenPopup = function () +//{ +// if (window.google) +// { +// var +// oPicker = new window.google.picker.PickerBuilder() +// .enableFeature(window.google.picker.Feature.NAV_HIDDEN) +// .addView(new window.google.picker.View(window.google.picker.ViewId.DOCS)) +// .setCallback(this.driveCallback).build() +// ; +// +// oPicker.setVisible(true); +// } +//}; + +/** + * @param {string} sId + * @return {?Object} + */ +PopupsComposeViewModel.prototype.getAttachmentById = function (sId) +{ + var + aAttachments = this.attachments(), + iIndex = 0, + iLen = aAttachments.length + ; + + for (; iIndex < iLen; iIndex++) + { + if (aAttachments[iIndex] && sId === aAttachments[iIndex].id) + { + return aAttachments[iIndex]; + } + } + + return null; +}; + +PopupsComposeViewModel.prototype.initUploader = function () +{ + if (this.composeUploaderButton()) + { + var + oUploadCache = {}, + iAttachmentSizeLimit = Utils.pInt(RL.settingsGet('AttachmentLimit')), + oJua = new Jua({ + 'action': RL.link().upload(), + 'name': 'uploader', + 'queueSize': 2, + 'multipleSizeLimit': 50, + 'disableFolderDragAndDrop': false, + 'clickElement': this.composeUploaderButton(), + 'dragAndDropElement': this.composeUploaderDropPlace() + }) + ; + + if (oJua) + { + oJua +// .on('onLimitReached', function (iLimit) { +// alert(iLimit); +// }) + .on('onDragEnter', _.bind(function () { + this.dragAndDropOver(true); + }, this)) + .on('onDragLeave', _.bind(function () { + this.dragAndDropOver(false); + }, this)) + .on('onBodyDragEnter', _.bind(function () { + this.dragAndDropVisible(true); + }, this)) + .on('onBodyDragLeave', _.bind(function () { + this.dragAndDropVisible(false); + }, this)) + .on('onProgress', _.bind(function (sId, iLoaded, iTotal) { + var oItem = null; + if (Utils.isUnd(oUploadCache[sId])) + { + oItem = this.getAttachmentById(sId); + if (oItem) + { + oUploadCache[sId] = oItem; + } + } + else + { + oItem = oUploadCache[sId]; + } + + if (oItem) + { + oItem.progress(' - ' + Math.floor(iLoaded / iTotal * 100) + '%'); + } + + }, this)) + .on('onSelect', _.bind(function (sId, oData) { + + this.dragAndDropOver(false); + + var + that = this, + sFileName = Utils.isUnd(oData.FileName) ? '' : oData.FileName.toString(), + mSize = Utils.isNormal(oData.Size) ? Utils.pInt(oData.Size) : null, + oAttachment = new ComposeAttachmentModel(sId, sFileName, mSize) + ; + + oAttachment.cancel = (function (sId) { + + return function () { + that.attachments.remove(function (oItem) { + return oItem && oItem.id === sId; + }); + + if (oJua) + { + oJua.cancel(sId); + } + }; + + }(sId)); + + this.attachments.push(oAttachment); + + if (0 < mSize && 0 < iAttachmentSizeLimit && iAttachmentSizeLimit < mSize) + { + oAttachment.error(Utils.i18n('UPLOAD/ERROR_FILE_IS_TOO_BIG')); + return false; + } + + return true; + + }, this)) + .on('onStart', _.bind(function (sId) { + + var + oItem = null + ; + + if (Utils.isUnd(oUploadCache[sId])) + { + oItem = this.getAttachmentById(sId); + if (oItem) + { + oUploadCache[sId] = oItem; + } + } + else + { + oItem = oUploadCache[sId]; + } + + if (oItem) + { + oItem.waiting(false); + oItem.uploading(true); + } + + }, this)) + .on('onComplete', _.bind(function (sId, bResult, oData) { + + var + sError = '', + mErrorCode = null, + oAttachmentJson = null, + oAttachment = this.getAttachmentById(sId) + ; + + oAttachmentJson = bResult && oData && oData.Result && oData.Result.Attachment ? oData.Result.Attachment : null; + mErrorCode = oData && oData.Result && oData.Result.ErrorCode ? oData.Result.ErrorCode : null; + + if (null !== mErrorCode) + { + sError = Utils.getUploadErrorDescByCode(mErrorCode); + } + else if (!oAttachmentJson) + { + sError = Utils.i18n('UPLOAD/ERROR_UNKNOWN'); + } + + if (oAttachment) + { + if ('' !== sError && 0 < sError.length) + { + oAttachment + .waiting(false) + .uploading(false) + .error(sError) + ; + } + else if (oAttachmentJson) + { + oAttachment + .waiting(false) + .uploading(false) + ; + + oAttachment.initByUploadJson(oAttachmentJson); + } + + if (Utils.isUnd(oUploadCache[sId])) + { + delete (oUploadCache[sId]); + } + } + + }, this)) + ; + + this + .addAttachmentEnabled(true) + .dragAndDropEnabled(oJua.isDragAndDropSupported()) + ; + } + else + { + this + .addAttachmentEnabled(false) + .dragAndDropEnabled(false) + ; + } + } +}; + +/** + * @return {Object} + */ +PopupsComposeViewModel.prototype.prepearAttachmentsForSendOrSave = function () +{ + var oResult = {}; + _.each(this.attachmentsInReady(), function (oItem) { + if (oItem && '' !== oItem.tempName() && oItem.enabled()) + { + oResult[oItem.tempName()] = [ + oItem.fileName(), + oItem.isInline ? '1' : '0', + oItem.CID, + oItem.contentLocation + ]; + } + }); + + return oResult; +}; + +/** + * @param {MessageModel} oMessage + */ +PopupsComposeViewModel.prototype.addMessageAsAttachment = function (oMessage) +{ + if (oMessage) + { + var + self = this, + oAttachment = null, + sTemp = oMessage.subject(), + fCancelFunc = function (sId) { + return function () { + self.attachments.remove(function (oItem) { + return oItem && oItem.id === sId; + }); + }; + } + ; + + sTemp = '.eml' === sTemp.substr(-4).toLowerCase() ? sTemp : sTemp + '.eml'; + oAttachment = new ComposeAttachmentModel( + oMessage.requestHash, sTemp, oMessage.size() + ); + + oAttachment.fromMessage = true; + oAttachment.cancel = fCancelFunc(oMessage.requestHash); + oAttachment.waiting(false).uploading(true); + + this.attachments.push(oAttachment); + } +}; + +/** + * @param {Object} oDropboxFile + * @return {boolean} + */ +PopupsComposeViewModel.prototype.addDropboxAttachment = function (oDropboxFile) +{ + var + self = this, + fCancelFunc = function (sId) { + return function () { + self.attachments.remove(function (oItem) { + return oItem && oItem.id === sId; + }); + }; + }, + iAttachmentSizeLimit = Utils.pInt(RL.settingsGet('AttachmentLimit')), + oAttachment = null, + mSize = oDropboxFile['bytes'] + ; + + oAttachment = new ComposeAttachmentModel( + oDropboxFile['link'], oDropboxFile['name'], mSize + ); + + oAttachment.fromMessage = false; + oAttachment.cancel = fCancelFunc(oDropboxFile['link']); + oAttachment.waiting(false).uploading(true); + + this.attachments.push(oAttachment); + + if (0 < mSize && 0 < iAttachmentSizeLimit && iAttachmentSizeLimit < mSize) + { + oAttachment.uploading(false); + oAttachment.error(Utils.i18n('UPLOAD/ERROR_FILE_IS_TOO_BIG')); + return false; + } + + RL.remote().composeUploadExternals(function (sResult, oData) { + + var bResult = false; + oAttachment.uploading(false); + + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + if (oData.Result[oAttachment.id]) + { + bResult = true; + oAttachment.tempName(oData.Result[oAttachment.id]); + } + } + + if (!bResult) + { + oAttachment.error(Utils.getUploadErrorDescByCode(Enums.UploadErrorCode.FileNoUploaded)); + } + + }, [oDropboxFile['link']]); + + return true; +}; + +/** + * @param {MessageModel} oMessage + * @param {string} sType + */ +PopupsComposeViewModel.prototype.prepearMessageAttachments = function (oMessage, sType) +{ + if (oMessage) + { + var + self = this, + aAttachments = Utils.isNonEmptyArray(oMessage.attachments()) ? oMessage.attachments() : [], + iIndex = 0, + iLen = aAttachments.length, + oAttachment = null, + oItem = null, + bAdd = false, + fCancelFunc = function (sId) { + return function () { + self.attachments.remove(function (oItem) { + return oItem && oItem.id === sId; + }); + }; + } + ; + + if (Enums.ComposeType.ForwardAsAttachment === sType) + { + this.addMessageAsAttachment(oMessage); + } + else + { + for (; iIndex < iLen; iIndex++) + { + oItem = aAttachments[iIndex]; + + bAdd = false; + switch (sType) { + case Enums.ComposeType.Reply: + case Enums.ComposeType.ReplyAll: + bAdd = oItem.isLinked; + break; + + case Enums.ComposeType.Forward: + case Enums.ComposeType.Draft: + case Enums.ComposeType.EditAsNew: + bAdd = true; + break; + } + + bAdd = true; + if (bAdd) + { + oAttachment = new ComposeAttachmentModel( + oItem.download, oItem.fileName, oItem.estimatedSize, + oItem.isInline, oItem.isLinked, oItem.cid, oItem.contentLocation + ); + + oAttachment.fromMessage = true; + oAttachment.cancel = fCancelFunc(oItem.download); + oAttachment.waiting(false).uploading(true); + + this.attachments.push(oAttachment); + } + } + } + } +}; + +PopupsComposeViewModel.prototype.removeLinkedAttachments = function () +{ + this.attachments.remove(function (oItem) { + return oItem && oItem.isLinked; + }); +}; + +PopupsComposeViewModel.prototype.setMessageAttachmentFailedDowbloadText = function () +{ + _.each(this.attachments(), function(oAttachment) { + if (oAttachment && oAttachment.fromMessage) + { + oAttachment + .waiting(false) + .uploading(false) + .error(Utils.getUploadErrorDescByCode(Enums.UploadErrorCode.FileNoUploaded)) + ; + } + }, this); +}; + +/** + * @param {boolean=} bIncludeAttachmentInProgress = true + * @return {boolean} + */ +PopupsComposeViewModel.prototype.isEmptyForm = function (bIncludeAttachmentInProgress) +{ + bIncludeAttachmentInProgress = Utils.isUnd(bIncludeAttachmentInProgress) ? true : !!bIncludeAttachmentInProgress; + var bAttach = bIncludeAttachmentInProgress ? + 0 === this.attachments().length : 0 === this.attachmentsInReady().length; + + return 0 === this.to().length && + 0 === this.cc().length && + 0 === this.bcc().length && + 0 === this.subject().length && + bAttach && + (!this.oEditor || '' === this.oEditor.getData()) + ; +}; + +PopupsComposeViewModel.prototype.reset = function () +{ + this.to(''); + this.cc(''); + this.bcc(''); + this.replyTo(''); + this.subject(''); + + this.requestReadReceipt(false); + + this.aDraftInfo = null; + this.sInReplyTo = ''; + this.bFromDraft = false; + this.sReferences = ''; + + this.sendError(false); + this.sendSuccessButSaveError(false); + this.savedError(false); + this.savedTime(0); + this.savedOrSendingText(''); + this.emptyToError(false); + this.showCcAndBcc(false); + + this.attachments([]); + this.dragAndDropOver(false); + this.dragAndDropVisible(false); + + this.draftFolder(''); + this.draftUid(''); + + this.sending(false); + this.saving(false); + + if (this.oEditor) + { + this.oEditor.clear(false); + } +}; + +/** + * @return {Array} + */ +PopupsComposeViewModel.prototype.getAttachmentsDownloadsForUpload = function () +{ + return _.map(_.filter(this.attachments(), function (oItem) { + return oItem && '' === oItem.tempName(); + }), function (oItem) { + return oItem.id; + }); +}; + +PopupsComposeViewModel.prototype.triggerForResize = function () +{ + this.resizer(!this.resizer()); + this.editorResizeThrottle(); +}; + + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsContactsViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsContacts'); + + var + self = this, + fFastClearEmptyListHelper = function (aList) { + if (aList && 0 < aList.length) { + self.viewProperties.removeAll(aList); + } + } + ; + + this.allowContactsSync = RL.data().allowContactsSync; + this.enableContactsSync = RL.data().enableContactsSync; + this.allowExport = !Globals.bMobileDevice; + + this.search = ko.observable(''); + this.contactsCount = ko.observable(0); + this.contacts = RL.data().contacts; + + this.currentContact = ko.observable(null); + + this.importUploaderButton = ko.observable(null); + + this.contactsPage = ko.observable(1); + this.contactsPageCount = ko.computed(function () { + var iPage = Math.ceil(this.contactsCount() / Consts.Defaults.ContactsPerPage); + return 0 >= iPage ? 1 : iPage; + }, this); + + this.contactsPagenator = ko.computed(Utils.computedPagenatorHelper(this.contactsPage, this.contactsPageCount)); + + this.emptySelection = ko.observable(true); + this.viewClearSearch = ko.observable(false); + + this.viewID = ko.observable(''); + this.viewReadOnly = ko.observable(false); + this.viewProperties = ko.observableArray([]); + + this.viewSaveTrigger = ko.observable(Enums.SaveSettingsStep.Idle); + + this.viewPropertiesNames = this.viewProperties.filter(function(oProperty) { + return -1 < Utils.inArray(oProperty.type(), [ + Enums.ContactPropertyType.FirstName, Enums.ContactPropertyType.LastName + ]); + }); + + this.viewPropertiesOther = this.viewProperties.filter(function(oProperty) { + return -1 < Utils.inArray(oProperty.type(), [ + Enums.ContactPropertyType.Note + ]); + }); + + this.viewPropertiesOther = ko.computed(function () { + + var aList = _.filter(this.viewProperties(), function (oProperty) { + return -1 < Utils.inArray(oProperty.type(), [ + Enums.ContactPropertyType.Nick + ]); + }); + + return _.sortBy(aList, function (oProperty) { + return oProperty.type(); + }); + + }, this); + + this.viewPropertiesEmails = this.viewProperties.filter(function(oProperty) { + return Enums.ContactPropertyType.Email === oProperty.type(); + }); + + this.viewPropertiesWeb = this.viewProperties.filter(function(oProperty) { + return Enums.ContactPropertyType.Web === oProperty.type(); + }); + + this.viewHasNonEmptyRequaredProperties = ko.computed(function() { + + var + aNames = this.viewPropertiesNames(), + aEmail = this.viewPropertiesEmails(), + fHelper = function (oProperty) { + return '' !== Utils.trim(oProperty.value()); + } + ; + + return !!(_.find(aNames, fHelper) || _.find(aEmail, fHelper)); + }, this); + + this.viewPropertiesPhones = this.viewProperties.filter(function(oProperty) { + return Enums.ContactPropertyType.Phone === oProperty.type(); + }); + + this.viewPropertiesEmailsNonEmpty = this.viewPropertiesNames.filter(function(oProperty) { + return '' !== Utils.trim(oProperty.value()); + }); + + this.viewPropertiesEmailsEmptyAndOnFocused = this.viewPropertiesEmails.filter(function(oProperty) { + var bF = oProperty.focused(); + return '' === Utils.trim(oProperty.value()) && !bF; + }); + + this.viewPropertiesPhonesEmptyAndOnFocused = this.viewPropertiesPhones.filter(function(oProperty) { + var bF = oProperty.focused(); + return '' === Utils.trim(oProperty.value()) && !bF; + }); + + this.viewPropertiesWebEmptyAndOnFocused = this.viewPropertiesWeb.filter(function(oProperty) { + var bF = oProperty.focused(); + return '' === Utils.trim(oProperty.value()) && !bF; + }); + + this.viewPropertiesOtherEmptyAndOnFocused = ko.computed(function () { + return _.filter(this.viewPropertiesOther(), function (oProperty) { + var bF = oProperty.focused(); + return '' === Utils.trim(oProperty.value()) && !bF; + }); + }, this); + + this.viewPropertiesEmailsEmptyAndOnFocused.subscribe(function(aList) { + fFastClearEmptyListHelper(aList); + }); + + this.viewPropertiesPhonesEmptyAndOnFocused.subscribe(function(aList) { + fFastClearEmptyListHelper(aList); + }); + + this.viewPropertiesWebEmptyAndOnFocused.subscribe(function(aList) { + fFastClearEmptyListHelper(aList); + }); + + this.viewPropertiesOtherEmptyAndOnFocused.subscribe(function(aList) { + fFastClearEmptyListHelper(aList); + }); + + this.viewSaving = ko.observable(false); + + this.useCheckboxesInList = RL.data().useCheckboxesInList; + + this.search.subscribe(function () { + this.reloadContactList(); + }, this); + + this.contacts.subscribe(function () { + Utils.windowResize(); + }, this); + + this.viewProperties.subscribe(function () { + Utils.windowResize(); + }, this); + + this.contactsChecked = ko.computed(function () { + return _.filter(this.contacts(), function (oItem) { + return oItem.checked(); + }); + }, this); + + this.contactsCheckedOrSelected = ko.computed(function () { + + var + aChecked = this.contactsChecked(), + oSelected = this.currentContact() + ; + + return _.union(aChecked, oSelected ? [oSelected] : []); + + }, this); + + this.contactsCheckedOrSelectedUids = ko.computed(function () { + return _.map(this.contactsCheckedOrSelected(), function (oContact) { + return oContact.idContact; + }); + }, this); + + this.selector = new Selector(this.contacts, this.currentContact, + '.e-contact-item .actionHandle', '.e-contact-item.selected', '.e-contact-item .checkboxItem', + '.e-contact-item.focused'); + + this.selector.on('onItemSelect', _.bind(function (oContact) { + this.populateViewContact(oContact ? oContact : null); + if (!oContact) + { + this.emptySelection(true); + } + }, this)); + + this.selector.on('onItemGetUid', function (oContact) { + return oContact ? oContact.generateUid() : ''; + }); + + this.newCommand = Utils.createCommand(this, function () { + this.populateViewContact(null); + this.currentContact(null); + }); + + this.deleteCommand = Utils.createCommand(this, function () { + this.deleteSelectedContacts(); + this.emptySelection(true); + }, function () { + return 0 < this.contactsCheckedOrSelected().length; + }); + + this.newMessageCommand = Utils.createCommand(this, function () { + var aC = this.contactsCheckedOrSelected(), aE = []; + if (Utils.isNonEmptyArray(aC)) + { + aE = _.map(aC, function (oItem) { + if (oItem) + { + var + aData = oItem.getNameAndEmailHelper(), + oEmail = aData ? new EmailModel(aData[0], aData[1]) : null + ; + + if (oEmail && oEmail.validate()) + { + return oEmail; + } + } + + return null; + }); + + aE = _.compact(aE); + } + + if (Utils.isNonEmptyArray(aE)) + { + kn.hideScreenPopup(PopupsContactsViewModel); + kn.showScreenPopup(PopupsComposeViewModel, [Enums.ComposeType.Empty, null, aE]); + } + + }, function () { + return 0 < this.contactsCheckedOrSelected().length; + }); + + this.clearCommand = Utils.createCommand(this, function () { + this.search(''); + }); + + this.saveCommand = Utils.createCommand(this, function () { + + this.viewSaving(true); + this.viewSaveTrigger(Enums.SaveSettingsStep.Animate); + + var + sRequestUid = Utils.fakeMd5(), + aProperties = [] + ; + + _.each(this.viewProperties(), function (oItem) { + if (oItem.type() && '' !== Utils.trim(oItem.value())) + { + aProperties.push([oItem.type(), oItem.value(), oItem.typeStr()]); + } + }); + + RL.remote().contactSave(function (sResult, oData) { + + var bRes = false; + self.viewSaving(false); + + if (Enums.StorageResultType.Success === sResult && oData && oData.Result && + oData.Result.RequestUid === sRequestUid && 0 < Utils.pInt(oData.Result.ResultID)) + { + if ('' === self.viewID()) + { + self.viewID(Utils.pInt(oData.Result.ResultID)); + } + + self.reloadContactList(); + bRes = true; + } + + _.delay(function () { + self.viewSaveTrigger(bRes ? Enums.SaveSettingsStep.TrueResult : Enums.SaveSettingsStep.FalseResult); + }, 300); + + if (bRes) + { + self.watchDirty(false); + + _.delay(function () { + self.viewSaveTrigger(Enums.SaveSettingsStep.Idle); + }, 1000); + } + + }, sRequestUid, this.viewID(), aProperties); + + }, function () { + var + bV = this.viewHasNonEmptyRequaredProperties(), + bReadOnly = this.viewReadOnly() + ; + return !this.viewSaving() && bV && !bReadOnly; + }); + + this.syncCommand = Utils.createCommand(this, function () { + + var self = this; + RL.contactsSync(function (sResult, oData) { + if (Enums.StorageResultType.Success !== sResult || !oData || !oData.Result) + { + window.alert(Utils.getNotification( + oData && oData.ErrorCode ? oData.ErrorCode : Enums.Notification.ContactsSyncError)); + } + + self.reloadContactList(true); + }); + + }, function () { + return !this.contacts.syncing() && !this.contacts.importing(); + }); + + this.bDropPageAfterDelete = false; + + this.watchDirty = ko.observable(false); + this.watchHash = ko.observable(false); + + this.viewHash = ko.computed(function () { + return '' + _.map(self.viewProperties(), function (oItem) { + return oItem.value(); + }).join(''); + }); + +// this.saveCommandDebounce = _.debounce(_.bind(this.saveCommand, this), 1000); + + this.viewHash.subscribe(function () { + if (this.watchHash() && !this.viewReadOnly() && !this.watchDirty()) + { + this.watchDirty(true); + } + }, this); + + this.sDefaultKeyScope = Enums.KeyState.ContactList; + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsContactsViewModel', PopupsContactsViewModel); + +PopupsContactsViewModel.prototype.getPropertyPlceholder = function (sType) +{ + var sResult = ''; + switch (sType) + { + case Enums.ContactPropertyType.LastName: + sResult = 'CONTACTS/PLACEHOLDER_ENTER_LAST_NAME'; + break; + case Enums.ContactPropertyType.FirstName: + sResult = 'CONTACTS/PLACEHOLDER_ENTER_FIRST_NAME'; + break; + case Enums.ContactPropertyType.Nick: + sResult = 'CONTACTS/PLACEHOLDER_ENTER_NICK_NAME'; + break; + } + + return sResult; +}; + +PopupsContactsViewModel.prototype.addNewProperty = function (sType, sTypeStr) +{ + this.viewProperties.push(new ContactPropertyModel(sType, sTypeStr || '', '', true, this.getPropertyPlceholder(sType))); +}; + +PopupsContactsViewModel.prototype.addNewOrFocusProperty = function (sType, sTypeStr) +{ + var oItem = _.find(this.viewProperties(), function (oItem) { + return sType === oItem.type(); + }); + + if (oItem) + { + oItem.focused(true); + } + else + { + this.addNewProperty(sType, sTypeStr); + } +}; + +PopupsContactsViewModel.prototype.addNewEmail = function () +{ + this.addNewProperty(Enums.ContactPropertyType.Email, 'Home'); +}; + +PopupsContactsViewModel.prototype.addNewPhone = function () +{ + this.addNewProperty(Enums.ContactPropertyType.Phone, 'Mobile'); +}; + +PopupsContactsViewModel.prototype.addNewWeb = function () +{ + this.addNewProperty(Enums.ContactPropertyType.Web); +}; + +PopupsContactsViewModel.prototype.addNewNickname = function () +{ + this.addNewOrFocusProperty(Enums.ContactPropertyType.Nick); +}; + +PopupsContactsViewModel.prototype.addNewNotes = function () +{ + this.addNewOrFocusProperty(Enums.ContactPropertyType.Note); +}; + +PopupsContactsViewModel.prototype.addNewBirthday = function () +{ + this.addNewOrFocusProperty(Enums.ContactPropertyType.Birthday); +}; + +//PopupsContactsViewModel.prototype.addNewAddress = function () +//{ +//}; + +PopupsContactsViewModel.prototype.exportVcf = function () +{ + RL.download(RL.link().exportContactsVcf()); +}; + +PopupsContactsViewModel.prototype.exportCsv = function () +{ + RL.download(RL.link().exportContactsCsv()); +}; + +PopupsContactsViewModel.prototype.initUploader = function () +{ + if (this.importUploaderButton()) + { + var + oJua = new Jua({ + 'action': RL.link().uploadContacts(), + 'name': 'uploader', + 'queueSize': 1, + 'multipleSizeLimit': 1, + 'disableFolderDragAndDrop': true, + 'disableDragAndDrop': true, + 'disableMultiple': true, + 'disableDocumentDropPrevent': true, + 'clickElement': this.importUploaderButton() + }) + ; + + if (oJua) + { + oJua + .on('onStart', _.bind(function () { + this.contacts.importing(true); + }, this)) + .on('onComplete', _.bind(function (sId, bResult, oData) { + + this.contacts.importing(false); + this.reloadContactList(); + + if (!sId || !bResult || !oData || !oData.Result) + { + window.alert(Utils.i18n('CONTACTS/ERROR_IMPORT_FILE')); + } + + }, this)) + ; + } + } +}; + +PopupsContactsViewModel.prototype.removeCheckedOrSelectedContactsFromList = function () +{ + var + self = this, + oKoContacts = this.contacts, + oCurrentContact = this.currentContact(), + iCount = this.contacts().length, + aContacts = this.contactsCheckedOrSelected() + ; + + if (0 < aContacts.length) + { + _.each(aContacts, function (oContact) { + + if (oCurrentContact && oCurrentContact.idContact === oContact.idContact) + { + oCurrentContact = null; + self.currentContact(null); + } + + oContact.deleted(true); + iCount--; + }); + + if (iCount <= 0) + { + this.bDropPageAfterDelete = true; + } + + _.delay(function () { + + _.each(aContacts, function (oContact) { + oKoContacts.remove(oContact); + }); + + }, 500); + } +}; + +PopupsContactsViewModel.prototype.deleteSelectedContacts = function () +{ + if (0 < this.contactsCheckedOrSelected().length) + { + RL.remote().contactsDelete( + _.bind(this.deleteResponse, this), + this.contactsCheckedOrSelectedUids() + ); + + this.removeCheckedOrSelectedContactsFromList(); + } +}; + +/** + * @param {string} sResult + * @param {AjaxJsonDefaultResponse} oData + */ +PopupsContactsViewModel.prototype.deleteResponse = function (sResult, oData) +{ + if (500 < (Enums.StorageResultType.Success === sResult && oData && oData.Time ? Utils.pInt(oData.Time) : 0)) + { + this.reloadContactList(this.bDropPageAfterDelete); + } + else + { + _.delay((function (self) { + return function () { + self.reloadContactList(self.bDropPageAfterDelete); + }; + }(this)), 500); + } +}; + +PopupsContactsViewModel.prototype.removeProperty = function (oProp) +{ + this.viewProperties.remove(oProp); +}; + +/** + * @param {?ContactModel} oContact + */ +PopupsContactsViewModel.prototype.populateViewContact = function (oContact) +{ + var + sId = '', + sLastName = '', + sFirstName = '', + aList = [] + ; + + this.watchHash(false); + + this.emptySelection(false); + this.viewReadOnly(false); + + if (oContact) + { + sId = oContact.idContact; + if (Utils.isNonEmptyArray(oContact.properties)) + { + _.each(oContact.properties, function (aProperty) { + if (aProperty && aProperty[0]) + { + if (Enums.ContactPropertyType.LastName === aProperty[0]) + { + sLastName = aProperty[1]; + } + else if (Enums.ContactPropertyType.FirstName === aProperty[0]) + { + sFirstName = aProperty[1]; + } + else + { + aList.push(new ContactPropertyModel(aProperty[0], aProperty[2] || '', aProperty[1])); + } + } + }); + } + + this.viewReadOnly(!!oContact.readOnly); + } + + aList.unshift(new ContactPropertyModel(Enums.ContactPropertyType.LastName, '', sLastName, false, + this.getPropertyPlceholder(Enums.ContactPropertyType.LastName))); + + aList.unshift(new ContactPropertyModel(Enums.ContactPropertyType.FirstName, '', sFirstName, !oContact, + this.getPropertyPlceholder(Enums.ContactPropertyType.FirstName))); + + this.viewID(sId); + this.viewProperties([]); + this.viewProperties(aList); + + this.watchDirty(false); + this.watchHash(true); +}; + +/** + * @param {boolean=} bDropPagePosition = false + */ +PopupsContactsViewModel.prototype.reloadContactList = function (bDropPagePosition) +{ + var + self = this, + iOffset = (this.contactsPage() - 1) * Consts.Defaults.ContactsPerPage + ; + + this.bDropPageAfterDelete = false; + + if (Utils.isUnd(bDropPagePosition) ? false : !!bDropPagePosition) + { + this.contactsPage(1); + iOffset = 0; + } + + this.contacts.loading(true); + RL.remote().contacts(function (sResult, oData) { + var + iCount = 0, + aList = [] + ; + + if (Enums.StorageResultType.Success === sResult && oData && oData.Result && oData.Result.List) + { + if (Utils.isNonEmptyArray(oData.Result.List)) + { + aList = _.map(oData.Result.List, function (oItem) { + var oContact = new ContactModel(); + return oContact.parse(oItem) ? oContact : null; + }); + + aList = _.compact(aList); + + iCount = Utils.pInt(oData.Result.Count); + iCount = 0 < iCount ? iCount : 0; + } + } + + self.contactsCount(iCount); + + self.contacts(aList); + self.viewClearSearch('' !== self.search()); + self.contacts.loading(false); + + }, iOffset, Consts.Defaults.ContactsPerPage, this.search()); +}; + +PopupsContactsViewModel.prototype.onBuild = function (oDom) +{ + this.oContentVisible = $('.b-list-content', oDom); + this.oContentScrollable = $('.content', this.oContentVisible); + + this.selector.init(this.oContentVisible, this.oContentScrollable, Enums.KeyState.ContactList); + + var self = this; + + key('delete', Enums.KeyState.ContactList, function () { + self.deleteCommand(); + return false; + }); + + oDom + .on('click', '.e-pagenator .e-page', function () { + var oPage = ko.dataFor(this); + if (oPage) + { + self.contactsPage(Utils.pInt(oPage.value)); + self.reloadContactList(); + } + }) + ; + + this.initUploader(); +}; + +PopupsContactsViewModel.prototype.onShow = function () +{ + kn.routeOff(); + this.reloadContactList(true); +}; + +PopupsContactsViewModel.prototype.onHide = function () +{ + kn.routeOn(); + this.currentContact(null); + this.emptySelection(true); + this.search(''); + + _.each(this.contacts(), function (oItem) { + oItem.checked(false); + }); +}; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsAdvancedSearchViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsAdvancedSearch'); + + this.fromFocus = ko.observable(false); + + this.from = ko.observable(''); + this.to = ko.observable(''); + this.subject = ko.observable(''); + this.text = ko.observable(''); + this.selectedDateValue = ko.observable(-1); + + this.hasAttachment = ko.observable(false); + this.starred = ko.observable(false); + this.unseen = ko.observable(false); + + this.searchCommand = Utils.createCommand(this, function () { + + var sSearch = this.buildSearchString(); + if ('' !== sSearch) + { + RL.data().mainMessageListSearch(sSearch); + } + + this.cancelCommand(); + }); + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsAdvancedSearchViewModel', PopupsAdvancedSearchViewModel); + +PopupsAdvancedSearchViewModel.prototype.buildSearchStringValue = function (sValue) +{ + if (-1 < sValue.indexOf(' ')) + { + sValue = '"' + sValue + '"'; + } + + return sValue; +}; + +PopupsAdvancedSearchViewModel.prototype.buildSearchString = function () +{ + var + aResult = [], + sFrom = Utils.trim(this.from()), + sTo = Utils.trim(this.to()), + sSubject = Utils.trim(this.subject()), + sText = Utils.trim(this.text()), + aIs = [], + aHas = [] + ; + + if (sFrom && '' !== sFrom) + { + aResult.push('from:' + this.buildSearchStringValue(sFrom)); + } + + if (sTo && '' !== sTo) + { + aResult.push('to:' + this.buildSearchStringValue(sTo)); + } + + if (sSubject && '' !== sSubject) + { + aResult.push('subject:' + this.buildSearchStringValue(sSubject)); + } + + if (this.hasAttachment()) + { + aHas.push('attachment'); + } + + if (this.unseen()) + { + aIs.push('unseen'); + } + + if (this.starred()) + { + aIs.push('flagged'); + } + + if (0 < aHas.length) + { + aResult.push('has:' + aHas.join(',')); + } + + if (0 < aIs.length) + { + aResult.push('is:' + aIs.join(',')); + } + + if (-1 < this.selectedDateValue()) + { + aResult.push('date:' + moment().subtract('days', this.selectedDateValue()).format('YYYY.MM.DD') + '/'); + } + + if (sText && '' !== sText) + { + aResult.push('text:' + this.buildSearchStringValue(sText)); + } + + return Utils.trim(aResult.join(' ')); +}; + +PopupsAdvancedSearchViewModel.prototype.clearPopup = function () +{ + this.from(''); + this.to(''); + this.subject(''); + this.text(''); + + this.selectedDateValue(-1); + this.hasAttachment(false); + this.starred(false); + this.unseen(false); + + this.fromFocus(true); +}; + +PopupsAdvancedSearchViewModel.prototype.onShow = function () +{ + this.clearPopup(); +}; + +PopupsAdvancedSearchViewModel.prototype.onFocus = function () +{ + this.fromFocus(true); +}; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsAddAccountViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsAddAccount'); + + this.email = ko.observable(''); + this.login = ko.observable(''); + this.password = ko.observable(''); + + this.emailError = ko.observable(false); + this.loginError = ko.observable(false); + this.passwordError = ko.observable(false); + + this.email.subscribe(function () { + this.emailError(false); + }, this); + + this.login.subscribe(function () { + this.loginError(false); + }, this); + + this.password.subscribe(function () { + this.passwordError(false); + }, this); + + this.allowCustomLogin = RL.data().allowCustomLogin; + + this.submitRequest = ko.observable(false); + this.submitError = ko.observable(''); + + this.emailFocus = ko.observable(false); + this.loginFocus = ko.observable(false); + + this.addAccountCommand = Utils.createCommand(this, function () { + + this.emailError('' === Utils.trim(this.email())); + this.passwordError('' === Utils.trim(this.password())); + + if (this.emailError() || this.passwordError()) + { + return false; + } + + this.submitRequest(true); + + RL.remote().accountAdd(_.bind(function (sResult, oData) { + + this.submitRequest(false); + if (Enums.StorageResultType.Success === sResult && oData && 'AccountAdd' === oData.Action) + { + if (oData.Result) + { + RL.accountsAndIdentities(); + this.cancelCommand(); + } + else if (oData.ErrorCode) + { + this.submitError(Utils.getNotification(oData.ErrorCode)); + } + } + else + { + this.submitError(Utils.getNotification(Enums.Notification.UnknownError)); + } + + }, this), this.email(), this.allowCustomLogin() ? this.login() : '', this.password()); + + return true; + + }, function () { + return !this.submitRequest(); + }); + + this.loginFocus.subscribe(function (bValue) { + if (bValue && '' === this.login() && '' !== this.email()) + { + this.login(this.email()); + } + }, this); + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsAddAccountViewModel', PopupsAddAccountViewModel); + +PopupsAddAccountViewModel.prototype.clearPopup = function () +{ + this.email(''); + this.login(''); + this.password(''); + + this.emailError(false); + this.loginError(false); + this.passwordError(false); + + this.submitRequest(false); + this.submitError(''); +}; + +PopupsAddAccountViewModel.prototype.onShow = function () +{ + this.clearPopup(); +}; + +PopupsAddAccountViewModel.prototype.onFocus = function () +{ + this.emailFocus(true); +}; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsAddOpenPgpKeyViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsAddOpenPgpKey'); + + this.key = ko.observable(''); + this.key.error = ko.observable(false); + this.key.focus = ko.observable(false); + + this.key.subscribe(function () { + this.key.error(false); + }, this); + + this.addOpenPgpKeyCommand = Utils.createCommand(this, function () { + + var + iCount = 30, + aMatch = null, + sKey = Utils.trim(this.key()), + oReg = /[\-]{3,6}BEGIN PGP (PRIVATE|PUBLIC) KEY BLOCK[\-]{3,6}[\s\S]+[\-]{3,6}END PGP (PRIVATE|PUBLIC) KEY BLOCK[\-]{3,6}/gi, + oOpenpgpKeyring = RL.data().openpgpKeyring + ; + + this.key.error('' === sKey); + + if (!oOpenpgpKeyring || this.key.error()) + { + return false; + } + + do + { + aMatch = oReg.exec(sKey); + if (!aMatch || 0 > iCount) + { + break; + } + + if (aMatch[0] && aMatch[1] && aMatch[2] && aMatch[1] === aMatch[2]) + { + if ('PRIVATE' === aMatch[1]) + { + oOpenpgpKeyring.privateKeys.importKey(aMatch[0]); + } + else if ('PUBLIC' === aMatch[1]) + { + oOpenpgpKeyring.publicKeys.importKey(aMatch[0]); + } + } + + iCount--; + } + while (true); + + oOpenpgpKeyring.store(); + + RL.reloadOpenPgpKeys(); + Utils.delegateRun(this, 'cancelCommand'); + + return true; + }); + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsAddOpenPgpKeyViewModel', PopupsAddOpenPgpKeyViewModel); + +PopupsAddOpenPgpKeyViewModel.prototype.clearPopup = function () +{ + this.key(''); + this.key.error(false); +}; + +PopupsAddOpenPgpKeyViewModel.prototype.onShow = function () +{ + this.clearPopup(); +}; + +PopupsAddOpenPgpKeyViewModel.prototype.onFocus = function () +{ + this.key.focus(true); +}; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsViewOpenPgpKeyViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsViewOpenPgpKey'); + + this.key = ko.observable(''); + this.keyDom = ko.observable(null); + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsViewOpenPgpKeyViewModel', PopupsViewOpenPgpKeyViewModel); + +PopupsViewOpenPgpKeyViewModel.prototype.clearPopup = function () +{ + this.key(''); +}; + +PopupsViewOpenPgpKeyViewModel.prototype.selectKey = function () +{ + var oEl = this.keyDom(); + if (oEl) + { + Utils.selectElement(oEl); + } +}; + +PopupsViewOpenPgpKeyViewModel.prototype.onShow = function (oOpenPgpKey) +{ + this.clearPopup(); + + if (oOpenPgpKey) + { + this.key(oOpenPgpKey.armor); + } +}; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsGenerateNewOpenPgpKeyViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsGenerateNewOpenPgpKey'); + + this.email = ko.observable(''); + this.email.focus = ko.observable(''); + this.email.error = ko.observable(false); + + this.name = ko.observable(''); + this.password = ko.observable(''); + this.keyBitLength = ko.observable(2048); + + this.submitRequest = ko.observable(false); + + this.email.subscribe(function () { + this.email.error(false); + }, this); + + this.generateOpenPgpKeyCommand = Utils.createCommand(this, function () { + + var + self = this, + sUserID = '', + mKeyPair = null, + oOpenpgpKeyring = RL.data().openpgpKeyring + ; + + this.email.error('' === Utils.trim(this.email())); + if (!oOpenpgpKeyring || this.email.error()) + { + return false; + } + + sUserID = this.email(); + if ('' !== this.name()) + { + sUserID = this.name() + ' <' + sUserID + '>'; + } + + this.submitRequest(true); + + _.delay(function () { + mKeyPair = window.openpgp.generateKeyPair(1, Utils.pInt(self.keyBitLength()), sUserID, Utils.trim(self.password())); + if (mKeyPair && mKeyPair.privateKeyArmored) + { + oOpenpgpKeyring.privateKeys.importKey(mKeyPair.privateKeyArmored); + oOpenpgpKeyring.publicKeys.importKey(mKeyPair.publicKeyArmored); + oOpenpgpKeyring.store(); + + RL.reloadOpenPgpKeys(); + Utils.delegateRun(self, 'cancelCommand'); + } + + self.submitRequest(false); + }, 100); + + return true; + }); + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsGenerateNewOpenPgpKeyViewModel', PopupsGenerateNewOpenPgpKeyViewModel); + +PopupsGenerateNewOpenPgpKeyViewModel.prototype.clearPopup = function () +{ + this.name(''); + this.password(''); + + this.email(''); + this.email.error(false); + this.keyBitLength(2048); +}; + +PopupsGenerateNewOpenPgpKeyViewModel.prototype.onShow = function () +{ + this.clearPopup(); +}; + +PopupsGenerateNewOpenPgpKeyViewModel.prototype.onFocus = function () +{ + this.email.focus(true); +}; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsComposeOpenPgpViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsComposeOpenPgp'); + + this.notification = ko.observable(''); + + this.sign = ko.observable(true); + this.encrypt = ko.observable(true); + + this.password = ko.observable(''); + this.password.focus = ko.observable(false); + this.buttonFocus = ko.observable(false); + + this.from = ko.observable(''); + this.to = ko.observableArray([]); + this.text = ko.observable(''); + + this.resultCallback = null; + + this.submitRequest = ko.observable(false); + + // commands + this.doCommand = Utils.createCommand(this, function () { + + var + self = this, + bResult = true, + oData = RL.data(), + oPrivateKey = null, + aPublicKeys = [] + ; + + this.submitRequest(true); + + if (bResult && this.sign() && '' === this.from()) + { + this.notification(Utils.i18n('PGP_NOTIFICATIONS/SPECIFY_FROM_EMAIL')); + bResult = false; + } + + if (bResult && this.sign()) + { + oPrivateKey = oData.findPrivateKeyByEmail(this.from(), this.password()); + if (!oPrivateKey) + { + this.notification(Utils.i18n('PGP_NOTIFICATIONS/NO_PRIVATE_KEY_FOUND_FOR', { + 'EMAIL': this.from() + })); + + bResult = false; + } + } + + if (bResult && this.encrypt() && 0 === this.to().length) + { + this.notification(Utils.i18n('PGP_NOTIFICATIONS/SPECIFY_AT_LEAST_ONE_RECIPIENT')); + bResult = false; + } + + if (bResult && this.encrypt()) + { + aPublicKeys = []; + _.each(this.to(), function (sEmail) { + var aKeys = oData.findPublicKeysByEmail(sEmail); + if (0 === aKeys.length && bResult) + { + self.notification(Utils.i18n('PGP_NOTIFICATIONS/NO_PUBLIC_KEYS_FOUND_FOR', { + 'EMAIL': sEmail + })); + + bResult = false; + } + + aPublicKeys = aPublicKeys.concat(aKeys); + }); + + if (bResult && (0 === aPublicKeys.length || this.to().length !== aPublicKeys.length)) + { + bResult = false; + } + } + + _.delay(function () { + + if (self.resultCallback && bResult) + { + try { + + if (oPrivateKey && 0 === aPublicKeys.length) + { + self.resultCallback( + window.openpgp.signClearMessage([oPrivateKey], self.text()) + ); + } + else if (oPrivateKey && 0 < aPublicKeys.length) + { + self.resultCallback( + window.openpgp.signAndEncryptMessage(aPublicKeys, oPrivateKey, self.text()) + ); + } + else if (!oPrivateKey && 0 < aPublicKeys.length) + { + self.resultCallback( + window.openpgp.encryptMessage(aPublicKeys, self.text()) + ); + } + } + catch (e) + { + self.notification(Utils.i18n('PGP_NOTIFICATIONS/PGP_ERROR', { + 'ERROR': '' + e + })); + + bResult = false; + } + } + + if (bResult) + { + self.cancelCommand(); + } + + self.submitRequest(false); + + }, 10); + + }, function () { + return !this.submitRequest() && (this.sign() || this.encrypt()); + }); + + this.sDefaultKeyScope = Enums.KeyState.PopupComposeOpenPGP; + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsComposeOpenPgpViewModel', PopupsComposeOpenPgpViewModel); + +PopupsComposeOpenPgpViewModel.prototype.clearPopup = function () +{ + this.notification(''); + + this.password(''); + this.password.focus(false); + this.buttonFocus(false); + + this.from(''); + this.to([]); + this.text(''); + + this.submitRequest(false); + + this.resultCallback = null; +}; + +PopupsComposeOpenPgpViewModel.prototype.onBuild = function () +{ + key('tab,shift+tab', Enums.KeyState.PopupComposeOpenPGP, _.bind(function () { + + switch (true) + { + case this.password.focus(): + this.buttonFocus(true); + break; + case this.buttonFocus(): + this.password.focus(true); + break; + } + + return false; + + }, this)); +}; + +PopupsComposeOpenPgpViewModel.prototype.onHide = function () +{ + this.clearPopup(); +}; + +PopupsComposeOpenPgpViewModel.prototype.onFocus = function () +{ + if (this.sign()) + { + this.password.focus(true); + } + else + { + this.buttonFocus(true); + } +}; + +PopupsComposeOpenPgpViewModel.prototype.onShow = function (fCallback, sText, sFromEmail, sTo, sCc, sBcc) +{ + this.clearPopup(); + + var + oEmail = new EmailModel(), + sResultFromEmail = '', + aRec = [] + ; + + this.resultCallback = fCallback; + + oEmail.clear(); + oEmail.mailsoParse(sFromEmail); + if ('' !== oEmail.email) + { + sResultFromEmail = oEmail.email; + } + + if ('' !== sTo) + { + aRec.push(sTo); + } + + if ('' !== sCc) + { + aRec.push(sCc); + } + + if ('' !== sBcc) + { + aRec.push(sBcc); + } + + aRec = aRec.join(', ').split(','); + aRec = _.compact(_.map(aRec, function (sValue) { + oEmail.clear(); + oEmail.mailsoParse(Utils.trim(sValue)); + return '' === oEmail.email ? false : oEmail.email; + })); + + this.from(sResultFromEmail); + this.to(aRec); + this.text(sText); +}; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsIdentityViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsIdentity'); + + this.id = ''; + this.edit = ko.observable(false); + this.owner = ko.observable(false); + + this.email = ko.observable('').validateEmail(); + this.email.focused = ko.observable(false); + this.name = ko.observable(''); + this.name.focused = ko.observable(false); + this.replyTo = ko.observable('').validateSimpleEmail(); + this.replyTo.focused = ko.observable(false); + this.bcc = ko.observable('').validateSimpleEmail(); + this.bcc.focused = ko.observable(false); + +// this.email.subscribe(function () { +// this.email.hasError(false); +// }, this); + + this.submitRequest = ko.observable(false); + this.submitError = ko.observable(''); + + this.addOrEditIdentityCommand = Utils.createCommand(this, function () { + + if (!this.email.hasError()) + { + this.email.hasError('' === Utils.trim(this.email())); + } + + if (this.email.hasError()) + { + if (!this.owner()) + { + this.email.focused(true); + } + + return false; + } + + if (this.replyTo.hasError()) + { + this.replyTo.focused(true); + return false; + } + + if (this.bcc.hasError()) + { + this.bcc.focused(true); + return false; + } + + this.submitRequest(true); + + RL.remote().identityUpdate(_.bind(function (sResult, oData) { + + this.submitRequest(false); + if (Enums.StorageResultType.Success === sResult && oData) + { + if (oData.Result) + { + RL.accountsAndIdentities(); + this.cancelCommand(); + } + else if (oData.ErrorCode) + { + this.submitError(Utils.getNotification(oData.ErrorCode)); + } + } + else + { + this.submitError(Utils.getNotification(Enums.Notification.UnknownError)); + } + + }, this), this.id, this.email(), this.name(), this.replyTo(), this.bcc()); + + return true; + + }, function () { + return !this.submitRequest(); + }); + + this.label = ko.computed(function () { + return Utils.i18n('POPUPS_IDENTITIES/' + (this.edit() ? 'TITLE_UPDATE_IDENTITY': 'TITLE_ADD_IDENTITY')); + }, this); + + this.button = ko.computed(function () { + return Utils.i18n('POPUPS_IDENTITIES/' + (this.edit() ? 'BUTTON_UPDATE_IDENTITY': 'BUTTON_ADD_IDENTITY')); + }, this); + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsIdentityViewModel', PopupsIdentityViewModel); + +PopupsIdentityViewModel.prototype.clearPopup = function () +{ + this.id = ''; + this.edit(false); + this.owner(false); + + this.name(''); + this.email(''); + this.replyTo(''); + this.bcc(''); + + this.email.hasError(false); + this.replyTo.hasError(false); + this.bcc.hasError(false); + + this.submitRequest(false); + this.submitError(''); +}; + +/** + * @param {?IdentityModel} oIdentity + */ +PopupsIdentityViewModel.prototype.onShow = function (oIdentity) +{ + this.clearPopup(); + + if (oIdentity) + { + this.edit(true); + + this.id = oIdentity.id; + this.name(oIdentity.name()); + this.email(oIdentity.email()); + this.replyTo(oIdentity.replyTo()); + this.bcc(oIdentity.bcc()); + + this.owner(this.id === RL.data().accountEmail()); + } +}; + +PopupsIdentityViewModel.prototype.onFocus = function () +{ + if (!this.owner()) + { + this.email.focused(true); + } +}; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsLanguagesViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsLanguages'); + + this.exp = ko.observable(false); + + this.languages = ko.computed(function () { + return _.map(RL.data().languages(), function (sLanguage) { + return { + 'key': sLanguage, + 'selected': ko.observable(false), + 'fullName': Utils.convertLangName(sLanguage) + }; + }); + }); + + RL.data().mainLanguage.subscribe(function () { + this.resetMainLanguage(); + }, this); + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsLanguagesViewModel', PopupsLanguagesViewModel); + +PopupsLanguagesViewModel.prototype.languageEnName = function (sLanguage) +{ + return Utils.convertLangName(sLanguage, true); +}; + +PopupsLanguagesViewModel.prototype.resetMainLanguage = function () +{ + var sCurrent = RL.data().mainLanguage(); + _.each(this.languages(), function (oItem) { + oItem['selected'](oItem['key'] === sCurrent); + }); +}; + +PopupsLanguagesViewModel.prototype.onShow = function () +{ + this.exp(true); + + this.resetMainLanguage(); +}; + +PopupsLanguagesViewModel.prototype.onHide = function () +{ + this.exp(false); +}; + +PopupsLanguagesViewModel.prototype.changeLanguage = function (sLang) +{ + RL.data().mainLanguage(sLang); + this.cancelCommand(); +}; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsTwoFactorTestViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsTwoFactorTest'); + + var self = this; + + this.code = ko.observable(''); + this.code.focused = ko.observable(false); + this.code.status = ko.observable(null); + + this.testing = ko.observable(false); + + // commands + this.testCode = Utils.createCommand(this, function () { + + this.testing(true); + RL.remote().testTwoFactor(function (sResult, oData) { + + self.testing(false); + self.code.status(Enums.StorageResultType.Success === sResult && oData && oData.Result ? true : false); + + }, this.code()); + + }, function () { + return '' !== this.code() && !this.testing(); + }); + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsTwoFactorTestViewModel', PopupsTwoFactorTestViewModel); + +PopupsTwoFactorTestViewModel.prototype.clearPopup = function () +{ + this.code(''); + this.code.focused(false); + this.code.status(null); + this.testing(false); +}; + +PopupsTwoFactorTestViewModel.prototype.onShow = function () +{ + this.clearPopup(); +}; + +PopupsTwoFactorTestViewModel.prototype.onFocus = function () +{ + this.code.focused(true); +}; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsAskViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsAsk'); + + this.askDesc = ko.observable(''); + this.yesButton = ko.observable(''); + this.noButton = ko.observable(''); + + this.yesFocus = ko.observable(false); + this.noFocus = ko.observable(false); + + this.fYesAction = null; + this.fNoAction = null; + + this.bDisabeCloseOnEsc = true; + this.sDefaultKeyScope = Enums.KeyState.PopupAsk; + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsAskViewModel', PopupsAskViewModel); + +PopupsAskViewModel.prototype.clearPopup = function () +{ + this.askDesc(''); + this.yesButton(Utils.i18n('POPUPS_ASK/BUTTON_YES')); + this.noButton(Utils.i18n('POPUPS_ASK/BUTTON_NO')); + + this.yesFocus(false); + this.noFocus(false); + + this.fYesAction = null; + this.fNoAction = null; +}; + +PopupsAskViewModel.prototype.yesClick = function () +{ + this.cancelCommand(); + + if (Utils.isFunc(this.fYesAction)) + { + this.fYesAction.call(null); + } +}; + +PopupsAskViewModel.prototype.noClick = function () +{ + this.cancelCommand(); + + if (Utils.isFunc(this.fNoAction)) + { + this.fNoAction.call(null); + } +}; + +/** + * @param {string} sAskDesc + * @param {Function=} fYesFunc + * @param {Function=} fNoFunc + * @param {string=} sYesButton + * @param {string=} sNoButton + */ +PopupsAskViewModel.prototype.onShow = function (sAskDesc, fYesFunc, fNoFunc, sYesButton, sNoButton) +{ + this.clearPopup(); + + this.fYesAction = fYesFunc || null; + this.fNoAction = fNoFunc || null; + + this.askDesc(sAskDesc || ''); + if (sYesButton) + { + this.yesButton(sYesButton); + } + + if (sYesButton) + { + this.yesButton(sNoButton); + } +}; + +PopupsAskViewModel.prototype.onFocus = function () +{ + this.yesFocus(true); +}; + +PopupsAskViewModel.prototype.onBuild = function () +{ + key('tab, shift+tab, right, left', Enums.KeyState.PopupAsk, _.bind(function () { + if (this.yesFocus()) + { + this.noFocus(true); + } + else + { + this.yesFocus(true); + } + return false; + }, this)); +}; + + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function PopupsKeyboardShortcutsHelpViewModel() +{ + KnoinAbstractViewModel.call(this, 'Popups', 'PopupsKeyboardShortcutsHelp'); + + this.sDefaultKeyScope = Enums.KeyState.PopupKeyboardShortcutsHelp; + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('PopupsKeyboardShortcutsHelpViewModel', PopupsKeyboardShortcutsHelpViewModel); + +PopupsKeyboardShortcutsHelpViewModel.prototype.onBuild = function (oDom) +{ + key('tab, shift+tab, left, right', Enums.KeyState.PopupKeyboardShortcutsHelp, _.bind(function (event, handler) { + if (event && handler) + { + var + $tabs = oDom.find('.nav.nav-tabs > li'), + bNext = handler && ('tab' === handler.shortcut || 'right' === handler.shortcut), + iIndex = $tabs.index($tabs.filter('.active')) + ; + + if (!bNext && iIndex > 0) + { + iIndex--; + } + else if (bNext && iIndex < $tabs.length - 1) + { + iIndex++; + } + else + { + iIndex = bNext ? 0 : $tabs.length - 1; + } + + $tabs.eq(iIndex).find('a[data-toggle="tab"]').tab('show'); + return false; + } + }, this)); +}; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function LoginViewModel() +{ + KnoinAbstractViewModel.call(this, 'Center', 'Login'); + + var oData = RL.data(); + + this.email = ko.observable(''); + this.login = ko.observable(''); + this.password = ko.observable(''); + this.signMe = ko.observable(false); + + this.additionalCode = ko.observable(''); + this.additionalCode.error = ko.observable(false); + this.additionalCode.focused = ko.observable(false); + this.additionalCode.visibility = ko.observable(false); + this.additionalCodeSignMe = ko.observable(false); + + this.logoImg = Utils.trim(RL.settingsGet('LoginLogo')); + this.loginDescription = Utils.trim(RL.settingsGet('LoginDescription')); + this.logoCss = Utils.trim(RL.settingsGet('LoginCss')); + + this.emailError = ko.observable(false); + this.loginError = ko.observable(false); + this.passwordError = ko.observable(false); + + this.emailFocus = ko.observable(false); + this.loginFocus = ko.observable(false); + this.submitFocus = ko.observable(false); + + this.email.subscribe(function () { + this.emailError(false); + this.additionalCode(''); + this.additionalCode.visibility(false); + }, this); + + this.login.subscribe(function () { + this.loginError(false); + }, this); + + this.password.subscribe(function () { + this.passwordError(false); + }, this); + + this.additionalCode.subscribe(function () { + this.additionalCode.error(false); + }, this); + + this.additionalCode.visibility.subscribe(function () { + this.additionalCode.error(false); + }, this); + + this.submitRequest = ko.observable(false); + this.submitError = ko.observable(''); + + this.allowCustomLogin = oData.allowCustomLogin; + this.allowLanguagesOnLogin = oData.allowLanguagesOnLogin; + + this.langRequest = ko.observable(false); + this.mainLanguage = oData.mainLanguage; + this.bSendLanguage = false; + + this.mainLanguageFullName = ko.computed(function () { + return Utils.convertLangName(this.mainLanguage()); + }, this); + + this.signMeType = ko.observable(Enums.LoginSignMeType.Unused); + + this.signMeType.subscribe(function (iValue) { + this.signMe(Enums.LoginSignMeType.DefaultOn === iValue); + }, this); + + this.signMeVisibility = ko.computed(function () { + return Enums.LoginSignMeType.Unused !== this.signMeType(); + }, this); + + this.submitCommand = Utils.createCommand(this, function () { + + this.emailError('' === Utils.trim(this.email())); + this.passwordError('' === Utils.trim(this.password())); + + if (this.additionalCode.visibility()) + { + this.additionalCode.error('' === Utils.trim(this.additionalCode())); + } + + if (this.emailError() || this.passwordError() || this.additionalCode.error()) + { + return false; + } + + this.submitRequest(true); + + RL.remote().login(_.bind(function (sResult, oData) { + + if (Enums.StorageResultType.Success === sResult && oData && 'Login' === oData.Action) + { + if (oData.Result) + { + if (oData.TwoFactorAuth) + { + this.additionalCode(''); + this.additionalCode.visibility(true); + this.additionalCode.focused(true); + + this.submitRequest(false); + } + else + { + RL.loginAndLogoutReload(); + } + } + else if (oData.ErrorCode) + { + this.submitRequest(false); + this.submitError(Utils.getNotification(oData.ErrorCode)); + + if ('' === this.submitError()) + { + this.submitError(Utils.getNotification(Enums.Notification.UnknownError)); + } + } + else + { + this.submitRequest(false); + } + } + else + { + this.submitRequest(false); + this.submitError(Utils.getNotification(Enums.Notification.UnknownError)); + } + + }, this), this.email(), this.allowCustomLogin() ? this.login() : '', this.password(), !!this.signMe(), + this.bSendLanguage ? this.mainLanguage() : '', + this.additionalCode.visibility() ? this.additionalCode() : '', + this.additionalCode.visibility() ? !!this.additionalCodeSignMe() : false + ); + + return true; + + }, function () { + return !this.submitRequest(); + }); + + this.facebookLoginEnabled = ko.observable(false); + + this.facebookCommand = Utils.createCommand(this, function () { + + window.open(RL.link().socialFacebook(), 'Facebook', 'left=200,top=100,width=650,height=335,menubar=no,status=no,resizable=yes,scrollbars=yes'); + return true; + + }, function () { + return !this.submitRequest() && this.facebookLoginEnabled(); + }); + + this.googleLoginEnabled = ko.observable(false); + + this.googleCommand = Utils.createCommand(this, function () { + + window.open(RL.link().socialGoogle(), 'Google', 'left=200,top=100,width=650,height=335,menubar=no,status=no,resizable=yes,scrollbars=yes'); + return true; + + }, function () { + return !this.submitRequest() && this.googleLoginEnabled(); + }); + + this.twitterLoginEnabled = ko.observable(false); + + this.twitterCommand = Utils.createCommand(this, function () { + + window.open(RL.link().socialTwitter(), 'Twitter', 'left=200,top=100,width=650,height=335,menubar=no,status=no,resizable=yes,scrollbars=yes'); + return true; + + }, function () { + return !this.submitRequest() && this.twitterLoginEnabled(); + }); + + this.loginFocus.subscribe(function (bValue) { + if (bValue && '' === this.login() && '' !== this.email()) + { + this.login(this.email()); + } + }, this); + + this.socialLoginEnabled = ko.computed(function () { + + var + bF = this.facebookLoginEnabled(), + bG = this.googleLoginEnabled(), + bT = this.twitterLoginEnabled() + ; + + return bF || bG || bT; + }, this); + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('LoginViewModel', LoginViewModel); + +LoginViewModel.prototype.onShow = function () +{ + kn.routeOff(); + + _.delay(_.bind(function () { + if ('' !== this.email() && '' !== this.password()) + { + this.submitFocus(true); + } + else + { + this.emailFocus(true); + } + + if (RL.settingsGet('UserLanguage')) + { + $.cookie('rllang', RL.data().language(), {'expires': 30}); + } + + }, this), 100); +}; + +LoginViewModel.prototype.onHide = function () +{ + this.submitFocus(false); + this.emailFocus(false); +}; + +LoginViewModel.prototype.onBuild = function () +{ + var + self = this, + sJsHash = RL.settingsGet('JsHash'), + fSocial = function (iErrorCode) { + iErrorCode = Utils.pInt(iErrorCode); + if (0 === iErrorCode) + { + self.submitRequest(true); + RL.loginAndLogoutReload(); + } + else + { + self.submitError(Utils.getNotification(iErrorCode)); + } + } + ; + + this.facebookLoginEnabled(!!RL.settingsGet('AllowFacebookSocial')); + this.twitterLoginEnabled(!!RL.settingsGet('AllowTwitterSocial')); + this.googleLoginEnabled(!!RL.settingsGet('AllowGoogleSocial')); + + switch ((RL.settingsGet('SignMe') || 'unused').toLowerCase()) + { + case Enums.LoginSignMeTypeAsString.DefaultOff: + this.signMeType(Enums.LoginSignMeType.DefaultOff); + break; + case Enums.LoginSignMeTypeAsString.DefaultOn: + this.signMeType(Enums.LoginSignMeType.DefaultOn); + break; + default: + case Enums.LoginSignMeTypeAsString.Unused: + this.signMeType(Enums.LoginSignMeType.Unused); + break; + } + + this.email(RL.data().devEmail); + this.login(RL.data().devLogin); + this.password(RL.data().devPassword); + + if (this.googleLoginEnabled()) + { + window['rl_' + sJsHash + '_google_login_service'] = fSocial; + } + + if (this.facebookLoginEnabled()) + { + window['rl_' + sJsHash + '_facebook_login_service'] = fSocial; + } + + if (this.twitterLoginEnabled()) + { + window['rl_' + sJsHash + '_twitter_login_service'] = fSocial; + } + + _.delay(function () { + RL.data().language.subscribe(function (sValue) { + self.langRequest(true); + $.ajax({ + 'url': RL.link().langLink(sValue), + 'dataType': 'script', + 'cache': true + }).done(function() { + self.bSendLanguage = true; + Utils.i18nToDoc(); + $.cookie('rllang', RL.data().language(), {'expires': 30}); + }).always(function() { + self.langRequest(false); + }); + }); + }, 50); +}; + +LoginViewModel.prototype.selectLanguage = function () +{ + kn.showScreenPopup(PopupsLanguagesViewModel); +}; + + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function AbstractSystemDropDownViewModel() +{ + KnoinAbstractViewModel.call(this, 'Right', 'SystemDropDown'); + + var oData = RL.data(); + + this.accounts = oData.accounts; + this.accountEmail = oData.accountEmail; + this.accountsLoading = oData.accountsLoading; + + this.accountMenuDropdownTrigger = ko.observable(false); + + this.allowAddAccount = RL.settingsGet('AllowAdditionalAccounts'); + + this.loading = ko.computed(function () { + return this.accountsLoading(); + }, this); + + this.accountClick = _.bind(this.accountClick, this); +} + +_.extend(AbstractSystemDropDownViewModel.prototype, KnoinAbstractViewModel.prototype); + +AbstractSystemDropDownViewModel.prototype.accountClick = function (oAccount, oEvent) +{ + if (oAccount && oEvent && !Utils.isUnd(oEvent.which) && 1 === oEvent.which) + { + var self = this; + this.accountsLoading(true); + _.delay(function () { + self.accountsLoading(false); + }, 1000); + } + + return true; +}; + +AbstractSystemDropDownViewModel.prototype.emailTitle = function () +{ + return RL.data().accountEmail(); +}; + +AbstractSystemDropDownViewModel.prototype.settingsClick = function () +{ + kn.setHash(RL.link().settings()); +}; + +AbstractSystemDropDownViewModel.prototype.settingsHelp = function () +{ + kn.showScreenPopup(PopupsKeyboardShortcutsHelpViewModel); +}; + +AbstractSystemDropDownViewModel.prototype.addAccountClick = function () +{ + if (this.allowAddAccount) + { + kn.showScreenPopup(PopupsAddAccountViewModel); + } +}; + +AbstractSystemDropDownViewModel.prototype.logoutClick = function () +{ + RL.remote().logout(function () { + if (window.__rlah_clear) + { + window.__rlah_clear(); + } + + RL.loginAndLogoutReload(true, RL.settingsGet('ParentEmail') && 0 < RL.settingsGet('ParentEmail').length); + }); +}; + +AbstractSystemDropDownViewModel.prototype.onBuild = function () +{ + var self = this; + key('`', [Enums.KeyState.MessageList, Enums.KeyState.MessageView, Enums.KeyState.Settings], function () { + if (self.viewModelVisibility()) + { + self.accountMenuDropdownTrigger(true); + } + }); + + // shortcuts help + key('shift+/', [Enums.KeyState.MessageList, Enums.KeyState.MessageView, Enums.KeyState.Settings], function () { + if (self.viewModelVisibility()) + { + kn.showScreenPopup(PopupsKeyboardShortcutsHelpViewModel); + return false; + } + }); +}; + +/** + * @constructor + * @extends AbstractSystemDropDownViewModel + */ +function MailBoxSystemDropDownViewModel() +{ + AbstractSystemDropDownViewModel.call(this); + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('MailBoxSystemDropDownViewModel', MailBoxSystemDropDownViewModel, AbstractSystemDropDownViewModel); + +/** + * @constructor + * @extends AbstractSystemDropDownViewModel + */ +function SettingsSystemDropDownViewModel() +{ + AbstractSystemDropDownViewModel.call(this); + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('SettingsSystemDropDownViewModel', SettingsSystemDropDownViewModel, AbstractSystemDropDownViewModel); + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function MailBoxFolderListViewModel() +{ + KnoinAbstractViewModel.call(this, 'Left', 'MailFolderList'); + + var oData = RL.data(); + + this.messageList = oData.messageList; + this.folderList = oData.folderList; + this.folderListSystem = oData.folderListSystem; + this.foldersChanging = oData.foldersChanging; + + this.leftPanelDisabled = oData.leftPanelDisabled; + + this.iDropOverTimer = 0; + + this.allowContacts = !!RL.settingsGet('ContactsIsAllowed'); + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('MailBoxFolderListViewModel', MailBoxFolderListViewModel); + +MailBoxFolderListViewModel.prototype.onBuild = function (oDom) +{ + var self = this; + + oDom + .on('click', '.b-folders .e-item .e-link .e-collapsed-sign', function (oEvent) { + + var + oFolder = ko.dataFor(this), + bCollapsed = false + ; + + if (oFolder && oEvent) + { + bCollapsed = oFolder.collapsed(); + Utils.setExpandedFolder(oFolder.fullNameHash, bCollapsed); + + oFolder.collapsed(!bCollapsed); + oEvent.preventDefault(); + oEvent.stopPropagation(); + } + }) + .on('click', '.b-folders .e-item .e-link.selectable', function (oEvent) { + + oEvent.preventDefault(); + + var + oData = RL.data(), + oFolder = ko.dataFor(this) + ; + + if (oFolder) + { + if (Enums.Layout.NoPreview === oData.layout()) + { + oData.message(null); + } + + if (oFolder.fullNameRaw === oData.currentFolderFullNameRaw()) + { + RL.cache().setFolderHash(oFolder.fullNameRaw, ''); + } + + kn.setHash(RL.link().mailBox(oFolder.fullNameHash)); + } + }) + ; + + key('up, down', Enums.KeyState.FolderList, function (event, handler) { + + var + iIndex = -1, + iKeyCode = handler && 'up' === handler.shortcut ? 38 : 40, + $items = $('.b-folders .e-item .e-link:not(.hidden):visible', oDom) + ; + + if (event && $items.length) + { + iIndex = $items.index($items.filter('.focused')); + if (-1 < iIndex) + { + $items.eq(iIndex).removeClass('focused'); + } + + if (iKeyCode === 38 && iIndex > 0) + { + iIndex--; + } + else if (iKeyCode === 40 && iIndex < $items.length - 1) + { + iIndex++; + } + + $items.eq(iIndex).addClass('focused'); + } + + return false; + }); + + key('enter', Enums.KeyState.FolderList, function () { + var $items = $('.b-folders .e-item .e-link:not(.hidden).focused', oDom); + if ($items.length && $items[0]) + { + self.folderList.focused(false); + $items.click(); + } + + return false; + }); + + key('space', Enums.KeyState.FolderList, function () { + var bCollapsed = true, oFolder = null, $items = $('.b-folders .e-item .e-link:not(.hidden).focused', oDom); + if ($items.length && $items[0]) + { + oFolder = ko.dataFor($items[0]); + if (oFolder) + { + bCollapsed = oFolder.collapsed(); + Utils.setExpandedFolder(oFolder.fullNameHash, bCollapsed); + oFolder.collapsed(!bCollapsed); + } + } + + return false; + }); + + key('esc, tab, shift+tab, right', Enums.KeyState.FolderList, function () { + self.folderList.focused(false); + return false; + }); + + self.folderList.focused.subscribe(function (bValue) { + $('.b-folders .e-item .e-link.focused', oDom).removeClass('focused'); + if (bValue) + { + $('.b-folders .e-item .e-link.selected', oDom).addClass('focused'); + } + }); +}; + +MailBoxFolderListViewModel.prototype.messagesDropOver = function (oFolder) +{ + window.clearTimeout(this.iDropOverTimer); + if (oFolder && oFolder.collapsed()) + { + this.iDropOverTimer = window.setTimeout(function () { + oFolder.collapsed(false); + Utils.setExpandedFolder(oFolder.fullNameHash, true); + Utils.windowResize(); + }, 500); + } +}; + +MailBoxFolderListViewModel.prototype.messagesDropOut = function () +{ + window.clearTimeout(this.iDropOverTimer); +}; + +/** + * + * @param {FolderModel} oToFolder + * @param {{helper:jQuery}} oUi + */ +MailBoxFolderListViewModel.prototype.messagesDrop = function (oToFolder, oUi) +{ + if (oToFolder && oUi && oUi.helper) + { + var + sFromFolderFullNameRaw = oUi.helper.data('rl-folder'), + bCopy = $html.hasClass('rl-ctrl-key-pressed'), + aUids = oUi.helper.data('rl-uids') + ; + + if (Utils.isNormal(sFromFolderFullNameRaw) && '' !== sFromFolderFullNameRaw && Utils.isArray(aUids)) + { + RL.moveMessagesToFolder(sFromFolderFullNameRaw, aUids, oToFolder.fullNameRaw, bCopy); + } + } +}; + +MailBoxFolderListViewModel.prototype.composeClick = function () +{ + kn.showScreenPopup(PopupsComposeViewModel); +}; + +MailBoxFolderListViewModel.prototype.createFolder = function () +{ + kn.showScreenPopup(PopupsFolderCreateViewModel); +}; + +MailBoxFolderListViewModel.prototype.configureFolders = function () +{ + kn.setHash(RL.link().settings('folders')); +}; + +MailBoxFolderListViewModel.prototype.contactsClick = function () +{ + if (this.allowContacts) + { + kn.showScreenPopup(PopupsContactsViewModel); + } +}; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function MailBoxMessageListViewModel() +{ + KnoinAbstractViewModel.call(this, 'Right', 'MailMessageList'); + + this.sLastUid = null; + this.bPrefetch = false; + this.emptySubjectValue = ''; + + var oData = RL.data(); + + this.popupVisibility = RL.popupVisibility; + + this.message = oData.message; + this.messageList = oData.messageList; + this.folderList = oData.folderList; + this.currentMessage = oData.currentMessage; + this.isMessageSelected = oData.isMessageSelected; + this.messageListSearch = oData.messageListSearch; + this.messageListError = oData.messageListError; + this.folderMenuForMove = oData.folderMenuForMove; + + this.useCheckboxesInList = oData.useCheckboxesInList; + + this.mainMessageListSearch = oData.mainMessageListSearch; + this.messageListEndFolder = oData.messageListEndFolder; + + this.messageListChecked = oData.messageListChecked; + this.messageListCheckedOrSelected = oData.messageListCheckedOrSelected; + this.messageListCheckedOrSelectedUidsWithSubMails = oData.messageListCheckedOrSelectedUidsWithSubMails; + this.messageListCompleteLoadingThrottle = oData.messageListCompleteLoadingThrottle; + + Utils.initOnStartOrLangChange(function () { + this.emptySubjectValue = Utils.i18n('MESSAGE_LIST/EMPTY_SUBJECT_TEXT'); + }, this); + + this.userQuota = oData.userQuota; + this.userUsageSize = oData.userUsageSize; + this.userUsageProc = oData.userUsageProc; + + this.moveDropdownTrigger = ko.observable(false); + this.moreDropdownTrigger = ko.observable(false); + + // append drag and drop + this.dragOver = ko.observable(false).extend({'throttle': 1}); + this.dragOverEnter = ko.observable(false).extend({'throttle': 1}); + this.dragOverArea = ko.observable(null); + this.dragOverBodyArea = ko.observable(null); + + this.messageListItemTemplate = ko.computed(function () { + return Enums.Layout.NoPreview !== oData.layout() ? + 'MailMessageListItem' : 'MailMessageListItemNoPreviewPane'; + }); + + this.messageListSearchDesc = ko.computed(function () { + var sValue = oData.messageListEndSearch(); + return '' === sValue ? '' : Utils.i18n('MESSAGE_LIST/SEARCH_RESULT_FOR', {'SEARCH': sValue}); + }); + + this.messageListPagenator = ko.computed(Utils.computedPagenatorHelper(oData.messageListPage, oData.messageListPageCount)); + + this.checkAll = ko.computed({ + 'read': function () { + return 0 < RL.data().messageListChecked().length; + }, + + 'write': function (bValue) { + bValue = !!bValue; + _.each(RL.data().messageList(), function (oMessage) { + oMessage.checked(bValue); + }); + } + }); + + this.inputMessageListSearchFocus = ko.observable(false); + + this.sLastSearchValue = ''; + this.inputProxyMessageListSearch = ko.computed({ + 'read': this.mainMessageListSearch, + 'write': function (sValue) { + this.sLastSearchValue = sValue; + }, + 'owner': this + }); + + this.isIncompleteChecked = ko.computed(function () { + var + iM = RL.data().messageList().length, + iC = RL.data().messageListChecked().length + ; + return 0 < iM && 0 < iC && iM > iC; + }, this); + + this.hasMessages = ko.computed(function () { + return 0 < this.messageList().length; + }, this); + + this.hasCheckedOrSelectedLines = ko.computed(function () { + return 0 < this.messageListCheckedOrSelected().length; + }, this); + + this.isSpamFolder = ko.computed(function () { + return oData.spamFolder() === this.messageListEndFolder() && + '' !== oData.spamFolder(); + }, this); + + this.isSpamDisabled = ko.computed(function () { + return Consts.Values.UnuseOptionValue === oData.spamFolder(); + }, this); + + this.isTrashFolder = ko.computed(function () { + return oData.trashFolder() === this.messageListEndFolder() && + '' !== oData.trashFolder(); + }, this); + + this.isDraftFolder = ko.computed(function () { + return oData.draftFolder() === this.messageListEndFolder() && + '' !== oData.draftFolder(); + }, this); + + this.isSentFolder = ko.computed(function () { + return oData.sentFolder() === this.messageListEndFolder() && + '' !== oData.sentFolder(); + }, this); + + this.isArchiveFolder = ko.computed(function () { + return oData.archiveFolder() === this.messageListEndFolder() && + '' !== oData.archiveFolder(); + }, this); + + this.isArchiveDisabled = ko.computed(function () { + return Consts.Values.UnuseOptionValue === RL.data().archiveFolder(); + }, this); + + this.canBeMoved = this.hasCheckedOrSelectedLines; + + this.clearCommand = Utils.createCommand(this, function () { + kn.showScreenPopup(PopupsFolderClearViewModel, [RL.data().currentFolder()]); + }); + + this.multyForwardCommand = Utils.createCommand(this, function () { + kn.showScreenPopup(PopupsComposeViewModel, [Enums.ComposeType.ForwardAsAttachment, RL.data().messageListCheckedOrSelected()]); + }, this.canBeMoved); + + this.deleteWithoutMoveCommand = Utils.createCommand(this, function () { + RL.deleteMessagesFromFolder(Enums.FolderType.Trash, + RL.data().currentFolderFullNameRaw(), + RL.data().messageListCheckedOrSelectedUidsWithSubMails(), false); + }, this.canBeMoved); + + this.deleteCommand = Utils.createCommand(this, function () { + RL.deleteMessagesFromFolder(Enums.FolderType.Trash, + RL.data().currentFolderFullNameRaw(), + RL.data().messageListCheckedOrSelectedUidsWithSubMails(), true); + }, this.canBeMoved); + + this.archiveCommand = Utils.createCommand(this, function () { + RL.deleteMessagesFromFolder(Enums.FolderType.Archive, + RL.data().currentFolderFullNameRaw(), + RL.data().messageListCheckedOrSelectedUidsWithSubMails(), true); + }, this.canBeMoved); + + this.spamCommand = Utils.createCommand(this, function () { + RL.deleteMessagesFromFolder(Enums.FolderType.Spam, + RL.data().currentFolderFullNameRaw(), + RL.data().messageListCheckedOrSelectedUidsWithSubMails(), true); + }, this.canBeMoved); + + this.notSpamCommand = Utils.createCommand(this, function () { + RL.deleteMessagesFromFolder(Enums.FolderType.NotSpam, + RL.data().currentFolderFullNameRaw(), + RL.data().messageListCheckedOrSelectedUidsWithSubMails(), true); + }, this.canBeMoved); + + this.moveCommand = Utils.createCommand(this, Utils.emptyFunction, this.canBeMoved); + + this.reloadCommand = Utils.createCommand(this, function () { + if (!RL.data().messageListCompleteLoadingThrottle()) + { + RL.reloadMessageList(false, true); + } + }); + + this.quotaTooltip = _.bind(this.quotaTooltip, this); + + this.selector = new Selector(this.messageList, this.currentMessage, + '.messageListItem .actionHandle', '.messageListItem.selected', '.messageListItem .checkboxMessage', + '.messageListItem.focused'); + + this.selector.on('onItemSelect', _.bind(function (oMessage) { + if (oMessage) + { + oData.message(oData.staticMessageList.populateByMessageListItem(oMessage)); + this.populateMessageBody(oData.message()); + + if (Enums.Layout.NoPreview === oData.layout()) + { + kn.setHash(RL.link().messagePreview(), true); + oData.message.focused(true); + } + } + else + { + oData.message(null); + } + }, this)); + + this.selector.on('onItemGetUid', function (oMessage) { + return oMessage ? oMessage.generateUid() : ''; + }); + + oData.messageListEndHash.subscribe(function () { + this.selector.scrollToTop(); + }, this); + + oData.layout.subscribe(function (mValue) { + this.selector.autoSelect(Enums.Layout.NoPreview !== mValue); + }, this); + + oData.layout.valueHasMutated(); + + RL + .sub('mailbox.message-list.selector.go-down', function () { + this.selector.goDown(true); + }, this) + .sub('mailbox.message-list.selector.go-up', function () { + this.selector.goUp(true); + }, this) + ; + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('MailBoxMessageListViewModel', MailBoxMessageListViewModel); + +/** + * @type {string} + */ +MailBoxMessageListViewModel.prototype.emptySubjectValue = ''; + +MailBoxMessageListViewModel.prototype.searchEnterAction = function () +{ + this.mainMessageListSearch(this.sLastSearchValue); + this.inputMessageListSearchFocus(false); +}; + +/** + * @returns {string} + */ +MailBoxMessageListViewModel.prototype.printableMessageCountForDeletion = function () +{ + var iCnt = this.messageListCheckedOrSelectedUidsWithSubMails().length; + return 1 < iCnt ? ' (' + (100 > iCnt ? iCnt : '99+') + ')' : ''; +}; + +MailBoxMessageListViewModel.prototype.cancelSearch = function () +{ + this.mainMessageListSearch(''); + this.inputMessageListSearchFocus(false); +}; + +/** + * @param {string} sToFolderFullNameRaw + * @return {boolean} + */ +MailBoxMessageListViewModel.prototype.moveSelectedMessagesToFolder = function (sToFolderFullNameRaw, bCopy) +{ + if (this.canBeMoved()) + { + RL.moveMessagesToFolder( + RL.data().currentFolderFullNameRaw(), + RL.data().messageListCheckedOrSelectedUidsWithSubMails(), sToFolderFullNameRaw, bCopy); + } + + return false; +}; + +MailBoxMessageListViewModel.prototype.dragAndDronHelper = function (oMessageListItem) +{ + if (oMessageListItem) + { + oMessageListItem.checked(true); + } + + var + oEl = Utils.draggeblePlace(), + aUids = RL.data().messageListCheckedOrSelectedUidsWithSubMails() + ; + + oEl.data('rl-folder', RL.data().currentFolderFullNameRaw()); + oEl.data('rl-uids', aUids); + oEl.find('.text').text('' + aUids.length); + + _.defer(function () { + var aUids = RL.data().messageListCheckedOrSelectedUidsWithSubMails(); + + oEl.data('rl-uids', aUids); + oEl.find('.text').text('' + aUids.length); + }); + + return oEl; +}; + +/** + * @param {string} sResult + * @param {AjaxJsonDefaultResponse} oData + * @param {boolean} bCached + */ +MailBoxMessageListViewModel.prototype.onMessageResponse = function (sResult, oData, bCached) +{ + var oRainLoopData = RL.data(); + + oRainLoopData.hideMessageBodies(); + oRainLoopData.messageLoading(false); + + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + oRainLoopData.setMessage(oData, bCached); + } + else if (Enums.StorageResultType.Unload === sResult) + { + oRainLoopData.message(null); + oRainLoopData.messageError(''); + } + else if (Enums.StorageResultType.Abort !== sResult) + { + oRainLoopData.message(null); + oRainLoopData.messageError((oData && oData.ErrorCode ? + Utils.getNotification(oData.ErrorCode) : + Utils.getNotification(Enums.Notification.UnknownError))); + } +}; + +MailBoxMessageListViewModel.prototype.populateMessageBody = function (oMessage) +{ + if (oMessage) + { + if (RL.remote().message(this.onMessageResponse, oMessage.folderFullNameRaw, oMessage.uid)) + { + RL.data().messageLoading(true); + } + else + { + Utils.log('Error: Unknown message request: ' + oMessage.folderFullNameRaw + ' ~ ' + oMessage.uid + ' [e-101]'); + } + } +}; + +/** + * @param {string} sFolderFullNameRaw + * @param {number} iSetAction + * @param {Array=} aMessages = null + */ +MailBoxMessageListViewModel.prototype.setAction = function (sFolderFullNameRaw, iSetAction, aMessages) +{ + var + aUids = [], + oFolder = null, + oCache = RL.cache(), + iAlreadyUnread = 0 + ; + + if (Utils.isUnd(aMessages)) + { + aMessages = RL.data().messageListChecked(); + } + + aUids = _.map(aMessages, function (oMessage) { + return oMessage.uid; + }); + + if ('' !== sFolderFullNameRaw && 0 < aUids.length) + { + switch (iSetAction) { + case Enums.MessageSetAction.SetSeen: + _.each(aMessages, function (oMessage) { + if (oMessage.unseen()) + { + iAlreadyUnread++; + } + + oMessage.unseen(false); + oCache.storeMessageFlagsToCache(oMessage); + }); + + oFolder = oCache.getFolderFromCacheList(sFolderFullNameRaw); + if (oFolder) + { + oFolder.messageCountUnread(oFolder.messageCountUnread() - iAlreadyUnread); + } + + RL.remote().messageSetSeen(Utils.emptyFunction, sFolderFullNameRaw, aUids, true); + break; + case Enums.MessageSetAction.UnsetSeen: + _.each(aMessages, function (oMessage) { + if (oMessage.unseen()) + { + iAlreadyUnread++; + } + + oMessage.unseen(true); + oCache.storeMessageFlagsToCache(oMessage); + }); + + oFolder = oCache.getFolderFromCacheList(sFolderFullNameRaw); + if (oFolder) + { + oFolder.messageCountUnread(oFolder.messageCountUnread() - iAlreadyUnread + aUids.length); + } + RL.remote().messageSetSeen(Utils.emptyFunction, sFolderFullNameRaw, aUids, false); + break; + case Enums.MessageSetAction.SetFlag: + _.each(aMessages, function (oMessage) { + oMessage.flagged(true); + oCache.storeMessageFlagsToCache(oMessage); + }); + RL.remote().messageSetFlagged(Utils.emptyFunction, sFolderFullNameRaw, aUids, true); + break; + case Enums.MessageSetAction.UnsetFlag: + _.each(aMessages, function (oMessage) { + oMessage.flagged(false); + oCache.storeMessageFlagsToCache(oMessage); + }); + RL.remote().messageSetFlagged(Utils.emptyFunction, sFolderFullNameRaw, aUids, false); + break; + } + + RL.reloadFlagsCurrentMessageListAndMessageFromCache(); + } +}; + +/** + * @param {string} sFolderFullNameRaw + * @param {number} iSetAction + */ +MailBoxMessageListViewModel.prototype.setActionForAll = function (sFolderFullNameRaw, iSetAction) +{ + var + oFolder = null, + aMessages = RL.data().messageList(), + oCache = RL.cache() + ; + + if ('' !== sFolderFullNameRaw) + { + oFolder = oCache.getFolderFromCacheList(sFolderFullNameRaw); + + if (oFolder) + { + switch (iSetAction) { + case Enums.MessageSetAction.SetSeen: + oFolder = oCache.getFolderFromCacheList(sFolderFullNameRaw); + if (oFolder) + { + _.each(aMessages, function (oMessage) { + oMessage.unseen(false); + }); + + oFolder.messageCountUnread(0); + oCache.clearMessageFlagsFromCacheByFolder(sFolderFullNameRaw); + } + + RL.remote().messageSetSeenToAll(Utils.emptyFunction, sFolderFullNameRaw, true); + break; + case Enums.MessageSetAction.UnsetSeen: + oFolder = oCache.getFolderFromCacheList(sFolderFullNameRaw); + if (oFolder) + { + _.each(aMessages, function (oMessage) { + oMessage.unseen(true); + }); + + oFolder.messageCountUnread(oFolder.messageCountAll()); + oCache.clearMessageFlagsFromCacheByFolder(sFolderFullNameRaw); + } + RL.remote().messageSetSeenToAll(Utils.emptyFunction, sFolderFullNameRaw, false); + break; + } + + RL.reloadFlagsCurrentMessageListAndMessageFromCache(); + } + } +}; + +MailBoxMessageListViewModel.prototype.listSetSeen = function () +{ + this.setAction(RL.data().currentFolderFullNameRaw(), Enums.MessageSetAction.SetSeen, RL.data().messageListCheckedOrSelected()); +}; + +MailBoxMessageListViewModel.prototype.listSetAllSeen = function () +{ + this.setActionForAll(RL.data().currentFolderFullNameRaw(), Enums.MessageSetAction.SetSeen); +}; + +MailBoxMessageListViewModel.prototype.listUnsetSeen = function () +{ + this.setAction(RL.data().currentFolderFullNameRaw(), Enums.MessageSetAction.UnsetSeen, RL.data().messageListCheckedOrSelected()); +}; + +MailBoxMessageListViewModel.prototype.listSetFlags = function () +{ + this.setAction(RL.data().currentFolderFullNameRaw(), Enums.MessageSetAction.SetFlag, RL.data().messageListCheckedOrSelected()); +}; + +MailBoxMessageListViewModel.prototype.listUnsetFlags = function () +{ + this.setAction(RL.data().currentFolderFullNameRaw(), Enums.MessageSetAction.UnsetFlag, RL.data().messageListCheckedOrSelected()); +}; + +MailBoxMessageListViewModel.prototype.flagMessages = function (oCurrentMessage) +{ + var + aChecked = this.messageListCheckedOrSelected(), + aCheckedUids = [] + ; + + if (oCurrentMessage) + { + if (0 < aChecked.length) + { + aCheckedUids = _.map(aChecked, function (oMessage) { + return oMessage.uid; + }); + } + + if (0 < aCheckedUids.length && -1 < Utils.inArray(oCurrentMessage.uid, aCheckedUids)) + { + this.setAction(oCurrentMessage.folderFullNameRaw, oCurrentMessage.flagged() ? + Enums.MessageSetAction.UnsetFlag : Enums.MessageSetAction.SetFlag, aChecked); + } + else + { + this.setAction(oCurrentMessage.folderFullNameRaw, oCurrentMessage.flagged() ? + Enums.MessageSetAction.UnsetFlag : Enums.MessageSetAction.SetFlag, [oCurrentMessage]); + } + } +}; + +MailBoxMessageListViewModel.prototype.flagMessagesFast = function (bFlag) +{ + var + aChecked = this.messageListCheckedOrSelected(), + aFlagged = [] + ; + + if (0 < aChecked.length) + { + aFlagged = _.filter(aChecked, function (oMessage) { + return oMessage.flagged(); + }); + + if (Utils.isUnd(bFlag)) + { + this.setAction(aChecked[0].folderFullNameRaw, + aChecked.length === aFlagged.length ? Enums.MessageSetAction.UnsetFlag : Enums.MessageSetAction.SetFlag, aChecked); + } + else + { + this.setAction(aChecked[0].folderFullNameRaw, + !bFlag ? Enums.MessageSetAction.UnsetFlag : Enums.MessageSetAction.SetFlag, aChecked); + } + } +}; + +MailBoxMessageListViewModel.prototype.seenMessagesFast = function (bSeen) +{ + var + aChecked = this.messageListCheckedOrSelected(), + aUnseen = [] + ; + + if (0 < aChecked.length) + { + aUnseen = _.filter(aChecked, function (oMessage) { + return oMessage.unseen(); + }); + + if (Utils.isUnd(bSeen)) + { + this.setAction(aChecked[0].folderFullNameRaw, + 0 < aUnseen.length ? Enums.MessageSetAction.SetSeen : Enums.MessageSetAction.UnsetSeen, aChecked); + } + else + { + this.setAction(aChecked[0].folderFullNameRaw, + bSeen ? Enums.MessageSetAction.SetSeen : Enums.MessageSetAction.UnsetSeen, aChecked); + } + } +}; + +MailBoxMessageListViewModel.prototype.onBuild = function (oDom) +{ + var + self = this, + oData = RL.data() + ; + + this.oContentVisible = $('.b-content', oDom); + this.oContentScrollable = $('.content', this.oContentVisible); + + this.oContentVisible.on('click', '.fullThreadHandle', function () { + var + aList = [], + oMessage = ko.dataFor(this) + ; + + if (oMessage && !oMessage.lastInCollapsedThreadLoading()) + { + RL.data().messageListThreadFolder(oMessage.folderFullNameRaw); + + aList = RL.data().messageListThreadUids(); + + if (oMessage.lastInCollapsedThread()) + { + aList.push(0 < oMessage.parentUid() ? oMessage.parentUid() : oMessage.uid); + } + else + { + aList = _.without(aList, 0 < oMessage.parentUid() ? oMessage.parentUid() : oMessage.uid); + } + + RL.data().messageListThreadUids(_.uniq(aList)); + + oMessage.lastInCollapsedThreadLoading(true); + oMessage.lastInCollapsedThread(!oMessage.lastInCollapsedThread()); + RL.reloadMessageList(); + } + + return false; + }); + + this.selector.init(this.oContentVisible, this.oContentScrollable, Enums.KeyState.MessageList); + + oDom + .on('click', '.messageList .b-message-list-wrapper', function () { + if (self.message.focused()) + { + self.message.focused(false); + } + }) + .on('click', '.e-pagenator .e-page', function () { + var oPage = ko.dataFor(this); + if (oPage) + { + kn.setHash(RL.link().mailBox( + oData.currentFolderFullNameHash(), + oPage.value, + oData.messageListSearch() + )); + } + }) + .on('click', '.messageList .checkboxCkeckAll', function () { + self.checkAll(!self.checkAll()); + }) + .on('click', '.messageList .messageListItem .flagParent', function () { + self.flagMessages(ko.dataFor(this)); + }) + ; + + this.initUploaderForAppend(); + this.initShortcuts(); + + if (!Globals.bMobileDevice && !!RL.settingsGet('AllowPrefetch') && ifvisible) + { + ifvisible.setIdleDuration(10); + + ifvisible.idle(function () { + self.prefetchNextTick(); + }); + } +}; + +MailBoxMessageListViewModel.prototype.initShortcuts = function () +{ + var self = this; + + // disable print + key('ctrl+p, command+p', Enums.KeyState.MessageList, function () { + return false; + }); + + // TODO // more toggle +// key('', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { +// self.moreDropdownTrigger(true); +// return false; +// }); + + // archive (zip) + key('z', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + self.archiveCommand(); + return false; + }); + + // delete + key('delete, shift+delete', Enums.KeyState.MessageList, function (event, handler) { + if (event) + { + if (0 < RL.data().messageListCheckedOrSelected().length) + { + if (handler && 'shift+delete' === handler.shortcut) + { + self.deleteWithoutMoveCommand(); + } + else + { + self.deleteCommand(); + } + } + + return false; + } + }); + + // check all + key('ctrl+a, command+a', Enums.KeyState.MessageList, function () { + self.checkAll(!(self.checkAll() && !self.isIncompleteChecked())); + return false; + }); + + // write/compose (open compose popup) + key('w,c', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + kn.showScreenPopup(PopupsComposeViewModel); + return false; + }); + + // important - star/flag messages + key('i', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + self.flagMessagesFast(); + return false; + }); + + // move + key('m', Enums.KeyState.MessageList, function () { + self.moveDropdownTrigger(true); + return false; + }); + + // read + key('q', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + self.seenMessagesFast(true); + return false; + }); + + // unread + key('u', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + self.seenMessagesFast(false); + return false; + }); + + key('shift+f', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + self.multyForwardCommand(); + return false; + }); + + // search input focus + key('/', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + self.inputMessageListSearchFocus(true); + return false; + }); + + // cancel search + key('esc', Enums.KeyState.MessageList, function () { + if ('' !== self.messageListSearchDesc()) + { + self.cancelSearch(); + return false; + } + }); + + // change focused state + key('tab, shift+tab, left, right', Enums.KeyState.MessageList, function (event, handler) { + if (event && handler && 'shift+tab' === handler.shortcut || 'left' === handler.shortcut) + { + self.folderList.focused(true); + } + else if (self.message()) + { + self.message.focused(true); + } + + return false; + }); + + // TODO + key('ctrl+left, command+left', Enums.KeyState.MessageView, function () { + return false; + }); + + // TODO + key('ctrl+right, command+right', Enums.KeyState.MessageView, function () { + return false; + }); +}; + +MailBoxMessageListViewModel.prototype.prefetchNextTick = function () +{ + if (!this.bPrefetch && !ifvisible.now() && this.viewModelVisibility()) + { + var + self = this, + oCache = RL.cache(), + oMessage = _.find(this.messageList(), function (oMessage) { + return oMessage && + !oCache.hasRequestedMessage(oMessage.folderFullNameRaw, oMessage.uid); + }) + ; + + if (oMessage) + { + this.bPrefetch = true; + + RL.cache().addRequestedMessage(oMessage.folderFullNameRaw, oMessage.uid); + + RL.remote().message(function (sResult, oData) { + + var bNext = !!(Enums.StorageResultType.Success === sResult && oData && oData.Result); + + _.delay(function () { + self.bPrefetch = false; + if (bNext) + { + self.prefetchNextTick(); + } + }, 1000); + + }, oMessage.folderFullNameRaw, oMessage.uid); + } + } +}; + +MailBoxMessageListViewModel.prototype.composeClick = function () +{ + kn.showScreenPopup(PopupsComposeViewModel); +}; + +MailBoxMessageListViewModel.prototype.advancedSearchClick = function () +{ + kn.showScreenPopup(PopupsAdvancedSearchViewModel); +}; + +MailBoxMessageListViewModel.prototype.quotaTooltip = function () +{ + return Utils.i18n('MESSAGE_LIST/QUOTA_SIZE', { + 'SIZE': Utils.friendlySize(this.userUsageSize()), + 'PROC': this.userUsageProc(), + 'LIMIT': Utils.friendlySize(this.userQuota()) + }); +}; + +MailBoxMessageListViewModel.prototype.initUploaderForAppend = function () +{ + if (!RL.settingsGet('AllowAppendMessage') || !this.dragOverArea()) + { + return false; + } + + var oJua = new Jua({ + 'action': RL.link().append(), + 'name': 'AppendFile', + 'queueSize': 1, + 'multipleSizeLimit': 1, + 'disableFolderDragAndDrop': true, + 'hidden': { + 'Folder': function () { + return RL.data().currentFolderFullNameRaw(); + } + }, + 'dragAndDropElement': this.dragOverArea(), + 'dragAndDropBodyElement': this.dragOverBodyArea() + }); + + oJua + .on('onDragEnter', _.bind(function () { + this.dragOverEnter(true); + }, this)) + .on('onDragLeave', _.bind(function () { + this.dragOverEnter(false); + }, this)) + .on('onBodyDragEnter', _.bind(function () { + this.dragOver(true); + }, this)) + .on('onBodyDragLeave', _.bind(function () { + this.dragOver(false); + }, this)) + .on('onSelect', _.bind(function (sUid, oData) { + if (sUid && oData && 'message/rfc822' === oData['Type']) + { + RL.data().messageListLoading(true); + return true; + } + + return false; + }, this)) + .on('onComplete', _.bind(function () { + RL.reloadMessageList(true, true); + }, this)) + ; + + return !!oJua; +}; +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function MailBoxMessageViewViewModel() +{ + KnoinAbstractViewModel.call(this, 'Right', 'MailMessageView'); + + var + self = this, + sLastEmail = '', + oData = RL.data(), + createCommandHelper = function (sType) { + return Utils.createCommand(self, function () { + this.replyOrforward(sType); + }, self.canBeRepliedOrForwarded); + } + ; + + this.oMessageScrollerDom = null; + + this.keyScope = oData.keyScope; + this.message = oData.message; + this.currentMessage = oData.currentMessage; + this.messageListChecked = oData.messageListChecked; + this.hasCheckedMessages = oData.hasCheckedMessages; + this.messageListCheckedOrSelectedUidsWithSubMails = oData.messageListCheckedOrSelectedUidsWithSubMails; + this.messageLoading = oData.messageLoading; + this.messageLoadingThrottle = oData.messageLoadingThrottle; + this.messagesBodiesDom = oData.messagesBodiesDom; + this.useThreads = oData.useThreads; + this.replySameFolder = oData.replySameFolder; + this.layout = oData.layout; + this.usePreviewPane = oData.usePreviewPane; + this.isMessageSelected = oData.isMessageSelected; + this.messageActiveDom = oData.messageActiveDom; + this.messageError = oData.messageError; + + this.fullScreenMode = oData.messageFullScreenMode; + + this.showFullInfo = ko.observable(false); + this.moreDropdownTrigger = ko.observable(false); + this.messageDomFocused = ko.observable(false).extend({'rateLimit': 0}); + + this.messageVisibility = ko.computed(function () { + return !this.messageLoadingThrottle() && !!this.message(); + }, this); + + this.message.subscribe(function (oMessage) { + if (!oMessage) + { + this.currentMessage(null); + } + }, this); + + this.canBeRepliedOrForwarded = this.messageVisibility; + + // commands + this.closeMessage = Utils.createCommand(this, function () { + oData.message(null); + }); + + this.replyCommand = createCommandHelper(Enums.ComposeType.Reply); + this.replyAllCommand = createCommandHelper(Enums.ComposeType.ReplyAll); + this.forwardCommand = createCommandHelper(Enums.ComposeType.Forward); + this.forwardAsAttachmentCommand = createCommandHelper(Enums.ComposeType.ForwardAsAttachment); + this.editAsNewCommand = createCommandHelper(Enums.ComposeType.EditAsNew); + + this.messageVisibilityCommand = Utils.createCommand(this, Utils.emptyFunction, this.messageVisibility); + + this.messageEditCommand = Utils.createCommand(this, function () { + this.editMessage(); + }, this.messageVisibility); + + this.deleteCommand = Utils.createCommand(this, function () { + if (this.message()) + { + RL.deleteMessagesFromFolder(Enums.FolderType.Trash, + this.message().folderFullNameRaw, + [this.message().uid], true); + } + }, this.messageVisibility); + + this.deleteWithoutMoveCommand = Utils.createCommand(this, function () { + if (this.message()) + { + RL.deleteMessagesFromFolder(Enums.FolderType.Trash, + RL.data().currentFolderFullNameRaw(), + [this.message().uid], false); + } + }, this.messageVisibility); + + this.archiveCommand = Utils.createCommand(this, function () { + if (this.message()) + { + RL.deleteMessagesFromFolder(Enums.FolderType.Archive, + this.message().folderFullNameRaw, + [this.message().uid], true); + } + }, this.messageVisibility); + + this.spamCommand = Utils.createCommand(this, function () { + if (this.message()) + { + RL.deleteMessagesFromFolder(Enums.FolderType.Spam, + this.message().folderFullNameRaw, + [this.message().uid], true); + } + }, this.messageVisibility); + + this.notSpamCommand = Utils.createCommand(this, function () { + if (this.message()) + { + RL.deleteMessagesFromFolder(Enums.FolderType.NotSpam, + this.message().folderFullNameRaw, + [this.message().uid], true); + } + }, this.messageVisibility); + + // viewer + this.viewSubject = ko.observable(''); + this.viewFromShort = ko.observable(''); + this.viewToShort = ko.observable(''); + this.viewFrom = ko.observable(''); + this.viewTo = ko.observable(''); + this.viewCc = ko.observable(''); + this.viewBcc = ko.observable(''); + this.viewDate = ko.observable(''); + this.viewMoment = ko.observable(''); + this.viewLineAsCcc = ko.observable(''); + this.viewViewLink = ko.observable(''); + this.viewDownloadLink = ko.observable(''); + this.viewUserPic = ko.observable(Consts.DataImages.UserDotPic); + this.viewUserPicVisible = ko.observable(false); + + this.viewPgpPassword = ko.observable(''); + this.viewPgpSignedVerifyStatus = ko.computed(function () { + return this.message() ? this.message().pgpSignedVerifyStatus() : Enums.SignedVerifyStatus.None; + }, this); + + this.viewPgpSignedVerifyUser = ko.computed(function () { + return this.message() ? this.message().pgpSignedVerifyUser() : ''; + }, this); + + this.message.subscribe(function (oMessage) { + + this.messageActiveDom(null); + + this.viewPgpPassword(''); + + if (oMessage) + { + this.viewSubject(oMessage.subject()); + this.viewFromShort(oMessage.fromToLine(true, true)); + this.viewToShort(oMessage.toToLine(true, true)); + this.viewFrom(oMessage.fromToLine(false)); + this.viewTo(oMessage.toToLine(false)); + this.viewCc(oMessage.ccToLine(false)); + this.viewBcc(oMessage.bccToLine(false)); + this.viewDate(oMessage.fullFormatDateValue()); + this.viewMoment(oMessage.momentDate()); + this.viewLineAsCcc(oMessage.lineAsCcc()); + this.viewViewLink(oMessage.viewLink()); + this.viewDownloadLink(oMessage.downloadLink()); + + sLastEmail = oMessage.fromAsSingleEmail(); + RL.cache().getUserPic(sLastEmail, function (sPic, $sEmail) { + if (sPic !== self.viewUserPic() && sLastEmail === $sEmail) + { + self.viewUserPicVisible(false); + self.viewUserPic(Consts.DataImages.UserDotPic); + if ('' !== sPic) + { + self.viewUserPicVisible(true); + self.viewUserPic(sPic); + } + } + }); + } + + }, this); + + this.fullScreenMode.subscribe(function (bValue) { + if (bValue) + { + $html.addClass('rl-message-fullscreen'); + } + else + { + $html.removeClass('rl-message-fullscreen'); + } + + Utils.windowResize(); + }); + + this.messageLoadingThrottle.subscribe(function (bV) { + if (bV) + { + Utils.windowResize(); + } + }); + + this.messageActiveDom.subscribe(function () { + this.scrollMessageToTop(); + }, this); + + this.goUpCommand = Utils.createCommand(this, function () { + RL.pub('mailbox.message-list.selector.go-up'); + }); + + this.goDownCommand = Utils.createCommand(this, function () { + RL.pub('mailbox.message-list.selector.go-down'); + }); + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('MailBoxMessageViewViewModel', MailBoxMessageViewViewModel); + +MailBoxMessageViewViewModel.prototype.isPgpActionVisible = function () +{ + return Enums.SignedVerifyStatus.Success !== this.viewPgpSignedVerifyStatus(); +}; + +MailBoxMessageViewViewModel.prototype.isPgpStatusVerifyVisible = function () +{ + return Enums.SignedVerifyStatus.None !== this.viewPgpSignedVerifyStatus(); +}; + +MailBoxMessageViewViewModel.prototype.isPgpStatusVerifySuccess = function () +{ + return Enums.SignedVerifyStatus.Success === this.viewPgpSignedVerifyStatus(); +}; + +MailBoxMessageViewViewModel.prototype.pgpStatusVerifyMessage = function () +{ + var sResult = ''; + switch (this.viewPgpSignedVerifyStatus()) + { + case Enums.SignedVerifyStatus.UnknownPublicKeys: + sResult = Utils.i18n('PGP_NOTIFICATIONS/NO_PUBLIC_KEYS_FOUND'); + break; + case Enums.SignedVerifyStatus.UnknownPrivateKey: + sResult = Utils.i18n('PGP_NOTIFICATIONS/NO_PRIVATE_KEY_FOUND'); + break; + case Enums.SignedVerifyStatus.Unverified: + sResult = Utils.i18n('PGP_NOTIFICATIONS/UNVERIFIRED_SIGNATURE'); + break; + case Enums.SignedVerifyStatus.Error: + sResult = Utils.i18n('PGP_NOTIFICATIONS/DECRYPTION_ERROR'); + break; + case Enums.SignedVerifyStatus.Success: + sResult = Utils.i18n('PGP_NOTIFICATIONS/GOOD_SIGNATURE', { + 'USER': this.viewPgpSignedVerifyUser() + }); + break; + } + + return sResult; +}; + +MailBoxMessageViewViewModel.prototype.scrollToTop = function () +{ + var oCont = $('.messageItem.nano .content', this.viewModelDom); + if (oCont && oCont[0]) + { +// oCont.animate({'scrollTop': 0}, 300); + oCont.scrollTop(0); + } + else + { +// $('.messageItem', this.viewModelDom).animate({'scrollTop': 0}, 300); + $('.messageItem', this.viewModelDom).scrollTop(0); + } + + Utils.windowResize(); +}; + +MailBoxMessageViewViewModel.prototype.fullScreen = function () +{ + this.fullScreenMode(true); + Utils.windowResize(); +}; + +MailBoxMessageViewViewModel.prototype.unFullScreen = function () +{ + this.fullScreenMode(false); + Utils.windowResize(); +}; + +MailBoxMessageViewViewModel.prototype.toggleFullScreen = function () +{ + Utils.removeSelection(); + + this.fullScreenMode(!this.fullScreenMode()); + Utils.windowResize(); +}; + +/** + * @param {string} sType + */ +MailBoxMessageViewViewModel.prototype.replyOrforward = function (sType) +{ + kn.showScreenPopup(PopupsComposeViewModel, [sType, RL.data().message()]); +}; + +MailBoxMessageViewViewModel.prototype.onBuild = function (oDom) +{ + var + self = this, + oData = RL.data() + ; + + this.fullScreenMode.subscribe(function (bValue) { + if (bValue) + { + self.message.focused(true); + } + }, this); + + $('.attachmentsPlace', oDom).magnificPopup({ + 'delegate': '.magnificPopupImage:visible', + 'type': 'image', + 'gallery': { + 'enabled': true, + 'preload': [1, 1], + 'navigateByImgClick': true + }, + 'callbacks': { + 'open': function() { + oData.useKeyboardShortcuts(false); + }, + 'close': function() { + oData.useKeyboardShortcuts(true); + } + }, + 'mainClass': 'mfp-fade', + 'removalDelay': 400 + }); + + oDom + .on('click', '.messageView .messageItem .messageItemHeader', function () { + if (oData.useKeyboardShortcuts() && self.message()) + { + self.message.focused(true); + } + }) + .on('mousedown', 'a', function (oEvent) { + // setup maito protocol + return !(oEvent && 3 !== oEvent['which'] && RL.mailToHelper($(this).attr('href'))); + }) + .on('click', '.attachmentsPlace .attachmentPreview', function (oEvent) { + if (oEvent && oEvent.stopPropagation) + { + oEvent.stopPropagation(); + } + }) + .on('click', '.attachmentsPlace .attachmentItem', function () { + + var + oAttachment = ko.dataFor(this) + ; + + if (oAttachment && oAttachment.download) + { + RL.download(oAttachment.linkDownload()); + } + }) + ; + + this.message.focused.subscribe(function (bValue) { + if (bValue && !Utils.inFocus()) { + this.messageDomFocused(true); + } else { + this.messageDomFocused(false); + } + }, this); + + this.messageDomFocused.subscribe(function (bValue) { + if (!bValue && Enums.KeyState.MessageView === this.keyScope()) + { + this.message.focused(false); + } + }, this); + + this.keyScope.subscribe(function (sValue) { + if (Enums.KeyState.MessageView === sValue && this.message.focused()) + { + this.messageDomFocused(true); + } + }, this); + + this.oMessageScrollerDom = oDom.find('.messageItem .content'); + this.oMessageScrollerDom = this.oMessageScrollerDom && this.oMessageScrollerDom[0] ? this.oMessageScrollerDom : null; + + this.initShortcuts(); +}; + +/** + * @return {boolean} + */ +MailBoxMessageViewViewModel.prototype.escShortcuts = function () +{ + if (this.viewModelVisibility() && this.message()) + { + if (this.fullScreenMode()) + { + this.fullScreenMode(false); + } + else if (Enums.Layout.NoPreview === RL.data().layout()) + { + this.message(null); + } + else + { + this.message.focused(false); + } + + return false; + } +}; + +MailBoxMessageViewViewModel.prototype.initShortcuts = function () +{ + var + self = this, + oData = RL.data() + ; + + // exit fullscreen, back + key('esc', Enums.KeyState.MessageView, _.bind(this.escShortcuts, this)); + + // fullscreen + key('enter', Enums.KeyState.MessageView, function () { + self.toggleFullScreen(); + return false; + }); + + key('enter', Enums.KeyState.MessageList, function () { + if (Enums.Layout.NoPreview !== oData.layout() && self.message()) + { + self.toggleFullScreen(); + return false; + } + }); + + // TODO // more toggle +// key('', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { +// self.moreDropdownTrigger(true); +// return false; +// }); + + // reply + key('r', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + if (oData.message()) + { + self.replyCommand(); + return false; + } + }); + + // replaAll + key('a', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + if (oData.message()) + { + self.replyAllCommand(); + return false; + } + }); + + // forward + key('f', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + if (oData.message()) + { + self.forwardCommand(); + return false; + } + }); + + // message information +// key('i', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { +// if (oData.message()) +// { +// self.showFullInfo(!self.showFullInfo()); +// return false; +// } +// }); + + // toggle message blockquotes + key('b', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + if (oData.message() && oData.message().body) + { + Utils.toggleMessageBlockquote(oData.message().body); + return false; + } + }); + + key('ctrl+left, command+left, ctrl+up, command+up', Enums.KeyState.MessageView, function () { + self.goUpCommand(); + return false; + }); + + key('ctrl+right, command+right, ctrl+down, command+down', Enums.KeyState.MessageView, function () { + self.goDownCommand(); + return false; + }); + + // print + key('ctrl+p, command+p', Enums.KeyState.MessageView, function () { + if (self.message()) + { + self.message().printMessage(); + } + + return false; + }); + + // delete + key('delete, shift+delete', Enums.KeyState.MessageView, function (event, handler) { + if (event) + { + if (handler && 'shift+delete' === handler.shortcut) + { + self.deleteWithoutMoveCommand(); + } + else + { + self.deleteCommand(); + } + + return false; + } + }); + + // change focused state + key('tab, shift+tab, left', Enums.KeyState.MessageView, function () { + if (!self.fullScreenMode() && self.message() && Enums.Layout.NoPreview !== oData.layout()) + { + self.message.focused(false); + } + + return false; + }); +}; + +/** + * @return {boolean} + */ +MailBoxMessageViewViewModel.prototype.isDraftFolder = function () +{ + return RL.data().message() && RL.data().draftFolder() === RL.data().message().folderFullNameRaw; +}; + +/** + * @return {boolean} + */ +MailBoxMessageViewViewModel.prototype.isSentFolder = function () +{ + return RL.data().message() && RL.data().sentFolder() === RL.data().message().folderFullNameRaw; +}; + +/** + * @return {boolean} + */ +MailBoxMessageViewViewModel.prototype.isSpamFolder = function () +{ + return RL.data().message() && RL.data().spamFolder() === RL.data().message().folderFullNameRaw; +}; + +/** + * @return {boolean} + */ +MailBoxMessageViewViewModel.prototype.isSpamDisabled = function () +{ + return RL.data().message() && RL.data().spamFolder() === Consts.Values.UnuseOptionValue; +}; + +/** + * @return {boolean} + */ +MailBoxMessageViewViewModel.prototype.isArchiveFolder = function () +{ + return RL.data().message() && RL.data().archiveFolder() === RL.data().message().folderFullNameRaw; +}; + +/** + * @return {boolean} + */ +MailBoxMessageViewViewModel.prototype.isArchiveDisabled = function () +{ + return RL.data().message() && RL.data().archiveFolder() === Consts.Values.UnuseOptionValue; +}; + +/** + * @return {boolean} + */ +MailBoxMessageViewViewModel.prototype.isDraftOrSentFolder = function () +{ + return this.isDraftFolder() || this.isSentFolder(); +}; + +MailBoxMessageViewViewModel.prototype.composeClick = function () +{ + kn.showScreenPopup(PopupsComposeViewModel); +}; + +MailBoxMessageViewViewModel.prototype.editMessage = function () +{ + if (RL.data().message()) + { + kn.showScreenPopup(PopupsComposeViewModel, [Enums.ComposeType.Draft, RL.data().message()]); + } +}; + +MailBoxMessageViewViewModel.prototype.scrollMessageToTop = function () +{ + if (this.oMessageScrollerDom) + { + this.oMessageScrollerDom.scrollTop(0); + } +}; + +/** + * @param {MessageModel} oMessage + */ +MailBoxMessageViewViewModel.prototype.showImages = function (oMessage) +{ + if (oMessage && oMessage.showExternalImages) + { + oMessage.showExternalImages(true); + } +}; + +/** + * @returns {string} + */ +MailBoxMessageViewViewModel.prototype.printableCheckedMessageCount = function () +{ + var iCnt = this.messageListCheckedOrSelectedUidsWithSubMails().length; + return 0 < iCnt ? (100 > iCnt ? iCnt : '99+') : ''; +}; + + +/** + * @param {MessageModel} oMessage + */ +MailBoxMessageViewViewModel.prototype.verifyPgpSignedClearMessage = function (oMessage) +{ + if (oMessage) + { + oMessage.verifyPgpSignedClearMessage(); + } +}; + +/** + * @param {MessageModel} oMessage + */ +MailBoxMessageViewViewModel.prototype.decryptPgpEncryptedMessage = function (oMessage) +{ + if (oMessage) + { + oMessage.decryptPgpEncryptedMessage(this.viewPgpPassword()); + } +}; + +/** + * @param {MessageModel} oMessage + */ +MailBoxMessageViewViewModel.prototype.readReceipt = function (oMessage) +{ + if (oMessage && '' !== oMessage.readReceipt()) + { + RL.remote().sendReadReceiptMessage(Utils.emptyFunction, oMessage.folderFullNameRaw, oMessage.uid, + oMessage.readReceipt(), + Utils.i18n('READ_RECEIPT/SUBJECT', {'SUBJECT': oMessage.subject()}), + Utils.i18n('READ_RECEIPT/BODY', {'READ-RECEIPT': RL.data().accountEmail()})); + + oMessage.isReadReceipt(true); + + RL.cache().storeMessageFlagsToCache(oMessage); + RL.reloadFlagsCurrentMessageListAndMessageFromCache(); + } +}; + +/** + * @param {?} oScreen + * + * @constructor + * @extends KnoinAbstractViewModel + */ +function SettingsMenuViewModel(oScreen) +{ + KnoinAbstractViewModel.call(this, 'Left', 'SettingsMenu'); + + this.leftPanelDisabled = RL.data().leftPanelDisabled; + + this.menu = oScreen.menu; + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('SettingsMenuViewModel', SettingsMenuViewModel); + +SettingsMenuViewModel.prototype.link = function (sRoute) +{ + return RL.link().settings(sRoute); +}; + +SettingsMenuViewModel.prototype.backToMailBoxClick = function () +{ + kn.setHash(RL.link().inbox()); +}; + +/** + * @constructor + * @extends KnoinAbstractViewModel + */ +function SettingsPaneViewModel() +{ + KnoinAbstractViewModel.call(this, 'Right', 'SettingsPane'); + + Knoin.constructorEnd(this); +} + +Utils.extendAsViewModel('SettingsPaneViewModel', SettingsPaneViewModel); + +SettingsPaneViewModel.prototype.onBuild = function () +{ + var self = this; + key('esc', Enums.KeyState.Settings, function () { + self.backToMailBoxClick(); + }); +}; + +SettingsPaneViewModel.prototype.onShow = function () +{ + RL.data().message(null); +}; + +SettingsPaneViewModel.prototype.backToMailBoxClick = function () +{ + kn.setHash(RL.link().inbox()); +}; + +/** + * @constructor + */ +function SettingsGeneral() +{ + var oData = RL.data(); + + this.mainLanguage = oData.mainLanguage; + this.mainMessagesPerPage = oData.mainMessagesPerPage; + this.mainMessagesPerPageArray = Consts.Defaults.MessagesPerPageArray; + this.editorDefaultType = oData.editorDefaultType; + this.showImages = oData.showImages; + this.interfaceAnimation = oData.interfaceAnimation; + this.useDesktopNotifications = oData.useDesktopNotifications; + this.threading = oData.threading; + this.useThreads = oData.useThreads; + this.replySameFolder = oData.replySameFolder; + this.layout = oData.layout; + this.usePreviewPane = oData.usePreviewPane; + this.useCheckboxesInList = oData.useCheckboxesInList; + this.allowLanguagesOnSettings = oData.allowLanguagesOnSettings; + + this.isDesktopNotificationsSupported = ko.computed(function () { + return Enums.DesktopNotifications.NotSupported !== oData.desktopNotificationsPermisions(); + }); + + this.isDesktopNotificationsDenied = ko.computed(function () { + return Enums.DesktopNotifications.NotSupported === oData.desktopNotificationsPermisions() || + Enums.DesktopNotifications.Denied === oData.desktopNotificationsPermisions(); + }); + + this.mainLanguageFullName = ko.computed(function () { + return Utils.convertLangName(this.mainLanguage()); + }, this); + + this.languageTrigger = ko.observable(Enums.SaveSettingsStep.Idle).extend({'throttle': 100}); + this.mppTrigger = ko.observable(Enums.SaveSettingsStep.Idle); + + this.isAnimationSupported = Globals.bAnimationSupported; +} + +Utils.addSettingsViewModel(SettingsGeneral, 'SettingsGeneral', 'SETTINGS_LABELS/LABEL_GENERAL_NAME', 'general', true); + +SettingsGeneral.prototype.toggleLayout = function () +{ + this.layout(Enums.Layout.NoPreview === this.layout() ? Enums.Layout.SidePreview : Enums.Layout.NoPreview); +}; + +SettingsGeneral.prototype.onBuild = function () +{ + var self = this; + + _.delay(function () { + + var + oData = RL.data(), + f1 = Utils.settingsSaveHelperSimpleFunction(self.mppTrigger, self) + ; + + oData.language.subscribe(function (sValue) { + + self.languageTrigger(Enums.SaveSettingsStep.Animate); + + $.ajax({ + 'url': RL.link().langLink(sValue), + 'dataType': 'script', + 'cache': true + }).done(function() { + Utils.i18nToDoc(); + self.languageTrigger(Enums.SaveSettingsStep.TrueResult); + }).fail(function() { + self.languageTrigger(Enums.SaveSettingsStep.FalseResult); + }).always(function() { + _.delay(function () { + self.languageTrigger(Enums.SaveSettingsStep.Idle); + }, 1000); + }); + + RL.remote().saveSettings(Utils.emptyFunction, { + 'Language': sValue + }); + }); + + oData.editorDefaultType.subscribe(function (sValue) { + RL.remote().saveSettings(Utils.emptyFunction, { + 'EditorDefaultType': sValue + }); + }); + + oData.messagesPerPage.subscribe(function (iValue) { + RL.remote().saveSettings(f1, { + 'MPP': iValue + }); + }); + + oData.showImages.subscribe(function (bValue) { + RL.remote().saveSettings(Utils.emptyFunction, { + 'ShowImages': bValue ? '1' : '0' + }); + }); + + oData.interfaceAnimation.subscribe(function (sValue) { + RL.remote().saveSettings(Utils.emptyFunction, { + 'InterfaceAnimation': sValue + }); + }); + + oData.useDesktopNotifications.subscribe(function (bValue) { + Utils.timeOutAction('SaveDesktopNotifications', function () { + RL.remote().saveSettings(Utils.emptyFunction, { + 'DesktopNotifications': bValue ? '1' : '0' + }); + }, 3000); + }); + + oData.replySameFolder.subscribe(function (bValue) { + Utils.timeOutAction('SaveReplySameFolder', function () { + RL.remote().saveSettings(Utils.emptyFunction, { + 'ReplySameFolder': bValue ? '1' : '0' + }); + }, 3000); + }); + + oData.useThreads.subscribe(function (bValue) { + + oData.messageList([]); + + RL.remote().saveSettings(Utils.emptyFunction, { + 'UseThreads': bValue ? '1' : '0' + }); + }); + + oData.layout.subscribe(function (nValue) { + + oData.messageList([]); + + RL.remote().saveSettings(Utils.emptyFunction, { + 'Layout': nValue + }); + }); + + oData.useCheckboxesInList.subscribe(function (bValue) { + RL.remote().saveSettings(Utils.emptyFunction, { + 'UseCheckboxesInList': bValue ? '1' : '0' + }); + }); + + }, 50); +}; + +SettingsGeneral.prototype.onShow = function () +{ + RL.data().desktopNotifications.valueHasMutated(); +}; + +SettingsGeneral.prototype.selectLanguage = function () +{ + kn.showScreenPopup(PopupsLanguagesViewModel); +}; + +/** + * @constructor + */ +function SettingsContacts() +{ + var oData = RL.data(); + + this.contactsAutosave = oData.contactsAutosave; + + this.allowContactsSync = oData.allowContactsSync; + this.enableContactsSync = oData.enableContactsSync; + this.contactsSyncUrl = oData.contactsSyncUrl; + this.contactsSyncUser = oData.contactsSyncUser; + this.contactsSyncPass = oData.contactsSyncPass; + + this.saveTrigger = ko.computed(function () { + return [ + this.enableContactsSync() ? '1' : '0', + this.contactsSyncUrl(), + this.contactsSyncUser(), + this.contactsSyncPass() + ].join('|'); + }, this).extend({'throttle': 500}); + + this.saveTrigger.subscribe(function () { + RL.remote().saveContactsSyncData(null, + this.enableContactsSync(), + this.contactsSyncUrl(), + this.contactsSyncUser(), + this.contactsSyncPass() + ); + }, this); +} + +Utils.addSettingsViewModel(SettingsContacts, 'SettingsContacts', 'SETTINGS_LABELS/LABEL_CONTACTS_NAME', 'contacts'); + +SettingsContacts.prototype.onBuild = function () +{ + RL.data().contactsAutosave.subscribe(function (bValue) { + RL.remote().saveSettings(Utils.emptyFunction, { + 'ContactsAutosave': bValue ? '1' : '0' + }); + }); +}; + +//SettingsContacts.prototype.onShow = function () +//{ +// +//}; + +/** + * @constructor + */ +function SettingsAccounts() +{ + var oData = RL.data(); + + this.accounts = oData.accounts; + + this.processText = ko.computed(function () { + return oData.accountsLoading() ? Utils.i18n('SETTINGS_ACCOUNTS/LOADING_PROCESS') : ''; + }, this); + + this.visibility = ko.computed(function () { + return '' === this.processText() ? 'hidden' : 'visible'; + }, this); + + this.accountForDeletion = ko.observable(null).extend({'falseTimeout': 3000}).extend({'toggleSubscribe': [this, + function (oPrev) { + if (oPrev) + { + oPrev.deleteAccess(false); + } + }, function (oNext) { + if (oNext) + { + oNext.deleteAccess(true); + } + } + ]}); +} + +Utils.addSettingsViewModel(SettingsAccounts, 'SettingsAccounts', 'SETTINGS_LABELS/LABEL_ACCOUNTS_NAME', 'accounts'); + +SettingsAccounts.prototype.addNewAccount = function () +{ + kn.showScreenPopup(PopupsAddAccountViewModel); +}; + +/** + * @param {AccountModel} oAccountToRemove + */ +SettingsAccounts.prototype.deleteAccount = function (oAccountToRemove) +{ + if (oAccountToRemove && oAccountToRemove.deleteAccess()) + { + this.accountForDeletion(null); + + var + fRemoveAccount = function (oAccount) { + return oAccountToRemove === oAccount; + } + ; + + if (oAccountToRemove) + { + this.accounts.remove(fRemoveAccount); + + RL.remote().accountDelete(function (sResult, oData) { + + if (Enums.StorageResultType.Success === sResult && oData && + oData.Result && oData.Reload) + { + kn.routeOff(); + kn.setHash(RL.link().root(), true); + kn.routeOff(); + + _.defer(function () { + window.location.reload(); + }); + } + else + { + RL.accountsAndIdentities(); + } + + }, oAccountToRemove.email); + } + } +}; + +/** + * @constructor + */ +function SettingsIdentity() +{ + var oData = RL.data(); + + this.editor = null; + + this.displayName = oData.displayName; + this.signature = oData.signature; + this.signatureToAll = oData.signatureToAll; + this.replyTo = oData.replyTo; + + this.signatureDom = ko.observable(null); + + this.displayNameTrigger = ko.observable(Enums.SaveSettingsStep.Idle); + this.replyTrigger = ko.observable(Enums.SaveSettingsStep.Idle); + this.signatureTrigger = ko.observable(Enums.SaveSettingsStep.Idle); +} + +Utils.addSettingsViewModel(SettingsIdentity, 'SettingsIdentity', 'SETTINGS_LABELS/LABEL_IDENTITY_NAME', 'identity'); + +SettingsIdentity.prototype.onFocus = function () +{ + if (!this.editor && this.signatureDom()) + { + var + self = this, + sSignature = RL.data().signature() + ; + + this.editor = new NewHtmlEditorWrapper(self.signatureDom(), function () { + RL.data().signature( + (self.editor.isHtml() ? ':HTML:' : '') + self.editor.getData() + ); + }, function () { + if (':HTML:' === sSignature.substr(0, 6)) + { + self.editor.setHtml(sSignature.substr(6), false); + } + else + { + self.editor.setPlain(sSignature, false); + } + }); + } +}; + +SettingsIdentity.prototype.onBuild = function () +{ + var self = this; + _.delay(function () { + + var + oData = RL.data(), + f1 = Utils.settingsSaveHelperSimpleFunction(self.displayNameTrigger, self), + f2 = Utils.settingsSaveHelperSimpleFunction(self.replyTrigger, self), + f3 = Utils.settingsSaveHelperSimpleFunction(self.signatureTrigger, self) + ; + + oData.displayName.subscribe(function (sValue) { + RL.remote().saveSettings(f1, { + 'DisplayName': sValue + }); + }); + + oData.replyTo.subscribe(function (sValue) { + RL.remote().saveSettings(f2, { + 'ReplyTo': sValue + }); + }); + + oData.signature.subscribe(function (sValue) { + RL.remote().saveSettings(f3, { + 'Signature': sValue + }); + }); + + oData.signatureToAll.subscribe(function (bValue) { + RL.remote().saveSettings(null, { + 'SignatureToAll': bValue ? '1' : '0' + }); + }); + + }, 50); +}; + +/** + * @constructor + */ +function SettingsIdentities() +{ + var oData = RL.data(); + + this.editor = null; + + this.displayName = oData.displayName; + this.signature = oData.signature; + this.signatureToAll = oData.signatureToAll; + this.replyTo = oData.replyTo; + + this.signatureDom = ko.observable(null); + + this.displayNameTrigger = ko.observable(Enums.SaveSettingsStep.Idle); + this.replyTrigger = ko.observable(Enums.SaveSettingsStep.Idle); + this.signatureTrigger = ko.observable(Enums.SaveSettingsStep.Idle); + + this.identities = oData.identities; + + this.processText = ko.computed(function () { + return oData.identitiesLoading() ? Utils.i18n('SETTINGS_IDENTITIES/LOADING_PROCESS') : ''; + }, this); + + this.visibility = ko.computed(function () { + return '' === this.processText() ? 'hidden' : 'visible'; + }, this); + + this.identityForDeletion = ko.observable(null).extend({'falseTimeout': 3000}).extend({'toggleSubscribe': [this, + function (oPrev) { + if (oPrev) + { + oPrev.deleteAccess(false); + } + }, function (oNext) { + if (oNext) + { + oNext.deleteAccess(true); + } + } + ]}); +} + +Utils.addSettingsViewModel(SettingsIdentities, 'SettingsIdentities', 'SETTINGS_LABELS/LABEL_IDENTITIES_NAME', 'identities'); + +SettingsIdentities.prototype.addNewIdentity = function () +{ + kn.showScreenPopup(PopupsIdentityViewModel); +}; + +SettingsIdentities.prototype.editIdentity = function (oIdentity) +{ + kn.showScreenPopup(PopupsIdentityViewModel, [oIdentity]); +}; + +/** + * @param {IdentityModel} oIdentityToRemove + */ +SettingsIdentities.prototype.deleteIdentity = function (oIdentityToRemove) +{ + if (oIdentityToRemove && oIdentityToRemove.deleteAccess()) + { + this.identityForDeletion(null); + + var + fRemoveFolder = function (oIdentity) { + return oIdentityToRemove === oIdentity; + } + ; + + if (oIdentityToRemove) + { + this.identities.remove(fRemoveFolder); + + RL.remote().identityDelete(function () { + RL.accountsAndIdentities(); + }, oIdentityToRemove.id); + } + } +}; + +SettingsIdentities.prototype.onFocus = function () +{ + if (!this.editor && this.signatureDom()) + { + var + self = this, + sSignature = RL.data().signature() + ; + + this.editor = new NewHtmlEditorWrapper(self.signatureDom(), function () { + RL.data().signature( + (self.editor.isHtml() ? ':HTML:' : '') + self.editor.getData() + ); + }, function () { + if (':HTML:' === sSignature.substr(0, 6)) + { + self.editor.setHtml(sSignature.substr(6), false); + } + else + { + self.editor.setPlain(sSignature, false); + } + }); + } +}; + +SettingsIdentities.prototype.onBuild = function (oDom) +{ + var self = this; + + oDom + .on('click', '.identity-item .e-action', function () { + var oIdentityItem = ko.dataFor(this); + if (oIdentityItem) + { + self.editIdentity(oIdentityItem); + } + }) + ; + + _.delay(function () { + + var + oData = RL.data(), + f1 = Utils.settingsSaveHelperSimpleFunction(self.displayNameTrigger, self), + f2 = Utils.settingsSaveHelperSimpleFunction(self.replyTrigger, self), + f3 = Utils.settingsSaveHelperSimpleFunction(self.signatureTrigger, self) + ; + + oData.displayName.subscribe(function (sValue) { + RL.remote().saveSettings(f1, { + 'DisplayName': sValue + }); + }); + + oData.replyTo.subscribe(function (sValue) { + RL.remote().saveSettings(f2, { + 'ReplyTo': sValue + }); + }); + + oData.signature.subscribe(function (sValue) { + RL.remote().saveSettings(f3, { + 'Signature': sValue + }); + }); + + oData.signatureToAll.subscribe(function (bValue) { + RL.remote().saveSettings(null, { + 'SignatureToAll': bValue ? '1' : '0' + }); + }); + + }, 50); +}; +/** + * @constructor + */ +function SettingsSecurity() +{ + this.processing = ko.observable(false); + this.clearing = ko.observable(false); + this.secreting = ko.observable(false); + + this.viewUser = ko.observable(''); + this.viewEnable = ko.observable(false); + this.viewEnable.subs = true; + this.twoFactorStatus = ko.observable(false); + + this.viewSecret = ko.observable(''); + this.viewBackupCodes = ko.observable(''); + this.viewUrl = ko.observable(''); + + this.bFirst = true; + + this.viewTwoFactorStatus = ko.computed(function () { + Globals.langChangeTrigger(); + return Utils.i18n( + this.twoFactorStatus() ? + 'SETTINGS_SECURITY/TWO_FACTOR_SECRET_CONFIGURED_DESC' : + 'SETTINGS_SECURITY/TWO_FACTOR_SECRET_NOT_CONFIGURED_DESC' + ); + }, this); + + this.onResult = _.bind(this.onResult, this); + this.onSecretResult = _.bind(this.onSecretResult, this); +} + +Utils.addSettingsViewModel(SettingsSecurity, 'SettingsSecurity', 'SETTINGS_LABELS/LABEL_SECURITY_NAME', 'security'); + +SettingsSecurity.prototype.showSecret = function () +{ + this.secreting(true); + RL.remote().showTwoFactorSecret(this.onSecretResult); +}; + +SettingsSecurity.prototype.hideSecret = function () +{ + this.viewSecret(''); + this.viewBackupCodes(''); + this.viewUrl(''); +}; + +SettingsSecurity.prototype.createTwoFactor = function () +{ + this.processing(true); + RL.remote().createTwoFactor(this.onResult); +}; + +SettingsSecurity.prototype.enableTwoFactor = function () +{ + this.processing(true); + RL.remote().enableTwoFactor(this.onResult, this.viewEnable()); +}; + +SettingsSecurity.prototype.testTwoFactor = function () +{ + kn.showScreenPopup(PopupsTwoFactorTestViewModel); +}; + +SettingsSecurity.prototype.clearTwoFactor = function () +{ + this.viewSecret(''); + this.viewBackupCodes(''); + this.viewUrl(''); + + this.clearing(true); + RL.remote().clearTwoFactor(this.onResult); +}; + +SettingsSecurity.prototype.onShow = function () +{ + this.viewSecret(''); + this.viewBackupCodes(''); + this.viewUrl(''); +}; + +SettingsSecurity.prototype.onResult = function (sResult, oData) +{ + this.processing(false); + this.clearing(false); + + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + this.viewUser(Utils.pString(oData.Result.User)); + this.viewEnable(!!oData.Result.Enable); + this.twoFactorStatus(!!oData.Result.IsSet); + + this.viewSecret(Utils.pString(oData.Result.Secret)); + this.viewBackupCodes(Utils.pString(oData.Result.BackupCodes).replace(/[\s]+/g, ' ')); + this.viewUrl(Utils.pString(oData.Result.Url)); + } + else + { + this.viewUser(''); + this.viewEnable(false); + this.twoFactorStatus(false); + + this.viewSecret(''); + this.viewBackupCodes(''); + this.viewUrl(''); + } + + if (this.bFirst) + { + this.bFirst = false; + var self = this; + this.viewEnable.subscribe(function (bValue) { + if (this.viewEnable.subs) + { + RL.remote().enableTwoFactor(function (sResult, oData) { + if (Enums.StorageResultType.Success !== sResult || !oData || !oData.Result) + { + self.viewEnable.subs = false; + self.viewEnable(false); + self.viewEnable.subs = true; + } + }, bValue); + } + }, this); + } +}; + +SettingsSecurity.prototype.onSecretResult = function (sResult, oData) +{ + this.secreting(false); + + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + this.viewSecret(Utils.pString(oData.Result.Secret)); + this.viewUrl(Utils.pString(oData.Result.Url)); + } + else + { + this.viewSecret(''); + this.viewUrl(''); + } +}; + +SettingsSecurity.prototype.onBuild = function () +{ + this.processing(true); + RL.remote().getTwoFactor(this.onResult); +}; + +/** + * @constructor + */ +function SettingsSocialScreen() +{ + var oData = RL.data(); + + this.googleEnable = oData.googleEnable; + + this.googleActions = oData.googleActions; + this.googleLoggined = oData.googleLoggined; + this.googleUserName = oData.googleUserName; + + this.facebookEnable = oData.facebookEnable; + + this.facebookActions = oData.facebookActions; + this.facebookLoggined = oData.facebookLoggined; + this.facebookUserName = oData.facebookUserName; + + this.twitterEnable = oData.twitterEnable; + + this.twitterActions = oData.twitterActions; + this.twitterLoggined = oData.twitterLoggined; + this.twitterUserName = oData.twitterUserName; + + this.connectGoogle = Utils.createCommand(this, function () { + if (!this.googleLoggined()) + { + RL.googleConnect(); + } + }, function () { + return !this.googleLoggined() && !this.googleActions(); + }); + + this.disconnectGoogle = Utils.createCommand(this, function () { + RL.googleDisconnect(); + }); + + this.connectFacebook = Utils.createCommand(this, function () { + if (!this.facebookLoggined()) + { + RL.facebookConnect(); + } + }, function () { + return !this.facebookLoggined() && !this.facebookActions(); + }); + + this.disconnectFacebook = Utils.createCommand(this, function () { + RL.facebookDisconnect(); + }); + + this.connectTwitter = Utils.createCommand(this, function () { + if (!this.twitterLoggined()) + { + RL.twitterConnect(); + } + }, function () { + return !this.twitterLoggined() && !this.twitterActions(); + }); + + this.disconnectTwitter = Utils.createCommand(this, function () { + RL.twitterDisconnect(); + }); +} + +Utils.addSettingsViewModel(SettingsSocialScreen, 'SettingsSocial', 'SETTINGS_LABELS/LABEL_SOCIAL_NAME', 'social'); + +/** + * @constructor + */ +function SettingsChangePasswordScreen() +{ + this.changeProcess = ko.observable(false); + + this.errorDescription = ko.observable(''); + this.passwordMismatch = ko.observable(false); + this.passwordUpdateError = ko.observable(false); + this.passwordUpdateSuccess = ko.observable(false); + + this.currentPassword = ko.observable(''); + this.currentPassword.error = ko.observable(false); + this.newPassword = ko.observable(''); + this.newPassword2 = ko.observable(''); + + this.currentPassword.subscribe(function () { + this.passwordUpdateError(false); + this.passwordUpdateSuccess(false); + this.currentPassword.error(false); + }, this); + + this.newPassword.subscribe(function () { + this.passwordUpdateError(false); + this.passwordUpdateSuccess(false); + this.passwordMismatch(false); + }, this); + + this.newPassword2.subscribe(function () { + this.passwordUpdateError(false); + this.passwordUpdateSuccess(false); + this.passwordMismatch(false); + }, this); + + this.saveNewPasswordCommand = Utils.createCommand(this, function () { + + if (this.newPassword() !== this.newPassword2()) + { + this.passwordMismatch(true); + this.errorDescription(Utils.i18n('SETTINGS_CHANGE_PASSWORD/ERROR_PASSWORD_MISMATCH')); + } + else + { + this.changeProcess(true); + + this.passwordUpdateError(false); + this.passwordUpdateSuccess(false); + this.currentPassword.error(false); + this.passwordMismatch(false); + this.errorDescription(''); + + RL.remote().changePassword(this.onChangePasswordResponse, this.currentPassword(), this.newPassword()); + } + + }, function () { + return !this.changeProcess() && '' !== this.currentPassword() && + '' !== this.newPassword() && '' !== this.newPassword2(); + }); + + this.onChangePasswordResponse = _.bind(this.onChangePasswordResponse, this); +} + +Utils.addSettingsViewModel(SettingsChangePasswordScreen, 'SettingsChangePassword', 'SETTINGS_LABELS/LABEL_CHANGE_PASSWORD_NAME', 'change-password'); + +SettingsChangePasswordScreen.prototype.onHide = function () +{ + this.changeProcess(false); + this.currentPassword(''); + this.newPassword(''); + this.newPassword2(''); + this.errorDescription(''); + this.passwordMismatch(false); + this.currentPassword.error(false); +}; + +SettingsChangePasswordScreen.prototype.onChangePasswordResponse = function (sResult, oData) +{ + this.changeProcess(false); + this.passwordMismatch(false); + this.errorDescription(''); + this.currentPassword.error(false); + + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + this.currentPassword(''); + this.newPassword(''); + this.newPassword2(''); + + this.passwordUpdateSuccess(true); + this.currentPassword.error(false); + } + else + { + if (oData && Enums.Notification.CurrentPasswordIncorrect === oData.ErrorCode) + { + this.currentPassword.error(true); + } + + this.passwordUpdateError(true); + this.errorDescription(oData && oData.ErrorCode ? Utils.getNotification(oData.ErrorCode) : + Utils.getNotification(Enums.Notification.CouldNotSaveNewPassword)); + } +}; + +/** + * @constructor + */ +function SettingsFolders() +{ + var oData = RL.data(); + + this.foldersListError = oData.foldersListError; + this.folderList = oData.folderList; + + this.processText = ko.computed(function () { + + var + oData = RL.data(), + bLoading = oData.foldersLoading(), + bCreating = oData.foldersCreating(), + bDeleting = oData.foldersDeleting(), + bRenaming = oData.foldersRenaming() + ; + + if (bCreating) + { + return Utils.i18n('SETTINGS_FOLDERS/CREATING_PROCESS'); + } + else if (bDeleting) + { + return Utils.i18n('SETTINGS_FOLDERS/DELETING_PROCESS'); + } + else if (bRenaming) + { + return Utils.i18n('SETTINGS_FOLDERS/RENAMING_PROCESS'); + } + else if (bLoading) + { + return Utils.i18n('SETTINGS_FOLDERS/LOADING_PROCESS'); + } + + return ''; + + }, this); + + this.visibility = ko.computed(function () { + return '' === this.processText() ? 'hidden' : 'visible'; + }, this); + + this.folderForDeletion = ko.observable(null).extend({'falseTimeout': 3000}).extend({'toggleSubscribe': [this, + function (oPrev) { + if (oPrev) + { + oPrev.deleteAccess(false); + } + }, function (oNext) { + if (oNext) + { + oNext.deleteAccess(true); + } + } + ]}); + + this.folderForEdit = ko.observable(null).extend({'toggleSubscribe': [this, + function (oPrev) { + if (oPrev) + { + oPrev.edited(false); + } + }, function (oNext) { + if (oNext && oNext.canBeEdited()) + { + oNext.edited(true); + } + } + ]}); + + this.useImapSubscribe = !!RL.settingsGet('UseImapSubscribe'); +} + +Utils.addSettingsViewModel(SettingsFolders, 'SettingsFolders', 'SETTINGS_LABELS/LABEL_FOLDERS_NAME', 'folders'); + +SettingsFolders.prototype.folderEditOnEnter = function (oFolder) +{ + var sEditName = oFolder ? Utils.trim(oFolder.nameForEdit()) : ''; + if ('' !== sEditName && oFolder.name() !== sEditName) + { + RL.local().set(Enums.ClientSideKeyName.FoldersLashHash, ''); + + RL.data().foldersRenaming(true); + RL.remote().folderRename(function (sResult, oData) { + + RL.data().foldersRenaming(false); + if (Enums.StorageResultType.Success !== sResult || !oData || !oData.Result) + { + RL.data().foldersListError( + oData && oData.ErrorCode ? Utils.getNotification(oData.ErrorCode) : Utils.i18n('NOTIFICATIONS/CANT_RENAME_FOLDER')); + } + + RL.folders(); + + }, oFolder.fullNameRaw, sEditName); + + RL.cache().removeFolderFromCacheList(oFolder.fullNameRaw); + + oFolder.name(sEditName); + } + + oFolder.edited(false); +}; + +SettingsFolders.prototype.folderEditOnEsc = function (oFolder) +{ + if (oFolder) + { + oFolder.edited(false); + } +}; + +SettingsFolders.prototype.onShow = function () +{ + RL.data().foldersListError(''); +}; + +SettingsFolders.prototype.createFolder = function () +{ + kn.showScreenPopup(PopupsFolderCreateViewModel); +}; + +SettingsFolders.prototype.systemFolder = function () +{ + kn.showScreenPopup(PopupsFolderSystemViewModel); +}; + +SettingsFolders.prototype.deleteFolder = function (oFolderToRemove) +{ + if (oFolderToRemove && oFolderToRemove.canBeDeleted() && oFolderToRemove.deleteAccess() && + 0 === oFolderToRemove.privateMessageCountAll()) + { + this.folderForDeletion(null); + + var + fRemoveFolder = function (oFolder) { + + if (oFolderToRemove === oFolder) + { + return true; + } + + oFolder.subFolders.remove(fRemoveFolder); + return false; + } + ; + + if (oFolderToRemove) + { + RL.local().set(Enums.ClientSideKeyName.FoldersLashHash, ''); + + RL.data().folderList.remove(fRemoveFolder); + + RL.data().foldersDeleting(true); + RL.remote().folderDelete(function (sResult, oData) { + + RL.data().foldersDeleting(false); + if (Enums.StorageResultType.Success !== sResult || !oData || !oData.Result) + { + RL.data().foldersListError( + oData && oData.ErrorCode ? Utils.getNotification(oData.ErrorCode) : Utils.i18n('NOTIFICATIONS/CANT_DELETE_FOLDER')); + } + + RL.folders(); + + }, oFolderToRemove.fullNameRaw); + + RL.cache().removeFolderFromCacheList(oFolderToRemove.fullNameRaw); + } + } + else if (0 < oFolderToRemove.privateMessageCountAll()) + { + RL.data().foldersListError(Utils.getNotification(Enums.Notification.CantDeleteNonEmptyFolder)); + } +}; + +SettingsFolders.prototype.subscribeFolder = function (oFolder) +{ + RL.local().set(Enums.ClientSideKeyName.FoldersLashHash, ''); + RL.remote().folderSetSubscribe(Utils.emptyFunction, oFolder.fullNameRaw, true); + + oFolder.subScribed(true); +}; + +SettingsFolders.prototype.unSubscribeFolder = function (oFolder) +{ + RL.local().set(Enums.ClientSideKeyName.FoldersLashHash, ''); + RL.remote().folderSetSubscribe(Utils.emptyFunction, oFolder.fullNameRaw, false); + + oFolder.subScribed(false); +}; + +/** + * @constructor + */ +function SettingsThemes() +{ + var + self = this, + oData = RL.data() + ; + + this.mainTheme = oData.mainTheme; + this.themesObjects = ko.observableArray([]); + + this.themeTrigger = ko.observable(Enums.SaveSettingsStep.Idle).extend({'throttle': 100}); + + this.oLastAjax = null; + this.iTimer = 0; + + RL.data().theme.subscribe(function (sValue) { + + _.each(this.themesObjects(), function (oTheme) { + oTheme.selected(sValue === oTheme.name); + }); + + var + oThemeLink = $('#rlThemeLink'), + oThemeStyle = $('#rlThemeStyle'), + sUrl = oThemeLink.attr('href') + ; + + if (!sUrl) + { + sUrl = oThemeStyle.attr('data-href'); + } + + if (sUrl) + { + sUrl = sUrl.toString().replace(/\/-\/[^\/]+\/\-\//, '/-/' + sValue + '/-/'); + sUrl = sUrl.toString().replace(/\/Css\/[^\/]+\/User\//, '/Css/0/User/'); + + if ('Json/' !== sUrl.substring(sUrl.length - 5, sUrl.length)) + { + sUrl += 'Json/'; + } + + window.clearTimeout(self.iTimer); + self.themeTrigger(Enums.SaveSettingsStep.Animate); + + if (this.oLastAjax && this.oLastAjax.abort) + { + this.oLastAjax.abort(); + } + + this.oLastAjax = $.ajax({ + 'url': sUrl, + 'dataType': 'json' + }).done(function(aData) { + if (aData && Utils.isArray(aData) && 2 === aData.length) + { + if (oThemeLink && oThemeLink[0] && (!oThemeStyle || !oThemeStyle[0])) + { + oThemeStyle = $(''); + oThemeLink.after(oThemeStyle); + oThemeLink.remove(); + } + + if (oThemeStyle && oThemeStyle[0]) + { + oThemeStyle.attr('data-href', sUrl).attr('data-theme', aData[0]); + if (oThemeStyle && oThemeStyle[0] && oThemeStyle[0].styleSheet && !Utils.isUnd(oThemeStyle[0].styleSheet.cssText)) + { + oThemeStyle[0].styleSheet.cssText = aData[1]; + } + else + { + oThemeStyle.text(aData[1]); + } + } + + self.themeTrigger(Enums.SaveSettingsStep.TrueResult); + } + + }).always(function() { + + self.iTimer = window.setTimeout(function () { + self.themeTrigger(Enums.SaveSettingsStep.Idle); + }, 1000); + + self.oLastAjax = null; + }); + } + + RL.remote().saveSettings(null, { + 'Theme': sValue + }); + + }, this); +} + +Utils.addSettingsViewModel(SettingsThemes, 'SettingsThemes', 'SETTINGS_LABELS/LABEL_THEMES_NAME', 'themes'); + +SettingsThemes.prototype.onBuild = function () +{ + var sCurrentTheme = RL.data().theme(); + this.themesObjects(_.map(RL.data().themes(), function (sTheme) { + return { + 'name': sTheme, + 'nameDisplay': Utils.convertThemeName(sTheme), + 'selected': ko.observable(sTheme === sCurrentTheme), + 'themePreviewSrc': RL.link().themePreviewLink(sTheme) + }; + })); +}; + +/** + * @constructor + */ +function SettingsOpenPGP() +{ + this.openpgpkeys = RL.data().openpgpkeys; + this.openpgpkeysPublic = RL.data().openpgpkeysPublic; + this.openpgpkeysPrivate = RL.data().openpgpkeysPrivate; + + this.openPgpKeyForDeletion = ko.observable(null).extend({'falseTimeout': 3000}).extend({'toggleSubscribe': [this, + function (oPrev) { + if (oPrev) + { + oPrev.deleteAccess(false); + } + }, function (oNext) { + if (oNext) + { + oNext.deleteAccess(true); + } + } + ]}); +} + +Utils.addSettingsViewModel(SettingsOpenPGP, 'SettingsOpenPGP', 'SETTINGS_LABELS/LABEL_OPEN_PGP_NAME', 'openpgp'); + +SettingsOpenPGP.prototype.addOpenPgpKey = function () +{ + kn.showScreenPopup(PopupsAddOpenPgpKeyViewModel); +}; + +SettingsOpenPGP.prototype.generateOpenPgpKey = function () +{ + kn.showScreenPopup(PopupsGenerateNewOpenPgpKeyViewModel); +}; + +SettingsOpenPGP.prototype.viewOpenPgpKey = function (oOpenPgpKey) +{ + if (oOpenPgpKey) + { + kn.showScreenPopup(PopupsViewOpenPgpKeyViewModel, [oOpenPgpKey]); + } +}; + +/** + * @param {OpenPgpKeyModel} oOpenPgpKeyToRemove + */ +SettingsOpenPGP.prototype.deleteOpenPgpKey = function (oOpenPgpKeyToRemove) +{ + if (oOpenPgpKeyToRemove && oOpenPgpKeyToRemove.deleteAccess()) + { + this.openPgpKeyForDeletion(null); + + if (oOpenPgpKeyToRemove && RL.data().openpgpKeyring) + { + this.openpgpkeys.remove(function (oOpenPgpKey) { + return oOpenPgpKeyToRemove === oOpenPgpKey; + }); + + RL.data().openpgpKeyring[oOpenPgpKeyToRemove.isPrivate ? 'privateKeys' : 'publicKeys'] + .removeForId(oOpenPgpKeyToRemove.guid); + + RL.data().openpgpKeyring.store(); + + RL.reloadOpenPgpKeys(); + } + } +}; +/** + * @constructor + */ +function AbstractData() +{ + this.leftPanelDisabled = ko.observable(false); + this.useKeyboardShortcuts = ko.observable(true); + + this.keyScopeReal = ko.observable(Enums.KeyState.All); + this.keyScopeFake = ko.observable(Enums.KeyState.All); + + this.keyScope = ko.computed({ + 'owner': this, + 'read': function () { + return this.keyScopeFake(); + }, + 'write': function (sValue) { + + if (Enums.KeyState.Menu !== sValue) + { + if (Enums.KeyState.Compose === sValue) + { + Utils.disableKeyFilter(); + } + else + { + Utils.restoreKeyFilter(); + } + + this.keyScopeFake(sValue); + if (Globals.dropdownVisibility()) + { + sValue = Enums.KeyState.Menu; + } + } + + this.keyScopeReal(sValue); + } + }); + + this.keyScopeReal.subscribe(function (sValue) { +// window.console.log(sValue); + key.setScope(sValue); + }); + + this.leftPanelDisabled.subscribe(function (bValue) { + RL.pub('left-panel.' + (bValue ? 'off' : 'on')); + }); + + Globals.dropdownVisibility.subscribe(function (bValue) { + if (bValue) + { + this.keyScope(Enums.KeyState.Menu); + } + else if (Enums.KeyState.Menu === key.getScope()) + { + this.keyScope(this.keyScopeFake()); + } + }, this); + + Utils.initDataConstructorBySettings(this); +} + +AbstractData.prototype.populateDataOnStart = function() +{ + var + mLayout = Utils.pInt(RL.settingsGet('Layout')), + aLanguages = RL.settingsGet('Languages'), + aThemes = RL.settingsGet('Themes') + ; + + if (Utils.isArray(aLanguages)) + { + this.languages(aLanguages); + } + + if (Utils.isArray(aThemes)) + { + this.themes(aThemes); + } + + this.mainLanguage(RL.settingsGet('Language')); + this.mainTheme(RL.settingsGet('Theme')); + + this.allowAdditionalAccounts(!!RL.settingsGet('AllowAdditionalAccounts')); + this.allowIdentities(!!RL.settingsGet('AllowIdentities')); + this.allowGravatar(!!RL.settingsGet('AllowGravatar')); + this.determineUserLanguage(!!RL.settingsGet('DetermineUserLanguage')); + + this.allowThemes(!!RL.settingsGet('AllowThemes')); + this.allowCustomLogin(!!RL.settingsGet('AllowCustomLogin')); + this.allowLanguagesOnLogin(!!RL.settingsGet('AllowLanguagesOnLogin')); + this.allowLanguagesOnSettings(!!RL.settingsGet('AllowLanguagesOnSettings')); + + this.editorDefaultType(RL.settingsGet('EditorDefaultType')); + this.showImages(!!RL.settingsGet('ShowImages')); + this.contactsAutosave(!!RL.settingsGet('ContactsAutosave')); + this.interfaceAnimation(RL.settingsGet('InterfaceAnimation')); + + this.mainMessagesPerPage(RL.settingsGet('MPP')); + + this.desktopNotifications(!!RL.settingsGet('DesktopNotifications')); + this.useThreads(!!RL.settingsGet('UseThreads')); + this.replySameFolder(!!RL.settingsGet('ReplySameFolder')); + this.useCheckboxesInList(!!RL.settingsGet('UseCheckboxesInList')); + + this.layout(Enums.Layout.SidePreview); + if (-1 < Utils.inArray(mLayout, [Enums.Layout.NoPreview, Enums.Layout.SidePreview, Enums.Layout.BottomPreview])) + { + this.layout(mLayout); + } + + this.facebookEnable(!!RL.settingsGet('AllowFacebookSocial')); + this.facebookAppID(RL.settingsGet('FacebookAppID')); + this.facebookAppSecret(RL.settingsGet('FacebookAppSecret')); + + this.twitterEnable(!!RL.settingsGet('AllowTwitterSocial')); + this.twitterConsumerKey(RL.settingsGet('TwitterConsumerKey')); + this.twitterConsumerSecret(RL.settingsGet('TwitterConsumerSecret')); + + this.googleEnable(!!RL.settingsGet('AllowGoogleSocial')); + this.googleClientID(RL.settingsGet('GoogleClientID')); + this.googleClientSecret(RL.settingsGet('GoogleClientSecret')); + + this.dropboxEnable(!!RL.settingsGet('AllowDropboxSocial')); + this.dropboxApiKey(RL.settingsGet('DropboxApiKey')); + + this.contactsIsAllowed(!!RL.settingsGet('ContactsIsAllowed')); +}; + +/** + * @constructor + * @extends AbstractData + */ +function WebMailDataStorage() +{ + AbstractData.call(this); + + var + fRemoveSystemFolderType = function (observable) { + return function () { + var oFolder = RL.cache().getFolderFromCacheList(observable()); + if (oFolder) + { + oFolder.type(Enums.FolderType.User); + } + }; + }, + fSetSystemFolderType = function (iType) { + return function (sValue) { + var oFolder = RL.cache().getFolderFromCacheList(sValue); + if (oFolder) + { + oFolder.type(iType); + } + }; + } + ; + + this.devEmail = ''; + this.devLogin = ''; + this.devPassword = ''; + + this.accountEmail = ko.observable(''); + this.accountIncLogin = ko.observable(''); + this.accountOutLogin = ko.observable(''); + this.projectHash = ko.observable(''); + this.threading = ko.observable(false); + + this.lastFoldersHash = ''; + this.remoteSuggestions = false; + + // system folders + this.sentFolder = ko.observable(''); + this.draftFolder = ko.observable(''); + this.spamFolder = ko.observable(''); + this.trashFolder = ko.observable(''); + this.archiveFolder = ko.observable(''); + + this.sentFolder.subscribe(fRemoveSystemFolderType(this.sentFolder), this, 'beforeChange'); + this.draftFolder.subscribe(fRemoveSystemFolderType(this.draftFolder), this, 'beforeChange'); + this.spamFolder.subscribe(fRemoveSystemFolderType(this.spamFolder), this, 'beforeChange'); + this.trashFolder.subscribe(fRemoveSystemFolderType(this.trashFolder), this, 'beforeChange'); + this.archiveFolder.subscribe(fRemoveSystemFolderType(this.archiveFolder), this, 'beforeChange'); + + this.sentFolder.subscribe(fSetSystemFolderType(Enums.FolderType.SentItems), this); + this.draftFolder.subscribe(fSetSystemFolderType(Enums.FolderType.Draft), this); + this.spamFolder.subscribe(fSetSystemFolderType(Enums.FolderType.Spam), this); + this.trashFolder.subscribe(fSetSystemFolderType(Enums.FolderType.Trash), this); + this.archiveFolder.subscribe(fSetSystemFolderType(Enums.FolderType.Archive), this); + + this.draftFolderNotEnabled = ko.computed(function () { + return '' === this.draftFolder() || Consts.Values.UnuseOptionValue === this.draftFolder(); + }, this); + + // personal + this.displayName = ko.observable(''); + this.signature = ko.observable(''); + this.signatureToAll = ko.observable(false); + this.replyTo = ko.observable(''); + + // security + this.enableTwoFactor = ko.observable(false); + + // accounts + this.accounts = ko.observableArray([]); + this.accountsLoading = ko.observable(false).extend({'throttle': 100}); + + // identities + this.identities = ko.observableArray([]); + this.identitiesLoading = ko.observable(false).extend({'throttle': 100}); + + // contacts + this.contacts = ko.observableArray([]); + this.contacts.loading = ko.observable(false).extend({'throttle': 200}); + this.contacts.importing = ko.observable(false).extend({'throttle': 200}); + this.contacts.syncing = ko.observable(false).extend({'throttle': 200}); + this.contacts.exportingVcf = ko.observable(false).extend({'throttle': 200}); + this.contacts.exportingCsv = ko.observable(false).extend({'throttle': 200}); + + this.allowContactsSync = ko.observable(false); + this.enableContactsSync = ko.observable(false); + this.contactsSyncUrl = ko.observable(''); + this.contactsSyncUser = ko.observable(''); + this.contactsSyncPass = ko.observable(''); + + this.allowContactsSync = ko.observable(!!RL.settingsGet('ContactsSyncIsAllowed')); + this.enableContactsSync = ko.observable(!!RL.settingsGet('EnableContactsSync')); + this.contactsSyncUrl = ko.observable(RL.settingsGet('ContactsSyncUrl')); + this.contactsSyncUser = ko.observable(RL.settingsGet('ContactsSyncUser')); + this.contactsSyncPass = ko.observable(RL.settingsGet('ContactsSyncPassword')); + + // folders + this.namespace = ''; + this.folderList = ko.observableArray([]); + this.folderList.focused = ko.observable(false); + + this.foldersListError = ko.observable(''); + + this.foldersLoading = ko.observable(false); + this.foldersCreating = ko.observable(false); + this.foldersDeleting = ko.observable(false); + this.foldersRenaming = ko.observable(false); + + this.foldersChanging = ko.computed(function () { + var + bLoading = this.foldersLoading(), + bCreating = this.foldersCreating(), + bDeleting = this.foldersDeleting(), + bRenaming = this.foldersRenaming() + ; + return bLoading || bCreating || bDeleting || bRenaming; + }, this); + + this.foldersInboxUnreadCount = ko.observable(0); + + this.currentFolder = ko.observable(null).extend({'toggleSubscribe': [null, + function (oPrev) { + if (oPrev) + { + oPrev.selected(false); + } + }, function (oNext) { + if (oNext) + { + oNext.selected(true); + } + } + ]}); + + this.currentFolderFullNameRaw = ko.computed(function () { + return this.currentFolder() ? this.currentFolder().fullNameRaw : ''; + }, this); + + this.currentFolderFullName = ko.computed(function () { + return this.currentFolder() ? this.currentFolder().fullName : ''; + }, this); + + this.currentFolderFullNameHash = ko.computed(function () { + return this.currentFolder() ? this.currentFolder().fullNameHash : ''; + }, this); + + this.currentFolderName = ko.computed(function () { + return this.currentFolder() ? this.currentFolder().name() : ''; + }, this); + + this.folderListSystemNames = ko.computed(function () { + + var + aList = ['INBOX'], + aFolders = this.folderList(), + sSentFolder = this.sentFolder(), + sDraftFolder = this.draftFolder(), + sSpamFolder = this.spamFolder(), + sTrashFolder = this.trashFolder(), + sArchiveFolder = this.archiveFolder() + ; + + if (Utils.isArray(aFolders) && 0 < aFolders.length) + { + if ('' !== sSentFolder && Consts.Values.UnuseOptionValue !== sSentFolder) + { + aList.push(sSentFolder); + } + if ('' !== sDraftFolder && Consts.Values.UnuseOptionValue !== sDraftFolder) + { + aList.push(sDraftFolder); + } + if ('' !== sSpamFolder && Consts.Values.UnuseOptionValue !== sSpamFolder) + { + aList.push(sSpamFolder); + } + if ('' !== sTrashFolder && Consts.Values.UnuseOptionValue !== sTrashFolder) + { + aList.push(sTrashFolder); + } + if ('' !== sArchiveFolder && Consts.Values.UnuseOptionValue !== sArchiveFolder) + { + aList.push(sArchiveFolder); + } + } + + return aList; + + }, this); + + this.folderListSystem = ko.computed(function () { + return _.compact(_.map(this.folderListSystemNames(), function (sName) { + return RL.cache().getFolderFromCacheList(sName); + })); + }, this); + + this.folderMenuForMove = ko.computed(function () { + return RL.folderListOptionsBuilder(this.folderListSystem(), this.folderList(), [ + this.currentFolderFullNameRaw() + ], null, null, null, null, function (oItem) { + return oItem ? oItem.localName() : ''; + }); + }, this); + + // message list + this.staticMessageList = []; + + this.messageList = ko.observableArray([]).extend({'rateLimit': 0}); + + this.messageListCount = ko.observable(0); + this.messageListSearch = ko.observable(''); + this.messageListPage = ko.observable(1); + + this.messageListThreadFolder = ko.observable(''); + this.messageListThreadUids = ko.observableArray([]); + + this.messageListThreadFolder.subscribe(function () { + this.messageListThreadUids([]); + }, this); + + this.messageListEndFolder = ko.observable(''); + this.messageListEndSearch = ko.observable(''); + this.messageListEndPage = ko.observable(1); + + this.messageListEndHash = ko.computed(function () { + return this.messageListEndFolder() + '|' + this.messageListEndSearch() + '|' + this.messageListEndPage(); + }, this); + + this.messageListPageCount = ko.computed(function () { + var iPage = Math.ceil(this.messageListCount() / this.messagesPerPage()); + return 0 >= iPage ? 1 : iPage; + }, this); + + this.mainMessageListSearch = ko.computed({ + 'read': this.messageListSearch, + 'write': function (sValue) { + kn.setHash(RL.link().mailBox( + this.currentFolderFullNameHash(), 1, Utils.trim(sValue.toString()) + )); + }, + 'owner': this + }); + + this.messageListError = ko.observable(''); + + this.messageListLoading = ko.observable(false); + this.messageListIsNotCompleted = ko.observable(false); + this.messageListCompleteLoadingThrottle = ko.observable(false).extend({'throttle': 200}); + + this.messageListCompleteLoading = ko.computed(function () { + var + bOne = this.messageListLoading(), + bTwo = this.messageListIsNotCompleted() + ; + return bOne || bTwo; + }, this); + + this.messageListCompleteLoading.subscribe(function (bValue) { + this.messageListCompleteLoadingThrottle(bValue); + }, this); + + this.messageList.subscribe(_.debounce(function (aList) { + _.each(aList, function (oItem) { + if (oItem.newForAnimation()) + { + oItem.newForAnimation(false); + } + }); + }, 500)); + + // message preview + this.staticMessageList = new MessageModel(); + this.message = ko.observable(null); + this.messageLoading = ko.observable(false); + this.messageLoadingThrottle = ko.observable(false).extend({'throttle': 50}); + + this.message.focused = ko.observable(false); + + this.message.subscribe(function (oMessage) { + if (!oMessage) + { + this.message.focused(false); + this.hideMessageBodies(); + + if (Enums.Layout.NoPreview === RL.data().layout() && + -1 < window.location.hash.indexOf('message-preview')) + { + RL.historyBack(); + } + } + else if (Enums.Layout.NoPreview === this.layout()) + { + this.message.focused(true); + } + }, this); + + this.message.focused.subscribe(function (bValue) { + if (bValue) + { + RL.data().folderList.focused(false); + RL.data().keyScope(Enums.KeyState.MessageView); + } + else if (Enums.KeyState.MessageView === RL.data().keyScope()) + { + RL.data().keyScope(Enums.KeyState.MessageList); + } + }); + + this.folderList.focused.subscribe(function (bValue) { + if (bValue) + { + RL.data().keyScope(Enums.KeyState.FolderList); + } + else if (Enums.KeyState.FolderList === RL.data().keyScope()) + { + RL.data().keyScope(Enums.KeyState.MessageList); + } + }); + + this.messageLoading.subscribe(function (bValue) { + this.messageLoadingThrottle(bValue); + }, this); + + this.messageFullScreenMode = ko.observable(false); + + this.messageError = ko.observable(''); + + this.messagesBodiesDom = ko.observable(null); + + this.messagesBodiesDom.subscribe(function (oDom) { + if (oDom && !(oDom instanceof jQuery)) + { + this.messagesBodiesDom($(oDom)); + } + }, this); + + this.messageActiveDom = ko.observable(null); + + this.isMessageSelected = ko.computed(function () { + return null !== this.message(); + }, this); + + this.currentMessage = ko.observable(null); + + this.messageListChecked = ko.computed(function () { + return _.filter(this.messageList(), function (oItem) { + return oItem.checked(); + }); + }, this).extend({'rateLimit': 0}); + + this.hasCheckedMessages = ko.computed(function () { + return 0 < this.messageListChecked().length; + }, this).extend({'rateLimit': 0}); + + this.messageListCheckedOrSelected = ko.computed(function () { + + var + aChecked = this.messageListChecked(), + oSelectedMessage = this.currentMessage() + ; + + return _.union(aChecked, oSelectedMessage ? [oSelectedMessage] : []); + + }, this); + + this.messageListCheckedOrSelectedUidsWithSubMails = ko.computed(function () { + var aList = []; + _.each(this.messageListCheckedOrSelected(), function (oMessage) { + if (oMessage) + { + aList.push(oMessage.uid); + if (0 < oMessage.threadsLen() && 0 === oMessage.parentUid() && oMessage.lastInCollapsedThread()) + { + aList = _.union(aList, oMessage.threads()); + } + } + }); + return aList; + }, this); + + // quota + this.userQuota = ko.observable(0); + this.userUsageSize = ko.observable(0); + this.userUsageProc = ko.computed(function () { + + var + iQuota = this.userQuota(), + iUsed = this.userUsageSize() + ; + + return 0 < iQuota ? Math.ceil((iUsed / iQuota) * 100) : 0; + + }, this); + + // other + this.allowOpenPGP = ko.observable(false); + this.openpgpkeys = ko.observableArray([]); + this.openpgpKeyring = null; + + this.openpgpkeysPublic = this.openpgpkeys.filter(function (oItem) { + return !!(oItem && !oItem.isPrivate); + }); + + this.openpgpkeysPrivate = this.openpgpkeys.filter(function (oItem) { + return !!(oItem && oItem.isPrivate); + }); + + // google + this.googleActions = ko.observable(false); + this.googleLoggined = ko.observable(false); + this.googleUserName = ko.observable(''); + + // facebook + this.facebookActions = ko.observable(false); + this.facebookLoggined = ko.observable(false); + this.facebookUserName = ko.observable(''); + + // twitter + this.twitterActions = ko.observable(false); + this.twitterLoggined = ko.observable(false); + this.twitterUserName = ko.observable(''); + + this.customThemeType = ko.observable(Enums.CustomThemeType.Light); + + this.purgeMessageBodyCacheThrottle = _.throttle(this.purgeMessageBodyCache, 1000 * 30); +} + +_.extend(WebMailDataStorage.prototype, AbstractData.prototype); + +WebMailDataStorage.prototype.purgeMessageBodyCache = function() +{ + var + iCount = 0, + oMessagesBodiesDom = null, + iEnd = Globals.iMessageBodyCacheCount - Consts.Values.MessageBodyCacheLimit + ; + + if (0 < iEnd) + { + oMessagesBodiesDom = this.messagesBodiesDom(); + if (oMessagesBodiesDom) + { + oMessagesBodiesDom.find('.rl-cache-class').each(function () { + var oItem = $(this); + if (iEnd > oItem.data('rl-cache-count')) + { + oItem.addClass('rl-cache-purge'); + iCount++; + } + }); + + if (0 < iCount) + { + _.delay(function () { + oMessagesBodiesDom.find('.rl-cache-purge').remove(); + }, 300); + } + } + } +}; + +WebMailDataStorage.prototype.populateDataOnStart = function() +{ + AbstractData.prototype.populateDataOnStart.call(this); + + this.accountEmail(RL.settingsGet('Email')); + this.accountIncLogin(RL.settingsGet('IncLogin')); + this.accountOutLogin(RL.settingsGet('OutLogin')); + this.projectHash(RL.settingsGet('ProjectHash')); + + this.displayName(RL.settingsGet('DisplayName')); + this.replyTo(RL.settingsGet('ReplyTo')); + this.signature(RL.settingsGet('Signature')); + this.signatureToAll(!!RL.settingsGet('SignatureToAll')); + this.enableTwoFactor(!!RL.settingsGet('EnableTwoFactor')); + + this.lastFoldersHash = RL.local().get(Enums.ClientSideKeyName.FoldersLashHash) || ''; + + this.remoteSuggestions = !!RL.settingsGet('RemoteSuggestions'); + + this.devEmail = RL.settingsGet('DevEmail'); + this.devLogin = RL.settingsGet('DevLogin'); + this.devPassword = RL.settingsGet('DevPassword'); +}; + +WebMailDataStorage.prototype.initUidNextAndNewMessages = function (sFolder, sUidNext, aNewMessages) +{ + if ('INBOX' === sFolder && Utils.isNormal(sUidNext) && sUidNext !== '') + { + if (Utils.isArray(aNewMessages) && 0 < aNewMessages.length) + { + var + oCache = RL.cache(), + iIndex = 0, + iLen = aNewMessages.length, + fNotificationHelper = function (sImageSrc, sTitle, sText) + { + var oNotification = null; + if (NotificationClass && RL.data().useDesktopNotifications()) + { + oNotification = new NotificationClass(sTitle, { + 'body': sText, + 'icon': sImageSrc + }); + + if (oNotification) + { + if (oNotification.show) + { + oNotification.show(); + } + + window.setTimeout((function (oLocalNotifications) { + return function () { + if (oLocalNotifications.cancel) + { + oLocalNotifications.cancel(); + } + else if (oLocalNotifications.close) + { + oLocalNotifications.close(); + } + }; + }(oNotification)), 7000); + } + } + } + ; + + _.each(aNewMessages, function (oItem) { + oCache.addNewMessageCache(sFolder, oItem.Uid); + }); + + if (3 < iLen) + { + fNotificationHelper( + RL.link().notificationMailIcon(), + RL.data().accountEmail(), + Utils.i18n('MESSAGE_LIST/NEW_MESSAGE_NOTIFICATION', { + 'COUNT': iLen + }) + ); + } + else + { + for (; iIndex < iLen; iIndex++) + { + fNotificationHelper( + RL.link().notificationMailIcon(), + MessageModel.emailsToLine(MessageModel.initEmailsFromJson(aNewMessages[iIndex].From), false), + aNewMessages[iIndex].Subject + ); + } + } + } + + RL.cache().setFolderUidNext(sFolder, sUidNext); + } +}; + +/** + * @param {string} sNamespace + * @param {Array} aFolders + * @return {Array} + */ +WebMailDataStorage.prototype.folderResponseParseRec = function (sNamespace, aFolders) +{ + var + iIndex = 0, + iLen = 0, + oFolder = null, + oCacheFolder = null, + sFolderFullNameRaw = '', + aSubFolders = [], + aList = [] + ; + + for (iIndex = 0, iLen = aFolders.length; iIndex < iLen; iIndex++) + { + oFolder = aFolders[iIndex]; + if (oFolder) + { + sFolderFullNameRaw = oFolder.FullNameRaw; + + oCacheFolder = RL.cache().getFolderFromCacheList(sFolderFullNameRaw); + if (!oCacheFolder) + { + oCacheFolder = FolderModel.newInstanceFromJson(oFolder); + if (oCacheFolder) + { + RL.cache().setFolderToCacheList(sFolderFullNameRaw, oCacheFolder); + RL.cache().setFolderFullNameRaw(oCacheFolder.fullNameHash, sFolderFullNameRaw); + } + } + + if (oCacheFolder) + { + oCacheFolder.collapsed(!Utils.isFolderExpanded(oCacheFolder.fullNameHash)); + + if (oFolder.Extended) + { + if (oFolder.Extended.Hash) + { + RL.cache().setFolderHash(oCacheFolder.fullNameRaw, oFolder.Extended.Hash); + } + + if (Utils.isNormal(oFolder.Extended.MessageCount)) + { + oCacheFolder.messageCountAll(oFolder.Extended.MessageCount); + } + + if (Utils.isNormal(oFolder.Extended.MessageUnseenCount)) + { + oCacheFolder.messageCountUnread(oFolder.Extended.MessageUnseenCount); + } + } + + aSubFolders = oFolder['SubFolders']; + if (aSubFolders && 'Collection/FolderCollection' === aSubFolders['@Object'] && + aSubFolders['@Collection'] && Utils.isArray(aSubFolders['@Collection'])) + { + oCacheFolder.subFolders( + this.folderResponseParseRec(sNamespace, aSubFolders['@Collection'])); + } + + aList.push(oCacheFolder); + } + } + } + + return aList; +}; + +/** + * @param {*} oData + */ +WebMailDataStorage.prototype.setFolders = function (oData) +{ + var + aList = [], + bUpdate = false, + oRLData = RL.data(), + fNormalizeFolder = function (sFolderFullNameRaw) { + return ('' === sFolderFullNameRaw || Consts.Values.UnuseOptionValue === sFolderFullNameRaw || + null !== RL.cache().getFolderFromCacheList(sFolderFullNameRaw)) ? sFolderFullNameRaw : ''; + } + ; + + if (oData && oData.Result && 'Collection/FolderCollection' === oData.Result['@Object'] && + oData.Result['@Collection'] && Utils.isArray(oData.Result['@Collection'])) + { + if (!Utils.isUnd(oData.Result.Namespace)) + { + oRLData.namespace = oData.Result.Namespace; + } + + this.threading(!!RL.settingsGet('UseImapThread') && oData.Result.IsThreadsSupported && true); + + aList = this.folderResponseParseRec(oRLData.namespace, oData.Result['@Collection']); + oRLData.folderList(aList); + + if (oData.Result['SystemFolders'] && + '' === '' + RL.settingsGet('SentFolder') + RL.settingsGet('DraftFolder') + + RL.settingsGet('SpamFolder') + RL.settingsGet('TrashFolder') + RL.settingsGet('ArchiveFolder') + + RL.settingsGet('NullFolder')) + { + // TODO Magic Numbers + RL.settingsSet('SentFolder', oData.Result['SystemFolders'][2] || null); + RL.settingsSet('DraftFolder', oData.Result['SystemFolders'][3] || null); + RL.settingsSet('SpamFolder', oData.Result['SystemFolders'][4] || null); + RL.settingsSet('TrashFolder', oData.Result['SystemFolders'][5] || null); + RL.settingsSet('ArchiveFolder', oData.Result['SystemFolders'][12] || null); + + bUpdate = true; + } + + oRLData.sentFolder(fNormalizeFolder(RL.settingsGet('SentFolder'))); + oRLData.draftFolder(fNormalizeFolder(RL.settingsGet('DraftFolder'))); + oRLData.spamFolder(fNormalizeFolder(RL.settingsGet('SpamFolder'))); + oRLData.trashFolder(fNormalizeFolder(RL.settingsGet('TrashFolder'))); + oRLData.archiveFolder(fNormalizeFolder(RL.settingsGet('ArchiveFolder'))); + + if (bUpdate) + { + RL.remote().saveSystemFolders(Utils.emptyFunction, { + 'SentFolder': oRLData.sentFolder(), + 'DraftFolder': oRLData.draftFolder(), + 'SpamFolder': oRLData.spamFolder(), + 'TrashFolder': oRLData.trashFolder(), + 'ArchiveFolder': oRLData.archiveFolder(), + 'NullFolder': 'NullFolder' + }); + } + + RL.local().set(Enums.ClientSideKeyName.FoldersLashHash, oData.Result.FoldersHash); + } +}; + +WebMailDataStorage.prototype.hideMessageBodies = function () +{ + var oMessagesBodiesDom = this.messagesBodiesDom(); + if (oMessagesBodiesDom) + { + oMessagesBodiesDom.find('.b-text-part').hide(); + } +}; + +/** + * @param {boolean=} bBoot = false + * @returns {Array} + */ +WebMailDataStorage.prototype.getNextFolderNames = function (bBoot) +{ + bBoot = Utils.isUnd(bBoot) ? false : !!bBoot; + + var + aResult = [], + iLimit = 10, + iUtc = moment().unix(), + iTimeout = iUtc - 60 * 5, + aTimeouts = [], + fSearchFunction = function (aList) { + _.each(aList, function (oFolder) { + if (oFolder && 'INBOX' !== oFolder.fullNameRaw && + oFolder.selectable && oFolder.existen && + iTimeout > oFolder.interval && + (!bBoot || oFolder.subScribed())) + { + aTimeouts.push([oFolder.interval, oFolder.fullNameRaw]); + } + + if (oFolder && 0 < oFolder.subFolders().length) + { + fSearchFunction(oFolder.subFolders()); + } + }); + } + ; + + fSearchFunction(this.folderList()); + + aTimeouts.sort(function(a, b) { + if (a[0] < b[0]) + { + return -1; + } + else if (a[0] > b[0]) + { + return 1; + } + + return 0; + }); + + _.find(aTimeouts, function (aItem) { + var oFolder = RL.cache().getFolderFromCacheList(aItem[1]); + if (oFolder) + { + oFolder.interval = iUtc; + aResult.push(aItem[1]); + } + + return iLimit <= aResult.length; + }); + + return _.uniq(aResult); +}; + +/** + * @param {string} sFromFolderFullNameRaw + * @param {Array} aUidForRemove + * @param {string=} sToFolderFullNameRaw = '' + * @param {bCopy=} bCopy = false + */ +WebMailDataStorage.prototype.removeMessagesFromList = function ( + sFromFolderFullNameRaw, aUidForRemove, sToFolderFullNameRaw, bCopy) +{ + sToFolderFullNameRaw = Utils.isNormal(sToFolderFullNameRaw) ? sToFolderFullNameRaw : ''; + bCopy = Utils.isUnd(bCopy) ? false : !!bCopy; + + aUidForRemove = _.map(aUidForRemove, function (mValue) { + return Utils.pInt(mValue); + }); + + var + iUnseenCount = 0, + oData = RL.data(), + oCache = RL.cache(), + aMessageList = oData.messageList(), + oFromFolder = RL.cache().getFolderFromCacheList(sFromFolderFullNameRaw), + oToFolder = '' === sToFolderFullNameRaw ? null : oCache.getFolderFromCacheList(sToFolderFullNameRaw || ''), + sCurrentFolderFullNameRaw = oData.currentFolderFullNameRaw(), + oCurrentMessage = oData.message(), + aMessages = sCurrentFolderFullNameRaw === sFromFolderFullNameRaw ? _.filter(aMessageList, function (oMessage) { + return oMessage && -1 < Utils.inArray(Utils.pInt(oMessage.uid), aUidForRemove); + }) : [] + ; + + _.each(aMessages, function (oMessage) { + if (oMessage && oMessage.unseen()) + { + iUnseenCount++; + } + }); + + if (oFromFolder && !bCopy) + { + oFromFolder.messageCountAll(0 <= oFromFolder.messageCountAll() - aUidForRemove.length ? + oFromFolder.messageCountAll() - aUidForRemove.length : 0); + + if (0 < iUnseenCount) + { + oFromFolder.messageCountUnread(0 <= oFromFolder.messageCountUnread() - iUnseenCount ? + oFromFolder.messageCountUnread() - iUnseenCount : 0); + } + } + + if (oToFolder) + { + oToFolder.messageCountAll(oToFolder.messageCountAll() + aUidForRemove.length); + if (0 < iUnseenCount) + { + oToFolder.messageCountUnread(oToFolder.messageCountUnread() + iUnseenCount); + } + + oToFolder.actionBlink(true); + } + + if (0 < aMessages.length) + { + if (bCopy) + { + _.each(aMessages, function (oMessage) { + oMessage.checked(false); + }); + } + else + { + oData.messageListIsNotCompleted(true); + + _.each(aMessages, function (oMessage) { + if (oCurrentMessage && oCurrentMessage.hash === oMessage.hash) + { + oCurrentMessage = null; + oData.message(null); + } + + oMessage.deleted(true); + }); + + _.delay(function () { + _.each(aMessages, function (oMessage) { + oData.messageList.remove(oMessage); + }); + }, 400); + } + } + + if ('' !== sFromFolderFullNameRaw) + { + oCache.setFolderHash(sFromFolderFullNameRaw, ''); + } + + if ('' !== sToFolderFullNameRaw) + { + oCache.setFolderHash(sToFolderFullNameRaw, ''); + } +}; + +WebMailDataStorage.prototype.setMessage = function (oData, bCached) +{ + var + bIsHtml = false, + bHasExternals = false, + bHasInternals = false, + oBody = null, + oTextBody = null, + sId = '', + sPlain = '', + bPgpSigned = false, + bPgpEncrypted = false, + oMessagesBodiesDom = this.messagesBodiesDom(), + oMessage = this.message() + ; + + if (oData && oMessage && oData.Result && 'Object/Message' === oData.Result['@Object'] && + oMessage.folderFullNameRaw === oData.Result.Folder && oMessage.uid === oData.Result.Uid) + { + this.messageError(''); + + oMessage.initUpdateByMessageJson(oData.Result); + RL.cache().addRequestedMessage(oMessage.folderFullNameRaw, oMessage.uid); + + if (!bCached) + { + oMessage.initFlagsByJson(oData.Result); + } + + oMessagesBodiesDom = oMessagesBodiesDom && oMessagesBodiesDom[0] ? oMessagesBodiesDom : null; + if (oMessagesBodiesDom) + { + sId = 'rl-mgs-' + oMessage.hash.replace(/[^a-zA-Z0-9]/g, ''); + oTextBody = oMessagesBodiesDom.find('#' + sId); + if (!oTextBody || !oTextBody[0]) + { + bHasExternals = !!oData.Result.HasExternals; + bHasInternals = !!oData.Result.HasInternals; + + oBody = $('').hide().addClass('rl-cache-class'); + oBody.data('rl-cache-count', ++Globals.iMessageBodyCacheCount); + + if (Utils.isNormal(oData.Result.Html) && '' !== oData.Result.Html) + { + bIsHtml = true; + oBody.html(oData.Result.Html.toString()).addClass('b-text-part html'); + } + else if (Utils.isNormal(oData.Result.Plain) && '' !== oData.Result.Plain) + { + bIsHtml = false; + sPlain = oData.Result.Plain.toString(); + + if ((oMessage.isPgpSigned() || oMessage.isPgpEncrypted()) && + RL.data().allowOpenPGP() && + Utils.isNormal(oData.Result.PlainRaw)) + { + oMessage.plainRaw = Utils.pString(oData.Result.PlainRaw); + + bPgpEncrypted = /---BEGIN PGP MESSAGE---/.test(oMessage.plainRaw); + if (!bPgpEncrypted) + { + bPgpSigned = /-----BEGIN PGP SIGNED MESSAGE-----/.test(oMessage.plainRaw) && + /-----BEGIN PGP SIGNATURE-----/.test(oMessage.plainRaw); + } + + $proxyDiv.empty(); + if (bPgpSigned && oMessage.isPgpSigned()) + { + sPlain = + $proxyDiv.append( + $('').text(oMessage.plainRaw) + ).html() + ; + } + else if (bPgpEncrypted && oMessage.isPgpEncrypted()) + { + sPlain = + $proxyDiv.append( + $('').text(oMessage.plainRaw) + ).html() + ; + } + + $proxyDiv.empty(); + + oMessage.isPgpSigned(bPgpSigned); + oMessage.isPgpEncrypted(bPgpEncrypted); + } + + oBody.html(sPlain).addClass('b-text-part plain'); + } + else + { + bIsHtml = false; + } + + oMessage.isHtml(!!bIsHtml); + oMessage.hasImages(!!bHasExternals); + oMessage.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.None); + oMessage.pgpSignedVerifyUser(''); + + if (oData.Result.Rtl) + { + oMessage.isRtl(true); + oBody.addClass('rtl-text-part'); + } + + oMessage.body = oBody; + if (oMessage.body) + { + oMessagesBodiesDom.append(oMessage.body); + } + + oMessage.storeDataToDom(); + + if (bHasInternals) + { + oMessage.showInternalImages(true); + } + + if (oMessage.hasImages() && this.showImages()) + { + oMessage.showExternalImages(true); + } + + this.purgeMessageBodyCacheThrottle(); + } + else + { + oMessage.body = oTextBody; + if (oMessage.body) + { + oMessage.body.data('rl-cache-count', ++Globals.iMessageBodyCacheCount); + oMessage.fetchDataToDom(); + } + } + + this.messageActiveDom(oMessage.body); + + this.hideMessageBodies(); + oMessage.body.show(); + + if (oBody) + { + Utils.initBlockquoteSwitcher(oBody); + } + } + + RL.cache().initMessageFlagsFromCache(oMessage); + if (oMessage.unseen()) + { + RL.setMessageSeen(oMessage); + } + + Utils.windowResize(); + } +}; + +/** + * @param {Array} aList + * @returns {string} + */ +WebMailDataStorage.prototype.calculateMessageListHash = function (aList) +{ + return _.map(aList, function (oMessage) { + return '' + oMessage.hash + '_' + oMessage.threadsLen() + '_' + oMessage.flagHash(); + }).join('|'); +}; + +WebMailDataStorage.prototype.setMessageList = function (oData, bCached) +{ + if (oData && oData.Result && 'Collection/MessageCollection' === oData.Result['@Object'] && + oData.Result['@Collection'] && Utils.isArray(oData.Result['@Collection'])) + { + var + oRainLoopData = RL.data(), + oCache = RL.cache(), + mLastCollapsedThreadUids = null, + iIndex = 0, + iLen = 0, + iCount = 0, + iOffset = 0, + aList = [], + iUtc = moment().unix(), + aStaticList = oRainLoopData.staticMessageList, + oJsonMessage = null, + oMessage = null, + oFolder = null, + iNewCount = 0, + bUnreadCountChange = false + ; + + iCount = Utils.pInt(oData.Result.MessageResultCount); + iOffset = Utils.pInt(oData.Result.Offset); + + if (Utils.isNonEmptyArray(oData.Result.LastCollapsedThreadUids)) + { + mLastCollapsedThreadUids = oData.Result.LastCollapsedThreadUids; + } + + oFolder = RL.cache().getFolderFromCacheList( + Utils.isNormal(oData.Result.Folder) ? oData.Result.Folder : ''); + + if (oFolder && !bCached) + { + oFolder.interval = iUtc; + + RL.cache().setFolderHash(oData.Result.Folder, oData.Result.FolderHash); + + if (Utils.isNormal(oData.Result.MessageCount)) + { + oFolder.messageCountAll(oData.Result.MessageCount); + } + + if (Utils.isNormal(oData.Result.MessageUnseenCount)) + { + if (Utils.pInt(oFolder.messageCountUnread()) !== Utils.pInt(oData.Result.MessageUnseenCount)) + { + bUnreadCountChange = true; + } + + oFolder.messageCountUnread(oData.Result.MessageUnseenCount); + } + + this.initUidNextAndNewMessages(oFolder.fullNameRaw, oData.Result.UidNext, oData.Result.NewMessages); + } + + if (bUnreadCountChange && oFolder) + { + RL.cache().clearMessageFlagsFromCacheByFolder(oFolder.fullNameRaw); + } + + for (iIndex = 0, iLen = oData.Result['@Collection'].length; iIndex < iLen; iIndex++) + { + oJsonMessage = oData.Result['@Collection'][iIndex]; + if (oJsonMessage && 'Object/Message' === oJsonMessage['@Object']) + { + oMessage = aStaticList[iIndex]; + if (!oMessage || !oMessage.initByJson(oJsonMessage)) + { + oMessage = MessageModel.newInstanceFromJson(oJsonMessage); + } + + if (oMessage) + { + if (oCache.hasNewMessageAndRemoveFromCache(oMessage.folderFullNameRaw, oMessage.uid) && 5 >= iNewCount) + { + iNewCount++; + oMessage.newForAnimation(true); + } + + oMessage.deleted(false); + + if (bCached) + { + RL.cache().initMessageFlagsFromCache(oMessage); + } + else + { + RL.cache().storeMessageFlagsToCache(oMessage); + } + + oMessage.lastInCollapsedThread(mLastCollapsedThreadUids && -1 < Utils.inArray(Utils.pInt(oMessage.uid), mLastCollapsedThreadUids) ? true : false); + + aList.push(oMessage); + } + } + } + + oRainLoopData.messageListCount(iCount); + oRainLoopData.messageListSearch(Utils.isNormal(oData.Result.Search) ? oData.Result.Search : ''); + oRainLoopData.messageListPage(Math.ceil((iOffset / oRainLoopData.messagesPerPage()) + 1)); + oRainLoopData.messageListEndFolder(Utils.isNormal(oData.Result.Folder) ? oData.Result.Folder : ''); + oRainLoopData.messageListEndSearch(Utils.isNormal(oData.Result.Search) ? oData.Result.Search : ''); + oRainLoopData.messageListEndPage(oRainLoopData.messageListPage()); + + oRainLoopData.messageList(aList); + oRainLoopData.messageListIsNotCompleted(false); + + if (aStaticList.length < aList.length) + { + oRainLoopData.staticMessageList = aList; + } + + oCache.clearNewMessageCache(); + + if (oFolder && (bCached || bUnreadCountChange || RL.data().useThreads())) + { + RL.folderInformation(oFolder.fullNameRaw, aList); + } + } + else + { + RL.data().messageListCount(0); + RL.data().messageList([]); + RL.data().messageListError(Utils.getNotification( + oData && oData.ErrorCode ? oData.ErrorCode : Enums.Notification.CantGetMessageList + )); + } +}; + +WebMailDataStorage.prototype.findPublicKeyByHex = function (sHash) +{ + return _.find(this.openpgpkeysPublic(), function (oItem) { + return oItem && sHash === oItem.id; + }); +}; + +WebMailDataStorage.prototype.findPublicKeysByEmail = function (sEmail) +{ + return _.compact(_.map(this.openpgpkeysPublic(), function (oItem) { + + var oKey = null; + if (oItem && sEmail === oItem.email) + { + try + { + oKey = window.openpgp.key.readArmored(oItem.armor); + if (oKey && !oKey.err && oKey.keys && oKey.keys[0]) + { + return oKey.keys[0]; + } + } + catch (e) {} + } + + return null; + + })); +}; + +/** + * @param {string} sEmail + * @param {string=} sPassword + * @returns {?} + */ +WebMailDataStorage.prototype.findPrivateKeyByEmail = function (sEmail, sPassword) +{ + var + oPrivateKey = null, + oKey = _.find(this.openpgpkeysPrivate(), function (oItem) { + return oItem && sEmail === oItem.email; + }) + ; + + if (oKey) + { + try + { + oPrivateKey = window.openpgp.key.readArmored(oKey.armor); + if (oPrivateKey && !oPrivateKey.err && oPrivateKey.keys && oPrivateKey.keys[0]) + { + oPrivateKey = oPrivateKey.keys[0]; + oPrivateKey.decrypt(Utils.pString(sPassword)); + } + else + { + oPrivateKey = null; + } + } + catch (e) + { + oPrivateKey = null; + } + } + + return oPrivateKey; +}; + +/** + * @param {string=} sPassword + * @returns {?} + */ +WebMailDataStorage.prototype.findSelfPrivateKey = function (sPassword) +{ + return this.findPrivateKeyByEmail(this.accountEmail(), sPassword); +}; + +/** + * @constructor + */ +function AbstractAjaxRemoteStorage() +{ + this.oRequests = {}; +} + +AbstractAjaxRemoteStorage.prototype.oRequests = {}; + +/** + * @param {?Function} fCallback + * @param {string} sRequestAction + * @param {string} sType + * @param {?AjaxJsonDefaultResponse} oData + * @param {boolean} bCached + * @param {*=} oRequestParameters + */ +AbstractAjaxRemoteStorage.prototype.defaultResponse = function (fCallback, sRequestAction, sType, oData, bCached, oRequestParameters) +{ + var + fCall = function () { + if (Enums.StorageResultType.Success !== sType && Globals.bUnload) + { + sType = Enums.StorageResultType.Unload; + } + + if (Enums.StorageResultType.Success === sType && oData && !oData.Result) + { + if (oData && -1 < Utils.inArray(oData.ErrorCode, [ + Enums.Notification.AuthError, Enums.Notification.AccessError, + Enums.Notification.ConnectionError, Enums.Notification.DomainNotAllowed, Enums.Notification.AccountNotAllowed, + Enums.Notification.MailServerError, Enums.Notification.UnknownNotification, Enums.Notification.UnknownError + ])) + { + Globals.iAjaxErrorCount++; + } + + if (oData && Enums.Notification.InvalidToken === oData.ErrorCode) + { + Globals.iTokenErrorCount++; + } + + if (Consts.Values.TokenErrorLimit < Globals.iTokenErrorCount) + { + RL.loginAndLogoutReload(true); + } + + if (oData.Logout || Consts.Values.AjaxErrorLimit < Globals.iAjaxErrorCount) + { + if (window.__rlah_clear) + { + window.__rlah_clear(); + } + + RL.loginAndLogoutReload(true); + } + } + else if (Enums.StorageResultType.Success === sType && oData && oData.Result) + { + Globals.iAjaxErrorCount = 0; + Globals.iTokenErrorCount = 0; + } + + if (fCallback) + { + Plugins.runHook('ajax-default-response', [sRequestAction, Enums.StorageResultType.Success === sType ? oData : null, sType, bCached, oRequestParameters]); + + fCallback( + sType, + Enums.StorageResultType.Success === sType ? oData : null, + bCached, + sRequestAction, + oRequestParameters + ); + } + } + ; + + switch (sType) + { + case 'success': + sType = Enums.StorageResultType.Success; + break; + case 'abort': + sType = Enums.StorageResultType.Abort; + break; + default: + sType = Enums.StorageResultType.Error; + break; + } + + if (Enums.StorageResultType.Error === sType) + { + _.delay(fCall, 300); + } + else + { + fCall(); + } +}; + +/** + * @param {?Function} fResultCallback + * @param {Object} oParameters + * @param {?number=} iTimeOut = 20000 + * @param {string=} sGetAdd = '' + * @param {Array=} aAbortActions = [] + * @return {jQuery.jqXHR} + */ +AbstractAjaxRemoteStorage.prototype.ajaxRequest = function (fResultCallback, oParameters, iTimeOut, sGetAdd, aAbortActions) +{ + var + self = this, + bPost = '' === sGetAdd, + oHeaders = {}, + iStart = (new window.Date()).getTime(), + oDefAjax = null, + sAction = '' + ; + + oParameters = oParameters || {}; + iTimeOut = Utils.isNormal(iTimeOut) ? iTimeOut : 20000; + sGetAdd = Utils.isUnd(sGetAdd) ? '' : Utils.pString(sGetAdd); + aAbortActions = Utils.isArray(aAbortActions) ? aAbortActions : []; + + sAction = oParameters.Action || ''; + + if (sAction && 0 < aAbortActions.length) + { + _.each(aAbortActions, function (sActionToAbort) { + if (self.oRequests[sActionToAbort]) + { + self.oRequests[sActionToAbort].__aborted = true; + if (self.oRequests[sActionToAbort].abort) + { + self.oRequests[sActionToAbort].abort(); + } + self.oRequests[sActionToAbort] = null; + } + }); + } + + if (bPost) + { + oParameters['XToken'] = RL.settingsGet('Token'); + } + + oDefAjax = $.ajax({ + 'type': bPost ? 'POST' : 'GET', + 'url': RL.link().ajax(sGetAdd) , + 'async': true, + 'dataType': 'json', + 'data': bPost ? oParameters : {}, + 'headers': oHeaders, + 'timeout': iTimeOut, + 'global': true + }); + + oDefAjax.always(function (oData, sType) { + + var bCached = false; + if (oData && oData['Time']) + { + bCached = Utils.pInt(oData['Time']) > (new window.Date()).getTime() - iStart; + } + + if (sAction && self.oRequests[sAction]) + { + if (self.oRequests[sAction].__aborted) + { + sType = 'abort'; + } + + self.oRequests[sAction] = null; + } + + self.defaultResponse(fResultCallback, sAction, sType, oData, bCached, oParameters); + }); + + if (sAction && 0 < aAbortActions.length && -1 < Utils.inArray(sAction, aAbortActions)) + { + if (this.oRequests[sAction]) + { + this.oRequests[sAction].__aborted = true; + if (this.oRequests[sAction].abort) + { + this.oRequests[sAction].abort(); + } + this.oRequests[sAction] = null; + } + + this.oRequests[sAction] = oDefAjax; + } + + return oDefAjax; +}; + +/** + * @param {?Function} fCallback + * @param {string} sAction + * @param {Object=} oParameters + * @param {?number=} iTimeout + * @param {string=} sGetAdd = '' + * @param {Array=} aAbortActions = [] + */ +AbstractAjaxRemoteStorage.prototype.defaultRequest = function (fCallback, sAction, oParameters, iTimeout, sGetAdd, aAbortActions) +{ + oParameters = oParameters || {}; + oParameters.Action = sAction; + + sGetAdd = Utils.pString(sGetAdd); + + Plugins.runHook('ajax-default-request', [sAction, oParameters, sGetAdd]); + + this.ajaxRequest(fCallback, oParameters, + Utils.isUnd(iTimeout) ? Consts.Defaults.DefaultAjaxTimeout : Utils.pInt(iTimeout), sGetAdd, aAbortActions); +}; + +/** + * @param {?Function} fCallback + */ +AbstractAjaxRemoteStorage.prototype.noop = function (fCallback) +{ + this.defaultRequest(fCallback, 'Noop'); +}; + +/** + * @param {?Function} fCallback + * @param {string} sMessage + * @param {string} sFileName + * @param {number} iLineNo + * @param {string} sLocation + * @param {string} sHtmlCapa + * @param {number} iTime + */ +AbstractAjaxRemoteStorage.prototype.jsError = function (fCallback, sMessage, sFileName, iLineNo, sLocation, sHtmlCapa, iTime) +{ + this.defaultRequest(fCallback, 'JsError', { + 'Message': sMessage, + 'FileName': sFileName, + 'LineNo': iLineNo, + 'Location': sLocation, + 'HtmlCapa': sHtmlCapa, + 'TimeOnPage': iTime + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sType + * @param {Array=} mData = null + * @param {boolean=} bIsError = false + */ +AbstractAjaxRemoteStorage.prototype.jsInfo = function (fCallback, sType, mData, bIsError) +{ + this.defaultRequest(fCallback, 'JsInfo', { + 'Type': sType, + 'Data': mData, + 'IsError': (Utils.isUnd(bIsError) ? false : !!bIsError) ? '1' : '0' + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sVersion + */ +AbstractAjaxRemoteStorage.prototype.jsVersion = function (fCallback, sVersion) +{ + this.defaultRequest(fCallback, 'Version', { + 'Version': sVersion + }); +}; + +/** + * @constructor + * @extends AbstractAjaxRemoteStorage + */ +function WebMailAjaxRemoteStorage() +{ + AbstractAjaxRemoteStorage.call(this); + + this.oRequests = {}; +} + +_.extend(WebMailAjaxRemoteStorage.prototype, AbstractAjaxRemoteStorage.prototype); + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.folders = function (fCallback) +{ + this.defaultRequest(fCallback, 'Folders', { + 'SentFolder': RL.settingsGet('SentFolder'), + 'DraftFolder': RL.settingsGet('DraftFolder'), + 'SpamFolder': RL.settingsGet('SpamFolder'), + 'TrashFolder': RL.settingsGet('TrashFolder'), + 'ArchiveFolder': RL.settingsGet('ArchiveFolder') + }, null, '', ['Folders']); +}; + +/** + * @param {?Function} fCallback + * @param {string} sEmail + * @param {string} sLogin + * @param {string} sPassword + * @param {boolean} bSignMe + * @param {string=} sLanguage + * @param {string=} sAdditionalCode + * @param {boolean=} bAdditionalCodeSignMe + */ +WebMailAjaxRemoteStorage.prototype.login = function (fCallback, sEmail, sLogin, sPassword, bSignMe, sLanguage, sAdditionalCode, bAdditionalCodeSignMe) +{ + this.defaultRequest(fCallback, 'Login', { + 'Email': sEmail, + 'Login': sLogin, + 'Password': sPassword, + 'Language': sLanguage || '', + 'AdditionalCode': sAdditionalCode || '', + 'AdditionalCodeSignMe': bAdditionalCodeSignMe ? '1' : '0', + 'SignMe': bSignMe ? '1' : '0' + }); +}; + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.getTwoFactor = function (fCallback) +{ + this.defaultRequest(fCallback, 'GetTwoFactorInfo'); +}; + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.createTwoFactor = function (fCallback) +{ + this.defaultRequest(fCallback, 'CreateTwoFactorSecret'); +}; + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.clearTwoFactor = function (fCallback) +{ + this.defaultRequest(fCallback, 'ClearTwoFactorInfo'); +}; + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.showTwoFactorSecret = function (fCallback) +{ + this.defaultRequest(fCallback, 'ShowTwoFactorSecret'); +}; + +/** + * @param {?Function} fCallback + * @param {string} sCode + */ +WebMailAjaxRemoteStorage.prototype.testTwoFactor = function (fCallback, sCode) +{ + this.defaultRequest(fCallback, 'TestTwoFactorInfo', { + 'Code': sCode + }); +}; + +/** + * @param {?Function} fCallback + * @param {boolean} bEnable + */ +WebMailAjaxRemoteStorage.prototype.enableTwoFactor = function (fCallback, bEnable) +{ + this.defaultRequest(fCallback, 'EnableTwoFactor', { + 'Enable': bEnable ? '1' : '0' + }); +}; + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.clearTwoFactorInfo = function (fCallback) +{ + this.defaultRequest(fCallback, 'ClearTwoFactorInfo'); +}; + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.contactsSync = function (fCallback) +{ + this.defaultRequest(fCallback, 'ContactsSync', null, Consts.Defaults.ContactsSyncAjaxTimeout); +}; + +/** + * @param {?Function} fCallback + * @param {boolean} bEnable + * @param {string} sUrl + * @param {string} sUser + * @param {string} sPassword + */ +WebMailAjaxRemoteStorage.prototype.saveContactsSyncData = function (fCallback, bEnable, sUrl, sUser, sPassword) +{ + this.defaultRequest(fCallback, 'SaveContactsSyncData', { + 'Enable': bEnable ? '1' : '0', + 'Url': sUrl, + 'User': sUser, + 'Password': sPassword + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sEmail + * @param {string} sLogin + * @param {string} sPassword + */ +WebMailAjaxRemoteStorage.prototype.accountAdd = function (fCallback, sEmail, sLogin, sPassword) +{ + this.defaultRequest(fCallback, 'AccountAdd', { + 'Email': sEmail, + 'Login': sLogin, + 'Password': sPassword + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sEmailToDelete + */ +WebMailAjaxRemoteStorage.prototype.accountDelete = function (fCallback, sEmailToDelete) +{ + this.defaultRequest(fCallback, 'AccountDelete', { + 'EmailToDelete': sEmailToDelete + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sId + * @param {string} sEmail + * @param {string} sName + * @param {string} sReplyTo + * @param {string} sBcc + */ +WebMailAjaxRemoteStorage.prototype.identityUpdate = function (fCallback, sId, sEmail, sName, sReplyTo, sBcc) +{ + this.defaultRequest(fCallback, 'IdentityUpdate', { + 'Id': sId, + 'Email': sEmail, + 'Name': sName, + 'ReplyTo': sReplyTo, + 'Bcc': sBcc + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sIdToDelete + */ +WebMailAjaxRemoteStorage.prototype.identityDelete = function (fCallback, sIdToDelete) +{ + this.defaultRequest(fCallback, 'IdentityDelete', { + 'IdToDelete': sIdToDelete + }); +}; + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.accountsAndIdentities = function (fCallback) +{ + this.defaultRequest(fCallback, 'AccountsAndIdentities'); +}; + +/** + * @param {?Function} fCallback + * @param {string} sFolderFullNameRaw + * @param {number=} iOffset = 0 + * @param {number=} iLimit = 20 + * @param {string=} sSearch = '' + * @param {boolean=} bSilent = false + */ +WebMailAjaxRemoteStorage.prototype.messageList = function (fCallback, sFolderFullNameRaw, iOffset, iLimit, sSearch, bSilent) +{ + sFolderFullNameRaw = Utils.pString(sFolderFullNameRaw); + + var + oData = RL.data(), + sFolderHash = RL.cache().getFolderHash(sFolderFullNameRaw) + ; + + bSilent = Utils.isUnd(bSilent) ? false : !!bSilent; + iOffset = Utils.isUnd(iOffset) ? 0 : Utils.pInt(iOffset); + iLimit = Utils.isUnd(iOffset) ? 20 : Utils.pInt(iLimit); + sSearch = Utils.pString(sSearch); + + if ('' !== sFolderHash && ('' === sSearch || -1 === sSearch.indexOf('has:'))) + { + this.defaultRequest(fCallback, 'MessageList', {}, + '' === sSearch ? Consts.Defaults.DefaultAjaxTimeout : Consts.Defaults.SearchAjaxTimeout, + 'MessageList/' + Base64.urlsafe_encode([ + sFolderFullNameRaw, + iOffset, + iLimit, + sSearch, + oData.projectHash(), + sFolderHash, + 'INBOX' === sFolderFullNameRaw ? RL.cache().getFolderUidNext(sFolderFullNameRaw) : '', + oData.threading() && oData.useThreads() ? '1' : '0', + oData.threading() && sFolderFullNameRaw === oData.messageListThreadFolder() ? oData.messageListThreadUids().join(',') : '' + ].join(String.fromCharCode(0))), bSilent ? [] : ['MessageList']); + } + else + { + this.defaultRequest(fCallback, 'MessageList', { + 'Folder': sFolderFullNameRaw, + 'Offset': iOffset, + 'Limit': iLimit, + 'Search': sSearch, + 'UidNext': 'INBOX' === sFolderFullNameRaw ? RL.cache().getFolderUidNext(sFolderFullNameRaw) : '', + 'UseThreads': RL.data().threading() && RL.data().useThreads() ? '1' : '0', + 'ExpandedThreadUid': oData.threading() && sFolderFullNameRaw === oData.messageListThreadFolder() ? oData.messageListThreadUids().join(',') : '' + }, '' === sSearch ? Consts.Defaults.DefaultAjaxTimeout : Consts.Defaults.SearchAjaxTimeout, '', bSilent ? [] : ['MessageList']); + } +}; + +/** + * @param {?Function} fCallback + * @param {Array} aDownloads + */ +WebMailAjaxRemoteStorage.prototype.messageUploadAttachments = function (fCallback, aDownloads) +{ + this.defaultRequest(fCallback, 'MessageUploadAttachments', { + 'Attachments': aDownloads + }, 999000); +}; + +/** + * @param {?Function} fCallback + * @param {string} sFolderFullNameRaw + * @param {number} iUid + * @return {boolean} + */ +WebMailAjaxRemoteStorage.prototype.message = function (fCallback, sFolderFullNameRaw, iUid) +{ + sFolderFullNameRaw = Utils.pString(sFolderFullNameRaw); + iUid = Utils.pInt(iUid); + + if (RL.cache().getFolderFromCacheList(sFolderFullNameRaw) && 0 < iUid) + { + this.defaultRequest(fCallback, 'Message', {}, null, + 'Message/' + Base64.urlsafe_encode([ + sFolderFullNameRaw, + iUid, + RL.data().projectHash(), + RL.data().threading() && RL.data().useThreads() ? '1' : '0' + ].join(String.fromCharCode(0))), ['Message']); + + return true; + } + + return false; +}; + +/** + * @param {?Function} fCallback + * @param {Array} aExternals + */ +WebMailAjaxRemoteStorage.prototype.composeUploadExternals = function (fCallback, aExternals) +{ + this.defaultRequest(fCallback, 'ComposeUploadExternals', { + 'Externals': aExternals + }, 999000); +}; + +/** + * @param {?Function} fCallback + * @param {string} sFolder + * @param {Array=} aList = [] + */ +WebMailAjaxRemoteStorage.prototype.folderInformation = function (fCallback, sFolder, aList) +{ + var + bRequest = true, + oCache = RL.cache(), + aUids = [] + ; + + if (Utils.isArray(aList) && 0 < aList.length) + { + bRequest = false; + _.each(aList, function (oMessageListItem) { + if (!oCache.getMessageFlagsFromCache(oMessageListItem.folderFullNameRaw, oMessageListItem.uid)) + { + aUids.push(oMessageListItem.uid); + } + + if (0 < oMessageListItem.threads().length) + { + _.each(oMessageListItem.threads(), function (sUid) { + if (!oCache.getMessageFlagsFromCache(oMessageListItem.folderFullNameRaw, sUid)) + { + aUids.push(sUid); + } + }); + } + }); + + if (0 < aUids.length) + { + bRequest = true; + } + } + + if (bRequest) + { + this.defaultRequest(fCallback, 'FolderInformation', { + 'Folder': sFolder, + 'FlagsUids': Utils.isArray(aUids) ? aUids.join(',') : '', + 'UidNext': 'INBOX' === sFolder ? RL.cache().getFolderUidNext(sFolder) : '' + }); + } + else if (RL.data().useThreads()) + { + RL.reloadFlagsCurrentMessageListAndMessageFromCache(); + } +}; + +/** + * @param {?Function} fCallback + * @param {Array} aFolders + */ +WebMailAjaxRemoteStorage.prototype.folderInformationMultiply = function (fCallback, aFolders) +{ + this.defaultRequest(fCallback, 'FolderInformationMultiply', { + 'Folders': aFolders + }); +}; + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.logout = function (fCallback) +{ + this.defaultRequest(fCallback, 'Logout'); +}; + +/** + * @param {?Function} fCallback + * @param {string} sFolderFullNameRaw + * @param {Array} aUids + * @param {boolean} bSetFlagged + */ +WebMailAjaxRemoteStorage.prototype.messageSetFlagged = function (fCallback, sFolderFullNameRaw, aUids, bSetFlagged) +{ + this.defaultRequest(fCallback, 'MessageSetFlagged', { + 'Folder': sFolderFullNameRaw, + 'Uids': aUids.join(','), + 'SetAction': bSetFlagged ? '1' : '0' + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sFolderFullNameRaw + * @param {Array} aUids + * @param {boolean} bSetSeen + */ +WebMailAjaxRemoteStorage.prototype.messageSetSeen = function (fCallback, sFolderFullNameRaw, aUids, bSetSeen) +{ + this.defaultRequest(fCallback, 'MessageSetSeen', { + 'Folder': sFolderFullNameRaw, + 'Uids': aUids.join(','), + 'SetAction': bSetSeen ? '1' : '0' + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sFolderFullNameRaw + * @param {boolean} bSetSeen + */ +WebMailAjaxRemoteStorage.prototype.messageSetSeenToAll = function (fCallback, sFolderFullNameRaw, bSetSeen) +{ + this.defaultRequest(fCallback, 'MessageSetSeenToAll', { + 'Folder': sFolderFullNameRaw, + 'SetAction': bSetSeen ? '1' : '0' + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sMessageFolder + * @param {string} sMessageUid + * @param {string} sDraftFolder + * @param {string} sFrom + * @param {string} sTo + * @param {string} sCc + * @param {string} sBcc + * @param {string} sSubject + * @param {boolean} bTextIsHtml + * @param {string} sText + * @param {Array} aAttachments + * @param {(Array|null)} aDraftInfo + * @param {string} sInReplyTo + * @param {string} sReferences + */ +WebMailAjaxRemoteStorage.prototype.saveMessage = function (fCallback, sMessageFolder, sMessageUid, sDraftFolder, + sFrom, sTo, sCc, sBcc, sSubject, bTextIsHtml, sText, aAttachments, aDraftInfo, sInReplyTo, sReferences) +{ + this.defaultRequest(fCallback, 'SaveMessage', { + 'MessageFolder': sMessageFolder, + 'MessageUid': sMessageUid, + 'DraftFolder': sDraftFolder, + 'From': sFrom, + 'To': sTo, + 'Cc': sCc, + 'Bcc': sBcc, + 'Subject': sSubject, + 'TextIsHtml': bTextIsHtml ? '1' : '0', + 'Text': sText, + 'DraftInfo': aDraftInfo, + 'InReplyTo': sInReplyTo, + 'References': sReferences, + 'Attachments': aAttachments + }, Consts.Defaults.SaveMessageAjaxTimeout); +}; + + +/** + * @param {?Function} fCallback + * @param {string} sMessageFolder + * @param {string} sMessageUid + * @param {string} sReadReceipt + * @param {string} sSubject + * @param {string} sText + */ +WebMailAjaxRemoteStorage.prototype.sendReadReceiptMessage = function (fCallback, sMessageFolder, sMessageUid, sReadReceipt, sSubject, sText) +{ + this.defaultRequest(fCallback, 'SendReadReceiptMessage', { + 'MessageFolder': sMessageFolder, + 'MessageUid': sMessageUid, + 'ReadReceipt': sReadReceipt, + 'Subject': sSubject, + 'Text': sText + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sMessageFolder + * @param {string} sMessageUid + * @param {string} sSentFolder + * @param {string} sFrom + * @param {string} sTo + * @param {string} sCc + * @param {string} sBcc + * @param {string} sSubject + * @param {boolean} bTextIsHtml + * @param {string} sText + * @param {Array} aAttachments + * @param {(Array|null)} aDraftInfo + * @param {string} sInReplyTo + * @param {string} sReferences + * @param {boolean} bRequestReadReceipt + */ +WebMailAjaxRemoteStorage.prototype.sendMessage = function (fCallback, sMessageFolder, sMessageUid, sSentFolder, + sFrom, sTo, sCc, sBcc, sSubject, bTextIsHtml, sText, aAttachments, aDraftInfo, sInReplyTo, sReferences, bRequestReadReceipt) +{ + this.defaultRequest(fCallback, 'SendMessage', { + 'MessageFolder': sMessageFolder, + 'MessageUid': sMessageUid, + 'SentFolder': sSentFolder, + 'From': sFrom, + 'To': sTo, + 'Cc': sCc, + 'Bcc': sBcc, + 'Subject': sSubject, + 'TextIsHtml': bTextIsHtml ? '1' : '0', + 'Text': sText, + 'DraftInfo': aDraftInfo, + 'InReplyTo': sInReplyTo, + 'References': sReferences, + 'ReadReceiptRequest': bRequestReadReceipt ? '1' : '0', + 'Attachments': aAttachments + }, Consts.Defaults.SendMessageAjaxTimeout); +}; + +/** + * @param {?Function} fCallback + * @param {Object} oData + */ +WebMailAjaxRemoteStorage.prototype.saveSystemFolders = function (fCallback, oData) +{ + this.defaultRequest(fCallback, 'SystemFoldersUpdate', oData); +}; + +/** + * @param {?Function} fCallback + * @param {Object} oData + */ +WebMailAjaxRemoteStorage.prototype.saveSettings = function (fCallback, oData) +{ + this.defaultRequest(fCallback, 'SettingsUpdate', oData); +}; + +/** + * @param {?Function} fCallback + * @param {string} sPrevPassword + * @param {string} sNewPassword + */ +WebMailAjaxRemoteStorage.prototype.changePassword = function (fCallback, sPrevPassword, sNewPassword) +{ + this.defaultRequest(fCallback, 'ChangePassword', { + 'PrevPassword': sPrevPassword, + 'NewPassword': sNewPassword + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sNewFolderName + * @param {string} sParentName + */ +WebMailAjaxRemoteStorage.prototype.folderCreate = function (fCallback, sNewFolderName, sParentName) +{ + this.defaultRequest(fCallback, 'FolderCreate', { + 'Folder': sNewFolderName, + 'Parent': sParentName + }, null, '', ['Folders']); +}; + +/** + * @param {?Function} fCallback + * @param {string} sFolderFullNameRaw + */ +WebMailAjaxRemoteStorage.prototype.folderDelete = function (fCallback, sFolderFullNameRaw) +{ + this.defaultRequest(fCallback, 'FolderDelete', { + 'Folder': sFolderFullNameRaw + }, null, '', ['Folders']); +}; + +/** + * @param {?Function} fCallback + * @param {string} sPrevFolderFullNameRaw + * @param {string} sNewFolderName + */ +WebMailAjaxRemoteStorage.prototype.folderRename = function (fCallback, sPrevFolderFullNameRaw, sNewFolderName) +{ + this.defaultRequest(fCallback, 'FolderRename', { + 'Folder': sPrevFolderFullNameRaw, + 'NewFolderName': sNewFolderName + }, null, '', ['Folders']); +}; + +/** + * @param {?Function} fCallback + * @param {string} sFolderFullNameRaw + */ +WebMailAjaxRemoteStorage.prototype.folderClear = function (fCallback, sFolderFullNameRaw) +{ + this.defaultRequest(fCallback, 'FolderClear', { + 'Folder': sFolderFullNameRaw + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sFolderFullNameRaw + * @param {boolean} bSubscribe + */ +WebMailAjaxRemoteStorage.prototype.folderSetSubscribe = function (fCallback, sFolderFullNameRaw, bSubscribe) +{ + this.defaultRequest(fCallback, 'FolderSubscribe', { + 'Folder': sFolderFullNameRaw, + 'Subscribe': bSubscribe ? '1' : '0' + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sFolder + * @param {string} sToFolder + * @param {Array} aUids + * @param {string=} sLearning + */ +WebMailAjaxRemoteStorage.prototype.messagesMove = function (fCallback, sFolder, sToFolder, aUids, sLearning) +{ + this.defaultRequest(fCallback, 'MessageMove', { + 'FromFolder': sFolder, + 'ToFolder': sToFolder, + 'Uids': aUids.join(','), + 'Learning': sLearning || '' + }, null, '', ['MessageList']); +}; + +/** + * @param {?Function} fCallback + * @param {string} sFolder + * @param {string} sToFolder + * @param {Array} aUids + */ +WebMailAjaxRemoteStorage.prototype.messagesCopy = function (fCallback, sFolder, sToFolder, aUids) +{ + this.defaultRequest(fCallback, 'MessageCopy', { + 'FromFolder': sFolder, + 'ToFolder': sToFolder, + 'Uids': aUids.join(',') + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sFolder + * @param {Array} aUids + */ +WebMailAjaxRemoteStorage.prototype.messagesDelete = function (fCallback, sFolder, aUids) +{ + this.defaultRequest(fCallback, 'MessageDelete', { + 'Folder': sFolder, + 'Uids': aUids.join(',') + }, null, '', ['MessageList']); +}; + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.appDelayStart = function (fCallback) +{ + this.defaultRequest(fCallback, 'AppDelayStart'); +}; + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.quota = function (fCallback) +{ + this.defaultRequest(fCallback, 'Quota'); +}; + +/** + * @param {?Function} fCallback + * @param {number} iOffset + * @param {number} iLimit + * @param {string} sSearch + */ +WebMailAjaxRemoteStorage.prototype.contacts = function (fCallback, iOffset, iLimit, sSearch) +{ + this.defaultRequest(fCallback, 'Contacts', { + 'Offset': iOffset, + 'Limit': iLimit, + 'Search': sSearch + }, null, '', ['Contacts']); +}; + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.contactSave = function (fCallback, sRequestUid, sUid, aProperties) +{ + this.defaultRequest(fCallback, 'ContactSave', { + 'RequestUid': sRequestUid, + 'Uid': Utils.trim(sUid), + 'Properties': aProperties + }); +}; + +/** + * @param {?Function} fCallback + * @param {Array} aUids + */ +WebMailAjaxRemoteStorage.prototype.contactsDelete = function (fCallback, aUids) +{ + this.defaultRequest(fCallback, 'ContactsDelete', { + 'Uids': aUids.join(',') + }); +}; + +/** + * @param {?Function} fCallback + * @param {string} sQuery + * @param {number} iPage + */ +WebMailAjaxRemoteStorage.prototype.suggestions = function (fCallback, sQuery, iPage) +{ + this.defaultRequest(fCallback, 'Suggestions', { + 'Query': sQuery, + 'Page': iPage + }, null, '', ['Suggestions']); +}; + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.servicesPics = function (fCallback) +{ + this.defaultRequest(fCallback, 'ServicesPics'); +}; + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.emailsPicsHashes = function (fCallback) +{ + this.defaultRequest(fCallback, 'EmailsPicsHashes'); +}; + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.facebookUser = function (fCallback) +{ + this.defaultRequest(fCallback, 'SocialFacebookUserInformation'); +}; + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.facebookDisconnect = function (fCallback) +{ + this.defaultRequest(fCallback, 'SocialFacebookDisconnect'); +}; + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.twitterUser = function (fCallback) +{ + this.defaultRequest(fCallback, 'SocialTwitterUserInformation'); +}; + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.twitterDisconnect = function (fCallback) +{ + this.defaultRequest(fCallback, 'SocialTwitterDisconnect'); +}; + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.googleUser = function (fCallback) +{ + this.defaultRequest(fCallback, 'SocialGoogleUserInformation'); +}; + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.googleDisconnect = function (fCallback) +{ + this.defaultRequest(fCallback, 'SocialGoogleDisconnect'); +}; + +/** + * @param {?Function} fCallback + */ +WebMailAjaxRemoteStorage.prototype.socialUsers = function (fCallback) +{ + this.defaultRequest(fCallback, 'SocialUsers'); +}; + + +/** + * @constructor + */ +function AbstractCacheStorage() +{ + this.oEmailsPicsHashes = {}; + this.oServices = {}; + this.bAllowGravatar = !!RL.settingsGet('AllowGravatar'); +} + +/** + * @type {Object} + */ +AbstractCacheStorage.prototype.oEmailsPicsHashes = {}; + +/** + * @type {Object} + */ +AbstractCacheStorage.prototype.oServices = {}; + +/** + * @type {boolean} + */ +AbstractCacheStorage.prototype.bAllowGravatar = false; + +AbstractCacheStorage.prototype.clear = function () +{ + this.oServices = {}; + this.oEmailsPicsHashes = {}; +}; + +/** + * @param {string} sEmail + * @return {string} + */ +AbstractCacheStorage.prototype.getUserPic = function (sEmail, fCallback) +{ + sEmail = Utils.trim(sEmail); + + var + sUrl = '', + sService = '', + sEmailLower = sEmail.toLowerCase(), + sPicHash = Utils.isUnd(this.oEmailsPicsHashes[sEmailLower]) ? '' : this.oEmailsPicsHashes[sEmailLower] + ; + + if ('' !== sPicHash) + { + sUrl = RL.link().getUserPicUrlFromHash(sPicHash); + } + else + { + sService = sEmailLower.substr(sEmail.indexOf('@') + 1); + sUrl = '' !== sService && this.oServices[sService] ? this.oServices[sService] : ''; + } + + + if (this.bAllowGravatar && '' === sUrl) + { + fCallback('//secure.gravatar.com/avatar/' + Utils.md5(sEmailLower) + '.jpg?s=80&d=mm', sEmail); + } + else + { + fCallback(sUrl, sEmail); + } +}; + +/** + * @param {Object} oData + */ +AbstractCacheStorage.prototype.setServicesData = function (oData) +{ + this.oServices = oData; +}; + +/** + * @param {Object} oData + */ +AbstractCacheStorage.prototype.setEmailsPicsHashesData = function (oData) +{ + this.oEmailsPicsHashes = oData; +}; + +/** + * @constructor + * @extends AbstractCacheStorage + */ +function WebMailCacheStorage() +{ + AbstractCacheStorage.call(this); + + this.oFoldersCache = {}; + this.oFoldersNamesCache = {}; + this.oFolderHashCache = {}; + this.oFolderUidNextCache = {}; + this.oMessageListHashCache = {}; + this.oMessageFlagsCache = {}; + this.oNewMessage = {}; + this.oRequestedMessage = {}; +} + +_.extend(WebMailCacheStorage.prototype, AbstractCacheStorage.prototype); + +/** + * @type {Object} + */ +WebMailCacheStorage.prototype.oFoldersCache = {}; + +/** + * @type {Object} + */ +WebMailCacheStorage.prototype.oFoldersNamesCache = {}; + +/** + * @type {Object} + */ +WebMailCacheStorage.prototype.oFolderHashCache = {}; + +/** + * @type {Object} + */ +WebMailCacheStorage.prototype.oFolderUidNextCache = {}; + +/** + * @type {Object} + */ +WebMailCacheStorage.prototype.oMessageListHashCache = {}; + +/** + * @type {Object} + */ +WebMailCacheStorage.prototype.oMessageFlagsCache = {}; + +/** + * @type {Object} + */ +WebMailCacheStorage.prototype.oBodies = {}; + +/** + * @type {Object} + */ +WebMailCacheStorage.prototype.oNewMessage = {}; + +/** + * @type {Object} + */ +WebMailCacheStorage.prototype.oRequestedMessage = {}; + +WebMailCacheStorage.prototype.clear = function () +{ + AbstractCacheStorage.prototype.clear.call(this); + + this.oFoldersCache = {}; + this.oFoldersNamesCache = {}; + this.oFolderHashCache = {}; + this.oFolderUidNextCache = {}; + this.oMessageListHashCache = {}; + this.oMessageFlagsCache = {}; + this.oBodies = {}; +}; + +/** + * @param {string} sFolderFullNameRaw + * @param {string} sUid + * @return {string} + */ +WebMailCacheStorage.prototype.getMessageKey = function (sFolderFullNameRaw, sUid) +{ + return sFolderFullNameRaw + '#' + sUid; +}; + +/** + * @param {string} sFolder + * @param {string} sUid + */ +WebMailCacheStorage.prototype.addRequestedMessage = function (sFolder, sUid) +{ + this.oRequestedMessage[this.getMessageKey(sFolder, sUid)] = true; +}; + +/** + * @param {string} sFolder + * @param {string} sUid + * @return {boolean} + */ +WebMailCacheStorage.prototype.hasRequestedMessage = function (sFolder, sUid) +{ + return true === this.oRequestedMessage[this.getMessageKey(sFolder, sUid)]; +}; + +/** + * @param {string} sFolderFullNameRaw + * @param {string} sUid + */ +WebMailCacheStorage.prototype.addNewMessageCache = function (sFolderFullNameRaw, sUid) +{ + this.oNewMessage[this.getMessageKey(sFolderFullNameRaw, sUid)] = true; +}; + +/** + * @param {string} sFolderFullNameRaw + * @param {string} sUid + */ +WebMailCacheStorage.prototype.hasNewMessageAndRemoveFromCache = function (sFolderFullNameRaw, sUid) +{ + if (this.oNewMessage[this.getMessageKey(sFolderFullNameRaw, sUid)]) + { + this.oNewMessage[this.getMessageKey(sFolderFullNameRaw, sUid)] = null; + return true; + } + + return false; +}; + +WebMailCacheStorage.prototype.clearNewMessageCache = function () +{ + this.oNewMessage = {}; +}; + +/** + * @param {string} sFolderHash + * @return {string} + */ +WebMailCacheStorage.prototype.getFolderFullNameRaw = function (sFolderHash) +{ + return '' !== sFolderHash && this.oFoldersNamesCache[sFolderHash] ? this.oFoldersNamesCache[sFolderHash] : ''; +}; + +/** + * @param {string} sFolderHash + * @param {string} sFolderFullNameRaw + */ +WebMailCacheStorage.prototype.setFolderFullNameRaw = function (sFolderHash, sFolderFullNameRaw) +{ + this.oFoldersNamesCache[sFolderHash] = sFolderFullNameRaw; +}; + +/** + * @param {string} sFolderFullNameRaw + * @return {string} + */ +WebMailCacheStorage.prototype.getFolderHash = function (sFolderFullNameRaw) +{ + return '' !== sFolderFullNameRaw && this.oFolderHashCache[sFolderFullNameRaw] ? this.oFolderHashCache[sFolderFullNameRaw] : ''; +}; + +/** + * @param {string} sFolderFullNameRaw + * @param {string} sFolderHash + */ +WebMailCacheStorage.prototype.setFolderHash = function (sFolderFullNameRaw, sFolderHash) +{ + this.oFolderHashCache[sFolderFullNameRaw] = sFolderHash; +}; + +/** + * @param {string} sFolderFullNameRaw + * @return {string} + */ +WebMailCacheStorage.prototype.getFolderUidNext = function (sFolderFullNameRaw) +{ + return '' !== sFolderFullNameRaw && this.oFolderUidNextCache[sFolderFullNameRaw] ? this.oFolderUidNextCache[sFolderFullNameRaw] : ''; +}; + +/** + * @param {string} sFolderFullNameRaw + * @param {string} sUidNext + */ +WebMailCacheStorage.prototype.setFolderUidNext = function (sFolderFullNameRaw, sUidNext) +{ + this.oFolderUidNextCache[sFolderFullNameRaw] = sUidNext; +}; + +/** + * @param {string} sFolderFullNameRaw + * @return {?FolderModel} + */ +WebMailCacheStorage.prototype.getFolderFromCacheList = function (sFolderFullNameRaw) +{ + return '' !== sFolderFullNameRaw && this.oFoldersCache[sFolderFullNameRaw] ? this.oFoldersCache[sFolderFullNameRaw] : null; +}; + +/** + * @param {string} sFolderFullNameRaw + * @param {?FolderModel} oFolder + */ +WebMailCacheStorage.prototype.setFolderToCacheList = function (sFolderFullNameRaw, oFolder) +{ + this.oFoldersCache[sFolderFullNameRaw] = oFolder; +}; + +/** + * @param {string} sFolderFullNameRaw + */ +WebMailCacheStorage.prototype.removeFolderFromCacheList = function (sFolderFullNameRaw) +{ + this.setFolderToCacheList(sFolderFullNameRaw, null); +}; + +/** + * @param {string} sFolderFullName + * @param {string} sUid + * @return {?Array} + */ +WebMailCacheStorage.prototype.getMessageFlagsFromCache = function (sFolderFullName, sUid) +{ + return this.oMessageFlagsCache[sFolderFullName] && this.oMessageFlagsCache[sFolderFullName][sUid] ? + this.oMessageFlagsCache[sFolderFullName][sUid] : null; +}; + +/** + * @param {string} sFolderFullName + * @param {string} sUid + * @param {Array} aFlagsCache + */ +WebMailCacheStorage.prototype.setMessageFlagsToCache = function (sFolderFullName, sUid, aFlagsCache) +{ + if (!this.oMessageFlagsCache[sFolderFullName]) + { + this.oMessageFlagsCache[sFolderFullName] = {}; + } + + this.oMessageFlagsCache[sFolderFullName][sUid] = aFlagsCache; +}; + +/** + * @param {string} sFolderFullName + */ +WebMailCacheStorage.prototype.clearMessageFlagsFromCacheByFolder = function (sFolderFullName) +{ + this.oMessageFlagsCache[sFolderFullName] = {}; +}; + +/** + * @param {(MessageModel|null)} oMessage + */ +WebMailCacheStorage.prototype.initMessageFlagsFromCache = function (oMessage) +{ + if (oMessage) + { + var + self = this, + aFlags = this.getMessageFlagsFromCache(oMessage.folderFullNameRaw, oMessage.uid), + mUnseenSubUid = null, + mFlaggedSubUid = null + ; + + if (aFlags && 0 < aFlags.length) + { + oMessage.unseen(!!aFlags[0]); + oMessage.flagged(!!aFlags[1]); + oMessage.answered(!!aFlags[2]); + oMessage.forwarded(!!aFlags[3]); + oMessage.isReadReceipt(!!aFlags[4]); + } + + if (0 < oMessage.threads().length) + { + mUnseenSubUid = _.find(oMessage.threads(), function (iSubUid) { + var aFlags = self.getMessageFlagsFromCache(oMessage.folderFullNameRaw, iSubUid); + return aFlags && 0 < aFlags.length && !!aFlags[0]; + }); + + mFlaggedSubUid = _.find(oMessage.threads(), function (iSubUid) { + var aFlags = self.getMessageFlagsFromCache(oMessage.folderFullNameRaw, iSubUid); + return aFlags && 0 < aFlags.length && !!aFlags[1]; + }); + + oMessage.hasUnseenSubMessage(mUnseenSubUid && 0 < Utils.pInt(mUnseenSubUid)); + oMessage.hasFlaggedSubMessage(mFlaggedSubUid && 0 < Utils.pInt(mFlaggedSubUid)); + } + } +}; + +/** + * @param {(MessageModel|null)} oMessage + */ +WebMailCacheStorage.prototype.storeMessageFlagsToCache = function (oMessage) +{ + if (oMessage) + { + this.setMessageFlagsToCache( + oMessage.folderFullNameRaw, + oMessage.uid, + [oMessage.unseen(), oMessage.flagged(), oMessage.answered(), oMessage.forwarded(), oMessage.isReadReceipt()] + ); + } +}; +/** + * @param {string} sFolder + * @param {string} sUid + * @param {Array} aFlags + */ +WebMailCacheStorage.prototype.storeMessageFlagsToCacheByFolderAndUid = function (sFolder, sUid, aFlags) +{ + if (Utils.isArray(aFlags) && 0 < aFlags.length) + { + this.setMessageFlagsToCache(sFolder, sUid, aFlags); + } +}; + +/** + * @param {Array} aViewModels + * @constructor + * @extends KnoinAbstractScreen + */ +function AbstractSettings(aViewModels) +{ + KnoinAbstractScreen.call(this, 'settings', aViewModels); + + this.menu = ko.observableArray([]); + + this.oCurrentSubScreen = null; + this.oViewModelPlace = null; +} + +_.extend(AbstractSettings.prototype, KnoinAbstractScreen.prototype); + +AbstractSettings.prototype.onRoute = function (sSubName) +{ + var + self = this, + oSettingsScreen = null, + RoutedSettingsViewModel = null, + oViewModelPlace = null, + oViewModelDom = null + ; + + RoutedSettingsViewModel = _.find(ViewModels['settings'], function (SettingsViewModel) { + return SettingsViewModel && SettingsViewModel.__rlSettingsData && + sSubName === SettingsViewModel.__rlSettingsData.Route; + }); + + if (RoutedSettingsViewModel) + { + if (_.find(ViewModels['settings-removed'], function (DisabledSettingsViewModel) { + return DisabledSettingsViewModel && DisabledSettingsViewModel === RoutedSettingsViewModel; + })) + { + RoutedSettingsViewModel = null; + } + + if (RoutedSettingsViewModel && _.find(ViewModels['settings-disabled'], function (DisabledSettingsViewModel) { + return DisabledSettingsViewModel && DisabledSettingsViewModel === RoutedSettingsViewModel; + })) + { + RoutedSettingsViewModel = null; + } + } + + if (RoutedSettingsViewModel) + { + if (RoutedSettingsViewModel.__builded && RoutedSettingsViewModel.__vm) + { + oSettingsScreen = RoutedSettingsViewModel.__vm; + } + else + { + oViewModelPlace = this.oViewModelPlace; + if (oViewModelPlace && 1 === oViewModelPlace.length) + { + RoutedSettingsViewModel = /** @type {?Function} */ RoutedSettingsViewModel; + oSettingsScreen = new RoutedSettingsViewModel(); + + oViewModelDom = $('').addClass('rl-settings-view-model').hide().attr('data-bind', + 'template: {name: "' + RoutedSettingsViewModel.__rlSettingsData.Template + '"}, i18nInit: true'); + + oViewModelDom.appendTo(oViewModelPlace); + + oSettingsScreen.data = RL.data(); + oSettingsScreen.viewModelDom = oViewModelDom; + + oSettingsScreen.__rlSettingsData = RoutedSettingsViewModel.__rlSettingsData; + + RoutedSettingsViewModel.__dom = oViewModelDom; + RoutedSettingsViewModel.__builded = true; + RoutedSettingsViewModel.__vm = oSettingsScreen; + + ko.applyBindings(oSettingsScreen, oViewModelDom[0]); + Utils.delegateRun(oSettingsScreen, 'onBuild', [oViewModelDom]); + } + else + { + Utils.log('Cannot find sub settings view model position: SettingsSubScreen'); + } + } + + if (oSettingsScreen) + { + _.defer(function () { + // hide + if (self.oCurrentSubScreen) + { + Utils.delegateRun(self.oCurrentSubScreen, 'onHide'); + self.oCurrentSubScreen.viewModelDom.hide(); + } + // -- + + self.oCurrentSubScreen = oSettingsScreen; + + // show + if (self.oCurrentSubScreen) + { + self.oCurrentSubScreen.viewModelDom.show(); + Utils.delegateRun(self.oCurrentSubScreen, 'onShow'); + Utils.delegateRun(self.oCurrentSubScreen, 'onFocus', [], 200); + + _.each(self.menu(), function (oItem) { + oItem.selected(oSettingsScreen && oSettingsScreen.__rlSettingsData && oItem.route === oSettingsScreen.__rlSettingsData.Route); + }); + + $('#rl-content .b-settings .b-content .content').scrollTop(0); + } + // -- + + Utils.windowResize(); + }); + } + } + else + { + kn.setHash(RL.link().settings(), false, true); + } +}; + +AbstractSettings.prototype.onHide = function () +{ + if (this.oCurrentSubScreen && this.oCurrentSubScreen.viewModelDom) + { + Utils.delegateRun(this.oCurrentSubScreen, 'onHide'); + this.oCurrentSubScreen.viewModelDom.hide(); + } +}; + +AbstractSettings.prototype.onBuild = function () +{ + _.each(ViewModels['settings'], function (SettingsViewModel) { + if (SettingsViewModel && SettingsViewModel.__rlSettingsData && + !_.find(ViewModels['settings-removed'], function (RemoveSettingsViewModel) { + return RemoveSettingsViewModel && RemoveSettingsViewModel === SettingsViewModel; + })) + { + this.menu.push({ + 'route': SettingsViewModel.__rlSettingsData.Route, + 'label': SettingsViewModel.__rlSettingsData.Label, + 'selected': ko.observable(false), + 'disabled': !!_.find(ViewModels['settings-disabled'], function (DisabledSettingsViewModel) { + return DisabledSettingsViewModel && DisabledSettingsViewModel === SettingsViewModel; + }) + }); + } + }, this); + + this.oViewModelPlace = $('#rl-content #rl-settings-subscreen'); +}; + +AbstractSettings.prototype.routes = function () +{ + var + DefaultViewModel = _.find(ViewModels['settings'], function (SettingsViewModel) { + return SettingsViewModel && SettingsViewModel.__rlSettingsData && SettingsViewModel.__rlSettingsData['IsDefault']; + }), + sDefaultRoute = DefaultViewModel ? DefaultViewModel.__rlSettingsData['Route'] : 'general', + oRules = { + 'subname': /^(.*)$/, + 'normalize_': function (oRequest, oVals) { + oVals.subname = Utils.isUnd(oVals.subname) ? sDefaultRoute : Utils.pString(oVals.subname); + return [oVals.subname]; + } + } + ; + + return [ + ['{subname}/', oRules], + ['{subname}', oRules], + ['', oRules] + ]; +}; + +/** + * @constructor + * @extends KnoinAbstractScreen + */ +function LoginScreen() +{ + KnoinAbstractScreen.call(this, 'login', [LoginViewModel]); +} + +_.extend(LoginScreen.prototype, KnoinAbstractScreen.prototype); + +LoginScreen.prototype.onShow = function () +{ + RL.setTitle(''); +}; +/** + * @constructor + * @extends KnoinAbstractScreen + */ +function MailBoxScreen() +{ + KnoinAbstractScreen.call(this, 'mailbox', [ + MailBoxSystemDropDownViewModel, + MailBoxFolderListViewModel, + MailBoxMessageListViewModel, + MailBoxMessageViewViewModel + ]); + + this.oLastRoute = {}; +} + +_.extend(MailBoxScreen.prototype, KnoinAbstractScreen.prototype); + +/** + * @type {Object} + */ +MailBoxScreen.prototype.oLastRoute = {}; + +MailBoxScreen.prototype.setNewTitle = function () +{ + var + sEmail = RL.data().accountEmail(), + ifoldersInboxUnreadCount = RL.data().foldersInboxUnreadCount() + ; + + RL.setTitle(('' === sEmail ? '' : + (0 < ifoldersInboxUnreadCount ? '(' + ifoldersInboxUnreadCount + ') ' : ' ') + sEmail + ' - ') + Utils.i18n('TITLES/MAILBOX')); +}; + +MailBoxScreen.prototype.onShow = function () +{ + this.setNewTitle(); + RL.data().keyScope(Enums.KeyState.MessageList); +}; + +/** + * @param {string} sFolderHash + * @param {number} iPage + * @param {string} sSearch + * @param {boolean=} bPreview = false + */ +MailBoxScreen.prototype.onRoute = function (sFolderHash, iPage, sSearch, bPreview) +{ + if (Utils.isUnd(bPreview) ? false : !!bPreview) + { + if (Enums.Layout.NoPreview === RL.data().layout() && !RL.data().message()) + { + RL.historyBack(); + } + } + else + { + var + oData = RL.data(), + sFolderFullNameRaw = RL.cache().getFolderFullNameRaw(sFolderHash), + oFolder = RL.cache().getFolderFromCacheList(sFolderFullNameRaw) + ; + + if (oFolder) + { + oData + .currentFolder(oFolder) + .messageListPage(iPage) + .messageListSearch(sSearch) + ; + + if (Enums.Layout.NoPreview === oData.layout() && oData.message()) + { + oData.message(null); + oData.messageFullScreenMode(false); + } + + RL.reloadMessageList(); + } + } +}; + +MailBoxScreen.prototype.onStart = function () +{ + var + oData = RL.data(), + fResizeFunction = function () { + Utils.windowResize(); + } + ; + + if (RL.settingsGet('AllowAdditionalAccounts') || RL.settingsGet('AllowIdentities')) + { + RL.accountsAndIdentities(); + } + + _.delay(function () { + if ('INBOX' !== oData.currentFolderFullNameRaw()) + { + RL.folderInformation('INBOX'); + } + }, 1000); + + _.delay(function () { + RL.quota(); + }, 5000); + + _.delay(function () { + RL.remote().appDelayStart(Utils.emptyFunction); + }, 35000); + + $html.toggleClass('rl-no-preview-pane', Enums.Layout.NoPreview === oData.layout()); + + oData.folderList.subscribe(fResizeFunction); + oData.messageList.subscribe(fResizeFunction); + oData.message.subscribe(fResizeFunction); + + oData.layout.subscribe(function (nValue) { + $html.toggleClass('rl-no-preview-pane', Enums.Layout.NoPreview === nValue); + }); + + oData.foldersInboxUnreadCount.subscribe(function () { + this.setNewTitle(); + }, this); +}; + +/** + * @return {Array} + */ +MailBoxScreen.prototype.routes = function () +{ + var + fNormP = function () { + return ['Inbox', 1, '', true]; + }, + fNormS = function (oRequest, oVals) { + oVals[0] = Utils.pString(oVals[0]); + oVals[1] = Utils.pInt(oVals[1]); + oVals[1] = 0 >= oVals[1] ? 1 : oVals[1]; + oVals[2] = Utils.pString(oVals[2]); + + if ('' === oRequest) + { + oVals[0] = 'Inbox'; + oVals[1] = 1; + } + + return [decodeURI(oVals[0]), oVals[1], decodeURI(oVals[2]), false]; + }, + fNormD = function (oRequest, oVals) { + oVals[0] = Utils.pString(oVals[0]); + oVals[1] = Utils.pString(oVals[1]); + + if ('' === oRequest) + { + oVals[0] = 'Inbox'; + } + + return [decodeURI(oVals[0]), 1, decodeURI(oVals[1]), false]; + } + ; + + return [ + [/^([a-zA-Z0-9]+)\/p([1-9][0-9]*)\/(.+)\/?$/, {'normalize_': fNormS}], + [/^([a-zA-Z0-9]+)\/p([1-9][0-9]*)$/, {'normalize_': fNormS}], + [/^([a-zA-Z0-9]+)\/(.+)\/?$/, {'normalize_': fNormD}], + [/^message-preview$/, {'normalize_': fNormP}], + [/^([^\/]*)$/, {'normalize_': fNormS}] + ]; +}; + +/** + * @constructor + * @extends AbstractSettings + */ +function SettingsScreen() +{ + AbstractSettings.call(this, [ + SettingsSystemDropDownViewModel, + SettingsMenuViewModel, + SettingsPaneViewModel + ]); + + Utils.initOnStartOrLangChange(function () { + this.sSettingsTitle = Utils.i18n('TITLES/SETTINGS'); + }, this, function () { + RL.setTitle(this.sSettingsTitle); + }); +} + +_.extend(SettingsScreen.prototype, AbstractSettings.prototype); + +SettingsScreen.prototype.onShow = function () +{ +// AbstractSettings.prototype.onShow.call(this); + + RL.setTitle(this.sSettingsTitle); + RL.data().keyScope(Enums.KeyState.Settings); +}; + +/** + * @constructor + * @extends KnoinAbstractBoot + */ +function AbstractApp() +{ + KnoinAbstractBoot.call(this); + + this.oSettings = null; + this.oPlugins = null; + this.oLocal = null; + this.oLink = null; + this.oSubs = {}; + + this.isLocalAutocomplete = true; + + this.popupVisibilityNames = ko.observableArray([]); + + this.popupVisibility = ko.computed(function () { + return 0 < this.popupVisibilityNames().length; + }, this); + + this.iframe = $('').appendTo('body'); + + $window.on('error', function (oEvent) { + if (RL && oEvent && oEvent.originalEvent && oEvent.originalEvent.message && + -1 === Utils.inArray(oEvent.originalEvent.message, [ + 'Script error.', 'Uncaught Error: Error calling method on NPObject.' + ])) + { + RL.remote().jsError( + Utils.emptyFunction, + oEvent.originalEvent.message, + oEvent.originalEvent.filename, + oEvent.originalEvent.lineno, + location && location.toString ? location.toString() : '', + $html.attr('class'), + Utils.microtime() - Globals.now + ); + } + }); + + $document.on('keydown', function (oEvent) { + if (oEvent && oEvent.ctrlKey) + { + $html.addClass('rl-ctrl-key-pressed'); + } + }).on('keyup', function (oEvent) { + if (oEvent && !oEvent.ctrlKey) + { + $html.removeClass('rl-ctrl-key-pressed'); + } + }); +} + +_.extend(AbstractApp.prototype, KnoinAbstractBoot.prototype); + +AbstractApp.prototype.oSettings = null; +AbstractApp.prototype.oPlugins = null; +AbstractApp.prototype.oLocal = null; +AbstractApp.prototype.oLink = null; +AbstractApp.prototype.oSubs = {}; + +/** + * @param {string} sLink + * @return {boolean} + */ +AbstractApp.prototype.download = function (sLink) +{ + var + oLink = null, + oE = null, + sUserAgent = navigator.userAgent.toLowerCase() + ; + + if (sUserAgent && (sUserAgent.indexOf('chrome') > -1 || sUserAgent.indexOf('chrome') > -1)) + { + oLink = document.createElement('a'); + oLink['href'] = sLink; + + if (document['createEvent']) + { + oE = document['createEvent']('MouseEvents'); + if (oE && oE['initEvent'] && oLink['dispatchEvent']) + { + oE['initEvent']('click', true, true); + oLink['dispatchEvent'](oE); + return true; + } + } + } + + if (Globals.bMobileDevice) + { + window.open(sLink, '_self'); + window.focus(); + } + else + { + this.iframe.attr('src', sLink); +// window.document.location.href = sLink; + } + + return true; +}; + +/** + * @return {LinkBuilder} + */ +AbstractApp.prototype.link = function () +{ + if (null === this.oLink) + { + this.oLink = new LinkBuilder(); + } + + return this.oLink; +}; + +/** + * @return {LocalStorage} + */ +AbstractApp.prototype.local = function () +{ + if (null === this.oLocal) + { + this.oLocal = new LocalStorage(); + } + + return this.oLocal; +}; + +/** + * @param {string} sName + * @return {?} + */ +AbstractApp.prototype.settingsGet = function (sName) +{ + if (null === this.oSettings) + { + this.oSettings = Utils.isNormal(AppData) ? AppData : {}; + } + + return Utils.isUnd(this.oSettings[sName]) ? null : this.oSettings[sName]; +}; + +/** + * @param {string} sName + * @param {?} mValue + */ +AbstractApp.prototype.settingsSet = function (sName, mValue) +{ + if (null === this.oSettings) + { + this.oSettings = Utils.isNormal(AppData) ? AppData : {}; + } + + this.oSettings[sName] = mValue; +}; + +AbstractApp.prototype.setTitle = function (sTitle) +{ + sTitle = ((Utils.isNormal(sTitle) && 0 < sTitle.length) ? sTitle + ' - ' : '') + + RL.settingsGet('Title') || ''; + + window.document.title = '_'; + window.document.title = sTitle; +}; + +/** + * @param {boolean=} bLogout = false + * @param {boolean=} bClose = false + */ +AbstractApp.prototype.loginAndLogoutReload = function (bLogout, bClose) +{ + var + sCustomLogoutLink = Utils.pString(RL.settingsGet('CustomLogoutLink')), + bInIframe = !!RL.settingsGet('InIframe') + ; + + bLogout = Utils.isUnd(bLogout) ? false : !!bLogout; + bClose = Utils.isUnd(bClose) ? false : !!bClose; + + if (bLogout && bClose && window.close) + { + window.close(); + } + + if (bLogout && '' !== sCustomLogoutLink && window.location.href !== sCustomLogoutLink) + { + _.delay(function () { + if (bInIframe && window.parent) + { + window.parent.location.href = sCustomLogoutLink; + } + else + { + window.location.href = sCustomLogoutLink; + } + }, 100); + } + else + { + kn.routeOff(); + kn.setHash(RL.link().root(), true); + kn.routeOff(); + + _.delay(function () { + if (bInIframe && window.parent) + { + window.parent.location.reload(); + } + else + { + window.location.reload(); + } + }, 100); + } +}; + +AbstractApp.prototype.historyBack = function () +{ + window.history.back(); +}; + +/** + * @param {string} sQuery + * @param {Function} fCallback + */ +AbstractApp.prototype.getAutocomplete = function (sQuery, fCallback) +{ + fCallback([], sQuery); +}; + +/** + * @param {string} sName + * @param {Function} fFunc + * @param {Object=} oContext + * @return {AbstractApp} + */ +AbstractApp.prototype.sub = function (sName, fFunc, oContext) +{ + if (Utils.isUnd(this.oSubs[sName])) + { + this.oSubs[sName] = []; + } + + this.oSubs[sName].push([fFunc, oContext]); + + return this; +}; + +/** + * @param {string} sName + * @param {Array=} aArgs + * @return {AbstractApp} + */ +AbstractApp.prototype.pub = function (sName, aArgs) +{ + Plugins.runHook('rl-pub', [sName, aArgs]); + if (!Utils.isUnd(this.oSubs[sName])) + { + _.each(this.oSubs[sName], function (aItem) { + if (aItem[0]) + { + aItem[0].apply(aItem[1] || null, aArgs || []); + } + }); + } + + return this; +}; + +AbstractApp.prototype.bootstart = function () +{ + var self = this; + + Utils.initOnStartOrLangChange(function () { + Utils.initNotificationLanguage(); + }, null); + + _.delay(function () { + Utils.windowResize(); + }, 1000); + + ssm.addState({ + 'id': 'mobile', + 'maxWidth': 767, + 'onEnter': function() { + $html.addClass('ssm-state-mobile'); + self.pub('ssm.mobile-enter'); + }, + 'onLeave': function() { + $html.removeClass('ssm-state-mobile'); + self.pub('ssm.mobile-leave'); + } + }); + + ssm.addState({ + 'id': 'tablet', + 'minWidth': 768, + 'maxWidth': 999, + 'onEnter': function() { + $html.addClass('ssm-state-tablet'); + }, + 'onLeave': function() { + $html.removeClass('ssm-state-tablet'); + } + }); + + ssm.addState({ + 'id': 'desktop', + 'minWidth': 1000, + 'maxWidth': 1400, + 'onEnter': function() { + $html.addClass('ssm-state-desktop'); + }, + 'onLeave': function() { + $html.removeClass('ssm-state-desktop'); + } + }); + + ssm.addState({ + 'id': 'desktop-large', + 'minWidth': 1400, + 'onEnter': function() { + $html.addClass('ssm-state-desktop-large'); + }, + 'onLeave': function() { + $html.removeClass('ssm-state-desktop-large'); + } + }); + + RL.sub('ssm.mobile-enter', function () { + RL.data().leftPanelDisabled(true); + }); + + RL.sub('ssm.mobile-leave', function () { + RL.data().leftPanelDisabled(false); + }); + + RL.data().leftPanelDisabled.subscribe(function (bValue) { + $html.toggleClass('rl-left-panel-disabled', bValue); + }); + + ssm.ready(); +}; + +/** + * @constructor + * @extends AbstractApp + */ +function RainLoopApp() +{ + AbstractApp.call(this); + + this.oData = null; + this.oRemote = null; + this.oCache = null; + this.oMoveCache = {}; + + this.quotaDebounce = _.debounce(this.quota, 1000 * 30); + this.moveOrDeleteResponseHelper = _.bind(this.moveOrDeleteResponseHelper, this); + + this.messagesMoveTrigger = _.debounce(this.messagesMoveTrigger, 500); + + window.setInterval(function () { + RL.pub('interval.30s'); + }, 30000); + + window.setInterval(function () { + RL.pub('interval.1m'); + }, 60000); + + window.setInterval(function () { + RL.pub('interval.2m'); + }, 60000 * 2); + + window.setInterval(function () { + RL.pub('interval.3m'); + }, 60000 * 3); + + window.setInterval(function () { + RL.pub('interval.5m'); + }, 60000 * 5); + + window.setInterval(function () { + RL.pub('interval.10m'); + }, 60000 * 10); + + window.setTimeout(function () { + window.setInterval(function () { + RL.pub('interval.10m-after5m'); + }, 60000 * 10); + }, 60000 * 5); + + $.wakeUp(function () { + RL.remote().jsVersion(function (sResult, oData) { + if (Enums.StorageResultType.Success === sResult && oData && !oData.Result) + { + if (window.parent && !!RL.settingsGet('InIframe')) + { + window.parent.location.reload(); + } + else + { + window.location.reload(); + } + } + }, RL.settingsGet('Version')); + }, {}, 60 * 60 * 1000); +} + +_.extend(RainLoopApp.prototype, AbstractApp.prototype); + +RainLoopApp.prototype.oData = null; +RainLoopApp.prototype.oRemote = null; +RainLoopApp.prototype.oCache = null; + +/** + * @return {WebMailDataStorage} + */ +RainLoopApp.prototype.data = function () +{ + if (null === this.oData) + { + this.oData = new WebMailDataStorage(); + } + + return this.oData; +}; + +/** + * @return {WebMailAjaxRemoteStorage} + */ +RainLoopApp.prototype.remote = function () +{ + if (null === this.oRemote) + { + this.oRemote = new WebMailAjaxRemoteStorage(); + } + + return this.oRemote; +}; + +/** + * @return {WebMailCacheStorage} + */ +RainLoopApp.prototype.cache = function () +{ + if (null === this.oCache) + { + this.oCache = new WebMailCacheStorage(); + } + + return this.oCache; +}; + +RainLoopApp.prototype.reloadFlagsCurrentMessageListAndMessageFromCache = function () +{ + var oCache = RL.cache(); + _.each(RL.data().messageList(), function (oMessage) { + oCache.initMessageFlagsFromCache(oMessage); + }); + + oCache.initMessageFlagsFromCache(RL.data().message()); +}; + +/** + * @param {boolean=} bDropPagePosition = false + * @param {boolean=} bDropCurrenFolderCache = false + */ +RainLoopApp.prototype.reloadMessageList = function (bDropPagePosition, bDropCurrenFolderCache) +{ + var + oRLData = RL.data(), + iOffset = (oRLData.messageListPage() - 1) * oRLData.messagesPerPage() + ; + + if (Utils.isUnd(bDropCurrenFolderCache) ? false : !!bDropCurrenFolderCache) + { + RL.cache().setFolderHash(oRLData.currentFolderFullNameRaw(), ''); + } + + if (Utils.isUnd(bDropPagePosition) ? false : !!bDropPagePosition) + { + oRLData.messageListPage(1); + iOffset = 0; + } + + oRLData.messageListLoading(true); + RL.remote().messageList(function (sResult, oData, bCached) { + + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + oRLData.messageListError(''); + oRLData.messageListLoading(false); + oRLData.setMessageList(oData, bCached); + } + else if (Enums.StorageResultType.Unload === sResult) + { + oRLData.messageListError(''); + oRLData.messageListLoading(false); + } + else if (Enums.StorageResultType.Abort !== sResult) + { + oRLData.messageList([]); + oRLData.messageListLoading(false); + oRLData.messageListError(oData && oData.ErrorCode ? + Utils.getNotification(oData.ErrorCode) : Utils.i18n('NOTIFICATIONS/CANT_GET_MESSAGE_LIST') + ); + } + + }, oRLData.currentFolderFullNameRaw(), iOffset, oRLData.messagesPerPage(), oRLData.messageListSearch()); +}; + +RainLoopApp.prototype.recacheInboxMessageList = function () +{ + RL.remote().messageList(Utils.emptyFunction, 'INBOX', 0, RL.data().messagesPerPage(), '', true); +}; + +RainLoopApp.prototype.reloadMessageListHelper = function (bEmptyList) +{ + RL.reloadMessageList(bEmptyList); +}; + +/** + * @param {Function} fResultFunc + * @returns {boolean} + */ +RainLoopApp.prototype.contactsSync = function (fResultFunc) +{ + var oContacts = RL.data().contacts; + if (oContacts.importing() || oContacts.syncing() || !RL.data().enableContactsSync() || !RL.data().allowContactsSync()) + { + return false; + } + + oContacts.syncing(true); + + RL.remote().contactsSync(function (sResult, oData) { + + oContacts.syncing(false); + + if (fResultFunc) + { + fResultFunc(sResult, oData); + } + }); + + return true; +}; + +RainLoopApp.prototype.messagesMoveTrigger = function () +{ + var + self = this, + sSpamFolder = RL.data().spamFolder() + ; + + _.each(this.oMoveCache, function (oItem) { + + var + bSpam = sSpamFolder === oItem['To'], + bHam = !bSpam && sSpamFolder === oItem['From'] && 'INBOX' === oItem['To'] + ; + + RL.remote().messagesMove(self.moveOrDeleteResponseHelper, oItem['From'], oItem['To'], oItem['Uid'], + bSpam ? 'SPAM' : (bHam ? 'HAM' : '')); + }); + + this.oMoveCache = {}; +}; + +RainLoopApp.prototype.messagesMoveHelper = function (sFromFolderFullNameRaw, sToFolderFullNameRaw, aUidForMove) +{ + var sH = '$$' + sFromFolderFullNameRaw + '$$' + sToFolderFullNameRaw + '$$'; + if (!this.oMoveCache[sH]) + { + this.oMoveCache[sH] = { + 'From': sFromFolderFullNameRaw, + 'To': sToFolderFullNameRaw, + 'Uid': [] + }; + } + + this.oMoveCache[sH]['Uid'] = _.union(this.oMoveCache[sH]['Uid'], aUidForMove); + this.messagesMoveTrigger(); +}; + +RainLoopApp.prototype.messagesCopyHelper = function (sFromFolderFullNameRaw, sToFolderFullNameRaw, aUidForCopy) +{ + RL.remote().messagesCopy( + this.moveOrDeleteResponseHelper, + sFromFolderFullNameRaw, + sToFolderFullNameRaw, + aUidForCopy + ); +}; + +RainLoopApp.prototype.messagesDeleteHelper = function (sFromFolderFullNameRaw, aUidForRemove) +{ + RL.remote().messagesDelete( + this.moveOrDeleteResponseHelper, + sFromFolderFullNameRaw, + aUidForRemove + ); +}; + +RainLoopApp.prototype.moveOrDeleteResponseHelper = function (sResult, oData) +{ + if (Enums.StorageResultType.Success === sResult && RL.data().currentFolder()) + { + if (oData && Utils.isArray(oData.Result) && 2 === oData.Result.length) + { + RL.cache().setFolderHash(oData.Result[0], oData.Result[1]); + } + else + { + RL.cache().setFolderHash(RL.data().currentFolderFullNameRaw(), ''); + + if (oData && -1 < Utils.inArray(oData.ErrorCode, + [Enums.Notification.CantMoveMessage, Enums.Notification.CantCopyMessage])) + { + window.alert(Utils.getNotification(oData.ErrorCode)); + } + } + + RL.reloadMessageListHelper(0 === RL.data().messageList().length); + RL.quotaDebounce(); + } +}; + +/** + * @param {string} sFromFolderFullNameRaw + * @param {Array} aUidForRemove + */ +RainLoopApp.prototype.deleteMessagesFromFolderWithoutCheck = function (sFromFolderFullNameRaw, aUidForRemove) +{ + this.messagesDeleteHelper(sFromFolderFullNameRaw, aUidForRemove); + RL.data().removeMessagesFromList(sFromFolderFullNameRaw, aUidForRemove); +}; + +/** + * @param {number} iDeleteType + * @param {string} sFromFolderFullNameRaw + * @param {Array} aUidForRemove + * @param {boolean=} bUseFolder = true + */ +RainLoopApp.prototype.deleteMessagesFromFolder = function (iDeleteType, sFromFolderFullNameRaw, aUidForRemove, bUseFolder) +{ + var + self = this, + oData = RL.data(), + oCache = RL.cache(), + oMoveFolder = null, + nSetSystemFoldersNotification = null + ; + + switch (iDeleteType) + { + case Enums.FolderType.Spam: + oMoveFolder = oCache.getFolderFromCacheList(oData.spamFolder()); + nSetSystemFoldersNotification = Enums.SetSystemFoldersNotification.Spam; + break; + case Enums.FolderType.NotSpam: + oMoveFolder = oCache.getFolderFromCacheList('INBOX'); + break; + case Enums.FolderType.Trash: + oMoveFolder = oCache.getFolderFromCacheList(oData.trashFolder()); + nSetSystemFoldersNotification = Enums.SetSystemFoldersNotification.Trash; + break; + case Enums.FolderType.Archive: + oMoveFolder = oCache.getFolderFromCacheList(oData.archiveFolder()); + nSetSystemFoldersNotification = Enums.SetSystemFoldersNotification.Archive; + break; + } + + bUseFolder = Utils.isUnd(bUseFolder) ? true : !!bUseFolder; + if (bUseFolder) + { + if ((Enums.FolderType.Spam === iDeleteType && Consts.Values.UnuseOptionValue === oData.spamFolder()) || + (Enums.FolderType.Trash === iDeleteType && Consts.Values.UnuseOptionValue === oData.trashFolder()) || + (Enums.FolderType.Archive === iDeleteType && Consts.Values.UnuseOptionValue === oData.archiveFolder())) + { + bUseFolder = false; + } + } + + if (!oMoveFolder && bUseFolder) + { + kn.showScreenPopup(PopupsFolderSystemViewModel, [nSetSystemFoldersNotification]); + } + else if (!bUseFolder || (Enums.FolderType.Trash === iDeleteType && + (sFromFolderFullNameRaw === oData.spamFolder() || sFromFolderFullNameRaw === oData.trashFolder()))) + { + kn.showScreenPopup(PopupsAskViewModel, [Utils.i18n('POPUPS_ASK/DESC_WANT_DELETE_MESSAGES'), function () { + + self.messagesDeleteHelper(sFromFolderFullNameRaw, aUidForRemove); + oData.removeMessagesFromList(sFromFolderFullNameRaw, aUidForRemove); + + }]); + } + else if (oMoveFolder) + { + this.messagesMoveHelper(sFromFolderFullNameRaw, oMoveFolder.fullNameRaw, aUidForRemove); + oData.removeMessagesFromList(sFromFolderFullNameRaw, aUidForRemove, oMoveFolder.fullNameRaw); + } +}; + +/** + * @param {string} sFromFolderFullNameRaw + * @param {Array} aUidForMove + * @param {string} sToFolderFullNameRaw + * @param {boolean=} bCopy = false + */ +RainLoopApp.prototype.moveMessagesToFolder = function (sFromFolderFullNameRaw, aUidForMove, sToFolderFullNameRaw, bCopy) +{ + if (sFromFolderFullNameRaw !== sToFolderFullNameRaw && Utils.isArray(aUidForMove) && 0 < aUidForMove.length) + { + var + oFromFolder = RL.cache().getFolderFromCacheList(sFromFolderFullNameRaw), + oToFolder = RL.cache().getFolderFromCacheList(sToFolderFullNameRaw) + ; + + if (oFromFolder && oToFolder) + { + if (Utils.isUnd(bCopy) ? false : !!bCopy) + { + this.messagesCopyHelper(oFromFolder.fullNameRaw, oToFolder.fullNameRaw, aUidForMove); + } + else + { + this.messagesMoveHelper(oFromFolder.fullNameRaw, oToFolder.fullNameRaw, aUidForMove); + } + + RL.data().removeMessagesFromList(oFromFolder.fullNameRaw, aUidForMove, oToFolder.fullNameRaw, bCopy); + return true; + } + } + + return false; +}; + +/** + * @param {Function=} fCallback + */ +RainLoopApp.prototype.folders = function (fCallback) +{ + this.data().foldersLoading(true); + this.remote().folders(_.bind(function (sResult, oData) { + + RL.data().foldersLoading(false); + if (Enums.StorageResultType.Success === sResult) + { + this.data().setFolders(oData); + if (fCallback) + { + fCallback(true); + } + } + else + { + if (fCallback) + { + fCallback(false); + } + } + }, this)); +}; + +RainLoopApp.prototype.reloadOpenPgpKeys = function () +{ + if (RL.data().allowOpenPGP()) + { + var + aKeys = [], + oEmail = new EmailModel(), + oOpenpgpKeyring = RL.data().openpgpKeyring, + oOpenpgpKeys = oOpenpgpKeyring ? oOpenpgpKeyring.getAllKeys() : [] + ; + + _.each(oOpenpgpKeys, function (oItem, iIndex) { + if (oItem && oItem.primaryKey) + { + var + + oPrimaryUser = oItem.getPrimaryUser(), + sUser = (oPrimaryUser && oPrimaryUser.user) ? oPrimaryUser.user.userId.userid + : (oItem.users && oItem.users[0] ? oItem.users[0].userId.userid : '') + ; + + oEmail.clear(); + oEmail.mailsoParse(sUser); + + if (oEmail.validate()) + { + aKeys.push(new OpenPgpKeyModel( + iIndex, + oItem.primaryKey.getFingerprint(), + oItem.primaryKey.getKeyId().toHex().toLowerCase(), + sUser, + oEmail.email, + oItem.isPrivate(), + oItem.armor()) + ); + } + } + }); + + RL.data().openpgpkeys(aKeys); + } +}; + +RainLoopApp.prototype.accountsAndIdentities = function () +{ + var oRainLoopData = RL.data(); + + oRainLoopData.accountsLoading(true); + oRainLoopData.identitiesLoading(true); + + RL.remote().accountsAndIdentities(function (sResult, oData) { + + oRainLoopData.accountsLoading(false); + oRainLoopData.identitiesLoading(false); + + if (Enums.StorageResultType.Success === sResult && oData.Result) + { + var + sParentEmail = RL.settingsGet('ParentEmail'), + sAccountEmail = oRainLoopData.accountEmail() + ; + + sParentEmail = '' === sParentEmail ? sAccountEmail : sParentEmail; + + if (Utils.isArray(oData.Result['Accounts'])) + { + oRainLoopData.accounts(_.map(oData.Result['Accounts'], function (sValue) { + return new AccountModel(sValue, sValue !== sParentEmail); + })); + } + + if (Utils.isArray(oData.Result['Identities'])) + { + oRainLoopData.identities(_.map(oData.Result['Identities'], function (oIdentityData) { + + var + sId = Utils.pString(oIdentityData['Id']), + sEmail = Utils.pString(oIdentityData['Email']), + oIdentity = new IdentityModel(sId, sEmail, sId !== sAccountEmail) + ; + + oIdentity.name(Utils.pString(oIdentityData['Name'])); + oIdentity.replyTo(Utils.pString(oIdentityData['ReplyTo'])); + oIdentity.bcc(Utils.pString(oIdentityData['Bcc'])); + + return oIdentity; + })); + } + } + }); +}; + +RainLoopApp.prototype.quota = function () +{ + this.remote().quota(function (sResult, oData) { + if (Enums.StorageResultType.Success === sResult && oData && oData.Result && + Utils.isArray(oData.Result) && 1 < oData.Result.length && + Utils.isPosNumeric(oData.Result[0], true) && Utils.isPosNumeric(oData.Result[1], true)) + { + RL.data().userQuota(Utils.pInt(oData.Result[1]) * 1024); + RL.data().userUsageSize(Utils.pInt(oData.Result[0]) * 1024); + } + }); +}; + +/** + * @param {string} sFolder + * @param {Array=} aList = [] + */ +RainLoopApp.prototype.folderInformation = function (sFolder, aList) +{ + if ('' !== Utils.trim(sFolder)) + { + this.remote().folderInformation(function (sResult, oData) { + if (Enums.StorageResultType.Success === sResult) + { + if (oData && oData.Result && oData.Result.Hash && oData.Result.Folder) + { + var + iUtc = moment().unix(), + sHash = RL.cache().getFolderHash(oData.Result.Folder), + oFolder = RL.cache().getFolderFromCacheList(oData.Result.Folder), + bCheck = false, + sUid = '', + aList = [], + bUnreadCountChange = false, + oFlags = null + ; + + if (oFolder) + { + oFolder.interval = iUtc; + + if (oData.Result.Hash) + { + RL.cache().setFolderHash(oData.Result.Folder, oData.Result.Hash); + } + + if (Utils.isNormal(oData.Result.MessageCount)) + { + oFolder.messageCountAll(oData.Result.MessageCount); + } + + if (Utils.isNormal(oData.Result.MessageUnseenCount)) + { + if (Utils.pInt(oFolder.messageCountUnread()) !== Utils.pInt(oData.Result.MessageUnseenCount)) + { + bUnreadCountChange = true; + } + + oFolder.messageCountUnread(oData.Result.MessageUnseenCount); + } + + if (bUnreadCountChange) + { + RL.cache().clearMessageFlagsFromCacheByFolder(oFolder.fullNameRaw); + } + + if (oData.Result.Flags) + { + for (sUid in oData.Result.Flags) + { + if (oData.Result.Flags.hasOwnProperty(sUid)) + { + bCheck = true; + oFlags = oData.Result.Flags[sUid]; + RL.cache().storeMessageFlagsToCacheByFolderAndUid(oFolder.fullNameRaw, sUid.toString(), [ + !oFlags['IsSeen'], !!oFlags['IsFlagged'], !!oFlags['IsAnswered'], !!oFlags['IsForwarded'], !!oFlags['IsReadReceipt'] + ]); + } + } + + if (bCheck) + { + RL.reloadFlagsCurrentMessageListAndMessageFromCache(); + } + } + + RL.data().initUidNextAndNewMessages(oFolder.fullNameRaw, oData.Result.UidNext, oData.Result.NewMessages); + + if (oData.Result.Hash !== sHash || '' === sHash) + { + if (oFolder.fullNameRaw === RL.data().currentFolderFullNameRaw()) + { + RL.reloadMessageList(); + } + else if ('INBOX' === oFolder.fullNameRaw) + { + RL.recacheInboxMessageList(); + } + } + else if (bUnreadCountChange) + { + if (oFolder.fullNameRaw === RL.data().currentFolderFullNameRaw()) + { + aList = RL.data().messageList(); + if (Utils.isNonEmptyArray(aList)) + { + RL.folderInformation(oFolder.fullNameRaw, aList); + } + } + } + } + } + } + }, sFolder, aList); + } +}; + +/** + * @param {boolean=} bBoot = false + */ +RainLoopApp.prototype.folderInformationMultiply = function (bBoot) +{ + bBoot = Utils.isUnd(bBoot) ? false : !!bBoot; + + var + iUtc = moment().unix(), + aFolders = RL.data().getNextFolderNames(bBoot) + ; + + if (Utils.isNonEmptyArray(aFolders)) + { + this.remote().folderInformationMultiply(function (sResult, oData) { + if (Enums.StorageResultType.Success === sResult) + { + if (oData && oData.Result && oData.Result.List && Utils.isNonEmptyArray(oData.Result.List)) + { + _.each(oData.Result.List, function (oItem) { + + var + aList = [], + sHash = RL.cache().getFolderHash(oItem.Folder), + oFolder = RL.cache().getFolderFromCacheList(oItem.Folder), + bUnreadCountChange = false + ; + + if (oFolder) + { + oFolder.interval = iUtc; + + if (oItem.Hash) + { + RL.cache().setFolderHash(oItem.Folder, oItem.Hash); + } + + if (Utils.isNormal(oItem.MessageCount)) + { + oFolder.messageCountAll(oItem.MessageCount); + } + + if (Utils.isNormal(oItem.MessageUnseenCount)) + { + if (Utils.pInt(oFolder.messageCountUnread()) !== Utils.pInt(oItem.MessageUnseenCount)) + { + bUnreadCountChange = true; + } + + oFolder.messageCountUnread(oItem.MessageUnseenCount); + } + + if (bUnreadCountChange) + { + RL.cache().clearMessageFlagsFromCacheByFolder(oFolder.fullNameRaw); + } + + if (oItem.Hash !== sHash || '' === sHash) + { + if (oFolder.fullNameRaw === RL.data().currentFolderFullNameRaw()) + { + RL.reloadMessageList(); + } + } + else if (bUnreadCountChange) + { + if (oFolder.fullNameRaw === RL.data().currentFolderFullNameRaw()) + { + aList = RL.data().messageList(); + if (Utils.isNonEmptyArray(aList)) + { + RL.folderInformation(oFolder.fullNameRaw, aList); + } + } + } + } + }); + + if (bBoot) + { + RL.folderInformationMultiply(true); + } + } + } + }, aFolders); + } +}; + +RainLoopApp.prototype.setMessageSeen = function (oMessage) +{ + if (oMessage.unseen()) + { + oMessage.unseen(false); + + var oFolder = RL.cache().getFolderFromCacheList(oMessage.folderFullNameRaw); + if (oFolder) + { + oFolder.messageCountUnread(0 <= oFolder.messageCountUnread() - 1 ? + oFolder.messageCountUnread() - 1 : 0); + } + + RL.cache().storeMessageFlagsToCache(oMessage); + RL.reloadFlagsCurrentMessageListAndMessageFromCache(); + } + + RL.remote().messageSetSeen(Utils.emptyFunction, oMessage.folderFullNameRaw, [oMessage.uid], true); +}; + +RainLoopApp.prototype.googleConnect = function () +{ + window.open(RL.link().socialGoogle(), 'Google', 'left=200,top=100,width=650,height=600,menubar=no,status=no,resizable=yes,scrollbars=yes'); +}; + +RainLoopApp.prototype.twitterConnect = function () +{ + window.open(RL.link().socialTwitter(), 'Twitter', 'left=200,top=100,width=650,height=350,menubar=no,status=no,resizable=yes,scrollbars=yes'); +}; + +RainLoopApp.prototype.facebookConnect = function () +{ + window.open(RL.link().socialFacebook(), 'Facebook', 'left=200,top=100,width=650,height=335,menubar=no,status=no,resizable=yes,scrollbars=yes'); +}; + +/** + * @param {boolean=} bFireAllActions + */ +RainLoopApp.prototype.socialUsers = function (bFireAllActions) +{ + var oRainLoopData = RL.data(); + + if (bFireAllActions) + { + oRainLoopData.googleActions(true); + oRainLoopData.facebookActions(true); + oRainLoopData.twitterActions(true); + } + + RL.remote().socialUsers(function (sResult, oData) { + + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + oRainLoopData.googleUserName(oData.Result['Google'] || ''); + oRainLoopData.facebookUserName(oData.Result['Facebook'] || ''); + oRainLoopData.twitterUserName(oData.Result['Twitter'] || ''); + } + else + { + oRainLoopData.googleUserName(''); + oRainLoopData.facebookUserName(''); + oRainLoopData.twitterUserName(''); + } + + oRainLoopData.googleLoggined('' !== oRainLoopData.googleUserName()); + oRainLoopData.facebookLoggined('' !== oRainLoopData.facebookUserName()); + oRainLoopData.twitterLoggined('' !== oRainLoopData.twitterUserName()); + + oRainLoopData.googleActions(false); + oRainLoopData.facebookActions(false); + oRainLoopData.twitterActions(false); + }); +}; + +RainLoopApp.prototype.googleDisconnect = function () +{ + RL.data().googleActions(true); + RL.remote().googleDisconnect(function () { + RL.socialUsers(); + }); +}; + +RainLoopApp.prototype.facebookDisconnect = function () +{ + RL.data().facebookActions(true); + RL.remote().facebookDisconnect(function () { + RL.socialUsers(); + }); +}; + +RainLoopApp.prototype.twitterDisconnect = function () +{ + RL.data().twitterActions(true); + RL.remote().twitterDisconnect(function () { + RL.socialUsers(); + }); +}; + +/** + * @param {Array} aSystem + * @param {Array} aList + * @param {Array=} aDisabled + * @param {Array=} aHeaderLines + * @param {?number=} iUnDeep + * @param {Function=} fDisableCallback + * @param {Function=} fVisibleCallback + * @param {Function=} fRenameCallback + * @param {boolean=} bSystem + * @param {boolean=} bBuildUnvisible + * @return {Array} + */ +RainLoopApp.prototype.folderListOptionsBuilder = function (aSystem, aList, aDisabled, aHeaderLines, iUnDeep, fDisableCallback, fVisibleCallback, fRenameCallback, bSystem, bBuildUnvisible) +{ + var + iIndex = 0, + iLen = 0, + /** + * @type {?FolderModel} + */ + oItem = null, + bSep = false, + sDeepPrefix = '\u00A0\u00A0\u00A0', + aResult = [] + ; + + bSystem = !Utils.isNormal(bSystem) ? 0 < aSystem.length : bSystem; + bBuildUnvisible = Utils.isUnd(bBuildUnvisible) ? false : !!bBuildUnvisible; + iUnDeep = !Utils.isNormal(iUnDeep) ? 0 : iUnDeep; + fDisableCallback = Utils.isNormal(fDisableCallback) ? fDisableCallback : null; + fVisibleCallback = Utils.isNormal(fVisibleCallback) ? fVisibleCallback : null; + fRenameCallback = Utils.isNormal(fRenameCallback) ? fRenameCallback : null; + + if (!Utils.isArray(aDisabled)) + { + aDisabled = []; + } + + if (!Utils.isArray(aHeaderLines)) + { + aHeaderLines = []; + } + + for (iIndex = 0, iLen = aHeaderLines.length; iIndex < iLen; iIndex++) + { + aResult.push({ + 'id': aHeaderLines[iIndex][0], + 'name': aHeaderLines[iIndex][1], + 'system': false, + 'seporator': false, + 'disabled': false + }); + } + + bSep = true; + for (iIndex = 0, iLen = aSystem.length; iIndex < iLen; iIndex++) + { + oItem = aSystem[iIndex]; + if (fVisibleCallback ? fVisibleCallback.call(null, oItem) : true) + { + if (bSep && 0 < aResult.length) + { + aResult.push({ + 'id': '---', + 'name': '---', + 'system': false, + 'seporator': true, + 'disabled': true + }); + } + + bSep = false; + aResult.push({ + 'id': oItem.fullNameRaw, + 'name': fRenameCallback ? fRenameCallback.call(null, oItem) : oItem.name(), + 'system': true, + 'seporator': false, + 'disabled': !oItem.selectable || -1 < Utils.inArray(oItem.fullNameRaw, aDisabled) || + (fDisableCallback ? fDisableCallback.call(null, oItem) : false) + }); + } + } + + bSep = true; + for (iIndex = 0, iLen = aList.length; iIndex < iLen; iIndex++) + { + oItem = aList[iIndex]; + if (oItem.subScribed() || !oItem.existen) + { + if (fVisibleCallback ? fVisibleCallback.call(null, oItem) : true) + { + if (Enums.FolderType.User === oItem.type() || !bSystem || 0 < oItem.subFolders().length) + { + if (bSep && 0 < aResult.length) + { + aResult.push({ + 'id': '---', + 'name': '---', + 'system': false, + 'seporator': true, + 'disabled': true + }); + } + + bSep = false; + aResult.push({ + 'id': oItem.fullNameRaw, + 'name': (new window.Array(oItem.deep + 1 - iUnDeep)).join(sDeepPrefix) + + (fRenameCallback ? fRenameCallback.call(null, oItem) : oItem.name()), + 'system': false, + 'seporator': false, + 'disabled': !oItem.selectable || -1 < Utils.inArray(oItem.fullNameRaw, aDisabled) || + (fDisableCallback ? fDisableCallback.call(null, oItem) : false) + }); + } + } + } + + if (oItem.subScribed() && 0 < oItem.subFolders().length) + { + aResult = aResult.concat(RL.folderListOptionsBuilder([], oItem.subFolders(), aDisabled, [], + iUnDeep, fDisableCallback, fVisibleCallback, fRenameCallback, bSystem, bBuildUnvisible)); + } + } + + return aResult; +}; + +/** + * @param {string} sQuery + * @param {Function} fCallback + */ +RainLoopApp.prototype.getAutocomplete = function (sQuery, fCallback) +{ + var + aData = [] + ; + + RL.remote().suggestions(function (sResult, oData) { + if (Enums.StorageResultType.Success === sResult && oData && Utils.isArray(oData.Result)) + { + aData = _.map(oData.Result, function (aItem) { + return aItem && aItem[0] ? new EmailModel(aItem[0], aItem[1]) : null; + }); + + fCallback(_.compact(aData)); + } + else if (Enums.StorageResultType.Abort !== sResult) + { + fCallback([]); + } + + }, sQuery); +}; + +RainLoopApp.prototype.emailsPicsHashes = function () +{ + RL.remote().emailsPicsHashes(function (sResult, oData) { + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + RL.cache().setEmailsPicsHashesData(oData.Result); + } + }); +}; + +/** + * @param {string} sMailToUrl + * @returns {boolean} + */ +RainLoopApp.prototype.mailToHelper = function (sMailToUrl) +{ + if (sMailToUrl && 'mailto:' === sMailToUrl.toString().toLowerCase().substr(0, 7)) + { + var oEmailModel = null; + oEmailModel = new EmailModel(); + oEmailModel.parse(window.decodeURI(sMailToUrl.toString().substr(7).replace(/\?.+$/, ''))); + + if (oEmailModel && oEmailModel.email) + { + kn.showScreenPopup(PopupsComposeViewModel, [Enums.ComposeType.Empty, null, [oEmailModel]]); + return true; + } + } + + return false; +}; + +RainLoopApp.prototype.bootstart = function () +{ + RL.pub('rl.bootstart'); + AbstractApp.prototype.bootstart.call(this); + + RL.data().populateDataOnStart(); + + var + sCustomLoginLink = '', + sJsHash = RL.settingsGet('JsHash'), + iContactsSyncInterval = Utils.pInt(RL.settingsGet('ContactsSyncInterval')), + bGoogle = RL.settingsGet('AllowGoogleSocial'), + bFacebook = RL.settingsGet('AllowFacebookSocial'), + bTwitter = RL.settingsGet('AllowTwitterSocial') + ; + + if (!RL.settingsGet('ChangePasswordIsAllowed')) + { + Utils.removeSettingsViewModel(SettingsChangePasswordScreen); + } + + if (!RL.settingsGet('ContactsIsAllowed')) + { + Utils.removeSettingsViewModel(SettingsContacts); + } + + if (!RL.settingsGet('AllowAdditionalAccounts')) + { + Utils.removeSettingsViewModel(SettingsAccounts); + } + + if (RL.settingsGet('AllowIdentities')) + { + Utils.removeSettingsViewModel(SettingsIdentity); + } + else + { + Utils.removeSettingsViewModel(SettingsIdentities); + } + + if (!RL.settingsGet('OpenPGP')) + { + Utils.removeSettingsViewModel(SettingsOpenPGP); + } + + if (!RL.settingsGet('AllowTwoFactorAuth')) + { + Utils.removeSettingsViewModel(SettingsSecurity); + } + + if (!bGoogle && !bFacebook && !bTwitter) + { + Utils.removeSettingsViewModel(SettingsSocialScreen); + } + + if (!RL.settingsGet('AllowThemes')) + { + Utils.removeSettingsViewModel(SettingsThemes); + } + + Utils.initOnStartOrLangChange(function () { + + $.extend(true, $.magnificPopup.defaults, { + 'tClose': Utils.i18n('MAGNIFIC_POPUP/CLOSE'), + 'tLoading': Utils.i18n('MAGNIFIC_POPUP/LOADING'), + 'gallery': { + 'tPrev': Utils.i18n('MAGNIFIC_POPUP/GALLERY_PREV'), + 'tNext': Utils.i18n('MAGNIFIC_POPUP/GALLERY_NEXT'), + 'tCounter': Utils.i18n('MAGNIFIC_POPUP/GALLERY_COUNTER') + }, + 'image': { + 'tError': Utils.i18n('MAGNIFIC_POPUP/IMAGE_ERROR') + }, + 'ajax': { + 'tError': Utils.i18n('MAGNIFIC_POPUP/AJAX_ERROR') + } + }); + + }, this); + + if (window.SimplePace) + { + window.SimplePace.set(70); + window.SimplePace.sleep(); + } + + if (!!RL.settingsGet('Auth')) + { + this.setTitle(Utils.i18n('TITLES/LOADING')); + + this.folders(_.bind(function (bValue) { + + kn.hideLoading(); + + if (bValue) + { + if (window.crypto && window.crypto.getRandomValues && RL.settingsGet('OpenPGP')) + { + $.ajax({ + 'url': RL.link().openPgpJs(), + 'dataType': 'script', + 'cache': true, + 'success': function () { + if (window.openpgp) + { + RL.data().openpgpKeyring = new window.openpgp.Keyring(); + RL.data().allowOpenPGP(true); + + RL.pub('openpgp.init'); + + RL.reloadOpenPgpKeys(); + } + } + }); + } + else + { + RL.data().allowOpenPGP(false); + } + + kn.startScreens([MailBoxScreen, SettingsScreen]); + + if (bGoogle || bFacebook || bTwitter) + { + RL.socialUsers(true); + } + + RL.sub('interval.2m', function () { + RL.folderInformation('INBOX'); + }); + + RL.sub('interval.2m', function () { + var sF = RL.data().currentFolderFullNameRaw(); + if ('INBOX' !== sF) + { + RL.folderInformation(sF); + } + }); + + RL.sub('interval.3m', function () { + RL.folderInformationMultiply(); + }); + + RL.sub('interval.5m', function () { + RL.quota(); + }); + + RL.sub('interval.10m', function () { + RL.folders(); + }); + + iContactsSyncInterval = 5 <= iContactsSyncInterval ? iContactsSyncInterval : 20; + iContactsSyncInterval = 320 >= iContactsSyncInterval ? iContactsSyncInterval : 320; + + window.setInterval(function () { + RL.contactsSync(); + }, iContactsSyncInterval * 60000 + 5000); + + _.delay(function () { + RL.contactsSync(); + }, 5000); + + _.delay(function () { + RL.folderInformationMultiply(true); + }, 500); + + _.delay(function () { + + RL.emailsPicsHashes(); + + RL.remote().servicesPics(function (sResult, oData) { + if (Enums.StorageResultType.Success === sResult && oData && oData.Result) + { + RL.cache().setServicesData(oData.Result); + } + }); + + }, 2000); + + Plugins.runHook('rl-start-user-screens'); + RL.pub('rl.bootstart-user-screens'); + + if (!!RL.settingsGet('AccountSignMe') && window.navigator.registerProtocolHandler) + { + _.delay(function () { + try { + window.navigator.registerProtocolHandler('mailto', + window.location.protocol + '//' + window.location.host + window.location.pathname + '?mailto&to=%s', + '' + (RL.settingsGet('Title') || 'RainLoop')); + } catch(e) {} + + if (RL.settingsGet('MailToEmail')) + { + RL.mailToHelper(RL.settingsGet('MailToEmail')); + } + }, 500); + } + } + else + { + kn.startScreens([LoginScreen]); + + Plugins.runHook('rl-start-login-screens'); + RL.pub('rl.bootstart-login-screens'); + } + + if (window.SimplePace) + { + window.SimplePace.set(100); + } + + if (!Globals.bMobileDevice) + { + _.defer(function () { + Utils.initLayoutResizer('#rl-left', '#rl-right', Enums.ClientSideKeyName.FolderListSize); + }); + } + + }, this)); + } + else + { + sCustomLoginLink = Utils.pString(RL.settingsGet('CustomLoginLink')); + if (!sCustomLoginLink) + { + kn.hideLoading(); + kn.startScreens([LoginScreen]); + + Plugins.runHook('rl-start-login-screens'); + RL.pub('rl.bootstart-login-screens'); + + if (window.SimplePace) + { + window.SimplePace.set(100); + } + } + else + { + kn.routeOff(); + kn.setHash(RL.link().root(), true); + kn.routeOff(); + + _.defer(function () { + window.location.href = sCustomLoginLink; + }); + } + } + + if (bGoogle) + { + window['rl_' + sJsHash + '_google_service'] = function () { + RL.data().googleActions(true); + RL.socialUsers(); + }; + } + + if (bFacebook) + { + window['rl_' + sJsHash + '_facebook_service'] = function () { + RL.data().facebookActions(true); + RL.socialUsers(); + }; + } + + if (bTwitter) + { + window['rl_' + sJsHash + '_twitter_service'] = function () { + RL.data().twitterActions(true); + RL.socialUsers(); + }; + } + + RL.sub('interval.1m', function () { + Globals.momentTrigger(!Globals.momentTrigger()); + }); + + Plugins.runHook('rl-start-screens'); + RL.pub('rl.bootstart-end'); +}; + +/** + * @type {RainLoopApp} + */ +RL = new RainLoopApp(); + +$html.addClass(Globals.bMobileDevice ? 'mobile' : 'no-mobile'); + +$window.keydown(Utils.killCtrlAandS).keyup(Utils.killCtrlAandS); +$window.unload(function () { + Globals.bUnload = true; +}); + +$html.on('click.dropdown.data-api', function () { + Utils.detectDropdownVisibility(); +}); + +// export +window['rl'] = window['rl'] || {}; +window['rl']['addHook'] = Plugins.addHook; +window['rl']['settingsGet'] = Plugins.mainSettingsGet; +window['rl']['remoteRequest'] = Plugins.remoteRequest; +window['rl']['pluginSettingsGet'] = Plugins.settingsGet; +window['rl']['addSettingsViewModel'] = Utils.addSettingsViewModel; +window['rl']['createCommand'] = Utils.createCommand; + +window['rl']['EmailModel'] = EmailModel; +window['rl']['Enums'] = Enums; + +window['__RLBOOT'] = function (fCall) { + + // boot + $(function () { + + if (window['rainloopTEMPLATES'] && window['rainloopTEMPLATES'][0]) + { + $('#rl-templates').html(window['rainloopTEMPLATES'][0]); + + _.delay(function () { + window['rainloopAppData'] = {}; + window['rainloopI18N'] = {}; + window['rainloopTEMPLATES'] = {}; + + kn.setBoot(RL).bootstart(); + $html.removeClass('no-js rl-booted-trigger').addClass('rl-booted'); + + }, 50); + } + else + { + fCall(false); + } + + window['__RLBOOT'] = null; + }); +}; + +if (window.SimplePace) { + window.SimplePace.add(10); } }(window, jQuery, ko, crossroads, hasher, moment, Jua, _, ifvisible, key)); \ No newline at end of file diff --git a/rainloop/v/0.0.0/static/js/app.min.js b/rainloop/v/0.0.0/static/js/app.min.js index 378edf62f..52b41d03c 100644 --- a/rainloop/v/0.0.0/static/js/app.min.js +++ b/rainloop/v/0.0.0/static/js/app.min.js @@ -1,10 +1,10 @@ /*! RainLoop Webmail Main Module (c) RainLoop Team | Licensed under CC BY-NC-SA 3.0 */ -!function(a,b,c,d,e,f,g,h,i,j){"use strict";function k(){this.sBase="#/",this.sVersion=Ob.settingsGet("Version"),this.sSpecSuffix=Ob.settingsGet("AuthAccountHash")||"0",this.sServer=(Ob.settingsGet("IndexFile")||"./")+"?"}function l(a,c,d,e){var f=this;f.editor=null,f.iBlurTimer=0,f.fOnBlur=c||null,f.fOnReady=d||null,f.fOnModeChange=e||null,f.$element=b(a),f.init()}function m(a,b,d,e,f,g){this.list=a,this.listChecked=c.computed(function(){return h.filter(this.list(),function(a){return a.checked()})},this).extend({rateLimit:0}),this.isListChecked=c.computed(function(){return 00&&-1 b?b:a))},this),this.body=null,this.plainRaw="",this.isRtl=c.observable(!1),this.isHtml=c.observable(!1),this.hasImages=c.observable(!1),this.attachments=c.observableArray([]),this.isPgpSigned=c.observable(!1),this.isPgpEncrypted=c.observable(!1),this.pgpSignedVerifyStatus=c.observable(zb.SignedVerifyStatus.None),this.pgpSignedVerifyUser=c.observable(""),this.priority=c.observable(zb.MessagePriority.Normal),this.readReceipt=c.observable(""),this.aDraftInfo=[],this.sMessageId="",this.sInReplyTo="",this.sReferences="",this.parentUid=c.observable(0),this.threads=c.observableArray([]),this.threadsLen=c.observable(0),this.hasUnseenSubMessage=c.observable(!1),this.hasFlaggedSubMessage=c.observable(!1),this.lastInCollapsedThread=c.observable(!1),this.lastInCollapsedThreadLoading=c.observable(!1),this.threadsLenResult=c.computed(function(){var a=this.threadsLen();return 0===this.parentUid()&&a>0?a+1:""},this)}function A(){this.name=c.observable(""),this.fullName="",this.fullNameRaw="",this.fullNameHash="",this.delimiter="",this.namespace="",this.deep=0,this.interval=0,this.selectable=!1,this.existen=!0,this.type=c.observable(zb.FolderType.User),this.focused=c.observable(!1),this.selected=c.observable(!1),this.edited=c.observable(!1),this.collapsed=c.observable(!0),this.subScribed=c.observable(!0),this.subFolders=c.observableArray([]),this.deleteAccess=c.observable(!1),this.actionBlink=c.observable(!1).extend({falseTimeout:1e3}),this.nameForEdit=c.observable(""),this.name.subscribe(function(a){this.nameForEdit(a)},this),this.edited.subscribe(function(a){a&&this.nameForEdit(this.name())},this),this.privateMessageCountAll=c.observable(0),this.privateMessageCountUnread=c.observable(0),this.collapsedPrivate=c.observable(!0)}function B(a,b){this.email=a,this.deleteAccess=c.observable(!1),this.canBeDalete=c.observable(b)}function C(a,b,d){this.id=a,this.email=c.observable(b),this.name=c.observable(""),this.replyTo=c.observable(""),this.bcc=c.observable(""),this.deleteAccess=c.observable(!1),this.canBeDalete=c.observable(d)}function D(a,b,d,e,f,g,h){this.index=a,this.id=d,this.guid=b,this.user=e,this.email=f,this.armor=h,this.isPrivate=!!g,this.deleteAccess=c.observable(!1)}function E(){r.call(this,"Popups","PopupsFolderClear"),this.selectedFolder=c.observable(null),this.clearingProcess=c.observable(!1),this.clearingError=c.observable(""),this.folderFullNameForClear=c.computed(function(){var a=this.selectedFolder();return a?a.printableFullName():""},this),this.folderNameForClear=c.computed(function(){var a=this.selectedFolder();return a?a.localName():""},this),this.dangerDescHtml=c.computed(function(){return Bb.i18n("POPUPS_CLEAR_FOLDER/DANGER_DESC_HTML_1",{FOLDER:this.folderNameForClear()})},this),this.clearCommand=Bb.createCommand(this,function(){var a=this,b=this.selectedFolder();b&&(Ob.data().message(null),Ob.data().messageList([]),this.clearingProcess(!0),Ob.cache().setFolderHash(b.fullNameRaw,""),Ob.remote().folderClear(function(b,c){a.clearingProcess(!1),zb.StorageResultType.Success===b&&c&&c.Result?(Ob.reloadMessageList(!0),a.cancelCommand()):c&&c.ErrorCode?a.clearingError(Bb.getNotification(c.ErrorCode)):a.clearingError(Bb.getNotification(zb.Notification.MailServerError))},b.fullNameRaw))},function(){var a=this.selectedFolder(),b=this.clearingProcess();return!b&&null!==a}),t.constructorEnd(this)}function F(){r.call(this,"Popups","PopupsFolderCreate"),Bb.initOnStartOrLangChange(function(){this.sNoParentText=Bb.i18n("POPUPS_CREATE_FOLDER/SELECT_NO_PARENT")},this),this.folderName=c.observable(""),this.folderName.focused=c.observable(!1),this.selectedParentValue=c.observable(yb.Values.UnuseOptionValue),this.parentFolderSelectList=c.computed(function(){var a=Ob.data(),b=[],c=null,d=null,e=a.folderList(),f=function(a){return a?a.isSystemFolder()?a.name()+" "+a.manageFolderSystemName():a.name():""};return b.push(["",this.sNoParentText]),""!==a.namespace&&(c=function(b){return a.namespace!==b.fullNameRaw.substr(0,a.namespace.length)}),Ob.folderListOptionsBuilder([],e,[],b,null,c,d,f)},this),this.createFolder=Bb.createCommand(this,function(){var a=Ob.data(),b=this.selectedParentValue();""===b&&1 =a?1:a},this),this.contactsPagenator=c.computed(Bb.computedPagenatorHelper(this.contactsPage,this.contactsPageCount)),this.emptySelection=c.observable(!0),this.viewClearSearch=c.observable(!1),this.viewID=c.observable(""),this.viewReadOnly=c.observable(!1),this.viewProperties=c.observableArray([]),this.viewSaveTrigger=c.observable(zb.SaveSettingsStep.Idle),this.viewPropertiesNames=this.viewProperties.filter(function(a){return-1 a)break;b[0]&&b[1]&&b[2]&&b[1]===b[2]&&("PRIVATE"===b[1]?e.privateKeys.importKey(b[0]):"PUBLIC"===b[1]&&e.publicKeys.importKey(b[0])),a--}return e.store(),Ob.reloadOpenPgpKeys(),Bb.delegateRun(this,"cancelCommand"),!0}),t.constructorEnd(this)}function M(){r.call(this,"Popups","PopupsViewOpenPgpKey"),this.key=c.observable(""),this.keyDom=c.observable(null),t.constructorEnd(this)}function N(){r.call(this,"Popups","PopupsGenerateNewOpenPgpKey"),this.email=c.observable(""),this.email.focus=c.observable(""),this.email.error=c.observable(!1),this.name=c.observable(""),this.password=c.observable(""),this.keyBitLength=c.observable(2048),this.submitRequest=c.observable(!1),this.email.subscribe(function(){this.email.error(!1)},this),this.generateOpenPgpKeyCommand=Bb.createCommand(this,function(){var b=this,c="",d=null,e=Ob.data().openpgpKeyring;return this.email.error(""===Bb.trim(this.email())),!e||this.email.error()?!1:(c=this.email(),""!==this.name()&&(c=this.name()+" <"+c+">"),this.submitRequest(!0),h.delay(function(){d=a.openpgp.generateKeyPair(1,Bb.pInt(b.keyBitLength()),c,Bb.trim(b.password())),d&&d.privateKeyArmored&&(e.privateKeys.importKey(d.privateKeyArmored),e.publicKeys.importKey(d.publicKeyArmored),e.store(),Ob.reloadOpenPgpKeys(),Bb.delegateRun(b,"cancelCommand")),b.submitRequest(!1)},100),!0)}),t.constructorEnd(this)}function O(){r.call(this,"Popups","PopupsComposeOpenPgp"),this.notification=c.observable(""),this.sign=c.observable(!0),this.encrypt=c.observable(!0),this.password=c.observable(""),this.password.focus=c.observable(!1),this.buttonFocus=c.observable(!1),this.from=c.observable(""),this.to=c.observableArray([]),this.text=c.observable(""),this.resultCallback=null,this.submitRequest=c.observable(!1),this.doCommand=Bb.createCommand(this,function(){var b=this,c=!0,d=Ob.data(),e=null,f=[];this.submitRequest(!0),c&&this.sign()&&""===this.from()&&(this.notification(Bb.i18n("PGP_NOTIFICATIONS/SPECIFY_FROM_EMAIL")),c=!1),c&&this.sign()&&(e=d.findPrivateKeyByEmail(this.from(),this.password()),e||(this.notification(Bb.i18n("PGP_NOTIFICATIONS/NO_PRIVATE_KEY_FOUND_FOR",{EMAIL:this.from()})),c=!1)),c&&this.encrypt()&&0===this.to().length&&(this.notification(Bb.i18n("PGP_NOTIFICATIONS/SPECIFY_AT_LEAST_ONE_RECIPIENT")),c=!1),c&&this.encrypt()&&(f=[],h.each(this.to(),function(a){var e=d.findPublicKeysByEmail(a);0===e.length&&c&&(b.notification(Bb.i18n("PGP_NOTIFICATIONS/NO_PUBLIC_KEYS_FOUND_FOR",{EMAIL:a})),c=!1),f=f.concat(e)}),!c||0!==f.length&&this.to().length===f.length||(c=!1)),h.delay(function(){if(b.resultCallback&&c)try{e&&0===f.length?b.resultCallback(a.openpgp.signClearMessage([e],b.text())):e&&0 0&&b>0&&a>b},this),this.hasMessages=c.computed(function(){return 0 '),e.after(f),e.remove()),f&&f[0]&&(f.attr("data-href",g).attr("data-theme",a[0]),f&&f[0]&&f[0].styleSheet&&!Bb.isUnd(f[0].styleSheet.cssText)?f[0].styleSheet.cssText=a[1]:f.text(a[1])),d.themeTrigger(zb.SaveSettingsStep.TrueResult))}).always(function(){d.iTimer=a.setTimeout(function(){d.themeTrigger(zb.SaveSettingsStep.Idle)},1e3),d.oLastAjax=null})),Ob.remote().saveSettings(null,{Theme:c})},this)}function lb(){this.openpgpkeys=Ob.data().openpgpkeys,this.openpgpkeysPublic=Ob.data().openpgpkeysPublic,this.openpgpkeysPrivate=Ob.data().openpgpkeysPrivate,this.openPgpKeyForDeletion=c.observable(null).extend({falseTimeout:3e3}).extend({toggleSubscribe:[this,function(a){a&&a.deleteAccess(!1)},function(a){a&&a.deleteAccess(!0)}]})}function mb(){this.leftPanelDisabled=c.observable(!1),this.useKeyboardShortcuts=c.observable(!0),this.keyScopeReal=c.observable(zb.KeyState.All),this.keyScopeFake=c.observable(zb.KeyState.All),this.keyScope=c.computed({owner:this,read:function(){return this.keyScopeFake()},write:function(a){zb.KeyState.Menu!==a&&(zb.KeyState.Compose===a?Bb.disableKeyFilter():Bb.restoreKeyFilter(),this.keyScopeFake(a),Eb.dropdownVisibility()&&(a=zb.KeyState.Menu)),this.keyScopeReal(a)}}),this.keyScopeReal.subscribe(function(a){j.setScope(a)}),this.leftPanelDisabled.subscribe(function(a){Ob.pub("left-panel."+(a?"off":"on"))}),Eb.dropdownVisibility.subscribe(function(a){a?this.keyScope(zb.KeyState.Menu):zb.KeyState.Menu===j.getScope()&&this.keyScope(this.keyScopeFake())},this),Bb.initDataConstructorBySettings(this)}function nb(){mb.call(this);var d=function(a){return function(){var b=Ob.cache().getFolderFromCacheList(a());b&&b.type(zb.FolderType.User)}},e=function(a){return function(b){var c=Ob.cache().getFolderFromCacheList(b);c&&c.type(a)}};this.devEmail="",this.devLogin="",this.devPassword="",this.accountEmail=c.observable(""),this.accountIncLogin=c.observable(""),this.accountOutLogin=c.observable(""),this.projectHash=c.observable(""),this.threading=c.observable(!1),this.lastFoldersHash="",this.remoteSuggestions=!1,this.sentFolder=c.observable(""),this.draftFolder=c.observable(""),this.spamFolder=c.observable(""),this.trashFolder=c.observable(""),this.archiveFolder=c.observable(""),this.sentFolder.subscribe(d(this.sentFolder),this,"beforeChange"),this.draftFolder.subscribe(d(this.draftFolder),this,"beforeChange"),this.spamFolder.subscribe(d(this.spamFolder),this,"beforeChange"),this.trashFolder.subscribe(d(this.trashFolder),this,"beforeChange"),this.archiveFolder.subscribe(d(this.archiveFolder),this,"beforeChange"),this.sentFolder.subscribe(e(zb.FolderType.SentItems),this),this.draftFolder.subscribe(e(zb.FolderType.Draft),this),this.spamFolder.subscribe(e(zb.FolderType.Spam),this),this.trashFolder.subscribe(e(zb.FolderType.Trash),this),this.archiveFolder.subscribe(e(zb.FolderType.Archive),this),this.draftFolderNotEnabled=c.computed(function(){return""===this.draftFolder()||yb.Values.UnuseOptionValue===this.draftFolder()},this),this.displayName=c.observable(""),this.signature=c.observable(""),this.signatureToAll=c.observable(!1),this.replyTo=c.observable(""),this.enableTwoFactor=c.observable(!1),this.accounts=c.observableArray([]),this.accountsLoading=c.observable(!1).extend({throttle:100}),this.identities=c.observableArray([]),this.identitiesLoading=c.observable(!1).extend({throttle:100}),this.contacts=c.observableArray([]),this.contacts.loading=c.observable(!1).extend({throttle:200}),this.contacts.importing=c.observable(!1).extend({throttle:200}),this.contacts.syncing=c.observable(!1).extend({throttle:200}),this.contacts.exportingVcf=c.observable(!1).extend({throttle:200}),this.contacts.exportingCsv=c.observable(!1).extend({throttle:200}),this.allowContactsSync=c.observable(!1),this.enableContactsSync=c.observable(!1),this.contactsSyncUrl=c.observable(""),this.contactsSyncUser=c.observable(""),this.contactsSyncPass=c.observable(""),this.allowContactsSync=c.observable(!!Ob.settingsGet("ContactsSyncIsAllowed")),this.enableContactsSync=c.observable(!!Ob.settingsGet("EnableContactsSync")),this.contactsSyncUrl=c.observable(Ob.settingsGet("ContactsSyncUrl")),this.contactsSyncUser=c.observable(Ob.settingsGet("ContactsSyncUser")),this.contactsSyncPass=c.observable(Ob.settingsGet("ContactsSyncPassword")),this.namespace="",this.folderList=c.observableArray([]),this.folderList.focused=c.observable(!1),this.foldersListError=c.observable(""),this.foldersLoading=c.observable(!1),this.foldersCreating=c.observable(!1),this.foldersDeleting=c.observable(!1),this.foldersRenaming=c.observable(!1),this.foldersChanging=c.computed(function(){var a=this.foldersLoading(),b=this.foldersCreating(),c=this.foldersDeleting(),d=this.foldersRenaming();return a||b||c||d},this),this.foldersInboxUnreadCount=c.observable(0),this.currentFolder=c.observable(null).extend({toggleSubscribe:[null,function(a){a&&a.selected(!1)},function(a){a&&a.selected(!0)}]}),this.currentFolderFullNameRaw=c.computed(function(){return this.currentFolder()?this.currentFolder().fullNameRaw:""},this),this.currentFolderFullName=c.computed(function(){return this.currentFolder()?this.currentFolder().fullName:""},this),this.currentFolderFullNameHash=c.computed(function(){return this.currentFolder()?this.currentFolder().fullNameHash:""},this),this.currentFolderName=c.computed(function(){return this.currentFolder()?this.currentFolder().name():""},this),this.folderListSystemNames=c.computed(function(){var a=["INBOX"],b=this.folderList(),c=this.sentFolder(),d=this.draftFolder(),e=this.spamFolder(),f=this.trashFolder(),g=this.archiveFolder(); -return Bb.isArray(b)&&0 =a?1:a},this),this.mainMessageListSearch=c.computed({read:this.messageListSearch,write:function(a){Hb.setHash(Ob.link().mailBox(this.currentFolderFullNameHash(),1,Bb.trim(a.toString())))},owner:this}),this.messageListError=c.observable(""),this.messageListLoading=c.observable(!1),this.messageListIsNotCompleted=c.observable(!1),this.messageListCompleteLoadingThrottle=c.observable(!1).extend({throttle:200}),this.messageListCompleteLoading=c.computed(function(){var a=this.messageListLoading(),b=this.messageListIsNotCompleted();return a||b},this),this.messageListCompleteLoading.subscribe(function(a){this.messageListCompleteLoadingThrottle(a)},this),this.messageList.subscribe(h.debounce(function(a){h.each(a,function(a){a.newForAnimation()&&a.newForAnimation(!1)})},500)),this.staticMessageList=new z,this.message=c.observable(null),this.messageLoading=c.observable(!1),this.messageLoadingThrottle=c.observable(!1).extend({throttle:50}),this.message.focused=c.observable(!1),this.message.subscribe(function(b){b?zb.Layout.NoPreview===this.layout()&&this.message.focused(!0):(this.message.focused(!1),this.hideMessageBodies(),zb.Layout.NoPreview===Ob.data().layout()&&-1 0?Math.ceil(b/a*100):0},this),this.allowOpenPGP=c.observable(!1),this.openpgpkeys=c.observableArray([]),this.openpgpKeyring=null,this.openpgpkeysPublic=this.openpgpkeys.filter(function(a){return!(!a||a.isPrivate)}),this.openpgpkeysPrivate=this.openpgpkeys.filter(function(a){return!(!a||!a.isPrivate)}),this.googleActions=c.observable(!1),this.googleLoggined=c.observable(!1),this.googleUserName=c.observable(""),this.facebookActions=c.observable(!1),this.facebookLoggined=c.observable(!1),this.facebookUserName=c.observable(""),this.twitterActions=c.observable(!1),this.twitterLoggined=c.observable(!1),this.twitterUserName=c.observable(""),this.customThemeType=c.observable(zb.CustomThemeType.Light),this.purgeMessageBodyCacheThrottle=h.throttle(this.purgeMessageBodyCache,3e4)}function ob(){this.oRequests={}}function pb(){ob.call(this),this.oRequests={}}function qb(){this.oEmailsPicsHashes={},this.oServices={},this.bAllowGravatar=!!Ob.settingsGet("AllowGravatar")}function rb(){qb.call(this),this.oFoldersCache={},this.oFoldersNamesCache={},this.oFolderHashCache={},this.oFolderUidNextCache={},this.oMessageListHashCache={},this.oMessageFlagsCache={},this.oNewMessage={},this.oRequestedMessage={}}function sb(a){s.call(this,"settings",a),this.menu=c.observableArray([]),this.oCurrentSubScreen=null,this.oViewModelPlace=null}function tb(){s.call(this,"login",[U])}function ub(){s.call(this,"mailbox",[W,Y,Z,$]),this.oLastRoute={}}function vb(){sb.call(this,[X,_,ab]),Bb.initOnStartOrLangChange(function(){this.sSettingsTitle=Bb.i18n("TITLES/SETTINGS")},this,function(){Ob.setTitle(this.sSettingsTitle)})}function wb(){q.call(this),this.oSettings=null,this.oPlugins=null,this.oLocal=null,this.oLink=null,this.oSubs={},this.isLocalAutocomplete=!0,this.popupVisibilityNames=c.observableArray([]),this.popupVisibility=c.computed(function(){return 0 ').appendTo("body"),Lb.on("error",function(a){Ob&&a&&a.originalEvent&&a.originalEvent.message&&-1===Bb.inArray(a.originalEvent.message,["Script error.","Uncaught Error: Error calling method on NPObject."])&&Ob.remote().jsError(Bb.emptyFunction,a.originalEvent.message,a.originalEvent.filename,a.originalEvent.lineno,location&&location.toString?location.toString():"",Kb.attr("class"),Bb.microtime()-Eb.now)}),Mb.on("keydown",function(a){a&&a.ctrlKey&&Kb.addClass("rl-ctrl-key-pressed")}).on("keyup",function(a){a&&!a.ctrlKey&&Kb.removeClass("rl-ctrl-key-pressed")})}function xb(){wb.call(this),this.oData=null,this.oRemote=null,this.oCache=null,this.oMoveCache={},this.quotaDebounce=h.debounce(this.quota,3e4),this.moveOrDeleteResponseHelper=h.bind(this.moveOrDeleteResponseHelper,this),this.messagesMoveTrigger=h.debounce(this.messagesMoveTrigger,500),a.setInterval(function(){Ob.pub("interval.30s")},3e4),a.setInterval(function(){Ob.pub("interval.1m")},6e4),a.setInterval(function(){Ob.pub("interval.2m")},12e4),a.setInterval(function(){Ob.pub("interval.3m")},18e4),a.setInterval(function(){Ob.pub("interval.5m")},3e5),a.setInterval(function(){Ob.pub("interval.10m")},6e5),a.setTimeout(function(){a.setInterval(function(){Ob.pub("interval.10m-after5m")},6e5)},3e5),b.wakeUp(function(){Ob.remote().jsVersion(function(b,c){zb.StorageResultType.Success===b&&c&&!c.Result&&(a.parent&&Ob.settingsGet("InIframe")?a.parent.location.reload():a.location.reload())},Ob.settingsGet("Version"))},{},36e5)}var yb={},zb={},Ab={},Bb={},Cb={},Db={},Eb={},Fb={settings:[],"settings-removed":[],"settings-disabled":[]},Gb=[],Hb=null,Ib=a.rainloopAppData||{},Jb=a.rainloopI18N||{},Kb=b("html"),Lb=b(a),Mb=b(a.document),Nb=a.Notification&&a.Notification.requestPermission?a.Notification:null,Ob=null,Pb=b("");Eb.now=(new Date).getTime(),Eb.momentTrigger=c.observable(!0),Eb.dropdownVisibility=c.observable(!1).extend({rateLimit:0}),Eb.langChangeTrigger=c.observable(!0),Eb.iAjaxErrorCount=0,Eb.iTokenErrorCount=0,Eb.iMessageBodyCacheCount=0,Eb.bUnload=!1,Eb.sUserAgent=(navigator.userAgent||"").toLowerCase(),Eb.bIsiOSDevice=-1 /g,">").replace(/"/g,""").replace(/'/g,"'"):""},Bb.splitPlainText=function(a,b){var c="",d="",e=a,f=0,g=0;for(b=Bb.isUnd(b)?100:b;e.length>b;)d=e.substring(0,b),f=d.lastIndexOf(" "),g=d.lastIndexOf("\n"),-1!==g&&(f=g),-1===f&&(f=b),c+=d.substring(0,f)+"\n",e=e.substring(f+1);return c+e},Bb.timeOutAction=function(){var b={};return function(c,d,e){Bb.isUnd(b[c])&&(b[c]=0),a.clearTimeout(b[c]),b[c]=a.setTimeout(d,e)}}(),Bb.timeOutActionSecond=function(){var b={};return function(c,d,e){b[c]||(b[c]=a.setTimeout(function(){d(),b[c]=0},e))}}(),Bb.audio=function(){var b=!1;return function(c,d){if(!1===b)if(Eb.bIsiOSDevice)b=null;else{var e=!1,f=!1,g=a.Audio?new a.Audio:null;g&&g.canPlayType&&g.play?(e=""!==g.canPlayType('audio/mpeg; codecs="mp3"'),e||(f=""!==g.canPlayType('audio/ogg; codecs="vorbis"')),e||f?(b=g,b.preload="none",b.loop=!1,b.autoplay=!1,b.muted=!1,b.src=e?c:d):b=null):b=null}return b}}(),Bb.hos=function(a,b){return a&&Object.hasOwnProperty?Object.hasOwnProperty.call(a,b):!1},Bb.i18n=function(a,b,c){var d="",e=Bb.isUnd(Jb[a])?Bb.isUnd(c)?a:c:Jb[a];if(!Bb.isUnd(b)&&!Bb.isNull(b))for(d in b)Bb.hos(b,d)&&(e=e.replace("%"+d+"%",b[d]));return e},Bb.i18nToNode=function(a){h.defer(function(){b(".i18n",a).each(function(){var a=b(this),c="";c=a.data("i18n-text"),c?a.text(Bb.i18n(c)):(c=a.data("i18n-html"),c&&a.html(Bb.i18n(c)),c=a.data("i18n-placeholder"),c&&a.attr("placeholder",Bb.i18n(c)),c=a.data("i18n-title"),c&&a.attr("title",Bb.i18n(c)))})})},Bb.i18nToDoc=function(){a.rainloopI18N&&(Jb=a.rainloopI18N||{},Bb.i18nToNode(Mb),Eb.langChangeTrigger(!Eb.langChangeTrigger())),a.rainloopI18N={}},Bb.initOnStartOrLangChange=function(a,b,c){a&&a.call(b),c?Eb.langChangeTrigger.subscribe(function(){a&&a.call(b),c.call(b)}):a&&Eb.langChangeTrigger.subscribe(a,b)},Bb.inFocus=function(){var a=document.activeElement;return a&&("INPUT"===a.tagName||"TEXTAREA"===a.tagName||"IFRAME"===a.tagName||"DIV"===a.tagName&&"editorHtmlArea"===a.className&&a.contentEditable)},Bb.removeInFocus=function(){if(document&&document.activeElement&&document.activeElement.blur){var a=b(document.activeElement);(a.is("input")||a.is("textarea"))&&document.activeElement.blur()}},Bb.removeSelection=function(){if(a&&a.getSelection){var b=a.getSelection();b&&b.removeAllRanges&&b.removeAllRanges()}else document&&document.selection&&document.selection.empty&&document.selection.empty()},Bb.replySubjectAdd=function(b,c,d){var e=null,f=Bb.trim(c);return f=null===(e=new a.RegExp("^"+b+"[\\s]?\\:(.*)$","gi").exec(c))||Bb.isUnd(e[1])?null===(e=new a.RegExp("^("+b+"[\\s]?[\\[\\(]?)([\\d]+)([\\]\\)]?[\\s]?\\:.*)$","gi").exec(c))||Bb.isUnd(e[1])||Bb.isUnd(e[2])||Bb.isUnd(e[3])?b+": "+c:e[1]+(Bb.pInt(e[2])+1)+e[3]:b+"[2]: "+e[1],f=f.replace(/[\s]+/g," "),f=(Bb.isUnd(d)?!0:d)?Bb.fixLongSubject(f):f},Bb.fixLongSubject=function(a){var b=0,c=null;a=Bb.trim(a.replace(/[\s]+/," "));do c=/^Re(\[([\d]+)\]|):[\s]{0,3}Re(\[([\d]+)\]|):/gi.exec(a),(!c||Bb.isUnd(c[0]))&&(c=null),c&&(b=0,b+=Bb.isUnd(c[2])?1:0+Bb.pInt(c[2]),b+=Bb.isUnd(c[4])?1:0+Bb.pInt(c[4]),a=a.replace(/^Re(\[[\d]+\]|):[\s]{0,3}Re(\[[\d]+\]|):/gi,"Re"+(b>0?"["+b+"]":"")+":"));while(c);return a=a.replace(/[\s]+/," ")},Bb.roundNumber=function(a,b){return Math.round(a*Math.pow(10,b))/Math.pow(10,b)},Bb.friendlySize=function(a){return a=Bb.pInt(a),a>=1073741824?Bb.roundNumber(a/1073741824,1)+"GB":a>=1048576?Bb.roundNumber(a/1048576,1)+"MB":a>=1024?Bb.roundNumber(a/1024,0)+"KB":a+"B"},Bb.log=function(b){a.console&&a.console.log&&a.console.log(b)},Bb.getNotification=function(a,b){return a=Bb.pInt(a),zb.Notification.ClientViewError===a&&b?b:Bb.isUnd(Ab[a])?"":Ab[a]},Bb.initNotificationLanguage=function(){Ab[zb.Notification.InvalidToken]=Bb.i18n("NOTIFICATIONS/INVALID_TOKEN"),Ab[zb.Notification.AuthError]=Bb.i18n("NOTIFICATIONS/AUTH_ERROR"),Ab[zb.Notification.AccessError]=Bb.i18n("NOTIFICATIONS/ACCESS_ERROR"),Ab[zb.Notification.ConnectionError]=Bb.i18n("NOTIFICATIONS/CONNECTION_ERROR"),Ab[zb.Notification.CaptchaError]=Bb.i18n("NOTIFICATIONS/CAPTCHA_ERROR"),Ab[zb.Notification.SocialFacebookLoginAccessDisable]=Bb.i18n("NOTIFICATIONS/SOCIAL_FACEBOOK_LOGIN_ACCESS_DISABLE"),Ab[zb.Notification.SocialTwitterLoginAccessDisable]=Bb.i18n("NOTIFICATIONS/SOCIAL_TWITTER_LOGIN_ACCESS_DISABLE"),Ab[zb.Notification.SocialGoogleLoginAccessDisable]=Bb.i18n("NOTIFICATIONS/SOCIAL_GOOGLE_LOGIN_ACCESS_DISABLE"),Ab[zb.Notification.DomainNotAllowed]=Bb.i18n("NOTIFICATIONS/DOMAIN_NOT_ALLOWED"),Ab[zb.Notification.AccountNotAllowed]=Bb.i18n("NOTIFICATIONS/ACCOUNT_NOT_ALLOWED"),Ab[zb.Notification.AccountTwoFactorAuthRequired]=Bb.i18n("NOTIFICATIONS/ACCOUNT_TWO_FACTOR_AUTH_REQUIRED"),Ab[zb.Notification.AccountTwoFactorAuthError]=Bb.i18n("NOTIFICATIONS/ACCOUNT_TWO_FACTOR_AUTH_ERROR"),Ab[zb.Notification.CouldNotSaveNewPassword]=Bb.i18n("NOTIFICATIONS/COULD_NOT_SAVE_NEW_PASSWORD"),Ab[zb.Notification.CurrentPasswordIncorrect]=Bb.i18n("NOTIFICATIONS/CURRENT_PASSWORD_INCORRECT"),Ab[zb.Notification.NewPasswordShort]=Bb.i18n("NOTIFICATIONS/NEW_PASSWORD_SHORT"),Ab[zb.Notification.NewPasswordWeak]=Bb.i18n("NOTIFICATIONS/NEW_PASSWORD_WEAK"),Ab[zb.Notification.NewPasswordForbidden]=Bb.i18n("NOTIFICATIONS/NEW_PASSWORD_FORBIDDENT"),Ab[zb.Notification.ContactsSyncError]=Bb.i18n("NOTIFICATIONS/CONTACTS_SYNC_ERROR"),Ab[zb.Notification.CantGetMessageList]=Bb.i18n("NOTIFICATIONS/CANT_GET_MESSAGE_LIST"),Ab[zb.Notification.CantGetMessage]=Bb.i18n("NOTIFICATIONS/CANT_GET_MESSAGE"),Ab[zb.Notification.CantDeleteMessage]=Bb.i18n("NOTIFICATIONS/CANT_DELETE_MESSAGE"),Ab[zb.Notification.CantMoveMessage]=Bb.i18n("NOTIFICATIONS/CANT_MOVE_MESSAGE"),Ab[zb.Notification.CantCopyMessage]=Bb.i18n("NOTIFICATIONS/CANT_MOVE_MESSAGE"),Ab[zb.Notification.CantSaveMessage]=Bb.i18n("NOTIFICATIONS/CANT_SAVE_MESSAGE"),Ab[zb.Notification.CantSendMessage]=Bb.i18n("NOTIFICATIONS/CANT_SEND_MESSAGE"),Ab[zb.Notification.InvalidRecipients]=Bb.i18n("NOTIFICATIONS/INVALID_RECIPIENTS"),Ab[zb.Notification.CantCreateFolder]=Bb.i18n("NOTIFICATIONS/CANT_CREATE_FOLDER"),Ab[zb.Notification.CantRenameFolder]=Bb.i18n("NOTIFICATIONS/CANT_RENAME_FOLDER"),Ab[zb.Notification.CantDeleteFolder]=Bb.i18n("NOTIFICATIONS/CANT_DELETE_FOLDER"),Ab[zb.Notification.CantDeleteNonEmptyFolder]=Bb.i18n("NOTIFICATIONS/CANT_DELETE_NON_EMPTY_FOLDER"),Ab[zb.Notification.CantSubscribeFolder]=Bb.i18n("NOTIFICATIONS/CANT_SUBSCRIBE_FOLDER"),Ab[zb.Notification.CantUnsubscribeFolder]=Bb.i18n("NOTIFICATIONS/CANT_UNSUBSCRIBE_FOLDER"),Ab[zb.Notification.CantSaveSettings]=Bb.i18n("NOTIFICATIONS/CANT_SAVE_SETTINGS"),Ab[zb.Notification.CantSavePluginSettings]=Bb.i18n("NOTIFICATIONS/CANT_SAVE_PLUGIN_SETTINGS"),Ab[zb.Notification.DomainAlreadyExists]=Bb.i18n("NOTIFICATIONS/DOMAIN_ALREADY_EXISTS"),Ab[zb.Notification.CantInstallPackage]=Bb.i18n("NOTIFICATIONS/CANT_INSTALL_PACKAGE"),Ab[zb.Notification.CantDeletePackage]=Bb.i18n("NOTIFICATIONS/CANT_DELETE_PACKAGE"),Ab[zb.Notification.InvalidPluginPackage]=Bb.i18n("NOTIFICATIONS/INVALID_PLUGIN_PACKAGE"),Ab[zb.Notification.UnsupportedPluginPackage]=Bb.i18n("NOTIFICATIONS/UNSUPPORTED_PLUGIN_PACKAGE"),Ab[zb.Notification.LicensingServerIsUnavailable]=Bb.i18n("NOTIFICATIONS/LICENSING_SERVER_IS_UNAVAILABLE"),Ab[zb.Notification.LicensingExpired]=Bb.i18n("NOTIFICATIONS/LICENSING_EXPIRED"),Ab[zb.Notification.LicensingBanned]=Bb.i18n("NOTIFICATIONS/LICENSING_BANNED"),Ab[zb.Notification.DemoSendMessageError]=Bb.i18n("NOTIFICATIONS/DEMO_SEND_MESSAGE_ERROR"),Ab[zb.Notification.AccountAlreadyExists]=Bb.i18n("NOTIFICATIONS/ACCOUNT_ALREADY_EXISTS"),Ab[zb.Notification.MailServerError]=Bb.i18n("NOTIFICATIONS/MAIL_SERVER_ERROR"),Ab[zb.Notification.UnknownNotification]=Bb.i18n("NOTIFICATIONS/UNKNOWN_ERROR"),Ab[zb.Notification.UnknownError]=Bb.i18n("NOTIFICATIONS/UNKNOWN_ERROR")},Bb.getUploadErrorDescByCode=function(a){var b="";switch(Bb.pInt(a)){case zb.UploadErrorCode.FileIsTooBig:b=Bb.i18n("UPLOAD/ERROR_FILE_IS_TOO_BIG");break;case zb.UploadErrorCode.FilePartiallyUploaded:b=Bb.i18n("UPLOAD/ERROR_FILE_PARTIALLY_UPLOADED");break;case zb.UploadErrorCode.FileNoUploaded:b=Bb.i18n("UPLOAD/ERROR_NO_FILE_UPLOADED");break;case zb.UploadErrorCode.MissingTempFolder:b=Bb.i18n("UPLOAD/ERROR_MISSING_TEMP_FOLDER");break;case zb.UploadErrorCode.FileOnSaveingError:b=Bb.i18n("UPLOAD/ERROR_ON_SAVING_FILE");break;case zb.UploadErrorCode.FileType:b=Bb.i18n("UPLOAD/ERROR_FILE_TYPE");break;default:b=Bb.i18n("UPLOAD/ERROR_UNKNOWN")}return b},Bb.delegateRun=function(a,b,c,d){a&&a[b]&&(d=Bb.pInt(d),0>=d?a[b].apply(a,Bb.isArray(c)?c:[]):h.delay(function(){a[b].apply(a,Bb.isArray(c)?c:[])},d))},Bb.killCtrlAandS=function(b){if(b=b||a.event,b&&b.ctrlKey&&!b.shiftKey&&!b.altKey){var c=b.target||b.srcElement,d=b.keyCode||b.which;if(d===zb.EventKeyCode.S)return b.preventDefault(),void 0;if(c&&c.tagName&&c.tagName.match(/INPUT|TEXTAREA/i))return;d===zb.EventKeyCode.A&&(a.getSelection?a.getSelection().removeAllRanges():a.document.selection&&a.document.selection.clear&&a.document.selection.clear(),b.preventDefault())}},Bb.createCommand=function(a,b,d){var e=b?function(){return e.canExecute&&e.canExecute()&&b.apply(a,Array.prototype.slice.call(arguments)),!1}:function(){};return e.enabled=c.observable(!0),d=Bb.isUnd(d)?!0:d,e.canExecute=Bb.isFunc(d)?c.computed(function(){return e.enabled()&&d.call(a)}):c.computed(function(){return e.enabled()&&!!d}),e},Bb.initDataConstructorBySettings=function(b){b.editorDefaultType=c.observable(zb.EditorDefaultType.Html),b.showImages=c.observable(!1),b.interfaceAnimation=c.observable(zb.InterfaceAnimation.Full),b.contactsAutosave=c.observable(!1),Eb.sAnimationType=zb.InterfaceAnimation.Full,b.allowThemes=c.observable(!0),b.allowCustomLogin=c.observable(!1),b.allowLanguagesOnSettings=c.observable(!0),b.allowLanguagesOnLogin=c.observable(!0),b.desktopNotifications=c.observable(!1),b.useThreads=c.observable(!0),b.replySameFolder=c.observable(!0),b.useCheckboxesInList=c.observable(!0),b.layout=c.observable(zb.Layout.SidePreview),b.usePreviewPane=c.computed(function(){return zb.Layout.NoPreview!==b.layout()}),b.interfaceAnimation.subscribe(function(a){if(Eb.bMobileDevice||a===zb.InterfaceAnimation.None)Kb.removeClass("rl-anim rl-anim-full").addClass("no-rl-anim"),Eb.sAnimationType=zb.InterfaceAnimation.None;else switch(a){case zb.InterfaceAnimation.Full:Kb.removeClass("no-rl-anim").addClass("rl-anim rl-anim-full"),Eb.sAnimationType=a;break;case zb.InterfaceAnimation.Normal:Kb.removeClass("no-rl-anim rl-anim-full").addClass("rl-anim"),Eb.sAnimationType=a}}),b.interfaceAnimation.valueHasMutated(),b.desktopNotificationsPermisions=c.computed(function(){b.desktopNotifications();var c=zb.DesktopNotifications.NotSupported;if(Nb&&Nb.permission)switch(Nb.permission.toLowerCase()){case"granted":c=zb.DesktopNotifications.Allowed;break;case"denied":c=zb.DesktopNotifications.Denied;break;case"default":c=zb.DesktopNotifications.NotAllowed}else a.webkitNotifications&&a.webkitNotifications.checkPermission&&(c=a.webkitNotifications.checkPermission());return c}),b.useDesktopNotifications=c.computed({read:function(){return b.desktopNotifications()&&zb.DesktopNotifications.Allowed===b.desktopNotificationsPermisions()},write:function(a){if(a){var c=b.desktopNotificationsPermisions();zb.DesktopNotifications.Allowed===c?b.desktopNotifications(!0):zb.DesktopNotifications.NotAllowed===c?Nb.requestPermission(function(){b.desktopNotifications.valueHasMutated(),zb.DesktopNotifications.Allowed===b.desktopNotificationsPermisions()?b.desktopNotifications()?b.desktopNotifications.valueHasMutated():b.desktopNotifications(!0):b.desktopNotifications()?b.desktopNotifications(!1):b.desktopNotifications.valueHasMutated()}):b.desktopNotifications(!1)}else b.desktopNotifications(!1)}}),b.language=c.observable(""),b.languages=c.observableArray([]),b.mainLanguage=c.computed({read:b.language,write:function(a){a!==b.language()?-1 =b.diff(c,"hours")?d:b.format("L")===c.format("L")?Bb.i18n("MESSAGE_LIST/TODAY_AT",{TIME:c.format("LT")}):b.clone().subtract("days",1).format("L")===c.format("L")?Bb.i18n("MESSAGE_LIST/YESTERDAY_AT",{TIME:c.format("LT")}):b.year()===c.year()?c.format("D MMM."):c.format("LL")},a)},Bb.isFolderExpanded=function(a){var b=Ob.local().get(zb.ClientSideKeyName.ExpandedFolders);return h.isArray(b)&&-1!==h.indexOf(b,a)},Bb.setExpandedFolder=function(a,b){var c=Ob.local().get(zb.ClientSideKeyName.ExpandedFolders);h.isArray(c)||(c=[]),b?(c.push(a),c=h.uniq(c)):c=h.without(c,a),Ob.local().set(zb.ClientSideKeyName.ExpandedFolders,c)},Bb.initLayoutResizer=function(a,c,d){var e=155,f=b(a),g=b(c),h=Ob.local().get(d)||null,i=function(a){a&&(f.css({width:""+a+"px"}),g.css({left:""+a+"px"}))},j=function(a){var b=5;a?(f.resizable("disable"),i(b)):(f.resizable("enable"),b=Bb.pInt(Ob.local().get(d))||e,i(b>e?b:e))},k=function(a,b){b&&b.size&&b.size.width&&(Ob.local().set(d,b.size.width),g.css({left:""+b.size.width+"px"}))};null!==h&&i(h),f.resizable({helper:"ui-resizable-helper",minWidth:e,maxWidth:350,handles:"e",stop:k}),Ob.sub("left-panel.off",function(){j(!0)}),Ob.sub("left-panel.on",function(){j(!1)})},Bb.initBlockquoteSwitcher=function(a){if(a){var c=b("blockquote:not(.rl-bq-switcher)",a).filter(function(){return 0===b(this).parent().closest("blockquote",a).length});c&&0 100)&&(a.addClass("rl-bq-switcher hidden-bq"),b('').insertBefore(a).click(function(){a.toggleClass("hidden-bq"),Bb.windowResize()}).after("
").before("
"))})}},Bb.removeBlockquoteSwitcher=function(a){a&&(b(a).find("blockquote.rl-bq-switcher").each(function(){b(this).removeClass("rl-bq-switcher hidden-bq")}),b(a).find(".rlBlockquoteSwitcher").each(function(){b(this).remove()}))},Bb.toggleMessageBlockquote=function(a){a&&a.find(".rlBlockquoteSwitcher").click()},Bb.extendAsViewModel=function(a,b,c){b&&(c||(c=r),b.__name=a,Cb.regViewModelHook(a,b),h.extend(b.prototype,c.prototype))},Bb.addSettingsViewModel=function(a,b,c,d,e){a.__rlSettingsData={Label:c,Template:b,Route:d,IsDefault:!!e},Fb.settings.push(a)},Bb.removeSettingsViewModel=function(a){Fb["settings-removed"].push(a)},Bb.disableSettingsViewModel=function(a){Fb["settings-disabled"].push(a)},Bb.convertThemeName=function(a){return"@custom"===a.substr(-7)&&(a=Bb.trim(a.substring(0,a.length-7))),Bb.trim(a.replace(/[^a-zA-Z]+/g," ").replace(/([A-Z])/g," $1").replace(/[\s]+/g," "))},Bb.quoteName=function(a){return a.replace(/["]/g,'\\"')},Bb.microtime=function(){return(new Date).getTime()},Bb.convertLangName=function(a,b){return Bb.i18n("LANGS_NAMES"+(!0===b?"_EN":"")+"/LANG_"+a.toUpperCase().replace(/[^a-zA-Z0-9]+/,"_"),null,a)},Bb.fakeMd5=function(a){var b="",c="0123456789abcdefghijklmnopqrstuvwxyz";for(a=Bb.isUnd(a)?32:Bb.pInt(a);b.length>>32-b}function c(a,b){var c,d,e,f,g;return e=2147483648&a,f=2147483648&b,c=1073741824&a,d=1073741824&b,g=(1073741823&a)+(1073741823&b),c&d?2147483648^g^e^f:c|d?1073741824&g?3221225472^g^e^f:1073741824^g^e^f:g^e^f -}function d(a,b,c){return a&b|~a&c}function e(a,b,c){return a&c|b&~c}function f(a,b,c){return a^b^c}function g(a,b,c){return b^(a|~c)}function h(a,e,f,g,h,i,j){return a=c(a,c(c(d(e,f,g),h),j)),c(b(a,i),e)}function i(a,d,f,g,h,i,j){return a=c(a,c(c(e(d,f,g),h),j)),c(b(a,i),d)}function j(a,d,e,g,h,i,j){return a=c(a,c(c(f(d,e,g),h),j)),c(b(a,i),d)}function k(a,d,e,f,h,i,j){return a=c(a,c(c(g(d,e,f),h),j)),c(b(a,i),d)}function l(a){for(var b,c=a.length,d=c+8,e=(d-d%64)/64,f=16*(e+1),g=Array(f-1),h=0,i=0;c>i;)b=(i-i%4)/4,h=i%4*8,g[b]=g[b]|a.charCodeAt(i)<>>29,g}function m(a){var b,c,d="",e="";for(c=0;3>=c;c++)b=a>>>8*c&255,e="0"+b.toString(16),d+=e.substr(e.length-2,2);return d}function n(a){a=a.replace(/rn/g,"n");for(var b="",c=0;c d?b+=String.fromCharCode(d):d>127&&2048>d?(b+=String.fromCharCode(d>>6|192),b+=String.fromCharCode(63&d|128)):(b+=String.fromCharCode(d>>12|224),b+=String.fromCharCode(d>>6&63|128),b+=String.fromCharCode(63&d|128))}return b}var o,p,q,r,s,t,u,v,w,x=Array(),y=7,z=12,A=17,B=22,C=5,D=9,E=14,F=20,G=4,H=11,I=16,J=23,K=6,L=10,M=15,N=21;for(a=n(a),x=l(a),t=1732584193,u=4023233417,v=2562383102,w=271733878,o=0;o /g,">").replace(/")},Bb.draggeblePlace=function(){return b(' ').appendTo("#rl-hidden")},Bb.defautOptionsAfterRender=function(a,c){c&&!Bb.isUnd(c.disabled)&&a&&b(a).toggleClass("disabled",c.disabled).prop("disabled",c.disabled)},Bb.windowPopupKnockout=function(c,d,e,f){var g=null,h=a.open(""),i="__OpenerApplyBindingsUid"+Bb.fakeMd5()+"__",j=b("#"+d);a[i]=function(){if(h&&h.document.body&&j&&j[0]){var d=b(h.document.body);b("#rl-content",d).html(j.html()),b("html",h.document).addClass("external "+b("html").attr("class")),Bb.i18nToNode(d),t.prototype.applyExternal(c,b("#rl-content",d)[0]),a[i]=null,f(h)}},h.document.open(),h.document.write(''+Bb.encodeHtml(e)+' '),h.document.close(),g=h.document.createElement("script"),g.type="text/javascript",g.innerHTML="if(window&&window.opener&&window.opener['"+i+"']){window.opener['"+i+"']();window.opener['"+i+"']=null}",h.document.getElementsByTagName("head")[0].appendChild(g)},Bb.settingsSaveHelperFunction=function(a,b,c,d){return c=c||null,d=Bb.isUnd(d)?1e3:Bb.pInt(d),function(e,f,g,i,j){b.call(c,f&&f.Result?zb.SaveSettingsStep.TrueResult:zb.SaveSettingsStep.FalseResult),a&&a.call(c,e,f,g,i,j),h.delay(function(){b.call(c,zb.SaveSettingsStep.Idle)},d)}},Bb.settingsSaveHelperSimpleFunction=function(a,b){return Bb.settingsSaveHelperFunction(null,a,b,1e3)},Bb.htmlToPlain=function(a){var c="",d="> ",e=function(){if(arguments&&1\n",a.replace(/\n([> ]+)/gm,function(){return arguments&&1 ]*>(.|[\s\S\r\n]*)<\/div>/gim,f),a="\n"+b.trim(a)+"\n"),a}return""},g=function(){return arguments&&1 /g,">"):""},h=function(){if(arguments&&1 /gim,"\n").replace(/<\/h\d>/gi,"\n").replace(/<\/p>/gi,"\n\n").replace(/<\/li>/gi,"\n").replace(/<\/td>/gi,"\n").replace(/<\/tr>/gi,"\n").replace(/
]*>/gim,"\n_______________________________\n\n").replace(/]*>/gim,"").replace(/
]*>(.|[\s\S\r\n]*)<\/div>/gim,f).replace(/]*>/gim,"\n__bq__start__\n").replace(/<\/blockquote>/gim,"\n__bq__end__\n").replace(/]*>(.|[\s\S\r\n]*)<\/a>/gim,h).replace(/ /gi," ").replace(/<[^>]*>/gm,"").replace(/>/gi,">").replace(/</gi,"<").replace(/&/gi,"&").replace(/&\w{2,6};/gi,""),c.replace(/\n[ \t]+/gm,"\n").replace(/[\n]{3,}/gm,"\n\n").replace(/__bq__start__(.|[\s\S\r\n]*)__bq__end__/gm,e).replace(/__bq__start__/gm,"").replace(/__bq__end__/gm,"")},Bb.plainToHtml=function(a){return a.toString().replace(/&/g,"&").replace(/>/g,">").replace(/")},Bb.resizeAndCrop=function(b,c,d){var e=new a.Image;e.onload=function(){var a=[0,0],b=document.createElement("canvas"),e=b.getContext("2d");b.width=c,b.height=c,a=this.width>this.height?[this.width-this.height,0]:[0,this.height-this.width],e.fillStyle="#fff",e.fillRect(0,0,c,c),e.drawImage(this,a[0]/2,a[1]/2,this.width-a[0],this.height-a[1],0,0,c,c),d(b.toDataURL("image/jpeg"))},e.src=b},Bb.computedPagenatorHelper=function(a,b){return function(){var c=0,d=0,e=2,f=[],g=a(),h=b(),i=function(a,b,c){var d={current:a===g,name:Bb.isUnd(c)?a.toString():c.toString(),custom:Bb.isUnd(c)?!1:!0,title:Bb.isUnd(c)?"":a.toString(),value:a.toString()};(Bb.isUnd(b)?0:!b)?f.unshift(d):f.push(d)};if(h>1||h>0&&g>h){for(g>h?(i(h),c=h,d=h):((3>=g||g>=h-2)&&(e+=2),i(g),c=g,d=g);e>0;)if(c-=1,d+=1,c>0&&(i(c,!1),e--),h>=d)i(d,!0),e--;else if(0>=c)break;3===c?i(2,!1):c>3&&i(Math.round((c-1)/2),!1,"..."),h-2===d?i(h-1,!0):h-2>d&&i(Math.round((h+d)/2),!0,"..."),c>1&&i(1,!1),h>d&&i(h,!0)}return f}},Bb.selectElement=function(b){if(a.getSelection){var c=a.getSelection();c.removeAllRanges();var d=document.createRange();d.selectNodeContents(b),c.addRange(d)}else if(document.selection){var e=document.body.createTextRange();e.moveToElementText(b),e.select()}},Bb.disableKeyFilter=function(){a.key&&(j.filter=function(){return Ob.data().useKeyboardShortcuts()})},Bb.restoreKeyFilter=function(){a.key&&(j.filter=function(a){if(Ob.data().useKeyboardShortcuts()){var b=a.target||a.srcElement,c=b?b.tagName:"";return c=c.toUpperCase(),!("INPUT"===c||"SELECT"===c||"TEXTAREA"===c||b&&"DIV"===c&&"editorHtmlArea"===b.className&&b.contentEditable)}return!1})},Bb.detectDropdownVisibility=h.debounce(function(){Eb.dropdownVisibility(!!h.find(Gb,function(a){return a.hasClass("open")}))},50),Db={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",urlsafe_encode:function(a){return Db.encode(a).replace(/[+]/g,"-").replace(/[\/]/g,"_").replace(/[=]/g,".")},encode:function(a){var b,c,d,e,f,g,h,i="",j=0;for(a=Db._utf8_encode(a);j>2,f=(3&b)<<4|c>>4,g=(15&c)<<2|d>>6,h=63&d,isNaN(c)?g=h=64:isNaN(d)&&(h=64),i=i+this._keyStr.charAt(e)+this._keyStr.charAt(f)+this._keyStr.charAt(g)+this._keyStr.charAt(h);return i},decode:function(a){var b,c,d,e,f,g,h,i="",j=0;for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");j >4,c=(15&f)<<4|g>>2,d=(3&g)<<6|h,i+=String.fromCharCode(b),64!==g&&(i+=String.fromCharCode(c)),64!==h&&(i+=String.fromCharCode(d));return Db._utf8_decode(i)},_utf8_encode:function(a){a=a.replace(/\r\n/g,"\n");for(var b="",c=0,d=a.length,e=0;d>c;c++)e=a.charCodeAt(c),128>e?b+=String.fromCharCode(e):e>127&&2048>e?(b+=String.fromCharCode(e>>6|192),b+=String.fromCharCode(63&e|128)):(b+=String.fromCharCode(e>>12|224),b+=String.fromCharCode(e>>6&63|128),b+=String.fromCharCode(63&e|128));return b},_utf8_decode:function(a){for(var b="",c=0,d=0,e=0,f=0;c d?(b+=String.fromCharCode(d),c++):d>191&&224>d?(e=a.charCodeAt(c+1),b+=String.fromCharCode((31&d)<<6|63&e),c+=2):(e=a.charCodeAt(c+1),f=a.charCodeAt(c+2),b+=String.fromCharCode((15&d)<<12|(63&e)<<6|63&f),c+=3);return b}},c.bindingHandlers.tooltip={init:function(a,d){if(!Eb.bMobileDevice){var e=b(a),f=e.data("tooltip-class")||"",g=e.data("tooltip-placement")||"top";e.tooltip({delay:{show:500,hide:100},html:!0,container:"body",placement:g,trigger:"hover",title:function(){return e.is(".disabled")||Eb.dropdownVisibility()?"":''+Bb.i18n(c.utils.unwrapObservable(d()))+""}}).click(function(){e.tooltip("hide")}),Eb.dropdownVisibility.subscribe(function(a){a&&e.tooltip("hide")})}}},c.bindingHandlers.tooltip2={init:function(a,c){var d=b(a),e=d.data("tooltip-class")||"",f=d.data("tooltip-placement")||"top";d.tooltip({delay:{show:500,hide:100},html:!0,container:"body",placement:f,title:function(){return d.is(".disabled")||Eb.dropdownVisibility()?"":''+c()()+""}}).click(function(){d.tooltip("hide")}),Eb.dropdownVisibility.subscribe(function(a){a&&d.tooltip("hide")})}},c.bindingHandlers.tooltip3={init:function(a){var c=b(a);c.tooltip({container:"body",trigger:"hover manual",title:function(){return c.data("tooltip3-data")||""}}),Eb.dropdownVisibility.subscribe(function(a){a&&c.tooltip("hide")}),Mb.click(function(){c.tooltip("hide")})},update:function(a,d){var e=c.utils.unwrapObservable(d());""===e?b(a).data("tooltip3-data","").tooltip("hide"):b(a).data("tooltip3-data",e).tooltip("show")}},c.bindingHandlers.registrateBootstrapDropdown={init:function(a){Gb.push(b(a))}},c.bindingHandlers.openDropdownTrigger={update:function(a,d){if(c.utils.unwrapObservable(d())){var e=b(a);e.hasClass("open")||(e.find(".dropdown-toggle").dropdown("toggle"),Bb.detectDropdownVisibility()),d()(!1)}}},c.bindingHandlers.dropdownCloser={init:function(a){b(a).closest(".dropdown").on("click",".e-item",function(){b(a).dropdown("toggle")})}},c.bindingHandlers.popover={init:function(a,d){b(a).popover(c.utils.unwrapObservable(d()))}},c.bindingHandlers.csstext={init:function(a,d){a&&a.styleSheet&&!Bb.isUnd(a.styleSheet.cssText)?a.styleSheet.cssText=c.utils.unwrapObservable(d()):b(a).text(c.utils.unwrapObservable(d()))},update:function(a,d){a&&a.styleSheet&&!Bb.isUnd(a.styleSheet.cssText)?a.styleSheet.cssText=c.utils.unwrapObservable(d()):b(a).text(c.utils.unwrapObservable(d()))}},c.bindingHandlers.resizecrop={init:function(a){b(a).addClass("resizecrop").resizecrop({width:"100",height:"100",wrapperCSS:{"border-radius":"10px"}})},update:function(a,c){c()(),b(a).resizecrop({width:"100",height:"100"})}},c.bindingHandlers.onEnter={init:function(c,d,e,f){b(c).on("keypress",function(e){e&&13===a.parseInt(e.keyCode,10)&&(b(c).trigger("change"),d().call(f))})}},c.bindingHandlers.onEsc={init:function(c,d,e,f){b(c).on("keypress",function(e){e&&27===a.parseInt(e.keyCode,10)&&(b(c).trigger("change"),d().call(f))})}},c.bindingHandlers.clickOnTrue={update:function(a,d){c.utils.unwrapObservable(d())&&b(a).click()}},c.bindingHandlers.modal={init:function(a,d){b(a).toggleClass("fade",!Eb.bMobileDevice).modal({keyboard:!1,show:c.utils.unwrapObservable(d())}).on("shown",function(){Bb.windowResize()}).find(".close").click(function(){d()(!1)})},update:function(a,d){b(a).modal(c.utils.unwrapObservable(d())?"show":"hide")}},c.bindingHandlers.i18nInit={init:function(a){Bb.i18nToNode(a)}},c.bindingHandlers.i18nUpdate={update:function(a,b){c.utils.unwrapObservable(b()),Bb.i18nToNode(a)}},c.bindingHandlers.link={update:function(a,d){b(a).attr("href",c.utils.unwrapObservable(d()))}},c.bindingHandlers.title={update:function(a,d){b(a).attr("title",c.utils.unwrapObservable(d()))}},c.bindingHandlers.textF={init:function(a,d){b(a).text(c.utils.unwrapObservable(d()))}},c.bindingHandlers.initDom={init:function(a,b){b()(a)}},c.bindingHandlers.initResizeTrigger={init:function(a,d){var e=c.utils.unwrapObservable(d());b(a).css({height:e[1],"min-height":e[1]})},update:function(a,d){var e=c.utils.unwrapObservable(d()),f=Bb.pInt(e[1]),g=0,h=b(a).offset().top;h>0&&(h+=Bb.pInt(e[2]),g=Lb.height()-h,g>f&&(f=g),b(a).css({height:f,"min-height":f}))}},c.bindingHandlers.appendDom={update:function(a,d){b(a).hide().empty().append(c.utils.unwrapObservable(d())).show()}},c.bindingHandlers.draggable={init:function(d,e,f){if(!Eb.bMobileDevice){var g=100,h=3,i=f(),j=i&&i.droppableSelector?i.droppableSelector:"",k={distance:20,handle:".dragHandle",cursorAt:{top:22,left:3},refreshPositions:!0,scroll:!0};j&&(k.drag=function(c){b(j).each(function(){var d=null,e=null,f=b(this),i=f.offset(),j=i.top+f.height();a.clearInterval(f.data("timerScroll")),f.data("timerScroll",!1),c.pageX>=i.left&&c.pageX<=i.left+f.width()&&(c.pageY>=j-g&&c.pageY<=j&&(d=function(){f.scrollTop(f.scrollTop()+h),Bb.windowResize()},f.data("timerScroll",a.setInterval(d,10)),d()),c.pageY>=i.top&&c.pageY<=i.top+g&&(e=function(){f.scrollTop(f.scrollTop()-h),Bb.windowResize()},f.data("timerScroll",a.setInterval(e,10)),e()))})},k.stop=function(){b(j).each(function(){a.clearInterval(b(this).data("timerScroll")),b(this).data("timerScroll",!1)})}),k.helper=function(a){return e()(a&&a.target?c.dataFor(a.target):null)},b(d).draggable(k).on("mousedown",function(){Bb.removeInFocus()})}}},c.bindingHandlers.droppable={init:function(a,c,d){if(!Eb.bMobileDevice){var e=c(),f=d(),g=f&&f.droppableOver?f.droppableOver:null,h=f&&f.droppableOut?f.droppableOut:null,i={tolerance:"pointer",hoverClass:"droppableHover"};e&&(i.drop=function(a,b){e(a,b)},g&&(i.over=function(a,b){g(a,b)}),h&&(i.out=function(a,b){h(a,b)}),b(a).droppable(i))}}},c.bindingHandlers.nano={init:function(a){Eb.bDisableNanoScroll||b(a).addClass("nano").nanoScroller({iOSNativeScrolling:!1,preventPageScrolling:!0})}},c.bindingHandlers.saveTrigger={init:function(a){var c=b(a);c.data("save-trigger-type",c.is("input[type=text],input[type=email],input[type=password],select,textarea")?"input":"custom"),"custom"===c.data("save-trigger-type")?c.append(' ').addClass("settings-saved-trigger"):c.addClass("settings-saved-trigger-input")},update:function(a,d){var e=c.utils.unwrapObservable(d()),f=b(a);if("custom"===f.data("save-trigger-type"))switch(e.toString()){case"1":f.find(".animated,.error").hide().removeClass("visible").end().find(".success").show().addClass("visible");break;case"0":f.find(".animated,.success").hide().removeClass("visible").end().find(".error").show().addClass("visible");break;case"-2":f.find(".error,.success").hide().removeClass("visible").end().find(".animated").show().addClass("visible");break;default:f.find(".animated").hide().end().find(".error,.success").removeClass("visible")}else switch(e.toString()){case"1":f.addClass("success").removeClass("error");break;case"0":f.addClass("error").removeClass("success");break;case"-2":break;default:f.removeClass("error success")}}},c.bindingHandlers.emailsTags={init:function(a,c){var d=b(a),e=c();d.inputosaurus({parseOnBlur:!0,inputDelimiters:[",",";"],autoCompleteSource:function(a,b){Ob.getAutocomplete(a.term,function(a){b(h.map(a,function(a){return a.toLine(!1)}))})},parseHook:function(a){return h.map(a,function(a){var b=Bb.trim(a),c=null;return""!==b?(c=new u,c.mailsoParse(b),c.clearDuplicateName(),[c.toLine(!1),c]):[b,null]})},change:h.bind(function(a){d.data("EmailsTagsValue",a.target.value),e(a.target.value)},this)}),e.subscribe(function(a){d.data("EmailsTagsValue")!==a&&(d.val(a),d.data("EmailsTagsValue",a),d.inputosaurus("refresh"))}),e.focusTrigger&&e.focusTrigger.subscribe(function(){d.inputosaurus("focus")})}},c.bindingHandlers.command={init:function(a,d,e,f){var g=b(a),h=d();if(!h||!h.enabled||!h.canExecute)throw new Error("You are not using command function");g.addClass("command"),c.bindingHandlers[g.is("form")?"submit":"click"].init.apply(f,arguments)},update:function(a,c){var d=!0,e=b(a),f=c();d=f.enabled(),e.toggleClass("command-not-enabled",!d),d&&(d=f.canExecute(),e.toggleClass("command-can-not-be-execute",!d)),e.toggleClass("command-disabled disable disabled",!d).toggleClass("no-disabled",!!d),(e.is("input")||e.is("button"))&&e.prop("disabled",!d)}},c.extenders.trimmer=function(a){var b=c.computed({read:a,write:function(b){a(Bb.trim(b.toString()))},owner:this});return b(a()),b},c.extenders.reversible=function(a){var b=a();return a.commit=function(){b=a()},a.reverse=function(){a(b)},a.commitedValue=function(){return b},a},c.extenders.toggleSubscribe=function(a,b){return a.subscribe(b[1],b[0],"beforeChange"),a.subscribe(b[2],b[0]),a},c.extenders.falseTimeout=function(b,c){return b.iTimeout=0,b.subscribe(function(d){d&&(a.clearTimeout(b.iTimeout),b.iTimeout=a.setTimeout(function(){b(!1),b.iTimeout=0},Bb.pInt(c)))}),b},c.observable.fn.validateNone=function(){return this.hasError=c.observable(!1),this},c.observable.fn.validateEmail=function(){return this.hasError=c.observable(!1),this.subscribe(function(a){a=Bb.trim(a),this.hasError(""!==a&&!/^[^@\s]+@[^@\s]+$/.test(a))},this),this.valueHasMutated(),this},c.observable.fn.validateSimpleEmail=function(){return this.hasError=c.observable(!1),this.subscribe(function(a){a=Bb.trim(a),this.hasError(""!==a&&!/^.+@.+$/.test(a))},this),this.valueHasMutated(),this},c.observable.fn.validateFunc=function(a){return this.hasFuncError=c.observable(!1),Bb.isFunc(a)&&(this.subscribe(function(b){this.hasFuncError(!a(b))},this),this.valueHasMutated()),this},k.prototype.root=function(){return this.sBase},k.prototype.attachmentDownload=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/Download/"+a},k.prototype.attachmentPreview=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/View/"+a},k.prototype.attachmentPreviewAsPlain=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/ViewAsPlain/"+a},k.prototype.upload=function(){return this.sServer+"/Upload/"+this.sSpecSuffix+"/"},k.prototype.uploadContacts=function(){return this.sServer+"/UploadContacts/"+this.sSpecSuffix+"/"},k.prototype.uploadBackground=function(){return this.sServer+"/UploadBackground/"+this.sSpecSuffix+"/"},k.prototype.append=function(){return this.sServer+"/Append/"+this.sSpecSuffix+"/"},k.prototype.change=function(b){return this.sServer+"/Change/"+this.sSpecSuffix+"/"+a.encodeURIComponent(b)+"/"},k.prototype.ajax=function(a){return this.sServer+"/Ajax/"+this.sSpecSuffix+"/"+a},k.prototype.messageViewLink=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/ViewAsPlain/"+a},k.prototype.messageDownloadLink=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/Download/"+a},k.prototype.inbox=function(){return this.sBase+"mailbox/Inbox"},k.prototype.messagePreview=function(){return this.sBase+"mailbox/message-preview"},k.prototype.settings=function(a){var b=this.sBase+"settings";return Bb.isUnd(a)||""===a||(b+="/"+a),b},k.prototype.admin=function(a){var b=this.sBase;switch(a){case"AdminDomains":b+="domains";break;case"AdminSecurity":b+="security";break;case"AdminLicensing":b+="licensing"}return b},k.prototype.mailBox=function(a,b,c){b=Bb.isNormal(b)?Bb.pInt(b):1,c=Bb.pString(c);var d=this.sBase+"mailbox/";return""!==a&&(d+=encodeURI(a)),b>1&&(d=d.replace(/[\/]+$/,""),d+="/p"+b),""!==c&&(d=d.replace(/[\/]+$/,""),d+="/"+encodeURI(c)),d},k.prototype.phpInfo=function(){return this.sServer+"Info"},k.prototype.langLink=function(a){return this.sServer+"/Lang/0/"+encodeURI(a)+"/"+this.sVersion+"/"},k.prototype.getUserPicUrlFromHash=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/UserPic/"+a+"/"+this.sVersion+"/"},k.prototype.exportContactsVcf=function(){return this.sServer+"/Raw/"+this.sSpecSuffix+"/ContactsVcf/"},k.prototype.exportContactsCsv=function(){return this.sServer+"/Raw/"+this.sSpecSuffix+"/ContactsCsv/"},k.prototype.emptyContactPic=function(){return"rainloop/v/"+this.sVersion+"/static/css/images/empty-contact.png"},k.prototype.sound=function(a){return"rainloop/v/"+this.sVersion+"/static/sounds/"+a},k.prototype.themePreviewLink=function(a){var b="rainloop/v/"+this.sVersion+"/";return"@custom"===a.substr(-7)&&(a=Bb.trim(a.substring(0,a.length-7)),b=""),b+"themes/"+encodeURI(a)+"/images/preview.png"},k.prototype.notificationMailIcon=function(){return"rainloop/v/"+this.sVersion+"/static/css/images/icom-message-notification.png"},k.prototype.openPgpJs=function(){return"rainloop/v/"+this.sVersion+"/static/js/openpgp.min.js"},k.prototype.socialGoogle=function(){return this.sServer+"SocialGoogle"+(""!==this.sSpecSuffix?"/"+this.sSpecSuffix+"/":"")},k.prototype.socialTwitter=function(){return this.sServer+"SocialTwitter"+(""!==this.sSpecSuffix?"/"+this.sSpecSuffix+"/":"")},k.prototype.socialFacebook=function(){return this.sServer+"SocialFacebook"+(""!==this.sSpecSuffix?"/"+this.sSpecSuffix+"/":"")},Cb.oViewModelsHooks={},Cb.oSimpleHooks={},Cb.regViewModelHook=function(a,b){b&&(b.__hookName=a)},Cb.addHook=function(a,b){Bb.isFunc(b)&&(Bb.isArray(Cb.oSimpleHooks[a])||(Cb.oSimpleHooks[a]=[]),Cb.oSimpleHooks[a].push(b))},Cb.runHook=function(a,b){Bb.isArray(Cb.oSimpleHooks[a])&&(b=b||[],h.each(Cb.oSimpleHooks[a],function(a){a.apply(null,b)}))},Cb.mainSettingsGet=function(a){return Ob?Ob.settingsGet(a):null},Cb.remoteRequest=function(a,b,c,d,e,f){Ob&&Ob.remote().defaultRequest(a,b,c,d,e,f)},Cb.settingsGet=function(a,b){var c=Cb.mainSettingsGet("Plugins");return c=c&&Bb.isUnd(c[a])?null:c[a],c?Bb.isUnd(c[b])?null:c[b]:null},l.prototype.blurTrigger=function(){if(this.fOnBlur){var b=this;a.clearTimeout(b.iBlurTimer),b.iBlurTimer=a.setTimeout(function(){b.fOnBlur()},200)}},l.prototype.focusTrigger=function(){this.fOnBlur&&a.clearTimeout(this.iBlurTimer)},l.prototype.isHtml=function(){return this.editor?"wysiwyg"===this.editor.mode:!1},l.prototype.checkDirty=function(){return this.editor?this.editor.checkDirty():!1},l.prototype.resetDirty=function(){this.editor&&this.editor.resetDirty()},l.prototype.getData=function(){return this.editor?"plain"===this.editor.mode&&this.editor.plugins.plain&&this.editor.__plain?this.editor.__plain.getRawData():this.editor.getData():""},l.prototype.modeToggle=function(a){this.editor&&(a?"plain"===this.editor.mode&&this.editor.setMode("wysiwyg"):"wysiwyg"===this.editor.mode&&this.editor.setMode("plain"))},l.prototype.setHtml=function(a,b){this.editor&&(this.modeToggle(!0),this.editor.setData(a),b&&this.focus())},l.prototype.setPlain=function(a,b){if(this.editor){if(this.modeToggle(!1),"plain"===this.editor.mode&&this.editor.plugins.plain&&this.editor.__plain)return this.editor.__plain.setRawData(a);this.editor.setData(a),b&&this.focus()}},l.prototype.init=function(){if(this.$element&&this.$element[0]){var b=this,c=Eb.oHtmlEditorDefaultConfig,d=Ob.settingsGet("Language"),e=!!Ob.settingsGet("AllowHtmlEditorSourceButton");e&&c.toolbarGroups&&!c.toolbarGroups.__SourceInited&&(c.toolbarGroups.__SourceInited=!0,c.toolbarGroups.push({name:"document",groups:["mode","document","doctools"]})),c.language=Eb.oHtmlEditorLangsMap[d]||"en",b.editor=a.CKEDITOR.appendTo(b.$element[0],c),b.editor.on("key",function(a){return a&&a.data&&9===a.data.keyCode?!1:void 0}),b.editor.on("blur",function(){b.blurTrigger()}),b.editor.on("mode",function(){b.blurTrigger(),b.fOnModeChange&&b.fOnModeChange("plain"!==b.editor.mode)}),b.editor.on("focus",function(){b.focusTrigger()}),b.fOnReady&&b.editor.on("instanceReady",function(){b.editor.setKeystroke(a.CKEDITOR.CTRL+65,"selectAll"),b.fOnReady(),b.__resizable=!0,b.resize()})}},l.prototype.focus=function(){this.editor&&this.editor.focus()},l.prototype.blur=function(){this.editor&&this.editor.focusManager.blur(!0)},l.prototype.resize=function(){this.editor&&this.__resizable&&this.editor.resize(this.$element.width(),this.$element.innerHeight())},l.prototype.clear=function(a){this.setHtml("",a)},m.prototype.itemSelected=function(a){this.isListChecked()?a||(this.oCallbacks.onItemSelect||this.emptyFunction)(a||null):a&&(this.oCallbacks.onItemSelect||this.emptyFunction)(a)},m.prototype.goDown=function(a){this.newSelectPosition(zb.EventKeyCode.Down,!1,a)},m.prototype.goUp=function(a){this.newSelectPosition(zb.EventKeyCode.Up,!1,a)},m.prototype.init=function(a,d,e){if(this.oContentVisible=a,this.oContentScrollable=d,e=e||"all",this.oContentVisible&&this.oContentScrollable){var f=this;b(this.oContentVisible).on("selectstart",function(a){a&&a.preventDefault&&a.preventDefault()}).on("click",this.sItemSelector,function(a){f.actionClick(c.dataFor(this),a)}).on("click",this.sItemCheckedSelector,function(a){var b=c.dataFor(this);b&&(a&&a.shiftKey?f.actionClick(b,a):(f.focusedItem(b),b.checked(!b.checked())))}),j("enter",e,function(){return f.focusedItem()&&!f.focusedItem().selected()?(f.actionClick(f.focusedItem()),!1):!0}),j("ctrl+up, command+up, ctrl+down, command+down",e,function(){return!1}),j("up, shift+up, down, shift+down, home, end, pageup, pagedown, insert, space",e,function(a,b){if(a&&b&&b.shortcut){var c=0;switch(b.shortcut){case"up":case"shift+up":c=zb.EventKeyCode.Up;break;case"down":case"shift+down":c=zb.EventKeyCode.Down;break;case"insert":c=zb.EventKeyCode.Insert;break;case"space":c=zb.EventKeyCode.Space;break;case"home":c=zb.EventKeyCode.Home;break;case"end":c=zb.EventKeyCode.End;break;case"pageup":c=zb.EventKeyCode.PageUp;break;case"pagedown":c=zb.EventKeyCode.PageDown}if(c>0)return f.newSelectPosition(c,j.shift),!1}})}},m.prototype.autoSelect=function(a){this.bAutoSelect=!!a},m.prototype.getItemUid=function(a){var b="",c=this.oCallbacks.onItemGetUid||null;return c&&a&&(b=c(a)),b.toString()},m.prototype.newSelectPosition=function(a,b,c){var d=0,e=10,f=!1,g=!1,i=null,j=this.list(),k=j?j.length:0,l=this.focusedItem();if(k>0)if(l){if(l)if(zb.EventKeyCode.Down===a||zb.EventKeyCode.Up===a||zb.EventKeyCode.Insert===a||zb.EventKeyCode.Space===a)h.each(j,function(b){if(!g)switch(a){case zb.EventKeyCode.Up:l===b?g=!0:i=b;break;case zb.EventKeyCode.Down:case zb.EventKeyCode.Insert:f?(i=b,g=!0):l===b&&(f=!0)}});else if(zb.EventKeyCode.Home===a||zb.EventKeyCode.End===a)zb.EventKeyCode.Home===a?i=j[0]:zb.EventKeyCode.End===a&&(i=j[j.length-1]);else if(zb.EventKeyCode.PageDown===a){for(;k>d;d++)if(l===j[d]){d+=e,d=d>k-1?k-1:d,i=j[d];break}}else if(zb.EventKeyCode.PageUp===a)for(d=k;d>=0;d--)if(l===j[d]){d-=e,d=0>d?0:d,i=j[d];break}}else zb.EventKeyCode.Down===a||zb.EventKeyCode.Insert===a||zb.EventKeyCode.Space===a||zb.EventKeyCode.Home===a||zb.EventKeyCode.PageUp===a?i=j[0]:(zb.EventKeyCode.Up===a||zb.EventKeyCode.End===a||zb.EventKeyCode.PageDown===a)&&(i=j[j.length-1]);i?(this.focusedItem(i),l&&(b?(zb.EventKeyCode.Up===a||zb.EventKeyCode.Down===a)&&l.checked(!l.checked()):(zb.EventKeyCode.Insert===a||zb.EventKeyCode.Space===a)&&l.checked(!l.checked())),!this.bAutoSelect&&!c||this.isListChecked()||zb.EventKeyCode.Space===a||this.selectedItem(i),this.scrollToFocused()):l&&(!b||zb.EventKeyCode.Up!==a&&zb.EventKeyCode.Down!==a?(zb.EventKeyCode.Insert===a||zb.EventKeyCode.Space===a)&&l.checked(!l.checked()):l.checked(!l.checked()),this.focusedItem(l))},m.prototype.scrollToFocused=function(){if(!this.oContentVisible||!this.oContentScrollable)return!1;var a=20,c=b(this.sItemFocusedSelector,this.oContentScrollable),d=c.position(),e=this.oContentVisible.height(),f=c.outerHeight();return d&&(d.top<0||d.top+f>e)?(d.top<0?this.oContentScrollable.scrollTop(this.oContentScrollable.scrollTop()+d.top-a):this.oContentScrollable.scrollTop(this.oContentScrollable.scrollTop()+d.top-e+f+a),!0):!1},m.prototype.scrollToTop=function(a){return this.oContentVisible&&this.oContentScrollable?(a?this.oContentScrollable.scrollTop(0):this.oContentScrollable.stop().animate({scrollTop:0},200),!0):!1},m.prototype.eventClickFunction=function(a,b){var c=this.getItemUid(a),d=0,e=0,f=null,g="",h=!1,i=!1,j=[],k=!1;if(b&&b.shiftKey&&""!==c&&""!==this.sLastUid&&c!==this.sLastUid)for(j=this.list(),k=a.checked(),d=0,e=j.length;e>d;d++)f=j[d],g=this.getItemUid(f),h=!1,(g===this.sLastUid||g===c)&&(h=!0),h&&(i=!i),(i||h)&&f.checked(k);this.sLastUid=""===c?"":c},m.prototype.actionClick=function(a,b){if(a){var c=!0,d=this.getItemUid(a);b&&(!b.shiftKey||b.ctrlKey||b.altKey?!b.ctrlKey||b.shiftKey||b.altKey||(c=!1,this.focusedItem(a),this.selectedItem()&&a!==this.selectedItem()&&this.selectedItem().checked(!0),a.checked(!a.checked())):(c=!1,""===this.sLastUid&&(this.sLastUid=d),a.checked(!a.checked()),this.eventClickFunction(a,b),this.focusedItem(a))),c&&(this.focusedItem(a),this.selectedItem(a))}},m.prototype.on=function(a,b){this.oCallbacks[a]=b},n.supported=function(){return!0},n.prototype.set=function(a,c){var d=b.cookie(yb.Values.ClientSideCookieIndexName),e=!1,f=null;try{f=null===d?null:JSON.parse(d),f||(f={}),f[a]=c,b.cookie(yb.Values.ClientSideCookieIndexName,JSON.stringify(f),{expires:30}),e=!0}catch(g){}return e},n.prototype.get=function(a){var c=b.cookie(yb.Values.ClientSideCookieIndexName),d=null;try{d=null===c?null:JSON.parse(c),d=d&&!Bb.isUnd(d[a])?d[a]:null}catch(e){}return d},o.supported=function(){return!!a.localStorage},o.prototype.set=function(b,c){var d=a.localStorage[yb.Values.ClientSideCookieIndexName]||null,e=!1,f=null;try{f=null===d?null:JSON.parse(d),f||(f={}),f[b]=c,a.localStorage[yb.Values.ClientSideCookieIndexName]=JSON.stringify(f),e=!0}catch(g){}return e},o.prototype.get=function(b){var c=a.localStorage[yb.Values.ClientSideCookieIndexName]||null,d=null;try{d=null===c?null:JSON.parse(c),d=d&&!Bb.isUnd(d[b])?d[b]:null}catch(e){}return d},p.prototype.oDriver=null,p.prototype.set=function(a,b){return this.oDriver?this.oDriver.set("p"+a,b):!1},p.prototype.get=function(a){return this.oDriver?this.oDriver.get("p"+a):null},q.prototype.bootstart=function(){},r.prototype.sPosition="",r.prototype.sTemplate="",r.prototype.viewModelName="",r.prototype.viewModelDom=null,r.prototype.viewModelTemplate=function(){return this.sTemplate -},r.prototype.viewModelPosition=function(){return this.sPosition},r.prototype.cancelCommand=r.prototype.closeCommand=function(){},r.prototype.storeAndSetKeyScope=function(){this.sCurrentKeyScope=Ob.data().keyScope(),Ob.data().keyScope(this.sDefaultKeyScope)},r.prototype.restoreKeyScope=function(){Ob.data().keyScope(this.sCurrentKeyScope)},r.prototype.registerPopupEscapeKey=function(){var a=this;Lb.on("keydown",function(b){return b&&zb.EventKeyCode.Esc===b.keyCode&&a.modalVisibility&&a.modalVisibility()?(Bb.delegateRun(a,"cancelCommand"),!1):!0})},s.prototype.oCross=null,s.prototype.sScreenName="",s.prototype.aViewModels=[],s.prototype.viewModels=function(){return this.aViewModels},s.prototype.screenName=function(){return this.sScreenName},s.prototype.routes=function(){return null},s.prototype.__cross=function(){return this.oCross},s.prototype.__start=function(){var a=this.routes(),b=null,c=null;Bb.isNonEmptyArray(a)&&(c=h.bind(this.onRoute||Bb.emptyFunction,this),b=d.create(),h.each(a,function(a){b.addRoute(a[0],c).rules=a[1]}),this.oCross=b)},t.constructorEnd=function(a){Bb.isFunc(a.__constructor_end)&&a.__constructor_end.call(a)},t.prototype.sDefaultScreenName="",t.prototype.oScreens={},t.prototype.oBoot=null,t.prototype.oCurrentScreen=null,t.prototype.hideLoading=function(){b("#rl-loading").hide()},t.prototype.routeOff=function(){e.changed.active=!1},t.prototype.routeOn=function(){e.changed.active=!0},t.prototype.setBoot=function(a){return Bb.isNormal(a)&&(this.oBoot=a),this},t.prototype.screen=function(a){return""===a||Bb.isUnd(this.oScreens[a])?null:this.oScreens[a]},t.prototype.buildViewModel=function(a,d){if(a&&!a.__builded){var e=new a(d),f=e.viewModelPosition(),g=b("#rl-content #rl-"+f.toLowerCase()),i=null;a.__builded=!0,a.__vm=e,e.data=Ob.data(),e.viewModelName=a.__name,g&&1===g.length?(i=b(" ").addClass("rl-view-model").addClass("RL-"+e.viewModelTemplate()).hide().attr("data-bind",'template: {name: "'+e.viewModelTemplate()+'"}, i18nInit: true'),i.appendTo(g),e.viewModelDom=i,a.__dom=i,"Popups"===f&&(e.cancelCommand=e.closeCommand=Bb.createCommand(e,function(){Hb.hideScreenPopup(a)}),e.modalVisibility.subscribe(function(a){var b=this;a?(this.viewModelDom.show(),this.storeAndSetKeyScope(),Ob.popupVisibilityNames.push(this.viewModelName),e.viewModelDom.css("z-index",3e3+Ob.popupVisibilityNames().length+10),Bb.delegateRun(this,"onFocus",[],500)):(Bb.delegateRun(this,"onHide"),this.restoreKeyScope(),Ob.popupVisibilityNames.remove(this.viewModelName),e.viewModelDom.css("z-index",2e3),h.delay(function(){b.viewModelDom.hide()},300))},e)),Cb.runHook("view-model-pre-build",[a.__name,e,i]),c.applyBindings(e,i[0]),Bb.delegateRun(e,"onBuild",[i]),e&&"Popups"===f&&!e.bDisabeCloseOnEsc&&e.registerPopupEscapeKey(),Cb.runHook("view-model-post-build",[a.__name,e,i])):Bb.log("Cannot find view model position: "+f)}return a?a.__vm:null},t.prototype.applyExternal=function(a,b){a&&b&&c.applyBindings(a,b)},t.prototype.hideScreenPopup=function(a){a&&a.__vm&&a.__dom&&(a.__vm.modalVisibility(!1),Cb.runHook("view-model-on-hide",[a.__name,a.__vm]))},t.prototype.showScreenPopup=function(a,b){a&&(this.buildViewModel(a),a.__vm&&a.__dom&&(a.__vm.modalVisibility(!0),Bb.delegateRun(a.__vm,"onShow",b||[]),Cb.runHook("view-model-on-show",[a.__name,a.__vm,b||[]])))},t.prototype.screenOnRoute=function(a,b){var c=this,d=null,e=null;""===Bb.pString(a)&&(a=this.sDefaultScreenName),""!==a&&(d=this.screen(a),d||(d=this.screen(this.sDefaultScreenName),d&&(b=a+"/"+b,a=this.sDefaultScreenName)),d&&d.__started&&(d.__builded||(d.__builded=!0,Bb.isNonEmptyArray(d.viewModels())&&h.each(d.viewModels(),function(a){this.buildViewModel(a,d)},this),Bb.delegateRun(d,"onBuild")),h.defer(function(){c.oCurrentScreen&&(Bb.delegateRun(c.oCurrentScreen,"onHide"),Bb.isNonEmptyArray(c.oCurrentScreen.viewModels())&&h.each(c.oCurrentScreen.viewModels(),function(a){a.__vm&&a.__dom&&"Popups"!==a.__vm.viewModelPosition()&&(a.__dom.hide(),a.__vm.viewModelVisibility(!1),Bb.delegateRun(a.__vm,"onHide"))})),c.oCurrentScreen=d,c.oCurrentScreen&&(Bb.delegateRun(c.oCurrentScreen,"onShow"),Cb.runHook("screen-on-show",[c.oCurrentScreen.screenName(),c.oCurrentScreen]),Bb.isNonEmptyArray(c.oCurrentScreen.viewModels())&&h.each(c.oCurrentScreen.viewModels(),function(a){a.__vm&&a.__dom&&"Popups"!==a.__vm.viewModelPosition()&&(a.__dom.show(),a.__vm.viewModelVisibility(!0),Bb.delegateRun(a.__vm,"onShow"),Bb.delegateRun(a.__vm,"onFocus",[],200),Cb.runHook("view-model-on-show",[a.__name,a.__vm]))},c)),e=d.__cross(),e&&e.parse(b)})))},t.prototype.startScreens=function(a){b("#rl-content").css({visibility:"hidden"}),h.each(a,function(a){var b=new a,c=b?b.screenName():"";b&&""!==c&&(""===this.sDefaultScreenName&&(this.sDefaultScreenName=c),this.oScreens[c]=b)},this),h.each(this.oScreens,function(a){a&&!a.__started&&a.__start&&(a.__started=!0,a.__start(),Cb.runHook("screen-pre-start",[a.screenName(),a]),Bb.delegateRun(a,"onStart"),Cb.runHook("screen-post-start",[a.screenName(),a]))},this);var c=d.create();c.addRoute(/^([a-zA-Z0-9\-]*)\/?(.*)$/,h.bind(this.screenOnRoute,this)),e.initialized.add(c.parse,c),e.changed.add(c.parse,c),e.init(),b("#rl-content").css({visibility:"visible"}),h.delay(function(){Kb.removeClass("rl-started-trigger").addClass("rl-started")},50)},t.prototype.setHash=function(a,b,c){a="#"===a.substr(0,1)?a.substr(1):a,a="/"===a.substr(0,1)?a.substr(1):a,c=Bb.isUnd(c)?!1:!!c,(Bb.isUnd(b)?1:!b)?(e.changed.active=!0,e[c?"replaceHash":"setHash"](a),e.setHash(a)):(e.changed.active=!1,e[c?"replaceHash":"setHash"](a),e.changed.active=!0)},t.prototype.bootstart=function(){return this.oBoot&&this.oBoot.bootstart&&this.oBoot.bootstart(),this},Hb=new t,u.newInstanceFromJson=function(a){var b=new u;return b.initByJson(a)?b:null},u.prototype.name="",u.prototype.email="",u.prototype.privateType=null,u.prototype.clear=function(){this.email="",this.name="",this.privateType=null},u.prototype.validate=function(){return""!==this.name||""!==this.email},u.prototype.hash=function(a){return"#"+(a?"":this.name)+"#"+this.email+"#"},u.prototype.clearDuplicateName=function(){this.name===this.email&&(this.name="")},u.prototype.type=function(){return null===this.privateType&&(this.email&&"@facebook.com"===this.email.substr(-13)&&(this.privateType=zb.EmailType.Facebook),null===this.privateType&&(this.privateType=zb.EmailType.Default)),this.privateType},u.prototype.search=function(a){return-1<(this.name+" "+this.email).toLowerCase().indexOf(a.toLowerCase())},u.prototype.parse=function(a){this.clear(),a=Bb.trim(a);var b=/(?:"([^"]+)")? ?(.*?@[^>,]+)>?,? ?/g,c=b.exec(a);c?(this.name=c[1]||"",this.email=c[2]||"",this.clearDuplicateName()):/^[^@]+@[^@]+$/.test(a)&&(this.name="",this.email=a)},u.prototype.initByJson=function(a){var b=!1;return a&&"Object/Email"===a["@Object"]&&(this.name=Bb.trim(a.Name),this.email=Bb.trim(a.Email),b=""!==this.email,this.clearDuplicateName()),b},u.prototype.toLine=function(a,b,c){var d="";return""!==this.email&&(b=Bb.isUnd(b)?!1:!!b,c=Bb.isUnd(c)?!1:!!c,a&&""!==this.name?d=b?'")+'" target="_blank" tabindex="-1">'+Bb.encodeHtml(this.name)+"":c?Bb.encodeHtml(this.name):this.name:(d=this.email,""!==this.name?b?d=Bb.encodeHtml('"'+this.name+'" <')+'")+'" target="_blank" tabindex="-1">'+Bb.encodeHtml(d)+""+Bb.encodeHtml(">"):(d='"'+this.name+'" <'+d+">",c&&(d=Bb.encodeHtml(d))):b&&(d=''+Bb.encodeHtml(this.email)+""))),d},u.prototype.mailsoParse=function(a){if(a=Bb.trim(a),""===a)return!1;for(var b=function(a,b,c){a+="";var d=a.length;return 0>b&&(b+=d),d="undefined"==typeof c?d:0>c?c+d:c+b,b>=a.length||0>b||b>d?!1:a.slice(b,d)},c=function(a,b,c,d){return 0>c&&(c+=a.length),d=void 0!==d?d:a.length,0>d&&(d=d+a.length-c),a.slice(0,c)+b.substr(0,d)+b.slice(d)+a.slice(c+d)},d="",e="",f="",g=!1,h=!1,i=!1,j=null,k=0,l=0,m=0;m").addClass("rl-settings-view-model").hide().attr("data-bind",'template: {name: "'+f.__rlSettingsData.Template+'"}, i18nInit: true'),i.appendTo(g),e.data=Ob.data(),e.viewModelDom=i,e.__rlSettingsData=f.__rlSettingsData,f.__dom=i,f.__builded=!0,f.__vm=e,c.applyBindings(e,i[0]),Bb.delegateRun(e,"onBuild",[i])):Bb.log("Cannot find sub settings view model position: SettingsSubScreen")),e&&h.defer(function(){d.oCurrentSubScreen&&(Bb.delegateRun(d.oCurrentSubScreen,"onHide"),d.oCurrentSubScreen.viewModelDom.hide()),d.oCurrentSubScreen=e,d.oCurrentSubScreen&&(d.oCurrentSubScreen.viewModelDom.show(),Bb.delegateRun(d.oCurrentSubScreen,"onShow"),Bb.delegateRun(d.oCurrentSubScreen,"onFocus",[],200),h.each(d.menu(),function(a){a.selected(e&&e.__rlSettingsData&&a.route===e.__rlSettingsData.Route)}),b("#rl-content .b-settings .b-content .content").scrollTop(0)),Bb.windowResize()})):Hb.setHash(Ob.link().settings(),!1,!0)},sb.prototype.onHide=function(){this.oCurrentSubScreen&&this.oCurrentSubScreen.viewModelDom&&(Bb.delegateRun(this.oCurrentSubScreen,"onHide"),this.oCurrentSubScreen.viewModelDom.hide())},sb.prototype.onBuild=function(){h.each(Fb.settings,function(a){a&&a.__rlSettingsData&&!h.find(Fb["settings-removed"],function(b){return b&&b===a})&&this.menu.push({route:a.__rlSettingsData.Route,label:a.__rlSettingsData.Label,selected:c.observable(!1),disabled:!!h.find(Fb["settings-disabled"],function(b){return b&&b===a})})},this),this.oViewModelPlace=b("#rl-content #rl-settings-subscreen")},sb.prototype.routes=function(){var a=h.find(Fb.settings,function(a){return a&&a.__rlSettingsData&&a.__rlSettingsData.IsDefault}),b=a?a.__rlSettingsData.Route:"general",c={subname:/^(.*)$/,normalize_:function(a,c){return c.subname=Bb.isUnd(c.subname)?b:Bb.pString(c.subname),[c.subname]}};return[["{subname}/",c],["{subname}",c],["",c]]},h.extend(tb.prototype,s.prototype),tb.prototype.onShow=function(){Ob.setTitle("")},h.extend(ub.prototype,s.prototype),ub.prototype.oLastRoute={},ub.prototype.setNewTitle=function(){var a=Ob.data().accountEmail(),b=Ob.data().foldersInboxUnreadCount();Ob.setTitle((""===a?"":(b>0?"("+b+") ":" ")+a+" - ")+Bb.i18n("TITLES/MAILBOX"))},ub.prototype.onShow=function(){this.setNewTitle(),Ob.data().keyScope(zb.KeyState.MessageList)},ub.prototype.onRoute=function(a,b,c,d){if(Bb.isUnd(d)?1:!d){var e=Ob.data(),f=Ob.cache().getFolderFullNameRaw(a),g=Ob.cache().getFolderFromCacheList(f);g&&(e.currentFolder(g).messageListPage(b).messageListSearch(c),zb.Layout.NoPreview===e.layout()&&e.message()&&(e.message(null),e.messageFullScreenMode(!1)),Ob.reloadMessageList())}else zb.Layout.NoPreview!==Ob.data().layout()||Ob.data().message()||Ob.historyBack()},ub.prototype.onStart=function(){var a=Ob.data(),b=function(){Bb.windowResize()};(Ob.settingsGet("AllowAdditionalAccounts")||Ob.settingsGet("AllowIdentities"))&&Ob.accountsAndIdentities(),h.delay(function(){"INBOX"!==a.currentFolderFullNameRaw()&&Ob.folderInformation("INBOX")},1e3),h.delay(function(){Ob.quota()},5e3),h.delay(function(){Ob.remote().appDelayStart(Bb.emptyFunction)},35e3),Kb.toggleClass("rl-no-preview-pane",zb.Layout.NoPreview===a.layout()),a.folderList.subscribe(b),a.messageList.subscribe(b),a.message.subscribe(b),a.layout.subscribe(function(a){Kb.toggleClass("rl-no-preview-pane",zb.Layout.NoPreview===a)}),a.foldersInboxUnreadCount.subscribe(function(){this.setNewTitle()},this)},ub.prototype.routes=function(){var a=function(){return["Inbox",1,"",!0]},b=function(a,b){return b[0]=Bb.pString(b[0]),b[1]=Bb.pInt(b[1]),b[1]=0>=b[1]?1:b[1],b[2]=Bb.pString(b[2]),""===a&&(b[0]="Inbox",b[1]=1),[decodeURI(b[0]),b[1],decodeURI(b[2]),!1]},c=function(a,b){return b[0]=Bb.pString(b[0]),b[1]=Bb.pString(b[1]),""===a&&(b[0]="Inbox"),[decodeURI(b[0]),1,decodeURI(b[1]),!1]};return[[/^([a-zA-Z0-9]+)\/p([1-9][0-9]*)\/(.+)\/?$/,{normalize_:b}],[/^([a-zA-Z0-9]+)\/p([1-9][0-9]*)$/,{normalize_:b}],[/^([a-zA-Z0-9]+)\/(.+)\/?$/,{normalize_:c}],[/^message-preview$/,{normalize_:a}],[/^([^\/]*)$/,{normalize_:b}]]},h.extend(vb.prototype,sb.prototype),vb.prototype.onShow=function(){Ob.setTitle(this.sSettingsTitle),Ob.data().keyScope(zb.KeyState.Settings)},h.extend(wb.prototype,q.prototype),wb.prototype.oSettings=null,wb.prototype.oPlugins=null,wb.prototype.oLocal=null,wb.prototype.oLink=null,wb.prototype.oSubs={},wb.prototype.download=function(b){var c=null,d=null,e=navigator.userAgent.toLowerCase();return e&&(e.indexOf("chrome")>-1||e.indexOf("chrome")>-1)&&(c=document.createElement("a"),c.href=b,document.createEvent&&(d=document.createEvent("MouseEvents"),d&&d.initEvent&&c.dispatchEvent))?(d.initEvent("click",!0,!0),c.dispatchEvent(d),!0):(Eb.bMobileDevice?(a.open(b,"_self"),a.focus()):this.iframe.attr("src",b),!0)},wb.prototype.link=function(){return null===this.oLink&&(this.oLink=new k),this.oLink},wb.prototype.local=function(){return null===this.oLocal&&(this.oLocal=new p),this.oLocal},wb.prototype.settingsGet=function(a){return null===this.oSettings&&(this.oSettings=Bb.isNormal(Ib)?Ib:{}),Bb.isUnd(this.oSettings[a])?null:this.oSettings[a]},wb.prototype.settingsSet=function(a,b){null===this.oSettings&&(this.oSettings=Bb.isNormal(Ib)?Ib:{}),this.oSettings[a]=b},wb.prototype.setTitle=function(b){b=(Bb.isNormal(b)&&00&&0===d.length&&(d=b(a,0,m)),h=!0,k=m);break;case">":h&&(l=m,e=b(a,k+1,l-k-1),a=c(a,"",k,l-k+1),l=0,m=0,k=0,h=!1);break;case"(":g||h||i||(i=!0,k=m);break;case")":i&&(l=m,f=b(a,k+1,l-k-1),a=c(a,"",k,l-k+1),l=0,m=0,k=0,i=!1);break;case"\\":m++}m++}return 0===e.length&&(j=a.match(/[^@\s]+@\S+/i),j&&j[0]?e=j[0]:d=a),e.length>0&&0===d.length&&0===f.length&&(d=a.replace(e,"")),e=Bb.trim(e).replace(/^[<]+/,"").replace(/[>]+$/,""),d=Bb.trim(d).replace(/^["']+/,"").replace(/["']+$/,""),f=Bb.trim(f).replace(/^[(]+/,"").replace(/[)]+$/,""),d=d.replace(/\\\\(.)/,"$1"),f=f.replace(/\\\\(.)/,"$1"),this.name=d,this.email=e,this.clearDuplicateName(),!0},u.prototype.inputoTagLine=function(){return 0 +$/,""),b=!0),b},x.prototype.isImage=function(){return-1 e;e++)d.push(a[e].toLine(b,c));return d.join(", ")},z.initEmailsFromJson=function(a){var b=0,c=0,d=null,e=[];if(Bb.isNonEmptyArray(a))for(b=0,c=a.length;c>b;b++)d=u.newInstanceFromJson(a[b]),d&&e.push(d);return e},z.replyHelper=function(a,b,c){if(a&&0 d;d++)Bb.isUnd(b[a[d].email])&&(b[a[d].email]=!0,c.push(a[d]))},z.prototype.clear=function(){this.folderFullNameRaw="",this.uid="",this.hash="",this.requestHash="",this.subject(""),this.size(0),this.dateTimeStampInUTC(0),this.priority(zb.MessagePriority.Normal),this.fromEmailString(""),this.toEmailsString(""),this.senderEmailsString(""),this.emails=[],this.from=[],this.to=[],this.cc=[],this.bcc=[],this.replyTo=[],this.newForAnimation(!1),this.deleted(!1),this.unseen(!1),this.flagged(!1),this.answered(!1),this.forwarded(!1),this.isReadReceipt(!1),this.selected(!1),this.checked(!1),this.hasAttachments(!1),this.attachmentsMainType(""),this.body=null,this.isRtl(!1),this.isHtml(!1),this.hasImages(!1),this.attachments([]),this.isPgpSigned(!1),this.isPgpEncrypted(!1),this.pgpSignedVerifyStatus(zb.SignedVerifyStatus.None),this.pgpSignedVerifyUser(""),this.priority(zb.MessagePriority.Normal),this.readReceipt(""),this.aDraftInfo=[],this.sMessageId="",this.sInReplyTo="",this.sReferences="",this.parentUid(0),this.threads([]),this.threadsLen(0),this.hasUnseenSubMessage(!1),this.hasFlaggedSubMessage(!1),this.lastInCollapsedThread(!1),this.lastInCollapsedThreadLoading(!1)},z.prototype.computeSenderEmail=function(){var a=Ob.data().sentFolder(),b=Ob.data().draftFolder();this.senderEmailsString(this.folderFullNameRaw===a||this.folderFullNameRaw===b?this.toEmailsString():this.fromEmailString())},z.prototype.initByJson=function(a){var b=!1;return a&&"Object/Message"===a["@Object"]&&(this.folderFullNameRaw=a.Folder,this.uid=a.Uid,this.hash=a.Hash,this.requestHash=a.RequestHash,this.size(Bb.pInt(a.Size)),this.from=z.initEmailsFromJson(a.From),this.to=z.initEmailsFromJson(a.To),this.cc=z.initEmailsFromJson(a.Cc),this.bcc=z.initEmailsFromJson(a.Bcc),this.replyTo=z.initEmailsFromJson(a.ReplyTo),this.subject(a.Subject),this.dateTimeStampInUTC(Bb.pInt(a.DateTimeStampInUTC)),this.hasAttachments(!!a.HasAttachments),this.attachmentsMainType(a.AttachmentsMainType),this.fromEmailString(z.emailsToLine(this.from,!0)),this.toEmailsString(z.emailsToLine(this.to,!0)),this.parentUid(Bb.pInt(a.ParentThread)),this.threads(Bb.isArray(a.Threads)?a.Threads:[]),this.threadsLen(Bb.pInt(a.ThreadsLen)),this.initFlagsByJson(a),this.computeSenderEmail(),b=!0),b},z.prototype.initUpdateByMessageJson=function(a){var b=!1,c=zb.MessagePriority.Normal;return a&&"Object/Message"===a["@Object"]&&(c=Bb.pInt(a.Priority),this.priority(-1 b;b++)d=x.newInstanceFromJson(a["@Collection"][b]),d&&(""!==d.cidWithOutTags&&0 +$/,""),b=h.find(c,function(b){return a===b.cidWithOutTags})),b||null},z.prototype.findAttachmentByContentLocation=function(a){var b=null,c=this.attachments();return Bb.isNonEmptyArray(c)&&(b=h.find(c,function(b){return a===b.contentLocation})),b||null},z.prototype.messageId=function(){return this.sMessageId},z.prototype.inReplyTo=function(){return this.sInReplyTo},z.prototype.references=function(){return this.sReferences},z.prototype.fromAsSingleEmail=function(){return Bb.isArray(this.from)&&this.from[0]?this.from[0].email:""},z.prototype.viewLink=function(){return Ob.link().messageViewLink(this.requestHash)},z.prototype.downloadLink=function(){return Ob.link().messageDownloadLink(this.requestHash)},z.prototype.replyEmails=function(a){var b=[],c=Bb.isUnd(a)?{}:a;return z.replyHelper(this.replyTo,c,b),0===b.length&&z.replyHelper(this.from,c,b),b},z.prototype.replyAllEmails=function(a){var b=[],c=[],d=Bb.isUnd(a)?{}:a;return z.replyHelper(this.replyTo,d,b),0===b.length&&z.replyHelper(this.from,d,b),z.replyHelper(this.to,d,b),z.replyHelper(this.cc,d,c),[b,c]},z.prototype.textBodyToString=function(){return this.body?this.body.html():""},z.prototype.attachmentsToStringLine=function(){var a=h.map(this.attachments(),function(a){return a.fileName+" ("+a.friendlySize+")"});return a&&0 =0&&e&&!f&&d.attr("src",e)}),c&&a.setTimeout(function(){d.print()},100))})},z.prototype.printMessage=function(){this.viewPopupMessage(!0)},z.prototype.generateUid=function(){return this.folderFullNameRaw+"/"+this.uid},z.prototype.populateByMessageListItem=function(a){return this.folderFullNameRaw=a.folderFullNameRaw,this.uid=a.uid,this.hash=a.hash,this.requestHash=a.requestHash,this.subject(a.subject()),this.size(a.size()),this.dateTimeStampInUTC(a.dateTimeStampInUTC()),this.priority(a.priority()),this.fromEmailString(a.fromEmailString()),this.toEmailsString(a.toEmailsString()),this.emails=a.emails,this.from=a.from,this.to=a.to,this.cc=a.cc,this.bcc=a.bcc,this.replyTo=a.replyTo,this.unseen(a.unseen()),this.flagged(a.flagged()),this.answered(a.answered()),this.forwarded(a.forwarded()),this.isReadReceipt(a.isReadReceipt()),this.selected(a.selected()),this.checked(a.checked()),this.hasAttachments(a.hasAttachments()),this.attachmentsMainType(a.attachmentsMainType()),this.moment(a.moment()),this.body=null,this.priority(zb.MessagePriority.Normal),this.aDraftInfo=[],this.sMessageId="",this.sInReplyTo="",this.sReferences="",this.parentUid(a.parentUid()),this.threads(a.threads()),this.threadsLen(a.threadsLen()),this.computeSenderEmail(),this},z.prototype.showExternalImages=function(a){this.body&&this.body.data("rl-has-images")&&(a=Bb.isUnd(a)?!1:a,this.hasImages(!1),this.body.data("rl-has-images",!1),b("[data-x-src]",this.body).each(function(){a&&b(this).is("img")?b(this).addClass("lazy").attr("data-original",b(this).attr("data-x-src")).removeAttr("data-x-src"):b(this).attr("src",b(this).attr("data-x-src")).removeAttr("data-x-src")}),b("[data-x-style-url]",this.body).each(function(){var a=Bb.trim(b(this).attr("style"));a=""===a?"":";"===a.substr(-1)?a+" ":a+"; ",b(this).attr("style",a+b(this).attr("data-x-style-url")).removeAttr("data-x-style-url")}),a&&(b("img.lazy",this.body).addClass("lazy-inited").lazyload({threshold:400,effect:"fadeIn",skip_invisible:!1,container:b(".RL-MailMessageView .messageView .messageItem .content")[0]}),Lb.resize()),Bb.windowResize(500))},z.prototype.showInternalImages=function(a){if(this.body&&!this.body.data("rl-init-internal-images")){this.body.data("rl-init-internal-images",!0),a=Bb.isUnd(a)?!1:a;var c=this;b("[data-x-src-cid]",this.body).each(function(){var d=c.findAttachmentByCid(b(this).attr("data-x-src-cid"));d&&d.download&&(a&&b(this).is("img")?b(this).addClass("lazy").attr("data-original",d.linkPreview()):b(this).attr("src",d.linkPreview()))}),b("[data-x-src-location]",this.body).each(function(){var d=c.findAttachmentByContentLocation(b(this).attr("data-x-src-location"));d||(d=c.findAttachmentByCid(b(this).attr("data-x-src-location"))),d&&d.download&&(a&&b(this).is("img")?b(this).addClass("lazy").attr("data-original",d.linkPreview()):b(this).attr("src",d.linkPreview()))}),b("[data-x-style-cid]",this.body).each(function(){var a="",d="",e=c.findAttachmentByCid(b(this).attr("data-x-style-cid"));e&&e.linkPreview&&(d=b(this).attr("data-x-style-cid-name"),""!==d&&(a=Bb.trim(b(this).attr("style")),a=""===a?"":";"===a.substr(-1)?a+" ":a+"; ",b(this).attr("style",a+d+": url('"+e.linkPreview()+"')")))}),a&&!function(a,b){h.delay(function(){a.addClass("lazy-inited").lazyload({threshold:400,effect:"fadeIn",skip_invisible:!1,container:b})},300)}(b("img.lazy",c.body),b(".RL-MailMessageView .messageView .messageItem .content")[0]),Bb.windowResize(500)}},z.prototype.storeDataToDom=function(){this.body&&(this.body.data("rl-is-rtl",!!this.isRtl()),this.body.data("rl-is-html",!!this.isHtml()),this.body.data("rl-has-images",!!this.hasImages()),this.body.data("rl-plain-raw",this.plainRaw),Ob.data().allowOpenPGP()&&(this.body.data("rl-plain-pgp-signed",!!this.isPgpSigned()),this.body.data("rl-plain-pgp-encrypted",!!this.isPgpEncrypted()),this.body.data("rl-pgp-verify-status",this.pgpSignedVerifyStatus()),this.body.data("rl-pgp-verify-user",this.pgpSignedVerifyUser())))},z.prototype.storePgpVerifyDataToDom=function(){this.body&&Ob.data().allowOpenPGP()&&(this.body.data("rl-pgp-verify-status",this.pgpSignedVerifyStatus()),this.body.data("rl-pgp-verify-user",this.pgpSignedVerifyUser()))},z.prototype.fetchDataToDom=function(){this.body&&(this.isRtl(!!this.body.data("rl-is-rtl")),this.isHtml(!!this.body.data("rl-is-html")),this.hasImages(!!this.body.data("rl-has-images")),this.plainRaw=Bb.pString(this.body.data("rl-plain-raw")),Ob.data().allowOpenPGP()?(this.isPgpSigned(!!this.body.data("rl-plain-pgp-signed")),this.isPgpEncrypted(!!this.body.data("rl-plain-pgp-encrypted")),this.pgpSignedVerifyStatus(this.body.data("rl-pgp-verify-status")),this.pgpSignedVerifyUser(this.body.data("rl-pgp-verify-user"))):(this.isPgpSigned(!1),this.isPgpEncrypted(!1),this.pgpSignedVerifyStatus(zb.SignedVerifyStatus.None),this.pgpSignedVerifyUser("")))},z.prototype.verifyPgpSignedClearMessage=function(){if(this.isPgpSigned()){var c=[],d=null,e=this.from&&this.from[0]&&this.from[0].email?this.from[0].email:"",f=Ob.data().findPublicKeysByEmail(e),g=null,i=null,j="";this.pgpSignedVerifyStatus(zb.SignedVerifyStatus.Error),this.pgpSignedVerifyUser("");try{d=a.openpgp.cleartext.readArmored(this.plainRaw),d&&d.getText&&(this.pgpSignedVerifyStatus(f.length?zb.SignedVerifyStatus.Unverified:zb.SignedVerifyStatus.UnknownPublicKeys),c=d.verify(f),c&&0 ').text(j)).html(),Pb.empty(),this.replacePlaneTextBody(j)))))}catch(k){}this.storePgpVerifyDataToDom()}},z.prototype.decryptPgpEncryptedMessage=function(c){if(this.isPgpEncrypted()){var d=[],e=null,f=null,g=this.from&&this.from[0]&&this.from[0].email?this.from[0].email:"",i=Ob.data().findPublicKeysByEmail(g),j=Ob.data().findSelfPrivateKey(c),k=null,l=null,m="";this.pgpSignedVerifyStatus(zb.SignedVerifyStatus.Error),this.pgpSignedVerifyUser(""),j||this.pgpSignedVerifyStatus(zb.SignedVerifyStatus.UnknownPrivateKey);try{e=a.openpgp.message.readArmored(this.plainRaw),e&&j&&e.decrypt&&(this.pgpSignedVerifyStatus(zb.SignedVerifyStatus.Unverified),f=e.decrypt(j),f&&(d=f.verify(i),d&&0 ').text(m)).html(),Pb.empty(),this.replacePlaneTextBody(m)))}catch(n){}this.storePgpVerifyDataToDom()}},z.prototype.replacePlaneTextBody=function(a){this.body&&this.body.html(a).addClass("b-text-part plain")},z.prototype.flagHash=function(){return[this.deleted(),this.unseen(),this.flagged(),this.answered(),this.forwarded(),this.isReadReceipt()].join("")},A.newInstanceFromJson=function(a){var b=new A;return b.initByJson(a)?b.initComputed():null},A.prototype.initComputed=function(){return this.hasSubScribedSubfolders=c.computed(function(){return!!h.find(this.subFolders(),function(a){return a.subScribed()&&!a.isSystemFolder()})},this),this.canBeEdited=c.computed(function(){return zb.FolderType.User===this.type()&&this.existen&&this.selectable},this),this.visible=c.computed(function(){var a=this.subScribed(),b=this.hasSubScribedSubfolders();return a||b&&(!this.existen||!this.selectable)},this),this.isSystemFolder=c.computed(function(){return zb.FolderType.User!==this.type()},this),this.hidden=c.computed(function(){var a=this.isSystemFolder(),b=this.hasSubScribedSubfolders();return a&&!b||!this.selectable&&!b},this),this.selectableForFolderList=c.computed(function(){return!this.isSystemFolder()&&this.selectable},this),this.messageCountAll=c.computed({read:this.privateMessageCountAll,write:function(a){Bb.isPosNumeric(a,!0)?this.privateMessageCountAll(a):this.privateMessageCountAll.valueHasMutated()},owner:this}),this.messageCountUnread=c.computed({read:this.privateMessageCountUnread,write:function(a){Bb.isPosNumeric(a,!0)?this.privateMessageCountUnread(a):this.privateMessageCountUnread.valueHasMutated()},owner:this}),this.printableUnreadCount=c.computed(function(){var a=this.messageCountAll(),b=this.messageCountUnread(),c=this.type();if(zb.FolderType.Inbox===c&&Ob.data().foldersInboxUnreadCount(b),a>0){if(zb.FolderType.Draft===c)return""+a;if(b>0&&zb.FolderType.Trash!==c&&zb.FolderType.Archive!==c&&zb.FolderType.SentItems!==c)return""+b}return""},this),this.canBeDeleted=c.computed(function(){var a=this.isSystemFolder();return!a&&0===this.subFolders().length&&"INBOX"!==this.fullNameRaw},this),this.canBeSubScribed=c.computed(function(){return!this.isSystemFolder()&&this.selectable&&"INBOX"!==this.fullNameRaw},this),this.visible.subscribe(function(){Bb.timeOutAction("folder-list-folder-visibility-change",function(){Lb.trigger("folder-list-folder-visibility-change")},100)}),this.localName=c.computed(function(){Eb.langChangeTrigger();var a=this.type(),b=this.name();if(this.isSystemFolder())switch(a){case zb.FolderType.Inbox:b=Bb.i18n("FOLDER_LIST/INBOX_NAME");break;case zb.FolderType.SentItems:b=Bb.i18n("FOLDER_LIST/SENT_NAME");break;case zb.FolderType.Draft:b=Bb.i18n("FOLDER_LIST/DRAFTS_NAME");break;case zb.FolderType.Spam:b=Bb.i18n("FOLDER_LIST/SPAM_NAME");break;case zb.FolderType.Trash:b=Bb.i18n("FOLDER_LIST/TRASH_NAME");break;case zb.FolderType.Archive:b=Bb.i18n("FOLDER_LIST/ARCHIVE_NAME")}return b},this),this.manageFolderSystemName=c.computed(function(){Eb.langChangeTrigger();var a="",b=this.type(),c=this.name();if(this.isSystemFolder())switch(b){case zb.FolderType.Inbox:a="("+Bb.i18n("FOLDER_LIST/INBOX_NAME")+")";break;case zb.FolderType.SentItems:a="("+Bb.i18n("FOLDER_LIST/SENT_NAME")+")";break;case zb.FolderType.Draft:a="("+Bb.i18n("FOLDER_LIST/DRAFTS_NAME")+")";break;case zb.FolderType.Spam:a="("+Bb.i18n("FOLDER_LIST/SPAM_NAME")+")";break;case zb.FolderType.Trash:a="("+Bb.i18n("FOLDER_LIST/TRASH_NAME")+")";break;case zb.FolderType.Archive:a="("+Bb.i18n("FOLDER_LIST/ARCHIVE_NAME")+")"}return(""!==a&&"("+c+")"===a||"(inbox)"===a.toLowerCase())&&(a=""),a},this),this.collapsed=c.computed({read:function(){return!this.hidden()&&this.collapsedPrivate()},write:function(a){this.collapsedPrivate(a)},owner:this}),this.hasUnreadMessages=c.computed(function(){return 0 "},C.prototype.formattedNameForCompose=function(){var a=this.name();return""===a?this.email():a+" ("+this.email()+")"},C.prototype.formattedNameForEmail=function(){var a=this.name();return""===a?this.email():'"'+Bb.quoteName(a)+'" <'+this.email()+">"},D.prototype.index=0,D.prototype.id="",D.prototype.guid="",D.prototype.user="",D.prototype.email="",D.prototype.armor="",D.prototype.isPrivate=!1,Bb.extendAsViewModel("PopupsFolderClearViewModel",E),E.prototype.clearPopup=function(){this.clearingProcess(!1),this.selectedFolder(null)},E.prototype.onShow=function(a){this.clearPopup(),a&&this.selectedFolder(a)},Bb.extendAsViewModel("PopupsFolderCreateViewModel",F),F.prototype.sNoParentText="",F.prototype.simpleFolderNameValidation=function(a){return/^[^\\\/]+$/g.test(Bb.trim(a))},F.prototype.clearPopup=function(){this.folderName(""),this.selectedParentValue(""),this.folderName.focused(!1)},F.prototype.onShow=function(){this.clearPopup()},F.prototype.onFocus=function(){this.folderName.focused(!0)},Bb.extendAsViewModel("PopupsFolderSystemViewModel",G),G.prototype.sChooseOnText="",G.prototype.sUnuseText="",G.prototype.onShow=function(a){var b="";switch(a=Bb.isUnd(a)?zb.SetSystemFoldersNotification.None:a){case zb.SetSystemFoldersNotification.Sent:b=Bb.i18n("POPUPS_SYSTEM_FOLDERS/NOTIFICATION_SENT");break;case zb.SetSystemFoldersNotification.Draft:b=Bb.i18n("POPUPS_SYSTEM_FOLDERS/NOTIFICATION_DRAFTS");break;case zb.SetSystemFoldersNotification.Spam:b=Bb.i18n("POPUPS_SYSTEM_FOLDERS/NOTIFICATION_SPAM");break;case zb.SetSystemFoldersNotification.Trash:b=Bb.i18n("POPUPS_SYSTEM_FOLDERS/NOTIFICATION_TRASH");break;case zb.SetSystemFoldersNotification.Archive:b=Bb.i18n("POPUPS_SYSTEM_FOLDERS/NOTIFICATION_ARCHIVE")}this.notification(b)},Bb.extendAsViewModel("PopupsComposeViewModel",H),H.prototype.openOpenPgpPopup=function(){if(this.allowOpenPGP()&&this.oEditor&&!this.oEditor.isHtml()){var a=this;Hb.showScreenPopup(O,[function(b){a.editor(function(a){a.setPlain(b)})},this.oEditor.getData(),this.currentIdentityResultEmail(),this.to(),this.cc(),this.bcc()])}},H.prototype.reloadDraftFolder=function(){var a=Ob.data().draftFolder();""!==a&&(Ob.cache().setFolderHash(a,""),Ob.data().currentFolderFullNameRaw()===a?Ob.reloadMessageList(!0):Ob.folderInformation(a))},H.prototype.findIdentityIdByMessage=function(a,b){var c={},d="",e=function(a){return a&&a.email&&c[a.email]?(d=c[a.email],!0):!1};if(this.bAllowIdentities&&h.each(this.identities(),function(a){c[a.email()]=a.id}),c[Ob.data().accountEmail()]=Ob.data().accountEmail(),b)switch(a){case zb.ComposeType.Empty:d=Ob.data().accountEmail();break;case zb.ComposeType.Reply:case zb.ComposeType.ReplyAll:case zb.ComposeType.Forward:case zb.ComposeType.ForwardAsAttachment:h.find(h.union(b.to,b.cc,b.bcc),e);break;case zb.ComposeType.Draft:h.find(h.union(b.from,b.replyTo),e)}else d=Ob.data().accountEmail();return d},H.prototype.selectIdentity=function(a){a&&this.currentIdentityID(a.optValue)},H.prototype.formattedFrom=function(a){var b=Ob.data().displayName(),c=Ob.data().accountEmail();return""===b?c:(Bb.isUnd(a)?1:!a)?b+" ("+c+")":'"'+Bb.quoteName(b)+'" <'+c+">"},H.prototype.sendMessageResponse=function(b,c){var d=!1,e="";this.sending(!1),zb.StorageResultType.Success===b&&c&&c.Result&&(d=!0,this.modalVisibility()&&Bb.delegateRun(this,"closeCommand")),this.modalVisibility()&&!d&&(c&&zb.Notification.CantSaveMessage===c.ErrorCode?(this.sendSuccessButSaveError(!0),a.alert(Bb.trim(Bb.i18n("COMPOSE/SAVED_ERROR_ON_SEND")))):(e=Bb.getNotification(c&&c.ErrorCode?c.ErrorCode:zb.Notification.CantSendMessage,c&&c.ErrorMessage?c.ErrorMessage:""),this.sendError(!0),a.alert(e||Bb.getNotification(zb.Notification.CantSendMessage)))),this.reloadDraftFolder()},H.prototype.saveMessageResponse=function(b,c){var d=!1,e=null;this.saving(!1),zb.StorageResultType.Success===b&&c&&c.Result&&c.Result.NewFolder&&c.Result.NewUid&&(this.bFromDraft&&(e=Ob.data().message(),e&&this.draftFolder()===e.folderFullNameRaw&&this.draftUid()===e.uid&&Ob.data().message(null)),this.draftFolder(c.Result.NewFolder),this.draftUid(c.Result.NewUid),this.modalVisibility()&&(this.savedTime(Math.round((new a.Date).getTime()/1e3)),this.savedOrSendingText(0 c;c++)e.push(a[c].toLine(!!b));return e.join(", ")};if(c=c||null,c&&Bb.isNormal(c)&&(v=Bb.isArray(c)&&1===c.length?c[0]:Bb.isArray(c)?null:c),null!==q&&(p[q]=!0,this.currentIdentityID(this.findIdentityIdByMessage(w,v))),this.reset(),Bb.isNonEmptyArray(d)&&this.to(x(d)),""!==w&&v){switch(j=v.fullFormatDateValue(),k=v.subject(),u=v.aDraftInfo,l=b(v.body).clone(),Bb.removeBlockquoteSwitcher(l),m=l.html(),w){case zb.ComposeType.Empty:break;case zb.ComposeType.Reply:this.to(x(v.replyEmails(p))),this.subject(Bb.replySubjectAdd("Re",k)),this.prepearMessageAttachments(v,w),this.aDraftInfo=["reply",v.uid,v.folderFullNameRaw],this.sInReplyTo=v.sMessageId,this.sReferences=Bb.trim(this.sInReplyTo+" "+v.sReferences);break;case zb.ComposeType.ReplyAll:o=v.replyAllEmails(p),this.to(x(o[0])),this.cc(x(o[1])),this.subject(Bb.replySubjectAdd("Re",k)),this.prepearMessageAttachments(v,w),this.aDraftInfo=["reply",v.uid,v.folderFullNameRaw],this.sInReplyTo=v.sMessageId,this.sReferences=Bb.trim(this.sInReplyTo+" "+v.references());break;case zb.ComposeType.Forward:this.subject(Bb.replySubjectAdd("Fwd",k)),this.prepearMessageAttachments(v,w),this.aDraftInfo=["forward",v.uid,v.folderFullNameRaw],this.sInReplyTo=v.sMessageId,this.sReferences=Bb.trim(this.sInReplyTo+" "+v.sReferences);break;case zb.ComposeType.ForwardAsAttachment:this.subject(Bb.replySubjectAdd("Fwd",k)),this.prepearMessageAttachments(v,w),this.aDraftInfo=["forward",v.uid,v.folderFullNameRaw],this.sInReplyTo=v.sMessageId,this.sReferences=Bb.trim(this.sInReplyTo+" "+v.sReferences);break;case zb.ComposeType.Draft:this.to(x(v.to)),this.cc(x(v.cc)),this.bcc(x(v.bcc)),this.bFromDraft=!0,this.draftFolder(v.folderFullNameRaw),this.draftUid(v.uid),this.subject(k),this.prepearMessageAttachments(v,w),this.aDraftInfo=Bb.isNonEmptyArray(u)&&3===u.length?u:null,this.sInReplyTo=v.sInReplyTo,this.sReferences=v.sReferences;break;case zb.ComposeType.EditAsNew:this.to(x(v.to)),this.cc(x(v.cc)),this.bcc(x(v.bcc)),this.subject(k),this.prepearMessageAttachments(v,w),this.aDraftInfo=Bb.isNonEmptyArray(u)&&3===u.length?u:null,this.sInReplyTo=v.sInReplyTo,this.sReferences=v.sReferences}switch(w){case zb.ComposeType.Reply:case zb.ComposeType.ReplyAll:f=v.fromToLine(!1,!0),n=Bb.i18n("COMPOSE/REPLY_MESSAGE_TITLE",{DATETIME:j,EMAIL:f}),m="
"+n+":";break;case zb.ComposeType.Forward:f=v.fromToLine(!1,!0),g=v.toToLine(!1,!0),i=v.ccToLine(!1,!0),m=""+m+"
"+Bb.i18n("COMPOSE/FORWARD_MESSAGE_TOP_TITLE")+"
"+Bb.i18n("COMPOSE/FORWARD_MESSAGE_TOP_FROM")+": "+f+"
"+Bb.i18n("COMPOSE/FORWARD_MESSAGE_TOP_TO")+": "+g+(0"+Bb.i18n("COMPOSE/FORWARD_MESSAGE_TOP_CC")+": "+i:"")+"
"+Bb.i18n("COMPOSE/FORWARD_MESSAGE_TOP_SENT")+": "+Bb.encodeHtml(j)+"
"+Bb.i18n("COMPOSE/FORWARD_MESSAGE_TOP_SUBJECT")+": "+Bb.encodeHtml(k)+"
"+m;break;case zb.ComposeType.ForwardAsAttachment:m=""}s&&""!==r&&zb.ComposeType.EditAsNew!==w&&zb.ComposeType.Draft!==w&&(m=this.convertSignature(r,x(v.from,!0))+"
"+m),this.editor(function(a){a.setHtml(m,!1),v.isHtml()||a.modeToggle(!1)})}else zb.ComposeType.Empty===w?(m=this.convertSignature(r),this.editor(function(a){a.setHtml(m,!1),zb.EditorDefaultType.Html!==Ob.data().editorDefaultType()&&a.modeToggle(!1)})):Bb.isNonEmptyArray(c)&&h.each(c,function(a){e.addMessageAsAttachment(a)});t=this.getAttachmentsDownloadsForUpload(),Bb.isNonEmptyArray(t)&&Ob.remote().messageUploadAttachments(function(a,b){if(zb.StorageResultType.Success===a&&b&&b.Result){var c=null,d="";if(!e.viewModelVisibility())for(d in b.Result)b.Result.hasOwnProperty(d)&&(c=e.getAttachmentById(b.Result[d]),c&&c.tempName(d))}else e.setMessageAttachmentFailedDowbloadText()},t),this.triggerForResize()},H.prototype.onFocus=function(){""===this.to()?this.to.focusTrigger(!this.to.focusTrigger()):this.oEditor&&this.oEditor.focus(),this.triggerForResize()},H.prototype.editorResize=function(){this.oEditor&&this.oEditor.resize()},H.prototype.tryToClosePopup=function(){var a=this;Hb.showScreenPopup(S,[Bb.i18n("POPUPS_ASK/DESC_WANT_CLOSE_THIS_WINDOW"),function(){a.modalVisibility()&&Bb.delegateRun(a,"closeCommand")}])},H.prototype.onBuild=function(){this.initUploader();var a=this,c=null;j("ctrl+q, command+q",zb.KeyState.Compose,function(){return a.identitiesDropdownTrigger(!0),!1}),j("ctrl+s, command+s",zb.KeyState.Compose,function(){return a.saveCommand(),!1}),j("ctrl+enter, command+enter",zb.KeyState.Compose,function(){return a.sendCommand(),!1}),j("esc",zb.KeyState.Compose,function(){return a.tryToClosePopup(),!1}),Lb.on("resize",function(){a.triggerForResize()}),this.dropboxEnabled()&&(c=document.createElement("script"),c.type="text/javascript",c.src="https://www.dropbox.com/static/api/1/dropins.js",b(c).attr("id","dropboxjs").attr("data-app-key",Ob.settingsGet("DropboxApiKey")),document.body.appendChild(c))},H.prototype.getAttachmentById=function(a){for(var b=this.attachments(),c=0,d=b.length;d>c;c++)if(b[c]&&a===b[c].id)return b[c];return null},H.prototype.initUploader=function(){if(this.composeUploaderButton()){var a={},b=Bb.pInt(Ob.settingsGet("AttachmentLimit")),c=new g({action:Ob.link().upload(),name:"uploader",queueSize:2,multipleSizeLimit:50,disableFolderDragAndDrop:!1,clickElement:this.composeUploaderButton(),dragAndDropElement:this.composeUploaderDropPlace()});c?(c.on("onDragEnter",h.bind(function(){this.dragAndDropOver(!0)},this)).on("onDragLeave",h.bind(function(){this.dragAndDropOver(!1)},this)).on("onBodyDragEnter",h.bind(function(){this.dragAndDropVisible(!0)},this)).on("onBodyDragLeave",h.bind(function(){this.dragAndDropVisible(!1)},this)).on("onProgress",h.bind(function(b,c,d){var e=null;Bb.isUnd(a[b])?(e=this.getAttachmentById(b),e&&(a[b]=e)):e=a[b],e&&e.progress(" - "+Math.floor(c/d*100)+"%")},this)).on("onSelect",h.bind(function(a,d){this.dragAndDropOver(!1);var e=this,f=Bb.isUnd(d.FileName)?"":d.FileName.toString(),g=Bb.isNormal(d.Size)?Bb.pInt(d.Size):null,h=new y(a,f,g);return h.cancel=function(a){return function(){e.attachments.remove(function(b){return b&&b.id===a}),c&&c.cancel(a)}}(a),this.attachments.push(h),g>0&&b>0&&g>b?(h.error(Bb.i18n("UPLOAD/ERROR_FILE_IS_TOO_BIG")),!1):!0},this)).on("onStart",h.bind(function(b){var c=null;Bb.isUnd(a[b])?(c=this.getAttachmentById(b),c&&(a[b]=c)):c=a[b],c&&(c.waiting(!1),c.uploading(!0))},this)).on("onComplete",h.bind(function(b,c,d){var e="",f=null,g=null,h=this.getAttachmentById(b);g=c&&d&&d.Result&&d.Result.Attachment?d.Result.Attachment:null,f=d&&d.Result&&d.Result.ErrorCode?d.Result.ErrorCode:null,null!==f?e=Bb.getUploadErrorDescByCode(f):g||(e=Bb.i18n("UPLOAD/ERROR_UNKNOWN")),h&&(""!==e&&00&&d>0&&f>d?(e.uploading(!1),e.error(Bb.i18n("UPLOAD/ERROR_FILE_IS_TOO_BIG")),!1):(Ob.remote().composeUploadExternals(function(a,b){var c=!1;e.uploading(!1),zb.StorageResultType.Success===a&&b&&b.Result&&b.Result[e.id]&&(c=!0,e.tempName(b.Result[e.id])),c||e.error(Bb.getUploadErrorDescByCode(zb.UploadErrorCode.FileNoUploaded))},[a.link]),!0)},H.prototype.prepearMessageAttachments=function(a,b){if(a){var c=this,d=Bb.isNonEmptyArray(a.attachments())?a.attachments():[],e=0,f=d.length,g=null,h=null,i=!1,j=function(a){return function(){c.attachments.remove(function(b){return b&&b.id===a})}};if(zb.ComposeType.ForwardAsAttachment===b)this.addMessageAsAttachment(a);else for(;f>e;e++){switch(h=d[e],i=!1,b){case zb.ComposeType.Reply:case zb.ComposeType.ReplyAll:i=h.isLinked;break;case zb.ComposeType.Forward:case zb.ComposeType.Draft:case zb.ComposeType.EditAsNew:i=!0}i=!0,i&&(g=new y(h.download,h.fileName,h.estimatedSize,h.isInline,h.isLinked,h.cid,h.contentLocation),g.fromMessage=!0,g.cancel=j(h.download),g.waiting(!1).uploading(!0),this.attachments.push(g))}}},H.prototype.removeLinkedAttachments=function(){this.attachments.remove(function(a){return a&&a.isLinked})},H.prototype.setMessageAttachmentFailedDowbloadText=function(){h.each(this.attachments(),function(a){a&&a.fromMessage&&a.waiting(!1).uploading(!1).error(Bb.getUploadErrorDescByCode(zb.UploadErrorCode.FileNoUploaded))},this)},H.prototype.isEmptyForm=function(a){a=Bb.isUnd(a)?!0:!!a;var b=a?0===this.attachments().length:0===this.attachmentsInReady().length;return 0===this.to().length&&0===this.cc().length&&0===this.bcc().length&&0===this.subject().length&&b&&(!this.oEditor||""===this.oEditor.getData())},H.prototype.reset=function(){this.to(""),this.cc(""),this.bcc(""),this.replyTo(""),this.subject(""),this.requestReadReceipt(!1),this.aDraftInfo=null,this.sInReplyTo="",this.bFromDraft=!1,this.sReferences="",this.sendError(!1),this.sendSuccessButSaveError(!1),this.savedError(!1),this.savedTime(0),this.savedOrSendingText(""),this.emptyToError(!1),this.showCcAndBcc(!1),this.attachments([]),this.dragAndDropOver(!1),this.dragAndDropVisible(!1),this.draftFolder(""),this.draftUid(""),this.sending(!1),this.saving(!1),this.oEditor&&this.oEditor.clear(!1)},H.prototype.getAttachmentsDownloadsForUpload=function(){return h.map(h.filter(this.attachments(),function(a){return a&&""===a.tempName()}),function(a){return a.id})},H.prototype.triggerForResize=function(){this.resizer(!this.resizer()),this.editorResizeThrottle()},Bb.extendAsViewModel("PopupsContactsViewModel",I),I.prototype.getPropertyPlceholder=function(a){var b="";switch(a){case zb.ContactPropertyType.LastName:b="CONTACTS/PLACEHOLDER_ENTER_LAST_NAME";break;case zb.ContactPropertyType.FirstName:b="CONTACTS/PLACEHOLDER_ENTER_FIRST_NAME";break;case zb.ContactPropertyType.Nick:b="CONTACTS/PLACEHOLDER_ENTER_NICK_NAME"}return b},I.prototype.addNewProperty=function(a,b){this.viewProperties.push(new w(a,b||"","",!0,this.getPropertyPlceholder(a)))},I.prototype.addNewOrFocusProperty=function(a,b){var c=h.find(this.viewProperties(),function(b){return a===b.type()});c?c.focused(!0):this.addNewProperty(a,b)},I.prototype.addNewEmail=function(){this.addNewProperty(zb.ContactPropertyType.Email,"Home")},I.prototype.addNewPhone=function(){this.addNewProperty(zb.ContactPropertyType.Phone,"Mobile")},I.prototype.addNewWeb=function(){this.addNewProperty(zb.ContactPropertyType.Web)},I.prototype.addNewNickname=function(){this.addNewOrFocusProperty(zb.ContactPropertyType.Nick)},I.prototype.addNewNotes=function(){this.addNewOrFocusProperty(zb.ContactPropertyType.Note)},I.prototype.addNewBirthday=function(){this.addNewOrFocusProperty(zb.ContactPropertyType.Birthday)},I.prototype.exportVcf=function(){Ob.download(Ob.link().exportContactsVcf())},I.prototype.exportCsv=function(){Ob.download(Ob.link().exportContactsCsv())},I.prototype.initUploader=function(){if(this.importUploaderButton()){var b=new g({action:Ob.link().uploadContacts(),name:"uploader",queueSize:1,multipleSizeLimit:1,disableFolderDragAndDrop:!0,disableDragAndDrop:!0,disableMultiple:!0,disableDocumentDropPrevent:!0,clickElement:this.importUploaderButton()});b&&b.on("onStart",h.bind(function(){this.contacts.importing(!0)},this)).on("onComplete",h.bind(function(b,c,d){this.contacts.importing(!1),this.reloadContactList(),b&&c&&d&&d.Result||a.alert(Bb.i18n("CONTACTS/ERROR_IMPORT_FILE"))},this))}},I.prototype.removeCheckedOrSelectedContactsFromList=function(){var a=this,b=this.contacts,c=this.currentContact(),d=this.contacts().length,e=this.contactsCheckedOrSelected();0 =d&&(this.bDropPageAfterDelete=!0),h.delay(function(){h.each(e,function(a){b.remove(a)})},500))},I.prototype.deleteSelectedContacts=function(){0 0?d:0),b.contactsCount(d),b.contacts(e),b.viewClearSearch(""!==b.search()),b.contacts.loading(!1)},c,yb.Defaults.ContactsPerPage,this.search())},I.prototype.onBuild=function(a){this.oContentVisible=b(".b-list-content",a),this.oContentScrollable=b(".content",this.oContentVisible),this.selector.init(this.oContentVisible,this.oContentScrollable,zb.KeyState.ContactList);var d=this;j("delete",zb.KeyState.ContactList,function(){return d.deleteCommand(),!1}),a.on("click",".e-pagenator .e-page",function(){var a=c.dataFor(this);a&&(d.contactsPage(Bb.pInt(a.value)),d.reloadContactList())}),this.initUploader()},I.prototype.onShow=function(){Hb.routeOff(),this.reloadContactList(!0)},I.prototype.onHide=function(){Hb.routeOn(),this.currentContact(null),this.emptySelection(!0),this.search(""),h.each(this.contacts(),function(a){a.checked(!1)})},Bb.extendAsViewModel("PopupsAdvancedSearchViewModel",J),J.prototype.buildSearchStringValue=function(a){return-1 li"),e=c&&("tab"===c.shortcut||"right"===c.shortcut),f=d.index(d.filter(".active"));return!e&&f>0?f--:e&&f -1&&g.eq(e).removeClass("focused"),38===f&&e>0?e--:40===f&&e 1?" ("+(100>a?a:"99+")+")":""},Z.prototype.cancelSearch=function(){this.mainMessageListSearch(""),this.inputMessageListSearchFocus(!1)},Z.prototype.moveSelectedMessagesToFolder=function(a,b){return this.canBeMoved()&&Ob.moveMessagesToFolder(Ob.data().currentFolderFullNameRaw(),Ob.data().messageListCheckedOrSelectedUidsWithSubMails(),a,b),!1},Z.prototype.dragAndDronHelper=function(a){a&&a.checked(!0);var b=Bb.draggeblePlace(),c=Ob.data().messageListCheckedOrSelectedUidsWithSubMails();return b.data("rl-folder",Ob.data().currentFolderFullNameRaw()),b.data("rl-uids",c),b.find(".text").text(""+c.length),h.defer(function(){var a=Ob.data().messageListCheckedOrSelectedUidsWithSubMails();b.data("rl-uids",a),b.find(".text").text(""+a.length)}),b},Z.prototype.onMessageResponse=function(a,b,c){var d=Ob.data();d.hideMessageBodies(),d.messageLoading(!1),zb.StorageResultType.Success===a&&b&&b.Result?d.setMessage(b,c):zb.StorageResultType.Unload===a?(d.message(null),d.messageError("")):zb.StorageResultType.Abort!==a&&(d.message(null),d.messageError(b&&b.ErrorCode?Bb.getNotification(b.ErrorCode):Bb.getNotification(zb.Notification.UnknownError)))},Z.prototype.populateMessageBody=function(a){a&&(Ob.remote().message(this.onMessageResponse,a.folderFullNameRaw,a.uid)?Ob.data().messageLoading(!0):Bb.log("Error: Unknown message request: "+a.folderFullNameRaw+" ~ "+a.uid+" [e-101]"))},Z.prototype.setAction=function(a,b,c){var d=[],e=null,f=Ob.cache(),g=0;if(Bb.isUnd(c)&&(c=Ob.data().messageListChecked()),d=h.map(c,function(a){return a.uid}),""!==a&&0 0?100>a?a:"99+":""},$.prototype.verifyPgpSignedClearMessage=function(a){a&&a.verifyPgpSignedClearMessage()},$.prototype.decryptPgpEncryptedMessage=function(a){a&&a.decryptPgpEncryptedMessage(this.viewPgpPassword())},$.prototype.readReceipt=function(a){a&&""!==a.readReceipt()&&(Ob.remote().sendReadReceiptMessage(Bb.emptyFunction,a.folderFullNameRaw,a.uid,a.readReceipt(),Bb.i18n("READ_RECEIPT/SUBJECT",{SUBJECT:a.subject()}),Bb.i18n("READ_RECEIPT/BODY",{"READ-RECEIPT":Ob.data().accountEmail()})),a.isReadReceipt(!0),Ob.cache().storeMessageFlagsToCache(a),Ob.reloadFlagsCurrentMessageListAndMessageFromCache())},Bb.extendAsViewModel("SettingsMenuViewModel",_),_.prototype.link=function(a){return Ob.link().settings(a)},_.prototype.backToMailBoxClick=function(){Hb.setHash(Ob.link().inbox())},Bb.extendAsViewModel("SettingsPaneViewModel",ab),ab.prototype.onBuild=function(){var a=this;j("esc",zb.KeyState.Settings,function(){a.backToMailBoxClick()})},ab.prototype.onShow=function(){Ob.data().message(null)},ab.prototype.backToMailBoxClick=function(){Hb.setHash(Ob.link().inbox())},Bb.addSettingsViewModel(bb,"SettingsGeneral","SETTINGS_LABELS/LABEL_GENERAL_NAME","general",!0),bb.prototype.toggleLayout=function(){this.layout(zb.Layout.NoPreview===this.layout()?zb.Layout.SidePreview:zb.Layout.NoPreview)},bb.prototype.onBuild=function(){var a=this;h.delay(function(){var c=Ob.data(),d=Bb.settingsSaveHelperSimpleFunction(a.mppTrigger,a);c.language.subscribe(function(c){a.languageTrigger(zb.SaveSettingsStep.Animate),b.ajax({url:Ob.link().langLink(c),dataType:"script",cache:!0}).done(function(){Bb.i18nToDoc(),a.languageTrigger(zb.SaveSettingsStep.TrueResult)}).fail(function(){a.languageTrigger(zb.SaveSettingsStep.FalseResult)}).always(function(){h.delay(function(){a.languageTrigger(zb.SaveSettingsStep.Idle)},1e3)}),Ob.remote().saveSettings(Bb.emptyFunction,{Language:c})}),c.editorDefaultType.subscribe(function(a){Ob.remote().saveSettings(Bb.emptyFunction,{EditorDefaultType:a})}),c.messagesPerPage.subscribe(function(a){Ob.remote().saveSettings(d,{MPP:a})}),c.showImages.subscribe(function(a){Ob.remote().saveSettings(Bb.emptyFunction,{ShowImages:a?"1":"0"})}),c.interfaceAnimation.subscribe(function(a){Ob.remote().saveSettings(Bb.emptyFunction,{InterfaceAnimation:a})}),c.useDesktopNotifications.subscribe(function(a){Bb.timeOutAction("SaveDesktopNotifications",function(){Ob.remote().saveSettings(Bb.emptyFunction,{DesktopNotifications:a?"1":"0"})},3e3)}),c.replySameFolder.subscribe(function(a){Bb.timeOutAction("SaveReplySameFolder",function(){Ob.remote().saveSettings(Bb.emptyFunction,{ReplySameFolder:a?"1":"0"})},3e3)}),c.useThreads.subscribe(function(a){c.messageList([]),Ob.remote().saveSettings(Bb.emptyFunction,{UseThreads:a?"1":"0"})}),c.layout.subscribe(function(a){c.messageList([]),Ob.remote().saveSettings(Bb.emptyFunction,{Layout:a})}),c.useCheckboxesInList.subscribe(function(a){Ob.remote().saveSettings(Bb.emptyFunction,{UseCheckboxesInList:a?"1":"0"})})},50)},bb.prototype.onShow=function(){Ob.data().desktopNotifications.valueHasMutated()},bb.prototype.selectLanguage=function(){Hb.showScreenPopup(Q)},Bb.addSettingsViewModel(cb,"SettingsContacts","SETTINGS_LABELS/LABEL_CONTACTS_NAME","contacts"),cb.prototype.onBuild=function(){Ob.data().contactsAutosave.subscribe(function(a){Ob.remote().saveSettings(Bb.emptyFunction,{ContactsAutosave:a?"1":"0"})})},Bb.addSettingsViewModel(db,"SettingsAccounts","SETTINGS_LABELS/LABEL_ACCOUNTS_NAME","accounts"),db.prototype.addNewAccount=function(){Hb.showScreenPopup(K)},db.prototype.deleteAccount=function(b){if(b&&b.deleteAccess()){this.accountForDeletion(null);var c=function(a){return b===a};b&&(this.accounts.remove(c),Ob.remote().accountDelete(function(b,c){zb.StorageResultType.Success===b&&c&&c.Result&&c.Reload?(Hb.routeOff(),Hb.setHash(Ob.link().root(),!0),Hb.routeOff(),h.defer(function(){a.location.reload()})):Ob.accountsAndIdentities()},b.email))}},Bb.addSettingsViewModel(eb,"SettingsIdentity","SETTINGS_LABELS/LABEL_IDENTITY_NAME","identity"),eb.prototype.onFocus=function(){if(!this.editor&&this.signatureDom()){var a=this,b=Ob.data().signature();this.editor=new l(a.signatureDom(),function(){Ob.data().signature((a.editor.isHtml()?":HTML:":"")+a.editor.getData())},function(){":HTML:"===b.substr(0,6)?a.editor.setHtml(b.substr(6),!1):a.editor.setPlain(b,!1)})}},eb.prototype.onBuild=function(){var a=this;h.delay(function(){var b=Ob.data(),c=Bb.settingsSaveHelperSimpleFunction(a.displayNameTrigger,a),d=Bb.settingsSaveHelperSimpleFunction(a.replyTrigger,a),e=Bb.settingsSaveHelperSimpleFunction(a.signatureTrigger,a);b.displayName.subscribe(function(a){Ob.remote().saveSettings(c,{DisplayName:a})}),b.replyTo.subscribe(function(a){Ob.remote().saveSettings(d,{ReplyTo:a})}),b.signature.subscribe(function(a){Ob.remote().saveSettings(e,{Signature:a})}),b.signatureToAll.subscribe(function(a){Ob.remote().saveSettings(null,{SignatureToAll:a?"1":"0"})})},50)},Bb.addSettingsViewModel(fb,"SettingsIdentities","SETTINGS_LABELS/LABEL_IDENTITIES_NAME","identities"),fb.prototype.addNewIdentity=function(){Hb.showScreenPopup(P)},fb.prototype.editIdentity=function(a){Hb.showScreenPopup(P,[a])},fb.prototype.deleteIdentity=function(a){if(a&&a.deleteAccess()){this.identityForDeletion(null);var b=function(b){return a===b};a&&(this.identities.remove(b),Ob.remote().identityDelete(function(){Ob.accountsAndIdentities()},a.id))}},fb.prototype.onFocus=function(){if(!this.editor&&this.signatureDom()){var a=this,b=Ob.data().signature();this.editor=new l(a.signatureDom(),function(){Ob.data().signature((a.editor.isHtml()?":HTML:":"")+a.editor.getData())},function(){":HTML:"===b.substr(0,6)?a.editor.setHtml(b.substr(6),!1):a.editor.setPlain(b,!1)})}},fb.prototype.onBuild=function(a){var b=this;a.on("click",".identity-item .e-action",function(){var a=c.dataFor(this);a&&b.editIdentity(a)}),h.delay(function(){var a=Ob.data(),c=Bb.settingsSaveHelperSimpleFunction(b.displayNameTrigger,b),d=Bb.settingsSaveHelperSimpleFunction(b.replyTrigger,b),e=Bb.settingsSaveHelperSimpleFunction(b.signatureTrigger,b);a.displayName.subscribe(function(a){Ob.remote().saveSettings(c,{DisplayName:a})}),a.replyTo.subscribe(function(a){Ob.remote().saveSettings(d,{ReplyTo:a})}),a.signature.subscribe(function(a){Ob.remote().saveSettings(e,{Signature:a})}),a.signatureToAll.subscribe(function(a){Ob.remote().saveSettings(null,{SignatureToAll:a?"1":"0"})})},50)},Bb.addSettingsViewModel(gb,"SettingsSecurity","SETTINGS_LABELS/LABEL_SECURITY_NAME","security"),gb.prototype.showSecret=function(){this.secreting(!0),Ob.remote().showTwoFactorSecret(this.onSecretResult)},gb.prototype.hideSecret=function(){this.viewSecret(""),this.viewBackupCodes(""),this.viewUrl("")},gb.prototype.createTwoFactor=function(){this.processing(!0),Ob.remote().createTwoFactor(this.onResult)},gb.prototype.enableTwoFactor=function(){this.processing(!0),Ob.remote().enableTwoFactor(this.onResult,this.viewEnable())},gb.prototype.testTwoFactor=function(){Hb.showScreenPopup(R)},gb.prototype.clearTwoFactor=function(){this.viewSecret(""),this.viewBackupCodes(""),this.viewUrl(""),this.clearing(!0),Ob.remote().clearTwoFactor(this.onResult)},gb.prototype.onShow=function(){this.viewSecret(""),this.viewBackupCodes(""),this.viewUrl("")},gb.prototype.onResult=function(a,b){if(this.processing(!1),this.clearing(!1),zb.StorageResultType.Success===a&&b&&b.Result?(this.viewUser(Bb.pString(b.Result.User)),this.viewEnable(!!b.Result.Enable),this.twoFactorStatus(!!b.Result.IsSet),this.viewSecret(Bb.pString(b.Result.Secret)),this.viewBackupCodes(Bb.pString(b.Result.BackupCodes).replace(/[\s]+/g," ")),this.viewUrl(Bb.pString(b.Result.Url))):(this.viewUser(""),this.viewEnable(!1),this.twoFactorStatus(!1),this.viewSecret(""),this.viewBackupCodes(""),this.viewUrl("")),this.bFirst){this.bFirst=!1;var c=this;this.viewEnable.subscribe(function(a){this.viewEnable.subs&&Ob.remote().enableTwoFactor(function(a,b){zb.StorageResultType.Success===a&&b&&b.Result||(c.viewEnable.subs=!1,c.viewEnable(!1),c.viewEnable.subs=!0)},a)},this)}},gb.prototype.onSecretResult=function(a,b){this.secreting(!1),zb.StorageResultType.Success===a&&b&&b.Result?(this.viewSecret(Bb.pString(b.Result.Secret)),this.viewUrl(Bb.pString(b.Result.Url))):(this.viewSecret(""),this.viewUrl(""))},gb.prototype.onBuild=function(){this.processing(!0),Ob.remote().getTwoFactor(this.onResult)},Bb.addSettingsViewModel(hb,"SettingsSocial","SETTINGS_LABELS/LABEL_SOCIAL_NAME","social"),Bb.addSettingsViewModel(ib,"SettingsChangePassword","SETTINGS_LABELS/LABEL_CHANGE_PASSWORD_NAME","change-password"),ib.prototype.onHide=function(){this.changeProcess(!1),this.currentPassword(""),this.newPassword(""),this.newPassword2(""),this.errorDescription(""),this.passwordMismatch(!1),this.currentPassword.error(!1)},ib.prototype.onChangePasswordResponse=function(a,b){this.changeProcess(!1),this.passwordMismatch(!1),this.errorDescription(""),this.currentPassword.error(!1),zb.StorageResultType.Success===a&&b&&b.Result?(this.currentPassword(""),this.newPassword(""),this.newPassword2(""),this.passwordUpdateSuccess(!0),this.currentPassword.error(!1)):(b&&zb.Notification.CurrentPasswordIncorrect===b.ErrorCode&&this.currentPassword.error(!0),this.passwordUpdateError(!0),this.errorDescription(b&&b.ErrorCode?Bb.getNotification(b.ErrorCode):Bb.getNotification(zb.Notification.CouldNotSaveNewPassword)))},Bb.addSettingsViewModel(jb,"SettingsFolders","SETTINGS_LABELS/LABEL_FOLDERS_NAME","folders"),jb.prototype.folderEditOnEnter=function(a){var b=a?Bb.trim(a.nameForEdit()):"";""!==b&&a.name()!==b&&(Ob.local().set(zb.ClientSideKeyName.FoldersLashHash,""),Ob.data().foldersRenaming(!0),Ob.remote().folderRename(function(a,b){Ob.data().foldersRenaming(!1),zb.StorageResultType.Success===a&&b&&b.Result||Ob.data().foldersListError(b&&b.ErrorCode?Bb.getNotification(b.ErrorCode):Bb.i18n("NOTIFICATIONS/CANT_RENAME_FOLDER")),Ob.folders()},a.fullNameRaw,b),Ob.cache().removeFolderFromCacheList(a.fullNameRaw),a.name(b)),a.edited(!1)},jb.prototype.folderEditOnEsc=function(a){a&&a.edited(!1)},jb.prototype.onShow=function(){Ob.data().foldersListError("")},jb.prototype.createFolder=function(){Hb.showScreenPopup(F)},jb.prototype.systemFolder=function(){Hb.showScreenPopup(G)},jb.prototype.deleteFolder=function(a){if(a&&a.canBeDeleted()&&a.deleteAccess()&&0===a.privateMessageCountAll()){this.folderForDeletion(null);var b=function(c){return a===c?!0:(c.subFolders.remove(b),!1)};a&&(Ob.local().set(zb.ClientSideKeyName.FoldersLashHash,""),Ob.data().folderList.remove(b),Ob.data().foldersDeleting(!0),Ob.remote().folderDelete(function(a,b){Ob.data().foldersDeleting(!1),zb.StorageResultType.Success===a&&b&&b.Result||Ob.data().foldersListError(b&&b.ErrorCode?Bb.getNotification(b.ErrorCode):Bb.i18n("NOTIFICATIONS/CANT_DELETE_FOLDER")),Ob.folders()},a.fullNameRaw),Ob.cache().removeFolderFromCacheList(a.fullNameRaw))}else 0 0&&(c=this.messagesBodiesDom(),c&&(c.find(".rl-cache-class").each(function(){var c=b(this); -d>c.data("rl-cache-count")&&(c.addClass("rl-cache-purge"),a++)}),a>0&&h.delay(function(){c.find(".rl-cache-purge").remove()},300)))},nb.prototype.populateDataOnStart=function(){mb.prototype.populateDataOnStart.call(this),this.accountEmail(Ob.settingsGet("Email")),this.accountIncLogin(Ob.settingsGet("IncLogin")),this.accountOutLogin(Ob.settingsGet("OutLogin")),this.projectHash(Ob.settingsGet("ProjectHash")),this.displayName(Ob.settingsGet("DisplayName")),this.replyTo(Ob.settingsGet("ReplyTo")),this.signature(Ob.settingsGet("Signature")),this.signatureToAll(!!Ob.settingsGet("SignatureToAll")),this.enableTwoFactor(!!Ob.settingsGet("EnableTwoFactor")),this.lastFoldersHash=Ob.local().get(zb.ClientSideKeyName.FoldersLashHash)||"",this.remoteSuggestions=!!Ob.settingsGet("RemoteSuggestions"),this.devEmail=Ob.settingsGet("DevEmail"),this.devLogin=Ob.settingsGet("DevLogin"),this.devPassword=Ob.settingsGet("DevPassword")},nb.prototype.initUidNextAndNewMessages=function(b,c,d){if("INBOX"===b&&Bb.isNormal(c)&&""!==c){if(Bb.isArray(d)&&0 3)i(Ob.link().notificationMailIcon(),Ob.data().accountEmail(),Bb.i18n("MESSAGE_LIST/NEW_MESSAGE_NOTIFICATION",{COUNT:g}));else for(;g>f;f++)i(Ob.link().notificationMailIcon(),z.emailsToLine(z.initEmailsFromJson(d[f].From),!1),d[f].Subject)}Ob.cache().setFolderUidNext(b,c)}},nb.prototype.folderResponseParseRec=function(a,b){var c=0,d=0,e=null,f=null,g="",h=[],i=[];for(c=0,d=b.length;d>c;c++)e=b[c],e&&(g=e.FullNameRaw,f=Ob.cache().getFolderFromCacheList(g),f||(f=A.newInstanceFromJson(e),f&&(Ob.cache().setFolderToCacheList(g,f),Ob.cache().setFolderFullNameRaw(f.fullNameHash,g))),f&&(f.collapsed(!Bb.isFolderExpanded(f.fullNameHash)),e.Extended&&(e.Extended.Hash&&Ob.cache().setFolderHash(f.fullNameRaw,e.Extended.Hash),Bb.isNormal(e.Extended.MessageCount)&&f.messageCountAll(e.Extended.MessageCount),Bb.isNormal(e.Extended.MessageUnseenCount)&&f.messageCountUnread(e.Extended.MessageUnseenCount)),h=e.SubFolders,h&&"Collection/FolderCollection"===h["@Object"]&&h["@Collection"]&&Bb.isArray(h["@Collection"])&&f.subFolders(this.folderResponseParseRec(a,h["@Collection"])),i.push(f)));return i},nb.prototype.setFolders=function(a){var b=[],c=!1,d=Ob.data(),e=function(a){return""===a||yb.Values.UnuseOptionValue===a||null!==Ob.cache().getFolderFromCacheList(a)?a:""};a&&a.Result&&"Collection/FolderCollection"===a.Result["@Object"]&&a.Result["@Collection"]&&Bb.isArray(a.Result["@Collection"])&&(Bb.isUnd(a.Result.Namespace)||(d.namespace=a.Result.Namespace),this.threading(!!Ob.settingsGet("UseImapThread")&&a.Result.IsThreadsSupported&&!0),b=this.folderResponseParseRec(d.namespace,a.Result["@Collection"]),d.folderList(b),a.Result.SystemFolders&&""==""+Ob.settingsGet("SentFolder")+Ob.settingsGet("DraftFolder")+Ob.settingsGet("SpamFolder")+Ob.settingsGet("TrashFolder")+Ob.settingsGet("ArchiveFolder")+Ob.settingsGet("NullFolder")&&(Ob.settingsSet("SentFolder",a.Result.SystemFolders[2]||null),Ob.settingsSet("DraftFolder",a.Result.SystemFolders[3]||null),Ob.settingsSet("SpamFolder",a.Result.SystemFolders[4]||null),Ob.settingsSet("TrashFolder",a.Result.SystemFolders[5]||null),Ob.settingsSet("ArchiveFolder",a.Result.SystemFolders[12]||null),c=!0),d.sentFolder(e(Ob.settingsGet("SentFolder"))),d.draftFolder(e(Ob.settingsGet("DraftFolder"))),d.spamFolder(e(Ob.settingsGet("SpamFolder"))),d.trashFolder(e(Ob.settingsGet("TrashFolder"))),d.archiveFolder(e(Ob.settingsGet("ArchiveFolder"))),c&&Ob.remote().saveSystemFolders(Bb.emptyFunction,{SentFolder:d.sentFolder(),DraftFolder:d.draftFolder(),SpamFolder:d.spamFolder(),TrashFolder:d.trashFolder(),ArchiveFolder:d.archiveFolder(),NullFolder:"NullFolder"}),Ob.local().set(zb.ClientSideKeyName.FoldersLashHash,a.Result.FoldersHash))},nb.prototype.hideMessageBodies=function(){var a=this.messagesBodiesDom();a&&a.find(".b-text-part").hide()},nb.prototype.getNextFolderNames=function(a){a=Bb.isUnd(a)?!1:!!a;var b=[],c=10,d=f().unix(),e=d-300,g=[],i=function(b){h.each(b,function(b){b&&"INBOX"!==b.fullNameRaw&&b.selectable&&b.existen&&e>b.interval&&(!a||b.subScribed())&&g.push([b.interval,b.fullNameRaw]),b&&0 b[0]?1:0}),h.find(g,function(a){var e=Ob.cache().getFolderFromCacheList(a[1]);return e&&(e.interval=d,b.push(a[1])),c<=b.length}),h.uniq(b)},nb.prototype.removeMessagesFromList=function(a,b,c,d){c=Bb.isNormal(c)?c:"",d=Bb.isUnd(d)?!1:!!d,b=h.map(b,function(a){return Bb.pInt(a)});var e=0,f=Ob.data(),g=Ob.cache(),i=f.messageList(),j=Ob.cache().getFolderFromCacheList(a),k=""===c?null:g.getFolderFromCacheList(c||""),l=f.currentFolderFullNameRaw(),m=f.message(),n=l===a?h.filter(i,function(a){return a&&-1 0&&j.messageCountUnread(0<=j.messageCountUnread()-e?j.messageCountUnread()-e:0)),k&&(k.messageCountAll(k.messageCountAll()+b.length),e>0&&k.messageCountUnread(k.messageCountUnread()+e),k.actionBlink(!0)),0 ').hide().addClass("rl-cache-class"),g.data("rl-cache-count",++Eb.iMessageBodyCacheCount),Bb.isNormal(a.Result.Html)&&""!==a.Result.Html?(d=!0,g.html(a.Result.Html.toString()).addClass("b-text-part html")):Bb.isNormal(a.Result.Plain)&&""!==a.Result.Plain?(d=!1,j=a.Result.Plain.toString(),(n.isPgpSigned()||n.isPgpEncrypted())&&Ob.data().allowOpenPGP()&&Bb.isNormal(a.Result.PlainRaw)&&(n.plainRaw=Bb.pString(a.Result.PlainRaw),l=/---BEGIN PGP MESSAGE---/.test(n.plainRaw),l||(k=/-----BEGIN PGP SIGNED MESSAGE-----/.test(n.plainRaw)&&/-----BEGIN PGP SIGNATURE-----/.test(n.plainRaw)),Pb.empty(),k&&n.isPgpSigned()?j=Pb.append(b('').text(n.plainRaw)).html():l&&n.isPgpEncrypted()&&(j=Pb.append(b('').text(n.plainRaw)).html()),Pb.empty(),n.isPgpSigned(k),n.isPgpEncrypted(l)),g.html(j).addClass("b-text-part plain")):d=!1,n.isHtml(!!d),n.hasImages(!!e),n.pgpSignedVerifyStatus(zb.SignedVerifyStatus.None),n.pgpSignedVerifyUser(""),a.Result.Rtl&&(n.isRtl(!0),g.addClass("rtl-text-part")),n.body=g,n.body&&m.append(n.body),n.storeDataToDom(),f&&n.showInternalImages(!0),n.hasImages()&&this.showImages()&&n.showExternalImages(!0),this.purgeMessageBodyCacheThrottle()),this.messageActiveDom(n.body),this.hideMessageBodies(),n.body.show(),g&&Bb.initBlockquoteSwitcher(g)),Ob.cache().initMessageFlagsFromCache(n),n.unseen()&&Ob.setMessageSeen(n),Bb.windowResize())},nb.prototype.calculateMessageListHash=function(a){return h.map(a,function(a){return""+a.hash+"_"+a.threadsLen()+"_"+a.flagHash()}).join("|")},nb.prototype.setMessageList=function(a,b){if(a&&a.Result&&"Collection/MessageCollection"===a.Result["@Object"]&&a.Result["@Collection"]&&Bb.isArray(a.Result["@Collection"])){var c=Ob.data(),d=Ob.cache(),e=null,g=0,h=0,i=0,j=0,k=[],l=f().unix(),m=c.staticMessageList,n=null,o=null,p=null,q=0,r=!1;for(i=Bb.pInt(a.Result.MessageResultCount),j=Bb.pInt(a.Result.Offset),Bb.isNonEmptyArray(a.Result.LastCollapsedThreadUids)&&(e=a.Result.LastCollapsedThreadUids),p=Ob.cache().getFolderFromCacheList(Bb.isNormal(a.Result.Folder)?a.Result.Folder:""),p&&!b&&(p.interval=l,Ob.cache().setFolderHash(a.Result.Folder,a.Result.FolderHash),Bb.isNormal(a.Result.MessageCount)&&p.messageCountAll(a.Result.MessageCount),Bb.isNormal(a.Result.MessageUnseenCount)&&(Bb.pInt(p.messageCountUnread())!==Bb.pInt(a.Result.MessageUnseenCount)&&(r=!0),p.messageCountUnread(a.Result.MessageUnseenCount)),this.initUidNextAndNewMessages(p.fullNameRaw,a.Result.UidNext,a.Result.NewMessages)),r&&p&&Ob.cache().clearMessageFlagsFromCacheByFolder(p.fullNameRaw),g=0,h=a.Result["@Collection"].length;h>g;g++)n=a.Result["@Collection"][g],n&&"Object/Message"===n["@Object"]&&(o=m[g],o&&o.initByJson(n)||(o=z.newInstanceFromJson(n)),o&&(d.hasNewMessageAndRemoveFromCache(o.folderFullNameRaw,o.uid)&&5>=q&&(q++,o.newForAnimation(!0)),o.deleted(!1),b?Ob.cache().initMessageFlagsFromCache(o):Ob.cache().storeMessageFlagsToCache(o),o.lastInCollapsedThread(e&&-1 (new a.Date).getTime()-l),n&&i.oRequests[n]&&(i.oRequests[n].__aborted&&(e="abort"),i.oRequests[n]=null),i.defaultResponse(c,n,e,b,f,d)}),n&&0 0?(this.defaultRequest(a,"Message",{},null,"Message/"+Db.urlsafe_encode([b,c,Ob.data().projectHash(),Ob.data().threading()&&Ob.data().useThreads()?"1":"0"].join(String.fromCharCode(0))),["Message"]),!0):!1},pb.prototype.composeUploadExternals=function(a,b){this.defaultRequest(a,"ComposeUploadExternals",{Externals:b},999e3)},pb.prototype.folderInformation=function(a,b,c){var d=!0,e=Ob.cache(),f=[];Bb.isArray(c)&&0 l;l++)q.push({id:e[l][0],name:e[l][1],system:!1,seporator:!1,disabled:!1});for(o=!0,l=0,m=b.length;m>l;l++)n=b[l],(h?h.call(null,n):!0)&&(o&&0 l;l++)n=c[l],(n.subScribed()||!n.existen)&&(h?h.call(null,n):!0)&&(zb.FolderType.User===n.type()||!j||0 =5?e:20,e=320>=e?e:320,a.setInterval(function(){Ob.contactsSync()},6e4*e+5e3),h.delay(function(){Ob.contactsSync()},5e3),h.delay(function(){Ob.folderInformationMultiply(!0)},500),h.delay(function(){Ob.emailsPicsHashes(),Ob.remote().servicesPics(function(a,b){zb.StorageResultType.Success===a&&b&&b.Result&&Ob.cache().setServicesData(b.Result)})},2e3),Cb.runHook("rl-start-user-screens"),Ob.pub("rl.bootstart-user-screens"),Ob.settingsGet("AccountSignMe")&&a.navigator.registerProtocolHandler&&h.delay(function(){try{a.navigator.registerProtocolHandler("mailto",a.location.protocol+"//"+a.location.host+a.location.pathname+"?mailto&to=%s",""+(Ob.settingsGet("Title")||"RainLoop"))}catch(b){}Ob.settingsGet("MailToEmail")&&Ob.mailToHelper(Ob.settingsGet("MailToEmail"))},500)):(Hb.startScreens([tb]),Cb.runHook("rl-start-login-screens"),Ob.pub("rl.bootstart-login-screens")),a.SimplePace&&a.SimplePace.set(100),Eb.bMobileDevice||h.defer(function(){Bb.initLayoutResizer("#rl-left","#rl-right",zb.ClientSideKeyName.FolderListSize)})},this))):(c=Bb.pString(Ob.settingsGet("CustomLoginLink")),c?(Hb.routeOff(),Hb.setHash(Ob.link().root(),!0),Hb.routeOff(),h.defer(function(){a.location.href=c})):(Hb.hideLoading(),Hb.startScreens([tb]),Cb.runHook("rl-start-login-screens"),Ob.pub("rl.bootstart-login-screens"),a.SimplePace&&a.SimplePace.set(100))),f&&(a["rl_"+d+"_google_service"]=function(){Ob.data().googleActions(!0),Ob.socialUsers()}),g&&(a["rl_"+d+"_facebook_service"]=function(){Ob.data().facebookActions(!0),Ob.socialUsers()}),i&&(a["rl_"+d+"_twitter_service"]=function(){Ob.data().twitterActions(!0),Ob.socialUsers()}),Ob.sub("interval.1m",function(){Eb.momentTrigger(!Eb.momentTrigger())}),Cb.runHook("rl-start-screens"),Ob.pub("rl.bootstart-end")},Ob=new xb,Kb.addClass(Eb.bMobileDevice?"mobile":"no-mobile"),Lb.keydown(Bb.killCtrlAandS).keyup(Bb.killCtrlAandS),Lb.unload(function(){Eb.bUnload=!0}),Kb.on("click.dropdown.data-api",function(){Bb.detectDropdownVisibility()}),a.rl=a.rl||{},a.rl.addHook=Cb.addHook,a.rl.settingsGet=Cb.mainSettingsGet,a.rl.remoteRequest=Cb.remoteRequest,a.rl.pluginSettingsGet=Cb.settingsGet,a.rl.addSettingsViewModel=Bb.addSettingsViewModel,a.rl.createCommand=Bb.createCommand,a.rl.EmailModel=u,a.rl.Enums=zb,a.__RLBOOT=function(c){b(function(){a.rainloopTEMPLATES&&a.rainloopTEMPLATES[0]?(b("#rl-templates").html(a.rainloopTEMPLATES[0]),h.delay(function(){a.rainloopAppData={},a.rainloopI18N={},a.rainloopTEMPLATES={},Hb.setBoot(Ob).bootstart(),Kb.removeClass("no-js rl-booted-trigger").addClass("rl-booted")},50)):c(!1),a.__RLBOOT=null})},a.SimplePace&&a.SimplePace.add(10)}(window,jQuery,ko,crossroads,hasher,moment,Jua,_,ifvisible,key); \ No newline at end of file +!function(a,b,c,d,e,f,g,h,i,j){"use strict";function k(){this.sBase="#/",this.sVersion=Ob.settingsGet("Version"),this.sSpecSuffix=Ob.settingsGet("AuthAccountHash")||"0",this.sServer=(Ob.settingsGet("IndexFile")||"./")+"?"}function l(a,c,d,e){var f=this;f.editor=null,f.iBlurTimer=0,f.fOnBlur=c||null,f.fOnReady=d||null,f.fOnModeChange=e||null,f.$element=b(a),f.init()}function m(a,b,d,e,f,g){this.list=a,this.listChecked=c.computed(function(){return h.filter(this.list(),function(a){return a.checked()})},this).extend({rateLimit:0}),this.isListChecked=c.computed(function(){return 0 0&&-1 b?b:a))},this),this.body=null,this.plainRaw="",this.isRtl=c.observable(!1),this.isHtml=c.observable(!1),this.hasImages=c.observable(!1),this.attachments=c.observableArray([]),this.isPgpSigned=c.observable(!1),this.isPgpEncrypted=c.observable(!1),this.pgpSignedVerifyStatus=c.observable(zb.SignedVerifyStatus.None),this.pgpSignedVerifyUser=c.observable(""),this.priority=c.observable(zb.MessagePriority.Normal),this.readReceipt=c.observable(""),this.aDraftInfo=[],this.sMessageId="",this.sInReplyTo="",this.sReferences="",this.parentUid=c.observable(0),this.threads=c.observableArray([]),this.threadsLen=c.observable(0),this.hasUnseenSubMessage=c.observable(!1),this.hasFlaggedSubMessage=c.observable(!1),this.lastInCollapsedThread=c.observable(!1),this.lastInCollapsedThreadLoading=c.observable(!1),this.threadsLenResult=c.computed(function(){var a=this.threadsLen();return 0===this.parentUid()&&a>0?a+1:""},this)}function A(){this.name=c.observable(""),this.fullName="",this.fullNameRaw="",this.fullNameHash="",this.delimiter="",this.namespace="",this.deep=0,this.interval=0,this.selectable=!1,this.existen=!0,this.type=c.observable(zb.FolderType.User),this.focused=c.observable(!1),this.selected=c.observable(!1),this.edited=c.observable(!1),this.collapsed=c.observable(!0),this.subScribed=c.observable(!0),this.subFolders=c.observableArray([]),this.deleteAccess=c.observable(!1),this.actionBlink=c.observable(!1).extend({falseTimeout:1e3}),this.nameForEdit=c.observable(""),this.name.subscribe(function(a){this.nameForEdit(a)},this),this.edited.subscribe(function(a){a&&this.nameForEdit(this.name())},this),this.privateMessageCountAll=c.observable(0),this.privateMessageCountUnread=c.observable(0),this.collapsedPrivate=c.observable(!0)}function B(a,b){this.email=a,this.deleteAccess=c.observable(!1),this.canBeDalete=c.observable(b)}function C(a,b,d){this.id=a,this.email=c.observable(b),this.name=c.observable(""),this.replyTo=c.observable(""),this.bcc=c.observable(""),this.deleteAccess=c.observable(!1),this.canBeDalete=c.observable(d)}function D(a,b,d,e,f,g,h){this.index=a,this.id=d,this.guid=b,this.user=e,this.email=f,this.armor=h,this.isPrivate=!!g,this.deleteAccess=c.observable(!1)}function E(){r.call(this,"Popups","PopupsFolderClear"),this.selectedFolder=c.observable(null),this.clearingProcess=c.observable(!1),this.clearingError=c.observable(""),this.folderFullNameForClear=c.computed(function(){var a=this.selectedFolder();return a?a.printableFullName():""},this),this.folderNameForClear=c.computed(function(){var a=this.selectedFolder();return a?a.localName():""},this),this.dangerDescHtml=c.computed(function(){return Bb.i18n("POPUPS_CLEAR_FOLDER/DANGER_DESC_HTML_1",{FOLDER:this.folderNameForClear()})},this),this.clearCommand=Bb.createCommand(this,function(){var a=this,b=this.selectedFolder();b&&(Ob.data().message(null),Ob.data().messageList([]),this.clearingProcess(!0),Ob.cache().setFolderHash(b.fullNameRaw,""),Ob.remote().folderClear(function(b,c){a.clearingProcess(!1),zb.StorageResultType.Success===b&&c&&c.Result?(Ob.reloadMessageList(!0),a.cancelCommand()):a.clearingError(c&&c.ErrorCode?Bb.getNotification(c.ErrorCode):Bb.getNotification(zb.Notification.MailServerError))},b.fullNameRaw))},function(){var a=this.selectedFolder(),b=this.clearingProcess();return!b&&null!==a}),t.constructorEnd(this)}function F(){r.call(this,"Popups","PopupsFolderCreate"),Bb.initOnStartOrLangChange(function(){this.sNoParentText=Bb.i18n("POPUPS_CREATE_FOLDER/SELECT_NO_PARENT")},this),this.folderName=c.observable(""),this.folderName.focused=c.observable(!1),this.selectedParentValue=c.observable(yb.Values.UnuseOptionValue),this.parentFolderSelectList=c.computed(function(){var a=Ob.data(),b=[],c=null,d=null,e=a.folderList(),f=function(a){return a?a.isSystemFolder()?a.name()+" "+a.manageFolderSystemName():a.name():""};return b.push(["",this.sNoParentText]),""!==a.namespace&&(c=function(b){return a.namespace!==b.fullNameRaw.substr(0,a.namespace.length)}),Ob.folderListOptionsBuilder([],e,[],b,null,c,d,f)},this),this.createFolder=Bb.createCommand(this,function(){var a=Ob.data(),b=this.selectedParentValue();""===b&&1 =a?1:a},this),this.contactsPagenator=c.computed(Bb.computedPagenatorHelper(this.contactsPage,this.contactsPageCount)),this.emptySelection=c.observable(!0),this.viewClearSearch=c.observable(!1),this.viewID=c.observable(""),this.viewReadOnly=c.observable(!1),this.viewProperties=c.observableArray([]),this.viewSaveTrigger=c.observable(zb.SaveSettingsStep.Idle),this.viewPropertiesNames=this.viewProperties.filter(function(a){return-1 a)break;b[0]&&b[1]&&b[2]&&b[1]===b[2]&&("PRIVATE"===b[1]?e.privateKeys.importKey(b[0]):"PUBLIC"===b[1]&&e.publicKeys.importKey(b[0])),a--}return e.store(),Ob.reloadOpenPgpKeys(),Bb.delegateRun(this,"cancelCommand"),!0}),t.constructorEnd(this)}function M(){r.call(this,"Popups","PopupsViewOpenPgpKey"),this.key=c.observable(""),this.keyDom=c.observable(null),t.constructorEnd(this)}function N(){r.call(this,"Popups","PopupsGenerateNewOpenPgpKey"),this.email=c.observable(""),this.email.focus=c.observable(""),this.email.error=c.observable(!1),this.name=c.observable(""),this.password=c.observable(""),this.keyBitLength=c.observable(2048),this.submitRequest=c.observable(!1),this.email.subscribe(function(){this.email.error(!1)},this),this.generateOpenPgpKeyCommand=Bb.createCommand(this,function(){var b=this,c="",d=null,e=Ob.data().openpgpKeyring;return this.email.error(""===Bb.trim(this.email())),!e||this.email.error()?!1:(c=this.email(),""!==this.name()&&(c=this.name()+" <"+c+">"),this.submitRequest(!0),h.delay(function(){d=a.openpgp.generateKeyPair(1,Bb.pInt(b.keyBitLength()),c,Bb.trim(b.password())),d&&d.privateKeyArmored&&(e.privateKeys.importKey(d.privateKeyArmored),e.publicKeys.importKey(d.publicKeyArmored),e.store(),Ob.reloadOpenPgpKeys(),Bb.delegateRun(b,"cancelCommand")),b.submitRequest(!1)},100),!0)}),t.constructorEnd(this)}function O(){r.call(this,"Popups","PopupsComposeOpenPgp"),this.notification=c.observable(""),this.sign=c.observable(!0),this.encrypt=c.observable(!0),this.password=c.observable(""),this.password.focus=c.observable(!1),this.buttonFocus=c.observable(!1),this.from=c.observable(""),this.to=c.observableArray([]),this.text=c.observable(""),this.resultCallback=null,this.submitRequest=c.observable(!1),this.doCommand=Bb.createCommand(this,function(){var b=this,c=!0,d=Ob.data(),e=null,f=[];this.submitRequest(!0),c&&this.sign()&&""===this.from()&&(this.notification(Bb.i18n("PGP_NOTIFICATIONS/SPECIFY_FROM_EMAIL")),c=!1),c&&this.sign()&&(e=d.findPrivateKeyByEmail(this.from(),this.password()),e||(this.notification(Bb.i18n("PGP_NOTIFICATIONS/NO_PRIVATE_KEY_FOUND_FOR",{EMAIL:this.from()})),c=!1)),c&&this.encrypt()&&0===this.to().length&&(this.notification(Bb.i18n("PGP_NOTIFICATIONS/SPECIFY_AT_LEAST_ONE_RECIPIENT")),c=!1),c&&this.encrypt()&&(f=[],h.each(this.to(),function(a){var e=d.findPublicKeysByEmail(a);0===e.length&&c&&(b.notification(Bb.i18n("PGP_NOTIFICATIONS/NO_PUBLIC_KEYS_FOUND_FOR",{EMAIL:a})),c=!1),f=f.concat(e)}),!c||0!==f.length&&this.to().length===f.length||(c=!1)),h.delay(function(){if(b.resultCallback&&c)try{e&&0===f.length?b.resultCallback(a.openpgp.signClearMessage([e],b.text())):e&&0 0&&b>0&&a>b},this),this.hasMessages=c.computed(function(){return 0 '),e.after(f),e.remove()),f&&f[0]&&(f.attr("data-href",g).attr("data-theme",a[0]),f&&f[0]&&f[0].styleSheet&&!Bb.isUnd(f[0].styleSheet.cssText)?f[0].styleSheet.cssText=a[1]:f.text(a[1])),d.themeTrigger(zb.SaveSettingsStep.TrueResult))}).always(function(){d.iTimer=a.setTimeout(function(){d.themeTrigger(zb.SaveSettingsStep.Idle)},1e3),d.oLastAjax=null})),Ob.remote().saveSettings(null,{Theme:c})},this)}function lb(){this.openpgpkeys=Ob.data().openpgpkeys,this.openpgpkeysPublic=Ob.data().openpgpkeysPublic,this.openpgpkeysPrivate=Ob.data().openpgpkeysPrivate,this.openPgpKeyForDeletion=c.observable(null).extend({falseTimeout:3e3}).extend({toggleSubscribe:[this,function(a){a&&a.deleteAccess(!1)},function(a){a&&a.deleteAccess(!0)}]})}function mb(){this.leftPanelDisabled=c.observable(!1),this.useKeyboardShortcuts=c.observable(!0),this.keyScopeReal=c.observable(zb.KeyState.All),this.keyScopeFake=c.observable(zb.KeyState.All),this.keyScope=c.computed({owner:this,read:function(){return this.keyScopeFake()},write:function(a){zb.KeyState.Menu!==a&&(zb.KeyState.Compose===a?Bb.disableKeyFilter():Bb.restoreKeyFilter(),this.keyScopeFake(a),Eb.dropdownVisibility()&&(a=zb.KeyState.Menu)),this.keyScopeReal(a)}}),this.keyScopeReal.subscribe(function(a){j.setScope(a)}),this.leftPanelDisabled.subscribe(function(a){Ob.pub("left-panel."+(a?"off":"on"))}),Eb.dropdownVisibility.subscribe(function(a){a?this.keyScope(zb.KeyState.Menu):zb.KeyState.Menu===j.getScope()&&this.keyScope(this.keyScopeFake())},this),Bb.initDataConstructorBySettings(this)}function nb(){mb.call(this);var d=function(a){return function(){var b=Ob.cache().getFolderFromCacheList(a());b&&b.type(zb.FolderType.User)}},e=function(a){return function(b){var c=Ob.cache().getFolderFromCacheList(b);c&&c.type(a)}};this.devEmail="",this.devLogin="",this.devPassword="",this.accountEmail=c.observable(""),this.accountIncLogin=c.observable(""),this.accountOutLogin=c.observable(""),this.projectHash=c.observable(""),this.threading=c.observable(!1),this.lastFoldersHash="",this.remoteSuggestions=!1,this.sentFolder=c.observable(""),this.draftFolder=c.observable(""),this.spamFolder=c.observable(""),this.trashFolder=c.observable(""),this.archiveFolder=c.observable(""),this.sentFolder.subscribe(d(this.sentFolder),this,"beforeChange"),this.draftFolder.subscribe(d(this.draftFolder),this,"beforeChange"),this.spamFolder.subscribe(d(this.spamFolder),this,"beforeChange"),this.trashFolder.subscribe(d(this.trashFolder),this,"beforeChange"),this.archiveFolder.subscribe(d(this.archiveFolder),this,"beforeChange"),this.sentFolder.subscribe(e(zb.FolderType.SentItems),this),this.draftFolder.subscribe(e(zb.FolderType.Draft),this),this.spamFolder.subscribe(e(zb.FolderType.Spam),this),this.trashFolder.subscribe(e(zb.FolderType.Trash),this),this.archiveFolder.subscribe(e(zb.FolderType.Archive),this),this.draftFolderNotEnabled=c.computed(function(){return""===this.draftFolder()||yb.Values.UnuseOptionValue===this.draftFolder()},this),this.displayName=c.observable(""),this.signature=c.observable(""),this.signatureToAll=c.observable(!1),this.replyTo=c.observable(""),this.enableTwoFactor=c.observable(!1),this.accounts=c.observableArray([]),this.accountsLoading=c.observable(!1).extend({throttle:100}),this.identities=c.observableArray([]),this.identitiesLoading=c.observable(!1).extend({throttle:100}),this.contacts=c.observableArray([]),this.contacts.loading=c.observable(!1).extend({throttle:200}),this.contacts.importing=c.observable(!1).extend({throttle:200}),this.contacts.syncing=c.observable(!1).extend({throttle:200}),this.contacts.exportingVcf=c.observable(!1).extend({throttle:200}),this.contacts.exportingCsv=c.observable(!1).extend({throttle:200}),this.allowContactsSync=c.observable(!1),this.enableContactsSync=c.observable(!1),this.contactsSyncUrl=c.observable(""),this.contactsSyncUser=c.observable(""),this.contactsSyncPass=c.observable(""),this.allowContactsSync=c.observable(!!Ob.settingsGet("ContactsSyncIsAllowed")),this.enableContactsSync=c.observable(!!Ob.settingsGet("EnableContactsSync")),this.contactsSyncUrl=c.observable(Ob.settingsGet("ContactsSyncUrl")),this.contactsSyncUser=c.observable(Ob.settingsGet("ContactsSyncUser")),this.contactsSyncPass=c.observable(Ob.settingsGet("ContactsSyncPassword")),this.namespace="",this.folderList=c.observableArray([]),this.folderList.focused=c.observable(!1),this.foldersListError=c.observable(""),this.foldersLoading=c.observable(!1),this.foldersCreating=c.observable(!1),this.foldersDeleting=c.observable(!1),this.foldersRenaming=c.observable(!1),this.foldersChanging=c.computed(function(){var a=this.foldersLoading(),b=this.foldersCreating(),c=this.foldersDeleting(),d=this.foldersRenaming();return a||b||c||d},this),this.foldersInboxUnreadCount=c.observable(0),this.currentFolder=c.observable(null).extend({toggleSubscribe:[null,function(a){a&&a.selected(!1)},function(a){a&&a.selected(!0)}]}),this.currentFolderFullNameRaw=c.computed(function(){return this.currentFolder()?this.currentFolder().fullNameRaw:""},this),this.currentFolderFullName=c.computed(function(){return this.currentFolder()?this.currentFolder().fullName:""},this),this.currentFolderFullNameHash=c.computed(function(){return this.currentFolder()?this.currentFolder().fullNameHash:""},this),this.currentFolderName=c.computed(function(){return this.currentFolder()?this.currentFolder().name():""},this),this.folderListSystemNames=c.computed(function(){var a=["INBOX"],b=this.folderList(),c=this.sentFolder(),d=this.draftFolder(),e=this.spamFolder(),f=this.trashFolder(),g=this.archiveFolder();return Bb.isArray(b)&&0 =a?1:a},this),this.mainMessageListSearch=c.computed({read:this.messageListSearch,write:function(a){Hb.setHash(Ob.link().mailBox(this.currentFolderFullNameHash(),1,Bb.trim(a.toString())))},owner:this}),this.messageListError=c.observable(""),this.messageListLoading=c.observable(!1),this.messageListIsNotCompleted=c.observable(!1),this.messageListCompleteLoadingThrottle=c.observable(!1).extend({throttle:200}),this.messageListCompleteLoading=c.computed(function(){var a=this.messageListLoading(),b=this.messageListIsNotCompleted();return a||b},this),this.messageListCompleteLoading.subscribe(function(a){this.messageListCompleteLoadingThrottle(a)},this),this.messageList.subscribe(h.debounce(function(a){h.each(a,function(a){a.newForAnimation()&&a.newForAnimation(!1)})},500)),this.staticMessageList=new z,this.message=c.observable(null),this.messageLoading=c.observable(!1),this.messageLoadingThrottle=c.observable(!1).extend({throttle:50}),this.message.focused=c.observable(!1),this.message.subscribe(function(b){b?zb.Layout.NoPreview===this.layout()&&this.message.focused(!0):(this.message.focused(!1),this.hideMessageBodies(),zb.Layout.NoPreview===Ob.data().layout()&&-1 0?Math.ceil(b/a*100):0},this),this.allowOpenPGP=c.observable(!1),this.openpgpkeys=c.observableArray([]),this.openpgpKeyring=null,this.openpgpkeysPublic=this.openpgpkeys.filter(function(a){return!(!a||a.isPrivate)}),this.openpgpkeysPrivate=this.openpgpkeys.filter(function(a){return!(!a||!a.isPrivate)}),this.googleActions=c.observable(!1),this.googleLoggined=c.observable(!1),this.googleUserName=c.observable(""),this.facebookActions=c.observable(!1),this.facebookLoggined=c.observable(!1),this.facebookUserName=c.observable(""),this.twitterActions=c.observable(!1),this.twitterLoggined=c.observable(!1),this.twitterUserName=c.observable(""),this.customThemeType=c.observable(zb.CustomThemeType.Light),this.purgeMessageBodyCacheThrottle=h.throttle(this.purgeMessageBodyCache,3e4)}function ob(){this.oRequests={}}function pb(){ob.call(this),this.oRequests={}}function qb(){this.oEmailsPicsHashes={},this.oServices={},this.bAllowGravatar=!!Ob.settingsGet("AllowGravatar")}function rb(){qb.call(this),this.oFoldersCache={},this.oFoldersNamesCache={},this.oFolderHashCache={},this.oFolderUidNextCache={},this.oMessageListHashCache={},this.oMessageFlagsCache={},this.oNewMessage={},this.oRequestedMessage={}}function sb(a){s.call(this,"settings",a),this.menu=c.observableArray([]),this.oCurrentSubScreen=null,this.oViewModelPlace=null}function tb(){s.call(this,"login",[U])}function ub(){s.call(this,"mailbox",[W,Y,Z,$]),this.oLastRoute={}}function vb(){sb.call(this,[X,_,ab]),Bb.initOnStartOrLangChange(function(){this.sSettingsTitle=Bb.i18n("TITLES/SETTINGS")},this,function(){Ob.setTitle(this.sSettingsTitle)})}function wb(){q.call(this),this.oSettings=null,this.oPlugins=null,this.oLocal=null,this.oLink=null,this.oSubs={},this.isLocalAutocomplete=!0,this.popupVisibilityNames=c.observableArray([]),this.popupVisibility=c.computed(function(){return 0 ').appendTo("body"),Lb.on("error",function(a){Ob&&a&&a.originalEvent&&a.originalEvent.message&&-1===Bb.inArray(a.originalEvent.message,["Script error.","Uncaught Error: Error calling method on NPObject."])&&Ob.remote().jsError(Bb.emptyFunction,a.originalEvent.message,a.originalEvent.filename,a.originalEvent.lineno,location&&location.toString?location.toString():"",Kb.attr("class"),Bb.microtime()-Eb.now)}),Mb.on("keydown",function(a){a&&a.ctrlKey&&Kb.addClass("rl-ctrl-key-pressed")}).on("keyup",function(a){a&&!a.ctrlKey&&Kb.removeClass("rl-ctrl-key-pressed")})}function xb(){wb.call(this),this.oData=null,this.oRemote=null,this.oCache=null,this.oMoveCache={},this.quotaDebounce=h.debounce(this.quota,3e4),this.moveOrDeleteResponseHelper=h.bind(this.moveOrDeleteResponseHelper,this),this.messagesMoveTrigger=h.debounce(this.messagesMoveTrigger,500),a.setInterval(function(){Ob.pub("interval.30s")},3e4),a.setInterval(function(){Ob.pub("interval.1m")},6e4),a.setInterval(function(){Ob.pub("interval.2m")},12e4),a.setInterval(function(){Ob.pub("interval.3m")},18e4),a.setInterval(function(){Ob.pub("interval.5m")},3e5),a.setInterval(function(){Ob.pub("interval.10m")},6e5),a.setTimeout(function(){a.setInterval(function(){Ob.pub("interval.10m-after5m")},6e5)},3e5),b.wakeUp(function(){Ob.remote().jsVersion(function(b,c){zb.StorageResultType.Success===b&&c&&!c.Result&&(a.parent&&Ob.settingsGet("InIframe")?a.parent.location.reload():a.location.reload())},Ob.settingsGet("Version"))},{},36e5)}var yb={},zb={},Ab={},Bb={},Cb={},Db={},Eb={},Fb={settings:[],"settings-removed":[],"settings-disabled":[]},Gb=[],Hb=null,Ib=a.rainloopAppData||{},Jb=a.rainloopI18N||{},Kb=b("html"),Lb=b(a),Mb=b(a.document),Nb=a.Notification&&a.Notification.requestPermission?a.Notification:null,Ob=null,Pb=b("");Eb.now=(new Date).getTime(),Eb.momentTrigger=c.observable(!0),Eb.dropdownVisibility=c.observable(!1).extend({rateLimit:0}),Eb.langChangeTrigger=c.observable(!0),Eb.iAjaxErrorCount=0,Eb.iTokenErrorCount=0,Eb.iMessageBodyCacheCount=0,Eb.bUnload=!1,Eb.sUserAgent=(navigator.userAgent||"").toLowerCase(),Eb.bIsiOSDevice=-1 /g,">").replace(/"/g,""").replace(/'/g,"'"):""},Bb.splitPlainText=function(a,b){var c="",d="",e=a,f=0,g=0;for(b=Bb.isUnd(b)?100:b;e.length>b;)d=e.substring(0,b),f=d.lastIndexOf(" "),g=d.lastIndexOf("\n"),-1!==g&&(f=g),-1===f&&(f=b),c+=d.substring(0,f)+"\n",e=e.substring(f+1);return c+e},Bb.timeOutAction=function(){var b={};return function(c,d,e){Bb.isUnd(b[c])&&(b[c]=0),a.clearTimeout(b[c]),b[c]=a.setTimeout(d,e)}}(),Bb.timeOutActionSecond=function(){var b={};return function(c,d,e){b[c]||(b[c]=a.setTimeout(function(){d(),b[c]=0},e))}}(),Bb.audio=function(){var b=!1;return function(c,d){if(!1===b)if(Eb.bIsiOSDevice)b=null;else{var e=!1,f=!1,g=a.Audio?new a.Audio:null;g&&g.canPlayType&&g.play?(e=""!==g.canPlayType('audio/mpeg; codecs="mp3"'),e||(f=""!==g.canPlayType('audio/ogg; codecs="vorbis"')),e||f?(b=g,b.preload="none",b.loop=!1,b.autoplay=!1,b.muted=!1,b.src=e?c:d):b=null):b=null}return b}}(),Bb.hos=function(a,b){return a&&Object.hasOwnProperty?Object.hasOwnProperty.call(a,b):!1},Bb.i18n=function(a,b,c){var d="",e=Bb.isUnd(Jb[a])?Bb.isUnd(c)?a:c:Jb[a];if(!Bb.isUnd(b)&&!Bb.isNull(b))for(d in b)Bb.hos(b,d)&&(e=e.replace("%"+d+"%",b[d]));return e},Bb.i18nToNode=function(a){h.defer(function(){b(".i18n",a).each(function(){var a=b(this),c="";c=a.data("i18n-text"),c?a.text(Bb.i18n(c)):(c=a.data("i18n-html"),c&&a.html(Bb.i18n(c)),c=a.data("i18n-placeholder"),c&&a.attr("placeholder",Bb.i18n(c)),c=a.data("i18n-title"),c&&a.attr("title",Bb.i18n(c)))})})},Bb.i18nToDoc=function(){a.rainloopI18N&&(Jb=a.rainloopI18N||{},Bb.i18nToNode(Mb),Eb.langChangeTrigger(!Eb.langChangeTrigger())),a.rainloopI18N={}},Bb.initOnStartOrLangChange=function(a,b,c){a&&a.call(b),c?Eb.langChangeTrigger.subscribe(function(){a&&a.call(b),c.call(b)}):a&&Eb.langChangeTrigger.subscribe(a,b)},Bb.inFocus=function(){var a=document.activeElement;return a&&("INPUT"===a.tagName||"TEXTAREA"===a.tagName||"IFRAME"===a.tagName||"DIV"===a.tagName&&"editorHtmlArea"===a.className&&a.contentEditable)},Bb.removeInFocus=function(){if(document&&document.activeElement&&document.activeElement.blur){var a=b(document.activeElement);(a.is("input")||a.is("textarea"))&&document.activeElement.blur()}},Bb.removeSelection=function(){if(a&&a.getSelection){var b=a.getSelection();b&&b.removeAllRanges&&b.removeAllRanges()}else document&&document.selection&&document.selection.empty&&document.selection.empty()},Bb.replySubjectAdd=function(b,c,d){var e=null,f=Bb.trim(c);return f=null===(e=new a.RegExp("^"+b+"[\\s]?\\:(.*)$","gi").exec(c))||Bb.isUnd(e[1])?null===(e=new a.RegExp("^("+b+"[\\s]?[\\[\\(]?)([\\d]+)([\\]\\)]?[\\s]?\\:.*)$","gi").exec(c))||Bb.isUnd(e[1])||Bb.isUnd(e[2])||Bb.isUnd(e[3])?b+": "+c:e[1]+(Bb.pInt(e[2])+1)+e[3]:b+"[2]: "+e[1],f=f.replace(/[\s]+/g," "),f=(Bb.isUnd(d)?!0:d)?Bb.fixLongSubject(f):f},Bb.fixLongSubject=function(a){var b=0,c=null;a=Bb.trim(a.replace(/[\s]+/," "));do c=/^Re(\[([\d]+)\]|):[\s]{0,3}Re(\[([\d]+)\]|):/gi.exec(a),(!c||Bb.isUnd(c[0]))&&(c=null),c&&(b=0,b+=Bb.isUnd(c[2])?1:0+Bb.pInt(c[2]),b+=Bb.isUnd(c[4])?1:0+Bb.pInt(c[4]),a=a.replace(/^Re(\[[\d]+\]|):[\s]{0,3}Re(\[[\d]+\]|):/gi,"Re"+(b>0?"["+b+"]":"")+":"));while(c);return a=a.replace(/[\s]+/," ")},Bb.roundNumber=function(a,b){return Math.round(a*Math.pow(10,b))/Math.pow(10,b)},Bb.friendlySize=function(a){return a=Bb.pInt(a),a>=1073741824?Bb.roundNumber(a/1073741824,1)+"GB":a>=1048576?Bb.roundNumber(a/1048576,1)+"MB":a>=1024?Bb.roundNumber(a/1024,0)+"KB":a+"B"},Bb.log=function(b){a.console&&a.console.log&&a.console.log(b)},Bb.getNotification=function(a,b){return a=Bb.pInt(a),zb.Notification.ClientViewError===a&&b?b:Bb.isUnd(Ab[a])?"":Ab[a]},Bb.initNotificationLanguage=function(){Ab[zb.Notification.InvalidToken]=Bb.i18n("NOTIFICATIONS/INVALID_TOKEN"),Ab[zb.Notification.AuthError]=Bb.i18n("NOTIFICATIONS/AUTH_ERROR"),Ab[zb.Notification.AccessError]=Bb.i18n("NOTIFICATIONS/ACCESS_ERROR"),Ab[zb.Notification.ConnectionError]=Bb.i18n("NOTIFICATIONS/CONNECTION_ERROR"),Ab[zb.Notification.CaptchaError]=Bb.i18n("NOTIFICATIONS/CAPTCHA_ERROR"),Ab[zb.Notification.SocialFacebookLoginAccessDisable]=Bb.i18n("NOTIFICATIONS/SOCIAL_FACEBOOK_LOGIN_ACCESS_DISABLE"),Ab[zb.Notification.SocialTwitterLoginAccessDisable]=Bb.i18n("NOTIFICATIONS/SOCIAL_TWITTER_LOGIN_ACCESS_DISABLE"),Ab[zb.Notification.SocialGoogleLoginAccessDisable]=Bb.i18n("NOTIFICATIONS/SOCIAL_GOOGLE_LOGIN_ACCESS_DISABLE"),Ab[zb.Notification.DomainNotAllowed]=Bb.i18n("NOTIFICATIONS/DOMAIN_NOT_ALLOWED"),Ab[zb.Notification.AccountNotAllowed]=Bb.i18n("NOTIFICATIONS/ACCOUNT_NOT_ALLOWED"),Ab[zb.Notification.AccountTwoFactorAuthRequired]=Bb.i18n("NOTIFICATIONS/ACCOUNT_TWO_FACTOR_AUTH_REQUIRED"),Ab[zb.Notification.AccountTwoFactorAuthError]=Bb.i18n("NOTIFICATIONS/ACCOUNT_TWO_FACTOR_AUTH_ERROR"),Ab[zb.Notification.CouldNotSaveNewPassword]=Bb.i18n("NOTIFICATIONS/COULD_NOT_SAVE_NEW_PASSWORD"),Ab[zb.Notification.CurrentPasswordIncorrect]=Bb.i18n("NOTIFICATIONS/CURRENT_PASSWORD_INCORRECT"),Ab[zb.Notification.NewPasswordShort]=Bb.i18n("NOTIFICATIONS/NEW_PASSWORD_SHORT"),Ab[zb.Notification.NewPasswordWeak]=Bb.i18n("NOTIFICATIONS/NEW_PASSWORD_WEAK"),Ab[zb.Notification.NewPasswordForbidden]=Bb.i18n("NOTIFICATIONS/NEW_PASSWORD_FORBIDDENT"),Ab[zb.Notification.ContactsSyncError]=Bb.i18n("NOTIFICATIONS/CONTACTS_SYNC_ERROR"),Ab[zb.Notification.CantGetMessageList]=Bb.i18n("NOTIFICATIONS/CANT_GET_MESSAGE_LIST"),Ab[zb.Notification.CantGetMessage]=Bb.i18n("NOTIFICATIONS/CANT_GET_MESSAGE"),Ab[zb.Notification.CantDeleteMessage]=Bb.i18n("NOTIFICATIONS/CANT_DELETE_MESSAGE"),Ab[zb.Notification.CantMoveMessage]=Bb.i18n("NOTIFICATIONS/CANT_MOVE_MESSAGE"),Ab[zb.Notification.CantCopyMessage]=Bb.i18n("NOTIFICATIONS/CANT_MOVE_MESSAGE"),Ab[zb.Notification.CantSaveMessage]=Bb.i18n("NOTIFICATIONS/CANT_SAVE_MESSAGE"),Ab[zb.Notification.CantSendMessage]=Bb.i18n("NOTIFICATIONS/CANT_SEND_MESSAGE"),Ab[zb.Notification.InvalidRecipients]=Bb.i18n("NOTIFICATIONS/INVALID_RECIPIENTS"),Ab[zb.Notification.CantCreateFolder]=Bb.i18n("NOTIFICATIONS/CANT_CREATE_FOLDER"),Ab[zb.Notification.CantRenameFolder]=Bb.i18n("NOTIFICATIONS/CANT_RENAME_FOLDER"),Ab[zb.Notification.CantDeleteFolder]=Bb.i18n("NOTIFICATIONS/CANT_DELETE_FOLDER"),Ab[zb.Notification.CantDeleteNonEmptyFolder]=Bb.i18n("NOTIFICATIONS/CANT_DELETE_NON_EMPTY_FOLDER"),Ab[zb.Notification.CantSubscribeFolder]=Bb.i18n("NOTIFICATIONS/CANT_SUBSCRIBE_FOLDER"),Ab[zb.Notification.CantUnsubscribeFolder]=Bb.i18n("NOTIFICATIONS/CANT_UNSUBSCRIBE_FOLDER"),Ab[zb.Notification.CantSaveSettings]=Bb.i18n("NOTIFICATIONS/CANT_SAVE_SETTINGS"),Ab[zb.Notification.CantSavePluginSettings]=Bb.i18n("NOTIFICATIONS/CANT_SAVE_PLUGIN_SETTINGS"),Ab[zb.Notification.DomainAlreadyExists]=Bb.i18n("NOTIFICATIONS/DOMAIN_ALREADY_EXISTS"),Ab[zb.Notification.CantInstallPackage]=Bb.i18n("NOTIFICATIONS/CANT_INSTALL_PACKAGE"),Ab[zb.Notification.CantDeletePackage]=Bb.i18n("NOTIFICATIONS/CANT_DELETE_PACKAGE"),Ab[zb.Notification.InvalidPluginPackage]=Bb.i18n("NOTIFICATIONS/INVALID_PLUGIN_PACKAGE"),Ab[zb.Notification.UnsupportedPluginPackage]=Bb.i18n("NOTIFICATIONS/UNSUPPORTED_PLUGIN_PACKAGE"),Ab[zb.Notification.LicensingServerIsUnavailable]=Bb.i18n("NOTIFICATIONS/LICENSING_SERVER_IS_UNAVAILABLE"),Ab[zb.Notification.LicensingExpired]=Bb.i18n("NOTIFICATIONS/LICENSING_EXPIRED"),Ab[zb.Notification.LicensingBanned]=Bb.i18n("NOTIFICATIONS/LICENSING_BANNED"),Ab[zb.Notification.DemoSendMessageError]=Bb.i18n("NOTIFICATIONS/DEMO_SEND_MESSAGE_ERROR"),Ab[zb.Notification.AccountAlreadyExists]=Bb.i18n("NOTIFICATIONS/ACCOUNT_ALREADY_EXISTS"),Ab[zb.Notification.MailServerError]=Bb.i18n("NOTIFICATIONS/MAIL_SERVER_ERROR"),Ab[zb.Notification.UnknownNotification]=Bb.i18n("NOTIFICATIONS/UNKNOWN_ERROR"),Ab[zb.Notification.UnknownError]=Bb.i18n("NOTIFICATIONS/UNKNOWN_ERROR")},Bb.getUploadErrorDescByCode=function(a){var b="";switch(Bb.pInt(a)){case zb.UploadErrorCode.FileIsTooBig:b=Bb.i18n("UPLOAD/ERROR_FILE_IS_TOO_BIG");break;case zb.UploadErrorCode.FilePartiallyUploaded:b=Bb.i18n("UPLOAD/ERROR_FILE_PARTIALLY_UPLOADED");break;case zb.UploadErrorCode.FileNoUploaded:b=Bb.i18n("UPLOAD/ERROR_NO_FILE_UPLOADED");break;case zb.UploadErrorCode.MissingTempFolder:b=Bb.i18n("UPLOAD/ERROR_MISSING_TEMP_FOLDER");break;case zb.UploadErrorCode.FileOnSaveingError:b=Bb.i18n("UPLOAD/ERROR_ON_SAVING_FILE");break;case zb.UploadErrorCode.FileType:b=Bb.i18n("UPLOAD/ERROR_FILE_TYPE");break;default:b=Bb.i18n("UPLOAD/ERROR_UNKNOWN")}return b},Bb.delegateRun=function(a,b,c,d){a&&a[b]&&(d=Bb.pInt(d),0>=d?a[b].apply(a,Bb.isArray(c)?c:[]):h.delay(function(){a[b].apply(a,Bb.isArray(c)?c:[])},d))},Bb.killCtrlAandS=function(b){if(b=b||a.event,b&&b.ctrlKey&&!b.shiftKey&&!b.altKey){var c=b.target||b.srcElement,d=b.keyCode||b.which;if(d===zb.EventKeyCode.S)return void b.preventDefault();if(c&&c.tagName&&c.tagName.match(/INPUT|TEXTAREA/i))return;d===zb.EventKeyCode.A&&(a.getSelection?a.getSelection().removeAllRanges():a.document.selection&&a.document.selection.clear&&a.document.selection.clear(),b.preventDefault())}},Bb.createCommand=function(a,b,d){var e=b?function(){return e.canExecute&&e.canExecute()&&b.apply(a,Array.prototype.slice.call(arguments)),!1}:function(){};return e.enabled=c.observable(!0),d=Bb.isUnd(d)?!0:d,e.canExecute=c.computed(Bb.isFunc(d)?function(){return e.enabled()&&d.call(a)}:function(){return e.enabled()&&!!d}),e},Bb.initDataConstructorBySettings=function(b){b.editorDefaultType=c.observable(zb.EditorDefaultType.Html),b.showImages=c.observable(!1),b.interfaceAnimation=c.observable(zb.InterfaceAnimation.Full),b.contactsAutosave=c.observable(!1),Eb.sAnimationType=zb.InterfaceAnimation.Full,b.allowThemes=c.observable(!0),b.allowCustomLogin=c.observable(!1),b.allowLanguagesOnSettings=c.observable(!0),b.allowLanguagesOnLogin=c.observable(!0),b.desktopNotifications=c.observable(!1),b.useThreads=c.observable(!0),b.replySameFolder=c.observable(!0),b.useCheckboxesInList=c.observable(!0),b.layout=c.observable(zb.Layout.SidePreview),b.usePreviewPane=c.computed(function(){return zb.Layout.NoPreview!==b.layout()}),b.interfaceAnimation.subscribe(function(a){if(Eb.bMobileDevice||a===zb.InterfaceAnimation.None)Kb.removeClass("rl-anim rl-anim-full").addClass("no-rl-anim"),Eb.sAnimationType=zb.InterfaceAnimation.None;else switch(a){case zb.InterfaceAnimation.Full:Kb.removeClass("no-rl-anim").addClass("rl-anim rl-anim-full"),Eb.sAnimationType=a;break;case zb.InterfaceAnimation.Normal:Kb.removeClass("no-rl-anim rl-anim-full").addClass("rl-anim"),Eb.sAnimationType=a}}),b.interfaceAnimation.valueHasMutated(),b.desktopNotificationsPermisions=c.computed(function(){b.desktopNotifications();var c=zb.DesktopNotifications.NotSupported;if(Nb&&Nb.permission)switch(Nb.permission.toLowerCase()){case"granted":c=zb.DesktopNotifications.Allowed;break;case"denied":c=zb.DesktopNotifications.Denied;break;case"default":c=zb.DesktopNotifications.NotAllowed}else a.webkitNotifications&&a.webkitNotifications.checkPermission&&(c=a.webkitNotifications.checkPermission());return c}),b.useDesktopNotifications=c.computed({read:function(){return b.desktopNotifications()&&zb.DesktopNotifications.Allowed===b.desktopNotificationsPermisions()},write:function(a){if(a){var c=b.desktopNotificationsPermisions();zb.DesktopNotifications.Allowed===c?b.desktopNotifications(!0):zb.DesktopNotifications.NotAllowed===c?Nb.requestPermission(function(){b.desktopNotifications.valueHasMutated(),zb.DesktopNotifications.Allowed===b.desktopNotificationsPermisions()?b.desktopNotifications()?b.desktopNotifications.valueHasMutated():b.desktopNotifications(!0):b.desktopNotifications()?b.desktopNotifications(!1):b.desktopNotifications.valueHasMutated()}):b.desktopNotifications(!1)}else b.desktopNotifications(!1)}}),b.language=c.observable(""),b.languages=c.observableArray([]),b.mainLanguage=c.computed({read:b.language,write:function(a){a!==b.language()?-1 =b.diff(c,"hours")?d:b.format("L")===c.format("L")?Bb.i18n("MESSAGE_LIST/TODAY_AT",{TIME:c.format("LT")}):b.clone().subtract("days",1).format("L")===c.format("L")?Bb.i18n("MESSAGE_LIST/YESTERDAY_AT",{TIME:c.format("LT")}):c.format(b.year()===c.year()?"D MMM.":"LL")},a)},Bb.isFolderExpanded=function(a){var b=Ob.local().get(zb.ClientSideKeyName.ExpandedFolders);return h.isArray(b)&&-1!==h.indexOf(b,a)},Bb.setExpandedFolder=function(a,b){var c=Ob.local().get(zb.ClientSideKeyName.ExpandedFolders);h.isArray(c)||(c=[]),b?(c.push(a),c=h.uniq(c)):c=h.without(c,a),Ob.local().set(zb.ClientSideKeyName.ExpandedFolders,c)},Bb.initLayoutResizer=function(a,c,d){var e=65,f=155,g=b(a),h=b(c),i=Ob.local().get(d)||null,j=function(a){a&&(g.css({width:""+a+"px"}),h.css({left:""+a+"px"}))},k=function(a){if(a)g.resizable("disable"),j(e);else{g.resizable("enable");var b=Bb.pInt(Ob.local().get(d))||f;j(b>f?b:f)}},l=function(a,b){b&&b.size&&b.size.width&&(Ob.local().set(d,b.size.width),h.css({left:""+b.size.width+"px"}))};null!==i&&j(i>f?i:f),g.resizable({helper:"ui-resizable-helper",minWidth:f,maxWidth:350,handles:"e",stop:l}),Ob.sub("left-panel.off",function(){k(!0)}),Ob.sub("left-panel.on",function(){k(!1)})},Bb.initBlockquoteSwitcher=function(a){if(a){var c=b("blockquote:not(.rl-bq-switcher)",a).filter(function(){return 0===b(this).parent().closest("blockquote",a).length});c&&0 100)&&(a.addClass("rl-bq-switcher hidden-bq"),b('').insertBefore(a).click(function(){a.toggleClass("hidden-bq"),Bb.windowResize()}).after("
").before("
"))})}},Bb.removeBlockquoteSwitcher=function(a){a&&(b(a).find("blockquote.rl-bq-switcher").each(function(){b(this).removeClass("rl-bq-switcher hidden-bq")}),b(a).find(".rlBlockquoteSwitcher").each(function(){b(this).remove()}))},Bb.toggleMessageBlockquote=function(a){a&&a.find(".rlBlockquoteSwitcher").click()},Bb.extendAsViewModel=function(a,b,c){b&&(c||(c=r),b.__name=a,Cb.regViewModelHook(a,b),h.extend(b.prototype,c.prototype))},Bb.addSettingsViewModel=function(a,b,c,d,e){a.__rlSettingsData={Label:c,Template:b,Route:d,IsDefault:!!e},Fb.settings.push(a)},Bb.removeSettingsViewModel=function(a){Fb["settings-removed"].push(a)},Bb.disableSettingsViewModel=function(a){Fb["settings-disabled"].push(a)},Bb.convertThemeName=function(a){return"@custom"===a.substr(-7)&&(a=Bb.trim(a.substring(0,a.length-7))),Bb.trim(a.replace(/[^a-zA-Z]+/g," ").replace(/([A-Z])/g," $1").replace(/[\s]+/g," "))},Bb.quoteName=function(a){return a.replace(/["]/g,'\\"')},Bb.microtime=function(){return(new Date).getTime()},Bb.convertLangName=function(a,b){return Bb.i18n("LANGS_NAMES"+(!0===b?"_EN":"")+"/LANG_"+a.toUpperCase().replace(/[^a-zA-Z0-9]+/,"_"),null,a)},Bb.fakeMd5=function(a){var b="",c="0123456789abcdefghijklmnopqrstuvwxyz";for(a=Bb.isUnd(a)?32:Bb.pInt(a);b.length>>32-b}function c(a,b){var c,d,e,f,g;return e=2147483648&a,f=2147483648&b,c=1073741824&a,d=1073741824&b,g=(1073741823&a)+(1073741823&b),c&d?2147483648^g^e^f:c|d?1073741824&g?3221225472^g^e^f:1073741824^g^e^f:g^e^f}function d(a,b,c){return a&b|~a&c}function e(a,b,c){return a&c|b&~c}function f(a,b,c){return a^b^c}function g(a,b,c){return b^(a|~c)}function h(a,e,f,g,h,i,j){return a=c(a,c(c(d(e,f,g),h),j)),c(b(a,i),e)}function i(a,d,f,g,h,i,j){return a=c(a,c(c(e(d,f,g),h),j)),c(b(a,i),d) +}function j(a,d,e,g,h,i,j){return a=c(a,c(c(f(d,e,g),h),j)),c(b(a,i),d)}function k(a,d,e,f,h,i,j){return a=c(a,c(c(g(d,e,f),h),j)),c(b(a,i),d)}function l(a){for(var b,c=a.length,d=c+8,e=(d-d%64)/64,f=16*(e+1),g=Array(f-1),h=0,i=0;c>i;)b=(i-i%4)/4,h=i%4*8,g[b]=g[b]|a.charCodeAt(i)<>>29,g}function m(a){var b,c,d="",e="";for(c=0;3>=c;c++)b=a>>>8*c&255,e="0"+b.toString(16),d+=e.substr(e.length-2,2);return d}function n(a){a=a.replace(/rn/g,"n");for(var b="",c=0;c d?b+=String.fromCharCode(d):d>127&&2048>d?(b+=String.fromCharCode(d>>6|192),b+=String.fromCharCode(63&d|128)):(b+=String.fromCharCode(d>>12|224),b+=String.fromCharCode(d>>6&63|128),b+=String.fromCharCode(63&d|128))}return b}var o,p,q,r,s,t,u,v,w,x=Array(),y=7,z=12,A=17,B=22,C=5,D=9,E=14,F=20,G=4,H=11,I=16,J=23,K=6,L=10,M=15,N=21;for(a=n(a),x=l(a),t=1732584193,u=4023233417,v=2562383102,w=271733878,o=0;o /g,">").replace(/")},Bb.draggeblePlace=function(){return b(' ').appendTo("#rl-hidden")},Bb.defautOptionsAfterRender=function(a,c){c&&!Bb.isUnd(c.disabled)&&a&&b(a).toggleClass("disabled",c.disabled).prop("disabled",c.disabled)},Bb.windowPopupKnockout=function(c,d,e,f){var g=null,h=a.open(""),i="__OpenerApplyBindingsUid"+Bb.fakeMd5()+"__",j=b("#"+d);a[i]=function(){if(h&&h.document.body&&j&&j[0]){var d=b(h.document.body);b("#rl-content",d).html(j.html()),b("html",h.document).addClass("external "+b("html").attr("class")),Bb.i18nToNode(d),t.prototype.applyExternal(c,b("#rl-content",d)[0]),a[i]=null,f(h)}},h.document.open(),h.document.write(''+Bb.encodeHtml(e)+' '),h.document.close(),g=h.document.createElement("script"),g.type="text/javascript",g.innerHTML="if(window&&window.opener&&window.opener['"+i+"']){window.opener['"+i+"']();window.opener['"+i+"']=null}",h.document.getElementsByTagName("head")[0].appendChild(g)},Bb.settingsSaveHelperFunction=function(a,b,c,d){return c=c||null,d=Bb.isUnd(d)?1e3:Bb.pInt(d),function(e,f,g,i,j){b.call(c,f&&f.Result?zb.SaveSettingsStep.TrueResult:zb.SaveSettingsStep.FalseResult),a&&a.call(c,e,f,g,i,j),h.delay(function(){b.call(c,zb.SaveSettingsStep.Idle)},d)}},Bb.settingsSaveHelperSimpleFunction=function(a,b){return Bb.settingsSaveHelperFunction(null,a,b,1e3)},Bb.htmlToPlain=function(a){var c="",d="> ",e=function(){if(arguments&&1\n",a.replace(/\n([> ]+)/gm,function(){return arguments&&1 ]*>(.|[\s\S\r\n]*)<\/div>/gim,f),a="\n"+b.trim(a)+"\n"),a}return""},g=function(){return arguments&&1 /g,">"):""},h=function(){if(arguments&&1 /gim,"\n").replace(/<\/h\d>/gi,"\n").replace(/<\/p>/gi,"\n\n").replace(/<\/li>/gi,"\n").replace(/<\/td>/gi,"\n").replace(/<\/tr>/gi,"\n").replace(/
]*>/gim,"\n_______________________________\n\n").replace(/]*>/gim,"").replace(/
]*>(.|[\s\S\r\n]*)<\/div>/gim,f).replace(/]*>/gim,"\n__bq__start__\n").replace(/<\/blockquote>/gim,"\n__bq__end__\n").replace(/]*>(.|[\s\S\r\n]*)<\/a>/gim,h).replace(/ /gi," ").replace(/<[^>]*>/gm,"").replace(/>/gi,">").replace(/</gi,"<").replace(/&/gi,"&").replace(/&\w{2,6};/gi,""),c.replace(/\n[ \t]+/gm,"\n").replace(/[\n]{3,}/gm,"\n\n").replace(/__bq__start__(.|[\s\S\r\n]*)__bq__end__/gm,e).replace(/__bq__start__/gm,"").replace(/__bq__end__/gm,"")},Bb.plainToHtml=function(a){return a.toString().replace(/&/g,"&").replace(/>/g,">").replace(/")},Bb.resizeAndCrop=function(b,c,d){var e=new a.Image;e.onload=function(){var a=[0,0],b=document.createElement("canvas"),e=b.getContext("2d");b.width=c,b.height=c,a=this.width>this.height?[this.width-this.height,0]:[0,this.height-this.width],e.fillStyle="#fff",e.fillRect(0,0,c,c),e.drawImage(this,a[0]/2,a[1]/2,this.width-a[0],this.height-a[1],0,0,c,c),d(b.toDataURL("image/jpeg"))},e.src=b},Bb.computedPagenatorHelper=function(a,b){return function(){var c=0,d=0,e=2,f=[],g=a(),h=b(),i=function(a,b,c){var d={current:a===g,name:Bb.isUnd(c)?a.toString():c.toString(),custom:Bb.isUnd(c)?!1:!0,title:Bb.isUnd(c)?"":a.toString(),value:a.toString()};(Bb.isUnd(b)?0:!b)?f.unshift(d):f.push(d)};if(h>1||h>0&&g>h){for(g>h?(i(h),c=h,d=h):((3>=g||g>=h-2)&&(e+=2),i(g),c=g,d=g);e>0;)if(c-=1,d+=1,c>0&&(i(c,!1),e--),h>=d)i(d,!0),e--;else if(0>=c)break;3===c?i(2,!1):c>3&&i(Math.round((c-1)/2),!1,"..."),h-2===d?i(h-1,!0):h-2>d&&i(Math.round((h+d)/2),!0,"..."),c>1&&i(1,!1),h>d&&i(h,!0)}return f}},Bb.selectElement=function(b){if(a.getSelection){var c=a.getSelection();c.removeAllRanges();var d=document.createRange();d.selectNodeContents(b),c.addRange(d)}else if(document.selection){var e=document.body.createTextRange();e.moveToElementText(b),e.select()}},Bb.disableKeyFilter=function(){a.key&&(j.filter=function(){return Ob.data().useKeyboardShortcuts()})},Bb.restoreKeyFilter=function(){a.key&&(j.filter=function(a){if(Ob.data().useKeyboardShortcuts()){var b=a.target||a.srcElement,c=b?b.tagName:"";return c=c.toUpperCase(),!("INPUT"===c||"SELECT"===c||"TEXTAREA"===c||b&&"DIV"===c&&"editorHtmlArea"===b.className&&b.contentEditable)}return!1})},Bb.detectDropdownVisibility=h.debounce(function(){Eb.dropdownVisibility(!!h.find(Gb,function(a){return a.hasClass("open")}))},50),Db={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",urlsafe_encode:function(a){return Db.encode(a).replace(/[+]/g,"-").replace(/[\/]/g,"_").replace(/[=]/g,".")},encode:function(a){var b,c,d,e,f,g,h,i="",j=0;for(a=Db._utf8_encode(a);j>2,f=(3&b)<<4|c>>4,g=(15&c)<<2|d>>6,h=63&d,isNaN(c)?g=h=64:isNaN(d)&&(h=64),i=i+this._keyStr.charAt(e)+this._keyStr.charAt(f)+this._keyStr.charAt(g)+this._keyStr.charAt(h);return i},decode:function(a){var b,c,d,e,f,g,h,i="",j=0;for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");j >4,c=(15&f)<<4|g>>2,d=(3&g)<<6|h,i+=String.fromCharCode(b),64!==g&&(i+=String.fromCharCode(c)),64!==h&&(i+=String.fromCharCode(d));return Db._utf8_decode(i)},_utf8_encode:function(a){a=a.replace(/\r\n/g,"\n");for(var b="",c=0,d=a.length,e=0;d>c;c++)e=a.charCodeAt(c),128>e?b+=String.fromCharCode(e):e>127&&2048>e?(b+=String.fromCharCode(e>>6|192),b+=String.fromCharCode(63&e|128)):(b+=String.fromCharCode(e>>12|224),b+=String.fromCharCode(e>>6&63|128),b+=String.fromCharCode(63&e|128));return b},_utf8_decode:function(a){for(var b="",c=0,d=0,e=0,f=0;c d?(b+=String.fromCharCode(d),c++):d>191&&224>d?(e=a.charCodeAt(c+1),b+=String.fromCharCode((31&d)<<6|63&e),c+=2):(e=a.charCodeAt(c+1),f=a.charCodeAt(c+2),b+=String.fromCharCode((15&d)<<12|(63&e)<<6|63&f),c+=3);return b}},c.bindingHandlers.tooltip={init:function(a,d){if(!Eb.bMobileDevice){var e=b(a),f=e.data("tooltip-class")||"",g=e.data("tooltip-placement")||"top";e.tooltip({delay:{show:500,hide:100},html:!0,container:"body",placement:g,trigger:"hover",title:function(){return e.is(".disabled")||Eb.dropdownVisibility()?"":''+Bb.i18n(c.utils.unwrapObservable(d()))+""}}).click(function(){e.tooltip("hide")}),Eb.dropdownVisibility.subscribe(function(a){a&&e.tooltip("hide")})}}},c.bindingHandlers.tooltip2={init:function(a,c){var d=b(a),e=d.data("tooltip-class")||"",f=d.data("tooltip-placement")||"top";d.tooltip({delay:{show:500,hide:100},html:!0,container:"body",placement:f,title:function(){return d.is(".disabled")||Eb.dropdownVisibility()?"":''+c()()+""}}).click(function(){d.tooltip("hide")}),Eb.dropdownVisibility.subscribe(function(a){a&&d.tooltip("hide")})}},c.bindingHandlers.tooltip3={init:function(a){var c=b(a);c.tooltip({container:"body",trigger:"hover manual",title:function(){return c.data("tooltip3-data")||""}}),Eb.dropdownVisibility.subscribe(function(a){a&&c.tooltip("hide")}),Mb.click(function(){c.tooltip("hide")})},update:function(a,d){var e=c.utils.unwrapObservable(d());""===e?b(a).data("tooltip3-data","").tooltip("hide"):b(a).data("tooltip3-data",e).tooltip("show")}},c.bindingHandlers.registrateBootstrapDropdown={init:function(a){Gb.push(b(a))}},c.bindingHandlers.openDropdownTrigger={update:function(a,d){if(c.utils.unwrapObservable(d())){var e=b(a);e.hasClass("open")||(e.find(".dropdown-toggle").dropdown("toggle"),Bb.detectDropdownVisibility()),d()(!1)}}},c.bindingHandlers.dropdownCloser={init:function(a){b(a).closest(".dropdown").on("click",".e-item",function(){b(a).dropdown("toggle")})}},c.bindingHandlers.popover={init:function(a,d){b(a).popover(c.utils.unwrapObservable(d()))}},c.bindingHandlers.csstext={init:function(a,d){a&&a.styleSheet&&!Bb.isUnd(a.styleSheet.cssText)?a.styleSheet.cssText=c.utils.unwrapObservable(d()):b(a).text(c.utils.unwrapObservable(d()))},update:function(a,d){a&&a.styleSheet&&!Bb.isUnd(a.styleSheet.cssText)?a.styleSheet.cssText=c.utils.unwrapObservable(d()):b(a).text(c.utils.unwrapObservable(d()))}},c.bindingHandlers.resizecrop={init:function(a){b(a).addClass("resizecrop").resizecrop({width:"100",height:"100",wrapperCSS:{"border-radius":"10px"}})},update:function(a,c){c()(),b(a).resizecrop({width:"100",height:"100"})}},c.bindingHandlers.onEnter={init:function(c,d,e,f){b(c).on("keypress",function(e){e&&13===a.parseInt(e.keyCode,10)&&(b(c).trigger("change"),d().call(f))})}},c.bindingHandlers.onEsc={init:function(c,d,e,f){b(c).on("keypress",function(e){e&&27===a.parseInt(e.keyCode,10)&&(b(c).trigger("change"),d().call(f))})}},c.bindingHandlers.clickOnTrue={update:function(a,d){c.utils.unwrapObservable(d())&&b(a).click()}},c.bindingHandlers.modal={init:function(a,d){b(a).toggleClass("fade",!Eb.bMobileDevice).modal({keyboard:!1,show:c.utils.unwrapObservable(d())}).on("shown",function(){Bb.windowResize()}).find(".close").click(function(){d()(!1)})},update:function(a,d){b(a).modal(c.utils.unwrapObservable(d())?"show":"hide")}},c.bindingHandlers.i18nInit={init:function(a){Bb.i18nToNode(a)}},c.bindingHandlers.i18nUpdate={update:function(a,b){c.utils.unwrapObservable(b()),Bb.i18nToNode(a)}},c.bindingHandlers.link={update:function(a,d){b(a).attr("href",c.utils.unwrapObservable(d()))}},c.bindingHandlers.title={update:function(a,d){b(a).attr("title",c.utils.unwrapObservable(d()))}},c.bindingHandlers.textF={init:function(a,d){b(a).text(c.utils.unwrapObservable(d()))}},c.bindingHandlers.initDom={init:function(a,b){b()(a)}},c.bindingHandlers.initResizeTrigger={init:function(a,d){var e=c.utils.unwrapObservable(d());b(a).css({height:e[1],"min-height":e[1]})},update:function(a,d){var e=c.utils.unwrapObservable(d()),f=Bb.pInt(e[1]),g=0,h=b(a).offset().top;h>0&&(h+=Bb.pInt(e[2]),g=Lb.height()-h,g>f&&(f=g),b(a).css({height:f,"min-height":f}))}},c.bindingHandlers.appendDom={update:function(a,d){b(a).hide().empty().append(c.utils.unwrapObservable(d())).show()}},c.bindingHandlers.draggable={init:function(d,e,f){if(!Eb.bMobileDevice){var g=100,h=3,i=f(),j=i&&i.droppableSelector?i.droppableSelector:"",k={distance:20,handle:".dragHandle",cursorAt:{top:22,left:3},refreshPositions:!0,scroll:!0};j&&(k.drag=function(c){b(j).each(function(){var d=null,e=null,f=b(this),i=f.offset(),j=i.top+f.height();a.clearInterval(f.data("timerScroll")),f.data("timerScroll",!1),c.pageX>=i.left&&c.pageX<=i.left+f.width()&&(c.pageY>=j-g&&c.pageY<=j&&(d=function(){f.scrollTop(f.scrollTop()+h),Bb.windowResize()},f.data("timerScroll",a.setInterval(d,10)),d()),c.pageY>=i.top&&c.pageY<=i.top+g&&(e=function(){f.scrollTop(f.scrollTop()-h),Bb.windowResize()},f.data("timerScroll",a.setInterval(e,10)),e()))})},k.stop=function(){b(j).each(function(){a.clearInterval(b(this).data("timerScroll")),b(this).data("timerScroll",!1)})}),k.helper=function(a){return e()(a&&a.target?c.dataFor(a.target):null)},b(d).draggable(k).on("mousedown",function(){Bb.removeInFocus()})}}},c.bindingHandlers.droppable={init:function(a,c,d){if(!Eb.bMobileDevice){var e=c(),f=d(),g=f&&f.droppableOver?f.droppableOver:null,h=f&&f.droppableOut?f.droppableOut:null,i={tolerance:"pointer",hoverClass:"droppableHover"};e&&(i.drop=function(a,b){e(a,b)},g&&(i.over=function(a,b){g(a,b)}),h&&(i.out=function(a,b){h(a,b)}),b(a).droppable(i))}}},c.bindingHandlers.nano={init:function(a){Eb.bDisableNanoScroll||b(a).addClass("nano").nanoScroller({iOSNativeScrolling:!1,preventPageScrolling:!0})}},c.bindingHandlers.saveTrigger={init:function(a){var c=b(a);c.data("save-trigger-type",c.is("input[type=text],input[type=email],input[type=password],select,textarea")?"input":"custom"),"custom"===c.data("save-trigger-type")?c.append(' ').addClass("settings-saved-trigger"):c.addClass("settings-saved-trigger-input")},update:function(a,d){var e=c.utils.unwrapObservable(d()),f=b(a);if("custom"===f.data("save-trigger-type"))switch(e.toString()){case"1":f.find(".animated,.error").hide().removeClass("visible").end().find(".success").show().addClass("visible");break;case"0":f.find(".animated,.success").hide().removeClass("visible").end().find(".error").show().addClass("visible");break;case"-2":f.find(".error,.success").hide().removeClass("visible").end().find(".animated").show().addClass("visible");break;default:f.find(".animated").hide().end().find(".error,.success").removeClass("visible")}else switch(e.toString()){case"1":f.addClass("success").removeClass("error");break;case"0":f.addClass("error").removeClass("success");break;case"-2":break;default:f.removeClass("error success")}}},c.bindingHandlers.emailsTags={init:function(a,c){var d=b(a),e=c();d.inputosaurus({parseOnBlur:!0,inputDelimiters:[",",";"],autoCompleteSource:function(a,b){Ob.getAutocomplete(a.term,function(a){b(h.map(a,function(a){return a.toLine(!1)}))})},parseHook:function(a){return h.map(a,function(a){var b=Bb.trim(a),c=null;return""!==b?(c=new u,c.mailsoParse(b),c.clearDuplicateName(),[c.toLine(!1),c]):[b,null]})},change:h.bind(function(a){d.data("EmailsTagsValue",a.target.value),e(a.target.value)},this)}),e.subscribe(function(a){d.data("EmailsTagsValue")!==a&&(d.val(a),d.data("EmailsTagsValue",a),d.inputosaurus("refresh"))}),e.focusTrigger&&e.focusTrigger.subscribe(function(){d.inputosaurus("focus")})}},c.bindingHandlers.command={init:function(a,d,e,f){var g=b(a),h=d();if(!h||!h.enabled||!h.canExecute)throw new Error("You are not using command function");g.addClass("command"),c.bindingHandlers[g.is("form")?"submit":"click"].init.apply(f,arguments)},update:function(a,c){var d=!0,e=b(a),f=c();d=f.enabled(),e.toggleClass("command-not-enabled",!d),d&&(d=f.canExecute(),e.toggleClass("command-can-not-be-execute",!d)),e.toggleClass("command-disabled disable disabled",!d).toggleClass("no-disabled",!!d),(e.is("input")||e.is("button"))&&e.prop("disabled",!d)}},c.extenders.trimmer=function(a){var b=c.computed({read:a,write:function(b){a(Bb.trim(b.toString()))},owner:this});return b(a()),b},c.extenders.reversible=function(a){var b=a();return a.commit=function(){b=a()},a.reverse=function(){a(b)},a.commitedValue=function(){return b},a},c.extenders.toggleSubscribe=function(a,b){return a.subscribe(b[1],b[0],"beforeChange"),a.subscribe(b[2],b[0]),a},c.extenders.falseTimeout=function(b,c){return b.iTimeout=0,b.subscribe(function(d){d&&(a.clearTimeout(b.iTimeout),b.iTimeout=a.setTimeout(function(){b(!1),b.iTimeout=0},Bb.pInt(c)))}),b},c.observable.fn.validateNone=function(){return this.hasError=c.observable(!1),this},c.observable.fn.validateEmail=function(){return this.hasError=c.observable(!1),this.subscribe(function(a){a=Bb.trim(a),this.hasError(""!==a&&!/^[^@\s]+@[^@\s]+$/.test(a))},this),this.valueHasMutated(),this},c.observable.fn.validateSimpleEmail=function(){return this.hasError=c.observable(!1),this.subscribe(function(a){a=Bb.trim(a),this.hasError(""!==a&&!/^.+@.+$/.test(a))},this),this.valueHasMutated(),this},c.observable.fn.validateFunc=function(a){return this.hasFuncError=c.observable(!1),Bb.isFunc(a)&&(this.subscribe(function(b){this.hasFuncError(!a(b))},this),this.valueHasMutated()),this},k.prototype.root=function(){return this.sBase},k.prototype.attachmentDownload=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/Download/"+a},k.prototype.attachmentPreview=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/View/"+a},k.prototype.attachmentPreviewAsPlain=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/ViewAsPlain/"+a},k.prototype.upload=function(){return this.sServer+"/Upload/"+this.sSpecSuffix+"/"},k.prototype.uploadContacts=function(){return this.sServer+"/UploadContacts/"+this.sSpecSuffix+"/"},k.prototype.uploadBackground=function(){return this.sServer+"/UploadBackground/"+this.sSpecSuffix+"/"},k.prototype.append=function(){return this.sServer+"/Append/"+this.sSpecSuffix+"/"},k.prototype.change=function(b){return this.sServer+"/Change/"+this.sSpecSuffix+"/"+a.encodeURIComponent(b)+"/"},k.prototype.ajax=function(a){return this.sServer+"/Ajax/"+this.sSpecSuffix+"/"+a},k.prototype.messageViewLink=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/ViewAsPlain/"+a},k.prototype.messageDownloadLink=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/Download/"+a},k.prototype.inbox=function(){return this.sBase+"mailbox/Inbox"},k.prototype.messagePreview=function(){return this.sBase+"mailbox/message-preview"},k.prototype.settings=function(a){var b=this.sBase+"settings";return Bb.isUnd(a)||""===a||(b+="/"+a),b},k.prototype.admin=function(a){var b=this.sBase;switch(a){case"AdminDomains":b+="domains";break;case"AdminSecurity":b+="security";break;case"AdminLicensing":b+="licensing"}return b},k.prototype.mailBox=function(a,b,c){b=Bb.isNormal(b)?Bb.pInt(b):1,c=Bb.pString(c);var d=this.sBase+"mailbox/";return""!==a&&(d+=encodeURI(a)),b>1&&(d=d.replace(/[\/]+$/,""),d+="/p"+b),""!==c&&(d=d.replace(/[\/]+$/,""),d+="/"+encodeURI(c)),d},k.prototype.phpInfo=function(){return this.sServer+"Info"},k.prototype.langLink=function(a){return this.sServer+"/Lang/0/"+encodeURI(a)+"/"+this.sVersion+"/"},k.prototype.getUserPicUrlFromHash=function(a){return this.sServer+"/Raw/"+this.sSpecSuffix+"/UserPic/"+a+"/"+this.sVersion+"/"},k.prototype.exportContactsVcf=function(){return this.sServer+"/Raw/"+this.sSpecSuffix+"/ContactsVcf/"},k.prototype.exportContactsCsv=function(){return this.sServer+"/Raw/"+this.sSpecSuffix+"/ContactsCsv/"},k.prototype.emptyContactPic=function(){return"rainloop/v/"+this.sVersion+"/static/css/images/empty-contact.png"},k.prototype.sound=function(a){return"rainloop/v/"+this.sVersion+"/static/sounds/"+a},k.prototype.themePreviewLink=function(a){var b="rainloop/v/"+this.sVersion+"/";return"@custom"===a.substr(-7)&&(a=Bb.trim(a.substring(0,a.length-7)),b=""),b+"themes/"+encodeURI(a)+"/images/preview.png"},k.prototype.notificationMailIcon=function(){return"rainloop/v/"+this.sVersion+"/static/css/images/icom-message-notification.png"},k.prototype.openPgpJs=function(){return"rainloop/v/"+this.sVersion+"/static/js/openpgp.min.js"},k.prototype.socialGoogle=function(){return this.sServer+"SocialGoogle"+(""!==this.sSpecSuffix?"/"+this.sSpecSuffix+"/":"")},k.prototype.socialTwitter=function(){return this.sServer+"SocialTwitter"+(""!==this.sSpecSuffix?"/"+this.sSpecSuffix+"/":"")},k.prototype.socialFacebook=function(){return this.sServer+"SocialFacebook"+(""!==this.sSpecSuffix?"/"+this.sSpecSuffix+"/":"")},Cb.oViewModelsHooks={},Cb.oSimpleHooks={},Cb.regViewModelHook=function(a,b){b&&(b.__hookName=a)},Cb.addHook=function(a,b){Bb.isFunc(b)&&(Bb.isArray(Cb.oSimpleHooks[a])||(Cb.oSimpleHooks[a]=[]),Cb.oSimpleHooks[a].push(b))},Cb.runHook=function(a,b){Bb.isArray(Cb.oSimpleHooks[a])&&(b=b||[],h.each(Cb.oSimpleHooks[a],function(a){a.apply(null,b)}))},Cb.mainSettingsGet=function(a){return Ob?Ob.settingsGet(a):null},Cb.remoteRequest=function(a,b,c,d,e,f){Ob&&Ob.remote().defaultRequest(a,b,c,d,e,f)},Cb.settingsGet=function(a,b){var c=Cb.mainSettingsGet("Plugins");return c=c&&Bb.isUnd(c[a])?null:c[a],c?Bb.isUnd(c[b])?null:c[b]:null},l.prototype.blurTrigger=function(){if(this.fOnBlur){var b=this;a.clearTimeout(b.iBlurTimer),b.iBlurTimer=a.setTimeout(function(){b.fOnBlur()},200)}},l.prototype.focusTrigger=function(){this.fOnBlur&&a.clearTimeout(this.iBlurTimer)},l.prototype.isHtml=function(){return this.editor?"wysiwyg"===this.editor.mode:!1},l.prototype.checkDirty=function(){return this.editor?this.editor.checkDirty():!1},l.prototype.resetDirty=function(){this.editor&&this.editor.resetDirty()},l.prototype.getData=function(){return this.editor?"plain"===this.editor.mode&&this.editor.plugins.plain&&this.editor.__plain?this.editor.__plain.getRawData():this.editor.getData():""},l.prototype.modeToggle=function(a){this.editor&&(a?"plain"===this.editor.mode&&this.editor.setMode("wysiwyg"):"wysiwyg"===this.editor.mode&&this.editor.setMode("plain"))},l.prototype.setHtml=function(a,b){this.editor&&(this.modeToggle(!0),this.editor.setData(a),b&&this.focus())},l.prototype.setPlain=function(a,b){if(this.editor){if(this.modeToggle(!1),"plain"===this.editor.mode&&this.editor.plugins.plain&&this.editor.__plain)return this.editor.__plain.setRawData(a);this.editor.setData(a),b&&this.focus()}},l.prototype.init=function(){if(this.$element&&this.$element[0]){var b=this,c=Eb.oHtmlEditorDefaultConfig,d=Ob.settingsGet("Language"),e=!!Ob.settingsGet("AllowHtmlEditorSourceButton");e&&c.toolbarGroups&&!c.toolbarGroups.__SourceInited&&(c.toolbarGroups.__SourceInited=!0,c.toolbarGroups.push({name:"document",groups:["mode","document","doctools"]})),c.language=Eb.oHtmlEditorLangsMap[d]||"en",b.editor=a.CKEDITOR.appendTo(b.$element[0],c),b.editor.on("key",function(a){return a&&a.data&&9===a.data.keyCode?!1:void 0}),b.editor.on("blur",function(){b.blurTrigger()}),b.editor.on("mode",function(){b.blurTrigger(),b.fOnModeChange&&b.fOnModeChange("plain"!==b.editor.mode)}),b.editor.on("focus",function(){b.focusTrigger()}),b.fOnReady&&b.editor.on("instanceReady",function(){b.editor.setKeystroke(a.CKEDITOR.CTRL+65,"selectAll"),b.fOnReady(),b.__resizable=!0,b.resize()})}},l.prototype.focus=function(){this.editor&&this.editor.focus()},l.prototype.blur=function(){this.editor&&this.editor.focusManager.blur(!0)},l.prototype.resize=function(){this.editor&&this.__resizable&&this.editor.resize(this.$element.width(),this.$element.innerHeight())},l.prototype.clear=function(a){this.setHtml("",a)},m.prototype.itemSelected=function(a){this.isListChecked()?a||(this.oCallbacks.onItemSelect||this.emptyFunction)(a||null):a&&(this.oCallbacks.onItemSelect||this.emptyFunction)(a)},m.prototype.goDown=function(a){this.newSelectPosition(zb.EventKeyCode.Down,!1,a)},m.prototype.goUp=function(a){this.newSelectPosition(zb.EventKeyCode.Up,!1,a)},m.prototype.init=function(a,d,e){if(this.oContentVisible=a,this.oContentScrollable=d,e=e||"all",this.oContentVisible&&this.oContentScrollable){var f=this;b(this.oContentVisible).on("selectstart",function(a){a&&a.preventDefault&&a.preventDefault()}).on("click",this.sItemSelector,function(a){f.actionClick(c.dataFor(this),a)}).on("click",this.sItemCheckedSelector,function(a){var b=c.dataFor(this);b&&(a&&a.shiftKey?f.actionClick(b,a):(f.focusedItem(b),b.checked(!b.checked())))}),j("enter",e,function(){return f.focusedItem()&&!f.focusedItem().selected()?(f.actionClick(f.focusedItem()),!1):!0}),j("ctrl+up, command+up, ctrl+down, command+down",e,function(){return!1}),j("up, shift+up, down, shift+down, home, end, pageup, pagedown, insert, space",e,function(a,b){if(a&&b&&b.shortcut){var c=0;switch(b.shortcut){case"up":case"shift+up":c=zb.EventKeyCode.Up;break;case"down":case"shift+down":c=zb.EventKeyCode.Down;break;case"insert":c=zb.EventKeyCode.Insert;break;case"space":c=zb.EventKeyCode.Space;break;case"home":c=zb.EventKeyCode.Home;break;case"end":c=zb.EventKeyCode.End;break;case"pageup":c=zb.EventKeyCode.PageUp;break;case"pagedown":c=zb.EventKeyCode.PageDown}if(c>0)return f.newSelectPosition(c,j.shift),!1}})}},m.prototype.autoSelect=function(a){this.bAutoSelect=!!a},m.prototype.getItemUid=function(a){var b="",c=this.oCallbacks.onItemGetUid||null;return c&&a&&(b=c(a)),b.toString()},m.prototype.newSelectPosition=function(a,b,c){var d=0,e=10,f=!1,g=!1,i=null,j=this.list(),k=j?j.length:0,l=this.focusedItem();if(k>0)if(l){if(l)if(zb.EventKeyCode.Down===a||zb.EventKeyCode.Up===a||zb.EventKeyCode.Insert===a||zb.EventKeyCode.Space===a)h.each(j,function(b){if(!g)switch(a){case zb.EventKeyCode.Up:l===b?g=!0:i=b;break;case zb.EventKeyCode.Down:case zb.EventKeyCode.Insert:f?(i=b,g=!0):l===b&&(f=!0)}});else if(zb.EventKeyCode.Home===a||zb.EventKeyCode.End===a)zb.EventKeyCode.Home===a?i=j[0]:zb.EventKeyCode.End===a&&(i=j[j.length-1]);else if(zb.EventKeyCode.PageDown===a){for(;k>d;d++)if(l===j[d]){d+=e,d=d>k-1?k-1:d,i=j[d];break}}else if(zb.EventKeyCode.PageUp===a)for(d=k;d>=0;d--)if(l===j[d]){d-=e,d=0>d?0:d,i=j[d];break}}else zb.EventKeyCode.Down===a||zb.EventKeyCode.Insert===a||zb.EventKeyCode.Space===a||zb.EventKeyCode.Home===a||zb.EventKeyCode.PageUp===a?i=j[0]:(zb.EventKeyCode.Up===a||zb.EventKeyCode.End===a||zb.EventKeyCode.PageDown===a)&&(i=j[j.length-1]);i?(this.focusedItem(i),l&&(b?(zb.EventKeyCode.Up===a||zb.EventKeyCode.Down===a)&&l.checked(!l.checked()):(zb.EventKeyCode.Insert===a||zb.EventKeyCode.Space===a)&&l.checked(!l.checked())),!this.bAutoSelect&&!c||this.isListChecked()||zb.EventKeyCode.Space===a||this.selectedItem(i),this.scrollToFocused()):l&&(!b||zb.EventKeyCode.Up!==a&&zb.EventKeyCode.Down!==a?(zb.EventKeyCode.Insert===a||zb.EventKeyCode.Space===a)&&l.checked(!l.checked()):l.checked(!l.checked()),this.focusedItem(l))},m.prototype.scrollToFocused=function(){if(!this.oContentVisible||!this.oContentScrollable)return!1;var a=20,c=b(this.sItemFocusedSelector,this.oContentScrollable),d=c.position(),e=this.oContentVisible.height(),f=c.outerHeight();return d&&(d.top<0||d.top+f>e)?(this.oContentScrollable.scrollTop(d.top<0?this.oContentScrollable.scrollTop()+d.top-a:this.oContentScrollable.scrollTop()+d.top-e+f+a),!0):!1},m.prototype.scrollToTop=function(a){return this.oContentVisible&&this.oContentScrollable?(a?this.oContentScrollable.scrollTop(0):this.oContentScrollable.stop().animate({scrollTop:0},200),!0):!1},m.prototype.eventClickFunction=function(a,b){var c=this.getItemUid(a),d=0,e=0,f=null,g="",h=!1,i=!1,j=[],k=!1;if(b&&b.shiftKey&&""!==c&&""!==this.sLastUid&&c!==this.sLastUid)for(j=this.list(),k=a.checked(),d=0,e=j.length;e>d;d++)f=j[d],g=this.getItemUid(f),h=!1,(g===this.sLastUid||g===c)&&(h=!0),h&&(i=!i),(i||h)&&f.checked(k);this.sLastUid=""===c?"":c},m.prototype.actionClick=function(a,b){if(a){var c=!0,d=this.getItemUid(a);b&&(!b.shiftKey||b.ctrlKey||b.altKey?!b.ctrlKey||b.shiftKey||b.altKey||(c=!1,this.focusedItem(a),this.selectedItem()&&a!==this.selectedItem()&&this.selectedItem().checked(!0),a.checked(!a.checked())):(c=!1,""===this.sLastUid&&(this.sLastUid=d),a.checked(!a.checked()),this.eventClickFunction(a,b),this.focusedItem(a))),c&&(this.focusedItem(a),this.selectedItem(a))}},m.prototype.on=function(a,b){this.oCallbacks[a]=b},n.supported=function(){return!0},n.prototype.set=function(a,c){var d=b.cookie(yb.Values.ClientSideCookieIndexName),e=!1,f=null;try{f=null===d?null:JSON.parse(d),f||(f={}),f[a]=c,b.cookie(yb.Values.ClientSideCookieIndexName,JSON.stringify(f),{expires:30}),e=!0}catch(g){}return e},n.prototype.get=function(a){var c=b.cookie(yb.Values.ClientSideCookieIndexName),d=null;try{d=null===c?null:JSON.parse(c),d=d&&!Bb.isUnd(d[a])?d[a]:null}catch(e){}return d},o.supported=function(){return!!a.localStorage},o.prototype.set=function(b,c){var d=a.localStorage[yb.Values.ClientSideCookieIndexName]||null,e=!1,f=null;try{f=null===d?null:JSON.parse(d),f||(f={}),f[b]=c,a.localStorage[yb.Values.ClientSideCookieIndexName]=JSON.stringify(f),e=!0}catch(g){}return e},o.prototype.get=function(b){var c=a.localStorage[yb.Values.ClientSideCookieIndexName]||null,d=null;try{d=null===c?null:JSON.parse(c),d=d&&!Bb.isUnd(d[b])?d[b]:null}catch(e){}return d},p.prototype.oDriver=null,p.prototype.set=function(a,b){return this.oDriver?this.oDriver.set("p"+a,b):!1},p.prototype.get=function(a){return this.oDriver?this.oDriver.get("p"+a):null},q.prototype.bootstart=function(){},r.prototype.sPosition="",r.prototype.sTemplate="",r.prototype.viewModelName="",r.prototype.viewModelDom=null,r.prototype.viewModelTemplate=function(){return this.sTemplate},r.prototype.viewModelPosition=function(){return this.sPosition},r.prototype.cancelCommand=r.prototype.closeCommand=function(){},r.prototype.storeAndSetKeyScope=function(){this.sCurrentKeyScope=Ob.data().keyScope(),Ob.data().keyScope(this.sDefaultKeyScope) +},r.prototype.restoreKeyScope=function(){Ob.data().keyScope(this.sCurrentKeyScope)},r.prototype.registerPopupEscapeKey=function(){var a=this;Lb.on("keydown",function(b){return b&&zb.EventKeyCode.Esc===b.keyCode&&a.modalVisibility&&a.modalVisibility()?(Bb.delegateRun(a,"cancelCommand"),!1):!0})},s.prototype.oCross=null,s.prototype.sScreenName="",s.prototype.aViewModels=[],s.prototype.viewModels=function(){return this.aViewModels},s.prototype.screenName=function(){return this.sScreenName},s.prototype.routes=function(){return null},s.prototype.__cross=function(){return this.oCross},s.prototype.__start=function(){var a=this.routes(),b=null,c=null;Bb.isNonEmptyArray(a)&&(c=h.bind(this.onRoute||Bb.emptyFunction,this),b=d.create(),h.each(a,function(a){b.addRoute(a[0],c).rules=a[1]}),this.oCross=b)},t.constructorEnd=function(a){Bb.isFunc(a.__constructor_end)&&a.__constructor_end.call(a)},t.prototype.sDefaultScreenName="",t.prototype.oScreens={},t.prototype.oBoot=null,t.prototype.oCurrentScreen=null,t.prototype.hideLoading=function(){b("#rl-loading").hide()},t.prototype.routeOff=function(){e.changed.active=!1},t.prototype.routeOn=function(){e.changed.active=!0},t.prototype.setBoot=function(a){return Bb.isNormal(a)&&(this.oBoot=a),this},t.prototype.screen=function(a){return""===a||Bb.isUnd(this.oScreens[a])?null:this.oScreens[a]},t.prototype.buildViewModel=function(a,d){if(a&&!a.__builded){var e=new a(d),f=e.viewModelPosition(),g=b("#rl-content #rl-"+f.toLowerCase()),i=null;a.__builded=!0,a.__vm=e,e.data=Ob.data(),e.viewModelName=a.__name,g&&1===g.length?(i=b(" ").addClass("rl-view-model").addClass("RL-"+e.viewModelTemplate()).hide().attr("data-bind",'template: {name: "'+e.viewModelTemplate()+'"}, i18nInit: true'),i.appendTo(g),e.viewModelDom=i,a.__dom=i,"Popups"===f&&(e.cancelCommand=e.closeCommand=Bb.createCommand(e,function(){Hb.hideScreenPopup(a)}),e.modalVisibility.subscribe(function(a){var b=this;a?(this.viewModelDom.show(),this.storeAndSetKeyScope(),Ob.popupVisibilityNames.push(this.viewModelName),e.viewModelDom.css("z-index",3e3+Ob.popupVisibilityNames().length+10),Bb.delegateRun(this,"onFocus",[],500)):(Bb.delegateRun(this,"onHide"),this.restoreKeyScope(),Ob.popupVisibilityNames.remove(this.viewModelName),e.viewModelDom.css("z-index",2e3),h.delay(function(){b.viewModelDom.hide()},300))},e)),Cb.runHook("view-model-pre-build",[a.__name,e,i]),c.applyBindings(e,i[0]),Bb.delegateRun(e,"onBuild",[i]),e&&"Popups"===f&&!e.bDisabeCloseOnEsc&&e.registerPopupEscapeKey(),Cb.runHook("view-model-post-build",[a.__name,e,i])):Bb.log("Cannot find view model position: "+f)}return a?a.__vm:null},t.prototype.applyExternal=function(a,b){a&&b&&c.applyBindings(a,b)},t.prototype.hideScreenPopup=function(a){a&&a.__vm&&a.__dom&&(a.__vm.modalVisibility(!1),Cb.runHook("view-model-on-hide",[a.__name,a.__vm]))},t.prototype.showScreenPopup=function(a,b){a&&(this.buildViewModel(a),a.__vm&&a.__dom&&(a.__vm.modalVisibility(!0),Bb.delegateRun(a.__vm,"onShow",b||[]),Cb.runHook("view-model-on-show",[a.__name,a.__vm,b||[]])))},t.prototype.screenOnRoute=function(a,b){var c=this,d=null,e=null;""===Bb.pString(a)&&(a=this.sDefaultScreenName),""!==a&&(d=this.screen(a),d||(d=this.screen(this.sDefaultScreenName),d&&(b=a+"/"+b,a=this.sDefaultScreenName)),d&&d.__started&&(d.__builded||(d.__builded=!0,Bb.isNonEmptyArray(d.viewModels())&&h.each(d.viewModels(),function(a){this.buildViewModel(a,d)},this),Bb.delegateRun(d,"onBuild")),h.defer(function(){c.oCurrentScreen&&(Bb.delegateRun(c.oCurrentScreen,"onHide"),Bb.isNonEmptyArray(c.oCurrentScreen.viewModels())&&h.each(c.oCurrentScreen.viewModels(),function(a){a.__vm&&a.__dom&&"Popups"!==a.__vm.viewModelPosition()&&(a.__dom.hide(),a.__vm.viewModelVisibility(!1),Bb.delegateRun(a.__vm,"onHide"))})),c.oCurrentScreen=d,c.oCurrentScreen&&(Bb.delegateRun(c.oCurrentScreen,"onShow"),Cb.runHook("screen-on-show",[c.oCurrentScreen.screenName(),c.oCurrentScreen]),Bb.isNonEmptyArray(c.oCurrentScreen.viewModels())&&h.each(c.oCurrentScreen.viewModels(),function(a){a.__vm&&a.__dom&&"Popups"!==a.__vm.viewModelPosition()&&(a.__dom.show(),a.__vm.viewModelVisibility(!0),Bb.delegateRun(a.__vm,"onShow"),Bb.delegateRun(a.__vm,"onFocus",[],200),Cb.runHook("view-model-on-show",[a.__name,a.__vm]))},c)),e=d.__cross(),e&&e.parse(b)})))},t.prototype.startScreens=function(a){b("#rl-content").css({visibility:"hidden"}),h.each(a,function(a){var b=new a,c=b?b.screenName():"";b&&""!==c&&(""===this.sDefaultScreenName&&(this.sDefaultScreenName=c),this.oScreens[c]=b)},this),h.each(this.oScreens,function(a){a&&!a.__started&&a.__start&&(a.__started=!0,a.__start(),Cb.runHook("screen-pre-start",[a.screenName(),a]),Bb.delegateRun(a,"onStart"),Cb.runHook("screen-post-start",[a.screenName(),a]))},this);var c=d.create();c.addRoute(/^([a-zA-Z0-9\-]*)\/?(.*)$/,h.bind(this.screenOnRoute,this)),e.initialized.add(c.parse,c),e.changed.add(c.parse,c),e.init(),b("#rl-content").css({visibility:"visible"}),h.delay(function(){Kb.removeClass("rl-started-trigger").addClass("rl-started")},50)},t.prototype.setHash=function(a,b,c){a="#"===a.substr(0,1)?a.substr(1):a,a="/"===a.substr(0,1)?a.substr(1):a,c=Bb.isUnd(c)?!1:!!c,(Bb.isUnd(b)?1:!b)?(e.changed.active=!0,e[c?"replaceHash":"setHash"](a),e.setHash(a)):(e.changed.active=!1,e[c?"replaceHash":"setHash"](a),e.changed.active=!0)},t.prototype.bootstart=function(){return this.oBoot&&this.oBoot.bootstart&&this.oBoot.bootstart(),this},Hb=new t,u.newInstanceFromJson=function(a){var b=new u;return b.initByJson(a)?b:null},u.prototype.name="",u.prototype.email="",u.prototype.privateType=null,u.prototype.clear=function(){this.email="",this.name="",this.privateType=null},u.prototype.validate=function(){return""!==this.name||""!==this.email},u.prototype.hash=function(a){return"#"+(a?"":this.name)+"#"+this.email+"#"},u.prototype.clearDuplicateName=function(){this.name===this.email&&(this.name="")},u.prototype.type=function(){return null===this.privateType&&(this.email&&"@facebook.com"===this.email.substr(-13)&&(this.privateType=zb.EmailType.Facebook),null===this.privateType&&(this.privateType=zb.EmailType.Default)),this.privateType},u.prototype.search=function(a){return-1<(this.name+" "+this.email).toLowerCase().indexOf(a.toLowerCase())},u.prototype.parse=function(a){this.clear(),a=Bb.trim(a);var b=/(?:"([^"]+)")? ?(.*?@[^>,]+)>?,? ?/g,c=b.exec(a);c?(this.name=c[1]||"",this.email=c[2]||"",this.clearDuplicateName()):/^[^@]+@[^@]+$/.test(a)&&(this.name="",this.email=a)},u.prototype.initByJson=function(a){var b=!1;return a&&"Object/Email"===a["@Object"]&&(this.name=Bb.trim(a.Name),this.email=Bb.trim(a.Email),b=""!==this.email,this.clearDuplicateName()),b},u.prototype.toLine=function(a,b,c){var d="";return""!==this.email&&(b=Bb.isUnd(b)?!1:!!b,c=Bb.isUnd(c)?!1:!!c,a&&""!==this.name?d=b?'")+'" target="_blank" tabindex="-1">'+Bb.encodeHtml(this.name)+"":c?Bb.encodeHtml(this.name):this.name:(d=this.email,""!==this.name?b?d=Bb.encodeHtml('"'+this.name+'" <')+'")+'" target="_blank" tabindex="-1">'+Bb.encodeHtml(d)+""+Bb.encodeHtml(">"):(d='"'+this.name+'" <'+d+">",c&&(d=Bb.encodeHtml(d))):b&&(d=''+Bb.encodeHtml(this.email)+""))),d},u.prototype.mailsoParse=function(a){if(a=Bb.trim(a),""===a)return!1;for(var b=function(a,b,c){a+="";var d=a.length;return 0>b&&(b+=d),d="undefined"==typeof c?d:0>c?c+d:c+b,b>=a.length||0>b||b>d?!1:a.slice(b,d)},c=function(a,b,c,d){return 0>c&&(c+=a.length),d=void 0!==d?d:a.length,0>d&&(d=d+a.length-c),a.slice(0,c)+b.substr(0,d)+b.slice(d)+a.slice(c+d)},d="",e="",f="",g=!1,h=!1,i=!1,j=null,k=0,l=0,m=0;m").addClass("rl-settings-view-model").hide().attr("data-bind",'template: {name: "'+f.__rlSettingsData.Template+'"}, i18nInit: true'),i.appendTo(g),e.data=Ob.data(),e.viewModelDom=i,e.__rlSettingsData=f.__rlSettingsData,f.__dom=i,f.__builded=!0,f.__vm=e,c.applyBindings(e,i[0]),Bb.delegateRun(e,"onBuild",[i])):Bb.log("Cannot find sub settings view model position: SettingsSubScreen")),e&&h.defer(function(){d.oCurrentSubScreen&&(Bb.delegateRun(d.oCurrentSubScreen,"onHide"),d.oCurrentSubScreen.viewModelDom.hide()),d.oCurrentSubScreen=e,d.oCurrentSubScreen&&(d.oCurrentSubScreen.viewModelDom.show(),Bb.delegateRun(d.oCurrentSubScreen,"onShow"),Bb.delegateRun(d.oCurrentSubScreen,"onFocus",[],200),h.each(d.menu(),function(a){a.selected(e&&e.__rlSettingsData&&a.route===e.__rlSettingsData.Route)}),b("#rl-content .b-settings .b-content .content").scrollTop(0)),Bb.windowResize()})):Hb.setHash(Ob.link().settings(),!1,!0)},sb.prototype.onHide=function(){this.oCurrentSubScreen&&this.oCurrentSubScreen.viewModelDom&&(Bb.delegateRun(this.oCurrentSubScreen,"onHide"),this.oCurrentSubScreen.viewModelDom.hide())},sb.prototype.onBuild=function(){h.each(Fb.settings,function(a){a&&a.__rlSettingsData&&!h.find(Fb["settings-removed"],function(b){return b&&b===a})&&this.menu.push({route:a.__rlSettingsData.Route,label:a.__rlSettingsData.Label,selected:c.observable(!1),disabled:!!h.find(Fb["settings-disabled"],function(b){return b&&b===a})})},this),this.oViewModelPlace=b("#rl-content #rl-settings-subscreen")},sb.prototype.routes=function(){var a=h.find(Fb.settings,function(a){return a&&a.__rlSettingsData&&a.__rlSettingsData.IsDefault}),b=a?a.__rlSettingsData.Route:"general",c={subname:/^(.*)$/,normalize_:function(a,c){return c.subname=Bb.isUnd(c.subname)?b:Bb.pString(c.subname),[c.subname]}};return[["{subname}/",c],["{subname}",c],["",c]]},h.extend(tb.prototype,s.prototype),tb.prototype.onShow=function(){Ob.setTitle("")},h.extend(ub.prototype,s.prototype),ub.prototype.oLastRoute={},ub.prototype.setNewTitle=function(){var a=Ob.data().accountEmail(),b=Ob.data().foldersInboxUnreadCount();Ob.setTitle((""===a?"":(b>0?"("+b+") ":" ")+a+" - ")+Bb.i18n("TITLES/MAILBOX"))},ub.prototype.onShow=function(){this.setNewTitle(),Ob.data().keyScope(zb.KeyState.MessageList)},ub.prototype.onRoute=function(a,b,c,d){if(Bb.isUnd(d)?1:!d){var e=Ob.data(),f=Ob.cache().getFolderFullNameRaw(a),g=Ob.cache().getFolderFromCacheList(f);g&&(e.currentFolder(g).messageListPage(b).messageListSearch(c),zb.Layout.NoPreview===e.layout()&&e.message()&&(e.message(null),e.messageFullScreenMode(!1)),Ob.reloadMessageList())}else zb.Layout.NoPreview!==Ob.data().layout()||Ob.data().message()||Ob.historyBack()},ub.prototype.onStart=function(){var a=Ob.data(),b=function(){Bb.windowResize()};(Ob.settingsGet("AllowAdditionalAccounts")||Ob.settingsGet("AllowIdentities"))&&Ob.accountsAndIdentities(),h.delay(function(){"INBOX"!==a.currentFolderFullNameRaw()&&Ob.folderInformation("INBOX")},1e3),h.delay(function(){Ob.quota()},5e3),h.delay(function(){Ob.remote().appDelayStart(Bb.emptyFunction)},35e3),Kb.toggleClass("rl-no-preview-pane",zb.Layout.NoPreview===a.layout()),a.folderList.subscribe(b),a.messageList.subscribe(b),a.message.subscribe(b),a.layout.subscribe(function(a){Kb.toggleClass("rl-no-preview-pane",zb.Layout.NoPreview===a)}),a.foldersInboxUnreadCount.subscribe(function(){this.setNewTitle()},this)},ub.prototype.routes=function(){var a=function(){return["Inbox",1,"",!0]},b=function(a,b){return b[0]=Bb.pString(b[0]),b[1]=Bb.pInt(b[1]),b[1]=0>=b[1]?1:b[1],b[2]=Bb.pString(b[2]),""===a&&(b[0]="Inbox",b[1]=1),[decodeURI(b[0]),b[1],decodeURI(b[2]),!1]},c=function(a,b){return b[0]=Bb.pString(b[0]),b[1]=Bb.pString(b[1]),""===a&&(b[0]="Inbox"),[decodeURI(b[0]),1,decodeURI(b[1]),!1]};return[[/^([a-zA-Z0-9]+)\/p([1-9][0-9]*)\/(.+)\/?$/,{normalize_:b}],[/^([a-zA-Z0-9]+)\/p([1-9][0-9]*)$/,{normalize_:b}],[/^([a-zA-Z0-9]+)\/(.+)\/?$/,{normalize_:c}],[/^message-preview$/,{normalize_:a}],[/^([^\/]*)$/,{normalize_:b}]]},h.extend(vb.prototype,sb.prototype),vb.prototype.onShow=function(){Ob.setTitle(this.sSettingsTitle),Ob.data().keyScope(zb.KeyState.Settings)},h.extend(wb.prototype,q.prototype),wb.prototype.oSettings=null,wb.prototype.oPlugins=null,wb.prototype.oLocal=null,wb.prototype.oLink=null,wb.prototype.oSubs={},wb.prototype.download=function(b){var c=null,d=null,e=navigator.userAgent.toLowerCase();return e&&(e.indexOf("chrome")>-1||e.indexOf("chrome")>-1)&&(c=document.createElement("a"),c.href=b,document.createEvent&&(d=document.createEvent("MouseEvents"),d&&d.initEvent&&c.dispatchEvent))?(d.initEvent("click",!0,!0),c.dispatchEvent(d),!0):(Eb.bMobileDevice?(a.open(b,"_self"),a.focus()):this.iframe.attr("src",b),!0)},wb.prototype.link=function(){return null===this.oLink&&(this.oLink=new k),this.oLink},wb.prototype.local=function(){return null===this.oLocal&&(this.oLocal=new p),this.oLocal},wb.prototype.settingsGet=function(a){return null===this.oSettings&&(this.oSettings=Bb.isNormal(Ib)?Ib:{}),Bb.isUnd(this.oSettings[a])?null:this.oSettings[a]},wb.prototype.settingsSet=function(a,b){null===this.oSettings&&(this.oSettings=Bb.isNormal(Ib)?Ib:{}),this.oSettings[a]=b},wb.prototype.setTitle=function(b){b=(Bb.isNormal(b)&&00&&0===d.length&&(d=b(a,0,m)),h=!0,k=m);break;case">":h&&(l=m,e=b(a,k+1,l-k-1),a=c(a,"",k,l-k+1),l=0,m=0,k=0,h=!1);break;case"(":g||h||i||(i=!0,k=m);break;case")":i&&(l=m,f=b(a,k+1,l-k-1),a=c(a,"",k,l-k+1),l=0,m=0,k=0,i=!1);break;case"\\":m++}m++}return 0===e.length&&(j=a.match(/[^@\s]+@\S+/i),j&&j[0]?e=j[0]:d=a),e.length>0&&0===d.length&&0===f.length&&(d=a.replace(e,"")),e=Bb.trim(e).replace(/^[<]+/,"").replace(/[>]+$/,""),d=Bb.trim(d).replace(/^["']+/,"").replace(/["']+$/,""),f=Bb.trim(f).replace(/^[(]+/,"").replace(/[)]+$/,""),d=d.replace(/\\\\(.)/,"$1"),f=f.replace(/\\\\(.)/,"$1"),this.name=d,this.email=e,this.clearDuplicateName(),!0},u.prototype.inputoTagLine=function(){return 0 +$/,""),b=!0),b},x.prototype.isImage=function(){return-1 e;e++)d.push(a[e].toLine(b,c));return d.join(", ")},z.initEmailsFromJson=function(a){var b=0,c=0,d=null,e=[];if(Bb.isNonEmptyArray(a))for(b=0,c=a.length;c>b;b++)d=u.newInstanceFromJson(a[b]),d&&e.push(d);return e},z.replyHelper=function(a,b,c){if(a&&0 d;d++)Bb.isUnd(b[a[d].email])&&(b[a[d].email]=!0,c.push(a[d]))},z.prototype.clear=function(){this.folderFullNameRaw="",this.uid="",this.hash="",this.requestHash="",this.subject(""),this.size(0),this.dateTimeStampInUTC(0),this.priority(zb.MessagePriority.Normal),this.fromEmailString(""),this.toEmailsString(""),this.senderEmailsString(""),this.emails=[],this.from=[],this.to=[],this.cc=[],this.bcc=[],this.replyTo=[],this.newForAnimation(!1),this.deleted(!1),this.unseen(!1),this.flagged(!1),this.answered(!1),this.forwarded(!1),this.isReadReceipt(!1),this.selected(!1),this.checked(!1),this.hasAttachments(!1),this.attachmentsMainType(""),this.body=null,this.isRtl(!1),this.isHtml(!1),this.hasImages(!1),this.attachments([]),this.isPgpSigned(!1),this.isPgpEncrypted(!1),this.pgpSignedVerifyStatus(zb.SignedVerifyStatus.None),this.pgpSignedVerifyUser(""),this.priority(zb.MessagePriority.Normal),this.readReceipt(""),this.aDraftInfo=[],this.sMessageId="",this.sInReplyTo="",this.sReferences="",this.parentUid(0),this.threads([]),this.threadsLen(0),this.hasUnseenSubMessage(!1),this.hasFlaggedSubMessage(!1),this.lastInCollapsedThread(!1),this.lastInCollapsedThreadLoading(!1)},z.prototype.computeSenderEmail=function(){var a=Ob.data().sentFolder(),b=Ob.data().draftFolder();this.senderEmailsString(this.folderFullNameRaw===a||this.folderFullNameRaw===b?this.toEmailsString():this.fromEmailString())},z.prototype.initByJson=function(a){var b=!1;return a&&"Object/Message"===a["@Object"]&&(this.folderFullNameRaw=a.Folder,this.uid=a.Uid,this.hash=a.Hash,this.requestHash=a.RequestHash,this.size(Bb.pInt(a.Size)),this.from=z.initEmailsFromJson(a.From),this.to=z.initEmailsFromJson(a.To),this.cc=z.initEmailsFromJson(a.Cc),this.bcc=z.initEmailsFromJson(a.Bcc),this.replyTo=z.initEmailsFromJson(a.ReplyTo),this.subject(a.Subject),this.dateTimeStampInUTC(Bb.pInt(a.DateTimeStampInUTC)),this.hasAttachments(!!a.HasAttachments),this.attachmentsMainType(a.AttachmentsMainType),this.fromEmailString(z.emailsToLine(this.from,!0)),this.toEmailsString(z.emailsToLine(this.to,!0)),this.parentUid(Bb.pInt(a.ParentThread)),this.threads(Bb.isArray(a.Threads)?a.Threads:[]),this.threadsLen(Bb.pInt(a.ThreadsLen)),this.initFlagsByJson(a),this.computeSenderEmail(),b=!0),b},z.prototype.initUpdateByMessageJson=function(a){var b=!1,c=zb.MessagePriority.Normal;return a&&"Object/Message"===a["@Object"]&&(c=Bb.pInt(a.Priority),this.priority(-1 b;b++)d=x.newInstanceFromJson(a["@Collection"][b]),d&&(""!==d.cidWithOutTags&&0 +$/,""),b=h.find(c,function(b){return a===b.cidWithOutTags})),b||null},z.prototype.findAttachmentByContentLocation=function(a){var b=null,c=this.attachments();return Bb.isNonEmptyArray(c)&&(b=h.find(c,function(b){return a===b.contentLocation})),b||null},z.prototype.messageId=function(){return this.sMessageId},z.prototype.inReplyTo=function(){return this.sInReplyTo},z.prototype.references=function(){return this.sReferences},z.prototype.fromAsSingleEmail=function(){return Bb.isArray(this.from)&&this.from[0]?this.from[0].email:""},z.prototype.viewLink=function(){return Ob.link().messageViewLink(this.requestHash)},z.prototype.downloadLink=function(){return Ob.link().messageDownloadLink(this.requestHash)},z.prototype.replyEmails=function(a){var b=[],c=Bb.isUnd(a)?{}:a;return z.replyHelper(this.replyTo,c,b),0===b.length&&z.replyHelper(this.from,c,b),b},z.prototype.replyAllEmails=function(a){var b=[],c=[],d=Bb.isUnd(a)?{}:a;return z.replyHelper(this.replyTo,d,b),0===b.length&&z.replyHelper(this.from,d,b),z.replyHelper(this.to,d,b),z.replyHelper(this.cc,d,c),[b,c]},z.prototype.textBodyToString=function(){return this.body?this.body.html():""},z.prototype.attachmentsToStringLine=function(){var a=h.map(this.attachments(),function(a){return a.fileName+" ("+a.friendlySize+")"});return a&&0 =0&&e&&!f&&d.attr("src",e)}),c&&a.setTimeout(function(){d.print()},100))})},z.prototype.printMessage=function(){this.viewPopupMessage(!0)},z.prototype.generateUid=function(){return this.folderFullNameRaw+"/"+this.uid},z.prototype.populateByMessageListItem=function(a){return this.folderFullNameRaw=a.folderFullNameRaw,this.uid=a.uid,this.hash=a.hash,this.requestHash=a.requestHash,this.subject(a.subject()),this.size(a.size()),this.dateTimeStampInUTC(a.dateTimeStampInUTC()),this.priority(a.priority()),this.fromEmailString(a.fromEmailString()),this.toEmailsString(a.toEmailsString()),this.emails=a.emails,this.from=a.from,this.to=a.to,this.cc=a.cc,this.bcc=a.bcc,this.replyTo=a.replyTo,this.unseen(a.unseen()),this.flagged(a.flagged()),this.answered(a.answered()),this.forwarded(a.forwarded()),this.isReadReceipt(a.isReadReceipt()),this.selected(a.selected()),this.checked(a.checked()),this.hasAttachments(a.hasAttachments()),this.attachmentsMainType(a.attachmentsMainType()),this.moment(a.moment()),this.body=null,this.priority(zb.MessagePriority.Normal),this.aDraftInfo=[],this.sMessageId="",this.sInReplyTo="",this.sReferences="",this.parentUid(a.parentUid()),this.threads(a.threads()),this.threadsLen(a.threadsLen()),this.computeSenderEmail(),this},z.prototype.showExternalImages=function(a){this.body&&this.body.data("rl-has-images")&&(a=Bb.isUnd(a)?!1:a,this.hasImages(!1),this.body.data("rl-has-images",!1),b("[data-x-src]",this.body).each(function(){a&&b(this).is("img")?b(this).addClass("lazy").attr("data-original",b(this).attr("data-x-src")).removeAttr("data-x-src"):b(this).attr("src",b(this).attr("data-x-src")).removeAttr("data-x-src")}),b("[data-x-style-url]",this.body).each(function(){var a=Bb.trim(b(this).attr("style"));a=""===a?"":";"===a.substr(-1)?a+" ":a+"; ",b(this).attr("style",a+b(this).attr("data-x-style-url")).removeAttr("data-x-style-url")}),a&&(b("img.lazy",this.body).addClass("lazy-inited").lazyload({threshold:400,effect:"fadeIn",skip_invisible:!1,container:b(".RL-MailMessageView .messageView .messageItem .content")[0]}),Lb.resize()),Bb.windowResize(500))},z.prototype.showInternalImages=function(a){if(this.body&&!this.body.data("rl-init-internal-images")){this.body.data("rl-init-internal-images",!0),a=Bb.isUnd(a)?!1:a;var c=this;b("[data-x-src-cid]",this.body).each(function(){var d=c.findAttachmentByCid(b(this).attr("data-x-src-cid"));d&&d.download&&(a&&b(this).is("img")?b(this).addClass("lazy").attr("data-original",d.linkPreview()):b(this).attr("src",d.linkPreview()))}),b("[data-x-src-location]",this.body).each(function(){var d=c.findAttachmentByContentLocation(b(this).attr("data-x-src-location"));d||(d=c.findAttachmentByCid(b(this).attr("data-x-src-location"))),d&&d.download&&(a&&b(this).is("img")?b(this).addClass("lazy").attr("data-original",d.linkPreview()):b(this).attr("src",d.linkPreview()))}),b("[data-x-style-cid]",this.body).each(function(){var a="",d="",e=c.findAttachmentByCid(b(this).attr("data-x-style-cid"));e&&e.linkPreview&&(d=b(this).attr("data-x-style-cid-name"),""!==d&&(a=Bb.trim(b(this).attr("style")),a=""===a?"":";"===a.substr(-1)?a+" ":a+"; ",b(this).attr("style",a+d+": url('"+e.linkPreview()+"')")))}),a&&!function(a,b){h.delay(function(){a.addClass("lazy-inited").lazyload({threshold:400,effect:"fadeIn",skip_invisible:!1,container:b})},300)}(b("img.lazy",c.body),b(".RL-MailMessageView .messageView .messageItem .content")[0]),Bb.windowResize(500)}},z.prototype.storeDataToDom=function(){this.body&&(this.body.data("rl-is-rtl",!!this.isRtl()),this.body.data("rl-is-html",!!this.isHtml()),this.body.data("rl-has-images",!!this.hasImages()),this.body.data("rl-plain-raw",this.plainRaw),Ob.data().allowOpenPGP()&&(this.body.data("rl-plain-pgp-signed",!!this.isPgpSigned()),this.body.data("rl-plain-pgp-encrypted",!!this.isPgpEncrypted()),this.body.data("rl-pgp-verify-status",this.pgpSignedVerifyStatus()),this.body.data("rl-pgp-verify-user",this.pgpSignedVerifyUser())))},z.prototype.storePgpVerifyDataToDom=function(){this.body&&Ob.data().allowOpenPGP()&&(this.body.data("rl-pgp-verify-status",this.pgpSignedVerifyStatus()),this.body.data("rl-pgp-verify-user",this.pgpSignedVerifyUser()))},z.prototype.fetchDataToDom=function(){this.body&&(this.isRtl(!!this.body.data("rl-is-rtl")),this.isHtml(!!this.body.data("rl-is-html")),this.hasImages(!!this.body.data("rl-has-images")),this.plainRaw=Bb.pString(this.body.data("rl-plain-raw")),Ob.data().allowOpenPGP()?(this.isPgpSigned(!!this.body.data("rl-plain-pgp-signed")),this.isPgpEncrypted(!!this.body.data("rl-plain-pgp-encrypted")),this.pgpSignedVerifyStatus(this.body.data("rl-pgp-verify-status")),this.pgpSignedVerifyUser(this.body.data("rl-pgp-verify-user"))):(this.isPgpSigned(!1),this.isPgpEncrypted(!1),this.pgpSignedVerifyStatus(zb.SignedVerifyStatus.None),this.pgpSignedVerifyUser("")))},z.prototype.verifyPgpSignedClearMessage=function(){if(this.isPgpSigned()){var c=[],d=null,e=this.from&&this.from[0]&&this.from[0].email?this.from[0].email:"",f=Ob.data().findPublicKeysByEmail(e),g=null,i=null,j="";this.pgpSignedVerifyStatus(zb.SignedVerifyStatus.Error),this.pgpSignedVerifyUser("");try{d=a.openpgp.cleartext.readArmored(this.plainRaw),d&&d.getText&&(this.pgpSignedVerifyStatus(f.length?zb.SignedVerifyStatus.Unverified:zb.SignedVerifyStatus.UnknownPublicKeys),c=d.verify(f),c&&0 ').text(j)).html(),Pb.empty(),this.replacePlaneTextBody(j)))))}catch(k){}this.storePgpVerifyDataToDom()}},z.prototype.decryptPgpEncryptedMessage=function(c){if(this.isPgpEncrypted()){var d=[],e=null,f=null,g=this.from&&this.from[0]&&this.from[0].email?this.from[0].email:"",i=Ob.data().findPublicKeysByEmail(g),j=Ob.data().findSelfPrivateKey(c),k=null,l=null,m="";this.pgpSignedVerifyStatus(zb.SignedVerifyStatus.Error),this.pgpSignedVerifyUser(""),j||this.pgpSignedVerifyStatus(zb.SignedVerifyStatus.UnknownPrivateKey);try{e=a.openpgp.message.readArmored(this.plainRaw),e&&j&&e.decrypt&&(this.pgpSignedVerifyStatus(zb.SignedVerifyStatus.Unverified),f=e.decrypt(j),f&&(d=f.verify(i),d&&0 ').text(m)).html(),Pb.empty(),this.replacePlaneTextBody(m)))}catch(n){}this.storePgpVerifyDataToDom()}},z.prototype.replacePlaneTextBody=function(a){this.body&&this.body.html(a).addClass("b-text-part plain")},z.prototype.flagHash=function(){return[this.deleted(),this.unseen(),this.flagged(),this.answered(),this.forwarded(),this.isReadReceipt()].join("")},A.newInstanceFromJson=function(a){var b=new A;return b.initByJson(a)?b.initComputed():null},A.prototype.initComputed=function(){return this.hasSubScribedSubfolders=c.computed(function(){return!!h.find(this.subFolders(),function(a){return a.subScribed()&&!a.isSystemFolder()})},this),this.canBeEdited=c.computed(function(){return zb.FolderType.User===this.type()&&this.existen&&this.selectable},this),this.visible=c.computed(function(){var a=this.subScribed(),b=this.hasSubScribedSubfolders();return a||b&&(!this.existen||!this.selectable)},this),this.isSystemFolder=c.computed(function(){return zb.FolderType.User!==this.type()},this),this.hidden=c.computed(function(){var a=this.isSystemFolder(),b=this.hasSubScribedSubfolders();return a&&!b||!this.selectable&&!b},this),this.selectableForFolderList=c.computed(function(){return!this.isSystemFolder()&&this.selectable},this),this.messageCountAll=c.computed({read:this.privateMessageCountAll,write:function(a){Bb.isPosNumeric(a,!0)?this.privateMessageCountAll(a):this.privateMessageCountAll.valueHasMutated()},owner:this}),this.messageCountUnread=c.computed({read:this.privateMessageCountUnread,write:function(a){Bb.isPosNumeric(a,!0)?this.privateMessageCountUnread(a):this.privateMessageCountUnread.valueHasMutated()},owner:this}),this.printableUnreadCount=c.computed(function(){var a=this.messageCountAll(),b=this.messageCountUnread(),c=this.type();if(zb.FolderType.Inbox===c&&Ob.data().foldersInboxUnreadCount(b),a>0){if(zb.FolderType.Draft===c)return""+a;if(b>0&&zb.FolderType.Trash!==c&&zb.FolderType.Archive!==c&&zb.FolderType.SentItems!==c)return""+b}return""},this),this.canBeDeleted=c.computed(function(){var a=this.isSystemFolder();return!a&&0===this.subFolders().length&&"INBOX"!==this.fullNameRaw},this),this.canBeSubScribed=c.computed(function(){return!this.isSystemFolder()&&this.selectable&&"INBOX"!==this.fullNameRaw},this),this.visible.subscribe(function(){Bb.timeOutAction("folder-list-folder-visibility-change",function(){Lb.trigger("folder-list-folder-visibility-change")},100)}),this.localName=c.computed(function(){Eb.langChangeTrigger();var a=this.type(),b=this.name();if(this.isSystemFolder())switch(a){case zb.FolderType.Inbox:b=Bb.i18n("FOLDER_LIST/INBOX_NAME");break;case zb.FolderType.SentItems:b=Bb.i18n("FOLDER_LIST/SENT_NAME");break;case zb.FolderType.Draft:b=Bb.i18n("FOLDER_LIST/DRAFTS_NAME");break;case zb.FolderType.Spam:b=Bb.i18n("FOLDER_LIST/SPAM_NAME");break;case zb.FolderType.Trash:b=Bb.i18n("FOLDER_LIST/TRASH_NAME");break;case zb.FolderType.Archive:b=Bb.i18n("FOLDER_LIST/ARCHIVE_NAME")}return b},this),this.manageFolderSystemName=c.computed(function(){Eb.langChangeTrigger();var a="",b=this.type(),c=this.name();if(this.isSystemFolder())switch(b){case zb.FolderType.Inbox:a="("+Bb.i18n("FOLDER_LIST/INBOX_NAME")+")";break;case zb.FolderType.SentItems:a="("+Bb.i18n("FOLDER_LIST/SENT_NAME")+")";break;case zb.FolderType.Draft:a="("+Bb.i18n("FOLDER_LIST/DRAFTS_NAME")+")";break;case zb.FolderType.Spam:a="("+Bb.i18n("FOLDER_LIST/SPAM_NAME")+")";break;case zb.FolderType.Trash:a="("+Bb.i18n("FOLDER_LIST/TRASH_NAME")+")";break;case zb.FolderType.Archive:a="("+Bb.i18n("FOLDER_LIST/ARCHIVE_NAME")+")"}return(""!==a&&"("+c+")"===a||"(inbox)"===a.toLowerCase())&&(a=""),a},this),this.collapsed=c.computed({read:function(){return!this.hidden()&&this.collapsedPrivate()},write:function(a){this.collapsedPrivate(a)},owner:this}),this.hasUnreadMessages=c.computed(function(){return 0 "},C.prototype.formattedNameForCompose=function(){var a=this.name();return""===a?this.email():a+" ("+this.email()+")"},C.prototype.formattedNameForEmail=function(){var a=this.name();return""===a?this.email():'"'+Bb.quoteName(a)+'" <'+this.email()+">"},D.prototype.index=0,D.prototype.id="",D.prototype.guid="",D.prototype.user="",D.prototype.email="",D.prototype.armor="",D.prototype.isPrivate=!1,Bb.extendAsViewModel("PopupsFolderClearViewModel",E),E.prototype.clearPopup=function(){this.clearingProcess(!1),this.selectedFolder(null)},E.prototype.onShow=function(a){this.clearPopup(),a&&this.selectedFolder(a)},Bb.extendAsViewModel("PopupsFolderCreateViewModel",F),F.prototype.sNoParentText="",F.prototype.simpleFolderNameValidation=function(a){return/^[^\\\/]+$/g.test(Bb.trim(a))},F.prototype.clearPopup=function(){this.folderName(""),this.selectedParentValue(""),this.folderName.focused(!1)},F.prototype.onShow=function(){this.clearPopup()},F.prototype.onFocus=function(){this.folderName.focused(!0)},Bb.extendAsViewModel("PopupsFolderSystemViewModel",G),G.prototype.sChooseOnText="",G.prototype.sUnuseText="",G.prototype.onShow=function(a){var b="";switch(a=Bb.isUnd(a)?zb.SetSystemFoldersNotification.None:a){case zb.SetSystemFoldersNotification.Sent:b=Bb.i18n("POPUPS_SYSTEM_FOLDERS/NOTIFICATION_SENT");break;case zb.SetSystemFoldersNotification.Draft:b=Bb.i18n("POPUPS_SYSTEM_FOLDERS/NOTIFICATION_DRAFTS");break;case zb.SetSystemFoldersNotification.Spam:b=Bb.i18n("POPUPS_SYSTEM_FOLDERS/NOTIFICATION_SPAM");break;case zb.SetSystemFoldersNotification.Trash:b=Bb.i18n("POPUPS_SYSTEM_FOLDERS/NOTIFICATION_TRASH");break;case zb.SetSystemFoldersNotification.Archive:b=Bb.i18n("POPUPS_SYSTEM_FOLDERS/NOTIFICATION_ARCHIVE")}this.notification(b)},Bb.extendAsViewModel("PopupsComposeViewModel",H),H.prototype.openOpenPgpPopup=function(){if(this.allowOpenPGP()&&this.oEditor&&!this.oEditor.isHtml()){var a=this;Hb.showScreenPopup(O,[function(b){a.editor(function(a){a.setPlain(b)})},this.oEditor.getData(),this.currentIdentityResultEmail(),this.to(),this.cc(),this.bcc()])}},H.prototype.reloadDraftFolder=function(){var a=Ob.data().draftFolder();""!==a&&(Ob.cache().setFolderHash(a,""),Ob.data().currentFolderFullNameRaw()===a?Ob.reloadMessageList(!0):Ob.folderInformation(a))},H.prototype.findIdentityIdByMessage=function(a,b){var c={},d="",e=function(a){return a&&a.email&&c[a.email]?(d=c[a.email],!0):!1};if(this.bAllowIdentities&&h.each(this.identities(),function(a){c[a.email()]=a.id}),c[Ob.data().accountEmail()]=Ob.data().accountEmail(),b)switch(a){case zb.ComposeType.Empty:d=Ob.data().accountEmail();break;case zb.ComposeType.Reply:case zb.ComposeType.ReplyAll:case zb.ComposeType.Forward:case zb.ComposeType.ForwardAsAttachment:h.find(h.union(b.to,b.cc,b.bcc),e);break;case zb.ComposeType.Draft:h.find(h.union(b.from,b.replyTo),e)}else d=Ob.data().accountEmail();return d},H.prototype.selectIdentity=function(a){a&&this.currentIdentityID(a.optValue)},H.prototype.formattedFrom=function(a){var b=Ob.data().displayName(),c=Ob.data().accountEmail();return""===b?c:(Bb.isUnd(a)?1:!a)?b+" ("+c+")":'"'+Bb.quoteName(b)+'" <'+c+">"},H.prototype.sendMessageResponse=function(b,c){var d=!1,e="";this.sending(!1),zb.StorageResultType.Success===b&&c&&c.Result&&(d=!0,this.modalVisibility()&&Bb.delegateRun(this,"closeCommand")),this.modalVisibility()&&!d&&(c&&zb.Notification.CantSaveMessage===c.ErrorCode?(this.sendSuccessButSaveError(!0),a.alert(Bb.trim(Bb.i18n("COMPOSE/SAVED_ERROR_ON_SEND")))):(e=Bb.getNotification(c&&c.ErrorCode?c.ErrorCode:zb.Notification.CantSendMessage,c&&c.ErrorMessage?c.ErrorMessage:""),this.sendError(!0),a.alert(e||Bb.getNotification(zb.Notification.CantSendMessage)))),this.reloadDraftFolder()},H.prototype.saveMessageResponse=function(b,c){var d=!1,e=null;this.saving(!1),zb.StorageResultType.Success===b&&c&&c.Result&&c.Result.NewFolder&&c.Result.NewUid&&(this.bFromDraft&&(e=Ob.data().message(),e&&this.draftFolder()===e.folderFullNameRaw&&this.draftUid()===e.uid&&Ob.data().message(null)),this.draftFolder(c.Result.NewFolder),this.draftUid(c.Result.NewUid),this.modalVisibility()&&(this.savedTime(Math.round((new a.Date).getTime()/1e3)),this.savedOrSendingText(0 c;c++)e.push(a[c].toLine(!!b));return e.join(", ")};if(c=c||null,c&&Bb.isNormal(c)&&(v=Bb.isArray(c)&&1===c.length?c[0]:Bb.isArray(c)?null:c),null!==q&&(p[q]=!0,this.currentIdentityID(this.findIdentityIdByMessage(w,v))),this.reset(),Bb.isNonEmptyArray(d)&&this.to(x(d)),""!==w&&v){switch(j=v.fullFormatDateValue(),k=v.subject(),u=v.aDraftInfo,l=b(v.body).clone(),Bb.removeBlockquoteSwitcher(l),m=l.html(),w){case zb.ComposeType.Empty:break;case zb.ComposeType.Reply:this.to(x(v.replyEmails(p))),this.subject(Bb.replySubjectAdd("Re",k)),this.prepearMessageAttachments(v,w),this.aDraftInfo=["reply",v.uid,v.folderFullNameRaw],this.sInReplyTo=v.sMessageId,this.sReferences=Bb.trim(this.sInReplyTo+" "+v.sReferences);break;case zb.ComposeType.ReplyAll:o=v.replyAllEmails(p),this.to(x(o[0])),this.cc(x(o[1])),this.subject(Bb.replySubjectAdd("Re",k)),this.prepearMessageAttachments(v,w),this.aDraftInfo=["reply",v.uid,v.folderFullNameRaw],this.sInReplyTo=v.sMessageId,this.sReferences=Bb.trim(this.sInReplyTo+" "+v.references());break;case zb.ComposeType.Forward:this.subject(Bb.replySubjectAdd("Fwd",k)),this.prepearMessageAttachments(v,w),this.aDraftInfo=["forward",v.uid,v.folderFullNameRaw],this.sInReplyTo=v.sMessageId,this.sReferences=Bb.trim(this.sInReplyTo+" "+v.sReferences);break;case zb.ComposeType.ForwardAsAttachment:this.subject(Bb.replySubjectAdd("Fwd",k)),this.prepearMessageAttachments(v,w),this.aDraftInfo=["forward",v.uid,v.folderFullNameRaw],this.sInReplyTo=v.sMessageId,this.sReferences=Bb.trim(this.sInReplyTo+" "+v.sReferences);break;case zb.ComposeType.Draft:this.to(x(v.to)),this.cc(x(v.cc)),this.bcc(x(v.bcc)),this.bFromDraft=!0,this.draftFolder(v.folderFullNameRaw),this.draftUid(v.uid),this.subject(k),this.prepearMessageAttachments(v,w),this.aDraftInfo=Bb.isNonEmptyArray(u)&&3===u.length?u:null,this.sInReplyTo=v.sInReplyTo,this.sReferences=v.sReferences;break;case zb.ComposeType.EditAsNew:this.to(x(v.to)),this.cc(x(v.cc)),this.bcc(x(v.bcc)),this.subject(k),this.prepearMessageAttachments(v,w),this.aDraftInfo=Bb.isNonEmptyArray(u)&&3===u.length?u:null,this.sInReplyTo=v.sInReplyTo,this.sReferences=v.sReferences}switch(w){case zb.ComposeType.Reply:case zb.ComposeType.ReplyAll:f=v.fromToLine(!1,!0),n=Bb.i18n("COMPOSE/REPLY_MESSAGE_TITLE",{DATETIME:j,EMAIL:f}),m="
"+n+":";break;case zb.ComposeType.Forward:f=v.fromToLine(!1,!0),g=v.toToLine(!1,!0),i=v.ccToLine(!1,!0),m=""+m+"
"+Bb.i18n("COMPOSE/FORWARD_MESSAGE_TOP_TITLE")+"
"+Bb.i18n("COMPOSE/FORWARD_MESSAGE_TOP_FROM")+": "+f+"
"+Bb.i18n("COMPOSE/FORWARD_MESSAGE_TOP_TO")+": "+g+(0"+Bb.i18n("COMPOSE/FORWARD_MESSAGE_TOP_CC")+": "+i:"")+"
"+Bb.i18n("COMPOSE/FORWARD_MESSAGE_TOP_SENT")+": "+Bb.encodeHtml(j)+"
"+Bb.i18n("COMPOSE/FORWARD_MESSAGE_TOP_SUBJECT")+": "+Bb.encodeHtml(k)+"
"+m;break;case zb.ComposeType.ForwardAsAttachment:m=""}s&&""!==r&&zb.ComposeType.EditAsNew!==w&&zb.ComposeType.Draft!==w&&(m=this.convertSignature(r,x(v.from,!0))+"
"+m),this.editor(function(a){a.setHtml(m,!1),v.isHtml()||a.modeToggle(!1)})}else zb.ComposeType.Empty===w?(m=this.convertSignature(r),this.editor(function(a){a.setHtml(m,!1),zb.EditorDefaultType.Html!==Ob.data().editorDefaultType()&&a.modeToggle(!1)})):Bb.isNonEmptyArray(c)&&h.each(c,function(a){e.addMessageAsAttachment(a)});t=this.getAttachmentsDownloadsForUpload(),Bb.isNonEmptyArray(t)&&Ob.remote().messageUploadAttachments(function(a,b){if(zb.StorageResultType.Success===a&&b&&b.Result){var c=null,d="";if(!e.viewModelVisibility())for(d in b.Result)b.Result.hasOwnProperty(d)&&(c=e.getAttachmentById(b.Result[d]),c&&c.tempName(d))}else e.setMessageAttachmentFailedDowbloadText()},t),this.triggerForResize()},H.prototype.onFocus=function(){""===this.to()?this.to.focusTrigger(!this.to.focusTrigger()):this.oEditor&&this.oEditor.focus(),this.triggerForResize()},H.prototype.editorResize=function(){this.oEditor&&this.oEditor.resize()},H.prototype.tryToClosePopup=function(){var a=this;Hb.showScreenPopup(S,[Bb.i18n("POPUPS_ASK/DESC_WANT_CLOSE_THIS_WINDOW"),function(){a.modalVisibility()&&Bb.delegateRun(a,"closeCommand")}])},H.prototype.onBuild=function(){this.initUploader();var a=this,c=null;j("ctrl+q, command+q",zb.KeyState.Compose,function(){return a.identitiesDropdownTrigger(!0),!1}),j("ctrl+s, command+s",zb.KeyState.Compose,function(){return a.saveCommand(),!1}),j("ctrl+enter, command+enter",zb.KeyState.Compose,function(){return a.sendCommand(),!1}),j("esc",zb.KeyState.Compose,function(){return a.tryToClosePopup(),!1}),Lb.on("resize",function(){a.triggerForResize()}),this.dropboxEnabled()&&(c=document.createElement("script"),c.type="text/javascript",c.src="https://www.dropbox.com/static/api/1/dropins.js",b(c).attr("id","dropboxjs").attr("data-app-key",Ob.settingsGet("DropboxApiKey")),document.body.appendChild(c))},H.prototype.getAttachmentById=function(a){for(var b=this.attachments(),c=0,d=b.length;d>c;c++)if(b[c]&&a===b[c].id)return b[c];return null},H.prototype.initUploader=function(){if(this.composeUploaderButton()){var a={},b=Bb.pInt(Ob.settingsGet("AttachmentLimit")),c=new g({action:Ob.link().upload(),name:"uploader",queueSize:2,multipleSizeLimit:50,disableFolderDragAndDrop:!1,clickElement:this.composeUploaderButton(),dragAndDropElement:this.composeUploaderDropPlace()});c?(c.on("onDragEnter",h.bind(function(){this.dragAndDropOver(!0)},this)).on("onDragLeave",h.bind(function(){this.dragAndDropOver(!1)},this)).on("onBodyDragEnter",h.bind(function(){this.dragAndDropVisible(!0)},this)).on("onBodyDragLeave",h.bind(function(){this.dragAndDropVisible(!1)},this)).on("onProgress",h.bind(function(b,c,d){var e=null;Bb.isUnd(a[b])?(e=this.getAttachmentById(b),e&&(a[b]=e)):e=a[b],e&&e.progress(" - "+Math.floor(c/d*100)+"%")},this)).on("onSelect",h.bind(function(a,d){this.dragAndDropOver(!1);var e=this,f=Bb.isUnd(d.FileName)?"":d.FileName.toString(),g=Bb.isNormal(d.Size)?Bb.pInt(d.Size):null,h=new y(a,f,g);return h.cancel=function(a){return function(){e.attachments.remove(function(b){return b&&b.id===a}),c&&c.cancel(a)}}(a),this.attachments.push(h),g>0&&b>0&&g>b?(h.error(Bb.i18n("UPLOAD/ERROR_FILE_IS_TOO_BIG")),!1):!0},this)).on("onStart",h.bind(function(b){var c=null;Bb.isUnd(a[b])?(c=this.getAttachmentById(b),c&&(a[b]=c)):c=a[b],c&&(c.waiting(!1),c.uploading(!0))},this)).on("onComplete",h.bind(function(b,c,d){var e="",f=null,g=null,h=this.getAttachmentById(b);g=c&&d&&d.Result&&d.Result.Attachment?d.Result.Attachment:null,f=d&&d.Result&&d.Result.ErrorCode?d.Result.ErrorCode:null,null!==f?e=Bb.getUploadErrorDescByCode(f):g||(e=Bb.i18n("UPLOAD/ERROR_UNKNOWN")),h&&(""!==e&&00&&d>0&&f>d?(e.uploading(!1),e.error(Bb.i18n("UPLOAD/ERROR_FILE_IS_TOO_BIG")),!1):(Ob.remote().composeUploadExternals(function(a,b){var c=!1;e.uploading(!1),zb.StorageResultType.Success===a&&b&&b.Result&&b.Result[e.id]&&(c=!0,e.tempName(b.Result[e.id])),c||e.error(Bb.getUploadErrorDescByCode(zb.UploadErrorCode.FileNoUploaded))},[a.link]),!0)},H.prototype.prepearMessageAttachments=function(a,b){if(a){var c=this,d=Bb.isNonEmptyArray(a.attachments())?a.attachments():[],e=0,f=d.length,g=null,h=null,i=!1,j=function(a){return function(){c.attachments.remove(function(b){return b&&b.id===a})}};if(zb.ComposeType.ForwardAsAttachment===b)this.addMessageAsAttachment(a);else for(;f>e;e++){switch(h=d[e],i=!1,b){case zb.ComposeType.Reply:case zb.ComposeType.ReplyAll:i=h.isLinked;break;case zb.ComposeType.Forward:case zb.ComposeType.Draft:case zb.ComposeType.EditAsNew:i=!0}i=!0,i&&(g=new y(h.download,h.fileName,h.estimatedSize,h.isInline,h.isLinked,h.cid,h.contentLocation),g.fromMessage=!0,g.cancel=j(h.download),g.waiting(!1).uploading(!0),this.attachments.push(g))}}},H.prototype.removeLinkedAttachments=function(){this.attachments.remove(function(a){return a&&a.isLinked})},H.prototype.setMessageAttachmentFailedDowbloadText=function(){h.each(this.attachments(),function(a){a&&a.fromMessage&&a.waiting(!1).uploading(!1).error(Bb.getUploadErrorDescByCode(zb.UploadErrorCode.FileNoUploaded))},this)},H.prototype.isEmptyForm=function(a){a=Bb.isUnd(a)?!0:!!a;var b=a?0===this.attachments().length:0===this.attachmentsInReady().length;return 0===this.to().length&&0===this.cc().length&&0===this.bcc().length&&0===this.subject().length&&b&&(!this.oEditor||""===this.oEditor.getData())},H.prototype.reset=function(){this.to(""),this.cc(""),this.bcc(""),this.replyTo(""),this.subject(""),this.requestReadReceipt(!1),this.aDraftInfo=null,this.sInReplyTo="",this.bFromDraft=!1,this.sReferences="",this.sendError(!1),this.sendSuccessButSaveError(!1),this.savedError(!1),this.savedTime(0),this.savedOrSendingText(""),this.emptyToError(!1),this.showCcAndBcc(!1),this.attachments([]),this.dragAndDropOver(!1),this.dragAndDropVisible(!1),this.draftFolder(""),this.draftUid(""),this.sending(!1),this.saving(!1),this.oEditor&&this.oEditor.clear(!1)},H.prototype.getAttachmentsDownloadsForUpload=function(){return h.map(h.filter(this.attachments(),function(a){return a&&""===a.tempName()}),function(a){return a.id})},H.prototype.triggerForResize=function(){this.resizer(!this.resizer()),this.editorResizeThrottle()},Bb.extendAsViewModel("PopupsContactsViewModel",I),I.prototype.getPropertyPlceholder=function(a){var b="";switch(a){case zb.ContactPropertyType.LastName:b="CONTACTS/PLACEHOLDER_ENTER_LAST_NAME";break;case zb.ContactPropertyType.FirstName:b="CONTACTS/PLACEHOLDER_ENTER_FIRST_NAME";break;case zb.ContactPropertyType.Nick:b="CONTACTS/PLACEHOLDER_ENTER_NICK_NAME"}return b},I.prototype.addNewProperty=function(a,b){this.viewProperties.push(new w(a,b||"","",!0,this.getPropertyPlceholder(a)))},I.prototype.addNewOrFocusProperty=function(a,b){var c=h.find(this.viewProperties(),function(b){return a===b.type()});c?c.focused(!0):this.addNewProperty(a,b)},I.prototype.addNewEmail=function(){this.addNewProperty(zb.ContactPropertyType.Email,"Home")},I.prototype.addNewPhone=function(){this.addNewProperty(zb.ContactPropertyType.Phone,"Mobile")},I.prototype.addNewWeb=function(){this.addNewProperty(zb.ContactPropertyType.Web)},I.prototype.addNewNickname=function(){this.addNewOrFocusProperty(zb.ContactPropertyType.Nick)},I.prototype.addNewNotes=function(){this.addNewOrFocusProperty(zb.ContactPropertyType.Note)},I.prototype.addNewBirthday=function(){this.addNewOrFocusProperty(zb.ContactPropertyType.Birthday)},I.prototype.exportVcf=function(){Ob.download(Ob.link().exportContactsVcf())},I.prototype.exportCsv=function(){Ob.download(Ob.link().exportContactsCsv())},I.prototype.initUploader=function(){if(this.importUploaderButton()){var b=new g({action:Ob.link().uploadContacts(),name:"uploader",queueSize:1,multipleSizeLimit:1,disableFolderDragAndDrop:!0,disableDragAndDrop:!0,disableMultiple:!0,disableDocumentDropPrevent:!0,clickElement:this.importUploaderButton()});b&&b.on("onStart",h.bind(function(){this.contacts.importing(!0)},this)).on("onComplete",h.bind(function(b,c,d){this.contacts.importing(!1),this.reloadContactList(),b&&c&&d&&d.Result||a.alert(Bb.i18n("CONTACTS/ERROR_IMPORT_FILE"))},this))}},I.prototype.removeCheckedOrSelectedContactsFromList=function(){var a=this,b=this.contacts,c=this.currentContact(),d=this.contacts().length,e=this.contactsCheckedOrSelected();0 =d&&(this.bDropPageAfterDelete=!0),h.delay(function(){h.each(e,function(a){b.remove(a)})},500))},I.prototype.deleteSelectedContacts=function(){0 0?d:0),b.contactsCount(d),b.contacts(e),b.viewClearSearch(""!==b.search()),b.contacts.loading(!1)},c,yb.Defaults.ContactsPerPage,this.search())},I.prototype.onBuild=function(a){this.oContentVisible=b(".b-list-content",a),this.oContentScrollable=b(".content",this.oContentVisible),this.selector.init(this.oContentVisible,this.oContentScrollable,zb.KeyState.ContactList);var d=this;j("delete",zb.KeyState.ContactList,function(){return d.deleteCommand(),!1}),a.on("click",".e-pagenator .e-page",function(){var a=c.dataFor(this);a&&(d.contactsPage(Bb.pInt(a.value)),d.reloadContactList())}),this.initUploader()},I.prototype.onShow=function(){Hb.routeOff(),this.reloadContactList(!0)},I.prototype.onHide=function(){Hb.routeOn(),this.currentContact(null),this.emptySelection(!0),this.search(""),h.each(this.contacts(),function(a){a.checked(!1)})},Bb.extendAsViewModel("PopupsAdvancedSearchViewModel",J),J.prototype.buildSearchStringValue=function(a){return-1 li"),e=c&&("tab"===c.shortcut||"right"===c.shortcut),f=d.index(d.filter(".active"));return!e&&f>0?f--:e&&f -1&&g.eq(e).removeClass("focused"),38===f&&e>0?e--:40===f&&e 1?" ("+(100>a?a:"99+")+")":""},Z.prototype.cancelSearch=function(){this.mainMessageListSearch(""),this.inputMessageListSearchFocus(!1)},Z.prototype.moveSelectedMessagesToFolder=function(a,b){return this.canBeMoved()&&Ob.moveMessagesToFolder(Ob.data().currentFolderFullNameRaw(),Ob.data().messageListCheckedOrSelectedUidsWithSubMails(),a,b),!1},Z.prototype.dragAndDronHelper=function(a){a&&a.checked(!0);var b=Bb.draggeblePlace(),c=Ob.data().messageListCheckedOrSelectedUidsWithSubMails();return b.data("rl-folder",Ob.data().currentFolderFullNameRaw()),b.data("rl-uids",c),b.find(".text").text(""+c.length),h.defer(function(){var a=Ob.data().messageListCheckedOrSelectedUidsWithSubMails();b.data("rl-uids",a),b.find(".text").text(""+a.length)}),b},Z.prototype.onMessageResponse=function(a,b,c){var d=Ob.data();d.hideMessageBodies(),d.messageLoading(!1),zb.StorageResultType.Success===a&&b&&b.Result?d.setMessage(b,c):zb.StorageResultType.Unload===a?(d.message(null),d.messageError("")):zb.StorageResultType.Abort!==a&&(d.message(null),d.messageError(Bb.getNotification(b&&b.ErrorCode?b.ErrorCode:zb.Notification.UnknownError)))},Z.prototype.populateMessageBody=function(a){a&&(Ob.remote().message(this.onMessageResponse,a.folderFullNameRaw,a.uid)?Ob.data().messageLoading(!0):Bb.log("Error: Unknown message request: "+a.folderFullNameRaw+" ~ "+a.uid+" [e-101]"))},Z.prototype.setAction=function(a,b,c){var d=[],e=null,f=Ob.cache(),g=0;if(Bb.isUnd(c)&&(c=Ob.data().messageListChecked()),d=h.map(c,function(a){return a.uid}),""!==a&&0 0?100>a?a:"99+":""},$.prototype.verifyPgpSignedClearMessage=function(a){a&&a.verifyPgpSignedClearMessage()},$.prototype.decryptPgpEncryptedMessage=function(a){a&&a.decryptPgpEncryptedMessage(this.viewPgpPassword())},$.prototype.readReceipt=function(a){a&&""!==a.readReceipt()&&(Ob.remote().sendReadReceiptMessage(Bb.emptyFunction,a.folderFullNameRaw,a.uid,a.readReceipt(),Bb.i18n("READ_RECEIPT/SUBJECT",{SUBJECT:a.subject()}),Bb.i18n("READ_RECEIPT/BODY",{"READ-RECEIPT":Ob.data().accountEmail()})),a.isReadReceipt(!0),Ob.cache().storeMessageFlagsToCache(a),Ob.reloadFlagsCurrentMessageListAndMessageFromCache())},Bb.extendAsViewModel("SettingsMenuViewModel",_),_.prototype.link=function(a){return Ob.link().settings(a)},_.prototype.backToMailBoxClick=function(){Hb.setHash(Ob.link().inbox())},Bb.extendAsViewModel("SettingsPaneViewModel",ab),ab.prototype.onBuild=function(){var a=this;j("esc",zb.KeyState.Settings,function(){a.backToMailBoxClick()})},ab.prototype.onShow=function(){Ob.data().message(null)},ab.prototype.backToMailBoxClick=function(){Hb.setHash(Ob.link().inbox())},Bb.addSettingsViewModel(bb,"SettingsGeneral","SETTINGS_LABELS/LABEL_GENERAL_NAME","general",!0),bb.prototype.toggleLayout=function(){this.layout(zb.Layout.NoPreview===this.layout()?zb.Layout.SidePreview:zb.Layout.NoPreview)},bb.prototype.onBuild=function(){var a=this;h.delay(function(){var c=Ob.data(),d=Bb.settingsSaveHelperSimpleFunction(a.mppTrigger,a);c.language.subscribe(function(c){a.languageTrigger(zb.SaveSettingsStep.Animate),b.ajax({url:Ob.link().langLink(c),dataType:"script",cache:!0}).done(function(){Bb.i18nToDoc(),a.languageTrigger(zb.SaveSettingsStep.TrueResult)}).fail(function(){a.languageTrigger(zb.SaveSettingsStep.FalseResult)}).always(function(){h.delay(function(){a.languageTrigger(zb.SaveSettingsStep.Idle)},1e3)}),Ob.remote().saveSettings(Bb.emptyFunction,{Language:c})}),c.editorDefaultType.subscribe(function(a){Ob.remote().saveSettings(Bb.emptyFunction,{EditorDefaultType:a})}),c.messagesPerPage.subscribe(function(a){Ob.remote().saveSettings(d,{MPP:a})}),c.showImages.subscribe(function(a){Ob.remote().saveSettings(Bb.emptyFunction,{ShowImages:a?"1":"0"})}),c.interfaceAnimation.subscribe(function(a){Ob.remote().saveSettings(Bb.emptyFunction,{InterfaceAnimation:a})}),c.useDesktopNotifications.subscribe(function(a){Bb.timeOutAction("SaveDesktopNotifications",function(){Ob.remote().saveSettings(Bb.emptyFunction,{DesktopNotifications:a?"1":"0"})},3e3)}),c.replySameFolder.subscribe(function(a){Bb.timeOutAction("SaveReplySameFolder",function(){Ob.remote().saveSettings(Bb.emptyFunction,{ReplySameFolder:a?"1":"0"})},3e3)}),c.useThreads.subscribe(function(a){c.messageList([]),Ob.remote().saveSettings(Bb.emptyFunction,{UseThreads:a?"1":"0"})}),c.layout.subscribe(function(a){c.messageList([]),Ob.remote().saveSettings(Bb.emptyFunction,{Layout:a})}),c.useCheckboxesInList.subscribe(function(a){Ob.remote().saveSettings(Bb.emptyFunction,{UseCheckboxesInList:a?"1":"0"})})},50)},bb.prototype.onShow=function(){Ob.data().desktopNotifications.valueHasMutated()},bb.prototype.selectLanguage=function(){Hb.showScreenPopup(Q)},Bb.addSettingsViewModel(cb,"SettingsContacts","SETTINGS_LABELS/LABEL_CONTACTS_NAME","contacts"),cb.prototype.onBuild=function(){Ob.data().contactsAutosave.subscribe(function(a){Ob.remote().saveSettings(Bb.emptyFunction,{ContactsAutosave:a?"1":"0"})})},Bb.addSettingsViewModel(db,"SettingsAccounts","SETTINGS_LABELS/LABEL_ACCOUNTS_NAME","accounts"),db.prototype.addNewAccount=function(){Hb.showScreenPopup(K)},db.prototype.deleteAccount=function(b){if(b&&b.deleteAccess()){this.accountForDeletion(null);var c=function(a){return b===a};b&&(this.accounts.remove(c),Ob.remote().accountDelete(function(b,c){zb.StorageResultType.Success===b&&c&&c.Result&&c.Reload?(Hb.routeOff(),Hb.setHash(Ob.link().root(),!0),Hb.routeOff(),h.defer(function(){a.location.reload()})):Ob.accountsAndIdentities()},b.email))}},Bb.addSettingsViewModel(eb,"SettingsIdentity","SETTINGS_LABELS/LABEL_IDENTITY_NAME","identity"),eb.prototype.onFocus=function(){if(!this.editor&&this.signatureDom()){var a=this,b=Ob.data().signature();this.editor=new l(a.signatureDom(),function(){Ob.data().signature((a.editor.isHtml()?":HTML:":"")+a.editor.getData())},function(){":HTML:"===b.substr(0,6)?a.editor.setHtml(b.substr(6),!1):a.editor.setPlain(b,!1)})}},eb.prototype.onBuild=function(){var a=this;h.delay(function(){var b=Ob.data(),c=Bb.settingsSaveHelperSimpleFunction(a.displayNameTrigger,a),d=Bb.settingsSaveHelperSimpleFunction(a.replyTrigger,a),e=Bb.settingsSaveHelperSimpleFunction(a.signatureTrigger,a);b.displayName.subscribe(function(a){Ob.remote().saveSettings(c,{DisplayName:a})}),b.replyTo.subscribe(function(a){Ob.remote().saveSettings(d,{ReplyTo:a})}),b.signature.subscribe(function(a){Ob.remote().saveSettings(e,{Signature:a})}),b.signatureToAll.subscribe(function(a){Ob.remote().saveSettings(null,{SignatureToAll:a?"1":"0"})})},50)},Bb.addSettingsViewModel(fb,"SettingsIdentities","SETTINGS_LABELS/LABEL_IDENTITIES_NAME","identities"),fb.prototype.addNewIdentity=function(){Hb.showScreenPopup(P)},fb.prototype.editIdentity=function(a){Hb.showScreenPopup(P,[a])},fb.prototype.deleteIdentity=function(a){if(a&&a.deleteAccess()){this.identityForDeletion(null);var b=function(b){return a===b};a&&(this.identities.remove(b),Ob.remote().identityDelete(function(){Ob.accountsAndIdentities()},a.id))}},fb.prototype.onFocus=function(){if(!this.editor&&this.signatureDom()){var a=this,b=Ob.data().signature();this.editor=new l(a.signatureDom(),function(){Ob.data().signature((a.editor.isHtml()?":HTML:":"")+a.editor.getData())},function(){":HTML:"===b.substr(0,6)?a.editor.setHtml(b.substr(6),!1):a.editor.setPlain(b,!1)})}},fb.prototype.onBuild=function(a){var b=this;a.on("click",".identity-item .e-action",function(){var a=c.dataFor(this);a&&b.editIdentity(a)}),h.delay(function(){var a=Ob.data(),c=Bb.settingsSaveHelperSimpleFunction(b.displayNameTrigger,b),d=Bb.settingsSaveHelperSimpleFunction(b.replyTrigger,b),e=Bb.settingsSaveHelperSimpleFunction(b.signatureTrigger,b);a.displayName.subscribe(function(a){Ob.remote().saveSettings(c,{DisplayName:a})}),a.replyTo.subscribe(function(a){Ob.remote().saveSettings(d,{ReplyTo:a})}),a.signature.subscribe(function(a){Ob.remote().saveSettings(e,{Signature:a})}),a.signatureToAll.subscribe(function(a){Ob.remote().saveSettings(null,{SignatureToAll:a?"1":"0"})})},50)},Bb.addSettingsViewModel(gb,"SettingsSecurity","SETTINGS_LABELS/LABEL_SECURITY_NAME","security"),gb.prototype.showSecret=function(){this.secreting(!0),Ob.remote().showTwoFactorSecret(this.onSecretResult)},gb.prototype.hideSecret=function(){this.viewSecret(""),this.viewBackupCodes(""),this.viewUrl("")},gb.prototype.createTwoFactor=function(){this.processing(!0),Ob.remote().createTwoFactor(this.onResult)},gb.prototype.enableTwoFactor=function(){this.processing(!0),Ob.remote().enableTwoFactor(this.onResult,this.viewEnable())},gb.prototype.testTwoFactor=function(){Hb.showScreenPopup(R)},gb.prototype.clearTwoFactor=function(){this.viewSecret(""),this.viewBackupCodes(""),this.viewUrl(""),this.clearing(!0),Ob.remote().clearTwoFactor(this.onResult)},gb.prototype.onShow=function(){this.viewSecret(""),this.viewBackupCodes(""),this.viewUrl("")},gb.prototype.onResult=function(a,b){if(this.processing(!1),this.clearing(!1),zb.StorageResultType.Success===a&&b&&b.Result?(this.viewUser(Bb.pString(b.Result.User)),this.viewEnable(!!b.Result.Enable),this.twoFactorStatus(!!b.Result.IsSet),this.viewSecret(Bb.pString(b.Result.Secret)),this.viewBackupCodes(Bb.pString(b.Result.BackupCodes).replace(/[\s]+/g," ")),this.viewUrl(Bb.pString(b.Result.Url))):(this.viewUser(""),this.viewEnable(!1),this.twoFactorStatus(!1),this.viewSecret(""),this.viewBackupCodes(""),this.viewUrl("")),this.bFirst){this.bFirst=!1;var c=this;this.viewEnable.subscribe(function(a){this.viewEnable.subs&&Ob.remote().enableTwoFactor(function(a,b){zb.StorageResultType.Success===a&&b&&b.Result||(c.viewEnable.subs=!1,c.viewEnable(!1),c.viewEnable.subs=!0)},a)},this)}},gb.prototype.onSecretResult=function(a,b){this.secreting(!1),zb.StorageResultType.Success===a&&b&&b.Result?(this.viewSecret(Bb.pString(b.Result.Secret)),this.viewUrl(Bb.pString(b.Result.Url))):(this.viewSecret(""),this.viewUrl(""))},gb.prototype.onBuild=function(){this.processing(!0),Ob.remote().getTwoFactor(this.onResult)},Bb.addSettingsViewModel(hb,"SettingsSocial","SETTINGS_LABELS/LABEL_SOCIAL_NAME","social"),Bb.addSettingsViewModel(ib,"SettingsChangePassword","SETTINGS_LABELS/LABEL_CHANGE_PASSWORD_NAME","change-password"),ib.prototype.onHide=function(){this.changeProcess(!1),this.currentPassword(""),this.newPassword(""),this.newPassword2(""),this.errorDescription(""),this.passwordMismatch(!1),this.currentPassword.error(!1)},ib.prototype.onChangePasswordResponse=function(a,b){this.changeProcess(!1),this.passwordMismatch(!1),this.errorDescription(""),this.currentPassword.error(!1),zb.StorageResultType.Success===a&&b&&b.Result?(this.currentPassword(""),this.newPassword(""),this.newPassword2(""),this.passwordUpdateSuccess(!0),this.currentPassword.error(!1)):(b&&zb.Notification.CurrentPasswordIncorrect===b.ErrorCode&&this.currentPassword.error(!0),this.passwordUpdateError(!0),this.errorDescription(Bb.getNotification(b&&b.ErrorCode?b.ErrorCode:zb.Notification.CouldNotSaveNewPassword)))},Bb.addSettingsViewModel(jb,"SettingsFolders","SETTINGS_LABELS/LABEL_FOLDERS_NAME","folders"),jb.prototype.folderEditOnEnter=function(a){var b=a?Bb.trim(a.nameForEdit()):"";""!==b&&a.name()!==b&&(Ob.local().set(zb.ClientSideKeyName.FoldersLashHash,""),Ob.data().foldersRenaming(!0),Ob.remote().folderRename(function(a,b){Ob.data().foldersRenaming(!1),zb.StorageResultType.Success===a&&b&&b.Result||Ob.data().foldersListError(b&&b.ErrorCode?Bb.getNotification(b.ErrorCode):Bb.i18n("NOTIFICATIONS/CANT_RENAME_FOLDER")),Ob.folders()},a.fullNameRaw,b),Ob.cache().removeFolderFromCacheList(a.fullNameRaw),a.name(b)),a.edited(!1)},jb.prototype.folderEditOnEsc=function(a){a&&a.edited(!1)},jb.prototype.onShow=function(){Ob.data().foldersListError("")},jb.prototype.createFolder=function(){Hb.showScreenPopup(F)},jb.prototype.systemFolder=function(){Hb.showScreenPopup(G)},jb.prototype.deleteFolder=function(a){if(a&&a.canBeDeleted()&&a.deleteAccess()&&0===a.privateMessageCountAll()){this.folderForDeletion(null);var b=function(c){return a===c?!0:(c.subFolders.remove(b),!1)};a&&(Ob.local().set(zb.ClientSideKeyName.FoldersLashHash,""),Ob.data().folderList.remove(b),Ob.data().foldersDeleting(!0),Ob.remote().folderDelete(function(a,b){Ob.data().foldersDeleting(!1),zb.StorageResultType.Success===a&&b&&b.Result||Ob.data().foldersListError(b&&b.ErrorCode?Bb.getNotification(b.ErrorCode):Bb.i18n("NOTIFICATIONS/CANT_DELETE_FOLDER")),Ob.folders()},a.fullNameRaw),Ob.cache().removeFolderFromCacheList(a.fullNameRaw))}else 0 0&&(c=this.messagesBodiesDom(),c&&(c.find(".rl-cache-class").each(function(){var c=b(this);d>c.data("rl-cache-count")&&(c.addClass("rl-cache-purge"),a++)}),a>0&&h.delay(function(){c.find(".rl-cache-purge").remove()},300)))},nb.prototype.populateDataOnStart=function(){mb.prototype.populateDataOnStart.call(this),this.accountEmail(Ob.settingsGet("Email")),this.accountIncLogin(Ob.settingsGet("IncLogin")),this.accountOutLogin(Ob.settingsGet("OutLogin")),this.projectHash(Ob.settingsGet("ProjectHash")),this.displayName(Ob.settingsGet("DisplayName")),this.replyTo(Ob.settingsGet("ReplyTo")),this.signature(Ob.settingsGet("Signature")),this.signatureToAll(!!Ob.settingsGet("SignatureToAll")),this.enableTwoFactor(!!Ob.settingsGet("EnableTwoFactor")),this.lastFoldersHash=Ob.local().get(zb.ClientSideKeyName.FoldersLashHash)||"",this.remoteSuggestions=!!Ob.settingsGet("RemoteSuggestions"),this.devEmail=Ob.settingsGet("DevEmail"),this.devLogin=Ob.settingsGet("DevLogin"),this.devPassword=Ob.settingsGet("DevPassword") +},nb.prototype.initUidNextAndNewMessages=function(b,c,d){if("INBOX"===b&&Bb.isNormal(c)&&""!==c){if(Bb.isArray(d)&&0 3)i(Ob.link().notificationMailIcon(),Ob.data().accountEmail(),Bb.i18n("MESSAGE_LIST/NEW_MESSAGE_NOTIFICATION",{COUNT:g}));else for(;g>f;f++)i(Ob.link().notificationMailIcon(),z.emailsToLine(z.initEmailsFromJson(d[f].From),!1),d[f].Subject)}Ob.cache().setFolderUidNext(b,c)}},nb.prototype.folderResponseParseRec=function(a,b){var c=0,d=0,e=null,f=null,g="",h=[],i=[];for(c=0,d=b.length;d>c;c++)e=b[c],e&&(g=e.FullNameRaw,f=Ob.cache().getFolderFromCacheList(g),f||(f=A.newInstanceFromJson(e),f&&(Ob.cache().setFolderToCacheList(g,f),Ob.cache().setFolderFullNameRaw(f.fullNameHash,g))),f&&(f.collapsed(!Bb.isFolderExpanded(f.fullNameHash)),e.Extended&&(e.Extended.Hash&&Ob.cache().setFolderHash(f.fullNameRaw,e.Extended.Hash),Bb.isNormal(e.Extended.MessageCount)&&f.messageCountAll(e.Extended.MessageCount),Bb.isNormal(e.Extended.MessageUnseenCount)&&f.messageCountUnread(e.Extended.MessageUnseenCount)),h=e.SubFolders,h&&"Collection/FolderCollection"===h["@Object"]&&h["@Collection"]&&Bb.isArray(h["@Collection"])&&f.subFolders(this.folderResponseParseRec(a,h["@Collection"])),i.push(f)));return i},nb.prototype.setFolders=function(a){var b=[],c=!1,d=Ob.data(),e=function(a){return""===a||yb.Values.UnuseOptionValue===a||null!==Ob.cache().getFolderFromCacheList(a)?a:""};a&&a.Result&&"Collection/FolderCollection"===a.Result["@Object"]&&a.Result["@Collection"]&&Bb.isArray(a.Result["@Collection"])&&(Bb.isUnd(a.Result.Namespace)||(d.namespace=a.Result.Namespace),this.threading(!!Ob.settingsGet("UseImapThread")&&a.Result.IsThreadsSupported&&!0),b=this.folderResponseParseRec(d.namespace,a.Result["@Collection"]),d.folderList(b),a.Result.SystemFolders&&""==""+Ob.settingsGet("SentFolder")+Ob.settingsGet("DraftFolder")+Ob.settingsGet("SpamFolder")+Ob.settingsGet("TrashFolder")+Ob.settingsGet("ArchiveFolder")+Ob.settingsGet("NullFolder")&&(Ob.settingsSet("SentFolder",a.Result.SystemFolders[2]||null),Ob.settingsSet("DraftFolder",a.Result.SystemFolders[3]||null),Ob.settingsSet("SpamFolder",a.Result.SystemFolders[4]||null),Ob.settingsSet("TrashFolder",a.Result.SystemFolders[5]||null),Ob.settingsSet("ArchiveFolder",a.Result.SystemFolders[12]||null),c=!0),d.sentFolder(e(Ob.settingsGet("SentFolder"))),d.draftFolder(e(Ob.settingsGet("DraftFolder"))),d.spamFolder(e(Ob.settingsGet("SpamFolder"))),d.trashFolder(e(Ob.settingsGet("TrashFolder"))),d.archiveFolder(e(Ob.settingsGet("ArchiveFolder"))),c&&Ob.remote().saveSystemFolders(Bb.emptyFunction,{SentFolder:d.sentFolder(),DraftFolder:d.draftFolder(),SpamFolder:d.spamFolder(),TrashFolder:d.trashFolder(),ArchiveFolder:d.archiveFolder(),NullFolder:"NullFolder"}),Ob.local().set(zb.ClientSideKeyName.FoldersLashHash,a.Result.FoldersHash))},nb.prototype.hideMessageBodies=function(){var a=this.messagesBodiesDom();a&&a.find(".b-text-part").hide()},nb.prototype.getNextFolderNames=function(a){a=Bb.isUnd(a)?!1:!!a;var b=[],c=10,d=f().unix(),e=d-300,g=[],i=function(b){h.each(b,function(b){b&&"INBOX"!==b.fullNameRaw&&b.selectable&&b.existen&&e>b.interval&&(!a||b.subScribed())&&g.push([b.interval,b.fullNameRaw]),b&&0 b[0]?1:0}),h.find(g,function(a){var e=Ob.cache().getFolderFromCacheList(a[1]);return e&&(e.interval=d,b.push(a[1])),c<=b.length}),h.uniq(b)},nb.prototype.removeMessagesFromList=function(a,b,c,d){c=Bb.isNormal(c)?c:"",d=Bb.isUnd(d)?!1:!!d,b=h.map(b,function(a){return Bb.pInt(a)});var e=0,f=Ob.data(),g=Ob.cache(),i=f.messageList(),j=Ob.cache().getFolderFromCacheList(a),k=""===c?null:g.getFolderFromCacheList(c||""),l=f.currentFolderFullNameRaw(),m=f.message(),n=l===a?h.filter(i,function(a){return a&&-1 0&&j.messageCountUnread(0<=j.messageCountUnread()-e?j.messageCountUnread()-e:0)),k&&(k.messageCountAll(k.messageCountAll()+b.length),e>0&&k.messageCountUnread(k.messageCountUnread()+e),k.actionBlink(!0)),0 ').hide().addClass("rl-cache-class"),g.data("rl-cache-count",++Eb.iMessageBodyCacheCount),Bb.isNormal(a.Result.Html)&&""!==a.Result.Html?(d=!0,g.html(a.Result.Html.toString()).addClass("b-text-part html")):Bb.isNormal(a.Result.Plain)&&""!==a.Result.Plain?(d=!1,j=a.Result.Plain.toString(),(n.isPgpSigned()||n.isPgpEncrypted())&&Ob.data().allowOpenPGP()&&Bb.isNormal(a.Result.PlainRaw)&&(n.plainRaw=Bb.pString(a.Result.PlainRaw),l=/---BEGIN PGP MESSAGE---/.test(n.plainRaw),l||(k=/-----BEGIN PGP SIGNED MESSAGE-----/.test(n.plainRaw)&&/-----BEGIN PGP SIGNATURE-----/.test(n.plainRaw)),Pb.empty(),k&&n.isPgpSigned()?j=Pb.append(b('').text(n.plainRaw)).html():l&&n.isPgpEncrypted()&&(j=Pb.append(b('').text(n.plainRaw)).html()),Pb.empty(),n.isPgpSigned(k),n.isPgpEncrypted(l)),g.html(j).addClass("b-text-part plain")):d=!1,n.isHtml(!!d),n.hasImages(!!e),n.pgpSignedVerifyStatus(zb.SignedVerifyStatus.None),n.pgpSignedVerifyUser(""),a.Result.Rtl&&(n.isRtl(!0),g.addClass("rtl-text-part")),n.body=g,n.body&&m.append(n.body),n.storeDataToDom(),f&&n.showInternalImages(!0),n.hasImages()&&this.showImages()&&n.showExternalImages(!0),this.purgeMessageBodyCacheThrottle()),this.messageActiveDom(n.body),this.hideMessageBodies(),n.body.show(),g&&Bb.initBlockquoteSwitcher(g)),Ob.cache().initMessageFlagsFromCache(n),n.unseen()&&Ob.setMessageSeen(n),Bb.windowResize())},nb.prototype.calculateMessageListHash=function(a){return h.map(a,function(a){return""+a.hash+"_"+a.threadsLen()+"_"+a.flagHash()}).join("|")},nb.prototype.setMessageList=function(a,b){if(a&&a.Result&&"Collection/MessageCollection"===a.Result["@Object"]&&a.Result["@Collection"]&&Bb.isArray(a.Result["@Collection"])){var c=Ob.data(),d=Ob.cache(),e=null,g=0,h=0,i=0,j=0,k=[],l=f().unix(),m=c.staticMessageList,n=null,o=null,p=null,q=0,r=!1;for(i=Bb.pInt(a.Result.MessageResultCount),j=Bb.pInt(a.Result.Offset),Bb.isNonEmptyArray(a.Result.LastCollapsedThreadUids)&&(e=a.Result.LastCollapsedThreadUids),p=Ob.cache().getFolderFromCacheList(Bb.isNormal(a.Result.Folder)?a.Result.Folder:""),p&&!b&&(p.interval=l,Ob.cache().setFolderHash(a.Result.Folder,a.Result.FolderHash),Bb.isNormal(a.Result.MessageCount)&&p.messageCountAll(a.Result.MessageCount),Bb.isNormal(a.Result.MessageUnseenCount)&&(Bb.pInt(p.messageCountUnread())!==Bb.pInt(a.Result.MessageUnseenCount)&&(r=!0),p.messageCountUnread(a.Result.MessageUnseenCount)),this.initUidNextAndNewMessages(p.fullNameRaw,a.Result.UidNext,a.Result.NewMessages)),r&&p&&Ob.cache().clearMessageFlagsFromCacheByFolder(p.fullNameRaw),g=0,h=a.Result["@Collection"].length;h>g;g++)n=a.Result["@Collection"][g],n&&"Object/Message"===n["@Object"]&&(o=m[g],o&&o.initByJson(n)||(o=z.newInstanceFromJson(n)),o&&(d.hasNewMessageAndRemoveFromCache(o.folderFullNameRaw,o.uid)&&5>=q&&(q++,o.newForAnimation(!0)),o.deleted(!1),b?Ob.cache().initMessageFlagsFromCache(o):Ob.cache().storeMessageFlagsToCache(o),o.lastInCollapsedThread(e&&-1 (new a.Date).getTime()-l),n&&i.oRequests[n]&&(i.oRequests[n].__aborted&&(e="abort"),i.oRequests[n]=null),i.defaultResponse(c,n,e,b,f,d)}),n&&0 0?(this.defaultRequest(a,"Message",{},null,"Message/"+Db.urlsafe_encode([b,c,Ob.data().projectHash(),Ob.data().threading()&&Ob.data().useThreads()?"1":"0"].join(String.fromCharCode(0))),["Message"]),!0):!1},pb.prototype.composeUploadExternals=function(a,b){this.defaultRequest(a,"ComposeUploadExternals",{Externals:b},999e3)},pb.prototype.folderInformation=function(a,b,c){var d=!0,e=Ob.cache(),f=[];Bb.isArray(c)&&0 l;l++)q.push({id:e[l][0],name:e[l][1],system:!1,seporator:!1,disabled:!1});for(o=!0,l=0,m=b.length;m>l;l++)n=b[l],(h?h.call(null,n):!0)&&(o&&0 l;l++)n=c[l],(n.subScribed()||!n.existen)&&(h?h.call(null,n):!0)&&(zb.FolderType.User===n.type()||!j||0 =5?e:20,e=320>=e?e:320,a.setInterval(function(){Ob.contactsSync()},6e4*e+5e3),h.delay(function(){Ob.contactsSync()},5e3),h.delay(function(){Ob.folderInformationMultiply(!0)},500),h.delay(function(){Ob.emailsPicsHashes(),Ob.remote().servicesPics(function(a,b){zb.StorageResultType.Success===a&&b&&b.Result&&Ob.cache().setServicesData(b.Result)})},2e3),Cb.runHook("rl-start-user-screens"),Ob.pub("rl.bootstart-user-screens"),Ob.settingsGet("AccountSignMe")&&a.navigator.registerProtocolHandler&&h.delay(function(){try{a.navigator.registerProtocolHandler("mailto",a.location.protocol+"//"+a.location.host+a.location.pathname+"?mailto&to=%s",""+(Ob.settingsGet("Title")||"RainLoop"))}catch(b){}Ob.settingsGet("MailToEmail")&&Ob.mailToHelper(Ob.settingsGet("MailToEmail"))},500)):(Hb.startScreens([tb]),Cb.runHook("rl-start-login-screens"),Ob.pub("rl.bootstart-login-screens")),a.SimplePace&&a.SimplePace.set(100),Eb.bMobileDevice||h.defer(function(){Bb.initLayoutResizer("#rl-left","#rl-right",zb.ClientSideKeyName.FolderListSize)})},this))):(c=Bb.pString(Ob.settingsGet("CustomLoginLink")),c?(Hb.routeOff(),Hb.setHash(Ob.link().root(),!0),Hb.routeOff(),h.defer(function(){a.location.href=c})):(Hb.hideLoading(),Hb.startScreens([tb]),Cb.runHook("rl-start-login-screens"),Ob.pub("rl.bootstart-login-screens"),a.SimplePace&&a.SimplePace.set(100))),f&&(a["rl_"+d+"_google_service"]=function(){Ob.data().googleActions(!0),Ob.socialUsers()}),g&&(a["rl_"+d+"_facebook_service"]=function(){Ob.data().facebookActions(!0),Ob.socialUsers()}),i&&(a["rl_"+d+"_twitter_service"]=function(){Ob.data().twitterActions(!0),Ob.socialUsers()}),Ob.sub("interval.1m",function(){Eb.momentTrigger(!Eb.momentTrigger())}),Cb.runHook("rl-start-screens"),Ob.pub("rl.bootstart-end")},Ob=new xb,Kb.addClass(Eb.bMobileDevice?"mobile":"no-mobile"),Lb.keydown(Bb.killCtrlAandS).keyup(Bb.killCtrlAandS),Lb.unload(function(){Eb.bUnload=!0}),Kb.on("click.dropdown.data-api",function(){Bb.detectDropdownVisibility()}),a.rl=a.rl||{},a.rl.addHook=Cb.addHook,a.rl.settingsGet=Cb.mainSettingsGet,a.rl.remoteRequest=Cb.remoteRequest,a.rl.pluginSettingsGet=Cb.settingsGet,a.rl.addSettingsViewModel=Bb.addSettingsViewModel,a.rl.createCommand=Bb.createCommand,a.rl.EmailModel=u,a.rl.Enums=zb,a.__RLBOOT=function(c){b(function(){a.rainloopTEMPLATES&&a.rainloopTEMPLATES[0]?(b("#rl-templates").html(a.rainloopTEMPLATES[0]),h.delay(function(){a.rainloopAppData={},a.rainloopI18N={},a.rainloopTEMPLATES={},Hb.setBoot(Ob).bootstart(),Kb.removeClass("no-js rl-booted-trigger").addClass("rl-booted")},50)):c(!1),a.__RLBOOT=null})},a.SimplePace&&a.SimplePace.add(10)}(window,jQuery,ko,crossroads,hasher,moment,Jua,_,ifvisible,key); \ No newline at end of file diff --git a/rainloop/v/0.0.0/static/js/boot.js b/rainloop/v/0.0.0/static/js/boot.js index 1c6b26edf..df0844cac 100644 --- a/rainloop/v/0.0.0/static/js/boot.js +++ b/rainloop/v/0.0.0/static/js/boot.js @@ -1,6 +1,6 @@ /*! See http://www.JSON.org/js.html */ var JSON;JSON||(JSON={}),function(){function str(a,b){var c,d,e,f,g=gap,h,i=b[a];i&&typeof i=="object"&&typeof i.toJSON=="function"&&(i=i.toJSON(a)),typeof rep=="function"&&(i=rep.call(b,a,i));switch(typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i)return"null";gap+=indent,h=[];if(Object.prototype.toString.apply(i)==="[object Array]"){f=i.length;for(c=0;c b.progress&&b.add(b.addSpeed)},500)},b.prototype.stopAddInterval=function(){a.clearInterval(this.addInterval),this.addInterval=0},b.prototype.build=function(){if(null===this.el){var a=document.querySelector("body");a&&(this.el=document.createElement("div"),this.el.className="simple-pace simple-pace-active",this.el.innerHTML=' ',a.firstChild?a.insertBefore(this.el,a.firstChild):a.appendChild(this.el))}return this.el},b.prototype.reset=function(){return this.progress=0,this.render()},b.prototype.update=function(b){var c=a.parseInt(b,10);return c>this.progress&&(this.progress=c,this.progress=100this.progress?0:this.progress),this.render()},b.prototype.add=function(b){return this.progress+=a.parseInt(b,10),this.progress=100 this.progress?0:this.progress,this.render()},b.prototype.setSpeed=function(a,b){this.addSpeed=a,this.stopProgress=b||100},b.prototype.render=function(){var b=this.build();b&&b.children&&b.children[0]&&b.children[0].setAttribute("style","width:"+this.progress+"%"),100!==this.progress||this.done?100>this.progress&&this.done?(this.done=!1,this.startAddInterval(),b.className=b.className.replace("simple-pace-inactive",""),b.className+=" simple-pace-inactive"):100>this.progress&&!this.done&&0===this.addInterval&&this.startAddInterval():(this.done=!0,this.stopAddInterval(),a.setTimeout(function(){b.className=b.className.replace("simple-pace-active",""),b.className+=" simple-pace-inactive"},500))},!a.SimplePace){var c=new b;a.SimplePace={sleep:function(){c.setSpeed(2,95)},set:function(a){c.update(a)},add:function(a){c.add(a)}}}}(window); -/*! RainLoop Top Driver v1.0 (c) 2013 RainLoop Team; Licensed under MIT */ +/*! RainLoop Top Driver v1.0 (c) 2013 RainLoop Team; Licensed under MIT */ !function(a,b){function c(){}c.prototype.s=a.sessionStorage,c.prototype.t=a.top||a,c.prototype.getHash=function(){var a=null;if(this.s)a=this.s.getItem("__rlA")||null;else if(this.t){var c=this.t.name&&b&&"{"===this.t.name.toString().substr(0,1)?b.parse(this.t.name.toString()):null;a=c?c.__rlA||null:null}return a},c.prototype.setHash=function(){var c=a.rainloopAppData,d=null;this.s?this.s.setItem("__rlA",c&&c.AuthAccountHash?c.AuthAccountHash:""):this.t&&b&&(d={},d.__rlA=c&&c.AuthAccountHash?c.AuthAccountHash:"",this.t.name=b.stringify(d))},c.prototype.clearHash=function(){this.s?this.s.setItem("__rlA",""):this.t&&(this.t.name="")},a._rlhh=new c,a.__rlah=function(){return a._rlhh?a._rlhh.getHash():null},a.__rlah_set=function(){a._rlhh&&a._rlhh.setHash()},a.__rlah_clear=function(){a._rlhh&&a._rlhh.clearHash()}}(window,window.JSON); \ No newline at end of file diff --git a/rainloop/v/0.0.0/static/js/libs.js b/rainloop/v/0.0.0/static/js/libs.js index 6515aced2..d77bf5154 100644 --- a/rainloop/v/0.0.0/static/js/libs.js +++ b/rainloop/v/0.0.0/static/js/libs.js @@ -1,42 +1,42 @@ -/* Modernizr 2.6.2 (Custom Build) | MIT & BSD - * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-svg-touch-shiv-cssclasses-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-fullscreen_api - */ +/* Modernizr 2.6.2 (Custom Build) | MIT & BSD + * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-svg-touch-shiv-cssclasses-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-fullscreen_api + */ ;window.Modernizr=function(a,b,c){function C(a){j.cssText=a}function D(a,b){return C(n.join(a+";")+(b||""))}function E(a,b){return typeof a===b}function F(a,b){return!!~(""+a).indexOf(b)}function G(a,b){for(var d in a){var e=a[d];if(!F(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function H(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:E(f,"function")?f.bind(d||b):f}return!1}function I(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return E(b,"string")||E(b,"undefined")?G(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),H(e,b,c))}function J(){e.input=function(c){for(var d=0,e=c.length;d ',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=E(e[d],"function"),E(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),A={}.hasOwnProperty,B;!E(A,"undefined")&&!E(A.call,"undefined")?B=function(a,b){return A.call(a,b)}:B=function(a,b){return b in a&&E(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return I("flexWrap")},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!I("indexedDB",a)},s.hashchange=function(){return z("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return C("background-color:rgba(150,255,150,.5)"),F(j.backgroundColor,"rgba")},s.hsla=function(){return C("background-color:hsla(120,40%,100%,.5)"),F(j.backgroundColor,"rgba")||F(j.backgroundColor,"hsla")},s.multiplebgs=function(){return C("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return I("backgroundSize")},s.borderimage=function(){return I("borderImage")},s.borderradius=function(){return I("borderRadius")},s.boxshadow=function(){return I("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return D("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return I("animationName")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return C((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),F(j.backgroundImage,"gradient")},s.cssreflections=function(){return I("boxReflect")},s.csstransforms=function(){return!!I("transform")},s.csstransforms3d=function(){var a=!!I("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return I("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect};for(var K in s)B(s,K)&&(x=K.toLowerCase(),e[x]=s[K](),v.push((e[x]?"":"no-")+x));return e.input||J(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)B(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},C(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e ",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.hasEvent=z,e.testProp=function(a){return G([a])},e.testAllProps=I,e.testStyles=y,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),Modernizr.addTest("fullscreen",function(){for(var a=0;a u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a=j.keys(n),u=0,i=a.length;i>u;u++)if(t.call(e,n[a[u]],a[u],n)===r)return};j.map=j.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e.push(t.call(r,n,u,i))}),e)};var E="Reduce of empty array with no initial value";j.reduce=j.foldl=j.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=j.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(E);return r},j.reduceRight=j.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=j.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=j.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(E);return r},j.find=j.detect=function(n,t,r){var e;return O(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},j.filter=j.select=function(n,t,r){var e=[];return null==n?e:g&&n.filter===g?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&e.push(n)}),e)},j.reject=function(n,t,r){return j.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},j.every=j.all=function(n,t,e){t||(t=j.identity);var u=!0;return null==n?u:d&&n.every===d?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var O=j.some=j.any=function(n,t,e){t||(t=j.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};j.contains=j.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:O(n,function(n){return n===t})},j.invoke=function(n,t){var r=o.call(arguments,2),e=j.isFunction(t);return j.map(n,function(n){return(e?t:n[t]).apply(n,r)})},j.pluck=function(n,t){return j.map(n,function(n){return n[t]})},j.where=function(n,t,r){return j.isEmpty(t)?r?void 0:[]:j[r?"find":"filter"](n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},j.findWhere=function(n,t){return j.where(n,t,!0)},j.max=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.max.apply(Math,n);if(!t&&j.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>e.computed&&(e={value:n,computed:a})}),e.value},j.min=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.min.apply(Math,n);if(!t&&j.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={},i=null==r?j.identity:k(r);return A(t,function(r,a){var o=i.call(e,r,a,t);n(u,o,r)}),u}};j.groupBy=F(function(n,t,r){(j.has(n,t)?n[t]:n[t]=[]).push(r)}),j.indexBy=F(function(n,t,r){n[t]=r}),j.countBy=F(function(n,t){j.has(n,t)?n[t]++:n[t]=1}),j.sortedIndex=function(n,t,r,e){r=null==r?j.identity:k(r);for(var u=r.call(e,t),i=0,a=n.length;a>i;){var o=i+a>>>1;r.call(e,n[o])=0})})},j.difference=function(n){var t=c.apply(e,o.call(arguments,1));return j.filter(n,function(n){return!j.contains(t,n)})},j.zip=function(){for(var n=j.max(j.pluck(arguments,"length").concat(0)),t=new Array(n),r=0;n>r;r++)t[r]=j.pluck(arguments,""+r);return t},j.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},j.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=j.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},j.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},j.range=function(n,t,r){arguments.length<=1&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=new Array(e);e>u;)i[u++]=n,n+=r;return i};var R=function(){};j.bind=function(n,t){var r,e;if(_&&n.bind===_)return _.apply(n,o.call(arguments,1));if(!j.isFunction(n))throw new TypeError;return r=o.call(arguments,2),e=function(){if(!(this instanceof e))return n.apply(t,r.concat(o.call(arguments)));R.prototype=n.prototype;var u=new R;R.prototype=null;var i=n.apply(u,r.concat(o.call(arguments)));return Object(i)===i?i:u}},j.partial=function(n){var t=o.call(arguments,1);return function(){return n.apply(this,t.concat(o.call(arguments)))}},j.bindAll=function(n){var t=o.call(arguments,1);if(0===t.length)throw new Error("bindAll must be passed function names");return A(t,function(t){n[t]=j.bind(n[t],n)}),n},j.memoize=function(n,t){var r={};return t||(t=j.identity),function(){var e=t.apply(this,arguments);return j.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},j.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},j.defer=function(n){return j.delay.apply(j,[n,1].concat(o.call(arguments,1)))},j.throttle=function(n,t,r){var e,u,i,a=null,o=0;r||(r={});var c=function(){o=r.leading===!1?0:new Date,a=null,i=n.apply(e,u)};return function(){var l=new Date;o||r.leading!==!1||(o=l);var f=t-(l-o);return e=this,u=arguments,0>=f?(clearTimeout(a),a=null,o=l,i=n.apply(e,u)):a||r.trailing===!1||(a=setTimeout(c,f)),i}},j.debounce=function(n,t,r){var e,u,i,a,o;return function(){i=this,u=arguments,a=new Date;var c=function(){var l=new Date-a;t>l?e=setTimeout(c,t-l):(e=null,r||(o=n.apply(i,u)))},l=r&&!e;return e||(e=setTimeout(c,t)),l&&(o=n.apply(i,u)),o}},j.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},j.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},j.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},j.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},j.keys=w||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)j.has(n,r)&&t.push(r);return t},j.values=function(n){for(var t=j.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},j.pairs=function(n){for(var t=j.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},j.invert=function(n){for(var t={},r=j.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},j.functions=j.methods=function(n){var t=[];for(var r in n)j.isFunction(n[r])&&t.push(r);return t.sort()},j.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},j.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},j.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)j.contains(r,u)||(t[u]=n[u]);return t},j.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]===void 0&&(n[r]=t[r])}),n},j.clone=function(n){return j.isObject(n)?j.isArray(n)?n.slice():j.extend({},n):n},j.tap=function(n,t){return t(n),n};var S=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof j&&(n=n._wrapped),t instanceof j&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==String(t);case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;var a=n.constructor,o=t.constructor;if(a!==o&&!(j.isFunction(a)&&a instanceof a&&j.isFunction(o)&&o instanceof o))return!1;r.push(n),e.push(t);var c=0,f=!0;if("[object Array]"==u){if(c=n.length,f=c==t.length)for(;c--&&(f=S(n[c],t[c],r,e)););}else{for(var s in n)if(j.has(n,s)&&(c++,!(f=j.has(t,s)&&S(n[s],t[s],r,e))))break;if(f){for(s in t)if(j.has(t,s)&&!c--)break;f=!c}}return r.pop(),e.pop(),f};j.isEqual=function(n,t){return S(n,t,[],[])},j.isEmpty=function(n){if(null==n)return!0;if(j.isArray(n)||j.isString(n))return 0===n.length;for(var t in n)if(j.has(n,t))return!1;return!0},j.isElement=function(n){return!(!n||1!==n.nodeType)},j.isArray=x||function(n){return"[object Array]"==l.call(n)},j.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){j["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),j.isArguments(arguments)||(j.isArguments=function(n){return!(!n||!j.has(n,"callee"))}),"function"!=typeof/./&&(j.isFunction=function(n){return"function"==typeof n}),j.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},j.isNaN=function(n){return j.isNumber(n)&&n!=+n},j.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},j.isNull=function(n){return null===n},j.isUndefined=function(n){return n===void 0},j.has=function(n,t){return f.call(n,t)},j.noConflict=function(){return n._=t,this},j.identity=function(n){return n},j.times=function(n,t,r){for(var e=Array(Math.max(0,n)),u=0;n>u;u++)e[u]=t.call(r,u);return e},j.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))};var I={escape:{"&":"&","<":"<",">":">",'"':""","'":"'"}};I.unescape=j.invert(I.escape);var T={escape:new RegExp("["+j.keys(I.escape).join("")+"]","g"),unescape:new RegExp("("+j.keys(I.unescape).join("|")+")","g")};j.each(["escape","unescape"],function(n){j[n]=function(t){return null==t?"":(""+t).replace(T[n],function(t){return I[n][t]})}}),j.result=function(n,t){if(null==n)return void 0;var r=n[t];return j.isFunction(r)?r.call(n):r},j.mixin=function(n){A(j.functions(n),function(t){var r=j[t]=n[t];j.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),z.call(this,r.apply(j,n))}})};var N=0;j.uniqueId=function(n){var t=++N+"";return n?n+t:t},j.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var q=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\t|\u2028|\u2029/g;j.template=function(n,t,r){var e;r=j.defaults({},r,j.templateSettings);var u=new RegExp([(r.escape||q).source,(r.interpolate||q).source,(r.evaluate||q).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(D,function(n){return"\\"+B[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=new Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,j);var c=function(n){return e.call(this,n,j)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},j.chain=function(n){return j(n).chain()};var z=function(n){return this._chain?j(n).chain():n};j.mixin(j),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];j.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],z.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];j.prototype[n]=function(){return z.call(this,t.apply(this._wrapped,arguments))}}),j.extend(j.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this); -/*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ -!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.1",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h; -if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML=" a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h
]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/\s*$/g,rb={option:[1,""],legend:[1,""],area:[1,""],param:[1,""],thead:[1," ","
"],tr:[2,"","
"],col:[2,""],td:[3,"
"," "],_default:k.htmlSerialize?[0,"",""]:[1,"X
"," ",""]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1>$2>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?"