diff --git a/art/themes/luciano_blocktronics/activitypub_social_manager.ans b/art/themes/luciano_blocktronics/activitypub_social_manager.ans index c5fd35d6..5348f1b2 100644 Binary files a/art/themes/luciano_blocktronics/activitypub_social_manager.ans and b/art/themes/luciano_blocktronics/activitypub_social_manager.ans differ diff --git a/art/themes/luciano_blocktronics/theme.hjson b/art/themes/luciano_blocktronics/theme.hjson index 638132fb..a2e82698 100644 --- a/art/themes/luciano_blocktronics/theme.hjson +++ b/art/themes/luciano_blocktronics/theme.hjson @@ -97,7 +97,7 @@ mci: { VM1: { height: 10 - width: 20 + width: 71 itemFormat: "|00|11{userName:<12}|08: |03{oneliner:<59.59}" } TM2: { @@ -229,6 +229,7 @@ VM1: { height: 10 itemFormat: "|00|11{userName:<12}|08: |03{oneliner:<59.59}" + width: 71 } TM2: { focusTextStyle: first lower @@ -486,7 +487,7 @@ activityPubFollowingManager: { config: { - selectedActorInfoFormat: "|00|15{preferredUsername}\n|02{name}\n{plainTextSummary}" + selectedActorInfoFormat: "|00|15{preferredUsername} |08(|02{name}|08)\n|07following|08: {statusIndicator}\n\n|06{plainTextSummary}" statusIndicatorEnabled: "|00|10√" staticIndicatorDisabled: "|00|12X" } @@ -494,13 +495,13 @@ mci: { VM1: { height: 15 - width: 30 + width: 35 itemFormat: "|00{statusIndicator} |00|03{subject}" focusItemFormat: "|00{statusIndicator} |00|19|15{subject}" } MT2: { height: 15 - width: 38 + width: 34 } TM3: { focusTextStyle: first upper diff --git a/core/full_menu_view.js b/core/full_menu_view.js index 396e827f..9a46f6b3 100644 --- a/core/full_menu_view.js +++ b/core/full_menu_view.js @@ -254,12 +254,11 @@ function FullMenuView(options) { if (relativeColumn + renderLength > this.dimens.width) { const overflow = this.hasTextOverflow() ? this.textOverflow : ''; - text = - strUtil.renderSubstr( - text, - 0, - this.dimens.width - (relativeColumn + overflow.length) - ) + overflow; + + text = strUtil.renderTruncate(text, { + length: this.dimens.width - (relativeColumn + overflow.length), + omission: overflow, + }); } let padLength = Math.min(item.fixedLength + 1, this.dimens.width); diff --git a/core/servers/content/web_handlers/nodeinfo2.js b/core/servers/content/web_handlers/nodeinfo2.js index 4be7f85c..9adab0ef 100644 --- a/core/servers/content/web_handlers/nodeinfo2.js +++ b/core/servers/content/web_handlers/nodeinfo2.js @@ -72,10 +72,12 @@ exports.getModule = class NodeInfo2WebHadnler extends WebHandlerModule { }, // :TODO: Only list what's enabled protocols: ['telnet', 'ssh', 'gopher', 'nntp', 'ws', 'activitypub'], - services: { - inbound: [], - outbound: [''], - }, + + // :TODO: what should we really be doing here??? + // services: { + // inbound: [], + // outbound: [], + // }, openRegistrations: !config.general.closedSystem, usage: { users: { diff --git a/core/string_util.js b/core/string_util.js index 066548b9..2ff418ea 100644 --- a/core/string_util.js +++ b/core/string_util.js @@ -19,6 +19,7 @@ exports.debugEscapedString = debugEscapedString; exports.stringFromNullTermBuffer = stringFromNullTermBuffer; exports.stringToNullTermBuffer = stringToNullTermBuffer; exports.renderSubstr = renderSubstr; +exports.renderTruncate = renderTruncate; exports.renderStringLength = renderStringLength; exports.ansiRenderStringLength = ansiRenderStringLength; exports.formatByteSizeAbbr = formatByteSizeAbbr; @@ -136,13 +137,12 @@ function stylizeString(s, style) { return s; } -function pad(s, len, padChar, justify, stringSGR, padSGR, useRenderLen) { +function pad(s, len, padChar, justify, stringSGR, padSGR, useRenderLen = true) { len = len || 0; padChar = padChar || ' '; justify = justify || 'left'; stringSGR = stringSGR || ''; padSGR = padSGR || ''; - useRenderLen = _.isUndefined(useRenderLen) ? true : useRenderLen; const renderLen = useRenderLen ? renderStringLength(s) : s.length; const padLen = len > renderLen ? len - renderLen : 0; @@ -290,6 +290,29 @@ function renderSubstr(str, start, length) { return out; } +const DefaultTruncateLen = 30; +const DefaultTruncateOmission = '...'; + +function renderTruncate(str, options) { + // shortcut for empty strings + if (0 === str.length) { + return str; + } + + options = options || {}; + options.length = options.length || DefaultTruncateLen; + options.omission = _.isString(options.omission) + ? options.omission + : DefaultTruncateOmission; + + let out = renderSubstr(str, 0, options.length - options.omission.length); + if (out.length < str.length) { + out += options.omission; + } + + return out; +} + // // Method to return the "rendered" length taking into account Pipe and ANSI color codes. // @@ -464,7 +487,7 @@ function isAnsiLine(line) { // * Pipe codes // * Extended (CP437) ASCII - https://www.ascii-codes.com/ // * Tabs -// * Contigous 3+ spaces before the end of the line +// * Contiguous 3+ spaces before the end of the line // function isFormattedLine(line) { if (renderStringLength(line) < line.length) { diff --git a/core/vertical_menu_view.js b/core/vertical_menu_view.js index bf3ac57b..e34794c8 100644 --- a/core/vertical_menu_view.js +++ b/core/vertical_menu_view.js @@ -98,10 +98,10 @@ function VerticalMenuView(options) { sgr = index === self.focusedItemIndex ? self.getFocusSGR() : self.getSGR(); } - const renderLength = strUtil.renderStringLength(text); - if (renderLength > this.dimens.width) { - text = strUtil.renderSubstr(text, 0, this.dimens.width); - } + text = strUtil.renderTruncate(text, { + length: this.dimens.width, + omission: this.textOverflow, + }); text = `${sgr}${strUtil.pad( `${text}${this.styleSGR1}`, @@ -109,6 +109,7 @@ function VerticalMenuView(options) { this.fillChar, this.justify )}`; + self.client.term.write(`${ansi.goto(item.row, self.position.col)}${text}`); this.setRenderCacheItem(index, text, item.focused); }; diff --git a/core/view.js b/core/view.js index ed8f08d0..a82751b5 100644 --- a/core/view.js +++ b/core/view.js @@ -50,6 +50,7 @@ function View(options) { this.textStyle = options.textStyle || 'normal'; this.focusTextStyle = options.focusTextStyle || this.textStyle; this.offsetsApplied = false; + this.truncateOmission = options.truncateOmission || ''; if (options.id) { this.setId(options.id); @@ -273,6 +274,12 @@ View.prototype.setPropertyValue = function (propName, value) { this.validate = value; } break; + + case 'truncateOmission': + if (_.isString(value)) { + this.truncateOmission = value; + } + break; } if (/styleSGR[0-9]{1,2}/.test(propName)) { diff --git a/docs/_docs/art/views/vertical_menu_view.md b/docs/_docs/art/views/vertical_menu_view.md index ed439dbc..e11e087c 100644 --- a/docs/_docs/art/views/vertical_menu_view.md +++ b/docs/_docs/art/views/vertical_menu_view.md @@ -31,6 +31,7 @@ Items can be selected on a menu via the cursor keys, Page Up, Page Down, Home, a | `fillChar` | Specifies a character to fill extra space in the menu with. Defaults to an empty space | | `items` | List of items to show in the menu. See **Items** below. | `focusItemFormat` | Sets the format for a focused list entry. See **Entry Formatting** in [MCI](../mci.md) | +| `truncateOmission` | Sets the omission characters for truncated text if used. Defaults to an empty string. Commonly set to "..." | ### Hot Keys