diff --git a/.gitignore b/.gitignore index 82c4d0387..213da1a26 100644 --- a/.gitignore +++ b/.gitignore @@ -6,13 +6,7 @@ /npm-debug.log /rainloop.sublime-project /rainloop.sublime-workspace -/rainloop/v/0.0.0/static/ckeditor/* -/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/static/* /rainloop/v/0.0.0/app/localization/moment/* !/rainloop/v/0.0.0/app/localization/moment/.gitempty /vendors/.* diff --git a/rainloop/v/0.0.0/static/android-icon.png b/asserts/android-icon.png similarity index 100% rename from rainloop/v/0.0.0/static/android-icon.png rename to asserts/android-icon.png diff --git a/rainloop/v/0.0.0/static/apple-touch-icon.png b/asserts/apple-touch-icon.png similarity index 100% rename from rainloop/v/0.0.0/static/apple-touch-icon.png rename to asserts/apple-touch-icon.png diff --git a/rainloop/v/0.0.0/static/browsers/chrome.gif b/asserts/browsers/chrome.gif similarity index 100% rename from rainloop/v/0.0.0/static/browsers/chrome.gif rename to asserts/browsers/chrome.gif diff --git a/rainloop/v/0.0.0/static/browsers/firefox.gif b/asserts/browsers/firefox.gif similarity index 100% rename from rainloop/v/0.0.0/static/browsers/firefox.gif rename to asserts/browsers/firefox.gif diff --git a/rainloop/v/0.0.0/static/browsers/opera.gif b/asserts/browsers/opera.gif similarity index 100% rename from rainloop/v/0.0.0/static/browsers/opera.gif rename to asserts/browsers/opera.gif diff --git a/rainloop/v/0.0.0/static/browsers/safari.gif b/asserts/browsers/safari.gif similarity index 100% rename from rainloop/v/0.0.0/static/browsers/safari.gif rename to asserts/browsers/safari.gif diff --git a/rainloop/v/0.0.0/static/css/default-skin.png b/asserts/css/default-skin.png similarity index 100% rename from rainloop/v/0.0.0/static/css/default-skin.png rename to asserts/css/default-skin.png diff --git a/rainloop/v/0.0.0/static/css/default-skin.svg b/asserts/css/default-skin.svg similarity index 100% rename from rainloop/v/0.0.0/static/css/default-skin.svg rename to asserts/css/default-skin.svg diff --git a/rainloop/v/0.0.0/static/css/flags.png b/asserts/css/flags.png similarity index 100% rename from rainloop/v/0.0.0/static/css/flags.png rename to asserts/css/flags.png diff --git a/rainloop/v/0.0.0/static/css/images/editor.png b/asserts/css/images/editor.png similarity index 100% rename from rainloop/v/0.0.0/static/css/images/editor.png rename to asserts/css/images/editor.png diff --git a/rainloop/v/0.0.0/static/css/images/empty-contact.png b/asserts/css/images/empty-contact.png similarity index 100% rename from rainloop/v/0.0.0/static/css/images/empty-contact.png rename to asserts/css/images/empty-contact.png diff --git a/rainloop/v/0.0.0/static/css/images/grey.png b/asserts/css/images/grey.png similarity index 100% rename from rainloop/v/0.0.0/static/css/images/grey.png rename to asserts/css/images/grey.png diff --git a/rainloop/v/0.0.0/static/css/images/icom-message-notification.png b/asserts/css/images/icom-message-notification.png similarity index 100% rename from rainloop/v/0.0.0/static/css/images/icom-message-notification.png rename to asserts/css/images/icom-message-notification.png diff --git a/rainloop/v/0.0.0/static/css/images/loading.gif b/asserts/css/images/loading.gif similarity index 100% rename from rainloop/v/0.0.0/static/css/images/loading.gif rename to asserts/css/images/loading.gif diff --git a/rainloop/v/0.0.0/static/css/images/rainloop-logo.png b/asserts/css/images/rainloop-logo.png similarity index 100% rename from rainloop/v/0.0.0/static/css/images/rainloop-logo.png rename to asserts/css/images/rainloop-logo.png diff --git a/rainloop/v/0.0.0/static/css/images/sync.gif b/asserts/css/images/sync.gif similarity index 100% rename from rainloop/v/0.0.0/static/css/images/sync.gif rename to asserts/css/images/sync.gif diff --git a/rainloop/v/0.0.0/static/css/images/sync.png b/asserts/css/images/sync.png similarity index 100% rename from rainloop/v/0.0.0/static/css/images/sync.png rename to asserts/css/images/sync.png diff --git a/rainloop/v/0.0.0/static/css/images/white.png b/asserts/css/images/white.png similarity index 100% rename from rainloop/v/0.0.0/static/css/images/white.png rename to asserts/css/images/white.png diff --git a/rainloop/v/0.0.0/static/css/img/loading.gif b/asserts/css/img/loading.gif similarity index 100% rename from rainloop/v/0.0.0/static/css/img/loading.gif rename to asserts/css/img/loading.gif diff --git a/rainloop/v/0.0.0/static/css/loading.gif b/asserts/css/loading.gif similarity index 100% rename from rainloop/v/0.0.0/static/css/loading.gif rename to asserts/css/loading.gif diff --git a/rainloop/v/0.0.0/static/css/preloader.gif b/asserts/css/preloader.gif similarity index 100% rename from rainloop/v/0.0.0/static/css/preloader.gif rename to asserts/css/preloader.gif diff --git a/rainloop/v/0.0.0/static/favicon.ico b/asserts/favicon.ico similarity index 100% rename from rainloop/v/0.0.0/static/favicon.ico rename to asserts/favicon.ico diff --git a/rainloop/v/0.0.0/static/favicon.png b/asserts/favicon.png similarity index 100% rename from rainloop/v/0.0.0/static/favicon.png rename to asserts/favicon.png diff --git a/rainloop/v/0.0.0/static/manifest.json b/asserts/manifest.json similarity index 95% rename from rainloop/v/0.0.0/static/manifest.json rename to asserts/manifest.json index c166c6f83..f7369adf2 100644 --- a/rainloop/v/0.0.0/static/manifest.json +++ b/asserts/manifest.json @@ -1,16 +1,16 @@ -{ - "name": "RainLoop Webmail", - "short_name": "RainLoop", - "description": "Simple, modern & fast web-based email client", - "display": "standalone", - "icons": [{ - "src": "apple-touch-icon.png", - "sizes": "64x64", - "type": "image/png" - }, { - "src": "android-icon.png", - "sizes": "192x192", - "type": "image/png" - }], - "start_url": "../../../../" +{ + "name": "RainLoop Webmail", + "short_name": "RainLoop", + "description": "Simple, modern & fast web-based email client", + "display": "standalone", + "icons": [{ + "src": "apple-touch-icon.png", + "sizes": "64x64", + "type": "image/png" + }, { + "src": "android-icon.png", + "sizes": "192x192", + "type": "image/png" + }], + "start_url": "../../../../" } \ No newline at end of file diff --git a/rainloop/v/0.0.0/static/sounds/new-mail.mp3 b/asserts/sounds/new-mail.mp3 similarity index 100% rename from rainloop/v/0.0.0/static/sounds/new-mail.mp3 rename to asserts/sounds/new-mail.mp3 diff --git a/rainloop/v/0.0.0/static/sounds/new-mail.ogg b/asserts/sounds/new-mail.ogg similarity index 100% rename from rainloop/v/0.0.0/static/sounds/new-mail.ogg rename to asserts/sounds/new-mail.ogg diff --git a/dev/Common/Utils.js b/dev/Common/Utils.js index 25b73a05a..80915820e 100644 --- a/dev/Common/Utils.js +++ b/dev/Common/Utils.js @@ -504,6 +504,7 @@ export function createCommandLegacy(context, fExecute, fCanExecute = true) fResult = fExecute ? fNonEmpty : noop; fResult.enabled = ko.observable(true); + fResult.isCommand = true; if (isFunc(fCanExecute)) { diff --git a/dev/External/ko.js b/dev/External/ko.js index 2dfdb8746..dbfb4d992 100644 --- a/dev/External/ko.js +++ b/dev/External/ko.js @@ -931,11 +931,29 @@ ko.bindingHandlers.command = { init: (element, fValueAccessor, fAllBindingsAccessor, viewModel, bindingContext) => { const 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'); diff --git a/dev/Knoin/Knoin.js b/dev/Knoin/Knoin.js index af0c18a06..092159d01 100644 --- a/dev/Knoin/Knoin.js +++ b/dev/Knoin/Knoin.js @@ -9,7 +9,7 @@ import {runHook} from 'Common/Plugins'; import {$html, aViewModels as VIEW_MODELS, popupVisibilityNames} from 'Common/Globals'; import { - isArray, isUnd, pString, log, + isArray, isUnd, pString, log, isFunc, createCommand, delegateRun, isNonEmptyArray } from 'Common/Utils'; @@ -481,7 +481,7 @@ export function setHash(hash, silence = false, replace = false) /** * @param {Object} params - * @returns {void} + * @returns {Function} */ 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}; diff --git a/dev/Styles/@Main.less b/dev/Styles/@Main.less index c2f77b22f..8915d30f5 100644 --- a/dev/Styles/@Main.less +++ b/dev/Styles/@Main.less @@ -74,6 +74,7 @@ @import "MessageView.less"; @import "Contacts.less"; @import "Compose.less"; + @import "Admin.less"; @import "AdminGeneral.less"; @import "AdminBranding.less"; @@ -84,6 +85,7 @@ @import "AdminPlugin.less"; @import "AdminAbout.less"; @import "Activate.less"; + @import "Settings.less"; @import "SettingsGeneral.less"; @import "SettingsAccounts.less"; diff --git a/dev/View/Admin/Login.js b/dev/View/Admin/Login.js index ac0cf2bc0..986cdff66 100644 --- a/dev/View/Admin/Login.js +++ b/dev/View/Admin/Login.js @@ -3,8 +3,7 @@ import ko from 'ko'; import _ from '_'; import { - trim, createCommand, - triggerAutocompleteInputChange + trim, triggerAutocompleteInputChange } from 'Common/Utils'; import {StorageResultType, Notification, Magics} from 'Common/Enums'; @@ -16,7 +15,7 @@ import Remote from 'Remote/Admin/Ajax'; 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'; @view({ @@ -61,53 +60,52 @@ class LoginAdminView extends AbstractViewNext this.submitRequest = ko.observable(false); this.submitError = ko.observable(''); + } - this.submitCommand = createCommand(() => { + @command((self) => !self.submitRequest()) + submitCommand() { - triggerAutocompleteInputChange(); + triggerAutocompleteInputChange(); - this.loginError(false); - this.passwordError(false); + this.loginError(false); + this.passwordError(false); - this.loginError('' === trim(this.login())); - this.passwordError('' === trim(this.password())); + this.loginError('' === trim(this.login())); + 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; - } - - this.submitRequest(true); - - Remote.adminLogin((sResult, oData) => { - - if (StorageResultType.Success === sResult && oData && 'AdminLogin' === oData.Action) + if (oData.Result) { - if (oData.Result) - { - getApp().loginAndLogoutReload(true); - } - else if (oData.ErrorCode) - { - this.submitRequest(false); - this.submitError(getNotification(oData.ErrorCode)); - } + getApp().loginAndLogoutReload(true); } - else + else if (oData.ErrorCode) { 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; - - }, () => !this.submitRequest()); + return true; } onShow() { - routeOff(); _.delay(() => { diff --git a/dev/View/User/About.js b/dev/View/User/About.js index ab72c03bb..772c3723e 100644 --- a/dev/View/User/About.js +++ b/dev/View/User/About.js @@ -15,7 +15,6 @@ class AboutUserView extends AbstractViewNext { constructor() { super(); - this.version = ko.observable(Settings.appSettingsGet('version')); } } diff --git a/dev/View/User/AbstractSystemDropDown.js b/dev/View/User/AbstractSystemDropDown.js index 2cbe0c069..32b27040b 100644 --- a/dev/View/User/AbstractSystemDropDown.js +++ b/dev/View/User/AbstractSystemDropDown.js @@ -46,15 +46,15 @@ class AbstractSystemDropDownUserView extends AbstractViewNext this.addAccountClick = _.bind(this.addAccountClick, this); Events.sub('audio.stop', () => AppStore.currentAudio('')); - Events.sub('audio.start', (sName) => AppStore.currentAudio(sName)); + Events.sub('audio.start', (name) => AppStore.currentAudio(name)); } stopPlay() { Events.pub('audio.api.stop'); } - accountClick(oAccount, oEvent) { - if (oAccount && oEvent && !isUnd(oEvent.which) && 1 === oEvent.which) + accountClick(account, event) { + if (account && event && !isUnd(event.which) && 1 === event.which) { AccountStore.accounts.loading(true); _.delay(() => AccountStore.accounts.loading(false), Magics.Time1s); diff --git a/dev/View/User/Login.js b/dev/View/User/Login.js index 4261a4f5c..f1729b6c6 100644 --- a/dev/View/User/Login.js +++ b/dev/View/User/Login.js @@ -14,9 +14,7 @@ import { import { trim, inArray, pInt, - convertLangName, - createCommand, createCommandLegacy, - triggerAutocompleteInputChange + convertLangName, triggerAutocompleteInputChange } from 'Common/Utils'; import {socialFacebook, socialGoogle, socialTwitter} from 'Common/Links'; @@ -34,7 +32,7 @@ import Remote from 'Remote/User/Ajax'; 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'; @view({ @@ -151,36 +149,10 @@ class LoginUserView extends AbstractViewNext ); 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.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.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(() => { const bF = this.facebookLoginEnabled(), @@ -194,11 +166,33 @@ class LoginUserView extends AbstractViewNext { 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() { triggerAutocompleteInputChange(); @@ -383,10 +377,8 @@ class LoginUserView extends AbstractViewNext this.facebookLoginEnabled(!!Settings.settingsGet('AllowFacebookSocial')); this.twitterLoginEnabled(!!Settings.settingsGet('AllowTwitterSocial')); - this.googleLoginEnabled(!!Settings.settingsGet('AllowGoogleSocial') && - !!Settings.settingsGet('AllowGoogleSocialAuth')); - this.googleFastLoginEnabled(!!Settings.settingsGet('AllowGoogleSocial') && - !!Settings.settingsGet('AllowGoogleSocialAuthFast')); + this.googleLoginEnabled(!!Settings.settingsGet('AllowGoogleSocial') && !!Settings.settingsGet('AllowGoogleSocialAuth')); + this.googleFastLoginEnabled(!!Settings.settingsGet('AllowGoogleSocial') && !!Settings.settingsGet('AllowGoogleSocialAuthFast')); switch (signMe) { diff --git a/dev/View/User/MailBox/MessageList.js b/dev/View/User/MailBox/MessageList.js index ef04309d6..a82de9112 100644 --- a/dev/View/User/MailBox/MessageList.js +++ b/dev/View/User/MailBox/MessageList.js @@ -26,7 +26,6 @@ import { import { noop, noopFalse, - createCommand, computedPagenatorHelper, draggablePlace, friendlySize, @@ -55,9 +54,11 @@ import Remote from 'Remote/User/Ajax'; 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'; +const canBeMovedHelper = (self) => self.canBeMoved(); + @view({ name: 'View/User/MailBox/MessageList', type: ViewType.Right, @@ -226,63 +227,6 @@ class MessageListMailBoxUserView extends AbstractViewNext 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.selector = new Selector( @@ -340,16 +284,82 @@ class MessageListMailBoxUserView extends AbstractViewNext }); } - hideLeft(oItem, oEvent) { - oEvent.preventDefault(); - oEvent.stopPropagation(); + @command() + clearCommand() { + 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); } - showLeft(oItem, oEvent) { - oEvent.preventDefault(); - oEvent.stopPropagation(); + showLeft(item, event) { + event.preventDefault(); + event.stopPropagation(); leftPanelDisabled(false); } diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js index b9be7531e..1dcf74403 100644 --- a/dev/View/User/MailBox/MessageView.js +++ b/dev/View/User/MailBox/MessageView.js @@ -20,10 +20,10 @@ import { } from 'Common/Globals'; import { - createCommand, inArray, trim, noop, - isNonEmptyArray, windowResize, windowResizeCallback, + inArray, isArray, isNonEmptyArray, trim, noop, + windowResize, windowResizeCallback, inFocus, removeSelection, removeInFocus, mailToHelper, - inFocus, isArray + createCommand } from 'Common/Utils'; import Audio from 'Common/Audio'; @@ -52,7 +52,7 @@ import Promises from 'Promises/User/Ajax'; 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'; @view({ @@ -66,10 +66,22 @@ class MessageViewMailBoxUserView extends AbstractViewNext super(); let lastEmail = ''; - const createCommandHelper = (type) => createCommand(() => { - this.lastReplyAction(type); - this.replyOrforward(type); - }, this.canBeRepliedOrForwarded); + + const + createCommandReplyHelper = (type) => createCommand(() => { + 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.oHeaderDom = null; @@ -214,71 +226,17 @@ class MessageViewMailBoxUserView extends AbstractViewNext }); // commands - this.closeMessage = createCommand(() => { - MessageStore.message(null); - }); + this.replyCommand = createCommandReplyHelper(ComposeType.Reply); + 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.replyAllCommand = createCommandHelper(ComposeType.ReplyAll); - this.forwardCommand = createCommandHelper(ComposeType.Forward); - this.forwardAsAttachmentCommand = createCommandHelper(ComposeType.ForwardAsAttachment); - this.editAsNewCommand = createCommandHelper(ComposeType.EditAsNew); - - 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.deleteCommand = createCommandActionHelper(FolderType.Trash, true); + this.deleteWithoutMoveCommand = createCommandActionHelper(FolderType.Trash, false); + this.archiveCommand = createCommandActionHelper(FolderType.Archive, true); + this.spamCommand = createCommandActionHelper(FolderType.Spam, true); + this.notSpamCommand = createCommandActionHelper(FolderType.NotSpam, true); this.dropboxEnabled = SocialStore.dropbox.enabled; this.dropboxApiKey = SocialStore.dropbox.apiKey; @@ -430,18 +388,6 @@ class MessageViewMailBoxUserView extends AbstractViewNext () => 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', () => { this.toggleFullScreen(); }); @@ -449,6 +395,33 @@ class MessageViewMailBoxUserView extends AbstractViewNext 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) { let limit = 5, diff --git a/dev/View/User/Settings/Menu.js b/dev/View/User/Settings/Menu.js index 7b0b9747b..5d359eae5 100644 --- a/dev/View/User/Settings/Menu.js +++ b/dev/View/User/Settings/Menu.js @@ -69,8 +69,8 @@ class MenuSettingsUserView extends AbstractViewNext }, Magics.Time200ms)); } - link(sRoute) { - return settings(sRoute); + link(route) { + return settings(route); } backToMailBoxClick() { diff --git a/dev/View/User/Settings/Pane.js b/dev/View/User/Settings/Pane.js index 878fbaa62..ebaf49ca0 100644 --- a/dev/View/User/Settings/Pane.js +++ b/dev/View/User/Settings/Pane.js @@ -29,16 +29,16 @@ class PaneSettingsUserView extends AbstractViewNext MessageStore.message(null); } - hideLeft(oItem, oEvent) { - oEvent.preventDefault(); - oEvent.stopPropagation(); + hideLeft(item, event) { + event.preventDefault(); + event.stopPropagation(); leftPanelDisabled(true); } - showLeft(oItem, oEvent) { - oEvent.preventDefault(); - oEvent.stopPropagation(); + showLeft(item, event) { + event.preventDefault(); + event.stopPropagation(); leftPanelDisabled(false); } diff --git a/gulpfile.js b/gulpfile.js index 521bf251d..24668558f 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -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.momentLocales = 'rainloop/v/' + cfg.devVersion + '/app/localization/moment/'; +cfg.paths.asserts = { + src: 'asserts/**/*.*' +}; + cfg.paths.less = { main: { 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 gulp.task('css:clean', function() { return cleanDir(cfg.paths.staticCSS + '/*.css'); }); -gulp.task('css:main', function() { +gulp.task('css:main', ['asserts'], function() { var autoprefixer = require('gulp-autoprefixer'), less = require('gulp-less'), lessFilter = filter('**/*.less', {restore: true}), @@ -586,7 +602,7 @@ gulp.task('css', ['css:min']); 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']); diff --git a/rainloop/v/0.0.0/app/templates/Views/User/MailMessageView.html b/rainloop/v/0.0.0/app/templates/Views/User/MailMessageView.html index 1ef0ebabc..75474c356 100644 --- a/rainloop/v/0.0.0/app/templates/Views/User/MailMessageView.html +++ b/rainloop/v/0.0.0/app/templates/Views/User/MailMessageView.html @@ -4,7 +4,7 @@
@@ -216,7 +216,7 @@
- + diff --git a/rainloop/v/0.0.0/static/css/fonts/.gitempty b/rainloop/v/0.0.0/static/css/fonts/.gitempty deleted file mode 100644 index e69de29bb..000000000 diff --git a/rainloop/v/0.0.0/static/js/.empty b/rainloop/v/0.0.0/static/js/.empty deleted file mode 100644 index e69de29bb..000000000 diff --git a/rainloop/v/0.0.0/static/js/min/.empty b/rainloop/v/0.0.0/static/js/min/.empty deleted file mode 100644 index e69de29bb..000000000