mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-10 06:58:27 +03:00
Small fixes
Utf8 clear supports icon unicode
This commit is contained in:
parent
e6725198c4
commit
19f089d0bf
15 changed files with 141 additions and 62 deletions
|
|
@ -7,7 +7,6 @@
|
|||
Globals = {},
|
||||
|
||||
window = require('window'),
|
||||
is = require('is'),
|
||||
_ = require('_'),
|
||||
$ = require('$'),
|
||||
ko = require('ko'),
|
||||
|
|
@ -69,14 +68,21 @@
|
|||
Globals.bUnload = false;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @type {string}
|
||||
*/
|
||||
Globals.bTabletDevice = is.tablet();
|
||||
Globals.sUserAgent = 'navigator' in window && 'userAgent' in window.navigator &&
|
||||
window.navigator.userAgent.toLowerCase() || '';
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
Globals.bMobileDevice = is.mobile() || is.tablet();
|
||||
Globals.bMobileDevice =
|
||||
/android/i.test(Globals.sUserAgent) ||
|
||||
/iphone/i.test(Globals.sUserAgent) ||
|
||||
/ipod/i.test(Globals.sUserAgent) ||
|
||||
/ipad/i.test(Globals.sUserAgent) ||
|
||||
/blackberry/i.test(Globals.sUserAgent)
|
||||
;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@
|
|||
this.selectedItem(null);
|
||||
}
|
||||
}
|
||||
else if (this.bAutoSelect && this.focusedItem())
|
||||
else if (this.autoSelect() && this.focusedItem())
|
||||
{
|
||||
this.selectedItem(this.focusedItem());
|
||||
}
|
||||
|
|
@ -124,10 +124,10 @@
|
|||
this.sItemFocusedSelector = sItemFocusedSelector;
|
||||
|
||||
this.sLastUid = '';
|
||||
this.bAutoSelect = true;
|
||||
this.oCallbacks = {};
|
||||
|
||||
this.emptyFunction = function () {};
|
||||
this.emptyTrueFunction = function () { return true; };
|
||||
|
||||
this.focusedItem.subscribe(function (oItem) {
|
||||
if (oItem)
|
||||
|
|
@ -221,7 +221,7 @@
|
|||
|
||||
this.selectedItemUseCallback = true;
|
||||
|
||||
if (!bChecked && !bSelected && this.bAutoSelect)
|
||||
if (!bChecked && !bSelected && this.autoSelect())
|
||||
{
|
||||
if (self.focusedItem())
|
||||
{
|
||||
|
|
@ -392,9 +392,12 @@
|
|||
}
|
||||
};
|
||||
|
||||
Selector.prototype.autoSelect = function (bValue)
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Selector.prototype.autoSelect = function ()
|
||||
{
|
||||
this.bAutoSelect = !!bValue;
|
||||
return !!(this.oCallbacks['onAutoSelect'] || this.emptyTrueFunction)();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -540,7 +543,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
if ((this.bAutoSelect || !!bForceSelect) &&
|
||||
if ((this.autoSelect() || !!bForceSelect) &&
|
||||
!this.isListChecked() && Enums.EventKeyCode.Space !== iEventKeyCode)
|
||||
{
|
||||
this.selectedItem(oResult);
|
||||
|
|
|
|||
|
|
@ -244,9 +244,7 @@
|
|||
*/
|
||||
Utils.encodeHtml = function (sText)
|
||||
{
|
||||
return Utils.isNormal(sText) ? sText.toString()
|
||||
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
||||
.replace(/"/g, '"').replace(/'/g, ''') : '';
|
||||
return Utils.isNormal(sText) ? _.escape(sText.toString()) : '';
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -512,7 +510,7 @@
|
|||
/**
|
||||
* @param {?} oEvent
|
||||
*/
|
||||
Utils.killCtrlAandS = function (oEvent)
|
||||
Utils.kill_CtrlA_CtrlS = function (oEvent)
|
||||
{
|
||||
oEvent = oEvent || window.event;
|
||||
if (oEvent && oEvent.ctrlKey && !oEvent.shiftKey && !oEvent.altKey)
|
||||
|
|
@ -944,7 +942,7 @@
|
|||
|
||||
fixAttibuteValue = function () {
|
||||
return (arguments && 1 < arguments.length) ?
|
||||
'' + arguments[1] + arguments[2].replace(/</g, '<').replace(/>/g, '>') : '';
|
||||
'' + arguments[1] + _.escape(arguments[2]) : '';
|
||||
},
|
||||
|
||||
convertLinks = function () {
|
||||
|
|
@ -1550,6 +1548,36 @@
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} sStr
|
||||
* @return {string}
|
||||
*/
|
||||
Utils.FullHtmlEncode = function (sStr)
|
||||
{
|
||||
var
|
||||
iIndex = 0,
|
||||
sChr = '',
|
||||
iChrCode = 0,
|
||||
sResult = '';
|
||||
;
|
||||
|
||||
for (iIndex = 0; iIndex < sStr.length; iIndex++)
|
||||
{
|
||||
sChr = sStr[iIndex];
|
||||
if (-1 < Utils.inArray(sChr, ['&', '<', '>', '"', '`', '\'']))
|
||||
{
|
||||
sResult += _.escape(sChr);
|
||||
}
|
||||
else
|
||||
{
|
||||
iChrCode = sChr.charCodeAt(0);
|
||||
sResult += (iChrCode > 128) ? '&#' + iChrCode + ';' : sChr;
|
||||
}
|
||||
}
|
||||
|
||||
return sResult;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Object|Array} mObjectOrObjects
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@
|
|||
|
||||
if (Consts.Values.TokenErrorLimit < Globals.iTokenErrorCount)
|
||||
{
|
||||
if (Globals.__APP__)
|
||||
if (Globals.__APP__ && Globals.__APP__.loginAndLogoutReload)
|
||||
{
|
||||
Globals.__APP__.loginAndLogoutReload(true);
|
||||
}
|
||||
|
|
@ -71,11 +71,11 @@
|
|||
|
||||
if (oData.ClearAuth || oData.Logout || Consts.Values.AjaxErrorLimit < Globals.iAjaxErrorCount)
|
||||
{
|
||||
if (Globals.__APP__)
|
||||
if (Globals.__APP__ && Globals.__APP__.clearClientSideToken)
|
||||
{
|
||||
Globals.__APP__.clearClientSideToken();
|
||||
|
||||
if (!oData.ClearAuth)
|
||||
if (!oData.ClearAuth && Globals.__APP__.loginAndLogoutReload)
|
||||
{
|
||||
Globals.__APP__.loginAndLogoutReload(true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
this.submitRequest = ko.observable(false);
|
||||
this.submitError = ko.observable('');
|
||||
this.submitErrorAdditional = ko.observable('');
|
||||
|
||||
this.emailFocus = ko.observable(false);
|
||||
|
||||
|
|
@ -61,21 +62,28 @@
|
|||
Remote.accountSetup(_.bind(function (sResult, oData) {
|
||||
|
||||
this.submitRequest(false);
|
||||
if (Enums.StorageResultType.Success === sResult && oData && 'AccountSetup' === oData.Action)
|
||||
if (Enums.StorageResultType.Success === sResult && oData)
|
||||
{
|
||||
if (oData.Result)
|
||||
{
|
||||
require('App/User').accountsAndIdentities();
|
||||
this.cancelCommand();
|
||||
}
|
||||
else if (oData.ErrorCode)
|
||||
else
|
||||
{
|
||||
this.submitError(Translator.getNotification(oData.ErrorCode));
|
||||
this.submitError(oData.ErrorCode ? Translator.getNotification(oData.ErrorCode) :
|
||||
Translator.getNotification(Enums.Notification.UnknownError));
|
||||
|
||||
if (oData.ErrorMessageAdditional)
|
||||
{
|
||||
this.submitErrorAdditional(oData.ErrorMessageAdditional);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.submitError(Translator.getNotification(Enums.Notification.UnknownError));
|
||||
this.submitErrorAdditional('');
|
||||
}
|
||||
|
||||
}, this), this.email(), this.password(), this.isNew());
|
||||
|
|
@ -104,6 +112,7 @@
|
|||
|
||||
this.submitRequest(false);
|
||||
this.submitError('');
|
||||
this.submitErrorAdditional('');
|
||||
};
|
||||
|
||||
AccountPopupView.prototype.onShow = function (oAccount)
|
||||
|
|
|
|||
|
|
@ -251,15 +251,9 @@
|
|||
return oMessage ? oMessage.generateUid() : '';
|
||||
});
|
||||
|
||||
MessageStore.messageListEndHash.subscribe(function () {
|
||||
this.selector.scrollToTop();
|
||||
}, this);
|
||||
|
||||
SettingsStore.layout.subscribe(function (mValue) {
|
||||
this.selector.autoSelect(Enums.Layout.NoPreview !== mValue);
|
||||
}, this);
|
||||
|
||||
SettingsStore.layout.valueHasMutated();
|
||||
this.selector.on('onAutoSelect', _.bind(function () {
|
||||
return this.useAutoSelect();
|
||||
}, this));
|
||||
|
||||
Events
|
||||
.sub('mailbox.message-list.selector.go-down', function () {
|
||||
|
|
@ -270,6 +264,10 @@
|
|||
}, this)
|
||||
;
|
||||
|
||||
MessageStore.messageListEndHash.subscribe(function () {
|
||||
this.selector.scrollToTop();
|
||||
}, this);
|
||||
|
||||
kn.constructorEnd(this);
|
||||
}
|
||||
|
||||
|
|
@ -281,6 +279,16 @@
|
|||
*/
|
||||
MessageListMailBoxUserView.prototype.emptySubjectValue = '';
|
||||
|
||||
MessageListMailBoxUserView.prototype.useAutoSelect = function ()
|
||||
{
|
||||
if (/is:unseen/.test(this.mainMessageListSearch()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Enums.Layout.NoPreview !== SettingsStore.layout();
|
||||
};
|
||||
|
||||
MessageListMailBoxUserView.prototype.searchEnterAction = function ()
|
||||
{
|
||||
this.mainMessageListSearch(this.sLastSearchValue);
|
||||
|
|
@ -721,6 +729,14 @@
|
|||
return false;
|
||||
});
|
||||
|
||||
key('enter', Enums.KeyState.MessageList, function () {
|
||||
if (self.message() && self.useAutoSelect())
|
||||
{
|
||||
Events.pub('mailbox.message-view.toggle-full-screen');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// archive (zip)
|
||||
key('z', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () {
|
||||
self.archiveCommand();
|
||||
|
|
|
|||
|
|
@ -323,6 +323,10 @@
|
|||
Events.pub('mailbox.message-list.selector.go-down');
|
||||
});
|
||||
|
||||
Events.sub('mailbox.message-view.toggle-full-screen', function () {
|
||||
this.toggleFullScreen();
|
||||
}, this);
|
||||
|
||||
kn.constructorEnd(this);
|
||||
}
|
||||
|
||||
|
|
@ -581,6 +585,11 @@
|
|||
if (this.fullScreenMode())
|
||||
{
|
||||
this.fullScreenMode(false);
|
||||
|
||||
if (Enums.Layout.NoPreview !== this.layout())
|
||||
{
|
||||
this.message.focused(false);
|
||||
}
|
||||
}
|
||||
else if (Enums.Layout.NoPreview === this.layout())
|
||||
{
|
||||
|
|
@ -610,14 +619,6 @@
|
|||
return false;
|
||||
});
|
||||
|
||||
key('enter', Enums.KeyState.MessageList, function () {
|
||||
if (Enums.Layout.NoPreview !== self.layout() && self.message())
|
||||
{
|
||||
self.toggleFullScreen();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// reply
|
||||
key('r', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () {
|
||||
if (MessageStore.message())
|
||||
|
|
|
|||
6
dev/bootstrap.js
vendored
6
dev/bootstrap.js
vendored
|
|
@ -22,8 +22,8 @@
|
|||
Globals.__APP__ = App;
|
||||
|
||||
Globals.$win
|
||||
.keydown(Utils.killCtrlAandS)
|
||||
.keyup(Utils.killCtrlAandS)
|
||||
.keydown(Utils.kill_CtrlA_CtrlS)
|
||||
.keyup(Utils.kill_CtrlA_CtrlS)
|
||||
.unload(function () {
|
||||
Globals.bUnload = true;
|
||||
})
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
window['rl']['createCommand'] = Utils.createCommand;
|
||||
|
||||
window['rl']['addSettingsViewModel'] = _.bind(Plugins.addSettingsViewModel, Plugins);
|
||||
|
||||
|
||||
window['rl']['pluginRemoteRequest'] = _.bind(Plugins.remoteRequest, Plugins);
|
||||
window['rl']['pluginSettingsGet'] = _.bind(Plugins.settingsGet, Plugins);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"name": "RainLoop",
|
||||
"title": "RainLoop Webmail",
|
||||
"version": "1.8.1",
|
||||
"release": "272",
|
||||
"release": "274",
|
||||
"description": "Simple, modern & fast web-based email client",
|
||||
"homepage": "http://rainloop.net",
|
||||
"main": "gulpfile.js",
|
||||
|
|
|
|||
|
|
@ -17,6 +17,22 @@ namespace MailSo\Base;
|
|||
*/
|
||||
class Utils
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
static $sValidUtf8Regexp = <<<'END'
|
||||
/
|
||||
(
|
||||
(?: [\x00-\x7F] # single-byte sequences 0xxxxxxx
|
||||
| [\xC0-\xDF][\x80-\xBF] # double-byte sequences 110xxxxx 10xxxxxx
|
||||
| [\xE0-\xEF][\x80-\xBF]{2} # triple-byte sequences 1110xxxx 10xxxxxx * 2
|
||||
| [\xF0-\xF7][\x80-\xBF]{3} # quadruple-byte sequence 11110xxx 10xxxxxx * 3
|
||||
){1,100} # ...one or more times
|
||||
)
|
||||
| . # anything else
|
||||
/x
|
||||
END;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
|
|
@ -1432,15 +1448,7 @@ class Utils
|
|||
return $sUtfString;
|
||||
}
|
||||
|
||||
$sUtfString = \preg_replace(
|
||||
'/[\x00-\x08\x10\x0B\x0C\x0E-\x1F\x7F]'.
|
||||
'|[\x00-\x7F][\x80-\xBF]+'.
|
||||
'|([\xC0\xC1]|[\xF0-\xFF])[\x80-\xBF]*'.
|
||||
'|[\xC2-\xDF]((?![\x80-\xBF])|[\x80-\xBF]{2,})'.
|
||||
'|[\xE0-\xEF](([\x80-\xBF](?![\x80-\xBF]))|(?![\x80-\xBF]{2})|[\x80-\xBF]{3,})/S',
|
||||
$sReplaceOn,
|
||||
$sUtfString
|
||||
);
|
||||
$sUtfString = \preg_replace(\MailSo\Base\Utils::$sValidUtf8Regexp, '$1', $sUtfString);
|
||||
|
||||
$sUtfString = \preg_replace(
|
||||
'/\xE0[\x80-\x9F][\x80-\xBF]'.
|
||||
|
|
@ -1450,15 +1458,16 @@ class Utils
|
|||
$sUtfString = \preg_replace('/\xEF\xBF\xBD/', '?', $sUtfString);
|
||||
|
||||
$sNewUtfString = false;
|
||||
if (\MailSo\Base\Utils::IsIconvSupported())
|
||||
{
|
||||
$sNewUtfString = \MailSo\Base\Utils::IconvConvertEncoding($sUtfString, 'UTF-8', 'UTF-8');
|
||||
}
|
||||
else if (\MailSo\Base\Utils::IsMbStringSupported())
|
||||
if (false === $sNewUtfString && \MailSo\Base\Utils::IsMbStringSupported())
|
||||
{
|
||||
$sNewUtfString = \MailSo\Base\Utils::MbConvertEncoding($sUtfString, 'UTF-8', 'UTF-8');
|
||||
}
|
||||
|
||||
if (false === $sNewUtfString && \MailSo\Base\Utils::IsIconvSupported())
|
||||
{
|
||||
$sNewUtfString = \MailSo\Base\Utils::IconvConvertEncoding($sUtfString, 'UTF-8', 'UTF-8');
|
||||
}
|
||||
|
||||
if (false !== $sNewUtfString)
|
||||
{
|
||||
$sUtfString = $sNewUtfString;
|
||||
|
|
|
|||
|
|
@ -1185,7 +1185,7 @@ class ImapClient extends \MailSo\Net\NetClient
|
|||
foreach ($aResponse as /* @var $oImapResponse \MailSo\Imap\Response */ $oImapResponse)
|
||||
{
|
||||
if (\MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oImapResponse->ResponseType
|
||||
&& 'ESEARCH' === $oImapResponse->StatusOrIndex
|
||||
&& ('ESEARCH' === $oImapResponse->StatusOrIndex || 'ESORT' === $oImapResponse->StatusOrIndex)
|
||||
&& \is_array($oImapResponse->ResponseList)
|
||||
&& isset($oImapResponse->ResponseList[2], $oImapResponse->ResponseList[2][0], $oImapResponse->ResponseList[2][1])
|
||||
&& 'TAG' === $oImapResponse->ResponseList[2][0] && $sRequestTag === $oImapResponse->ResponseList[2][1]
|
||||
|
|
|
|||
|
|
@ -2156,6 +2156,9 @@ class Actions
|
|||
1 < \count($aOrder['Accounts']))
|
||||
{
|
||||
$aAccounts = \array_merge(\array_flip($aOrder['Accounts']), $aAccounts);
|
||||
$aAccounts = \array_filter($aAccounts, function ($sHash) {
|
||||
return 5 < \strlen($sHash);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -131,9 +131,10 @@
|
|||
<div class="content g-scrollbox">
|
||||
<div class="content-wrapper">
|
||||
<div class="listSearchDesc" data-bind="visible: '' !== messageListSearchDesc()">
|
||||
<a class="btn btn-small pull-right searchCancelButton" data-bind="click: cancelSearch">
|
||||
<a class="close-custom" data-bind="click: cancelSearch">×</a>
|
||||
<!-- <a class="btn btn-small pull-right searchCancelButton" data-bind="click: cancelSearch">
|
||||
<i class="icon-remove"></i>
|
||||
</a>
|
||||
</a>-->
|
||||
<span data-bind="text: messageListSearchDesc"></span>:
|
||||
</div>
|
||||
<div class="listDragOver" data-bind="css: {'viewAppendArea': dragOver() && '' === messageListError() && !popupVisibility(), 'dragOverEnter': dragOverEnter }, initDom: dragOverArea">
|
||||
|
|
|
|||
|
|
@ -11,14 +11,18 @@
|
|||
<div class="modal-body">
|
||||
<div class="form-horizontal">
|
||||
<div class="alert" data-bind="visible: '' !== submitError()">
|
||||
<button type="button" class="close" data-bind="click: function () { submitError('') }">×</button>
|
||||
<button type="button" class="close-custom" data-bind="click: function () { submitError('') }">×</button>
|
||||
<span data-bind="text: submitError"></span>
|
||||
<div data-bind="visible: submitErrorAdditional">
|
||||
<br />
|
||||
<span data-bind="text: submitErrorAdditional"></span>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div class="control-group" data-bind="css: {'error': emailError}">
|
||||
<label class="i18n control-label" data-i18n-text="LOGIN/LABEL_EMAIL"></label>
|
||||
<div class="controls">
|
||||
<label style="margin-top: 5px;"><strong data-bind="visible: !isNew(), text: email"></strong></label>
|
||||
<label style="margin-top: 5px;" data-bind="visible: !isNew()"><strong data-bind="text: email"></strong></label>
|
||||
<input type="email" class="inputEmail input-large" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
data-bind="visible: isNew, textInput: email, onEnter: addAccountCommand, hasfocus: emailFocus" />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ module.exports = {
|
|||
'ssm': 'window.ssm',
|
||||
'key': 'window.key',
|
||||
'_': 'window._',
|
||||
'is': 'window.is',
|
||||
'$': 'window.jQuery'
|
||||
}
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue