diff --git a/dev/Apps/RainLoopApp.js b/dev/Apps/RainLoopApp.js
index b94a981d8..8aa5d60db 100644
--- a/dev/Apps/RainLoopApp.js
+++ b/dev/Apps/RainLoopApp.js
@@ -25,12 +25,12 @@
Cache = require('Storage:RainLoop:Cache'),
Remote = require('Storage:RainLoop:Remote'),
- EmailModel = require('Model:Email'),
- FolderModel = require('Model:Folder'),
- MessageModel = require('Model:Message'),
- AccountModel = require('Model:Account'),
- IdentityModel = require('Model:Identity'),
- OpenPgpKeyModel = require('Model:OpenPgpKey'),
+ EmailModel = require('Model/Email'),
+ FolderModel = require('Model/Folder'),
+ MessageModel = require('Model/Message'),
+ AccountModel = require('Model/Account'),
+ IdentityModel = require('Model/Identity'),
+ OpenPgpKeyModel = require('Model/OpenPgpKey'),
AbstractApp = require('App:Abstract')
;
@@ -1298,19 +1298,20 @@
{
this.setTitle(Utils.i18n('TITLES/LOADING'));
- this.folders(_.bind(function (bValue) {
+ require.ensure([], function () {
- if (bValue)
- {
- require.ensure([], function () {
+ self.folders(_.bind(function (bValue) {
- kn.hideLoading();
+ kn.hideLoading();
+ if (bValue)
+ {
if (window.$LAB && window.crypto && window.crypto.getRandomValues && Settings.capa(Enums.Capa.OpenPGP))
{
window.$LAB.script(window.openpgp ? '' : LinkBuilder.openPgpJs()).wait(function () {
if (window.openpgp)
{
+ Data.openpgp = window.openpgp;
Data.openpgpKeyring = new window.openpgp.Keyring();
Data.capaOpenPGP(true);
@@ -1400,21 +1401,20 @@
self.initLayoutResizer('#rl-left', '#rl-right', Enums.ClientSideKeyName.FolderListSize);
});
}
- });
- }
- else
- {
- kn.hideLoading();
+ }
+ else
+ {
+ self.bootstartLoginScreen();
+ }
- self.bootstartLoginScreen();
- }
+ if (window.SimplePace)
+ {
+ window.SimplePace.set(100);
+ }
- if (window.SimplePace)
- {
- window.SimplePace.set(100);
- }
-
- }, this));
+ }, self));
+
+ });
}
else
{
diff --git a/dev/Boot.js b/dev/Boot.js
index 7859b25d7..eec1bff40 100644
--- a/dev/Boot.js
+++ b/dev/Boot.js
@@ -15,26 +15,25 @@
Utils = require('Common/Utils'),
Enums = require('Common/Enums'),
- EmailModel = require('Model:Email')
+ EmailModel = require('Model/Email')
;
- Globals.__APP = App;
+ Globals.__APP__ = App;
- Plugins.__boot = App;
- Plugins.__remote = App.remote();
- Plugins.__data = App.data();
+ Globals.$win
+ .keydown(Utils.killCtrlAandS)
+ .keyup(Utils.killCtrlAandS)
+ .unload(function () {
+ Globals.bUnload = true;
+ })
+ ;
- Globals.$html.addClass(Globals.bMobileDevice ? 'mobile' : 'no-mobile');
-
- Globals.$win.keydown(Utils.killCtrlAandS).keyup(Utils.killCtrlAandS);
-
- Globals.$win.unload(function () {
- Globals.bUnload = true;
- });
-
- Globals.$html.on('click.dropdown.data-api', function () {
- Utils.detectDropdownVisibility();
- });
+ Globals.$html
+ .addClass(Globals.bMobileDevice ? 'mobile' : 'no-mobile')
+ .on('click.dropdown.data-api', function () {
+ Utils.detectDropdownVisibility();
+ })
+ ;
// export
window['rl'] = window['rl'] || {};
@@ -49,7 +48,6 @@
window['__APP_BOOT'] = function (fCall) {
- // boot
$(function () {
if (window['rainloopTEMPLATES'] && window['rainloopTEMPLATES'][0])
@@ -59,7 +57,11 @@
_.delay(function () {
App.bootstart();
- Globals.$html.removeClass('no-js rl-booted-trigger').addClass('rl-booted');
+
+ Globals.$html
+ .removeClass('no-js rl-booted-trigger')
+ .addClass('rl-booted')
+ ;
}, 10);
}
diff --git a/dev/Common/Globals.js b/dev/Common/Globals.js
index 7f4e4f65e..ce60cbb66 100644
--- a/dev/Common/Globals.js
+++ b/dev/Common/Globals.js
@@ -118,7 +118,7 @@
/**
* @type {*}
*/
- Globals.__APP = null;
+ Globals.__APP__ = null;
/**
* @type {Object}
diff --git a/dev/Common/Plugins.js b/dev/Common/Plugins.js
index da37b5223..c25564796 100644
--- a/dev/Common/Plugins.js
+++ b/dev/Common/Plugins.js
@@ -6,6 +6,7 @@
var
_ = require('_'),
+ Globals = require('Common/Globals'),
Utils = require('Common/Utils')
;
@@ -14,19 +15,15 @@
*/
function Plugins()
{
- this.__boot = null;
- this.__data = null;
- this.__remote = null;
-
this.oSettings = require('Storage:Settings');
-
this.oViewModelsHooks = {};
this.oSimpleHooks = {};
}
- Plugins.prototype.__boot = null;
- Plugins.prototype.__data = null;
- Plugins.prototype.__remote = null;
+ /**
+ * @type {Object}
+ */
+ Plugins.prototype.oSettings = {};
/**
* @type {Object}
@@ -90,9 +87,9 @@
*/
Plugins.prototype.remoteRequest = function (fCallback, sAction, oParameters, iTimeout, sGetAdd, aAbortActions)
{
- if (this.__remote)
+ if (Globals.__APP__)
{
- this.__remote.defaultRequest(fCallback, sAction, oParameters, iTimeout, sGetAdd, aAbortActions);
+ Globals.__APP__.remote().defaultRequest(fCallback, sAction, oParameters, iTimeout, sGetAdd, aAbortActions);
}
};
diff --git a/dev/Common/Utils.js b/dev/Common/Utils.js
index 702b94cc4..660d5c0de 100644
--- a/dev/Common/Utils.js
+++ b/dev/Common/Utils.js
@@ -10,6 +10,7 @@
_ = require('_'),
$ = require('$'),
ko = require('ko'),
+ Autolinker = require('Autolinker'),
Enums = require('Common/Enums'),
Consts = require('Common/Consts'),
@@ -146,7 +147,7 @@
oEmailModel = null,
sEmail = sMailToUrl.replace(/\?.+$/, ''),
sQueryString = sMailToUrl.replace(/^[^\?]*\?/, ''),
- EmailModel = require('Model:Email')
+ EmailModel = require('Model/Email')
;
oEmailModel = new EmailModel();
@@ -1517,10 +1518,10 @@
/**
* @param {string} sPlain
- * @param {boolean} bLinkify = false
+ * @param {boolean} bFindEmailAndLinks = false
* @return {string}
*/
- Utils.plainToHtml = function (sPlain, bLinkify)
+ Utils.plainToHtml = function (sPlain, bFindEmailAndLinks)
{
sPlain = sPlain.toString().replace(/\r/g, '');
@@ -1551,9 +1552,16 @@
}
else if (!bStart && bIn)
{
- bIn = false;
- aNextText.push('~~~/blockquote~~~');
- aNextText.push(sLine);
+ if ('' !== sLine)
+ {
+ bIn = false;
+ aNextText.push('~~~/blockquote~~~');
+ aNextText.push(sLine);
+ }
+ else
+ {
+ aNextText.push(sLine);
+ }
}
else if (bStart && bIn)
{
@@ -1578,6 +1586,7 @@
sPlain = aText.join("\n");
sPlain = sPlain
+// .replace(/~~~\/blockquote~~~\n~~~blockquote~~~/g, '\n')
.replace(/&/g, '&')
.replace(/>/g, '>').replace(/')
@@ -1585,7 +1594,7 @@
.replace(/[\-_~]{10,}/g, '
')
.replace(/\n/g, ' ');
- return bLinkify ? Utils.linkify(sPlain) : sPlain;
+ return bFindEmailAndLinks ? Utils.findEmailAndLinks(sPlain) : sPlain;
};
window.rainloop_Utils_htmlToPlain = Utils.htmlToPlain;
@@ -1595,17 +1604,25 @@
* @param {string} sHtml
* @return {string}
*/
- Utils.linkify = function (sHtml)
+ Utils.findEmailAndLinks = function (sHtml)
{
- if ($.fn && $.fn.linkify)
- {
- sHtml = Globals.$div.html(sHtml.replace(/&/ig, 'amp_amp_12345_amp_amp'))
- .linkify()
- .find('.linkified').removeClass('linkified').end()
- .html()
- .replace(/amp_amp_12345_amp_amp/g, '&')
- ;
- }
+ sHtml = Autolinker.link(sHtml, {
+ 'newWindow': true,
+ 'stripPrefix': false,
+ 'urls': true,
+ 'email': true,
+ 'twitter': false
+ });
+
+// if ($.fn && $.fn.linkify)
+// {
+// sHtml = Globals.$div.html(sHtml.replace(/&/ig, 'amp_amp_12345_amp_amp'))
+// .linkify()
+// .find('.linkified').removeClass('linkified').end()
+// .html()
+// .replace(/amp_amp_12345_amp_amp/g, '&')
+// ;
+// }
return sHtml;
};
@@ -1936,6 +1953,29 @@
}
};
+
+ /**
+ * @param {string} sLanguage
+ * @param {Function=} fDone
+ * @param {Function=} fFail
+ * @param {Function=} fAllways
+ */
+ Utils.reloadLanguage = function (sLanguage, fDone, fFail, fAllways)
+ {
+ $.ajax({
+ 'url': require('Common/LinkBuilder').langLink(sLanguage),
+ 'dataType': 'script',
+ 'cache': true
+ })
+ .done(function () {
+ Utils.i18nReload();
+ (fDone || Utils.emptyFunction)();
+ })
+ .fail(fFail || Utils.emptyFunction)
+ .always(fAllways || Utils.emptyFunction)
+ ;
+ };
+
module.exports = Utils;
}());
\ No newline at end of file
diff --git a/dev/External/ko.js b/dev/External/ko.js
index fd2cbc7e6..a549085e2 100644
--- a/dev/External/ko.js
+++ b/dev/External/ko.js
@@ -568,7 +568,7 @@
var
Utils = require('Common/Utils'),
- EmailModel = require('Model:Email'),
+ EmailModel = require('Model/Email'),
$oEl = $(oElement),
fValue = fValueAccessor(),
@@ -600,7 +600,6 @@
{
oEmail = new EmailModel();
oEmail.mailsoParse(sValue);
- oEmail.clearDuplicateName();
return [oEmail.toLine(false), oEmail];
}
@@ -642,7 +641,7 @@
var
Utils = require('Common/Utils'),
- ContactTagModel = require('Model:ContactTag'),
+ ContactTagModel = require('Model/ContactTag'),
$oEl = $(oElement),
fValue = fValueAccessor(),
diff --git a/dev/Models/AccountModel.js b/dev/Model/Account.js
similarity index 100%
rename from dev/Models/AccountModel.js
rename to dev/Model/Account.js
diff --git a/dev/Models/AttachmentModel.js b/dev/Model/Attachment.js
similarity index 100%
rename from dev/Models/AttachmentModel.js
rename to dev/Model/Attachment.js
diff --git a/dev/Models/ComposeAttachmentModel.js b/dev/Model/ComposeAttachment.js
similarity index 100%
rename from dev/Models/ComposeAttachmentModel.js
rename to dev/Model/ComposeAttachment.js
diff --git a/dev/Models/ContactModel.js b/dev/Model/Contact.js
similarity index 100%
rename from dev/Models/ContactModel.js
rename to dev/Model/Contact.js
diff --git a/dev/Models/ContactPropertyModel.js b/dev/Model/ContactProperty.js
similarity index 100%
rename from dev/Models/ContactPropertyModel.js
rename to dev/Model/ContactProperty.js
diff --git a/dev/Models/ContactTagModel.js b/dev/Model/ContactTag.js
similarity index 100%
rename from dev/Models/ContactTagModel.js
rename to dev/Model/ContactTag.js
diff --git a/dev/Models/EmailModel.js b/dev/Model/Email.js
similarity index 100%
rename from dev/Models/EmailModel.js
rename to dev/Model/Email.js
diff --git a/dev/Models/FilterModel.js b/dev/Model/Filter.js
similarity index 97%
rename from dev/Models/FilterModel.js
rename to dev/Model/Filter.js
index 54f0a26b0..88f6da5d3 100644
--- a/dev/Models/FilterModel.js
+++ b/dev/Model/Filter.js
@@ -8,7 +8,7 @@
Enums = require('Common/Enums'),
Utils = require('Common/Utils'),
- FilterConditionModel = require('Model:FilterCondition')
+ FilterConditionModel = require('Model/FilterCondition')
;
/**
diff --git a/dev/Models/FilterConditionModel.js b/dev/Model/FilterCondition.js
similarity index 100%
rename from dev/Models/FilterConditionModel.js
rename to dev/Model/FilterCondition.js
diff --git a/dev/Models/FolderModel.js b/dev/Model/Folder.js
similarity index 100%
rename from dev/Models/FolderModel.js
rename to dev/Model/Folder.js
diff --git a/dev/Models/IdentityModel.js b/dev/Model/Identity.js
similarity index 100%
rename from dev/Models/IdentityModel.js
rename to dev/Model/Identity.js
diff --git a/dev/Models/MessageModel.js b/dev/Model/Message.js
similarity index 99%
rename from dev/Models/MessageModel.js
rename to dev/Model/Message.js
index 33a380f90..718db9f50 100644
--- a/dev/Models/MessageModel.js
+++ b/dev/Model/Message.js
@@ -15,8 +15,8 @@
Globals = require('Common/Globals'),
LinkBuilder = require('Common/LinkBuilder'),
- EmailModel = require('Model:Email'),
- AttachmentModel = require('Model:Attachment')
+ EmailModel = require('Model/Email'),
+ AttachmentModel = require('Model/Attachment')
;
/**
@@ -431,8 +431,8 @@
MessageModel.prototype.initUpdateByMessageJson = function (oJsonMessage)
{
var
- Data = require('Storage:RainLoop:Data'),
bResult = false,
+ Data = require('Storage:RainLoop:Data'),
iPriority = Enums.MessagePriority.Normal
;
@@ -1156,7 +1156,7 @@
try
{
- mPgpMessage = window.openpgp.cleartext.readArmored(this.plainRaw);
+ mPgpMessage = Data.openpgp.cleartext.readArmored(this.plainRaw);
if (mPgpMessage && mPgpMessage.getText)
{
this.pgpSignedVerifyStatus(
@@ -1226,7 +1226,7 @@
try
{
- mPgpMessage = window.openpgp.message.readArmored(this.plainRaw);
+ mPgpMessage = Data.openpgp.message.readArmored(this.plainRaw);
if (mPgpMessage && oPrivateKey && mPgpMessage.decrypt)
{
this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Unverified);
diff --git a/dev/Models/OpenPgpKeyModel.js b/dev/Model/OpenPgpKey.js
similarity index 100%
rename from dev/Models/OpenPgpKeyModel.js
rename to dev/Model/OpenPgpKey.js
diff --git a/dev/Settings/App/SettingsContacts.js b/dev/Settings/App/SettingsContacts.js
index d0993a438..d2ae55609 100644
--- a/dev/Settings/App/SettingsContacts.js
+++ b/dev/Settings/App/SettingsContacts.js
@@ -47,7 +47,7 @@
SettingsContacts.prototype.onBuild = function ()
{
Data.contactsAutosave.subscribe(function (bValue) {
- Remote.saveSettings(Utils.emptyFunction, {
+ Remote.saveSettings(null, {
'ContactsAutosave': bValue ? '1' : '0'
});
});
diff --git a/dev/Settings/App/SettingsFilters.js b/dev/Settings/App/SettingsFilters.js
index 244d3666c..1ec2c476b 100644
--- a/dev/Settings/App/SettingsFilters.js
+++ b/dev/Settings/App/SettingsFilters.js
@@ -30,7 +30,7 @@
SettingsFilters.prototype.addFilter = function ()
{
var
- FilterModel = require('Model:Filter')
+ FilterModel = require('Model/Filter')
;
require('App:Knoin').showScreenPopup(
diff --git a/dev/Settings/App/SettingsGeneral.js b/dev/Settings/App/SettingsGeneral.js
index 74a6b7ca7..6682dbbc4 100644
--- a/dev/Settings/App/SettingsGeneral.js
+++ b/dev/Settings/App/SettingsGeneral.js
@@ -76,28 +76,23 @@
self.languageTrigger(Enums.SaveSettingsStep.Animate);
- $.ajax({
- 'url': LinkBuilder.langLink(sValue),
- 'dataType': 'script',
- 'cache': true
- }).done(function() {
- Utils.i18nReload();
+ Utils.reloadLanguage(sValue, function() {
self.languageTrigger(Enums.SaveSettingsStep.TrueResult);
- }).fail(function() {
+ }, function() {
self.languageTrigger(Enums.SaveSettingsStep.FalseResult);
- }).always(function() {
+ }, function() {
_.delay(function () {
self.languageTrigger(Enums.SaveSettingsStep.Idle);
}, 1000);
});
- Remote.saveSettings(Utils.emptyFunction, {
+ Remote.saveSettings(null, {
'Language': sValue
});
});
Data.editorDefaultType.subscribe(function (sValue) {
- Remote.saveSettings(Utils.emptyFunction, {
+ Remote.saveSettings(null, {
'EditorDefaultType': sValue
});
});
@@ -109,20 +104,20 @@
});
Data.showImages.subscribe(function (bValue) {
- Remote.saveSettings(Utils.emptyFunction, {
+ Remote.saveSettings(null, {
'ShowImages': bValue ? '1' : '0'
});
});
Data.interfaceAnimation.subscribe(function (sValue) {
- Remote.saveSettings(Utils.emptyFunction, {
+ Remote.saveSettings(null, {
'InterfaceAnimation': sValue
});
});
Data.useDesktopNotifications.subscribe(function (bValue) {
Utils.timeOutAction('SaveDesktopNotifications', function () {
- Remote.saveSettings(Utils.emptyFunction, {
+ Remote.saveSettings(null, {
'DesktopNotifications': bValue ? '1' : '0'
});
}, 3000);
@@ -130,7 +125,7 @@
Data.replySameFolder.subscribe(function (bValue) {
Utils.timeOutAction('SaveReplySameFolder', function () {
- Remote.saveSettings(Utils.emptyFunction, {
+ Remote.saveSettings(null, {
'ReplySameFolder': bValue ? '1' : '0'
});
}, 3000);
@@ -140,7 +135,7 @@
Data.messageList([]);
- Remote.saveSettings(Utils.emptyFunction, {
+ Remote.saveSettings(null, {
'UseThreads': bValue ? '1' : '0'
});
});
@@ -149,13 +144,13 @@
Data.messageList([]);
- Remote.saveSettings(Utils.emptyFunction, {
+ Remote.saveSettings(null, {
'Layout': nValue
});
});
Data.useCheckboxesInList.subscribe(function (bValue) {
- Remote.saveSettings(Utils.emptyFunction, {
+ Remote.saveSettings(null, {
'UseCheckboxesInList': bValue ? '1' : '0'
});
});
diff --git a/dev/Settings/App/SettingsThemes.js b/dev/Settings/App/SettingsThemes.js
index bb10a685a..ab3880f42 100644
--- a/dev/Settings/App/SettingsThemes.js
+++ b/dev/Settings/App/SettingsThemes.js
@@ -29,8 +29,8 @@
this.themeTrigger = ko.observable(Enums.SaveSettingsStep.Idle).extend({'throttle': 100});
- this.oLastAjax = null;
this.iTimer = 0;
+ this.oThemeAjaxRequest = null;
Data.theme.subscribe(function (sValue) {
@@ -62,12 +62,12 @@
window.clearTimeout(self.iTimer);
self.themeTrigger(Enums.SaveSettingsStep.Animate);
- if (this.oLastAjax && this.oLastAjax.abort)
+ if (this.oThemeAjaxRequest && this.oThemeAjaxRequest.abort)
{
- this.oLastAjax.abort();
+ this.oThemeAjaxRequest.abort();
}
- this.oLastAjax = $.ajax({
+ this.oThemeAjaxRequest = $.ajax({
'url': sUrl,
'dataType': 'json'
}).done(function(aData) {
@@ -103,7 +103,7 @@
self.themeTrigger(Enums.SaveSettingsStep.Idle);
}, 1000);
- self.oLastAjax = null;
+ self.oThemeAjaxRequest = null;
});
}
diff --git a/dev/Storages/AbstractRemoteStorage.js b/dev/Storages/AbstractRemoteStorage.js
index 356ba6d33..0759e1743 100644
--- a/dev/Storages/AbstractRemoteStorage.js
+++ b/dev/Storages/AbstractRemoteStorage.js
@@ -64,9 +64,9 @@
if (Consts.Values.TokenErrorLimit < Globals.iTokenErrorCount)
{
- if (Globals.__APP)
+ if (Globals.__APP__)
{
- Globals.__APP.loginAndLogoutReload(true);
+ Globals.__APP__.loginAndLogoutReload(true);
}
}
@@ -77,9 +77,9 @@
window.__rlah_clear();
}
- if (Globals.__APP)
+ if (Globals.__APP__)
{
- Globals.__APP.loginAndLogoutReload(true);
+ Globals.__APP__.loginAndLogoutReload(true);
}
}
}
diff --git a/dev/Storages/DataStorage.js b/dev/Storages/DataStorage.js
index 8e5947c78..8aa50ed28 100644
--- a/dev/Storages/DataStorage.js
+++ b/dev/Storages/DataStorage.js
@@ -22,7 +22,7 @@
kn = require('App:Knoin'),
- MessageModel = require('Model:Message'),
+ MessageModel = require('Model/Message'),
LocalStorage = require('Storage:LocalStorage'),
AbstractData = require('Storage:Abstract:Data')
@@ -323,10 +323,7 @@
if (Enums.Layout.NoPreview === this.layout() &&
-1 < window.location.hash.indexOf('message-preview'))
{
- if (Globals.__APP)
- {
- Globals.__APP.historyBack();
- }
+ require('App:RainLoop').historyBack();
}
}
else if (Enums.Layout.NoPreview === this.layout())
@@ -443,6 +440,7 @@
// other
this.capaOpenPGP = ko.observable(false);
this.openpgpkeys = ko.observableArray([]);
+ this.openpgp = null;
this.openpgpKeyring = null;
this.openpgpkeysPublic = this.openpgpkeys.filter(function (oItem) {
@@ -782,7 +780,6 @@
};
/**
- * @private
* @param {Object} oMessageTextBody
*/
DataStorage.prototype.initBlockquoteSwitcher = function (oMessageTextBody)
@@ -795,22 +792,24 @@
if ($oList && 0 < $oList.length)
{
- $oList.each(function () {
- var $self = $(this), iH = $self.height();
- if (0 === iH || 100 < iH)
- {
- $self.addClass('rl-bq-switcher hidden-bq');
- $(' ')
- .insertBefore($self)
- .click(function () {
- $self.toggleClass('hidden-bq');
- Utils.windowResize();
- })
- .after(' ')
- .before(' ')
- ;
- }
- });
+ _.delay(function () {
+ $oList.each(function () {
+ var $self = $(this), iH = $self.height();
+ if (0 === iH || 150 < iH)
+ {
+ $self.addClass('rl-bq-switcher hidden-bq');
+ $(' ')
+ .insertBefore($self)
+ .click(function () {
+ $self.toggleClass('hidden-bq');
+ Utils.windowResize();
+ })
+ .after(' ')
+ .before(' ')
+ ;
+ }
+ });
+ }, 100);
}
}
};
@@ -818,6 +817,7 @@
DataStorage.prototype.setMessage = function (oData, bCached)
{
var
+ self = this,
bIsHtml = false,
bHasExternals = false,
bHasInternals = false,
@@ -908,7 +908,7 @@
}
oBody
- .html(Utils.linkify(sResultHtml))
+ .html(Utils.findEmailAndLinks(sResultHtml))
.addClass('b-text-part ' + (bIsHtml ? 'html' : 'plain'))
;
@@ -961,10 +961,7 @@
Cache.initMessageFlagsFromCache(oMessage);
if (oMessage.unseen())
{
- if (Globals.__APP)
- {
- Globals.__APP.setMessageSeen(oMessage);
- }
+ require('App:RainLoop').setMessageSeen(oMessage);
}
Utils.windowResize();
@@ -991,6 +988,7 @@
DataStorage.prototype.findPublicKeysByEmail = function (sEmail)
{
+ var self = this;
return _.compact(_.map(this.openpgpkeysPublic(), function (oItem) {
var oKey = null;
@@ -998,7 +996,7 @@
{
try
{
- oKey = window.openpgp.key.readArmored(oItem.armor);
+ oKey = self.openpgp.key.readArmored(oItem.armor);
if (oKey && !oKey.err && oKey.keys && oKey.keys[0])
{
return oKey.keys[0];
@@ -1020,6 +1018,7 @@
DataStorage.prototype.findPrivateKeyByEmail = function (sEmail, sPassword)
{
var
+ self = this,
oPrivateKey = null,
oKey = _.find(this.openpgpkeysPrivate(), function (oItem) {
return oItem && sEmail === oItem.email;
@@ -1030,7 +1029,7 @@
{
try
{
- oPrivateKey = window.openpgp.key.readArmored(oKey.armor);
+ oPrivateKey = self.openpgp.key.readArmored(oKey.armor);
if (oPrivateKey && !oPrivateKey.err && oPrivateKey.keys && oPrivateKey.keys[0])
{
oPrivateKey = oPrivateKey.keys[0];
diff --git a/dev/Storages/RemoteStorage.js b/dev/Storages/RemoteStorage.js
index d8b587667..333cf400e 100644
--- a/dev/Storages/RemoteStorage.js
+++ b/dev/Storages/RemoteStorage.js
@@ -381,10 +381,7 @@
}
else if (Data.useThreads())
{
- if (Globals.__APP)
- {
- Globals.__APP.reloadFlagsCurrentMessageListAndMessageFromCache();
- }
+ require('App:RainLoop').reloadFlagsCurrentMessageListAndMessageFromCache();
}
};
diff --git a/dev/ViewModels/LoginViewModel.js b/dev/ViewModels/LoginViewModel.js
index b9330a60d..2ef141401 100644
--- a/dev/ViewModels/LoginViewModel.js
+++ b/dev/ViewModels/LoginViewModel.js
@@ -337,18 +337,16 @@
_.delay(function () {
Data.language.subscribe(function (sValue) {
+
self.langRequest(true);
- $.ajax({
- 'url': LinkBuilder.langLink(sValue),
- 'dataType': 'script',
- 'cache': true
- }).done(function() {
+
+ Utils.reloadLanguage(sValue, function() {
self.bSendLanguage = true;
- Utils.i18nReload();
- $.cookie('rllang', Data.language(), {'expires': 30});
- }).always(function() {
+ $.cookie('rllang', sValue, {'expires': 30});
+ }, null, function() {
self.langRequest(false);
});
+
});
}, 50);
diff --git a/dev/ViewModels/Popups/PopupsComposeOpenPgpViewModel.js b/dev/ViewModels/Popups/PopupsComposeOpenPgpViewModel.js
index 2e7d531f9..1de6a3f43 100644
--- a/dev/ViewModels/Popups/PopupsComposeOpenPgpViewModel.js
+++ b/dev/ViewModels/Popups/PopupsComposeOpenPgpViewModel.js
@@ -4,7 +4,6 @@
'use strict';
var
- window = require('window'),
_ = require('_'),
ko = require('ko'),
key = require('key'),
@@ -14,7 +13,7 @@
Data = require('Storage:RainLoop:Data'),
- EmailModel = require('Model:Email'),
+ EmailModel = require('Model/Email'),
kn = require('App:Knoin'),
KnoinAbstractViewModel = require('Knoin:AbstractViewModel')
@@ -114,19 +113,19 @@
if (oPrivateKey && 0 === aPublicKeys.length)
{
self.resultCallback(
- window.openpgp.signClearMessage([oPrivateKey], self.text())
+ Data.openpgp.signClearMessage([oPrivateKey], self.text())
);
}
else if (oPrivateKey && 0 < aPublicKeys.length)
{
self.resultCallback(
- window.openpgp.signAndEncryptMessage(aPublicKeys, oPrivateKey, self.text())
+ Data.openpgp.signAndEncryptMessage(aPublicKeys, oPrivateKey, self.text())
);
}
else if (!oPrivateKey && 0 < aPublicKeys.length)
{
self.resultCallback(
- window.openpgp.encryptMessage(aPublicKeys, self.text())
+ Data.openpgp.encryptMessage(aPublicKeys, self.text())
);
}
}
diff --git a/dev/ViewModels/Popups/PopupsComposeViewModel.js b/dev/ViewModels/Popups/PopupsComposeViewModel.js
index df419f739..4a6fcb10d 100644
--- a/dev/ViewModels/Popups/PopupsComposeViewModel.js
+++ b/dev/ViewModels/Popups/PopupsComposeViewModel.js
@@ -25,7 +25,7 @@
Cache = require('Storage:RainLoop:Cache'),
Remote = require('Storage:RainLoop:Remote'),
- ComposeAttachmentModel = require('Model:ComposeAttachment'),
+ ComposeAttachmentModel = require('Model/ComposeAttachment'),
kn = require('App:Knoin'),
KnoinAbstractViewModel = require('Knoin:AbstractViewModel')
diff --git a/dev/ViewModels/Popups/PopupsContactsViewModel.js b/dev/ViewModels/Popups/PopupsContactsViewModel.js
index 1af7befeb..b7449d4aa 100644
--- a/dev/ViewModels/Popups/PopupsContactsViewModel.js
+++ b/dev/ViewModels/Popups/PopupsContactsViewModel.js
@@ -20,10 +20,10 @@
Data = require('Storage:RainLoop:Data'),
Remote = require('Storage:RainLoop:Remote'),
- EmailModel = require('Model:Email'),
- ContactModel = require('Model:Contact'),
- ContactTagModel = require('Model:ContactTag'),
- ContactPropertyModel = require('Model:ContactProperty'),
+ EmailModel = require('Model/Email'),
+ ContactModel = require('Model/Contact'),
+ ContactTagModel = require('Model/ContactTag'),
+ ContactPropertyModel = require('Model/ContactProperty'),
kn = require('App:Knoin'),
KnoinAbstractViewModel = require('Knoin:AbstractViewModel')
diff --git a/dev/ViewModels/Popups/PopupsLanguagesViewModel.js b/dev/ViewModels/Popups/PopupsLanguagesViewModel.js
index 48543f7a9..89750be23 100644
--- a/dev/ViewModels/Popups/PopupsLanguagesViewModel.js
+++ b/dev/ViewModels/Popups/PopupsLanguagesViewModel.js
@@ -22,7 +22,7 @@
{
KnoinAbstractViewModel.call(this, 'Popups', 'PopupsLanguages');
- this.Data = Globals.__APP.data(); // TODO
+ this.Data = Globals.__APP__.data(); // TODO
this.exp = ko.observable(false);
diff --git a/dev/ViewModels/Popups/PopupsNewOpenPgpKeyViewModel.js b/dev/ViewModels/Popups/PopupsNewOpenPgpKeyViewModel.js
index 1c46ba562..dc6394044 100644
--- a/dev/ViewModels/Popups/PopupsNewOpenPgpKeyViewModel.js
+++ b/dev/ViewModels/Popups/PopupsNewOpenPgpKeyViewModel.js
@@ -4,7 +4,6 @@
'use strict';
var
- window = require('window'),
_ = require('_'),
ko = require('ko'),
@@ -62,8 +61,8 @@
this.submitRequest(true);
_.delay(function () {
- // mKeyPair = window.openpgp.generateKeyPair(1, Utils.pInt(self.keyBitLength()), sUserID, Utils.trim(self.password()));
- mKeyPair = window.openpgp.generateKeyPair({
+ // mKeyPair = Data.openpgp.generateKeyPair(1, Utils.pInt(self.keyBitLength()), sUserID, Utils.trim(self.password()));
+ mKeyPair = Data.openpgp.generateKeyPair({
'userId': sUserID,
'numBits': Utils.pInt(self.keyBitLength()),
'passphrase': Utils.trim(self.password())
diff --git a/gulpfile.js b/gulpfile.js
index d79ce5cdb..e70c409e6 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -144,7 +144,7 @@ cfg.paths.js = {
'vendors/jquery-lazyload/jquery.lazyload.min.js',
'vendors/jquery-nanoscroller/jquery.nanoscroller-0.7.min.js',
'vendors/jquery-wakeup/jquery.wakeup.min.js',
- 'vendors/jquery-linkify/jquery.linkify.min.js',
+// 'vendors/jquery-linkify/jquery.linkify.min.js',
'vendors/inputosaurus/inputosaurus.min.js',
'vendors/moment/min/moment.min.js ',
'vendors/routes/signals.min.js',
@@ -154,6 +154,7 @@ cfg.paths.js = {
'vendors/knockout-projections/knockout-projections-1.0.0.min.js',
'vendors/ssm/ssm.min.js',
'vendors/jua/jua.min.js',
+ 'vendors/Autolinker/Autolinker.min.js',
'vendors/jsbn/bundle.js',
'vendors/keymaster/keymaster.js',
'vendors/ifvisible/ifvisible.min.js',
diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php
index 48c86d05d..70a7bc4b0 100644
--- a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php
+++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php
@@ -2650,13 +2650,22 @@ class Actions
$bResult = false;
$oConfig = $this->Config();
+ $sLogin = \trim($this->GetActionParam('Login', ''));
$sPassword = $this->GetActionParam('Password', '');
$sNewPassword = $this->GetActionParam('NewPassword', '');
+ $this->Logger()->AddSecret($sPassword);
+ $this->Logger()->AddSecret($sNewPassword);
+
if ($oConfig->ValidatePassword($sPassword))
{
- $bResult = true;
+ if (0 < strlen($sLogin))
+ {
+ $oConfig->Set('security', 'admin_login', $sLogin);
+ }
+
$oConfig->SetPassword($sNewPassword);
+ $bResult = true;
}
return $this->DefaultResponse(__FUNCTION__, $bResult ? $oConfig->Save() : false);
@@ -7400,6 +7409,8 @@ class Actions
$mResult['Plain'] = $sPlain;
// $mResult['Plain'] = 0 === \strlen($sPlain) ? '' : \MailSo\Base\HtmlUtils::ConvertPlainToHtml($sPlain);
+ $this->Logger()->WriteDump($mResult['Html']);
+
$mResult['TextHash'] = \md5($mResult['Html'].$mResult['Plain']);
$mResult['TextPartIsTrimmed'] = $mResponse->TextPartIsTrimmed();
diff --git a/rainloop/v/0.0.0/app/templates/Index.html b/rainloop/v/0.0.0/app/templates/Index.html
index cb5187b58..be13a044d 100644
--- a/rainloop/v/0.0.0/app/templates/Index.html
+++ b/rainloop/v/0.0.0/app/templates/Index.html
@@ -1,5 +1,5 @@
-
+
@@ -8,7 +8,7 @@
-
+```
+
+#### Using with the [Bower](http://bower.io) package manager:
+
+Command line:
+
+```shell
+bower install Autolinker.js --save
+```
+
+#### Using with [Node.js](http://nodejs.org) via [npm](https://www.npmjs.org/):
+
+Command Line:
+
+```shell
+npm install autolinker --save
+```
+
+JavaScript:
+
+```javascript
+var Autolinker = require( 'autolinker' );
+// note: npm wants an all-lowercase package name, but the utility is a class and should be
+// aliased with a captial letter
+```
+
+
+## Usage
+
+Using the static `link()` method:
+
+```javascript
+var linkedText = Autolinker.link( textToAutolink[, options] );
+```
+
+Using as a class:
+
+```javascript
+var autolinker = new Autolinker( [ options ] );
+
+var linkedText = autolinker.link( textToAutoLink );
+```
+
+
+#### Example:
+
+```javascript
+var linkedText = Autolinker.link( "Check out google.com", { className: "myLink" } );
+// Produces: "Check out google.com "
+```
+
+## Options
+
+These are the options which may be specified for linking. These are specified by providing an Object as the second parameter to `Autolinker.link()`. These include:
+
+- **newWindow** : Boolean
+ `true` to have the links should open in a new window when clicked, `false` otherwise. Defaults to `true`.
+- **stripPrefix** : Boolean
+ `true` to have the 'http://' or 'https://' and/or the 'www.' stripped from the beginning of links, `false` otherwise. Defaults to `true`.
+- **truncate** : Number
+ A number for how many characters long URLs/emails/twitter handles should be truncated to inside the text of a link. If the URL/email/twitter is over the number of characters, it will be truncated to this length by replacing the end of the string with a two period ellipsis ('..').
+ Example: a url like 'http://www.yahoo.com/some/long/path/to/a/file' truncated to 25 characters may look like this: 'yahoo.com/some/long/pat..'
+- **className** : String
+ A CSS class name to add to the generated anchor tags. This class will be added to all links, as well as this class
+ plus "url"/"email"/"twitter" suffixes for styling url/email/twitter links differently.
+
+ For example, if this config is provided as "myLink", then:
+
+ 1) URL links will have the CSS classes: "myLink myLink-url"
+ 2) Email links will have the CSS classes: "myLink myLink-email", and
+ 3) Twitter links will have the CSS classes: "myLink myLink-twitter"
+
+- **urls** : Boolean
+ `true` to have URLs auto-linked, `false` to skip auto-linking of URLs. Defaults to `true`.
+- **email** : Boolean
+ `true` to have email addresses auto-linked, `false` to skip auto-linking of email addresses. Defaults to `true`.
+- **twitter** : Boolean
+ `true` to have Twitter handles auto-linked, `false` to skip auto-linking of Twitter handles. Defaults to `true`.
+
+For example, if you wanted to disable links from opening in new windows, you could do:
+
+```javascript
+var linkedText = Autolinker.link( "Check out google.com", { newWindow: false } );
+// Produces: "Check out google.com "
+```
+
+And if you wanted to truncate the length of URLs (while also not opening in a new window), you could do:
+
+```javascript
+var linkedText = Autolinker.link( "http://www.yahoo.com/some/long/path/to/a/file", { truncate: 25, newWindow: false } );
+// Produces: "yahoo.com/some/long/pat.. "
+```
+
+## More Examples
+One could update an entire DOM element that has unlinked text to auto-link them as such:
+
+```javascript
+var myTextEl = document.getElementById( 'text' );
+myTextEl.innerHTML = Autolinker.link( myTextEl.innerHTML );
+```
+
+Using the same pre-configured Autolinker instance in multiple locations of a codebase (usually by dependency injection):
+
+```javascript
+var autolinker = new Autolinker( { newWindow: false, truncate: 25 } );
+
+//...
+
+autolinker.link( "Check out http://www.yahoo.com/some/long/path/to/a/file" );
+// Produces: "Check out yahoo.com/some/long/pat.. "
+
+//...
+
+autolinker.link( "Go to www.google.com" );
+// Produces: "Go to google.com "
+
+```
+
+
+## Changelog:
+
+### 0.11.0
+
+- Allow Autolinker to link fully-capitalized URLs/Emails/Twitter handles.
+
+### 0.10.1
+
+- Added fix to not autolink strings like "version:1.0", which were accidentally being interpreted as a protocol:domain string.
+
+### 0.10.0
+
+- Added support for protocol-relative URLs (ex: `//google.com`, which will effectively either have the `http://` or `https://`
+ protocol depending on the protocol that is hosting the website)
+
+### 0.9.4
+
+- Fixed an issue where a string in the form of `abc:def` would be autolinked as a protocol and domain name URL. Autolinker now
+ requires the domain name to have at least one period in it to be considered.
+
+### 0.9.3
+
+- Fixed an issue where Twitter handles wouldn't be autolinked if they existed as the sole entity within parenthesis or brackets
+ (thanks [@busticated](https://github.com/busticated) for pointing this out and providing unit tests)
+
+### 0.9.2
+
+- Fixed an issue with nested tags within an existing <a> tag, where the nested tags' inner text would be accidentally
+ removed from the output (thanks [@mjsabin01](https://github.com/mjsabin01))
+
+### 0.9.1
+
+- Added a patch to attempt to better handle extraneous </a> tags in the input string if any exist. This is for when the
+ input may have some invalid markup (for instance, on sites which allow user comments, blog posts, etc.).
+
+### 0.9.0
+
+- Added better support for the processing of existing HTML in the input string. Now handles namespaced tags, and attribute names
+ with dashes or any other Unicode character (thanks [@aziraphale](https://github.com/aziraphale))
+
+### 0.8.0
+
+- Added `className` option for easily styling produced links (thanks [@busticated](https://github.com/busticated))
+- Refactored into a JS class. Autolinker can now be instantiated using:
+
+```javascript
+var autolinker = new Autolinker( { newWindow: false, truncate: 25 } );
+
+autolinker.link( "Check out http://www.yahoo.com/some/long/path/to/a/file" );
+// Produces: "Check out yahoo.com/some/long/pat.. "
+```
+
+This allows options to be set on a single instance, and used throughout a codebase by injecting the `autolinker` instance as a dependency to the modules/classes that use it. (Note: Autolinker may still be used with the static `Autolinker.link()` method as was previously available as well.)
+
+### 0.7.0
+
+- Changed build system to Grunt.
+- Added AMD and CommonJS module loading support (ex: RequireJS, and Node.js's module loader).
+- Added command line Jasmine test runner (`grunt test`)
+- Upgraded Jasmine from 1.3.1 to 2.0
+- Added license header to dist files.
+
+(Thanks to [@busticated](https://github.com/busticated)!)
+
+### 0.6.1
+
+- Added LICENSE file to repository.
+
+### 0.6.0
+
+- Added options for granular control of which types are linked (urls, email addresses, and/or twitter handles).
+ (thanks [@aziraphale](https://github.com/aziraphale))
+
+### 0.5.0
+
+- Simplified the path / query string / hash processing into a single regular expression instead of 3 separate ones.
+- Added support for parenthesis in URLs, such as: `en.wikipedia.org/wiki/IANA_(disambiguation)` (thanks [@dandv](https://github.com/dandv))
+- Add all known top-level domains (TLDs) (thanks [@wouter0100](https://github.com/wouter0100))
+
+### 0.4.0
+
+Merged pull requests from [@afeld](https://github.com/afeld):
+
+- strip protocol and 'www.' by default - fixes #1
+- truncate URLs from the end
+- make simpler regex for detecting prefix
+- remove trailing slashes from URLs, and handle periods at the end of paths
+- re-use domain+TLD regexes for email matching
+- add .me and .io to list of TLDs
+
+Thanks Aidan :)
+
+### 0.3.1
+
+- Fixed an issue with handling nested HTML tags within anchor tags.
+
+### 0.3
+
+- Implemented the `truncate` option.
+
+### 0.2
+
+- Implemented autolinking Twitter handles.
+
+### 0.1
+
+* Initial implementation, which autolinks URLs and email addresses. Working on linking Twitter handles.
diff --git a/webpack.config.js b/webpack.config.js
index 4f8d86c35..55fe39dd9 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -20,6 +20,7 @@ module.exports = {
extensions: ['', '.js'],
alias: {
"ko": __dirname + "/dev/External/ko.js",
+ "openpgp": __dirname + "/vendors/openpgp/openpgp-0.7.2.min.js",
"Knoin:AbstractBoot": __dirname + "/dev/Knoin/KnoinAbstractBoot.js",
"Knoin:AbstractScreen": __dirname + "/dev/Knoin/KnoinAbstractScreen.js",
@@ -31,20 +32,6 @@ module.exports = {
"App:RainLoop": __dirname + "/dev/Apps/RainLoopApp.js",
"App:Admin": __dirname + "/dev/Apps/AdminApp.js",
- "Model:Account": __dirname + "/dev/Models/AccountModel.js",
- "Model:Attachment": __dirname + "/dev/Models/AttachmentModel.js",
- "Model:ComposeAttachment": __dirname + "/dev/Models/ComposeAttachmentModel.js",
- "Model:Contact": __dirname + "/dev/Models/ContactModel.js",
- "Model:ContactProperty": __dirname + "/dev/Models/ContactPropertyModel.js",
- "Model:ContactTag": __dirname + "/dev/Models/ContactTagModel.js",
- "Model:Email": __dirname + "/dev/Models/EmailModel.js",
- "Model:Filter": __dirname + "/dev/Models/FilterModel.js",
- "Model:FilterCondition": __dirname + "/dev/Models/FilterConditionModel.js",
- "Model:Folder": __dirname + "/dev/Models/FolderModel.js",
- "Model:Identity": __dirname + "/dev/Models/IdentityModel.js",
- "Model:Message": __dirname + "/dev/Models/MessageModel.js",
- "Model:OpenPgpKey": __dirname + "/dev/Models/OpenPgpKeyModel.js",
-
"Storage:LocalStorage": __dirname + "/dev/Storages/LocalStorage.js",
"Storage:LocalStorage:Cookie": __dirname + "/dev/Storages/LocalStorages/CookieDriver.js",
"Storage:LocalStorage:LocalStorage": __dirname + "/dev/Storages/LocalStorages/LocalStorageDriver.js",
@@ -137,8 +124,9 @@ module.exports = {
'moment': 'moment',
'ifvisible': 'ifvisible',
'crossroads': 'crossroads',
- 'Jua': 'Jua',
'hasher': 'hasher',
+ 'Jua': 'Jua',
+ 'Autolinker': 'Autolinker',
'ssm': 'ssm',
'key': 'key',
'_': '_',