diff --git a/art/themes/luciano_blocktronics/theme.hjson b/art/themes/luciano_blocktronics/theme.hjson index 13830fad..a3fc4f85 100644 --- a/art/themes/luciano_blocktronics/theme.hjson +++ b/art/themes/luciano_blocktronics/theme.hjson @@ -309,9 +309,9 @@ // node status VM1: { height: 5 - width: 36 - itemFormat: "|00 |11{node:<3.2} |10{userName:<13} |02{action:<14.13} |14{serverName}" - focusItemFormat: "|00|15> |11{node:<3.2} |10{userName:<13} |02{action:<14.13} |14{serverName}" + width: 37 + itemFormat: "|00 |11{node:<3.2} |10{userName:<12} |02{action:<14.13} |14{serverName}" + focusItemFormat: "|00|15> |11{node:<3.2} |10{userName:<12} |02{action:<14.13} |14{serverName}" focusItemAtTop: false } // quick log diff --git a/art/themes/luciano_blocktronics/wfc.ans b/art/themes/luciano_blocktronics/wfc.ans index 2333e610..79fe75b9 100644 Binary files a/art/themes/luciano_blocktronics/wfc.ans and b/art/themes/luciano_blocktronics/wfc.ans differ diff --git a/core/client.js b/core/client.js index fcc9bcdf..8c292003 100644 --- a/core/client.js +++ b/core/client.js @@ -577,7 +577,9 @@ Client.prototype.isLocal = function() { Client.prototype.friendlyRemoteAddress = function() { // convert any :ffff: IPv4's to 32bit version - return this.remoteAddress.replace(/^::ffff:/, '') + return this.remoteAddress + .replace(/^::ffff:/, '') + .replace(/^::1$/, 'localhost'); } /////////////////////////////////////////////////////////////////////////////// diff --git a/core/client_connections.js b/core/client_connections.js index ae1de622..102f79a3 100644 --- a/core/client_connections.js +++ b/core/client_connections.js @@ -123,7 +123,7 @@ function addNewClient(client, clientSock) { connInfo.family = clientSock.localFamily; } - client.log.info(connInfo, `Client connected (${connInfo.port}/${connInfo.serverName})`); + client.log.info(connInfo, `Client connected (${connInfo.serverName}/${connInfo.port})`); Events.emit( Events.getSystemEvents().ClientConnected, diff --git a/core/predefined_mci.js b/core/predefined_mci.js index 690b4029..b57dca98 100644 --- a/core/predefined_mci.js +++ b/core/predefined_mci.js @@ -121,7 +121,7 @@ const PREDEFINED_MCI_GENERATORS = { UD : function themeId(client) { return userStatAsString(client, UserProps.ThemeId, ''); }, UC : function loginCount(client) { return userStatAsCountString(client, UserProps.LoginCount, 0); }, ND : function connectedNode(client) { return client.node.toString(); }, - IP : function clientIpAddress(client) { return client.remoteAddress.friendlyRemoteAddress() }, + IP : function clientIpAddress(client) { return client.friendlyRemoteAddress() }, ST : function serverName(client) { return client.session.serverName; }, FN : function activeFileBaseFilterName(client) { const activeFilter = FileBaseFilters.getActiveFilter(client); @@ -370,7 +370,7 @@ function getPredefinedMCIValue(client, code, extra) { try { value = generator(client, extra); } catch(e) { - Log.error( { code : code, exception : e.message }, 'Exception caught generating predefined MCI value' ); + Log.error( { code : code, exception : e.message }, `Failed generating predefined MCI value (${code})` ); } return value; diff --git a/core/vertical_menu_view.js b/core/vertical_menu_view.js index 6130ebde..a1daf025 100644 --- a/core/vertical_menu_view.js +++ b/core/vertical_menu_view.js @@ -83,6 +83,15 @@ function VerticalMenuView(options) { self.client.term.write(`${ansi.goto(item.row, self.position.col)}${text}`); this.setRenderCacheItem(index, text, item.focused); }; + + this.drawRemovedItem = function(index) { + if (index <= this.items.length - 1) { + return; + } + const row = this.position.row + index; + this.client.term.rawWrite(`${ansi.goto(row, this.position.col)}${ansi.normal()}${this.fillChar.repeat(this.dimens.width)}`) + }; + } util.inherits(VerticalMenuView, MenuView); @@ -123,6 +132,11 @@ VerticalMenuView.prototype.redraw = function() { this.drawItem(i); } } + + const remain = Math.max(0, this.dimens.height - this.items.length); + for (let i = this.items.length; i < remain; ++i) { + this.drawRemovedItem(i); + } }; VerticalMenuView.prototype.setHeight = function(height) { diff --git a/core/wfc.js b/core/wfc.js index 4ae93b4c..40eedfe1 100644 --- a/core/wfc.js +++ b/core/wfc.js @@ -1,5 +1,6 @@ // ENiGMA½ const { MenuModule } = require('./menu_module'); +const stringFormat = require('./string_format'); const { getActiveConnectionList, @@ -33,6 +34,7 @@ const MciViewIds = { main : { nodeStatus : 1, quickLogView : 2, + nodeStatusSelection : 3, customRangeStart : 10, } @@ -119,7 +121,7 @@ exports.getModule = class WaitingForCallerModule extends MenuModule { ); }, (callback) => { - const quickLogView = this.viewControllers.main.getView(MciViewIds.main.quickLogView); + const quickLogView = this.getView('main', MciViewIds.main.quickLogView); if (!quickLogView) { return callback(null); } @@ -138,6 +140,20 @@ exports.getModule = class WaitingForCallerModule extends MenuModule { }); } + const nodeStatusView = this.getView('main', MciViewIds.main.nodeStatus); + const nodeStatusSelectionView = this.getView('main', MciViewIds.main.nodeStatusSelection); + const nodeStatusSelectionFormat = this.config.nodeStatusSelectionFormat || '{text}'; + if (nodeStatusView && nodeStatusSelectionView) { + nodeStatusView.on('index update', index => { + const item = nodeStatusView.getItems()[index]; + if (item) { + nodeStatusSelectionView.setText(stringFormat(nodeStatusSelectionFormat, item)); + // :TODO: Update view + // :TODO: this is not triggered by key-presses (1, 2, ...) -- we need to handle that as well + } + }); + } + return callback(null); }, (callback) => { @@ -354,10 +370,15 @@ exports.getModule = class WaitingForCallerModule extends MenuModule { const [availIndicator, visIndicator] = this._getStatusStrings(ac.isAvailable, ac.isVisible); + const timeOn = ac.timeOn || moment.duration(0); + return Object.assign(ac, { availIndicator, visIndicator, - timeOn : _.upperFirst((ac.timeOn || moment.duration(0)).humanize()), // make friendly + timeOnMinutes : timeOn.asMinutes(), + timeOn : _.upperFirst(timeOn.humanize()), // make friendly + affils : ac.affils || 'N/A', + realName : ac.realName || 'N/A', }); }); diff --git a/docs/_docs/modding/wfc.md b/docs/_docs/modding/wfc.md index dbc866f6..1e6831df 100644 --- a/docs/_docs/modding/wfc.md +++ b/docs/_docs/modding/wfc.md @@ -35,7 +35,20 @@ The following MCI codes are available: * `VM1`: Node status list with the following format items available: * `text`: Username or `*Pre Auth*`. * `action`: Current action/menu. + * `affils`: Any affiliations related to the if `authenticated`, else "N/A". + * `authenticated`: Boolean rather the node is authenticated (logged in) or not. + * `availIndicator`: Indicator of availability (e.g. for messaging)? Displayed via `statusAvailableIndicators` or system theme. See also [Themes](../art/themes.md). + * `isAvailalbe`: Boolean rather the node is availalbe (e.g. for messaging) or not. + * `isSecure`: Is the node securely connected (ie: SSL)? + * `isVisible`: Boolean rather the node is visible to others or not. + * `node`: The node ID. + * `realName`: Real name of authenticated user, or "N/A". + * `serverName`: Name of connected server such as "Telnet" or "SSH". * `timeOn`: How long the node has been connected. + * `timeOnMinutes`: How long in **minutes** the node has been connected. + * `userId`: User ID of authenticated node, or 0 if not yet authenticated. + * `userName`: User name of authenticated user or "*Pre Auth*" + * `visIndicator`: Indicator of visibility. Displayed via `statusVisibleIndicators` or system theme. See also [Themes](../art/themes.md). * `VM2`: Quick log with the following format keys available: * `timestamp`: Log entry timestamp in `quickLogTimestampFormat` format. * `level`: Log entry level from Bunyan.