Skip to content
Snippets Groups Projects
Commit d73bc918 authored by Rob Swindell's avatar Rob Swindell :speech_balloon:
Browse files

Merge branch 'dd_msg_reader_reader_operator_menu_and_add_author_to_twitlist' into 'master'

DDMsgReader: New reader-mode operator menu (using the Ctrl-O hotkey), with a (new) option to add the author's name to the twit list

See merge request !372
parents 3bad3b81 6a42f5cd
No related branches found
No related tags found
1 merge request!372DDMsgReader: New reader-mode operator menu (using the Ctrl-O hotkey), with a (new) option to add the author's name to the twit list
...@@ -88,6 +88,15 @@ ...@@ -88,6 +88,15 @@
* (defaults to true). * (defaults to true).
* Fix for setting colors for the key help lines so that the background * Fix for setting colors for the key help lines so that the background
* won't get un-done if the other help line colors have a N (normal) attribute. * won't get un-done if the other help line colors have a N (normal) attribute.
* 2023-12-02 Eric Oulashin Version 1.90 Beta
* New: operator menu for read mode, with the option to add the author to the
* twit list, etc.
* Fix: When refreshing a rectangular area of a message, if it's a poll message,
* the background color for the voted responses was used for the non-selected
* responses.
* Removed the setting useScrollingInterfaceForANSIMessages.
* 2023-12-04 Eric Oulashin Version 1.90
* Releasing this version
*/ */
   
"use strict"; "use strict";
...@@ -192,8 +201,8 @@ var ansiterm = require("ansiterm_lib.js", 'expand_ctrl_a'); ...@@ -192,8 +201,8 @@ var ansiterm = require("ansiterm_lib.js", 'expand_ctrl_a');
   
   
// Reader version information // Reader version information
var READER_VERSION = "1.89"; var READER_VERSION = "1.90";
var READER_DATE = "2023-11-30"; var READER_DATE = "2023-12-04";
   
// Keyboard key codes for displaying on the screen // Keyboard key codes for displaying on the screen
var UP_ARROW = ascii(24); var UP_ARROW = ascii(24);
...@@ -714,9 +723,13 @@ function DigDistMsgReader(pSubBoardCode, pScriptArgs) ...@@ -714,9 +723,13 @@ function DigDistMsgReader(pSubBoardCode, pScriptArgs)
this.WriteMsgListScreenTopHeader = DigDistMsgReader_WriteMsgListScreenTopHeader; this.WriteMsgListScreenTopHeader = DigDistMsgReader_WriteMsgListScreenTopHeader;
this.ReadMessageEnhanced = DigDistMsgReader_ReadMessageEnhanced; this.ReadMessageEnhanced = DigDistMsgReader_ReadMessageEnhanced;
this.ReadMessageEnhanced_Scrollable = DigDistMsgReader_ReadMessageEnhanced_Scrollable; this.ReadMessageEnhanced_Scrollable = DigDistMsgReader_ReadMessageEnhanced_Scrollable;
this.ShowHdrOrKludgeLines_Scrollable = DigDistMsgReader_ShowHdrOrKludgeLines_Scrollable;
this.ShowVoteInfo_Scrollable = DigDistMsgReader_ShowVoteInfo_Scrollable;
this.ScrollableReaderNextReadableMessage = DigDistMsgReader_ScrollableReaderNextReadableMessage; this.ScrollableReaderNextReadableMessage = DigDistMsgReader_ScrollableReaderNextReadableMessage;
this.ScrollReaderDetermineClickCoordAction = DigDistMsgReader_ScrollReaderDetermineClickCoordAction; this.ScrollReaderDetermineClickCoordAction = DigDistMsgReader_ScrollReaderDetermineClickCoordAction;
this.ReadMessageEnhanced_Traditional = DigDistMsgReader_ReadMessageEnhanced_Traditional; this.ReadMessageEnhanced_Traditional = DigDistMsgReader_ReadMessageEnhanced_Traditional;
this.ShowReadModeOpMenuAndGetSelection = DigDistMsgReader_ShowReadModeOpMenuAndGetSelection;
this.CreateReadModeOpMenu = DigDistMsgReader_CreateReadModeOpMenu;
this.EnhReaderPrepLast2LinesForPrompt = DigDistMsgReader_EnhReaderPrepLast2LinesForPrompt; this.EnhReaderPrepLast2LinesForPrompt = DigDistMsgReader_EnhReaderPrepLast2LinesForPrompt;
this.LookForNextOrPriorNonDeletedMsg = DigDistMsgReader_LookForNextOrPriorNonDeletedMsg; this.LookForNextOrPriorNonDeletedMsg = DigDistMsgReader_LookForNextOrPriorNonDeletedMsg;
this.PrintMessageInfo = DigDistMsgReader_PrintMessageInfo; this.PrintMessageInfo = DigDistMsgReader_PrintMessageInfo;
...@@ -969,12 +982,6 @@ function DigDistMsgReader(pSubBoardCode, pScriptArgs) ...@@ -969,12 +982,6 @@ function DigDistMsgReader(pSubBoardCode, pScriptArgs)
// the > key to go to the next sub-board. // the > key to go to the next sub-board.
this.doingMultiSubBoardScan = false; this.doingMultiSubBoardScan = false;
   
// An option for using the scrollable interface for messages with ANSI
// content - The sysop can set this to false if the sysop thinks the
// scrolling ANSI interface (using frame.js and scrollbar.js) doesn't
// look good enough
this.useScrollingInterfaceForANSIMessages = true;
// Whether or not to pause (with a message) after doing a new message scan // Whether or not to pause (with a message) after doing a new message scan
this.pauseAfterNewMsgScan = true; this.pauseAfterNewMsgScan = true;
   
...@@ -1023,6 +1030,7 @@ function DigDistMsgReader(pSubBoardCode, pScriptArgs) ...@@ -1023,6 +1030,7 @@ function DigDistMsgReader(pSubBoardCode, pScriptArgs)
userSettings: CTRL_U, userSettings: CTRL_U,
validateMsg: "A", // Only if the user is a sysop validateMsg: "A", // Only if the user is a sysop
quickValUser: CTRL_Q, quickValUser: CTRL_Q,
operatorMenu: CTRL_O,
threadView: "*" // TODO: Implement this threadView: "*" // TODO: Implement this
}; };
//if (user.is_sysop) //if (user.is_sysop)
...@@ -1499,6 +1507,17 @@ function DigDistMsgReader(pSubBoardCode, pScriptArgs) ...@@ -1499,6 +1507,17 @@ function DigDistMsgReader(pSubBoardCode, pScriptArgs)
this.pausePromptText = bbs.text(Pause); this.pausePromptText = bbs.text(Pause);
if (this.pausePromptText.toUpperCase().indexOf("@EXEC:") > -1) if (this.pausePromptText.toUpperCase().indexOf("@EXEC:") > -1)
this.pausePromptText = "\x01n\x01c[ Press a key ] "; this.pausePromptText = "\x01n\x01c[ Press a key ] ";
// Menu option values to use for the operator menu for reader mode
this.readerOpMenuOptValues = {
validateMsg: 0,
editAuthorUserAccount: 1,
showHdrLines: 2,
showKludgeLines: 3,
showTallyStats: 4,
quickValUser: 5,
addAuthorToTwitList: 6
};
} }
   
// For the DigDistMsgReader class: Sets the subBoardCode property and also // For the DigDistMsgReader class: Sets the subBoardCode property and also
...@@ -5106,6 +5125,25 @@ function DigDistMsgReader_ReadMessageEnhanced_Scrollable(msgHeader, allowChgMsgA ...@@ -5106,6 +5125,25 @@ function DigDistMsgReader_ReadMessageEnhanced_Scrollable(msgHeader, allowChgMsgA
var msgReaderObj = this; var msgReaderObj = this;
   
var msgHasAttachments = msgHdrHasAttachmentFlag(msgHeader); var msgHasAttachments = msgHdrHasAttachmentFlag(msgHeader);
// For editing a user account. Only for the sysop.
function userEdit(msgHeader, pOffset, pReader)
{
console.attributes = "N";
console.crlf();
console.print("- Edit user " + msgHeader.from);
console.crlf();
var editObj = editUser(msgHeader.from);
if (editObj.errorMsg.length != 0)
{
console.attributes = "N";
console.crlf();
console.print("\x01y\x01h" + editObj.errorMsg + "\x01n");
console.crlf();
console.pause();
}
}
// User input loop // User input loop
var continueOn = true; var continueOn = true;
while (continueOn) while (continueOn)
...@@ -5628,51 +5666,16 @@ function DigDistMsgReader_ReadMessageEnhanced_Scrollable(msgHeader, allowChgMsgA ...@@ -5628,51 +5666,16 @@ function DigDistMsgReader_ReadMessageEnhanced_Scrollable(msgHeader, allowChgMsgA
case this.enhReaderKeys.showKludgeLines: case this.enhReaderKeys.showKludgeLines:
if (user.is_sysop) if (user.is_sysop)
{ {
// Save the original cursor position writeMessage = this.ShowHdrOrKludgeLines_Scrollable(retObj.lastKeypress == this.enhReaderKeys.showKludgeLines, msgHeader, msgAreaWidth, msgAreaHeight);
var originalCurPos = console.getxy(); // Display the scrollbar for the message to refresh it on the screen
if (this.userSettings.useEnhReaderScrollbar)
// Get an array of the extended header info/kludge lines and then
// allow the user to scroll through them.
var onlyKludgeLines = (retObj.lastKeypress == this.enhReaderKeys.showKludgeLines);
var extdHdrInfoLines = this.GetExtdMsgHdrInfo(this.subBoardCode, msgHeader.number, onlyKludgeLines);
if (extdHdrInfoLines.length > 0)
{ {
if (this.userSettings.useEnhReaderScrollbar) solidBlockStartRow = this.msgAreaTop + Math.floor(numNonSolidScrollBlocks * fractionToLastPage);
{ this.DisplayEnhancedReaderWholeScrollbar(solidBlockStartRow, numSolidScrollBlocks);
// Calculate information for the scrollbar for the kludge lines
var infoFractionShown = this.msgAreaHeight / extdHdrInfoLines.length;
if (infoFractionShown > 1)
infoFractionShown = 1.0;
var numInfoSolidScrollBlocks = Math.floor(this.msgAreaHeight * infoFractionShown);
if (numInfoSolidScrollBlocks == 0)
numInfoSolidScrollBlocks = 1;
var numNonSolidInfoScrollBlocks = this.msgAreaHeight - numInfoSolidScrollBlocks;
var lastInfoSolidBlockStartRow = this.msgAreaTop;
// Display the kludge lines and let the user scroll through them
this.DisplayEnhancedReaderWholeScrollbar(this.msgAreaTop, numInfoSolidScrollBlocks);
}
scrollTextLines(extdHdrInfoLines, 0, this.colors["msgBodyColor"], true, this.msgAreaLeft,
this.msgAreaTop, msgAreaWidth, msgAreaHeight, 1, console.screen_rows,
this.userSettings.useEnhReaderScrollbar, msgInfoScrollbarUpdateFn);
// Display the scrollbar for the message to refresh it on the screen
if (this.userSettings.useEnhReaderScrollbar)
{
solidBlockStartRow = this.msgAreaTop + Math.floor(numNonSolidScrollBlocks * fractionToLastPage);
this.DisplayEnhancedReaderWholeScrollbar(solidBlockStartRow, numSolidScrollBlocks);
}
else
{
// TODO
}
writeMessage = true; // We want to refresh the message on the screen
} }
else else
{ {
// There are no header/kludge lines for this message // TODO
var msgText = onlyKludgeLines ? this.text.noKludgeLinesForThisMsgText : this.text.noHdrLinesForThisMsgText;
this.DisplayEnhReaderError(replaceAtCodesInStr(msgText), msgInfo.messageLines, topMsgLineIdx, msgLineFormatStr);
console.gotoxy(originalCurPos);
writeMessage = false;
} }
} }
else // The user is not a sysop else // The user is not a sysop
...@@ -5770,30 +5773,17 @@ function DigDistMsgReader_ReadMessageEnhanced_Scrollable(msgHeader, allowChgMsgA ...@@ -5770,30 +5773,17 @@ function DigDistMsgReader_ReadMessageEnhanced_Scrollable(msgHeader, allowChgMsgA
case this.enhReaderKeys.userEdit: // Edit the user who wrote the message case this.enhReaderKeys.userEdit: // Edit the user who wrote the message
if (user.is_sysop) if (user.is_sysop)
{ {
console.attributes = "N"; userEdit(msgHeader, pOffset, this);
console.crlf();
console.print("- Edit user " + msgHeader.from);
console.crlf();
var editObj = editUser(msgHeader.from);
if (editObj.errorMsg.length != 0)
{
console.attributes = "N";
console.crlf();
console.print("\x01y\x01h" + editObj.errorMsg + "\x01n");
console.crlf();
console.pause();
}
// Refresh things on the screen // Refresh things on the screen
console.clear("\x01n"); console.clear("\x01n");
// Display the message header and key help line again // Display the message header and key help line again
this.DisplayEnhancedMsgHdr(msgHeader, pOffset+1, 1); pReader.DisplayEnhancedMsgHdr(msgHeader, pOffset+1, 1);
this.DisplayEnhancedMsgReadHelpLine(console.screen_rows, allowChgMsgArea); pReader.DisplayEnhancedMsgReadHelpLine(console.screen_rows, allowChgMsgArea);
// Display the scrollbar again to refresh it on the screen // Display the scrollbar again to refresh it on the screen
if (this.userSettings.useEnhReaderScrollbar) if (pReader.userSettings.useEnhReaderScrollbar)
{ {
solidBlockStartRow = this.msgAreaTop + Math.floor(numNonSolidScrollBlocks * fractionToLastPage); retObj.solidBlockStartRow = pReader.msgAreaTop + Math.floor(numNonSolidScrollBlocks * fractionToLastPage);
this.DisplayEnhancedReaderWholeScrollbar(solidBlockStartRow, numSolidScrollBlocks); pReader.DisplayEnhancedReaderWholeScrollbar(solidBlockStartRow, numSolidScrollBlocks);
} }
else else
{ {
...@@ -5920,33 +5910,10 @@ function DigDistMsgReader_ReadMessageEnhanced_Scrollable(msgHeader, allowChgMsgA ...@@ -5920,33 +5910,10 @@ function DigDistMsgReader_ReadMessageEnhanced_Scrollable(msgHeader, allowChgMsgA
writeMessage = false; writeMessage = false;
break; break;
case this.enhReaderKeys.showVotes: // Show votes case this.enhReaderKeys.showVotes: // Show votes
// Save the original cursor position var DVRetObj = this.ShowVoteInfo_Scrollable(msgHeader, msgAreaWidth, msgAreaHeight);
var originalCurPos = console.getxy(); writeMessage = DVRetObj.writeMessage;
if (msgHeader.hasOwnProperty("total_votes") && msgHeader.hasOwnProperty("upvotes")) if (DVRetObj.hasVoteProps)
{ {
var voteInfo = this.GetUpvoteAndDownvoteInfo(msgHeader);
// Display the vote info and let the user scroll through them
// (the console height should be enough, but do this just in case)
// Calculate information for the scrollbar for the vote info lines
if (this.userSettings.useEnhReaderScrollbar)
{
var infoFractionShown = this.msgAreaHeight / voteInfo.length;
if (infoFractionShown > 1)
infoFractionShown = 1.0;
var numInfoSolidScrollBlocks = Math.floor(this.msgAreaHeight * infoFractionShown);
if (numInfoSolidScrollBlocks == 0)
numInfoSolidScrollBlocks = 1;
var numNonSolidInfoScrollBlocks = this.msgAreaHeight - numInfoSolidScrollBlocks;
var lastInfoSolidBlockStartRow = this.msgAreaTop;
// Display the vote info lines and let the user scroll through them
this.DisplayEnhancedReaderWholeScrollbar(this.msgAreaTop, numInfoSolidScrollBlocks);
}
else
{
// TODO
}
scrollTextLines(voteInfo, 0, this.colors["msgBodyColor"], true, this.msgAreaLeft, this.msgAreaTop, msgAreaWidth,
msgAreaHeight, 1, console.screen_rows, this.userSettings.useEnhReaderScrollbar, msgInfoScrollbarUpdateFn);
// Display the scrollbar for the message to refresh it on the screen // Display the scrollbar for the message to refresh it on the screen
if (this.userSettings.useEnhReaderScrollbar) if (this.userSettings.useEnhReaderScrollbar)
{ {
...@@ -5957,13 +5924,6 @@ function DigDistMsgReader_ReadMessageEnhanced_Scrollable(msgHeader, allowChgMsgA ...@@ -5957,13 +5924,6 @@ function DigDistMsgReader_ReadMessageEnhanced_Scrollable(msgHeader, allowChgMsgA
{ {
// TODO // TODO
} }
writeMessage = true; // We want to refresh the message on the screen
}
else
{
this.DisplayEnhReaderError("There is no voting information for this message", msgInfo.messageLines, topMsgLineIdx, msgLineFormatStr);
console.gotoxy(originalCurPos);
writeMessage = false;
} }
break; break;
case this.enhReaderKeys.closePoll: // Close a poll message case this.enhReaderKeys.closePoll: // Close a poll message
...@@ -6206,6 +6166,126 @@ function DigDistMsgReader_ReadMessageEnhanced_Scrollable(msgHeader, allowChgMsgA ...@@ -6206,6 +6166,126 @@ function DigDistMsgReader_ReadMessageEnhanced_Scrollable(msgHeader, allowChgMsgA
this.RefreshMsgAreaRectangle(msgInfo.messageLines, topMsgLineIdx, userSettingsRetObj.optionBoxTopLeftX, userSettingsRetObj.optionBoxTopLeftY, userSettingsRetObj.optionBoxWidth, userSettingsRetObj.optionBoxHeight); this.RefreshMsgAreaRectangle(msgInfo.messageLines, topMsgLineIdx, userSettingsRetObj.optionBoxTopLeftX, userSettingsRetObj.optionBoxTopLeftY, userSettingsRetObj.optionBoxWidth, userSettingsRetObj.optionBoxHeight);
} }
break; break;
case this.enhReaderKeys.operatorMenu: // Operator menu
writeMessage = false;
if (user.is_sysop)
{
var opRetObj = this.ShowReadModeOpMenuAndGetSelection();
// Refresh the message area where the option menu was
this.RefreshMsgAreaRectangle(msgInfo.messageLines, topMsgLineIdx, opRetObj.menuTopLeftX, opRetObj.menuTopLeftY, opRetObj.menuWidth, opRetObj.menuHeight);
if (opRetObj.chosenOption != null)
{
switch (opRetObj.chosenOption)
{
case this.readerOpMenuOptValues.validateMsg: // Validate the message
if (this.subBoardCode != "mail" && msg_area.sub[this.subBoardCode].is_moderated)
{
var message = "";
if (this.ValidateMsg(this.subBoardCode, msgHeader.number))
{
message = "\x01n\x01cMessage validation successful";
// Refresh the message header in the arrays
this.RefreshMsgHdrInArrays(msgHeader.number);
// Exit out of the reader and come back to read
// the same message again so that the voting results
// are re-loaded and displayed on the screen.
retObj.newMsgOffset = pOffset;
retObj.nextAction = ACTION_GO_SPECIFIC_MSG;
continueOn = false;
this.DisplayEnhancedMsgReadHelpLine(console.screen_rows, allowChgMsgArea);
}
else
message = "\x01n\x01y\x01hMessage validation failed!";
this.DisplayEnhReaderError(message, msgInfo.messageLines, topMsgLineIdx, msgLineFormatStr);
writeMessage = true;
}
break;
case this.readerOpMenuOptValues.editAuthorUserAccount: // Edit the local user account
userEdit(msgHeader, pOffset, this);
// Refresh things on the screen
console.clear("\x01n");
// Display the message header and key help line again
pReader.DisplayEnhancedMsgHdr(msgHeader, pOffset+1, 1);
pReader.DisplayEnhancedMsgReadHelpLine(console.screen_rows, allowChgMsgArea);
// Display the scrollbar again to refresh it on the screen
if (pReader.userSettings.useEnhReaderScrollbar)
{
retObj.solidBlockStartRow = pReader.msgAreaTop + Math.floor(numNonSolidScrollBlocks * fractionToLastPage);
pReader.DisplayEnhancedReaderWholeScrollbar(solidBlockStartRow, numSolidScrollBlocks);
}
else
{
// TODO
}
writeMessage = true; // We want to refresh the message on the screen
break;
case this.readerOpMenuOptValues.showHdrLines: // Show header or kludge lines
case this.readerOpMenuOptValues.showKludgeLines:
writeMessage = this.ShowHdrOrKludgeLines_Scrollable(opRetObj.chosenOption == this.readerOpMenuOptValues.showKludgeLines, msgHeader, msgAreaWidth, msgAreaHeight);
// Display the scrollbar for the message to refresh it on the screen
if (this.userSettings.useEnhReaderScrollbar)
{
solidBlockStartRow = this.msgAreaTop + Math.floor(numNonSolidScrollBlocks * fractionToLastPage);
this.DisplayEnhancedReaderWholeScrollbar(solidBlockStartRow, numSolidScrollBlocks);
}
else
{
// TODO
}
break;
case this.readerOpMenuOptValues.showTallyStats: // Show tally/vote stats/info
var DVRetObj = this.ShowVoteInfo_Scrollable(msgHeader, msgAreaWidth, msgAreaHeight);
writeMessage = DVRetObj.writeMessage;
if (DVRetObj.hasVoteProps)
{
// Display the scrollbar for the message to refresh it on the screen
if (this.userSettings.useEnhReaderScrollbar)
{
solidBlockStartRow = this.msgAreaTop + Math.floor(numNonSolidScrollBlocks * fractionToLastPage);
this.DisplayEnhancedReaderWholeScrollbar(solidBlockStartRow, numSolidScrollBlocks);
}
else
{
// TODO
}
}
break;
case this.readerOpMenuOptValues.quickValUser: // Quick validate the user
var valRetObj = quickValidateLocalUser(msgHeader.from, this.scrollingReaderInterface && console.term_supports(USER_ANSI), this.quickUserValSetIndex);
if (valRetObj.needWholeScreenRefresh)
{
this.DisplayEnhancedMsgHdr(msgHeader, pOffset+1, 1);
if (this.userSettings.useEnhReaderScrollbar)
this.DisplayEnhancedReaderWholeScrollbar(solidBlockStartRow, numSolidScrollBlocks);
else
{
// TODO
}
this.DisplayEnhancedMsgReadHelpLine(console.screen_rows, allowChgMsgArea);
}
else
{
writeMessage = false; // Don't refresh the whole message
if (valRetObj.refreshBottomLine)
this.DisplayEnhancedMsgReadHelpLine(console.screen_rows, allowChgMsgArea);
if (valRetObj.optionBoxTopLeftX > 0 && valRetObj.optionBoxTopLeftY > 0 && valRetObj.optionBoxWidth > 0 && valRetObj.optionBoxHeight > 0)
this.RefreshMsgAreaRectangle(msgInfo.messageLines, topMsgLineIdx, valRetObj.optionBoxTopLeftX, valRetObj.optionBoxTopLeftY, valRetObj.optionBoxWidth, valRetObj.optionBoxHeight);
}
break;
case this.readerOpMenuOptValues.addAuthorToTwitList: // Add author to twit list
var promptTxt = format("Add %s to twit list", msgHeader.from);
if (this.EnhReaderPromptYesNo(promptTxt, msgInfo.messageLines, topMsgLineIdx, msgLineFormatStr, solidBlockStartRow, numSolidScrollBlocks, true))
{
var statusMsg = "\x01n" + addToTwitList(msgHeader.from) ? "\x01w\x01hSuccessfully updated the twit list" : "\x01y\x01hFailed to update the twit list!"
writeWithPause(1, console.screen_rows, statusMsg, ERROR_PAUSE_WAIT_MS, "\x01n", true);
console.attributes = "N";
this.DisplayEnhancedMsgReadHelpLine(console.screen_rows, allowChgMsgArea);
}
break;
}
}
}
break;
case this.enhReaderKeys.quit: // Quit case this.enhReaderKeys.quit: // Quit
case KEY_ESC: case KEY_ESC:
// Normally, if quitFromReaderGoesToMsgList is enabled, then do that // Normally, if quitFromReaderGoesToMsgList is enabled, then do that
...@@ -6228,6 +6308,114 @@ function DigDistMsgReader_ReadMessageEnhanced_Scrollable(msgHeader, allowChgMsgA ...@@ -6228,6 +6308,114 @@ function DigDistMsgReader_ReadMessageEnhanced_Scrollable(msgHeader, allowChgMsgA
   
return retObj; return retObj;
} }
// Helper method for ReadMessageEnhanced_Scrollable(): Shows header or kludge lines for the scrollable interface. For the sysop.
function DigDistMsgReader_ShowHdrOrKludgeLines_Scrollable(pOnlyKludgeLines, msgHeader, msgAreaWidth, msgAreaHeight)
{
var msgReaderObj = this;
// This is a scrollbar update function for use when viewing the header info/kludge lines.
function msgInfoScrollbarUpdateFn(pFractionToLastPage)
{
var infoSolidBlockStartRow = msgReaderObj.msgAreaTop + Math.floor(numNonSolidInfoScrollBlocks * pFractionToLastPage);
if (infoSolidBlockStartRow != lastInfoSolidBlockStartRow)
msgReaderObj.UpdateEnhancedReaderScrollbar(infoSolidBlockStartRow, lastInfoSolidBlockStartRow, numInfoSolidScrollBlocks);
lastInfoSolidBlockStartRow = infoSolidBlockStartRow;
console.gotoxy(1, console.screen_rows);
}
var writeMessage = false;
// Save the original cursor position
var originalCurPos = console.getxy();
// Get an array of the extended header info/kludge lines and then
// allow the user to scroll through them.
var extdHdrInfoLines = this.GetExtdMsgHdrInfo(this.subBoardCode, msgHeader.number, pOnlyKludgeLines);
if (extdHdrInfoLines.length > 0)
{
if (this.userSettings.useEnhReaderScrollbar)
{
// Calculate information for the scrollbar for the kludge lines
var infoFractionShown = this.msgAreaHeight / extdHdrInfoLines.length;
if (infoFractionShown > 1)
infoFractionShown = 1.0;
var numInfoSolidScrollBlocks = Math.floor(this.msgAreaHeight * infoFractionShown);
if (numInfoSolidScrollBlocks == 0)
numInfoSolidScrollBlocks = 1;
var numNonSolidInfoScrollBlocks = this.msgAreaHeight - numInfoSolidScrollBlocks;
var lastInfoSolidBlockStartRow = this.msgAreaTop;
// Display the kludge lines and let the user scroll through them
this.DisplayEnhancedReaderWholeScrollbar(this.msgAreaTop, numInfoSolidScrollBlocks);
}
scrollTextLines(extdHdrInfoLines, 0, this.colors["msgBodyColor"], true, this.msgAreaLeft,
this.msgAreaTop, msgAreaWidth, msgAreaHeight, 1, console.screen_rows,
this.userSettings.useEnhReaderScrollbar, msgInfoScrollbarUpdateFn);
writeMessage = true; // We want to refresh the message on the screen
}
else
{
// There are no header/kludge lines for this message
var msgText = pOnlyKludgeLines ? this.text.noKludgeLinesForThisMsgText : this.text.noHdrLinesForThisMsgText;
this.DisplayEnhReaderError(replaceAtCodesInStr(msgText), msgInfo.messageLines, topMsgLineIdx, msgLineFormatStr);
console.gotoxy(originalCurPos);
}
return writeMessage;
}
// For the DDMsgReader class: Shows vote/tally information, for the scrollable interface.
function DigDistMsgReader_ShowVoteInfo_Scrollable(pMsgHeader, pMsgAreaWidth, pMsgAreaHeight)
{
var msgReaderObj = this;
// This is a scrollbar update function for use when viewing the header info/kludge lines.
function msgInfoScrollbarUpdateFn(pFractionToLastPage)
{
var infoSolidBlockStartRow = msgReaderObj.msgAreaTop + Math.floor(numNonSolidInfoScrollBlocks * pFractionToLastPage);
if (infoSolidBlockStartRow != lastInfoSolidBlockStartRow)
msgReaderObj.UpdateEnhancedReaderScrollbar(infoSolidBlockStartRow, lastInfoSolidBlockStartRow, numInfoSolidScrollBlocks);
lastInfoSolidBlockStartRow = infoSolidBlockStartRow;
console.gotoxy(1, console.screen_rows);
}
var retObj = {
hasVoteProps: pMsgHeader.hasOwnProperty("total_votes") && pMsgHeader.hasOwnProperty("upvotes"),
writeMessage: false
};
// Save the original cursor position
var originalCurPos = console.getxy();
if (retObj.hasVoteProps)
{
var voteInfo = this.GetUpvoteAndDownvoteInfo(pMsgHeader);
// Display the vote info and let the user scroll through them
// (the console height should be enough, but do this just in case)
// Calculate information for the scrollbar for the vote info lines
if (this.userSettings.useEnhReaderScrollbar)
{
var infoFractionShown = this.pMsgAreaHeight / voteInfo.length;
if (infoFractionShown > 1)
infoFractionShown = 1.0;
var numInfoSolidScrollBlocks = Math.floor(this.pMsgAreaHeight * infoFractionShown);
if (numInfoSolidScrollBlocks == 0)
numInfoSolidScrollBlocks = 1;
var numNonSolidInfoScrollBlocks = this.pMsgAreaHeight - numInfoSolidScrollBlocks;
var lastInfoSolidBlockStartRow = this.msgAreaTop;
// Display the vote info lines and let the user scroll through them
this.DisplayEnhancedReaderWholeScrollbar(this.msgAreaTop, numInfoSolidScrollBlocks);
}
else
{
// TODO
}
scrollTextLines(voteInfo, 0, this.colors.msgBodyColor, true, this.msgAreaLeft, this.msgAreaTop, pMsgAreaWidth,
pMsgAreaHeight, 1, console.screen_rows, this.userSettings.useEnhReaderScrollbar, msgInfoScrollbarUpdateFn);
retObj.writeMessage = true; // We want to refresh the message on the screen
}
else
{
this.DisplayEnhReaderError("There is no voting information for this message", msgInfo.messageLines, topMsgLineIdx, msgLineFormatStr);
console.gotoxy(originalCurPos);
}
return retObj;
}
// Helper method for ReadMessageEnhanced_Scrollable(): Determines if there is a readable message after the // Helper method for ReadMessageEnhanced_Scrollable(): Determines if there is a readable message after the
// one at the given offset. // one at the given offset.
// //
...@@ -7119,8 +7307,7 @@ function DigDistMsgReader_ReadMessageEnhanced_Traditional(msgHeader, allowChgMsg ...@@ -7119,8 +7307,7 @@ function DigDistMsgReader_ReadMessageEnhanced_Traditional(msgHeader, allowChgMsg
writeMessage = true; writeMessage = true;
} }
console.crlf(); console.crlf();
console.print(message); console.print(message + "\x01n");
console.attributes = "N";
console.crlf(); console.crlf();
console.pause(); console.pause();
} }
...@@ -7129,7 +7316,7 @@ function DigDistMsgReader_ReadMessageEnhanced_Traditional(msgHeader, allowChgMsg ...@@ -7129,7 +7316,7 @@ function DigDistMsgReader_ReadMessageEnhanced_Traditional(msgHeader, allowChgMsg
break; break;
case this.enhReaderKeys.quickValUser: // Quick-validate the user case this.enhReaderKeys.quickValUser: // Quick-validate the user
if (user.is_sysop) if (user.is_sysop)
quickValidateLocalUser(msgHeader.from, this.scrollingReaderInterface && console.term_supports(USER_ANSI), this.quickUserValSetIndex); quickValidateLocalUser(msgHeader.from, false, this.quickUserValSetIndex);
else else
writeMessage = false; writeMessage = false;
break; break;
...@@ -7206,6 +7393,125 @@ function DigDistMsgReader_ReadMessageEnhanced_Traditional(msgHeader, allowChgMsg ...@@ -7206,6 +7393,125 @@ function DigDistMsgReader_ReadMessageEnhanced_Traditional(msgHeader, allowChgMsg
writeMessage = true; writeMessage = true;
} }
break; break;
case this.enhReaderKeys.operatorMenu: // Operator menu
if (user.is_sysop)
{
writeMessage = true;
writePromptText = true;
console.crlf();
console.print("\x01w\x01h== Operator menu ==\x01n");
console.crlf();
var opRetObj = this.ShowReadModeOpMenuAndGetSelection();
if (opRetObj.chosenOption != null)
{
switch (opRetObj.chosenOption)
{
case this.readerOpMenuOptValues.validateMsg: // Validate the message
if (this.subBoardCode != "mail" && msg_area.sub[this.subBoardCode].is_moderated)
{
var message = "";
if (this.ValidateMsg(this.subBoardCode, msgHeader.number))
{
message = "\x01n\x01cMessage validation successful";
// Refresh the message header in the arrays
this.RefreshMsgHdrInArrays(msgHeader.number);
// Exit out of the reader and come back to read
// the same message again so that the voting results
// are re-loaded and displayed on the screen.
retObj.newMsgOffset = pOffset;
retObj.nextAction = ACTION_GO_SPECIFIC_MSG;
continueOn = false;
}
else
message = "\x01n\x01y\x01hMessage validation failed!";
console.crlf();
console.print(message + "\x01n");
console.crlf();
console.pause();
}
break;
case this.readerOpMenuOptValues.editAuthorUserAccount: // Edit author's user account
console.attributes = "N";
console.crlf();
console.print("- Edit user " + msgHeader.from);
console.crlf();
var editObj = editUser(msgHeader.from);
if (editObj.errorMsg.length != 0)
{
console.attributes = "N";
console.crlf();
console.print("\x01y\x01h" + editObj.errorMsg + "\x01n");
console.crlf();
console.pause();
}
console.attributes = "N";
break;
case this.readerOpMenuOptValues.showHdrLines: // Show header or kludge lines
case this.readerOpMenuOptValues.showKludgeLines:
console.crlf();
// Get an array of the extended header info/kludge lines and then
// display them.
var extdHdrInfoLines = this.GetExtdMsgHdrInfo(this.subBoardCode, msgHeader.number, (opRetObj.chosenOption == this.readerOpMenuOptValues.showKludgeLines));
if (extdHdrInfoLines.length > 0)
{
console.crlf();
for (var infoIter = 0; infoIter < extdHdrInfoLines.length; ++infoIter)
{
console.print(extdHdrInfoLines[infoIter]);
console.crlf();
}
console.pause();
}
else
{
// There are no kludge lines for this message
console.print(replaceAtCodesInStr(this.text.noKludgeLinesForThisMsgText));
console.crlf();
console.pause();
}
break;
case this.readerOpMenuOptValues.showTallyStats: // Show tally stats
if (msgHeader.hasOwnProperty("total_votes") && msgHeader.hasOwnProperty("upvotes"))
{
console.attributes = "N";
console.crlf();
var voteInfo = this.GetUpvoteAndDownvoteInfo(msgHeader);
for (var voteInfoIdx = 0; voteInfoIdx < voteInfo.length; ++voteInfoIdx)
{
console.print(voteInfo[voteInfoIdx]);
console.crlf();
}
}
else
{
console.print("\x01n\x01h\x01yThere is no voting information for this message\x01n");
console.crlf();
}
console.pause();
break;
case this.readerOpMenuOptValues.quickValUser: // Quick-validate the user
quickValidateLocalUser(msgHeader.from, false, this.quickUserValSetIndex);
break;
case this.readerOpMenuOptValues.addAuthorToTwitList: // Add author to twit list
var promptTxt = format("Add %s to twit list", msgHeader.from);
if (!console.noyes(promptTxt))
{
var statusMsg = "\x01n" + addToTwitList(msgHeader.from) ? "\x01w\x01hSuccessfully updated the twit list" : "\x01y\x01hFailed to update the twit list!"
console.print(statusMsg);
console.attributes = "N";
console.crlf();
console.pause();
}
break;
}
}
}
else
{
writeMessage = false;
writePromptText = false;
}
break;
case this.enhReaderKeys.quit: // Quit case this.enhReaderKeys.quit: // Quit
case KEY_ESC: case KEY_ESC:
// Normally, if quitFromReaderGoesToMsgList is enabled, then do that, except // Normally, if quitFromReaderGoesToMsgList is enabled, then do that, except
...@@ -7232,6 +7538,105 @@ function DigDistMsgReader_ReadMessageEnhanced_Traditional(msgHeader, allowChgMsg ...@@ -7232,6 +7538,105 @@ function DigDistMsgReader_ReadMessageEnhanced_Traditional(msgHeader, allowChgMsg
return retObj; return retObj;
} }
   
// For the DDMsgReader class: Does the operator mode for reading.
//
// Return value: An object with the following properties:
// menuTopLeftX: The horizontal component of the upper-left corner of the operator menu (for scrollable mode)
// menuTopLeftY: The vertical component of the upper-left corner of the operator menu (for scrollable mode)
// menuWidth: The width of the operator menu (for scrollable mode)
// menuHeight: The height of the operator menu (for scrollable mode)
// chosenOption: The user's chosen option from the menu (one of this.readerOpMenuOptValues), or null
// if the user quit/aborted
// lastUserInput: The user's last key input from the menu (empty string if there is none)
function DigDistMsgReader_ShowReadModeOpMenuAndGetSelection()
{
var retObj = {
menuTopLeftX: 1,
menuTopLeftY: 1,
menuWidth: 0,
menuHeight: 0,
chosenOption: null,
lastUserInput: ""
};
// This is only for the sysop
if (!user.is_sysop)
return retObj;
// If using scrollable mode, create the operator menu & display it
var opMenu = this.CreateReadModeOpMenu();
retObj.menuTopLeftX = opMenu.pos.x;
retObj.menuTopLeftY = opMenu.pos.y;
retObj.menuWidth = opMenu.size.width;
retObj.menuHeight = opMenu.size.height;
//GetVal(pDraw, pSelectedItemIndexes)
retObj.chosenOption = opMenu.GetVal();
if (typeof(opMenu.lastUserInput) === "string")
retObj.lastUserInput = opMenu.lastUserInput;
// If the user pressed one of the additional quit keys set up for the
// menu, make sure the chosen option is null (it should be anyway)
if (retObj.lastUserInput.toUpperCase() == "Q" || retObj.lastUserInput == KEY_ESC) // Quit
retObj.chosenOption = null;
return retObj;
}
// For the DDMsgReader class: Creates the operator menu for read mode.
// The menu should be created each time, because the options could be different for
// each sub-board (i.e., if the sub-board is moderated, then the 'Validate message'
// option will be available).
function DigDistMsgReader_CreateReadModeOpMenu()
{
//var itemFormatStr = "\x01n\x01c\x01h%s\x01y";
// We'll add the 'Validate message' option if the sub-board isn't email and is moderated
var subBoardIsModerated = (this.subBoardCode != "mail" && msg_area.sub[this.subBoardCode].is_moderated);
var opMenuWidth = 35;
var opMenuHeight = 8;
if (subBoardIsModerated)
++opMenuHeight;
var opMenuX = Math.floor(console.screen_columns/2) - Math.floor(opMenuWidth/2);
var opMenuY = this.msgAreaTop + 2;
var opMenu = new DDLightbarMenu(opMenuX, opMenuY, opMenuWidth, opMenuHeight);
opMenu.borderEnabled = true;
opMenu.allowANSI = this.scrollingReaderInterface && console.term_supports(USER_ANSI);
opMenu.topBorderText = "\x01n\x01w\x01hOperator menu (reader mode)";
if (subBoardIsModerated)
opMenu.Add("&A: Validate the message", this.readerOpMenuOptValues.validateMsg);
// If the scrollbar/ANSI interface is being used, then add the menu items with hotkey characters.
// Otherwise don't use the hotkey characters (the menu will use numbered mode).
if (opMenu.allowANSI)
{
opMenu.Add("&U: Edit author's user account", this.readerOpMenuOptValues.editAuthorUserAccount);
opMenu.Add("&H: Show header lines", this.readerOpMenuOptValues.showHdrLines);
opMenu.Add("&K: Show kludge lines", this.readerOpMenuOptValues.showKludgeLines);
opMenu.Add("&T: Show tally stats", this.readerOpMenuOptValues.showTallyStats);
opMenu.Add("&A: Quick validate the user", this.readerOpMenuOptValues.quickValUser);
opMenu.Add("&I: Add author to twit list", this.readerOpMenuOptValues.addAuthorToTwitList);
// Use cyan for the item color, and cyan with blue background for selected item color
opMenu.colors.itemColor = "\x01n\x01c";
opMenu.colors.selectedItemColor = "\x01n\x01c\x014";
}
else
{
opMenu.Add("Edit author's user account", this.readerOpMenuOptValues.editAuthorUserAccount);
opMenu.Add("Show header lines", this.readerOpMenuOptValues.showHdrLines);
opMenu.Add("Show kludge lines", this.readerOpMenuOptValues.showKludgeLines);
opMenu.Add("Show tally stats", this.readerOpMenuOptValues.showTallyStats);
opMenu.Add("Quick validate the user", this.readerOpMenuOptValues.quickValUser);
opMenu.Add("Add author to twit list", this.readerOpMenuOptValues.addAuthorToTwitList);
// Use green for the item color and high cyan for the item number color
opMenu.colors.itemColor = "\x01n\x01g";
opMenu.colors.itemNumColor = "\x01n\x01c\x01h";
}
opMenu.AddAdditionalQuitKeys("qQ" + this.enhReaderKeys.operatorMenu);
return opMenu;
}
// For the ReadMessageEnhanced methods: This function converts a thread navigation // For the ReadMessageEnhanced methods: This function converts a thread navigation
// key character to its corresponding thread type value // key character to its corresponding thread type value
function keypressToThreadType(pKeypress, pEnhReaderKeys) function keypressToThreadType(pKeypress, pEnhReaderKeys)
...@@ -8468,8 +8873,6 @@ function DigDistMsgReader_ReadConfigFile() ...@@ -8468,8 +8873,6 @@ function DigDistMsgReader_ReadConfigFile()
this.msgListUseLightbarListInterface = (settingsObj.listInterfaceStyle.toUpperCase() == "LIGHTBAR"); this.msgListUseLightbarListInterface = (settingsObj.listInterfaceStyle.toUpperCase() == "LIGHTBAR");
if (typeof(settingsObj["readerInterfaceStyle"]) === "string") if (typeof(settingsObj["readerInterfaceStyle"]) === "string")
this.scrollingReaderInterface = (settingsObj.readerInterfaceStyle.toUpperCase() == "SCROLLABLE"); this.scrollingReaderInterface = (settingsObj.readerInterfaceStyle.toUpperCase() == "SCROLLABLE");
if (typeof(settingsObj["readerInterfaceStyleForANSIMessages"]) === "string")
this.useScrollingInterfaceForANSIMessages = (settingsObj.readerInterfaceStyleForANSIMessages.toUpperCase() == "SCROLLABLE");
if (typeof(settingsObj["displayBoardInfoInHeader"]) === "boolean") if (typeof(settingsObj["displayBoardInfoInHeader"]) === "boolean")
this.displayBoardInfoInHeader = settingsObj.displayBoardInfoInHeader; this.displayBoardInfoInHeader = settingsObj.displayBoardInfoInHeader;
if (typeof(settingsObj["promptToContinueListingMessages"]) === "boolean") if (typeof(settingsObj["promptToContinueListingMessages"]) === "boolean")
...@@ -10486,6 +10889,7 @@ function DigDistMsgReader_DisplayEnhancedReaderHelp(pDisplayChgAreaOpt, pDisplay ...@@ -10486,6 +10889,7 @@ function DigDistMsgReader_DisplayEnhancedReaderHelp(pDisplayChgAreaOpt, pDisplay
keyHelpLines.push("\x01h\x01cDEL \x01g: \x01n\x01cDelete the current message"); keyHelpLines.push("\x01h\x01cDEL \x01g: \x01n\x01cDelete the current message");
keyHelpLines.push("\x01h\x01cCtrl-S \x01g: \x01n\x01cSave the message (to the BBS machine)"); keyHelpLines.push("\x01h\x01cCtrl-S \x01g: \x01n\x01cSave the message (to the BBS machine)");
keyHelpLines.push("\x01h\x01c" + this.enhReaderKeys.validateMsg + " \x01g: \x01n\x01cValidate the message"); keyHelpLines.push("\x01h\x01c" + this.enhReaderKeys.validateMsg + " \x01g: \x01n\x01cValidate the message");
keyHelpLines.push("\x01h\x01cCtrl-O \x01g: \x01n\x01cShow operator menu");
var quickValUserLine = "\x01h\x01cCtrl-Q \x01g: \x01n\x01cQuick-validate user (must be local)"; var quickValUserLine = "\x01h\x01cCtrl-Q \x01g: \x01n\x01cQuick-validate user (must be local)";
if (this.quickUserValSetIndex >= 0 && this.quickUserValSetIndex < 10) if (this.quickUserValSetIndex >= 0 && this.quickUserValSetIndex < 10)
quickValUserLine += "; Set index: " + this.quickUserValSetIndex; quickValUserLine += "; Set index: " + this.quickUserValSetIndex;
...@@ -14027,7 +14431,7 @@ function DigDistMsgReader_ValidateMsg(pSubBoardCode, pMsgNum) ...@@ -14027,7 +14431,7 @@ function DigDistMsgReader_ValidateMsg(pSubBoardCode, pMsgNum)
var msgHdr = msgbase.get_msg_header(false, pMsgNum, false); var msgHdr = msgbase.get_msg_header(false, pMsgNum, false);
if (msgHdr != null) if (msgHdr != null)
{ {
if ((msgHdr.attr & MSG_VALIDATED) == 0) if (!Boolean(msgHdr.attr & MSG_VALIDATED))
{ {
msgHdr.attr |= MSG_VALIDATED; msgHdr.attr |= MSG_VALIDATED;
validationSuccessful = msgbase.put_msg_header(false, msgHdr.number, msgHdr); validationSuccessful = msgbase.put_msg_header(false, msgHdr.number, msgHdr);
...@@ -15259,7 +15663,7 @@ function DigDistMsgReader_CreateLightbarIndexedModeMenu(pNumMsgsWidth, pNumNewMs ...@@ -15259,7 +15663,7 @@ function DigDistMsgReader_CreateLightbarIndexedModeMenu(pNumMsgsWidth, pNumNewMs
// Add additional keypresses for quitting the menu's input loop so we can // Add additional keypresses for quitting the menu's input loop so we can
// respond to these keys // respond to these keys
// TODO: Include Mm to allow the user to view the message list instead of read it from the indexed menu // TODO: Include Mm to allow the user to view the message list instead of read it from the indexed menu
indexedModeMenu.AddAdditionalQuitKeys(); //indexedModeMenu.AddAdditionalQuitKeys();
for (var key in this.indexedModeMenuKeys) for (var key in this.indexedModeMenuKeys)
{ {
if (/[a-zA-Z]/.test(this.indexedModeMenuKeys[key])) if (/[a-zA-Z]/.test(this.indexedModeMenuKeys[key]))
...@@ -16909,7 +17313,7 @@ function DigDistMsgReader_RefreshMsgAreaRectangle(pTxtLines, pTopLineIdx, pTopLe ...@@ -16909,7 +17313,7 @@ function DigDistMsgReader_RefreshMsgAreaRectangle(pTxtLines, pTopLineIdx, pTopLe
//console.print(getAllEditLineAttrsUntilLineIdx(pTxtLines, txtLineIdx, true, txtLineStartIdx)); //console.print(getAllEditLineAttrsUntilLineIdx(pTxtLines, txtLineIdx, true, txtLineStartIdx));
// Get the section of line (and make sure it can fill the needed width), and print it // Get the section of line (and make sure it can fill the needed width), and print it
// Note: substrWithAttrCodes() is defined in dd_lightbar_menu.js // Note: substrWithAttrCodes() is defined in dd_lightbar_menu.js
var lineText = substrWithAttrCodes(pTxtLines[txtLineIdx].replace(/[\r\n]+/g, ""), txtLineStartIdx, pWidth); var lineText = "\x01n" + substrWithAttrCodes(pTxtLines[txtLineIdx].replace(/[\r\n]+/g, ""), txtLineStartIdx, pWidth);
var printableTxtLen = console.strlen(lineText); var printableTxtLen = console.strlen(lineText);
if (printableTxtLen < pWidth) if (printableTxtLen < pWidth)
lineText += format("\x01n%*s", pWidth - printableTxtLen, ""); lineText += format("\x01n%*s", pWidth - printableTxtLen, "");
...@@ -17782,6 +18186,20 @@ function scrollTextLines(pTxtLines, pTopLineIdx, pTxtAttrib, pWriteTxtLines, pTo ...@@ -17782,6 +18186,20 @@ function scrollTextLines(pTxtLines, pTopLineIdx, pTxtAttrib, pWriteTxtLines, pTo
topLineIdx: pTopLineIdx topLineIdx: pTopLineIdx
}; };
   
/*
// Temporary
if (user.is_sysop)
{
console.print("\x01n\r\n");
console.print("pWidth: " + pWidth + "\r\n");
console.print("pHeight: " + pHeight + "\r\n");
console.print("pUseScrollbar: " + pUseScrollbar + "\r\n");
console.print("pScrollUpdateFn: " + typeof(pScrollUpdateFn) + "\r\n");
console.pause();
}
// End Temporary
*/
// Create an array of color/attribute codes for each line of // Create an array of color/attribute codes for each line of
// text, in case there are any such codes in the text lines, // text, in case there are any such codes in the text lines,
// so that the colors in the message are displayed properly. // so that the colors in the message are displayed properly.
...@@ -22533,7 +22951,12 @@ function quickValidateLocalUser(pUsername, pUseANSI, pQuickValSetIdx) ...@@ -22533,7 +22951,12 @@ function quickValidateLocalUser(pUsername, pUseANSI, pQuickValSetIdx)
console.print(menuHdrStr); console.print(menuHdrStr);
} }
else else
{
retObj.needWholeScreenRefresh = true; retObj.needWholeScreenRefresh = true;
// Use green for the item color and high cyan for the item number color
valSetMenu.colors.itemColor = "\x01n\x01g";
valSetMenu.colors.itemNumColor = "\x01n\x01c\x01h";
}
quickValidationValSet = valSetMenu.GetVal(); quickValidationValSet = valSetMenu.GetVal();
displayedMenu = true; displayedMenu = true;
console.attributes = "N"; console.attributes = "N";
...@@ -22951,6 +23374,69 @@ function getMsgHdr(pSubCode, pByOffset, pNumOrOffset, pExpandFields, pIncludeVot ...@@ -22951,6 +23374,69 @@ function getMsgHdr(pSubCode, pByOffset, pNumOrOffset, pExpandFields, pIncludeVot
return msgHdr; return msgHdr;
} }
   
// Adds to the twit list.
//
// Parameters:
// pStr: A name/email or netmail address
//
// Return value: Boolean - Whether or not this was successful
function addToTwitList(pStr)
{
if (typeof(pStr) !== "string")
return false;
var wasSuccessful = true;
if (!entryExistsInTwitList(pStr))
{
wasSuccessful = false;
var twitFile = new File(system.ctrl_dir + "twitlist.cfg");
//if (twitFile.open(twitFile.exists ? "r+" : "w+"))
if (twitFile.open("a"))
{
wasSuccessful = twitFile.writeln(pStr);
twitFile.close();
}
}
return wasSuccessful;
}
// Returns whether an entry exists in the twit list.
//
// Parameters:
// pStr: An entry to check in the twit list
//
// Return value: Boolean - Whether or not the given string exists in the twit list
function entryExistsInTwitList(pStr)
{
if (typeof(pStr) !== "string")
return false;
var entryExists = false;
var twitFile = new File(system.ctrl_dir + "twitlist.cfg");
if (twitFile.open("r"))
{
while (!twitFile.eof && !entryExists)
{
//// Read the next line from the config file.
var fileLine = twitFile.readln(2048);
// fileLine should be a string, but I've seen some cases
// where for some reason it isn't. If it's not a string,
// then continue onto the next line.
if (typeof(fileLine) != "string")
continue;
// If the line starts with with a semicolon (the comment
// character) or is blank, then skip it.
if ((fileLine.substr(0, 1) == ";") || (fileLine.length == 0))
continue;
// See if this line matches the given string
entryExists = (pStr == skipsp(truncsp(fileLine)));
}
twitFile.close();
}
return entryExists;
}
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
   
// For debugging: Writes some text on the screen at a given location with a given pause. // For debugging: Writes some text on the screen at a given location with a given pause.
......
Digital Distortion Message Reader Digital Distortion Message Reader
Version 1.89 Version 1.90
Release date: 2023-11-30 Release date: 2023-12-04
by by
...@@ -154,21 +154,10 @@ When displaying a message to the user, this script will honor the attribute ...@@ -154,21 +154,10 @@ When displaying a message to the user, this script will honor the attribute
code toggles set up under Synchronet's configuration program (SCFG), code toggles set up under Synchronet's configuration program (SCFG),
under Message Options > Extra Attribute Codes. under Message Options > Extra Attribute Codes.
If a message contains ANSI codes and the scrollable reader interface is being As the sysop, when reading a message, the hotkey Ctrl-O will show the operator
used, Digital Distortion Message Reader will try to use frame.js and menu. Most of the operator menu items are already available, but the operator
scrollbar.js if those are available on your BBS filesystem. The reason is that menu also has the additional option to add the author of the message (the 'from'
frame.js is able to parse and display ANSI in a scrollable interface very well. name) to the twit list.
If frame.js and scrollbar.js are not available on your BBS system, the reader
will still display the message, but it might look garbled if it has ANSI codes.
So for best results when reading ANSI messages,ensure that you have the latest
frame.js and scrollbar.js in your sbbs/exec/load directory. frame.js and
scrollbar.js are included in Synchronet 3.16, and I believe in earlier versions
too. As of this writing, the latest versions of those files can be found in
Synchronet's CVS repository at the following URLs:
frame.js:
http://cvs.synchro.net/cgi-bin/viewcvs.cgi/exec/load/frame.js?view=log
scrollbar.js:
http://cvs.synchro.net/cgi-bin/viewcvs.cgi/exec/load/scrollbar.js?view=log
3. Installation & Setup 3. Installation & Setup
......
...@@ -5,6 +5,12 @@ Revision History (change log) ...@@ -5,6 +5,12 @@ Revision History (change log)
============================= =============================
Version Date Description Version Date Description
------- ---- ----------- ------- ---- -----------
1.90 2023-12-04 New: operator menu for read mode, with the option to add
the author to the twit list, etc.
Fix: When refreshing a rectangular area of a message, if
it's a poll message, the background color for the voted
responses was used for the non-selected responses.
Removed the setting useScrollingInterfaceForANSIMessages.
1.89 2023-11-30 New: User option to toggle whether to display the email 1.89 2023-11-30 New: User option to toggle whether to display the email
'replied' indicator (defaults to true). 'replied' indicator (defaults to true).
Fix for setting colors for the key help lines so that the Fix for setting colors for the key help lines so that the
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment