+ Start work on MenuView & friends

* connect.js no longer a module. Part of initial connection always
* Cleaner & expandable BBS init
* Better theme handling
This commit is contained in:
Bryan Ashby 2014-10-30 22:59:21 -06:00
parent 14a321de2f
commit c3aa4c44e2
8 changed files with 96 additions and 64 deletions

View File

@ -11,6 +11,7 @@ var database = require('./database.js');
var iconv = require('iconv-lite'); var iconv = require('iconv-lite');
var paths = require('path'); var paths = require('path');
var async = require('async'); var async = require('async');
var util = require('util');
exports.bbsMain = bbsMain; exports.bbsMain = bbsMain;
@ -51,22 +52,15 @@ function bbsMain() {
conf.createDefault(); conf.createDefault();
} }
logger.init(); initialize(function onInit(err) {
if(err) {
process.on('SIGINT', function onSigInt() { console.error('Error initializing: ' + util.inspect(err));
// :TODO: for any client in |clientConnections|, if 'ready', send a "Server Disconnecting" + semi-gracefull hangup return;
// e.g. client.disconnectNow() }
logger.log.info('Process interrupted, shutting down');
process.exit();
});
database.initializeDatabases();
preServingInit();
startListening(); startListening();
}; });
}
function parseArgs() { function parseArgs() {
var args = []; var args = [];
@ -91,6 +85,8 @@ function initialize(cb) {
process.exit(); process.exit();
}); });
iconv.extendNodeEncodings();
callback(null); callback(null);
}, },
function initDatabases(callback) { function initDatabases(callback) {
@ -112,10 +108,6 @@ function initialize(cb) {
); );
} }
function preServingInit() {
iconv.extendNodeEncodings();
}
var clientConnections = []; var clientConnections = [];
function startListening() { function startListening() {
@ -151,14 +143,13 @@ function startListening() {
} }
addNewClient(client); addNewClient(client);
//client.runtime.id = clientConnections.push(client) - 1;
//logger.log.info({ clientId : client.runtime.id, from : client.address(), server : module.moduleInfo.name }, 'Client connected'); //logger.log.info({ clientId : client.runtime.id, from : client.address(), server : module.moduleInfo.name }, 'Client connected');
client.on('ready', function onClientReady() { client.on('ready', function onClientReady() {
// Go to module -- use default error handler // Go to module -- use default error handler
prepareClient(client, function onPrepared() { prepareClient(client, function onPrepared() {
modules.goto(conf.config.entryMod, client); require('./connect.js').connectEntry(client);
}); });
}); });
@ -199,6 +190,7 @@ function removeClient(client) {
} }
function prepareClient(client, cb) { function prepareClient(client, cb) {
// :TODO: it feels like this should go somewhere else... and be a bit more elegant.
if('*' === conf.config.preLoginTheme) { if('*' === conf.config.preLoginTheme) {
var theme = require('./theme.js'); var theme = require('./theme.js');
theme.getRandomTheme(function onRandTheme(err, themeId) { theme.getRandomTheme(function onRandTheme(err, themeId) {

View File

@ -7,7 +7,7 @@ var miscUtil = require('./misc_util.js');
module.exports = { module.exports = {
// :TODO: remove this ... anti-pattern! // :TODO: remove this ... anti-pattern!
config : undefined, //config : undefined,
defaultPath : function() { defaultPath : function() {
var base = miscUtil.resolvePath('~/'); var base = miscUtil.resolvePath('~/');
@ -26,7 +26,7 @@ module.exports = {
bbsName : 'Another Fine ENiGMA½ BBS', bbsName : 'Another Fine ENiGMA½ BBS',
// :TODO: probably replace this with 'firstMenu' or somthing once that's available // :TODO: probably replace this with 'firstMenu' or somthing once that's available
entryMod : 'connect', entryMod : 'matrix',
preLoginTheme : '*', preLoginTheme : '*',

View File

@ -1,21 +1,17 @@
/* jslint node: true */ /* jslint node: true */
'use strict'; 'use strict';
var ansi = require('../core/ansi_term.js'); var ansi = require('./ansi_term.js');
var artwork = require('../core/art.js'); var artwork = require('./art.js');
var modules = require('../core/modules.js'); var modules = require('./modules.js');
var Log = require('../core/logger.js').log; var Log = require('./logger.js').log;
var Config = require('./config.js').config;
var packageJson = require('../package.json'); var packageJson = require('../package.json');
var assert = require('assert');
var util = require('util'); var util = require('util');
exports.moduleInfo = { exports.connectEntry = connectEntry;
name : 'Connect',
desc : 'First module upon connection',
author : 'NuSkooler',
};
exports.entryPoint = entryPoint;
function ansiQueryTermSizeIfNeeded(client) { function ansiQueryTermSizeIfNeeded(client) {
if(client.term.termHeight > 0 || client.term.termWidth > 0) { if(client.term.termHeight > 0 || client.term.termWidth > 0) {
@ -30,10 +26,13 @@ function ansiQueryTermSizeIfNeeded(client) {
return; return;
} }
assert(2 === pos.length);
client.term.termHeight = pos[0]; client.term.termHeight = pos[0];
client.term.termWidth = pos[1]; client.term.termWidth = pos[1];
Log.debug({ termWidth : client.term.termWidth, termHeight : client.term.termHeight, updateSource : 'ANSI CPR' }, 'Window size updated'); Log.debug(
{ termWidth : client.term.termWidth, termHeight : client.term.termHeight, updateSource : 'ANSI CPR' },
'Window size updated');
}; };
client.once('cursor position report', onCPR); client.once('cursor position report', onCPR);
@ -46,7 +45,21 @@ function ansiQueryTermSizeIfNeeded(client) {
client.term.write(ansi.queryScreenSize()); client.term.write(ansi.queryScreenSize());
} }
function entryPoint(client) { function prepareTerminal(term) {
term.write(ansi.normal());
term.write(ansi.disableVT100LineWrapping());
// :TODO: set xterm stuff -- see x84/others
}
function displayBanner(term) {
// :TODO: add URL to banner
term.write(ansi.fromPipeCode(util.format('' +
'|33Conected to |32EN|33|01i|32|22GMA|32|01½|00 |33BBS version|31|01 %s\n' +
'|00|33Copyright (c) 2014 Bryan Ashby\n' +
'|00', packageJson.version)));
}
function connectEntry(client) {
var term = client.term; var term = client.term;
// //
@ -55,24 +68,8 @@ function entryPoint(client) {
// //
ansiQueryTermSizeIfNeeded(client); ansiQueryTermSizeIfNeeded(client);
term.write(ansi.normal()); prepareTerminal(term);
displayBanner(term);
term.write(ansi.disableVT100LineWrapping());
//
// If we don't yet know the client term width/height, try
// a nonstandard ANSI query
//
// :TODO: set xterm stuff -- see x84/others
// :TODO: add URL to banner
term.write(ansi.fromPipeCode(util.format('' +
'|33Conected to |32EN|33|01i|32|22GMA|32|01½|00 |33BBS version|31|01 %s\n' +
'|00|33Copyright (c) 2014 Bryan Ashby\n' +
'|00', packageJson.version)));
setTimeout(function onTimeout() { setTimeout(function onTimeout() {
term.write(ansi.clearScreen()); term.write(ansi.clearScreen());
@ -87,7 +84,7 @@ function entryPoint(client) {
setTimeout(function onTimeout() { setTimeout(function onTimeout() {
term.write(ansi.clearScreen()); term.write(ansi.clearScreen());
modules.goto('matrix', client); modules.goto(Config.entryMod, client);
}, timeout); }, timeout);
}); });
}, 500); }, 500);

31
core/menu_view.js Normal file
View File

@ -0,0 +1,31 @@
/* jslint node: true */
'use strict';
var View = require('./view.js').View;
var ansi = require('./ansi_term.js');
var util = require('util');
var assert = require('assert');
exports.MenuView = MenuView;
function MenuView(client, options) {
View.call(this, client, options);
this.items = [];
if(this.options.items) {
this.options.items.forEach(function onItem(itemText) {
this.items.push({
text : itemText,
focused : false,
selected : false,
});
});
}
this.itemSpacing = this.options.itemSpacing || 1;
this.focusPrefix = this.options.focusPrefix || '';
this.focusSuffix = this.options.focusSuffix || '';
}
util.inherits(MenuView, View);

View File

@ -13,8 +13,6 @@ exports.TextView = TextView;
function TextView(client, options) { function TextView(client, options) {
View.call(this, client, options); View.call(this, client, options);
var self = this;
if(this.options.maxLength) { if(this.options.maxLength) {
this.maxLength = this.options.maxLength; this.maxLength = this.options.maxLength;
} }
@ -31,7 +29,7 @@ function TextView(client, options) {
this.setText(this.options.text || ''); this.setText(this.options.text || '');
this.isPasswordTextStyle = 'P' === self.textStyle || 'password' === self.textStyle; this.isPasswordTextStyle = 'P' === this.textStyle || 'password' === this.textStyle;
if(this.isPasswordTextStyle) { if(this.isPasswordTextStyle) {
this.textMaskChar = miscUtil.valueWithDefault(this.options.textMaskChar, '*').substr(0, 1); this.textMaskChar = miscUtil.valueWithDefault(this.options.textMaskChar, '*').substr(0, 1);

View File

@ -33,7 +33,6 @@ function getThemeInfo(themeID, cb) {
var availableThemes = {}; var availableThemes = {};
function initAvailableThemes(cb) { function initAvailableThemes(cb) {
// lazy init
async.waterfall( async.waterfall(
[ [
function getDir(callback) { function getDir(callback) {
@ -56,9 +55,9 @@ function initAvailableThemes(cb) {
} }
availableThemes[themeId] = info; availableThemes[themeId] = info;
} }
});
});
callback(null); callback(null);
});
});
} }
], ],
function onComplete(err) { function onComplete(err) {

View File

@ -0,0 +1,17 @@
/* jslint node: true */
'use strict';
var MenuView = require('./menu_view.js').MenuView;
var ansi = require('./ansi_term.js');
var util = require('util');
var assert = require('assert');
function VerticalMenuView(client, options) {
MenuView.call(this, client, options);
}
util.inherits(VerticalMenuView, MenuView);
VerticalMenuView.prototype.redraw = function() {
VerticalMenuView.super_.prototype.redraw.call(this);
};

View File

@ -40,8 +40,6 @@ function entryPoint(client) {
return; return;
} }
console.log(mci);
user.authenticate('NuSkooler', 'password', client, function onAuth(isValid) { user.authenticate('NuSkooler', 'password', client, function onAuth(isValid) {
console.log(isValid); console.log(isValid);
}); });