mirror of https://github.com/espruino/BangleApps
Refactor entire app so that it can have a settings.js
parent
e542bed0a0
commit
27af11a9ca
|
@ -0,0 +1 @@
|
|||
0.01: Initial version
|
|
@ -1,10 +1,9 @@
|
|||
Layout = require('Layout');
|
||||
locale = require('locale');
|
||||
storage = require('Storage');
|
||||
const Layout = require('Layout');
|
||||
const locale = require('locale');
|
||||
const storage = require('Storage');
|
||||
|
||||
const tsl = require('timestamplog');
|
||||
|
||||
// Storage filenames
|
||||
const LOG_FILENAME = 'timestamplog.json';
|
||||
const SETTINGS_FILENAME = 'timestamplog.settings.json';
|
||||
|
||||
// Min number of pixels of movement to recognize a touchscreen drag/swipe
|
||||
const DRAG_THRESHOLD = 30;
|
||||
|
@ -13,35 +12,6 @@ const DRAG_THRESHOLD = 30;
|
|||
const SCROLL_BAR_WIDTH = 12;
|
||||
|
||||
|
||||
// Settings
|
||||
|
||||
const SETTINGS = Object.assign({
|
||||
logFont: '12x20',
|
||||
logFontHSize: 1,
|
||||
logFontVSize: 1,
|
||||
maxLogLength: 30,
|
||||
rotateLog: false,
|
||||
buttonAction: 'Log time',
|
||||
}, storage.readJSON(SETTINGS_FILENAME, true) || {});
|
||||
|
||||
const SETTINGS_BUTTON_ACTION = [
|
||||
'Log time',
|
||||
'Show menu',
|
||||
'Quit app',
|
||||
'Do nothing',
|
||||
];
|
||||
|
||||
function saveSettings() {
|
||||
if (!storage.writeJSON(SETTINGS_FILENAME, SETTINGS)) {
|
||||
E.showAlert('Trouble saving settings');
|
||||
}
|
||||
}
|
||||
|
||||
function fontSpec(name, hsize, vsize) {
|
||||
return name + ':' + hsize + 'x' + vsize;
|
||||
}
|
||||
|
||||
|
||||
// Fetch a stringified image
|
||||
function getIcon(id) {
|
||||
if (id == 'add') {
|
||||
|
@ -88,120 +58,13 @@ function getIcon(id) {
|
|||
}
|
||||
|
||||
|
||||
//// Data models //////////////////////////////////
|
||||
|
||||
// High-level timestamp log object that provides an interface to the
|
||||
// UI for managing log entries and automatically loading/saving
|
||||
// changes to flash storage.
|
||||
class StampLog {
|
||||
constructor(filename, maxLength) {
|
||||
// Name of file to save log to
|
||||
this.filename = filename;
|
||||
// Maximum entries for log before old entries are overwritten with
|
||||
// newer ones
|
||||
this.maxLength = maxLength;
|
||||
|
||||
// `true` when we have changes that need to be saved
|
||||
this.isDirty = false;
|
||||
// Wait at most this many msec upon first data change before
|
||||
// saving (this is to avoid excessive writes to flash if several
|
||||
// changes happen quickly; we wait a little bit so they can be
|
||||
// rolled into a single write)
|
||||
this.saveTimeout = 30000;
|
||||
// setTimeout ID for scheduled save job
|
||||
this.saveId = null;
|
||||
// Underlying raw log data object. Outside this class it's
|
||||
// recommended to use only the class methods to change it rather
|
||||
// than modifying the object directly to ensure that changes are
|
||||
// recognized and saved to storage.
|
||||
this.log = this.load();
|
||||
}
|
||||
|
||||
// Return the version of the log data that is currently in storage
|
||||
load() {
|
||||
let log = storage.readJSON(this.filename, true);
|
||||
if (!log) log = [];
|
||||
// Convert stringified datetimes back into Date objects
|
||||
for (let logEntry of log) {
|
||||
logEntry.stamp = new Date(logEntry.stamp);
|
||||
}
|
||||
return log;
|
||||
}
|
||||
|
||||
// Write current log data to storage if anything needs to be saved
|
||||
save() {
|
||||
// Cancel any pending scheduled calls to save()
|
||||
if (this.saveId) {
|
||||
clearTimeout(this.saveId);
|
||||
this.saveId = null;
|
||||
}
|
||||
|
||||
if (this.isDirty) {
|
||||
let logToSave = [];
|
||||
for (let logEntry of this.log) {
|
||||
// Serialize each Date object into an ISO string before saving
|
||||
let newEntry = Object.assign({}, logEntry);
|
||||
newEntry.stamp = logEntry.stamp.toISOString();
|
||||
logToSave.push(newEntry);
|
||||
}
|
||||
|
||||
if (storage.writeJSON(this.filename, logToSave)) {
|
||||
console.log('stamplog: save to storage completed');
|
||||
this.isDirty = false;
|
||||
} else {
|
||||
console.log('stamplog: save to storage FAILED');
|
||||
this.emit('saveError');
|
||||
}
|
||||
} else {
|
||||
console.log('stamplog: skipping save to storage because no changes made');
|
||||
}
|
||||
}
|
||||
|
||||
// Mark log as needing to be (re)written to storage
|
||||
setDirty() {
|
||||
this.isDirty = true;
|
||||
if (!this.saveId) {
|
||||
this.saveId = setTimeout(this.save.bind(this), this.saveTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
// Add a timestamp for the current time to the end of the log
|
||||
addEntry() {
|
||||
// If log full, purge an old entry to make room for new one
|
||||
if (this.maxLength) {
|
||||
while (this.log.length + 1 > this.maxLength) {
|
||||
this.log.shift();
|
||||
}
|
||||
}
|
||||
// Add new entry
|
||||
this.log.push({
|
||||
stamp: new Date()
|
||||
});
|
||||
this.setDirty();
|
||||
}
|
||||
|
||||
// Delete the log objects given in the array `entries` from the log
|
||||
deleteEntries(entries) {
|
||||
this.log = this.log.filter(entry => !entries.includes(entry));
|
||||
this.setDirty();
|
||||
}
|
||||
|
||||
// Does the log currently contain the maximum possible number of entries?
|
||||
isFull() {
|
||||
return this.log.length >= this.maxLength;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// UI ///////////////////////////////////////////
|
||||
|
||||
// UI layout render callback for log entries
|
||||
function renderLogItem(elem) {
|
||||
if (elem.item) {
|
||||
g.setColor(g.theme.bg)
|
||||
.fillRect(elem.x, elem.y, elem.x + elem.w - 1, elem.y + elem.h - 1)
|
||||
.setFont(fontSpec(SETTINGS.logFont,
|
||||
SETTINGS.logFontHSize, SETTINGS.logFontVSize))
|
||||
.setFont(tsl.fontSpec(tsl.SETTINGS.logFont,
|
||||
tsl.SETTINGS.logFontHSize, tsl.SETTINGS.logFontVSize))
|
||||
.setFontAlign(-1, -1)
|
||||
.setColor(g.theme.fg)
|
||||
.drawLine(elem.x, elem.y, elem.x + elem.w - 1, elem.y)
|
||||
|
@ -254,9 +117,7 @@ function renderScrollBar(elem, scroll) {
|
|||
// Main app screen interface, launched by calling start()
|
||||
class MainScreen {
|
||||
|
||||
constructor(stampLog) {
|
||||
this.stampLog = stampLog;
|
||||
|
||||
constructor() {
|
||||
// Values set up by start()
|
||||
this.itemsPerPage = null;
|
||||
this.scrollPos = null;
|
||||
|
@ -320,7 +181,7 @@ class MainScreen {
|
|||
{type: 'btn', font: '6x8:2', fillx: 1, label: '+ XX:XX', id: 'addBtn',
|
||||
cb: this.addTimestamp.bind(this)},
|
||||
{type: 'btn', font: '6x8:2', label: getIcon('menu'), id: 'menuBtn',
|
||||
cb: launchSettingsMenu},
|
||||
cb: () => launchSettingsMenu(returnFromSettings)},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
@ -330,8 +191,8 @@ class MainScreen {
|
|||
// Calculate how many log items per page we have space to display
|
||||
layout.update();
|
||||
let availableHeight = layout.placeholder.h;
|
||||
g.setFont(fontSpec(SETTINGS.logFont,
|
||||
SETTINGS.logFontHSize, SETTINGS.logFontVSize));
|
||||
g.setFont(tsl.fontSpec(tsl.SETTINGS.logFont,
|
||||
tsl.SETTINGS.logFontHSize, tsl.SETTINGS.logFontVSize));
|
||||
let logItemHeight = g.getFontHeight() * 2;
|
||||
this.itemsPerPage = Math.max(1,
|
||||
Math.floor(availableHeight / logItemHeight));
|
||||
|
@ -357,7 +218,7 @@ class MainScreen {
|
|||
let logIdx = this.scrollPos - this.itemsPerPage;
|
||||
for (let elem of layLogItems.c) {
|
||||
logIdx++;
|
||||
elem.item = this.stampLog.log[logIdx];
|
||||
elem.item = stampLog.log[logIdx];
|
||||
elem.itemIdx = logIdx;
|
||||
}
|
||||
this.layout.render(layLogItems);
|
||||
|
@ -367,7 +228,7 @@ class MainScreen {
|
|||
if (!item || item == 'buttons') {
|
||||
let addBtn = this.layout.addBtn;
|
||||
|
||||
if (!SETTINGS.rotateLog && this.stampLog.isFull()) {
|
||||
if (!tsl.SETTINGS.rotateLog && stampLog.isFull()) {
|
||||
// Dimmed appearance for unselectable button
|
||||
addBtn.btnFaceCol = g.blendColor(g.theme.bg2, g.theme.bg, 0.5);
|
||||
addBtn.btnBorderCol = g.blendColor(g.theme.fg2, g.theme.bg, 0.5);
|
||||
|
@ -433,7 +294,7 @@ class MainScreen {
|
|||
logUIObj.x <= xy.x && xy.x < logUIObj.x + logUIObj.w &&
|
||||
logUIObj.y <= xy.y && xy.y < logUIObj.y + logUIObj.h &&
|
||||
logUIObj.item) {
|
||||
switchUI(new LogEntryScreen(this.stampLog, logUIObj.itemIdx));
|
||||
switchUI(new LogEntryScreen(stampLog, logUIObj.itemIdx));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -443,14 +304,14 @@ class MainScreen {
|
|||
Bangle.on('touch', this.listeners.touch);
|
||||
|
||||
function buttonHandler() {
|
||||
let act = SETTINGS.buttonAction;
|
||||
let act = tsl.SETTINGS.buttonAction;
|
||||
if (act == 'Log time') {
|
||||
if (currentUI != mainUI) {
|
||||
switchUI(mainUI);
|
||||
}
|
||||
mainUI.addTimestamp();
|
||||
} else if (act == 'Show menu') {
|
||||
launchSettingsMenu();
|
||||
} else if (act == 'Open settings') {
|
||||
launchSettingsMenu(returnFromSettings);
|
||||
} else if (act == 'Quit app') {
|
||||
Bangle.showClock();
|
||||
}
|
||||
|
@ -462,8 +323,8 @@ class MainScreen {
|
|||
|
||||
// Add current timestamp to log if possible and update UI display
|
||||
addTimestamp() {
|
||||
if (SETTINGS.rotateLog || !this.stampLog.isFull()) {
|
||||
this.stampLog.addEntry();
|
||||
if (tsl.SETTINGS.rotateLog || !stampLog.isFull()) {
|
||||
stampLog.addEntry();
|
||||
this.scroll('b');
|
||||
this.render('buttons');
|
||||
}
|
||||
|
@ -473,8 +334,8 @@ class MainScreen {
|
|||
scrollInfo() {
|
||||
return {
|
||||
pos: this.scrollPos,
|
||||
min: (this.stampLog.log.length - 1) % this.itemsPerPage,
|
||||
max: this.stampLog.log.length - 1,
|
||||
min: (stampLog.log.length - 1) % this.itemsPerPage,
|
||||
max: stampLog.log.length - 1,
|
||||
itemsPerPage: this.itemsPerPage
|
||||
};
|
||||
}
|
||||
|
@ -524,12 +385,12 @@ class MainScreen {
|
|||
class LogEntryScreen {
|
||||
|
||||
constructor(stampLog, logIdx) {
|
||||
this.stampLog = stampLog;
|
||||
stampLog = stampLog;
|
||||
this.logIdx = logIdx;
|
||||
this.logItem = stampLog.log[logIdx];
|
||||
|
||||
this.defaultFont = fontSpec(
|
||||
SETTINGS.logFont, SETTINGS.logFontHSize, SETTINGS.logFontVSize);
|
||||
this.defaultFont = tsl.fontSpec(
|
||||
tsl.SETTINGS.logFont, tsl.SETTINGS.logFontHSize, tsl.SETTINGS.logFontVSize);
|
||||
}
|
||||
|
||||
start() {
|
||||
|
@ -577,7 +438,7 @@ class LogEntryScreen {
|
|||
}
|
||||
|
||||
refresh() {
|
||||
this.logItem = this.stampLog.log[this.logIdx];
|
||||
this.logItem = stampLog.log[this.logIdx];
|
||||
this.layout.date.label = locale.date(this.logItem.stamp, 1);
|
||||
this.layout.time.label = locale.time(this.logItem.stamp).trim();
|
||||
this.layout.update();
|
||||
|
@ -585,22 +446,22 @@ class LogEntryScreen {
|
|||
}
|
||||
|
||||
prevLogItem() {
|
||||
this.logIdx = this.logIdx ? this.logIdx-1 : this.stampLog.log.length-1;
|
||||
this.logIdx = this.logIdx ? this.logIdx-1 : stampLog.log.length-1;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
nextLogItem() {
|
||||
this.logIdx = this.logIdx == this.stampLog.log.length-1 ? 0 : this.logIdx+1;
|
||||
this.logIdx = this.logIdx == stampLog.log.length-1 ? 0 : this.logIdx+1;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
delLogItem() {
|
||||
this.stampLog.deleteEntries([this.logItem]);
|
||||
if (!this.stampLog.log.length) {
|
||||
stampLog.deleteEntries([this.logItem]);
|
||||
if (!stampLog.log.length) {
|
||||
this.back();
|
||||
return;
|
||||
} else if (this.logIdx > this.stampLog.log.length - 1) {
|
||||
this.logIdx = this.stampLog.log.length - 1;
|
||||
} else if (this.logIdx > stampLog.log.length - 1) {
|
||||
this.logIdx = stampLog.log.length - 1;
|
||||
}
|
||||
|
||||
// Create a brief “blink” on the screen to provide user feedback
|
||||
|
@ -612,104 +473,10 @@ class LogEntryScreen {
|
|||
}
|
||||
|
||||
|
||||
function launchSettingsMenu() {
|
||||
const fonts = g.getFonts();
|
||||
|
||||
function topMenu() {
|
||||
E.showMenu({
|
||||
'': {
|
||||
title: 'Stamplog',
|
||||
back: endMenu,
|
||||
},
|
||||
'Log': logMenu,
|
||||
'Appearance': appearanceMenu,
|
||||
'Button': {
|
||||
value: SETTINGS_BUTTON_ACTION.indexOf(SETTINGS.buttonAction),
|
||||
min: 0, max: SETTINGS_BUTTON_ACTION.length - 1,
|
||||
format: v => SETTINGS_BUTTON_ACTION[v],
|
||||
onchange: v => {
|
||||
SETTINGS.buttonAction = SETTINGS_BUTTON_ACTION[v];
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function logMenu() {
|
||||
E.showMenu({
|
||||
'': {
|
||||
title: 'Log',
|
||||
back: topMenu,
|
||||
},
|
||||
'Max entries': {
|
||||
value: SETTINGS.maxLogLength,
|
||||
min: 5, max: 100, step: 5,
|
||||
onchange: v => {
|
||||
SETTINGS.maxLogLength = v;
|
||||
stampLog.maxLength = v;
|
||||
}
|
||||
},
|
||||
'Auto-delete oldest': {
|
||||
value: SETTINGS.rotateLog,
|
||||
onchange: v => {
|
||||
SETTINGS.rotateLog = !SETTINGS.rotateLog;
|
||||
}
|
||||
},
|
||||
'Clear log': clearLogPrompt,
|
||||
});
|
||||
}
|
||||
|
||||
function appearanceMenu() {
|
||||
E.showMenu({
|
||||
'': {
|
||||
title: 'Appearance',
|
||||
back: topMenu,
|
||||
},
|
||||
'Log font': {
|
||||
value: fonts.indexOf(SETTINGS.logFont),
|
||||
min: 0, max: fonts.length - 1,
|
||||
format: v => fonts[v],
|
||||
onchange: v => {
|
||||
SETTINGS.logFont = fonts[v];
|
||||
},
|
||||
},
|
||||
'Log font H size': {
|
||||
value: SETTINGS.logFontHSize,
|
||||
min: 1, max: 50,
|
||||
onchange: v => {
|
||||
SETTINGS.logFontHSize = v;
|
||||
},
|
||||
},
|
||||
'Log font V size': {
|
||||
value: SETTINGS.logFontVSize,
|
||||
min: 1, max: 50,
|
||||
onchange: v => {
|
||||
SETTINGS.logFontVSize = v;
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function endMenu() {
|
||||
saveSettings();
|
||||
currentUI.start();
|
||||
}
|
||||
|
||||
function clearLogPrompt() {
|
||||
E.showPrompt('Erase ALL log entries?', {
|
||||
title: 'Clear log',
|
||||
buttons: {'Erase':1, "Don't":0}
|
||||
}).then((yes) => {
|
||||
if (yes) {
|
||||
stampLog.deleteEntries(stampLog.log)
|
||||
endMenu();
|
||||
} else {
|
||||
logMenu();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function switchUI(newUI) {
|
||||
currentUI.stop();
|
||||
topMenu();
|
||||
currentUI = newUI;
|
||||
currentUI.start();
|
||||
}
|
||||
|
||||
|
||||
|
@ -725,17 +492,29 @@ function saveErrorAlert() {
|
|||
}
|
||||
|
||||
|
||||
function switchUI(newUI) {
|
||||
function launchSettingsMenu(backCb) {
|
||||
currentUI.stop();
|
||||
currentUI = newUI;
|
||||
stampLog.save();
|
||||
tsl.launchSettingsMenu(backCb);
|
||||
}
|
||||
|
||||
function returnFromSettings() {
|
||||
// Reload stampLog to pick up any changes made from settings UI
|
||||
stampLog = loadStampLog();
|
||||
currentUI.start();
|
||||
}
|
||||
|
||||
|
||||
function loadStampLog() {
|
||||
// Create a StampLog object with its data loaded from storage
|
||||
return new tsl.StampLog(tsl.LOG_FILENAME, tsl.SETTINGS.maxLogLength);
|
||||
}
|
||||
|
||||
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
|
||||
stampLog = new StampLog(LOG_FILENAME, SETTINGS.maxLogLength);
|
||||
var stampLog = loadStampLog();
|
||||
E.on('kill', stampLog.save.bind(stampLog));
|
||||
stampLog.on('saveError', saveErrorAlert);
|
||||
|
||||
|
|
|
@ -0,0 +1,245 @@
|
|||
const storage = require('Storage');
|
||||
|
||||
// Storage filenames
|
||||
|
||||
const LOG_FILENAME = 'timestamplog.json';
|
||||
const SETTINGS_FILENAME = 'timestamplog.settings.json';
|
||||
|
||||
|
||||
// Settings
|
||||
|
||||
const SETTINGS = Object.assign({
|
||||
logFont: '12x20',
|
||||
logFontHSize: 1,
|
||||
logFontVSize: 1,
|
||||
maxLogLength: 30,
|
||||
rotateLog: false,
|
||||
buttonAction: 'Log time',
|
||||
}, storage.readJSON(SETTINGS_FILENAME, true) || {});
|
||||
|
||||
const SETTINGS_BUTTON_ACTION = [
|
||||
'Log time',
|
||||
'Open settings',
|
||||
'Quit app',
|
||||
'Do nothing',
|
||||
];
|
||||
|
||||
|
||||
function fontSpec(name, hsize, vsize) {
|
||||
return name + ':' + hsize + 'x' + vsize;
|
||||
}
|
||||
|
||||
|
||||
//// Data models ////
|
||||
|
||||
// High-level timestamp log object that provides an interface to the
|
||||
// UI for managing log entries and automatically loading/saving
|
||||
// changes to flash storage.
|
||||
class StampLog {
|
||||
constructor(filename, maxLength) {
|
||||
// Name of file to save log to
|
||||
this.filename = filename;
|
||||
// Maximum entries for log before old entries are overwritten with
|
||||
// newer ones
|
||||
this.maxLength = maxLength;
|
||||
|
||||
// `true` when we have changes that need to be saved
|
||||
this.isDirty = false;
|
||||
// Wait at most this many msec upon first data change before
|
||||
// saving (this is to avoid excessive writes to flash if several
|
||||
// changes happen quickly; we wait a little bit so they can be
|
||||
// rolled into a single write)
|
||||
this.saveTimeout = 30000;
|
||||
// setTimeout ID for scheduled save job
|
||||
this.saveId = null;
|
||||
// Underlying raw log data object. Outside this class it's
|
||||
// recommended to use only the class methods to change it rather
|
||||
// than modifying the object directly to ensure that changes are
|
||||
// recognized and saved to storage.
|
||||
this.log = [];
|
||||
|
||||
this.load();
|
||||
}
|
||||
|
||||
// Read in the log data that is currently in storage
|
||||
load() {
|
||||
let log = storage.readJSON(this.filename, true);
|
||||
if (!log) log = [];
|
||||
// Convert stringified datetimes back into Date objects
|
||||
for (let logEntry of log) {
|
||||
logEntry.stamp = new Date(logEntry.stamp);
|
||||
}
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
// Write current log data to storage if anything needs to be saved
|
||||
save() {
|
||||
// Cancel any pending scheduled calls to save()
|
||||
if (this.saveId) {
|
||||
clearTimeout(this.saveId);
|
||||
this.saveId = null;
|
||||
}
|
||||
|
||||
if (this.isDirty) {
|
||||
let logToSave = [];
|
||||
for (let logEntry of this.log) {
|
||||
// Serialize each Date object into an ISO string before saving
|
||||
let newEntry = Object.assign({}, logEntry);
|
||||
newEntry.stamp = logEntry.stamp.toISOString();
|
||||
logToSave.push(newEntry);
|
||||
}
|
||||
|
||||
if (storage.writeJSON(this.filename, logToSave)) {
|
||||
console.log('stamplog: save to storage completed');
|
||||
this.isDirty = false;
|
||||
} else {
|
||||
console.log('stamplog: save to storage FAILED');
|
||||
this.emit('saveError');
|
||||
}
|
||||
} else {
|
||||
console.log('stamplog: skipping save to storage because no changes made');
|
||||
}
|
||||
}
|
||||
|
||||
// Mark log as needing to be (re)written to storage
|
||||
setDirty() {
|
||||
this.isDirty = true;
|
||||
if (!this.saveId) {
|
||||
this.saveId = setTimeout(this.save.bind(this), this.saveTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
// Add a timestamp for the current time to the end of the log
|
||||
addEntry() {
|
||||
// If log full, purge an old entry to make room for new one
|
||||
if (this.maxLength) {
|
||||
while (this.log.length + 1 > this.maxLength) {
|
||||
this.log.shift();
|
||||
}
|
||||
}
|
||||
// Add new entry
|
||||
this.log.push({
|
||||
stamp: new Date()
|
||||
});
|
||||
this.setDirty();
|
||||
}
|
||||
|
||||
// Delete the log objects given in the array `entries` from the log
|
||||
deleteEntries(entries) {
|
||||
this.log = this.log.filter(entry => !entries.includes(entry));
|
||||
this.setDirty();
|
||||
}
|
||||
|
||||
// Does the log currently contain the maximum possible number of entries?
|
||||
isFull() {
|
||||
return this.log.length >= this.maxLength;
|
||||
}
|
||||
}
|
||||
|
||||
function launchSettingsMenu(backCb) {
|
||||
const fonts = g.getFonts();
|
||||
const stampLog = new StampLog(LOG_FILENAME, SETTINGS.maxLogLength);
|
||||
|
||||
function saveSettings() {
|
||||
stampLog.save();
|
||||
if (!storage.writeJSON(SETTINGS_FILENAME, SETTINGS)) {
|
||||
E.showAlert('Trouble saving settings');
|
||||
}
|
||||
}
|
||||
|
||||
function endMenu() {
|
||||
saveSettings();
|
||||
backCb();
|
||||
}
|
||||
|
||||
function topMenu() {
|
||||
E.showMenu({
|
||||
'': {
|
||||
title: 'Stamplog',
|
||||
back: endMenu,
|
||||
},
|
||||
'Log': logMenu,
|
||||
'Appearance': appearanceMenu,
|
||||
'Button': {
|
||||
value: SETTINGS_BUTTON_ACTION.indexOf(SETTINGS.buttonAction),
|
||||
min: 0, max: SETTINGS_BUTTON_ACTION.length - 1,
|
||||
format: v => SETTINGS_BUTTON_ACTION[v],
|
||||
onchange: v => {
|
||||
SETTINGS.buttonAction = SETTINGS_BUTTON_ACTION[v];
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function logMenu() {
|
||||
E.showMenu({
|
||||
'': {
|
||||
title: 'Log',
|
||||
back: topMenu,
|
||||
},
|
||||
'Max entries': {
|
||||
value: SETTINGS.maxLogLength,
|
||||
min: 5, max: 100, step: 5,
|
||||
onchange: v => {
|
||||
SETTINGS.maxLogLength = v;
|
||||
stampLog.maxLength = v;
|
||||
}
|
||||
},
|
||||
'Auto-delete oldest': {
|
||||
value: SETTINGS.rotateLog,
|
||||
onchange: v => {
|
||||
SETTINGS.rotateLog = !SETTINGS.rotateLog;
|
||||
}
|
||||
},
|
||||
'Clear log': doClearLog,
|
||||
});
|
||||
}
|
||||
|
||||
function appearanceMenu() {
|
||||
E.showMenu({
|
||||
'': {
|
||||
title: 'Appearance',
|
||||
back: topMenu,
|
||||
},
|
||||
'Log font': {
|
||||
value: fonts.indexOf(SETTINGS.logFont),
|
||||
min: 0, max: fonts.length - 1,
|
||||
format: v => fonts[v],
|
||||
onchange: v => {
|
||||
SETTINGS.logFont = fonts[v];
|
||||
},
|
||||
},
|
||||
'Log font H size': {
|
||||
value: SETTINGS.logFontHSize,
|
||||
min: 1, max: 50,
|
||||
onchange: v => {
|
||||
SETTINGS.logFontHSize = v;
|
||||
},
|
||||
},
|
||||
'Log font V size': {
|
||||
value: SETTINGS.logFontVSize,
|
||||
min: 1, max: 50,
|
||||
onchange: v => {
|
||||
SETTINGS.logFontVSize = v;
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function doClearLog() {
|
||||
E.showPrompt('Erase ALL log entries?', {
|
||||
title: 'Clear log',
|
||||
buttons: {'Erase':1, "Don't":0}
|
||||
}).then((yes) => {
|
||||
if (yes) {
|
||||
stampLog.deleteEntries(stampLog.log);
|
||||
}
|
||||
logMenu();
|
||||
});
|
||||
}
|
||||
|
||||
topMenu();
|
||||
}
|
||||
|
||||
exports = {LOG_FILENAME, SETTINGS_FILENAME, SETTINGS, SETTINGS_BUTTON_ACTION, fontSpec, StampLog,
|
||||
launchSettingsMenu};
|
|
@ -10,7 +10,8 @@
|
|||
"interface": "interface.html",
|
||||
"storage": [
|
||||
{"name": "timestamplog.app.js", "url": "app.js"},
|
||||
{"name": "timestamplog.img", "url": "app-icon.js", "evaluate": true}
|
||||
{"name": "timestamplog.img", "url": "app-icon.js", "evaluate": true},
|
||||
{"name": "lib.js", "url": "lib.js"}
|
||||
],
|
||||
"data": [
|
||||
{"name": "timestamplog.settings"},
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
const tsl = require('timestamplog');
|
||||
|
||||
(
|
||||
function(backCb) {
|
||||
tsl.launchSettingsMenu(backCb);
|
||||
}
|
||||
);
|
Loading…
Reference in New Issue