Merge pull request #3862 from voloved/counter2

Added ability to display only one counter and fast-scrolling
master
Rob Pilling 2025-06-03 21:59:48 +01:00 committed by GitHub
commit d07eb4b477
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 158 additions and 57 deletions

View File

@ -3,3 +3,4 @@
0.03: Fix lint warnings 0.03: Fix lint warnings
0.04: Fix lint warnings 0.04: Fix lint warnings
0.05: Fix on not reading counter defaults in Settings 0.05: Fix on not reading counter defaults in Settings
0.06: Added ability to display only one counter and fast-scrolling

View File

@ -11,10 +11,13 @@ The counter state gets saved. Best to use this with pattern launcher or ClockCal
## Howto ## Howto
- Tap top side or swipe up to increase counter - Tap top side or swipe up to increase counter
- Tap bottom side or swipe down to decrease counter - Tap bottom side or swipe down to decrease counter
- Hold (600ms) to reset to default value (configurable) - Hold either side to quickly increase or decrease the counter.
- Press button to exit - If the counters are not on their presets, then press the button to reset them
- If the counters are on their presets, then press the button to leave the screen
- Long press the button to leave the screen regardless of the counter values
## Configurable Features ## Configurable Features
- Display both Counters or only Counter 1
- Default value Counter 1 - Default value Counter 1
- Default value Counter 2 - Default value Counter 2
- Buzz on interact - Buzz on interact

View File

@ -1,20 +1,25 @@
Bangle.loadWidgets();
var s = Object.assign({ var s = Object.assign({
display2:true,
counter0:10, counter0:10,
counter1:20, counter1:20,
max0:15, max0:15,
max1:25, max1:25,
fullscreen:true,
buzz: true, buzz: true,
colortext: true, colortext: true,
}, require('Storage').readJSON("counter2.json", true) || {}); }, require('Storage').readJSON("counter2.json", true) || {});
var sGlob = Object.assign({
timeout: 10,
}, require('Storage').readJSON("setting.json", true) || {});
const f1 = (s.colortext) ? "#f00" : "#fff"; const f1 = (s.colortext) ? "#f00" : "#fff";
const f2 = (s.colortext) ? "#00f" : "#fff"; const f2 = (s.colortext) ? "#00f" : "#fff";
const b1 = (s.colortext) ? g.theme.bg : "#f00"; const b1 = (s.colortext) ? g.theme.bg : "#f00";
const b2 = (s.colortext) ? g.theme.bg : "#00f"; const b2 = (s.colortext) ? g.theme.bg : "#00f";
var drag; var drag;
var dragCurr = {x:0 ,y:0 ,dx:0 ,dy:0 ,b:false};
const screenwidth = g.getWidth(); const screenwidth = g.getWidth();
const screenheight = g.getHeight(); const screenheight = g.getHeight();
@ -37,51 +42,111 @@ function saveSettings() {
} }
let ignoreonce = false; let ignoreonce = false;
let fastupdateoccurring = false;
var dragtimeout; var dragtimeout;
function updateScreen() { function updateScreen() {
g.setBgColor(b1); if (s.display2) {
g.clearRect(0, 0, halfwidth, screenheight); g.setBgColor(b1);
g.setBgColor(b2); g.clearRect(0, 0, halfwidth, screenheight);
g.clearRect(halfwidth, 0, screenwidth, screenheight); g.setBgColor(b2);
g.setFont("Vector", 60).setFontAlign(0, 0); g.clearRect(halfwidth, 0, screenwidth, screenheight);
g.setColor(f1); g.setFont("Vector", 60).setFontAlign(0, 0);
g.drawString(Math.floor(counter[0]), halfwidth * 0.5, halfheight); g.setColor(f1);
g.setColor(f2); g.drawString(Math.floor(counter[0]), halfwidth * 0.5, halfheight);
g.drawString(Math.floor(counter[1]), halfwidth * 1.5, halfheight); g.setColor(f2);
g.drawString(Math.floor(counter[1]), halfwidth * 1.5, halfheight);
}
else {
g.setBgColor(b2); // Using right counter's colors b/c blue looks nicer than red
g.clearRect(0, 0, screenwidth, screenheight);
g.setFont("Vector", 90).setFontAlign(0, 0);
g.setColor(f2);
g.drawString(Math.floor(counter[0]), halfwidth, halfheight);
}
saveSettings(); saveSettings();
if (s.buzz) Bangle.buzz(50,.5); if (s.buzz) Bangle.buzz(50,.5);
Bangle.drawWidgets();
Bangle.loadWidgets();
if (s.fullscreen) {
require("widget_utils").hide();
}
else {
Bangle.drawWidgets();
}
} }
// Clearing the timer on lock is likely uneeded, but just in case
Bangle.on('lock', e => {
drag = undefined;
var timeOutTimer = sGlob.timeout * 1000;
Bangle.setOptions({backlightTimeout: timeOutTimer, lockTimeout: timeOutTimer});
if (dragtimeout) clearTimeout(dragtimeout);
fastupdateoccurring = false;
});
Bangle.on("drag", e => { Bangle.on("drag", e => {
const c = (e.x < halfwidth) ? 0 : 1; const c = (e.x >= halfwidth && s.display2) ? 1 : 0;
dragCurr = e;
if (!drag) { if (!drag) {
if (ignoreonce) { if (ignoreonce) {
ignoreonce = false; ignoreonce = false;
return; return;
} }
drag = { x: e.x, y: e.y }; drag = { x: e.x, y: e.y };
dragtimeout = setTimeout(function () { resetcounter(c); }, 600); //if dragging for 500ms, reset counter dragtimeout = setTimeout(function () { fastupdatecounter(c); }, 600); //if dragging for 500ms, reset counter
} }
else if (drag && !e.b) { // released else if (drag && !e.b) { // released
let adjust = 0; if (!fastupdateoccurring)
const dx = e.x - drag.x, dy = e.y - drag.y; updatecounter(c);
if (Math.abs(dy) > Math.abs(dx) + 30) { drag = undefined;
adjust = (dy > 0) ? -1 : 1; if (dragtimeout) {
} else { let timeOutTimer = 1000;
adjust = (e.y > halfwidth) ? -1 : 1; Bangle.setOptions({backlightTimeout: timeOutTimer, lockTimeout: timeOutTimer});
}
counter[c] += adjust;
updateScreen();
drag = undefined;
clearTimeout(dragtimeout); clearTimeout(dragtimeout);
} }
fastupdateoccurring = false;
}
}); });
function updatecounter(which) {
let adjust = 0;
const dx = dragCurr.x - drag.x, dy = dragCurr.y - drag.y;
if (Math.abs(dy) > Math.abs(dx) + 30) {
adjust = (dy > 0) ? -1 : 1;
} else {
adjust = (dragCurr.y > halfheight) ? -1 : 1;
}
counter[which] += adjust;
updateScreen();
}
function fastupdatecounter(which) {
fastupdateoccurring = true;
updatecounter(which);
Bangle.setOptions({backlightTimeout: 0, lockTimeout: 0});
dragtimeout = setTimeout(function () { fastupdatecounter(which); }, 10);
}
function resetcounter(which) { function resetcounter(which) {
counter[which] = defaults[which]; // If which is null, reset all
console.log("resetting counter ", which); fastupdateoccurring = false;
if (dragtimeout) {
let timeOutTimer = 1000;
Bangle.setOptions({backlightTimeout: timeOutTimer, lockTimeout: timeOutTimer});
clearTimeout(dragtimeout);
}
if (which == null) {
for (let iter = 0; iter < defaults.length; iter++) {
counter[iter] = defaults[iter];
}
console.log("resetting all counters");
}
else {
counter[which] = defaults[which];
console.log("resetting counter ", which);
}
updateScreen(); updateScreen();
drag = undefined; drag = undefined;
ignoreonce = true; ignoreonce = true;
@ -91,5 +156,13 @@ function resetcounter(which) {
updateScreen(); updateScreen();
setWatch(function() { setWatch(function() {
for (let which = 0; which < defaults.length; which++) {
if(counter[which] != defaults[which]) {
resetcounter(null);
return;
}
}
var timeOutTimer = sGlob.timeout * 1000;
Bangle.setOptions({backlightTimeout: timeOutTimer, lockTimeout: timeOutTimer});
load(); load();
}, BTN1, {repeat:true, edge:"falling"}); }, BTN1, {repeat:true, edge:"falling"});

View File

@ -1,7 +1,7 @@
{ {
"id": "counter2", "id": "counter2",
"name": "Counter2", "name": "Counter2",
"version": "0.05", "version": "0.06",
"description": "Dual Counter", "description": "Dual Counter",
"readme":"README.md", "readme":"README.md",
"icon": "counter2-icon.png", "icon": "counter2-icon.png",

View File

@ -1,10 +1,12 @@
(function (back) { (function (back) {
var FILE = "counter2.json"; var FILE = "counter2.json";
const defaults={ const defaults={
display2:true,
counter0:12, counter0:12,
counter1:0, counter1:0,
max0:12, max0:12,
max1:0, max1:0,
fullscreen: true,
buzz: true, buzz: true,
colortext: true, colortext: true,
}; };
@ -14,26 +16,40 @@
require('Storage').writeJSON(FILE, settings); require('Storage').writeJSON(FILE, settings);
} }
const menu = { function showMainMenu() {
"": { "title": "Counter2" }, let appMenu = {
"< Back": () => back(), "": { "title": "Counter2" },
'Default C1': { "< Back": () => back(),
value: settings.max0, 'Counters to Display ': {
min: -99, max: 99, value: settings.display2,
onchange: v => { format: v => v?"2":"1",
settings.max0 = v; onchange: v => {
writeSettings(); settings.display2 = v;
} writeSettings();
}, // redisplay the menu with/without C2 setting
'Default C2': { setTimeout(showMainMenu, 0);
value: settings.max1, }
min: -99, max: 99, },
onchange: v => { 'Default C1': {
settings.max1 = v; value: settings.max0,
writeSettings(); min: -99, max: 99,
} onchange: v => {
}, settings.max0 = v;
'Color': { writeSettings();
}
},
};
if (settings.display2) {
appMenu['Default C2'] = {
value: settings.max1,
min: -99, max: 99,
onchange: v => {
settings.max1 = v;
writeSettings();
}
};
}
appMenu['Color'] = {
value: settings.colortext, value: settings.colortext,
format: v => v?"Text":"Backg", format: v => v?"Text":"Backg",
onchange: v => { onchange: v => {
@ -41,15 +57,23 @@
console.log("Color",v); console.log("Color",v);
writeSettings(); writeSettings();
} }
}, };
'Vibrate': { appMenu['Fullscreen'] = {
value: settings.fullscreen,
onchange: v => {
settings.fullscreen = v;
writeSettings();
}
};
appMenu['Vibrate'] = {
value: settings.buzz, value: settings.buzz,
onchange: v => { onchange: v => {
settings.buzz = v; settings.buzz = v;
writeSettings(); writeSettings();
} },
} };
}; E.showMenu(appMenu);
// Show the menu }
E.showMenu(menu);
}) showMainMenu();
})