mirror of
https://github.com/the-djmaze/snappymail.git
synced 2025-09-13 08:34:36 +08:00
Replace babel command decorators with proper knockout command decorators
This commit is contained in:
parent
b6d8fa5b3f
commit
540b12ed26
27 changed files with 181 additions and 132 deletions
16
README.md
16
README.md
|
@ -114,23 +114,23 @@ RainLoop 1.15 vs SnappyMail
|
|||
|
||||
|js/* |RainLoop |Snappy |
|
||||
|--------------- |--------: |--------: |
|
||||
|admin.js |2.158.025 | 114.168 |
|
||||
|app.js |4.215.733 | 529.069 |
|
||||
|admin.js |2.158.025 | 110.918 |
|
||||
|app.js |4.215.733 | 519.708 |
|
||||
|boot.js | 672.433 | 4.726 |
|
||||
|libs.js | 647.679 | 227.341 |
|
||||
|libs.js | 647.679 | 227.110 |
|
||||
|polyfills.js | 325.908 | 0 |
|
||||
|serviceworker.js | 0 | 285 |
|
||||
|TOTAL |8.019.778 | 875.589 |
|
||||
|
||||
|js/min/* |RainLoop |Snappy |RL gzip |SM gzip |RL brotli |SM brotli |
|
||||
|--------------- |--------: |--------: |------: |------: |--------: |--------: |
|
||||
|admin.min.js | 255.514 | 57.878 | 73.899 | 16.598 | 60.674 | 14.745 |
|
||||
|app.min.js | 516.000 | 257.954 |140.430 | 74.500 |110.657 | 62.522 |
|
||||
|admin.min.js | 255.514 | 56.127 | 73.899 | 16.069 | 60.674 | 14.274 |
|
||||
|app.min.js | 516.000 | 253.025 |140.430 | 73.063 |110.657 | 61.430 |
|
||||
|boot.min.js | 66.456 | 2.525 | 22.553 | 1.391 | 20.043 | 1.201 |
|
||||
|libs.min.js | 574.626 | 119.938 |177.280 | 43.997 |151.855 | 39.158 |
|
||||
|libs.min.js | 574.626 | 119.817 |177.280 | 43.974 |151.855 | 39.127 |
|
||||
|polyfills.min.js | 32.608 | 0 | 11.315 | 0 | 10.072 | 0 |
|
||||
|TOTAL |1.445.204 | 438.295 |425.477 |136.486 |353.301 |117.626 |
|
||||
|TOTAL (no admin) |1.189.690 | 380.417 |351.061 |119.888 |292.627 |102.881 |
|
||||
|TOTAL |1.445.204 | 431.494 |425.477 |134.497 |353.301 |116.032 |
|
||||
|TOTAL (no admin) |1.189.690 | 375.474 |351.061 |118.428 |292.627 |101.758 |
|
||||
|
||||
For a user its around 65% smaller and faster than traditional RainLoop.
|
||||
|
||||
|
|
15
dev/External/ko.js
vendored
15
dev/External/ko.js
vendored
|
@ -86,23 +86,10 @@ ko.bindingHandlers.command = {
|
|||
init: (element, fValueAccessor, fAllBindingsAccessor, viewModel, bindingContext) => {
|
||||
const command = fValueAccessor();
|
||||
|
||||
if (!command || !command.isCommand) {
|
||||
if (!command || !command.enabled || !command.canExecute) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
element.classList.add('command');
|
||||
ko.bindingHandlers['FORM'==element.nodeName ? 'submit' : 'click'].init(
|
||||
element,
|
||||
|
|
|
@ -320,32 +320,27 @@ export function startScreens(screensClasses) {
|
|||
setTimeout(() => $htmlCL.add('rl-started-delay'), 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 = typeof canExecute === 'function' ? canExecute : () => !!canExecute;
|
||||
|
||||
descriptor.value = function(...args) {
|
||||
if (normCanExecute.call(this, this)) {
|
||||
value.apply(this, args);
|
||||
function decorateKoCommands(thisArg, commands) {
|
||||
Object.entries(commands).forEach(([key, canExecute]) => {
|
||||
let command = thisArg[key],
|
||||
fn = function(...args) {
|
||||
if (fn.enabled() && canExecute.call(thisArg, thisArg)) {
|
||||
command.apply(thisArg, args);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
descriptor.value.__realCanExecute = normCanExecute;
|
||||
descriptor.value.isCommand = true;
|
||||
// fn.__realCanExecute = canExecute;
|
||||
// fn.isCommand = true;
|
||||
|
||||
return descriptor;
|
||||
};
|
||||
fn.enabled = ko.observable(true);
|
||||
|
||||
fn.canExecute = (typeof canExecute === 'function')
|
||||
? ko.computed(() => fn.enabled() && canExecute.call(thisArg, thisArg))
|
||||
: ko.computed(() => fn.enabled() && !!canExecute);
|
||||
|
||||
thisArg[key] = fn;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -370,7 +365,6 @@ function settingsMenuKeysHandler(items) {
|
|||
}
|
||||
|
||||
export {
|
||||
commandDecorator,
|
||||
commandDecorator as command,
|
||||
decorateKoCommands,
|
||||
settingsMenuKeysHandler
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@ import { settingsSaveHelperSimpleFunction, defaultOptionsAfterRender } from 'Com
|
|||
|
||||
import { SaveSettingsStep, StorageResultType } from 'Common/Enums';
|
||||
import Remote from 'Remote/Admin/Fetch';
|
||||
import { command } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands } from 'Knoin/Knoin';
|
||||
|
||||
const settingsGet = rl.settings.get;
|
||||
|
||||
|
@ -74,9 +74,12 @@ export class ContactsAdminSettings {
|
|||
this.contactsType(settingsGet('ContactsPdoType'));
|
||||
|
||||
this.onTestContactsResponse = this.onTestContactsResponse.bind(this);
|
||||
|
||||
decorateKoCommands(this, {
|
||||
testContactsCommand: self => self.pdoDsn() && self.pdoUser()
|
||||
});
|
||||
}
|
||||
|
||||
@command((self) => self.pdoDsn() && self.pdoUser())
|
||||
testContactsCommand() {
|
||||
this.testContactsSuccess(false);
|
||||
this.testContactsError(false);
|
||||
|
|
|
@ -7,7 +7,7 @@ import { CapaAdminStore } from 'Stores/Admin/Capa';
|
|||
|
||||
import Remote from 'Remote/Admin/Fetch';
|
||||
|
||||
import { command } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands } from 'Knoin/Knoin';
|
||||
|
||||
const settingsGet = rl.settings.get;
|
||||
|
||||
|
@ -75,9 +75,12 @@ export class SecurityAdminSettings {
|
|||
});
|
||||
|
||||
this.onNewAdminPasswordResponse = this.onNewAdminPasswordResponse.bind(this);
|
||||
|
||||
decorateKoCommands(this, {
|
||||
saveNewAdminPasswordCommand: self => self.adminLogin().trim() && self.adminPassword()
|
||||
});
|
||||
}
|
||||
|
||||
@command((self) => self.adminLogin().trim() && self.adminPassword())
|
||||
saveNewAdminPasswordCommand() {
|
||||
if (!this.adminLogin().trim()) {
|
||||
this.adminLoginError(true);
|
||||
|
|
|
@ -5,7 +5,7 @@ import { getNotification } from 'Common/Translator';
|
|||
|
||||
import Remote from 'Remote/Admin/Fetch';
|
||||
|
||||
import { command } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands } from 'Knoin/Knoin';
|
||||
import { AbstractViewCenter } from 'Knoin/AbstractViews';
|
||||
|
||||
class LoginAdminView extends AbstractViewCenter {
|
||||
|
@ -38,9 +38,12 @@ class LoginAdminView extends AbstractViewCenter {
|
|||
|
||||
passwordError: v => this.formError(!!v)
|
||||
});
|
||||
|
||||
decorateKoCommands(this, {
|
||||
submitCommand: self => !self.submitRequest()
|
||||
});
|
||||
}
|
||||
|
||||
@command((self) => !self.submitRequest())
|
||||
submitCommand() {
|
||||
this.loginError(false);
|
||||
this.passwordError(false);
|
||||
|
|
|
@ -3,7 +3,7 @@ import { getNotification } from 'Common/Translator';
|
|||
|
||||
import Remote from 'Remote/User/Fetch';
|
||||
|
||||
import { command } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
class AccountPopupView extends AbstractViewPopup {
|
||||
|
@ -29,9 +29,12 @@ class AccountPopupView extends AbstractViewPopup {
|
|||
this.email.subscribe(() => this.emailError(false));
|
||||
|
||||
this.password.subscribe(() => this.passwordError(false));
|
||||
|
||||
decorateKoCommands(this, {
|
||||
addAccountCommand: self => !self.submitRequest()
|
||||
});
|
||||
}
|
||||
|
||||
@command((self) => !self.submitRequest())
|
||||
addAccountCommand() {
|
||||
this.emailError(!this.email().trim());
|
||||
this.passwordError(!this.password().trim());
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import PgpStore from 'Stores/User/Pgp';
|
||||
|
||||
import { command } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
class AddOpenPgpKeyPopupView extends AbstractViewPopup {
|
||||
|
@ -17,9 +17,12 @@ class AddOpenPgpKeyPopupView extends AbstractViewPopup {
|
|||
this.keyError(false);
|
||||
this.keyErrorMessage('');
|
||||
});
|
||||
|
||||
decorateKoCommands(this, {
|
||||
addOpenPgpKeyCommand: 1
|
||||
});
|
||||
}
|
||||
|
||||
@command()
|
||||
addOpenPgpKeyCommand() {
|
||||
// eslint-disable-next-line max-len
|
||||
const reg = /[-]{3,6}BEGIN[\s]PGP[\s](PRIVATE|PUBLIC)[\s]KEY[\s]BLOCK[-]{3,6}[\s\S]+?[-]{3,6}END[\s]PGP[\s](PRIVATE|PUBLIC)[\s]KEY[\s]BLOCK[-]{3,6}/gi,
|
||||
|
|
|
@ -4,7 +4,7 @@ import { i18n, trigger as translatorTrigger } from 'Common/Translator';
|
|||
|
||||
import MessageStore from 'Stores/User/Message';
|
||||
|
||||
import { command } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
class AdvancedSearchPopupView extends AbstractViewPopup {
|
||||
|
@ -38,9 +38,12 @@ class AdvancedSearchPopupView extends AbstractViewPopup {
|
|||
{ id: 365, name: i18n(prefix + 'YEAR') }
|
||||
];
|
||||
});
|
||||
|
||||
decorateKoCommands(this, {
|
||||
searchCommand: 1
|
||||
});
|
||||
}
|
||||
|
||||
@command()
|
||||
searchCommand() {
|
||||
const search = this.buildSearchString();
|
||||
if (search) {
|
||||
|
|
|
@ -37,7 +37,7 @@ import Remote from 'Remote/User/Fetch';
|
|||
|
||||
import { ComposeAttachmentModel } from 'Model/ComposeAttachment';
|
||||
|
||||
import { command, isPopupVisible, showScreenPopup, hideScreenPopup } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands, isPopupVisible, showScreenPopup, hideScreenPopup } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
import { FolderSystemPopupView } from 'View/Popup/FolderSystem';
|
||||
|
@ -332,6 +332,14 @@ class ComposePopupView extends AbstractViewPopup {
|
|||
this.saveCommand();
|
||||
}
|
||||
}, 120000);
|
||||
|
||||
decorateKoCommands(this, {
|
||||
sendCommand: self => self.canBeSentOrSaved(),
|
||||
saveCommand: self => self.canBeSentOrSaved(),
|
||||
deleteCommand: self => self.isDraftFolderMessage(),
|
||||
skipCommand: self => self.canBeSentOrSaved(),
|
||||
contactsCommand: self => self.allowContacts
|
||||
});
|
||||
}
|
||||
|
||||
getMessageRequestParams(sSaveFolder)
|
||||
|
@ -359,7 +367,6 @@ class ComposePopupView extends AbstractViewPopup {
|
|||
};
|
||||
}
|
||||
|
||||
@command((self) => self.canBeSentOrSaved())
|
||||
sendCommand() {
|
||||
let sSentFolder = FolderStore.sentFolder();
|
||||
|
||||
|
@ -429,7 +436,6 @@ class ComposePopupView extends AbstractViewPopup {
|
|||
}
|
||||
}
|
||||
|
||||
@command((self) => self.canBeSentOrSaved())
|
||||
saveCommand() {
|
||||
if (!this.allowFolders) {
|
||||
return false;
|
||||
|
@ -454,7 +460,6 @@ class ComposePopupView extends AbstractViewPopup {
|
|||
return true;
|
||||
}
|
||||
|
||||
@command((self) => self.isDraftFolderMessage())
|
||||
deleteCommand() {
|
||||
if (!isPopupVisible(AskPopupView) && this.modalVisibility()) {
|
||||
showScreenPopup(AskPopupView, [
|
||||
|
@ -469,7 +474,6 @@ class ComposePopupView extends AbstractViewPopup {
|
|||
}
|
||||
}
|
||||
|
||||
@command((self) => self.canBeSentOrSaved())
|
||||
skipCommand() {
|
||||
this.bSkipNextHide = true;
|
||||
|
||||
|
@ -486,7 +490,6 @@ class ComposePopupView extends AbstractViewPopup {
|
|||
this.tryToClosePopup();
|
||||
}
|
||||
|
||||
@command((self) => self.allowContacts)
|
||||
contactsCommand() {
|
||||
if (this.allowContacts) {
|
||||
this.skipCommand();
|
||||
|
|
|
@ -9,7 +9,7 @@ import PgpStore from 'Stores/User/Pgp';
|
|||
|
||||
import { EmailModel } from 'Model/Email';
|
||||
|
||||
import { command } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
const KEY_NAME_SUBSTR = -8,
|
||||
|
@ -103,9 +103,15 @@ class ComposeOpenPgpPopupView extends AbstractViewPopup {
|
|||
};
|
||||
|
||||
this.deletePublickKey = this.deletePublickKey.bind(this);
|
||||
|
||||
decorateKoCommands(this, {
|
||||
doCommand: self => !self.submitRequest() && (self.sign() || self.encrypt()),
|
||||
selectCommand: 1,
|
||||
addCommand: 1,
|
||||
updateCommand: 1,
|
||||
});
|
||||
}
|
||||
|
||||
@command((self) => !self.submitRequest() && (self.sign() || self.encrypt()))
|
||||
doCommand() {
|
||||
let result = true,
|
||||
privateKey = null,
|
||||
|
@ -237,7 +243,6 @@ class ComposeOpenPgpPopupView extends AbstractViewPopup {
|
|||
return result;
|
||||
}
|
||||
|
||||
@command()
|
||||
selectCommand() {
|
||||
const keyId = this.selectedPrivateKey(),
|
||||
option = keyId ? this.privateKeysOptions().find(item => item && keyId === item.id) : null;
|
||||
|
@ -253,7 +258,6 @@ class ComposeOpenPgpPopupView extends AbstractViewPopup {
|
|||
}
|
||||
}
|
||||
|
||||
@command()
|
||||
addCommand() {
|
||||
const keyId = this.selectedPublicKey(),
|
||||
option = keyId ? this.publicKeysOptions().find(item => item && keyId === item.id) : null;
|
||||
|
@ -270,7 +274,6 @@ class ComposeOpenPgpPopupView extends AbstractViewPopup {
|
|||
}
|
||||
}
|
||||
|
||||
@command()
|
||||
updateCommand() {
|
||||
this.encryptKeys.forEach(oKey =>
|
||||
oKey.removable(!this.sign() || !this.signKey() || this.signKey().key.id !== oKey.key.id)
|
||||
|
|
|
@ -26,7 +26,7 @@ import { EmailModel } from 'Model/Email';
|
|||
import { ContactModel } from 'Model/Contact';
|
||||
import { ContactPropertyModel, ContactPropertyType } from 'Model/ContactProperty';
|
||||
|
||||
import { command, hideScreenPopup } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands, hideScreenPopup } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
|
||||
|
@ -162,21 +162,28 @@ class ContactsPopupView extends AbstractViewPopup {
|
|||
this.watchDirty(true);
|
||||
}
|
||||
});
|
||||
|
||||
decorateKoCommands(this, {
|
||||
newCommand: 1,
|
||||
deleteCommand: self => 0 < self.contactsCheckedOrSelected().length,
|
||||
newMessageCommand: self => 0 < self.contactsCheckedOrSelected().length,
|
||||
clearCommand: 1,
|
||||
saveCommand: self => !self.viewSaving() && !self.viewReadOnly()
|
||||
&& (self.contactHasValidName() || self.viewProperties.find(prop => propertyIsMail(prop) && prop.isValid())),
|
||||
syncCommand: self => !self.contacts.syncing() && !self.contacts.importing()
|
||||
});
|
||||
}
|
||||
|
||||
@command()
|
||||
newCommand() {
|
||||
this.populateViewContact(null);
|
||||
this.currentContact(null);
|
||||
}
|
||||
|
||||
@command((self) => 0 < self.contactsCheckedOrSelected().length)
|
||||
deleteCommand() {
|
||||
this.deleteSelectedContacts();
|
||||
this.emptySelection(true);
|
||||
}
|
||||
|
||||
@command((self) => 0 < self.contactsCheckedOrSelected().length)
|
||||
newMessageCommand() {
|
||||
if (!rl.settings.capa(Capa.Composer)) {
|
||||
return false;
|
||||
|
@ -233,15 +240,10 @@ class ContactsPopupView extends AbstractViewPopup {
|
|||
return true;
|
||||
}
|
||||
|
||||
@command()
|
||||
clearCommand() {
|
||||
this.search('');
|
||||
}
|
||||
|
||||
@command(self =>
|
||||
!self.viewSaving() && !self.viewReadOnly()
|
||||
&& (self.contactHasValidName() || self.viewProperties.find(prop => propertyIsMail(prop) && prop.isValid()))
|
||||
)
|
||||
saveCommand() {
|
||||
this.viewSaving(true);
|
||||
this.viewSaveTrigger(SaveSettingsStep.Animate);
|
||||
|
@ -283,7 +285,6 @@ class ContactsPopupView extends AbstractViewPopup {
|
|||
);
|
||||
}
|
||||
|
||||
@command((self) => !self.contacts.syncing() && !self.contacts.importing())
|
||||
syncCommand() {
|
||||
rl.app.contactsSync((result, data) => {
|
||||
if (StorageResultType.Success !== result || !data || !data.Result) {
|
||||
|
|
|
@ -6,7 +6,7 @@ import { CapaAdminStore } from 'Stores/Admin/Capa';
|
|||
|
||||
import Remote from 'Remote/Admin/Fetch';
|
||||
|
||||
import { command } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
class DomainPopupView extends AbstractViewPopup {
|
||||
|
@ -162,9 +162,16 @@ class DomainPopupView extends AbstractViewPopup {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
decorateKoCommands(this, {
|
||||
createOrAddCommand: self => self.canBeSaved(),
|
||||
testConnectionCommand: self => self.canBeTested(),
|
||||
whiteListCommand: 1,
|
||||
backCommand: 1,
|
||||
sieveCommand: 1
|
||||
});
|
||||
}
|
||||
|
||||
@command((self) => self.canBeSaved())
|
||||
createOrAddCommand() {
|
||||
this.saving(true);
|
||||
Remote.createOrUpdateDomain(
|
||||
|
@ -173,7 +180,6 @@ class DomainPopupView extends AbstractViewPopup {
|
|||
);
|
||||
}
|
||||
|
||||
@command((self) => self.canBeTested())
|
||||
testConnectionCommand() {
|
||||
this.page('main');
|
||||
|
||||
|
@ -189,17 +195,14 @@ class DomainPopupView extends AbstractViewPopup {
|
|||
);
|
||||
}
|
||||
|
||||
@command()
|
||||
whiteListCommand() {
|
||||
this.page('white-list');
|
||||
}
|
||||
|
||||
@command()
|
||||
backCommand() {
|
||||
this.page('main');
|
||||
}
|
||||
|
||||
@command()
|
||||
sieveCommand() {
|
||||
this.sieveSettings(!this.sieveSettings());
|
||||
this.clearTesting();
|
||||
|
|
|
@ -7,7 +7,7 @@ import { DomainAdminStore } from 'Stores/Admin/Domain';
|
|||
|
||||
import Remote from 'Remote/Admin/Fetch';
|
||||
|
||||
import { command } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
class DomainAliasPopupView extends AbstractViewPopup {
|
||||
|
@ -30,9 +30,12 @@ class DomainAliasPopupView extends AbstractViewPopup {
|
|||
this.canBeSaved = ko.computed(() => !this.saving() && this.name() && this.alias());
|
||||
|
||||
this.onDomainAliasCreateOrSaveResponse = this.onDomainAliasCreateOrSaveResponse.bind(this);
|
||||
|
||||
decorateKoCommands(this, {
|
||||
createCommand: self => self.canBeSaved()
|
||||
});
|
||||
}
|
||||
|
||||
@command((self) => self.canBeSaved())
|
||||
createCommand() {
|
||||
this.saving(true);
|
||||
Remote.createDomainAlias(this.onDomainAliasCreateOrSaveResponse, this.name(), this.alias());
|
||||
|
|
|
@ -8,7 +8,7 @@ import { i18n, initOnStartOrLangChange } from 'Common/Translator';
|
|||
import FolderStore from 'Stores/User/Folder';
|
||||
import { SieveUserStore } from 'Stores/User/Sieve';
|
||||
|
||||
import { command } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
class FilterPopupView extends AbstractViewPopup {
|
||||
|
@ -36,9 +36,12 @@ class FilterPopupView extends AbstractViewPopup {
|
|||
initOnStartOrLangChange(this.populateOptions.bind(this));
|
||||
|
||||
SieveUserStore.capa.subscribe(this.populateOptions, this);
|
||||
|
||||
decorateKoCommands(this, {
|
||||
saveFilterCommand: 1
|
||||
});
|
||||
}
|
||||
|
||||
@command()
|
||||
saveFilterCommand() {
|
||||
if (this.filter()) {
|
||||
if (FilterAction.MoveTo === this.filter().actionType()) {
|
||||
|
|
|
@ -6,7 +6,7 @@ import MessageStore from 'Stores/User/Message';
|
|||
|
||||
import Remote from 'Remote/User/Fetch';
|
||||
|
||||
import { command } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
class FolderClearPopupView extends AbstractViewPopup {
|
||||
|
@ -32,14 +32,15 @@ class FolderClearPopupView extends AbstractViewPopup {
|
|||
|
||||
dangerDescHtml: () => i18n('POPUPS_CLEAR_FOLDER/DANGER_DESC_HTML_1', { 'FOLDER': this.folderNameForClear() })
|
||||
});
|
||||
|
||||
decorateKoCommands(this, {
|
||||
clearCommand: self => {
|
||||
const folder = self.selectedFolder();
|
||||
return !self.clearingProcess() && null !== folder;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@command((self) => {
|
||||
const folder = self.selectedFolder(),
|
||||
isClearing = self.clearingProcess();
|
||||
|
||||
return !isClearing && null !== folder;
|
||||
})
|
||||
clearCommand() {
|
||||
const folderToClear = this.selectedFolder();
|
||||
if (folderToClear) {
|
||||
|
|
|
@ -9,7 +9,7 @@ import FolderStore from 'Stores/User/Folder';
|
|||
|
||||
import Remote from 'Remote/User/Fetch';
|
||||
|
||||
import { command } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
class FolderCreatePopupView extends AbstractViewPopup {
|
||||
|
@ -40,9 +40,12 @@ class FolderCreatePopupView extends AbstractViewPopup {
|
|||
});
|
||||
|
||||
this.defaultOptionsAfterRender = defaultOptionsAfterRender;
|
||||
|
||||
decorateKoCommands(this, {
|
||||
createFolderCommand: self => self.simpleFolderNameValidation(self.folderName())
|
||||
});
|
||||
}
|
||||
|
||||
@command((self) => self.simpleFolderNameValidation(self.folderName()))
|
||||
createFolderCommand() {
|
||||
let parentFolderName = this.selectedParentValue();
|
||||
if (!parentFolderName && 1 < FolderStore.namespace.length) {
|
||||
|
|
|
@ -3,7 +3,7 @@ import { getNotification } from 'Common/Translator';
|
|||
|
||||
import Remote from 'Remote/User/Fetch';
|
||||
|
||||
import { command } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
const reEmail = /^[^@\s]+@[^@\s]+$/;
|
||||
|
@ -61,9 +61,11 @@ class IdentityPopupView extends AbstractViewPopup {
|
|||
this.replyTo.valueHasMutated();
|
||||
this.bcc.valueHasMutated();
|
||||
*/
|
||||
decorateKoCommands(this, {
|
||||
addOrEditIdentityCommand: self => !self.submitRequest()
|
||||
});
|
||||
}
|
||||
|
||||
@command((self) => !self.submitRequest())
|
||||
addOrEditIdentityCommand() {
|
||||
if (this.signature && this.signature.__fetchEditorValue) {
|
||||
this.signature.__fetchEditorValue();
|
||||
|
|
|
@ -3,7 +3,7 @@ import ko from 'ko';
|
|||
import { pString } from 'Common/Utils';
|
||||
import { KeyState } from 'Common/Enums';
|
||||
|
||||
import { command } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
class MessageOpenPgpPopupView extends AbstractViewPopup {
|
||||
|
@ -21,9 +21,12 @@ class MessageOpenPgpPopupView extends AbstractViewPopup {
|
|||
this.resultCallback = null;
|
||||
|
||||
this.sDefaultKeyScope = KeyState.PopupMessageOpenPGP;
|
||||
|
||||
decorateKoCommands(this, {
|
||||
doCommand: self => !self.submitRequest()
|
||||
});
|
||||
}
|
||||
|
||||
@command((self) => !self.submitRequest())
|
||||
doCommand() {
|
||||
this.submitRequest(true);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import { pInt } from 'Common/Utils';
|
|||
|
||||
import PgpStore from 'Stores/User/Pgp';
|
||||
|
||||
import { command } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
class NewOpenPgpKeyPopupView extends AbstractViewPopup {
|
||||
|
@ -23,9 +23,12 @@ class NewOpenPgpKeyPopupView extends AbstractViewPopup {
|
|||
});
|
||||
|
||||
this.email.subscribe(() => this.emailError(false));
|
||||
|
||||
decorateKoCommands(this, {
|
||||
generateOpenPgpKeyCommand: 1
|
||||
});
|
||||
}
|
||||
|
||||
@command()
|
||||
generateOpenPgpKeyCommand() {
|
||||
const userId = {},
|
||||
openpgpKeyring = PgpStore.openpgpKeyring;
|
||||
|
|
|
@ -5,7 +5,7 @@ import { getNotification, i18n } from 'Common/Translator';
|
|||
|
||||
import Remote from 'Remote/Admin/Fetch';
|
||||
|
||||
import { command, isPopupVisible, showScreenPopup } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands, isPopupVisible, showScreenPopup } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
import { AskPopupView } from 'View/Popup/Ask';
|
||||
|
||||
|
@ -30,9 +30,12 @@ class PluginPopupView extends AbstractViewPopup {
|
|||
this.sDefaultKeyScope = KeyState.All;
|
||||
|
||||
this.tryToClosePopup = this.tryToClosePopup.debounce(200);
|
||||
|
||||
decorateKoCommands(this, {
|
||||
saveCommand: self => self.hasConfiguration()
|
||||
});
|
||||
}
|
||||
|
||||
@command((self) => self.hasConfiguration())
|
||||
saveCommand() {
|
||||
const list = {};
|
||||
list.Name = this.name();
|
||||
|
|
|
@ -9,7 +9,7 @@ import Remote from 'Remote/User/Fetch';
|
|||
import { FilterModel } from 'Model/Filter';
|
||||
import { SieveUserStore } from 'Stores/User/Sieve';
|
||||
|
||||
import { showScreenPopup/*, command*/ } from 'Knoin/Knoin';
|
||||
import { showScreenPopup/*, decorateKoCommands*/ } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
import { FilterPopupView } from 'View/Popup/Filter';
|
||||
|
@ -30,9 +30,13 @@ class SieveScriptPopupView extends AbstractViewPopup {
|
|||
this.saving = false;
|
||||
|
||||
this.filterForDeletion = ko.observable(null).deleteAccessHelper();
|
||||
/*
|
||||
decorateKoCommands(this, {
|
||||
saveScriptCommand: 1
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
// @command()
|
||||
saveScriptCommand() {
|
||||
let self = this,
|
||||
script = self.script();
|
||||
|
|
|
@ -4,7 +4,7 @@ import { HtmlEditor } from 'Common/Html';
|
|||
|
||||
import Remote from 'Remote/User/Fetch';
|
||||
|
||||
import { command } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
import { TemplateModel } from 'Model/Template';
|
||||
|
||||
|
@ -34,9 +34,12 @@ class TemplatePopupView extends AbstractViewPopup {
|
|||
this.name.subscribe(() => this.nameError(false));
|
||||
|
||||
this.body.subscribe(() => this.bodyError(false));
|
||||
|
||||
decorateKoCommands(this, {
|
||||
addTemplateCommand: self => !self.submitRequest()
|
||||
});
|
||||
}
|
||||
|
||||
@command((self) => !self.submitRequest())
|
||||
addTemplateCommand() {
|
||||
this.populateBodyFromEditor();
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import { StorageResultType } from 'Common/Enums';
|
|||
|
||||
import Remote from 'Remote/User/Fetch';
|
||||
|
||||
import { command } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
class TwoFactorTestPopupView extends AbstractViewPopup {
|
||||
|
@ -18,9 +18,12 @@ class TwoFactorTestPopupView extends AbstractViewPopup {
|
|||
});
|
||||
|
||||
this.koTestedTrigger = null;
|
||||
|
||||
decorateKoCommands(this, {
|
||||
testCodeCommand: self => self.code() && !self.testing()
|
||||
});
|
||||
}
|
||||
|
||||
@command((self) => self.code() && !self.testing())
|
||||
testCodeCommand() {
|
||||
this.testing(true);
|
||||
Remote.testTwoFactor((result, data) => {
|
||||
|
|
|
@ -16,7 +16,7 @@ import * as Local from 'Storage/Client';
|
|||
|
||||
import Remote from 'Remote/User/Fetch';
|
||||
|
||||
import { command, showScreenPopup } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands, showScreenPopup } from 'Knoin/Knoin';
|
||||
import { AbstractViewCenter } from 'Knoin/AbstractViews';
|
||||
|
||||
import { Settings } from 'Common/Globals';
|
||||
|
@ -113,13 +113,16 @@ class LoginUserView extends AbstractViewCenter {
|
|||
if (Settings.get('AdditionalLoginError') && !this.submitError()) {
|
||||
this.submitError(Settings.get('AdditionalLoginError'));
|
||||
}
|
||||
|
||||
decorateKoCommands(this, {
|
||||
submitCommand: self => !self.submitRequest()
|
||||
});
|
||||
}
|
||||
|
||||
windowOpenFeatures(wh) {
|
||||
return `left=200,top=100,width=${wh},height=${wh},menubar=no,status=no,resizable=yes,scrollbars=yes`;
|
||||
}
|
||||
|
||||
@command((self) => !self.submitRequest())
|
||||
submitCommand() {
|
||||
this.emailError(false);
|
||||
this.passwordError(false);
|
||||
|
|
|
@ -41,7 +41,7 @@ import { ThemeStore } from 'Stores/Theme';
|
|||
|
||||
import Remote from 'Remote/User/Fetch';
|
||||
|
||||
import { command, showScreenPopup, popupVisibility } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands, showScreenPopup, popupVisibility } from 'Knoin/Knoin';
|
||||
import { AbstractViewRight } from 'Knoin/AbstractViews';
|
||||
|
||||
import { FolderClearPopupView } from 'View/Popup/FolderClear';
|
||||
|
@ -237,23 +237,33 @@ export class MessageListMailBoxUserView extends AbstractViewRight {
|
|||
MessageStore.messageListEndHash.subscribe((() =>
|
||||
this.selector.scrollToFocused()
|
||||
).throttle(50));
|
||||
|
||||
decorateKoCommands(this, {
|
||||
clearCommand: 1,
|
||||
reloadCommand: 1,
|
||||
multyForwardCommand: canBeMovedHelper,
|
||||
deleteWithoutMoveCommand: canBeMovedHelper,
|
||||
deleteCommand: canBeMovedHelper,
|
||||
archiveCommand: canBeMovedHelper,
|
||||
spamCommand: canBeMovedHelper,
|
||||
notSpamCommand: canBeMovedHelper,
|
||||
moveCommand: canBeMovedHelper,
|
||||
moveNewCommand: canBeMovedHelper,
|
||||
});
|
||||
}
|
||||
|
||||
@command()
|
||||
clearCommand() {
|
||||
if (Settings.capa(Capa.DangerousActions)) {
|
||||
showScreenPopup(FolderClearPopupView, [FolderStore.currentFolder()]);
|
||||
}
|
||||
}
|
||||
|
||||
@command()
|
||||
reloadCommand() {
|
||||
if (!MessageStore.messageListCompleteLoadingThrottleForAnimation() && this.allowReload) {
|
||||
rl.app.reloadMessageList(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
@command(canBeMovedHelper)
|
||||
multyForwardCommand() {
|
||||
if (Settings.capa(Capa.Composer)) {
|
||||
showScreenPopup(ComposePopupView, [
|
||||
|
@ -263,7 +273,6 @@ export class MessageListMailBoxUserView extends AbstractViewRight {
|
|||
}
|
||||
}
|
||||
|
||||
@command(canBeMovedHelper)
|
||||
deleteWithoutMoveCommand() {
|
||||
if (Settings.capa(Capa.DangerousActions)) {
|
||||
rl.app.deleteMessagesFromFolder(
|
||||
|
@ -275,7 +284,6 @@ export class MessageListMailBoxUserView extends AbstractViewRight {
|
|||
}
|
||||
}
|
||||
|
||||
@command(canBeMovedHelper)
|
||||
deleteCommand() {
|
||||
rl.app.deleteMessagesFromFolder(
|
||||
FolderType.Trash,
|
||||
|
@ -285,7 +293,6 @@ export class MessageListMailBoxUserView extends AbstractViewRight {
|
|||
);
|
||||
}
|
||||
|
||||
@command(canBeMovedHelper)
|
||||
archiveCommand() {
|
||||
rl.app.deleteMessagesFromFolder(
|
||||
FolderType.Archive,
|
||||
|
@ -295,7 +302,6 @@ export class MessageListMailBoxUserView extends AbstractViewRight {
|
|||
);
|
||||
}
|
||||
|
||||
@command(canBeMovedHelper)
|
||||
spamCommand() {
|
||||
rl.app.deleteMessagesFromFolder(
|
||||
FolderType.Spam,
|
||||
|
@ -305,7 +311,6 @@ export class MessageListMailBoxUserView extends AbstractViewRight {
|
|||
);
|
||||
}
|
||||
|
||||
@command(canBeMovedHelper)
|
||||
notSpamCommand() {
|
||||
rl.app.deleteMessagesFromFolder(
|
||||
FolderType.NotSpam,
|
||||
|
@ -315,10 +320,8 @@ export class MessageListMailBoxUserView extends AbstractViewRight {
|
|||
);
|
||||
}
|
||||
|
||||
@command(canBeMovedHelper)
|
||||
moveCommand() {} // eslint-disable-line no-empty-function
|
||||
moveCommand() {}
|
||||
|
||||
@command(canBeMovedHelper)
|
||||
moveNewCommand(vm, event) {
|
||||
if (this.newMoveToFolder && this.mobileCheckedStateShow()) {
|
||||
if (vm && event && event.preventDefault) {
|
||||
|
|
|
@ -38,7 +38,7 @@ import * as Local from 'Storage/Client';
|
|||
|
||||
import Remote from 'Remote/User/Fetch';
|
||||
|
||||
import { command, showScreenPopup, createCommand } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands, showScreenPopup, createCommand } from 'Knoin/Knoin';
|
||||
import { AbstractViewRight } from 'Knoin/AbstractViews';
|
||||
|
||||
import { ComposePopupView } from 'View/Popup/Compose';
|
||||
|
@ -266,29 +266,32 @@ class MessageViewMailBoxUserView extends AbstractViewRight {
|
|||
addEventListener('mailbox.message-view.toggle-full-screen', () => this.toggleFullScreen());
|
||||
|
||||
this.attachmentPreview = this.attachmentPreview.bind(this);
|
||||
|
||||
decorateKoCommands(this, {
|
||||
closeMessageCommand: 1,
|
||||
messageVisibilityCommand: self => self.messageVisibility(),
|
||||
messageEditCommand: self => self.messageVisibility(),
|
||||
goUpCommand: self => !self.messageListAndMessageViewLoading(),
|
||||
goDownCommand: self => !self.messageListAndMessageViewLoading()
|
||||
});
|
||||
}
|
||||
|
||||
@command()
|
||||
closeMessageCommand() {
|
||||
MessageStore.message(null);
|
||||
}
|
||||
|
||||
@command((self) => self.messageVisibility())
|
||||
messageVisibilityCommand() {} // eslint-disable-line no-empty-function
|
||||
messageVisibilityCommand() {}
|
||||
|
||||
@command((self) => self.messageVisibility())
|
||||
messageEditCommand() {
|
||||
this.editMessage();
|
||||
}
|
||||
|
||||
@command((self) => !self.messageListAndMessageViewLoading())
|
||||
goUpCommand() {
|
||||
dispatchEvent(new CustomEvent('mailbox.message-list.selector.go-up',
|
||||
{detail:SettingsStore.usePreviewPane() || !!this.message()} // bForceSelect
|
||||
));
|
||||
}
|
||||
|
||||
@command((self) => !self.messageListAndMessageViewLoading())
|
||||
goDownCommand() {
|
||||
dispatchEvent(new CustomEvent('mailbox.message-list.selector.go-down',
|
||||
{detail:SettingsStore.usePreviewPane() || !!this.message()} // bForceSelect
|
||||
|
|
Loading…
Add table
Reference in a new issue