diff --git a/core/fse.js b/core/fse.js index b1455e5d..ea8e69b5 100644 --- a/core/fse.js +++ b/core/fse.js @@ -5,7 +5,6 @@ const MenuModule = require('../core/menu_module.js').MenuModule; const ViewController = require('../core/view_controller.js').ViewController; const ansi = require('../core/ansi_term.js'); const theme = require('../core/theme.js'); -const MultiLineEditTextView = require('../core/multi_line_edit_text_view.js').MultiLineEditTextView; const Message = require('../core/message.js'); const getMessageAreaByTag = require('../core/message_area.js').getMessageAreaByTag; const updateMessageAreaLastReadId = require('../core/message_area.js').updateMessageAreaLastReadId; @@ -694,14 +693,16 @@ function FullScreenEditorModule(options) { setFooterText(MCICodeIds.ViewModeFooter.MsgTotal, self.messageTotal.toString()); }; - this.displayHelp = function() { + this.displayHelp = function(cb) { self.client.term.rawWrite(ansi.resetScreen()); - theme.displayThemeArt( { name : self.menuConfig.config.art.help, client : self.client }, - function helpDisplayed(err, artData) { - self.client.waitForKeyPress(function keyPress(ch, key) { - self.redrawScreen(function redrawn(err) { + theme.displayThemeArt( + { name : self.menuConfig.config.art.help, client : self.client }, + () => { + self.client.waitForKeyPress( () => { + self.redrawScreen( () => { self.viewControllers[self.getFooterName()].setFocus(true); + return cb(null); }); }); } @@ -867,10 +868,11 @@ function FullScreenEditorModule(options) { cb(newFocusViewId); }, - headerSubmit : function(formData, extraArgs) { + headerSubmit : function(formData, extraArgs, cb) { self.switchToBody(); + return cb(null); }, - editModeEscPressed : function(formData, extraArgs) { + editModeEscPressed : function(formData, extraArgs, cb) { self.footerMode = 'editor' === self.footerMode ? 'editorMenu' : 'editor'; self.switchFooter(function next(err) { @@ -879,38 +881,40 @@ function FullScreenEditorModule(options) { console.log(err) } else { switch(self.footerMode) { - case 'editor' : - if(!_.isUndefined(self.viewControllers.footerEditorMenu)) { - //self.viewControllers.footerEditorMenu.setFocus(false); - self.viewControllers.footerEditorMenu.detachClientEvents(); - } - self.viewControllers.body.switchFocus(1); - self.observeEditorEvents(); - break; + case 'editor' : + if(!_.isUndefined(self.viewControllers.footerEditorMenu)) { + //self.viewControllers.footerEditorMenu.setFocus(false); + self.viewControllers.footerEditorMenu.detachClientEvents(); + } + self.viewControllers.body.switchFocus(1); + self.observeEditorEvents(); + break; - case 'editorMenu' : - self.viewControllers.body.setFocus(false); - self.viewControllers.footerEditorMenu.switchFocus(1); - break; + case 'editorMenu' : + self.viewControllers.body.setFocus(false); + self.viewControllers.footerEditorMenu.switchFocus(1); + break; - default : throw new Error('Unexpected mode'); + default : throw new Error('Unexpected mode'); } - } + + return cb(null); }); }, - editModeMenuQuote : function(formData, extraArgs) { + editModeMenuQuote : function(formData, extraArgs, cb) { self.viewControllers.footerEditorMenu.setFocus(false); self.displayQuoteBuilder(); + return cb(null); }, - appendQuoteEntry: function(formData, extraArgs) { + appendQuoteEntry: function(formData, extraArgs, cb) { // :TODO: Dont' use magic # ID's here var quoteMsgView = self.viewControllers.quoteBuilder.getView(1); if(self.newQuoteBlock) { self.newQuoteBlock = false; - // :TODO: Make date/time format avail as FSE config + // :TODO: Make date/time format avail as FSE config -- also the line itself! var dtFormat = self.client.currentTheme.helpers.getDateTimeFormat(); quoteMsgView.addText( 'On {0} {1} said...'.format( @@ -932,9 +936,12 @@ function FullScreenEditorModule(options) { } else { self.quoteBuilderFinalize(); } + + return cb(null); }, - quoteBuilderEscPressed : function(formData, extraArgs) { + quoteBuilderEscPressed : function(formData, extraArgs, cb) { self.quoteBuilderFinalize(); + return cb(null); }, /* replyDiscard : function(formData, extraArgs) { @@ -943,22 +950,16 @@ function FullScreenEditorModule(options) { self.prevMenu(); }, */ - editModeMenuHelp : function(formData, extraArgs) { + editModeMenuHelp : function(formData, extraArgs, cb) { self.viewControllers.footerEditorMenu.setFocus(false); - self.displayHelp(); + return self.displayHelp(cb); }, /////////////////////////////////////////////////////////////////////// // View Mode /////////////////////////////////////////////////////////////////////// - viewModeEscPressed : function(formData, extraArgs) { - // - // MLTEV won't get key events -- we need to handle them all here? - // ...up/down, page up/page down... both should go by pages - // ...Next/Prev/Etc. here - }, - viewModeMenuHelp : function(formData, extraArgs) { + viewModeMenuHelp : function(formData, extraArgs, cb) { self.viewControllers.footerView.setFocus(false); - self.displayHelp(); + return self.displayHelp(cb); } }; diff --git a/core/menu_module.js b/core/menu_module.js index 3cda8ce6..5eb7c913 100644 --- a/core/menu_module.js +++ b/core/menu_module.js @@ -125,17 +125,21 @@ function MenuModule(options) { } else { callback(null); } + }, + function finishAndNext(callback) { + self.finishedLoading(); + + self.autoNextMenu(callback); } ], function complete(err) { if(err) { console.log(err) // :TODO: what to do exactly????? - return self.prevMenu(); + return self.prevMenu( () => { + // dummy + }); } - - self.finishedLoading(); - self.autoNextMenu(); } ); }; @@ -148,16 +152,16 @@ function MenuModule(options) { return _.isNumber(self.menuConfig.options.nextTimeout); }; - this.autoNextMenu = function() { + this.autoNextMenu = function(cb) { function goNext() { if(_.isString(self.menuConfig.next) || _.isArray(self.menuConfig.next)) { - menuUtil.handleNext(self.client, self.menuConfig.next); + return menuUtil.handleNext(self.client, self.menuConfig.next, {}, cb); } else { - self.prevMenu(); + return self.prevMenu(cb); } } - if(_.has(self.menuConfig, 'runtime.autoNext') && true === self.menuConfig.runtime.autoNext) { + if(_.has(self.menuConfig, 'runtime.autoNext') && true === self.menuConfig.runtime.autoNext) { /* If 'next' is supplied, we'll use it. Otherwise, utlize fallback which may be explicit (supplied) or non-explicit (previous menu) @@ -175,8 +179,8 @@ function MenuModule(options) { } */ if(self.hasNextTimeout()) { - setTimeout(function nextTimeout() { - goNext(); + setTimeout( () => { + return goNext(); }, this.menuConfig.options.nextTimeout); } else { goNext(); @@ -208,7 +212,7 @@ MenuModule.prototype.getSaveState = function() { // nothing in base }; -MenuModule.prototype.restoreSavedState = function(savedState) { +MenuModule.prototype.restoreSavedState = function(/*savedState*/) { // nothing in base }; @@ -217,20 +221,9 @@ MenuModule.prototype.nextMenu = function(cb) { // If we don't actually have |next|, we'll go previous // if(!this.haveNext()) { - this.prevMenu(cb); - return; - } - - // :TODO: this, prevMenu(), and gotoMenu() need a default |cb| handler if none is supplied. - // ...if the error is that we do not meet ACS requirements and did not get a match, then what? - if(!cb) { - cb = function(err) { - if(err) { - // :TODO: Don't console.log() here! - console.log(err) - } - } + return this.prevMenu(cb); } + this.client.menuStack.next(cb); }; diff --git a/core/menu_util.js b/core/menu_util.js index eaa20e52..76068d04 100644 --- a/core/menu_util.js +++ b/core/menu_util.js @@ -171,10 +171,6 @@ function handleAction(client, formData, conf, cb) { assert(_.isObject(conf)); assert(_.isString(conf.action)); - cb = function() { - // nothing -- remove me! - }; - const actionAsset = asset.parseAsset(conf.action); assert(_.isObject(actionAsset)); diff --git a/core/system_menu_method.js b/core/system_menu_method.js index fe16c2b9..95a47a96 100644 --- a/core/system_menu_method.js +++ b/core/system_menu_method.js @@ -20,26 +20,25 @@ exports.nextConf = nextConf; exports.prevArea = prevArea; exports.nextArea = nextArea; -function login(callingMenu, formData) { +function login(callingMenu, formData, extraArgs, cb) { userLogin(callingMenu.client, formData.value.username, formData.value.password, err => { if(err) { // login failure if(err.existingConn && _.has(callingMenu, 'menuConfig.config.tooNodeMenu')) { - callingMenu.gotoMenu(callingMenu.menuConfig.config.tooNodeMenu); + return callingMenu.gotoMenu(callingMenu.menuConfig.config.tooNodeMenu, cb); } else { // Other error - callingMenu.prevMenu(); + return callingMenu.prevMenu(cb); } - - } else { - // success! - callingMenu.nextMenu(); } + + // success! + return callingMenu.nextMenu(cb); }); } -function logoff(callingMenu) { +function logoff(callingMenu, formData, extraArgs, cb) { // // Simple logoff. Note that recording of @ logoff properties/stats // occurs elsewhere! @@ -56,49 +55,52 @@ function logoff(callingMenu) { 'NO CARRIER', null, () => { // after data is written, disconnect & remove the client - return removeClient(client); + removeClient(client); + return cb(null); } ); }, 500); } -function prevMenu(callingMenu) { +function prevMenu(callingMenu, formData, extraArgs, cb) { callingMenu.prevMenu( err => { if(err) { - callingMenu.client.log.error( { error : err.toString() }, 'Error attempting to fallback!'); + callingMenu.client.log.error( { error : err.toString() }, 'Error attempting to fallback!'); } + return cb(err); }); } -function nextMenu(callingMenu) { +function nextMenu(callingMenu, formData, extraArgs, cb) { callingMenu.nextMenu( err => { if(err) { callingMenu.client.log.error( { error : err.toString() }, 'Error attempting to go to next menu!'); } + return cb(err); }); } // :TODO: prev/nextConf, prev/nextArea should use a NYI MenuModule.redraw() or such -- avoid pop/goto() hack! -function reloadMenu(menu) { +function reloadMenu(menu, cb) { const prevMenu = menu.client.menuStack.pop(); prevMenu.instance.leave(); - menu.client.menuStack.goto(prevMenu.name); + menu.client.menuStack.goto(prevMenu.name, cb); } -function prevConf(callingMenu) { +function prevConf(callingMenu, formData, extraArgs, cb) { const confs = messageArea.getSortedAvailMessageConferences(callingMenu.client); const currIndex = confs.findIndex( e => e.confTag === callingMenu.client.user.properties.message_conf_tag) || confs.length; messageArea.changeMessageConference(callingMenu.client, confs[currIndex - 1].confTag, err => { if(err) { - return; // logged within changeMessageConference() + return cb(err); // logged within changeMessageConference() } - reloadMenu(callingMenu); + return reloadMenu(callingMenu, cb); }); } -function nextConf(callingMenu) { +function nextConf(callingMenu, formData, extraArgs, cb) { const confs = messageArea.getSortedAvailMessageConferences(callingMenu.client); let currIndex = confs.findIndex( e => e.confTag === callingMenu.client.user.properties.message_conf_tag); @@ -108,27 +110,27 @@ function nextConf(callingMenu) { messageArea.changeMessageConference(callingMenu.client, confs[currIndex + 1].confTag, err => { if(err) { - return; // logged within changeMessageConference() + return cb(err); // logged within changeMessageConference() } - reloadMenu(callingMenu); + return reloadMenu(callingMenu, cb); }); } -function prevArea(callingMenu) { +function prevArea(callingMenu, formData, extraArgs, cb) { const areas = messageArea.getSortedAvailMessageAreasByConfTag(callingMenu.client.user.properties.message_conf_tag); const currIndex = areas.findIndex( e => e.areaTag === callingMenu.client.user.properties.message_area_tag) || areas.length; messageArea.changeMessageArea(callingMenu.client, areas[currIndex - 1].areaTag, err => { if(err) { - return; // logged within changeMessageArea() + return cb(err); // logged within changeMessageArea() } - reloadMenu(callingMenu); + return reloadMenu(callingMenu, cb); }); } -function nextArea(callingMenu) { +function nextArea(callingMenu, formData, extraArgs, cb) { const areas = messageArea.getSortedAvailMessageAreasByConfTag(callingMenu.client.user.properties.message_conf_tag); let currIndex = areas.findIndex( e => e.areaTag === callingMenu.client.user.properties.message_area_tag); @@ -138,9 +140,9 @@ function nextArea(callingMenu) { messageArea.changeMessageArea(callingMenu.client, areas[currIndex + 1].areaTag, err => { if(err) { - return; // logged within changeMessageArea() + return cb(err); // logged within changeMessageArea() } - reloadMenu(callingMenu); + return reloadMenu(callingMenu, cb); }); } diff --git a/core/user_config.js b/core/user_config.js index 66eaa2e9..901ec80f 100644 --- a/core/user_config.js +++ b/core/user_config.js @@ -106,10 +106,13 @@ function UserConfigModule(options) { cb(newFocusId); }, - saveChanges : function(formData, extraArgs) { + // + // Handlers + // + saveChanges : function(formData, extraArgs, cb) { assert(formData.value.password === formData.value.passwordConfirm); - var newProperties = { + const newProperties = { real_name : formData.value.realName, birthdate : new Date(Date.parse(formData.value.birthdate)).toISOString(), sex : formData.value.sex, @@ -122,33 +125,31 @@ function UserConfigModule(options) { }; // runtime set theme - theme.setClientTheme(self.client, newProperties.theme_id); + theme.setClientTheme(self.client, newProperties.theme_id); // persist all changes - self.client.user.persistProperties(newProperties, function persisted(err) { + self.client.user.persistProperties(newProperties, err => { if(err) { self.client.log.warn( { error : err.toString() }, 'Failed persisting updated properties'); // :TODO: warn end user! - self.prevMenu(); + return self.prevMenu(cb); + } + // + // New password if it's not empty + // + self.client.log.info('User updated properties'); + + if(formData.value.password.length > 0) { + self.client.user.setNewAuthCredentials(formData.value.password, err => { + if(err) { + self.client.log.error( { err : err }, 'Failed storing new authentication credentials'); + } else { + self.client.log.info('User changed authentication credentials'); + } + return self.prevMenu(cb); + }); } else { - // - // New password if it's not empty - // - self.client.log.info('User updated properties'); - - if(formData.value.password.length > 0) { - self.client.user.setNewAuthCredentials(formData.value.password, function newAuthStored(err) { - if(err) { - // :TODO: warn the end user! - self.client.log.warn( { error : err.toString() }, 'Failed storing new authentication credentials'); - } else { - self.client.log.info('User changed authentication credentials'); - } - self.prevMenu(); - }); - } else { - self.prevMenu(); - } + return self.prevMenu(cb); } }); }, diff --git a/core/view_controller.js b/core/view_controller.js index b4c7f279..3e968563 100644 --- a/core/view_controller.js +++ b/core/view_controller.js @@ -4,11 +4,10 @@ // ENiGMA½ var MCIViewFactory = require('./mci_view_factory.js').MCIViewFactory; var menuUtil = require('./menu_util.js'); -//var Log = require('./logger.js').log; -var Config = require('./config.js').config; var asset = require('./asset.js'); var ansi = require('./ansi_term.js'); +// deps var events = require('events'); var util = require('util'); var assert = require('assert'); @@ -37,6 +36,26 @@ function ViewController(options) { this.actionKeyMap = {}; + // + // Small wrapper/proxy around handleAction() to ensure we do not allow + // input/additional actions queued while performing an action + // + this.handleActionWrapper = function(formData, actionBlock) { + if(self.waitActionCompletion) { + return; // ignore until this is finished! + } + + self.waitActionCompletion = true; + menuUtil.handleAction(self.client, formData, actionBlock, (err) => { + if(err) { + // :TODO: What can we really do here? + self.client.log.warn( { err : err }, 'Error during handleAction()'); + } + + self.waitActionCompletion = false; + }); + }; + this.clientKeyPressHandler = function(ch, key) { // // Process key presses treating form submit mapped keys special. @@ -51,10 +70,9 @@ function ViewController(options) { self.switchFocus(actionForKey.viewId); self.submitForm(key); } else if(_.isString(actionForKey.action)) { - menuUtil.handleAction( - self.client, - { ch : ch, key : key }, // formData - actionForKey); // action block + self.handleActionWrapper( + { ch : ch, key : key }, // formData + actionForKey); // actionBlock } } else { if(self.focusedView && self.focusedView.acceptsInput) { @@ -65,28 +83,28 @@ function ViewController(options) { this.viewActionListener = function(action, key) { switch(action) { - case 'next' : - self.emit('action', { view : this, action : action, key : key }); - self.nextFocus(); - break; + case 'next' : + self.emit('action', { view : this, action : action, key : key }); + self.nextFocus(); + break; - case 'accept' : - if(self.focusedView && self.focusedView.submit) { - // :TODO: need to do validation here!!! - var focusedView = self.focusedView; - self.validateView(focusedView, function validated(err, newFocusedViewId) { - if(err) { - var newFocusedView = self.getView(newFocusedViewId) || focusedView; - self.setViewFocusWithEvents(newFocusedView, true); - } else { - self.submitForm(key); - } - }); - //self.submitForm(key); - } else { - self.nextFocus(); - } - break; + case 'accept' : + if(self.focusedView && self.focusedView.submit) { + // :TODO: need to do validation here!!! + var focusedView = self.focusedView; + self.validateView(focusedView, function validated(err, newFocusedViewId) { + if(err) { + var newFocusedView = self.getView(newFocusedViewId) || focusedView; + self.setViewFocusWithEvents(newFocusedView, true); + } else { + self.submitForm(key); + } + }); + //self.submitForm(key); + } else { + self.nextFocus(); + } + break; } }; @@ -159,48 +177,48 @@ function ViewController(options) { propAsset = asset.getViewPropertyAsset(conf[propName]); if(propAsset) { switch(propAsset.type) { - case 'config' : - propValue = asset.resolveConfigAsset(conf[propName]); - break; + case 'config' : + propValue = asset.resolveConfigAsset(conf[propName]); + break; - // :TODO: handle @art (e.g. text : @art ...) + // :TODO: handle @art (e.g. text : @art ...) - case 'method' : - case 'systemMethod' : - if('validate' === propName) { - // :TODO: handle propAsset.location for @method script specification - if('systemMethod' === propAsset.type) { - // :TODO: implementation validation @systemMethod handling! - var methodModule = require(paths.join(__dirname, 'system_view_validate.js')); - if(_.isFunction(methodModule[propAsset.asset])) { - propValue = methodModule[propAsset.asset]; - } - } else { - if(_.isFunction(self.client.currentMenuModule.menuMethods[propAsset.asset])) { - propValue = self.client.currentMenuModule.menuMethods[propAsset.asset]; - } + case 'method' : + case 'systemMethod' : + if('validate' === propName) { + // :TODO: handle propAsset.location for @method script specification + if('systemMethod' === propAsset.type) { + // :TODO: implementation validation @systemMethod handling! + var methodModule = require(paths.join(__dirname, 'system_view_validate.js')); + if(_.isFunction(methodModule[propAsset.asset])) { + propValue = methodModule[propAsset.asset]; } } else { - if(_.isString(propAsset.location)) { + if(_.isFunction(self.client.currentMenuModule.menuMethods[propAsset.asset])) { + propValue = self.client.currentMenuModule.menuMethods[propAsset.asset]; + } + } + } else { + if(_.isString(propAsset.location)) { + } else { + if('systemMethod' === propAsset.type) { + // :TODO: } else { - if('systemMethod' === propAsset.type) { - // :TODO: - } else { - // local to current module - var currentModule = self.client.currentMenuModule; - if(_.isFunction(currentModule.menuMethods[propAsset.asset])) { - // :TODO: Fix formData & extraArgs... this all needs general processing - propValue = currentModule.menuMethods[propAsset.asset]({}, {});//formData, conf.extraArgs); - } + // local to current module + var currentModule = self.client.currentMenuModule; + if(_.isFunction(currentModule.menuMethods[propAsset.asset])) { + // :TODO: Fix formData & extraArgs... this all needs general processing + propValue = currentModule.menuMethods[propAsset.asset]({}, {});//formData, conf.extraArgs); } } } - break; + } + break; - default : - propValue = propValue = conf[propName]; - break; + default : + propValue = propValue = conf[propName]; + break; } } else { propValue = conf[propName]; @@ -287,6 +305,13 @@ function ViewController(options) { return false; } } else { + /* + :TODO: support: + value: { + someArgName: [ "key1", "key2", ... ], + someOtherArg: [ "key1, ... ] + } + */ var actionValueKeys = Object.keys(actionValue); for(var i = 0; i < actionValueKeys.length; ++i) { var viewId = actionValueKeys[i]; @@ -510,11 +535,12 @@ ViewController.prototype.loadFromPromptConfig = function(options, cb) { }, function prepareFormSubmission(callback) { if(false === self.noInput) { + self.on('submit', function promptSubmit(formData) { self.client.log.trace( { formData : self.getLogFriendlyFormData(formData) }, 'Prompt submit'); if(_.isString(self.client.currentMenuModule.menuConfig.action)) { - menuUtil.handleAction(self.client, formData, self.client.currentMenuModule.menuConfig); + self.handleActionWrapper(formData, self.client.currentMenuModule.menuConfig); } else { // // Menus that reference prompts can have a sepcial "submit" block without the @@ -538,7 +564,7 @@ ViewController.prototype.loadFromPromptConfig = function(options, cb) { var actionBlock = menuSubmit[c]; if(_.isEqual(formData.value, actionBlock.value, self.actionBlockValueComparator)) { - menuUtil.handleAction(self.client, formData, actionBlock); + self.handleActionWrapper(formData, actionBlock); break; // there an only be one... } } @@ -666,7 +692,7 @@ ViewController.prototype.loadFromMenuConfig = function(options, cb) { var actionBlock = confForFormId[c]; if(_.isEqual(formData.value, actionBlock.value, self.actionBlockValueComparator)) { - menuUtil.handleAction(self.client, formData, actionBlock); + self.handleActionWrapper(formData, actionBlock); break; // there an only be one... } } diff --git a/mods/bbs_list.js b/mods/bbs_list.js index cae05e3e..f941dd8f 100644 --- a/mods/bbs_list.js +++ b/mods/bbs_list.js @@ -325,23 +325,20 @@ function BBSListModule(options) { // // Key & submit handlers // - quitBBSList : function() { - self.prevMenu(); + addBBS : function(formData, extraArgs, cb) { + self.displayAddScreen(cb); }, - addBBS : function() { - self.displayAddScreen(); - }, - deleteBBS : function() { + deleteBBS : function(formData, extraArgs, cb) { const entriesView = self.viewControllers.view.getView(MciViewIds.view.BBSList); if(self.entries[self.selectedBBS].submitterUserId !== self.client.user.userId && !self.client.user.isSysOp()) { // must be owner or +op - return; + return cb(null); } const entry = self.entries[self.selectedBBS]; if(!entry) { - return; + return cb(null); } self.database.run( @@ -362,10 +359,12 @@ function BBSListModule(options) { self.viewControllers.view.redrawAll(); } + + return cb(null); } ); }, - submitBBS : function(formData) { + submitBBS : function(formData, extraArgs, cb) { let ok = true; [ 'BBSName', 'Sysop', 'Telnet' ].forEach( mciName => { @@ -375,7 +374,7 @@ function BBSListModule(options) { }); if(!ok) { // validators should prevent this! - return; + return cb(null); } self.database.run( @@ -388,13 +387,13 @@ function BBSListModule(options) { } self.clearAddForm(); - self.displayBBSList(true); + self.displayBBSList(true, cb); } ); }, - cancelSubmit : function() { + cancelSubmit : function(formData, extraArgs, cb) { self.clearAddForm(); - self.displayBBSList(true); + self.displayBBSList(true, cb); } }; diff --git a/mods/erc_client.js b/mods/erc_client.js index cb30f2d0..803d1f2c 100644 --- a/mods/erc_client.js +++ b/mods/erc_client.js @@ -143,7 +143,7 @@ function ErcClientModule(options) { this.menuMethods = { - inputAreaSubmit : function() { + inputAreaSubmit : function(formData, extraArgs, cb) { const inputAreaView = self.viewControllers.menu.getView(MciViewIds.InputArea); const inputData = inputAreaView.getData(); @@ -157,12 +157,15 @@ function ErcClientModule(options) { } inputAreaView.clearText(); } + return cb(null); }, - scrollUp : function(formData) { + scrollUp : function(formData, extraArgs, cb) { self.scrollHandler(formData.key.name); + return cb(null); }, - scrollDown : function(formData) { - self.scrollHandler(formData.key.name); + scrollDown : function(formData, extraArgs, cb) { + self.scrollHandler(formData.key.name); + return cb(null); } }; } diff --git a/mods/menu.hjson b/mods/menu.hjson index d65ba572..2bcea104 100644 --- a/mods/menu.hjson +++ b/mods/menu.hjson @@ -1198,7 +1198,7 @@ } { keys: [ "q", "escape" ] - action: @method:quitBBSList + action: @systemMethod:prevMenu } ] } diff --git a/mods/msg_area_list.js b/mods/msg_area_list.js index a984e9ff..82bb5ece 100644 --- a/mods/msg_area_list.js +++ b/mods/msg_area_list.js @@ -1,14 +1,14 @@ /* jslint node: true */ 'use strict'; -var MenuModule = require('../core/menu_module.js').MenuModule; -var ViewController = require('../core/view_controller.js').ViewController; -var messageArea = require('../core/message_area.js'); -var strUtil = require('../core/string_util.js'); +// ENiGMA½ +const MenuModule = require('../core/menu_module.js').MenuModule; +const ViewController = require('../core/view_controller.js').ViewController; +const messageArea = require('../core/message_area.js'); -var async = require('async'); -var assert = require('assert'); -var _ = require('lodash'); +// deps +const async = require('async'); +const _ = require('lodash'); exports.getModule = MessageAreaListModule; @@ -32,9 +32,8 @@ exports.moduleInfo = { |TI Current time */ -var MciCodesIds = { +const MCICodesIDs = { AreaList : 1, - CurrentArea : 2, }; function MessageAreaListModule(options) { @@ -42,27 +41,29 @@ function MessageAreaListModule(options) { var self = this; - this.messageAreas = messageArea.getSortedAvailMessageAreasByConfTag( + this.messageAreas = messageArea.getSortedAvailMessageAreasByConfTag( self.client.user.properties.message_conf_tag, { client : self.client } ); this.menuMethods = { - changeArea : function(formData, extraArgs) { + changeArea : function(formData, extraArgs, cb) { if(1 === formData.submitId) { const areaTag = self.messageAreas[formData.value.area].areaTag; - messageArea.changeMessageArea(self.client, areaTag, function areaChanged(err) { - if(err) { - self.client.term.pipeWrite('\n|00Cannot change area: ' + err.message + '\n'); + messageArea.changeMessageArea(self.client, areaTag, err => { + if(err) { + self.client.term.pipeWrite(`\n|00Cannot change area: ${err.message}\n`); - setTimeout(function timeout() { - self.prevMenu(); - }, 1000); - } else { - self.prevMenu(); - } - }); + setTimeout( () => { + return self.prevMenu(cb); + }, 1000); + } else { + return self.prevMenu(cb); + } + }); + } else { + return cb(null); } } }; @@ -79,7 +80,7 @@ function MessageAreaListModule(options) { require('util').inherits(MessageAreaListModule, MenuModule); MessageAreaListModule.prototype.mciReady = function(mciData, cb) { - var self = this; + const self = this; const vc = self.viewControllers.areaList = new ViewController( { client : self.client } ); async.series( @@ -90,7 +91,7 @@ MessageAreaListModule.prototype.mciReady = function(mciData, cb) { }); }, function loadFromConfig(callback) { - var loadOpts = { + const loadOpts = { callingMenu : self, mciMap : mciData.menu, formId : 0, @@ -104,40 +105,34 @@ MessageAreaListModule.prototype.mciReady = function(mciData, cb) { const listFormat = self.menuConfig.config.listFormat || '{index} ) - {name}'; const focusListFormat = self.menuConfig.config.focusListFormat || listFormat; - const areaListView = vc.getView(1); - let i = 1; - areaListView.setItems(_.map(self.messageAreas, v => { - return listFormat.format({ - index : i++, - areaTag : v.area.areaTag, - name : v.area.name, - desc : v.area.desc, - }); - })); - - i = 1; - areaListView.setFocusItems(_.map(self.messageAreas, v => { - return focusListFormat.format({ - index : i++, - areaTag : v.area.areaTag, - name : v.area.name, - desc : v.area.desc, - }) - })); + const areaListView = vc.getView(MCICodesIDs.AreaList); + let i = 1; + areaListView.setItems(_.map(self.messageAreas, v => { + return listFormat.format({ + index : i++, + areaTag : v.area.areaTag, + name : v.area.name, + desc : v.area.desc, + }); + })); + + i = 1; + areaListView.setFocusItems(_.map(self.messageAreas, v => { + return focusListFormat.format({ + index : i++, + areaTag : v.area.areaTag, + name : v.area.name, + desc : v.area.desc, + }); + })); areaListView.redraw(); - callback(null); - }, - function populateTextViews(callback) { - // :TODO: populate current message area desc! - //self.setViewText(MciCodesIds.CurrentArea, - callback(null); } ], function complete(err) { - cb(null); + return cb(err); } ); }; \ No newline at end of file diff --git a/mods/msg_area_post_fse.js b/mods/msg_area_post_fse.js index 292c0eec..f8ee7742 100644 --- a/mods/msg_area_post_fse.js +++ b/mods/msg_area_post_fse.js @@ -25,7 +25,7 @@ function AreaPostFSEModule(options) { // we're posting, so always start with 'edit' mode this.editorMode = 'edit'; - this.menuMethods.editModeMenuSave = function() { + this.menuMethods.editModeMenuSave = function(formData, extraArgs, cb) { var msg; async.series( @@ -33,16 +33,11 @@ function AreaPostFSEModule(options) { function getMessageObject(callback) { self.getMessage(function gotMsg(err, msgObj) { msg = msgObj; - callback(err); + return callback(err); }); }, function saveMessage(callback) { - persistMessage(msg, callback); - /* - msg.persist(function persisted(err) { - callback(err); - }); - */ + return persistMessage(msg, callback); } ], function complete(err) { @@ -56,7 +51,7 @@ function AreaPostFSEModule(options) { ); } - self.nextMenu(); + return self.nextMenu(cb); } ); }; diff --git a/mods/msg_area_view_fse.js b/mods/msg_area_view_fse.js index 09d823ed..38b806e0 100644 --- a/mods/msg_area_view_fse.js +++ b/mods/msg_area_view_fse.js @@ -1,14 +1,12 @@ /* jslint node: true */ 'use strict'; -var FullScreenEditorModule = require('../core/fse.js').FullScreenEditorModule; -var Message = require('../core/message.js'); -var messageArea = require('../core/message_area.js'); -var user = require('../core/user.js'); +// ENiGMA½ +const FullScreenEditorModule = require('../core/fse.js').FullScreenEditorModule; +const Message = require('../core/message.js'); -var _ = require('lodash'); -var async = require('async'); -var assert = require('assert'); +// deps +const _ = require('lodash'); exports.getModule = AreaViewFSEModule; @@ -21,8 +19,7 @@ exports.moduleInfo = { function AreaViewFSEModule(options) { FullScreenEditorModule.call(this, options); - var self = this; - var config = this.menuConfig.config; + const self = this; this.editorType = 'area'; this.editorMode = 'view'; @@ -36,57 +33,67 @@ function AreaViewFSEModule(options) { this.messageIndex = this.messageIndex || 0; this.messageTotal = this.messageList.length; - this.menuMethods.nextMessage = function(formData, extraArgs) { + this.menuMethods.nextMessage = function(formData, extraArgs, cb) { if(self.messageIndex + 1 < self.messageList.length) { self.messageIndex++; - self.loadMessageByUuid(self.messageList[self.messageIndex].messageUuid); + return self.loadMessageByUuid(self.messageList[self.messageIndex].messageUuid, cb); } + + return cb(null); }; - this.menuMethods.prevMessage = function(formData, extraArgs) { + this.menuMethods.prevMessage = function(formData, extraArgs, cb) { if(self.messageIndex > 0) { self.messageIndex--; - self.loadMessageByUuid(self.messageList[self.messageIndex].messageUuid); + return self.loadMessageByUuid(self.messageList[self.messageIndex].messageUuid, cb); } + + return cb(null); }; - this.menuMethods.movementKeyPressed = function(formData, extraArgs) { - var bodyView = self.viewControllers.body.getView(1); + this.menuMethods.movementKeyPressed = function(formData, extraArgs, cb) { + const bodyView = self.viewControllers.body.getView(1); // :TODO: use const here vs magic # // :TODO: Create methods for up/down vs using keyPressXXXXX switch(formData.key.name) { - case 'down arrow' : bodyView.scrollDocumentUp(); break; - case 'up arrow' : bodyView.scrollDocumentDown(); break; - case 'page up' : bodyView.keyPressPageUp(); break; - case 'page down' : bodyView.keyPressPageDown(); break; + case 'down arrow' : bodyView.scrollDocumentUp(); break; + case 'up arrow' : bodyView.scrollDocumentDown(); break; + case 'page up' : bodyView.keyPressPageUp(); break; + case 'page down' : bodyView.keyPressPageDown(); break; } // :TODO: need to stop down/page down if doing so would push the last - // visible page off the screen at all + // visible page off the screen at all .... this should be handled by MLTEV though... + + return cb(null); }; - this.menuMethods.replyMessage = function(formData, extraArgs) { + this.menuMethods.replyMessage = function(formData, extraArgs, cb) { if(_.isString(extraArgs.menu)) { - var modOpts = { + const modOpts = { extraArgs : { messageAreaTag : self.messageAreaTag, replyToMessage : self.message, } }; - self.gotoMenu(extraArgs.menu, modOpts); - } else { - self.client.log(extraArgs, 'Missing extraArgs.menu'); + return self.gotoMenu(extraArgs.menu, modOpts, cb); } + + self.client.log(extraArgs, 'Missing extraArgs.menu'); + return cb(null); }; - this.loadMessageByUuid = function(uuid) { - var msg = new Message(); - msg.load( { uuid : uuid, user : self.client.user }, function loaded(err) { + this.loadMessageByUuid = function(uuid, cb) { + const msg = new Message(); + msg.load( { uuid : uuid, user : self.client.user }, () => { self.setMessage(msg); + if(cb) { + return cb(null); + } }); }; } @@ -106,7 +113,7 @@ AreaViewFSEModule.prototype.getSaveState = function() { messageList : this.messageList, messageIndex : this.messageIndex, messageTotal : this.messageList.length, - } + }; }; AreaViewFSEModule.prototype.restoreSavedState = function(savedState) { diff --git a/mods/msg_conf_list.js b/mods/msg_conf_list.js index 308785d5..6629fc26 100644 --- a/mods/msg_conf_list.js +++ b/mods/msg_conf_list.js @@ -1,13 +1,14 @@ /* jslint node: true */ 'use strict'; -var MenuModule = require('../core/menu_module.js').MenuModule; -var ViewController = require('../core/view_controller.js').ViewController; -var messageArea = require('../core/message_area.js'); +// ENiGMA½ +const MenuModule = require('../core/menu_module.js').MenuModule; +const ViewController = require('../core/view_controller.js').ViewController; +const messageArea = require('../core/message_area.js'); -var async = require('async'); -var assert = require('assert'); -var _ = require('lodash'); +// deps +const async = require('async'); +const _ = require('lodash'); exports.getModule = MessageConfListModule; @@ -17,12 +18,11 @@ exports.moduleInfo = { author : 'NuSkooler', }; -var MciCodesIds = { +const MCICodeIDs = { ConfList : 1, - CurrentConf : 2, // :TODO: - // # areas in con + // # areas in conf .... see Obv/2, iNiQ, ... // }; @@ -34,7 +34,7 @@ function MessageConfListModule(options) { this.messageConfs = messageArea.getSortedAvailMessageConferences(self.client); this.menuMethods = { - changeConference : function(formData, extraArgs) { + changeConference : function(formData, extraArgs, cb) { if(1 === formData.submitId) { const confTag = self.messageConfs[formData.value.conf].confTag; @@ -42,13 +42,15 @@ function MessageConfListModule(options) { if(err) { self.client.term.pipeWrite(`\n|00Cannot change conference: ${err.message}\n`); - setTimeout(function timeout() { - self.prevMenu(); - }, 1000); + setTimeout( () => { + return self.prevMenu(cb); + }, 1000); } else { - self.prevMenu(); + return self.prevMenu(cb); } }); + } else { + return cb(null); } } }; @@ -85,26 +87,26 @@ MessageConfListModule.prototype.mciReady = function(mciData, cb) { const listFormat = self.menuConfig.config.listFormat || '{index} ) - {name}'; const focusListFormat = self.menuConfig.config.focusListFormat || listFormat; - const confListView = vc.getView(1); - let i = 1; - confListView.setItems(_.map(self.messageConfs, v => { - return listFormat.format({ - index : i++, - confTag : v.conf.confTag, - name : v.conf.name, - desc : v.conf.desc, - }); - })); - - i = 1; - confListView.setFocusItems(_.map(self.messageConfs, v => { - return focusListFormat.format({ - index : i++, - confTag : v.conf.confTag, - name : v.conf.name, - desc : v.conf.desc, - }) - })); + const confListView = vc.getView(MCICodeIDs.ConfList); + let i = 1; + confListView.setItems(_.map(self.messageConfs, v => { + return listFormat.format({ + index : i++, + confTag : v.conf.confTag, + name : v.conf.name, + desc : v.conf.desc, + }); + })); + + i = 1; + confListView.setFocusItems(_.map(self.messageConfs, v => { + return focusListFormat.format({ + index : i++, + confTag : v.conf.confTag, + name : v.conf.name, + desc : v.conf.desc, + }); + })); confListView.redraw(); diff --git a/mods/msg_list.js b/mods/msg_list.js index cdb571f0..a8804f27 100644 --- a/mods/msg_list.js +++ b/mods/msg_list.js @@ -70,7 +70,7 @@ function MessageListModule(options) { } this.menuMethods = { - selectMessage : function(formData) { + selectMessage : function(formData, extraArgs, cb) { if(1 === formData.submitId) { self.initialFocusIndex = formData.value.message; @@ -99,7 +99,9 @@ function MessageListModule(options) { }; }; - self.gotoMenu(config.menuViewPost || 'messageAreaViewPost', modOpts); + return self.gotoMenu(config.menuViewPost || 'messageAreaViewPost', modOpts, cb); + } else { + return cb(null); } } }; diff --git a/mods/nua.js b/mods/nua.js index a7e1a3a2..14ef4803 100644 --- a/mods/nua.js +++ b/mods/nua.js @@ -1,13 +1,13 @@ /* jslint node: true */ 'use strict'; -var MenuModule = require('../core/menu_module.js').MenuModule; -var user = require('../core/user.js'); -var theme = require('../core/theme.js'); -var login = require('../core/system_menu_method.js').login; -var Config = require('../core/config.js').config; -var messageArea = require('../core/message_area.js'); -var async = require('async'); +// ENiGMA½ +const MenuModule = require('../core/menu_module.js').MenuModule; +const user = require('../core/user.js'); +const theme = require('../core/theme.js'); +const login = require('../core/system_menu_method.js').login; +const Config = require('../core/config.js').config; +const messageArea = require('../core/message_area.js'); exports.getModule = NewUserAppModule; @@ -16,7 +16,7 @@ exports.moduleInfo = { desc : 'New User Application', }; -var MciViewIds = { +const MciViewIds = { userName : 1, password : 9, confirm : 10, @@ -26,54 +26,54 @@ var MciViewIds = { function NewUserAppModule(options) { MenuModule.call(this, options); - var self = this; + const self = this; this.menuMethods = { // // Validation stuff // validatePassConfirmMatch : function(data, cb) { - var passwordView = self.viewControllers.menu.getView(MciViewIds.password); - cb(passwordView.getData() === data ? null : new Error('Passwords do not match')); + const passwordView = self.viewControllers.menu.getView(MciViewIds.password); + return cb(passwordView.getData() === data ? null : new Error('Passwords do not match')); }, viewValidationListener : function(err, cb) { - var errMsgView = self.viewControllers.menu.getView(MciViewIds.errMsg); - var newFocusId; + const errMsgView = self.viewControllers.menu.getView(MciViewIds.errMsg); + let newFocusId; + if(err) { errMsgView.setText(err.message); err.view.clearText(); if(err.view.getId() === MciViewIds.confirm) { newFocusId = MciViewIds.password; - var passwordView = self.viewControllers.menu.getView(MciViewIds.password); - passwordView.clearText(); + self.viewControllers.menu.getView(MciViewIds.password).clearText(); } } else { errMsgView.clearText(); } - cb(newFocusId); + return cb(newFocusId); }, // // Submit handlers // - submitApplication : function(formData, extraArgs) { - var newUser = new user.User(); + submitApplication : function(formData, extraArgs, cb) { + const newUser = new user.User(); newUser.username = formData.value.username; // // We have to disable ACS checks for initial default areas as the user is not yet ready // - var confTag = messageArea.getDefaultMessageConferenceTag(self.client, true); // true=disableAcsCheck - var areaTag = messageArea.getDefaultMessageAreaTagByConfTag(self.client, confTag, true); // true=disableAcsCheck - - // can't store undefined! - confTag = confTag || ''; - areaTag = areaTag || ''; + let confTag = messageArea.getDefaultMessageConferenceTag(self.client, true); // true=disableAcsCheck + let areaTag = messageArea.getDefaultMessageAreaTagByConfTag(self.client, confTag, true); // true=disableAcsCheck + + // can't store undefined! + confTag = confTag || ''; + areaTag = areaTag || ''; newUser.properties = { real_name : formData.value.realName, @@ -102,14 +102,15 @@ function NewUserAppModule(options) { } // :TODO: User.create() should validate email uniqueness! - newUser.create( { password : formData.value.password }, function created(err) { + newUser.create( { password : formData.value.password }, err => { if(err) { self.client.log.info( { error : err, username : formData.value.username }, 'New user creation failed'); - self.gotoMenu(extraArgs.error, function result(err) { + self.gotoMenu(extraArgs.error, err => { if(err) { - self.prevMenu(); + return self.prevMenu(cb); } + return cb(null); }); } else { self.client.log.info( { username : formData.value.username, userId : newUser.userId }, 'New user created'); @@ -124,12 +125,12 @@ function NewUserAppModule(options) { } if(user.User.AccountStatus.inactive === self.client.user.properties.account_status) { - self.gotoMenu(extraArgs.inactive); + return self.gotoMenu(extraArgs.inactive, cb); } else { // // If active now, we need to call login() to authenticate // - login(self, formData, extraArgs); + return login(self, formData, extraArgs, cb); } } }); diff --git a/mods/onelinerz.js b/mods/onelinerz.js index 6244e968..d3639a47 100644 --- a/mods/onelinerz.js +++ b/mods/onelinerz.js @@ -231,11 +231,11 @@ function OnelinerzModule(options) { }; this.menuMethods = { - viewAddScreen : function() { - self.displayAddScreen(); + viewAddScreen : function(formData, extraArgs, cb) { + return self.displayAddScreen(cb); }, - addEntry : function(formData) { + addEntry : function(formData, extraArgs, cb) { if(_.isString(formData.value.oneliner) && formData.value.oneliner.length > 0) { const oneliner = formData.value.oneliner.trim(); // remove any trailing ws @@ -245,18 +245,18 @@ function OnelinerzModule(options) { } self.clearAddForm(); - self.displayViewScreen(true); // true=cls + return self.displayViewScreen(true, cb); // true=cls }); } else { // empty message - treat as if cancel was hit - self.displayViewScreen(true); // true=cls + return self.displayViewScreen(true, cb); // true=cls } }, - cancelAdd : function() { + cancelAdd : function(formData, extraArgs, cb) { self.clearAddForm(); - self.displayViewScreen(true); // true=cls + return self.displayViewScreen(true, cb); // true=cls } };