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 @@