Skip to content
Snippets Groups Projects
Commit 02daca9e authored by Kayz's avatar Kayz Committed by Rob Swindell
Browse files

Special menus (most launched, longest run, most recent), fixed mail check,...

Special menus (most launched, longest run, most recent), fixed mail check, fixed feedback subject, made all text configurable, added search, ESC to exit menus, lightbar navigation, return/quit in menu, can paste items in editor into empty menus, bug fixes, and more
parent 5a2b4cc6
No related branches found
No related tags found
1 merge request!463MRC mods by Codefenix (2024-10-20)
; Options for Xtrn Menu Mod
; http://wiki.synchro.net/module:xtrnmenu
; Refer to the wiki for instructions on how to customize individual menus
[xtrnmenu]
; Uncomment if you wish to have the mod hand over section menus to xtrn_sec.js
;use_xtrn_sec = true
; Default sort, can be "name", "key", or false (no sort)
sort = false
; Enable multi-column display (when more than 10 external programs in a section)
multicolumn = true
; Clear the (remote) terminal screen before displaying the menu
clear_screen = true
; uncomment and modify any of the below to change the look of the external programs menu
; to remove titles or underline, set to the text ' '
;multicolumn_separator: " "
;singlecolumn_margin=7
;header_fmt: \1n\1c\1h%s \1n\1cExternal Programs:\r\n\r\n
;titles: \1n\1cKey \1h\xb3\1n\1c Name \1n\1c
multicolumn_fmt: \1h\1c%3s \xb3 \1n\1c%-32.32s \1h
singlecolumn_fmt: \1h\1c%3s \xb3 \1n\1c%s \1h
;which: \r\n\1-\1cWhich or \1h~Q\1n\1cuit: \1h
;underline: \1c\1h\xc4\xc4\xc4\xc4\xc5\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4
; used by the lightbar
multicolumn_fmt_inverse: \1n\1w[\1y\1h%2s\1n\1w] \1n\1w\1h\x015%-32.32s \1n\1h
singlecolumn_fmt_inverse: \1n\1w[\1y\1h%2s\1n\1w] \1n\1w\1h\x015%s \1n\1h
; to enable cost display, use these instead
; Note: cost not supported in special menus
;titles: \1n\1cInput \1h\xb3\1n\1c Name Cost \1n\1c
;multicolumn_fmt: \1h\1c%3s \xb3 \1n\1c%-26.26s\1h %5u
;singlecolumn_fmt: \1h\1c%3s \xb3 \1n\1c%-26.26s\1h %5u
;multicolumn_fmt_inverse: \1h\1c%3s \xb3 \1n\x016\1w\1h%-26.26s\1n \1c%5u
;singlecolumn_fmt_inverse: \1h\1c%3s \xb3 \1n\x016\1w\1h%-26.26s\1n \1c%5u
; These are used for the special menus (most launched, etc.)
; It adds the "stats" field which is the number of launches, amount of time, etc.
multicolumn_fmt_special: \1h\1c%3s \xb3 \1m%-21.21s\1h \1m%-10s
singlecolumn_fmt_special: \1h\1c%3s \xb3 \1m%-21.21s\1h \1m%-10s
multicolumn_fmt_special: \1h\1c%3s \xb3 \1m%-21.21s\1h \1m%-10s
singlecolumn_fmt_special: \1h\1c%3s \xb3 \1m%-21.21s\1h \1m%-10s
; Override the message when there are no programs available
; (defaults to text.dat NoXtrnPrograms)
;no_programs_msg:
; Override the restricted user msg
; (defaults to text.dat R_ExternalPrograms)
;restricted_user_msg:
; JSON service powers special menus (most popular, recent, etc.)
; Add appropriate entry to json-service.ini and set host/port here
;json_enabled = true
;json_host = localhost
;json_port = 10088
; Exclude external codes or external sections from being tracked
; and showing up in special menus (most popular, recent, etc.)
blacklist_tracking_xtrncodes: bullshit,sbbslist,avatchoo
blacklist_tracking_xtrnsec: operator
; Formatting for the "return to previous menu" option
return_msg: "\xae Return to Previous Menu"
logoff_msg: "Logoff"
quit_msg: "Quit"
; Formatting for the "return to previous menu" option
return_msg: "\xae Return to Previous Menu"
logoff_msg: "Logoff"
quit_msg: "Quit"
return_multicolumn_fmt: \1h\1c%3s \xb3 \1n\1c%-32.32s \1h
return_singlecolumn_fmt: \1h\1c%3s \xb3 \1n\1c%s \1h
return_multicolumn_fmt_inverse: \1h\1c%3s \xb3 \1n\x016\1w\1h%-32.32s \1n\1h
return_singlecolumn_fmt_inverse: \1h\1c%3s \xb3 \1n\x016\1w\1h%s \1n\1h
return_multicolumn_special_fmt: \1h\1c%3s \xb3 \1m%-32.32s\1h
return_singlecolumn_special_fmt: \1h\1c%3s \xb3 \1m%s\1h
return_multicolumn_special_fmt_inverse: \1h\1c%3s \xb3 \x015\1w\1h%-32.32s\1n
return_singlecolumn_special_fmt_inverse: \1h\1c%3s \xb3 \x015\1w\1h%s\1n
; Change display of filearea command menu
;xfer_prompt: "\x01n\x01c\xfe \x01b\x01hFile \x01n\x01c\xfe \x01h"
;xfer_prompt2: " \x01n\x01c@DIR@: \x01n"
;command_prompt: "\r\n\x01gCommand: "
;view_prompt: "\r\n\x01c\x01hView File(s)\r\n"
;searchfname_prompt: "\r\n\x01c\x01hSearch for Filename(s)\r\n"
;remove_prompt: "\r\n\x01c\x01hRemove/Edit File(s)\r\n"
;finddesc_prompt: "\r\n\x01c\x01hFind Text in File Descriptions (no wildcards)\r\n"
;download:prompt: "\r\n\x01c\x01hDownload File(s)\r\n"
; Change display of search menu
entersearchterm: "\x01y\x01hEnter search term: "
searchresultheader: "\x01n\x01cSearch Results for \x01h%s"
searchagainmsg: "\x01n\x01mPress S to Search Again."
; Feedback Module
;feedback_subject: "Game Server Feedback\r\n"
;feedback_msg: Thank you for your Feedback, @SYSOP@ will get back to you ASAP!\r\n\r\n
; Favorites Module
;favorite_add_item: "Add Item"
;favorte_remove_item: "Remove Item"
;add_favorites_msg: "\x01c\x01hAdd Favorite"
;remove_favorites_msg: "\x01c\x01hRemove Favorite"
;favorites_inst: "\x01n\x01w\x01h\x012 [Up/Down/Home/End] to Navigate, [Enter] to Select, [Q] to Quit, [S] to Search "
;favorites_inst_rem: "\x01n\x01w\x01h\x012 [Up/Down/Home/End] to Navigate, [Enter] to Select, [Q] to Quit "
;favorite_add_search_prompt: "\x01c\x01hSearch (ESC to Cancel): \x01n"
; autocomplete (search) box on add favorite
; see cga_defs.js for color codes
; autocomplete input box
;favorite_add_search_fg=LIGHTGRAY
;favorite_add_search_bg=BG_BLACK
; autocomplete result box
;favorite_add_search_sfg=LIGHTGRAY
;favorite_add_search_sbg=BG_BLACK
; autocomplete highlighted row
;favorite_add_search_hsfg=WHITE
;favorite_add_search_hsbg=BG_MAGENTA
; scrolling menu on add favorite
; lightbar non-current item
;favorite_add_fg=LIGHTGRAY
;favorite_add_bg=BG_BLACK
; lightbar current item
;favorite_add_lfg=WHITE
;favorite_add_lbg=BG_MAGENTA
; tree heading
;favorite_add_cfg=WHITE
;favorite_add_cbg=BG_BLACK
\ No newline at end of file
...@@ -67,6 +67,12 @@ ExternalMenus.prototype.getOptions = function(menutype, menuid) { ...@@ -67,6 +67,12 @@ ExternalMenus.prototype.getOptions = function(menutype, menuid) {
if (this.options.singlecolumn_fmt === undefined) if (this.options.singlecolumn_fmt === undefined)
this.options.singlecolumn_fmt = "\x01h\x01c%3u \xb3 \x01n\x01c%s\x01h "; this.options.singlecolumn_fmt = "\x01h\x01c%3u \xb3 \x01n\x01c%s\x01h ";
if (this.options.multicolumn_fmt_inverse === undefined)
this.options.multicolumn_fmt_inverse = system.text(XtrnProgLstFmt);
if (this.options.singlecolumn_fmt_inverse === undefined)
this.options.singlecolumn_fmt_inverse = "\x01h\x01c%3u \xb3 \x01n\x01c%s\x01h ";
if (this.options.singlecolumn_margin == undefined) if (this.options.singlecolumn_margin == undefined)
this.options.singlecolumn_margin = 7; this.options.singlecolumn_margin = 7;
...@@ -120,6 +126,20 @@ ExternalMenus.prototype.getOptions = function(menutype, menuid) { ...@@ -120,6 +126,20 @@ ExternalMenus.prototype.getOptions = function(menutype, menuid) {
this.options.singlecolumn_fmt = "\x01h\x01c%3s \xb3 \x01n\x01c%s\x01h "; this.options.singlecolumn_fmt = "\x01h\x01c%3s \xb3 \x01n\x01c%s\x01h ";
} }
if (typeof this.xtrn_custommenu_options.multicolumn_fmt_inverse !== "undefined") {
this.options.multicolumn_fmt_inverse = this.xtrn_custommenu_options.multicolumn_fmt_inverse;
} else {
// cannot default to xtrn_sec multicolumn_fmt due to use of %u instead of %s
this.options.multicolumn_fmt_inverse = "\x01h\x01c%3s \xb3 \x01n\x016\x01w\x01h%-32.32s \x01n\x01h";
}
if (typeof this.xtrn_custommenu_options.singlecolumn_fmt_inverse !== "undefined") {
this.options.singlecolumn_fmt_inverse = this.xtrn_custommenu_options.singlecolumn_fmt_inverse;
} else {
// cannot default to xtrn_sec multicolumn_fmt due to use of %u instead of %s
this.options.singlecolumn_fmt_inverse = "\x01h\x01c%3s \xb3 \x01n\x016\x01w\x01h%s \x01n\x01h";
}
this.options.header_fmt = (typeof this.xtrn_custommenu_options.header_fmt !== "undefined") this.options.header_fmt = (typeof this.xtrn_custommenu_options.header_fmt !== "undefined")
? this.xtrn_custommenu_options.header_fmt : this.options.header_fmt; ? this.xtrn_custommenu_options.header_fmt : this.options.header_fmt;
...@@ -151,7 +171,7 @@ ExternalMenus.prototype.getOptions = function(menutype, menuid) { ...@@ -151,7 +171,7 @@ ExternalMenus.prototype.getOptions = function(menutype, menuid) {
this.options.singlecolumn_height = (typeof this.xtrn_custommenu_options.singlecolumn_height !== "undefined") this.options.singlecolumn_height = (typeof this.xtrn_custommenu_options.singlecolumn_height !== "undefined")
? this.xtrn_custommenu_options.singlecolumn_height : this.options.singlecolumn_height; ? this.xtrn_custommenu_options.singlecolumn_height : this.options.singlecolumn_height;
if (this.options.singlecolumn_height == undefined) if (this.options.singlecolumn_height === undefined)
this.options.singlecolumn_height = console.screen_rows - this.options.singlecolumn_margin; this.options.singlecolumn_height = console.screen_rows - this.options.singlecolumn_margin;
// override and turn off multicolumn if terminal width is less than 80 // override and turn off multicolumn if terminal width is less than 80
...@@ -164,13 +184,25 @@ ExternalMenus.prototype.getOptions = function(menutype, menuid) { ...@@ -164,13 +184,25 @@ ExternalMenus.prototype.getOptions = function(menutype, menuid) {
// Allow overriding on a per-menu basis // Allow overriding on a per-menu basis
var menuoptions = load({}, "modopts.js", "xtrnmenu:" + menuid); var menuoptions = load({}, "modopts.js", "xtrnmenu:" + menuid);
if ((typeof menuid !== "undefined") && (menuoptions != null)) { if ((typeof menuid !== "undefined") && (menuoptions !== null)) {
for (var m in menuoptions) { for (var m in menuoptions) {
this.options[m] = menuoptions[m]; this.options[m] = menuoptions[m];
} }
} }
} }
this.options.json_enabled = (typeof this.xtrn_custommenu_options.json_enabled !== undefined)
? this.xtrn_custommenu_options.json_enabled : false;
this.options.json_host = (typeof this.xtrn_custommenu_options.json_host !== undefined)
? this.xtrn_custommenu_options.json_host : "localhost";
this.options.json_port = (typeof this.xtrn_custommenu_options.json_port !== undefined)
? this.xtrn_custommenu_options.json_port : 10088;
this.options.blacklist_tracking_xtrncodes = (typeof this.xtrn_custommenu_options.blacklist_tracking_xtrncodes !== undefined)
? this.xtrn_custommenu_options.blacklist_tracking_xtrncodes : "";
this.options.blacklist_tracking_xtrnsec = (typeof this.xtrn_custommenu_options.blacklist_tracking_xtrnsec !== undefined)
? this.xtrn_custommenu_options.blacklist_tracking_xtrnsec : "";
// these options only apply to terminals/consoles // these options only apply to terminals/consoles
// the intention is to obtain all the mod_opts options for xtrn_sec, and // the intention is to obtain all the mod_opts options for xtrn_sec, and
...@@ -185,6 +217,8 @@ ExternalMenus.prototype.getOptions = function(menutype, menuid) { ...@@ -185,6 +217,8 @@ ExternalMenus.prototype.getOptions = function(menutype, menuid) {
this.options.custom_menu_program_not_found_msg = "Program %PROGRAMID% not found"; this.options.custom_menu_program_not_found_msg = "Program %PROGRAMID% not found";
} }
this.options.custom = this.xtrn_custommenu_options;
return this.options; return this.options;
} }
...@@ -216,20 +250,20 @@ ExternalMenus.prototype.getMenu = function(menuid) { ...@@ -216,20 +250,20 @@ ExternalMenus.prototype.getMenu = function(menuid) {
xtrn_area.sec_list.forEach(function (sec) { xtrn_area.sec_list.forEach(function (sec) {
if (sec.can_access) { if (sec.can_access) {
menuitems.push({ menuitems.push({
"input": i, input: i,
"target": sec.code, target: sec.code,
"type": "xtrnmenu", type: "xtrnmenu",
"title": sec.name, title: sec.name,
"access_string": sec.ars access_string: sec.ars
}); });
i++; i++;
} }
}); });
menu = { menu = {
"id": "main", id: "main",
"title": "Main Menu", title: "Main Menu",
"items": menuitems items: menuitems
}; };
} }
return menu; return menu;
...@@ -244,12 +278,17 @@ ExternalMenus.prototype.getSectionMenu = function(menuid) { ...@@ -244,12 +278,17 @@ ExternalMenus.prototype.getSectionMenu = function(menuid) {
} }
var menuitems = []; var menuitems = [];
var menu, title; var title;
xtrn_area.sec_list.some(function (sec) { var menu = {
id: menuid,
title: null,
items: []
}
xtrn_area.sec_list.some(function (sec) {
if (sec.code.toLowerCase() == menuid.toLowerCase()) { if (sec.code.toLowerCase() == menuid.toLowerCase()) {
title = sec.name; menu.title = sec.name;
if (!sec.can_access || sec.prog_list.length < 1) { if (!sec.can_access || sec.prog_list.length < 1) {
return false; return false;
...@@ -258,22 +297,18 @@ ExternalMenus.prototype.getSectionMenu = function(menuid) { ...@@ -258,22 +297,18 @@ ExternalMenus.prototype.getSectionMenu = function(menuid) {
var i = 1; var i = 1;
sec.prog_list.some(function (prog) { sec.prog_list.some(function (prog) {
menuitems.push({ menuitems.push({
'input' : i, input : i,
'target': prog.code, target: prog.code,
'title': prog.name, title: prog.name,
'type': 'xtrnprog', type: 'xtrnprog',
'access_string': prog.ars, access_string: prog.ars,
'cost': prog.cost cost: prog.cost
}); });
i++; i++;
}); });
if (menuitems.length > 0) { if (menuitems.length > 0) {
menu = { menu.items = menuitems;
'id': menuid,
'title': title,
'items': menuitems,
};
} }
return; return;
} }
...@@ -412,3 +447,214 @@ ExternalMenus.prototype.sort_by_input = function(a, b) { ...@@ -412,3 +447,214 @@ ExternalMenus.prototype.sort_by_input = function(a, b) {
} }
return 0; return 0;
} }
// Handle json update
ExternalMenus.prototype.processUpdate = function(update) {
log(ERROR, "Unhandled JSON DB packet: " + JSON.stringify(update));
}
// Sort for special menus, by value numerically desc
ExternalMenus.prototype.sort_special = function(obj) {
var keys = [];
for(var key in obj) {
keys.push(key);
}
return keys.sort(function(a,b) { return obj[b]-obj[a]});
}
// return menu object for special menu (most recent, etc.)
ExternalMenus.prototype.getSpecial = function(menutype, title, itemcount) {
var options = this.getOptions('custommenu', menutype);
var menu;
var menuitems = [];
if (itemcount === undefined) {
itemcount = 0;
}
if (menutype === undefined) {
log(LOG_DEBUG, "xtrnmenulib: getSpecial called without menutype");
return false;
}
if (!this.options.json_enabled) {
log(LOG_DEBUG, "xtrnmenulib: Skipping " + menutype + " because JSON is not enabled");
return false;
}
try {
require("json-client.js", "JSONClient");
var jsonClient = new JSONClient(this.options.json_host, this.options.json_port);
jsonClient.callback = this.processUpdate;
} catch (e) {
writeln("NP" + e);
log(LOG_ERR, "xtrnmenulib: Could not initialize JSON database so special menu is now disabled: " + e);
return false;
}
var sortedItems = [];
var jsonData = [];
switch (menutype) {
// game keys sorted by most recent descending
case 'recentall':
jsonData = jsonClient.read("xtrnmenu", "launchstart", 1);
break;
case 'recentuser':
jsonData = jsonClient.read("xtrnmenu", "launchstart_user_" + user.alias, 1);
break;
case 'mostlaunchedall':
jsonData = jsonClient.read("xtrnmenu", "launchnum", 1);
break;
case 'mostlauncheduser':
jsonData = jsonClient.read("xtrnmenu", "launchnum_user_" + user.alias, 1);
break;
case 'longestrunall':
jsonData = jsonClient.read("xtrnmenu", "timeran", 1);
break;
case 'longestrunuser':
jsonData = jsonClient.read("xtrnmenu", "timeran_user_" + user.alias, 1);
break;
default:
log(LOG_ERR, "xtrnmenulib: Unknown special menu type: " + menutype);
return false;
}
if (!jsonData) {
jsonData = {};
}
sortedItems = this.sort_special(jsonData);
var i = 1;
for (var d=0; d<sortedItems.length; d++) {
var doorid = sortedItems[d];
for (var e in xtrn_area.prog) {
if (xtrn_area.prog[e].code.toLowerCase() == doorid.toLowerCase()) {
var stats;
switch (menutype) {
case 'longestrunall':
case 'longestrunuser':
var seconds = jsonData[doorid];
var hours = ~~(seconds/3600);
var mins = ~~((seconds % 3600) / 60);
var secs = ~~seconds % 60;
stats = ("00"+hours).slice(-2) + ":" + ("00"+mins).slice(-2) + ":" + ("00"+secs).slice(-2);
break;
case 'recentall':
case 'recentuser':
var elapsedtime = (time() - jsonData[doorid])*1000;
var msPerMin = 60000;
var msPerHour = msPerMin * 60;
var msPerDay = msPerHour * 24;
var msPerMon = msPerDay * 30;
var msPerYear = msPerDay * 365;
if (elapsedtime < msPerMin) {
stats = Math.round(elapsedtime/1000) + ' sec ago';
} else if (elapsedtime < msPerHour) {
stats = Math.round(elapsedtime/msPerMin) + ' min ago';
} else if (elapsedtime < msPerDay) {
var stat = Math.round(elapsedtime/msPerHour)
stats = Math.round(elapsedtime/msPerHour) + ' hr ago';
} else if (elapsedtime < msPerMon) {
stats = Math.round(elapsedtime/msPerDay) + ' day ago';
} else if (elapsedtime < msPerYear) {
stats = Math.round(elapsedtime/msPerMonth) + ' mon ago';
} else {
stats = Math.round(elapsedtime/msPerYear) + ' yr ago';
}
break;
default:
stats = jsonData[doorid].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");;
break;
}
menuitems.push({
input: i,
target: xtrn_area.prog[e].code,
title: xtrn_area.prog[e].name,
type: 'xtrnprog',
access_string: xtrn_area.prog[e].ars,
cost: xtrn_area.prog[e].cost,
stats: stats,
});
i++;
break;
}
}
if ((itemcount > 0) && ((d + 1) >= itemcount)) {
break;
}
}
if (menuitems.length > 0) {
menu = {
id: menutype,
title: title,
items: menuitems,
};
}
return menu;
}
// return menu object for user's favorites
ExternalMenus.prototype.getFavorites = function(title, itemcount) {
var menu;
var menuitems = [];
if (itemcount === undefined) {
itemcount = 0;
}
if (!this.options.json_enabled) {
log(LOG_DEBUG, "xtrnmenulib: Skipping favorites because JSON is not enabled");
return false;
}
try {
require("json-client.js", "JSONClient");
var jsonClient = new JSONClient(this.options.json_host, this.options.json_port);
jsonClient.callback = this.processUpdate;
} catch (e) {
log(LOG_ERR, "xtrnmenulib: Could not initialize JSON database so favorites is now disabled: " + e);
return false;
}
var sortedItems = [];
var jsonData = jsonClient.read("xtrnmenu", "favorites_" + user.alias, 1);
if (!jsonData) {
jsonData = {};
}
var i = 1;
for (var d=0; d<jsonData.length; d++) {
for (var e in xtrn_area.prog) {
if (xtrn_area.prog[e].code.toLowerCase() == jsonData[d].toLowerCase()) {
var stats;
menuitems.push({
input: i,
target: xtrn_area.prog[e].code,
title: xtrn_area.prog[e].name,
type: 'xtrnprog',
access_string: xtrn_area.prog[e].ars,
cost: xtrn_area.prog[e].cost,
});
i++;
break;
}
}
if ((itemcount > 0) && ((d + 1) >= itemcount)) {
break;
}
}
menu = {
id: 'favorites',
title: title !== undefined ? title : 'Favorites',
items: menuitems,
};
return menu;
}
\ No newline at end of file
This diff is collapsed.
...@@ -72,7 +72,7 @@ var editMenu = function(menuid) { ...@@ -72,7 +72,7 @@ var editMenu = function(menuid) {
} }
while(1) { while(1) {
uifc.help_text = word_wrap("This screen allows you to edit the configuration options for the custom menu.\r\n\r\nMost options default or are set in modopts.ini, but here you can define them on a per-menu basis.\r\n\r\nClick Edit Items to edit the individual entries (programs, menus, etc.)"); uifc.help_text = word_wrap("This screen allows you to edit the configuration options for the custom menu.\r\n\r\nMost options default or are set in modopts.ini, but here you can define them on a per-menu basis.\r\n\r\nClick Edit Items to edit the individual entries (programs, menus, etc.)", 72);
selections = []; selections = [];
for (var j in menu.items) { for (var j in menu.items) {
...@@ -110,7 +110,7 @@ var editMenu = function(menuid) { ...@@ -110,7 +110,7 @@ var editMenu = function(menuid) {
switch (editproperty) { switch (editproperty) {
case 'id': case 'id':
uifc.help_text = word_wrap("This is a unique ID for the menu, which can be used as the target to\r\ncall the menu from other menus.\r\n\r\nFor the top-level menu, the id should be 'main'."); uifc.help_text = word_wrap("This is a unique ID for the menu, which can be used as the target to\r\ncall the menu from other menus.\r\n\r\nFor the top-level menu, the id should be 'main'.", 72);
var selection2 = uifc.input(WIN_MID, "Menu ID", menu.id, 50, K_EDIT); var selection2 = uifc.input(WIN_MID, "Menu ID", menu.id, 50, K_EDIT);
if ((selection2 < 0) || (selection2 == null)) { if ((selection2 < 0) || (selection2 == null)) {
// escape key // escape key
...@@ -129,7 +129,7 @@ var editMenu = function(menuid) { ...@@ -129,7 +129,7 @@ var editMenu = function(menuid) {
break; break;
case 'sort_type': case 'sort_type':
uifc.help_text = word_wrap("How to sort the menu:\r\nby input key\r\nby title\r\nnone (the items remain in the order they are in the config)"); uifc.help_text = word_wrap("How to sort the menu:\r\nby input key\r\nby title\r\nnone (the items remain in the order they are in the config)", 72);
switch (uifc.list(WIN_ORG | WIN_MID, "Sort Type", ["key", "title", "none"])) { switch (uifc.list(WIN_ORG | WIN_MID, "Sort Type", ["key", "title", "none"])) {
case 0: case 0:
...@@ -183,47 +183,37 @@ var editItems = function(menuid) { ...@@ -183,47 +183,37 @@ var editItems = function(menuid) {
} }
} }
/* commented out as it prevents pasting into new menu
if ((typeof menu.items == "undefined") || (menu.items.length == 0)) { if ((typeof menu.items == "undefined") || (menu.items.length == 0)) {
// no items, prompt them to make one // no items, prompt them to make one
editItem(menu.id, 0); editItem(menu.id, 0);
} }
*/
uifc.help_text = word_wrap("This menu allows editing the various items in this menu.\r\n\r\n" uifc.help_text = word_wrap("This menu allows editing the various items in this menu.\r\n\r\n"
+ "If you leave input key blank, it will use an auto-generated number at display time.\r\n\r\n" + "If you leave input key blank, it will use an auto-generated number at display time.\r\n\r\n"
+ "Choose a type first and the dropdown to choose tha target will allow you to select your target.\r\n\r\n" + "Choose a type first and the dropdown to choose the target will allow you to select your target.\r\n\r\n"
+ "Access string only applies to custom menu items. For external sections or external programs, use the access settings in scfg.\r\n\r\n"); + "Access string only applies to custom menu items, commands, and special menus. For external sections or external programs, use the access settings in scfg.\r\n\r\n",
72);
while(1) { while(1) {
items = []; items = [];
itemids = []; itemids = [];
for(i in menu.items) { for(i in menu.items) {
items.push(format( items.push(format(
"%6s %10s %s", "%6s %16s %s",
menu.items[i].input ? menu.items[i].input : '(auto)', menu.items[i].input ? menu.items[i].input : '(auto)',
menu.items[i].type, menu.items[i].type,
menu.items[i].title menu.items[i].title
)); ));
itemids.push(i); itemids.push(i);
} }
// WIN_ORG = original menu
// WIN_MID = centered mid
// WIN_ACT = menu remains active after a selection
// WIN_ESC = screen is active when escape is pressed
// WIN_XTR = blank line to insert
// WIN_INS = insert key
// WIN_DEL = delete
// WIN_CUT = cut ctrl-x
// WIN_COPY = copy ctrl-c
// WIN_PUT = paste ctrl-v
// WIN_SAV = use context/save position
selection = uifc.list( selection = uifc.list(
WIN_ORG|WIN_MID|WIN_ACT|WIN_ESC|WIN_XTR|WIN_INS|WIN_DEL|WIN_CUT|WIN_COPY|WIN_PASTE|WIN_SAV, WIN_ORG|WIN_MID|WIN_ACT|WIN_ESC|WIN_XTR|WIN_INS|WIN_DEL|WIN_CUT|WIN_COPY|WIN_PASTE|WIN_PASTEXTR|WIN_SAV,
menu.title + ": Items", menu.title + ": Items",
items, items,
ctxm ctxm
); );
if (selection == -1) { if (selection == -1) {
// esc key // esc key
break; break;
...@@ -270,7 +260,8 @@ var editItems = function(menuid) { ...@@ -270,7 +260,8 @@ var editItems = function(menuid) {
if ("type" in copyitem) { if ("type" in copyitem) {
// if item already exists in list, modify if since you can't have dupes (except empty input keys) // if item already exists in list, modify if since you can't have dupes (except empty input keys)
for (var i in menu.items) { for (var i in menu.items) {
if ((menu.items[i].input == copyitem.input) && (copyitem.input !== null) && (copyitem.input !== "")) { if ((menu.items[i].input == copyitem.input)
&& (copyitem.input !== null) && (copyitem.input !== "")) {
oktopaste = true; oktopaste = true;
while(1) { while(1) {
selection2 = uifc.input(WIN_MID, "Enter New Input Key", "", 3, K_EDIT); selection2 = uifc.input(WIN_MID, "Enter New Input Key", "", 3, K_EDIT);
...@@ -302,13 +293,20 @@ var editItems = function(menuid) { ...@@ -302,13 +293,20 @@ var editItems = function(menuid) {
} }
if ((oktopaste) || (copyitem.input === "null") || (copyitem.input === "")) { if ((oktopaste) || (copyitem.input === "null") || (copyitem.input === "")) {
var menuitems2 = []; var menuitems2 = [];
var pushed = false;
for (i in menu.items) { for (i in menu.items) {
menuitems2.push(menu.items[i]); // paste copied item before selected item
// paste copied item after selected item
if (i == itemids[selection]) { if (i == itemids[selection]) {
menuitems2.push(copyitem); menuitems2.push(copyitem);
ctxm.cur = i-1; ctxm.cur = i-1;
pushed = true;
} }
menuitems2.push(menu.items[i]);
}
if (!pushed) {
// add to end
menuitems2.push(copyitem);
ctxm.cur = menuitems2.length-1;
} }
menu.items = menuitems2; menu.items = menuitems2;
} }
...@@ -349,6 +347,7 @@ var editItem = function(menuid, itemindex) { ...@@ -349,6 +347,7 @@ var editItem = function(menuid, itemindex) {
if (typeof menu.items[itemindex] === "undefined") { if (typeof menu.items[itemindex] === "undefined") {
// new item // new item
//
menu.items.push({ menu.items.push({
"input": null, "input": null,
"title": "New Item " + time(), "title": "New Item " + time(),
...@@ -379,21 +378,69 @@ var editItem = function(menuid, itemindex) { ...@@ -379,21 +378,69 @@ var editItem = function(menuid, itemindex) {
("type" in item ? item.type : ""))); ("type" in item ? item.type : "")));
displayoptionids.push("type"); displayoptionids.push("type");
switch (item.type) {
case 'recentall':
case 'recentuser':
case 'mostlaunchedall':
case 'mostlauncheduser':
case 'longestrunall':
case 'longestrunuser':
case 'search':
case 'favorites':
displayoptions.push(format("%23s: %s", "count",
("target" in item ? item.target : "")));
displayoptionids.push("target");
break;
case 'custommenu':
case 'xtrnmenu':
case 'xtrnprog':
case 'command':
default:
displayoptions.push(format("%23s: %s", "target", displayoptions.push(format("%23s: %s", "target",
("target" in item ? item.target : ""))); ("target" in item ? item.target : "")));
displayoptionids.push("target"); displayoptionids.push("target");
break;
}
if ((item.type == "custommenu") || (item.type == "command")) { switch (item.type) {
case 'custommenu':
case 'command':
case 'recentall':
case 'recentuser':
case 'mostlaunchedall':
case 'mostlauncheduser':
case 'longestrunuser':
case 'longestrunall':
case 'search':
case 'favorites':
displayoptions.push(format("%23s: %s", "access_string", displayoptions.push(format("%23s: %s", "access_string",
("access_string" in item ? item.access_string : "(default)"))); ("access_string" in item ? item.access_string : "(default)")));
displayoptionids.push("access_string"); displayoptionids.push("access_string");
break;
case 'xtrnmenu':
case 'xtrnprog':
default:
break;
} }
selection = uifc.list(WIN_ORG | WIN_MID | WIN_ACT | WIN_ESC, selection = uifc.list(WIN_ORG | WIN_MID | WIN_ACT | WIN_ESC,
menu.title + ": Item " + itemindex, displayoptions, itemctx); menu.title + ": Item " + itemindex, displayoptions, itemctx);
if (selection < 0) { if (selection < 0) {
if (!item.title || !item.type || !item.target) { if (!item.title || !item.type) {
if (uifc.list(WIN_ORG | WIN_MID, "This item is missing required items.", ["Remove Item", "Edit Item"]) == 0) {
// delete item and continue
newitems = [];
for (i in menu.items) {
if (i != itemindex) {
newitems.push(menu.items[i]);
}
}
menu.items = newitems;
break;
}
} else if (!item.target && ((item.type == "custommenu") || (item.type == "command")
|| (item.type == "xtrnmenu") || (item.type == "xtrnprog"))) {
if (uifc.list(WIN_ORG | WIN_MID, "This item is missing required items.", ["Remove Item", "Edit Item"]) == 0) { if (uifc.list(WIN_ORG | WIN_MID, "This item is missing required items.", ["Remove Item", "Edit Item"]) == 0) {
// delete item and continue // delete item and continue
newitems = []; newitems = [];
...@@ -405,6 +452,7 @@ var editItem = function(menuid, itemindex) { ...@@ -405,6 +452,7 @@ var editItem = function(menuid, itemindex) {
menu.items = newitems; menu.items = newitems;
break; break;
} }
break;
} else { } else {
// leave menu // leave menu
break; break;
...@@ -414,7 +462,7 @@ var editItem = function(menuid, itemindex) { ...@@ -414,7 +462,7 @@ var editItem = function(menuid, itemindex) {
switch (displayoptionids[selection]) { switch (displayoptionids[selection]) {
case 'input': case 'input':
uifc.help_text = word_wrap("The input key to access this item. Can be anything except Q. Leave blank to auto-generate a number."); uifc.help_text = word_wrap("The input key to access this item. Can be anything except Q. Leave blank to auto-generate a number.", 72);
selection2 = uifc.input(WIN_MID, "Input Key", item.input, 3, K_EDIT); selection2 = uifc.input(WIN_MID, "Input Key", item.input, 3, K_EDIT);
if ((selection2 < 0) || (selection2 == null)) { if ((selection2 < 0) || (selection2 == null)) {
// escape key // escape key
...@@ -436,7 +484,9 @@ var editItem = function(menuid, itemindex) { ...@@ -436,7 +484,9 @@ var editItem = function(menuid, itemindex) {
} }
} }
if (keyused) { if (selection2 == "Q") {
uifc.msg("This input key Q is reserved");
} else if (keyused) {
uifc.msg("This input key is already used by another item."); uifc.msg("This input key is already used by another item.");
} else { } else {
item.input = selection2; item.input = selection2;
...@@ -470,7 +520,7 @@ var editItem = function(menuid, itemindex) { ...@@ -470,7 +520,7 @@ var editItem = function(menuid, itemindex) {
break; break;
case 'access_string': case 'access_string':
uifc.help_text = word_wrap("The access string for the custom menu.\r\n\r\nOnly applies to custom menu items.\r\n\r\nExample: LEVEL 60"); uifc.help_text = word_wrap("The access string for the custom menu.\r\n\r\nOnly applies to custom menu items.\r\n\r\nExample: LEVEL 60", 72);
selection2 = uifc.input(WIN_MID, "Access String", item.access_string, 255, K_EDIT); selection2 = uifc.input(WIN_MID, "Access String", item.access_string, 255, K_EDIT);
if ((selection2 < 0) || (selection2 == null)) { if ((selection2 < 0) || (selection2 == null)) {
// escape key // escape key
...@@ -491,7 +541,15 @@ function present_select_targettype(item) ...@@ -491,7 +541,15 @@ function present_select_targettype(item)
+ "custommenu is a custom menu defined in this tool.\r\n\r\n" + "custommenu is a custom menu defined in this tool.\r\n\r\n"
+ "xtrnmenu is a standard Syncrhonet External Section Menu (refer to the scfg tool).\r\n\r\n" + "xtrnmenu is a standard Syncrhonet External Section Menu (refer to the scfg tool).\r\n\r\n"
+ "xtrnprog is a direct link to an external program (refer to the scfg tool)" + "xtrnprog is a direct link to an external program (refer to the scfg tool)"
+ "command is a synchronet command line. See http://wiki.synchro.net/config:cmdline"); + "command is a synchronet command line. See http://wiki.synchro.net/config:cmdline"
+ "recentall is a special menu of most recently used games, by all users"
+ "recentuser is a special menu of most recently used games, for current user"
+ "mostlaunchedall is a special menu of most launched games, by all users"
+ "mostlauncheduser is a special menu of most launched games, for current user"
+ "longestrunall is a special menu of games that users spent the most time in"
+ "longestrunuser is a special menu of games that current user spent the most time in"
+ "search is a special menu item to perform a search"
+ "favorites is a special menu to let the user pick favorite games to play", 72);
var targetypectx = uifc.list.CTX(0, 0, 0, 0, 0); var targetypectx = uifc.list.CTX(0, 0, 0, 0, 0);
if (typeof item.type !== "undefined") { if (typeof item.type !== "undefined") {
...@@ -512,10 +570,44 @@ function present_select_targettype(item) ...@@ -512,10 +570,44 @@ function present_select_targettype(item)
targetypectx.cur = 3; targetypectx.cur = 3;
targetypectx.bar = 3; targetypectx.bar = 3;
break; break;
case 'recentall':
targetypectx.cur = 4;
targetypectx.bar = 4;
break;
case 'recentuser':
targetypectx.cur = 5;
targetypectx.bar = 5;
break;
case 'mostlaunchedall':
targetypectx.cur = 6;
targetypectx.bar = 6;
break;
case 'mostlauncheduser':
targetypectx.cur = 7;
targetypectx.bar = 7;
break;
case 'longestrunall':
targetypectx.cur = 8;
targetypectx.bar = 8;
break;
case 'longestrunuser':
targetypectx.cur = 9;
targetypectx.bar = 9;
break;
case 'search':
targetypectx.cur = 10;
targetypectx.bar = 10;
break;
case 'favorites':
targetypectx.cur = 11;
targetypectx.bar = 11;
break;
} }
} }
switch (uifc.list(WIN_ORG | WIN_MID | WIN_SAV, switch (uifc.list(WIN_ORG | WIN_MID | WIN_SAV,
"Target Type", ["custommenu", "xtrnmenu", "xtrnprog", "command"], targetypectx)) { "Target Type", ["custommenu", "xtrnmenu", "xtrnprog", "command", "recentall",
"recentuser", "mostlaunchedall", "mostlauncheduser", "longestrunall",
"longestrunuser", "search", "favorites"], targetypectx)) {
case 0: case 0:
item.type = "custommenu"; item.type = "custommenu";
break; break;
...@@ -528,6 +620,30 @@ function present_select_targettype(item) ...@@ -528,6 +620,30 @@ function present_select_targettype(item)
case 3: case 3:
item.type = "command"; item.type = "command";
break; break;
case 4:
item.type = "recentall";
break;
case 5:
item.type = "recentuser";
break;
case 6:
item.type = "mostlaunchedall";
break;
case 7:
item.type = "mostlauncheduser";
break;
case 8:
item.type = "longestrunall";
break;
case 9:
item.type = "longestrunuser";
break;
case 10:
item.type = "search";
break;
case 11:
item.type = "favorites";
break;
default: default:
// includes escape key // includes escape key
break; break;
...@@ -539,7 +655,8 @@ function present_select_targettype(item) ...@@ -539,7 +655,8 @@ function present_select_targettype(item)
function present_select_target(item) function present_select_target(item)
{ {
uifc.help_text = word_wrap("This is the ID of the custom menu, external program section, or external program to link to."); uifc.help_text = word_wrap("This is the ID of the custom menu, external program section, or external program to link to. "
+ "For special menus (recentall, etc.), it is the number of items to display.", 72);
var targetctx = uifc.list.CTX(0, 0, 0, 0, 0); var targetctx = uifc.list.CTX(0, 0, 0, 0, 0);
...@@ -623,7 +740,6 @@ function present_select_target(item) ...@@ -623,7 +740,6 @@ function present_select_target(item)
break; break;
case "xtrnprog": case "xtrnprog":
// present list of external programs // present list of external programs
// create sorted list // create sorted list
var proglist = []; var proglist = [];
...@@ -663,22 +779,38 @@ function present_select_target(item) ...@@ -663,22 +779,38 @@ function present_select_target(item)
} }
break; break;
command: case "command":
selection2 = uifc.input(WIN_ORG | WIN_MID, "Command", item.target, 63, K_EDIT); selection2 = uifc.input(WIN_ORG | WIN_MID, "Command", item.target, 63, K_EDIT);
if ((selection2 < 0) || (selection2 == null)) { if ((selection2 < 0) || (selection2 == null)) {
// escape key // escape key
break; break;
} }
item.target = selection2;
break;
case "recentall":
case "recentuser":
case "mostlaunchedall":
case "mostlauncheduser":
case "longestrunall":
case "longestrunuser":
case "search":
case "favorites":
selection2 = uifc.input(WIN_ORG | WIN_MID, "Number of Items to Display", item.target, 63, K_EDIT);
if ((selection2 < 0) || (selection2 == null)) {
// escape key
break;
}
item.target = selection2; item.target = selection2;
break; break;
break;
default: default:
selection2 = uifc.input(WIN_ORG | WIN_MID, "Target", item.target, 50, K_EDIT); selection2 = uifc.input(WIN_ORG | WIN_MID, "Target", item.target, 50, K_EDIT);
if ((selection2 < 0) || (selection2 == null)) { if ((selection2 < 0) || (selection2 == null)) {
// escape key // escape key
break; break;
} }
item.target = selection2; item.target = selection2;
break; break;
} }
...@@ -740,7 +872,7 @@ try { ...@@ -740,7 +872,7 @@ try {
var ctx = new uifc.list.CTX(0, 0, 0, 0, 0); var ctx = new uifc.list.CTX(0, 0, 0, 0, 0);
while(1) { while(1) {
uifc.help_text = word_wrap("This program allows managing the Enhanced External Program Menu feature."); uifc.help_text = word_wrap("This program allows managing the Enhanced External Program Menu feature.", 72);
// no menus or no main menu // no menus or no main menu
var mainmenufound = false; var mainmenufound = false;
......
<!--HIDDEN:Games--> <!--Games-->
<?xjs <?xjs
/** /**
* Web Display for Custom External Program Menus * Web Display for Custom External Program Menus
* by Michael Long mlong innerrealmbbs.us * by Michael Long mlong innerrealmbbs.us
* *
* See wiki at http://wiki.synchro.net/module:xtrnmenumod * See wiki at http://wiki.synchro.net/module:xtrnmenu
*/ */
load("ftelnethelper.js"); load("ftelnethelper.js");
...@@ -33,8 +33,43 @@ ...@@ -33,8 +33,43 @@
<?xjs <?xjs
var menuobj; var menuobj;
if ((Request.get_param('type') == 'xtrnmenu') && Request.has_param('target')) { if (Request.get_param('type')) {
menuobj = ExternalMenus.getSectionMenu(Request.get_param('target')); var target = Request.get_param('target');
switch (Request.get_param('type')) {
case 'custommenu':
if (target !== undefined) {
menuobj = ExternalMenus.getMenu(target);
}
break;
case 'xtrnmenu':
if (target !== undefined) {
menuobj = ExternalMenus.getSectionMenu(target);
}
break;
case 'recentall':
menuobj = ExternalMenus.getSpecial(Request.get_param('type'), "Most Recent - All", target);
break;
case 'recentuser':
menuobj = ExternalMenus.getSpecial(Request.get_param('type'), "Most Recent - Yours", target);
break;
case 'mostlaunchedall':
menuobj = ExternalMenus.getSpecial(Request.get_param('type'), "Most Launched - All", target);
break;
case 'mostlauncheduser':
menuobj = ExternalMenus.getSpecial(Request.get_param('type'), "Most Launched - Yours", target);
break;
case 'longestrunall':
menuobj = ExternalMenus.getSpecial(Request.get_param('type'), "Longest Run - All", target);
break;
case 'longestrunuser':
menuobj = ExternalMenus.getSpecial(Request.get_param('type'), "Longest Run - Yours", target);
break;
case 'favorites':
menuobj = ExternalMenus.getFavorites("Favorites", target);
break;
default:
break;
}
} else { } else {
if (Request.has_param('target')) { if (Request.has_param('target')) {
menuobj = ExternalMenus.getMenu(Request.get_param('target')); menuobj = ExternalMenus.getMenu(Request.get_param('target'));
...@@ -57,11 +92,27 @@ ...@@ -57,11 +92,27 @@
if (settings.xtrn_blacklist.indexOf(menuitem.target.toLowerCase()) > -1) { if (settings.xtrn_blacklist.indexOf(menuitem.target.toLowerCase()) > -1) {
return; return;
} }
switch (menuitem.type) {
case 'custommenu':
case 'xtrnmenu':
case 'xtrnprog':
case 'favorites':
case 'recentall':
case 'recentuser':
case 'mostlaunchedall':
case 'mostlauncheduser':
case 'longestrunuser':
case 'longestrunall':
menuitems.push({ menuitems.push({
'itemtitle': menuitem.title, 'itemtitle': menuitem.title,
'itemtype': menuitem.type, 'itemtype': menuitem.type,
'itemtarget': menuitem.target 'itemtarget': menuitem.target,
'stats': typeof menuitem.stats !== undefined ? menuitem.stats : null
}); });
break;
default:
break;
}
}); });
} }
?> ?>
...@@ -69,6 +120,7 @@ ...@@ -69,6 +120,7 @@
<script id="fTelnetScript" src="<?xjs write(get_url()); ?>"></script> <script id="fTelnetScript" src="<?xjs write(get_url()); ?>"></script>
<script type="text/javascript"> <script type="text/javascript">
window.addEventListener('load', (event) => {
var wsp = <?xjs write(settings.wsp || GetWebSocketServicePort()); ?>; var wsp = <?xjs write(settings.wsp || GetWebSocketServicePort()); ?>;
var wssp = <?xjs write(settings.wssp || GetWebSocketServicePort(true)); ?>; var wssp = <?xjs write(settings.wssp || GetWebSocketServicePort(true)); ?>;
var Options = new fTelnetOptions(); var Options = new fTelnetOptions();
...@@ -88,10 +140,11 @@ ...@@ -88,10 +140,11 @@
Options.ScreenRows = 25; Options.ScreenRows = 25;
Options.SplashScreen = Options.SplashScreen = '<?xjs write(get_splash()); ?>'; Options.SplashScreen = Options.SplashScreen = '<?xjs write(get_splash()); ?>';
Options.WebSocketUrlPath = '?Port=<?xjs write(GetRLoginPort()); ?>'; Options.WebSocketUrlPath = '?Port=<?xjs write(GetRLoginPort()); ?>';
var fTelnet = new fTelnetClient('fTelnetContainer', Options); window.fTelnet = new fTelnetClient('fTelnetContainer', Options);
fTelnet.OnConnectionClose = function () { fTelnet.OnConnectionClose = function () {
window.location.reload(); window.location.reload();
}; };
});
async function launchXtrn() { async function launchXtrn() {
var code = event.srcElement.id; var code = event.srcElement.id;
...@@ -109,12 +162,19 @@ ...@@ -109,12 +162,19 @@
sessionStorage.setItem("mainmenu", currentTitle); sessionStorage.setItem("mainmenu", currentTitle);
} }
var div = $('#xtrn-list'); var div = $('#xtrn-list');
menuitems.forEach(function (menuitem) { menuitems.forEach(function (menuitem) {
var a = document.createElement('a'); var a = document.createElement('a');
$(a).addClass("list-group-item"); $(a).addClass("list-group-item");
$(a).addClass("striped"); $(a).addClass("striped");
a.text = menuitem.itemtitle; a.text = menuitem.itemtitle;
if (typeof menuitem.stats !== "undefined") {
var badge = document.createElement('span');
$(badge).addClass('badge').text(menuitem.stats);
a.appendChild(badge);
}
if (menuitem.itemtype == "xtrnprog") { if (menuitem.itemtype == "xtrnprog") {
a.href = "#fTelnet"; a.href = "#fTelnet";
a.id = menuitem.itemtarget; a.id = menuitem.itemtarget;
......
<!--Game Stats-->
<div class="list-group">
<h1>Game Stats</h1>
<?xjs
load('sbbsdefs.js');
load("xtrnmenulib.js");
var ExternalMenus = new ExternalMenus();
if (typeof settings.xtrn_blacklist === 'string') {
settings.xtrn_blacklist = settings.xtrn_blacklist.toLowerCase().split(',');
} else {
settings.xtrn_blacklist = [];
}
// Edit these lines as needed to adjust the page
gameStats("recentall", "Most Recent", 10);
gameStats("mostlaunchedall", "Top 15 Most Launched", 15);
gameStats("longestrunall", "Top 15 Longest Run", 15);
function gameStats(menutype, title, maxitems) {
var menuobj = ExternalMenus.getSpecial(menutype, title);
?>
<div class="row list-group-item" style="background-color: #993399; color: #FFF">
<div class="col-sm-12"><h3><?xjs write(title) ?></h3></div>
</div>
<?xjs
if ((typeof menuobj.items !== "undefined") || (menuobj.items.length > 0)) {
var i = 0;
menuobj.items.some(function (menuitem) {
if (menuitem.type != "xtrnprog") {
return;
}
if (settings.xtrn_blacklist.indexOf(menuitem.target.toLowerCase()) > -1) return;
if (++i > maxitems) return;
?>
<div class="row list-group-item striped">
<div class="col-sm-2"><span class="badge badge-inverse"><?xjs write(menuitem.stats) ?></span></div>
<div class="col-sm-10"><?xjs write(menuitem.title) ?></div>
</div>
<?xjs
});
}
}
?>
</div>
<!--Games-->
<?xjs
/**
* Web Display for Custom External Program Menus
* by Michael Long mlong innerrealmbbs.us
*
* See wiki at http://wiki.synchro.net/module:xtrnmenu
*/
load("ftelnethelper.js");
load('sbbsdefs.js');
load("xtrnmenulib.js");
load(settings.web_lib + 'ftelnet.js');
load(settings.web_lib + 'request.js');
var ExternalMenus = new ExternalMenus();
if (typeof settings.xtrn_blacklist === 'string') {
settings.xtrn_blacklist = settings.xtrn_blacklist.toLowerCase().split(',');
} else {
settings.xtrn_blacklist = [];
}
var menuitems = [];
?>
<style>.fTelnetStatusBar { display : none; }</style>
<a name="fTelnet"></a>
<div id="fTelnetContainer" class="fTelnetContainer" style="margin-bottom:1em;"></div>
<div id="xtrn-list" class="list-group">
<?xjs
var menuobj;
if (Request.get_param('type')) {
var target = Request.get_param('target');
switch (Request.get_param('type')) {
case 'custommenu':
if (target !== undefined) {
menuobj = ExternalMenus.getMenu(target);
}
break;
case 'xtrnmenu':
if (target !== undefined) {
menuobj = ExternalMenus.getSectionMenu(target);
}
break;
case 'recentall':
menuobj = ExternalMenus.getSpecial(Request.get_param('type'), "Most Recent - All", target);
break;
case 'recentuser':
menuobj = ExternalMenus.getSpecial(Request.get_param('type'), "Most Recent - Yours", target);
break;
case 'mostlaunchedall':
menuobj = ExternalMenus.getSpecial(Request.get_param('type'), "Most Launched - All", target);
break;
case 'mostlauncheduser':
menuobj = ExternalMenus.getSpecial(Request.get_param('type'), "Most Launched - Yours", target);
break;
case 'longestrunall':
menuobj = ExternalMenus.getSpecial(Request.get_param('type'), "Longest Run - All", target);
break;
case 'longestrunuser':
menuobj = ExternalMenus.getSpecial(Request.get_param('type'), "Longest Run - Yours", target);
break;
case 'favorites':
menuobj = ExternalMenus.getFavorites("Favorites", target);
break;
default:
break;
}
} else {
if (Request.has_param('target')) {
menuobj = ExternalMenus.getMenu(Request.get_param('target'));
} else {
menuobj = ExternalMenus.getMenu('main');
}
}
if ((typeof menuobj === "undefined") || !menuobj
|| (typeof menuobj.items === "undefined") || (menuobj.items.length < 1)) {
writeln("<h4>" + ExternalMenus.options.no_programs_msg + "</h4>");
} else if (user.security.restrictions&UFLAG_X) {
writeln("<h4>" + options.restricted_user_msg + "</h4>");
} else {
// ok to display menu
writeln("<h4>" + menuobj.title + "</h4>");
var menuitemsfiltered = ExternalMenus.getSortedItems(menuobj);
menuitemsfiltered.forEach(function (menuitem) {
if (settings.xtrn_blacklist.indexOf(menuitem.target.toLowerCase()) > -1) {
return;
}
switch (menuitem.type) {
case 'custommenu':
case 'xtrnmenu':
case 'xtrnprog':
case 'favorites':
case 'recentall':
case 'recentuser':
case 'mostlaunchedall':
case 'mostlauncheduser':
case 'longestrunuser':
case 'longestrunall':
menuitems.push({
'itemtitle': menuitem.title,
'itemtype': menuitem.type,
'itemtarget': menuitem.target,
'stats': typeof menuitem.stats !== undefined ? menuitem.stats : null
});
break;
default:
break;
}
});
}
?>
</div>
<script id="fTelnetScript" src="<?xjs write(get_url()); ?>"></script>
<script type="text/javascript">
window.addEventListener('load', (event) => {
var wsp = <?xjs write(settings.wsp || GetWebSocketServicePort()); ?>;
var wssp = <?xjs write(settings.wssp || GetWebSocketServicePort(true)); ?>;
var Options = new fTelnetOptions();
Options.BareLFtoCRLF = false;
Options.BitsPerSecond = 57600;
Options.ConnectionType = 'rlogin';
Options.Emulation = 'ansi-bbs';
Options.Enter = '\r';
Options.Font = 'CP437';
Options.ForceWss = false;
Options.Hostname = '<?xjs write(http_request.vhost); ?>';
Options.LocalEcho = false;
Options.Port = location.protocol == 'https:' ? wssp : wsp;
Options.RLoginClientUsername = '<?xjs write(user.security.password); ?>';
Options.RLoginServerUsername = '<?xjs write(user.alias); ?>';
Options.ScreenColumns = 80;
Options.ScreenRows = 25;
Options.SplashScreen = Options.SplashScreen = '<?xjs write(get_splash()); ?>';
Options.WebSocketUrlPath = '?Port=<?xjs write(GetRLoginPort()); ?>';
window.fTelnet = new fTelnetClient('fTelnetContainer', Options);
fTelnet.OnConnectionClose = function () {
window.location.reload();
};
});
async function launchXtrn() {
var code = event.srcElement.id;
await v4_get('./api/system.ssjs?call=set-xtrn-intent&code=' + code);
fTelnet._Options.RLoginTerminalType = 'xtrn=' + code;
fTelnet.Connect();
}
var menuitems = <?xjs write(JSON.stringify(menuitems)); ?>;
var currentTarget = "<?xjs Request.write_param('target'); ?>";
var currentType = "<?xjs Request.write_param('type'); ?>";
var currentTitle = `<?xjs write(menuobj.title) ?>`;
if (currentTitle && !currentTarget) {
// main menu - store title for breadcrumb
sessionStorage.setItem("mainmenu", currentTitle);
}
var div = $('#xtrn-list');
menuitems.forEach(function (menuitem) {
var a = document.createElement('a');
$(a).addClass("list-group-item");
$(a).addClass("striped");
a.text = menuitem.itemtitle;
if (typeof menuitem.stats !== "undefined") {
var badge = document.createElement('span');
$(badge).addClass('badge').text(menuitem.stats);
a.appendChild(badge);
}
if (menuitem.itemtype == "xtrnprog") {
a.href = "#fTelnet";
a.id = menuitem.itemtarget;
a.onclick = function () { launchXtrn(); };
} else {
a.href = "/?page=<?xjs Request.write_param('page') ?>&type=" +menuitem.itemtype
+ "&target=" + menuitem.itemtarget;
a.onclick = function () {
sessionStorage.setItem('prev:' + menuitem.itemtarget.toLowerCase(), '<?xjs Request.write_param('target')?>');
sessionStorage.setItem('prevtype:' + menuitem.itemtarget.toLowerCase(), '<?xjs Request.write_param('type')?>');
sessionStorage.setItem('prevtitle:' + menuitem.itemtarget.toLowerCase(), currentTitle);
};
}
$(div).append(a);
});
// breadcrumb
var prevTarget = sessionStorage.getItem('prev:' + currentTarget.toLowerCase());
var prevType = sessionStorage.getItem('prevtype:' + currentTarget.toLowerCase());
var prevTitle = sessionStorage.getItem('prevtitle:' + currentTarget.toLowerCase());
if (prevType && prevTarget && prevTitle) {
$('#xtrn-list').prepend('<ol class="breadcrumb"><a href="/?page=<?xjs Request.write_param('page') ?>&type=' + prevType
+ '&target=' + prevTarget + '">' + prevTitle + '</a></ol>');
} else if (currentTarget) {
// level 2, not main menu
var mainmenuTitle = sessionStorage.getItem('mainmenu');
if (!mainmenuTitle) {
mainmenuTitle = 'Games';
}
$('#xtrn-list').prepend('<ol class="breadcrumb"><a href="/?page=<?xjs Request.write_param('page') ?>">' + mainmenuTitle + '</a></ol>');
}
</script>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment