mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-11 00:14:50 +03:00
Fixed Opening an email with specific content „hangs” RainLoop in the browser (Closes #308)
Code refactoring
This commit is contained in:
parent
af43329902
commit
7a374ebe03
40 changed files with 1100 additions and 181 deletions
41
dev/Model/Account.js
Normal file
41
dev/Model/Account.js
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
(function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
var
|
||||
ko = require('ko'),
|
||||
|
||||
Utils = require('Common/Utils')
|
||||
;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*
|
||||
* @param {string} sEmail
|
||||
* @param {boolean=} bCanBeDelete = true
|
||||
*/
|
||||
function AccountModel(sEmail, bCanBeDelete)
|
||||
{
|
||||
this.email = sEmail;
|
||||
|
||||
this.deleteAccess = ko.observable(false);
|
||||
this.canBeDalete = ko.observable(Utils.isUnd(bCanBeDelete) ? true : !!bCanBeDelete);
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
AccountModel.prototype.email = '';
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
AccountModel.prototype.changeAccountLink = function ()
|
||||
{
|
||||
return require('Common/LinkBuilder').change(this.email);
|
||||
};
|
||||
|
||||
module.exports = AccountModel;
|
||||
|
||||
}());
|
||||
252
dev/Model/Attachment.js
Normal file
252
dev/Model/Attachment.js
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
|
||||
(function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
var
|
||||
window = require('window'),
|
||||
|
||||
Globals = require('Common/Globals'),
|
||||
Utils = require('Common/Utils'),
|
||||
LinkBuilder = require('Common/LinkBuilder')
|
||||
;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
function AttachmentModel()
|
||||
{
|
||||
this.mimeType = '';
|
||||
this.fileName = '';
|
||||
this.estimatedSize = 0;
|
||||
this.friendlySize = '';
|
||||
this.isInline = false;
|
||||
this.isLinked = false;
|
||||
this.cid = '';
|
||||
this.cidWithOutTags = '';
|
||||
this.contentLocation = '';
|
||||
this.download = '';
|
||||
this.folder = '';
|
||||
this.uid = '';
|
||||
this.mimeIndex = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param {AjaxJsonAttachment} oJsonAttachment
|
||||
* @return {?AttachmentModel}
|
||||
*/
|
||||
AttachmentModel.newInstanceFromJson = function (oJsonAttachment)
|
||||
{
|
||||
var oAttachmentModel = new AttachmentModel();
|
||||
return oAttachmentModel.initByJson(oJsonAttachment) ? oAttachmentModel : null;
|
||||
};
|
||||
|
||||
AttachmentModel.prototype.mimeType = '';
|
||||
AttachmentModel.prototype.fileName = '';
|
||||
AttachmentModel.prototype.estimatedSize = 0;
|
||||
AttachmentModel.prototype.friendlySize = '';
|
||||
AttachmentModel.prototype.isInline = false;
|
||||
AttachmentModel.prototype.isLinked = false;
|
||||
AttachmentModel.prototype.cid = '';
|
||||
AttachmentModel.prototype.cidWithOutTags = '';
|
||||
AttachmentModel.prototype.contentLocation = '';
|
||||
AttachmentModel.prototype.download = '';
|
||||
AttachmentModel.prototype.folder = '';
|
||||
AttachmentModel.prototype.uid = '';
|
||||
AttachmentModel.prototype.mimeIndex = '';
|
||||
|
||||
/**
|
||||
* @param {AjaxJsonAttachment} oJsonAttachment
|
||||
*/
|
||||
AttachmentModel.prototype.initByJson = function (oJsonAttachment)
|
||||
{
|
||||
var bResult = false;
|
||||
if (oJsonAttachment && 'Object/Attachment' === oJsonAttachment['@Object'])
|
||||
{
|
||||
this.mimeType = (oJsonAttachment.MimeType || '').toLowerCase();
|
||||
this.fileName = oJsonAttachment.FileName;
|
||||
this.estimatedSize = Utils.pInt(oJsonAttachment.EstimatedSize);
|
||||
this.isInline = !!oJsonAttachment.IsInline;
|
||||
this.isLinked = !!oJsonAttachment.IsLinked;
|
||||
this.cid = oJsonAttachment.CID;
|
||||
this.contentLocation = oJsonAttachment.ContentLocation;
|
||||
this.download = oJsonAttachment.Download;
|
||||
|
||||
this.folder = oJsonAttachment.Folder;
|
||||
this.uid = oJsonAttachment.Uid;
|
||||
this.mimeIndex = oJsonAttachment.MimeIndex;
|
||||
|
||||
this.friendlySize = Utils.friendlySize(this.estimatedSize);
|
||||
this.cidWithOutTags = this.cid.replace(/^<+/, '').replace(/>+$/, '');
|
||||
|
||||
bResult = true;
|
||||
}
|
||||
|
||||
return bResult;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {boolean}
|
||||
*/
|
||||
AttachmentModel.prototype.isImage = function ()
|
||||
{
|
||||
return -1 < Utils.inArray(this.mimeType.toLowerCase(),
|
||||
['image/png', 'image/jpg', 'image/jpeg', 'image/gif']
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {boolean}
|
||||
*/
|
||||
AttachmentModel.prototype.isText = function ()
|
||||
{
|
||||
return 'text/' === this.mimeType.substr(0, 5) &&
|
||||
-1 === Utils.inArray(this.mimeType, ['text/html']);
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {boolean}
|
||||
*/
|
||||
AttachmentModel.prototype.isPdf = function ()
|
||||
{
|
||||
return Globals.bAllowPdfPreview && 'application/pdf' === this.mimeType;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
AttachmentModel.prototype.linkDownload = function ()
|
||||
{
|
||||
return LinkBuilder.attachmentDownload(this.download);
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
AttachmentModel.prototype.linkPreview = function ()
|
||||
{
|
||||
return LinkBuilder.attachmentPreview(this.download);
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
AttachmentModel.prototype.linkPreviewAsPlain = function ()
|
||||
{
|
||||
return LinkBuilder.attachmentPreviewAsPlain(this.download);
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
AttachmentModel.prototype.generateTransferDownloadUrl = function ()
|
||||
{
|
||||
var sLink = this.linkDownload();
|
||||
if ('http' !== sLink.substr(0, 4))
|
||||
{
|
||||
sLink = window.location.protocol + '//' + window.location.host + window.location.pathname + sLink;
|
||||
}
|
||||
|
||||
return this.mimeType + ':' + this.fileName + ':' + sLink;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {AttachmentModel} oAttachment
|
||||
* @param {*} oEvent
|
||||
* @return {boolean}
|
||||
*/
|
||||
AttachmentModel.prototype.eventDragStart = function (oAttachment, oEvent)
|
||||
{
|
||||
var oLocalEvent = oEvent.originalEvent || oEvent;
|
||||
if (oAttachment && oLocalEvent && oLocalEvent.dataTransfer && oLocalEvent.dataTransfer.setData)
|
||||
{
|
||||
oLocalEvent.dataTransfer.setData('DownloadURL', this.generateTransferDownloadUrl());
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
AttachmentModel.prototype.iconClass = function ()
|
||||
{
|
||||
var
|
||||
aParts = this.mimeType.toLocaleString().split('/'),
|
||||
sClass = 'icon-file'
|
||||
;
|
||||
|
||||
if (aParts && aParts[1])
|
||||
{
|
||||
if ('image' === aParts[0])
|
||||
{
|
||||
sClass = 'icon-file-image';
|
||||
}
|
||||
else if ('text' === aParts[0])
|
||||
{
|
||||
sClass = 'icon-file-text';
|
||||
}
|
||||
else if ('audio' === aParts[0])
|
||||
{
|
||||
sClass = 'icon-file-music';
|
||||
}
|
||||
else if ('video' === aParts[0])
|
||||
{
|
||||
sClass = 'icon-file-movie';
|
||||
}
|
||||
else if (-1 < Utils.inArray(aParts[1],
|
||||
['zip', '7z', 'tar', 'rar', 'gzip', 'bzip', 'bzip2', 'x-zip', 'x-7z', 'x-rar', 'x-tar', 'x-gzip', 'x-bzip', 'x-bzip2', 'x-zip-compressed', 'x-7z-compressed', 'x-rar-compressed']))
|
||||
{
|
||||
sClass = 'icon-file-zip';
|
||||
}
|
||||
// else if (-1 < Utils.inArray(aParts[1],
|
||||
// ['pdf', 'x-pdf']))
|
||||
// {
|
||||
// sClass = 'icon-file-pdf';
|
||||
// }
|
||||
// else if (-1 < Utils.inArray(aParts[1], [
|
||||
// 'exe', 'x-exe', 'x-winexe', 'bat'
|
||||
// ]))
|
||||
// {
|
||||
// sClass = 'icon-console';
|
||||
// }
|
||||
else if (-1 < Utils.inArray(aParts[1], [
|
||||
'rtf', 'msword', 'vnd.msword', 'vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'vnd.openxmlformats-officedocument.wordprocessingml.template',
|
||||
'vnd.ms-word.document.macroEnabled.12',
|
||||
'vnd.ms-word.template.macroEnabled.12'
|
||||
]))
|
||||
{
|
||||
sClass = 'icon-file-text';
|
||||
}
|
||||
else if (-1 < Utils.inArray(aParts[1], [
|
||||
'excel', 'ms-excel', 'vnd.ms-excel',
|
||||
'vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'vnd.openxmlformats-officedocument.spreadsheetml.template',
|
||||
'vnd.ms-excel.sheet.macroEnabled.12',
|
||||
'vnd.ms-excel.template.macroEnabled.12',
|
||||
'vnd.ms-excel.addin.macroEnabled.12',
|
||||
'vnd.ms-excel.sheet.binary.macroEnabled.12'
|
||||
]))
|
||||
{
|
||||
sClass = 'icon-file-excel';
|
||||
}
|
||||
else if (-1 < Utils.inArray(aParts[1], [
|
||||
'powerpoint', 'ms-powerpoint', 'vnd.ms-powerpoint',
|
||||
'vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
'vnd.openxmlformats-officedocument.presentationml.template',
|
||||
'vnd.openxmlformats-officedocument.presentationml.slideshow',
|
||||
'vnd.ms-powerpoint.addin.macroEnabled.12',
|
||||
'vnd.ms-powerpoint.presentation.macroEnabled.12',
|
||||
'vnd.ms-powerpoint.template.macroEnabled.12',
|
||||
'vnd.ms-powerpoint.slideshow.macroEnabled.12'
|
||||
]))
|
||||
{
|
||||
sClass = 'icon-file-chart-graph';
|
||||
}
|
||||
}
|
||||
|
||||
return sClass;
|
||||
};
|
||||
|
||||
module.exports = AttachmentModel;
|
||||
|
||||
}());
|
||||
76
dev/Model/ComposeAttachment.js
Normal file
76
dev/Model/ComposeAttachment.js
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
|
||||
(function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
var
|
||||
ko = require('ko'),
|
||||
|
||||
Utils = require('Common/Utils')
|
||||
;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {string} sId
|
||||
* @param {string} sFileName
|
||||
* @param {?number=} nSize
|
||||
* @param {boolean=} bInline
|
||||
* @param {boolean=} bLinked
|
||||
* @param {string=} sCID
|
||||
* @param {string=} sContentLocation
|
||||
*/
|
||||
function ComposeAttachmentModel(sId, sFileName, nSize, bInline, bLinked, sCID, sContentLocation)
|
||||
{
|
||||
this.id = sId;
|
||||
this.isInline = Utils.isUnd(bInline) ? false : !!bInline;
|
||||
this.isLinked = Utils.isUnd(bLinked) ? false : !!bLinked;
|
||||
this.CID = Utils.isUnd(sCID) ? '' : sCID;
|
||||
this.contentLocation = Utils.isUnd(sContentLocation) ? '' : sContentLocation;
|
||||
this.fromMessage = false;
|
||||
|
||||
this.fileName = ko.observable(sFileName);
|
||||
this.size = ko.observable(Utils.isUnd(nSize) ? null : nSize);
|
||||
this.tempName = ko.observable('');
|
||||
|
||||
this.progress = ko.observable('');
|
||||
this.error = ko.observable('');
|
||||
this.waiting = ko.observable(true);
|
||||
this.uploading = ko.observable(false);
|
||||
this.enabled = ko.observable(true);
|
||||
|
||||
this.friendlySize = ko.computed(function () {
|
||||
var mSize = this.size();
|
||||
return null === mSize ? '' : Utils.friendlySize(this.size());
|
||||
}, this);
|
||||
}
|
||||
|
||||
ComposeAttachmentModel.prototype.id = '';
|
||||
ComposeAttachmentModel.prototype.isInline = false;
|
||||
ComposeAttachmentModel.prototype.isLinked = false;
|
||||
ComposeAttachmentModel.prototype.CID = '';
|
||||
ComposeAttachmentModel.prototype.contentLocation = '';
|
||||
ComposeAttachmentModel.prototype.fromMessage = false;
|
||||
ComposeAttachmentModel.prototype.cancel = Utils.emptyFunction;
|
||||
|
||||
/**
|
||||
* @param {AjaxJsonComposeAttachment} oJsonAttachment
|
||||
*/
|
||||
ComposeAttachmentModel.prototype.initByUploadJson = function (oJsonAttachment)
|
||||
{
|
||||
var bResult = false;
|
||||
if (oJsonAttachment)
|
||||
{
|
||||
this.fileName(oJsonAttachment.Name);
|
||||
this.size(Utils.isUnd(oJsonAttachment.Size) ? 0 : Utils.pInt(oJsonAttachment.Size));
|
||||
this.tempName(Utils.isUnd(oJsonAttachment.TempName) ? '' : oJsonAttachment.TempName);
|
||||
this.isInline = false;
|
||||
|
||||
bResult = true;
|
||||
}
|
||||
|
||||
return bResult;
|
||||
};
|
||||
|
||||
module.exports = ComposeAttachmentModel;
|
||||
|
||||
}());
|
||||
141
dev/Model/Contact.js
Normal file
141
dev/Model/Contact.js
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
|
||||
(function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
var
|
||||
_ = require('_'),
|
||||
ko = require('ko'),
|
||||
|
||||
Enums = require('Common/Enums'),
|
||||
Utils = require('Common/Utils'),
|
||||
LinkBuilder = require('Common/LinkBuilder')
|
||||
;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
function ContactModel()
|
||||
{
|
||||
this.idContact = 0;
|
||||
this.display = '';
|
||||
this.properties = [];
|
||||
this.tags = '';
|
||||
this.readOnly = false;
|
||||
|
||||
this.focused = ko.observable(false);
|
||||
this.selected = ko.observable(false);
|
||||
this.checked = ko.observable(false);
|
||||
this.deleted = ko.observable(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array|null}
|
||||
*/
|
||||
ContactModel.prototype.getNameAndEmailHelper = function ()
|
||||
{
|
||||
var
|
||||
sName = '',
|
||||
sEmail = ''
|
||||
;
|
||||
|
||||
if (Utils.isNonEmptyArray(this.properties))
|
||||
{
|
||||
_.each(this.properties, function (aProperty) {
|
||||
if (aProperty)
|
||||
{
|
||||
if (Enums.ContactPropertyType.FirstName === aProperty[0])
|
||||
{
|
||||
sName = Utils.trim(aProperty[1] + ' ' + sName);
|
||||
}
|
||||
else if (Enums.ContactPropertyType.LastName === aProperty[0])
|
||||
{
|
||||
sName = Utils.trim(sName + ' ' + aProperty[1]);
|
||||
}
|
||||
else if ('' === sEmail && Enums.ContactPropertyType.Email === aProperty[0])
|
||||
{
|
||||
sEmail = aProperty[1];
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
|
||||
return '' === sEmail ? null : [sEmail, sName];
|
||||
};
|
||||
|
||||
ContactModel.prototype.parse = function (oItem)
|
||||
{
|
||||
var bResult = false;
|
||||
if (oItem && 'Object/Contact' === oItem['@Object'])
|
||||
{
|
||||
this.idContact = Utils.pInt(oItem['IdContact']);
|
||||
this.display = Utils.pString(oItem['Display']);
|
||||
this.readOnly = !!oItem['ReadOnly'];
|
||||
this.tags = '';
|
||||
|
||||
if (Utils.isNonEmptyArray(oItem['Properties']))
|
||||
{
|
||||
_.each(oItem['Properties'], function (oProperty) {
|
||||
if (oProperty && oProperty['Type'] && Utils.isNormal(oProperty['Value']) && Utils.isNormal(oProperty['TypeStr']))
|
||||
{
|
||||
this.properties.push([Utils.pInt(oProperty['Type']), Utils.pString(oProperty['Value']), Utils.pString(oProperty['TypeStr'])]);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
|
||||
if (Utils.isNonEmptyArray(oItem['Tags']))
|
||||
{
|
||||
this.tags = oItem['Tags'].join(',');
|
||||
}
|
||||
|
||||
bResult = true;
|
||||
}
|
||||
|
||||
return bResult;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
ContactModel.prototype.srcAttr = function ()
|
||||
{
|
||||
return LinkBuilder.emptyContactPic();
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
ContactModel.prototype.generateUid = function ()
|
||||
{
|
||||
return '' + this.idContact;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
ContactModel.prototype.lineAsCcc = function ()
|
||||
{
|
||||
var aResult = [];
|
||||
if (this.deleted())
|
||||
{
|
||||
aResult.push('deleted');
|
||||
}
|
||||
if (this.selected())
|
||||
{
|
||||
aResult.push('selected');
|
||||
}
|
||||
if (this.checked())
|
||||
{
|
||||
aResult.push('checked');
|
||||
}
|
||||
if (this.focused())
|
||||
{
|
||||
aResult.push('focused');
|
||||
}
|
||||
|
||||
return aResult.join(' ');
|
||||
};
|
||||
|
||||
module.exports = ContactModel;
|
||||
|
||||
}());
|
||||
42
dev/Model/ContactProperty.js
Normal file
42
dev/Model/ContactProperty.js
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
|
||||
(function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
var
|
||||
ko = require('ko'),
|
||||
|
||||
Enums = require('Common/Enums'),
|
||||
Utils = require('Common/Utils')
|
||||
;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {number=} iType = Enums.ContactPropertyType.Unknown
|
||||
* @param {string=} sTypeStr = ''
|
||||
* @param {string=} sValue = ''
|
||||
* @param {boolean=} bFocused = false
|
||||
* @param {string=} sPlaceholder = ''
|
||||
*/
|
||||
function ContactPropertyModel(iType, sTypeStr, sValue, bFocused, sPlaceholder)
|
||||
{
|
||||
this.type = ko.observable(Utils.isUnd(iType) ? Enums.ContactPropertyType.Unknown : iType);
|
||||
this.typeStr = ko.observable(Utils.isUnd(sTypeStr) ? '' : sTypeStr);
|
||||
this.focused = ko.observable(Utils.isUnd(bFocused) ? false : !!bFocused);
|
||||
this.value = ko.observable(Utils.pString(sValue));
|
||||
|
||||
this.placeholder = ko.observable(sPlaceholder || '');
|
||||
|
||||
this.placeholderValue = ko.computed(function () {
|
||||
var sPlaceholder = this.placeholder();
|
||||
return sPlaceholder ? Utils.i18n(sPlaceholder) : '';
|
||||
}, this);
|
||||
|
||||
this.largeValue = ko.computed(function () {
|
||||
return Enums.ContactPropertyType.Note === this.type();
|
||||
}, this);
|
||||
}
|
||||
|
||||
module.exports = ContactPropertyModel;
|
||||
|
||||
}());
|
||||
58
dev/Model/ContactTag.js
Normal file
58
dev/Model/ContactTag.js
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
|
||||
(function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
var
|
||||
ko = require('ko'),
|
||||
|
||||
Utils = require('Common/Utils')
|
||||
;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
function ContactTagModel()
|
||||
{
|
||||
this.idContactTag = 0;
|
||||
this.name = ko.observable('');
|
||||
this.readOnly = false;
|
||||
}
|
||||
|
||||
ContactTagModel.prototype.parse = function (oItem)
|
||||
{
|
||||
var bResult = false;
|
||||
if (oItem && 'Object/Tag' === oItem['@Object'])
|
||||
{
|
||||
this.idContact = Utils.pInt(oItem['IdContactTag']);
|
||||
this.name(Utils.pString(oItem['Name']));
|
||||
this.readOnly = !!oItem['ReadOnly'];
|
||||
|
||||
bResult = true;
|
||||
}
|
||||
|
||||
return bResult;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} sSearch
|
||||
* @return {boolean}
|
||||
*/
|
||||
ContactTagModel.prototype.filterHelper = function (sSearch)
|
||||
{
|
||||
return this.name().toLowerCase().indexOf(sSearch.toLowerCase()) !== -1;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {boolean=} bEncodeHtml = false
|
||||
* @return {string}
|
||||
*/
|
||||
ContactTagModel.prototype.toLine = function (bEncodeHtml)
|
||||
{
|
||||
return (Utils.isUnd(bEncodeHtml) ? false : !!bEncodeHtml) ?
|
||||
Utils.encodeHtml(this.name()) : this.name();
|
||||
};
|
||||
|
||||
module.exports = ContactTagModel;
|
||||
|
||||
}());
|
||||
348
dev/Model/Email.js
Normal file
348
dev/Model/Email.js
Normal file
|
|
@ -0,0 +1,348 @@
|
|||
|
||||
(function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
var
|
||||
Utils = require('Common/Utils')
|
||||
;
|
||||
|
||||
/**
|
||||
* @param {string=} sEmail
|
||||
* @param {string=} sName
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function EmailModel(sEmail, sName)
|
||||
{
|
||||
this.email = sEmail || '';
|
||||
this.name = sName || '';
|
||||
|
||||
this.clearDuplicateName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param {AjaxJsonEmail} oJsonEmail
|
||||
* @return {?EmailModel}
|
||||
*/
|
||||
EmailModel.newInstanceFromJson = function (oJsonEmail)
|
||||
{
|
||||
var oEmailModel = new EmailModel();
|
||||
return oEmailModel.initByJson(oJsonEmail) ? oEmailModel : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
EmailModel.prototype.name = '';
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
EmailModel.prototype.email = '';
|
||||
|
||||
EmailModel.prototype.clear = function ()
|
||||
{
|
||||
this.email = '';
|
||||
this.name = '';
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
EmailModel.prototype.validate = function ()
|
||||
{
|
||||
return '' !== this.name || '' !== this.email;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {boolean} bWithoutName = false
|
||||
* @return {string}
|
||||
*/
|
||||
EmailModel.prototype.hash = function (bWithoutName)
|
||||
{
|
||||
return '#' + (bWithoutName ? '' : this.name) + '#' + this.email + '#';
|
||||
};
|
||||
|
||||
EmailModel.prototype.clearDuplicateName = function ()
|
||||
{
|
||||
if (this.name === this.email)
|
||||
{
|
||||
this.name = '';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} sQuery
|
||||
* @return {boolean}
|
||||
*/
|
||||
EmailModel.prototype.search = function (sQuery)
|
||||
{
|
||||
return -1 < (this.name + ' ' + this.email).toLowerCase().indexOf(sQuery.toLowerCase());
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} sString
|
||||
*/
|
||||
EmailModel.prototype.parse = function (sString)
|
||||
{
|
||||
this.clear();
|
||||
|
||||
sString = Utils.trim(sString);
|
||||
|
||||
var
|
||||
mRegex = /(?:"([^"]+)")? ?<?(.*?@[^>,]+)>?,? ?/g,
|
||||
mMatch = mRegex.exec(sString)
|
||||
;
|
||||
|
||||
if (mMatch)
|
||||
{
|
||||
this.name = mMatch[1] || '';
|
||||
this.email = mMatch[2] || '';
|
||||
|
||||
this.clearDuplicateName();
|
||||
}
|
||||
else if ((/^[^@]+@[^@]+$/).test(sString))
|
||||
{
|
||||
this.name = '';
|
||||
this.email = sString;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {AjaxJsonEmail} oJsonEmail
|
||||
* @return {boolean}
|
||||
*/
|
||||
EmailModel.prototype.initByJson = function (oJsonEmail)
|
||||
{
|
||||
var bResult = false;
|
||||
if (oJsonEmail && 'Object/Email' === oJsonEmail['@Object'])
|
||||
{
|
||||
this.name = Utils.trim(oJsonEmail.Name);
|
||||
this.email = Utils.trim(oJsonEmail.Email);
|
||||
|
||||
bResult = '' !== this.email;
|
||||
this.clearDuplicateName();
|
||||
}
|
||||
|
||||
return bResult;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {boolean} bFriendlyView
|
||||
* @param {boolean=} bWrapWithLink = false
|
||||
* @param {boolean=} bEncodeHtml = false
|
||||
* @return {string}
|
||||
*/
|
||||
EmailModel.prototype.toLine = function (bFriendlyView, bWrapWithLink, bEncodeHtml)
|
||||
{
|
||||
var sResult = '';
|
||||
if ('' !== this.email)
|
||||
{
|
||||
bWrapWithLink = Utils.isUnd(bWrapWithLink) ? false : !!bWrapWithLink;
|
||||
bEncodeHtml = Utils.isUnd(bEncodeHtml) ? false : !!bEncodeHtml;
|
||||
|
||||
if (bFriendlyView && '' !== this.name)
|
||||
{
|
||||
sResult = bWrapWithLink ? '<a href="mailto:' + Utils.encodeHtml('"' + this.name + '" <' + this.email + '>') +
|
||||
'" target="_blank" tabindex="-1">' + Utils.encodeHtml(this.name) + '</a>' :
|
||||
(bEncodeHtml ? Utils.encodeHtml(this.name) : this.name);
|
||||
}
|
||||
else
|
||||
{
|
||||
sResult = this.email;
|
||||
if ('' !== this.name)
|
||||
{
|
||||
if (bWrapWithLink)
|
||||
{
|
||||
sResult = Utils.encodeHtml('"' + this.name + '" <') +
|
||||
'<a href="mailto:' + Utils.encodeHtml('"' + this.name + '" <' + this.email + '>') + '" target="_blank" tabindex="-1">' + Utils.encodeHtml(sResult) + '</a>' + Utils.encodeHtml('>');
|
||||
}
|
||||
else
|
||||
{
|
||||
sResult = '"' + this.name + '" <' + sResult + '>';
|
||||
if (bEncodeHtml)
|
||||
{
|
||||
sResult = Utils.encodeHtml(sResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bWrapWithLink)
|
||||
{
|
||||
sResult = '<a href="mailto:' + Utils.encodeHtml(this.email) + '" target="_blank" tabindex="-1">' + Utils.encodeHtml(this.email) + '</a>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sResult;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} $sEmailAddress
|
||||
* @return {boolean}
|
||||
*/
|
||||
EmailModel.prototype.mailsoParse = function ($sEmailAddress)
|
||||
{
|
||||
$sEmailAddress = Utils.trim($sEmailAddress);
|
||||
if ('' === $sEmailAddress)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var
|
||||
substr = function (str, start, len) {
|
||||
str += '';
|
||||
var end = str.length;
|
||||
|
||||
if (start < 0) {
|
||||
start += end;
|
||||
}
|
||||
|
||||
end = typeof len === 'undefined' ? end : (len < 0 ? len + end : len + start);
|
||||
|
||||
return start >= str.length || start < 0 || start > end ? false : str.slice(start, end);
|
||||
},
|
||||
|
||||
substr_replace = function (str, replace, start, length) {
|
||||
if (start < 0) {
|
||||
start = start + str.length;
|
||||
}
|
||||
length = length !== undefined ? length : str.length;
|
||||
if (length < 0) {
|
||||
length = length + str.length - start;
|
||||
}
|
||||
return str.slice(0, start) + replace.substr(0, length) + replace.slice(length) + str.slice(start + length);
|
||||
},
|
||||
|
||||
$sName = '',
|
||||
$sEmail = '',
|
||||
$sComment = '',
|
||||
|
||||
$bInName = false,
|
||||
$bInAddress = false,
|
||||
$bInComment = false,
|
||||
|
||||
$aRegs = null,
|
||||
|
||||
$iStartIndex = 0,
|
||||
$iEndIndex = 0,
|
||||
$iCurrentIndex = 0
|
||||
;
|
||||
|
||||
while ($iCurrentIndex < $sEmailAddress.length)
|
||||
{
|
||||
switch ($sEmailAddress.substr($iCurrentIndex, 1))
|
||||
{
|
||||
case '"':
|
||||
if ((!$bInName) && (!$bInAddress) && (!$bInComment))
|
||||
{
|
||||
$bInName = true;
|
||||
$iStartIndex = $iCurrentIndex;
|
||||
}
|
||||
else if ((!$bInAddress) && (!$bInComment))
|
||||
{
|
||||
$iEndIndex = $iCurrentIndex;
|
||||
$sName = substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
|
||||
$sEmailAddress = substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
|
||||
$iEndIndex = 0;
|
||||
$iCurrentIndex = 0;
|
||||
$iStartIndex = 0;
|
||||
$bInName = false;
|
||||
}
|
||||
break;
|
||||
case '<':
|
||||
if ((!$bInName) && (!$bInAddress) && (!$bInComment))
|
||||
{
|
||||
if ($iCurrentIndex > 0 && $sName.length === 0)
|
||||
{
|
||||
$sName = substr($sEmailAddress, 0, $iCurrentIndex);
|
||||
}
|
||||
|
||||
$bInAddress = true;
|
||||
$iStartIndex = $iCurrentIndex;
|
||||
}
|
||||
break;
|
||||
case '>':
|
||||
if ($bInAddress)
|
||||
{
|
||||
$iEndIndex = $iCurrentIndex;
|
||||
$sEmail = substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
|
||||
$sEmailAddress = substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
|
||||
$iEndIndex = 0;
|
||||
$iCurrentIndex = 0;
|
||||
$iStartIndex = 0;
|
||||
$bInAddress = false;
|
||||
}
|
||||
break;
|
||||
case '(':
|
||||
if ((!$bInName) && (!$bInAddress) && (!$bInComment))
|
||||
{
|
||||
$bInComment = true;
|
||||
$iStartIndex = $iCurrentIndex;
|
||||
}
|
||||
break;
|
||||
case ')':
|
||||
if ($bInComment)
|
||||
{
|
||||
$iEndIndex = $iCurrentIndex;
|
||||
$sComment = substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
|
||||
$sEmailAddress = substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
|
||||
$iEndIndex = 0;
|
||||
$iCurrentIndex = 0;
|
||||
$iStartIndex = 0;
|
||||
$bInComment = false;
|
||||
}
|
||||
break;
|
||||
case '\\':
|
||||
$iCurrentIndex++;
|
||||
break;
|
||||
}
|
||||
|
||||
$iCurrentIndex++;
|
||||
}
|
||||
|
||||
if ($sEmail.length === 0)
|
||||
{
|
||||
$aRegs = $sEmailAddress.match(/[^@\s]+@\S+/i);
|
||||
if ($aRegs && $aRegs[0])
|
||||
{
|
||||
$sEmail = $aRegs[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
$sName = $sEmailAddress;
|
||||
}
|
||||
}
|
||||
|
||||
if ($sEmail.length > 0 && $sName.length === 0 && $sComment.length === 0)
|
||||
{
|
||||
$sName = $sEmailAddress.replace($sEmail, '');
|
||||
}
|
||||
|
||||
$sEmail = Utils.trim($sEmail).replace(/^[<]+/, '').replace(/[>]+$/, '');
|
||||
$sName = Utils.trim($sName).replace(/^["']+/, '').replace(/["']+$/, '');
|
||||
$sComment = Utils.trim($sComment).replace(/^[(]+/, '').replace(/[)]+$/, '');
|
||||
|
||||
// Remove backslash
|
||||
$sName = $sName.replace(/\\\\(.)/g, '$1');
|
||||
$sComment = $sComment.replace(/\\\\(.)/g, '$1');
|
||||
|
||||
this.name = $sName;
|
||||
this.email = $sEmail;
|
||||
|
||||
this.clearDuplicateName();
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
EmailModel.prototype.inputoTagLine = function ()
|
||||
{
|
||||
return 0 < this.name.length ? this.name + ' (' + this.email + ')' : this.email;
|
||||
};
|
||||
|
||||
module.exports = EmailModel;
|
||||
|
||||
}());
|
||||
94
dev/Model/Filter.js
Normal file
94
dev/Model/Filter.js
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
|
||||
(function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
var
|
||||
ko = require('ko'),
|
||||
|
||||
Enums = require('Common/Enums'),
|
||||
Utils = require('Common/Utils'),
|
||||
FilterConditionModel = require('Model/FilterCondition')
|
||||
;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
function FilterModel()
|
||||
{
|
||||
this.isNew = ko.observable(true);
|
||||
this.enabled = ko.observable(true);
|
||||
|
||||
this.name = ko.observable('');
|
||||
|
||||
this.conditionsType = ko.observable(Enums.FilterRulesType.And);
|
||||
|
||||
this.conditions = ko.observableArray([]);
|
||||
|
||||
this.conditions.subscribe(function () {
|
||||
Utils.windowResize();
|
||||
});
|
||||
|
||||
// Actions
|
||||
this.actionMarkAsRead = ko.observable(false);
|
||||
this.actionSkipOtherFilters = ko.observable(true);
|
||||
this.actionValue = ko.observable('');
|
||||
|
||||
this.actionType = ko.observable(Enums.FiltersAction.Move);
|
||||
this.actionTypeOptions = [ // TODO i18n
|
||||
{'id': Enums.FiltersAction.None, 'name': 'Action - None'},
|
||||
{'id': Enums.FiltersAction.Move, 'name': 'Action - Move to'},
|
||||
// {'id': Enums.FiltersAction.Forward, 'name': 'Action - Forward to'},
|
||||
{'id': Enums.FiltersAction.Discard, 'name': 'Action - Discard'}
|
||||
];
|
||||
|
||||
this.actionMarkAsReadVisiblity = ko.computed(function () {
|
||||
return -1 < Utils.inArray(this.actionType(), [
|
||||
Enums.FiltersAction.None, Enums.FiltersAction.Forward, Enums.FiltersAction.Move
|
||||
]);
|
||||
}, this);
|
||||
|
||||
this.actionTemplate = ko.computed(function () {
|
||||
|
||||
var sTemplate = '';
|
||||
switch (this.actionType())
|
||||
{
|
||||
default:
|
||||
case Enums.FiltersAction.Move:
|
||||
sTemplate = 'SettingsFiltersActionValueAsFolders';
|
||||
break;
|
||||
case Enums.FiltersAction.Forward:
|
||||
sTemplate = 'SettingsFiltersActionWithValue';
|
||||
break;
|
||||
case Enums.FiltersAction.None:
|
||||
case Enums.FiltersAction.Discard:
|
||||
sTemplate = 'SettingsFiltersActionNoValue';
|
||||
break;
|
||||
}
|
||||
|
||||
return sTemplate;
|
||||
|
||||
}, this);
|
||||
}
|
||||
|
||||
FilterModel.prototype.addCondition = function ()
|
||||
{
|
||||
this.conditions.push(new FilterConditionModel(this.conditions));
|
||||
};
|
||||
|
||||
FilterModel.prototype.parse = function (oItem)
|
||||
{
|
||||
var bResult = false;
|
||||
if (oItem && 'Object/Filter' === oItem['@Object'])
|
||||
{
|
||||
this.name(Utils.pString(oItem['Name']));
|
||||
|
||||
bResult = true;
|
||||
}
|
||||
|
||||
return bResult;
|
||||
};
|
||||
|
||||
module.exports = FilterModel;
|
||||
|
||||
}());
|
||||
62
dev/Model/FilterCondition.js
Normal file
62
dev/Model/FilterCondition.js
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
|
||||
(function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
var
|
||||
ko = require('ko'),
|
||||
|
||||
Enums = require('Common/Enums')
|
||||
;
|
||||
|
||||
/**
|
||||
* @param {*} oKoList
|
||||
* @constructor
|
||||
*/
|
||||
function FilterConditionModel(oKoList)
|
||||
{
|
||||
this.parentList = oKoList;
|
||||
|
||||
this.field = ko.observable(Enums.FilterConditionField.From);
|
||||
|
||||
this.fieldOptions = [ // TODO i18n
|
||||
{'id': Enums.FilterConditionField.From, 'name': 'From'},
|
||||
{'id': Enums.FilterConditionField.Recipient, 'name': 'Recipient (To or CC)'},
|
||||
{'id': Enums.FilterConditionField.To, 'name': 'To'},
|
||||
{'id': Enums.FilterConditionField.Subject, 'name': 'Subject'}
|
||||
];
|
||||
|
||||
this.type = ko.observable(Enums.FilterConditionType.EqualTo);
|
||||
|
||||
this.typeOptions = [ // TODO i18n
|
||||
{'id': Enums.FilterConditionType.EqualTo, 'name': 'Equal To'},
|
||||
{'id': Enums.FilterConditionType.NotEqualTo, 'name': 'Not Equal To'},
|
||||
{'id': Enums.FilterConditionType.Contains, 'name': 'Contains'},
|
||||
{'id': Enums.FilterConditionType.NotContains, 'name': 'Not Contains'}
|
||||
];
|
||||
|
||||
this.value = ko.observable('');
|
||||
|
||||
this.template = ko.computed(function () {
|
||||
|
||||
var sTemplate = '';
|
||||
switch (this.type())
|
||||
{
|
||||
default:
|
||||
sTemplate = 'SettingsFiltersConditionDefault';
|
||||
break;
|
||||
}
|
||||
|
||||
return sTemplate;
|
||||
|
||||
}, this);
|
||||
}
|
||||
|
||||
FilterConditionModel.prototype.removeSelf = function ()
|
||||
{
|
||||
this.parentList.remove(this);
|
||||
};
|
||||
|
||||
module.exports = FilterConditionModel;
|
||||
|
||||
}());
|
||||
353
dev/Model/Folder.js
Normal file
353
dev/Model/Folder.js
Normal file
|
|
@ -0,0 +1,353 @@
|
|||
|
||||
(function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
var
|
||||
_ = require('_'),
|
||||
ko = require('ko'),
|
||||
|
||||
Enums = require('Common/Enums'),
|
||||
Globals = require('Common/Globals'),
|
||||
Utils = require('Common/Utils'),
|
||||
Events = require('Common/Events')
|
||||
;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
function FolderModel()
|
||||
{
|
||||
this.name = ko.observable('');
|
||||
this.fullName = '';
|
||||
this.fullNameRaw = '';
|
||||
this.fullNameHash = '';
|
||||
this.delimiter = '';
|
||||
this.namespace = '';
|
||||
this.deep = 0;
|
||||
this.interval = 0;
|
||||
|
||||
this.selectable = false;
|
||||
this.existen = true;
|
||||
|
||||
this.type = ko.observable(Enums.FolderType.User);
|
||||
|
||||
this.focused = ko.observable(false);
|
||||
this.selected = ko.observable(false);
|
||||
this.edited = ko.observable(false);
|
||||
this.collapsed = ko.observable(true);
|
||||
this.subScribed = ko.observable(true);
|
||||
this.subFolders = ko.observableArray([]);
|
||||
this.deleteAccess = ko.observable(false);
|
||||
this.actionBlink = ko.observable(false).extend({'falseTimeout': 1000});
|
||||
|
||||
this.nameForEdit = ko.observable('');
|
||||
|
||||
this.privateMessageCountAll = ko.observable(0);
|
||||
this.privateMessageCountUnread = ko.observable(0);
|
||||
|
||||
this.collapsedPrivate = ko.observable(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param {AjaxJsonFolder} oJsonFolder
|
||||
* @return {?FolderModel}
|
||||
*/
|
||||
FolderModel.newInstanceFromJson = function (oJsonFolder)
|
||||
{
|
||||
var oFolderModel = new FolderModel();
|
||||
return oFolderModel.initByJson(oJsonFolder) ? oFolderModel.initComputed() : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {FolderModel}
|
||||
*/
|
||||
FolderModel.prototype.initComputed = function ()
|
||||
{
|
||||
this.hasSubScribedSubfolders = ko.computed(function () {
|
||||
return !!_.find(this.subFolders(), function (oFolder) {
|
||||
return oFolder.subScribed() && !oFolder.isSystemFolder();
|
||||
});
|
||||
}, this);
|
||||
|
||||
this.canBeEdited = ko.computed(function () {
|
||||
return Enums.FolderType.User === this.type() && this.existen && this.selectable;
|
||||
}, this);
|
||||
|
||||
this.visible = ko.computed(function () {
|
||||
var
|
||||
bSubScribed = this.subScribed(),
|
||||
bSubFolders = this.hasSubScribedSubfolders()
|
||||
;
|
||||
|
||||
return (bSubScribed || (bSubFolders && (!this.existen || !this.selectable)));
|
||||
}, this);
|
||||
|
||||
this.isSystemFolder = ko.computed(function () {
|
||||
return Enums.FolderType.User !== this.type();
|
||||
}, this);
|
||||
|
||||
this.hidden = ko.computed(function () {
|
||||
var
|
||||
bSystem = this.isSystemFolder(),
|
||||
bSubFolders = this.hasSubScribedSubfolders()
|
||||
;
|
||||
|
||||
return (bSystem && !bSubFolders) || (!this.selectable && !bSubFolders);
|
||||
|
||||
}, this);
|
||||
|
||||
this.selectableForFolderList = ko.computed(function () {
|
||||
return !this.isSystemFolder() && this.selectable;
|
||||
}, this);
|
||||
|
||||
this.messageCountAll = ko.computed({
|
||||
'read': this.privateMessageCountAll,
|
||||
'write': function (iValue) {
|
||||
if (Utils.isPosNumeric(iValue, true))
|
||||
{
|
||||
this.privateMessageCountAll(iValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.privateMessageCountAll.valueHasMutated();
|
||||
}
|
||||
},
|
||||
'owner': this
|
||||
});
|
||||
|
||||
this.messageCountUnread = ko.computed({
|
||||
'read': this.privateMessageCountUnread,
|
||||
'write': function (iValue) {
|
||||
if (Utils.isPosNumeric(iValue, true))
|
||||
{
|
||||
this.privateMessageCountUnread(iValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.privateMessageCountUnread.valueHasMutated();
|
||||
}
|
||||
},
|
||||
'owner': this
|
||||
});
|
||||
|
||||
this.printableUnreadCount = ko.computed(function () {
|
||||
var
|
||||
iCount = this.messageCountAll(),
|
||||
iUnread = this.messageCountUnread(),
|
||||
iType = this.type()
|
||||
;
|
||||
|
||||
if (0 < iCount)
|
||||
{
|
||||
if (Enums.FolderType.Draft === iType)
|
||||
{
|
||||
return '' + iCount;
|
||||
}
|
||||
else if (0 < iUnread && Enums.FolderType.Trash !== iType && Enums.FolderType.Archive !== iType && Enums.FolderType.SentItems !== iType)
|
||||
{
|
||||
return '' + iUnread;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
|
||||
}, this);
|
||||
|
||||
this.canBeDeleted = ko.computed(function () {
|
||||
var
|
||||
bSystem = this.isSystemFolder()
|
||||
;
|
||||
return !bSystem && 0 === this.subFolders().length && 'INBOX' !== this.fullNameRaw;
|
||||
}, this);
|
||||
|
||||
this.canBeSubScribed = ko.computed(function () {
|
||||
return !this.isSystemFolder() && this.selectable && 'INBOX' !== this.fullNameRaw;
|
||||
}, this);
|
||||
|
||||
// this.visible.subscribe(function () {
|
||||
// Utils.timeOutAction('folder-list-folder-visibility-change', function () {
|
||||
// Globals.$win.trigger('folder-list-folder-visibility-change');
|
||||
// }, 100);
|
||||
// });
|
||||
|
||||
this.localName = ko.computed(function () {
|
||||
|
||||
Globals.langChangeTrigger();
|
||||
|
||||
var
|
||||
iType = this.type(),
|
||||
sName = this.name()
|
||||
;
|
||||
|
||||
if (this.isSystemFolder())
|
||||
{
|
||||
switch (iType)
|
||||
{
|
||||
case Enums.FolderType.Inbox:
|
||||
sName = Utils.i18n('FOLDER_LIST/INBOX_NAME');
|
||||
break;
|
||||
case Enums.FolderType.SentItems:
|
||||
sName = Utils.i18n('FOLDER_LIST/SENT_NAME');
|
||||
break;
|
||||
case Enums.FolderType.Draft:
|
||||
sName = Utils.i18n('FOLDER_LIST/DRAFTS_NAME');
|
||||
break;
|
||||
case Enums.FolderType.Spam:
|
||||
sName = Utils.i18n('FOLDER_LIST/SPAM_NAME');
|
||||
break;
|
||||
case Enums.FolderType.Trash:
|
||||
sName = Utils.i18n('FOLDER_LIST/TRASH_NAME');
|
||||
break;
|
||||
case Enums.FolderType.Archive:
|
||||
sName = Utils.i18n('FOLDER_LIST/ARCHIVE_NAME');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return sName;
|
||||
|
||||
}, this);
|
||||
|
||||
this.manageFolderSystemName = ko.computed(function () {
|
||||
|
||||
Globals.langChangeTrigger();
|
||||
|
||||
var
|
||||
sSuffix = '',
|
||||
iType = this.type(),
|
||||
sName = this.name()
|
||||
;
|
||||
|
||||
if (this.isSystemFolder())
|
||||
{
|
||||
switch (iType)
|
||||
{
|
||||
case Enums.FolderType.Inbox:
|
||||
sSuffix = '(' + Utils.i18n('FOLDER_LIST/INBOX_NAME') + ')';
|
||||
break;
|
||||
case Enums.FolderType.SentItems:
|
||||
sSuffix = '(' + Utils.i18n('FOLDER_LIST/SENT_NAME') + ')';
|
||||
break;
|
||||
case Enums.FolderType.Draft:
|
||||
sSuffix = '(' + Utils.i18n('FOLDER_LIST/DRAFTS_NAME') + ')';
|
||||
break;
|
||||
case Enums.FolderType.Spam:
|
||||
sSuffix = '(' + Utils.i18n('FOLDER_LIST/SPAM_NAME') + ')';
|
||||
break;
|
||||
case Enums.FolderType.Trash:
|
||||
sSuffix = '(' + Utils.i18n('FOLDER_LIST/TRASH_NAME') + ')';
|
||||
break;
|
||||
case Enums.FolderType.Archive:
|
||||
sSuffix = '(' + Utils.i18n('FOLDER_LIST/ARCHIVE_NAME') + ')';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ('' !== sSuffix && '(' + sName + ')' === sSuffix || '(inbox)' === sSuffix.toLowerCase())
|
||||
{
|
||||
sSuffix = '';
|
||||
}
|
||||
|
||||
return sSuffix;
|
||||
|
||||
}, this);
|
||||
|
||||
this.collapsed = ko.computed({
|
||||
'read': function () {
|
||||
return !this.hidden() && this.collapsedPrivate();
|
||||
},
|
||||
'write': function (mValue) {
|
||||
this.collapsedPrivate(mValue);
|
||||
},
|
||||
'owner': this
|
||||
});
|
||||
|
||||
this.hasUnreadMessages = ko.computed(function () {
|
||||
return 0 < this.messageCountUnread();
|
||||
}, this);
|
||||
|
||||
this.hasSubScribedUnreadMessagesSubfolders = ko.computed(function () {
|
||||
return !!_.find(this.subFolders(), function (oFolder) {
|
||||
return oFolder.hasUnreadMessages() || oFolder.hasSubScribedUnreadMessagesSubfolders();
|
||||
});
|
||||
}, this);
|
||||
|
||||
// subscribe
|
||||
this.name.subscribe(function (sValue) {
|
||||
this.nameForEdit(sValue);
|
||||
}, this);
|
||||
|
||||
this.edited.subscribe(function (bValue) {
|
||||
if (bValue)
|
||||
{
|
||||
this.nameForEdit(this.name());
|
||||
}
|
||||
}, this);
|
||||
|
||||
this.messageCountUnread.subscribe(function (iUnread) {
|
||||
if (Enums.FolderType.Inbox === this.type())
|
||||
{
|
||||
Events.pub('mailbox.inbox-unread-count', [iUnread]);
|
||||
}
|
||||
}, this);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
FolderModel.prototype.fullName = '';
|
||||
FolderModel.prototype.fullNameRaw = '';
|
||||
FolderModel.prototype.fullNameHash = '';
|
||||
FolderModel.prototype.delimiter = '';
|
||||
FolderModel.prototype.namespace = '';
|
||||
FolderModel.prototype.deep = 0;
|
||||
FolderModel.prototype.interval = 0;
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
FolderModel.prototype.collapsedCss = function ()
|
||||
{
|
||||
return this.hasSubScribedSubfolders() ?
|
||||
(this.collapsed() ? 'icon-right-mini e-collapsed-sign' : 'icon-down-mini e-collapsed-sign') : 'icon-none e-collapsed-sign';
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {AjaxJsonFolder} oJsonFolder
|
||||
* @return {boolean}
|
||||
*/
|
||||
FolderModel.prototype.initByJson = function (oJsonFolder)
|
||||
{
|
||||
var bResult = false;
|
||||
if (oJsonFolder && 'Object/Folder' === oJsonFolder['@Object'])
|
||||
{
|
||||
this.name(oJsonFolder.Name);
|
||||
this.delimiter = oJsonFolder.Delimiter;
|
||||
this.fullName = oJsonFolder.FullName;
|
||||
this.fullNameRaw = oJsonFolder.FullNameRaw;
|
||||
this.fullNameHash = oJsonFolder.FullNameHash;
|
||||
this.deep = oJsonFolder.FullNameRaw.split(this.delimiter).length - 1;
|
||||
this.selectable = !!oJsonFolder.IsSelectable;
|
||||
this.existen = !!oJsonFolder.IsExists;
|
||||
|
||||
this.subScribed(!!oJsonFolder.IsSubscribed);
|
||||
this.type('INBOX' === this.fullNameRaw ? Enums.FolderType.Inbox : Enums.FolderType.User);
|
||||
|
||||
bResult = true;
|
||||
}
|
||||
|
||||
return bResult;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
FolderModel.prototype.printableFullName = function ()
|
||||
{
|
||||
return this.fullName.split(this.delimiter).join(' / ');
|
||||
};
|
||||
|
||||
module.exports = FolderModel;
|
||||
|
||||
}());
|
||||
50
dev/Model/Identity.js
Normal file
50
dev/Model/Identity.js
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
|
||||
(function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
var
|
||||
ko = require('ko'),
|
||||
|
||||
Utils = require('Common/Utils')
|
||||
;
|
||||
|
||||
/**
|
||||
* @param {string} sId
|
||||
* @param {string} sEmail
|
||||
* @param {boolean=} bCanBeDelete = true
|
||||
* @constructor
|
||||
*/
|
||||
function IdentityModel(sId, sEmail, bCanBeDelete)
|
||||
{
|
||||
this.id = sId;
|
||||
this.email = ko.observable(sEmail);
|
||||
this.name = ko.observable('');
|
||||
this.replyTo = ko.observable('');
|
||||
this.bcc = ko.observable('');
|
||||
|
||||
this.deleteAccess = ko.observable(false);
|
||||
this.canBeDalete = ko.observable(bCanBeDelete);
|
||||
}
|
||||
|
||||
IdentityModel.prototype.formattedName = function ()
|
||||
{
|
||||
var sName = this.name();
|
||||
return '' === sName ? this.email() : sName + ' <' + this.email() + '>';
|
||||
};
|
||||
|
||||
IdentityModel.prototype.formattedNameForCompose = function ()
|
||||
{
|
||||
var sName = this.name();
|
||||
return '' === sName ? this.email() : sName + ' (' + this.email() + ')';
|
||||
};
|
||||
|
||||
IdentityModel.prototype.formattedNameForEmail = function ()
|
||||
{
|
||||
var sName = this.name();
|
||||
return '' === sName ? this.email() : '"' + Utils.quoteName(sName) + '" <' + this.email() + '>';
|
||||
};
|
||||
|
||||
module.exports = IdentityModel;
|
||||
|
||||
}());
|
||||
1294
dev/Model/Message.js
Normal file
1294
dev/Model/Message.js
Normal file
File diff suppressed because it is too large
Load diff
43
dev/Model/OpenPgpKey.js
Normal file
43
dev/Model/OpenPgpKey.js
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
|
||||
(function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
var
|
||||
ko = require('ko')
|
||||
;
|
||||
|
||||
/**
|
||||
* @param {string} iIndex
|
||||
* @param {string} sGuID
|
||||
* @param {string} sID
|
||||
* @param {string} sUserID
|
||||
* @param {string} sEmail
|
||||
* @param {boolean} bIsPrivate
|
||||
* @param {string} sArmor
|
||||
* @constructor
|
||||
*/
|
||||
function OpenPgpKeyModel(iIndex, sGuID, sID, sUserID, sEmail, bIsPrivate, sArmor)
|
||||
{
|
||||
this.index = iIndex;
|
||||
this.id = sID;
|
||||
this.guid = sGuID;
|
||||
this.user = sUserID;
|
||||
this.email = sEmail;
|
||||
this.armor = sArmor;
|
||||
this.isPrivate = !!bIsPrivate;
|
||||
|
||||
this.deleteAccess = ko.observable(false);
|
||||
}
|
||||
|
||||
OpenPgpKeyModel.prototype.index = 0;
|
||||
OpenPgpKeyModel.prototype.id = '';
|
||||
OpenPgpKeyModel.prototype.guid = '';
|
||||
OpenPgpKeyModel.prototype.user = '';
|
||||
OpenPgpKeyModel.prototype.email = '';
|
||||
OpenPgpKeyModel.prototype.armor = '';
|
||||
OpenPgpKeyModel.prototype.isPrivate = false;
|
||||
|
||||
module.exports = OpenPgpKeyModel;
|
||||
|
||||
}());
|
||||
Loading…
Add table
Add a link
Reference in a new issue