diff --git a/dev/App/User.js b/dev/App/User.js index 2509c1d8d..1a876b0d6 100644 --- a/dev/App/User.js +++ b/dev/App/User.js @@ -1315,26 +1315,6 @@ bTwitter = Settings.settingsGet('AllowTwitterSocial') ; -// Utils.initOnStartOrLangChange(function () { -// -// $.extend(true, $.magnificPopup.defaults, { -// 'tClose': Utils.i18n('PREVIEW_POPUP/CLOSE'), -// 'tLoading': Utils.i18n('PREVIEW_POPUP/LOADING'), -// 'gallery': { -// 'tPrev': Utils.i18n('PREVIEW_POPUP/GALLERY_PREV'), -// 'tNext': Utils.i18n('PREVIEW_POPUP/GALLERY_NEXT'), -// 'tCounter': Utils.i18n('PREVIEW_POPUP/GALLERY_COUNTER') -// }, -// 'image': { -// 'tError': Utils.i18n('PREVIEW_POPUP/IMAGE_ERROR') -// }, -// 'ajax': { -// 'tError': Utils.i18n('PREVIEW_POPUP/AJAX_ERROR') -// } -// }); -// -// }, this); - if (SimplePace) { SimplePace.set(70); @@ -1359,18 +1339,29 @@ { if ($LAB && window.crypto && window.crypto.getRandomValues && Settings.capa(Enums.Capa.OpenPGP)) { - $LAB.script(window.openpgp ? '' : Links.openPgpJs()).wait(function () { - if (window.openpgp) - { - Data.openpgp = window.openpgp; - Data.openpgpKeyring = new window.openpgp.Keyring(); - Data.capaOpenPGP(true); + var fOpenpgpCallback = function (openpgp) { + Data.openpgp = openpgp; + Data.openpgpKeyring = new openpgp.Keyring(); + Data.capaOpenPGP(true); - Events.pub('openpgp.init'); + Events.pub('openpgp.init'); - self.reloadOpenPgpKeys(); - } - }); + self.reloadOpenPgpKeys(); + }; + + if (window.openpgp) + { + fOpenpgpCallback(window.openpgp); + } + else + { + $LAB.script(Links.openPgpJs()).wait(function () { + if (window.openpgp) + { + fOpenpgpCallback(window.openpgp); + } + }); + } } else { diff --git a/dev/Common/Enums.js b/dev/Common/Enums.js index d2e5cffba..29db43cd7 100644 --- a/dev/Common/Enums.js +++ b/dev/Common/Enums.js @@ -52,6 +52,7 @@ 'Themes': 'THEMES', 'UserBackground': 'USER_BACKGROUND', 'Sieve': 'SIEVE', + 'AttachmentThumbnails': 'ATTACHMENT_THUMBNAILS', 'AdditionalAccounts': 'ADDITIONAL_ACCOUNTS', 'AdditionalIdentities': 'ADDITIONAL_IDENTITIES' }; @@ -304,7 +305,7 @@ 'EqualTo': 'EqualTo', 'NotEqualTo': 'NotEqualTo' }; - + /** * @enum {string} */ diff --git a/dev/Common/Mime.js b/dev/Common/Mime.js new file mode 100644 index 000000000..a29e3ae36 --- /dev/null +++ b/dev/Common/Mime.js @@ -0,0 +1,168 @@ +(function () { + + 'use strict'; + + module.exports = { + + 'eml' : 'message/rfc822', + 'mime' : 'message/rfc822', + 'txt' : 'text/plain', + 'text' : 'text/plain', + 'def' : 'text/plain', + 'list' : 'text/plain', + 'in' : 'text/plain', + 'ini' : 'text/plain', + 'log' : 'text/plain', + 'sql' : 'text/plain', + 'cfg' : 'text/plain', + 'conf' : 'text/plain', + 'asc' : 'text/plain', + 'rtx' : 'text/richtext', + 'vcard' : 'text/vcard', + 'vcf' : 'text/vcard', + 'htm' : 'text/html', + 'html' : 'text/html', + 'csv' : 'text/csv', + 'ics' : 'text/calendar', + 'ifb' : 'text/calendar', + 'xml' : 'text/xml', + 'json' : 'application/json', + 'swf' : 'application/x-shockwave-flash', + 'hlp' : 'application/winhlp', + 'wgt' : 'application/widget', + 'chm' : 'application/vnd.ms-htmlhelp', + 'p10' : 'application/pkcs10', + 'p7c' : 'application/pkcs7-mime', + 'p7m' : 'application/pkcs7-mime', + 'p7s' : 'application/pkcs7-signature', + 'torrent' : 'application/x-bittorrent', + + // scripts + 'js' : 'application/javascript', + 'pl' : 'text/perl', + 'css' : 'text/css', + 'asp' : 'text/asp', + 'php' : 'application/x-httpd-php', + 'php3' : 'application/x-httpd-php', + 'php4' : 'application/x-httpd-php', + 'php5' : 'application/x-httpd-php', + 'phtml' : 'application/x-httpd-php', + + // images + 'png' : 'image/png', + 'jpg' : 'image/jpeg', + 'jpeg' : 'image/jpeg', + 'jpe' : 'image/jpeg', + 'jfif' : 'image/jpeg', + 'gif' : 'image/gif', + 'bmp' : 'image/bmp', + 'cgm' : 'image/cgm', + 'ief' : 'image/ief', + 'ico' : 'image/x-icon', + 'tif' : 'image/tiff', + 'tiff' : 'image/tiff', + 'svg' : 'image/svg+xml', + 'svgz' : 'image/svg+xml', + 'djv' : 'image/vnd.djvu', + 'djvu' : 'image/vnd.djvu', + 'webp' : 'image/webp', + + // archives + 'zip' : 'application/zip', + '7z' : 'application/x-7z-compressed', + 'rar' : 'application/x-rar-compressed', + 'exe' : 'application/x-msdownload', + 'dll' : 'application/x-msdownload', + 'scr' : 'application/x-msdownload', + 'com' : 'application/x-msdownload', + 'bat' : 'application/x-msdownload', + 'msi' : 'application/x-msdownload', + 'cab' : 'application/vnd.ms-cab-compressed', + 'gz' : 'application/x-gzip', + 'tgz' : 'application/x-gzip', + 'bz' : 'application/x-bzip', + 'bz2' : 'application/x-bzip2', + 'deb' : 'application/x-debian-package', + + // fonts + 'psf' : 'application/x-font-linux-psf', + 'otf' : 'application/x-font-otf', + 'pcf' : 'application/x-font-pcf', + 'snf' : 'application/x-font-snf', + 'ttf' : 'application/x-font-ttf', + 'ttc' : 'application/x-font-ttf', + + // audio + 'mp3' : 'audio/mpeg', + 'amr' : 'audio/amr', + 'aac' : 'audio/x-aac', + 'aif' : 'audio/x-aiff', + 'aifc' : 'audio/x-aiff', + 'aiff' : 'audio/x-aiff', + 'wav' : 'audio/x-wav', + 'wma' : 'audio/x-ms-wma', + 'wax' : 'audio/x-ms-wax', + 'midi' : 'audio/midi', + 'mp4a' : 'audio/mp4', + 'ogg' : 'audio/ogg', + 'weba' : 'audio/webm', + 'ra' : 'audio/x-pn-realaudio', + 'ram' : 'audio/x-pn-realaudio', + 'rmp' : 'audio/x-pn-realaudio-plugin', + 'm3u' : 'audio/x-mpegurl', + + // video + 'flv' : 'video/x-flv', + 'qt' : 'video/quicktime', + 'mov' : 'video/quicktime', + 'wmv' : 'video/windows-media', + 'avi' : 'video/x-msvideo', + 'mpg' : 'video/mpeg', + 'mpeg' : 'video/mpeg', + 'mpe' : 'video/mpeg', + 'm1v' : 'video/mpeg', + 'm2v' : 'video/mpeg', + '3gp' : 'video/3gpp', + '3g2' : 'video/3gpp2', + 'h261' : 'video/h261', + 'h263' : 'video/h263', + 'h264' : 'video/h264', + 'jpgv' : 'video/jpgv', + 'mp4' : 'video/mp4', + 'mp4v' : 'video/mp4', + 'mpg4' : 'video/mp4', + 'ogv' : 'video/ogg', + 'webm' : 'video/webm', + 'm4v' : 'video/x-m4v', + 'asf' : 'video/x-ms-asf', + 'asx' : 'video/x-ms-asf', + 'wm' : 'video/x-ms-wm', + 'wmx' : 'video/x-ms-wmx', + 'wvx' : 'video/x-ms-wvx', + 'movie' : 'video/x-sgi-movie', + + // adobe + 'pdf' : 'application/pdf', + 'psd' : 'image/vnd.adobe.photoshop', + 'ai' : 'application/postscript', + 'eps' : 'application/postscript', + 'ps' : 'application/postscript', + + // ms office + 'doc' : 'application/msword', + 'dot' : 'application/msword', + 'rtf' : 'application/rtf', + 'xls' : 'application/vnd.ms-excel', + 'ppt' : 'application/vnd.ms-powerpoint', + 'docx' : 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'xlsx' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'dotx' : 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'pptx' : 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + + // open office + 'odt' : 'application/vnd.oasis.opendocument.text', + 'ods' : 'application/vnd.oasis.opendocument.spreadsheet' + + }; + +}()); diff --git a/dev/Common/Utils.js b/dev/Common/Utils.js index 178d8d8f4..2a12a8b31 100644 --- a/dev/Common/Utils.js +++ b/dev/Common/Utils.js @@ -15,6 +15,8 @@ Autolinker = require('Autolinker'), JSEncrypt = require('JSEncrypt'), + Mime = require('Common/Mime'), + Enums = require('Common/Enums'), Consts = require('Common/Consts'), Globals = require('Common/Globals') @@ -1060,6 +1062,7 @@ oData.capaAdditionalIdentities = ko.observable(false); oData.capaGravatar = ko.observable(false); oData.capaSieve = ko.observable(false); + oData.capaAttachmentThumbnails = ko.observable(false); oData.determineUserLanguage = ko.observable(false); oData.determineUserDomain = ko.observable(false); @@ -1256,7 +1259,7 @@ Utils.draggablePlace = function () { return $('
' + - ' ' + + ' ' + '
').appendTo('#rl-hidden'); }; @@ -2029,6 +2032,45 @@ $('#rl-head-viewport').attr('content', aContent.join(', ')); }; + /** + * @param {string} sFileName + * @return {string} + */ + Utils.getFileExtension = function (sFileName) + { + sFileName = Utils.trim(sFileName).toLowerCase(); + + var sResult = sFileName.split('.').pop(); + return (sResult === sFileName) ? '' : sResult; + }; + + /** + * @param {string} sFileName + * @return {string} + */ + Utils.mimeContentType = function (sFileName) + { + var + sExt = '', + sResult = 'application/octet-stream' + ; + + sFileName = Utils.trim(sFileName).toLowerCase(); + + if ('winmail.dat' === sFileName) + { + return 'application/ms-tnef'; + } + + sExt = Utils.getFileExtension(sFileName); + if (sExt && 0 < sExt.length && !Utils.isUnd(Mime[sExt])) + { + sResult = Mime[sExt]; + } + + return sResult; + }; + /** * @param {mixed} mPropOrValue * @param {mixed} mValue diff --git a/dev/Model/Attachment.js b/dev/Model/Attachment.js index 9d4524f50..00ebb212d 100644 --- a/dev/Model/Attachment.js +++ b/dev/Model/Attachment.js @@ -167,13 +167,21 @@ return Links.attachmentPreview(this.download); }; + /** + * @return {string} + */ + AttachmentModel.prototype.linkThumbnail = function () + { + return this.hasThumbnail() ? Links.attachmentThumbnailPreview(this.download) : ''; + }; + /** * @return {string} */ AttachmentModel.prototype.linkThumbnailPreviewStyle = function () { - return !this.hasThumbnail() ? '' : - 'background:url(' + Links.attachmentThumbnailPreview(this.download) + ')'; + var sLink = this.linkThumbnail(); + return '' === sLink ? '' : 'background:url(' + sLink + ')'; }; /** @@ -211,7 +219,7 @@ sResult = this.linkFramed(); break; } - + return sResult; }; @@ -253,10 +261,14 @@ return true; }; - AttachmentModel.prototype.iconClass = function () + /** + * @param {string} sMimeType + * @returns {string} + */ + AttachmentModel.staticIconClassHelper = function (sMimeType) { var - aParts = this.mimeType.toLocaleString().split('/'), + aParts = sMimeType.toLocaleString().split('/'), sClass = 'icon-file' ; @@ -333,6 +345,14 @@ return sClass; }; + /** + * @returns {string} + */ + AttachmentModel.prototype.iconClass = function () + { + return AttachmentModel.staticIconClassHelper(this.mimeType); + }; + module.exports = AttachmentModel; }()); \ No newline at end of file diff --git a/dev/Model/ComposeAttachment.js b/dev/Model/ComposeAttachment.js index 232be7af5..caae27a9b 100644 --- a/dev/Model/ComposeAttachment.js +++ b/dev/Model/ComposeAttachment.js @@ -9,6 +9,8 @@ Utils = require('Common/Utils'), + AttachmentModel = require('Model/Attachment'), + AbstractModel = require('Knoin/AbstractModel') ; @@ -37,17 +39,37 @@ this.size = ko.observable(Utils.isUnd(nSize) ? null : nSize); this.tempName = ko.observable(''); - this.progress = ko.observable(''); + this.progress = ko.observable(0); this.error = ko.observable(''); this.waiting = ko.observable(true); this.uploading = ko.observable(false); this.enabled = ko.observable(true); + this.complete = ko.observable(false); + + this.progressText = ko.computed(function () { + var iP = this.progress(); + return 0 === iP ? '' : '' + (99 === iP ? 100 : iP) + '%'; + }, this); + + this.progressStyle = ko.computed(function () { + var iP = this.progress(); + return 0 === iP ? '' : 'width:' + (99 === iP ? 100 : iP) + '%'; + }, this); + + this.title = ko.computed(function () { + var sError = this.error(); + return '' !== sError ? sError : this.fileName(); + }, this); this.friendlySize = ko.computed(function () { var mSize = this.size(); return null === mSize ? '' : Utils.friendlySize(this.size()); }, this); + this.mimeType = ko.computed(function () { + return Utils.mimeContentType(this.fileName()); + }, this); + this.regDisposables([this.friendlySize]); } @@ -63,6 +85,7 @@ /** * @param {AjaxJsonComposeAttachment} oJsonAttachment + * @return {boolean} */ ComposeAttachmentModel.prototype.initByUploadJson = function (oJsonAttachment) { @@ -80,6 +103,15 @@ return bResult; }; + /** + * @return {string} + */ + ComposeAttachmentModel.prototype.iconClass = function () + { + return AttachmentModel.staticIconClassHelper(this.mimeType()); + }; + + module.exports = ComposeAttachmentModel; }()); \ No newline at end of file diff --git a/dev/Screen/User/MailBox.js b/dev/Screen/User/MailBox.js index 74e4b31ec..30968132d 100644 --- a/dev/Screen/User/MailBox.js +++ b/dev/Screen/User/MailBox.js @@ -106,6 +106,7 @@ ; Globals.$html.toggleClass('rl-no-preview-pane', Enums.Layout.NoPreview === Data.layout()); + Globals.$html.toggleClass('rl-bottom-preview-pane', Enums.Layout.BottomPreview === Data.layout()); Data.folderList.subscribe(fResizeFunction); Data.messageList.subscribe(fResizeFunction); @@ -113,6 +114,7 @@ Data.layout.subscribe(function (nValue) { Globals.$html.toggleClass('rl-no-preview-pane', Enums.Layout.NoPreview === nValue); + Globals.$html.toggleClass('rl-bottom-preview-pane', Enums.Layout.BottomPreview === nValue); }); Events.sub('mailbox.inbox-unread-count', function (nCount) { diff --git a/dev/Settings/Admin/General.js b/dev/Settings/Admin/General.js index e1b49c96b..90024fdec 100644 --- a/dev/Settings/Admin/General.js +++ b/dev/Settings/Admin/General.js @@ -32,6 +32,7 @@ this.capaGravatar = Data.capaGravatar; this.capaAdditionalAccounts = Data.capaAdditionalAccounts; this.capaAdditionalIdentities = Data.capaAdditionalIdentities; + this.capaAttachmentThumbnails = Data.capaAttachmentThumbnails; this.weakPassword = Data.weakPassword; @@ -114,6 +115,12 @@ }); }); + self.capaAttachmentThumbnails.subscribe(function (bValue) { + Remote.saveAdminConfig(null, { + 'CapaAttachmentThumbnails': bValue ? '1' : '0' + }); + }); + self.capaThemes.subscribe(function (bValue) { Remote.saveAdminConfig(null, { 'CapaThemes': bValue ? '1' : '0' diff --git a/dev/Settings/User/General.js b/dev/Settings/User/General.js index fdcd69b0a..547e0c534 100644 --- a/dev/Settings/User/General.js +++ b/dev/Settings/User/General.js @@ -36,13 +36,6 @@ this.useCheckboxesInList = Data.useCheckboxesInList; this.allowLanguagesOnSettings = Data.allowLanguagesOnSettings; - this.usePreviewPaneCheckbox = ko.computed({ - read: this.usePreviewPane, - write: function (bValue) { - this.layout(bValue ? Enums.Layout.SidePreview : Enums.Layout.NoPreview); - } - }, this); - this.isDesktopNotificationsSupported = ko.computed(function () { return Enums.DesktopNotifications.NotSupported !== Data.desktopNotificationsPermisions(); }); @@ -60,6 +53,7 @@ this.mppTrigger = ko.observable(Enums.SaveSettingsStep.Idle); this.editorDefaultTypeTrigger = ko.observable(Enums.SaveSettingsStep.Idle); + this.layoutTrigger = ko.observable(Enums.SaveSettingsStep.Idle); this.isAnimationSupported = Globals.bAnimationSupported; @@ -72,12 +66,16 @@ {'id': Enums.EditorDefaultType.PlainForced, 'name': Utils.i18n('SETTINGS_GENERAL/LABEL_EDITOR_PLAIN_FORCED')} ]; }, this); - } - GeneralUserSettings.prototype.toggleLayout = function () - { - this.layout(Enums.Layout.NoPreview === this.layout() ? Enums.Layout.SidePreview : Enums.Layout.NoPreview); - }; + this.layoutTypes = ko.computed(function () { + Globals.langChangeTrigger(); + return [ + {'id': Enums.Layout.NoPreview, 'name': Utils.i18n('SETTINGS_GENERAL/LABEL_LAYOUT_NO_SPLIT')}, + {'id': Enums.Layout.SidePreview, 'name': Utils.i18n('SETTINGS_GENERAL/LABEL_LAYOUT_VERTICAL_SPLIT')}, + {'id': Enums.Layout.BottomPreview, 'name': Utils.i18n('SETTINGS_GENERAL/LABEL_LAYOUT_HORIZONTAL_SPLIT')} + ]; + }, this); + } GeneralUserSettings.prototype.onBuild = function () { @@ -88,6 +86,7 @@ var f0 = Utils.settingsSaveHelperSimpleFunction(self.editorDefaultTypeTrigger, self), f1 = Utils.settingsSaveHelperSimpleFunction(self.mppTrigger, self), + f2 = Utils.settingsSaveHelperSimpleFunction(self.layoutTrigger, self), fReloadLanguageHelper = function (iSaveSettingsStep) { return function() { self.languageTrigger(iSaveSettingsStep); @@ -164,7 +163,7 @@ Data.messageList([]); - Remote.saveSettings(null, { + Remote.saveSettings(f2, { 'Layout': nValue }); }); diff --git a/dev/Storage/AbstractData.js b/dev/Storage/AbstractData.js index 7add1a6d5..bd3148ef4 100644 --- a/dev/Storage/AbstractData.js +++ b/dev/Storage/AbstractData.js @@ -45,6 +45,7 @@ this.capaAdditionalAccounts(Settings.capa(Enums.Capa.AdditionalAccounts)); this.capaAdditionalIdentities(Settings.capa(Enums.Capa.AdditionalIdentities)); this.capaGravatar(Settings.capa(Enums.Capa.Gravatar)); + this.capaAttachmentThumbnails(Settings.capa(Enums.Capa.AttachmentThumbnails)); this.capaSieve(Settings.capa(Enums.Capa.Sieve)); this.determineUserLanguage(!!Settings.settingsGet('DetermineUserLanguage')); this.determineUserDomain(!!Settings.settingsGet('DetermineUserDomain')); @@ -74,6 +75,7 @@ { this.layout(mLayout); } + this.facebookSupported(!!Settings.settingsGet('SupportedFacebookSocial')); this.facebookEnable(!!Settings.settingsGet('AllowFacebookSocial')); this.facebookAppID(Settings.settingsGet('FacebookAppID')); diff --git a/dev/Styles/Compose.less b/dev/Styles/Compose.less index be59d8f7a..cd609d643 100644 --- a/dev/Styles/Compose.less +++ b/dev/Styles/Compose.less @@ -12,8 +12,158 @@ } } - .textAreaParent { + .textAreaParent, .attachmentAreaParent { overflow: hidden; + position: relative; + } + + .attachmentAreaParent { + padding: 10px 10px 6px 10px; + background: #ddd; + border-top: 1px solid #ccc; + + overflow-y: auto; + } + + .attachmentAreaParent { + + .no-attachments-desc { + padding: 50px 10px; + text-align: center; + font-size: 24px; + color: #666; + text-shadow: 0 1px 0 #fff; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + } + + .attachmentList { + + margin: 0; + padding: 10px; + + .attachmentItem { + + display: inline-block; + margin: 3px 6px;; + max-width: 200px; + min-width: 60px; + overflow: hidden; + /*cursor: pointer;*/ + list-style: none; + line-height: 24px; + border: 0; + background-color: #fff; + box-shadow: 0 1px 5px #ccc; + box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2); + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.04), 0 1px 5px rgba(0, 0, 0, 0.1); + + border-radius: 2px; + + &.waiting { + opacity: 0.6; + } + + &.error { + .attachmentIcon, .attachmentSize, .attachmentName { + color: red; + } + } + + .attachmentIconParent { + + position: relative; + + height: 56px; + width: 60px; + + background: none; + + .iconPreview, .iconBG, .iconMain, .iconProgress { + position: absolute; + top: 0; + left: 0; + + display: inline-block; + width: 100%; + height: 100%; + } + + .iconProgress { + background: #eee; + width: 0%; + } + + .iconBG { + font-size: 18px; + text-align: center; + color: #999; + font-weight: bold; + line-height: 55px; + + text-shadow: 0 1px 0 #FFF; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.8); + } + + .iconPreview { + display: none; + + background: #555; + background-image: none; + background: rgba(0, 0, 0, .5) !important; + + .attachmentIcon { + color: #fff; + text-shadow: 0 1px 0 #000; + } + } + } + + .attachmentNameParent { + + position: relative; + + margin-left: 60px; + padding: 4px; + padding-left: 6px; + min-width: 90px; + + color: #333; + background: #fafafa; + border-left: 1px solid #ddd; + } + + .attachmentIcon { + margin: 6px 0 0 13px; + font-size: 36px; + width: 36px; + height: 36px; + color: #aaa; + } + + .attachmentIconParent.hasPreview:hover { + .iconPreview { + display: inline-block; + } + .iconMain { + display: none; + } + } + + .showPreview { + display: none; + } + + .attachmentIconParent.hasPreview { + .showPreview { + display: inline; + } + + .hidePreview { + display: none; + } + } + } + } } .b-header-toolbar { diff --git a/dev/Styles/Layout.less b/dev/Styles/Layout.less index da764aa40..2bd35162d 100644 --- a/dev/Styles/Layout.less +++ b/dev/Styles/Layout.less @@ -230,6 +230,51 @@ html.rl-no-preview-pane { } } +html.rl-bottom-preview-pane { + + #rl-sub-left { + right: @rlBottomMargin !important; + width: inherit; + + .b-message-list-wrapper { + bottom: inherit; + height: 300px; + + box-shadow: none; + } + + .messageList .inputSearch { + width: 300px !important; + } + } + + #rl-sub-right { + + left: 0 !important; + + .messageView .top-toolbar { + display: none; + } + + .b-message-view-wrapper { + top: 356px; + left: 0; + right: 5px; + + + box-shadow: none; + } + + .message-fixed-button-toolbar { + top: 370px; + } + } + + #rl-right .ui-resizable-handle { + display: none !important; + } +} + .visible-on-ctrl, .visible-on-ctrl-btn { display: none; } diff --git a/dev/Styles/MessageView.less b/dev/Styles/MessageView.less index 61f2d45b9..aea2a97b5 100644 --- a/dev/Styles/MessageView.less +++ b/dev/Styles/MessageView.less @@ -30,12 +30,11 @@ html.rl-no-preview-pane { top: 50px + @rlLowMargin; bottom: @rlLowMargin + @rlBottomMargin; right: @rlLowMargin; - left: -1px; - overflow: hidden; + left: -2px; + /*overflow: hidden;*/ border: @rlLowBorderSize solid @rlMainDarkColor; - .border-top-right-radius(@rlLowBorderRadius); - .border-bottom-right-radius(@rlLowBorderRadius); + .border-radius(@rlLowBorderRadius); background-color: #fff; @@ -58,8 +57,8 @@ html.rl-no-preview-pane { text-align: center; font-size: 24px; line-height: 30px; - padding-top: 120px; color: #999; + padding: 120px 10px 0 10px; } .b-message-view-desc.error { @@ -70,7 +69,10 @@ html.rl-no-preview-pane { -webkit-overflow-scrolling: touch; } - .messageItemDropdown { + .message-fixed-button-toolbar { + + float: right; + z-index: 100; position: fixed; top: 70px; @@ -155,7 +157,7 @@ html.rl-no-preview-pane { margin: 0 5px 0 0; background: #fff; border: 1px solid #ccc; - border-radius: 10px; + border-radius: 6px; box-sizing: border-box; } @@ -240,10 +242,8 @@ html.rl-no-preview-pane { max-width: 200px; min-width: 60px; overflow: hidden; - cursor: pointer; list-style: none; line-height: 24px; - /*border: 2px solid grey;*/ border: 0; background-color: #fff; box-shadow: 0 1px 5px #ccc; @@ -294,6 +294,8 @@ html.rl-no-preview-pane { padding-left: 6px; min-width: 90px; + cursor: pointer; + color: #333; background: #fafafa; border-left: 1px solid #ddd; @@ -441,7 +443,7 @@ html.rl-no-preview-pane { &.message-focused .b-content { z-index: 102; - box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.3); + box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.2); border-radius: @rlLowBorderRadius; border-color: darken(@rlMainDarkColor, 5%); } @@ -479,26 +481,26 @@ html.rl-message-fullscreen { } .messageView .b-content { - position: fixed; - margin: 5px; - top: 0; - left: 0; - right: 0; - bottom: 0; - z-index: 10000; - border: @rlLowBorderSize solid @rlMainDarkColor; - border-radius: @rlLowBorderRadius; + position: fixed !important; + margin: 5px !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + bottom: 0 !important; + z-index: 10000 !important; + border: @rlLowBorderSize solid @rlMainDarkColor !important; + border-radius: @rlLowBorderRadius !important; - .messageItemDropdown { - top: 20px; + .message-fixed-button-toolbar { + top: 20px !important; } .buttonUnFull { - display: inline-block; + display: inline-block !important; } .buttonFull { - display: none; + display: none !important; } } } diff --git a/dev/Styles/SystemDropDown.less b/dev/Styles/SystemDropDown.less index 8aa437661..882e1238e 100644 --- a/dev/Styles/SystemDropDown.less +++ b/dev/Styles/SystemDropDown.less @@ -34,6 +34,29 @@ vertical-align: middle; } + .accountPlace { + background-color: #000; + background-color: rgba(0, 0, 0, 0.5); + + color: #fff; + text-shadow: 0 1px 0 #000; + + position: absolute; + top: 11px; + right: 70px; + display: inline-block; + height: 28px; + max-width: 250px; + border-radius: 4px; + font-size: 16px; + line-height: 30px; + padding: 1px 8px; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 4px; + font-weight: bold; + } + .account-item { .icon-ok { @@ -57,4 +80,8 @@ .g-ui-menu .e-link.account-item { padding-right: 5px; } +} + +html.ssm-state-mobile .accountPlace { + max-width: 150px !important; } \ No newline at end of file diff --git a/dev/Styles/_BootstrapFix.less b/dev/Styles/_BootstrapFix.less index 83ec3d92b..595c716cb 100644 --- a/dev/Styles/_BootstrapFix.less +++ b/dev/Styles/_BootstrapFix.less @@ -135,6 +135,8 @@ html.rgba.textshadow { text-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2); padding: 5px 10px; border-radius: 2px; + overflow: hidden; + text-overflow: ellipsis; } .tooltip-big { diff --git a/dev/Styles/_Values.less b/dev/Styles/_Values.less index a30e71fd4..c81735ba1 100644 --- a/dev/Styles/_Values.less +++ b/dev/Styles/_Values.less @@ -10,7 +10,7 @@ @rlMainBorderRadius: 5px; @rlLowBorderRadius: 3px; -@rlMainShadow: 0px 2px 8px rgba(0, 0, 0, 0.3); +@rlMainShadow: 0px 2px 8px rgba(0, 0, 0, 0.2); @rlLowMargin: 8px; @rlBottomMargin: 5px; diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js index 6ab63bca4..41317684c 100644 --- a/dev/View/Popup/Compose.js +++ b/dev/View/Popup/Compose.js @@ -51,6 +51,9 @@ var self = this, + fResizeSub = function () { + Utils.windowResize(); + }, fCcAndBccCheckHelper = function (aValue) { if (false === self.showCcAndBcc() && 0 < aValue.length) { @@ -89,6 +92,7 @@ this.emptyToError = ko.observable(false); this.attachmentsInProcessError = ko.observable(false); + this.attachmentsInErrorError = ko.observable(false); this.showCcAndBcc = ko.observable(false); this.cc.subscribe(fCcAndBccCheckHelper, this); @@ -101,21 +105,45 @@ this.attachments = ko.observableArray([]); this.attachmentsInProcess = this.attachments.filter(function (oItem) { - return oItem && '' === oItem.tempName(); + return oItem && !oItem.complete(); }); this.attachmentsInReady = this.attachments.filter(function (oItem) { - return oItem && '' !== oItem.tempName(); + return oItem && oItem.complete(); }); - this.attachments.subscribe(function () { - this.triggerForResize(); + this.attachmentsInError = this.attachments.filter(function (oItem) { + return oItem && '' !== oItem.error(); + }); + + this.attachmentsCount = ko.computed(function () { + return this.attachments().length; + }, this); + + this.attachmentsInErrorCount = ko.computed(function () { + return this.attachmentsInError().length; + }, this); + + this.attachmentsInProcessCount = ko.computed(function () { + return this.attachmentsInProcess().length; }, this); this.isDraftFolderMessage = ko.computed(function () { return '' !== this.draftFolder() && '' !== this.draftUid(); }, this); + this.attachmentsPlace = ko.observable(false); + + this.attachments.subscribe(fResizeSub); + this.attachmentsPlace.subscribe(fResizeSub); + + this.attachmentsInErrorCount.subscribe(function (iN) { + if (0 === iN) + { + this.attachmentsInErrorError(false); + } + }, this); + this.composeUploaderButton = ko.observable(null); this.composeUploaderDropPlace = ko.observable(null); this.dragAndDropEnabled = ko.observable(false); @@ -227,6 +255,7 @@ this.saveMessageResponse = _.bind(this.saveMessageResponse, this); this.sendCommand = Utils.createCommand(this, function () { + var sTo = Utils.trim(this.to()), sSentFolder = Data.sentFolder(), @@ -236,6 +265,12 @@ if (0 < this.attachmentsInProcess().length) { this.attachmentsInProcessError(true); + this.attachmentsPlace(true); + } + else if (0 < this.attachmentsInError().length) + { + this.attachmentsInErrorError(true); + this.attachmentsPlace(true); } else if (0 === sTo.length) { @@ -1111,6 +1146,7 @@ if (oAttachment) { oAttachment.tempName(sTempName); + oAttachment.waiting(false).uploading(false).complete(true); } } } @@ -1118,7 +1154,7 @@ } else { - self.setMessageAttachmentFailedDowbloadText(); + self.setMessageAttachmentFailedDownloadText(); } }, aDownloads); @@ -1480,7 +1516,7 @@ if (oItem) { - oItem.progress(' - ' + window.Math.floor(iLoaded / iTotal * 100) + '%'); + oItem.progress(window.Math.floor(iLoaded / iTotal * 100)); } }, this)) @@ -1499,9 +1535,14 @@ this.attachments.push(oAttachment); + this.attachmentsPlace(true); + if (0 < mSize && 0 < iAttachmentSizeLimit && iAttachmentSizeLimit < mSize) { - oAttachment.error(Utils.i18n('UPLOAD/ERROR_FILE_IS_TOO_BIG')); + oAttachment + .waiting(false).uploading(true).complete(true) + .error(Utils.i18n('UPLOAD/ERROR_FILE_IS_TOO_BIG')); + return false; } @@ -1529,8 +1570,7 @@ if (oItem) { - oItem.waiting(false); - oItem.uploading(true); + oItem.waiting(false).uploading(true).complete(false); } }, this)) @@ -1562,6 +1602,7 @@ oAttachment .waiting(false) .uploading(false) + .complete(true) .error(sError) ; } @@ -1570,6 +1611,7 @@ oAttachment .waiting(false) .uploading(false) + .complete(true) ; oAttachment.initByUploadJson(oAttachmentJson); @@ -1639,7 +1681,7 @@ oAttachment.fromMessage = true; oAttachment.cancel = this.cancelAttachmentHelper(oMessage.requestHash); - oAttachment.waiting(false).uploading(true); + oAttachment.waiting(false).uploading(true).complete(true); this.attachments.push(oAttachment); } @@ -1663,13 +1705,15 @@ oAttachment.fromMessage = false; oAttachment.cancel = this.cancelAttachmentHelper(oDropboxFile['link']); - oAttachment.waiting(false).uploading(true); + oAttachment.waiting(false).uploading(true).complete(false); this.attachments.push(oAttachment); + this.attachmentsPlace(true); + if (0 < mSize && 0 < iAttachmentSizeLimit && iAttachmentSizeLimit < mSize) { - oAttachment.uploading(false); + oAttachment.uploading(false).complete(true); oAttachment.error(Utils.i18n('UPLOAD/ERROR_FILE_IS_TOO_BIG')); return false; } @@ -1677,7 +1721,7 @@ Remote.composeUploadExternals(function (sResult, oData) { var bResult = false; - oAttachment.uploading(false); + oAttachment.uploading(false).complete(true); if (Enums.StorageResultType.Success === sResult && oData && oData.Result) { @@ -1717,13 +1761,15 @@ oAttachment.fromMessage = false; oAttachment.cancel = this.cancelAttachmentHelper(oDriveFile['downloadUrl']); - oAttachment.waiting(false).uploading(true); + oAttachment.waiting(false).uploading(true).complete(false); this.attachments.push(oAttachment); + this.attachmentsPlace(true); + if (0 < mSize && 0 < iAttachmentSizeLimit && iAttachmentSizeLimit < mSize) { - oAttachment.uploading(false); + oAttachment.uploading(false).complete(true); oAttachment.error(Utils.i18n('UPLOAD/ERROR_FILE_IS_TOO_BIG')); return false; } @@ -1731,7 +1777,7 @@ Remote.composeUploadDrive(function (sResult, oData) { var bResult = false; - oAttachment.uploading(false); + oAttachment.uploading(false).complete(true); if (Enums.StorageResultType.Success === sResult && oData && oData.Result) { @@ -1803,7 +1849,7 @@ oAttachment.fromMessage = true; oAttachment.cancel = this.cancelAttachmentHelper(oItem.download); - oAttachment.waiting(false).uploading(true); + oAttachment.waiting(false).uploading(true).complete(false); this.attachments.push(oAttachment); } @@ -1825,7 +1871,7 @@ } }; - ComposePopupView.prototype.setMessageAttachmentFailedDowbloadText = function () + ComposePopupView.prototype.setMessageAttachmentFailedDownloadText = function () { _.each(this.attachments(), function(oAttachment) { if (oAttachment && oAttachment.fromMessage) @@ -1833,6 +1879,7 @@ oAttachment .waiting(false) .uploading(false) + .complete(true) .error(Utils.getUploadErrorDescByCode(Enums.UploadErrorCode.FileNoUploaded)) ; } @@ -1869,6 +1916,8 @@ this.requestReadReceipt(false); this.markAsImportant(false); + this.attachmentsPlace(false); + this.aDraftInfo = null; this.sInReplyTo = ''; this.bFromDraft = false; diff --git a/dev/View/User/MailBox/MessageList.js b/dev/View/User/MailBox/MessageList.js index ebea101b0..e135689cb 100644 --- a/dev/View/User/MailBox/MessageList.js +++ b/dev/View/User/MailBox/MessageList.js @@ -81,7 +81,7 @@ this.dragOverBodyArea = ko.observable(null); this.messageListItemTemplate = ko.computed(function () { - return Enums.Layout.NoPreview !== Data.layout() ? + return Enums.Layout.SidePreview === Data.layout() ? 'MailMessageListItem' : 'MailMessageListItemNoPreviewPane'; }); diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js index 1b239c3a3..300564ea3 100644 --- a/dev/View/User/MailBox/MessageView.js +++ b/dev/View/User/MailBox/MessageView.js @@ -345,27 +345,8 @@ } }, this); -// $('.attachmentsPlace', oDom).magnificPopup({ -// 'delegate': '.attachmentImagePreview:visible', -// 'type': 'image', -// 'gallery': { -// 'enabled': true, -// 'preload': [1, 1], -// 'navigateByImgClick': true -// }, -// 'callbacks': { -// 'open': function() { -// Globals.useKeyboardShortcuts(false); -// }, -// 'close': function() { -// Globals.useKeyboardShortcuts(true); -// } -// }, -// 'mainClass': 'mfp-fade', -// 'removalDelay': 400 -// }); - this.pswpDom = $('.pswp', oDom)[0]; + if (this.pswpDom) { oDom @@ -375,18 +356,31 @@ oPs = null, oEl = oEvent.currentTarget || null, aItems = [] +// fThumbBoundsFn = function (index) { +// var oRes = null, oEl = aItems[index], oPos = null; +// if (oEl && oEl.el) +// { +// oPos = oEl.el.find('.iconBG').offset(); +// oRes = oPos && oPos.top && oPos.left ? +// {x: oPos.left, y: oPos.top, w: 60} : null; +// } +// +// return oRes; +// } ; oDom.find('.attachmentImagePreview[data-index]').each(function (index, oSubElement) { - var $oItem = $(oSubElement); + var + $oItem = $(oSubElement) + ; aItems.push({ - w: 600, h: 400, +// 'el': $oItem, + 'w': 600, 'h': 400, 'src': $oItem.attr('href'), 'title': $oItem.attr('title') || '' }); - }); if (aItems && 0 < aItems.length) @@ -400,6 +394,7 @@ 'errorMsg': '
' + sErrorMessage + '
', 'showHideOpacity': true, 'tapToToggleControls': false, +// 'getThumbBoundsFn': fThumbBoundsFn, 'timeToIdle': 0, 'timeToIdleOutside': 0, 'history': false, @@ -414,7 +409,7 @@ item.w = item.img.width; item.h = item.img.height; - oPs.updateSize(); + oPs.updateSize(true); } }); @@ -434,13 +429,13 @@ // setup maito protocol return !(!!oEvent && 3 !== oEvent['which'] && Utils.mailToHelper($(this).attr('href'), require('View/Popup/Compose'))); }) - .on('click', '.attachmentsPlace .attachmentPreview', function (oEvent) { + .on('click', '.attachmentsPlace .attachmentIconParent', function (oEvent) { if (oEvent && oEvent.stopPropagation) { oEvent.stopPropagation(); } }) - .on('click', '.attachmentsPlace .attachmentItem', function () { + .on('click', '.attachmentsPlace .attachmentItem .attachmentNameParent', function () { var oAttachment = ko.dataFor(this) diff --git a/gulpfile.js b/gulpfile.js index 67b9196ad..5011a3d9e 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -95,8 +95,6 @@ cfg.paths.css = { 'vendors/normalize/normalize.css', 'vendors/fontastic/styles.css', 'vendors/jquery-nanoscroller/nanoscroller.css', -// 'vendors/jquery-magnific-popup/magnific-popup.css', -// 'vendors/jquery-magnific-popup/magnific-popup-animations.css', 'vendors/jquery-letterfx/jquery-letterfx.min.css', 'vendors/simple-pace/styles.css', 'vendors/inputosaurus/inputosaurus.css', @@ -390,12 +388,6 @@ regOtherMinTask('other:pace', 'vendors/simple-pace/', 'simple-pace.js', 'simple- regOtherMinTask('other:rl', 'vendors/rl/', 'rl.js', 'rl-1.3.min.js', '/*! RainLoop Index Helper v1.3 (c) 2014 RainLoop Team; Licensed under MIT */\n'); -gulp.task('package-inc-release', function() { - fs.writeFileSync('package.json', - fs.readFileSync('package.json', 'utf8').replace(/"release":\s?"[\d]+",/, '"release": "' + - (1 + parseInt(pkg.release, 10)) + '",')); -}); - gulp.task('fontastic-fonts:clear', function() { return cleanDir('rainloop/v/' + cfg.devVersion + '/static/css/fonts/rainloop.*'); }); @@ -537,8 +529,6 @@ gulp.task('default', ['js:libs', 'js:boot', 'js:openpgp', 'js:min', 'css:main:mi gulp.task('fast', ['js:app', 'js:admin', 'js:chunks', 'css:main']); gulp.task('rainloop', ['js:lint', 'rainloop:copy', 'rainloop:setup', 'rainloop:zip', 'rainloop:md5', 'rainloop:clean']); -gulp.task('rainloop+', ['rainloop', 'package-inc-release']); - gulp.task('owncloud', ['rainloop:owncloud:copy', 'rainloop:owncloud:setup', 'rainloop:owncloud:zip', 'rainloop:owncloud:md5', 'rainloop:owncloud:clean']); //WATCH @@ -547,16 +537,13 @@ gulp.task('watch', ['fast'], function() { gulp.watch(cfg.paths.less.main.watch, {interval: 500}, ['css:main']); }); -// aliases +// ALIASES gulp.task('w', ['watch']); gulp.task('f', ['fast']); gulp.task('rl', ['rainloop']); -gulp.task('rl+', ['rainloop+']); gulp.task('build', ['rainloop']); -gulp.task('build+', ['rainloop+']); gulp.task('b', ['build']); -gulp.task('b+', ['build+']); gulp.task('own', ['owncloud']); gulp.task('js:hint', ['js:lint']); \ No newline at end of file diff --git a/index.php b/index.php index 5ba5d470e..3731a17e7 100644 --- a/index.php +++ b/index.php @@ -7,9 +7,9 @@ if (!defined('APP_VERSION')) define('APP_INDEX_ROOT_PATH', str_replace('\\', '/', rtrim(dirname(__FILE__), '\\/').'/')); } -if (file_exists(APP_INDEX_ROOT_PATH.'rainloop/v/'.APP_VERSION.'/index.php')) +if (file_exists(APP_INDEX_ROOT_PATH.'rainloop/v/'.APP_VERSION.'/include.php')) { - include APP_INDEX_ROOT_PATH.'rainloop/v/'.APP_VERSION.'/index.php'; + include APP_INDEX_ROOT_PATH.'rainloop/v/'.APP_VERSION.'/include.php'; } else { diff --git a/package.json b/package.json index a18856dc0..f14556c78 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "RainLoop", "title": "RainLoop Webmail", "version": "1.7.2", - "release": "220", + "release": "224", "description": "Simple, modern & fast web-based email client", "homepage": "http://rainloop.net", "main": "gulpfile.js", diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Base/Utils.php b/rainloop/v/0.0.0/app/libraries/MailSo/Base/Utils.php index 6882f082f..4d258380b 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Base/Utils.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Base/Utils.php @@ -882,7 +882,6 @@ class Utils 'p7c' => 'application/pkcs7-mime', 'p7m' => 'application/pkcs7-mime', 'p7s' => 'application/pkcs7-signature', - 'ttf' => 'application/x-ttf', 'torrent' => 'application/x-bittorrent', // scripts @@ -963,7 +962,6 @@ class Utils 'flv' => 'video/x-flv', 'qt' => 'video/quicktime', 'mov' => 'video/quicktime', - 'wmv' => 'video/windows-media', 'avi' => 'video/x-msvideo', 'mpg' => 'video/mpeg', 'mpeg' => 'video/mpeg', @@ -976,6 +974,7 @@ class Utils 'h263' => 'video/h263', 'h264' => 'video/h264', 'jpgv' => 'video/jpgv', + 'mp4' => 'video/mp4', 'mp4v' => 'video/mp4', 'mpg4' => 'video/mp4', 'ogv' => 'video/ogg', diff --git a/rainloop/v/0.0.0/app/src/RainLoop/Actions.php b/rainloop/v/0.0.0/app/src/RainLoop/Actions.php index f59c3576d..fdf0dc35b 100644 --- a/rainloop/v/0.0.0/app/src/RainLoop/Actions.php +++ b/rainloop/v/0.0.0/app/src/RainLoop/Actions.php @@ -2067,7 +2067,7 @@ class Actions } return $this->TrueResponse(__FUNCTION__); - return $this->DefaultResponse(__FUNCTION__, $this->FiltersProvider()->Save($aFilters)); +// return $this->DefaultResponse(__FUNCTION__, $this->FiltersProvider()->Save($aFilters)); } /** @@ -2539,6 +2539,9 @@ class Actions case \RainLoop\Enumerations\Capa::GRAVATAR: $this->setConfigFromParams($oConfig, $sParamName, 'labs', 'allow_gravatar', 'bool'); break; + case \RainLoop\Enumerations\Capa::ATTACHMENT_THUMBNAILS: + $this->setConfigFromParams($oConfig, $sParamName, 'interface', 'show_attachment_thumbnail', 'bool'); + break; case \RainLoop\Enumerations\Capa::THEMES: $this->setConfigFromParams($oConfig, $sParamName, 'webmail', 'allow_themes', 'bool'); break; @@ -2636,6 +2639,7 @@ class Actions $this->setCapaFromParams($oConfig, 'CapaGravatar', \RainLoop\Enumerations\Capa::GRAVATAR); $this->setCapaFromParams($oConfig, 'CapaThemes', \RainLoop\Enumerations\Capa::THEMES); $this->setCapaFromParams($oConfig, 'CapaUserBackground', \RainLoop\Enumerations\Capa::USER_BACKGROUND); + $this->setCapaFromParams($oConfig, 'CapaAttachmentThumbnails', \RainLoop\Enumerations\Capa::ATTACHMENT_THUMBNAILS); $this->setConfigFromParams($oConfig, 'DetermineUserLanguage', 'login', 'determine_user_language', 'bool'); $this->setConfigFromParams($oConfig, 'DetermineUserDomain', 'login', 'determine_user_domain', 'bool'); @@ -3538,6 +3542,19 @@ class Actions \is_file(APP_INDEX_ROOT_PATH.'rainloop/v/'.$sNewVersion.'/index.php')) { $bResult = \copy($sTmpFolder.'/index.php', APP_INDEX_ROOT_PATH.'index.php'); + + if ($bResult) + { + if (\MailSo\Base\Utils::FunctionExistsAndEnabled('opcache_invalidate')) + { + @\opcache_invalidate(APP_INDEX_ROOT_PATH.'index.php', true); + } + + if (\MailSo\Base\Utils::FunctionExistsAndEnabled('apc_delete_file')) + { + @\apc_delete_file(APP_INDEX_ROOT_PATH.'index.php'); + } + } } else { @@ -3577,6 +3594,7 @@ class Actions $aDirs = @\array_map('basename', @\array_filter(@\glob($sVPath.'*'), 'is_dir')); $this->Logger()->Write('Versions GC: Count:'.(\is_array($aDirs) ? \count($aDirs) : 0)); + if (\is_array($aDirs) && 5 < \count($aDirs)) { \uasort($aDirs, 'version_compare'); @@ -6945,6 +6963,11 @@ class Actions $aResult[] = \RainLoop\Enumerations\Capa::GRAVATAR; } + if ($oConfig->Get('interface', 'show_attachment_thumbnail', true)) + { + $aResult[] = \RainLoop\Enumerations\Capa::ATTACHMENT_THUMBNAILS; + } + if ($oConfig->Get('labs', 'allow_prefetch', false)) { $aResult[] = \RainLoop\Enumerations\Capa::PREFETCH; @@ -8017,6 +8040,7 @@ class Actions $bHook = true; $sClassName = \get_class($mResponse); $bHasSimpleJsonFunc = \method_exists($mResponse, 'ToSimpleJSON'); + $bThumb = $this->GetCapa(false, \RainLoop\Enumerations\Capa::ATTACHMENT_THUMBNAILS); if ($bHasSimpleJsonFunc) { @@ -8278,7 +8302,7 @@ class Actions 'CID' => $mResponse->Cid(), 'ContentLocation' => $mResponse->ContentLocation(), 'IsInline' => $mResponse->IsInline(), - 'IsThumbnail' => !!$this->Config()->Get('interface', 'show_attachment_thumbnail', true), + 'IsThumbnail' => $bThumb, 'IsLinked' => ($mFoundedCIDs && \in_array(\trim(\trim($mResponse->Cid()), '<>'), $mFoundedCIDs)) || ($mFoundedContentLocationUrls && \in_array(\trim($mResponse->ContentLocation()), $mFoundedContentLocationUrls)) )); @@ -8300,8 +8324,6 @@ class Actions 'FileName' => $mResult['FileName'], 'Framed' => $mResult['Framed'] )); - - $this->Logger()->WriteDump($mResult); } else if ('MailSo\Mail\Folder' === $sClassName) { diff --git a/rainloop/v/0.0.0/app/src/RainLoop/Config/AbstractConfig.php b/rainloop/v/0.0.0/app/src/RainLoop/Config/AbstractConfig.php index 5722e6ce3..6403e7940 100644 --- a/rainloop/v/0.0.0/app/src/RainLoop/Config/AbstractConfig.php +++ b/rainloop/v/0.0.0/app/src/RainLoop/Config/AbstractConfig.php @@ -151,7 +151,7 @@ abstract class AbstractConfig if (\is_int($iMTime) && 0 < $iMTime) { $sKey = $this->cacheKey(); - + \apc_store($sKey.'time', $iMTime); \apc_store($sKey.'data', $this->aData); @@ -161,7 +161,7 @@ abstract class AbstractConfig return false; } - + /** * @return bool */ @@ -192,7 +192,7 @@ abstract class AbstractConfig return true; } - $aData = @\parse_ini_file($this->sFile, true); + $aData = \RainLoop\Utils::CustomParseIniFile($this->sFile, true); if (\is_array($aData) && 0 < count($aData)) { foreach ($aData as $sSectionKey => $aSectionValue) diff --git a/rainloop/v/0.0.0/app/src/RainLoop/Enumerations/Capa.php b/rainloop/v/0.0.0/app/src/RainLoop/Enumerations/Capa.php index 02e9953f8..de98ef967 100644 --- a/rainloop/v/0.0.0/app/src/RainLoop/Enumerations/Capa.php +++ b/rainloop/v/0.0.0/app/src/RainLoop/Enumerations/Capa.php @@ -12,6 +12,7 @@ class Capa const THEMES = 'THEMES'; const USER_BACKGROUND = 'USER_BACKGROUND'; const SIEVE = 'SIEVE'; + const ATTACHMENT_THUMBNAILS = 'ATTACHMENT_THUMBNAILS'; const ADDITIONAL_ACCOUNTS = 'ADDITIONAL_ACCOUNTS'; const ADDITIONAL_IDENTITIES = 'ADDITIONAL_IDENTITIES'; } diff --git a/rainloop/v/0.0.0/app/src/RainLoop/Providers/Domain/DefaultDomain.php b/rainloop/v/0.0.0/app/src/RainLoop/Providers/Domain/DefaultDomain.php index e23a3eed1..3ce150c5e 100644 --- a/rainloop/v/0.0.0/app/src/RainLoop/Providers/Domain/DefaultDomain.php +++ b/rainloop/v/0.0.0/app/src/RainLoop/Providers/Domain/DefaultDomain.php @@ -166,7 +166,7 @@ class DefaultDomain implements \RainLoop\Providers\Domain\DomainAdminInterface if (\file_exists($this->sDomainPath.'/'.$sRealFileName.'.ini') && (!$bCheckDisabled || 0 === \strlen($sDisabled) || false === \strpos(','.$sDisabled.',', ','.\MailSo\Base\Utils::IdnToAscii($sName, true).','))) { - $aDomain = @\parse_ini_file($this->sDomainPath.'/'.$sRealFileName.'.ini'); + $aDomain = \RainLoop\Utils::CustomParseIniFile($this->sDomainPath.'/'.$sRealFileName.'.ini'); // fix misspellings (#119) if (\is_array($aDomain)) { diff --git a/rainloop/v/0.0.0/app/src/RainLoop/Utils.php b/rainloop/v/0.0.0/app/src/RainLoop/Utils.php index 9190c6326..23a1a516a 100644 --- a/rainloop/v/0.0.0/app/src/RainLoop/Utils.php +++ b/rainloop/v/0.0.0/app/src/RainLoop/Utils.php @@ -149,16 +149,16 @@ class Utils } /** - * @param string $FileName + * @param string $sFileName * @param array $aResultLang * * @return void */ - public static function ReadAndAddLang($FileName, &$aResultLang) + public static function ReadAndAddLang($sFileName, &$aResultLang) { - if (\file_exists($FileName)) + if (\file_exists($sFileName)) { - $aLang = @\parse_ini_file($FileName, true); + $aLang = \RainLoop\Utils::CustomParseIniFile($sFileName, true); if (\is_array($aLang)) { foreach ($aLang as $sKey => $mValue) @@ -307,6 +307,23 @@ class Utils @\setcookie($sName, '', \time() - 3600 * 24 * 30, '/'); } + /** + * @param string $sFileName + * @param bool $bProcessSections = false + * + * @return array + */ + public static function CustomParseIniFile($sFileName, $bProcessSections = false) + { + if (\MailSo\Base\Utils::FunctionExistsAndEnabled('parse_ini_file')) + { + return @\parse_ini_file($sFileName, !!$bProcessSections); + } + + $sData = @\file_get_contents($sFileName); + return \is_string($sData) ? @\parse_ini_string($sData, !!$bProcessSections) : null; + } + public static function CustomBaseConvert($sNumberInput, $sFromBaseInput = '0123456789', $sToBaseInput = '0123456789') { if ($sFromBaseInput === $sToBaseInput) diff --git a/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsGeneral.html b/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsGeneral.html index ed2f00833..b11fc30ee 100644 --- a/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsGeneral.html +++ b/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsGeneral.html @@ -76,6 +76,14 @@
+
- -
\ No newline at end of file +
  • +
    +
    + +
    +
    +
    +
    +
    + +
    +   +
    +
    +   +
    +
    +
  • \ No newline at end of file diff --git a/rainloop/v/0.0.0/app/templates/Views/User/ComposeAttachmentInProcess.html b/rainloop/v/0.0.0/app/templates/Views/User/ComposeAttachmentInProcess.html deleted file mode 100644 index 12110f313..000000000 --- a/rainloop/v/0.0.0/app/templates/Views/User/ComposeAttachmentInProcess.html +++ /dev/null @@ -1,13 +0,0 @@ -
    - × - - - -    - () - - -
    - -
    -
    \ No newline at end of file diff --git a/rainloop/v/0.0.0/app/templates/Views/User/MailMessageView.html b/rainloop/v/0.0.0/app/templates/Views/User/MailMessageView.html index c42dc28cf..794dc5a35 100644 --- a/rainloop/v/0.0.0/app/templates/Views/User/MailMessageView.html +++ b/rainloop/v/0.0.0/app/templates/Views/User/MailMessageView.html @@ -1,10 +1,10 @@
    -
    +
    -
    +
    @@ -42,7 +42,7 @@
    -
    +
    @@ -57,124 +57,131 @@
    @@ -295,7 +302,8 @@
    -
    +
    + +
    +
    +
    +
    @@ -74,13 +91,6 @@ value: useCheckboxesInList } }">
    -
    +