Add asserts folder

Add @command decorator
This commit is contained in:
RainLoop Team 2016-09-03 02:19:37 +03:00
parent a60ffc06e1
commit 1526130bfc
44 changed files with 300 additions and 264 deletions

8
.gitignore vendored
View file

@ -6,13 +6,7 @@
/npm-debug.log /npm-debug.log
/rainloop.sublime-project /rainloop.sublime-project
/rainloop.sublime-workspace /rainloop.sublime-workspace
/rainloop/v/0.0.0/static/ckeditor/* /rainloop/v/0.0.0/static/*
/rainloop/v/0.0.0/static/css/fonts/*
!/rainloop/v/0.0.0/static/css/fonts/.gitempty
/rainloop/v/0.0.0/static/css/*.css
/rainloop/v/0.0.0/static/js/*.js
/rainloop/v/0.0.0/static/js/**/*.js
!/rainloop/v/0.0.0/static/js/min/.gitempty
/rainloop/v/0.0.0/app/localization/moment/* /rainloop/v/0.0.0/app/localization/moment/*
!/rainloop/v/0.0.0/app/localization/moment/.gitempty !/rainloop/v/0.0.0/app/localization/moment/.gitempty
/vendors/.* /vendors/.*

View file

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View file

Before

Width:  |  Height:  |  Size: 832 B

After

Width:  |  Height:  |  Size: 832 B

View file

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View file

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View file

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View file

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View file

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 77 KiB

View file

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View file

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

Before

Width:  |  Height:  |  Size: 109 B

After

Width:  |  Height:  |  Size: 109 B

View file

Before

Width:  |  Height:  |  Size: 832 B

After

Width:  |  Height:  |  Size: 832 B

View file

Before

Width:  |  Height:  |  Size: 869 B

After

Width:  |  Height:  |  Size: 869 B

View file

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

View file

Before

Width:  |  Height:  |  Size: 847 B

After

Width:  |  Height:  |  Size: 847 B

View file

Before

Width:  |  Height:  |  Size: 356 B

After

Width:  |  Height:  |  Size: 356 B

View file

Before

Width:  |  Height:  |  Size: 110 B

After

Width:  |  Height:  |  Size: 110 B

View file

Before

Width:  |  Height:  |  Size: 869 B

After

Width:  |  Height:  |  Size: 869 B

View file

Before

Width:  |  Height:  |  Size: 869 B

After

Width:  |  Height:  |  Size: 869 B

View file

Before

Width:  |  Height:  |  Size: 869 B

After

Width:  |  Height:  |  Size: 869 B

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 832 B

After

Width:  |  Height:  |  Size: 832 B

View file

@ -1,16 +1,16 @@
{ {
"name": "RainLoop Webmail", "name": "RainLoop Webmail",
"short_name": "RainLoop", "short_name": "RainLoop",
"description": "Simple, modern & fast web-based email client", "description": "Simple, modern & fast web-based email client",
"display": "standalone", "display": "standalone",
"icons": [{ "icons": [{
"src": "apple-touch-icon.png", "src": "apple-touch-icon.png",
"sizes": "64x64", "sizes": "64x64",
"type": "image/png" "type": "image/png"
}, { }, {
"src": "android-icon.png", "src": "android-icon.png",
"sizes": "192x192", "sizes": "192x192",
"type": "image/png" "type": "image/png"
}], }],
"start_url": "../../../../" "start_url": "../../../../"
} }

View file

@ -504,6 +504,7 @@ export function createCommandLegacy(context, fExecute, fCanExecute = true)
fResult = fExecute ? fNonEmpty : noop; fResult = fExecute ? fNonEmpty : noop;
fResult.enabled = ko.observable(true); fResult.enabled = ko.observable(true);
fResult.isCommand = true;
if (isFunc(fCanExecute)) if (isFunc(fCanExecute))
{ {

24
dev/External/ko.js vendored
View file

@ -931,11 +931,29 @@ ko.bindingHandlers.command = {
init: (element, fValueAccessor, fAllBindingsAccessor, viewModel, bindingContext) => { init: (element, fValueAccessor, fAllBindingsAccessor, viewModel, bindingContext) => {
const const
jqElement = $(element), jqElement = $(element),
oCommand = fValueAccessor(); command = fValueAccessor();
if (!oCommand || !oCommand.enabled || !oCommand.canExecute) if (!command || !command.isCommand)
{ {
throw new Error('You are not using command function'); throw new Error('Value should be a command');
}
if (!command.enabled)
{
command.enabled = ko.observable(true);
}
if (!command.canExecute)
{
const __realCanExecute = command.__realCanExecute;
if (_.isFunction(__realCanExecute))
{
command.canExecute = ko.computed(() => command.enabled() && __realCanExecute.call(viewModel, viewModel));
}
else
{
command.canExecute = ko.computed(() => command.enabled() && !!__realCanExecute);
}
} }
jqElement.addClass('command'); jqElement.addClass('command');

View file

@ -9,7 +9,7 @@ import {runHook} from 'Common/Plugins';
import {$html, aViewModels as VIEW_MODELS, popupVisibilityNames} from 'Common/Globals'; import {$html, aViewModels as VIEW_MODELS, popupVisibilityNames} from 'Common/Globals';
import { import {
isArray, isUnd, pString, log, isArray, isUnd, pString, log, isFunc,
createCommand, delegateRun, isNonEmptyArray createCommand, delegateRun, isNonEmptyArray
} from 'Common/Utils'; } from 'Common/Utils';
@ -481,7 +481,7 @@ export function setHash(hash, silence = false, replace = false)
/** /**
* @param {Object} params * @param {Object} params
* @returns {void} * @returns {Function}
*/ */
function viewDecorator({name, type, templateID}) function viewDecorator({name, type, templateID})
{ {
@ -515,4 +515,37 @@ function viewDecorator({name, type, templateID})
}; };
} }
export {viewDecorator, viewDecorator as view, viewDecorator as viewModel}; /**
* @param {Function} canExecute
* @returns {Function}
*/
function commandDecorator(canExecute = true)
{
return (target, key, descriptor) => {
if (!key || !key.match(/Command$/))
{
throw new Error(`name "${key}" should end with Command suffix`);
}
const
value = descriptor.value || descriptor.initializer(),
normCanExecute = isFunc(canExecute) ? canExecute : () => !!canExecute;
descriptor.value = function(...args) {
if (normCanExecute.call(this, this))
{
value.apply(this, args);
}
return false;
};
descriptor.value.__realCanExecute = normCanExecute;
descriptor.value.isCommand = true;
return descriptor;
};
}
export {commandDecorator, commandDecorator as command, viewDecorator, viewDecorator as view, viewDecorator as viewModel};

View file

@ -74,6 +74,7 @@
@import "MessageView.less"; @import "MessageView.less";
@import "Contacts.less"; @import "Contacts.less";
@import "Compose.less"; @import "Compose.less";
@import "Admin.less"; @import "Admin.less";
@import "AdminGeneral.less"; @import "AdminGeneral.less";
@import "AdminBranding.less"; @import "AdminBranding.less";
@ -84,6 +85,7 @@
@import "AdminPlugin.less"; @import "AdminPlugin.less";
@import "AdminAbout.less"; @import "AdminAbout.less";
@import "Activate.less"; @import "Activate.less";
@import "Settings.less"; @import "Settings.less";
@import "SettingsGeneral.less"; @import "SettingsGeneral.less";
@import "SettingsAccounts.less"; @import "SettingsAccounts.less";

View file

@ -3,8 +3,7 @@ import ko from 'ko';
import _ from '_'; import _ from '_';
import { import {
trim, createCommand, trim, triggerAutocompleteInputChange
triggerAutocompleteInputChange
} from 'Common/Utils'; } from 'Common/Utils';
import {StorageResultType, Notification, Magics} from 'Common/Enums'; import {StorageResultType, Notification, Magics} from 'Common/Enums';
@ -16,7 +15,7 @@ import Remote from 'Remote/Admin/Ajax';
import {getApp} from 'Helper/Apps/Admin'; import {getApp} from 'Helper/Apps/Admin';
import {view, ViewType, routeOff} from 'Knoin/Knoin'; import {view, command, ViewType, routeOff} from 'Knoin/Knoin';
import {AbstractViewNext} from 'Knoin/AbstractViewNext'; import {AbstractViewNext} from 'Knoin/AbstractViewNext';
@view({ @view({
@ -61,53 +60,52 @@ class LoginAdminView extends AbstractViewNext
this.submitRequest = ko.observable(false); this.submitRequest = ko.observable(false);
this.submitError = ko.observable(''); this.submitError = ko.observable('');
}
this.submitCommand = createCommand(() => { @command((self) => !self.submitRequest())
submitCommand() {
triggerAutocompleteInputChange(); triggerAutocompleteInputChange();
this.loginError(false); this.loginError(false);
this.passwordError(false); this.passwordError(false);
this.loginError('' === trim(this.login())); this.loginError('' === trim(this.login()));
this.passwordError('' === trim(this.password())); this.passwordError('' === trim(this.password()));
if (this.loginError() || this.passwordError()) if (this.loginError() || this.passwordError())
{
return false;
}
this.submitRequest(true);
Remote.adminLogin((sResult, oData) => {
if (StorageResultType.Success === sResult && oData && 'AdminLogin' === oData.Action)
{ {
return false; if (oData.Result)
}
this.submitRequest(true);
Remote.adminLogin((sResult, oData) => {
if (StorageResultType.Success === sResult && oData && 'AdminLogin' === oData.Action)
{ {
if (oData.Result) getApp().loginAndLogoutReload(true);
{
getApp().loginAndLogoutReload(true);
}
else if (oData.ErrorCode)
{
this.submitRequest(false);
this.submitError(getNotification(oData.ErrorCode));
}
} }
else else if (oData.ErrorCode)
{ {
this.submitRequest(false); this.submitRequest(false);
this.submitError(getNotification(Notification.UnknownError)); this.submitError(getNotification(oData.ErrorCode));
} }
}
else
{
this.submitRequest(false);
this.submitError(getNotification(Notification.UnknownError));
}
}, this.login(), this.password()); }, this.login(), this.password());
return true; return true;
}, () => !this.submitRequest());
} }
onShow() { onShow() {
routeOff(); routeOff();
_.delay(() => { _.delay(() => {

View file

@ -15,7 +15,6 @@ class AboutUserView extends AbstractViewNext
{ {
constructor() { constructor() {
super(); super();
this.version = ko.observable(Settings.appSettingsGet('version')); this.version = ko.observable(Settings.appSettingsGet('version'));
} }
} }

View file

@ -46,15 +46,15 @@ class AbstractSystemDropDownUserView extends AbstractViewNext
this.addAccountClick = _.bind(this.addAccountClick, this); this.addAccountClick = _.bind(this.addAccountClick, this);
Events.sub('audio.stop', () => AppStore.currentAudio('')); Events.sub('audio.stop', () => AppStore.currentAudio(''));
Events.sub('audio.start', (sName) => AppStore.currentAudio(sName)); Events.sub('audio.start', (name) => AppStore.currentAudio(name));
} }
stopPlay() { stopPlay() {
Events.pub('audio.api.stop'); Events.pub('audio.api.stop');
} }
accountClick(oAccount, oEvent) { accountClick(account, event) {
if (oAccount && oEvent && !isUnd(oEvent.which) && 1 === oEvent.which) if (account && event && !isUnd(event.which) && 1 === event.which)
{ {
AccountStore.accounts.loading(true); AccountStore.accounts.loading(true);
_.delay(() => AccountStore.accounts.loading(false), Magics.Time1s); _.delay(() => AccountStore.accounts.loading(false), Magics.Time1s);

View file

@ -14,9 +14,7 @@ import {
import { import {
trim, inArray, pInt, trim, inArray, pInt,
convertLangName, convertLangName, triggerAutocompleteInputChange
createCommand, createCommandLegacy,
triggerAutocompleteInputChange
} from 'Common/Utils'; } from 'Common/Utils';
import {socialFacebook, socialGoogle, socialTwitter} from 'Common/Links'; import {socialFacebook, socialGoogle, socialTwitter} from 'Common/Links';
@ -34,7 +32,7 @@ import Remote from 'Remote/User/Ajax';
import {getApp} from 'Helper/Apps/User'; import {getApp} from 'Helper/Apps/User';
import {view, ViewType, routeOff, showScreenPopup} from 'Knoin/Knoin'; import {view, command, ViewType, routeOff, showScreenPopup} from 'Knoin/Knoin';
import {AbstractViewNext} from 'Knoin/AbstractViewNext'; import {AbstractViewNext} from 'Knoin/AbstractViewNext';
@view({ @view({
@ -151,36 +149,10 @@ class LoginUserView extends AbstractViewNext
); );
this.facebookLoginEnabled = ko.observable(false); this.facebookLoginEnabled = ko.observable(false);
this.facebookCommand = createCommand(() => {
window.open(socialFacebook(), 'Facebook',
'left=200,top=100,width=500,height=500,menubar=no,status=no,resizable=yes,scrollbars=yes');
return true;
}, () => !this.submitRequest() && this.facebookLoginEnabled());
this.googleLoginEnabled = ko.observable(false); this.googleLoginEnabled = ko.observable(false);
this.googleFastLoginEnabled = ko.observable(false); this.googleFastLoginEnabled = ko.observable(false);
this.googleCommand = createCommand(() => {
window.open(socialGoogle(), 'Google',
'left=200,top=100,width=550,height=550,menubar=no,status=no,resizable=yes,scrollbars=yes');
return true;
}, () => !this.submitRequest() && this.googleLoginEnabled());
this.googleFastCommand = createCommand(() => {
window.open(socialGoogle(true), 'Google',
'left=200,top=100,width=550,height=550,menubar=no,status=no,resizable=yes,scrollbars=yes');
return true;
}, () => !this.submitRequest() && this.googleFastLoginEnabled());
this.twitterLoginEnabled = ko.observable(false); this.twitterLoginEnabled = ko.observable(false);
this.twitterCommand = createCommand(() => {
window.open(socialTwitter(), 'Twitter',
'left=200,top=100,width=500,height=500,menubar=no,status=no,resizable=yes,scrollbars=yes');
return true;
}, () => !this.submitRequest() && this.twitterLoginEnabled());
this.socialLoginEnabled = ko.computed(() => { this.socialLoginEnabled = ko.computed(() => {
const const
bF = this.facebookLoginEnabled(), bF = this.facebookLoginEnabled(),
@ -194,11 +166,33 @@ class LoginUserView extends AbstractViewNext
{ {
this.submitError(Settings.settingsGet('AdditionalLoginError')); this.submitError(Settings.settingsGet('AdditionalLoginError'));
} }
// commands // todo
this.submitCommand = createCommandLegacy(this, this.submitCommand, () => !this.submitRequest());
} }
@command((self) => !self.submitRequest() && self.facebookLoginEnabled())
facebookCommand() {
window.open(socialFacebook(), 'Facebook', 'left=200,top=100,width=500,height=500,menubar=no,status=no,resizable=yes,scrollbars=yes');
return true;
}
@command((self) => !self.submitRequest() && self.googleLoginEnabled())
googleCommand() {
window.open(socialGoogle(), 'Google', 'left=200,top=100,width=550,height=550,menubar=no,status=no,resizable=yes,scrollbars=yes');
return true;
}
@command((self) => !self.submitRequest() && self.googleFastLoginEnabled())
googleFastCommand() {
window.open(socialGoogle(true), 'Google', 'left=200,top=100,width=550,height=550,menubar=no,status=no,resizable=yes,scrollbars=yes');
return true;
}
@command((self) => !self.submitRequest() && self.twitterLoginEnabled())
twitterCommand() {
window.open(socialTwitter(), 'Twitter', 'left=200,top=100,width=500,height=500,menubar=no,status=no,resizable=yes,scrollbars=yes');
return true;
}
@command((self) => !self.submitRequest())
submitCommand() { submitCommand() {
triggerAutocompleteInputChange(); triggerAutocompleteInputChange();
@ -383,10 +377,8 @@ class LoginUserView extends AbstractViewNext
this.facebookLoginEnabled(!!Settings.settingsGet('AllowFacebookSocial')); this.facebookLoginEnabled(!!Settings.settingsGet('AllowFacebookSocial'));
this.twitterLoginEnabled(!!Settings.settingsGet('AllowTwitterSocial')); this.twitterLoginEnabled(!!Settings.settingsGet('AllowTwitterSocial'));
this.googleLoginEnabled(!!Settings.settingsGet('AllowGoogleSocial') && this.googleLoginEnabled(!!Settings.settingsGet('AllowGoogleSocial') && !!Settings.settingsGet('AllowGoogleSocialAuth'));
!!Settings.settingsGet('AllowGoogleSocialAuth')); this.googleFastLoginEnabled(!!Settings.settingsGet('AllowGoogleSocial') && !!Settings.settingsGet('AllowGoogleSocialAuthFast'));
this.googleFastLoginEnabled(!!Settings.settingsGet('AllowGoogleSocial') &&
!!Settings.settingsGet('AllowGoogleSocialAuthFast'));
switch (signMe) switch (signMe)
{ {

View file

@ -26,7 +26,6 @@ import {
import { import {
noop, noop,
noopFalse, noopFalse,
createCommand,
computedPagenatorHelper, computedPagenatorHelper,
draggablePlace, draggablePlace,
friendlySize, friendlySize,
@ -55,9 +54,11 @@ import Remote from 'Remote/User/Ajax';
import {getApp} from 'Helper/Apps/User'; import {getApp} from 'Helper/Apps/User';
import {view, ViewType, showScreenPopup, setHash} from 'Knoin/Knoin'; import {view, command, ViewType, showScreenPopup, setHash} from 'Knoin/Knoin';
import {AbstractViewNext} from 'Knoin/AbstractViewNext'; import {AbstractViewNext} from 'Knoin/AbstractViewNext';
const canBeMovedHelper = (self) => self.canBeMoved();
@view({ @view({
name: 'View/User/MailBox/MessageList', name: 'View/User/MailBox/MessageList',
type: ViewType.Right, type: ViewType.Right,
@ -226,63 +227,6 @@ class MessageListMailBoxUserView extends AbstractViewNext
this.canBeMoved = this.hasCheckedOrSelectedLines; this.canBeMoved = this.hasCheckedOrSelectedLines;
this.clearCommand = createCommand(() => {
if (Settings.capa(Capa.DangerousActions))
{
showScreenPopup(require('View/Popup/FolderClear'), [FolderStore.currentFolder()]);
}
});
this.multyForwardCommand = createCommand(() => {
if (Settings.capa(Capa.Composer))
{
showScreenPopup(require('View/Popup/Compose'), [
ComposeType.ForwardAsAttachment, MessageStore.messageListCheckedOrSelected()]);
}
}, this.canBeMoved);
this.deleteWithoutMoveCommand = createCommand(() => {
if (Settings.capa(Capa.DangerousActions))
{
getApp().deleteMessagesFromFolder(FolderType.Trash,
FolderStore.currentFolderFullNameRaw(),
MessageStore.messageListCheckedOrSelectedUidsWithSubMails(), false);
}
}, this.canBeMoved);
this.deleteCommand = createCommand(() => {
getApp().deleteMessagesFromFolder(FolderType.Trash,
FolderStore.currentFolderFullNameRaw(),
MessageStore.messageListCheckedOrSelectedUidsWithSubMails(), true);
}, this.canBeMoved);
this.archiveCommand = createCommand(() => {
getApp().deleteMessagesFromFolder(FolderType.Archive,
FolderStore.currentFolderFullNameRaw(),
MessageStore.messageListCheckedOrSelectedUidsWithSubMails(), true);
}, this.canBeMoved);
this.spamCommand = createCommand(() => {
getApp().deleteMessagesFromFolder(FolderType.Spam,
FolderStore.currentFolderFullNameRaw(),
MessageStore.messageListCheckedOrSelectedUidsWithSubMails(), true);
}, this.canBeMoved);
this.notSpamCommand = createCommand(() => {
getApp().deleteMessagesFromFolder(FolderType.NotSpam,
FolderStore.currentFolderFullNameRaw(),
MessageStore.messageListCheckedOrSelectedUidsWithSubMails(), true);
}, this.canBeMoved);
this.moveCommand = createCommand(noop, this.canBeMoved);
this.reloadCommand = createCommand(() => {
if (!MessageStore.messageListCompleteLoadingThrottleForAnimation() && this.allowReload)
{
getApp().reloadMessageList(false, true);
}
});
this.quotaTooltip = _.bind(this.quotaTooltip, this); this.quotaTooltip = _.bind(this.quotaTooltip, this);
this.selector = new Selector( this.selector = new Selector(
@ -340,16 +284,82 @@ class MessageListMailBoxUserView extends AbstractViewNext
}); });
} }
hideLeft(oItem, oEvent) { @command()
oEvent.preventDefault(); clearCommand() {
oEvent.stopPropagation(); if (Settings.capa(Capa.DangerousActions))
{
showScreenPopup(require('View/Popup/FolderClear'), [FolderStore.currentFolder()]);
}
}
@command()
reloadCommand() {
if (!MessageStore.messageListCompleteLoadingThrottleForAnimation() && this.allowReload)
{
getApp().reloadMessageList(false, true);
}
}
@command(canBeMovedHelper)
multyForwardCommand() {
if (Settings.capa(Capa.Composer))
{
showScreenPopup(require('View/Popup/Compose'), [
ComposeType.ForwardAsAttachment, MessageStore.messageListCheckedOrSelected()]);
}
}
@command(canBeMovedHelper)
deleteWithoutMoveCommand() {
if (Settings.capa(Capa.DangerousActions))
{
getApp().deleteMessagesFromFolder(FolderType.Trash,
FolderStore.currentFolderFullNameRaw(),
MessageStore.messageListCheckedOrSelectedUidsWithSubMails(), false);
}
}
@command(canBeMovedHelper)
deleteCommand() {
getApp().deleteMessagesFromFolder(FolderType.Trash,
FolderStore.currentFolderFullNameRaw(),
MessageStore.messageListCheckedOrSelectedUidsWithSubMails(), true);
}
@command(canBeMovedHelper)
archiveCommand() {
getApp().deleteMessagesFromFolder(FolderType.Archive,
FolderStore.currentFolderFullNameRaw(),
MessageStore.messageListCheckedOrSelectedUidsWithSubMails(), true);
}
@command(canBeMovedHelper)
spamCommand() {
getApp().deleteMessagesFromFolder(FolderType.Spam,
FolderStore.currentFolderFullNameRaw(),
MessageStore.messageListCheckedOrSelectedUidsWithSubMails(), true);
}
@command(canBeMovedHelper)
notSpamCommand() {
getApp().deleteMessagesFromFolder(FolderType.NotSpam,
FolderStore.currentFolderFullNameRaw(),
MessageStore.messageListCheckedOrSelectedUidsWithSubMails(), true);
}
@command(canBeMovedHelper)
moveCommand() {} // eslint-disable-line no-empty-function
hideLeft(item, event) {
event.preventDefault();
event.stopPropagation();
leftPanelDisabled(true); leftPanelDisabled(true);
} }
showLeft(oItem, oEvent) { showLeft(item, event) {
oEvent.preventDefault(); event.preventDefault();
oEvent.stopPropagation(); event.stopPropagation();
leftPanelDisabled(false); leftPanelDisabled(false);
} }

View file

@ -20,10 +20,10 @@ import {
} from 'Common/Globals'; } from 'Common/Globals';
import { import {
createCommand, inArray, trim, noop, inArray, isArray, isNonEmptyArray, trim, noop,
isNonEmptyArray, windowResize, windowResizeCallback, windowResize, windowResizeCallback, inFocus,
removeSelection, removeInFocus, mailToHelper, removeSelection, removeInFocus, mailToHelper,
inFocus, isArray createCommand
} from 'Common/Utils'; } from 'Common/Utils';
import Audio from 'Common/Audio'; import Audio from 'Common/Audio';
@ -52,7 +52,7 @@ import Promises from 'Promises/User/Ajax';
import {getApp} from 'Helper/Apps/User'; import {getApp} from 'Helper/Apps/User';
import {view, ViewType, showScreenPopup} from 'Knoin/Knoin'; import {view, command, ViewType, showScreenPopup} from 'Knoin/Knoin';
import {AbstractViewNext} from 'Knoin/AbstractViewNext'; import {AbstractViewNext} from 'Knoin/AbstractViewNext';
@view({ @view({
@ -66,10 +66,22 @@ class MessageViewMailBoxUserView extends AbstractViewNext
super(); super();
let lastEmail = ''; let lastEmail = '';
const createCommandHelper = (type) => createCommand(() => {
this.lastReplyAction(type); const
this.replyOrforward(type); createCommandReplyHelper = (type) => createCommand(() => {
}, this.canBeRepliedOrForwarded); this.lastReplyAction(type);
this.replyOrforward(type);
}, this.canBeRepliedOrForwarded),
createCommandActionHelper = (folderType, useFolder) => createCommand(() => {
const message = this.message();
if (message && this.allowMessageListActions)
{
this.message(null);
getApp().deleteMessagesFromFolder(
folderType, message.folderFullNameRaw, [message.uid], useFolder);
}
}, this.messageVisibility);
this.oDom = null; this.oDom = null;
this.oHeaderDom = null; this.oHeaderDom = null;
@ -214,71 +226,17 @@ class MessageViewMailBoxUserView extends AbstractViewNext
}); });
// commands // commands
this.closeMessage = createCommand(() => { this.replyCommand = createCommandReplyHelper(ComposeType.Reply);
MessageStore.message(null); this.replyAllCommand = createCommandReplyHelper(ComposeType.ReplyAll);
}); this.forwardCommand = createCommandReplyHelper(ComposeType.Forward);
this.forwardAsAttachmentCommand = createCommandReplyHelper(ComposeType.ForwardAsAttachment);
this.editAsNewCommand = createCommandReplyHelper(ComposeType.EditAsNew);
this.replyCommand = createCommandHelper(ComposeType.Reply); this.deleteCommand = createCommandActionHelper(FolderType.Trash, true);
this.replyAllCommand = createCommandHelper(ComposeType.ReplyAll); this.deleteWithoutMoveCommand = createCommandActionHelper(FolderType.Trash, false);
this.forwardCommand = createCommandHelper(ComposeType.Forward); this.archiveCommand = createCommandActionHelper(FolderType.Archive, true);
this.forwardAsAttachmentCommand = createCommandHelper(ComposeType.ForwardAsAttachment); this.spamCommand = createCommandActionHelper(FolderType.Spam, true);
this.editAsNewCommand = createCommandHelper(ComposeType.EditAsNew); this.notSpamCommand = createCommandActionHelper(FolderType.NotSpam, true);
this.messageVisibilityCommand = createCommand(noop, this.messageVisibility);
this.messageEditCommand = createCommand(() => {
this.editMessage();
}, this.messageVisibility);
this.deleteCommand = createCommand(() => {
const message = this.message();
if (message && this.allowMessageListActions)
{
this.message(null);
getApp().deleteMessagesFromFolder(FolderType.Trash,
message.folderFullNameRaw, [message.uid], true);
}
}, this.messageVisibility);
this.deleteWithoutMoveCommand = createCommand(() => {
const message = this.message();
if (message && this.allowMessageListActions)
{
this.message(null);
getApp().deleteMessagesFromFolder(FolderType.Trash,
message.folderFullNameRaw, [message.uid], false);
}
}, this.messageVisibility);
this.archiveCommand = createCommand(() => {
const message = this.message();
if (message && this.allowMessageListActions)
{
this.message(null);
getApp().deleteMessagesFromFolder(FolderType.Archive,
message.folderFullNameRaw, [message.uid], true);
}
}, this.messageVisibility);
this.spamCommand = createCommand(() => {
const message = this.message();
if (message && this.allowMessageListActions)
{
this.message(null);
getApp().deleteMessagesFromFolder(FolderType.Spam,
message.folderFullNameRaw, [message.uid], true);
}
}, this.messageVisibility);
this.notSpamCommand = createCommand(() => {
const message = this.message();
if (message && this.allowMessageListActions)
{
this.message(null);
getApp().deleteMessagesFromFolder(FolderType.NotSpam,
message.folderFullNameRaw, [message.uid], true);
}
}, this.messageVisibility);
this.dropboxEnabled = SocialStore.dropbox.enabled; this.dropboxEnabled = SocialStore.dropbox.enabled;
this.dropboxApiKey = SocialStore.dropbox.apiKey; this.dropboxApiKey = SocialStore.dropbox.apiKey;
@ -430,18 +388,6 @@ class MessageViewMailBoxUserView extends AbstractViewNext
() => MessageStore.messageListCompleteLoadingThrottle() || MessageStore.messageLoadingThrottle() () => MessageStore.messageListCompleteLoadingThrottle() || MessageStore.messageLoadingThrottle()
); );
this.goUpCommand = createCommand(() => {
Events.pub('mailbox.message-list.selector.go-up', [
Layout.NoPreview === this.layout() ? !!this.message() : true
]);
}, () => !this.messageListAndMessageViewLoading());
this.goDownCommand = createCommand(() => {
Events.pub('mailbox.message-list.selector.go-down', [
Layout.NoPreview === this.layout() ? !!this.message() : true
]);
}, () => !this.messageListAndMessageViewLoading());
Events.sub('mailbox.message-view.toggle-full-screen', () => { Events.sub('mailbox.message-view.toggle-full-screen', () => {
this.toggleFullScreen(); this.toggleFullScreen();
}); });
@ -449,6 +395,33 @@ class MessageViewMailBoxUserView extends AbstractViewNext
this.attachmentPreview = _.bind(this.attachmentPreview, this); this.attachmentPreview = _.bind(this.attachmentPreview, this);
} }
@command()
closeMessageCommand() {
MessageStore.message(null);
}
@command((self) => self.messageVisibility())
messageVisibilityCommand() {} // eslint-disable-line no-empty-function
@command((self) => self.messageVisibility())
messageEditCommand() {
this.editMessage();
}
@command((self) => !self.messageListAndMessageViewLoading())
goUpCommand() {
Events.pub('mailbox.message-list.selector.go-up', [
Layout.NoPreview === this.layout() ? !!this.message() : true
]);
}
@command((self) => !self.messageListAndMessageViewLoading())
goDownCommand() {
Events.pub('mailbox.message-list.selector.go-down', [
Layout.NoPreview === this.layout() ? !!this.message() : true
]);
}
detectDomBackgroundColor(dom) { detectDomBackgroundColor(dom) {
let let
limit = 5, limit = 5,

View file

@ -69,8 +69,8 @@ class MenuSettingsUserView extends AbstractViewNext
}, Magics.Time200ms)); }, Magics.Time200ms));
} }
link(sRoute) { link(route) {
return settings(sRoute); return settings(route);
} }
backToMailBoxClick() { backToMailBoxClick() {

View file

@ -29,16 +29,16 @@ class PaneSettingsUserView extends AbstractViewNext
MessageStore.message(null); MessageStore.message(null);
} }
hideLeft(oItem, oEvent) { hideLeft(item, event) {
oEvent.preventDefault(); event.preventDefault();
oEvent.stopPropagation(); event.stopPropagation();
leftPanelDisabled(true); leftPanelDisabled(true);
} }
showLeft(oItem, oEvent) { showLeft(item, event) {
oEvent.preventDefault(); event.preventDefault();
oEvent.stopPropagation(); event.stopPropagation();
leftPanelDisabled(false); leftPanelDisabled(false);
} }

View file

@ -167,6 +167,10 @@ cfg.paths.staticMinJS = 'rainloop/v/' + cfg.devVersion + '/static/js/min/';
cfg.paths.staticCSS = 'rainloop/v/' + cfg.devVersion + '/static/css/'; cfg.paths.staticCSS = 'rainloop/v/' + cfg.devVersion + '/static/css/';
cfg.paths.momentLocales = 'rainloop/v/' + cfg.devVersion + '/app/localization/moment/'; cfg.paths.momentLocales = 'rainloop/v/' + cfg.devVersion + '/app/localization/moment/';
cfg.paths.asserts = {
src: 'asserts/**/*.*'
};
cfg.paths.less = { cfg.paths.less = {
main: { main: {
src: 'dev/Styles/@Main.less', src: 'dev/Styles/@Main.less',
@ -262,13 +266,25 @@ cfg.paths.js = {
} }
}; };
// assers
gulp.task('asserts:clean', function() {
return cleanDir(cfg.paths.static);
});
gulp.task('asserts', ['asserts:clean'], function() {
return gulp.src(cfg.paths.asserts.src)
.pipe(gulp.dest(cfg.paths.static));
});
// CSS // CSS
gulp.task('css:clean', function() { gulp.task('css:clean', function() {
return cleanDir(cfg.paths.staticCSS + '/*.css'); return cleanDir(cfg.paths.staticCSS + '/*.css');
}); });
gulp.task('css:main', function() { gulp.task('css:main', ['asserts'], function() {
var autoprefixer = require('gulp-autoprefixer'), var autoprefixer = require('gulp-autoprefixer'),
less = require('gulp-less'), less = require('gulp-less'),
lessFilter = filter('**/*.less', {restore: true}), lessFilter = filter('**/*.less', {restore: true}),
@ -586,7 +602,7 @@ gulp.task('css', ['css:min']);
gulp.task('vendors', ['moment', 'ckeditor', 'fontastic', 'lightgallery']); gulp.task('vendors', ['moment', 'ckeditor', 'fontastic', 'lightgallery']);
gulp.task('clean', ['js:clean', 'css:clean']); gulp.task('clean', ['js:clean', 'css:clean', 'asserts:clean']);
gulp.task('rainloop:start', ['rainloop:copy', 'rainloop:setup']); gulp.task('rainloop:start', ['rainloop:copy', 'rainloop:setup']);

View file

@ -4,7 +4,7 @@
<nobr> <nobr>
<div class="messageButtons btn-toolbar"> <div class="messageButtons btn-toolbar">
<div class="btn-group" data-tooltip-join="top" data-bind="tooltip: 'MESSAGE/BUTTON_CLOSE'"> <div class="btn-group" data-tooltip-join="top" data-bind="tooltip: 'MESSAGE/BUTTON_CLOSE'">
<a class="btn single btn-dark-disabled-border buttonClose" data-bind="command: closeMessage"> <a class="btn single btn-dark-disabled-border buttonClose" data-bind="command: closeMessageCommand">
<i class="icon-remove"></i> <i class="icon-remove"></i>
</a> </a>
</div> </div>
@ -216,7 +216,7 @@
<div data-bind="visible: message"> <div data-bind="visible: message">
<div class="messageItemHeader" data-bind="css: {'emptySubject': '' === viewSubject()}"> <div class="messageItemHeader" data-bind="css: {'emptySubject': '' === viewSubject()}">
<div class="subjectParent"> <div class="subjectParent">
<button class="close" data-bind="command: closeMessage" style="margin-top: -2px;">&times;</button> <button class="close" data-bind="command: closeMessageCommand" style="margin-top: -2px;">&times;</button>
<span class="infoParent g-ui-user-select-none" data-bind="click: function() { showFullInfo(!showFullInfo()); }"> <span class="infoParent g-ui-user-select-none" data-bind="click: function() { showFullInfo(!showFullInfo()); }">
<i class="icon-info" style="padding-top: 1px;"></i> <i class="icon-info" style="padding-top: 1px;"></i>
</span> </span>