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

Merge branch 'dd_msg_reader_speed_improvements_and_newscan_and_indexed_mode_updates' into 'master'

DDMsgReader: Speed improvements and updates for newscans, and updates for the indexed newscan menu mode.

See merge request main/sbbs!363
parents 1ffd1d55 2e4f2219
Branches
No related tags found
No related merge requests found
...@@ -52,10 +52,6 @@ convertYStyleMCIAttrsToSync=true ...@@ -52,10 +52,6 @@ convertYStyleMCIAttrsToSync=true
; Whether or not to prepend the subject for forwarded messages with "Fwd: " ; Whether or not to prepend the subject for forwarded messages with "Fwd: "
prependFowardMsgSubject=true prependFowardMsgSubject=true
; For indexed reader mode, whether or not to enable caching the message
; header lists for performance
enableIndexedModeMsgListCache=true
; An index of a quick-validation set from SCFG > System > Security Options > Quick-Validation Values ; An index of a quick-validation set from SCFG > System > Security Options > Quick-Validation Values
; to be used by the sysop to quick-validate a local user who has posted a message while reading the ; to be used by the sysop to quick-validate a local user who has posted a message while reading the
; message. This index is 0-based, as they appear in SCFG. Normally there are 10 quick-validation ; message. This index is 0-based, as they appear in SCFG. Normally there are 10 quick-validation
...@@ -74,5 +70,18 @@ saveAllHdrsWhenSavingMsgToBBSPC=false ...@@ -74,5 +70,18 @@ saveAllHdrsWhenSavingMsgToBBSPC=false
; user setting; users can toggle this for themselves as they like. ; user setting; users can toggle this for themselves as they like.
useIndexedModeForNewscan=false useIndexedModeForNewscan=false
; For indexed reader mode, whether or not to enable caching the message
; header lists for performance
enableIndexedModeMsgListCache=true
; Default for a user setting: During a newscan, whether or not to only show new
; messages. Users can then toggle this as they like.
newscanOnlyShowNewMsgs=true
; Default for a user setting: For the indexed newscan sub-board list, whether or not
; to "snap" the lightbar selected item to the next sub-board with new messages upon
; displaying or returning to the indexed newscan menu
indexedModeMenuSnapToFirstWithNew=false
; The theme file name (for colors, strings, etc.) ; The theme file name (for colors, strings, etc.)
themeFilename=DefaultTheme.cfg themeFilename=DefaultTheme.cfg
...@@ -58,6 +58,24 @@ ...@@ -58,6 +58,24 @@
* as DDMsgReader doesn't implement those yet). * as DDMsgReader doesn't implement those yet).
* Fix: In the message list, to-user alternate colors weren't being used * Fix: In the message list, to-user alternate colors weren't being used
* unless the message was read. The correct colors are used again. * unless the message was read. The correct colors are used again.
* 2023-11-09 Eric Oulashin Version 1.87 Beta
* Trying to speed things up by not getting vote headers all the time
* when calling get_all_msg_headers(), unless the vote headers are needed
* (when the sysop views who votes on a message when viewing tally info)
* New: User setting to only show new messages in a newscan (defaults to true/enabled)
* In the message list, there is now an additional space before the
* 'from' name, in case one of the status characters is a letter (this should
* look better).
* New: In lightbar mode, the indexed newscan menu can optionally 'snap' to
* the next sub-board with new messages when showing/returning to the menu
* Fix: When listing personal email, messages to the user were written
* with the to-user color wuen unread. Now the regular colors are always
* used (since all of a user's personal emails are 'to' them).
* Fix: For indexed newscan, if there are no sub-boards selected for scan
* in the user's newscan configuration, then output a message and return.
* Otherwise, it would end up in an infinite loop.
* Updated how user settings are loaded, to ensure that default user settings
* from DDMsgReader.cfg actually get set properly in the user settings.
*/ */
   
"use strict"; "use strict";
...@@ -162,8 +180,8 @@ var ansiterm = require("ansiterm_lib.js", 'expand_ctrl_a'); ...@@ -162,8 +180,8 @@ var ansiterm = require("ansiterm_lib.js", 'expand_ctrl_a');
   
   
// Reader version information // Reader version information
var READER_VERSION = "1.86"; var READER_VERSION = "1.87";
var READER_DATE = "2023-11-09"; var READER_DATE = "2023-11-18";
   
// 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);
...@@ -332,6 +350,12 @@ const REFRESH_MSG_AREA_CHG_LIGHTBAR_HELP_LINE = 0; ...@@ -332,6 +350,12 @@ const REFRESH_MSG_AREA_CHG_LIGHTBAR_HELP_LINE = 0;
const MSG_LIST_SORT_DATETIME_RECEIVED = 0; const MSG_LIST_SORT_DATETIME_RECEIVED = 0;
const MSG_LIST_SORT_DATETIME_WRITTEN = 1; const MSG_LIST_SORT_DATETIME_WRITTEN = 1;
   
// Special value for passing to PopulateHdrsForCurrentSubBoard(): Start populating
// message headers from the scan pointer.
// This is a negative number so it won't get confuesd with a message header index.
const POPULATE_MSG_HDRS_FROM_SCAN_PTR = -1;
const POPULATE_NEWSCAN_FORCE_GET_ALL_HDRS = -2; // Get all message headers even for a newscan
// Misc. defines // Misc. defines
var ERROR_WAIT_MS = 1500; var ERROR_WAIT_MS = 1500;
var SEARCH_TIMEOUT_MS = 10000; var SEARCH_TIMEOUT_MS = 10000;
...@@ -816,7 +840,7 @@ function DigDistMsgReader(pSubBoardCode, pScriptArgs) ...@@ -816,7 +840,7 @@ function DigDistMsgReader(pSubBoardCode, pScriptArgs)
this.hdrsForCurrentSubBoard = []; this.hdrsForCurrentSubBoard = [];
// hdrsForCurrentSubBoardByMsgNum is an object that maps absolute message numbers // hdrsForCurrentSubBoardByMsgNum is an object that maps absolute message numbers
// to their index to hdrsForCurrentSubBoard // to their index to hdrsForCurrentSubBoard
this.hdrsForCurrentSubBoardByMsgNum = {}; this.msgNumToIdxMap = {};
   
// msgSearchHdrs is an object containing message headers found via searching. // msgSearchHdrs is an object containing message headers found via searching.
// It is indexed by internal message area code. Each internal code index // It is indexed by internal message area code. Each internal code index
...@@ -841,6 +865,7 @@ function DigDistMsgReader(pSubBoardCode, pScriptArgs) ...@@ -841,6 +865,7 @@ function DigDistMsgReader(pSubBoardCode, pScriptArgs)
// SEARCH_ALL_TO_USER_SCAN: All messages to the current user // SEARCH_ALL_TO_USER_SCAN: All messages to the current user
this.searchType = SEARCH_NONE; this.searchType = SEARCH_NONE;
this.doingMsgScan = false; // Set to true in MessageAreaScan() this.doingMsgScan = false; // Set to true in MessageAreaScan()
this.doingNewscan = false; // Whether or not we're doing a newscan
   
this.subBoardCode = bbs.cursub_code; // The message sub-board code this.subBoardCode = bbs.cursub_code; // The message sub-board code
this.readingPersonalEmail = false; this.readingPersonalEmail = false;
...@@ -888,11 +913,11 @@ function DigDistMsgReader(pSubBoardCode, pScriptArgs) ...@@ -888,11 +913,11 @@ function DigDistMsgReader(pSubBoardCode, pScriptArgs)
this.DATE_LEN = 10; // i.e., YYYY-MM-DD this.DATE_LEN = 10; // i.e., YYYY-MM-DD
this.TIME_LEN = 8; // i.e., HH:MM:SS this.TIME_LEN = 8; // i.e., HH:MM:SS
// Variable field widths: From, to, and subject // Variable field widths: From, to, and subject
this.FROM_LEN = (console.screen_columns * (15/console.screen_columns)).toFixed(0); this.FROM_LEN = ((console.screen_columns * (15/console.screen_columns)).toFixed(0)) - 1; // - 1 to make room for the space after the message indicator character
this.TO_LEN = (console.screen_columns * (15/console.screen_columns)).toFixed(0); this.TO_LEN = ((console.screen_columns * (15/console.screen_columns)).toFixed(0)) - 1; // - 1 to account for the spaces around the status character
//var colsLeftForSubject = console.screen_columns-this.MSGNUM_LEN-this.DATE_LEN-this.TIME_LEN-this.FROM_LEN-this.TO_LEN-6; // 6 to account for the spaces //var colsLeftForSubject = console.screen_columns-this.MSGNUM_LEN-this.DATE_LEN-this.TIME_LEN-this.FROM_LEN-this.TO_LEN-6; // 6 to account for the spaces
//this.SUBJ_LEN = (console.screen_columns * (colsLeftForSubject/console.screen_columns)).toFixed(0); //this.SUBJ_LEN = (console.screen_columns * (colsLeftForSubject/console.screen_columns)).toFixed(0);
this.SUBJ_LEN = console.screen_columns-this.MSGNUM_LEN-this.DATE_LEN-this.TIME_LEN-this.FROM_LEN-this.TO_LEN-6; // 6 to account for the spaces this.SUBJ_LEN = console.screen_columns-this.MSGNUM_LEN-this.DATE_LEN-this.TIME_LEN-this.FROM_LEN-this.TO_LEN-8; // 8 to account for the spaces
// For showing message scores in the message list // For showing message scores in the message list
this.SCORE_LEN = 4; this.SCORE_LEN = 4;
// Whether or not to show message scores in the message list: Only if the terminal // Whether or not to show message scores in the message list: Only if the terminal
...@@ -1101,8 +1126,13 @@ function DigDistMsgReader(pSubBoardCode, pScriptArgs) ...@@ -1101,8 +1126,13 @@ function DigDistMsgReader(pSubBoardCode, pScriptArgs)
twitList: [], twitList: [],
// Whether or not to use the scrollbar in the enhanced message reader // Whether or not to use the scrollbar in the enhanced message reader
useEnhReaderScrollbar: true, useEnhReaderScrollbar: true,
// Whether or not to only show new messages when doing a newscan
newscanOnlyShowNewMsgs: true,
// Whether or not to use indexed mode for doing a newscan // Whether or not to use indexed mode for doing a newscan
useIndexedModeForNewscan: false, useIndexedModeForNewscan: false,
// Whether or not the indexed mode sub-board menu should "snap" selection to sub-boards with new messages
// when the menu is shown
indexedModeMenuSnapToFirstWithNew: false,
// Whether or not to list messages in reverse order // Whether or not to list messages in reverse order
listMessagesInReverse: false, listMessagesInReverse: false,
// Whether or not quitting from the reader goes to the message list (instead of exiting altogether) // Whether or not quitting from the reader goes to the message list (instead of exiting altogether)
...@@ -1515,13 +1545,15 @@ function DigDistMsgReader_SetSubBoardCode(pSubCode) ...@@ -1515,13 +1545,15 @@ function DigDistMsgReader_SetSubBoardCode(pSubCode)
// //
// Parameters: // Parameters:
// pStartIdx: Optional - The index of the first message to retrieve. Only used if pEndIdx is also valid. // pStartIdx: Optional - The index of the first message to retrieve. Only used if pEndIdx is also valid.
// This can also be the value POPULATE_MSG_HDRS_FROM_SCAN_PTR, to signify that the headers
// should be populated starting from the scan pointer for the current sub-board.
// pEndIdx: Optional - One past the index of the last message to retrieve. Only used if pStartIdx is also valid. // pEndIdx: Optional - One past the index of the last message to retrieve. Only used if pStartIdx is also valid.
function DigDistMsgReader_PopulateHdrsForCurrentSubBoard(pStartIdx, pEndIdx) function DigDistMsgReader_PopulateHdrsForCurrentSubBoard(pStartIdx, pEndIdx)
{ {
if (this.subBoardCode == "mail") if (this.subBoardCode == "mail")
{ {
this.hdrsForCurrentSubBoard = []; this.hdrsForCurrentSubBoard = [];
this.hdrsForCurrentSubBoardByMsgNum = {}; this.msgNumToIdxMap = {};
return; return;
} }
   
...@@ -1531,24 +1563,51 @@ function DigDistMsgReader_PopulateHdrsForCurrentSubBoard(pStartIdx, pEndIdx) ...@@ -1531,24 +1563,51 @@ function DigDistMsgReader_PopulateHdrsForCurrentSubBoard(pStartIdx, pEndIdx)
{ {
// First get all headers in a temporary array, then filter them into // First get all headers in a temporary array, then filter them into
// this.hdrsForCurrentSubBoard. // this.hdrsForCurrentSubBoard.
if (typeof(pStartIdx) === "number" && pStartIdx >= 0 && typeof(pEndIdx) === "number" && pEndIdx <= msgbase.total_msgs) var startIdxIsNumber = (typeof(pStartIdx) === "number");
// If doing a newscan but we want to get all headers anyway, then do it.
if (this.doingNewscan && startIdxIsNumber && pStartIdx == POPULATE_NEWSCAN_FORCE_GET_ALL_HDRS)
tmpHdrs = msgbase.get_all_msg_headers(false, false); // Don't include votes, don't expand fields
// If doing a newscan and the setting to only show new messages for a newscan is enabled, then
// only get messages from the user's scan pointer
else if (this.doingNewscan && (this.userSettings.newscanOnlyShowNewMsgs || (startIdxIsNumber && pStartIdx == POPULATE_MSG_HDRS_FROM_SCAN_PTR)))
{
{
// Populate the list of headers starting at the scan pointer.
var startMsgIdx = absMsgNumToIdxWithMsgbaseObj(msgbase, msg_area.sub[this.subBoardCode].scan_ptr);
var endMsgIdx = msgbase.total_msgs;
tmpHdrs = {};
for (var i = startMsgIdx+1; i < endMsgIdx; ++i)
{
// Get message header by index; Don't expand fields, don't include votes
var msgHdr = msgbase.get_msg_header(true, i, false, false);
if (msgHdr != null)
tmpHdrs[msgHdr.number] = msgHdr;
}
}
}
// If pStartIdx & pEndIdx are valid, then use those
else if (startIdxIsNumber && pStartIdx >= 0 && typeof(pEndIdx) === "number" && pEndIdx <= msgbase.total_msgs)
{ {
tmpHdrs = {}; tmpHdrs = {};
for (var i = pStartIdx; i < pEndIdx; ++i) for (var i = pStartIdx; i < pEndIdx; ++i)
{ {
// Get message header by index; Don't expand fields, include votes // Get message header by index; Don't expand fields, include votes
var msgHdr = msgbase.get_msg_header(true, i, false, true); //var msgHdr = msgbase.get_msg_header(true, i, false, true);
var msgHdr = msgbase.get_msg_header(true, i, false, false);
if (msgHdr != null) if (msgHdr != null)
tmpHdrs[msgHdr.number] = msgHdr; tmpHdrs[msgHdr.number] = msgHdr;
} }
} }
else else
{ {
// Get all message headers
// Note: get_all_msg_headers() was added in Synchronet 3.16. DDMsgReader requires a minimum // Note: get_all_msg_headers() was added in Synchronet 3.16. DDMsgReader requires a minimum
// of 3.18, so we're okay to use it. // of 3.18, so we're okay to use it.
// The first parameter is whether to include votes (the parameter was introduced in Synchronet 3.17+). // The first parameter is whether to include votes (the parameter was introduced in Synchronet 3.17+).
// We used to pass false here. // We used to pass false here.
tmpHdrs = msgbase.get_all_msg_headers(true, false); // Include votes, don't expand fields //tmpHdrs = msgbase.get_all_msg_headers(true, false); // Include votes, don't expand fields
tmpHdrs = msgbase.get_all_msg_headers(false, false); // Don't include votes, don't expand fields
} }
msgbase.close(); msgbase.close();
} }
...@@ -1559,48 +1618,45 @@ function DigDistMsgReader_PopulateHdrsForCurrentSubBoard(pStartIdx, pEndIdx) ...@@ -1559,48 +1618,45 @@ function DigDistMsgReader_PopulateHdrsForCurrentSubBoard(pStartIdx, pEndIdx)
   
// For the DigDistMsgReader class: Takes an array of message headers in the current // For the DigDistMsgReader class: Takes an array of message headers in the current
// sub-board and filters them into this.hdrsForCurrentSubBoard and // sub-board and filters them into this.hdrsForCurrentSubBoard and
// this.hdrsForCurrentSubBoardByMsgNum based on which messages are readable to the // this.msgNumToIdxMap based on which messages are readable to the
// user. // user.
// //
// Parameters: // Parameters:
// pMsgHdrs: An array/object of message header objects // pMsgHdrs: An array/object of message header objects
// pClearFirst: Boolean - Whether or not to empty this.hdrsForCurrentSubBoard // pClearFirst: Boolean - Whether or not to empty this.hdrsForCurrentSubBoard
// and this.hdrsForCurrentSubBoardByMsgNum first. // and this.msgNumToIdxMap first.
function DigDistMsgReader_FilterMsgHdrsIntoHdrsForCurrentSubBoard(pMsgHdrs, pClearFirst) function DigDistMsgReader_FilterMsgHdrsIntoHdrsForCurrentSubBoard(pMsgHdrs, pClearFirst)
{ {
if (pClearFirst) if (pClearFirst)
{ {
this.hdrsForCurrentSubBoard = []; this.hdrsForCurrentSubBoard = [];
this.hdrsForCurrentSubBoardByMsgNum = {}; this.msgNumToIdxMap = {};
} }
if (pMsgHdrs == null) if (pMsgHdrs == null)
return; return;
   
var idx = (this.hdrsForCurrentSubBoard.length > 0 ? this.hdrsForCurrentSubBoard.length - 1 : 0);
for (var prop in pMsgHdrs) for (var prop in pMsgHdrs)
{ {
// Only add the message header if the message is readable to the user // Only add the message header if the message is readable to the user
// and the from & to name isn't in the user's personal twitlist. // and the from & to name isn't in the user's personal twitlist.
// this.hdrsForCurrentSubBoardByMsgNum also has to be populated, but
// that's done later in this function, in case this.hdrsForCurrentSubBoard
// needs to be sorted.
if (isReadableMsgHdr(pMsgHdrs[prop], this.subBoardCode) && !this.MsgHdrFromOrToInUserTwitlist(pMsgHdrs[prop])) if (isReadableMsgHdr(pMsgHdrs[prop], this.subBoardCode) && !this.MsgHdrFromOrToInUserTwitlist(pMsgHdrs[prop]))
{ {
this.hdrsForCurrentSubBoard.push(pMsgHdrs[prop]); this.hdrsForCurrentSubBoard.push(pMsgHdrs[prop]);
// This isn't done right here anymore due to the possibility of this.msgNumToIdxMap[pMsgHdrs[prop].number] = idx++;
// this.hdrsForCurrentSubBoard being sorted
//this.hdrsForCurrentSubBoardByMsgNum[pMsgHdrs[prop].number] = this.hdrsForCurrentSubBoard.length - 1;
} }
} }
   
// If the sort type is date/time written, then sort the message header // If the sort type is date/time written, then sort the message header
// array as such // array as such
if (this.msgListSort == MSG_LIST_SORT_DATETIME_WRITTEN) if (this.msgListSort == MSG_LIST_SORT_DATETIME_WRITTEN)
{
this.hdrsForCurrentSubBoard.sort(sortMessageHdrsByDateTime); this.hdrsForCurrentSubBoard.sort(sortMessageHdrsByDateTime);
// Re-populate this.msgNumToIdxMap to match the order of this.hdrsForCurrentSubBoard
// Populate this.hdrsForCurrentSubBoardByMsgNum (this needs to be done here this.msgNumToIdxMap = {};
// based on the order of this.hdrsForCurrentSubBoard)
for (var idx = 0; idx < this.hdrsForCurrentSubBoard.length; ++idx) for (var idx = 0; idx < this.hdrsForCurrentSubBoard.length; ++idx)
this.hdrsForCurrentSubBoardByMsgNum[this.hdrsForCurrentSubBoard[idx].number] = idx; this.msgNumToIdxMap[this.hdrsForCurrentSubBoard[idx].number] = idx;
}
} }
   
// For the DigDistMsgReader class: Gets the message offset (index) for a message, given // For the DigDistMsgReader class: Gets the message offset (index) for a message, given
...@@ -1641,13 +1697,13 @@ function DigDistMsgReader_GetMsgIdx(pHdrOrMsgNum) ...@@ -1641,13 +1697,13 @@ function DigDistMsgReader_GetMsgIdx(pHdrOrMsgNum)
} }
else if (this.hdrsForCurrentSubBoard.length > 0) else if (this.hdrsForCurrentSubBoard.length > 0)
{ {
if (this.hdrsForCurrentSubBoardByMsgNum.hasOwnProperty(msgNum)) if (this.msgNumToIdxMap.hasOwnProperty(msgNum))
msgIdx = this.hdrsForCurrentSubBoardByMsgNum[msgNum]; msgIdx = this.msgNumToIdxMap[msgNum];
else else
{ {
msgIdx = absMsgNumToIdx(this.subBoardCode, msgNum); msgIdx = absMsgNumToIdx(this.subBoardCode, msgNum);
if (msgIdx != -1) if (msgIdx != -1)
this.hdrsForCurrentSubBoardByMsgNum[msgNum] = msgIdx; this.msgNumToIdxMap[msgNum] = msgIdx;
} }
} }
else else
...@@ -2418,6 +2474,8 @@ function DigDistMsgReader_MessageAreaScan(pScanCfgOpt, pScanMode, pScanScopeChar ...@@ -2418,6 +2474,8 @@ function DigDistMsgReader_MessageAreaScan(pScanCfgOpt, pScanMode, pScanScopeChar
writeToSysAndNodeLog(logMessage); writeToSysAndNodeLog(logMessage);
} }
   
this.doingNewscan = pScanMode === SCAN_NEW;
// If doing a newscan of all sub-boards, and the user has their setting for indexed mode // If doing a newscan of all sub-boards, and the user has their setting for indexed mode
// for newscan enabled, then do that and return instead of the traditional newscan. // for newscan enabled, then do that and return instead of the traditional newscan.
if (pScanCfgOpt === SCAN_CFG_NEW && pScanMode === SCAN_NEW && this.userSettings.useIndexedModeForNewscan) if (pScanCfgOpt === SCAN_CFG_NEW && pScanMode === SCAN_NEW && this.userSettings.useIndexedModeForNewscan)
...@@ -2426,6 +2484,7 @@ function DigDistMsgReader_MessageAreaScan(pScanCfgOpt, pScanMode, pScanScopeChar ...@@ -2426,6 +2484,7 @@ function DigDistMsgReader_MessageAreaScan(pScanCfgOpt, pScanMode, pScanScopeChar
if (scanScopeChar === "S") scanScope = SCAN_SCOPE_SUB_BOARD; if (scanScopeChar === "S") scanScope = SCAN_SCOPE_SUB_BOARD;
else if (scanScopeChar === "G") scanScope = SCAN_SCOPE_GROUP; else if (scanScopeChar === "G") scanScope = SCAN_SCOPE_GROUP;
msgReader.DoIndexedMode(scanScope); msgReader.DoIndexedMode(scanScope);
this.doingNewscan = false;
return; return;
} }
   
...@@ -2555,12 +2614,19 @@ function DigDistMsgReader_MessageAreaScan(pScanCfgOpt, pScanMode, pScanScopeChar ...@@ -2555,12 +2614,19 @@ function DigDistMsgReader_MessageAreaScan(pScanCfgOpt, pScanMode, pScanScopeChar
{ {
bbs.curgrp = grpIndex; bbs.curgrp = grpIndex;
bbs.cursub = subIndex; bbs.cursub = subIndex;
// For a newscan, start at index 0 if the user wants to only show new messages
// during a newscan; otherwise, start at the scan pointer message (the sub-board
// will have to be populated with all messages)
var startMsgIdx = 0;
if (!this.userSettings.newscanOnlyShowNewMsgs)
{
// Start at the scan pointer // Start at the scan pointer
var startMsgIdx = scanPtrMsgIdx; startMsgIdx = scanPtrMsgIdx;
// If the message has already been read, then start at the next message // If the message has already been read, then start at the next message
var tmpMsgHdr = this.GetMsgHdrByIdx(startMsgIdx); var tmpMsgHdr = this.GetMsgHdrByIdx(startMsgIdx);
if ((tmpMsgHdr != null) && (msg_area.sub[this.subBoardCode].last_read == tmpMsgHdr.number) && (startMsgIdx < this.NumMessages(true) - 1)) if ((tmpMsgHdr != null) && (msg_area.sub[this.subBoardCode].last_read == tmpMsgHdr.number) && (startMsgIdx < this.NumMessages() - 1))
++startMsgIdx; ++startMsgIdx;
}
// Allow the user to read messages in this sub-board. Don't allow // Allow the user to read messages in this sub-board. Don't allow
// the user to change to a different message area, don't pause // the user to change to a different message area, don't pause
// when there's no search results in a sub-board, and return // when there's no search results in a sub-board, and return
...@@ -2656,6 +2722,8 @@ function DigDistMsgReader_MessageAreaScan(pScanCfgOpt, pScanMode, pScanScopeChar ...@@ -2656,6 +2722,8 @@ function DigDistMsgReader_MessageAreaScan(pScanCfgOpt, pScanMode, pScanScopeChar
console.crlf(); console.crlf();
console.pause(); console.pause();
} }
this.doingNewscan = false;
} }
   
// For the DigDistMsgReader class: Performs the message reading activity. // For the DigDistMsgReader class: Performs the message reading activity.
...@@ -3491,7 +3559,7 @@ function DigDistMsgReader_ListMessages_Traditional(pAllowChgSubBoard) ...@@ -3491,7 +3559,7 @@ function DigDistMsgReader_ListMessages_Traditional(pAllowChgSubBoard)
   
// In case all messages were deleted, if the user can't view deleted messages, // In case all messages were deleted, if the user can't view deleted messages,
// show an appropriate message and don't continue listing messages. // show an appropriate message and don't continue listing messages.
//if (this.NumMessages(true) == 0) //if (this.NumMessages() == 0)
if (!this.NonDeletedMessagesExist() && !canViewDeletedMsgs()) if (!this.NonDeletedMessagesExist() && !canViewDeletedMsgs())
{ {
continueOn = false; continueOn = false;
...@@ -3551,7 +3619,8 @@ function DigDistMsgReader_ListMessages_Traditional(pAllowChgSubBoard) ...@@ -3551,7 +3619,8 @@ function DigDistMsgReader_ListMessages_Traditional(pAllowChgSubBoard)
var tmpMsgbase = new MsgBase(this.subBoardCode); var tmpMsgbase = new MsgBase(this.subBoardCode);
if (tmpMsgbase.open()) if (tmpMsgbase.open())
{ {
var tmpAllMsgHdrs = tmpMsgbase.get_all_msg_headers(true); //var tmpAllMsgHdrs = tmpMsgbase.get_all_msg_headers(true);
var tmpAllMsgHdrs = tmpMsgbase.get_all_msg_headers(false);
tmpMsgbase.close(); tmpMsgbase.close();
this.FilterMsgHdrsIntoHdrsForCurrentSubBoard(tmpAllMsgHdrs, true); this.FilterMsgHdrsIntoHdrsForCurrentSubBoard(tmpAllMsgHdrs, true);
} }
...@@ -3842,7 +3911,7 @@ function DigDistMsgReader_ListMessages_Lightbar(pAllowChgSubBoard) ...@@ -3842,7 +3911,7 @@ function DigDistMsgReader_ListMessages_Lightbar(pAllowChgSubBoard)
   
// In case all messages were deleted, if the user can't view deleted messages, // In case all messages were deleted, if the user can't view deleted messages,
// show an appropriate message and don't continue listing messages. // show an appropriate message and don't continue listing messages.
//if (this.NumMessages(true) == 0) //if (this.NumMessages() == 0)
if (!this.NonDeletedMessagesExist() && !canViewDeletedMsgs()) if (!this.NonDeletedMessagesExist() && !canViewDeletedMsgs())
continueOn = false; continueOn = false;
else else
...@@ -4037,7 +4106,7 @@ function DigDistMsgReader_ListMessages_Lightbar(pAllowChgSubBoard) ...@@ -4037,7 +4106,7 @@ function DigDistMsgReader_ListMessages_Lightbar(pAllowChgSubBoard)
   
// In case all messages were deleted, if the user can't view deleted messages, // In case all messages were deleted, if the user can't view deleted messages,
// show an appropriate message and don't continue listing messages. // show an appropriate message and don't continue listing messages.
//if (this.NumMessages(true) == 0) //if (this.NumMessages() == 0)
if (!this.NonDeletedMessagesExist() && !canViewDeletedMsgs()) if (!this.NonDeletedMessagesExist() && !canViewDeletedMsgs())
continueOn = false; continueOn = false;
else else
...@@ -4094,7 +4163,8 @@ function DigDistMsgReader_ListMessages_Lightbar(pAllowChgSubBoard) ...@@ -4094,7 +4163,8 @@ function DigDistMsgReader_ListMessages_Lightbar(pAllowChgSubBoard)
var tmpMsgbase = new MsgBase(this.subBoardCode); var tmpMsgbase = new MsgBase(this.subBoardCode);
if (tmpMsgbase.open()) if (tmpMsgbase.open())
{ {
var tmpAllMsgHdrs = tmpMsgbase.get_all_msg_headers(true); //var tmpAllMsgHdrs = tmpMsgbase.get_all_msg_headers(true);
var tmpAllMsgHdrs = tmpMsgbase.get_all_msg_headers(false);
tmpMsgbase.close(); tmpMsgbase.close();
this.FilterMsgHdrsIntoHdrsForCurrentSubBoard(tmpAllMsgHdrs, true); this.FilterMsgHdrsIntoHdrsForCurrentSubBoard(tmpAllMsgHdrs, true);
} }
...@@ -4134,9 +4204,9 @@ function DigDistMsgReader_CreateLightbarMsgListMenu() ...@@ -4134,9 +4204,9 @@ function DigDistMsgReader_CreateLightbarMsgListMenu()
msgNumStart: 0, msgNumStart: 0,
msgNumEnd: this.MSGNUM_LEN, msgNumEnd: this.MSGNUM_LEN,
selectMarkStart: this.MSGNUM_LEN, selectMarkStart: this.MSGNUM_LEN,
selectMarkEnd: this.MSGNUM_LEN+1, selectMarkEnd: this.MSGNUM_LEN+2,
}; };
msgListIdxes.fromNameStart = this.MSGNUM_LEN + 1; msgListIdxes.fromNameStart = this.MSGNUM_LEN + 2;
msgListIdxes.fromNameEnd = msgListIdxes.fromNameStart + +this.FROM_LEN + 1; msgListIdxes.fromNameEnd = msgListIdxes.fromNameStart + +this.FROM_LEN + 1;
msgListIdxes.toNameStart = msgListIdxes.fromNameEnd; msgListIdxes.toNameStart = msgListIdxes.fromNameEnd;
msgListIdxes.toNameEnd = msgListIdxes.toNameStart + +this.TO_LEN + 1; msgListIdxes.toNameEnd = msgListIdxes.toNameStart + +this.TO_LEN + 1;
...@@ -4245,7 +4315,8 @@ function DigDistMsgReader_CreateLightbarMsgListMenu() ...@@ -4245,7 +4315,8 @@ function DigDistMsgReader_CreateLightbarMsgListMenu()
menuItemObj.retval = msgHdr.number; menuItemObj.retval = msgHdr.number;
var msgIsToUser = userHandleAliasNameMatch(msgHdr.to); var msgIsToUser = userHandleAliasNameMatch(msgHdr.to);
var msgIsFromUser = userHandleAliasNameMatch(msgHdr.from); var msgIsFromUser = userHandleAliasNameMatch(msgHdr.from);
if (this.msgReader.subBoardCode != "mail") var readingPersonalEmail = (this.msgReader.subBoardCode == "mail");
if (!readingPersonalEmail)
menuItemObj.useAltColors = msgIsToUser; menuItemObj.useAltColors = msgIsToUser;
// For any indicator character next to the message, prioritize deleted, then selected, // For any indicator character next to the message, prioritize deleted, then selected,
// then unread, then attachments. // then unread, then attachments.
...@@ -4258,6 +4329,8 @@ function DigDistMsgReader_CreateLightbarMsgListMenu() ...@@ -4258,6 +4329,8 @@ function DigDistMsgReader_CreateLightbarMsgListMenu()
menuItemObj.itemColor = []; menuItemObj.itemColor = [];
var colorSet = this.colors.itemColor; var colorSet = this.colors.itemColor;
var selectedColorSet = this.colors.selectedItemColor; var selectedColorSet = this.colors.selectedItemColor;
if (!readingPersonalEmail)
{
if (msgIsToUser) if (msgIsToUser)
{ {
colorSet = this.colors.altItemColor; colorSet = this.colors.altItemColor;
...@@ -4274,6 +4347,7 @@ function DigDistMsgReader_CreateLightbarMsgListMenu() ...@@ -4274,6 +4347,7 @@ function DigDistMsgReader_CreateLightbarMsgListMenu()
{start: this.msgListIdxes.timeStart, end: this.msgListIdxes.timeEnd, attrs: this.msgReader.colors.msgListFromUserTimeColor}]; {start: this.msgListIdxes.timeStart, end: this.msgListIdxes.timeEnd, attrs: this.msgReader.colors.msgListFromUserTimeColor}];
selectedColorSet = this.colors.altSelectedItemColor; selectedColorSet = this.colors.altSelectedItemColor;
} }
}
for (var i = 0; i < colorSet.length; ++i) for (var i = 0; i < colorSet.length; ++i)
menuItemObj.itemColor.push(colorSet[i]); menuItemObj.itemColor.push(colorSet[i]);
menuItemObj.itemSelectedColor = []; menuItemObj.itemSelectedColor = [];
...@@ -4282,7 +4356,7 @@ function DigDistMsgReader_CreateLightbarMsgListMenu() ...@@ -4282,7 +4356,7 @@ function DigDistMsgReader_CreateLightbarMsgListMenu()
} }
// Change the color // Change the color
// Deleted // Deleted
if ((msgHdr.attr & MSG_DELETE) == MSG_DELETE) if (Boolean(msgHdr.attr & MSG_DELETE))
{ {
if (menuItemObj.itemColor.length >= 2) if (menuItemObj.itemColor.length >= 2)
menuItemObj.itemColor[1].attrs = "\x01r\x01h\x01i"; menuItemObj.itemColor[1].attrs = "\x01r\x01h\x01i";
...@@ -4598,7 +4672,7 @@ function DigDistMsgReader_PrintMessageInfo(pMsgHeader, pHighlight, pMsgNum, pRet ...@@ -4598,7 +4672,7 @@ function DigDistMsgReader_PrintMessageInfo(pMsgHeader, pHighlight, pMsgNum, pRet
msgIndicatorChar = "\x01n" + this.colors.selectedMsgMarkColor + this.colors.msgListHighlightBkgColor + CHECK_CHAR + "\x01n"; msgIndicatorChar = "\x01n" + this.colors.selectedMsgMarkColor + this.colors.msgListHighlightBkgColor + CHECK_CHAR + "\x01n";
else if (msgDeleted) else if (msgDeleted)
msgIndicatorChar = "\x01n\x01r\x01h\x01i" + this.colors.msgListHighlightBkgColor + "*\x01n"; msgIndicatorChar = "\x01n\x01r\x01h\x01i" + this.colors.msgListHighlightBkgColor + "*\x01n";
else if (this.readingPersonalEmail && (pMsgHeader.attr & MSG_READ) == 0) else if (this.readingPersonalEmail && !Boolean(pMsgHeader.attr & MSG_READ))
msgIndicatorChar = "\x01n" + this.colors.selectedMsgMarkColor + this.colors.msgListHighlightBkgColor + "U\x01n"; msgIndicatorChar = "\x01n" + this.colors.selectedMsgMarkColor + this.colors.msgListHighlightBkgColor + "U\x01n";
else if (msgHdrHasAttachmentFlag(pMsgHeader)) else if (msgHdrHasAttachmentFlag(pMsgHeader))
msgIndicatorChar = "\x01n" + this.colors.selectedMsgMarkColor + this.colors.msgListHighlightBkgColor + "A\x01n"; msgIndicatorChar = "\x01n" + this.colors.selectedMsgMarkColor + this.colors.msgListHighlightBkgColor + "A\x01n";
...@@ -6061,7 +6135,8 @@ function DigDistMsgReader_ReadMessageEnhanced_Scrollable(msgHeader, allowChgMsgA ...@@ -6061,7 +6135,8 @@ function DigDistMsgReader_ReadMessageEnhanced_Scrollable(msgHeader, allowChgMsgA
{ {
continueOn = false; continueOn = false;
writeMessage = false; writeMessage = false;
var tmpAllMsgHdrs = tmpMsgbase.get_all_msg_headers(true); //var tmpAllMsgHdrs = tmpMsgbase.get_all_msg_headers(true);
var tmpAllMsgHdrs = tmpMsgbase.get_all_msg_headers(false);
tmpMsgbase.close(); tmpMsgbase.close();
this.FilterMsgHdrsIntoHdrsForCurrentSubBoard(tmpAllMsgHdrs, true); this.FilterMsgHdrsIntoHdrsForCurrentSubBoard(tmpAllMsgHdrs, true);
// If the user is currently reading a message a message by someone who is now // If the user is currently reading a message a message by someone who is now
...@@ -7110,7 +7185,8 @@ function DigDistMsgReader_ReadMessageEnhanced_Traditional(msgHeader, allowChgMsg ...@@ -7110,7 +7185,8 @@ function DigDistMsgReader_ReadMessageEnhanced_Traditional(msgHeader, allowChgMsg
{ {
continueOn = false; continueOn = false;
writeMessage = false; writeMessage = false;
var tmpAllMsgHdrs = tmpMsgbase.get_all_msg_headers(true); //var tmpAllMsgHdrs = tmpMsgbase.get_all_msg_headers(true);
var tmpAllMsgHdrs = tmpMsgbase.get_all_msg_headers(false);
tmpMsgbase.close(); tmpMsgbase.close();
this.FilterMsgHdrsIntoHdrsForCurrentSubBoard(tmpAllMsgHdrs, true); this.FilterMsgHdrsIntoHdrsForCurrentSubBoard(tmpAllMsgHdrs, true);
// If the user is currently reading a message a message by someone who is now // If the user is currently reading a message a message by someone who is now
...@@ -8033,12 +8109,22 @@ function DigDistMsgReader_DisplayMessageListNotesHelp() ...@@ -8033,12 +8109,22 @@ function DigDistMsgReader_DisplayMessageListNotesHelp()
{ {
displayTextWithLineBelow("Notes about the message list:", false, displayTextWithLineBelow("Notes about the message list:", false,
this.colors["tradInterfaceHelpScreenColor"], "\x01n\x01k\x01h") this.colors["tradInterfaceHelpScreenColor"], "\x01n\x01k\x01h")
console.print(this.colors["tradInterfaceHelpScreenColor"]); console.print(this.colors.tradInterfaceHelpScreenColor);
console.print("If a message has been marked for deletion, it will appear with a blinking\r\n"); var helpLines = [
console.print("red asterisk (\x01n\x01h\x01r\x01i*" + "\x01n" + this.colors.tradInterfaceHelpScreenColor + ") in"); "If a message has been marked for deletion, it will appear with a blinking red asterisk (\x01n\x01h\x01r\x01i*" + "\x01n" +
console.print(" after the message number in the message list.\r\n"); this.colors.tradInterfaceHelpScreenColor + ") after the message number in the message list.",
console.print("For a message written to you, a U between the message number and 'from' name\r\n");
console.print("means the message is unread."); "If a message has attachments, an A will appear between the message number and 'from' name.",
"Unread messages written to you will have a U between the message number and 'from' name."
];
var wrapLen = console.screen_columns-1;
for (var i = 0; i < helpLines.length; ++i)
{
var wrappedLines = word_wrap(helpLines[i], wrapLen).split("\n");
for (var j = 0; j < wrappedLines.length; ++j)
console.print(wrappedLines[j] + "\r\n");
}
} }
// For the DigDistMsgReader Class: Sets the traditional UI pause prompt text // For the DigDistMsgReader Class: Sets the traditional UI pause prompt text
// strings, sLightbarModeHelpLine, the text string for the lightbar help line, // strings, sLightbarModeHelpLine, the text string for the lightbar help line,
...@@ -8459,6 +8545,10 @@ function DigDistMsgReader_ReadConfigFile() ...@@ -8459,6 +8545,10 @@ function DigDistMsgReader_ReadConfigFile()
this.userSettings.listMessagesInReverse = settingsObj.reverseListOrder; this.userSettings.listMessagesInReverse = settingsObj.reverseListOrder;
if (typeof(settingsObj["useIndexedModeForNewscan"]) === "boolean") if (typeof(settingsObj["useIndexedModeForNewscan"]) === "boolean")
this.userSettings.useIndexedModeForNewscan = settingsObj.useIndexedModeForNewscan; this.userSettings.useIndexedModeForNewscan = settingsObj.useIndexedModeForNewscan;
if (typeof(settingsObj["newscanOnlyShowNewMsgs"]) === "boolean")
this.userSettings.newscanOnlyShowNewMsgs = settingsObj.newscanOnlyShowNewMsgs;
if (typeof(settingsObj["indexedModeMenuSnapToFirstWithNew"]) === "boolean")
this.userSettings.indexedModeMenuSnapToFirstWithNew = settingsObj.indexedModeMenuSnapToFirstWithNew;
} }
else else
{ {
...@@ -8574,24 +8664,21 @@ function DigDistMsgReader_ReadUserSettingsFile(pOnlyTwitlist) ...@@ -8574,24 +8664,21 @@ function DigDistMsgReader_ReadUserSettingsFile(pOnlyTwitlist)
   
if (!onlyTwitList) if (!onlyTwitList)
{ {
// Open the user settings file, if it exists // Open and read the user settings file, if it exists
var userSettingsFile = new File(gUserSettingsFilename); var userSettingsFile = new File(gUserSettingsFilename);
if (userSettingsFile.open("r")) if (userSettingsFile.open("r"))
{ {
this.userSettings.useEnhReaderScrollbar = userSettingsFile.iniGetValue("BEHAVIOR", "useEnhReaderScrollbar", true); // Variables in this.userSettings are initialized in the DigDistMsgReader constructor. Then, default user
this.userSettings.useIndexedModeForNewscan = userSettingsFile.iniGetValue("BEHAVIOR", "useIndexedModeForNewscan", false); // settings are set when reading DDMsgReader.cfg, which is read before the user settings file. So for each
this.userSettings.listMessagesInReverse = userSettingsFile.iniGetValue("BEHAVIOR", "listMessagesInReverse", false); // user setting (except for twitlist), try to read it from the user settings file, but heave the default be
this.userSettings.quitFromReaderGoesToMsgList = userSettingsFile.iniGetValue("BEHAVIOR", "quitFromReaderGoesToMsgList", false); // whatever it's currently set to.
this.userSettings.enterFromIndexMenuShowsMsgList = userSettingsFile.iniGetValue("BEHAVIOR", "enterFromIndexMenuShowsMsgList", false); for (var settingName in this.userSettings)
//var behavior = userSettingsFile.iniGetObject("BEHAVIOR");
userSettingsFile.close();
/*
for (var prop in behavior)
{ {
var propUpper = prop.toUpperCase(); if (settingName == "twitList") continue;
//if (propUpper == "USEENHREADERSCROLLBAR" && typeof(behavior[prop]) === "boolean") this.userSettings[settingName] = userSettingsFile.iniGetValue("BEHAVIOR", settingName, this.userSettings[settingName]);
} }
*/
userSettingsFile.close();
} }
} }
} }
...@@ -8606,11 +8693,14 @@ function DigDistMsgReader_WriteUserSettingsFile() ...@@ -8606,11 +8693,14 @@ function DigDistMsgReader_WriteUserSettingsFile()
var userSettingsFile = new File(gUserSettingsFilename); var userSettingsFile = new File(gUserSettingsFilename);
if (userSettingsFile.open(userSettingsFile.exists ? "r+" : "w+")) if (userSettingsFile.open(userSettingsFile.exists ? "r+" : "w+"))
{ {
userSettingsFile.iniSetValue("BEHAVIOR", "useEnhReaderScrollbar", this.userSettings.useEnhReaderScrollbar); // Variables in this.userSettings are initialized in the DigDistMsgReader constructor. For each
userSettingsFile.iniSetValue("BEHAVIOR", "useIndexedModeForNewscan", this.userSettings.useIndexedModeForNewscan); // user setting (except for twitlist), save the setting in the user's settings file. The user's
userSettingsFile.iniSetValue("BEHAVIOR", "listMessagesInReverse", this.userSettings.listMessagesInReverse); // twit list is an array that is saved to a separate file.
userSettingsFile.iniSetValue("BEHAVIOR", "quitFromReaderGoesToMsgList", this.userSettings.quitFromReaderGoesToMsgList); for (var settingName in this.userSettings)
userSettingsFile.iniSetValue("BEHAVIOR", "enterFromIndexMenuShowsMsgList", this.userSettings.enterFromIndexMenuShowsMsgList); {
if (settingName == "twitList") continue;
userSettingsFile.iniSetValue("BEHAVIOR", settingName, this.userSettings[settingName]);
}
userSettingsFile.close(); userSettingsFile.close();
writeSucceeded = true; writeSucceeded = true;
} }
...@@ -8950,69 +9040,46 @@ function DigDistMsgReader_GetMsgHdrFilenameFull() ...@@ -8950,69 +9040,46 @@ function DigDistMsgReader_GetMsgHdrFilenameFull()
// //
// Parameters: // Parameters:
// pMsgbase: Optional - A MessageBase object // pMsgbase: Optional - A MessageBase object
// pCheckDeletedAttributes: Optional boolean - Whether or not to check the
// 'deleted' attributes of the messages and not
// count deleted messages. Defaults to false.
// //
// Return value: The number of messages // Return value: The number of messages
function DigDistMsgReader_NumMessages(pMsgbase, pCheckDeletedAttributes) function DigDistMsgReader_NumMessages(pMsgbase)
{
var numMsgs = 0;
if (this.SearchingAndResultObjsDefinedForCurSub())
numMsgs = this.msgSearchHdrs[this.subBoardCode].indexed.length;
else if (this.hdrsForCurrentSubBoard.length > 0)
numMsgs = this.hdrsForCurrentSubBoard.length;
else
{ {
var checkDeletedAttributes = (typeof(pCheckDeletedAttributes) == "boolean" ? pCheckDeletedAttributes : false);
var msgbase = null;
var closeMsgbaseInThisFunc = false; var closeMsgbaseInThisFunc = false;
if ((pMsgbase != null) && (typeof(pMsgbase) === "object")) var msgbase = null;
if (pMsgbase != null && typeof(pMsgbase) === "object")
msgbase = pMsgbase; msgbase = pMsgbase;
else else
{ {
msgbase = new MsgBase(this.subBoardCode);
if (msgbase.open())
closeMsgbaseInThisFunc = true; closeMsgbaseInThisFunc = true;
else msgbase = new MsgBase(this.subBoardCode);
return 0; msgbase.open();
} }
if (msgbase.is_open)
var numMsgs = 0;
if (this.SearchingAndResultObjsDefinedForCurSub())
numMsgs = this.msgSearchHdrs[this.subBoardCode].indexed.length;
else if (this.hdrsForCurrentSubBoard.length > 0)
numMsgs = this.hdrsForCurrentSubBoard.length;
else if ((msgbase != null) && msgbase.is_open)
{ {
//numMsgs = msgbase.total_msgs; //numMsgs = msgbase.total_msgs;
// Count the number of readable messages in the messagebase (i.e., // Count the number of readable messages in the messagebase (i.e.,
// messages that are not deleted, unvalidated, or null headers) // messages that are not deleted, unvalidated, or null headers)
numMsgs = 0; numMsgs = 0;
var totalNumMsgs = msgbase.total_msgs; var indexRecords = msgbase.get_index();
for (var msgIdx = 0; msgIdx < totalNumMsgs; ++msgIdx) if (indexRecords != null)
{
if (isReadableMsgHdr(msgbase.get_msg_index(true, msgIdx, false), this.subBoardCode))
++numMsgs;
}
}
// If the caller wants to check the deleted attributes, then do so.
if ((numMsgs > 0) && checkDeletedAttributes)
{
var msgHdr;
var originalNumMsgs = numMsgs;
for (var msgIdx = 0; msgIdx < originalNumMsgs; ++msgIdx)
{
msgHdr = this.GetMsgHdrByIdx(msgIdx);
if (msgHdr == null || (msgHdr.attr & MSG_DELETE) == MSG_DELETE)
{ {
--numMsgs; for (var i = 0; i < indexRecords.length; ++i)
if (numMsgs < 0)
{ {
numMsgs = 0; if (isReadableMsgHdr(indexRecords[i], this.subBoardCode))
break; ++numMsgs;
}
}
} }
} }
if (closeMsgbaseInThisFunc) if (closeMsgbaseInThisFunc)
msgbase.close(); msgbase.close();
}
}
   
return numMsgs; return numMsgs;
} }
...@@ -9219,7 +9286,29 @@ function DumpMsgHdr(pSubCode, pMsgNum, pExpandFields, pGetVoteInfo) ...@@ -9219,7 +9286,29 @@ function DumpMsgHdr(pSubCode, pMsgNum, pExpandFields, pGetVoteInfo)
// Return value: The message's index. On error, returns -1. // Return value: The message's index. On error, returns -1.
function DigDistMsgReader_AbsMsgNumToIdx(pMsgNum) function DigDistMsgReader_AbsMsgNumToIdx(pMsgNum)
{ {
return absMsgNumToIdx(this.subBoardCode, pMsgNum); //return absMsgNumToIdx(this.subBoardCode, pMsgNum);
//if (this.doingNewscan && this.userSettings.newscanOnlyShowNewMsgs)
// Check this.msgNumToIdxMap and/or this.hdrsForCurrentSubBoard if
// they're populated and return the index from that. Otherwise,
// check the messagebase directly.
var msgIdx = -1;
if (this.msgNumToIdxMap.hasOwnProperty(pMsgNum))
msgIdx = this.msgNumToIdxMap[pMsgNum];
else if (this.hdrsForCurrentSubBoard.length > 0)
{
for (var i = 0; i < this.hdrsForCurrentSubBoard.length; ++i)
{
if (this.hdrsForCurrentSubBoard[i].number == pMsgNum)
{
msgIdx = this.hdrsForCurrentSubBoard[i].number;
break;
}
}
}
else
msgIdx = absMsgNumToIdx(this.subBoardCode, pMsgNum);
return msgIdx;
} }
   
// For the DigDistMsgReader class: Takes a message index and returns // For the DigDistMsgReader class: Takes a message index and returns
...@@ -9232,12 +9321,23 @@ function DigDistMsgReader_AbsMsgNumToIdx(pMsgNum) ...@@ -9232,12 +9321,23 @@ function DigDistMsgReader_AbsMsgNumToIdx(pMsgNum)
function DigDistMsgReader_IdxToAbsMsgNum(pMsgIdx) function DigDistMsgReader_IdxToAbsMsgNum(pMsgIdx)
{ {
var msgIdx = -1; var msgIdx = -1;
// Check this.hdrsForCurrentSubBoard if it's populated and return
// the message number from the header at the given index if exists.
// therwise, check the messagebase directly.
if (this.hdrsForCurrentSubBoard.length > 0)
{
if (pMsgIdx >= 0 && pMsgIdx < this.hdrsForCurrentSubBoard.length)
msgIdx = this.hdrsForCurrentSubBoard[pMsgIdx].number;
}
else
{
var msgbase = new MsgBase(this.subBoardCode); var msgbase = new MsgBase(this.subBoardCode);
if (msgbase.open()) if (msgbase.open())
{ {
msgIdx = idxToAbsMsgNum(msgbase, pMsgIdx); msgIdx = idxToAbsMsgNum(msgbase, pMsgIdx);
msgbase.close(); msgbase.close();
} }
}
return msgIdx; return msgIdx;
} }
   
...@@ -9912,12 +10012,12 @@ function DigDistMsgReader_ReplyToMsg(pMsgHdr, pMsgText, pPrivate, pMsgIdx) ...@@ -9912,12 +10012,12 @@ function DigDistMsgReader_ReplyToMsg(pMsgHdr, pMsgText, pPrivate, pMsgIdx)
msgWasDeleted: false msgWasDeleted: false
}; };
   
if ((pMsgHdr == null) || (typeof(pMsgHdr) != "object")) if (pMsgHdr == null || typeof(pMsgHdr) !== "object")
return retObj; return retObj;
   
// If the "no-reply" attribute is enabled for the message, then don't // If the "no-reply" attribute is enabled for the message, then don't
// let the user rpely. // let the user rpely.
if ((pMsgHdr.attr & MSG_NOREPLY) == MSG_NOREPLY) if (Boolean(pMsgHdr.attr & MSG_NOREPLY))
{ {
console.crlf(); console.crlf();
console.print("\x01n\x01y\x01hReplies are not allowed for this message."); console.print("\x01n\x01y\x01hReplies are not allowed for this message.");
...@@ -10056,10 +10156,23 @@ function DigDistMsgReader_ReplyToMsg(pMsgHdr, pMsgText, pPrivate, pMsgIdx) ...@@ -10056,10 +10156,23 @@ function DigDistMsgReader_ReplyToMsg(pMsgHdr, pMsgText, pPrivate, pMsgIdx)
// would populate the search results, then search the last messages to // would populate the search results, then search the last messages to
// include the user's reply in the message matches or other new messages // include the user's reply in the message matches or other new messages
// that may have been posted that match the user's search. // that may have been posted that match the user's search.
// TODO: Make sure this works for a newscan & new-to-user scan
if (retObj.postSucceeded && msgbaseReOpened && (msgbase.total_msgs > numMessagesBefore)) if (retObj.postSucceeded && msgbaseReOpened && (msgbase.total_msgs > numMessagesBefore))
{ {
if (this.SearchTypePopulatesSearchResults() && this.msgSearchHdrs.hasOwnProperty(this.subBoardCode)) // If doing a newscan and the user setting for only showing new messages during a newscan
// is enabled, then get the last message header (which should be the message the user
// just posted) and add it to the cached array of message headers
if (this.doingNewscan && this.userSettings.newscanOnlyShowNewMsgs)
{
var lastMsgHdr = msgbase.get_msg_header(false, msgbase.last_msg);
if (msgIsFromUser(lastMsgHdr))
{
this.hdrsForCurrentSubBoard.push(lastMsgHdr);
this.msgNumToIdxMap[lastMsgHdr.number] = this.hdrsForCurrentSubBoard.length - 1;
}
}
// If doing a search and the search headers has the current sub-board, then add the posted
// message to the search headers
else if (this.SearchTypePopulatesSearchResults() && this.msgSearchHdrs.hasOwnProperty(this.subBoardCode))
{ {
if (!this.msgSearchHdrs.hasOwnProperty(this.subBoardCode)) if (!this.msgSearchHdrs.hasOwnProperty(this.subBoardCode))
this.msgSearchHdrs[this.subBoardCode] = searchMsgbase(this.subBoardCode, this.searchType, this.searchString, this.readingPersonalEmailFromUser); this.msgSearchHdrs[this.subBoardCode] = searchMsgbase(this.subBoardCode, this.searchType, this.searchString, this.readingPersonalEmailFromUser);
...@@ -10074,11 +10187,16 @@ function DigDistMsgReader_ReplyToMsg(pMsgHdr, pMsgText, pPrivate, pMsgIdx) ...@@ -10074,11 +10187,16 @@ function DigDistMsgReader_ReplyToMsg(pMsgHdr, pMsgText, pPrivate, pMsgIdx)
} }
} }
} }
// If we have cached message headers, add the user's just-posted message
else if (this.hdrsForCurrentSubBoard.length > 0) else if (this.hdrsForCurrentSubBoard.length > 0)
{ {
// Pass false to get_all_msg_headers() to tell it not to return vote messages //this.FilterMsgHdrsIntoHdrsForCurrentSubBoard(msgbase.get_all_msg_headers(false), true);
// (the parameter was introduced in Synchronet 3.17+) var lastMsgHdr = msgbase.get_msg_header(false, msgbase.last_msg);
this.FilterMsgHdrsIntoHdrsForCurrentSubBoard(msgbase.get_all_msg_headers(true), true); if (msgIsFromUser(lastMsgHdr))
{
this.hdrsForCurrentSubBoard.push(lastMsgHdr);
this.msgNumToIdxMap[lastMsgHdr.number] = this.hdrsForCurrentSubBoard.length - 1;
}
} }
} }
} }
...@@ -10816,14 +10934,14 @@ function DigDistMsgReader_MessageIsLastFromUser(pOffset) ...@@ -10816,14 +10934,14 @@ function DigDistMsgReader_MessageIsLastFromUser(pOffset)
// is, then look for the last message posted by the logged-in user and // is, then look for the last message posted by the logged-in user and
// if found, see if that message has the same offset as the offset // if found, see if that message has the same offset as the offset
// passed in. // passed in.
var msgHdr = msgbase.get_msg_index(true, pOffset, false); var msgIdx = msgbase.get_msg_index(true, pOffset, false);
if (userHandleAliasNameMatch(msgHdr.to)) if (msgIdx != null && userHandleAliasNameMatch(msgIdx.to))
{ {
var lastMsgOffsetFromUser = -1; var lastMsgOffsetFromUser = -1;
for (var msgOffset = msgbase.total_msgs-1; (msgOffset >= pOffset) && (lastMsgOffsetFromUser == -1); --msgOffset) for (var msgOffset = msgbase.total_msgs-1; (msgOffset >= pOffset) && (lastMsgOffsetFromUser == -1); --msgOffset)
{ {
msgHdr = msgbase.get_msg_index(true, msgOffset, false); msgIdx = msgbase.get_msg_index(true, msgOffset, false);
if (userHandleAliasNameMatch(msgHdr.to)) if (msgIdx != null && userHandleAliasNameMatch(msgIdx.to))
lastMsgOffsetFromUser = msgOffset; lastMsgOffsetFromUser = msgOffset;
} }
// See if the passed-in offset is the last message we found from // See if the passed-in offset is the last message we found from
...@@ -12407,9 +12525,9 @@ function DigDistMsgReader_GetExtdMsgHdrInfo(pSubCodeOrMsgbase, pMsgNum, pKludgeO ...@@ -12407,9 +12525,9 @@ function DigDistMsgReader_GetExtdMsgHdrInfo(pSubCodeOrMsgbase, pMsgNum, pKludgeO
// The message header retrieved that way might not have vote information, // The message header retrieved that way might not have vote information,
// so copy any additional header information from this.hdrsForCurrentSubBoard // so copy any additional header information from this.hdrsForCurrentSubBoard
// if there's a header there for this message. // if there's a header there for this message.
if (this.hdrsForCurrentSubBoardByMsgNum.hasOwnProperty(pMsgNum)) if (this.msgNumToIdxMap.hasOwnProperty(pMsgNum))
{ {
var tmpHdrIdx = this.hdrsForCurrentSubBoardByMsgNum[pMsgNum]; var tmpHdrIdx = this.msgNumToIdxMap[pMsgNum];
if (this.hdrsForCurrentSubBoard.hasOwnProperty(tmpHdrIdx)) if (this.hdrsForCurrentSubBoard.hasOwnProperty(tmpHdrIdx))
{ {
for (var hdrProp in this.hdrsForCurrentSubBoard[tmpHdrIdx]) for (var hdrProp in this.hdrsForCurrentSubBoard[tmpHdrIdx])
...@@ -13143,7 +13261,7 @@ function DigDistMsgReader_GetLastReadMsgIdxAndNum(pMailStartFromFirst) ...@@ -13143,7 +13261,7 @@ function DigDistMsgReader_GetLastReadMsgIdxAndNum(pMailStartFromFirst)
this.hdrsForCurrentSubBoard = []; this.hdrsForCurrentSubBoard = [];
// hdrsForCurrentSubBoardByMsgNum is an object that maps absolute message numbers // hdrsForCurrentSubBoardByMsgNum is an object that maps absolute message numbers
// to their index to hdrsForCurrentSubBoard // to their index to hdrsForCurrentSubBoard
this.hdrsForCurrentSubBoardByMsgNum = {}; this.msgNumToIdxMap = {};
*/ */
// Sanity checking for retObj.lastReadMsgIdx (note: this function should return -1 if // Sanity checking for retObj.lastReadMsgIdx (note: this function should return -1 if
// there is no last read message). // there is no last read message).
...@@ -13975,10 +14093,18 @@ function DigDistMsgReader_DoUserSettings_Scrollable(pDrawBottomhelpLineFn) ...@@ -13975,10 +14093,18 @@ function DigDistMsgReader_DoUserSettings_Scrollable(pDrawBottomhelpLineFn)
if (this.userSettings.listMessagesInReverse) if (this.userSettings.listMessagesInReverse)
optionBox.chgCharInTextItem(LIST_MESSAGES_IN_REVERSE_OPT_INDEX, checkIdx, CHECK_CHAR); optionBox.chgCharInTextItem(LIST_MESSAGES_IN_REVERSE_OPT_INDEX, checkIdx, CHECK_CHAR);
   
const NEWSCAN_ONLY_SHOW_NEW_MSGS_INDEX = optionBox.addTextItem(format(optionFormatStr, "Newscan: Only show new messages"));
if (this.userSettings.newscanOnlyShowNewMsgs)
optionBox.chgCharInTextItem(NEWSCAN_ONLY_SHOW_NEW_MSGS_INDEX, checkIdx, CHECK_CHAR);
const INDEXED_MODE_NEWSCAN_OPT_INDEX = optionBox.addTextItem(format(optionFormatStr, "Use indexed mode for newscan")); const INDEXED_MODE_NEWSCAN_OPT_INDEX = optionBox.addTextItem(format(optionFormatStr, "Use indexed mode for newscan"));
if (this.userSettings.useIndexedModeForNewscan) if (this.userSettings.useIndexedModeForNewscan)
optionBox.chgCharInTextItem(INDEXED_MODE_NEWSCAN_OPT_INDEX, checkIdx, CHECK_CHAR); optionBox.chgCharInTextItem(INDEXED_MODE_NEWSCAN_OPT_INDEX, checkIdx, CHECK_CHAR);
   
const INDEXED_MODE_MENU_SNAP_TO_NEW_MSGS_OPT_INDEX = optionBox.addTextItem(format(optionFormatStr, "Index menu: Snap to sub-boards w/ new messages"));
if (this.userSettings.indexedModeMenuSnapToFirstWithNew)
optionBox.chgCharInTextItem(INDEXED_MODE_MENU_SNAP_TO_NEW_MSGS_OPT_INDEX, checkIdx, CHECK_CHAR);
const INDEX_NEWSCAN_ENTER_SHOWS_MSG_LIST_OPT_INDEX = optionBox.addTextItem(format(optionFormatStr, "Index menu: Enter shows message list")); const INDEX_NEWSCAN_ENTER_SHOWS_MSG_LIST_OPT_INDEX = optionBox.addTextItem(format(optionFormatStr, "Index menu: Enter shows message list"));
if (this.userSettings.enterFromIndexMenuShowsMsgList) if (this.userSettings.enterFromIndexMenuShowsMsgList)
optionBox.chgCharInTextItem(INDEX_NEWSCAN_ENTER_SHOWS_MSG_LIST_OPT_INDEX, checkIdx, CHECK_CHAR); optionBox.chgCharInTextItem(INDEX_NEWSCAN_ENTER_SHOWS_MSG_LIST_OPT_INDEX, checkIdx, CHECK_CHAR);
...@@ -13991,7 +14117,9 @@ function DigDistMsgReader_DoUserSettings_Scrollable(pDrawBottomhelpLineFn) ...@@ -13991,7 +14117,9 @@ function DigDistMsgReader_DoUserSettings_Scrollable(pDrawBottomhelpLineFn)
var optionToggles = {}; var optionToggles = {};
optionToggles[ENH_SCROLLBAR_OPT_INDEX] = this.userSettings.useEnhReaderScrollbar; optionToggles[ENH_SCROLLBAR_OPT_INDEX] = this.userSettings.useEnhReaderScrollbar;
optionToggles[LIST_MESSAGES_IN_REVERSE_OPT_INDEX] = this.userSettings.listMessagesInReverse; optionToggles[LIST_MESSAGES_IN_REVERSE_OPT_INDEX] = this.userSettings.listMessagesInReverse;
optionToggles[NEWSCAN_ONLY_SHOW_NEW_MSGS_INDEX] = this.userSettings.newscanOnlyShowNewMsgs;
optionToggles[INDEXED_MODE_NEWSCAN_OPT_INDEX] = this.userSettings.useIndexedModeForNewscan; optionToggles[INDEXED_MODE_NEWSCAN_OPT_INDEX] = this.userSettings.useIndexedModeForNewscan;
optionToggles[INDEXED_MODE_MENU_SNAP_TO_NEW_MSGS_OPT_INDEX] = this.userSettings.indexedModeMenuSnapToFirstWithNew;
optionToggles[INDEX_NEWSCAN_ENTER_SHOWS_MSG_LIST_OPT_INDEX] = this.userSettings.enterFromIndexMenuShowsMsgList; optionToggles[INDEX_NEWSCAN_ENTER_SHOWS_MSG_LIST_OPT_INDEX] = this.userSettings.enterFromIndexMenuShowsMsgList;
optionToggles[READER_QUIT_TO_MSG_LIST_OPT_INDEX] = this.userSettings.quitFromReaderGoesToMsgList; optionToggles[READER_QUIT_TO_MSG_LIST_OPT_INDEX] = this.userSettings.quitFromReaderGoesToMsgList;
   
...@@ -14025,9 +14153,15 @@ function DigDistMsgReader_DoUserSettings_Scrollable(pDrawBottomhelpLineFn) ...@@ -14025,9 +14153,15 @@ function DigDistMsgReader_DoUserSettings_Scrollable(pDrawBottomhelpLineFn)
case LIST_MESSAGES_IN_REVERSE_OPT_INDEX: case LIST_MESSAGES_IN_REVERSE_OPT_INDEX:
this.readerObj.userSettings.listMessagesInReverse = !this.readerObj.userSettings.listMessagesInReverse; this.readerObj.userSettings.listMessagesInReverse = !this.readerObj.userSettings.listMessagesInReverse;
break; break;
case NEWSCAN_ONLY_SHOW_NEW_MSGS_INDEX:
this.readerObj.userSettings.newscanOnlyShowNewMsgs = !this.readerObj.userSettings.newscanOnlyShowNewMsgs;
break;
case INDEXED_MODE_NEWSCAN_OPT_INDEX: case INDEXED_MODE_NEWSCAN_OPT_INDEX:
this.readerObj.userSettings.useIndexedModeForNewscan = !this.readerObj.userSettings.useIndexedModeForNewscan; this.readerObj.userSettings.useIndexedModeForNewscan = !this.readerObj.userSettings.useIndexedModeForNewscan;
break; break;
case INDEXED_MODE_MENU_SNAP_TO_NEW_MSGS_OPT_INDEX:
this.readerObj.userSettings.indexedModeMenuSnapToFirstWithNew = !this.readerObj.userSettings.indexedModeMenuSnapToFirstWithNew;
break;
case INDEX_NEWSCAN_ENTER_SHOWS_MSG_LIST_OPT_INDEX: case INDEX_NEWSCAN_ENTER_SHOWS_MSG_LIST_OPT_INDEX:
this.readerObj.userSettings.enterFromIndexMenuShowsMsgList = !this.readerObj.userSettings.enterFromIndexMenuShowsMsgList; this.readerObj.userSettings.enterFromIndexMenuShowsMsgList = !this.readerObj.userSettings.enterFromIndexMenuShowsMsgList;
break; break;
...@@ -14119,10 +14253,11 @@ function DigDistMsgReader_DoUserSettings_Traditional() ...@@ -14119,10 +14253,11 @@ function DigDistMsgReader_DoUserSettings_Traditional()
}; };
   
var LIST_MESSAGES_IN_REVERSE_OPT_NUM = 1; var LIST_MESSAGES_IN_REVERSE_OPT_NUM = 1;
var USE_INDEXED_MODE_FOR_NEWSCAN_OPT_NUM = 2; var NEWSCAN_ONLY_SHOW_NEW_MSGS_OPT_NUM = 2;
var INDEX_NEWSCAN_ENTER_SHOWS_MSG_LIST_OPT_NUM = 3; var USE_INDEXED_MODE_FOR_NEWSCAN_OPT_NUM = 3;
var READER_QUIT_TO_MSG_LIST_OPT_NUM = 4; var INDEX_NEWSCAN_ENTER_SHOWS_MSG_LIST_OPT_NUM = 4;
var USER_TWITLIST_OPT_NUM = 5; var READER_QUIT_TO_MSG_LIST_OPT_NUM = 5;
var USER_TWITLIST_OPT_NUM = 6;
var HIGHEST_CHOICE_NUM = USER_TWITLIST_OPT_NUM; var HIGHEST_CHOICE_NUM = USER_TWITLIST_OPT_NUM;
   
console.crlf(); console.crlf();
...@@ -14130,6 +14265,7 @@ function DigDistMsgReader_DoUserSettings_Traditional() ...@@ -14130,6 +14265,7 @@ function DigDistMsgReader_DoUserSettings_Traditional()
var wordRemainingAttrs = "\x01c"; var wordRemainingAttrs = "\x01c";
console.print(colorFirstCharAndRemainingCharsInWords("User Settings", wordFirstCharAttrs, wordRemainingAttrs) + "\r\n"); console.print(colorFirstCharAndRemainingCharsInWords("User Settings", wordFirstCharAttrs, wordRemainingAttrs) + "\r\n");
printTradUserSettingOption(LIST_MESSAGES_IN_REVERSE_OPT_NUM, "List messages in reverse", wordFirstCharAttrs, wordRemainingAttrs); printTradUserSettingOption(LIST_MESSAGES_IN_REVERSE_OPT_NUM, "List messages in reverse", wordFirstCharAttrs, wordRemainingAttrs);
printTradUserSettingOption(NEWSCAN_ONLY_SHOW_NEW_MSGS_OPT_NUM, "Only show new messages for newscan", wordFirstCharAttrs, wordRemainingAttrs);
printTradUserSettingOption(USE_INDEXED_MODE_FOR_NEWSCAN_OPT_NUM, "Use Indexed mode for newscan", wordFirstCharAttrs, wordRemainingAttrs); printTradUserSettingOption(USE_INDEXED_MODE_FOR_NEWSCAN_OPT_NUM, "Use Indexed mode for newscan", wordFirstCharAttrs, wordRemainingAttrs);
printTradUserSettingOption(INDEX_NEWSCAN_ENTER_SHOWS_MSG_LIST_OPT_NUM, "Index: Selection shows message list", wordFirstCharAttrs, wordRemainingAttrs); printTradUserSettingOption(INDEX_NEWSCAN_ENTER_SHOWS_MSG_LIST_OPT_NUM, "Index: Selection shows message list", wordFirstCharAttrs, wordRemainingAttrs);
printTradUserSettingOption(READER_QUIT_TO_MSG_LIST_OPT_NUM, "Quitting From reader goes to message list", wordFirstCharAttrs, wordRemainingAttrs); printTradUserSettingOption(READER_QUIT_TO_MSG_LIST_OPT_NUM, "Quitting From reader goes to message list", wordFirstCharAttrs, wordRemainingAttrs);
...@@ -14150,6 +14286,11 @@ function DigDistMsgReader_DoUserSettings_Traditional() ...@@ -14150,6 +14286,11 @@ function DigDistMsgReader_DoUserSettings_Traditional()
this.userSettings.listMessagesInReverse = !console.noyes("List messages in reverse"); this.userSettings.listMessagesInReverse = !console.noyes("List messages in reverse");
userSettingsChanged = (this.userSettings.listMessagesInReverse != oldListMsgsInReverseSetting); userSettingsChanged = (this.userSettings.listMessagesInReverse != oldListMsgsInReverseSetting);
break; break;
case NEWSCAN_ONLY_SHOW_NEW_MSGS_OPT_NUM:
var oldOnlyShowNewMsgsSetting = this.userSettings.newscanOnlyShowNewMsgs;
this.userSettings.newscanOnlyShowNewMsgs = !console.noyes("Only show new messages for newscan");
userSettingsChanged = (this.userSettings.newscanOnlyShowNewMsgs != oldOnlyShowNewMsgsSetting);
break;
case USE_INDEXED_MODE_FOR_NEWSCAN_OPT_NUM: case USE_INDEXED_MODE_FOR_NEWSCAN_OPT_NUM:
var oldIndexedModeNewscanSetting = this.userSettings.useIndexedModeForNewscan; var oldIndexedModeNewscanSetting = this.userSettings.useIndexedModeForNewscan;
this.userSettings.useIndexedModeForNewscan = !console.noyes("Use indexed mode for newscan-all"); this.userSettings.useIndexedModeForNewscan = !console.noyes("Use indexed mode for newscan-all");
...@@ -14242,9 +14383,13 @@ function DigDistMsgReader_DoIndexedMode(pScanScope) ...@@ -14242,9 +14383,13 @@ function DigDistMsgReader_DoIndexedMode(pScanScope)
var continueOn = true; var continueOn = true;
while (continueOn) while (continueOn)
{ {
// A backup for the number of new messages so we can see if it changes (due to the user reading messages)
var origNumNewMessages = 0;
// Let the user choose a sub-board, and if their choice is valid, // Let the user choose a sub-board, and if their choice is valid,
// let them read the sub-board. // let them read the sub-board.
var indexRetObj = this.IndexedModeChooseSubBoard(clearScreenForMenu, drawMenu, writeBottomHelpLine, pScanScope); var indexRetObj = this.IndexedModeChooseSubBoard(clearScreenForMenu, drawMenu, writeBottomHelpLine, pScanScope);
if (typeof(indexRetObj.numNewMsgs) === "number")
origNumNewMessages = indexRetObj.numNewMsgs;
var userChoseAValidSubBoard = (typeof(indexRetObj.chosenSubCode) === "string" && msg_area.sub.hasOwnProperty(indexRetObj.chosenSubCode)); var userChoseAValidSubBoard = (typeof(indexRetObj.chosenSubCode) === "string" && msg_area.sub.hasOwnProperty(indexRetObj.chosenSubCode));
if (userChoseAValidSubBoard) if (userChoseAValidSubBoard)
{ {
...@@ -14261,17 +14406,32 @@ function DigDistMsgReader_DoIndexedMode(pScanScope) ...@@ -14261,17 +14406,32 @@ function DigDistMsgReader_DoIndexedMode(pScanScope)
console.cleartoeol("\x01n"); console.cleartoeol("\x01n");
console.print("\x01n\x01cLoading\x01h...\x01n"); console.print("\x01n\x01cLoading\x01h...\x01n");
} }
this.PopulateHdrsForCurrentSubBoard(); // If the user has the option to only show new messages for a newscan and there are
// new messages, then populate the sub-board with only the new message from their
// scan pointer; otherwise, populate with all message headers for the sub-board.
if (this.userSettings.newscanOnlyShowNewMsgs && indexRetObj.numNewMsgs > 0)
this.PopulateHdrsForCurrentSubBoard(POPULATE_MSG_HDRS_FROM_SCAN_PTR);
else
this.PopulateHdrsForCurrentSubBoard(POPULATE_NEWSCAN_FORCE_GET_ALL_HDRS);
} }
else else
{ {
this.hdrsForCurrentSubBoard = msgHdrsCache[indexRetObj.chosenSubCode].hdrsForCurrentSubBoard; this.hdrsForCurrentSubBoard = msgHdrsCache[indexRetObj.chosenSubCode].hdrsForCurrentSubBoard;
this.hdrsForCurrentSubBoardByMsgNum = msgHdrsCache[indexRetObj.chosenSubCode].hdrsForCurrentSubBoardByMsgNum; this.msgNumToIdxMap = msgHdrsCache[indexRetObj.chosenSubCode].hdrsForCurrentSubBoardByMsgNum;
} }
var numMessages = this.NumMessages(null, true); // Decide the index of the starting message: If there are no new messages, show the last
var startIdx = numMessages - indexRetObj.numNewMsgs; // messages. Otherwise, if only showing new messages, show the first messages.
// Otherwise, calculate the starting index.
var numMessages = this.NumMessages();
var startIdx = 0;
if (indexRetObj.numNewMsgs == 0)
startIdx = numMessages - 1;
else if (!this.userSettings.newscanOnlyShowNewMsgs)
{
startIdx = numMessages > 0 ? numMessages - indexRetObj.numNewMsgs : 0;
if (startIdx < 0) if (startIdx < 0)
startIdx = numMessages - 1; startIdx = numMessages - 1;
}
// If the user chose to view the message list, display the message list to let the user // If the user chose to view the message list, display the message list to let the user
// choose a message to read. Otherwise, start reader mode. // choose a message to read. Otherwise, start reader mode.
if (indexRetObj.viewMsgList) if (indexRetObj.viewMsgList)
...@@ -14291,7 +14451,7 @@ function DigDistMsgReader_DoIndexedMode(pScanScope) ...@@ -14291,7 +14451,7 @@ function DigDistMsgReader_DoIndexedMode(pScanScope)
{ {
msgHdrsCache[indexRetObj.chosenSubCode] = { msgHdrsCache[indexRetObj.chosenSubCode] = {
hdrsForCurrentSubBoard: this.hdrsForCurrentSubBoard, hdrsForCurrentSubBoard: this.hdrsForCurrentSubBoard,
hdrsForCurrentSubBoardByMsgNum: this.hdrsForCurrentSubBoardByMsgNum hdrsForCurrentSubBoardByMsgNum: this.msgNumToIdxMap
}; };
} }
} }
...@@ -14312,7 +14472,7 @@ function DigDistMsgReader_DoIndexedMode(pScanScope) ...@@ -14312,7 +14472,7 @@ function DigDistMsgReader_DoIndexedMode(pScanScope)
{ {
msgHdrsCache[indexRetObj.chosenSubCode] = { msgHdrsCache[indexRetObj.chosenSubCode] = {
hdrsForCurrentSubBoard: this.hdrsForCurrentSubBoard, hdrsForCurrentSubBoard: this.hdrsForCurrentSubBoard,
hdrsForCurrentSubBoardByMsgNum: this.hdrsForCurrentSubBoardByMsgNum hdrsForCurrentSubBoardByMsgNum: this.msgNumToIdxMap
}; };
} }
/* /*
...@@ -14326,6 +14486,18 @@ function DigDistMsgReader_DoIndexedMode(pScanScope) ...@@ -14326,6 +14486,18 @@ function DigDistMsgReader_DoIndexedMode(pScanScope)
} }
*/ */
} }
// If the number of new messages has changed (due to reading the sub-board),
// then empty the header caches so that we'll fully populate them next time
// the user chooses the same sub-board
var latestPostInfo = getLatestPostTimestampAndNumNewMsgs(indexRetObj.chosenSubCode);
if (latestPostInfo.numNewMsgs != origNumNewMessages)
{
this.hdrsForCurrentSubBoard = [];
this.msgNumToIdxMap = {};
if (msgHdrsCache.hasOwnProperty(indexRetObj.chosenSubCode))
delete msgHdrsCache[indexRetObj.chosenSubCode];
}
} }
else else
{ {
...@@ -14523,37 +14695,37 @@ function DigDistMsgReader_IndexedModeChooseSubBoard(pClearScreen, pDrawMenu, pDi ...@@ -14523,37 +14695,37 @@ function DigDistMsgReader_IndexedModeChooseSubBoard(pClearScreen, pDrawMenu, pDi
}); });
} }
} }
// If there are no items on the menu, then show a message and return
if (this.indexedModeMenu.NumItems() == 0)
{
console.print("\x01n" + this.text.msgScanCompleteText + "\x01n");
console.crlf();
console.pause();
return retObj;
}
// If we've saved the index of the selected item in the menu, then set it back in the menu, if it's // If we've saved the index of the selected item in the menu, then set it back in the menu, if it's
// valid. This is done because the list of items is cleared each time this function is called. // valid. This is done because the list of items is cleared each time this function is called.
if (typeof(DigDistMsgReader_IndexedModeChooseSubBoard.selectedItemIdx) === "number") if (typeof(DigDistMsgReader_IndexedModeChooseSubBoard.selectedItemIdx) === "number")
{ {
if (DigDistMsgReader_IndexedModeChooseSubBoard.selectedItemIdx >= 0 && var savedItemIdx = DigDistMsgReader_IndexedModeChooseSubBoard.selectedItemIdx;
DigDistMsgReader_IndexedModeChooseSubBoard.selectedItemIdx < this.indexedModeMenu.NumItems()) if (savedItemIdx >= 0 && savedItemIdx < this.indexedModeMenu.NumItems())
{ setIndexedSubBoardMenuSelectedItemIdx(this.indexedModeMenu, savedItemIdx);
this.indexedModeMenu.SetSelectedItemIdx(DigDistMsgReader_IndexedModeChooseSubBoard.selectedItemIdx);
// If the indexed menu has more items than will fit on the screen & isn't on the last
// page, then set the top item index to one before the selected index (if >0) or the
// same as the selected item index.
var selectedItemIsFirst = this.indexedModeMenu.selectedItemIdx == this.indexedModeMenu.topItemIdx;
var selectedItemOnLastPage = DigDistMsgReader_IndexedModeChooseSubBoard.selectedItemIdx >= this.indexedModeMenu.GetTopItemIdxOfLastPage();
var moreThanOneScreenfulOfItems = this.indexedModeMenu.NumItems() > console.screen_columns - 2;
// Checking if the selected item index is on the first page
var numItems = this.indexedModeMenu.NumItems();
var numItemsPerPage = this.indexedModeMenu.GetNumItemsPerPage();
var lastItemIdxForFirstPage = (numItems > numItemsPerPage ? numItemsPerPage - 1 : numItems - 1);
var selectedItemIsOnFirstPage = (this.indexedModeMenu.selectedItemIdx >= 0 && this.indexedModeMenu.selectedItemIdx <= lastItemIdxForFirstPage);
if (!selectedItemIsFirst && !selectedItemOnLastPage && moreThanOneScreenfulOfItems && !selectedItemIsOnFirstPage)
{
if (this.indexedModeMenu.selectedItemIdx > 0)
this.indexedModeMenu.topItemIdx = this.indexedModeMenu.selectedItemIdx - 1;
else
this.indexedModeMenu.topItemIdx = this.indexedModeMenu.selectedItemIdx;
}
}
else else
DigDistMsgReader_IndexedModeChooseSubBoard.selectedItemIdx = 0; DigDistMsgReader_IndexedModeChooseSubBoard.selectedItemIdx = 0;
} }
   
// If the user setting to "snap" to the first sub-board with new messages is enabled, then set that
// as the selected item index.
if (this.userSettings.indexedModeMenuSnapToFirstWithNew)
{
var foundMenuItem = indexedSubMenuSetSelectedNextWithnNewMsgs(this.indexedModeMenu, this.indexedModeMenu.selectedItemIdx, this.indexedModeMenu.NumItems());
// If we haven't found a sub-board with new messages and we didn't start at the
// first, then wrap around
if (!foundMenuItem && this.indexedModeMenu.selectedItemIdx > 0)
indexedSubMenuSetSelectedNextWithnNewMsgs(this.indexedModeMenu, 0, this.indexedModeMenu.selectedItemIdx);
}
// Clear the screen, if desired // Clear the screen, if desired
if (clearScreen) if (clearScreen)
console.clear("\x01n"); console.clear("\x01n");
...@@ -14593,7 +14765,9 @@ function DigDistMsgReader_IndexedModeChooseSubBoard(pClearScreen, pDrawMenu, pDi ...@@ -14593,7 +14765,9 @@ function DigDistMsgReader_IndexedModeChooseSubBoard(pClearScreen, pDrawMenu, pDi
var menuRetval = this.indexedModeMenu.GetVal(drawMenu); var menuRetval = this.indexedModeMenu.GetVal(drawMenu);
// Show the menu and get the user's choice // Show the menu and get the user's choice
retObj.lastUserInput = this.indexedModeMenu.lastUserInput; retObj.lastUserInput = this.indexedModeMenu.lastUserInput;
var lastUserInputUpper = this.indexedModeMenu.lastUserInput.toUpperCase(); var lastUserInputUpper = "";
if (typeof(this.indexedModeMenu.lastUserInput) === "string")
lastUserInputUpper = this.indexedModeMenu.lastUserInput.toUpperCase();
if (menuRetval != null) if (menuRetval != null)
{ {
retObj.chosenSubCode = menuRetval.subCode; retObj.chosenSubCode = menuRetval.subCode;
...@@ -14651,6 +14825,70 @@ function DigDistMsgReader_IndexedModeChooseSubBoard(pClearScreen, pDrawMenu, pDi ...@@ -14651,6 +14825,70 @@ function DigDistMsgReader_IndexedModeChooseSubBoard(pClearScreen, pDrawMenu, pDi
return retObj; return retObj;
} }
   
// Helper for DigDistMsgReader_IndexedModeChooseSubBoard(): Sets the selected item in the
// indexed mode sub-board menu and adjusts the menu items to be in a good location
//
// Parameters:
// pIndexSubBoardMenu: The indexed sub-board menu
// pSelectedItemIdx: The index of the item to set as the selected item
function setIndexedSubBoardMenuSelectedItemIdx(pIndexSubBoardMenu, pSelectedItemIdx)
{
if (pSelectedItemIdx >= 0 && pSelectedItemIdx < pIndexSubBoardMenu.NumItems())
{
pIndexSubBoardMenu.SetSelectedItemIdx(pSelectedItemIdx);
// If the indexed menu has more items than will fit on the screen & isn't on the last
// page, then set the top item index to one before the selected index (if >0) or the
// same as the selected item index.
var selectedItemIsFirst = pIndexSubBoardMenu.selectedItemIdx == pIndexSubBoardMenu.topItemIdx;
var selectedItemOnLastPage = pSelectedItemIdx >= pIndexSubBoardMenu.GetTopItemIdxOfLastPage();
var moreThanOneScreenfulOfItems = pIndexSubBoardMenu.NumItems() > console.screen_columns - 2;
// Checking if the selected item index is on the first page
var numItems = pIndexSubBoardMenu.NumItems();
var numItemsPerPage = pIndexSubBoardMenu.GetNumItemsPerPage();
var lastItemIdxForFirstPage = (numItems > numItemsPerPage ? numItemsPerPage - 1 : numItems - 1);
var selectedItemIsOnFirstPage = (pIndexSubBoardMenu.selectedItemIdx >= 0 && pIndexSubBoardMenu.selectedItemIdx <= lastItemIdxForFirstPage);
if (!selectedItemIsFirst && !selectedItemOnLastPage && moreThanOneScreenfulOfItems && !selectedItemIsOnFirstPage)
{
if (pIndexSubBoardMenu.selectedItemIdx > 0)
pIndexSubBoardMenu.topItemIdx = pIndexSubBoardMenu.selectedItemIdx - 1;
else
pIndexSubBoardMenu.topItemIdx = pIndexSubBoardMenu.selectedItemIdx;
}
}
}
// Helper for DigDistMsgReader_IndexedModeChooseSubBoard(): Sets the selected item in the
// indexed mode sub-board menu to the next sub-board with new messages, including the
// one at the given starting index.
//
// Parameters:
// pIndexSubBoardMenu: The indexed sub-board menu
// pStartIdx: The index of the sub-board to start at
// pOnePastLastIdx: One past the index of the last sub-board to check
//
// Return value: Boolean - Whether or not a sub-board with new messages was found in the menu
function indexedSubMenuSetSelectedNextWithnNewMsgs(pIndexSubBoardMenu, pStartIdx, pOnePastLastIdx)
{
var foundMenuItem = false;
for (var i = pStartIdx; i < pOnePastLastIdx; ++i)
{
var menuItem = pIndexSubBoardMenu.GetItem(i);
if (menuItem == null || typeof(menuItem) !== "object" || !menuItem.hasOwnProperty("retval"))
continue;
if (menuItem.retval != null && menuItem.retval.numNewMsgs > 0)
{
if (menuItem.retval.numNewMsgs > 0)
{
setIndexedSubBoardMenuSelectedItemIdx(pIndexSubBoardMenu, i);
DigDistMsgReader_IndexedModeChooseSubBoard.selectedItemIdx = i;
foundMenuItem = true;
break;
}
}
}
return foundMenuItem;
}
// Returns a string to use for a sub-board for the indexed mode sub-board menu // Returns a string to use for a sub-board for the indexed mode sub-board menu
// //
// Parameters: // Parameters:
...@@ -14838,7 +15076,6 @@ function getLatestPostTimestampAndNumNewMsgs(pSubCode) ...@@ -14838,7 +15076,6 @@ function getLatestPostTimestampAndNumNewMsgs(pSubCode)
{ {
retObj.latestMsgTimestamp = getLatestPostTimeWithMsgbase(msgbase, pSubCode); retObj.latestMsgTimestamp = getLatestPostTimeWithMsgbase(msgbase, pSubCode);
var totalNumMsgs = msgbase.total_msgs; var totalNumMsgs = msgbase.total_msgs;
msgbase.close();
// scan_ptr: user's current new message scan pointer (highest-read message number) // scan_ptr: user's current new message scan pointer (highest-read message number)
if (typeof(msg_area.sub[pSubCode].scan_ptr) === "number") if (typeof(msg_area.sub[pSubCode].scan_ptr) === "number")
{ {
...@@ -14866,7 +15103,14 @@ function getLatestPostTimestampAndNumNewMsgs(pSubCode) ...@@ -14866,7 +15103,14 @@ function getLatestPostTimestampAndNumNewMsgs(pSubCode)
} }
} }
else else
{
retObj.numNewMsgs = lastReadableMsgHdr.number - msg_area.sub[pSubCode].scan_ptr; retObj.numNewMsgs = lastReadableMsgHdr.number - msg_area.sub[pSubCode].scan_ptr;
// Calculating the number of new messages in the above way seems to
// sometimes (though rarely) be incorrect (returning more than the actual
// number of new messages). Another way might be to start from scan_ptr
// scan_ptr and count the number of readable messages.
//retObj.numNewMsgs = numReadableMsgsFromAbsMsgNumWithMsgbase(msgbase, pSubCode, msg_area.sub[pSubCode].scan_ptr);
}
} }
} }
} }
...@@ -14874,11 +15118,20 @@ function getLatestPostTimestampAndNumNewMsgs(pSubCode) ...@@ -14874,11 +15118,20 @@ function getLatestPostTimestampAndNumNewMsgs(pSubCode)
{ {
var lastReadableMsgHdr = getLastReadableMsgHdrInSubBoard(pSubCode); var lastReadableMsgHdr = getLastReadableMsgHdrInSubBoard(pSubCode);
if (lastReadableMsgHdr != null) if (lastReadableMsgHdr != null)
{
retObj.numNewMsgs = lastReadableMsgHdr.number - msg_area.sub[pSubCode].last_read; retObj.numNewMsgs = lastReadableMsgHdr.number - msg_area.sub[pSubCode].last_read;
// Calculating the number of new messages in the above way seems to
// sometimes (though rarely) be incorrect (returning more than the actual
// number of new messages). Another way might be to start from scan_ptr
// scan_ptr and count the number of readable messages.
//retObj.numNewMsgs = numReadableMsgsFromAbsMsgNumWithMsgbase(msgbase, pSubCode, msg_area.sub[pSubCode].last_read);
}
else // Count the number of new readable messages.
retObj.numNewMsgs = numReadableMsgsFromAbsMsgNumWithMsgbase(msgbase, pSubCode, msg_area.sub[pSubCode].last_read);
} }
else else
retObj.numNewMsgs = msg_area.sub[pSubCode].posts; retObj.numNewMsgs = msg_area.sub[pSubCode].posts;
//msgbase.close(); msgbase.close();
if (retObj.numNewMsgs < 0) if (retObj.numNewMsgs < 0)
retObj.numNewMsgs = 0; retObj.numNewMsgs = 0;
} }
...@@ -15957,10 +16210,11 @@ function DigDistMsgReader_VoteOnMessage(pMsgHdr, pRemoveNLsFromVoteText) ...@@ -15957,10 +16210,11 @@ function DigDistMsgReader_VoteOnMessage(pMsgHdr, pRemoveNLsFromVoteText)
// message header (for the message that was read) // message header (for the message that was read)
if (retObj.savedVote) if (retObj.savedVote)
{ {
if (this.hdrsForCurrentSubBoardByMsgNum.hasOwnProperty(pMsgHdr.number)) if (this.msgNumToIdxMap.hasOwnProperty(pMsgHdr.number))
{ {
var originalMsgIdx = this.hdrsForCurrentSubBoardByMsgNum[pMsgHdr.number]; var originalMsgIdx = this.msgNumToIdxMap[pMsgHdr.number];
var tmpHdrs = msgbase.get_all_msg_headers(true); //var tmpHdrs = msgbase.get_all_msg_headers(true);
var tmpHdrs = msgbase.get_all_msg_headers(false);
if (tmpHdrs.hasOwnProperty(pMsgHdr.number)) if (tmpHdrs.hasOwnProperty(pMsgHdr.number))
{ {
this.hdrsForCurrentSubBoard[originalMsgIdx] = tmpHdrs[pMsgHdr.number]; this.hdrsForCurrentSubBoard[originalMsgIdx] = tmpHdrs[pMsgHdr.number];
...@@ -16221,7 +16475,8 @@ function DigDistMsgReader_GetMsgBody(pMsgHdr) ...@@ -16221,7 +16475,8 @@ function DigDistMsgReader_GetMsgBody(pMsgHdr)
   
// Pass true to get_all_msg_headers() to tell it to return vote messages // Pass true to get_all_msg_headers() to tell it to return vote messages
// (the parameter was introduced in Synchronet 3.17+) // (the parameter was introduced in Synchronet 3.17+)
var tmpHdrs = msgbase.get_all_msg_headers(true); //var tmpHdrs = msgbase.get_all_msg_headers(true);
var tmpHdrs = msgbase.get_all_msg_headers(false);
for (var tmpProp in tmpHdrs) for (var tmpProp in tmpHdrs)
{ {
if (tmpHdrs[tmpProp] == null) if (tmpHdrs[tmpProp] == null)
...@@ -16331,12 +16586,13 @@ function DigDistMsgReader_RefreshMsgHdrInArrays(pMsgNum) ...@@ -16331,12 +16586,13 @@ function DigDistMsgReader_RefreshMsgHdrInArrays(pMsgNum)
} }
else if (this.hdrsForCurrentSubBoard.length > 0) else if (this.hdrsForCurrentSubBoard.length > 0)
{ {
if (this.hdrsForCurrentSubBoardByMsgNum.hasOwnProperty(pMsgNum)) if (this.msgNumToIdxMap.hasOwnProperty(pMsgNum))
{ {
var msgHdrs = msgbase.get_all_msg_headers(true); //var msgHdrs = msgbase.get_all_msg_headers(true);
var msgHdrs = msgbase.get_all_msg_headers(false);
if (msgHdrs.hasOwnProperty(pMsgNum)) if (msgHdrs.hasOwnProperty(pMsgNum))
{ {
var msgIdx = this.hdrsForCurrentSubBoardByMsgNum[pMsgNum]; var msgIdx = this.msgNumToIdxMap[pMsgNum];
this.hdrsForCurrentSubBoard[msgIdx] = msgHdrs[pMsgNum]; this.hdrsForCurrentSubBoard[msgIdx] = msgHdrs[pMsgNum];
} }
} }
...@@ -16365,7 +16621,7 @@ function DigDistMsgReader_RecalcMsgListWidthsAndFormatStrs(pMsgNumLen) ...@@ -16365,7 +16621,7 @@ function DigDistMsgReader_RecalcMsgListWidthsAndFormatStrs(pMsgNumLen)
this.sMsgInfoFromUserFormatStr = ""; this.sMsgInfoFromUserFormatStr = "";
this.sMsgInfoFormatHighlightStr = ""; this.sMsgInfoFormatHighlightStr = "";
   
this.MSGNUM_LEN = (typeof(pMsgNumLen) == "number" ? pMsgNumLen : this.NumMessages(null, true).toString().length); this.MSGNUM_LEN = (typeof(pMsgNumLen) == "number" ? pMsgNumLen : this.NumMessages().toString().length);
if (this.MSGNUM_LEN < 4) if (this.MSGNUM_LEN < 4)
this.MSGNUM_LEN = 4; this.MSGNUM_LEN = 4;
this.DATE_LEN = 10; // i.e., YYYY-MM-DD this.DATE_LEN = 10; // i.e., YYYY-MM-DD
...@@ -16375,7 +16631,7 @@ function DigDistMsgReader_RecalcMsgListWidthsAndFormatStrs(pMsgNumLen) ...@@ -16375,7 +16631,7 @@ function DigDistMsgReader_RecalcMsgListWidthsAndFormatStrs(pMsgNumLen)
this.TO_LEN = (console.screen_columns * (15/console.screen_columns)).toFixed(0); this.TO_LEN = (console.screen_columns * (15/console.screen_columns)).toFixed(0);
//var colsLeftForSubject = console.screen_columns-this.MSGNUM_LEN-this.DATE_LEN-this.TIME_LEN-this.FROM_LEN-this.TO_LEN-6; // 6 to account for the spaces //var colsLeftForSubject = console.screen_columns-this.MSGNUM_LEN-this.DATE_LEN-this.TIME_LEN-this.FROM_LEN-this.TO_LEN-6; // 6 to account for the spaces
//this.SUBJ_LEN = (console.screen_columns * (colsLeftForSubject/console.screen_columns)).toFixed(0); //this.SUBJ_LEN = (console.screen_columns * (colsLeftForSubject/console.screen_columns)).toFixed(0);
this.SUBJ_LEN = console.screen_columns-this.MSGNUM_LEN-this.DATE_LEN-this.TIME_LEN-this.FROM_LEN-this.TO_LEN-6; // 6 to account for the spaces this.SUBJ_LEN = console.screen_columns-this.MSGNUM_LEN-this.DATE_LEN-this.TIME_LEN-this.FROM_LEN-this.TO_LEN-8; // 8 to account for the spaces
   
if (this.showScoresInMsgList) if (this.showScoresInMsgList)
{ {
...@@ -17814,7 +18070,7 @@ function searchMsgbase(pSubCode, pSearchType, pSearchString, pListingPersonalEma ...@@ -17814,7 +18070,7 @@ function searchMsgbase(pSubCode, pSearchType, pSearchString, pListingPersonalEma
// Define a search function for the message field we're going to search // Define a search function for the message field we're going to search
var readingPersonalEmailFromUser = (typeof(pListingPersonalEmailFromUser) == "boolean" ? pListingPersonalEmailFromUser : false); var readingPersonalEmailFromUser = (typeof(pListingPersonalEmailFromUser) == "boolean" ? pListingPersonalEmailFromUser : false);
var matchFn = null; var matchFn = null;
var useGetAllMsgHdrs = false; var getAllMsgHdrs = false;
switch (pSearchType) switch (pSearchType)
{ {
// It might seem odd to have SEARCH_NONE in here, but it's here because // It might seem odd to have SEARCH_NONE in here, but it's here because
...@@ -17848,7 +18104,7 @@ function searchMsgbase(pSubCode, pSearchType, pSearchString, pListingPersonalEma ...@@ -17848,7 +18104,7 @@ function searchMsgbase(pSubCode, pSearchType, pSearchString, pListingPersonalEma
} }
break; break;
case SEARCH_KEYWORD: case SEARCH_KEYWORD:
useGetAllMsgHdrs = true; getAllMsgHdrs = true;
matchFn = function(pSearchStr, pMsgHdr, pMsgBase, pSubBoardCode) { matchFn = function(pSearchStr, pMsgHdr, pMsgBase, pSubBoardCode) {
var msgText = strip_ctrl(pMsgBase.get_msg_body(false, pMsgHdr.number, false, false, true, true)); var msgText = strip_ctrl(pMsgBase.get_msg_body(false, pMsgHdr.number, false, false, true, true));
var keywordFound = ((pMsgHdr.subject.toUpperCase().indexOf(pSearchStr) > -1) || (msgText.toUpperCase().indexOf(pSearchStr) > -1)); var keywordFound = ((pMsgHdr.subject.toUpperCase().indexOf(pSearchStr) > -1) || (msgText.toUpperCase().indexOf(pSearchStr) > -1));
...@@ -17859,7 +18115,7 @@ function searchMsgbase(pSubCode, pSearchType, pSearchString, pListingPersonalEma ...@@ -17859,7 +18115,7 @@ function searchMsgbase(pSubCode, pSearchType, pSearchString, pListingPersonalEma
} }
break; break;
case SEARCH_FROM_NAME: case SEARCH_FROM_NAME:
useGetAllMsgHdrs = true; getAllMsgHdrs = true;
matchFn = function(pSearchStr, pMsgHdr, pMsgBase, pSubBoardCode) { matchFn = function(pSearchStr, pMsgHdr, pMsgBase, pSubBoardCode) {
var fromNameFound = (pMsgHdr.from.toUpperCase() == pSearchStr.toUpperCase()); var fromNameFound = (pMsgHdr.from.toUpperCase() == pSearchStr.toUpperCase());
if (pSubBoardCode == "mail") if (pSubBoardCode == "mail")
...@@ -17869,13 +18125,13 @@ function searchMsgbase(pSubCode, pSearchType, pSearchString, pListingPersonalEma ...@@ -17869,13 +18125,13 @@ function searchMsgbase(pSubCode, pSearchType, pSearchString, pListingPersonalEma
} }
break; break;
case SEARCH_TO_NAME_CUR_MSG_AREA: case SEARCH_TO_NAME_CUR_MSG_AREA:
useGetAllMsgHdrs = true; getAllMsgHdrs = true;
matchFn = function(pSearchStr, pMsgHdr, pMsgBase, pSubBoardCode) { matchFn = function(pSearchStr, pMsgHdr, pMsgBase, pSubBoardCode) {
return (pMsgHdr.to.toUpperCase() == pSearchStr); return (pMsgHdr.to.toUpperCase() == pSearchStr);
} }
break; break;
case SEARCH_TO_USER_CUR_MSG_AREA: case SEARCH_TO_USER_CUR_MSG_AREA:
useGetAllMsgHdrs = true; getAllMsgHdrs = true;
case SEARCH_ALL_TO_USER_SCAN: case SEARCH_ALL_TO_USER_SCAN:
matchFn = function(pSearchStr, pMsgHdr, pMsgBase, pSubBoardCode) { matchFn = function(pSearchStr, pMsgHdr, pMsgBase, pSubBoardCode) {
// See if the message is not marked as deleted and the 'To' name // See if the message is not marked as deleted and the 'To' name
...@@ -17988,12 +18244,12 @@ function searchMsgbase(pSubCode, pSearchType, pSearchString, pListingPersonalEma ...@@ -17988,12 +18244,12 @@ function searchMsgbase(pSubCode, pSearchType, pSearchString, pListingPersonalEma
// Search the messages // Search the messages
if (matchFn != null) if (matchFn != null)
{ {
// If get_all_msg_headers exists as a function, then use it. Otherwise, // If we want to use get_all_msg_headers, then use it. Otherwise,
// iterate through all message offsets and get the headers. We want to // iterate through all message offsets and get the headers. We want to
// use get_all_msg_hdrs() if possible because that will include information // use get_all_msg_hdrs() if possible because that will include information
// about how many votes each message got (up/downvotes for regular // about how many votes each message got (up/downvotes for regular
// messages or who voted for which options for poll messages). // messages or who voted for which options for poll messages).
if (useGetAllMsgHdrs && (typeof(msgbase.get_all_msg_headers) === "function")) if (getAllMsgHdrs)
{ {
// Pass false to get_all_msg_headers() to tell it not to include vote messages // Pass false to get_all_msg_headers() to tell it not to include vote messages
// (the parameter was introduced in Synchronet 3.17+) // (the parameter was introduced in Synchronet 3.17+)
...@@ -18075,7 +18331,7 @@ function absMsgNumToIdxWithMsgbaseObj(pMsgbase, pMsgNum) ...@@ -18075,7 +18331,7 @@ function absMsgNumToIdxWithMsgbaseObj(pMsgbase, pMsgNum)
else else
{ {
var msgHdr = pMsgbase.get_msg_index(false, pMsgNum, false); var msgHdr = pMsgbase.get_msg_index(false, pMsgNum, false);
if ((msgHdr == null) && gCmdLineArgVals.verboselogging) if (msgHdr == null && gCmdLineArgVals.verboselogging)
{ {
writeToSysAndNodeLog("Message area " + pMsgbase.cfg.code + ": Tried to get message header for absolute message number " + writeToSysAndNodeLog("Message area " + pMsgbase.cfg.code + ": Tried to get message header for absolute message number " +
pMsgNum + " but got a null header object."); pMsgNum + " but got a null header object.");
...@@ -18126,7 +18382,7 @@ function idxToAbsMsgNum(pMsgbase, pMsgIdx) ...@@ -18126,7 +18382,7 @@ function idxToAbsMsgNum(pMsgbase, pMsgIdx)
return -1; return -1;
   
var msgHdr = pMsgbase.get_msg_index(true, pMsgIdx, false); var msgHdr = pMsgbase.get_msg_index(true, pMsgIdx, false);
if ((msgHdr == null) && gCmdLineArgVals.verboselogging) if (msgHdr == null && gCmdLineArgVals.verboselogging)
{ {
writeToSysAndNodeLog("Tried to get message header for message offset " + writeToSysAndNodeLog("Tried to get message header for message offset " +
pMsgIdx + " but got a null header object."); pMsgIdx + " but got a null header object.");
...@@ -18247,7 +18503,7 @@ function msgIsFromUser(pMsgHdr, pUserNum) ...@@ -18247,7 +18503,7 @@ function msgIsFromUser(pMsgHdr, pUserNum)
if (typeof(pMsgHdr) != "object") if (typeof(pMsgHdr) != "object")
return false; return false;
// Return false if the message is marked as deleted and the user can't read deleted messages // Return false if the message is marked as deleted and the user can't read deleted messages
if (((pMsgHdr.attr & MSG_DELETE) == MSG_DELETE) && !canViewDeletedMsgs()) if (Boolean(pMsgHdr.attr & MSG_DELETE) && !canViewDeletedMsgs())
return false; return false;
   
var pUserNumIsValid = (typeof(pUserNum) === "number" && pUserNum > 0 && pUserNum <= system.lastuser); var pUserNumIsValid = (typeof(pUserNum) === "number" && pUserNum > 0 && pUserNum <= system.lastuser);
...@@ -18319,6 +18575,31 @@ function curMsgSubBoardIsLast(pGrpIdx, pSubIdx) ...@@ -18319,6 +18575,31 @@ function curMsgSubBoardIsLast(pGrpIdx, pSubIdx)
return (curGrp == msg_area.grp_list.length-1) && (curSub == msg_area.grp_list[msg_area.grp_list.length-1].sub_list.length-1); return (curGrp == msg_area.grp_list.length-1) && (curSub == msg_area.grp_list[msg_area.grp_list.length-1].sub_list.length-1);
} }
   
// With a MsgBase object, counts the number of readable messages starting
// with (and including) a message number
//
// Parameters:
// pMsgbase: A MsgBase object (should be open)
// pSubCode: The internal code of the sub-board
// pMsgNum: A message number to start at
//
// Return value: The number of readable messages starting at the given message number
function numReadableMsgsFromAbsMsgNumWithMsgbase(pMsgbase, pSubCode, pMsgNum)
{
var numReadableMsgs = 0;
if (pMsgbase.is_open)
{
var totalNumMsgs = pMsgbase.total_msgs;
var msgIdx = absMsgNumToIdx(pMsgbase, pMsgNum);
for (; i < totalNumMsgs; ++msgIdx)
{
if (isReadableMsgHdr(pMsgbase.get_msg_index(true, msgIdx), pSubCode))
++numReadableMsgs;
}
}
return numReadableMsgs;
}
// Parses arguments, where each argument in the given array is in the format // Parses arguments, where each argument in the given array is in the format
// -arg=val. If the value is the string "true" or "false", then the value will // -arg=val. If the value is the string "true" or "false", then the value will
// be a boolean. Otherwise, the value will be a string. // be a boolean. Otherwise, the value will be a string.
...@@ -19495,11 +19776,7 @@ function toggleVoteMsgsDeleted(pMsgbase, pMsgNum, pMsgID, pDoDelete, pIsEmailSub ...@@ -19495,11 +19776,7 @@ function toggleVoteMsgsDeleted(pMsgbase, pMsgNum, pMsgID, pDoDelete, pIsEmailSub
if (pIsEmailSub) if (pIsEmailSub)
return retObj; return retObj;
   
// This relies on get_all_msg_headers() returning vote messages. The get_all_msg_headers() // This relies on get_all_msg_headers() returning vote messages.
// function was added in Synchronet 3.16, and the 'true' parameter to get vote headers was
// added in Synchronet 3.17.
if (typeof(pMsgbase.get_all_msg_headers) === "function")
{
var msgHdrs = pMsgbase.get_all_msg_headers(true); var msgHdrs = pMsgbase.get_all_msg_headers(true);
for (var msgHdrsProp in msgHdrs) for (var msgHdrsProp in msgHdrs)
{ {
...@@ -19532,7 +19809,6 @@ function toggleVoteMsgsDeleted(pMsgbase, pMsgNum, pMsgID, pDoDelete, pIsEmailSub ...@@ -19532,7 +19809,6 @@ function toggleVoteMsgsDeleted(pMsgbase, pMsgNum, pMsgID, pDoDelete, pIsEmailSub
++retObj.toggleVoteMsgsAffected; ++retObj.toggleVoteMsgsAffected;
} }
} }
}
   
return retObj; return retObj;
} }
...@@ -22471,6 +22747,8 @@ function subBoardNewscanAllRead(pSubCode) ...@@ -22471,6 +22747,8 @@ function subBoardNewscanAllRead(pSubCode)
   
// Mark any unread messages to the user as read // Mark any unread messages to the user as read
var indexRecords = msgbase.get_index(); var indexRecords = msgbase.get_index();
if (indexRecords != null)
{
for (var i = 0; i < indexRecords.length; ++i) for (var i = 0; i < indexRecords.length; ++i)
{ {
if (msgIsToCurrentUserByName(indexRecords[i]) && !Boolean(indexRecords[i].attr & MSG_READ)) if (msgIsToCurrentUserByName(indexRecords[i]) && !Boolean(indexRecords[i].attr & MSG_READ))
...@@ -22484,7 +22762,7 @@ function subBoardNewscanAllRead(pSubCode) ...@@ -22484,7 +22762,7 @@ function subBoardNewscanAllRead(pSubCode)
} }
} }
} }
}
msgbase.close(); msgbase.close();
} }
else else
......
...@@ -57,15 +57,15 @@ while (continueOn) ...@@ -57,15 +57,15 @@ while (continueOn)
if (userChoice) if (userChoice)
{ {
var saveRetObj = saveDDMsgReaderCfgFile(); var saveRetObj = saveDDMsgReaderCfgFile();
if (saveRetObj.saveSucceeded) // Show an error if failed to save the settings. If succeeded, only show
// a message if settings were saved to the mods directory.
if (!saveRetObj.saveSucceeded)
uifc.msg("Failed to save settings!");
else
{ {
var msg = "Changes were successfully saved";
if (saveRetObj.savedToModsDir) if (saveRetObj.savedToModsDir)
msg += " (saved to the mods dir)"; uifc.msg("Changes were successfully saved (to the mods dir)");
uifc.msg(msg);
} }
else
uifc.msg("Failed to save settings!");
} }
continueOn = false; continueOn = false;
} }
...@@ -111,6 +111,8 @@ function doMainMenu() ...@@ -111,6 +111,8 @@ function doMainMenu()
"quickUserValSetIndex", // Number (can be -1) "quickUserValSetIndex", // Number (can be -1)
"saveAllHdrsWhenSavingMsgToBBSPC", // Boolean "saveAllHdrsWhenSavingMsgToBBSPC", // Boolean
"useIndexedModeForNewscan", // Boolean "useIndexedModeForNewscan", // Boolean
"indexedModeMenuSnapToFirstWithNew", // Boolean
"newscanOnlyShowNewMsgs", // Boolean
"themeFilename" // String "themeFilename" // String
]; ];
// Strings for the options to display on the menu // Strings for the options to display on the menu
...@@ -139,6 +141,8 @@ function doMainMenu() ...@@ -139,6 +141,8 @@ function doMainMenu()
"Quick User Val Set Index", "Quick User Val Set Index",
"Save All Headers When Saving Message To BBS PC", "Save All Headers When Saving Message To BBS PC",
"Use Indexed Mode For Newscan", "Use Indexed Mode For Newscan",
"Index menu: Snap to sub-boards w/ new messages",
"During a newscan, only show new messages",
"Theme Filename" "Theme Filename"
]; ];
// Build an array of formatted string to be displayed on the menu // Build an array of formatted string to be displayed on the menu
...@@ -534,6 +538,16 @@ function getOptionHelpText() ...@@ -534,6 +538,16 @@ function getOptionHelpText()
optionHelpText["useIndexedModeForNewscan"] += "the reader will do a traditional newscan where it will scan through the sub-boards and go into reader "; optionHelpText["useIndexedModeForNewscan"] += "the reader will do a traditional newscan where it will scan through the sub-boards and go into reader ";
optionHelpText["useIndexedModeForNewscan"] += "mode when there are new messages in a sub-board."; optionHelpText["useIndexedModeForNewscan"] += "mode when there are new messages in a sub-board.";
optionHelpText["indexedModeMenuSnapToFirstWithNew"] = "Index menu: Snap to sub-boards w/ new messages: For the indexed newscan sub-board ";
optionHelpText["indexedModeMenuSnapToFirstWithNew"] += "menu in lightbar mode, whether or not to 'snap' the selected item to the next ";
optionHelpText["indexedModeMenuSnapToFirstWithNew"] += "sub-board with new messages upon displaying or returning to the indexed newscan ";
optionHelpText["indexedModeMenuSnapToFirstWithNew"] += "sub-board menu. This is a default for a user setting that users can toggle ";
optionHelpText["indexedModeMenuSnapToFirstWithNew"] += "for themselves".
optionHelpText["newscanOnlyShowNewMsgs"] = "During a newscan, only show new messages (default for a user setting): Whether or not ";
optionHelpText["newscanOnlyShowNewMsgs"] += "to only show new messages when the user is doing a newscan. Users can toggle this as ";
optionHelpText["newscanOnlyShowNewMsgs"] += "they like.";
optionHelpText["themeFilename"] = "Theme filename: The name of a file for a color theme to use"; optionHelpText["themeFilename"] = "Theme filename: The name of a file for a color theme to use";
// Word-wrap the help text items // Word-wrap the help text items
...@@ -556,7 +570,8 @@ function getMainHelp(pOptionHelpText, pCfgOptProps) ...@@ -556,7 +570,8 @@ function getMainHelp(pOptionHelpText, pCfgOptProps)
for (var i = 0; i < pCfgOptProps.length; ++i) for (var i = 0; i < pCfgOptProps.length; ++i)
{ {
var optName = pCfgOptProps[i]; var optName = pCfgOptProps[i];
helpText += pOptionHelpText[optName] + "\r\n\r\n"; //helpText += pOptionHelpText[optName] + "\r\n\r\n";
helpText += pOptionHelpText[optName] + "\r\n";
} }
return word_wrap(helpText, gHelpWrapWidth); return word_wrap(helpText, gHelpWrapWidth);
} }
......
Source diff could not be displayed: it is too large. Options to address this: view the blob.
...@@ -5,6 +5,26 @@ Revision History (change log) ...@@ -5,6 +5,26 @@ Revision History (change log)
============================= =============================
Version Date Description Version Date Description
------- ---- ----------- ------- ---- -----------
1.87 2023-11-18 Possible speed improvement when loading messages.
New: User setting to only show new messages in a newscan
(defaults to true/enabled)
In the message list, there is now an additional space
before the 'from' name, in case one of the status
characters is a letter (this should look better).
New: In lightbar mode, the indexed newscan menu can
optionally 'snap' to the next sub-board with new messages
when showing/returning to the menu
Fix: When listing personal email, messages to the user
were written with the to-user color wuen unread. Now the
regular colors are always used (since all of a user's
personal emails are 'to' them).
Fix: For indexed newscan, if there are no sub-boards
selected for scan in the user's newscan configuration,
then output a message and exit. Otherwise, it would end
up in an infinite loop.
Updated how user settings are loaded, to ensure that
default user settings from DDMsgReader.cfg actually get
set properly in the user settings.
1.86 2023-11-09 New feature: For indexed mode, when choosing a sub-board, 1.86 2023-11-09 New feature: For indexed mode, when choosing a sub-board,
the R key can be used to mark all messages as read in the the R key can be used to mark all messages as read in the
sub-board. sub-board.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment