From 97696f7928f9820eff469260c6560ec6957ffd85 Mon Sep 17 00:00:00 2001 From: Joseph Moroney Date: Thu, 6 Jan 2022 17:29:22 +1000 Subject: [PATCH 1/9] sonicclk minor - add settings to control twist/lcd --- apps.json | 2 +- apps/sonicclk/Changelog | 3 +- apps/sonicclk/README.md | 9 +++++- apps/sonicclk/app.js | 71 +++++++++++++++++++++++++++++++++++++---- 4 files changed, 75 insertions(+), 10 deletions(-) diff --git a/apps.json b/apps.json index ebafa9c97..ffc76f746 100644 --- a/apps.json +++ b/apps.json @@ -5381,7 +5381,7 @@ { "id": "sonicclk", "name": "Sonic Clock", - "version": "1.01", + "version": "1.10", "description": "A classic sonic clock featuring run, stop and wait animations.", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}], diff --git a/apps/sonicclk/Changelog b/apps/sonicclk/Changelog index 7c83f6988..4f597b627 100644 --- a/apps/sonicclk/Changelog +++ b/apps/sonicclk/Changelog @@ -1,2 +1,3 @@ 1.00 Added sonic clock app -1.01 Fixed text alignment issue; Increased acceleration required to activate twist; \ No newline at end of file +1.01 Fixed text alignment issue; Increased acceleration required to activate twist; +1.10 Added settings menu to control twist threshold and LCD Activity \ No newline at end of file diff --git a/apps/sonicclk/README.md b/apps/sonicclk/README.md index a381e0a07..adfbf47b4 100644 --- a/apps/sonicclk/README.md +++ b/apps/sonicclk/README.md @@ -8,6 +8,13 @@ A classic sonic clock featuring run, stop and wait animations. - Sonic will run when the screen is unlocked - Sonic will stop when the screen is locked -- Sonic will wait when looking at your watch face (when `Bangle.on("twist", fn)` is fired). +- Sonic will wait when looking at your watch face (when `Bangle.on("twist", fn)` is fired). This option is configurable (see below). + +## Configuration + +To access the settings menu, you can **double tap** on the **right** side of the watch. The following options are configurable: + +- `Active Mode` - catering for 'active' behaviour where the `twist` method can be fired undesirably. When `on` this will prevent the LCD from turning on when a `twist` event is fired. +- `Twist Thresh` - customise the acceleration needed to activate the twist method (see the [`Bangle.setOptions`](https://www.espruino.com/Reference#:~:text=twisted%3F%20default%20%3D%20true-,twistThreshold,-How%20much%20acceleration) method for more info). ### Made with love by [Joseph](https://github.com/Johoseph) 🤗 diff --git a/apps/sonicclk/app.js b/apps/sonicclk/app.js index 296677281..c92818b01 100644 --- a/apps/sonicclk/app.js +++ b/apps/sonicclk/app.js @@ -109,10 +109,14 @@ let currentSonic = -1; let drawTimeout, drawInterval, waitTimeout; let bgScroll = [0, null]; -const start = () => { +const fullReset = () => { if (drawTimeout) clearTimeout(drawTimeout); if (waitTimeout) clearTimeout(waitTimeout); if (drawInterval) clearInterval(drawInterval); +} + +const start = () => { + fullReset(); drawInterval = setInterval(() => { draw("start"); @@ -252,22 +256,75 @@ const draw = (action) => { if (action === "reset") queueDraw(); }; +// Settings +const settings = require("Storage").readJSON("sonicclk-settings") || { + activeMode: false, + twistThreshold: 1600, +}; +let isSettings = false; + +const settingsMenu = { + "": { "title": "Settings" }, + "Active Mode": { + value: settings.activeMode, + format: v => v ? "On" : "Off", + onchange: v => settings.activeMode = v, + }, + "Twist Thresh" : { + value: settings.twistThreshold, + min: 800, max: 4000, step: 200, + onchange: v => settings.twistThreshold = v, + }, + "Exit" : () => { + isSettings = false; + + require("Storage").writeJSON("sonicclk-settings", settings); + Bangle.setOptions({ + lockTimeout: 10000, + backlightTimeout: 12000, + twistThreshold: settings.twistThreshold, + }); + + E.showMenu(); + draw("reset"); + start(); + } +}; + g.setTheme({ bg: "#0099ff", fg: "#fff", dark: true }).clear(); Bangle.on("lock", (locked) => { - if (locked) { - stop(); - } else { - start(); + if (!isSettings) { + if (locked) { + stop(); + } else { + start(); + } } }); -Bangle.on("twist", () => wait()); +Bangle.on("twist", () => { + if (settings.activeMode) { + fullReset(); + draw("reset"); + } else { + wait(); + } +}); + +Bangle.on("tap", (d) => { + if (d.double && d.dir === "right") { + fullReset(); + isSettings = true; + Bangle.setLocked(false); + E.showMenu(settingsMenu); + } +}); Bangle.setOptions({ lockTimeout: 10000, backlightTimeout: 12000, - twistThreshold: 1600, + twistThreshold: settings.twistThreshold, }); Bangle.setUI("clock"); From d9cd94226e84a07e4cd4219dbd6f40b07195f798 Mon Sep 17 00:00:00 2001 From: Joseph Moroney Date: Thu, 6 Jan 2022 17:38:41 +1000 Subject: [PATCH 2/9] Missing semi-colon --- apps/sonicclk/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sonicclk/app.js b/apps/sonicclk/app.js index c92818b01..b12af48fd 100644 --- a/apps/sonicclk/app.js +++ b/apps/sonicclk/app.js @@ -113,7 +113,7 @@ const fullReset = () => { if (drawTimeout) clearTimeout(drawTimeout); if (waitTimeout) clearTimeout(waitTimeout); if (drawInterval) clearInterval(drawInterval); -} +}; const start = () => { fullReset(); From b930a8d2afbbff8f549e68291e7015d3b09280ab Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 27 Jan 2022 21:38:57 +0100 Subject: [PATCH 3/9] Update ChangeLog --- apps/vectorclock/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/vectorclock/ChangeLog b/apps/vectorclock/ChangeLog index 6ba096f88..f1fd5b134 100644 --- a/apps/vectorclock/ChangeLog +++ b/apps/vectorclock/ChangeLog @@ -2,3 +2,4 @@ 0.02: Use Bangle.setUI for button/launcher handling 0.03: Bangle.js 2 support 0.04: Adds costumizable colours and the respective settings menu +0.05: "Chime the time" (buzz or beep) with up/down swipe added From 22c30219a138863484486ca7c0a90f89f59245fc Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 27 Jan 2022 21:51:06 +0100 Subject: [PATCH 4/9] Update metadata.json --- apps/vectorclock/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/vectorclock/metadata.json b/apps/vectorclock/metadata.json index 3da93ccad..63d2ca678 100644 --- a/apps/vectorclock/metadata.json +++ b/apps/vectorclock/metadata.json @@ -1,7 +1,7 @@ { "id": "vectorclock", "name": "Vector Clock", - "version": "0.04", + "version": "0.05", "description": "A digital clock that uses the built-in vector font.", "icon": "app.png", "type": "clock", From 6718b4317f65c5c28468b978e62819f46efe45bb Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 27 Jan 2022 21:55:01 +0100 Subject: [PATCH 5/9] Update settings.js --- apps/vectorclock/settings.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/apps/vectorclock/settings.js b/apps/vectorclock/settings.js index a6f4dd807..86cbad1e5 100644 --- a/apps/vectorclock/settings.js +++ b/apps/vectorclock/settings.js @@ -10,10 +10,10 @@ var colnames = ["white", "yellow", "green", "cyan", "red", "orange", "magenta", "black"]; var colvalues = [0xFFFF, 0xFFE0, 0x07E0, 0x07FF, 0xF800, 0xFD20, 0xF81F, 0x0000]; + var chimenames = ["off", "buzz", "beep"]; // Show the menu E.showMenu({ - "" : { "title" : "VectorClock colours" }, - "< Back" : () => back(), + "" : { "title" : "VectorClock settings" }, 'Time': { value: Math.max(0 | colvalues.indexOf(settings.timecol),0), min: 0, max: colvalues.length-1, @@ -41,5 +41,15 @@ writeSettings(); } }, + 'Chimetype': { + value: Math.max(0 | chimenames.indexOf(settings.chimetype),0), + min: 0, max: chimenames.length-1, + format: v => chimenames[v], + onchange: v => { + settings.chimetype = chimenames[v]; + writeSettings(); + } + }, + "< Back" : () => back(), }); }) From 38ea17592a5d3ee4d761e61877156631c408fbcb Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 27 Jan 2022 21:58:24 +0100 Subject: [PATCH 6/9] Update app.js --- apps/vectorclock/app.js | 73 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 9 deletions(-) diff --git a/apps/vectorclock/app.js b/apps/vectorclock/app.js index e2e4c1e64..e99a13ed1 100644 --- a/apps/vectorclock/app.js +++ b/apps/vectorclock/app.js @@ -4,7 +4,7 @@ var settings = require('Storage').readJSON("vectorclock.json", true) || {}; var dowcol = settings.dowcol || g.theme.fg; var timecol = settings.timecol || g.theme.fg; var datecol = settings.datecol || g.theme.fg; - +var chimetype = settings.chimetype; function padNum(n, l) { return ("0".repeat(l)+n).substr(-l); @@ -44,7 +44,7 @@ function drawVectorText(text, size, x, y, alignX, alignY, color) { function draw() { g.reset(); - + let d = new Date(); let hours = is12Hour ? ((d.getHours() + 11) % 12) + 1 : d.getHours(); let timeText = `${hours}:${padNum(d.getMinutes(), 2)}`; @@ -58,27 +58,27 @@ function draw() { let timeFontSize = width / ((g.stringWidth(timeText) / 256) + (Math.max(g.stringWidth(meridian), g.stringWidth(secondsText)) / 512 * 9 / 10)); let dowFontSize = width / (g.stringWidth(dowText) / 256); let dateFontSize = width / (g.stringWidth(dateText) / 256); - + let timeHeight = g.setFont("Vector", timeFontSize).getFontHeight() * 9 / 10; let dowHeight = g.setFont("Vector", dowFontSize).getFontHeight(); let dateHeight = g.setFont("Vector", dateFontSize).getFontHeight(); - + let remainingHeight = g.getHeight() - 24 - timeHeight - dowHeight - dateHeight; let spacer = remainingHeight / 4; - + let x = 2; let y = 24 + spacer; - + pushCommand(drawVectorText, timeText, timeFontSize, x, y, -1, -1, timecol); pushCommand(drawVectorText, meridian, timeFontSize*9/20, x + width, y, 1, -1, timecol); if (showSeconds) pushCommand(drawVectorText, secondsText, timeFontSize*9/20, x + width, y + timeHeight, 1, 1, timecol); y += timeHeight + spacer; - + pushCommand(drawVectorText, dowText, dowFontSize, x + width/2, y, 0, -1, dowcol); y += dowHeight + spacer; - + pushCommand(drawVectorText, dateText, dateFontSize, x + width/2, y, 0, -1, datecol); - + executeCommands(); } @@ -90,6 +90,57 @@ function tick() { timeout = setTimeout(tick, period - getTime() * 1000 % period); } +// ====================================== Vibration (taken from "Vibrate Clock") +// vibrate 0..9 +function vibrateDigitBuzz(num) { + if (num==0) return Bangle.buzz(500); + return new Promise(function f(resolve){ + if (num--<=0) return resolve(); + Bangle.buzz(100).then(()=>{ + setTimeout(()=>f(resolve), 200); + }); + }); +} +function vibrateDigitBeep(num) { + if (num==0) return Bangle.beep(500); + return new Promise(function f(resolve){ + if (num--<=0) return resolve(); + Bangle.beep(100).then(()=>{ + setTimeout(()=>f(resolve), 200); + }); + }); +} +// vibrate multiple digits (num must be a string) +function vibrateNumber(num) { + return new Promise(function f(resolve){ + if (!num.length) return resolve(); + var digit = num[0]; + num = num.substr(1); + if ("buzz"==chimetype) + vibrateDigitBuzz(digit).then(()=>{ + setTimeout(()=>f(resolve),500);}); + if ("beep"==chimetype) + vibrateDigitBeep(digit).then(()=>{ + setTimeout(()=>f(resolve),500);}); + }); +} +var vibrateBusy; +function vibrateTime() { + if (vibrateBusy) return; + vibrateBusy = true; + var d = new Date(); + var hours = d.getHours(), minutes = d.getMinutes(); + if (is12Hour) { + if (hours == 0) hours = 12; + else if (hours>12) hours -= 12; + } + vibrateNumber(hours.toString()). + then(() => new Promise(resolve=>setTimeout(resolve,500))). + then(() => vibrateNumber(minutes.toString())). + then(() => vibrateBusy=false); +} + + Bangle.on('lcdPower', function(on) { if (timeout) clearTimeout(timeout); timeout = null; @@ -103,6 +154,10 @@ Bangle.on('lock', function(locked) { tick(); }); +if ("buzz"==chimetype || "beep"==chimetype) + Bangle.on("swipe",function(direction){ + if (0==direction) vibrateTime();}); // 0 = swipe up/down + g.clear(); tick(); Bangle.loadWidgets(); From ddbaf97b7dd0510a9aa5fdcac1cbeea6b5968064 Mon Sep 17 00:00:00 2001 From: Joseph Moroney Date: Sat, 29 Jan 2022 08:37:46 +1000 Subject: [PATCH 7/9] patch - call `Bangle.setUI` when exiting settings --- apps/sonicclk/Changelog | 7 ++++--- apps/sonicclk/README.md | 2 +- apps/sonicclk/app.js | 21 ++++++++++++--------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/apps/sonicclk/Changelog b/apps/sonicclk/Changelog index 4f597b627..050e18b5a 100644 --- a/apps/sonicclk/Changelog +++ b/apps/sonicclk/Changelog @@ -1,3 +1,4 @@ -1.00 Added sonic clock app -1.01 Fixed text alignment issue; Increased acceleration required to activate twist; -1.10 Added settings menu to control twist threshold and LCD Activity \ No newline at end of file +1.00 [MAJOR] Added sonic clock app +1.01 [PATCH] Fixed text alignment issue; Increased acceleration required to activate twist; +1.10 [MINOR] Added settings menu to control twist threshold and LCD Activity +1.11 [PATCH] Call `Bangle.setUI` when exiting settings menu, settings tap moved to top \ No newline at end of file diff --git a/apps/sonicclk/README.md b/apps/sonicclk/README.md index adfbf47b4..54de16115 100644 --- a/apps/sonicclk/README.md +++ b/apps/sonicclk/README.md @@ -12,7 +12,7 @@ A classic sonic clock featuring run, stop and wait animations. ## Configuration -To access the settings menu, you can **double tap** on the **right** side of the watch. The following options are configurable: +To access the settings menu, you can **double tap** on the **top** side of the watch. The following options are configurable: - `Active Mode` - catering for 'active' behaviour where the `twist` method can be fired undesirably. When `on` this will prevent the LCD from turning on when a `twist` event is fired. - `Twist Thresh` - customise the acceleration needed to activate the twist method (see the [`Bangle.setOptions`](https://www.espruino.com/Reference#:~:text=twisted%3F%20default%20%3D%20true-,twistThreshold,-How%20much%20acceleration) method for more info). diff --git a/apps/sonicclk/app.js b/apps/sonicclk/app.js index b12af48fd..1fae353ca 100644 --- a/apps/sonicclk/app.js +++ b/apps/sonicclk/app.js @@ -264,18 +264,20 @@ const settings = require("Storage").readJSON("sonicclk-settings") || { let isSettings = false; const settingsMenu = { - "": { "title": "Settings" }, + "": { title: "Settings" }, "Active Mode": { value: settings.activeMode, - format: v => v ? "On" : "Off", - onchange: v => settings.activeMode = v, + format: (v) => (v ? "On" : "Off"), + onchange: (v) => (settings.activeMode = v), }, - "Twist Thresh" : { + "Twist Thresh": { value: settings.twistThreshold, - min: 800, max: 4000, step: 200, - onchange: v => settings.twistThreshold = v, + min: 800, + max: 4000, + step: 200, + onchange: (v) => (settings.twistThreshold = v), }, - "Exit" : () => { + Exit: () => { isSettings = false; require("Storage").writeJSON("sonicclk-settings", settings); @@ -286,9 +288,10 @@ const settingsMenu = { }); E.showMenu(); + Bangle.setUI("clock"); draw("reset"); start(); - } + }, }; g.setTheme({ bg: "#0099ff", fg: "#fff", dark: true }).clear(); @@ -313,7 +316,7 @@ Bangle.on("twist", () => { }); Bangle.on("tap", (d) => { - if (d.double && d.dir === "right") { + if (d.double && d.dir === "top") { fullReset(); isSettings = true; Bangle.setLocked(false); From 651f3a5f8fbaa645bdbc32fd3d030a74e375909c Mon Sep 17 00:00:00 2001 From: Joseph Moroney Date: Sat, 29 Jan 2022 08:39:05 +1000 Subject: [PATCH 8/9] Increment sonicclk version --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index ffc76f746..8551481aa 100644 --- a/apps.json +++ b/apps.json @@ -5381,7 +5381,7 @@ { "id": "sonicclk", "name": "Sonic Clock", - "version": "1.10", + "version": "1.11", "description": "A classic sonic clock featuring run, stop and wait animations.", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}], From 55e4866efdf71760e49658f08e9fac1c534ef200 Mon Sep 17 00:00:00 2001 From: Joseph Moroney Date: Sat, 29 Jan 2022 11:05:26 +1000 Subject: [PATCH 9/9] patch - 2v11 changes + `fullReset` update --- apps/sonicclk/Changelog | 1 + apps/sonicclk/app.js | 5 ++++- apps/sonicclk/metadata.json | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/sonicclk/Changelog b/apps/sonicclk/Changelog index d0b0db581..d78fe291f 100644 --- a/apps/sonicclk/Changelog +++ b/apps/sonicclk/Changelog @@ -2,3 +2,4 @@ 0.02 [PATCH] Fixed text alignment issue; Increased acceleration required to activate twist; 0.03 [MINOR] Added settings menu to control twist threshold and LCD Activity 0.04 [PATCH] Call `Bangle.setUI` when exiting settings menu, settings tap moved to top +0.05 [PATCH] Firmware 2v11 - use `wakeOnTwist` rather than manual `setLCDPower`; Reset sonic on `fullReset` diff --git a/apps/sonicclk/app.js b/apps/sonicclk/app.js index 1fae353ca..eddb971f8 100644 --- a/apps/sonicclk/app.js +++ b/apps/sonicclk/app.js @@ -113,6 +113,8 @@ const fullReset = () => { if (drawTimeout) clearTimeout(drawTimeout); if (waitTimeout) clearTimeout(waitTimeout); if (drawInterval) clearInterval(drawInterval); + currentSonic = -1; + currentSpeed = 0; }; const start = () => { @@ -148,7 +150,6 @@ const wait = () => { currentSpeed = 0; if (drawTimeout) clearTimeout(drawTimeout); if (drawInterval) clearInterval(drawInterval); - Bangle.setLCDPower(1); drawInterval = setInterval(() => draw("wait"), timeout); @@ -285,6 +286,7 @@ const settingsMenu = { lockTimeout: 10000, backlightTimeout: 12000, twistThreshold: settings.twistThreshold, + wakeOnTwist: !settings.activeMode, }); E.showMenu(); @@ -328,6 +330,7 @@ Bangle.setOptions({ lockTimeout: 10000, backlightTimeout: 12000, twistThreshold: settings.twistThreshold, + wakeOnTwist: !settings.activeMode, }); Bangle.setUI("clock"); diff --git a/apps/sonicclk/metadata.json b/apps/sonicclk/metadata.json index 569518d84..5a2d64db1 100644 --- a/apps/sonicclk/metadata.json +++ b/apps/sonicclk/metadata.json @@ -1,7 +1,7 @@ { "id": "sonicclk", "name": "Sonic Clock", - "version": "0.04", + "version": "0.05", "description": "A classic sonic clock featuring run, stop and wait animations.", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}],