diff --git a/xtrn/SlyVote/SlyVote.js b/xtrn/SlyVote/SlyVote.js index 1989558d70b6f140c353aa196eef2e5369fa3e8b..76ea32ab42d1675cddba37fb1e1ac710127512ba 100644 --- a/xtrn/SlyVote/SlyVote.js +++ b/xtrn/SlyVote/SlyVote.js @@ -70,6 +70,15 @@ * allowed to vote, they can still view poll results. * Also, updated the poll viewing & stats view to * say if a poll is closed. + * 2017-09-08 Eric Oulashin Version 0.30 beta + * Implemented a user configuration file to store + * last-read message numbers separately from + * Synchronet's messagebase so that SlyVote won't + * mess with users' actual last-read message numbers. + * Also, updated so that when changing to another + * area, if the top item index is on the last page + * of the menu, then set the top item index to the + * first item on the last page. */ load("sbbsdefs.js"); @@ -118,8 +127,8 @@ load("scrollbar.js"); load("DDLightbarMenu.js"); // Version information -var SLYVOTE_VERSION = "0.29 Beta"; -var SLYVOTE_DATE = "2017-08-27"; +var SLYVOTE_VERSION = "0.30 Beta"; +var SLYVOTE_DATE = "2017-09-08"; // Determine the script's startup directory. // This code is a trick that was created by Deuce, suggested by Rob Swindell @@ -265,6 +274,11 @@ if (gSlyVoteCfg.subBoardCodes.length == 0) exit(); } +// Read the user settings file +// The name of the user's settings file for SlyVote +var gUserSettingsFilename = backslash(system.data_dir + "user") + format("%04d", user.number) + ".SlyVote.cfg"; +var gUserSettings = ReadUserSettingsFile(gUserSettingsFilename); + // Determine which sub-board to use - If there is more than one, let the user choose. var gSubBoardCode = ""; if (gSlyVoteCfg.subBoardCodes.length == 1) @@ -321,7 +335,12 @@ while (gContinueSlyVote) } } - +// Before exiting, update the user settings file +if (!WriteUserSettingsFile(gUserSettings, gUserSettingsFilename)) +{ + console.print("\1n\1y\1hFailed to update your user settings file!\1n"); + mswait(ERROR_PAUSE_WAIT_MS); +} @@ -351,6 +370,8 @@ function ChooseVotingSubBoard(pSubBoardCodes) var drawColRetObj = DrawVoteColumns(listTopRow, gBottomBorderRow-1, 17, 63); // Display the menu of voting areas + var topItemIndex = 0; + var selectedItemIndex = 0; console.gotoxy(drawColRetObj.columnX1+2, listTopRow-1); console.print("\1n\1b\1hChoose a voting area (\1cESC\1g=\1n\1cExit\1h\1b) \1y\1h" + CHECK_CHAR + "\1n\1c=\1b\1hHas polls\1n"); console.gotoxy(drawColRetObj.columnX1+2, listTopRow); @@ -364,6 +385,21 @@ function ChooseVotingSubBoard(pSubBoardCodes) var hasPollsChar = (subBoardHasPolls(pSubBoardCodes[idx]) ? "\1y\1h" + CHECK_CHAR + "\1n" : " "); var itemText = format("%-" + areaNameLen + "s %s", subBoardGrpAndName.substr(0, areaNameLen), hasPollsChar); subBoardMenu.Add(itemText, pSubBoardCodes[idx]); + if (pSubBoardCodes[idx] == gSubBoardCode) + { + topItemIndex = idx; + selectedItemIndex = idx; + } + } + // If the top item index is on the last page of the menu, then + // set the top item index to the first item on the last page. + if (subBoardMenu.items.length > subBoardMenu.GetNumItemsPerPage()) + { + if ((topItemIndex <= subBoardMenu.items.length - 1) && (topItemIndex >= subBoardMenu.GetTopItemIdxToTopOfLastPage())) + subBoardMenu.SetTopItemIdxToTopOfLastPage(); + else + subBoardMenu.topItemIdx = topItemIndex; + subBoardMenu.selectedItemIdx = selectedItemIndex; } var retObj = new Object(); retObj.subBoardChoice = subBoardMenu.GetVal(); @@ -940,6 +976,101 @@ function ReadConfigFile() return retObj; } +// Reads the user settings file. +// +// Parameters: +// pFilename: The name of the file to read +// +// Return value: An object with the following properties: +// lastRead: An object specifying last-read message numbers, indexed by sub-board code +function ReadUserSettingsFile(pFilename) +{ + var userSettingsObj = { + lastRead: { } + }; + + var userCfgFile = new File(pFilename); + if (userCfgFile.open("r")) + { + var fileLine = null; // A line read from the file + var equalsPos = 0; // Position of a = in the line + var commentPos = 0; // Position of the start of a comment + var setting = null; // A setting name (string) + var settingUpper = null; // Upper-case setting name + var value = null; // To store a value for a setting (string) + while (!userCfgFile.eof) + { + // Read the next line from the config file. + fileLine = userCfgFile.readln(2048); + + // fileLine should be a string, but I've seen some cases + // where it isn't, so check its type. + if (typeof(fileLine) != "string") + continue; + + // If the line starts with with a semicolon (the comment + // character) or is blank, then skip it. + if ((fileLine.substr(0, 1) == ";") || (fileLine.length == 0)) + continue; + + // If the line has a semicolon anywhere in it, then remove + // everything from the semicolon onward. + commentPos = fileLine.indexOf(";"); + if (commentPos > -1) + fileLine = fileLine.substr(0, commentPos); + + // Look for an equals sign, and if found, separate the line + // into the setting name (before the =) and the value (after the + // equals sign). + equalsPos = fileLine.indexOf("="); + if (equalsPos > 0) + { + // Read the setting & value, and trim leading & trailing spaces. + setting = trimSpaces(fileLine.substr(0, equalsPos), true, false, true); + settingUpper = setting.toUpperCase(); + value = trimSpaces(fileLine.substr(equalsPos+1), true, false, true); + + // Last-read message numbers. Lines starting with lastread_ + // should have a sub-board code after the "lastread_". Add + // the message number to userSettingsObj.lastRead if the value + // is all digits and there is a sub-board code specified. + if ((settingUpper.indexOf("LASTREAD_") == 0) && /^[0-9]+$/.test(value)) + { + var subBoardCode = setting.substr(9).toLowerCase(); + if (subBoardCode.length > 0) + userSettingsObj.lastRead[subBoardCode] = +value; // + to make it a numeric type + } + } + } + + userCfgFile.close(); + } + + return userSettingsObj; +} + +// Writes the user settings file +// +// Parameters: +// pUserCfg: The object containing the user's configuration settings +// pFilename: The name of the file to write (should be gUserSettingsFilename) +function WriteUserSettingsFile(pUserCfg, pFilename) +{ + var writeSucceeded = false; + var userCfgFile = new File(pFilename); + if (userCfgFile.open("w")) + { + for (var subBoardCode in pUserCfg.lastRead) + { + writeSucceeded = userCfgFile.writeln("lastread_" + subBoardCode + "=" + pUserCfg.lastRead[subBoardCode]); + if (!writeSucceeded) + break; + } + userCfgFile.close(); + } + return writeSucceeded; +} + // Checks to see whether a user has voted on a message. // // Parameters: @@ -1685,8 +1816,24 @@ function ViewVoteResults(pSubBoardCode) if (IsReadableMsgHdr(msgHdrs[prop], pSubBoardCode)) { pollMsgHdrs.push(msgHdrs[prop]); + // If the user settings has a last-read message number, then use it. + // Otherwise, look in Synchronet's message area array for the user's + // last-read message number. + if (gUserSettings.lastRead.hasOwnProperty(pSubBoardCode)) + { + if (msgHdrs[prop].number === gUserSettings.lastRead[pSubBoardCode]) + currentMsgIdx = pollMsgIdx; + } + else + { + if (msgHdrs[prop].number == msg_area.sub[pSubBoardCode].last_read) + currentMsgIdx = pollMsgIdx; + } + // TODO: Remove - Older - Dealing with Synchronet last read pointers: + /* if (msgHdrs[prop].number == msg_area.sub[pSubBoardCode].last_read) currentMsgIdx = pollMsgIdx; + */ ++pollMsgIdx; } } @@ -2008,6 +2155,10 @@ function ViewVoteResults(pSubBoardCode) else if (scrollRetObj.lastKeypress == gReaderKeys.quit) continueOn = false; + // Update the user's last read message number in their user settings + gUserSettings.lastRead[pSubBoardCode] = pollMsgHdrs[currentMsgIdx].number; + // TODO: Remove - Older - Dealing with Synchronet's scan pointer and last read pointer: + /* // Update the user's scan pointer and last read message pointer if (pSubBoardCode != "mail") { @@ -2017,6 +2168,7 @@ function ViewVoteResults(pSubBoardCode) msg_area.sub[pSubBoardCode].scan_ptr = pollMsgHdrs[currentMsgIdx].number; msg_area.sub[pSubBoardCode].last_read = pollMsgHdrs[currentMsgIdx].number; } + */ } msgbase.close(); diff --git a/xtrn/SlyVote/readme.txt b/xtrn/SlyVote/readme.txt index 80b2cb7260f5fb5aaac295a024f70afd756c2baf..5d5206de5274132467356f317abe663577a857ed 100644 --- a/xtrn/SlyVote/readme.txt +++ b/xtrn/SlyVote/readme.txt @@ -1,6 +1,6 @@ SlyVote - Version 0.29 Beta - Release date: 2017-08-27 + Version 0.30 Beta + Release date: 2017-09-08 by