Merge pull request #3630 from bobrippling/feat/settings-menu-return

settings: restore previous menu's scroll position
pull/3668/head
Rob Pilling 2024-11-20 18:42:20 +00:00 committed by GitHub
commit f1505b2023
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 138 additions and 91 deletions

View File

@ -82,4 +82,5 @@ of 'Select Clock'
0.71: Minor code improvements 0.71: Minor code improvements
0.72: Add setting for configuring BLE privacy 0.72: Add setting for configuring BLE privacy
0.73: Fix `const` bug / work with fastload 0.73: Fix `const` bug / work with fastload
0.74: Add extra layer of checks before allowing a factory reset (fix #3476) 0.74: Add extra layer of checks before allowing a factory reset (fix #3476)
0.75: Restore previous menu's scroll positions

View File

@ -67,3 +67,13 @@ The exact effects depend on the app. In general the watch will not wake up by i
* **Reset Settings** Reset the settings (as set in this app) to defaults. Does not reset settings for other apps. * **Reset Settings** Reset the settings (as set in this app) to defaults. Does not reset settings for other apps.
* **Factory Reset** (not available on Bangle.js 1) - wipe **everything** and return to a factory state * **Factory Reset** (not available on Bangle.js 1) - wipe **everything** and return to a factory state
* **Turn Off** Turn Bangle.js off * **Turn Off** Turn Bangle.js off
# Development
The settings code uses `push/pop/restoreMenu` to navigate different levels of menus. These functions are used as follows:
- `pushMenu`: enter a new level of menu, one deeper than the current (e.g. a submenu)
- `popMenu`: return to the previous menu level, one more shallow than the current (e.g. returning from a submenu)
- `restoreMenu`: redraw the current menu (e.g. after an alert)
These functions will keep track of outer menu's scroll positions, to avoid the user being returned to the very first entry as they navigate.

View File

@ -1,7 +1,7 @@
{ {
"id": "setting", "id": "setting",
"name": "Settings", "name": "Settings",
"version": "0.74", "version": "0.75",
"description": "A menu for setting up Bangle.js", "description": "A menu for setting up Bangle.js",
"icon": "settings.png", "icon": "settings.png",
"tags": "tool,system", "tags": "tool,system",

View File

@ -5,12 +5,41 @@ Bangle.drawWidgets();
const BANGLEJS2 = process.env.HWVERSION==2; const BANGLEJS2 = process.env.HWVERSION==2;
const storage = require('Storage'); const storage = require('Storage');
let settings; let settings;
const scrolls = [];
let menuScroller;
function updateSettings() { function updateSettings() {
//storage.erase('setting.json'); // - not needed, just causes extra writes if settings were the same //storage.erase('setting.json'); // - not needed, just causes extra writes if settings were the same
storage.write('setting.json', settings); storage.write('setting.json', settings);
} }
function pushMenu(menu) {
if(menuScroller) scrolls.push(menuScroller.scroll);
// if !menu, we're just pushing and something else takes
// care of E.showMenu()
if(menu) {
const m = E.showMenu(menu);
menuScroller = m.scroller;
return m;
}
}
function restoreMenu(menu) {
// equivalent to pushMenu(null); popMenu(menu);
if(!menu[""]) menu[""] = {};
menu[""].scroll = menuScroller.scroll;
menuScroller = E.showMenu(menu).scroller;
}
function popMenu(menu) {
if(!menu[""]) menu[""] = {};
menu[""].scroll = scrolls.pop() | 0;
const m = E.showMenu(menu);
menuScroller = m.scroller;
return m;
}
function updateOptions() { function updateOptions() {
var o = settings.options; var o = settings.options;
// Check to make sure nobody disabled all wakeups and locked themselves out! // Check to make sure nobody disabled all wakeups and locked themselves out!
@ -65,38 +94,38 @@ if (("object" != typeof settings) ||
("object" != typeof settings.options)) ("object" != typeof settings.options))
resetSettings(); resetSettings();
function showMainMenu() { function mainMenu() {
const mainmenu = { const mainmenu = {
'': { 'title': /*LANG*/'Settings' }, '': { 'title': /*LANG*/'Settings' },
'< Back': ()=>load(), '< Back': ()=>load(),
/*LANG*/'Apps': ()=>showAppSettingsMenu(), /*LANG*/'Apps': ()=>pushMenu(appSettingsMenu()),
/*LANG*/'System': ()=>showSystemMenu(), /*LANG*/'System': ()=>pushMenu(systemMenu()),
/*LANG*/'Bluetooth': ()=>showBLEMenu(), /*LANG*/'Bluetooth': ()=>pushMenu(BLEMenu()),
/*LANG*/'Alerts': ()=>showAlertsMenu(), /*LANG*/'Alerts': ()=>pushMenu(alertsMenu()),
/*LANG*/'Utils': ()=>showUtilMenu() /*LANG*/'Utils': ()=>pushMenu(utilMenu())
}; };
return E.showMenu(mainmenu); return mainmenu;
} }
function showSystemMenu() { function systemMenu() {
const mainmenu = { const mainmenu = {
'': { 'title': /*LANG*/'System' }, '': { 'title': /*LANG*/'System' },
'< Back': ()=>showMainMenu(), '< Back': ()=>popMenu(mainMenu()),
/*LANG*/'Theme': ()=>showThemeMenu(), /*LANG*/'Theme': ()=>showThemeMenu(),
/*LANG*/'LCD': ()=>showLCDMenu(), /*LANG*/'LCD': ()=>pushMenu(LCDMenu()),
/*LANG*/'Locale': ()=>showLocaleMenu(), /*LANG*/'Locale': ()=>pushMenu(localeMenu()),
/*LANG*/'Clock': ()=>showClockMenu(), /*LANG*/'Clock': ()=>pushMenu(clockMenu()),
/*LANG*/'Launcher': ()=>showLauncherMenu(), /*LANG*/'Launcher': ()=>pushMenu(launcherMenu()),
/*LANG*/'Date & Time': ()=>showSetTimeMenu() /*LANG*/'Date & Time': ()=>pushMenu(setTimeMenu())
}; };
return E.showMenu(mainmenu); return mainmenu;
} }
function showAlertsMenu() { function alertsMenu() {
var beepMenuItem; var beepMenuItem;
if (BANGLEJS2) { if (BANGLEJS2) {
beepMenuItem = { beepMenuItem = {
@ -128,7 +157,7 @@ function showAlertsMenu() {
const mainmenu = { const mainmenu = {
'': { 'title': /*LANG*/'Alerts' }, '': { 'title': /*LANG*/'Alerts' },
'< Back': ()=>showMainMenu(), '< Back': ()=>popMenu(mainMenu()),
/*LANG*/'Beep': beepMenuItem, /*LANG*/'Beep': beepMenuItem,
/*LANG*/'Vibration': { /*LANG*/'Vibration': {
value: settings.vibrate, value: settings.vibrate,
@ -153,18 +182,18 @@ function showAlertsMenu() {
} }
}; };
return E.showMenu(mainmenu); return mainmenu;
} }
function showBLEMenu() { function BLEMenu() {
var hidV = [false, "kbmedia", "kb", "com", "joy"]; var hidV = [false, "kbmedia", "kb", "com", "joy"];
var hidN = [/*LANG*/"Off", /*LANG*/"Kbrd & Media", /*LANG*/"Kbrd", /*LANG*/"Kbrd & Mouse", /*LANG*/"Joystick"]; var hidN = [/*LANG*/"Off", /*LANG*/"Kbrd & Media", /*LANG*/"Kbrd", /*LANG*/"Kbrd & Mouse", /*LANG*/"Joystick"];
var privacy = [/*LANG*/"Off", /*LANG*/"Show name", /*LANG*/"Hide name"]; var privacy = [/*LANG*/"Off", /*LANG*/"Show name", /*LANG*/"Hide name"];
E.showMenu({ return {
'': { 'title': /*LANG*/'Bluetooth' }, '': { 'title': /*LANG*/'Bluetooth' },
'< Back': ()=>showMainMenu(), '< Back': ()=>popMenu(mainMenu()),
/*LANG*/'Make Connectable': ()=>makeConnectable(), /*LANG*/'Make Connectable': ()=>makeConnectable(),
/*LANG*/'BLE': { /*LANG*/'BLE': {
value: settings.ble, value: settings.ble,
@ -217,7 +246,7 @@ function showBLEMenu() {
}, },
/*LANG*/'Passkey': { /*LANG*/'Passkey': {
value: settings.passkey?settings.passkey:/*LANG*/"none", value: settings.passkey?settings.passkey:/*LANG*/"none",
onchange: () => setTimeout(showPasskeyMenu) // graphical_menu redraws after the call onchange: () => setTimeout(() => pushMenu(passkeyMenu())) // graphical_menu redraws after the call
}, },
/*LANG*/'Whitelist': { /*LANG*/'Whitelist': {
value: value:
@ -228,12 +257,12 @@ function showBLEMenu() {
? " (" + settings.whitelist.length + ")" ? " (" + settings.whitelist.length + ")"
: "" : ""
), ),
onchange: () => setTimeout(showWhitelistMenu) // graphical_menu redraws after the call onchange: () => setTimeout(() => pushMenu(whitelistMenu())) // graphical_menu redraws after the call
} }
}); };
} }
function showThemeMenu() { function showThemeMenu(pop) {
function cl(x) { return g.setColor(x).getColor(); } function cl(x) { return g.setColor(x).getColor(); }
function upd(th) { function upd(th) {
g.theme = th; g.theme = th;
@ -250,7 +279,7 @@ function showThemeMenu() {
var themesMenu = { var themesMenu = {
'':{title:/*LANG*/'Theme'}, '':{title:/*LANG*/'Theme'},
'< Back': ()=>showSystemMenu(), '< Back': ()=>popMenu(systemMenu()),
/*LANG*/'Dark BW': ()=>{ /*LANG*/'Dark BW': ()=>{
upd({ upd({
fg:cl("#fff"), bg:cl("#000"), fg:cl("#fff"), bg:cl("#000"),
@ -274,18 +303,18 @@ function showThemeMenu() {
let newTheme = storage.readJSON(n); let newTheme = storage.readJSON(n);
themesMenu[newTheme.name ? newTheme.name : n] = () => { themesMenu[newTheme.name ? newTheme.name : n] = () => {
upd({ upd({
fg:cl(newTheme.fg), bg:cl(newTheme.bg), fg:cl(newTheme.fg), bg:cl(newTheme.bg),
fg2:cl(newTheme.fg2), bg2:cl(newTheme.bg2), fg2:cl(newTheme.fg2), bg2:cl(newTheme.bg2),
fgH:cl(newTheme.fgH), bgH:cl(newTheme.bgH), fgH:cl(newTheme.fgH), bgH:cl(newTheme.bgH),
dark:newTheme.dark dark:newTheme.dark
}); });
}; };
} }
); );
themesMenu[/*LANG*/'Customize'] = () => showCustomThemeMenu(); themesMenu[/*LANG*/'Customize'] = () => showCustomThemeMenu();
var m = E.showMenu(themesMenu); var m = (pop ? popMenu : pushMenu)(themesMenu);
function showCustomThemeMenu() { function showCustomThemeMenu() {
function setT(t, v) { function setT(t, v) {
@ -318,7 +347,7 @@ function showThemeMenu() {
} }
let menu = { let menu = {
'':{title:/*LANG*/'Custom Theme'}, '':{title:/*LANG*/'Custom Theme'},
"< Back": () => showThemeMenu() "< Back": () => showThemeMenu(1)
}; };
const labels = { const labels = {
fg: /*LANG*/'Foreground', bg: /*LANG*/'Background', fg: /*LANG*/'Foreground', bg: /*LANG*/'Background',
@ -341,18 +370,17 @@ function showThemeMenu() {
}, },
}; };
}); });
menu["< Back"] = () => showThemeMenu(); m = pushMenu(menu);
m = E.showMenu(menu);
} }
} }
function showPasskeyMenu() { function passkeyMenu() {
var menu = { var menu = {
"< Back" : ()=>showBLEMenu(), "< Back" : ()=>popMenu(BLEMenu()),
/*LANG*/"Disable" : () => { /*LANG*/"Disable" : () => {
settings.passkey = undefined; settings.passkey = undefined;
updateSettings(); updateSettings();
showBLEMenu(); popMenu(BLEMenu());
} }
}; };
if (!settings.passkey || settings.passkey.length!=6) { if (!settings.passkey || settings.passkey.length!=6) {
@ -371,24 +399,24 @@ function showPasskeyMenu() {
} }
}; };
})(i); })(i);
E.showMenu(menu); return menu;
} }
function showWhitelistMenu() { function whitelistMenu() {
var menu = { var menu = {
"< Back" : ()=>showBLEMenu(), "< Back" : ()=>popMenu(BLEMenu()),
}; };
if (settings.whitelist_disabled) { if (settings.whitelist_disabled) {
menu[/*LANG*/"Enable"] = () => { menu[/*LANG*/"Enable"] = () => {
delete settings.whitelist_disabled; delete settings.whitelist_disabled;
updateSettings(); updateSettings();
showBLEMenu(); popMenu(BLEMenu());
}; };
} else { } else {
menu[/*LANG*/"Disable"] = () => { menu[/*LANG*/"Disable"] = () => {
settings.whitelist_disabled = true; settings.whitelist_disabled = true;
updateSettings(); updateSettings();
showBLEMenu(); popMenu(BLEMenu());
}; };
} }
@ -399,14 +427,14 @@ function showWhitelistMenu() {
settings.whitelist.splice(settings.whitelist.indexOf(d),1); settings.whitelist.splice(settings.whitelist.indexOf(d),1);
updateSettings(); updateSettings();
} }
setTimeout(showWhitelistMenu, 50); setTimeout(() => restoreMenu(whitelistMenu()), 50);
}); });
} }
}); });
menu[/*LANG*/'Add Device']=function() { menu[/*LANG*/'Add Device']=function() {
E.showAlert(/*LANG*/"Connect device\nto add to\nwhitelist",/*LANG*/"Whitelist").then(function() { E.showAlert(/*LANG*/"Connect device\nto add to\nwhitelist",/*LANG*/"Whitelist").then(function() {
NRF.removeAllListeners('connect'); NRF.removeAllListeners('connect');
showWhitelistMenu(); restoreMenu(whitelistMenu());
}); });
NRF.removeAllListeners('connect'); NRF.removeAllListeners('connect');
NRF.on('connect', function(addr) { NRF.on('connect', function(addr) {
@ -421,13 +449,13 @@ function showWhitelistMenu() {
settings.whitelist.push(addr); settings.whitelist.push(addr);
updateSettings(); updateSettings();
NRF.removeAllListeners('connect'); NRF.removeAllListeners('connect');
showWhitelistMenu(); restoreMenu(whitelistMenu());
}); });
}; };
E.showMenu(menu); return menu;
} }
function showLCDMenu() { function LCDMenu() {
// converts g to Espruino internal unit // converts g to Espruino internal unit
function gToInternal(g) { return g * 8192; } function gToInternal(g) { return g * 8192; }
// converts Espruino internal unit to g // converts Espruino internal unit to g
@ -437,7 +465,7 @@ function showLCDMenu() {
const lcdMenu = { const lcdMenu = {
'': { 'title': 'LCD' }, '': { 'title': 'LCD' },
'< Back': ()=>showSystemMenu(), '< Back': ()=>popMenu(systemMenu()),
}; };
if (BANGLEJS2) if (BANGLEJS2)
Object.assign(lcdMenu, { Object.assign(lcdMenu, {
@ -584,13 +612,13 @@ function showLCDMenu() {
} }
}); });
return E.showMenu(lcdMenu) return lcdMenu
} }
function showLocaleMenu() { function localeMenu() {
const localemenu = { const localemenu = {
'': { 'title': /*LANG*/'Locale' }, '': { 'title': /*LANG*/'Locale' },
'< Back': ()=>showSystemMenu(), '< Back': ()=>popMenu(systemMenu()),
/*LANG*/'Time Zone': { /*LANG*/'Time Zone': {
value: settings.timezone, value: settings.timezone,
format: v => (v > 0 ? "+" : "") + v, format: v => (v > 0 ? "+" : "") + v,
@ -621,13 +649,13 @@ function showLocaleMenu() {
}, },
} }
}; };
return E.showMenu(localemenu); return localemenu;
} }
function showUtilMenu() { function utilMenu() {
var menu = { var menu = {
'': { 'title': /*LANG*/'Utilities' }, '': { 'title': /*LANG*/'Utilities' },
'< Back': ()=>showMainMenu(), '< Back': ()=>popMenu(mainMenu()),
/*LANG*/'Debug': { /*LANG*/'Debug': {
value: E.clip(0|settings.log,0,3), value: E.clip(0|settings.log,0,3),
min: 0, min: 0,
@ -641,7 +669,7 @@ function showUtilMenu() {
/*LANG*/'Compact Storage': () => { /*LANG*/'Compact Storage': () => {
E.showMessage(/*LANG*/"Compacting...\nTakes approx\n1 minute",{title:/*LANG*/"Storage"}); E.showMessage(/*LANG*/"Compacting...\nTakes approx\n1 minute",{title:/*LANG*/"Storage"});
storage.compact(); storage.compact();
showUtilMenu(); restoreMenu(utilMenu());
}, },
/*LANG*/'Rewrite Settings': () => { /*LANG*/'Rewrite Settings': () => {
storage.write(".boot0","eval(require('Storage').read('bootupdate.js'));"); storage.write(".boot0","eval(require('Storage').read('bootupdate.js'));");
@ -661,31 +689,35 @@ function showUtilMenu() {
}, 1); }, 1);
} }
}; };
const back = () => {
restoreMenu(utilMenu());
};
if (BANGLEJS2) if (BANGLEJS2)
menu[/*LANG*/'Calibrate Battery'] = () => { menu[/*LANG*/'Calibrate Battery'] = () => {
E.showPrompt(/*LANG*/"Is the battery fully charged?",{title:/*LANG*/"Calibrate",back:showUtilMenu}).then(ok => { E.showPrompt(/*LANG*/"Is the battery fully charged?",{title:/*LANG*/"Calibrate",back}).then(ok => {
if (ok) { if (ok) {
var s=storage.readJSON("setting.json"); var s=storage.readJSON("setting.json");
s.batFullVoltage = (analogRead(D3)+analogRead(D3)+analogRead(D3)+analogRead(D3))/4; s.batFullVoltage = (analogRead(D3)+analogRead(D3)+analogRead(D3)+analogRead(D3))/4;
storage.writeJSON("setting.json",s); storage.writeJSON("setting.json",s);
E.showAlert(/*LANG*/"Calibrated!").then(() => load("setting.app.js")); E.showAlert(/*LANG*/"Calibrated!").then(() => load("setting.app.js"));
} else { } else {
E.showAlert(/*LANG*/"Please charge Bangle.js for 3 hours and try again").then(() => load("setting.app.js")); E.showAlert(/*LANG*/"Please charge Bangle.js for 3 hours and try again").then(back);
} }
}); });
}; };
menu[/*LANG*/'Reset Settings'] = () => { menu[/*LANG*/'Reset Settings'] = () => {
E.showPrompt(/*LANG*/'Reset to Defaults?',{title:/*LANG*/"Settings",back:showUtilMenu}).then((v) => { E.showPrompt(/*LANG*/'Reset to Defaults?',{title:/*LANG*/"Settings",back}).then((v) => {
if (v) { if (v) {
E.showMessage(/*LANG*/'Resetting'); E.showMessage(/*LANG*/'Resetting');
resetSettings(); resetSettings();
setTimeout(showMainMenu, 50); setTimeout(() => popMenu(mainMenu()), 50);
} else showUtilMenu(); } else restoreMenu(utilMenu());
}); });
}; };
menu[/*LANG*/"Turn Off"] = () => { menu[/*LANG*/"Turn Off"] = () => {
E.showPrompt(/*LANG*/"Are you sure? Alarms and timers won't fire", { E.showPrompt(/*LANG*/"Are you sure? Alarms and timers won't fire", {
title:/*LANG*/"Turn Off",back:showUtilMenu title:/*LANG*/"Turn Off",back
}).then((confirmed) => { }).then((confirmed) => {
if (confirmed) { if (confirmed) {
E.showMessage(/*LANG*/"See you\nlater!", /*LANG*/"Goodbye"); E.showMessage(/*LANG*/"See you\nlater!", /*LANG*/"Goodbye");
@ -698,34 +730,34 @@ function showUtilMenu() {
Bangle.softOff ? Bangle.softOff() : Bangle.off(); Bangle.softOff ? Bangle.softOff() : Bangle.off();
}, 2500); }, 2500);
} else { } else {
showUtilMenu(); restoreMenu(utilMenu());
} }
}); });
}; };
if (Bangle.factoryReset) { if (Bangle.factoryReset) {
menu[/*LANG*/'Factory Reset'] = ()=>{ menu[/*LANG*/'Factory Reset'] = ()=>{
E.showPrompt(/*LANG*/'This will remove everything!',{title:/*LANG*/"Factory Reset",back:showUtilMenu}).then((v) => { E.showPrompt(/*LANG*/'This will remove everything!',{title:/*LANG*/"Factory Reset",back}).then((v) => {
if (v) { if (v) {
var n = ((Math.random()*4)&3) + 1; var n = ((Math.random()*4)&3) + 1;
E.showPrompt(/*LANG*/"To confirm, please press "+n,{ E.showPrompt(/*LANG*/"To confirm, please press "+n,{
title:/*LANG*/"Factory Reset", title:/*LANG*/"Factory Reset",
buttons : {"1":1,"2":2,"3":3,"4":4}, buttons : {"1":1,"2":2,"3":3,"4":4},
back:showUtilMenu back
}).then(function(v) { }).then(function(v) {
if (v==n) { if (v==n) {
E.showMessage(); E.showMessage();
Terminal.setConsole(); Terminal.setConsole();
Bangle.factoryReset(); Bangle.factoryReset();
} else { } else {
showUtilMenu(); back();
} }
}); });
} else showUtilMenu(); } else back();
}); });
} }
} }
return E.showMenu(menu); return menu;
} }
function makeConnectable() { function makeConnectable() {
@ -740,19 +772,20 @@ function makeConnectable() {
} }
if (!r) try { NRF.sleep(); } catch (e) { } if (!r) try { NRF.sleep(); } catch (e) { }
delete NRF.ignoreWhitelist; delete NRF.ignoreWhitelist;
showMainMenu(); restoreMenu(BLEMenu());
}); });
} }
function showClockMenu() { function clockMenu() {
var clockApps = storage.list(/\.info$/) var clockApps = storage.list(/\.info$/)
.map(app => {var a=storage.readJSON(app, 1);return (a&&a.type == "clock")?a:undefined}) .map(app => {var a=storage.readJSON(app, 1);return (a&&a.type == "clock")?a:undefined})
.filter(app => app) // filter out any undefined apps .filter(app => app) // filter out any undefined apps
.sort((a, b) => a.sortorder - b.sortorder); .sort((a, b) => a.sortorder - b.sortorder);
const back = ()=>popMenu(systemMenu());
const clockMenu = { const clockMenu = {
'': { '': {
'title': /*LANG*/'Select Clock', 'title': /*LANG*/'Select Clock',
}, },
'< Back': ()=>showSystemMenu(), '< Back': back,
}; };
clockApps.forEach((app, index) => { clockApps.forEach((app, index) => {
var label = app.name; var label = app.name;
@ -763,24 +796,25 @@ function showClockMenu() {
settings.clock = app.src; settings.clock = app.src;
settings.clockHasWidgets = storage.read(app.src).includes("Bangle.loadWidgets"); settings.clockHasWidgets = storage.read(app.src).includes("Bangle.loadWidgets");
updateSettings(); updateSettings();
showMainMenu(); back();
}; };
}); });
if (clockApps.length === 0) { if (clockApps.length === 0) {
clockMenu[/*LANG*/"No Clocks Found"] = () => { }; clockMenu[/*LANG*/"No Clocks Found"] = () => { };
} }
return E.showMenu(clockMenu); return clockMenu;
} }
function showLauncherMenu() { function launcherMenu() {
var launcherApps = storage.list(/\.info$/) var launcherApps = storage.list(/\.info$/)
.map(app => {var a=storage.readJSON(app, 1);return (a&&a.type == "launch")?a:undefined}) .map(app => {var a=storage.readJSON(app, 1);return (a&&a.type == "launch")?a:undefined})
.filter(app => app) // filter out any undefined apps .filter(app => app) // filter out any undefined apps
.sort((a, b) => a.sortorder - b.sortorder); .sort((a, b) => a.sortorder - b.sortorder);
const back = ()=>popMenu(systemMenu());
const launcherMenu = { const launcherMenu = {
'': { '': {
'title': /*LANG*/'Select Launcher', 'title': /*LANG*/'Select Launcher',
}, },
'< Back': ()=>showSystemMenu(), '< Back': back,
}; };
launcherApps.forEach((app, index) => { launcherApps.forEach((app, index) => {
var label = app.name; var label = app.name;
@ -790,22 +824,22 @@ function showLauncherMenu() {
launcherMenu[label] = () => { launcherMenu[label] = () => {
settings.launcher = app.src; settings.launcher = app.src;
updateSettings(); updateSettings();
showMainMenu(); back();
}; };
}); });
if (launcherApps.length === 0) { if (launcherApps.length === 0) {
launcherMenu[/*LANG*/"No Launchers Found"] = () => { }; launcherMenu[/*LANG*/"No Launchers Found"] = () => { };
} }
return E.showMenu(launcherMenu); return launcherMenu;
} }
function showSetTimeMenu() { function setTimeMenu() {
let d = new Date(); let d = new Date();
const timemenu = { const timemenu = {
'': { 'title': /*LANG*/'Date & Time' }, '': { 'title': /*LANG*/'Date & Time' },
'< Back': function () { '< Back': function () {
setTime(d.getTime() / 1000); setTime(d.getTime() / 1000);
showSystemMenu(); popMenu(systemMenu());
}, },
/*LANG*/'Day': { /*LANG*/'Day': {
value: d.getDate(), value: d.getDate(),
@ -852,13 +886,13 @@ function showSetTimeMenu() {
} }
} }
}; };
return E.showMenu(timemenu); return timemenu;
} }
function showAppSettingsMenu() { function appSettingsMenu() {
let appmenu = { let appmenu = {
'': { 'title': /*LANG*/'App Settings' }, '': { 'title': /*LANG*/'App Settings' },
'< Back': ()=>showMainMenu(), '< Back': ()=>popMenu(mainMenu()),
} }
const apps = storage.list(/\.settings\.js$/) const apps = storage.list(/\.settings\.js$/)
.map(s => s.substr(0, s.length-12)) .map(s => s.substr(0, s.length-12))
@ -879,12 +913,13 @@ function showAppSettingsMenu() {
apps.forEach(function (app) { apps.forEach(function (app) {
appmenu[app.name] = () => { showAppSettings(app) }; appmenu[app.name] = () => { showAppSettings(app) };
}) })
E.showMenu(appmenu) return appmenu;
} }
function showAppSettings(app) { function showAppSettings(app) {
const back = () => popMenu(appSettingsMenu());
const showError = msg => { const showError = msg => {
E.showMessage(`${app.name}:\n${msg}!\n\nBTN1 to go back`); E.showMessage(`${app.name}:\n${msg}!\n\nBTN1 to go back`);
setWatch(showAppSettingsMenu, BTN1, { repeat: false }); setWatch(back, BTN1, { repeat: false });
} }
let appSettings = storage.read(app.id+'.settings.js'); let appSettings = storage.read(app.id+'.settings.js');
try { try {
@ -897,8 +932,9 @@ function showAppSettings(app) {
return showError(/*LANG*/'Invalid settings'); return showError(/*LANG*/'Invalid settings');
} }
try { try {
// pass showAppSettingsMenu as "back" argument // pass appSettingsMenu as "back" argument
appSettings(()=>showAppSettingsMenu()); pushMenu();
appSettings(back);
} catch (e) { } catch (e) {
console.log(`${app.name} settings error:`, e); console.log(`${app.name} settings error:`, e);
return showError(/*LANG*/'Error in settings'); return showError(/*LANG*/'Error in settings');
@ -961,8 +997,8 @@ function showTouchscreenCalibration() {
storage.writeJSON("setting.json",s); storage.writeJSON("setting.json",s);
g.setFont("6x8:2").setFontAlign(0,0).drawString(/*LANG*/"Calibrated!", g.getWidth()/2, g.getHeight()/2); g.setFont("6x8:2").setFontAlign(0,0).drawString(/*LANG*/"Calibrated!", g.getWidth()/2, g.getHeight()/2);
} }
// now load the main menu again // now load the menu again
setTimeout(showLCDMenu, 500); setTimeout(() => restoreMenu(LCDMenu()), 500);
} }
function touchHandler(_,e) { function touchHandler(_,e) {
@ -994,5 +1030,5 @@ function showTouchscreenCalibration() {
showTapSpot(); showTapSpot();
} }
showMainMenu(); pushMenu(mainMenu());
} }