Added individual signatures for every identity.

This commit is contained in:
RainLoop Team 2015-02-08 05:11:13 +04:00
parent 996703311b
commit 1119022916
45 changed files with 1353 additions and 337 deletions

View file

@ -26,6 +26,7 @@
SettingsStore = require('Stores/User/Settings'),
AccountStore = require('Stores/User/Account'),
IdentityStore = require('Stores/User/Identity'),
TemplateStore = require('Stores/User/Template'),
FolderStore = require('Stores/User/Folder'),
PgpStore = require('Stores/User/Pgp'),
@ -587,6 +588,8 @@
oIdentity.name(Utils.pString(oIdentityData['Name']));
oIdentity.replyTo(Utils.pString(oIdentityData['ReplyTo']));
oIdentity.bcc(Utils.pString(oIdentityData['Bcc']));
oIdentity.signature(Utils.pString(oIdentityData['Signature']));
oIdentity.signatureInsertBefore(!!oIdentityData['SignatureInsertBefore']);
return oIdentity;
}));
@ -595,6 +598,29 @@
});
};
AppUser.prototype.templates = function ()
{
TemplateStore.templates.loading(true);
Remote.templates(function (sResult, oData) {
TemplateStore.templates.loading(false);
if (Enums.StorageResultType.Success === sResult && oData.Result &&
Utils.isArray(oData.Result['Templates']))
{
Utils.delegateRunOnDestroy(TemplateStore.templates());
IdentityStore.templates(_.map(oData.Result['Templates'], function (oIdentityData) {
return {
'id': Utils.pString(oIdentityData['Id']),
'name': Utils.pString(oIdentityData['Name'])
};
}));
}
});
};
AppUser.prototype.quota = function ()
{
Remote.quota(function (sResult, oData) {

View file

@ -135,7 +135,7 @@
'removeButtons': 'Format,Undo,Redo,Cut,Copy,Paste,Anchor,Strike,Subscript,Superscript,Image,SelectAll,Source',
'removeDialogTabs': 'link:advanced;link:target;image:advanced;images:advanced',
'extraPlugins': 'plain', // signature
'extraPlugins': 'plain,signature',
'allowedContent': true,
'font_defaultLabel': 'Arial',

View file

@ -64,12 +64,16 @@
/**
* @param {string} sSignature
* @param {bool} bHtml
* @param {bool} bInsertBefore
*/
HtmlEditor.prototype.setSignature = function (sSignature)
HtmlEditor.prototype.setSignature = function (sSignature, bHtml, bInsertBefore)
{
if (this.editor)
{
this.editor.execCommand('insertSignature', {
'isHtml': bHtml,
'insertBefore': bInsertBefore,
'signature': sSignature
});
}
@ -92,24 +96,46 @@
};
/**
* @param {boolean=} bWrapIsHtml = false
* @param {string} sText
* @return {string}
*/
HtmlEditor.prototype.getData = function (bWrapIsHtml)
HtmlEditor.prototype.clearSignatureSigns = function (sText)
{
return sText
.replace("\u0002", '').replace("\u0002", '')
.replace("\u0002", '').replace("\u0002", '')
.replace("\u0003", '').replace("\u0003", '')
.replace("\u0003", '').replace("\u0003", '')
;
}
/**
* @param {boolean=} bWrapIsHtml = false
* @param {boolean=} bClearSignatureSigns = false
* @return {string}
*/
HtmlEditor.prototype.getData = function (bWrapIsHtml, bClearSignatureSigns)
{
var sResult = '';
if (this.editor)
{
if ('plain' === this.editor.mode && this.editor.plugins.plain && this.editor.__plain)
{
return this.editor.__plain.getRawData();
sResult = this.editor.__plain.getRawData();
}
else
{
sResult = bWrapIsHtml ?
'<div data-html-editor-font-wrapper="true" style="font-family: arial, sans-serif; font-size: 13px;">' +
this.editor.getData() + '</div>' : this.editor.getData();
}
return bWrapIsHtml ?
'<div data-html-editor-font-wrapper="true" style="font-family: arial, sans-serif; font-size: 13px;">' +
this.editor.getData() + '</div>' : this.editor.getData();
if (bClearSignatureSigns)
{
sResult = this.clearSignatureSigns(sResult);
}
}
return '';
return sResult;
};
HtmlEditor.prototype.modeToggle = function (bPlain)

19
dev/External/ko.js vendored
View file

@ -954,6 +954,25 @@
return this;
};
ko.observable.fn.deleteAccessHelper = function ()
{
this.extend({'falseTimeout': 3000}).extend({'toggleSubscribe': [null,
function (oPrev) {
if (oPrev && oPrev.deleteAccess)
{
oPrev.deleteAccess(false);
}
}, function (oNext) {
if (oNext && oNext.deleteAccess)
{
oNext.deleteAccess(true);
}
}
]});
return this;
};
ko.observable.fn.validateFunc = function (fFunc)
{
var Utils = require('Common/Utils');

View file

@ -112,7 +112,7 @@
/**
* @return string
*/
ContactModel.prototype.lineAsCcc = function ()
ContactModel.prototype.lineAsCss = function ()
{
var aResult = [];
if (this.deleted())

View file

@ -7,8 +7,6 @@
_ = require('_'),
ko = require('ko'),
Utils = require('Common/Utils'),
AbstractModel = require('Knoin/AbstractModel')
;
@ -28,6 +26,9 @@
this.replyTo = ko.observable('');
this.bcc = ko.observable('');
this.signature = ko.observable('');
this.signatureInsertBefore = ko.observable(false);
this.deleteAccess = ko.observable(false);
this.canBeDeleted = ko.computed(function () {
return '' !== this.id();

View file

@ -63,6 +63,7 @@
this.newForAnimation = ko.observable(false);
this.deleted = ko.observable(false);
this.deletedMark = ko.observable(false);
this.unseen = ko.observable(false);
this.flagged = ko.observable(false);
this.answered = ko.observable(false);
@ -322,6 +323,7 @@
this.newForAnimation(false);
this.deleted(false);
this.deletedMark(false);
this.unseen(false);
this.flagged(false);
this.answered(false);
@ -546,6 +548,7 @@
this.answered(!!oJsonMessage.IsAnswered);
this.forwarded(!!oJsonMessage.IsForwarded);
this.isReadReceipt(!!oJsonMessage.IsReadReceipt);
this.deletedMark(!!oJsonMessage.IsDeleted);
bResult = true;
}
@ -621,13 +624,17 @@
/**
* @return string
*/
MessageModel.prototype.lineAsCcc = function ()
MessageModel.prototype.lineAsCss = function ()
{
var aResult = [];
if (this.deleted())
{
aResult.push('deleted');
}
if (this.deletedMark())
{
aResult.push('deleted-mark');
}
if (this.selected())
{
aResult.push('selected');
@ -972,6 +979,7 @@
this.answered(oMessage.answered());
this.forwarded(oMessage.forwarded());
this.isReadReceipt(oMessage.isReadReceipt());
this.deletedMark(oMessage.deletedMark());
this.priority(oMessage.priority());
@ -1339,8 +1347,8 @@
*/
MessageModel.prototype.flagHash = function ()
{
return [this.deleted(), this.unseen(), this.flagged(), this.answered(), this.forwarded(),
this.isReadReceipt()].join('');
return [this.deleted(), this.deletedMark(), this.unseen(), this.flagged(), this.answered(), this.forwarded(),
this.isReadReceipt()].join(',');
};
module.exports = MessageModel;

50
dev/Model/Template.js Normal file
View file

@ -0,0 +1,50 @@
(function () {
'use strict';
var
_ = require('_'),
ko = require('ko'),
AbstractModel = require('Knoin/AbstractModel')
;
/**
* @constructor
*
* @param {string} sID
* @param {string} sName
* @param {string} sBody
*/
function TemplateModel(sID, sName, sBody)
{
AbstractModel.call(this, 'TemplateModel');
this.id = sID;
this.name = sName;
this.body = sBody;
this.deleteAccess = ko.observable(false);
}
_.extend(TemplateModel.prototype, AbstractModel.prototype);
/**
* @type {string}
*/
TemplateModel.prototype.id = '';
/**
* @type {string}
*/
TemplateModel.prototype.name = '';
/**
* @type {string}
*/
TemplateModel.prototype.body = '';
module.exports = TemplateModel;
}());

View file

@ -85,6 +85,9 @@
'SettingsChangePassword', 'SETTINGS_LABELS/LABEL_CHANGE_PASSWORD_NAME', 'change-password');
}
// kn.addSettingsViewModel(require('Settings/User/Templates'),
// 'SettingsTemplates', 'SETTINGS_LABELS/LABEL_TEMPLATES_NAME', 'templates');
kn.addSettingsViewModel(require('Settings/User/Folders'),
'SettingsFolders', 'SETTINGS_LABELS/LABEL_FOLDERS_NAME', 'folders');

View file

@ -9,6 +9,7 @@
ko = require('ko'),
Enums = require('Common/Enums'),
Utils = require('Common/Utils'),
Translator = require('Common/Translator'),
Links = require('Common/Links'),
@ -34,33 +35,8 @@
return '' === this.processText() ? 'hidden' : 'visible';
}, this);
this.accountForDeletion = ko.observable(null).extend({'falseTimeout': 3000}).extend({'toggleSubscribe': [this,
function (oPrev) {
if (oPrev)
{
oPrev.deleteAccess(false);
}
}, function (oNext) {
if (oNext)
{
oNext.deleteAccess(true);
}
}
]});
this.identityForDeletion = ko.observable(null).extend({'falseTimeout': 3000}).extend({'toggleSubscribe': [this,
function (oPrev) {
if (oPrev)
{
oPrev.deleteAccess(false);
}
}, function (oNext) {
if (oNext)
{
oNext.deleteAccess(true);
}
}
]});
this.accountForDeletion = ko.observable(null).deleteAccessHelper();
this.identityForDeletion = ko.observable(null).deleteAccessHelper();
}
AccountsUserSettings.prototype.scrollableOptions = function ()
@ -158,6 +134,12 @@
}
};
AccountsUserSettings.prototype.accountsAndIdentitiesAfterMove = function ()
{
Remote.accountsAndIdentitiesSortOrder(null,
AccountStore.accountsEmails.peek(), IdentityStore.identitiesIDS.peek());
};
AccountsUserSettings.prototype.onBuild = function (oDom)
{
var self = this;

View file

@ -0,0 +1,105 @@
(function () {
'use strict';
var
ko = require('ko'),
Translator = require('Common/Translator'),
TemplateStore = require('Stores/User/Template'),
Remote = require('Storage/User/Remote')
;
/**
* @constructor
*/
function TemplatesUserSettings()
{
this.templates = TemplateStore.templates;
this.processText = ko.computed(function () {
return TemplateStore.templates.loading() ? Translator.i18n('SETTINGS_TEMPLETS/LOADING_PROCESS') : '';
}, this);
this.visibility = ko.computed(function () {
return '' === this.processText() ? 'hidden' : 'visible';
}, this);
this.templateForDeletion = ko.observable(null).deleteAccessHelper();
}
TemplatesUserSettings.prototype.scrollableOptions = function ()
{
return {
handle: '.drag-handle'
};
};
TemplatesUserSettings.prototype.addNewTemplate = function ()
{
require('Knoin/Knoin').showScreenPopup(require('View/Popup/Template'));
};
TemplatesUserSettings.prototype.editTemplate = function (oTemplateItem)
{
if (oTemplateItem)
{
require('Knoin/Knoin').showScreenPopup(require('View/Popup/Template'), [oTemplateItem]);
}
};
/**
* @param {AccountModel} oTemplateToRemove
*/
TemplatesUserSettings.prototype.deleteTemplate = function (oTemplateToRemove)
{
if (oTemplateToRemove && oTemplateToRemove.deleteAccess())
{
this.templateForDeletion(null);
var
self = this,
fRemoveAccount = function (oAccount) {
return oTemplateToRemove === oAccount;
}
;
if (oTemplateToRemove)
{
this.templates.remove(fRemoveAccount);
Remote.templateDelete(function () {
self.reloadTemplates();
}, oTemplateToRemove.id);
}
}
};
TemplatesUserSettings.prototype.reloadTemplates = function ()
{
require('App/User').templates();
};
TemplatesUserSettings.prototype.onBuild = function (oDom)
{
var self = this;
oDom
.on('click', '.templates-list .template-item .e-action', function () {
var oTemplateItem = ko.dataFor(this);
if (oTemplateItem)
{
self.editTemplate(oTemplateItem);
}
})
;
this.reloadTemplates();
};
module.exports = TemplatesUserSettings;
}());

View file

@ -313,6 +313,7 @@
oMessage.answered(!!aFlags[2]);
oMessage.forwarded(!!aFlags[3]);
oMessage.isReadReceipt(!!aFlags[4]);
oMessage.deletedMark(!!aFlags[5]);
}
if (0 < oMessage.threads().length)
@ -343,7 +344,8 @@
this.setMessageFlagsToCache(
oMessage.folderFullNameRaw,
oMessage.uid,
[oMessage.unseen(), oMessage.flagged(), oMessage.answered(), oMessage.forwarded(), oMessage.isReadReceipt()]
[oMessage.unseen(), oMessage.flagged(), oMessage.answered(), oMessage.forwarded(),
oMessage.isReadReceipt(), oMessage.deletedMark()]
);
}
};

View file

@ -188,11 +188,13 @@
/**
* @param {?Function} fCallback
* @param {Array} aAccounts
* @param {Array} aIdentities
*/
RemoteUserStorage.prototype.accountSortOrder = function (fCallback, aAccounts)
RemoteUserStorage.prototype.accountsAndIdentitiesSortOrder = function (fCallback, aAccounts, aIdentities)
{
this.defaultRequest(fCallback, 'AccountSortOrder', {
'Accounts': aAccounts
this.defaultRequest(fCallback, 'AccountsAndIdentitiesSortOrder', {
'Accounts': aAccounts,
'Identities': aIdentities
});
};
@ -203,15 +205,20 @@
* @param {string} sName
* @param {string} sReplyTo
* @param {string} sBcc
* @param {string} sSignature
* @param {boolean} bSignatureInsertBefore
*/
RemoteUserStorage.prototype.identityUpdate = function (fCallback, sId, sEmail, sName, sReplyTo, sBcc)
RemoteUserStorage.prototype.identityUpdate = function (fCallback, sId, sEmail, sName, sReplyTo, sBcc,
sSignature, bSignatureInsertBefore)
{
this.defaultRequest(fCallback, 'IdentityUpdate', {
'Id': sId,
'Email': sEmail,
'Name': sName,
'ReplyTo': sReplyTo,
'Bcc': sBcc
'Bcc': sBcc,
'Signature': sSignature,
'SignatureInsertBefore': bSignatureInsertBefore ? '1' : '0'
});
};
@ -265,6 +272,36 @@
this.defaultRequest(fCallback, 'Filters', {});
};
/**
* @param {?Function} fCallback
*/
RemoteUserStorage.prototype.templates = function (fCallback)
{
this.defaultRequest(fCallback, 'Templates', {});
};
/**
* @param {?Function} fCallback
*/
RemoteUserStorage.prototype.templateGetById = function (fCallback, sID)
{
this.defaultRequest(fCallback, 'TemplateGetByID', {
'ID': sID
});
};
/**
* @param {?Function} fCallback
*/
RemoteUserStorage.prototype.templateGetById = function (fCallback, sID, sName, sBody)
{
this.defaultRequest(fCallback, 'TemplateSetup', {
'ID': sID,
'Name': sName,
'Body': sBody
});
};
/**
* @param {?Function} fCallback
* @param {string} sFolderFullNameRaw

View file

@ -7,9 +7,7 @@
_ = require('_'),
ko = require('ko'),
Settings = require('Storage/Settings'),
Remote = require('Storage/User/Remote')
Settings = require('Storage/Settings')
;
/**
@ -26,24 +24,10 @@
this.accounts = ko.observableArray([]);
this.accounts.loading = ko.observable(false).extend({'throttle': 100});
this.accountsEmailNames = ko.observableArray([]).extend({'throttle': 1000});
this.accountsEmailNames.skipFirst = true;
this.accounts.subscribe(function (aList) {
this.accountsEmailNames(_.compact(_.map(aList, function (oItem) {
this.accountsEmails = ko.computed(function () {
return _.compact(_.map(this.accounts(), function (oItem) {
return oItem ? oItem.email : null;
})));
}, this);
this.accountsEmailNames.subscribe(function (aList) {
if (this.accountsEmailNames.skipFirst)
{
this.accountsEmailNames.skipFirst = false;
}
else if (aList && 1 < aList.length)
{
Remote.accountSortOrder(null, aList);
}
}));
}, this);
this.accountsUnreadCount = ko.computed(function () {
@ -65,10 +49,6 @@
AccountUserStore.prototype.populate = function ()
{
this.email(Settings.settingsGet('Email'));
// this.incLogin(Settings.settingsGet('IncLogin'));
// this.outLogin(Settings.settingsGet('OutLogin'));
// this.signature(Settings.settingsGet('Signature'));
};
module.exports = new AccountUserStore();

View file

@ -4,6 +4,7 @@
'use strict';
var
_ = require('_'),
ko = require('ko')
;
@ -14,6 +15,12 @@
{
this.identities = ko.observableArray([]);
this.identities.loading = ko.observable(false).extend({'throttle': 100});
this.identitiesIDS = ko.computed(function () {
return _.compact(_.map(this.identities(), function (oItem) {
return oItem ? oItem.id : null;
}));
}, this);
}
module.exports = new IdentityUserStore();

View file

@ -0,0 +1,44 @@
(function () {
'use strict';
var
_ = require('_'),
ko = require('ko'),
Remote = require('Storage/User/Remote')
;
/**
* @constructor
*/
function TemplateUserStore()
{
this.templates = ko.observableArray([]);
this.templates.loading = ko.observable(false).extend({'throttle': 100});
this.templatesNames = ko.observableArray([]).extend({'throttle': 1000});
this.templatesNames.skipFirst = true;
this.templates.subscribe(function (aList) {
this.templatesNames(_.compact(_.map(aList, function (oItem) {
return oItem ? oItem.name : null;
})));
}, this);
this.templatesNames.subscribe(function (aList) {
if (this.templatesNames.skipFirst)
{
this.templatesNames.skipFirst = false;
}
else if (aList && 1 < aList.length)
{
Remote.templatesSortOrder(null, aList);
}
}, this);
}
module.exports = new TemplateUserStore();
}());

View file

@ -63,6 +63,7 @@
@import "Filter.less";
@import "Languages.less";
@import "Account.less";
@import "Template.less";
@import "OpenPgpKey.less";
@import "TwoFactor.less";
@import "Identity.less";
@ -85,6 +86,7 @@
@import "Settings.less";
@import "SettingsGeneral.less";
@import "SettingsAccounts.less";
@import "SettingsTemplates.less";
@import "SettingsOpenPGP.less";
@import "SettingsFolders.less";
@import "SettingsThemes.less";

View file

@ -52,9 +52,10 @@
background-color: #333;
background-color: rgba(0,0,0,0.8) !important;
.close {
color: #fff;
.close, .close-custom, .minimize-custom {
opacity: 1;
color: #fff;
border-color: #eee;
}
.btn.disabled {
@ -157,7 +158,7 @@
.error {
color: red;
}
.close {
.close, .close-custom {
float: left;
padding-right: 13px;
}

View file

@ -41,7 +41,7 @@
background-color: #333;
background-color: rgba(0,0,0,0.8) !important;
.close {
.close, .close-custom {
color: #fff;
opacity: 1;
}

View file

@ -1,9 +1,30 @@
.popups {
.b-identity-content {
&.modal {
width: 750px;
}
.modal-header {
background-color: #fff;
}
.modal-body {
overflow: hidden;
}
.control-label {
width: 100px;
}
.controls {
margin-left: 120px;
}
.e-signature-place {
height: 300px;
}
.textEmail {
margin-top: 5px;
font-weight: bold;

View file

@ -249,6 +249,13 @@ html.rl-no-preview-pane {
margin-right:5px
}
&.deleted-mark {
opacity: .7;
.sender, .subject, .subject-prefix, .subject-suffix {
text-decoration: line-through;
}
}
&.important .importantMark {
display: inline;
}

View file

@ -0,0 +1,70 @@
.b-settings-identities {
.process-place {
text-align: center;
width: 600px;
padding: 14px 0;
}
.list-table {
width: 600px;
td {
padding: 4px 8px;
line-height: 30px;
}
.drag-handle {
color: #eee;
}
tr:hover .drag-handle {
color: #aaa;
}
.template-img {
font-size: 12px;
margin-right: 5px;
}
.template-name {
display: inline-block;
word-break: break-all;
box-sizing: border-box;
line-height: 22px;
}
}
.template-item {
.e-action {
cursor: pointer;
}
.drag-handle {
cursor: pointer;
}
.button-delete {
margin-right: 15px;
margin-top: 5px;
visibility: hidden;
opacity: 0;
}
.delete-access {
&.button-delete {
visibility: visible;
margin-right: 0;
opacity: 1;
}
}
.delete-template {
cursor: pointer;
opacity: 0.5;
}
}
}

12
dev/Styles/Template.less Normal file
View file

@ -0,0 +1,12 @@
.popups {
.b-template-add-content {
&.modal {
width: 700px;
}
.modal-header {
background-color: #fff;
}
}
}

View file

@ -11,6 +11,32 @@ label.inline {
display: inline-block;
}
.close-custom {
.close;
}
button.close-custom {
padding: 0;
cursor: pointer;
background: transparent;
border: 0;
-webkit-appearance: none;
}
.minimize-custom {
border: 0px solid #333;
border-bottom-width: 3px;
display: inline-block;
float: right;
height: 20px;
width: 16px;
font-size: 20px;
font-weight: bold;
line-height: 20px;
margin-right: 15px;
cursor: pointer;
}
.legend {
display: block;
width: 100%;

View file

@ -33,7 +33,6 @@
Data = require('Storage/User/Data'),
Cache = require('Storage/User/Cache'),
Remote = require('Storage/User/Remote'),
Local = require('Storage/Client'),
ComposeAttachmentModel = require('Model/ComposeAttachment'),
@ -74,6 +73,7 @@
}
;
this.oLastMessage = null;
this.oEditor = null;
this.aDraftInfo = null;
this.sInReplyTo = '';
@ -198,49 +198,19 @@
this.composeEditorArea = ko.observable(null);
this.identities = AccountStore.identities;
this.identities = IdentityStore.identities;
this.identitiesOptions = ko.computed(function () {
return _.map(IdentityStore.identities(), function (oItem) {
return {
'item': oItem,
'optValue': oItem.id(),
'optText': oItem.formattedName()
};
});
}, this);
this.currentIdentityID = ko.observable(
Local.get(Enums.ClientSideKeyName.ComposeLastIdentityID, ''));
this.currentIdentity = ko.computed(function () {
var
oItem = null,
sID = this.currentIdentityID(),
aList = IdentityStore.identities()
;
if (Utils.isArray(aList))
{
oItem = _.find(aList, function (oItem) {
return oItem && sID === oItem.id();
});
if (!oItem)
{
oItem = _.find(aList, function (oItem) {
return oItem && '' === oItem.id();
});
}
if (!oItem)
{
oItem = aList[0] ? aList[0] : null;
}
}
return oItem ? oItem : null;
}, this);
this.currentIdentity = ko.observable(
this.identities()[0] ? this.identities()[0] : null);
this.currentIdentity.extend({'toggleSubscribe': [this,
function (oIdentity) {
@ -361,7 +331,7 @@
Remote.sendMessage(
this.sendMessageResponse,
this.currentIdentityID(),
this.currentIdentity() ? this.currentIdentity().id() : '',
this.draftFolder(),
this.draftUid(),
sSentFolder,
@ -371,7 +341,7 @@
this.replyTo(),
this.subject(),
this.oEditor ? this.oEditor.isHtml() : false,
this.oEditor ? this.oEditor.getData(true) : '',
this.oEditor ? this.oEditor.getData(true, true) : '',
this.prepearAttachmentsForSendOrSave(),
this.aDraftInfo,
this.sInReplyTo,
@ -400,7 +370,7 @@
Remote.saveMessage(
this.saveMessageResponse,
this.currentIdentityID(),
this.currentIdentity() ? this.currentIdentity().id() : '',
this.draftFolder(),
this.draftUid(),
FolderStore.draftFolder(),
@ -597,7 +567,6 @@
ComposePopupView.prototype.findIdentityByMessage = function (sComposeType, oMessage)
{
var
sDefaultIdentityID = Local.get(Enums.ClientSideKeyName.ComposeLastIdentityID, ''),
aIdentities = IdentityStore.identities(),
oResultIdentity = null,
oIdentitiesCache = {},
@ -640,34 +609,15 @@
}
}
if (!oResultIdentity)
{
oResultIdentity = _.find(aIdentities, function (oItem) {
return oItem.id() === sDefaultIdentityID;
});
}
if (!oResultIdentity && '' !== sDefaultIdentityID)
{
oResultIdentity = _.find(aIdentities, function (oItem) {
return oItem.id() === '';
});
}
if (!oResultIdentity)
{
oResultIdentity = aIdentities[0] || null;
}
return oResultIdentity;
return oResultIdentity || aIdentities[0] || null;
};
ComposePopupView.prototype.selectIdentity = function (oIdentity)
{
if (oIdentity)
if (oIdentity && oIdentity.item)
{
this.currentIdentityID(oIdentity.optValue);
Local.set(Enums.ClientSideKeyName.ComposeLastIdentityID, oIdentity.optValue);
this.currentIdentity(oIdentity.item);
this.setSignatureFromIdentity(oIdentity.item);
}
};
@ -775,97 +725,6 @@
kn.routeOn();
};
/**
* @param {string} sInputText
* @param {string} sSignature
* @param {string=} sFrom
* @param {string=} sComposeType
* @return {string}
*/
ComposePopupView.prototype.convertSignature = function (sInputText, sSignature, sFrom, sComposeType)
{
var bHtml = false, bData = false;
if ('' !== sSignature)
{
if (':HTML:' === sSignature.substr(0, 6))
{
bHtml = true;
sSignature = sSignature.substr(6);
}
sSignature = sSignature.replace(/[\r]/g, '');
sFrom = Utils.pString(sFrom);
if ('' !== sFrom)
{
sSignature = sSignature.replace(/{{FROM-FULL}}/g, sFrom);
if (-1 === sFrom.indexOf(' ') && 0 < sFrom.indexOf('@'))
{
sFrom = sFrom.replace(/@(.+)$/, '');
}
sSignature = sSignature.replace(/{{FROM}}/g, sFrom);
}
sSignature = sSignature.replace(/[\s]{1,2}{{FROM}}/g, '{{FROM}}');
sSignature = sSignature.replace(/[\s]{1,2}{{FROM-FULL}}/g, '{{FROM-FULL}}');
sSignature = sSignature.replace(/{{FROM}}/g, '');
sSignature = sSignature.replace(/{{FROM-FULL}}/g, '');
if (-1 < sSignature.indexOf('{{DATE}}'))
{
sSignature = sSignature.replace(/{{DATE}}/g, moment().format('llll'));
}
// Enums.ComposeType.Empty === sComposeType
if (-1 < sSignature.indexOf('{{BODY}}'))
{
if (sInputText)
{
bData = true;
sSignature = bHtml ? sSignature : Utils.plainToHtml(sSignature, true);
sSignature = sSignature.replace('{{BODY}}', sInputText);
}
else
{
sSignature = sSignature.replace(/[\n]?{{BODY}}[\n]?/g, '{{BODY}}');
sSignature = sSignature.replace(/{{BODY}}/g, '');
sSignature = bHtml ? sSignature : Utils.plainToHtml(sSignature, true);
}
}
else
{
sSignature = bHtml ? sSignature : Utils.plainToHtml(sSignature, true);
}
}
if (!bData)
{
if (sSignature)
{
switch (sComposeType)
{
case Enums.ComposeType.Empty:
sInputText = sInputText + '<br />' + sSignature;
break;
default:
sInputText = sSignature + '<br />' + sInputText;
break;
}
}
}
else
{
sInputText = sSignature;
}
return sInputText;
};
ComposePopupView.prototype.editor = function (fOnInit)
{
if (fOnInit)
@ -873,13 +732,11 @@
var self = this;
if (!this.oEditor && this.composeEditorArea())
{
_.delay(function () {
self.oEditor = new HtmlEditor(self.composeEditorArea(), null, function () {
fOnInit(self.oEditor);
}, function (bHtml) {
self.isHtml(!!bHtml);
});
}, 300);
self.oEditor = new HtmlEditor(self.composeEditorArea(), null, function () {
fOnInit(self.oEditor);
}, function (bHtml) {
self.isHtml(!!bHtml);
});
}
else if (this.oEditor)
{
@ -888,6 +745,101 @@
}
};
ComposePopupView.prototype.converSignature = function (sSignature)
{
var
iLimit = 10,
oMatch = null,
aMoments = [],
oMomentRegx = /{{MOMENT:([^}]+)}}/g,
sFrom = ''
;
sSignature = sSignature.replace(/[\r]/g, '');
sFrom = this.oLastMessage ? this.emailArrayToStringLineHelper(this.oLastMessage.from, true) : '';
if ('' !== sFrom)
{
sSignature = sSignature.replace(/{{FROM-FULL}}/g, sFrom);
if (-1 === sFrom.indexOf(' ') && 0 < sFrom.indexOf('@'))
{
sFrom = sFrom.replace(/@[\S]+/, '');
}
sSignature = sSignature.replace(/{{FROM}}/g, sFrom);
}
sSignature = sSignature.replace(/[\s]{1,2}{{FROM}}/g, '{{FROM}}');
sSignature = sSignature.replace(/[\s]{1,2}{{FROM-FULL}}/g, '{{FROM-FULL}}');
sSignature = sSignature.replace(/{{FROM}}/g, '');
sSignature = sSignature.replace(/{{FROM-FULL}}/g, '');
if (-1 < sSignature.indexOf('{{DATE}}'))
{
sSignature = sSignature.replace(/{{DATE}}/g, moment().format('llll'));
}
if (-1 < sSignature.indexOf('{{TIME}}'))
{
sSignature = sSignature.replace(/{{TIME}}/g, moment().format('LT'));
}
if (-1 < sSignature.indexOf('{{MOMENT:'))
{
try
{
while ((oMatch = oMomentRegx.exec(sSignature)) !== null)
{
if (oMatch && oMatch[0] && oMatch[1])
{
aMoments.push([oMatch[0], oMatch[1]]);
}
iLimit--;
if (0 === iLimit)
{
break;
}
}
if (aMoments && 0 < aMoments.length)
{
_.each(aMoments, function (aData) {
sSignature = sSignature.replace(aData[0], moment().format(aData[1]));
});
}
sSignature = sSignature.replace(/{{MOMENT:[^}]+}}/g, '');
}
catch(e) {}
}
return sSignature;
};
ComposePopupView.prototype.setSignatureFromIdentity = function (oIdentity)
{
if (oIdentity)
{
var self = this;
this.editor(function (oEditor) {
var bHtml = false, sSignature = oIdentity.signature();
if ('' !== sSignature)
{
if (':HTML:' === sSignature.substr(0, 6))
{
bHtml = true;
sSignature = sSignature.substr(6);
}
}
oEditor.setSignature(self.converSignature(sSignature),
bHtml, !!oIdentity.signatureInsertBefore());
});
}
};
/**
* @param {string=} sType = Enums.ComposeType.Empty
* @param {?MessageModel|Array=} oMessageOrArray = null
@ -956,6 +908,28 @@
}
};
/**
*
* @param {Array} aList
* @param {boolean} bFriendly
* @returns {string}
*/
ComposePopupView.prototype.emailArrayToStringLineHelper = function (aList, bFriendly)
{
var
iIndex = 0,
iLen = aList.length,
aResult = []
;
for (; iIndex < iLen; iIndex++)
{
aResult.push(aList[iIndex].toLine(!!bFriendly));
}
return aResult.join(', ');
};
/**
* @param {string=} sType = Enums.ComposeType.Empty
* @param {?MessageModel|Array=} oMessageOrArray = null
@ -984,26 +958,10 @@
oExcludeEmail = {},
oIdentity = null,
mEmail = AccountStore.email(),
sSignature = AccountStore.signature(),
aDownloads = [],
aDraftInfo = null,
oMessage = null,
sComposeType = sType || Enums.ComposeType.Empty,
fEmailArrayToStringLineHelper = function (aList, bFriendly) {
var
iIndex = 0,
iLen = aList.length,
aResult = []
;
for (; iIndex < iLen; iIndex++)
{
aResult.push(aList[iIndex].toLine(!!bFriendly));
}
return aResult.join(', ');
}
sComposeType = sType || Enums.ComposeType.Empty
;
oMessageOrArray = oMessageOrArray || null;
@ -1013,39 +971,34 @@
(!Utils.isArray(oMessageOrArray) ? oMessageOrArray : null);
}
this.oLastMessage = oMessage;
if (null !== mEmail)
{
oExcludeEmail[mEmail] = true;
}
this.reset();
oIdentity = this.findIdentityByMessage(sComposeType, oMessage);
if (oIdentity)
{
oExcludeEmail[oIdentity.email()] = true;
this.currentIdentityID(oIdentity.id());
}
else
{
this.currentIdentityID('');
}
this.reset();
this.currentIdentityID.valueHasMutated(); // Populate BBC from Identity
if (Utils.isNonEmptyArray(aToEmails))
{
this.to(fEmailArrayToStringLineHelper(aToEmails));
this.to(this.emailArrayToStringLineHelper(aToEmails));
}
if (Utils.isNonEmptyArray(aCcEmails))
{
this.cc(fEmailArrayToStringLineHelper(aCcEmails));
this.cc(this.emailArrayToStringLineHelper(aCcEmails));
}
if (Utils.isNonEmptyArray(aBccEmails))
{
this.bcc(fEmailArrayToStringLineHelper(aBccEmails));
this.bcc(this.emailArrayToStringLineHelper(aBccEmails));
}
if ('' !== sComposeType && oMessage)
@ -1074,7 +1027,7 @@
break;
case Enums.ComposeType.Reply:
this.to(fEmailArrayToStringLineHelper(oMessage.replyEmails(oExcludeEmail)));
this.to(this.emailArrayToStringLineHelper(oMessage.replyEmails(oExcludeEmail)));
this.subject(Utils.replySubjectAdd('Re', sSubject));
this.prepearMessageAttachments(oMessage, sComposeType);
this.aDraftInfo = ['reply', oMessage.uid, oMessage.folderFullNameRaw];
@ -1084,8 +1037,8 @@
case Enums.ComposeType.ReplyAll:
aResplyAllParts = oMessage.replyAllEmails(oExcludeEmail);
this.to(fEmailArrayToStringLineHelper(aResplyAllParts[0]));
this.cc(fEmailArrayToStringLineHelper(aResplyAllParts[1]));
this.to(this.emailArrayToStringLineHelper(aResplyAllParts[0]));
this.cc(this.emailArrayToStringLineHelper(aResplyAllParts[1]));
this.subject(Utils.replySubjectAdd('Re', sSubject));
this.prepearMessageAttachments(oMessage, sComposeType);
this.aDraftInfo = ['reply', oMessage.uid, oMessage.folderFullNameRaw];
@ -1110,10 +1063,10 @@
break;
case Enums.ComposeType.Draft:
this.to(fEmailArrayToStringLineHelper(oMessage.to));
this.cc(fEmailArrayToStringLineHelper(oMessage.cc));
this.bcc(fEmailArrayToStringLineHelper(oMessage.bcc));
this.replyTo(fEmailArrayToStringLineHelper(oMessage.replyTo));
this.to(this.emailArrayToStringLineHelper(oMessage.to));
this.cc(this.emailArrayToStringLineHelper(oMessage.cc));
this.bcc(this.emailArrayToStringLineHelper(oMessage.bcc));
this.replyTo(this.emailArrayToStringLineHelper(oMessage.replyTo));
this.bFromDraft = true;
@ -1129,10 +1082,10 @@
break;
case Enums.ComposeType.EditAsNew:
this.to(fEmailArrayToStringLineHelper(oMessage.to));
this.cc(fEmailArrayToStringLineHelper(oMessage.cc));
this.bcc(fEmailArrayToStringLineHelper(oMessage.bcc));
this.replyTo(fEmailArrayToStringLineHelper(oMessage.replyTo));
this.to(this.emailArrayToStringLineHelper(oMessage.to));
this.cc(this.emailArrayToStringLineHelper(oMessage.cc));
this.bcc(this.emailArrayToStringLineHelper(oMessage.bcc));
this.replyTo(this.emailArrayToStringLineHelper(oMessage.replyTo));
this.subject(sSubject);
this.prepearMessageAttachments(oMessage, sComposeType);
@ -1153,7 +1106,7 @@
'EMAIL': sFrom
});
sText = '<br /><br />' + sReplyTitle + ':' +
sText = '<br />' + sReplyTitle + ':' +
'<blockquote><p>' + sText + '</p></blockquote>';
break;
@ -1162,7 +1115,7 @@
sFrom = oMessage.fromToLine(false, true);
sTo = oMessage.toToLine(false, true);
sCc = oMessage.ccToLine(false, true);
sText = '<br /><br /><br />' + Translator.i18n('COMPOSE/FORWARD_MESSAGE_TOP_TITLE') +
sText = '<br /><br />' + Translator.i18n('COMPOSE/FORWARD_MESSAGE_TOP_TITLE') +
'<br />' + Translator.i18n('COMPOSE/FORWARD_MESSAGE_TOP_FROM') + ': ' + sFrom +
'<br />' + Translator.i18n('COMPOSE/FORWARD_MESSAGE_TOP_TO') + ': ' + sTo +
(0 < sCc.length ? '<br />' + Translator.i18n('COMPOSE/FORWARD_MESSAGE_TOP_CC') + ': ' + sCc : '') +
@ -1175,19 +1128,20 @@
break;
}
if ('' !== sSignature &&
Enums.ComposeType.EditAsNew !== sComposeType && Enums.ComposeType.Draft !== sComposeType)
{
sText = this.convertSignature(sText, sSignature, fEmailArrayToStringLineHelper(oMessage.from, true), sComposeType);
}
this.editor(function (oEditor) {
oEditor.setHtml(sText, false);
if (Enums.EditorDefaultType.PlainForced === self.editorDefaultType() ||
(!oMessage.isHtml() && Enums.EditorDefaultType.HtmlForced !== self.editorDefaultType()))
{
oEditor.modeToggle(false);
}
if (oIdentity)
{
self.setSignatureFromIdentity(oIdentity);
}
});
}
else if (Enums.ComposeType.Empty === sComposeType)
@ -1195,18 +1149,21 @@
this.subject(Utils.isNormal(sCustomSubject) ? '' + sCustomSubject : '');
sText = Utils.isNormal(sCustomPlainText) ? '' + sCustomPlainText : '';
if ('' !== sSignature)
{
sText = this.convertSignature(Utils.plainToHtml(sText, true), sSignature, '', sComposeType);
}
this.editor(function (oEditor) {
oEditor.setHtml(sText, false);
if (Enums.EditorDefaultType.Html !== self.editorDefaultType() &&
Enums.EditorDefaultType.HtmlForced !== self.editorDefaultType())
{
oEditor.modeToggle(false);
}
if (oIdentity)
{
self.setSignatureFromIdentity(oIdentity);
}
});
}
else if (Utils.isNonEmptyArray(oMessageOrArray))
@ -1214,6 +1171,22 @@
_.each(oMessageOrArray, function (oMessage) {
self.addMessageAsAttachment(oMessage);
});
this.editor(function (oEditor) {
oEditor.setHtml('', false);
if (Enums.EditorDefaultType.Html !== self.editorDefaultType() &&
Enums.EditorDefaultType.HtmlForced !== self.editorDefaultType())
{
oEditor.modeToggle(false);
}
if (oIdentity)
{
self.setSignatureFromIdentity(oIdentity);
}
});
}
aDownloads = this.getAttachmentsDownloadsForUpload();
@ -1252,6 +1225,11 @@
}, aDownloads);
}
if (oIdentity)
{
this.currentIdentity(oIdentity);
}
this.triggerForResize();
};

View file

@ -26,6 +26,8 @@
{
AbstractView.call(this, 'Popups', 'PopupsIdentity');
var self = this;
this.id = '';
this.edit = ko.observable(false);
this.owner = ko.observable(false);
@ -43,16 +45,32 @@
this.bcc.focused = ko.observable(false);
this.signature = ko.observable('');
this.signatureInsertBefore = ko.observable(false);
// this.email.subscribe(function () {
// this.email.hasError(false);
// }, this);
this.showBcc = ko.observable(false);
this.showReplyTo = ko.observable(false);
this.submitRequest = ko.observable(false);
this.submitError = ko.observable('');
this.bcc.subscribe(function (aValue) {
if (false === self.showBcc() && 0 < aValue.length)
{
self.showBcc(true);
}
}, this);
this.replyTo.subscribe(function (aValue) {
if (false === self.showReplyTo() && 0 < aValue.length)
{
self.showReplyTo(true);
}
}, this);
this.addOrEditIdentityCommand = Utils.createCommand(this, function () {
this.populateSignatureFromEditor();
if (!this.email.hasError())
{
this.email.hasError('' === Utils.trim(this.email()));
@ -102,7 +120,8 @@
this.submitError(Translator.getNotification(Enums.Notification.UnknownError));
}
}, this), this.id, this.email(), this.name(), this.replyTo(), this.bcc());
}, this), this.id, this.email(), this.name(), this.replyTo(), this.bcc(),
this.signature(), this.signatureInsertBefore());
return true;
@ -126,17 +145,22 @@
this.email('');
this.replyTo('');
this.bcc('');
this.signature('');
this.signatureInsertBefore(false);
this.email.hasError(false);
this.replyTo.hasError(false);
this.bcc.hasError(false);
this.showBcc(false);
this.showReplyTo(false);
this.submitRequest(false);
this.submitError('');
if (this.editor)
{
this.editor.clear(false);
this.editor.setPlain('', false);
}
};
@ -156,6 +180,8 @@
this.email(oIdentity.email());
this.replyTo(oIdentity.replyTo());
this.bcc(oIdentity.bcc());
this.signature(oIdentity.signature());
this.signatureInsertBefore(oIdentity.signatureInsertBefore());
this.owner(this.id === '');
}
@ -185,15 +211,23 @@
}
};
IdentityPopupView.prototype.populateSignatureFromEditor = function ()
{
if (this.editor)
{
this.signature(
(this.editor.isHtml() ? ':HTML:' : '') + this.editor.getData()
);
}
};
IdentityPopupView.prototype.onFocus = function ()
{
if (!this.editor && this.signatureDom())
{
var self = this;
this.editor = new HtmlEditor(self.signatureDom(), function () {
self.signature(
(self.editor.isHtml() ? ':HTML:' : '') + self.editor.getData()
);
self.populateSignatureFromEditor();
}, function () {
self.setSignature(self.signature());
});

179
dev/View/Popup/Template.js Normal file
View file

@ -0,0 +1,179 @@
(function () {
'use strict';
var
_ = require('_'),
ko = require('ko'),
Enums = require('Common/Enums'),
Utils = require('Common/Utils'),
Translator = require('Common/Translator'),
HtmlEditor = require('Common/HtmlEditor'),
Remote = require('Storage/User/Remote'),
kn = require('Knoin/Knoin'),
AbstractView = require('Knoin/AbstractView')
;
/**
* @constructor
* @extends AbstractView
*/
function TemplatePopupView()
{
AbstractView.call(this, 'Popups', 'PopupsTemplate');
this.editor = null;
this.signatureDom = ko.observable(null);
this.id = ko.observable('');
this.name = ko.observable('');
this.name.error = ko.observable(false);
this.name.focus = ko.observable(false);
this.body = ko.observable('');
this.body.error = ko.observable(false);
this.name.subscribe(function () {
this.name.error(false);
}, this);
this.body.subscribe(function () {
this.body.error(false);
}, this);
this.submitRequest = ko.observable(false);
this.submitError = ko.observable('');
this.addTemplateCommand = Utils.createCommand(this, function () {
this.name.error('' === Utils.trim(this.name()));
this.body.error('' === Utils.trim(this.body()) ||
':HTML:' === Utils.trim(this.body()));
if (this.name.error() || this.body.error())
{
return false;
}
this.submitRequest(true);
Remote.templateSetup(_.bind(function (sResult, oData) {
this.submitRequest(false);
if (Enums.StorageResultType.Success === sResult && oData)
{
if (oData.Result)
{
require('App/User').templates();
this.cancelCommand();
}
else if (oData.ErrorCode)
{
this.submitError(Translator.getNotification(oData.ErrorCode));
}
}
else
{
this.submitError(Translator.getNotification(Enums.Notification.UnknownError));
}
}, this), this.id(), this.name(), this.body());
return true;
}, function () {
return !this.submitRequest();
});
kn.constructorEnd(this);
}
kn.extendAsViewModel(['View/Popup/Template'], TemplatePopupView);
_.extend(TemplatePopupView.prototype, AbstractView.prototype);
TemplatePopupView.prototype.clearPopup = function ()
{
this.id('');
this.name('');
this.name.error(false);
this.body('');
this.body.loading(false);
this.body.error(false);
this.submitRequest(false);
this.submitError('');
};
TemplatePopupView.prototype.editorSetBody = function (sBody)
{
var
self = this,
fEditorSetData = function (sBody) {
if (self.editor)
{
if (':HTML:' === sBody.substr(0, 6))
{
self.editor.setHtml(sBody.substr(6), false);
}
else
{
self.editor.setPlain(sBody, false);
}
}
}
;
if (!this.editor && this.signatureDom())
{
this.editor = new HtmlEditor(self.signatureDom(), function () {
self.body(
(self.editor.isHtml() ? ':HTML:' : '') + self.editor.getData()
);
}, function () {
fEditorSetData(sBody);
});
}
else if (this.editor)
{
fEditorSetData(sBody);
}
};
TemplatePopupView.prototype.onShow = function (oTemplate)
{
var self = this;
this.clearPopup();
if (oTemplate && oTemplate.id)
{
this.id(oTemplate.id);
this.name(oTemplate.name);
this.body.loading(true);
Remote.templateGetById(function () {
self.body.loading(false);
self.editorSetBody('');
}, this.id());
}
};
TemplatePopupView.prototype.onFocus = function ()
{
this.name.focus(true);
};
module.exports = TemplatePopupView;
}());

View file

@ -190,7 +190,7 @@
this.viewDate = ko.observable('');
this.viewSize = ko.observable('');
this.viewMoment = ko.observable('');
this.viewLineAsCcc = ko.observable('');
this.viewLineAsCss = ko.observable('');
this.viewViewLink = ko.observable('');
this.viewDownloadLink = ko.observable('');
this.viewUserPic = ko.observable(Consts.DataImages.UserDotPic);
@ -272,7 +272,7 @@
this.viewDate(oMessage.fullFormatDateValue());
this.viewSize(oMessage.friendlySize());
this.viewMoment(oMessage.momentDate());
this.viewLineAsCcc(oMessage.lineAsCcc());
this.viewLineAsCss(oMessage.lineAsCss());
this.viewViewLink(oMessage.viewLink());
this.viewDownloadLink(oMessage.downloadLink());
this.viewIsImportant(oMessage.isImportant());