mirror of
https://github.com/the-djmaze/snappymail.git
synced 2025-01-01 12:32:40 +08:00
PreRelease 1.8.3
This commit is contained in:
parent
39566292af
commit
0ea982671b
40 changed files with 712 additions and 370 deletions
|
@ -73,7 +73,7 @@
|
|||
|
||||
}, 50));
|
||||
|
||||
// TODO
|
||||
// DEBUG
|
||||
// Events.sub({
|
||||
// 'window.resize': function () {
|
||||
// window.console.log('window.resize');
|
||||
|
|
|
@ -211,7 +211,7 @@
|
|||
|
||||
/**
|
||||
* @param {Function} fResultFunc
|
||||
* @returns {boolean}
|
||||
* @return {boolean}
|
||||
*/
|
||||
AppUser.prototype.contactsSync = function (fResultFunc)
|
||||
{
|
||||
|
|
|
@ -20,58 +20,90 @@
|
|||
{
|
||||
var self = this;
|
||||
|
||||
this.obj = this.createNewObject();
|
||||
this.objForNotification = this.createNewObject();
|
||||
// this.userMedia = window.navigator.getUserMedia || window.navigator.webkitGetUserMedia ||
|
||||
// window.navigator.mozGetUserMedia || window.navigator.msGetUserMedia;
|
||||
//
|
||||
// this.audioContext = window.AudioContext || window.webkitAudioContext;
|
||||
// if (!this.audioContext || !window.Float32Array)
|
||||
// {
|
||||
// this.audioContext = null;
|
||||
// this.userMedia = null;
|
||||
// }
|
||||
|
||||
this.supported = !Globals.bMobileDevice && !Globals.bSafari &&
|
||||
this.obj && '' !== this.obj.canPlayType('audio/mpeg');
|
||||
this.player = this.createNewObject();
|
||||
|
||||
if (this.obj && this.supported)
|
||||
this.supported = !Globals.bMobileDevice && !Globals.bSafari && !!this.player && !!this.player.play;
|
||||
if (this.supported && this.player.canPlayType)
|
||||
{
|
||||
this.objForNotification.src = Links.sound('new-mail.mp3');
|
||||
this.supportedMp3 = '' !== this.player.canPlayType('audio/mpeg;').replace(/no/, '');
|
||||
this.supportedWav = '' !== this.player.canPlayType('audio/wav; codecs="1"').replace(/no/, '');
|
||||
this.supportedOgg = '' !== this.player.canPlayType('audio/ogg; codecs="vorbis"').replace(/no/, '');
|
||||
this.supportedNotification = this.supported && this.supportedMp3;
|
||||
}
|
||||
|
||||
$(this.obj).on('ended error', function () {
|
||||
if (!this.player || (!this.supportedMp3 && !this.supportedOgg && !this.supportedWav))
|
||||
{
|
||||
this.supported = false;
|
||||
this.supportedMp3 = false;
|
||||
this.supportedOgg = false;
|
||||
this.supportedWav = false;
|
||||
this.supportedNotification = false;
|
||||
}
|
||||
|
||||
if (this.supported)
|
||||
{
|
||||
$(this.player).on('ended error', function () {
|
||||
self.stop();
|
||||
});
|
||||
|
||||
Events.sub('audio.api.stop', function () {
|
||||
self.stop();
|
||||
});
|
||||
|
||||
Events.sub('audio.api.play', function (sUrl, sName) {
|
||||
self.playMp3(sUrl, sName);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Audio.prototype.obj = null;
|
||||
Audio.prototype.objForNotification = null;
|
||||
Audio.prototype.player = null;
|
||||
Audio.prototype.notificator = null;
|
||||
|
||||
Audio.prototype.supported = false;
|
||||
Audio.prototype.supportedMp3 = false;
|
||||
Audio.prototype.supportedOgg = false;
|
||||
Audio.prototype.supportedWav = false;
|
||||
Audio.prototype.supportedNotification = false;
|
||||
|
||||
// Audio.prototype.record = function ()
|
||||
// {
|
||||
// this.getUserMedia({audio:true}, function () {
|
||||
// window.console.log(arguments);
|
||||
// }, function(oError) {
|
||||
// window.console.log(arguments);
|
||||
// });
|
||||
// };
|
||||
|
||||
Audio.prototype.createNewObject = function ()
|
||||
{
|
||||
var obj = window.Audio ? new window.Audio() : null;
|
||||
if (obj && obj.canPlayType)
|
||||
var player = window.Audio ? new window.Audio() : null;
|
||||
if (player && player.canPlayType && player.pause && player.play)
|
||||
{
|
||||
obj.preload = 'none';
|
||||
obj.loop = false;
|
||||
obj.autoplay = false;
|
||||
obj.muted = false;
|
||||
player.preload = 'none';
|
||||
player.loop = false;
|
||||
player.autoplay = false;
|
||||
player.muted = false;
|
||||
}
|
||||
|
||||
return obj;
|
||||
return player;
|
||||
};
|
||||
|
||||
Audio.prototype.paused = function ()
|
||||
{
|
||||
return this.supported ? !!this.obj.paused : true;
|
||||
return this.supported ? !!this.player.paused : true;
|
||||
};
|
||||
|
||||
Audio.prototype.stop = function ()
|
||||
{
|
||||
if (this.supported && this.obj.pause)
|
||||
if (this.supported && this.player.pause)
|
||||
{
|
||||
this.obj.pause();
|
||||
this.player.pause();
|
||||
}
|
||||
|
||||
Events.pub('audio.stop');
|
||||
|
@ -79,33 +111,73 @@
|
|||
|
||||
Audio.prototype.pause = Audio.prototype.stop;
|
||||
|
||||
Audio.prototype.clearName = function (sName, sExt)
|
||||
{
|
||||
sExt = sExt || '';
|
||||
sName = Utils.isUnd(sName) ? '' : Utils.trim(sName);
|
||||
if (sExt && '.' + sExt === sName.toLowerCase().substr((sExt.length + 1) * -1))
|
||||
{
|
||||
sName = Utils.trim(sName.substr(0, sName.length - 4));
|
||||
}
|
||||
|
||||
if ('' === sName)
|
||||
{
|
||||
sName = 'audio';
|
||||
}
|
||||
|
||||
return sName;
|
||||
};
|
||||
|
||||
Audio.prototype.playMp3 = function (sUrl, sName)
|
||||
{
|
||||
if (this.supported && this.obj.play)
|
||||
if (this.supported && this.supportedMp3)
|
||||
{
|
||||
this.obj.src = sUrl;
|
||||
this.obj.play();
|
||||
this.player.src = sUrl;
|
||||
this.player.play();
|
||||
|
||||
sName = Utils.isUnd(sName) ? '' : Utils.trim(sName);
|
||||
if ('.mp3' === sName.toLowerCase().substr(-4))
|
||||
{
|
||||
sName = Utils.trim(sName.substr(0, sName.length - 4));
|
||||
}
|
||||
Events.pub('audio.start', [this.clearName(sName, 'mp3'), 'mp3']);
|
||||
}
|
||||
};
|
||||
|
||||
if ('' === sName)
|
||||
{
|
||||
sName = 'audio';
|
||||
}
|
||||
Audio.prototype.playOgg = function (sUrl, sName)
|
||||
{
|
||||
if (this.supported && this.supportedOgg)
|
||||
{
|
||||
this.player.src = sUrl;
|
||||
this.player.play();
|
||||
|
||||
Events.pub('audio.start', [sName]);
|
||||
sName = this.clearName(sName, 'oga');
|
||||
sName = this.clearName(sName, 'ogg');
|
||||
|
||||
Events.pub('audio.start', [sName, 'ogg']);
|
||||
}
|
||||
};
|
||||
|
||||
Audio.prototype.playWav = function (sUrl, sName)
|
||||
{
|
||||
if (this.supported && this.supportedWav)
|
||||
{
|
||||
this.player.src = sUrl;
|
||||
this.player.play();
|
||||
|
||||
Events.pub('audio.start', [this.clearName(sName, 'wav'), 'wav']);
|
||||
}
|
||||
};
|
||||
|
||||
Audio.prototype.playNotification = function ()
|
||||
{
|
||||
if (this.supported && this.objForNotification.play)
|
||||
if (this.supported && this.supportedMp3)
|
||||
{
|
||||
this.objForNotification.play();
|
||||
if (!this.notificator)
|
||||
{
|
||||
this.notificator = this.createNewObject();
|
||||
this.notificator.src = Links.sound('new-mail.mp3');
|
||||
}
|
||||
|
||||
if (this.notificator && this.notificator.play)
|
||||
{
|
||||
this.notificator.play();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -5,6 +5,26 @@
|
|||
|
||||
var Enums = {};
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
Enums.FileType = {
|
||||
'Unknown': 'unknown',
|
||||
'Text': 'text',
|
||||
'Html': 'html',
|
||||
'Code': 'code',
|
||||
'Eml': 'eml',
|
||||
'WordText': 'word-text',
|
||||
'Pdf': 'pdf',
|
||||
'Image': 'image',
|
||||
'Audio': 'audio',
|
||||
'Video': 'video',
|
||||
'Sheet': 'sheet',
|
||||
'Presentation': 'presentation',
|
||||
'Certificate': 'certificate',
|
||||
'Archive': 'archive'
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
Globals.$win = $(window);
|
||||
Globals.$doc = $(window.document);
|
||||
Globals.$html = $('html');
|
||||
Globals.$body = $('body');
|
||||
Globals.$div = $('<div></div>');
|
||||
|
||||
Globals.$win.__sizes = [0, 0];
|
||||
|
@ -268,7 +269,7 @@
|
|||
});
|
||||
|
||||
Globals.keyScopeReal.subscribe(function (sValue) {
|
||||
// window.console.log('keyScope=' + sValue); // TODO
|
||||
// window.console.log('keyScope=' + sValue); // DEBUG
|
||||
key.setScope(sValue);
|
||||
});
|
||||
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
|
||||
this.resize = _.throttle(_.bind(this.resize, this), 100);
|
||||
|
||||
this.__inited = false;
|
||||
this.__initedData = null;
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
|
@ -190,7 +193,7 @@
|
|||
|
||||
HtmlEditor.prototype.setHtml = function (sHtml, bFocus)
|
||||
{
|
||||
if (this.editor)
|
||||
if (this.editor && this.__inited)
|
||||
{
|
||||
this.modeToggle(true);
|
||||
|
||||
|
@ -203,11 +206,15 @@
|
|||
this.focus();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.__initedData = [true, sHtml, bFocus];
|
||||
}
|
||||
};
|
||||
|
||||
HtmlEditor.prototype.setPlain = function (sPlain, bFocus)
|
||||
{
|
||||
if (this.editor)
|
||||
if (this.editor && this.__inited)
|
||||
{
|
||||
this.modeToggle(false);
|
||||
if ('plain' === this.editor.mode && this.editor.plugins.plain && this.editor.__plain)
|
||||
|
@ -226,6 +233,10 @@
|
|||
this.focus();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.__initedData = [false, sPlain, bFocus];
|
||||
}
|
||||
};
|
||||
|
||||
HtmlEditor.prototype.init = function ()
|
||||
|
@ -322,7 +333,20 @@
|
|||
|
||||
self.fOnReady();
|
||||
self.__resizable = true;
|
||||
self.__inited = true;
|
||||
self.resize();
|
||||
|
||||
if (self.__initedData)
|
||||
{
|
||||
if (self.__initedData[0])
|
||||
{
|
||||
self.setHtml(self.__initedData[1], self.__initedData[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.setPlain(self.__initedData[1], self.__initedData[2]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -435,7 +435,7 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
* @return {boolean}
|
||||
*/
|
||||
Selector.prototype.autoSelect = function ()
|
||||
{
|
||||
|
@ -452,7 +452,7 @@
|
|||
|
||||
/**
|
||||
* @param {Object} oItem
|
||||
* @returns {string}
|
||||
* @return {string}
|
||||
*/
|
||||
Selector.prototype.getItemUid = function (oItem)
|
||||
{
|
||||
|
|
|
@ -144,7 +144,7 @@
|
|||
/**
|
||||
* @param {string} sMailToUrl
|
||||
* @param {Function} PopupComposeVoreModel
|
||||
* @returns {boolean}
|
||||
* @return {boolean}
|
||||
*/
|
||||
Utils.mailToHelper = function (sMailToUrl, PopupComposeVoreModel)
|
||||
{
|
||||
|
@ -598,7 +598,7 @@
|
|||
* @param {string} sTheme
|
||||
* @return {string}
|
||||
*/
|
||||
Utils.convertThemeName = function (sTheme)
|
||||
Utils.convertThemeName = _.memoize(function (sTheme)
|
||||
{
|
||||
if ('@custom' === sTheme.substr(-7))
|
||||
{
|
||||
|
@ -606,7 +606,7 @@
|
|||
}
|
||||
|
||||
return Utils.trim(sTheme.replace(/[^a-zA-Z0-9]+/g, ' ').replace(/([A-Z])/g, ' $1').replace(/[\s]+/g, ' '));
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {string} sName
|
||||
|
@ -822,40 +822,6 @@
|
|||
|
||||
sText = '',
|
||||
|
||||
splitPlainText = function (sText)
|
||||
{
|
||||
var
|
||||
iLen = 100,
|
||||
sPrefix = '',
|
||||
sSubText = '',
|
||||
sResult = sText,
|
||||
iSpacePos = 0,
|
||||
iNewLinePos = 0
|
||||
;
|
||||
|
||||
while (sResult.length > iLen)
|
||||
{
|
||||
sSubText = sResult.substring(0, iLen);
|
||||
iSpacePos = sSubText.lastIndexOf(' ');
|
||||
iNewLinePos = sSubText.lastIndexOf('\n');
|
||||
|
||||
if (-1 !== iNewLinePos)
|
||||
{
|
||||
iSpacePos = iNewLinePos;
|
||||
}
|
||||
|
||||
if (-1 === iSpacePos)
|
||||
{
|
||||
iSpacePos = iLen;
|
||||
}
|
||||
|
||||
sPrefix += sSubText.substring(0, iSpacePos) + '\n';
|
||||
sResult = sResult.substring(iSpacePos + 1);
|
||||
}
|
||||
|
||||
return sPrefix + sResult;
|
||||
},
|
||||
|
||||
convertBlockquote = function (sText) {
|
||||
sText = Utils.trim(sText);
|
||||
sText = '> ' + sText.replace(/\n/gm, '\n> ');
|
||||
|
@ -929,7 +895,7 @@
|
|||
.replace(/&/gi, '&')
|
||||
;
|
||||
|
||||
sText = splitPlainText(Utils.trim(sText));
|
||||
sText = Utils.splitPlainText(Utils.trim(sText));
|
||||
|
||||
iPos = 0;
|
||||
iLimit = 800;
|
||||
|
|
14
dev/External/Opentip.js
vendored
14
dev/External/Opentip.js
vendored
|
@ -9,10 +9,21 @@
|
|||
;
|
||||
|
||||
Opentip.styles.rainloop = {
|
||||
|
||||
'extends': 'standard',
|
||||
|
||||
'fixed': true,
|
||||
'target': true,
|
||||
|
||||
'delay': 0.2,
|
||||
'hideDelay': 0,
|
||||
|
||||
'hideEffect': 'fade',
|
||||
'hideEffectDuration': 0.2,
|
||||
|
||||
'showEffect': 'fade',
|
||||
'showEffectDuration': 0.2,
|
||||
|
||||
'showOn': 'mouseover click',
|
||||
'removeElementsOnHide': true,
|
||||
|
||||
|
@ -26,8 +37,7 @@
|
|||
|
||||
Opentip.styles.rainloopTip = {
|
||||
'extends': 'rainloop',
|
||||
'stemLength': 3,
|
||||
'stemBase': 5,
|
||||
'delay': 0.4,
|
||||
'group': 'rainloopTips'
|
||||
};
|
||||
|
||||
|
|
27
dev/External/ko.js
vendored
27
dev/External/ko.js
vendored
|
@ -33,7 +33,7 @@
|
|||
}
|
||||
},
|
||||
fUpdateKoValue = function () {
|
||||
if (oEditor)
|
||||
if (oEditor && oEditor.__inited)
|
||||
{
|
||||
fValue(oEditor.getDataWithHtmlMark());
|
||||
}
|
||||
|
@ -49,6 +49,7 @@
|
|||
fValue.__updateEditorValue = fUpdateEditorValue;
|
||||
|
||||
fValue.subscribe(fUpdateEditorValue);
|
||||
fUpdateEditorValue();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -61,6 +62,7 @@
|
|||
sValue = '',
|
||||
Translator = null,
|
||||
$oEl = $(oElement),
|
||||
fValue = fValueAccessor(),
|
||||
bMobile = 'on' === ($oEl.data('tooltip-mobile') || 'off'),
|
||||
Globals = require('Common/Globals')
|
||||
;
|
||||
|
@ -68,7 +70,7 @@
|
|||
if (!Globals.bMobileDevice || bMobile)
|
||||
{
|
||||
bi18n = 'on' === ($oEl.data('tooltip-i18n') || 'on');
|
||||
sValue = ko.unwrap(fValueAccessor());
|
||||
sValue = !ko.isObservable(fValue) && _.isFunction(fValue) ? fValue() : ko.unwrap(fValue);
|
||||
|
||||
oElement.__opentip = new Opentip(oElement, {
|
||||
'style': 'rainloopTip',
|
||||
|
@ -78,12 +80,21 @@
|
|||
|
||||
Globals.dropdownVisibility.subscribe(function (bV) {
|
||||
if (bV) {
|
||||
oElement.__opentip.deactivate();
|
||||
} else {
|
||||
oElement.__opentip.activate();
|
||||
oElement.__opentip.hide();
|
||||
}
|
||||
});
|
||||
|
||||
if ('' === sValue)
|
||||
{
|
||||
oElement.__opentip.hide();
|
||||
oElement.__opentip.deactivate();
|
||||
oElement.__opentip.setContent('');
|
||||
}
|
||||
else
|
||||
{
|
||||
oElement.__opentip.activate();
|
||||
}
|
||||
|
||||
if (bi18n)
|
||||
{
|
||||
Translator = require('Common/Translator');
|
||||
|
@ -113,6 +124,7 @@
|
|||
bi18n = true,
|
||||
sValue = '',
|
||||
$oEl = $(oElement),
|
||||
fValue = fValueAccessor(),
|
||||
bMobile = 'on' === ($oEl.data('tooltip-mobile') || 'off'),
|
||||
Globals = require('Common/Globals')
|
||||
;
|
||||
|
@ -120,7 +132,7 @@
|
|||
if ((!Globals.bMobileDevice || bMobile) && oElement.__opentip)
|
||||
{
|
||||
bi18n = 'on' === ($oEl.data('tooltip-i18n') || 'on');
|
||||
sValue = ko.unwrap(fValueAccessor());
|
||||
sValue = !ko.isObservable(fValue) && _.isFunction(fValue) ? fValue() : ko.unwrap(fValue);
|
||||
|
||||
if (sValue)
|
||||
{
|
||||
|
@ -165,7 +177,8 @@
|
|||
|
||||
var
|
||||
$oEl = $(oElement),
|
||||
sValue = ko.unwrap(fValueAccessor()),
|
||||
fValue = fValueAccessor(),
|
||||
sValue = !ko.isObservable(fValue) && _.isFunction(fValue) ? fValue() : ko.unwrap(fValue),
|
||||
oOpenTips = oElement.__opentip
|
||||
;
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
_ = require('_'),
|
||||
ko = require('ko'),
|
||||
|
||||
Enums = require('Common/Enums'),
|
||||
Globals = require('Common/Globals'),
|
||||
Utils = require('Common/Utils'),
|
||||
Links = require('Common/Links'),
|
||||
|
@ -27,6 +28,8 @@
|
|||
|
||||
this.mimeType = '';
|
||||
this.fileName = '';
|
||||
this.fileNameExt = '';
|
||||
this.fileType = Enums.FileType.Unknown;
|
||||
this.estimatedSize = 0;
|
||||
this.friendlySize = '';
|
||||
this.isInline = false;
|
||||
|
@ -57,6 +60,8 @@
|
|||
|
||||
AttachmentModel.prototype.mimeType = '';
|
||||
AttachmentModel.prototype.fileName = '';
|
||||
AttachmentModel.prototype.fileType = '';
|
||||
AttachmentModel.prototype.fileNameExt = '';
|
||||
AttachmentModel.prototype.estimatedSize = 0;
|
||||
AttachmentModel.prototype.friendlySize = '';
|
||||
AttachmentModel.prototype.isInline = false;
|
||||
|
@ -97,6 +102,9 @@
|
|||
this.friendlySize = Utils.friendlySize(this.estimatedSize);
|
||||
this.cidWithOutTags = this.cid.replace(/^<+/, '').replace(/>+$/, '');
|
||||
|
||||
this.fileNameExt = Utils.getFileExtension(this.fileName);
|
||||
this.fileType = AttachmentModel.staticFileType(this.fileNameExt, this.mimeType);
|
||||
|
||||
bResult = true;
|
||||
}
|
||||
|
||||
|
@ -108,9 +116,7 @@
|
|||
*/
|
||||
AttachmentModel.prototype.isImage = function ()
|
||||
{
|
||||
return -1 < Utils.inArray(this.mimeType.toLowerCase(),
|
||||
['image/png', 'image/jpg', 'image/jpeg', 'image/gif']
|
||||
);
|
||||
return Enums.FileType.Image === this.fileType;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -118,7 +124,26 @@
|
|||
*/
|
||||
AttachmentModel.prototype.isMp3 = function ()
|
||||
{
|
||||
return Audio.supported && '.mp3' === this.fileName.toLowerCase().substr(-4);
|
||||
return Enums.FileType.Audio === this.fileType &&
|
||||
'mp3' === this.fileNameExt;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {boolean}
|
||||
*/
|
||||
AttachmentModel.prototype.isOgg = function ()
|
||||
{
|
||||
return Enums.FileType.Audio === this.fileType &&
|
||||
('oga' === this.fileNameExt || 'ogg' === this.fileNameExt);
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {boolean}
|
||||
*/
|
||||
AttachmentModel.prototype.isWav = function ()
|
||||
{
|
||||
return Enums.FileType.Audio === this.fileType &&
|
||||
'wav' === this.fileNameExt;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -134,8 +159,12 @@
|
|||
*/
|
||||
AttachmentModel.prototype.isText = function ()
|
||||
{
|
||||
return -1 < Utils.inArray(this.mimeType, ['application/pgp-signature', 'message/delivery-status', 'message/rfc822']) ||
|
||||
('text/' === this.mimeType.substr(0, 5) && -1 === Utils.inArray(this.mimeType, ['text/html']));
|
||||
return Enums.FileType.Text === this.fileType ||
|
||||
Enums.FileType.Eml === this.fileType ||
|
||||
Enums.FileType.Certificate === this.fileType ||
|
||||
Enums.FileType.Html === this.fileType ||
|
||||
Enums.FileType.Code === this.fileType
|
||||
;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -143,7 +172,7 @@
|
|||
*/
|
||||
AttachmentModel.prototype.isPdf = function ()
|
||||
{
|
||||
return Globals.bAllowPdfPreview && 'application/pdf' === this.mimeType;
|
||||
return Enums.FileType.Pdf === this.fileType;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -152,7 +181,7 @@
|
|||
AttachmentModel.prototype.isFramed = function ()
|
||||
{
|
||||
return this.framed && (Globals.__APP__ && Globals.__APP__.googlePreviewSupported()) &&
|
||||
!this.isPdf() && !this.isText() && !this.isImage();
|
||||
!(this.isPdf() && Globals.bAllowPdfPreview) && !this.isText() && !this.isImage();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -160,7 +189,7 @@
|
|||
*/
|
||||
AttachmentModel.prototype.hasPreview = function ()
|
||||
{
|
||||
return this.isImage() || this.isPdf() || this.isText() || this.isFramed();
|
||||
return this.isImage() || (this.isPdf() && Globals.bAllowPdfPreview) || this.isText() || this.isFramed();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -168,7 +197,10 @@
|
|||
*/
|
||||
AttachmentModel.prototype.hasPreplay = function ()
|
||||
{
|
||||
return this.isMp3();
|
||||
return (Audio.supportedMp3 && this.isMp3()) ||
|
||||
(Audio.supportedOgg && this.isOgg()) ||
|
||||
(Audio.supportedWav && this.isWav())
|
||||
;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -229,7 +261,7 @@
|
|||
switch (true)
|
||||
{
|
||||
case this.isImage():
|
||||
case this.isPdf():
|
||||
case this.isPdf() && Globals.bAllowPdfPreview:
|
||||
sResult = this.linkPreview();
|
||||
break;
|
||||
case this.isText():
|
||||
|
@ -274,76 +306,85 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* @param {string} sExt
|
||||
* @param {string} sMimeType
|
||||
* @returns {string}
|
||||
* @return {string}
|
||||
*/
|
||||
AttachmentModel.staticIconClassHelper = function (sMimeType)
|
||||
AttachmentModel.staticFileType = _.memoize(function (sExt, sMimeType)
|
||||
{
|
||||
sExt = Utils.trim(sExt).toLowerCase();
|
||||
sMimeType = Utils.trim(sMimeType).toLowerCase();
|
||||
|
||||
var
|
||||
sText = '',
|
||||
sClass = 'icon-file',
|
||||
aParts = sMimeType.split('/')
|
||||
sResult = Enums.FileType.Unknown,
|
||||
aMimeTypeParts = sMimeType.split('/')
|
||||
;
|
||||
|
||||
if (aParts && aParts[1])
|
||||
switch (true)
|
||||
{
|
||||
if ('image' === aParts[0])
|
||||
{
|
||||
sClass = 'icon-file-image';
|
||||
}
|
||||
else if ('text' === aParts[0])
|
||||
{
|
||||
sClass = 'icon-file-text';
|
||||
}
|
||||
else if ('audio' === aParts[0])
|
||||
{
|
||||
sClass = 'icon-file-music';
|
||||
}
|
||||
else if ('video' === aParts[0])
|
||||
{
|
||||
sClass = 'icon-file-movie';
|
||||
}
|
||||
else if (-1 < Utils.inArray(aParts[1],
|
||||
['zip', '7z', 'tar', 'rar', 'gzip', 'bzip', 'bzip2', 'x-zip', 'x-7z', 'x-rar', 'x-tar', 'x-gzip', 'x-bzip', 'x-bzip2', 'x-zip-compressed', 'x-7z-compressed', 'x-rar-compressed']))
|
||||
{
|
||||
sClass = 'icon-file-zip';
|
||||
}
|
||||
else if (-1 < Utils.inArray(aParts[1],
|
||||
['pdf', 'x-pdf']))
|
||||
{
|
||||
sText = 'pdf';
|
||||
sClass = 'icon-none';
|
||||
}
|
||||
// else if (-1 < Utils.inArray(aParts[1], [
|
||||
// 'exe', 'x-exe', 'x-winexe', 'bat'
|
||||
// ]))
|
||||
// {
|
||||
// sClass = 'icon-console';
|
||||
// }
|
||||
else if (-1 < Utils.inArray(sMimeType, [
|
||||
'application/pgp-signature', 'application/pkcs7-signature'
|
||||
]))
|
||||
{
|
||||
sClass = 'icon-file-certificate';
|
||||
}
|
||||
else if (-1 < Utils.inArray(sMimeType, [
|
||||
case 'image' === aMimeTypeParts[0] || -1 < Utils.inArray(sExt, [
|
||||
'png', 'jpg', 'jpeg', 'gif', 'bmp'
|
||||
]):
|
||||
sResult = Enums.FileType.Image;
|
||||
break;
|
||||
case 'audio' === aMimeTypeParts[0] || -1 < Utils.inArray(sExt, [
|
||||
'mp3', 'ogg', 'oga', 'wav'
|
||||
]):
|
||||
sResult = Enums.FileType.Audio;
|
||||
break;
|
||||
case 'video' === aMimeTypeParts[0] || -1 < Utils.inArray(sExt, [
|
||||
'mkv', 'avi'
|
||||
]):
|
||||
sResult = Enums.FileType.Video;
|
||||
break;
|
||||
case -1 < Utils.inArray(sExt, [
|
||||
'php', 'js', 'css'
|
||||
]):
|
||||
sResult = Enums.FileType.Code;
|
||||
break;
|
||||
case 'eml' === sExt || -1 < Utils.inArray(sMimeType, [
|
||||
'message/delivery-status', 'message/rfc822'
|
||||
]))
|
||||
{
|
||||
sClass = 'icon-file-text';
|
||||
}
|
||||
else if (-1 < Utils.inArray(aParts[1], [
|
||||
]):
|
||||
sResult = Enums.FileType.Eml;
|
||||
break;
|
||||
case ('text' === aMimeTypeParts[0] && 'html' !== aMimeTypeParts[1]) || -1 < Utils.inArray(sExt, [
|
||||
'txt', 'log'
|
||||
]):
|
||||
sResult = Enums.FileType.Text;
|
||||
break;
|
||||
case ('text/html' === sMimeType) || -1 < Utils.inArray(sExt, [
|
||||
'html'
|
||||
]):
|
||||
sResult = Enums.FileType.Html;
|
||||
break;
|
||||
case -1 < Utils.inArray(aMimeTypeParts[1], [
|
||||
'zip', '7z', 'tar', 'rar', 'gzip', 'bzip', 'bzip2', 'x-zip', 'x-7z', 'x-rar', 'x-tar', 'x-gzip', 'x-bzip', 'x-bzip2', 'x-zip-compressed', 'x-7z-compressed', 'x-rar-compressed'
|
||||
]) || -1 < Utils.inArray(sExt, [
|
||||
'zip', '7z', 'tar', 'rar', 'gzip', 'bzip', 'bzip2'
|
||||
]):
|
||||
sResult = Enums.FileType.Archive;
|
||||
break;
|
||||
case -1 < Utils.inArray(aMimeTypeParts[1], ['pdf', 'x-pdf']) || -1 < Utils.inArray(sExt, [
|
||||
'pdf'
|
||||
]):
|
||||
sResult = Enums.FileType.Pdf;
|
||||
break;
|
||||
case -1 < Utils.inArray(sMimeType, [
|
||||
'application/pgp-signature', 'application/pkcs7-signature', 'application/pgp-keys'
|
||||
]) || -1 < Utils.inArray(sExt, [
|
||||
'asc', 'pem', 'ppk'
|
||||
]):
|
||||
sResult = Enums.FileType.Certificate;
|
||||
break;
|
||||
case -1 < Utils.inArray(aMimeTypeParts[1], [
|
||||
'rtf', 'msword', 'vnd.msword', 'vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'vnd.openxmlformats-officedocument.wordprocessingml.template',
|
||||
'vnd.ms-word.document.macroEnabled.12',
|
||||
'vnd.ms-word.template.macroEnabled.12'
|
||||
]))
|
||||
{
|
||||
sClass = 'icon-file-text';
|
||||
}
|
||||
else if (-1 < Utils.inArray(aParts[1], [
|
||||
]):
|
||||
sResult = Enums.FileType.WordText;
|
||||
break;
|
||||
case -1 < Utils.inArray(aMimeTypeParts[1], [
|
||||
'excel', 'ms-excel', 'vnd.ms-excel',
|
||||
'vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'vnd.openxmlformats-officedocument.spreadsheetml.template',
|
||||
|
@ -351,11 +392,10 @@
|
|||
'vnd.ms-excel.template.macroEnabled.12',
|
||||
'vnd.ms-excel.addin.macroEnabled.12',
|
||||
'vnd.ms-excel.sheet.binary.macroEnabled.12'
|
||||
]))
|
||||
{
|
||||
sClass = 'icon-file-excel';
|
||||
}
|
||||
else if (-1 < Utils.inArray(aParts[1], [
|
||||
]):
|
||||
sResult = Enums.FileType.Sheet;
|
||||
break;
|
||||
case -1 < Utils.inArray(aMimeTypeParts[1], [
|
||||
'powerpoint', 'ms-powerpoint', 'vnd.ms-powerpoint',
|
||||
'vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
'vnd.openxmlformats-officedocument.presentationml.template',
|
||||
|
@ -364,29 +404,140 @@
|
|||
'vnd.ms-powerpoint.presentation.macroEnabled.12',
|
||||
'vnd.ms-powerpoint.template.macroEnabled.12',
|
||||
'vnd.ms-powerpoint.slideshow.macroEnabled.12'
|
||||
]))
|
||||
{
|
||||
]):
|
||||
sResult = Enums.FileType.Presentation;
|
||||
break;
|
||||
}
|
||||
|
||||
return sResult;
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {string} sFileType
|
||||
* @return {string}
|
||||
*/
|
||||
AttachmentModel.staticIconClass = _.memoize(function (sFileType)
|
||||
{
|
||||
var
|
||||
sText = '',
|
||||
sClass = 'icon-file'
|
||||
;
|
||||
|
||||
switch (sFileType)
|
||||
{
|
||||
case Enums.FileType.Text:
|
||||
case Enums.FileType.Eml:
|
||||
case Enums.FileType.WordText:
|
||||
sClass = 'icon-file-text';
|
||||
break;
|
||||
case Enums.FileType.Html:
|
||||
case Enums.FileType.Code:
|
||||
sClass = 'icon-file-code';
|
||||
break;
|
||||
case Enums.FileType.Image:
|
||||
sClass = 'icon-file-image';
|
||||
break;
|
||||
case Enums.FileType.Audio:
|
||||
sClass = 'icon-file-music';
|
||||
break;
|
||||
case Enums.FileType.Video:
|
||||
sClass = 'icon-file-movie';
|
||||
break;
|
||||
case Enums.FileType.Archive:
|
||||
sClass = 'icon-file-zip';
|
||||
break;
|
||||
case Enums.FileType.Certificate:
|
||||
sClass = 'icon-file-certificate';
|
||||
break;
|
||||
case Enums.FileType.Sheet:
|
||||
sClass = 'icon-file-excel';
|
||||
break;
|
||||
case Enums.FileType.Presentation:
|
||||
sClass = 'icon-file-chart-graph';
|
||||
}
|
||||
break;
|
||||
case Enums.FileType.Pdf:
|
||||
sText = 'pdf';
|
||||
sClass = 'icon-none';
|
||||
break;
|
||||
}
|
||||
|
||||
return [sClass, sText];
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {string} sFileType
|
||||
* @return {string}
|
||||
*/
|
||||
AttachmentModel.staticCombinedIconClass = function (aData)
|
||||
{
|
||||
var
|
||||
sClass = '',
|
||||
aTypes = []
|
||||
;
|
||||
|
||||
if (Utils.isNonEmptyArray(aData))
|
||||
{
|
||||
sClass = 'icon-attachment';
|
||||
|
||||
aTypes = _.uniq(_.compact(_.map(aData, function (aItem) {
|
||||
return aItem ? AttachmentModel.staticFileType(
|
||||
Utils.getFileExtension(aItem[0]), aItem[1]) : '';
|
||||
})));
|
||||
|
||||
if (aTypes && 1 === aTypes.length && aTypes[0])
|
||||
{
|
||||
switch (aTypes[0])
|
||||
{
|
||||
case Enums.FileType.Text:
|
||||
case Enums.FileType.WordText:
|
||||
sClass = 'icon-file-text';
|
||||
break;
|
||||
case Enums.FileType.Html:
|
||||
case Enums.FileType.Code:
|
||||
sClass = 'icon-file-code';
|
||||
break;
|
||||
case Enums.FileType.Image:
|
||||
sClass = 'icon-file-image';
|
||||
break;
|
||||
case Enums.FileType.Audio:
|
||||
sClass = 'icon-file-music';
|
||||
break;
|
||||
case Enums.FileType.Video:
|
||||
sClass = 'icon-file-movie';
|
||||
break;
|
||||
case Enums.FileType.Archive:
|
||||
sClass = 'icon-file-zip';
|
||||
break;
|
||||
case Enums.FileType.Certificate:
|
||||
sClass = 'icon-file-certificate';
|
||||
break;
|
||||
case Enums.FileType.Sheet:
|
||||
sClass = 'icon-file-excel';
|
||||
break;
|
||||
case Enums.FileType.Presentation:
|
||||
sClass = 'icon-file-chart-graph';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sClass;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
* @return {string}
|
||||
*/
|
||||
AttachmentModel.prototype.iconClass = function ()
|
||||
{
|
||||
return AttachmentModel.staticIconClassHelper(this.mimeType)[0];
|
||||
return AttachmentModel.staticIconClass(this.fileType)[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
* @return {string}
|
||||
*/
|
||||
AttachmentModel.prototype.iconText = function ()
|
||||
{
|
||||
return AttachmentModel.staticIconClassHelper(this.mimeType)[1];
|
||||
return AttachmentModel.staticIconClass(this.fileType)[1];
|
||||
};
|
||||
|
||||
module.exports = AttachmentModel;
|
||||
|
|
|
@ -70,7 +70,11 @@
|
|||
return Utils.mimeContentType(this.fileName());
|
||||
}, this);
|
||||
|
||||
this.regDisposables([this.friendlySize]);
|
||||
this.fileExt = ko.computed(function () {
|
||||
return Utils.getFileExtension(this.fileName());
|
||||
}, this);
|
||||
|
||||
this.regDisposables([this.progressText, this.progressStyle, this.title, this.friendlySize, this.mimeType, this.fileExt]);
|
||||
}
|
||||
|
||||
_.extend(ComposeAttachmentModel.prototype, AbstractModel.prototype);
|
||||
|
@ -108,7 +112,8 @@
|
|||
*/
|
||||
ComposeAttachmentModel.prototype.iconClass = function ()
|
||||
{
|
||||
return AttachmentModel.staticIconClassHelper(this.mimeType())[0];
|
||||
return AttachmentModel.staticIconClass(
|
||||
AttachmentModel.staticFileType(this.fileExt(), this.mimeType()))[0];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -116,7 +121,8 @@
|
|||
*/
|
||||
ComposeAttachmentModel.prototype.iconText = function ()
|
||||
{
|
||||
return AttachmentModel.staticIconClassHelper(this.mimeType())[1];
|
||||
return AttachmentModel.staticIconClass(
|
||||
AttachmentModel.staticFileType(this.fileExt(), this.mimeType()))[1];
|
||||
};
|
||||
|
||||
module.exports = ComposeAttachmentModel;
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
* @return {boolean}
|
||||
*/
|
||||
EmailModel.prototype.validate = function ()
|
||||
{
|
||||
|
|
|
@ -74,30 +74,11 @@
|
|||
this.selected = ko.observable(false);
|
||||
this.checked = ko.observable(false);
|
||||
this.hasAttachments = ko.observable(false);
|
||||
this.attachmentsMainType = ko.observable('');
|
||||
this.attachmentsSpecData = ko.observableArray([]);
|
||||
|
||||
this.attachmentIconClass = ko.computed(function () {
|
||||
var sClass = '';
|
||||
if (this.hasAttachments())
|
||||
{
|
||||
sClass = 'icon-attachment';
|
||||
switch (this.attachmentsMainType())
|
||||
{
|
||||
case 'image':
|
||||
sClass = 'icon-image';
|
||||
break;
|
||||
case 'archive':
|
||||
sClass = 'icon-file-zip';
|
||||
break;
|
||||
case 'doc':
|
||||
sClass = 'icon-file-text';
|
||||
break;
|
||||
case 'certificate':
|
||||
sClass = 'icon-file-certificate';
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sClass;
|
||||
return AttachmentModel.staticCombinedIconClass(
|
||||
this.hasAttachments() ? this.attachmentsSpecData() : []);
|
||||
}, this);
|
||||
|
||||
this.body = null;
|
||||
|
@ -193,7 +174,7 @@
|
|||
this.selected(false);
|
||||
this.checked(false);
|
||||
this.hasAttachments(false);
|
||||
this.attachmentsMainType('');
|
||||
this.attachmentsSpecData([]);
|
||||
|
||||
this.body = null;
|
||||
this.isHtml(false);
|
||||
|
@ -287,7 +268,8 @@
|
|||
|
||||
this.dateTimeStampInUTC(Utils.pInt(oJsonMessage.DateTimeStampInUTC));
|
||||
this.hasAttachments(!!oJsonMessage.HasAttachments);
|
||||
this.attachmentsMainType(oJsonMessage.AttachmentsMainType);
|
||||
this.attachmentsSpecData(Utils.isArray(oJsonMessage.AttachmentsSpecData) ?
|
||||
oJsonMessage.AttachmentsSpecData : []);
|
||||
|
||||
this.fromEmailString(MessageHelper.emailArrayToString(this.from, true));
|
||||
this.fromClearEmailString(MessageHelper.emailArrayToStringClear(this.from));
|
||||
|
@ -337,7 +319,8 @@
|
|||
}
|
||||
|
||||
this.hasAttachments(!!oJsonMessage.HasAttachments);
|
||||
this.attachmentsMainType(oJsonMessage.AttachmentsMainType);
|
||||
this.attachmentsSpecData(Utils.isArray(oJsonMessage.AttachmentsSpecData) ?
|
||||
oJsonMessage.AttachmentsSpecData : []);
|
||||
|
||||
this.foundedCIDs = Utils.isArray(oJsonMessage.FoundedCIDs) ? oJsonMessage.FoundedCIDs : [];
|
||||
this.attachments(this.initAttachmentsFromJson(oJsonMessage.Attachments));
|
||||
|
@ -524,15 +507,6 @@
|
|||
if (this.hasAttachments())
|
||||
{
|
||||
aResult.push('withAttachments');
|
||||
switch (this.attachmentsMainType())
|
||||
{
|
||||
case 'image':
|
||||
aResult.push('imageOnlyAttachments');
|
||||
break;
|
||||
case 'archive':
|
||||
aResult.push('archiveOnlyAttachments');
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (this.newForAnimation())
|
||||
{
|
||||
|
@ -797,7 +771,7 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
* @return {string}
|
||||
*/
|
||||
MessageModel.prototype.generateUid = function ()
|
||||
{
|
||||
|
@ -850,7 +824,7 @@
|
|||
this.selected(oMessage.selected());
|
||||
this.checked(oMessage.checked());
|
||||
this.hasAttachments(oMessage.hasAttachments());
|
||||
this.attachmentsMainType(oMessage.attachmentsMainType());
|
||||
this.attachmentsSpecData(oMessage.attachmentsSpecData());
|
||||
|
||||
this.body = null;
|
||||
|
||||
|
|
|
@ -29,8 +29,6 @@
|
|||
MessageFullModel.prototype.requestHash = '';
|
||||
MessageFullModel.prototype.proxy = false;
|
||||
MessageFullModel.prototype.hasAttachments = false;
|
||||
MessageFullModel.prototype.attachmentsMainType = '';
|
||||
MessageFullModel.prototype.attachmentsClass = '';
|
||||
|
||||
MessageFullModel.prototype.clear = function ()
|
||||
{
|
||||
|
@ -43,37 +41,6 @@
|
|||
this.proxy = false;
|
||||
|
||||
this.hasAttachments = false;
|
||||
this.attachmentsMainType = '';
|
||||
this.attachmentsClass = '';
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
MessageFullModel.prototype.getAttachmentsClass = function ()
|
||||
{
|
||||
var sClass = '';
|
||||
if (this.hasAttachments)
|
||||
{
|
||||
sClass = 'icon-attachment';
|
||||
switch (this.attachmentsMainType)
|
||||
{
|
||||
case 'image':
|
||||
sClass = 'icon-image';
|
||||
break;
|
||||
case 'archive':
|
||||
sClass = 'icon-file-zip';
|
||||
break;
|
||||
case 'doc':
|
||||
sClass = 'icon-file-text';
|
||||
break;
|
||||
case 'certificate':
|
||||
sClass = 'icon-file-certificate';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return sClass;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -98,8 +65,6 @@
|
|||
this.proxy = !!oJson.ExternalProxy;
|
||||
|
||||
this.hasAttachments = !!oJson.HasAttachments;
|
||||
this.attachmentsMainType = Utils.pString(oJson.AttachmentsMainType);
|
||||
this.attachmentsClass = this.getAttachmentsClass();
|
||||
|
||||
bResult = true;
|
||||
}
|
||||
|
|
|
@ -112,6 +112,14 @@
|
|||
});
|
||||
};
|
||||
|
||||
UserAjaxUserPromises.prototype.attachmentsActions = function (sAction, aHashes, fTrigger)
|
||||
{
|
||||
return this.postRequest('AttachmentsActions', fTrigger, {
|
||||
'Action': sAction,
|
||||
'Hashes': aHashes
|
||||
});
|
||||
};
|
||||
|
||||
UserAjaxUserPromises.prototype.welcomeClose = function ()
|
||||
{
|
||||
return this.postRequest('WelcomeClose');
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
* @return {boolean}
|
||||
*/
|
||||
LicensingAdminSettings.prototype.licenseIsUnlim = function ()
|
||||
{
|
||||
|
@ -65,7 +65,7 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
* @return {string}
|
||||
*/
|
||||
LicensingAdminSettings.prototype.licenseExpiredMomentValue = function ()
|
||||
{
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
* @return {boolean}
|
||||
*/
|
||||
AccountUserStore.prototype.isRootAccount = function ()
|
||||
{
|
||||
|
|
|
@ -182,7 +182,7 @@
|
|||
|
||||
/**
|
||||
* @param {boolean=} bBoot = false
|
||||
* @returns {Array}
|
||||
* @return {Array}
|
||||
*/
|
||||
FolderUserStore.prototype.getNextFolderNames = function (bBoot)
|
||||
{
|
||||
|
|
|
@ -714,7 +714,7 @@
|
|||
|
||||
/**
|
||||
* @param {Array} aList
|
||||
* @returns {string}
|
||||
* @return {string}
|
||||
*/
|
||||
MessageUserStore.prototype.calculateMessageListHash = function (aList)
|
||||
{
|
||||
|
|
|
@ -142,7 +142,7 @@
|
|||
|
||||
NotificationUserStore.prototype.initNotificationPlayer = function ()
|
||||
{
|
||||
if (Audio && Audio.supported)
|
||||
if (Audio && Audio.supportedNotification)
|
||||
{
|
||||
this.soundNotificationIsSupported(true);
|
||||
}
|
||||
|
@ -155,7 +155,7 @@
|
|||
|
||||
NotificationUserStore.prototype.playSoundNotification = function (bSkipSetting)
|
||||
{
|
||||
if (Audio && Audio.supported && (bSkipSetting ? true : this.enableSoundNotification()))
|
||||
if (Audio && Audio.supportedNotification && (bSkipSetting ? true : this.enableSoundNotification()))
|
||||
{
|
||||
Audio.playNotification();
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
/**
|
||||
* @param {string} sEmail
|
||||
* @param {string=} sPassword
|
||||
* @returns {?}
|
||||
* @return {?}
|
||||
*/
|
||||
PgpUserStore.prototype.findPrivateKeyByEmail = function (sEmail, sPassword)
|
||||
{
|
||||
|
@ -109,7 +109,7 @@
|
|||
|
||||
/**
|
||||
* @param {string=} sPassword
|
||||
* @returns {?}
|
||||
* @return {?}
|
||||
*/
|
||||
PgpUserStore.prototype.findSelfPrivateKey = function (sPassword)
|
||||
{
|
||||
|
|
|
@ -21,6 +21,15 @@
|
|||
0% {background-position: 0 0;} 100% {background-position: 60px 0;}
|
||||
}
|
||||
|
||||
@keyframes login-form-shake {
|
||||
0% {transform: translateX(0);}
|
||||
12.5% {transform: translateX(-6px) rotateY(-5deg)}
|
||||
37.5% {transform: translateX(5px) rotateY(4deg)}
|
||||
62.5% {transform: translateX(-3px) rotateY(-2deg)}
|
||||
87.5% {transform: translateX(2px) rotateY(1deg)}
|
||||
100% {transform: translateX(0)}
|
||||
}
|
||||
|
||||
html.csstransitions.rl-started-trigger.no-mobile .b-login-content .loginFormWrapper {
|
||||
/*transform: scale(1.1);*/
|
||||
transform: translateY(-20px);
|
||||
|
@ -56,6 +65,14 @@ html.csstransitions.rl-started-trigger.no-mobile .b-login-content .loginFormWrap
|
|||
}
|
||||
}
|
||||
|
||||
&.cssanimations.csstransitions.no-mobile .b-login-content .errorAnimated {
|
||||
animation: login-form-shake 400ms ease-in-out;
|
||||
}
|
||||
|
||||
&.cssanimations.csstransitions.no-mobile .b-login-content .afterLoginHide {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* &.csstransitions.no-mobile #rl-content {
|
||||
.transition(opacity 0.3s ease-out);
|
||||
}*/
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
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;
|
||||
border-radius: 3px;
|
||||
|
||||
&.waiting {
|
||||
opacity: 0.6;
|
||||
|
@ -120,6 +120,15 @@
|
|||
color: #aaa;
|
||||
}
|
||||
|
||||
.attachmentIcon {
|
||||
&.icon-none {
|
||||
display: none;
|
||||
}
|
||||
&.icon-file-certificate {
|
||||
margin-left: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.attachmentIconText {
|
||||
display: inline-block;
|
||||
font-size: 28px;
|
||||
|
@ -131,15 +140,13 @@
|
|||
font-style: normal;
|
||||
}
|
||||
|
||||
.attachmentIcon.icon-none {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*
|
||||
.attachmentIconParent.hasPreview.isImage {
|
||||
.iconMain {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
.attachmentIconParent.hasPreview:hover {
|
||||
.iconPreview {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
perspective: 500px;
|
||||
|
||||
.descWrapper {
|
||||
|
||||
|
|
|
@ -322,7 +322,7 @@ html.rl-no-preview-pane {
|
|||
|
||||
&.e-single-line .attachmentParent {
|
||||
float: left;
|
||||
margin: 0 5px 0 0;
|
||||
margin: 0 8px 0 0;
|
||||
}
|
||||
|
||||
.senderParent {
|
||||
|
|
|
@ -230,4 +230,4 @@ html.cssanimations {
|
|||
|
||||
.command.command-disabled.hide-on-disabled-command {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
}
|
||||
|
||||
.opentip-container {
|
||||
|
||||
z-index: 2001 !important;
|
||||
.ot-content {
|
||||
font-size: 13px;
|
||||
|
@ -41,4 +42,30 @@
|
|||
&.style-rainloopErrorTip .ot-content {
|
||||
color: red;
|
||||
}
|
||||
|
||||
&.ot-show-effect-none, &.ot-hide-effect-none {
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
&.ot-show-effect-fade {
|
||||
|
||||
transition: none;
|
||||
|
||||
&.ot-hidden {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&.ot-going-to-show {
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
}
|
||||
&.ot-showing {
|
||||
opacity: 1;
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
}
|
||||
&.ot-visible {
|
||||
opacity: 1;
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,8 +34,17 @@
|
|||
this.loginError = ko.observable(false);
|
||||
this.passwordError = ko.observable(false);
|
||||
|
||||
this.loginErrorAnimation = ko.observable(false).extend({'falseTimeout': 500});
|
||||
this.passwordErrorAnimation = ko.observable(false).extend({'falseTimeout': 500});
|
||||
|
||||
this.loginFocus = ko.observable(false);
|
||||
|
||||
this.formHidden = ko.observable(false);
|
||||
|
||||
this.formError = ko.computed(function () {
|
||||
return this.loginErrorAnimation() || this.passwordErrorAnimation();
|
||||
}, this);
|
||||
|
||||
this.login.subscribe(function () {
|
||||
this.loginError(false);
|
||||
}, this);
|
||||
|
@ -44,6 +53,14 @@
|
|||
this.passwordError(false);
|
||||
}, this);
|
||||
|
||||
this.loginError.subscribe(function (bV) {
|
||||
this.loginErrorAnimation(!!bV);
|
||||
}, this);
|
||||
|
||||
this.passwordError.subscribe(function (bV) {
|
||||
this.passwordErrorAnimation(!!bV);
|
||||
}, this);
|
||||
|
||||
this.submitRequest = ko.observable(false);
|
||||
this.submitError = ko.observable('');
|
||||
|
||||
|
@ -51,6 +68,9 @@
|
|||
|
||||
Utils.triggerAutocompleteInputChange();
|
||||
|
||||
this.loginError(false);
|
||||
this.passwordError(false);
|
||||
|
||||
this.loginError('' === Utils.trim(this.login()));
|
||||
this.passwordError('' === Utils.trim(this.password()));
|
||||
|
||||
|
@ -67,6 +87,7 @@
|
|||
{
|
||||
if (oData.Result)
|
||||
{
|
||||
this.formHidden(true);
|
||||
require('App/Admin').loginAndLogoutReload(true);
|
||||
}
|
||||
else if (oData.ErrorCode)
|
||||
|
|
|
@ -137,7 +137,7 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
* @return {boolean}
|
||||
*/
|
||||
ActivatePopupView.prototype.validateSubscriptionKey = function ()
|
||||
{
|
||||
|
|
|
@ -995,7 +995,7 @@
|
|||
*
|
||||
* @param {Array} aList
|
||||
* @param {boolean} bFriendly
|
||||
* @returns {string}
|
||||
* @return {string}
|
||||
*/
|
||||
ComposePopupView.prototype.emailArrayToStringLineHelper = function (aList, bFriendly)
|
||||
{
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
|
||||
this.additionalCode = ko.observable('');
|
||||
this.additionalCode.error = ko.observable(false);
|
||||
this.additionalCode.errorAnimation = ko.observable(false).extend({'falseTimeout': 500});
|
||||
this.additionalCode.focused = ko.observable(false);
|
||||
this.additionalCode.visibility = ko.observable(false);
|
||||
this.additionalCodeSignMe = ko.observable(false);
|
||||
|
@ -56,6 +57,16 @@
|
|||
this.emailError = ko.observable(false);
|
||||
this.passwordError = ko.observable(false);
|
||||
|
||||
this.emailErrorAnimation = ko.observable(false).extend({'falseTimeout': 500});
|
||||
this.passwordErrorAnimation = ko.observable(false).extend({'falseTimeout': 500});
|
||||
|
||||
this.formHidden = ko.observable(false);
|
||||
|
||||
this.formError = ko.computed(function () {
|
||||
return this.emailErrorAnimation() || this.passwordErrorAnimation() ||
|
||||
(this.additionalCode.visibility() && this.additionalCode.errorAnimation());
|
||||
}, this);
|
||||
|
||||
this.emailFocus = ko.observable(false);
|
||||
this.passwordFocus = ko.observable(false);
|
||||
this.submitFocus = ko.observable(false);
|
||||
|
@ -78,6 +89,18 @@
|
|||
this.additionalCode.error(false);
|
||||
}, this);
|
||||
|
||||
this.emailError.subscribe(function (bV) {
|
||||
this.emailErrorAnimation(!!bV);
|
||||
}, this);
|
||||
|
||||
this.passwordError.subscribe(function (bV) {
|
||||
this.passwordErrorAnimation(!!bV);
|
||||
}, this);
|
||||
|
||||
this.additionalCode.error.subscribe(function (bV) {
|
||||
this.additionalCode.errorAnimation(!!bV);
|
||||
}, this);
|
||||
|
||||
this.submitRequest = ko.observable(false);
|
||||
this.submitError = ko.observable('');
|
||||
this.submitErrorAddidional = ko.observable('');
|
||||
|
@ -115,16 +138,34 @@
|
|||
|
||||
Utils.triggerAutocompleteInputChange();
|
||||
|
||||
this.emailError(false);
|
||||
this.passwordError(false);
|
||||
|
||||
this.emailError('' === Utils.trim(this.email()));
|
||||
this.passwordError('' === Utils.trim(this.password()));
|
||||
|
||||
if (this.additionalCode.visibility())
|
||||
{
|
||||
this.additionalCode.error(false);
|
||||
this.additionalCode.error('' === Utils.trim(this.additionalCode()));
|
||||
}
|
||||
|
||||
if (this.emailError() || this.passwordError() || this.additionalCode.error())
|
||||
if (this.emailError() || this.passwordError() ||
|
||||
(this.additionalCode.visibility() && this.additionalCode.error()))
|
||||
{
|
||||
switch (true)
|
||||
{
|
||||
case this.emailError():
|
||||
this.emailFocus(true);
|
||||
break;
|
||||
case this.passwordError():
|
||||
this.passwordFocus(true);
|
||||
break;
|
||||
case this.additionalCode.visibility() && this.additionalCode.error():
|
||||
this.additionalCode.focused(true);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -172,10 +213,12 @@
|
|||
}
|
||||
else if (oData.Admin)
|
||||
{
|
||||
this.formHidden(true);
|
||||
require('App/User').redirectToAdminPanel();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.formHidden(true);
|
||||
require('App/User').loginAndLogoutReload(false);
|
||||
}
|
||||
}
|
||||
|
@ -339,6 +382,8 @@
|
|||
if (0 === iErrorCode)
|
||||
{
|
||||
self.submitRequest(true);
|
||||
self.formHidden(true);
|
||||
|
||||
require('App/User').loginAndLogoutReload(false);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -374,7 +374,7 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
* @return {string}
|
||||
*/
|
||||
MessageListMailBoxUserView.prototype.printableMessageCountForDeletion = function ()
|
||||
{
|
||||
|
|
|
@ -82,6 +82,10 @@
|
|||
this.allowAttachmnetControls = ko.observable(false);
|
||||
this.showAttachmnetControls = ko.observable(false);
|
||||
|
||||
this.downloadAsZipLoading = ko.observable(false);
|
||||
this.saveToOwnCloudLoading = ko.observable(false);
|
||||
this.saveToDropboxLoading = ko.observable(false);
|
||||
|
||||
this.showAttachmnetControls.subscribe(function (bV) {
|
||||
if (this.message())
|
||||
{
|
||||
|
@ -115,12 +119,6 @@
|
|||
this.moreDropdownTrigger = ko.observable(false);
|
||||
this.messageDomFocused = ko.observable(false).extend({'rateLimit': 0});
|
||||
|
||||
// TODO
|
||||
// ko.computed(function () {
|
||||
// window.console.log('focus:' + AppStore.focusedState() + ', dom:' +
|
||||
// this.messageDomFocused() + ', key:' + Globals.keyScope() + ' ~ ' + Globals.keyScopeReal());
|
||||
// }, this).extend({'throttle': 1});
|
||||
|
||||
this.messageVisibility = ko.computed(function () {
|
||||
return !this.messageLoadingThrottle() && !!this.message();
|
||||
}, this);
|
||||
|
@ -759,9 +757,20 @@
|
|||
}
|
||||
|
||||
var oAttachment = ko.dataFor(this);
|
||||
if (oAttachment && oAttachment.isMp3() && Audio.supported)
|
||||
if (oAttachment && Audio.supported)
|
||||
{
|
||||
Audio.playMp3(oAttachment.linkDownload(), oAttachment.fileName);
|
||||
switch (true)
|
||||
{
|
||||
case Audio.supportedMp3 && oAttachment.isMp3():
|
||||
Audio.playMp3(oAttachment.linkDownload(), oAttachment.fileName);
|
||||
break;
|
||||
case Audio.supportedOgg && oAttachment.isOgg():
|
||||
Audio.playOgg(oAttachment.linkDownload(), oAttachment.fileName);
|
||||
break;
|
||||
case Audio.supportedWav && oAttachment.isWav():
|
||||
Audio.playWav(oAttachment.linkDownload(), oAttachment.fileName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
.on('click', '.thread-list .more-threads', function (e) {
|
||||
|
@ -1107,6 +1116,40 @@
|
|||
}
|
||||
};
|
||||
|
||||
MessageViewMailBoxUserView.prototype.getAttachmentsHashes = function ()
|
||||
{
|
||||
return _.compact(_.map(this.message() ? this.message().attachments() : [], function (oItem) {
|
||||
return oItem && oItem.checked() ? oItem.download : '';
|
||||
}));
|
||||
};
|
||||
|
||||
MessageViewMailBoxUserView.prototype.downloadAsZip = function ()
|
||||
{
|
||||
var aHashes = this.getAttachmentsHashes();
|
||||
if (0 < aHashes.length)
|
||||
{
|
||||
Promises.attachmentsActions('Zip', aHashes, this.downloadAsZipLoading);
|
||||
}
|
||||
};
|
||||
|
||||
MessageViewMailBoxUserView.prototype.saveToOwnCloud = function ()
|
||||
{
|
||||
var aHashes = this.getAttachmentsHashes();
|
||||
if (0 < aHashes.length)
|
||||
{
|
||||
Promises.attachmentsActions('OwnCloud', aHashes, this.saveToOwnCloudLoading);
|
||||
}
|
||||
};
|
||||
|
||||
MessageViewMailBoxUserView.prototype.saveToDropbox = function ()
|
||||
{
|
||||
var aHashes = this.getAttachmentsHashes();
|
||||
if (0 < aHashes.length)
|
||||
{
|
||||
Promises.attachmentsActions('Dropbox', aHashes, this.saveToDropboxLoading);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {MessageModel} oMessage
|
||||
*/
|
||||
|
@ -1119,7 +1162,7 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
* @return {string}
|
||||
*/
|
||||
MessageViewMailBoxUserView.prototype.printableCheckedMessageCount = function ()
|
||||
{
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "RainLoop",
|
||||
"title": "RainLoop Webmail",
|
||||
"version": "1.8.3",
|
||||
"release": "298",
|
||||
"release": "301",
|
||||
"description": "Simple, modern & fast web-based email client",
|
||||
"homepage": "http://rainloop.net",
|
||||
"main": "gulpfile.js",
|
||||
|
|
|
@ -58,62 +58,17 @@ class AttachmentCollection extends \MailSo\Base\Collection
|
|||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @return array
|
||||
*/
|
||||
public function ImageCount()
|
||||
public function SpecData()
|
||||
{
|
||||
$aList = $this->FilterList(function ($oAttachment) {
|
||||
return $oAttachment && $oAttachment->IsImage();
|
||||
return $this->MapList(function ($oAttachment) {
|
||||
if ($oAttachment)
|
||||
{
|
||||
return array($oAttachment->FileName(true), $oAttachment->MimeType());
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
return \is_array($aList) ? \count($aList) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function ArchiveCount()
|
||||
{
|
||||
$aList = $this->FilterList(function ($oAttachment) {
|
||||
return $oAttachment && $oAttachment->IsArchive();
|
||||
});
|
||||
|
||||
return \is_array($aList) ? \count($aList) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function PdfCount()
|
||||
{
|
||||
$aList = $this->FilterList(function ($oAttachment) {
|
||||
return $oAttachment && $oAttachment->IsPdf();
|
||||
});
|
||||
|
||||
return \is_array($aList) ? \count($aList) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function DocCount()
|
||||
{
|
||||
$aList = $this->FilterList(function ($oAttachment) {
|
||||
return $oAttachment && $oAttachment->IsDoc();
|
||||
});
|
||||
|
||||
return \is_array($aList) ? \count($aList) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function CertificateCount()
|
||||
{
|
||||
$aList = $this->FilterList(function ($oAttachment) {
|
||||
return $oAttachment && $oAttachment->IsPgpSignature();
|
||||
});
|
||||
|
||||
return \is_array($aList) ? \count($aList) : 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2630,6 +2630,17 @@ class Actions
|
|||
return $this->FalseResponse(__FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*
|
||||
* @throws \MailSo\Base\Exceptions\Exception
|
||||
*/
|
||||
public function DoAttachmentsActions()
|
||||
{
|
||||
\sleep(1);
|
||||
return $this->TrueResponse(__FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*
|
||||
|
@ -9079,28 +9090,7 @@ class Actions
|
|||
$iAttachmentsCount = $oAttachments ? $oAttachments->Count() : 0;
|
||||
|
||||
$mResult['HasAttachments'] = 0 < $iAttachmentsCount;
|
||||
$mResult['AttachmentsMainType'] = '';
|
||||
if (0 < $iAttachmentsCount)
|
||||
{
|
||||
switch (true)
|
||||
{
|
||||
case $iAttachmentsCount === $oAttachments->ImageCount():
|
||||
$mResult['AttachmentsMainType'] = 'image';
|
||||
break;
|
||||
case $iAttachmentsCount === $oAttachments->ArchiveCount():
|
||||
$mResult['AttachmentsMainType'] = 'archive';
|
||||
break;
|
||||
case $iAttachmentsCount === $oAttachments->PdfCount():
|
||||
$mResult['AttachmentsMainType'] = 'pdf';
|
||||
break;
|
||||
case $iAttachmentsCount === $oAttachments->DocCount():
|
||||
$mResult['AttachmentsMainType'] = 'doc';
|
||||
break;
|
||||
case $iAttachmentsCount === $oAttachments->CertificateCount():
|
||||
$mResult['AttachmentsMainType'] = 'certificate';
|
||||
break;
|
||||
}
|
||||
}
|
||||
$mResult['AttachmentsSpecData'] = $mResult['HasAttachments'] ? $oAttachments->SpecData() : array();
|
||||
|
||||
$sSubject = $mResult['Subject'];
|
||||
$mResult['Hash'] = \md5($mResult['Folder'].$mResult['Uid']);
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
<div class="b-login-content">
|
||||
<div class="loginFormWrapper">
|
||||
<div class="loginFormWrapper" data-bind="css: {'afterLoginHide': formHidden}">
|
||||
<center>
|
||||
<div class="alert alertError" data-bind="visible: '' !== submitError()">
|
||||
<button type="button" class="close" data-bind="click: function () { submitError('') }">×</button>
|
||||
<span data-bind="text: submitError"></span>
|
||||
</div>
|
||||
<form class="wrapper loginForm thm-login" action="#/" data-bind="submit: submitForm">
|
||||
<div class="controls" data-bind="css: {'error': loginError}">
|
||||
<form class="wrapper loginForm thm-login" action="#/" data-bind="submit: submitForm, css: {'errorAnimated': formError}">
|
||||
<div class="controls" data-bind="css: {'error': loginError, 'animated': loginErrorAnimation}">
|
||||
<div class="input-append">
|
||||
<input type="text" class="input-block-level inputLogin checkAutocomplete" name="RainLoopAdminLogin" id="RainLoopAdminLogin"
|
||||
<input type="text" class="input-block-level inputLogin checkAutocomplete"
|
||||
name="RainLoopAdminLogin" id="RainLoopAdminLogin"
|
||||
style="padding-right: 35px;"
|
||||
autocorrect="off" autocapitalize="off" spellcheck="false" data-i18n="[placeholder]LOGIN/LABEL_LOGIN"
|
||||
data-bind="textInput: login, hasFocus: loginFocus" />
|
||||
<span class="add-on">
|
||||
|
@ -16,9 +18,11 @@
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls" data-bind="css: {'error': passwordError}">
|
||||
<div class="controls" data-bind="css: {'error': passwordError, 'animated': passwordErrorAnimation}">
|
||||
<div class="input-append">
|
||||
<input type="password" class="input-block-level inputPassword checkAutocomplete" placeholder="Password" name="RainLoopAdminPassword" id="RainLoopAdminPassword"
|
||||
<input type="password" class="input-block-level inputPassword checkAutocomplete"
|
||||
placeholder="Password" name="RainLoopAdminPassword" id="RainLoopAdminPassword"
|
||||
style="padding-right: 35px;"
|
||||
autocorrect="off" autocapitalize="off" spellcheck="false" data-i18n="[placeholder]LOGIN/LABEL_PASSWORD"
|
||||
data-bind="textInput: password" />
|
||||
<span class="add-on">
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="b-login-content">
|
||||
<div class="loginFormWrapper">
|
||||
<div class="loginFormWrapper" data-bind="css: {'afterLoginHide': formHidden}">
|
||||
<center>
|
||||
{{INCLUDE/BeforeLogo/PLACE}}
|
||||
<!-- ko if: logoImg -->
|
||||
|
@ -19,12 +19,13 @@
|
|||
<span data-bind="text: submitErrorAddidional"></span>
|
||||
</div>
|
||||
</div>
|
||||
<form class="wrapper loginForm thm-login" action="#/" data-bind="submit: submitForm">
|
||||
<form class="wrapper loginForm thm-login" action="#/" data-bind="submit: submitForm, css: {'errorAnimated': formError}">
|
||||
{{INCLUDE/TopControlGroup/PLACE}}
|
||||
<div class="controls" data-bind="css: {'error': emailError}">
|
||||
<div class="controls" data-bind="css: {'error': emailError, 'animated': emailErrorAnimation}">
|
||||
<div class="input-append">
|
||||
<input type="email" class="i18n input-block-level inputEmail checkAutocomplete"
|
||||
name="RainLoopEmail" id="RainLoopEmail"
|
||||
style="padding-right: 35px;"
|
||||
autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
data-bind="textInput: email, hasFocus: emailFocus" data-i18n="[placeholder]LOGIN/LABEL_EMAIL" />
|
||||
<span class="add-on">
|
||||
|
@ -32,9 +33,11 @@
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls" data-bind="css: {'error': passwordError}">
|
||||
<div class="controls" data-bind="css: {'error': passwordError, 'animated': passwordErrorAnimation}">
|
||||
<div class="input-append">
|
||||
<input type="password" class="i18n input-block-level inputPassword checkAutocomplete" name="RainLoopPassword" id="RainLoopPassword"
|
||||
<input type="password" class="i18n input-block-level inputPassword checkAutocomplete"
|
||||
name="RainLoopPassword" id="RainLoopPassword"
|
||||
style="padding-right: 35px;"
|
||||
autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
data-bind="textInput: password, hasFocus: passwordFocus" data-i18n="[placeholder]LOGIN/LABEL_PASSWORD" />
|
||||
<span class="add-on">
|
||||
|
@ -42,9 +45,11 @@
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls" data-bind="visible: additionalCode.visibility(), css: {'error': additionalCode.error}">
|
||||
<div class="controls" data-bind="visible: additionalCode.visibility(), css: {'error': additionalCode.error, 'animated': additionalCode.errorAnimation}">
|
||||
<div class="input-append">
|
||||
<input type="text" class="i18n input-block-level inputAdditionalCode" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
<input type="text" class="i18n input-block-level inputAdditionalCode"
|
||||
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
style="padding-right: 35px;"
|
||||
data-bind="textInput: additionalCode, hasFocus: additionalCode.focused" data-i18n="[placeholder]LOGIN/LABEL_VERIFICATION_CODE" />
|
||||
<span class="add-on">
|
||||
<i class="icon-key"></i>
|
||||
|
|
|
@ -430,14 +430,31 @@
|
|||
<i class="icon-cog controls-handle" data-bind="visible: allowAttachmnetControls() && !showAttachmnetControls(), click: function () { showAttachmnetControls(true) }"></i>
|
||||
</div>
|
||||
<div class="attachmentsControls"
|
||||
data-bind="visible: showAttachmnetControls() && message() && message().hasVisibleAttachments()">
|
||||
<i class="icon-file-zip"></i>
|
||||
data-bind="visible: showAttachmnetControls() && message() && message().hasVisibleAttachments()">
|
||||
|
||||
<i class="icon-file-zip"
|
||||
data-bind="css: {'icon-file-zip': !downloadAsZipLoading(), 'icon-spinner animated': downloadAsZipLoading()}"></i>
|
||||
|
||||
|
||||
<span class="g-ui-link">Download as zip</span>
|
||||
<span class="g-ui-link" data-bind="click: downloadAsZip">Download as zip</span>
|
||||
|
||||
|
||||
<i class="icon-cloud-up"></i>
|
||||
|
||||
<i class="icon-cloud-up"
|
||||
data-bind="css: {'icon-cloud-up': !saveToOwnCloudLoading(), 'icon-spinner animated': saveToOwnCloudLoading()}"></i>
|
||||
|
||||
|
||||
<span class="g-ui-link">Save to ownCloud</span>
|
||||
<span class="g-ui-link" data-bind="click: saveToOwnCloud">Save to ownCloud</span>
|
||||
|
||||
|
||||
|
||||
<i class="icon-dropbox"
|
||||
data-bind="css: {'icon-dropbox': !saveToDropboxLoading(), 'icon-spinner animated': saveToDropboxLoading()}"></i>
|
||||
|
||||
|
||||
<span class="g-ui-link" data-bind="click: saveToDropbox">Save to Dropbox</span>
|
||||
|
||||
<!-- // --->
|
||||
<button type="button" class="close" style="margin-right: 5px;"
|
||||
data-bind="click: function () { showAttachmnetControls(false); }">×</button>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue