Merge branch 'master' into fix/promenu-y-offset
Conflicts: apps/promenu/ChangeLogmaster
commit
4c7556d8f6
|
|
@ -55,3 +55,4 @@
|
||||||
to select an alarm in the main menu.
|
to select an alarm in the main menu.
|
||||||
0.50: Bangle.js 2: Long touch of alarm in main menu toggle it on/off. Touching the icon on
|
0.50: Bangle.js 2: Long touch of alarm in main menu toggle it on/off. Touching the icon on
|
||||||
the right will do the same.
|
the right will do the same.
|
||||||
|
0.51: Fix long-touch to enable alarm/timer not updating time (fix #3804)
|
||||||
|
|
|
||||||
|
|
@ -87,11 +87,10 @@ function showMainMenu(scroll, group, scrollback) {
|
||||||
};
|
};
|
||||||
const getGroups = settings.showGroup && !group;
|
const getGroups = settings.showGroup && !group;
|
||||||
const groups = getGroups ? {} : undefined;
|
const groups = getGroups ? {} : undefined;
|
||||||
var showAlarm;
|
|
||||||
const getIcon = (e)=>{return e.on ? (e.timer ? iconTimerOn : iconAlarmOn) : (e.timer ? iconTimerOff : iconAlarmOff);};
|
const getIcon = (e)=>{return e.on ? (e.timer ? iconTimerOn : iconAlarmOn) : (e.timer ? iconTimerOff : iconAlarmOff);};
|
||||||
|
|
||||||
alarms.forEach((e, index) => {
|
alarms.forEach((e, index) => {
|
||||||
showAlarm = !settings.showGroup || (group ? e.group === group : !e.group);
|
const showAlarm = !settings.showGroup || (group ? e.group === group : !e.group);
|
||||||
if(showAlarm) {
|
if(showAlarm) {
|
||||||
const label = trimLabel(getLabel(e),40);
|
const label = trimLabel(getLabel(e),40);
|
||||||
menu[label] = {
|
menu[label] = {
|
||||||
|
|
@ -99,6 +98,7 @@ function showMainMenu(scroll, group, scrollback) {
|
||||||
onchange: (v, touch) => {
|
onchange: (v, touch) => {
|
||||||
if (touch && (2==touch.type || 145<touch.x)) { // Long touch or touched icon.
|
if (touch && (2==touch.type || 145<touch.x)) { // Long touch or touched icon.
|
||||||
e.on = v;
|
e.on = v;
|
||||||
|
if (e.on) prepareForSave(e, index);
|
||||||
saveAndReload();
|
saveAndReload();
|
||||||
} else {
|
} else {
|
||||||
setTimeout(e.timer ? showEditTimerMenu : showEditAlarmMenu, 10, e, index, undefined, scroller?scroller.scroll:undefined, group);
|
setTimeout(e.timer ? showEditTimerMenu : showEditAlarmMenu, 10, e, index, undefined, scroller?scroller.scroll:undefined, group);
|
||||||
|
|
@ -328,6 +328,14 @@ function prepareAlarmForSave(alarm, alarmIndex, time, date, temp) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function prepareForSave(alarm, alarmIndex) {
|
||||||
|
if (alarm.timer) {
|
||||||
|
prepareTimerForSave(alarm, alarmIndex, require("time_utils").decodeTime(alarm.timer));
|
||||||
|
} else {
|
||||||
|
prepareAlarmForSave(alarm, alarmIndex, require("time_utils").decodeTime(alarm.t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function saveAndReload() {
|
function saveAndReload() {
|
||||||
// Before saving revert the dow to the standard format (alarms only!)
|
// Before saving revert the dow to the standard format (alarms only!)
|
||||||
alarms.filter(e => e.timer === undefined).forEach(a => a.dow = handleFirstDayOfWeek(a.dow));
|
alarms.filter(e => e.timer === undefined).forEach(a => a.dow = handleFirstDayOfWeek(a.dow));
|
||||||
|
|
@ -574,13 +582,7 @@ function enableAll(on) {
|
||||||
if (confirm) {
|
if (confirm) {
|
||||||
alarms.forEach((alarm, i) => {
|
alarms.forEach((alarm, i) => {
|
||||||
alarm.on = on;
|
alarm.on = on;
|
||||||
if (on) {
|
if (on) prepareForSave(alarm, i);
|
||||||
if (alarm.timer) {
|
|
||||||
prepareTimerForSave(alarm, i, require("time_utils").decodeTime(alarm.timer));
|
|
||||||
} else {
|
|
||||||
prepareAlarmForSave(alarm, i, require("time_utils").decodeTime(alarm.t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
saveAndReload();
|
saveAndReload();
|
||||||
showMainMenu();
|
showMainMenu();
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "alarm",
|
"id": "alarm",
|
||||||
"name": "Alarms & Timers",
|
"name": "Alarms & Timers",
|
||||||
"shortName": "Alarms",
|
"shortName": "Alarms",
|
||||||
"version": "0.50",
|
"version": "0.51",
|
||||||
"description": "Set alarms and timers on your Bangle",
|
"description": "Set alarms and timers on your Bangle",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"tags": "tool,alarm",
|
"tags": "tool,alarm",
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,5 @@
|
||||||
0.02: Fix reset of progress bars on midnight. Fix display of 100k+ steps.
|
0.02: Fix reset of progress bars on midnight. Fix display of 100k+ steps.
|
||||||
0.03: Added option to display weather.
|
0.03: Added option to display weather.
|
||||||
0.04: Added option to display live updates of step count.
|
0.04: Added option to display live updates of step count.
|
||||||
|
0.05: Reset graphics before initial clearing of the screen. Helps in some
|
||||||
|
situations if using fastload utils.
|
||||||
|
|
|
||||||
|
|
@ -336,7 +336,7 @@
|
||||||
/* Startup Process
|
/* Startup Process
|
||||||
------------------------------------------------------------------------------*/
|
------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
g.clear();
|
g.clear(1);
|
||||||
drawAll();
|
drawAll();
|
||||||
startTimers();
|
startTimers();
|
||||||
registerEvents();
|
registerEvents();
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "edgeclk",
|
"id": "edgeclk",
|
||||||
"name": "Edge Clock",
|
"name": "Edge Clock",
|
||||||
"shortName": "Edge Clock",
|
"shortName": "Edge Clock",
|
||||||
"version": "0.04",
|
"version": "0.05",
|
||||||
"description": "Crisp clock with perfect readability.",
|
"description": "Crisp clock with perfect readability.",
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,7 @@
|
||||||
* @param _button 1 for left half, 2 for right half
|
* @param _button 1 for left half, 2 for right half
|
||||||
* @param xy postion on screen
|
* @param xy postion on screen
|
||||||
*/
|
*/
|
||||||
let onTouch = function (_button: number, xy: { x: number, y: number } | undefined) {
|
let onTouch = function (_button, xy) {
|
||||||
// Determine which grid cell was tapped
|
// Determine which grid cell was tapped
|
||||||
let x: number = Math.floor((xy!.x - 12) / ((g.getWidth() - 24) / config.display.rows));
|
let x: number = Math.floor((xy!.x - 12) / ((g.getWidth() - 24) / config.display.rows));
|
||||||
if (x < 0) x = 0;
|
if (x < 0) x = 0;
|
||||||
|
|
@ -206,7 +206,7 @@
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} satisfies TouchCallback;
|
||||||
|
|
||||||
let page: number = 0;
|
let page: number = 0;
|
||||||
let nPages: number; // Set when setting folder
|
let nPages: number; // Set when setting folder
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
0.01: first release
|
0.01: first release
|
||||||
0.02: memory leak fix; color changes to better align with VSCode color scheme; logo is transparent
|
0.02: memory leak fix; color changes to better align with VSCode color scheme; logo is transparent
|
||||||
|
0.03: Fixed redrawing of commas
|
||||||
|
|
|
||||||
|
|
@ -229,6 +229,7 @@ let redraw = function() {
|
||||||
if (!(key in valsArrs)) continue;
|
if (!(key in valsArrs)) continue;
|
||||||
let valsArr = valsArrs[key];
|
let valsArr = valsArrs[key];
|
||||||
if (value === valsArr.text) continue; // No need to update
|
if (value === valsArr.text) continue; // No need to update
|
||||||
|
if (valsArr.endComma) value = value.slice(0, -1);
|
||||||
valsArrs[key].text = value;
|
valsArrs[key].text = value;
|
||||||
|
|
||||||
// Clear prev values
|
// Clear prev values
|
||||||
|
|
@ -239,7 +240,7 @@ let redraw = function() {
|
||||||
g.drawString(value, valsArr.x, valsArr.y);
|
g.drawString(value, valsArr.x, valsArr.y);
|
||||||
if (valsArr.endComma){
|
if (valsArr.endComma){
|
||||||
g.setColor(clrs.brackets);
|
g.setColor(clrs.brackets);
|
||||||
g.drawString(',', valsArr.Banglex + g.stringWidth(value), valsArr.y);
|
g.drawString(',', valsArr.x + g.stringWidth(value), valsArr.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{ "id": "jsonclock",
|
{ "id": "jsonclock",
|
||||||
"name": "JsonClock",
|
"name": "JsonClock",
|
||||||
"version": "0.02",
|
"version": "0.03",
|
||||||
"description": "JSON view of the time, date, steps, battery, and sunrise and sunset times",
|
"description": "JSON view of the time, date, steps, battery, and sunrise and sunset times",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"screenshots": [{"url":"dark.png"}],
|
"screenshots": [{"url":"dark.png"}],
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,5 @@
|
||||||
0.02: Show elapsed time on pause screen
|
0.02: Show elapsed time on pause screen
|
||||||
0.03: Avoid initial GPS skew and allow reset of time/splits
|
0.03: Avoid initial GPS skew and allow reset of time/splits
|
||||||
0.04: Bump exstats module - show active time, not elapsed
|
0.04: Bump exstats module - show active time, not elapsed
|
||||||
|
0.05: Fix menu display - don't draw over the menu and vice-versa. Require
|
||||||
|
double-tap for menu
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,8 @@ A running pace app, useful for races. Will also record your splits and display t
|
||||||
Drag up/down on the pause menu to scroll through your splits.
|
Drag up/down on the pause menu to scroll through your splits.
|
||||||
Press the button to pause/resume - when resumed, pressing the button will pause instantly, regardless of whether the screen is locked.
|
Press the button to pause/resume - when resumed, pressing the button will pause instantly, regardless of whether the screen is locked.
|
||||||
|
|
||||||
|
Double tap the pause screen to access a menu for finer control
|
||||||
|
|
||||||
# Todo
|
# Todo
|
||||||
|
|
||||||
- Load splits on app start, button to reset (exs is always reset)
|
- Load splits on app start, button to reset (exs is always reset)
|
||||||
- Show total time on pause screen
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
});
|
});
|
||||||
var S_1 = require("Storage");
|
var S_1 = require("Storage");
|
||||||
var drawTimeout_1;
|
var drawTimeout_1;
|
||||||
|
var menuShown_1 = false;
|
||||||
var splits_1 = [];
|
var splits_1 = [];
|
||||||
var splitOffset_1 = 0, splitOffsetPx_1 = 0;
|
var splitOffset_1 = 0, splitOffsetPx_1 = 0;
|
||||||
var GPS_TIMEOUT_MS_1 = 30000;
|
var GPS_TIMEOUT_MS_1 = 30000;
|
||||||
|
|
@ -113,12 +114,10 @@
|
||||||
};
|
};
|
||||||
var pauseRun_1 = function () {
|
var pauseRun_1 = function () {
|
||||||
exs_1.stop();
|
exs_1.stop();
|
||||||
Bangle.setGPSPower(0, "pace");
|
|
||||||
draw_1();
|
draw_1();
|
||||||
};
|
};
|
||||||
var resumeRun_1 = function () {
|
var resumeRun_1 = function () {
|
||||||
exs_1.resume();
|
exs_1.resume();
|
||||||
Bangle.setGPSPower(1, "pace");
|
|
||||||
g.clearRect(Bangle.appRect);
|
g.clearRect(Bangle.appRect);
|
||||||
layout_1.forgetLazyState();
|
layout_1.forgetLazyState();
|
||||||
draw_1();
|
draw_1();
|
||||||
|
|
@ -129,6 +128,12 @@
|
||||||
else
|
else
|
||||||
resumeRun_1();
|
resumeRun_1();
|
||||||
};
|
};
|
||||||
|
var hideMenu_1 = function () {
|
||||||
|
if (!menuShown_1)
|
||||||
|
return;
|
||||||
|
Bangle.setUI();
|
||||||
|
menuShown_1 = false;
|
||||||
|
};
|
||||||
exs_1.start();
|
exs_1.start();
|
||||||
exs_1.stats.dist.on("notify", function (dist) {
|
exs_1.stats.dist.on("notify", function (dist) {
|
||||||
var prev = { time: 0, dist: 0 };
|
var prev = { time: 0, dist: 0 };
|
||||||
|
|
@ -156,7 +161,7 @@
|
||||||
});
|
});
|
||||||
setWatch(function () { return onButton_1(); }, BTN1, { repeat: true });
|
setWatch(function () { return onButton_1(); }, BTN1, { repeat: true });
|
||||||
Bangle.on('drag', function (e) {
|
Bangle.on('drag', function (e) {
|
||||||
if (exs_1.state.active || e.b === 0)
|
if (exs_1.state.active || e.b === 0 || menuShown_1)
|
||||||
return;
|
return;
|
||||||
splitOffsetPx_1 -= e.dy;
|
splitOffsetPx_1 -= e.dy;
|
||||||
if (splitOffsetPx_1 > 20) {
|
if (splitOffsetPx_1 > 20) {
|
||||||
|
|
@ -174,9 +179,10 @@
|
||||||
Bangle.on('twist', function () {
|
Bangle.on('twist', function () {
|
||||||
Bangle.setBacklight(1);
|
Bangle.setBacklight(1);
|
||||||
});
|
});
|
||||||
Bangle.on('tap', function (_e) {
|
Bangle.on('tap', function (e) {
|
||||||
if (exs_1.state.active)
|
if (exs_1.state.active || menuShown_1 || !e.double)
|
||||||
return;
|
return;
|
||||||
|
menuShown_1 = true;
|
||||||
var menu = {
|
var menu = {
|
||||||
"": {
|
"": {
|
||||||
remove: function () {
|
remove: function () {
|
||||||
|
|
@ -184,22 +190,23 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"< Back": function () {
|
"< Back": function () {
|
||||||
Bangle.setUI();
|
hideMenu_1();
|
||||||
},
|
},
|
||||||
"Zero time": function () {
|
"Zero time": function () {
|
||||||
exs_1.start();
|
exs_1.start();
|
||||||
exs_1.stop();
|
exs_1.stop();
|
||||||
Bangle.setUI();
|
hideMenu_1();
|
||||||
},
|
},
|
||||||
"Clear splits": function () {
|
"Clear splits": function () {
|
||||||
splits_1.splice(0, splits_1.length);
|
splits_1.splice(0, splits_1.length);
|
||||||
Bangle.setUI();
|
hideMenu_1();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
E.showMenu(menu);
|
E.showMenu(menu);
|
||||||
});
|
});
|
||||||
Bangle.loadWidgets();
|
Bangle.loadWidgets();
|
||||||
Bangle.drawWidgets();
|
Bangle.drawWidgets();
|
||||||
|
Bangle.setGPSPower(1, "pace");
|
||||||
g.clearRect(Bangle.appRect);
|
g.clearRect(Bangle.appRect);
|
||||||
draw_1();
|
draw_1();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ const exs = require("exstats").getStats(
|
||||||
const S = require("Storage");
|
const S = require("Storage");
|
||||||
|
|
||||||
let drawTimeout: TimeoutId | undefined;
|
let drawTimeout: TimeoutId | undefined;
|
||||||
|
let menuShown = false;
|
||||||
|
|
||||||
type Dist = number & { brand: 'dist' };
|
type Dist = number & { brand: 'dist' };
|
||||||
type Time = number & { brand: 'time' };
|
type Time = number & { brand: 'time' };
|
||||||
|
|
@ -151,13 +152,11 @@ const drawSplit = (i: number, y: number, pace: number | string) =>
|
||||||
|
|
||||||
const pauseRun = () => {
|
const pauseRun = () => {
|
||||||
exs.stop();
|
exs.stop();
|
||||||
Bangle.setGPSPower(0, "pace")
|
|
||||||
draw();
|
draw();
|
||||||
};
|
};
|
||||||
|
|
||||||
const resumeRun = () => {
|
const resumeRun = () => {
|
||||||
exs.resume();
|
exs.resume();
|
||||||
Bangle.setGPSPower(1, "pace");
|
|
||||||
|
|
||||||
g.clearRect(Bangle.appRect); // splits -> layout, clear. layout -> splits, fine
|
g.clearRect(Bangle.appRect); // splits -> layout, clear. layout -> splits, fine
|
||||||
layout.forgetLazyState();
|
layout.forgetLazyState();
|
||||||
|
|
@ -171,6 +170,12 @@ const onButton = () => {
|
||||||
resumeRun();
|
resumeRun();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const hideMenu = () => {
|
||||||
|
if (!menuShown) return;
|
||||||
|
Bangle.setUI(); // calls `remove`, which handles redrawing
|
||||||
|
menuShown = false;
|
||||||
|
}
|
||||||
|
|
||||||
exs.start(); // aka reset
|
exs.start(); // aka reset
|
||||||
|
|
||||||
exs.stats.dist.on("notify", (dist) => {
|
exs.stats.dist.on("notify", (dist) => {
|
||||||
|
|
@ -209,7 +214,7 @@ Bangle.on('lock', locked => {
|
||||||
setWatch(() => onButton(), BTN1, { repeat: true });
|
setWatch(() => onButton(), BTN1, { repeat: true });
|
||||||
|
|
||||||
Bangle.on('drag', e => {
|
Bangle.on('drag', e => {
|
||||||
if (exs.state.active || e.b === 0) return;
|
if (exs.state.active || e.b === 0 || menuShown) return;
|
||||||
|
|
||||||
splitOffsetPx -= e.dy;
|
splitOffsetPx -= e.dy;
|
||||||
if (splitOffsetPx > 20) {
|
if (splitOffsetPx > 20) {
|
||||||
|
|
@ -226,9 +231,11 @@ Bangle.on('twist', () => {
|
||||||
Bangle.setBacklight(1);
|
Bangle.setBacklight(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
Bangle.on('tap', _e => {
|
Bangle.on('tap', e => {
|
||||||
if(exs.state.active) return;
|
// require a double tap, to avoid picking up menu "< Back" taps
|
||||||
|
if(exs.state.active || menuShown || !e.double) return;
|
||||||
|
|
||||||
|
menuShown = true;
|
||||||
const menu: Menu = {
|
const menu: Menu = {
|
||||||
"": {
|
"": {
|
||||||
remove: () => {
|
remove: () => {
|
||||||
|
|
@ -236,16 +243,16 @@ Bangle.on('tap', _e => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"< Back": () => {
|
"< Back": () => {
|
||||||
Bangle.setUI(); // calls `remove`, which handles redrawing
|
hideMenu();
|
||||||
},
|
},
|
||||||
"Zero time": () => {
|
"Zero time": () => {
|
||||||
exs.start(); // calls reset
|
exs.start(); // calls reset
|
||||||
exs.stop(); // re-pauses
|
exs.stop(); // re-pauses
|
||||||
Bangle.setUI();
|
hideMenu();
|
||||||
},
|
},
|
||||||
"Clear splits": () => {
|
"Clear splits": () => {
|
||||||
splits.splice(0, splits.length);
|
splits.splice(0, splits.length);
|
||||||
Bangle.setUI();
|
hideMenu();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -254,6 +261,7 @@ Bangle.on('tap', _e => {
|
||||||
|
|
||||||
Bangle.loadWidgets();
|
Bangle.loadWidgets();
|
||||||
Bangle.drawWidgets();
|
Bangle.drawWidgets();
|
||||||
|
Bangle.setGPSPower(1, "pace");
|
||||||
|
|
||||||
g.clearRect(Bangle.appRect);
|
g.clearRect(Bangle.appRect);
|
||||||
draw();
|
draw();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "pace",
|
"id": "pace",
|
||||||
"name": "Pace",
|
"name": "Pace",
|
||||||
"version": "0.04",
|
"version": "0.05",
|
||||||
"description": "Show pace and time running splits",
|
"description": "Show pace and time running splits",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"tags": "run,running,fitness,outdoors",
|
"tags": "run,running,fitness,outdoors",
|
||||||
|
|
|
||||||
|
|
@ -14,4 +14,5 @@
|
||||||
0.10: Trigger `remove` callbacks when ending the menu
|
0.10: Trigger `remove` callbacks when ending the menu
|
||||||
0.11: Add options for natural scroll and disabling wrap-around
|
0.11: Add options for natural scroll and disabling wrap-around
|
||||||
0.12: Fix bug where settings would behave as if all were set to false
|
0.12: Fix bug where settings would behave as if all were set to false
|
||||||
0.13: Fix bug in handling changes to `Bangle.appRect`
|
0.13: Update to new touch-event handling
|
||||||
|
0.14: Fix bug in handling changes to `Bangle.appRect`
|
||||||
|
|
|
||||||
|
|
@ -133,10 +133,10 @@ E.showMenu = function (items) {
|
||||||
g.setColor((idx < menuItems.length) ? g.theme.fg : g.theme.bg).fillPoly([72, 166, 104, 166, 88, 174]);
|
g.setColor((idx < menuItems.length) ? g.theme.fg : g.theme.bg).fillPoly([72, 166, 104, 166, 88, 174]);
|
||||||
g.flip();
|
g.flip();
|
||||||
},
|
},
|
||||||
select: function () {
|
select: function (evt) {
|
||||||
var item = items[menuItems[selected]];
|
var item = items[menuItems[selected]];
|
||||||
if (typeof item === "function") {
|
if (typeof item === "function") {
|
||||||
item();
|
item(evt);
|
||||||
}
|
}
|
||||||
else if (typeof item === "object") {
|
else if (typeof item === "object") {
|
||||||
if (typeof item.value === "number") {
|
if (typeof item.value === "number") {
|
||||||
|
|
@ -146,12 +146,12 @@ E.showMenu = function (items) {
|
||||||
if (typeof item.value === "boolean")
|
if (typeof item.value === "boolean")
|
||||||
item.value = !item.value;
|
item.value = !item.value;
|
||||||
if (item.onchange)
|
if (item.onchange)
|
||||||
item.onchange(item.value);
|
item.onchange(item.value, evt);
|
||||||
}
|
}
|
||||||
l.draw();
|
l.draw();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
move: function (dir) {
|
move: function (dir, evt) {
|
||||||
var item = selectEdit;
|
var item = selectEdit;
|
||||||
if (typeof item === "object" && typeof item.value === "number") {
|
if (typeof item === "object" && typeof item.value === "number") {
|
||||||
var orig = item.value;
|
var orig = item.value;
|
||||||
|
|
@ -162,7 +162,7 @@ E.showMenu = function (items) {
|
||||||
item.value = item.wrap ? item.min : item.max;
|
item.value = item.wrap ? item.min : item.max;
|
||||||
if (item.value !== orig) {
|
if (item.value !== orig) {
|
||||||
if (item.onchange)
|
if (item.onchange)
|
||||||
item.onchange(item.value);
|
item.onchange(item.value, evt);
|
||||||
l.draw(selected, selected);
|
l.draw(selected, selected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -198,6 +198,12 @@ E.showMenu = function (items) {
|
||||||
};
|
};
|
||||||
Bangle.on('swipe', onSwipe);
|
Bangle.on('swipe', onSwipe);
|
||||||
}
|
}
|
||||||
|
var cb = function (dir, evt) {
|
||||||
|
if (dir)
|
||||||
|
l.move(prosettings.naturalScroll ? -dir : dir, evt);
|
||||||
|
else
|
||||||
|
l.select(evt);
|
||||||
|
};
|
||||||
Bangle.setUI({
|
Bangle.setUI({
|
||||||
mode: "updown",
|
mode: "updown",
|
||||||
back: back,
|
back: back,
|
||||||
|
|
@ -208,11 +214,9 @@ E.showMenu = function (items) {
|
||||||
Bangle.removeListener("swipe", onSwipe);
|
Bangle.removeListener("swipe", onSwipe);
|
||||||
(_a = options.remove) === null || _a === void 0 ? void 0 : _a.call(options);
|
(_a = options.remove) === null || _a === void 0 ? void 0 : _a.call(options);
|
||||||
},
|
},
|
||||||
}, function (dir) {
|
touch: (function (_button, xy) {
|
||||||
if (dir)
|
cb(void 0, xy);
|
||||||
l.move(prosettings.naturalScroll ? -dir : dir);
|
}),
|
||||||
else
|
}, cb);
|
||||||
l.select();
|
|
||||||
});
|
|
||||||
return l;
|
return l;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -175,11 +175,11 @@ E.showMenu = (items?: Menu): MenuInstance => {
|
||||||
g.setColor((idx < menuItems.length)?g.theme.fg:g.theme.bg).fillPoly([72, 166, 104, 166, 88, 174]);
|
g.setColor((idx < menuItems.length)?g.theme.fg:g.theme.bg).fillPoly([72, 166, 104, 166, 88, 174]);
|
||||||
g.flip();
|
g.flip();
|
||||||
},
|
},
|
||||||
select: () => {
|
select: (evt: TouchCallbackXY | undefined) => {
|
||||||
const item = items![menuItems[selected]] as ActualMenuItem;
|
const item = items![menuItems[selected]] as ActualMenuItem;
|
||||||
|
|
||||||
if (typeof item === "function") {
|
if (typeof item === "function") {
|
||||||
item();
|
item(evt);
|
||||||
} else if (typeof item === "object") {
|
} else if (typeof item === "object") {
|
||||||
if (typeof item.value === "number") {
|
if (typeof item.value === "number") {
|
||||||
selectEdit = selectEdit ? undefined : item;
|
selectEdit = selectEdit ? undefined : item;
|
||||||
|
|
@ -188,12 +188,12 @@ E.showMenu = (items?: Menu): MenuInstance => {
|
||||||
item.value = !item.value;
|
item.value = !item.value;
|
||||||
|
|
||||||
if (item.onchange)
|
if (item.onchange)
|
||||||
item.onchange(item.value as boolean);
|
item.onchange(item.value as boolean, evt);
|
||||||
}
|
}
|
||||||
l.draw();
|
l.draw();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
move: (dir: number) => {
|
move: (dir: number, evt: TouchCallbackXY | undefined) => {
|
||||||
const item = selectEdit;
|
const item = selectEdit;
|
||||||
|
|
||||||
if (typeof item === "object" && typeof item.value === "number") {
|
if (typeof item === "object" && typeof item.value === "number") {
|
||||||
|
|
@ -209,7 +209,7 @@ E.showMenu = (items?: Menu): MenuInstance => {
|
||||||
|
|
||||||
if (item.value !== orig) {
|
if (item.value !== orig) {
|
||||||
if (item.onchange)
|
if (item.onchange)
|
||||||
item.onchange(item.value);
|
item.onchange(item.value, evt);
|
||||||
|
|
||||||
l.draw(selected, selected);
|
l.draw(selected, selected);
|
||||||
}
|
}
|
||||||
|
|
@ -247,6 +247,11 @@ E.showMenu = (items?: Menu): MenuInstance => {
|
||||||
Bangle.on('swipe', onSwipe);
|
Bangle.on('swipe', onSwipe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cb = (dir?: 1 | -1, evt?: TouchCallbackXY) => {
|
||||||
|
if (dir) l.move(prosettings.naturalScroll ? -dir : dir, evt);
|
||||||
|
else l.select(evt);
|
||||||
|
};
|
||||||
|
|
||||||
Bangle.setUI({
|
Bangle.setUI({
|
||||||
mode: "updown",
|
mode: "updown",
|
||||||
back,
|
back,
|
||||||
|
|
@ -255,11 +260,13 @@ E.showMenu = (items?: Menu): MenuInstance => {
|
||||||
Bangle.removeListener("swipe", onSwipe);
|
Bangle.removeListener("swipe", onSwipe);
|
||||||
options.remove?.();
|
options.remove?.();
|
||||||
},
|
},
|
||||||
} as SetUIArg<"updown">,
|
touch: ((_button, xy) => {
|
||||||
dir => {
|
// since we've specified options.touch,
|
||||||
if (dir) l.move(prosettings.naturalScroll ? -dir : dir);
|
// we need to pass through all taps since the default
|
||||||
else l.select();
|
// touchHandler isn't installed in setUI
|
||||||
});
|
cb(void 0, xy);
|
||||||
|
}) satisfies TouchCallback,
|
||||||
|
} as SetUIArg<"updown">, cb);
|
||||||
|
|
||||||
return l;
|
return l;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "promenu",
|
"id": "promenu",
|
||||||
"name": "Pro Menu",
|
"name": "Pro Menu",
|
||||||
"version": "0.13",
|
"version": "0.14",
|
||||||
"description": "Replace the built in menu function. Supports Bangle.js 1 and Bangle.js 2.",
|
"description": "Replace the built in menu function. Supports Bangle.js 1 and Bangle.js 2.",
|
||||||
"icon": "icon.png",
|
"icon": "icon.png",
|
||||||
"type": "bootloader",
|
"type": "bootloader",
|
||||||
|
|
|
||||||
|
|
@ -31,4 +31,5 @@
|
||||||
0.28: Added an icon for disabled events
|
0.28: Added an icon for disabled events
|
||||||
0.29: Improve clkinfo startup time by 10ms
|
0.29: Improve clkinfo startup time by 10ms
|
||||||
0.30: Fix possible bug in toggling an alarm to on, from clkinfo
|
0.30: Fix possible bug in toggling an alarm to on, from clkinfo
|
||||||
0.31: Ensure we reschedule alarms after setTimeZone has been called (fix #3791)
|
0.31: Ensure we reschedule alarms after setTimeZone has been called (fix #3791)
|
||||||
|
0.32: clkinfo ensures an alarm won't trigger immediately (copying `alarm`'s behaviour)
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,9 @@ exports.resetTimer = function(alarm, time) {
|
||||||
time = time || new Date();
|
time = time || new Date();
|
||||||
var currentTime = (time.getHours()*3600000)+(time.getMinutes()*60000)+(time.getSeconds()*1000);
|
var currentTime = (time.getHours()*3600000)+(time.getMinutes()*60000)+(time.getSeconds()*1000);
|
||||||
alarm.t = (currentTime + alarm.timer) % 86400000;
|
alarm.t = (currentTime + alarm.timer) % 86400000;
|
||||||
|
alarm.last = "timer" in alarm || alarm.t >= require("time_utils").getCurrentTimeMillis()
|
||||||
|
? 0
|
||||||
|
: new Date().getDate();
|
||||||
};
|
};
|
||||||
/// Get time until the given alarm (object). Return undefined if alarm not enabled, or if 86400000 or more, alarm could be *more* than a day in the future
|
/// Get time until the given alarm (object). Return undefined if alarm not enabled, or if 86400000 or more, alarm could be *more* than a day in the future
|
||||||
exports.getTimeToAlarm = function(alarm, time) {
|
exports.getTimeToAlarm = function(alarm, time) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "sched",
|
"id": "sched",
|
||||||
"name": "Scheduler",
|
"name": "Scheduler",
|
||||||
"version": "0.31",
|
"version": "0.32",
|
||||||
"description": "Scheduling library for alarms and timers",
|
"description": "Scheduling library for alarms and timers",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "scheduler",
|
"type": "scheduler",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
0.01: New app!
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Tally
|
||||||
|
|
||||||
|
An app that lets you keep a tally - when events happen, etc.
|
||||||
|
|
||||||
|
Use the clock info to add to the tally. The app can be used to review/edit/delete tallies
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Navigate to the tally clock info, then swipe up/down to select one of the tallies to enter. Tap on it to add to the tally.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwwInkgf/AAXAg4FD8EPAofwAowcDAqkD4AFW4fAAqYEBAtp3XTZStFXIsAh/gD4cPBAIFDwAFEbAkOAokMAokIApQAKA=="))
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
var storage = require("Storage");
|
||||||
|
function readTallies() {
|
||||||
|
var tallies = [];
|
||||||
|
var f = storage.open("tallies.csv", "r");
|
||||||
|
var line;
|
||||||
|
while ((line = f.readLine()) !== undefined) {
|
||||||
|
var parts = line.replace("\n", "").split(",");
|
||||||
|
tallies.push({ date: new Date(parts[0]), name: parts[1] });
|
||||||
|
}
|
||||||
|
return tallies;
|
||||||
|
}
|
||||||
|
function saveTallies(tallies) {
|
||||||
|
var f = storage.open("tallies.csv", "w");
|
||||||
|
for (var _i = 0, tallies_1 = tallies; _i < tallies_1.length; _i++) {
|
||||||
|
var tally = tallies_1[_i];
|
||||||
|
f.write([tally.date.toISOString(), tally.name].join(",") + "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var dayEq = function (a, b) {
|
||||||
|
return a.getFullYear() === b.getFullYear()
|
||||||
|
&& a.getMonth() === b.getMonth()
|
||||||
|
&& a.getDate() === b.getDate();
|
||||||
|
};
|
||||||
|
function showTallies(tallies) {
|
||||||
|
var menu = {
|
||||||
|
"": { title: "Tallies" },
|
||||||
|
"< Back": function () { return load(); },
|
||||||
|
};
|
||||||
|
var today = new Date;
|
||||||
|
var day;
|
||||||
|
tallies.forEach(function (tally, i) {
|
||||||
|
var td = tally.date;
|
||||||
|
if (!dayEq(day !== null && day !== void 0 ? day : today, td)) {
|
||||||
|
var s = "".concat(td.getFullYear(), "-").concat(pad2(td.getMonth() + 1), "-").concat(pad2(td.getDate()));
|
||||||
|
menu[s] = function () { };
|
||||||
|
day = td;
|
||||||
|
}
|
||||||
|
menu["".concat(tfmt(tally), ": ").concat(tally.name)] = function () { return editTally(tallies, i); };
|
||||||
|
});
|
||||||
|
E.showMenu(menu);
|
||||||
|
}
|
||||||
|
function editTally(tallies, i) {
|
||||||
|
var tally = tallies[i];
|
||||||
|
var onback = function () {
|
||||||
|
saveTallies(tallies);
|
||||||
|
E.removeListener("kill", onback);
|
||||||
|
};
|
||||||
|
E.on("kill", onback);
|
||||||
|
var menu = {
|
||||||
|
"": { title: "Edit ".concat(tally.name) },
|
||||||
|
"< Back": function () {
|
||||||
|
onback();
|
||||||
|
showTallies(tallies);
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
value: tally.name,
|
||||||
|
onchange: function () {
|
||||||
|
setTimeout(function () {
|
||||||
|
require("textinput")
|
||||||
|
.input({ text: tally.name })
|
||||||
|
.then(function (text) {
|
||||||
|
if (text) {
|
||||||
|
tally.name = text;
|
||||||
|
}
|
||||||
|
editTally(tallies, i);
|
||||||
|
});
|
||||||
|
}, 0);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"Time": {
|
||||||
|
value: tally.date.getTime(),
|
||||||
|
format: function (_tm) { return tfmt(tally); },
|
||||||
|
onchange: function (v) {
|
||||||
|
tally.date = new Date(v);
|
||||||
|
},
|
||||||
|
step: 60000,
|
||||||
|
},
|
||||||
|
"Delete": function () {
|
||||||
|
E.showPrompt("Delete \"".concat(tally.name, "\"?"), {
|
||||||
|
title: "Delete",
|
||||||
|
buttons: { Yes: true, No: false },
|
||||||
|
}).then(function (confirm) {
|
||||||
|
if (confirm) {
|
||||||
|
tallies.splice(i, 1);
|
||||||
|
saveTallies(tallies);
|
||||||
|
showTallies(tallies);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
editTally(tallies, i);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
E.showMenu(menu);
|
||||||
|
}
|
||||||
|
function tfmt(tally) {
|
||||||
|
var d = tally.date;
|
||||||
|
return "".concat(d.getHours(), ":").concat(pad2(d.getMinutes()));
|
||||||
|
}
|
||||||
|
var pad2 = function (s) { return ("0" + s.toFixed(0)).slice(-2); };
|
||||||
|
showTallies(readTallies());
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 296 B |
|
|
@ -0,0 +1,120 @@
|
||||||
|
const storage = require("Storage");
|
||||||
|
|
||||||
|
type Tally = {
|
||||||
|
date: Date,
|
||||||
|
name: string,
|
||||||
|
};
|
||||||
|
|
||||||
|
function readTallies() {
|
||||||
|
const tallies: Tally[] = [];
|
||||||
|
const f = storage.open("tallies.csv", "r");
|
||||||
|
let line;
|
||||||
|
while ((line = f.readLine()) !== undefined) {
|
||||||
|
const parts = line.replace("\n", "").split(",");
|
||||||
|
tallies.push({ date: new Date(parts[0]), name: parts[1] });
|
||||||
|
}
|
||||||
|
return tallies;
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveTallies(tallies: Tally[]) {
|
||||||
|
const f = storage.open("tallies.csv", "w");
|
||||||
|
for(const tally of tallies){
|
||||||
|
f.write([tally.date.toISOString(), tally.name].join(",") + "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const dayEq = (a: Date, b: Date) =>
|
||||||
|
a.getFullYear() === b.getFullYear()
|
||||||
|
&& a.getMonth() === b.getMonth()
|
||||||
|
&& a.getDate() === b.getDate();
|
||||||
|
|
||||||
|
function showTallies(tallies: Tally[]) {
|
||||||
|
const menu: Menu = {
|
||||||
|
"": { title: "Tallies" },
|
||||||
|
"< Back": () => load(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const today = new Date;
|
||||||
|
let day: undefined | Date;
|
||||||
|
|
||||||
|
tallies.forEach((tally, i) => {
|
||||||
|
const td = tally.date;
|
||||||
|
if(!dayEq(day ?? today, td)){
|
||||||
|
const s = `${td.getFullYear()}-${pad2(td.getMonth() + 1)}-${pad2(td.getDate())}`;
|
||||||
|
menu[s] = () => {};
|
||||||
|
day = td;
|
||||||
|
}
|
||||||
|
|
||||||
|
menu[`${tfmt(tally)}: ${tally.name}`] = () => editTally(tallies, i);
|
||||||
|
});
|
||||||
|
|
||||||
|
E.showMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
function editTally(tallies: Tally[], i: number) {
|
||||||
|
const tally = tallies[i]!;
|
||||||
|
|
||||||
|
const onback = () => {
|
||||||
|
saveTallies(tallies);
|
||||||
|
E.removeListener("kill", onback);
|
||||||
|
};
|
||||||
|
E.on("kill", onback);
|
||||||
|
|
||||||
|
const menu: Menu = {
|
||||||
|
"": { title: `Edit ${tally.name}` },
|
||||||
|
"< Back": () => {
|
||||||
|
onback();
|
||||||
|
showTallies(tallies)
|
||||||
|
},
|
||||||
|
"Name": {
|
||||||
|
value: tally.name,
|
||||||
|
onchange: () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
require("textinput")
|
||||||
|
.input({ text: tally.name })
|
||||||
|
.then(text => {
|
||||||
|
if (text) {
|
||||||
|
tally.name = text;
|
||||||
|
}
|
||||||
|
editTally(tallies, i);
|
||||||
|
});
|
||||||
|
}, 0);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"Time": {
|
||||||
|
value: tally.date.getTime(),
|
||||||
|
format: (_tm: number) => tfmt(tally),
|
||||||
|
onchange: (v: number) => {
|
||||||
|
tally.date = new Date(v);
|
||||||
|
},
|
||||||
|
step: 60000, // 1 min
|
||||||
|
},
|
||||||
|
"Delete": () => {
|
||||||
|
E.showPrompt(`Delete "${tally.name}"?`, {
|
||||||
|
title: "Delete",
|
||||||
|
buttons: { Yes: true, No: false },
|
||||||
|
}).then(confirm => {
|
||||||
|
if (confirm) {
|
||||||
|
tallies.splice(i, 1);
|
||||||
|
saveTallies(tallies);
|
||||||
|
showTallies(tallies);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// need to regrab ui, can't `m.draw()`
|
||||||
|
editTally(tallies, i);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
E.showMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
function tfmt(tally: Tally) {
|
||||||
|
const d = tally.date;
|
||||||
|
return `${d.getHours()}:${pad2(d.getMinutes())}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pad2 = (s: number) => ("0" + s.toFixed(0)).slice(-2);
|
||||||
|
|
||||||
|
showTallies(readTallies());
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
(function () {
|
||||||
|
var storage = require("Storage");
|
||||||
|
var tallyEntries = storage.readJSON("tallycfg.json", 1) || [];
|
||||||
|
var img = atob("GBiBAAAAAAAAAAAAAB//+D///DAADDAADDAYDDAYDDAZjDAZjDGZjDGZjDGZjDGZjDAADDAADD///B//+APAAAMAAAIAAAAAAAAAAA==");
|
||||||
|
return {
|
||||||
|
name: "Tally",
|
||||||
|
img: img,
|
||||||
|
items: tallyEntries.map(function (ent) { return ({
|
||||||
|
name: ent.name,
|
||||||
|
img: img,
|
||||||
|
get: function () {
|
||||||
|
return { text: this.name, img: img };
|
||||||
|
},
|
||||||
|
run: function () {
|
||||||
|
var f = storage.open("tallies.csv", "a");
|
||||||
|
f.write([
|
||||||
|
new Date().toISOString(),
|
||||||
|
this.name,
|
||||||
|
].join(",") + "\n");
|
||||||
|
},
|
||||||
|
show: function () { },
|
||||||
|
hide: function () { },
|
||||||
|
}); }),
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
(function() {
|
||||||
|
const storage = require("Storage");
|
||||||
|
const tallyEntries = storage.readJSON("tallycfg.json", 1) as TallySettings || [];
|
||||||
|
|
||||||
|
// transparent
|
||||||
|
const img = atob("GBiBAAAAAAAAAAAAAB//+D///DAADDAADDAYDDAYDDAZjDAZjDGZjDGZjDGZjDGZjDAADDAADD///B//+APAAAMAAAIAAAAAAAAAAA==")
|
||||||
|
// non-transparent
|
||||||
|
//const img = atob("GBgBAAAAAAAAAAAAH//4P//8MAAMMAAMMBgMMBgMMBmMMBmMMZmMMZmMMZmMMZmMMAAMMAAMP//8H//4A4AAAwAAAgAAAAAAAAAA")
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: "Tally",
|
||||||
|
img,
|
||||||
|
items: tallyEntries.map(ent => ({
|
||||||
|
name: ent.name,
|
||||||
|
img,
|
||||||
|
get: function() {
|
||||||
|
return { text: this.name, img };
|
||||||
|
},
|
||||||
|
run: function() {
|
||||||
|
const f = storage.open("tallies.csv", "a");
|
||||||
|
f.write([
|
||||||
|
new Date().toISOString(),
|
||||||
|
this.name,
|
||||||
|
].join(",") + "\n");
|
||||||
|
},
|
||||||
|
show: function(){},
|
||||||
|
hide: function(){},
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
}) satisfies ClockInfoFunc
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 760 B |
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"id": "tally",
|
||||||
|
"name": "Tally Keeper",
|
||||||
|
"shortName": "Tally",
|
||||||
|
"version": "0.01",
|
||||||
|
"description": "Add to a tally from clock info",
|
||||||
|
"icon": "app.png",
|
||||||
|
"tags": "clkinfo",
|
||||||
|
"supports": ["BANGLEJS2"],
|
||||||
|
"readme": "README.md",
|
||||||
|
"storage": [
|
||||||
|
{ "name": "tally.settings.js", "url": "settings.js" },
|
||||||
|
{ "name": "tally.img", "url": "app-icon.js", "evaluate": true },
|
||||||
|
{ "name": "tally.clkinfo.js", "url": "clkinfo.js" },
|
||||||
|
{ "name": "tally.app.js", "url": "app.js" }
|
||||||
|
],
|
||||||
|
"data": [
|
||||||
|
{ "name": "tallycfg.json" },
|
||||||
|
{ "name": "tallies.csv" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
(function (back) {
|
||||||
|
var storage = require("Storage");
|
||||||
|
var SETTINGS_FILE = "tallycfg.json";
|
||||||
|
var tallycfg = storage.readJSON(SETTINGS_FILE, 1) || [];
|
||||||
|
function saveSettings() {
|
||||||
|
storage.writeJSON(SETTINGS_FILE, tallycfg);
|
||||||
|
}
|
||||||
|
function showMainMenu() {
|
||||||
|
var menu = {
|
||||||
|
"": { "title": "Tally Configs" },
|
||||||
|
"< Back": back,
|
||||||
|
"Add New": function () { return showEditMenu(); },
|
||||||
|
};
|
||||||
|
tallycfg.forEach(function (tally, index) {
|
||||||
|
menu[tally.name] = function () { return showEditMenu(tally, index); };
|
||||||
|
});
|
||||||
|
E.showMenu(menu);
|
||||||
|
}
|
||||||
|
function showEditMenu(tally, index) {
|
||||||
|
var isNew = tally == null;
|
||||||
|
if (tally == null) {
|
||||||
|
tally = { name: "" };
|
||||||
|
index = tallycfg.length;
|
||||||
|
tallycfg.push(tally);
|
||||||
|
}
|
||||||
|
var menu = {
|
||||||
|
"": { "title": isNew ? "New Tally" : "Edit Tally" },
|
||||||
|
"< Back": function () {
|
||||||
|
saveSettings();
|
||||||
|
showMainMenu();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
menu[tally.name || "<set name>"] = function () {
|
||||||
|
require("textinput")
|
||||||
|
.input({ text: tally.name })
|
||||||
|
.then(function (text) {
|
||||||
|
tally.name = text;
|
||||||
|
showEditMenu(tally, index);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
if (!isNew) {
|
||||||
|
menu["Delete"] = function () {
|
||||||
|
tallycfg.splice(index, 1);
|
||||||
|
saveSettings();
|
||||||
|
showMainMenu();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
E.showMenu(menu);
|
||||||
|
}
|
||||||
|
showMainMenu();
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
type TallySettings = TallySetting[];
|
||||||
|
type TallySetting = { name: string };
|
||||||
|
|
||||||
|
(function(back) {
|
||||||
|
const storage = require("Storage");
|
||||||
|
const SETTINGS_FILE = "tallycfg.json";
|
||||||
|
|
||||||
|
const tallycfg = storage.readJSON(SETTINGS_FILE, 1) as TallySettings || [];
|
||||||
|
|
||||||
|
function saveSettings() {
|
||||||
|
storage.writeJSON(SETTINGS_FILE, tallycfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showMainMenu() {
|
||||||
|
const menu: Menu = {
|
||||||
|
"": { "title": "Tally Configs" },
|
||||||
|
"< Back": back,
|
||||||
|
"Add New": () => showEditMenu(),
|
||||||
|
};
|
||||||
|
|
||||||
|
tallycfg.forEach((tally, index) => {
|
||||||
|
menu[tally.name] = () => showEditMenu(tally, index);
|
||||||
|
});
|
||||||
|
|
||||||
|
E.showMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showEditMenu(tally?: TallySetting, index?: number) {
|
||||||
|
const isNew = tally == null;
|
||||||
|
if (tally == null) {
|
||||||
|
tally = { name: "" };
|
||||||
|
index = tallycfg.length;
|
||||||
|
tallycfg.push(tally);
|
||||||
|
}
|
||||||
|
|
||||||
|
const menu: Menu = {
|
||||||
|
"": { "title": isNew ? "New Tally" : "Edit Tally" },
|
||||||
|
"< Back": () => {
|
||||||
|
saveSettings();
|
||||||
|
showMainMenu();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
menu[tally.name || "<set name>"] = () => {
|
||||||
|
require("textinput")
|
||||||
|
.input({ text: tally.name })
|
||||||
|
.then(text => {
|
||||||
|
tally.name = text;
|
||||||
|
|
||||||
|
showEditMenu(tally, index);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!isNew) {
|
||||||
|
menu["Delete"] = () => {
|
||||||
|
tallycfg.splice(index!, 1);
|
||||||
|
saveSettings();
|
||||||
|
showMainMenu();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
E.showMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
showMainMenu();
|
||||||
|
}) satisfies SettingsFunc;
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -8,3 +8,4 @@ declare function require(moduleName: "Layout"): typeof Layout.Layout;
|
||||||
declare function require(moduleName: "power_usage"): PowerUsageModule;
|
declare function require(moduleName: "power_usage"): PowerUsageModule;
|
||||||
declare function require(moduleName: "exstats"): typeof ExStats;
|
declare function require(moduleName: "exstats"): typeof ExStats;
|
||||||
declare function require(moduleName: "time_utils"): typeof TimeUtils;
|
declare function require(moduleName: "time_utils"): typeof TimeUtils;
|
||||||
|
declare function require(moduleName: "textinput"): typeof TextInput;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
declare module TextInput {
|
||||||
|
function input(options: { text: string }): Promise<string>;
|
||||||
|
}
|
||||||
2
webtools
2
webtools
|
|
@ -1 +1 @@
|
||||||
Subproject commit 4dc22df5fd9af2f8fc41a626cc7d8d5456b8e614
|
Subproject commit b03155d1835a9904c335b65dc22326cb606e7cdd
|
||||||
Loading…
Reference in New Issue