From 884691d10c320c9a15163646cd9fa7521e73b861 Mon Sep 17 00:00:00 2001 From: "Zachary D. Skelton" Date: Fri, 23 Feb 2024 11:27:09 -0600 Subject: [PATCH 01/57] Add: Fallout Clock --- apps/fallout_clock/CHANGELOG | 6 + apps/fallout_clock/LICENSE | 21 ++++ apps/fallout_clock/README.md | 29 +++++ apps/fallout_clock/app-icon.js | 1 + apps/fallout_clock/clock.js | 141 +++++++++++++++++++++++ apps/fallout_clock/icon.png | Bin 0 -> 7978 bytes apps/fallout_clock/metadate.json | 18 +++ apps/fallout_clock/res/fallout_icon.png | Bin 0 -> 7978 bytes apps/fallout_clock/res/good times rg.otf | Bin 0 -> 22476 bytes apps/fallout_clock/res/screenshot.png | Bin 0 -> 2243 bytes 10 files changed, 216 insertions(+) create mode 100644 apps/fallout_clock/CHANGELOG create mode 100644 apps/fallout_clock/LICENSE create mode 100644 apps/fallout_clock/README.md create mode 100644 apps/fallout_clock/app-icon.js create mode 100644 apps/fallout_clock/clock.js create mode 100644 apps/fallout_clock/icon.png create mode 100644 apps/fallout_clock/metadate.json create mode 100644 apps/fallout_clock/res/fallout_icon.png create mode 100644 apps/fallout_clock/res/good times rg.otf create mode 100644 apps/fallout_clock/res/screenshot.png diff --git a/apps/fallout_clock/CHANGELOG b/apps/fallout_clock/CHANGELOG new file mode 100644 index 000000000..ef31b4803 --- /dev/null +++ b/apps/fallout_clock/CHANGELOG @@ -0,0 +1,6 @@ +Version 0: +0.1.0 - (20240125): Basic Working Clock. +0.1.1 - (20240125): Widgets Added. Improved Interval Loop. +0.1.2 - (20240221): Fix: Month Reporting Wrong. +0.2.0 - (20240223): Created as a Package. +0.2.1 = (20240223): Added StandardJS and NPM. diff --git a/apps/fallout_clock/LICENSE b/apps/fallout_clock/LICENSE new file mode 100644 index 000000000..d9d472761 --- /dev/null +++ b/apps/fallout_clock/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Zachary D. Skelton + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/apps/fallout_clock/README.md b/apps/fallout_clock/README.md new file mode 100644 index 000000000..d535cc050 --- /dev/null +++ b/apps/fallout_clock/README.md @@ -0,0 +1,29 @@ +# Fallout Clock + +Inspired by the aesthetic of the Fallout series, this clock face looks to emulate the color and feel of a PipBoy. + +Add screen shots (if possible) to the app folder and link then into this file with ![clockface](./res/screenshot.png) + +## Usage + +You can also go into Settings, and choose it as the default clock under **Select Clock**. + +## Planned Features: +- Display Steps as Health +- Display Heartrate +- Brighter Color when the backlight is not on. +- Configurable Settings + +## Controls + +Zero Settings, Zero Configuration. Install and add as your clockface. + +## Requests + +To request new features, add [an issue](https://github.com/zskelton/fallout_clock/issues). + +## Creator + +Zachary D. Skelton \ +[Skelton Networks](https://skeltonnetworks.com)\ +[Github](https://github.com/zskelton) \ No newline at end of file diff --git a/apps/fallout_clock/app-icon.js b/apps/fallout_clock/app-icon.js new file mode 100644 index 000000000..9e38e51a8 --- /dev/null +++ b/apps/fallout_clock/app-icon.js @@ -0,0 +1 @@ +require('heatshrink').decompress(atob('mEw4cB388///t3/rX/6/2jOuCIOK70kyVJAQeQgEVkQIEAQ4uCiIGBCJVACIWJAwNUCJAyBAAMEDAcCCI5jDlQJC0EAhIRFkAQCgNSBIQGCKxEAhWSr+kyoHCCIlICIcEy//+hOENA8AomXr//9AIDCIYHDgX/+9L//4BIcSPQkBwED0mSCIP/DYgREh/AjoqBCIXgCIuAAoMO3/pCIIQBLYIkDCIhgBpf+y/bCQQLCUgQECh2Sr27tp+BGwoRG+u27duv/+7/wCIbCDt//1oRCIAO7/jPDCId19gRCuQRBzf+CI0C+vlCIWa5Mkz//siyBlIRCit/jdtEYXJkpaB6VJkqBDhN67YRCtojBCIjmDpN482N5Hb1ojB34RClQQCglJu3uxvW7fREYO3/hGBqARCkVJq3lt3W7gRC+wRBpRtDqVLEANyI4ON3Mly3uCILIChTUB43bvU2LIO5km2CINUEYVUCIhrCEYOT+mS0ARCkgRDuYjECIRXDCIRHBR4PdI4IJB+mVCIQcC23Xtlt28tNYQRB1DpGs+jy3a7e1CIOT+r7HtNtE4PtyoRBy8oCIckAgUK7ZqBrbXBk3dYQYREhihBLgNupM/YQkJCIcBrYREvTCDCIS2CgErI4ImBp/SpARDpMkyD+DCId96TCDCI0A1oRByXMYQkCCIK4DgEW23kyV+ygJDiQRCoAHCgdrtjUBFomSCIRPDgft9v/0jCCCItJA4UVl//pMlFgcECIjICiIGCYQoREUgSWBDAgHEAQZSB1IGCYQYOEAQcAxIDBpS8CPQYCGAYQiCKwoCG0iWCBYw')) diff --git a/apps/fallout_clock/clock.js b/apps/fallout_clock/clock.js new file mode 100644 index 000000000..56bb68a3a --- /dev/null +++ b/apps/fallout_clock/clock.js @@ -0,0 +1,141 @@ +/* global Bangle, Graphics, g */ + +// NAME: Fallout Clock (Bangle.js 2) +// DOCS: https://www.espruino.com/ReferenceBANGLEJS2 +// AUTHOR: Zachary D. Skelton +// VERSION: 0.1.0 (24JAN2024) - Creating [ Maj.Min.Bug ] REF: https://semver.org/ +// LICENSE: MIT License (2024) [ https://opensource.org/licenses/MIT ] + +/* THEME COLORS */ +// Dark Full - #000000 - (0,0.00,0) +// Dark Half - #002f00 - (0,0.18,0) +// Dark Zero - #005f00 - (0,0.37,0) +// Light Zero - #008e00 - (0,0.55,0) +// Light Half - #00bf00 - (0,0.75,0) +// Light Full - #00ee00 - (0,0.93,0) + +/* FONTS */ +// Font: Good Time Rg - https://www.dafont.com/good-times.font +// Large = 50px +Graphics.prototype.setLargeFont = function () { + this.setFontCustom( + atob('AAAAAAAAAAAAAAAAAAAAAABAAAAAAAB8AAAAAAA/gAAAAAAP4AAAAAAD+AAAAAAA/gAAAAAAP4AAAAAAB8AAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAADwAAAAAAD8AAAAAAD/AAAAAAD/wAAAAAD/8AAAAAH/8AAAAAH/8AAAAAH/4AAAAAH/4AAAAAH/4AAAAAH/4AAAAAP/4AAAAAP/wAAAAAP/wAAAAAP/wAAAAAP/wAAAAAH/wAAAAAB/wAAAAAAfgAAAAAAHgAAAAAABgAAAAAAAAAAAAAAAAAAOAAAAAAB//AAAAAB//8AAAAB///wAAAA////AAAAf///4AAAP////AAAH////4AAD/+B//AAB/8AD/wAAf8AAP+AAP+AAB/gAD/AAAP8AA/gAAB/AAf4AAAf4AH8AAAD+AB/AAAA/gAfwAAAP4AH8AAAD+AB/AAAA/gAfwAAAP4AH8AAAD+AB/AAAA/gAfwAAAP4AH8AAAD+AB/gAAB/gAP4AAAfwAD/AAAP8AA/4AAH+AAH/AAD/gAB/8AD/wAAP/4H/8AAB////+AAAP////AAAB////gAAAP///wAAAB///wAAAAH//wAAAAAf/wAAAAAAOAAAAAAAAAAAAAfgAAAAAAH8AAAAAAB/AAAAAAAfwAAAAAAH8AAAAAAB/AAAAAAAfwAAAAAAH+AAAAAAB/wAAAAAAf/////wAD/////8AA//////AAH/////wAA/////8AAH/////AAAf////wAAA////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/wAH8AA//8AB/AA///AAfwAf//wAH8AH//8AB/AD///AAfwA///wAH8Af//8AB/AH8B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwD+AfwAH+B/AH8AB///wB/AAf//8AfwAD///AH8AA///gB/AAH//wAfwAA//4AH8AAH/8AB/AAAf8AAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8AB/AAAB/AAfwAAAfwAH8AAAH8AB/AAAB/AAfwAAAfwAH8AAAH8AB/AAAB/AAfwAAAfwAH8AfAH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8A/gH8AB/gP4D/AAf8H/A/wAH///8/8AA/////+AAP/////gAB/////4AAf/8//8AAD/+P/+AAAf/B//AAAA/AH/AAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAH///AAAAB///8AAAAf///gAAAH///8AAAB////gAAAf///4AAAH////AAAAAAD/wAAAAAAP8AAAAAAB/AAAAAAAfwAAAAAAD+AAAAAAA/gAAAAAAP4AAAAAAD+AAAAAAA/gAAAAAAP4AAAAAAD+AAAAAAA/gAAAAAAP4AAAAAAD+AAAAAAA/gAAAAAAP4AAAAAAD+AAAAAAA/gAAAAAAP4AAAAAAD+AAAH/////8AB//////AAf/////wAH/////8AB//////AAf/////wAH/////8AAAAAP4AAAAAAD+AAAAAAA/gAAAAAAP4AAAAAAD+AAAAAAA/AAAAAAAAAAAAAAAAAAAAH///AD8AB///4B/AAf//+AfwAH///gH8AB///4B/AAf//+AfwAH///gH8AB///4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH8D/AAfwB/h/wAH8Af//8AB/AD//+AAfwA///gAH8AH//wAB/AA//4AAfgAH/8AAAAAAf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwAAAAAB//4AAAAB///wAAAB////AAAA////4AAAf////AAAP////4AAH/////AAB//fv/wAA/8H4f+AAP+B+D/gAH/AfgP8AB/gH4D/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+A/wAH8Afwf8AB/AH///AAfwA///gAH8AP//4AB/AD//8AAfwAf/+AAH8AD//AAAAAAP/gAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4AAAAAAB/AAAABAAfwAAAAwAH8AAAAcAB/AAAAfAAfwAAAPwAH8AAAH8AB/AAAD/AAfwAAD/wAH8AAB/8AB/AAA//AAfwAAf/gAH8AAP/gAB/AAP/wAAfwAH/4AAH8AD/8AAB/AB/8AAAfwB/+AAAH8A//AAAB/Af/gAAAfwP/gAAAH8P/wAAAB/H/4AAAAfz/8AAAAH9/8AAAAB//+AAAAAf//AAAAAH//gAAAAB//gAAAAAf/wAAAAAH/4AAAAAB/8AAAAAAf8AAAAAAH+AAAAAAB/AAAAAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP4AAAD/gP/gAAB/+H/8AAA//z//gAAf////8AAP/////gAD/////4AB//////AAf+P/B/wAH+A/gP8AB/AP4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8AfgH8AB/AH4B/AAfwB+AfwAH8A/gH8AB/gP8D/AAf+P/h/wAH/////8AA/////+AAP/////gAB/////wAAP/8//4AAB/+H/8AAAH+A/+AAAAAAD+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAH/4AAAAAH//gAAAAD//8AAAAB///AD8AA///4B/AAP///AfwAH///wH8AB/4f8B/AAf4B/AfwAH8APwH8AB/AD8B/AAfwA/AfwAH8APwH8AB/AD8B/AAfwA/AfwAH8APwH8AB/AD8B/AAfwA/AfwAH8APwH8AB/AD8B/AAfwA/AfwAH8APwH8AB/AD8B/AAfwA/AfwAH8APwH8AB/AD8B/AAfwA/AfwAH+APwP8AB/wD8D/AAP+A/B/gAD/wPx/4AAf/j9/+AAH/////AAA/////gAAH////4AAA////8AAAH///8AAAAf//+AAAAA//8AAAAAAfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAEAAAAD4AHwAAAB/AD+AAAAfwA/gAAAH8AP4AAAB/AD+AAAAfwA/gAAAD4AHwAAAAMAAYAAAAAAAAAAAAAAAAA'), + 46, + atob('DRYqEykpKiwsJi0rDQ=='), + 50 | 65536 + ) + return this +} + +// Medium = 16px () +Graphics.prototype.setMediumFont = function () { + this.setFontCustom( + atob('AAAAAAAADwAAAB8AAAAPAAAAGwAAAb8AAB/9AAH/kAAv+QAA/4AAAPQAAAACvkAAH//wAD///AC/Qf4A/AA/APQAHwDwAA8A9AAfAPwAPwC+Qf4AP//8AB//9AAG/4AAoAAAAPAAAAD4AAAA////AL///wAv//8AAAAAAPAL/wDwH/8A8D//APA9DwDwPA8A8DwPAPA8DwDwPA8A9DwPAP78DwD/+A8AL+APAPAADwDwAA8A8BQPAPA8DwDwPA8A8DwPAPA8DwDwPA8A9DwfAP7/vwD///8AP+v8AAUBUACqqQAA//9AAP//wABVW8AAAAPAAAADwAAAA8AAAAPAAAADwAD///8A////AP///wAAA8AAAAKAAAAAAAD//A8A//wPAP/8DwDwPA8A8DwPAPA8DwDwPA8A8DwPAPA8DwDwPR8A8D+/APAv/gCgC/gAC//gAD///AC///4A/Tx/APg8LwDwPA8A8DwPAPA8DwDwPA8A8D0fAPA/vwDwL/4AoAv4AAAAQABQAAAA8AAHAPAAHwDwAL8A8AP/APAf+ADwf9AA8v9AAP/4AAD/4AAA/0AAAP0AAAAAAEAAL9v4AL///gD//78A+H0vAPA8DwDwPA8A8DwPAPA8DwDwPA8A9D0fAP7/vwD///8AP9v8AC/4AAC//g8A/r8PAPQfDwDwDw8A8A8PAPAPDwDwDw8A+A8fAP5PfwC///4AL//8AAb/4AAAAAAAAAAAAAA8DwAAfB8AADwPAA=='), + 46, + atob('BAcNBg0NDg4ODA4OBA=='), + 16 | 131072 + ) + return this +} + +/* VARIABLES */ +// Const +const H = g.getHeight() +const W = g.getWidth() +// Mutable +let timer = null + +/* UTILITY FUNCTIONS */ +// Return String of Current Time +function getCurrentTime () { + try { + const d = new Date() + const h = d.getHours() + const m = d.getMinutes() + return `${h}:${m.toString().padStart(2, 0)}` + } catch (e) { + console.log(e) + return '0:00' + } +} + +// Return String of Current Date +function getCurrentDate () { + try { + const d = new Date() + const year = d.getFullYear() + const month = d.getMonth() + const day = d.getDate() + const display = `${month + 1}.${day.toString().padStart(2, 0)}.${year}` + return display + } catch (e) { + console.log(e) + return '0.0.0000' + } +} + +// Set A New Draw for the Next Minute +function setNextDraw () { + console.log('tick') + // Clear Timeout + if (timer) { + clearInterval(timer) + } + // Calculate time until next minute + const d = new Date() + const s = d.getSeconds() + const ms = d.getMilliseconds() + const delay = 60000 - (s * 1000) - ms + // Set Timeout + timer = setInterval(draw, delay) +} + +function draw () { + // Reset Variables + g.reset() + // Set Background Color + g.setBgColor(0, 0, 0) + // Draw Background + g.setColor(0, 0, 0) + g.fillRect(0, 0, W, H) + // Set Font for Time + g.setColor(0, 0.93, 0) + g.setLargeFont() + g.setFontAlign(0, 0) + // Draw Time + const time = getCurrentTime() + g.drawString(time, W / 2, H / 2, true /* clear background */) + // Set Font for Date + g.setColor(0, 0.75, 0) + g.setMediumFont() + g.setFontAlign(0, 1) + // Draw Date + const dateStr = getCurrentDate() + g.drawString(dateStr, W / 2, H - 45, true) + // Draw Border + g.setColor(0, 0.93, 0) + g.drawLine(5, 36, W - 5, 36) + g.drawLine(5, H - 9, W - 5, H - 9) + g.setColor(0, 0.18, 0) + g.fillRect(0, 27, W, 32) + g.fillRect(0, H, W, H - 5) + // Draw Widgets + Bangle.drawWidgets() + // Schedule Next Draw + setNextDraw() +} + +/* MAIN LOOP */ +function main () { + // Clear Screen + g.clear() + // Set as Clock to Enable Launcher Screen on BTN1 + Bangle.setUI('clock') + // Load Widgets + Bangle.loadWidgets() + // Draw Clock + draw() +} + +/* BOOT CODE */ +main() diff --git a/apps/fallout_clock/icon.png b/apps/fallout_clock/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..fc9bc1fdca8c690f29b7b1ae5310380deb041ea0 GIT binary patch literal 7978 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 literal 0 HcmV?d00001 diff --git a/apps/fallout_clock/metadate.json b/apps/fallout_clock/metadate.json new file mode 100644 index 000000000..f8de71f06 --- /dev/null +++ b/apps/fallout_clock/metadate.json @@ -0,0 +1,18 @@ +{ + "id":"fallout_clock", + "name":"Fallout Clock", + "version":"0.2.0", + "description":"A simple clock for the Fallout fan", + "icon":"icon.png", + "type":"clock", + "tags": ["clock", "fallout", "green"], + "supports": ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"fallout_clock.app.js", "url":"clock.js"}, + {"name":"fallout_clock.img", "url":"app-icon.js", "evaluate":true} + ], + "screenshots": [ + {"url":"./res/screenshot.png", "name":"Fallout Clock Screenshot"} + ] +} \ No newline at end of file diff --git a/apps/fallout_clock/res/fallout_icon.png b/apps/fallout_clock/res/fallout_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..fc9bc1fdca8c690f29b7b1ae5310380deb041ea0 GIT binary patch literal 7978 zcmeHKcU03^(+(Y?AYD+=5Ed0Ng%C=D6s1Uz5~PEakOF}~APF4-ArwLB(nLU%s&o)g z6i~W_qJn^+BH*ehO+>0+KzG+Y-+Rt?_MGqiZT$vuxXKFJT<0|Wp7 z{1|*D2R-L2SHqFIjzf#%kX(>Onn7mZ3HQ-~l&fEN)&^e2-50RIsWtewCE z(9X49IbUW|nAg7Bz5||>Z(&*^b+8RRWyjM+ZQK0c z%xgTk^KNeZY*^n-#PgZ+Y^5a0_c~`DOTAlNgui&Ig95k`IwBE`Agg{&6}ono3cThwVd_HtKqkj-=NDBeye2uc3M#ST0F3{ zQn0{Yrd=oN$=m&#rk%Oqbi;C>1WFtm0qmZS_})4@oYnqbPDM_XC(x0yhTq3K!(JBU z5qei_+IEsx;w3k)PrQxReGd>A^Ja^uGrJ4kVXhv4k%FjuQ+p*Hlm&{5p zYa>H6p6UU`5va~YsK197EAIe+W19Y6IJ`TN0dgj~kUiDGvv-=oATmK6Y^7ubH}cXZ zx{~z+X+*O?V{?3432;y5D=CIgdX6@!1+Tw=`vdoKQMHNbUcmh#UN8XL0gzOXQ~fF9Smm8gZ}W( z!^_C%Pk2xIPZn5w!2EGuFa;8@^<{zlbm%`?(9Ky@3Oh}tQ+;T7qOLE| zlOgjf1Ofl2y_XM-vKA!Y5x)XwlYi0$Ox@N#rtfzhtW|7Z>^6eQ1N5}dizyDl|aPf zaYzUruR??%omCVeI3(+)j3O$KNJs*SpyK=s6vmUzzolqLhen@D>DU%ks}@BUV8X za15LdjzMIB!VyR`Tmg+xGKZ_8SwEyQ1g?yR|DsPNkVygmm-bfqfR6pxbbT_NwSK_1 z=toVN5xswmehew(?P3Cfw#x#I!~Y0@j`JlFw*6#b{g}eL;yhi5tp4#cVgHbm|3fk$ zRgegx5()ufn5tK|N!@8?R~+6NY85V!*57s|k}pTWYmI>sN-9)tZaK8|fG{L*4rc0XjS*2U_C zus>VjPrkOA&VTXqb07YTE3lydUF09}`!8Mp()EuR_(#hBX4k)T{UZkck@COU_5Vf} z@UO!Z(UbKL$d7eYI#ZGq%sOUqJD)nK1Ngr6&AVHa!jkZL>D$l&fE^-R7aJfeTY@Fz zVPK4Od46Y;6ySxb$`l_000agxI>*gj$Lq2J80Ho^otn!Q7N;+ry(-MhOwf0?+S?D9KDL>aqKr#HF&K~(~y{?_QD7mV2NiR7p%)$op>SXL?N)v33P&| zux+sZnEFzgZB4(ALwdewE6zeC_0pg~aaV7^v+unxA)84?X5aIH_JYjUzS3?Nj!v+w;e3nk;Qo-N)bsSSgU$ ze1qUbu@*%OAtv!cYF^kU zs9B#s4Q|)+5p?sc!U4Crn&1K74uRp}kBttH3q(iFN5}0_MV(TTU1S$#Wp`!ThAQ(< zin(Dx8p1Kl$J>_cdJl1Np`s;}8m{}j=esg1UsPR>0&3~U=wX?Hc7@_@HkxtV3$e9) zAWhMj>zf9I;~&V=Q{{R>Zk@7Yl74Y2X(yY{^sEdfevU8YnLhWeu%RXIyY`+g`DdTS zE9;uuPC3~I^DkepeRVwe)QyhvyXg()pHBF`nQ&cNGH-yWOSy0!xtbt4T5P*nrziE9IcUq*_>Gb6cmxUC}ekLZkw2i^vWVtfK5i@6!aMmTO8$ zS0vjrYm7IWJ_xR)aGMnvy=!KW;yu6>g>BPZ;f+`SrJAo!7MB7Xm;rq7(amDP>zOTloMF2MVfsAZIi zp+n~*No}F9QjG1`9#f&hTiExDrZ#jTX>>)3aL*B`rdkgT#G2;njo-(3Js}Rxl=p)? zOhLaLZ64}TC)bG6%#EZqQlt0q4O6=h#T(utq1j7(D!mf1U@cx=#Cd@UwXwA$y2;6+ zt@r2mdMjIgRZGaPxo)?W5tf{toNY_BYXh6RhF9mH6B9=%>tB$*LGmh_&YY4m`4x%f zGcn4i?@!t8HWE-f-s+I*`Lb^|{pKntEjh1%$=}1-@8af`1TVba;(ssV-1?=g#M|p- zf=w?*`CR;NPIldJIUf(N>o&iI8K^k*brah;qz3hVXms9C!liwBu4?*0N^sQ%nE&GA zqY(Y6sPo=2p5gIBMKzugS77`Vf*J(F(EKHL^s3pN9pQ`uqtk(vOdi64nUnkm?W9FU zu`zF-Z19SaI&OOS*zz~v(Zb>21)JY4*IRezRx+D+mpf0zg-&#Bsy@l4gP2;piM-iR zev6ch2(b{QL&?voU9k528<=}LxC{sM9GqT^+VR;<95bm zJ!r@_B;lSJ zn?1drHobi%ajS>|YqnhgSX_{UhftmPqA};n-A{c=u=r2C^CKM3C3Ysi$Z!fd<}7pe z+g-zbiiJFteI-klcKpUgDYv=zzIk(1hZ*SvKfDhWaPD1PNbkoAV?98#{pY-usJe_3 z&a0I&0cVCJE1pGh%7O`jjsweU7N7UMBLt2+?a2z>r>PN37CF%R#B!kNeCh1LfaQT6XoeMFaxRI9KP(!V)gBAz^JdnuKq6GH(NtAM8uT2y;Y zLSr^fKu!hHs%B1}xzc_92&y}y!jbtczajh5nX5^8Rsv^)xT zN2hc_+uJ4SC9Ui7cN&o>g>#*|AuSXErlmJWKJN~Lov&ZL`64VPIq=zZqO`M2cVYUR zO#?%Qz2gYTEGX5XA;o23P)Ph`SZbxaAF6&lBcVGF8&DDz^f`#RS~wj)>%KRum`nlk z`mdczcuNa{^YGx|oO)@i+Ds6;JmF3_C6xj{l>ceg%AUg53yX_A^o?uhitS)NnpcYbVoN%Es@TwL}l zZxR;e(&gi9_8xRSI_<>We!V)VewY3I9Ce?alEUL<7W+%Ho6 zU&P3R99LFGrw*YMcA4D~jXrpA?se$+sir!kJ({WeJM#`(hpV{-3A5xcR90oq(a94ACOpx;bF4iqVyQg2V}DylT@&5$;aA(JVQ8B-VbY zh57PmcDW^V2<;zguO!kb>!i#RGV~!1H?{0%I=kcZEwFoI{#a{%QfDLTtVnDh$Fb(7 zp5td`p7-Ax{yf=Fge|;YZ_J1=w3=G)&m?DD@ZglQ?>iG{0FI8&Y271oar6^$^ed2L zXmk$<^U&};^h(L+@{3>~mM0I>3W;!Qkat()*1en6M}mv>Mb-FTZ?J9%||s(>g}xbSpj z)rjxV6JOschB_7?gu9w?L2rUvCnXb+Z7+Kz@}k{ELi@eO)H^|tho>%TG}BZM6=K$| zB8GV1qG`8gu=xPCBD;jQ6}KYNCddSvL?_3hXaPU=S@Cg9HU9R_w+#1yPpDEk# zwrA!{1LfV_C3%~#U1ulbd$fk?_9F@jlXF)ot6y*Urn)WYh3(BzW0R(<|6e>?fo*NZX>dd)jIN=xUEGb zR1YUjGAVi&9zU4=GB@us+AVeETzQH5YR5h8&P>%1I0zLim!M)yy0$#-M+Z*IT{~WM z=7_lj=iqqDjY^%laX!URS2C_YyzyE3CEBoPdra-l0Yy5mXTo=fiu4Z;(}(M+yT+&E z)<2|uB$It)l*9<2nLecE{)&W+f+AJ_1-lUS&^>ieL^p$-(52%pWScnAcNf&s_H3*~ zZq^IZf-4?pf_6MWEW9vXm-?;|Bz{8cM(4vPv%YgZDr>yJTX~0p8Wqu!DSC?d9)Ixt z(<6ww{MS}@*#th&g8V;3UefPBVSD@hkVA%^4uLat1a;ZK!TztIiDv=lM7!< zW;O+PRf@~GbBrF*bxYPlu_N+_P8%;`Yd-0YuT|_jI34fy(EbD?@a%5Ug9Y)UHVMyy zU9)n1E;kqE<5YSzG|mg2vU^cR#Y~h)?Ktet|Eag-KL0}01pCtjwu@!S>}Fia?^Y>% z5|7(@gOfWgue^Sdx#*FVSY4*>Eyhg!_R^Q}{G^Y)46J#c4YvDiTdf?1d5c5&IhADp z{z~d{g1^?id6D@sM$y!$mUr&hU>^3uib>@csuE?zO(n~5_MrZ$rg9R}WJgw^so79h z6G~AsCFM~=)%>R>gIhUSj|)qsH$FX*Vw;a1zkDb1gR69#0H{z?P{XrsZ5zYR_n#dh8DG)z?0|#8C-hB>+g#z;(Y{BQ-Bps+M;D$ zXkM|IZfoZ%+&JBnslTGeSDuTw1^B$jyA%%|4)W{my0i9<)*?Qf{>u%w&jv@ z@>bp22YD)wHDfn;rGa593I`zwna_mgj{YF%%bs`XQC|o(WgtyJtO3xF=X=5TONT?c z7zUtCJFwZ)`%=w&1-;)~&`}NSF!g{WSqT{Fq_7R4MjsAaF)&#=8ra~AZH`YvWdm)W zTRha3dGy(wEi<<7(2hw7X+o)1$Kex4j7|1E^c$}@P^qg7RNYlA+UAgWNGlrxg`>Y` cu6;isK6t`}Z=gYkb?60Pbd7b&PdJ7D55c)a;{X5v literal 0 HcmV?d00001 diff --git a/apps/fallout_clock/res/good times rg.otf b/apps/fallout_clock/res/good times rg.otf new file mode 100644 index 0000000000000000000000000000000000000000..53c181ccad978b674641b06b11fd8d0404d338e6 GIT binary patch literal 22476 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 Bw8j7c literal 0 HcmV?d00001 diff --git a/apps/fallout_clock/res/screenshot.png b/apps/fallout_clock/res/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..253554b728b4b7da36902477bc6cdc87107a9eba GIT binary patch literal 2243 zcmd^BSyYqP7CuQNVWvo#1f*0MR8TB3lYq)71QeMkqcVsLVM>LBK!7UZwcrwrI1r{b zARti?L}d7DQA7%nAz=_=1Z;&s0zp6$1I=Cc=|1-1KHZ12_uA|1v-fxQTHpCj!AWm7 zCHY zunz{P@l_`E2yow0JIzBGJc?9v36|cyp|8R-1yBs{nY>v5AO?#Jzli{*6V9gsP{1bc zhyPhiCq$4W;a2{8U6Xx}u8np+6xWVbliEVJ*)eJQr0ouLc&(uZ*L}6a=m8~!Fcj^` za*NaukX+VO7X_A}TZgZ{E2>21B9F-6vn4cs%-(;wClzh&*v!;}(69Ve#ELVD=(WgX z!;Tz$ejIFFE710n&j`lz49%2Jv6h|D1%XPzwsgP6rNjY5ubdKh$XHkmJs)VQ&@o^A z%w~y5C-5}_J7|x-@ArTo|8|B@$CJ-g4NfoIbB&%e+hYU0NlUy#w?cJ@Qlm3Oej3z9 z@2lql|8h{Qd^#bWlzNh#LFfD9dBtK3%6wS_`PG}9VIp%|jNlw>_Hsl9ELvFidMh*r zHjGG0(?IXiNd!syMj3$_A0932sS(JW)}pLdjo17E7usMu*T{8SXVjk@0wjd31xBRK zV;%WnBG)O!Q+d+b7z(D?(1m@UYb-;Zo)p5_?e!x0$qj9a*$Th+S!#~;eRoRvG9-o# z@`|jl0LL+8I=)Sv3cpWKS>rv7_@;z-s3R~leYIn#M*_3iIa7-t+3!TWNbDBV9d7K_ z0}eCPwpPs-970tCzezP5bTpIkSA=$a@A#xj^$=#D0c~My;icWM3D0fuAPL!eUFWdj zxrE51OE2D4+k>jae#Cm#pNjFYDYc(^T@>nGO9WH>v%dw1OS&q^sc_RQ_);J55*8Xc zw3I!Dxmj9V_1%rBcc>)=$n39bx;ZGfSA_U6TkmC#BD4IGdw1tqeKqY4jp1f7v0UTp z@ACC7oGY%hUkA9=%@NZDx&DyUkHO=U_A|25+z`7TS>Yjh8-3^;2Ha-6N2nH*q2n5P zc9ZkCw;9yGA{=2WvC2p;UKym;1$9keL}tYtSXi!BhKP!@xAa_TiFM#`V?cKv>$V$% zz`(N9H>L<*9U$7i1~tYjS)T-8Hx` zJE-tC)9vcmdDtL$9QDh_y`7ixD!iQQduf5)P563O)@eA`*r4^gAI^buJlJAq7Bi%t zDM2&Xf+1fd_qj1da%8z5csl{Q_A9XPA7BHi$i#w{3e~&u)byXj=4F$kCogD3bYG62 z1sYcOs^(046mmV5ZfVXbNMPL2U%nfZQrj%QjV65$z4cUPOi^Gw0(o6|xI|%RT*!rq9Jz3g7#f@8iAyus-Ut^nAK^ zIC+X$hYt@V9N3HYE7rli{5Gm8vz?io8?5G5cAdK3Om>W&pB@wMslZQH(?U8?5e${( z=r$Re%u1Fp1gUR)*Pr2S$LnGf1el9te71E%y-HHglV#5Dp#rpVHc^YTo`^j=2w6Lv z6U)Vwt(n@gMN92O4K%x6ZD6=^{V-7@U@e5WyMvYuKTzJpDu~kV>}F1j>x$QcYCcVg zF!X^Ptyi@=IHW)0u=Jz0-TnUI3qN7JGd*K?*s~8;yMjkCEb^h+esm7&K_uDfolk{{ znppyStvNq_dwY;xy>?51i3%3X6$;J1U^ZdvnFPpg#N|$nH=QFl6*4wC_Ppq0-eftU zT&M9b)cE-q6WUCRSO=0`jp+5nXEGy!xS!Y=Lx^k2ChDZqiAC9YaYE^!2ZMN~vE&6o zXJT1P=Y~JC_92-iF}+X8~I9xmR_jmL1ge*+z5 BIx+wN literal 0 HcmV?d00001 From f9cb2b14e2fbf380df61a3f99d23156937e35c24 Mon Sep 17 00:00:00 2001 From: "Zachary D. Skelton" Date: Fri, 23 Feb 2024 11:35:15 -0600 Subject: [PATCH 02/57] Add: Fallout Clock - fixed metadata --- apps/fallout_clock/{metadate.json => metadata.json} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/fallout_clock/{metadate.json => metadata.json} (100%) diff --git a/apps/fallout_clock/metadate.json b/apps/fallout_clock/metadata.json similarity index 100% rename from apps/fallout_clock/metadate.json rename to apps/fallout_clock/metadata.json From 0d44f1a43e2967aff11b68fa692a279d8488aeda Mon Sep 17 00:00:00 2001 From: "Zachary D. Skelton" Date: Fri, 23 Feb 2024 11:41:23 -0600 Subject: [PATCH 03/57] Add: Fallout Clock - fixed image --- apps/fallout_clock/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/fallout_clock/app-icon.js b/apps/fallout_clock/app-icon.js index 9e38e51a8..9c2b9bc1d 100644 --- a/apps/fallout_clock/app-icon.js +++ b/apps/fallout_clock/app-icon.js @@ -1 +1 @@ -require('heatshrink').decompress(atob('mEw4cB388///t3/rX/6/2jOuCIOK70kyVJAQeQgEVkQIEAQ4uCiIGBCJVACIWJAwNUCJAyBAAMEDAcCCI5jDlQJC0EAhIRFkAQCgNSBIQGCKxEAhWSr+kyoHCCIlICIcEy//+hOENA8AomXr//9AIDCIYHDgX/+9L//4BIcSPQkBwED0mSCIP/DYgREh/AjoqBCIXgCIuAAoMO3/pCIIQBLYIkDCIhgBpf+y/bCQQLCUgQECh2Sr27tp+BGwoRG+u27duv/+7/wCIbCDt//1oRCIAO7/jPDCId19gRCuQRBzf+CI0C+vlCIWa5Mkz//siyBlIRCit/jdtEYXJkpaB6VJkqBDhN67YRCtojBCIjmDpN482N5Hb1ojB34RClQQCglJu3uxvW7fREYO3/hGBqARCkVJq3lt3W7gRC+wRBpRtDqVLEANyI4ON3Mly3uCILIChTUB43bvU2LIO5km2CINUEYVUCIhrCEYOT+mS0ARCkgRDuYjECIRXDCIRHBR4PdI4IJB+mVCIQcC23Xtlt28tNYQRB1DpGs+jy3a7e1CIOT+r7HtNtE4PtyoRBy8oCIckAgUK7ZqBrbXBk3dYQYREhihBLgNupM/YQkJCIcBrYREvTCDCIS2CgErI4ImBp/SpARDpMkyD+DCId96TCDCI0A1oRByXMYQkCCIK4DgEW23kyV+ygJDiQRCoAHCgdrtjUBFomSCIRPDgft9v/0jCCCItJA4UVl//pMlFgcECIjICiIGCYQoREUgSWBDAgHEAQZSB1IGCYQYOEAQcAxIDBpS8CPQYCGAYQiCKwoCG0iWCBYw')) +atob('MDDDAb88//9u/1r/1/YZrgAAit4kkkkkkkkkkAAVIkkkkkkkkkkkkkkkkkkAAAARJJIkkkkkkkkkkkkkkkAAAACJJJJUkkkkkkkkkkkkkAAAAARJJJJAAkkkkkkkkkkkAAAAACpJJJKgAAkkkkkkkkkgAAAAAVJJJJIAAAEkkkkkkkkAAAAACpJfpJUAAAAkkkkkkkgAAAAABJf/9JAAAAAEkkkkkkAAAAAARJdf/+gAAAAAkkkkkgAAAAAC//dL//gAAAAAEkkkkAAAAYADpJJL//8AAAAAAkkkkAAAD8AdJJJL///gAAAAAkkkgAAADr/pJJL////0AAAAAEkkgAAABJJL/pfb////gAAAAAkkAAAADpJeu22X////4AAAAAkkAAAADpL1tttuf/7f8AAAAAkgAAAAb/+ttttuSSS7/AAAAAEgAAAAdeyttttySSSb/gAAAAEgAAAC9eWtttuaySSf/2SSSSkgAAAVfxtttttyySX//9JJJQAAAAAJetttttttyST//9JJJUAAAABJeOaNyNutySW//9JJKgAAAARJdu6N1tvRySS3/JJJUAAAACJJVuVu1tzRyST2/JJKAAAAAVJL1ttyttuNuSWW7pJKgAAACpJLxtt6NtttuSS27pJUAAAAVJJLxtt6ttttuSWT9JKgAAAAJJJLxttzNtttuSST9JIAAAAiJJJL1ttttt2NuSSS9JUAAAA2222212xtty3RySSS9KgAAAEgAAAAZ6OW2tu1ySST9QAAAAEgAAAAaW1ttu2VySSXKAAAAAEkAAAACtu221ttySbdKgAAAAEkAAAADNty1ttuST9JUAAAAAkkAAAAAVty1ttuSXpKAAAAAAkkgAAAACtttttyT9JIAAAAAEkkkAAAAARttttyfdJUAAAAAEkkkAAAAACtttuSzJKgAAAAAkkkkgAAAAAWtuSSfpQAAAAAEkkkkkAAAAADa2yT9JAAAAAAkkkkkkgAAAAD7e3/pKgAAAAAkkkkkkkAAAAVL/9JJUAAAAAEkkkkkkkgAAARJJJJKAAAAAEkkkkkkkkkAAAJJJJJIAAAAAkkkkkkkkkkkACpJJJJUAAAAEkkkkkkkkkkkgCJJJJKgAAAEkkkkkkkkkkkkklJJJJQAAAEkkkkkkkkkkkkkkkkpJJAAEkkkkkkkkk=') From 6ec4aa1a7929ecbfeb008d98e3eaf72c8ebe7e03 Mon Sep 17 00:00:00 2001 From: "Zachary D. Skelton" Date: Fri, 23 Feb 2024 11:51:53 -0600 Subject: [PATCH 04/57] Added Dev Docs --- apps/fallout_clock/.gitignore | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 apps/fallout_clock/.gitignore diff --git a/apps/fallout_clock/.gitignore b/apps/fallout_clock/.gitignore new file mode 100644 index 000000000..2597f0579 --- /dev/null +++ b/apps/fallout_clock/.gitignore @@ -0,0 +1,6 @@ +node_modules/ + +fallout_clock.code-workspace + +package.json +package-lock.json From 4a4f642c954501785d91fe5215e629454ef3b8e8 Mon Sep 17 00:00:00 2001 From: "Zachary D. Skelton" Date: Fri, 23 Feb 2024 12:09:20 -0600 Subject: [PATCH 05/57] Edit: Readme --- apps/fallout_clock/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/fallout_clock/README.md b/apps/fallout_clock/README.md index d535cc050..b48e7e762 100644 --- a/apps/fallout_clock/README.md +++ b/apps/fallout_clock/README.md @@ -2,7 +2,7 @@ Inspired by the aesthetic of the Fallout series, this clock face looks to emulate the color and feel of a PipBoy. -Add screen shots (if possible) to the app folder and link then into this file with ![clockface](./res/screenshot.png) +![clockface](./res/screenshot.png) ## Usage From 1ec46375fb9550691413a9357177fc8bfd966e73 Mon Sep 17 00:00:00 2001 From: Anton Date: Mon, 26 Feb 2024 01:13:16 +0100 Subject: [PATCH 06/57] Rename da_DA -> da_DK --- lang/{da_DA.json => da_DK.json} | 0 lang/index.json | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename lang/{da_DA.json => da_DK.json} (100%) diff --git a/lang/da_DA.json b/lang/da_DK.json similarity index 100% rename from lang/da_DA.json rename to lang/da_DK.json diff --git a/lang/index.json b/lang/index.json index 537c472f7..87af9a308 100644 --- a/lang/index.json +++ b/lang/index.json @@ -14,7 +14,7 @@ {"code":"pt_PT","name":"Portuguese","url":"pt_PT.json"}, {"code":"pt_BR","name":"Portuguese Brasil","url":"pt_BR.json"}, {"code":"bg_BG","name":"Bulgarian","url":"bg_BG.json", "disabled":"Characters not in ISO Latin codepage"}, - {"code":"da_DA","name":"Danish","url":"da_DA.json"}, + {"code":"da_DK","name":"Danish","url":"da_DK.json"}, {"code":"el_EL","name":"Greek","url":"el_EL.json", "disabled":"Characters not in ISO Latin codepage"}, {"code":"et_ET","name":"Estonian","url":"et_ET.json"}, {"code":"lt_LT","name":"Lithuanian","url":"lt_LT.json"}, From ca22b24590d6243a4a56aa7fcd01532461c520f3 Mon Sep 17 00:00:00 2001 From: shansou504 <123512155+shansou504@users.noreply.github.com> Date: Mon, 26 Feb 2024 01:31:11 -0500 Subject: [PATCH 07/57] Added settings to hide unused squares and show date --- apps/binaryclk/ChangeLog | 3 ++- apps/binaryclk/app.js | 39 +++++++++++++++++++++++++++------- apps/binaryclk/metadata.json | 4 ++-- apps/binaryclk/screenshot.png | Bin 3318 -> 16648 bytes apps/binaryclk/settings.js | 18 +++++++++++++++- 5 files changed, 52 insertions(+), 12 deletions(-) diff --git a/apps/binaryclk/ChangeLog b/apps/binaryclk/ChangeLog index 7b6810faa..dd35cb918 100644 --- a/apps/binaryclk/ChangeLog +++ b/apps/binaryclk/ChangeLog @@ -1,3 +1,4 @@ 0.01: Added app 0.02: Removed unneeded squares -0.03: Added settings with fullscreen option +0.03: Added setting for fullscreen option +0.04: Added settings to hide unused squares and show date diff --git a/apps/binaryclk/app.js b/apps/binaryclk/app.js index 94c906104..99d1755fb 100644 --- a/apps/binaryclk/app.js +++ b/apps/binaryclk/app.js @@ -1,11 +1,15 @@ -var settings = Object.assign({ +var settingsclk = Object.assign({ fullscreen: false, + hidesq: false, + showdate: false, }, require('Storage').readJSON("binaryclk.json", true) || {}); function draw() { + var dt = new Date(); - var h = dt.getHours(), m = dt.getMinutes(); + var h = dt.getHours(), m = dt.getMinutes(), d = dt.getDate(); const t = []; + t[0] = Math.floor(h/10); t[1] = Math.floor(h%10); t[2] = Math.floor(m/10); @@ -17,32 +21,51 @@ function draw() { let i = 0; var gap = 8; var mgn = 20; - if (settings.fullscreen) { + + if (settingsclk.fullscreen) { gap = 12; mgn = 0; } + const sq = 29; var pos = sq + gap; for (let r = 3; r >= 0; r--) { for (let c = 0; c < 4; c++) { if (t[c] & Math.pow(2, r)) { - g.fillRect(mgn/2 + gap + c * pos, mgn + gap + i * pos, mgn/2 + gap + c * pos + sq, mgn + gap + i * pos + sq); + g.fillRect(Math.floor(mgn/2) + gap + c * pos, mgn + gap + i * pos, Math.floor(mgn/2) + gap + c * pos + sq, mgn + gap + i * pos + sq); } else { - g.drawRect(mgn/2 + gap + c * pos, mgn + gap + i * pos, mgn/2 + gap + c * pos + sq, mgn + gap + i * pos + sq); + g.drawRect(Math.floor(mgn/2) + gap + c * pos, mgn + gap + i * pos, Math.floor(mgn/2) + gap + c * pos + sq, mgn + gap + i * pos + sq); } } i++; } - g.clearRect(mgn/2 + gap, mgn + gap, mgn/2 + gap + sq, mgn + 2 * gap + 2 * sq); - g.clearRect(mgn/2 + 3 * gap + 2 * sq, mgn + gap, mgn/2 + 3 * gap + 3 * sq, mgn + gap + sq); + + var c1sqhide = 0; + var c3sqhide = 0; + + if (settingsclk.hidesq) { + c1sqhide = 2; + c3sqhide = 1; + } + + if (settingsclk.hidesq) { + g.clearRect(Math.floor(mgn/2), mgn, Math.floor(mgn/2) + pos, mgn + c1sqhide * pos); + g.clearRect(Math.floor(mgn/2) + 2 * pos + gap, mgn, Math.floor(mgn/2) + 3 * pos, mgn + c3sqhide * pos); + } + if (settingsclk.showdate) { + g.setFontAlign(0, 0); + g.setFont("Vector",20); + g.drawRect(Math.floor(mgn/2) + gap, mgn + gap, Math.floor(mgn/2) + gap + sq, mgn + gap + sq); + g.drawString(d, Math.ceil(mgn/2) + gap + Math.ceil(sq/2) + 1, mgn + gap + Math.ceil(sq/2) + 1); + } } g.clear(); draw(); var secondInterval = setInterval(draw, 60000); Bangle.setUI("clock"); -if (!settings.fullscreen) { +if (!settingsclk.fullscreen) { Bangle.loadWidgets(); Bangle.drawWidgets(); } diff --git a/apps/binaryclk/metadata.json b/apps/binaryclk/metadata.json index b4ddc6544..1a5dee591 100644 --- a/apps/binaryclk/metadata.json +++ b/apps/binaryclk/metadata.json @@ -1,8 +1,8 @@ { "id": "binaryclk", "name": "Bin Clock", - "version": "0.03", - "description": "Clock face to show binary time in 24 hr format", + "version": "0.04", + "description": "Clock face to show binary time", "icon": "app-icon.png", "screenshots": [{"url":"screenshot.png"}], "type": "clock", diff --git a/apps/binaryclk/screenshot.png b/apps/binaryclk/screenshot.png index 8b54ed66fbda68f6f48421e1a4c814e537706f27..504a1926fbb2538d2b5bccc552067ebf48c6345b 100644 GIT binary patch literal 16648 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 z%0A6H<R-~F@JH=c;lI0hW9;-Mq+T%O*U1QcVTFW zfSD{kDGo#VzocBuzET6PNoe-Ukr@v5hWUb*Molv%gmCn^Lv?N7)Z`F3T7$*Gbz*du zaDUWnryyfJtsx@QLcrzEBiKG^S?i>~p*T literal 3318 zcmeHKYc$l|8lN#3*D;Y>uS=q-PNt9?1|tm9e)9LDloBw;3Z^x7~Ao+$fd zc8BfIW}Z;?h9rCJrVD{~Y`vHFQaf&8`htY@=iXJI5m88w*ouKac~vj%2cfwg@%JER zc&^#VGe|mQbD896el+XK`gUx`aR!^QeyzJ?czAdcxk7xQJ0^DHejbCt7^@vZn!!RP zM_OB}H@9PUYI07R^lprdl{>eo3r^o?GEHAx=l9>GHNf+_CLW8B8wf3+EW6qqxAn!v zaJNa-fu@}e(se=4`ALwRrr>>lHR9<&A?n*6K|{uDn?e~wGzeT_S>cTw#qgw|Yi($5 zd9_Ag2D8FpDzgtXD~A33xJ;x``UIXTg3R(WFC)I_j|uzh=}se4%9Je|G-VN?E_mNq zt?|@V7!-Phdu5$4yvp(94iGP{nR+tB>Vh)|UVYqdGVd6^4y}um!Zq`MdrqQoy`PuO z85vKEsmTkbh~|6QPxPIxz(NyKwOR)~y?0_Y3B%`~@7~|GdSYaR(}(0#g3)=7c1yMm zfh>#b!O@8kuc1+IG7!d6xY6M$Ia0_a{x=OKO5JM$R7L#)|LDh5qdH z=ShR88{BaeTT@e$IoA)WShbjXm5$DJ8)1Y~T4m=pWbx~>*pTx@(sMy08|zU#R@o|O z>YYdCGK!C<>RY?7G?pp5t>Hc%3=s;X+(k)wkHy#W%9hD18jdJ`=#ECi{q=+RRv%&(S7NImxrOS zbBBS0g}Ow0PV_tRyAOo%oY;f|jYieJ^P{WrS1CPM4i6GIyH!yo*+*fWz+$2`TD^;tV2N;G6PuD%I2FZ^TM{A188YmqUrGaX;(iO`6V$>kaJ zj&#K1DbXGQJ<2UFvu76rt_!xEQZ_F^5hOPFQEk|xl}}*kAdWs9&xGmKBL~aEYd*zf z4;3?Ep)Zs@8b`=q9==s=YD?cva$rcC3s)UjF_d(ItluW675tqo7vWF&*luDYdnMXyf~xJ-!0t4|xEe=czOp(b#Fnx=J0oE5L>LqqHOUO9d~)_ng} z;Il4pFsZV4?I#F76HfUBF>Ev(|C*;7cdP+IjyQFa&_DYfy^tk&*TpQOW4af=Lu{gs zZ>U@{6@bz|X?DSk1t8OXXMvg1C$tkEd`-OQ8j#ugm`9sFrW<~5OsX^*NE9qN zk~XoV&_PWeWsxXDWrOum>Y9tZBq*AFuefd!`5k*q|CyvaD_farLr_16ubQM6WDR_ zUk?AzW4OKoMr_I4>sULHAzxG&cgJa(+$@qapStx9hmLlp0>ZpGL`Iphb-Pif@NXvu zrPNFgX>wteFk^Q4*?!q?fHp7V%?|a00SUdU*8-HA9GH5b1qD~~vS58_C0cw*O7-M~ zbjeAFzEDLAA?FRgi*>CDvU|wFBk^o(hi!~uniTKA~dZSowouq&3~nGSo!_l{H1yNXHoBE@`j;4W_OW& zX0B1(ibZoF?b&0Xye@7{Umz#Tc8S>ejBr*9fK>T?Riu+nbw`Pfw=YOdE7DJ;xOz1s zF3X4gEUDU!h6N^E1RMen$K+9a7d#~TbK k4n7H06KL^-xGLBtltLS=eKN+d1U@n#oQ)% { settings.fullscreen = v; writeSettings(); - } + }, + }, + 'Hide Squares': { + value: settings.hidesq, + onchange: v => { + settings.hidesq = v; + writeSettings(); + }, + }, + 'Show Date': { + value: settings.showdate, + onchange: v => { + settings.showdate = v; + writeSettings(); + }, }, }); }) From df3c6d3f0cfba6e1f8d832124c28b0429ed28800 Mon Sep 17 00:00:00 2001 From: shansou504 <123512155+shansou504@users.noreply.github.com> Date: Mon, 26 Feb 2024 01:46:57 -0500 Subject: [PATCH 08/57] clean up --- apps/binaryclk/app.js | 14 +++++++------- apps/binaryclk/metadata.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/binaryclk/app.js b/apps/binaryclk/app.js index 99d1755fb..9b953e504 100644 --- a/apps/binaryclk/app.js +++ b/apps/binaryclk/app.js @@ -1,5 +1,5 @@ -var settingsclk = Object.assign({ - fullscreen: false, +var settings = Object.assign({ + fullscreen: false, hidesq: false, showdate: false, }, require('Storage').readJSON("binaryclk.json", true) || {}); @@ -22,7 +22,7 @@ function draw() { var gap = 8; var mgn = 20; - if (settingsclk.fullscreen) { + if (settings.fullscreen) { gap = 12; mgn = 0; } @@ -44,16 +44,16 @@ function draw() { var c1sqhide = 0; var c3sqhide = 0; - if (settingsclk.hidesq) { + if (settings.hidesq) { c1sqhide = 2; c3sqhide = 1; } - if (settingsclk.hidesq) { + if (settings.hidesq) { g.clearRect(Math.floor(mgn/2), mgn, Math.floor(mgn/2) + pos, mgn + c1sqhide * pos); g.clearRect(Math.floor(mgn/2) + 2 * pos + gap, mgn, Math.floor(mgn/2) + 3 * pos, mgn + c3sqhide * pos); } - if (settingsclk.showdate) { + if (settings.showdate) { g.setFontAlign(0, 0); g.setFont("Vector",20); g.drawRect(Math.floor(mgn/2) + gap, mgn + gap, Math.floor(mgn/2) + gap + sq, mgn + gap + sq); @@ -65,7 +65,7 @@ g.clear(); draw(); var secondInterval = setInterval(draw, 60000); Bangle.setUI("clock"); -if (!settingsclk.fullscreen) { +if (!settings.fullscreen) { Bangle.loadWidgets(); Bangle.drawWidgets(); } diff --git a/apps/binaryclk/metadata.json b/apps/binaryclk/metadata.json index 1a5dee591..b8489885a 100644 --- a/apps/binaryclk/metadata.json +++ b/apps/binaryclk/metadata.json @@ -2,7 +2,7 @@ "id": "binaryclk", "name": "Bin Clock", "version": "0.04", - "description": "Clock face to show binary time", + "description": "Clock face to show binary time in 24 hour format", "icon": "app-icon.png", "screenshots": [{"url":"screenshot.png"}], "type": "clock", From 241b6e20ce3caa1939056f7ef815156a7ffab7de Mon Sep 17 00:00:00 2001 From: Anton Date: Mon, 26 Feb 2024 15:03:50 +0100 Subject: [PATCH 09/57] Warn about empty blocks --- apps/.eslintrc.json | 2 +- apps/andark/app.js | 1 - apps/aptsciclk/app.js | 3 +-- apps/carcrazy/app.js | 4 +--- apps/doztime/app-bangle1.js | 5 ++--- apps/hwid_a_battery_widget/widget.js | 3 +-- apps/novaclock/app.js | 8 ++++---- apps/red7game/red7.js | 6 ++---- apps/spacew/prep/minitar.js | 2 -- apps/tabanchi/app.js | 6 ++---- 10 files changed, 14 insertions(+), 26 deletions(-) diff --git a/apps/.eslintrc.json b/apps/.eslintrc.json index d5a4bf2a3..a2973e931 100644 --- a/apps/.eslintrc.json +++ b/apps/.eslintrc.json @@ -144,7 +144,7 @@ ], "no-constant-condition": "off", "no-delete-var": "off", - "no-empty": "off", + "no-empty": ["warn", { "allowEmptyCatch": true }], "no-global-assign": "off", "no-inner-declarations": "off", "no-prototype-builtins": "off", diff --git a/apps/andark/app.js b/apps/andark/app.js index efa00ce6f..865e3e708 100644 --- a/apps/andark/app.js +++ b/apps/andark/app.js @@ -104,7 +104,6 @@ Bangle.on('lcdPower',on=>{ if (on) { secondInterval = setInterval(draw, 1000); draw(); // draw immediately - }else{ } }); Bangle.on('lock',on=>{ diff --git a/apps/aptsciclk/app.js b/apps/aptsciclk/app.js index c2903cf37..f32a52870 100644 --- a/apps/aptsciclk/app.js +++ b/apps/aptsciclk/app.js @@ -270,8 +270,7 @@ function queueDraw() { function draw() { - if (pause){} - else{ + if (!pause){ // get date var d = new Date(); var da = d.toString().split(" "); diff --git a/apps/carcrazy/app.js b/apps/carcrazy/app.js index 0fb765871..2bb9932a7 100644 --- a/apps/carcrazy/app.js +++ b/apps/carcrazy/app.js @@ -66,10 +66,8 @@ function moveEnemyPosition(){ enemyPositonCenterX2 = 120; }else if((randomRoadPositionIndicator2 == 3)){ enemyPositonCenterX2 = 155; - }else if(level == 7||level == 8){ - } - } + } // TODO: else if(level == 7) } function collision(){ diff --git a/apps/doztime/app-bangle1.js b/apps/doztime/app-bangle1.js index 38c5acbac..3042e9367 100644 --- a/apps/doztime/app-bangle1.js +++ b/apps/doztime/app-bangle1.js @@ -223,9 +223,8 @@ function fixTime() { Bangle.on("GPS",function cb(g) { Bangle.setGPSPower(0,"time"); Bangle.removeListener("GPS",cb); - if (!g.time || (g.time.getFullYear()<2000) || - (g.time.getFullYear()>2200)) { - } else { + if (g.time && (g.time.getFullYear()>=2000) && + (g.time.getFullYear()<=2200)) { // We have a GPS time. Set time setTime(g.time.getTime()/1000); } diff --git a/apps/hwid_a_battery_widget/widget.js b/apps/hwid_a_battery_widget/widget.js index 79ce9a5ad..7c76364a0 100644 --- a/apps/hwid_a_battery_widget/widget.js +++ b/apps/hwid_a_battery_widget/widget.js @@ -24,8 +24,7 @@ var s = width - 1; var x = this.x; var y = this.y; - if ((typeof x === 'undefined') || (typeof y === 'undefined')) { - } else { + if (x !== undefined && y !== undefined) { g.setBgColor(COLORS.white); g.clearRect(old_x, old_y, old_x + width, old_y + height); diff --git a/apps/novaclock/app.js b/apps/novaclock/app.js index 52bee0dbd..13cf3bfb3 100644 --- a/apps/novaclock/app.js +++ b/apps/novaclock/app.js @@ -85,7 +85,7 @@ function novaOpenEyes(speed, white, animation) { scale: 2.2 }); }, speed * 5); - } else {} + } } else { g.drawImage(novaEyesStage4(), -10, -10, { @@ -126,7 +126,7 @@ function novaOpenEyes(speed, white, animation) { }); open = true; }, speed * 5); - } else {} + } } } @@ -136,7 +136,7 @@ function novaCloseEyes(speed, white, animation) { g.drawImage(novaEyesStage0(), -10, -10, { scale: 2.2 }); - } else {} + } setTimeout(function() { g.drawImage(novaEyesStage1(), -10, -10, { scale: 2.2 @@ -164,7 +164,7 @@ function novaCloseEyes(speed, white, animation) { g.drawImage(novaEyesWhiteStage0(), -10, -10, { scale: 2.2 }); - } else {} + } setTimeout(function() { timedraw(true); g.drawImage(novaEyesTransStage1(), -10, -10, { diff --git a/apps/red7game/red7.js b/apps/red7game/red7.js index 697d36f97..fc8116cb8 100644 --- a/apps/red7game/red7.js +++ b/apps/red7game/red7.js @@ -486,8 +486,7 @@ function canPlay(hand, palette, otherPalette) { } else { //Check if any palette play can win with rule. for(let h of hand.handCards) { - if(h === c) {} - else { + if(h !== c) { clonePalette.addCard(c); if(isWinningCombo(c, clonePalette, otherPalette)) { return true; @@ -531,8 +530,7 @@ class AI { } else { //Check if any palette play can win with rule. for(let h of this.hand.handCards) { - if(h === c) {} - else { + if(h !== c) { clonePalette.addCard(h); if(isWinningCombo(c, clonePalette, otherPalette)) { ruleStack.addCard(c); diff --git a/apps/spacew/prep/minitar.js b/apps/spacew/prep/minitar.js index 4441a1705..7ac83cb1f 100755 --- a/apps/spacew/prep/minitar.js +++ b/apps/spacew/prep/minitar.js @@ -8,8 +8,6 @@ const hs = require('./heatshrink.js'); if (pc) { fs = require('fs'); var print=console.log; -} else { - } function writeDir(json) { diff --git a/apps/tabanchi/app.js b/apps/tabanchi/app.js index f159052b7..b1a32e71b 100644 --- a/apps/tabanchi/app.js +++ b/apps/tabanchi/app.js @@ -968,8 +968,7 @@ function activateItem () { animateToClock(); break; case 0: // food - if (tama.sleep) { - } else { + if (!tama.sleep) { // evolution = 0; mode = 'food'; lightSelect = 0; @@ -979,8 +978,7 @@ function activateItem () { mode = 'light'; break; case 2: // game - if (tama.sleep) { - } else { + if (!tama.sleep) { animateToGame(); } break; From c94c800a6db81859329793658e4e1eb4707171c6 Mon Sep 17 00:00:00 2001 From: Anton Date: Mon, 26 Feb 2024 20:46:12 +0100 Subject: [PATCH 10/57] Bump app versions --- apps/aptsciclk/ChangeLog | 1 + apps/aptsciclk/metadata.json | 2 +- apps/carcrazy/ChangeLog | 1 + apps/carcrazy/metadata.json | 2 +- apps/doztime/ChangeLog | 1 + apps/doztime/metadata.json | 2 +- apps/hwid_a_battery_widget/ChangeLog | 1 + apps/hwid_a_battery_widget/metadata.json | 2 +- apps/red7game/ChangeLog | 1 + apps/red7game/metadata.json | 2 +- apps/tabanchi/ChangeLog | 1 + apps/tabanchi/metadata.json | 2 +- 12 files changed, 12 insertions(+), 6 deletions(-) diff --git a/apps/aptsciclk/ChangeLog b/apps/aptsciclk/ChangeLog index ed32a45a2..19e7c9469 100644 --- a/apps/aptsciclk/ChangeLog +++ b/apps/aptsciclk/ChangeLog @@ -6,3 +6,4 @@ 0.06: Formatting 0.07: Added potato GLaDOS and quote functionality when you tap her 0.08: Fixed drawing issues with the quotes and added more +0.09: Minor code improvements diff --git a/apps/aptsciclk/metadata.json b/apps/aptsciclk/metadata.json index 77e40f843..edc9704d2 100644 --- a/apps/aptsciclk/metadata.json +++ b/apps/aptsciclk/metadata.json @@ -2,7 +2,7 @@ "id": "aptsciclk", "name": "Apeture Science Clock", "shortName":"AptSci Clock", - "version": "0.08", + "version": "0.09", "description": "A clock based on the portal series", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}], diff --git a/apps/carcrazy/ChangeLog b/apps/carcrazy/ChangeLog index f697617b4..f4fd9ab7b 100644 --- a/apps/carcrazy/ChangeLog +++ b/apps/carcrazy/ChangeLog @@ -1,3 +1,4 @@ 0.01: Car Crazy is now avialable for testing in beta! 0.02: 10 Levels are now added making the game harder as it goes along. Some of the levels include multiple cars and faster cars. More levels coming soon. 0.03: Settings are now added so that you can reset your high score. +0.04: Minor code improvements. diff --git a/apps/carcrazy/metadata.json b/apps/carcrazy/metadata.json index 3898de962..4a1b359c8 100644 --- a/apps/carcrazy/metadata.json +++ b/apps/carcrazy/metadata.json @@ -2,7 +2,7 @@ "id": "carcrazy", "name": "Car Crazy", "shortName": "Car Crazy", - "version": "0.03", + "version": "0.04", "description": "A simple car game where you try to avoid the other cars by tilting your wrist left and right. Hold down button 2 to start.", "icon": "carcrash.png", "tags": "game", diff --git a/apps/doztime/ChangeLog b/apps/doztime/ChangeLog index 77d82eff9..c3701b6d8 100644 --- a/apps/doztime/ChangeLog +++ b/apps/doztime/ChangeLog @@ -5,3 +5,4 @@ 0.05: extraneous comments and code removed display improved now supports Adjust Clock widget, if installed +0.06: minor code improvements diff --git a/apps/doztime/metadata.json b/apps/doztime/metadata.json index a05bf1470..83be15724 100644 --- a/apps/doztime/metadata.json +++ b/apps/doztime/metadata.json @@ -2,7 +2,7 @@ "id": "doztime", "name": "Dozenal Digital Time", "shortName": "Dozenal Digital", - "version": "0.05", + "version": "0.06", "description": "A dozenal Holocene calendar and dozenal diurnal digital clock", "icon": "app.png", "type": "clock", diff --git a/apps/hwid_a_battery_widget/ChangeLog b/apps/hwid_a_battery_widget/ChangeLog index e7cdd2b4b..99601c31b 100644 --- a/apps/hwid_a_battery_widget/ChangeLog +++ b/apps/hwid_a_battery_widget/ChangeLog @@ -8,3 +8,4 @@ 0.08: Handling exceptions 0.09: Add option for showing battery high mark 0.10: Fix background color +0.11: Minor code improvements diff --git a/apps/hwid_a_battery_widget/metadata.json b/apps/hwid_a_battery_widget/metadata.json index 98d7ce2d5..2abc57a9b 100644 --- a/apps/hwid_a_battery_widget/metadata.json +++ b/apps/hwid_a_battery_widget/metadata.json @@ -3,7 +3,7 @@ "name": "A Battery Widget (with percentage) - Hanks Mod", "shortName":"H Battery Widget", "icon": "widget.png", - "version":"0.10", + "version":"0.11", "type": "widget", "supports": ["BANGLEJS", "BANGLEJS2"], "readme": "README.md", diff --git a/apps/red7game/ChangeLog b/apps/red7game/ChangeLog index ffe131874..fffef63d5 100644 --- a/apps/red7game/ChangeLog +++ b/apps/red7game/ChangeLog @@ -4,3 +4,4 @@ 0.04: Update cards to draw rounded on newer firmware. Make sure in-game menu can't be pulled up during end of game. 0.05: add confirmation prompt to new game to prevent fat fingering new game during existing one. 0.06: fix AI logic typo and add prompt to show what AI played each turn. +0.07: Minor code improvements. diff --git a/apps/red7game/metadata.json b/apps/red7game/metadata.json index eeb1cfcb8..5f41740ed 100644 --- a/apps/red7game/metadata.json +++ b/apps/red7game/metadata.json @@ -2,7 +2,7 @@ "name": "Red 7 Card Game", "shortName" : "Red 7", "icon": "icon.png", - "version":"0.06", + "version":"0.07", "description": "An implementation of the card game Red 7 for your watch. Play against the AI and be the last player still in the game to win!", "tags": "game", "supports":["BANGLEJS2"], diff --git a/apps/tabanchi/ChangeLog b/apps/tabanchi/ChangeLog index 4e2facf6f..e5a4c8021 100644 --- a/apps/tabanchi/ChangeLog +++ b/apps/tabanchi/ChangeLog @@ -1,3 +1,4 @@ 0.01: Initial implementation 0.02: Fix app icon 0.03: Fix clock animation issue and reduce source size +0.04: Minor code improvements diff --git a/apps/tabanchi/metadata.json b/apps/tabanchi/metadata.json index f72147162..db81707b5 100644 --- a/apps/tabanchi/metadata.json +++ b/apps/tabanchi/metadata.json @@ -2,7 +2,7 @@ "id": "tabanchi", "name": "Tabanchi", "shortName": "Tabanchi", - "version": "0.03", + "version": "0.04", "type": "app", "description": "Tamagotchi WatchApp", "icon": "app.png", From 97b4369d67a492f535a16cfe2b6a00867b0eb514 Mon Sep 17 00:00:00 2001 From: shansou504 <123512155+shansou504@users.noreply.github.com> Date: Mon, 26 Feb 2024 17:11:44 -0500 Subject: [PATCH 11/57] fixed tab line 49 --- apps/binaryclk/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/binaryclk/app.js b/apps/binaryclk/app.js index 9b953e504..7969fe301 100644 --- a/apps/binaryclk/app.js +++ b/apps/binaryclk/app.js @@ -46,7 +46,7 @@ function draw() { if (settings.hidesq) { c1sqhide = 2; - c3sqhide = 1; + c3sqhide = 1; } if (settings.hidesq) { From b80c4cd824e2c1e84a72d1917187755b5d48b2bc Mon Sep 17 00:00:00 2001 From: "Zachary D. Skelton" Date: Mon, 26 Feb 2024 23:31:21 -0600 Subject: [PATCH 12/57] Applied PR Changes --- apps/fallout_clock/.gitignore | 1 + apps/fallout_clock/CHANGELOG | 11 +++++------ apps/fallout_clock/app-icon.js | 2 +- apps/fallout_clock/metadata.json | 4 ++-- apps/fallout_clock/screenshot.png | Bin 0 -> 2243 bytes 5 files changed, 9 insertions(+), 9 deletions(-) create mode 100644 apps/fallout_clock/screenshot.png diff --git a/apps/fallout_clock/.gitignore b/apps/fallout_clock/.gitignore index 2597f0579..e5f9ba937 100644 --- a/apps/fallout_clock/.gitignore +++ b/apps/fallout_clock/.gitignore @@ -1,4 +1,5 @@ node_modules/ +res/ fallout_clock.code-workspace diff --git a/apps/fallout_clock/CHANGELOG b/apps/fallout_clock/CHANGELOG index ef31b4803..ee9876b1a 100644 --- a/apps/fallout_clock/CHANGELOG +++ b/apps/fallout_clock/CHANGELOG @@ -1,6 +1,5 @@ -Version 0: -0.1.0 - (20240125): Basic Working Clock. -0.1.1 - (20240125): Widgets Added. Improved Interval Loop. -0.1.2 - (20240221): Fix: Month Reporting Wrong. -0.2.0 - (20240223): Created as a Package. -0.2.1 = (20240223): Added StandardJS and NPM. +0.10: (20240125) Basic Working Clock. +0.11: (20240125) Widgets Added. Improved Interval Loop. +0.12: (20240221) Fix: Month Reporting Wrong. +0.20: (20240223) Created as a Package. +0.21: (20240223) Added StandardJS and NPM. diff --git a/apps/fallout_clock/app-icon.js b/apps/fallout_clock/app-icon.js index 9c2b9bc1d..1e95ee2ed 100644 --- a/apps/fallout_clock/app-icon.js +++ b/apps/fallout_clock/app-icon.js @@ -1 +1 @@ -atob('MDDDAb88//9u/1r/1/YZrgAAit4kkkkkkkkkkAAVIkkkkkkkkkkkkkkkkkkAAAARJJIkkkkkkkkkkkkkkkAAAACJJJJUkkkkkkkkkkkkkAAAAARJJJJAAkkkkkkkkkkkAAAAACpJJJKgAAkkkkkkkkkgAAAAAVJJJJIAAAEkkkkkkkkAAAAACpJfpJUAAAAkkkkkkkgAAAAABJf/9JAAAAAEkkkkkkAAAAAARJdf/+gAAAAAkkkkkgAAAAAC//dL//gAAAAAEkkkkAAAAYADpJJL//8AAAAAAkkkkAAAD8AdJJJL///gAAAAAkkkgAAADr/pJJL////0AAAAAEkkgAAABJJL/pfb////gAAAAAkkAAAADpJeu22X////4AAAAAkkAAAADpL1tttuf/7f8AAAAAkgAAAAb/+ttttuSSS7/AAAAAEgAAAAdeyttttySSSb/gAAAAEgAAAC9eWtttuaySSf/2SSSSkgAAAVfxtttttyySX//9JJJQAAAAAJetttttttyST//9JJJUAAAABJeOaNyNutySW//9JJKgAAAARJdu6N1tvRySS3/JJJUAAAACJJVuVu1tzRyST2/JJKAAAAAVJL1ttyttuNuSWW7pJKgAAACpJLxtt6NtttuSS27pJUAAAAVJJLxtt6ttttuSWT9JKgAAAAJJJLxttzNtttuSST9JIAAAAiJJJL1ttttt2NuSSS9JUAAAA2222212xtty3RySSS9KgAAAEgAAAAZ6OW2tu1ySST9QAAAAEgAAAAaW1ttu2VySSXKAAAAAEkAAAACtu221ttySbdKgAAAAEkAAAADNty1ttuST9JUAAAAAkkAAAAAVty1ttuSXpKAAAAAAkkgAAAACtttttyT9JIAAAAAEkkkAAAAARttttyfdJUAAAAAEkkkAAAAACtttuSzJKgAAAAAkkkkgAAAAAWtuSSfpQAAAAAEkkkkkAAAAADa2yT9JAAAAAAkkkkkkgAAAAD7e3/pKgAAAAAkkkkkkkAAAAVL/9JJUAAAAAEkkkkkkkgAAARJJJJKAAAAAEkkkkkkkkkAAAJJJJJIAAAAAkkkkkkkkkkkACpJJJJUAAAAEkkkkkkkkkkkgCJJJJKgAAAEkkkkkkkkkkkkklJJJJQAAAEkkkkkkkkkkkkkkkkpJJAAEkkkkkkkkk=') +atob("MDDDAb88//9u/1r/1/YZrgAAit4kkkkkkkkkkAAVIkkkkkkkkkkkkkkkkkkAAAARJJIkkkkkkkkkkkkkkkAAAACJJJJUkkkkkkkkkkkkkAAAAARJJJJAAkkkkkkkkkkkAAAAACpJJJKgAAkkkkkkkkkgAAAAAVJJJJIAAAEkkkkkkkkAAAAACpJfpJUAAAAkkkkkkkgAAAAABJf/9JAAAAAEkkkkkkAAAAAARJdf/+gAAAAAkkkkkgAAAAAC//dL//gAAAAAEkkkkAAAAYADpJJL//8AAAAAAkkkkAAAD8AdJJJL///gAAAAAkkkgAAADr/pJJL////0AAAAAEkkgAAABJJL/pfb////gAAAAAkkAAAADpJeu22X////4AAAAAkkAAAADpL1tttuf/7f8AAAAAkgAAAAb/+ttttuSSS7/AAAAAEgAAAAdeyttttySSSb/gAAAAEgAAAC9eWtttuaySSf/2SSSSkgAAAVfxtttttyySX//9JJJQAAAAAJetttttttyST//9JJJUAAAABJeOaNyNutySW//9JJKgAAAARJdu6N1tvRySS3/JJJUAAAACJJVuVu1tzRyST2/JJKAAAAAVJL1ttyttuNuSWW7pJKgAAACpJLxtt6NtttuSS27pJUAAAAVJJLxtt6ttttuSWT9JKgAAAAJJJLxttzNtttuSST9JIAAAAiJJJL1ttttt2NuSSS9JUAAAA2222212xtty3RySSS9KgAAAEgAAAAZ6OW2tu1ySST9QAAAAEgAAAAaW1ttu2VySSXKAAAAAEkAAAACtu221ttySbdKgAAAAEkAAAADNty1ttuST9JUAAAAAkkAAAAAVty1ttuSXpKAAAAAAkkgAAAACtttttyT9JIAAAAAEkkkAAAAARttttyfdJUAAAAAEkkkAAAAACtttuSzJKgAAAAAkkkkgAAAAAWtuSSfpQAAAAAEkkkkkAAAAADa2yT9JAAAAAAkkkkkkgAAAAD7e3/pKgAAAAAkkkkkkkAAAAVL/9JJUAAAAAEkkkkkkkgAAARJJJJKAAAAAEkkkkkkkkkAAAJJJJJIAAAAAkkkkkkkkkkkACpJJJJUAAAAEkkkkkkkkkkkgCJJJJKgAAAEkkkkkkkkkkkkklJJJJQAAAEkkkkkkkkkkkkkkkkpJJAAEkkkkkkkkk=") // eslint-disable-line diff --git a/apps/fallout_clock/metadata.json b/apps/fallout_clock/metadata.json index f8de71f06..fe6115a9c 100644 --- a/apps/fallout_clock/metadata.json +++ b/apps/fallout_clock/metadata.json @@ -5,7 +5,7 @@ "description":"A simple clock for the Fallout fan", "icon":"icon.png", "type":"clock", - "tags": ["clock", "fallout", "green"], + "tags": "clock,fallout,green,retro", "supports": ["BANGLEJS2"], "readme": "README.md", "storage": [ @@ -13,6 +13,6 @@ {"name":"fallout_clock.img", "url":"app-icon.js", "evaluate":true} ], "screenshots": [ - {"url":"./res/screenshot.png", "name":"Fallout Clock Screenshot"} + {"url":"./screenshot.png", "name":"Fallout Clock Screenshot"} ] } \ No newline at end of file diff --git a/apps/fallout_clock/screenshot.png b/apps/fallout_clock/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..253554b728b4b7da36902477bc6cdc87107a9eba GIT binary patch literal 2243 zcmd^BSyYqP7CuQNVWvo#1f*0MR8TB3lYq)71QeMkqcVsLVM>LBK!7UZwcrwrI1r{b zARti?L}d7DQA7%nAz=_=1Z;&s0zp6$1I=Cc=|1-1KHZ12_uA|1v-fxQTHpCj!AWm7 zCHY zunz{P@l_`E2yow0JIzBGJc?9v36|cyp|8R-1yBs{nY>v5AO?#Jzli{*6V9gsP{1bc zhyPhiCq$4W;a2{8U6Xx}u8np+6xWVbliEVJ*)eJQr0ouLc&(uZ*L}6a=m8~!Fcj^` za*NaukX+VO7X_A}TZgZ{E2>21B9F-6vn4cs%-(;wClzh&*v!;}(69Ve#ELVD=(WgX z!;Tz$ejIFFE710n&j`lz49%2Jv6h|D1%XPzwsgP6rNjY5ubdKh$XHkmJs)VQ&@o^A z%w~y5C-5}_J7|x-@ArTo|8|B@$CJ-g4NfoIbB&%e+hYU0NlUy#w?cJ@Qlm3Oej3z9 z@2lql|8h{Qd^#bWlzNh#LFfD9dBtK3%6wS_`PG}9VIp%|jNlw>_Hsl9ELvFidMh*r zHjGG0(?IXiNd!syMj3$_A0932sS(JW)}pLdjo17E7usMu*T{8SXVjk@0wjd31xBRK zV;%WnBG)O!Q+d+b7z(D?(1m@UYb-;Zo)p5_?e!x0$qj9a*$Th+S!#~;eRoRvG9-o# z@`|jl0LL+8I=)Sv3cpWKS>rv7_@;z-s3R~leYIn#M*_3iIa7-t+3!TWNbDBV9d7K_ z0}eCPwpPs-970tCzezP5bTpIkSA=$a@A#xj^$=#D0c~My;icWM3D0fuAPL!eUFWdj zxrE51OE2D4+k>jae#Cm#pNjFYDYc(^T@>nGO9WH>v%dw1OS&q^sc_RQ_);J55*8Xc zw3I!Dxmj9V_1%rBcc>)=$n39bx;ZGfSA_U6TkmC#BD4IGdw1tqeKqY4jp1f7v0UTp z@ACC7oGY%hUkA9=%@NZDx&DyUkHO=U_A|25+z`7TS>Yjh8-3^;2Ha-6N2nH*q2n5P zc9ZkCw;9yGA{=2WvC2p;UKym;1$9keL}tYtSXi!BhKP!@xAa_TiFM#`V?cKv>$V$% zz`(N9H>L<*9U$7i1~tYjS)T-8Hx` zJE-tC)9vcmdDtL$9QDh_y`7ixD!iQQduf5)P563O)@eA`*r4^gAI^buJlJAq7Bi%t zDM2&Xf+1fd_qj1da%8z5csl{Q_A9XPA7BHi$i#w{3e~&u)byXj=4F$kCogD3bYG62 z1sYcOs^(046mmV5ZfVXbNMPL2U%nfZQrj%QjV65$z4cUPOi^Gw0(o6|xI|%RT*!rq9Jz3g7#f@8iAyus-Ut^nAK^ zIC+X$hYt@V9N3HYE7rli{5Gm8vz?io8?5G5cAdK3Om>W&pB@wMslZQH(?U8?5e${( z=r$Re%u1Fp1gUR)*Pr2S$LnGf1el9te71E%y-HHglV#5Dp#rpVHc^YTo`^j=2w6Lv z6U)Vwt(n@gMN92O4K%x6ZD6=^{V-7@U@e5WyMvYuKTzJpDu~kV>}F1j>x$QcYCcVg zF!X^Ptyi@=IHW)0u=Jz0-TnUI3qN7JGd*K?*s~8;yMjkCEb^h+esm7&K_uDfolk{{ znppyStvNq_dwY;xy>?51i3%3X6$;J1U^ZdvnFPpg#N|$nH=QFl6*4wC_Ppq0-eftU zT&M9b)cE-q6WUCRSO=0`jp+5nXEGy!xS!Y=Lx^k2ChDZqiAC9YaYE^!2ZMN~vE&6o zXJT1P=Y~JC_92-iF}+X8~I9xmR_jmL1ge*+z5 BIx+wN literal 0 HcmV?d00001 From 03bf02eb222aef10494c13c476258f2bb2b12cdd Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Tue, 27 Feb 2024 08:13:21 +0100 Subject: [PATCH 13/57] swipeinv: new app Inverts swipe direction globally or per app --- apps/swipeinv/boot.js | 19 ++++++++++++ apps/swipeinv/metadata.json | 17 +++++++++++ apps/swipeinv/settings.js | 58 +++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 apps/swipeinv/boot.js create mode 100644 apps/swipeinv/metadata.json create mode 100644 apps/swipeinv/settings.js diff --git a/apps/swipeinv/boot.js b/apps/swipeinv/boot.js new file mode 100644 index 000000000..fb64f920d --- /dev/null +++ b/apps/swipeinv/boot.js @@ -0,0 +1,19 @@ +{ + const settings = Object.assign({ + global: false, + apps: [] + }, require("Storage").readJSON("swipeinv.json", true) || {}); + + if (settings.global || settings.apps.length > 0) { + const setURIOrig = Bangle.setUI; + Bangle.setUI = (mode, callback) => { + if (typeof mode === "object" && mode.swipe) { + if (settings.global ^ settings.apps.includes(global.__FILE__)) { + const origSwipeCb = mode.swipe; + mode.swipe = (dirLR, dirUD) => origSwipeCb(dirLR*-1, dirUD*-1); + } + } + return setURIOrig(mode, callback); + }; + } +} diff --git a/apps/swipeinv/metadata.json b/apps/swipeinv/metadata.json new file mode 100644 index 000000000..32619b916 --- /dev/null +++ b/apps/swipeinv/metadata.json @@ -0,0 +1,17 @@ +{ + "id": "swipeinv", + "name": "Swipe inversion", + "shortName":"Swipe inv.", + "icon": "app.png", + "version":"0.01", + "description": "Inverts swipe direction globally or per app, see settings. If global inversion is enabled, you can unselect the inversion per app and vice versa.", + "type": "bootloader", + "tags": "system", + "supports": ["BANGLEJS2"], + "storage": [ + {"name":"swipeinv.boot.js","url":"boot.js"}, + {"name":"swipeinv.settings.js","url":"settings.js"} + ], + "data": [{"name":"swipeinv.json"}] +} + diff --git a/apps/swipeinv/settings.js b/apps/swipeinv/settings.js new file mode 100644 index 000000000..6ce16d00a --- /dev/null +++ b/apps/swipeinv/settings.js @@ -0,0 +1,58 @@ +(function(back) { + var FILE = "swipeinv.json"; + // Load settings + const settings = Object.assign({ + global: false, + apps: [] + }, require("Storage").readJSON(FILE, true) || {}); + + function writeSettings() { + require('Storage').writeJSON(FILE, settings); + } + + function appMenu() { + menu = { + "" : { "title" : /*LANG*/"Swipe inversion apps" }, + "< Back" : () => { writeSettings(); mainMenu();} + }; + require("Storage").list(/\.info$/).map(app=>require("Storage").readJSON(app,1)).filter(app => app.type === "app" || !app.type).sort((a,b) => { + if (a.nameb.name) return 1; + return 0; + }).forEach(app => { + menu[app.name] = { + value: settings.apps.includes(app.src), + onchange: v => { + if (v) { + settings.apps.push(app.src); + } else { + const idx = settings.apps.indexOf(app.src); + if (idx !== -1) { + settings.apps.splice(idx, 1); + } + } + } + }; + }); + E.showMenu(menu); + } + + function mainMenu() { + E.showMenu({ + "" : { "title" : /*LANG*/"Swipe inversion" }, + "< Back" : () => back(), + + /*LANG*/'Invert globally': { + value: !!settings.global, + onchange: v => { + settings.global = v; + writeSettings(); + } + }, + + /*LANG*/'Select apps': () => appMenu() + }); + } + + mainMenu(); +}) From 64c0e844d0eeccc4529da9aad57933f133b7290c Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Tue, 27 Feb 2024 18:53:26 +0100 Subject: [PATCH 14/57] swipeinv: add icon --- apps/swipeinv/app.png | Bin 0 -> 1058 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/swipeinv/app.png diff --git a/apps/swipeinv/app.png b/apps/swipeinv/app.png new file mode 100644 index 0000000000000000000000000000000000000000..a23f71111cb37a2cc8e1baea062ae1a754d16b8d GIT binary patch literal 1058 zcmV+-1l{|IP)`ax<~?Ef*7lt8ch=-sh4;mmPl->#(Hh7Hr`8AV&Xj}QnXP)4Y3xG6jY%6 zX22teEXG}S&sp6snTI_mvuD0DxBs6*NSv5HJ@_#du$&3l!h{N$rkPHX1UAHd`JZ}=|<Ql<0>um(`<`tpMox2S$ug7f| znWmX;2><611w~*26#@39!UUA*hRz8UCsts%Fu3|UCEz5f9&nme4>(P#2b|`e?14xB zHuZ%WmdYT>CZN&3^>r%XKPKcJ#%0(L%0JZ%enJRIBW@SCQCo+Btl5JHe_XaQ4(D|8 zL%A%-6z~OOYP72aG%YQUao@q;adp{R%r97orY|^TL`wzSrUJH2^}<9~2n?jNvlDOq zeH)LSIE@vR+i}UaD{*FS{_7%Kwoy+2Tqh8T=H?c>c=;;s*u4*P@B_Z1|GcfO9gm-?#-%G(q3O#) z3vzJt)++4k>T-bqSL5tAT3dH>*cy~D0YXR`6L3pcUQ`;!d-oqCodD4hBjxbF-4l9< zgo;YAeEnuTa`Xf?HMh81K%?W3NN1ylrLbh#N<33@9=p4{-6^06hr=V7M@=$>R8+us zdLQTsgZs(MEnJKjE?sq}K*aM@E8t~99=2C2UCP&O!nXEy_X`Z%@EDiXwnTnt0X8;1 z92SAS2M*c6++QS~^b9j0i|wy7I<~KGxF54XW!2C2j(>(E0xIB3`zwtOg&+R&C?kNhCT_wf7L6T}4B~y$5|kqvfAM5)I>O zgS#!{cn$oj}Iaz7wWppzZO)hsI1+-M5pYF7V* zDd8{< Date: Tue, 27 Feb 2024 22:12:09 +0000 Subject: [PATCH 15/57] sanitycheck: avoid error after emitting changelog error --- bin/sanitycheck.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index 78cadc34c..3bb9a822a 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -150,10 +150,13 @@ apps.forEach((app,appIdx) => { } else { var changeLog = fs.readFileSync(appDir+"ChangeLog").toString(); var versions = changeLog.match(/\d+\.\d+:/g); - if (!versions) ERROR(`No versions found in ${app.id} ChangeLog (${appDir}ChangeLog)`, {file:metadataFile}); - var lastChangeLog = versions.pop().slice(0,-1); - if (lastChangeLog != app.version) - ERROR(`App ${app.id} app version (${app.version}) and ChangeLog (${lastChangeLog}) don't agree`, {file:appDirRelative+"ChangeLog", line:changeLog.split("\n").length-1}); + if (!versions) { + ERROR(`No versions found in ${app.id} ChangeLog (${appDir}ChangeLog)`, {file:metadataFile}); + } else { + var lastChangeLog = versions.pop().slice(0,-1); + if (lastChangeLog != app.version) + ERROR(`App ${app.id} app version (${app.version}) and ChangeLog (${lastChangeLog}) don't agree`, {file:appDirRelative+"ChangeLog", line:changeLog.split("\n").length-1}); + } } } if (!app.description) ERROR(`App ${app.id} has no description`, {file:metadataFile}); From 2063cca87f8ec46fc1286fba29de2347166e7175 Mon Sep 17 00:00:00 2001 From: signaleleven Date: Wed, 28 Feb 2024 09:47:26 +0100 Subject: [PATCH 16/57] linuxclock - Bugfix Add 1 to month received from Date.getMonth (0..11) --- apps/linuxclock/ChangeLog | 1 + apps/linuxclock/app.js | 2 +- apps/linuxclock/metadata.json | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/linuxclock/ChangeLog b/apps/linuxclock/ChangeLog index 5529034be..d4ae7213e 100644 --- a/apps/linuxclock/ChangeLog +++ b/apps/linuxclock/ChangeLog @@ -3,3 +3,4 @@ 0.03: Update clock_info to avoid a redraw 0.04: Fix clkinfo -- use .get instead of .show 0.05: Use clock_info module as an app +0.06: Fix month in date (jan 0 -> 1, etc) \ No newline at end of file diff --git a/apps/linuxclock/app.js b/apps/linuxclock/app.js index cea33fe3a..67202dac1 100644 --- a/apps/linuxclock/app.js +++ b/apps/linuxclock/app.js @@ -112,7 +112,7 @@ function getTime(){ function getDate(){ var date = new Date(); - return twoD(date.getDate()) + "." + twoD(date.getMonth()); + return twoD(date.getDate()) + "." + twoD(date.getMonth() + 1); } function getDay(){ diff --git a/apps/linuxclock/metadata.json b/apps/linuxclock/metadata.json index ccd9db5e7..422306977 100644 --- a/apps/linuxclock/metadata.json +++ b/apps/linuxclock/metadata.json @@ -1,7 +1,7 @@ { "id": "linuxclock", "name": "Linux Clock", - "version": "0.05", + "version": "0.06", "description": "A Linux inspired clock.", "readme": "README.md", "icon": "app.png", From 3a4504953b5bfa1812bd9ff03cf7822ac11f5a1e Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 28 Feb 2024 20:52:47 +0000 Subject: [PATCH 17/57] rep: fix interface.html --- apps/rep/interface.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/rep/interface.html b/apps/rep/interface.html index e14fea4c9..5356b091f 100644 --- a/apps/rep/interface.html +++ b/apps/rep/interface.html @@ -101,7 +101,8 @@ function getData() { uploadBtn.disabled = true; Util.showModal("Loading..."); - Util.readStorageJSON(repJson, reps => { + Util.readStorageJSON(repJson, reps_ => { + reps = reps_; Util.hideModal(); for(const rep of reps){ renderRep(rep); From 44ebbe3a6d3174afa1eeadd08dc5ab7226258f48 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 28 Feb 2024 22:35:06 +0000 Subject: [PATCH 18/57] sched: update README based on latest settings --- apps/sched/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sched/README.md b/apps/sched/README.md index 2fb201cee..a7f90af09 100644 --- a/apps/sched/README.md +++ b/apps/sched/README.md @@ -14,9 +14,9 @@ Global Settings --------------- - `Unlock at Buzz` - If `Yes` the alarm/timer will unlock the watch +- `Delete Expired Timers` - Default for whether expired timers are removed after firing. - `Default Auto Snooze` - Default _Auto Snooze_ value for newly created alarms (_Alarms_ only) - `Default Snooze` - Default _Snooze_ value for newly created alarms/timers -- `Default Repeat` - Default _Repeat_ value for newly created alarms (_Alarms_ only) - `Buzz Count` - The number of buzzes before the watch goes silent - `Buzz Interval` - The interval between one buzz and the next - `Default Alarm/Timer Pattern` - Default vibration pattern for newly created alarms/timers From 40b718ed49a9ede706b8efa99ee26666dfe82dae Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 28 Feb 2024 22:35:11 +0000 Subject: [PATCH 19/57] sched: add setting to buzz forever when alarm is fired --- apps/sched/ChangeLog | 1 + apps/sched/README.md | 2 +- apps/sched/metadata.json | 2 +- apps/sched/sched.js | 2 +- apps/sched/settings.js | 5 +++-- typescript/types/sched.d.ts | 2 +- 6 files changed, 8 insertions(+), 6 deletions(-) diff --git a/apps/sched/ChangeLog b/apps/sched/ChangeLog index 92b04fb32..1d1c53ac1 100644 --- a/apps/sched/ChangeLog +++ b/apps/sched/ChangeLog @@ -23,3 +23,4 @@ 0.20: Alarm dismiss and snooze events 0.21: Fix crash in clock_info 0.22: Dated event repeat option +0.23: Allow buzzing forever when an alarm fires diff --git a/apps/sched/README.md b/apps/sched/README.md index a7f90af09..1216a1a11 100644 --- a/apps/sched/README.md +++ b/apps/sched/README.md @@ -17,7 +17,7 @@ Global Settings - `Delete Expired Timers` - Default for whether expired timers are removed after firing. - `Default Auto Snooze` - Default _Auto Snooze_ value for newly created alarms (_Alarms_ only) - `Default Snooze` - Default _Snooze_ value for newly created alarms/timers -- `Buzz Count` - The number of buzzes before the watch goes silent +- `Buzz Count` - The number of buzzes before the watch goes silent, or "forever" to buzz until stopped. - `Buzz Interval` - The interval between one buzz and the next - `Default Alarm/Timer Pattern` - Default vibration pattern for newly created alarms/timers diff --git a/apps/sched/metadata.json b/apps/sched/metadata.json index aa286ce6a..7f94a0a18 100644 --- a/apps/sched/metadata.json +++ b/apps/sched/metadata.json @@ -1,7 +1,7 @@ { "id": "sched", "name": "Scheduler", - "version": "0.22", + "version": "0.23", "description": "Scheduling library for alarms and timers", "icon": "app.png", "type": "scheduler", diff --git a/apps/sched/sched.js b/apps/sched/sched.js index bd84c3e47..88d3b90cd 100644 --- a/apps/sched/sched.js +++ b/apps/sched/sched.js @@ -71,7 +71,7 @@ function showAlarm(alarm) { const pattern = alarm.vibrate || (alarm.timer ? settings.defaultTimerPattern : settings.defaultAlarmPattern); require("buzz").pattern(pattern).then(() => { - if (buzzCount--) { + if (buzzCount == null || buzzCount--) { setTimeout(buzz, settings.buzzIntervalMillis); } else if (alarm.as) { // auto-snooze buzzCount = settings.buzzCount; diff --git a/apps/sched/settings.js b/apps/sched/settings.js index 83e4289f2..1650bfd8e 100644 --- a/apps/sched/settings.js +++ b/apps/sched/settings.js @@ -44,11 +44,12 @@ /*LANG*/"Buzz Count": { value: settings.buzzCount, - min: 5, + min: 4, max: 15, step: 1, + format: v => v === 4 ? "Forever" : v, onchange: v => { - settings.buzzCount = v; + settings.buzzCount = v === 4 ? null : v; require("sched").setSettings(settings); } }, diff --git a/typescript/types/sched.d.ts b/typescript/types/sched.d.ts index 78ad0c8d4..c2cd23d35 100644 --- a/typescript/types/sched.d.ts +++ b/typescript/types/sched.d.ts @@ -87,7 +87,7 @@ declare module Sched { defaultSnoozeMillis: number, defaultAutoSnooze: boolean, defaultDeleteExpiredTimers: boolean, - buzzCount: number, + buzzCount: number | null, // null means buzz forever buzzIntervalMillis: number, defaultAlarmPattern: string, defaultTimerPattern: string, From 1c28933dfd83091f2114d28da362a00b5ed4d1c8 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 28 Feb 2024 22:52:05 +0000 Subject: [PATCH 20/57] settings: fix typo --- apps/setting/ChangeLog | 3 ++- apps/setting/metadata.json | 2 +- apps/setting/settings.js | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index 2e6c76997..ee91834e7 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -77,4 +77,5 @@ of 'Select Clock' calibration was done. 0.67: Rename 'Wake on BTN1/Touch' to 'Wake on Button/Tap' on Bangle.js 2 0.68: Fix syntax error -0.69: Add option to wake on double tap \ No newline at end of file +0.69: Add option to wake on double tap +0.70: Fix load() typo diff --git a/apps/setting/metadata.json b/apps/setting/metadata.json index 1a850af83..7608a0766 100644 --- a/apps/setting/metadata.json +++ b/apps/setting/metadata.json @@ -1,7 +1,7 @@ { "id": "setting", "name": "Settings", - "version": "0.69", + "version": "0.70", "description": "A menu for setting up Bangle.js", "icon": "settings.png", "tags": "tool,system", diff --git a/apps/setting/settings.js b/apps/setting/settings.js index 7726822f4..df7fe2b3e 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -641,7 +641,7 @@ function showUtilMenu() { storage.writeJSON("setting.json",s); E.showAlert(/*LANG*/"Calibrated!").then(() => load("setting.app.js")); } else { - E.showAlert(/*LANG*/"Please charge Bangle.js for 3 hours and try again").then(() => load("settings.app.js")); + E.showAlert(/*LANG*/"Please charge Bangle.js for 3 hours and try again").then(() => load("setting.app.js")); } }); }; From 5240c4b1d307c7e39394a59585cb02487f1b9da0 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Wed, 28 Feb 2024 20:52:46 +0100 Subject: [PATCH 21/57] autoreset: bootloader app - universal timeout to clock face --- apps/autoreset/ChangeLog | 1 + apps/autoreset/README.md | 21 +++++++++++++++++++++ apps/autoreset/app.png | Bin 0 -> 1448 bytes apps/autoreset/boot.js | 20 ++++++++++++++++++++ apps/autoreset/metadata.json | 13 +++++++++++++ 5 files changed, 55 insertions(+) create mode 100644 apps/autoreset/ChangeLog create mode 100644 apps/autoreset/README.md create mode 100644 apps/autoreset/app.png create mode 100644 apps/autoreset/boot.js create mode 100644 apps/autoreset/metadata.json diff --git a/apps/autoreset/ChangeLog b/apps/autoreset/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/autoreset/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/autoreset/README.md b/apps/autoreset/README.md new file mode 100644 index 000000000..965b2e291 --- /dev/null +++ b/apps/autoreset/README.md @@ -0,0 +1,21 @@ +# Auto Reset + +Sets a timeout to load the clock face. The timeout is stopped and started again upon user input. + +## Usage + +Install with app loader and Auto Reset will run in background. If you don't interact with the watch it will time out to the clock face after 10 minutes. + +## TODO + +- Add settings page + - set how many minutes the timeout should count down. + - whitelist/blacklist for apps. + +## Requests + +Mention @thyttan in an issue on the espruino/BangleApps repo for bug reports and feature requests. + +## Creator + +thyttan diff --git a/apps/autoreset/app.png b/apps/autoreset/app.png new file mode 100644 index 0000000000000000000000000000000000000000..695c49931c8aabdcba329c0ff99ae7bf996f5157 GIT binary patch literal 1448 zcmV;Z1y}lsP)|yv{f=N=51Mo}pGwdcOEJd)b*Y zUe-S6Y{v)xu;5(QUhDtcd+l$3>)XJ&&UGf_2_PH5`v7_X`~+YFfK_e$c@{u7fcF4o z0Pw&W&~pGj0bl_@8r$yxJ^~Q-B#b``;A;R6g`wEkSh{xY8nw5#)8ynNZES3i)oP{v z{e4nk9>1K{h*Gq0Er3=CA(vaGVQvM4`4U%LP3=qLpQ1PF+4 zU3DdtWfK$>L=PT3AiZ_(-aYd7_ZJXfIBWh@v23)Qd1qxdo5{z=M?e%i6DpNxbL-YE zI&C#IH3@)a08cvt@C^@e`SRsMCrC?6BZI*}D=RCy09dV7%FWFc5T7~ngnh_yetv%b z&0la;{}5)yQSn3vT~ta(q7+l-Bk9Xt4GKnx5F2!LMzxXS?K2tzW`8^UU}Qh0c{fH24a)N^M}%w(lE zL~U)Y0C-ylpqD#yR;fjLLbSHF3V=2l0N#wy^z^jmiS&Xno6Q1XTn6Az?!39V>Cj}h z5T2f%O8(T>*XI;~#bOZvODCCk1F+}j=0CWFhQsDNIy#i? zB!}JJ-rj@XxhxYJ8Y%$#WB|CjrW`ObGD4@J+qZAqmRBewB;?>f4gfYc@S8FKS>k~5 z@^anHn@pyIkXv70Pa=#96%`fP0wl=*aLT&K2k=?py3J{rZ)j*xmJ5I8O$=*%d|ZK1 z&Ht=MNhy6Ss4rf;sQa>MXlPJ=697lFJL*1NN?~fvQaSkM&6~QLw|xp91F;F{995DNuqj@Kn6B{VoVs8kPR#o>}4T5f8L7Z4|eQHqL+qMn`} z>gwtezj4|lE#519dDP&%>$-B~ic&}Ah{f6I&d!d~mX?;3dxx{inwlC43k!Sfc%#v% zoP^^5#8dkE_3Pq0SL`&4L)gkm6FJiA)l@=bb4bqs_#D7LdVt`6W4v_Z0K5)h%9Q{@ z!2mu4@T&s`=K&Z2ye2kLHjUpc+l%v{H|+XK?GI!Vz!U)QsPTD1t?TcojX(dW7N*_; z@Vs4O_Ob?JFRK4@djV%iMF1Am7vP0Y+RV8iss8|gJHvm^7pf`%0000{ + if (timeoutAutoreset) clearTimeout(timeoutAutoreset); + setTimeout(()=>{ // Short outer timeout to make sure we have time to leave clock face before checking `Bangle.CLOCK!=1`. + if (Bangle.CLOCK!=1) { // Only add timeout if not already on clock face. + timeoutAutoreset = setTimeout(()=>{ + if (Bangle.CLOCK!=1) Bangle.showClock(); + }, 10*60*1000); + } + },200); +}; + +Bangle.on('touch', resetTimeoutAutoreset); +Bangle.on('swipe', resetTimeoutAutoreset); +Bangle.on('message', resetTimeoutAutoreset); +setWatch(resetTimeoutAutoreset, BTN, {repeat:true, edge:'rising'}); + +if (Bangle.CLOCK!=1) resetTimeoutAutoreset(); +} diff --git a/apps/autoreset/metadata.json b/apps/autoreset/metadata.json new file mode 100644 index 000000000..ca35b4d7a --- /dev/null +++ b/apps/autoreset/metadata.json @@ -0,0 +1,13 @@ +{ "id": "autoreset", + "name": "Auto Reset", + "version":"0.01", + "description": "Sets a timeout to load the clock face. The timeout is stopped and started again upon user input.", + "icon": "app.png", + "type": "bootloader", + "tags": "system", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"autoreset.boot.js","url":"boot.js"} + ] +} From 0f40ab025e3243564aaed3558b322ea1cca1b43f Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Thu, 29 Feb 2024 02:41:24 +0100 Subject: [PATCH 22/57] swipeinv: add README --- apps/swipeinv/README.md | 27 +++++++++++++++++++++++++++ apps/swipeinv/metadata.json | 1 + 2 files changed, 28 insertions(+) create mode 100644 apps/swipeinv/README.md diff --git a/apps/swipeinv/README.md b/apps/swipeinv/README.md new file mode 100644 index 000000000..389c4bb6e --- /dev/null +++ b/apps/swipeinv/README.md @@ -0,0 +1,27 @@ +# Swipe Inversion + +Inverts swipe direction globally or per app, see settings. If global inversion is enabled, you can unselect the inversion per app and vice versa. + +## Limitations + +Swipe Inversion can only invert directions on apps that use `Bangle.setUI` to set up swipes. Swipes set up with `Bangle.on("swipe", ...)` is currently not managed. + +Swiping behavior that uses the `drag` event is not altered either. + +## TODO + +- Try to handle swipes from `Bangle.on("swipe", ...)` + - alternatively refactor apps using that to only use `Bangle.setUI` for setting up swipes. + - Think about how to accommodate e.g. `touch` or `back` handlers set up in `Layout` library calls. They are removed if we refactor some `Bangle.on("swipe", ...)` to `Bangle.setUI`. (Is it maybe resolved if we call `Bangle.setUI` before the `Layout` call? - have not tested that yet.) +- Add bootloader apps and widgets to the list of apps that can be individually toggled in settings? + +## Requests + +Bug reports and feature requests should be done to the espruino/BangleApps github issue tracker. + +## Creator + +nxdefiant + +## Contributors + diff --git a/apps/swipeinv/metadata.json b/apps/swipeinv/metadata.json index 32619b916..bbd6f03ce 100644 --- a/apps/swipeinv/metadata.json +++ b/apps/swipeinv/metadata.json @@ -5,6 +5,7 @@ "icon": "app.png", "version":"0.01", "description": "Inverts swipe direction globally or per app, see settings. If global inversion is enabled, you can unselect the inversion per app and vice versa.", + "readme":"README.md", "type": "bootloader", "tags": "system", "supports": ["BANGLEJS2"], From 907ebd34f54179626db20b1da1cb2570838cc5b4 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Mon, 26 Feb 2024 21:51:54 +0100 Subject: [PATCH 23/57] messagegui: swipe up/down on msg goes to newer/older msg messagegui: small refactor of swipeHandler `if (ud!=0)` -> `if (ud>0) ... if (ud<0)` --- apps/messagegui/ChangeLog | 4 +++- apps/messagegui/README.md | 1 + apps/messagegui/app.js | 7 +++++-- apps/messagegui/metadata.json | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/apps/messagegui/ChangeLog b/apps/messagegui/ChangeLog index ea6b0fe43..cbf38af45 100644 --- a/apps/messagegui/ChangeLog +++ b/apps/messagegui/ChangeLog @@ -101,4 +101,6 @@ 0.72: Nav message updastes don't automatically launch navigation menu unless they're new 0.73: Add sharp left+right nav icons 0.74: Add option for driving on left (affects roundabout icons in navigation) -0.75: Handle text with images in messages list by just displaying the first line \ No newline at end of file +0.75: Handle text with images in messages list by just displaying the first line +0.76: Swipe up/down on a shown message to show the next newer/older message. + diff --git a/apps/messagegui/README.md b/apps/messagegui/README.md index 699588e1b..801ebfb2a 100644 --- a/apps/messagegui/README.md +++ b/apps/messagegui/README.md @@ -38,6 +38,7 @@ When a message is shown, you'll see a screen showing the message title and text. * The 'back-arrow' button (or physical button on Bangle.js 2) goes back to Messages, marking the current message as read. * The top-left icon shows more options, for instance deleting the message of marking unread * On Bangle.js 2 you can tap on the message body to view a scrollable version of the title and text (or can use the top-left icon + `View Message`) +- On Bangle.js 2 swipe up/down to show newer/older message * If shown, the 'tick' button: * **Android** opens the notification on the phone * **iOS** responds positively to the notification (accept call/etc) diff --git a/apps/messagegui/app.js b/apps/messagegui/app.js index 5596510c5..330c9677f 100644 --- a/apps/messagegui/app.js +++ b/apps/messagegui/app.js @@ -289,7 +289,8 @@ function showMessageSettings(msg) { } function showMessage(msgid) { - var msg = MESSAGES.find(m=>m.id==msgid); + let idx = MESSAGES.findIndex(m=>m.id==msgid); + var msg = MESSAGES[idx]; if (updateLabelsInterval) { clearInterval(updateLabelsInterval); updateLabelsInterval=undefined; @@ -389,9 +390,11 @@ function showMessage(msgid) { {type:"h",fillx:1, c: footer} ]},{back:goBack}); - Bangle.swipeHandler = lr => { + Bangle.swipeHandler = (lr,ud) => { if (lr>0 && posHandler) posHandler(); if (lr<0 && negHandler) negHandler(); + if (ud>0 && idx0) showMessage(MESSAGES[idx-1].id); }; Bangle.on("swipe", Bangle.swipeHandler); g.reset().clearRect(Bangle.appRect); diff --git a/apps/messagegui/metadata.json b/apps/messagegui/metadata.json index 6f2cb5d2e..1bf9b84d9 100644 --- a/apps/messagegui/metadata.json +++ b/apps/messagegui/metadata.json @@ -2,7 +2,7 @@ "id": "messagegui", "name": "Message UI", "shortName": "Messages", - "version": "0.75", + "version": "0.76", "description": "Default app to display notifications from iOS and Gadgetbridge/Android", "icon": "app.png", "type": "app", From a51405967ca5442120c7dc36f53bf9c179c7fa67 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Thu, 29 Feb 2024 23:15:28 +0000 Subject: [PATCH 24/57] multitimer: add setting for initial screen This also updates multitimer.json to hold settings as well as stopwatches. --- apps/multitimer/ChangeLog | 1 + apps/multitimer/app.js | 38 +++++++++++++++++++++++++++++------ apps/multitimer/metadata.json | 3 ++- apps/multitimer/settings.js | 31 ++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 7 deletions(-) create mode 100644 apps/multitimer/settings.js diff --git a/apps/multitimer/ChangeLog b/apps/multitimer/ChangeLog index 67b0cc014..fff0d3d23 100644 --- a/apps/multitimer/ChangeLog +++ b/apps/multitimer/ChangeLog @@ -6,3 +6,4 @@ 0.06: Support fastloading 0.07: Fix fastloading support - ensure drag handler's restored after menu display/fastload removes it +0.08: Add setting for initial page to display diff --git a/apps/multitimer/app.js b/apps/multitimer/app.js index 965a12d26..99830cea1 100644 --- a/apps/multitimer/app.js +++ b/apps/multitimer/app.js @@ -328,9 +328,21 @@ function editTimer(idx, a) { setUI(); } +function readAndConvJson() { + let json = require("Storage").readJSON("multitimer.json", true); + + if (Array.isArray(json)) { + // old format, convert + json = { sw: json }; + require("Storage").writeJSON("multitimer.json", json); + } + + return json; +} + function drawSw() { layer = 1; - const sw = require("Storage").readJSON("multitimer.json", true) || []; + const sw = readAndConvJson().sw; function updateTimers(idx) { if (!timerInt1[idx]) timerInt1[idx] = setTimeout(function() { @@ -382,12 +394,14 @@ function drawSw() { function swMenu(idx, a) { layer = -1; - const sw = require("Storage").readJSON("multitimer.json", true) || []; + const json = require("Storage").readJSON("multitimer.json", true) || {}; + json.sw = json.sw || []; + const sw = json.sw; if (sw[idx]) a = sw[idx]; else { a = {"t" : 0, "on" : false, "msg" : ""}; sw[idx] = a; - require("Storage").writeJSON("multitimer.json", sw); + require("Storage").writeJSON("multitimer.json", json); } function updateTimer() { @@ -408,7 +422,7 @@ function swMenu(idx, a) { } else delete a.msg; sw[idx] = a; - require("Storage").writeJSON("multitimer.json", sw); + require("Storage").writeJSON("multitimer.json", json); swMenu(idx, a); }); } @@ -458,7 +472,7 @@ function swMenu(idx, a) { select : (i) => { function saveAndReload() { - require("Storage").writeJSON("multitimer.json", sw); + require("Storage").writeJSON("multitimer.json", json); s.draw(); } @@ -707,5 +721,17 @@ function onDrag(e) { } } -drawTimers(); +switch (readAndConvJson().initialScreen) { + case 0: + case undefined: + default: + drawTimers(); + break; + case 1: + drawSw(); + break; + case 2: + drawAlarms(); + break; +} } diff --git a/apps/multitimer/metadata.json b/apps/multitimer/metadata.json index e753d0581..8ba946520 100644 --- a/apps/multitimer/metadata.json +++ b/apps/multitimer/metadata.json @@ -1,7 +1,7 @@ { "id": "multitimer", "name": "Multi Timer", - "version": "0.07", + "version": "0.08", "description": "Set timers and chronographs (stopwatches) and watch them count down in real time. Pause, create, edit, and delete timers and chronos, and add custom labels/messages. Also sets alarms.", "icon": "app.png", "screenshots": [ @@ -16,6 +16,7 @@ {"name":"multitimer.app.js","url":"app.js"}, {"name":"multitimer.boot.js","url":"boot.js"}, {"name":"multitimer.alarm.js","url":"alarm.js"}, + {"name":"multitimer.settings.js","url":"settings.js"}, {"name":"multitimer.img","url":"app-icon.js","evaluate":true} ], "data": [{"name":"multitimer.json"}], diff --git a/apps/multitimer/settings.js b/apps/multitimer/settings.js new file mode 100644 index 000000000..de0ed74f4 --- /dev/null +++ b/apps/multitimer/settings.js @@ -0,0 +1,31 @@ +(function(back) { + const file = "multitimer.json"; + let json = require('Storage').readJSON(file, true); + if (Array.isArray(json)) { + // old format, convert + json = { sw: json }; + } + + function writeSettings() { + require('Storage').writeJSON(file, json); + } + + const screens = ["Timers", "Chronos", "Alarms"]; + + E.showMenu({ + "": { + "title": "multitimer" + }, + "< Back": back, + "Initial screen": { + value: json.initialScreen || 0, + min: 0, + max: screens.length - 1, + format: v => screens[v], + onchange: v => { + json.initialScreen = v; + writeSettings(); + } + }, + }); +}); From 717d262f26e674dc5ba92f4cb351a1988edffb1c Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Thu, 29 Feb 2024 23:25:38 +0000 Subject: [PATCH 25/57] multitimer: handle espruino-specific switch --- apps/multitimer/app.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/multitimer/app.js b/apps/multitimer/app.js index 99830cea1..942254a2a 100644 --- a/apps/multitimer/app.js +++ b/apps/multitimer/app.js @@ -722,16 +722,16 @@ function onDrag(e) { } switch (readAndConvJson().initialScreen) { - case 0: - case undefined: - default: - drawTimers(); - break; case 1: drawSw(); break; case 2: drawAlarms(); break; + case 0: + case undefined: + default: + drawTimers(); + break; } } From 6aa0b8dbe777b92f4f824a8bd69a4b0a49c4b86c Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Thu, 29 Feb 2024 23:43:16 +0000 Subject: [PATCH 26/57] sched: fix initial display of forever-buzzcount --- apps/sched/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sched/settings.js b/apps/sched/settings.js index 1650bfd8e..76036db2b 100644 --- a/apps/sched/settings.js +++ b/apps/sched/settings.js @@ -43,7 +43,7 @@ }, /*LANG*/"Buzz Count": { - value: settings.buzzCount, + value: settings.buzzCount == null ? 4 : settings.buzzCount, min: 4, max: 15, step: 1, From 145b983b230b823b9949eeaef76b3c7fff4277d7 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Fri, 1 Mar 2024 08:53:58 +0000 Subject: [PATCH 27/57] multitimer: fix missing scroller (introduced, b9e73d47f1) --- apps/multitimer/app.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/multitimer/app.js b/apps/multitimer/app.js index 942254a2a..6d2c2f237 100644 --- a/apps/multitimer/app.js +++ b/apps/multitimer/app.js @@ -78,7 +78,7 @@ function drawTimers() { }, 1000 - (timers[idx].t % 1000)); } - E.showScroller({ + const s = E.showScroller({ h : 40, c : timers.length+2, back : function() {load();}, draw : (idx, r) => { @@ -138,7 +138,7 @@ function timerMenu(idx) { }, 1000 - (a.t % 1000)); } - E.showScroller({ + const s = E.showScroller({ h : 40, c : 5, back : function() { clearInt(); @@ -353,7 +353,7 @@ function drawSw() { }, 1000 - (sw[idx].t % 1000)); } - E.showScroller({ + const s = E.showScroller({ h : 40, c : sw.length+2, back : function() {load();}, draw : (idx, r) => { @@ -434,7 +434,7 @@ function swMenu(idx, a) { setUI(); } - E.showScroller({ + const s = E.showScroller({ h : 40, c : 5, back : function() { clearInt(); From a23f49a4535eed65ad84468a72ca4ece91b4bd6c Mon Sep 17 00:00:00 2001 From: Jordi Mas Date: Fri, 1 Mar 2024 20:55:27 +0100 Subject: [PATCH 28/57] Fixes to Catalan locale: right icon for all regions, shorter long data pattern and fix lang code --- apps/locale/locales.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/locale/locales.js b/apps/locale/locales.js index c307c405f..a0d5ea031 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -790,7 +790,8 @@ var locales = { trans: { yes: "ja", Yes: "Ja", no: "nei", No: "Nei", ok: "ok", on: "på", off: "av", "< Back": "< Tilbake", "Delete": "Slett", "Mark Unread": "Merk som ulest" } }, "ca_ES": { - lang: "es_ES", + lang: "ca_ES", + icon: "🇪🇺", decimal_point: ",", thousands_sep: ".", currency_symbol: "€", @@ -800,7 +801,7 @@ var locales = { temperature: "°C", ampm: { 0: "", 1: "" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, - datePattern: { 0: "%A, %d de %B %Y", "1": "%d/%m/%y" }, + datePattern: { 0: "%d %B %Y", "1": "%d/%m/%y" }, abmonth: "gen.,febr.,març,abr.,maig,juny,jul.,ag.,set.,oct.,nov.,des.", month: "gener,febrer,març,abril,maig,juny,juliol,agost,setembre,octobre,novembre,desembre", abday: "dg.,dl.,dt.,dc.,dj.,dv.,ds.", From 4a35b30bb07d382d02b7b9a74d33c79194f91477 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Fri, 1 Mar 2024 22:33:14 +0000 Subject: [PATCH 29/57] multitimer: restore json & sw default --- apps/multitimer/app.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/multitimer/app.js b/apps/multitimer/app.js index 6d2c2f237..31da18796 100644 --- a/apps/multitimer/app.js +++ b/apps/multitimer/app.js @@ -328,21 +328,22 @@ function editTimer(idx, a) { setUI(); } -function readAndConvJson() { - let json = require("Storage").readJSON("multitimer.json", true); +function readJson() { + let json = require("Storage").readJSON("multitimer.json", true) || {}; if (Array.isArray(json)) { // old format, convert json = { sw: json }; require("Storage").writeJSON("multitimer.json", json); } + if (!json.sw) json.sw = []; return json; } function drawSw() { layer = 1; - const sw = readAndConvJson().sw; + const sw = readJson().sw; function updateTimers(idx) { if (!timerInt1[idx]) timerInt1[idx] = setTimeout(function() { @@ -394,8 +395,7 @@ function drawSw() { function swMenu(idx, a) { layer = -1; - const json = require("Storage").readJSON("multitimer.json", true) || {}; - json.sw = json.sw || []; + const json = readJson(); const sw = json.sw; if (sw[idx]) a = sw[idx]; else { @@ -721,7 +721,7 @@ function onDrag(e) { } } -switch (readAndConvJson().initialScreen) { +switch (readJson().initialScreen) { case 1: drawSw(); break; From baa5b058095a244a1b9014110e0013af58540ae9 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sat, 2 Mar 2024 15:37:36 +0000 Subject: [PATCH 30/57] multitimer: fix settings --- apps/multitimer/settings.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/multitimer/settings.js b/apps/multitimer/settings.js index de0ed74f4..4faeb2573 100644 --- a/apps/multitimer/settings.js +++ b/apps/multitimer/settings.js @@ -1,10 +1,11 @@ (function(back) { const file = "multitimer.json"; - let json = require('Storage').readJSON(file, true); + let json = require('Storage').readJSON(file, true) || {}; if (Array.isArray(json)) { // old format, convert json = { sw: json }; } + if (!json.sw) json.sw = []; function writeSettings() { require('Storage').writeJSON(file, json); From 97d648d4affa58f2d13daf46a0e606809a96d786 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sat, 2 Mar 2024 15:00:16 +0000 Subject: [PATCH 31/57] sched: add day selection to interface.html --- apps/sched/interface.html | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/apps/sched/interface.html b/apps/sched/interface.html index 62e45676b..75c8ce67f 100644 --- a/apps/sched/interface.html +++ b/apps/sched/interface.html @@ -163,6 +163,26 @@ function renderAlarm(alarm, exists) { tr.appendChild(tdTime); tdTime.appendChild(inputTime); + const tdDays = document.createElement('td'); + tr.appendChild(tdDays); + const selectDays = document.createElement('select'); + selectDays.multiple = true; + selectDays.classList.add('form-input'); + selectDays.dataset.uid = alarm.id; + const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; + const options = days.map((day, i) => { + const option = document.createElement('option'); + option.value = day; + option.text = day; + option.selected = alarm.dow & (1 << i); + selectDays.appendChild(option); + return option; + }); + selectDays.onchange = (e => { + alarm.dow = options.reduce((bits, opt, i) => bits | (opt.selected ? 1 << i : 0), 0); + }); + tdDays.appendChild(selectDays); + const tdSummary = document.createElement('td'); tr.appendChild(tdSummary); const inputSummary = document.createElement('input'); @@ -320,6 +340,7 @@ function onInit() { Type Date/Time + Days Summary On? From d28d696deaa7eab31678d7e398fdc3a0375bb4de Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sat, 2 Mar 2024 16:12:06 +0000 Subject: [PATCH 32/57] sched: interface.html, Monday is the first day of the week --- apps/sched/interface.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/sched/interface.html b/apps/sched/interface.html index 75c8ce67f..61c554712 100644 --- a/apps/sched/interface.html +++ b/apps/sched/interface.html @@ -175,9 +175,11 @@ function renderAlarm(alarm, exists) { option.value = day; option.text = day; option.selected = alarm.dow & (1 << i); - selectDays.appendChild(option); + if(day !== "Sun") + selectDays.appendChild(option); return option; }); + selectDays.appendChild(options.find(o => o.text === "Sun")); selectDays.onchange = (e => { alarm.dow = options.reduce((bits, opt, i) => bits | (opt.selected ? 1 << i : 0), 0); }); From 0d5c39a1836ef979ca2d85d9e3574cdded1fd02b Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sat, 2 Mar 2024 16:22:15 +0000 Subject: [PATCH 33/57] sleeplog: only write log if we have something to write --- apps/sleeplog/ChangeLog | 3 ++- apps/sleeplog/lib.js | 3 ++- apps/sleeplog/metadata.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/sleeplog/ChangeLog b/apps/sleeplog/ChangeLog index 93202b291..7d2f147db 100644 --- a/apps/sleeplog/ChangeLog +++ b/apps/sleeplog/ChangeLog @@ -10,4 +10,5 @@ 0.12: Improve README, option to add functions triggered by status changes or time periods, remove old log (<0.10) conversion 0.13: Prevent to stay in consecutive sleep if not worn, correct trigger calling, add trigger object itself as argument to the fn function 0.14: Add "Delete all logfiles before" to interface.html, display all logfiles in the interface -0.15: Issue newline before GB commands (solves issue with console.log and ignored commands) \ No newline at end of file +0.15: Issue newline before GB commands (solves issue with console.log and ignored commands) +0.16: Only write logs if we have a non-empty log to write diff --git a/apps/sleeplog/lib.js b/apps/sleeplog/lib.js index 8aa1748b1..79d7db0d5 100644 --- a/apps/sleeplog/lib.js +++ b/apps/sleeplog/lib.js @@ -169,7 +169,8 @@ exports = { // check if before this fortnight period if (firstDay < thisFirstDay) { // write log in seperate file - require("Storage").writeJSON("sleeplog_" + this.msToFn(firstDay) + ".log", log); + if(log.length > 0) + require("Storage").writeJSON("sleeplog_" + this.msToFn(firstDay) + ".log", log); // set last day as first firstDay = lastDay; } else { diff --git a/apps/sleeplog/metadata.json b/apps/sleeplog/metadata.json index 911e0cfa1..212c47ff3 100644 --- a/apps/sleeplog/metadata.json +++ b/apps/sleeplog/metadata.json @@ -2,7 +2,7 @@ "id":"sleeplog", "name":"Sleep Log", "shortName": "SleepLog", - "version": "0.15", + "version": "0.16", "description": "Log and view your sleeping habits. This app is using the built in movement calculation.", "icon": "app.png", "type": "app", From b4b047d0cb5e06f921d7ab987007ead04e3559ca Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sat, 2 Mar 2024 18:29:47 +0000 Subject: [PATCH 34/57] sched: interface.html rowspan --- apps/sched/interface.html | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/apps/sched/interface.html b/apps/sched/interface.html index 61c554712..608212792 100644 --- a/apps/sched/interface.html +++ b/apps/sched/interface.html @@ -2,6 +2,11 @@ + From f1a8c03d52ddbdb1505325ee3e2556b17043f6c7 Mon Sep 17 00:00:00 2001 From: Logan B <3870583+thinkpoop@users.noreply.github.com> Date: Sun, 3 Mar 2024 11:07:42 -0600 Subject: [PATCH 40/57] Update apps/a_dndtoggle/a_dndtoggle.app.js Co-authored-by: Rob Pilling --- apps/a_dndtoggle/a_dndtoggle.app.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/a_dndtoggle/a_dndtoggle.app.js b/apps/a_dndtoggle/a_dndtoggle.app.js index da2293450..20fc9afa7 100644 --- a/apps/a_dndtoggle/a_dndtoggle.app.js +++ b/apps/a_dndtoggle/a_dndtoggle.app.js @@ -40,9 +40,9 @@ setTimeout('exitApp();', 2000); function exitApp(){ - require("Storage").writeJSON("setting.json", bSettings); - // reload clocks with new theme, otherwise just wait for user to switch apps - +require("Storage").writeJSON("setting.json", bSettings); +// reload clocks with new theme, otherwise just wait for user to switch apps + load() } \ No newline at end of file From 0d7640dae949bff7e9f42274f20f17997ede7e55 Mon Sep 17 00:00:00 2001 From: Logan B <3870583+thinkpoop@users.noreply.github.com> Date: Sun, 3 Mar 2024 11:07:51 -0600 Subject: [PATCH 41/57] Update apps/a_dndtoggle/a_dndtoggle.app.js Co-authored-by: Rob Pilling --- apps/a_dndtoggle/a_dndtoggle.app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/a_dndtoggle/a_dndtoggle.app.js b/apps/a_dndtoggle/a_dndtoggle.app.js index 20fc9afa7..7ee02d231 100644 --- a/apps/a_dndtoggle/a_dndtoggle.app.js +++ b/apps/a_dndtoggle/a_dndtoggle.app.js @@ -15,7 +15,7 @@ console.log("old: " + current); switch (current) { case 0: - bSettings.quiet = dndSettings.mode; + bSettings.quiet = dndSettings.mode || 2; Bangle.buzz(); setTimeout('Bangle.buzz();',500); break; From 9bca4822004a319540bf3e2307053f0f046cc75c Mon Sep 17 00:00:00 2001 From: Logan B <3870583+thinkpoop@users.noreply.github.com> Date: Sun, 3 Mar 2024 11:34:28 -0600 Subject: [PATCH 42/57] a_dndtoggle: remove default.json --- apps/a_dndtoggle/a_dndtoggle.app.js | 6 ++---- apps/a_dndtoggle/default.json | 1 - apps/a_dndtoggle/metadata.json | 1 - apps/a_dndtoggle/settings.js | 8 +++----- 4 files changed, 5 insertions(+), 11 deletions(-) delete mode 100644 apps/a_dndtoggle/default.json diff --git a/apps/a_dndtoggle/a_dndtoggle.app.js b/apps/a_dndtoggle/a_dndtoggle.app.js index 7ee02d231..207034209 100644 --- a/apps/a_dndtoggle/a_dndtoggle.app.js +++ b/apps/a_dndtoggle/a_dndtoggle.app.js @@ -6,10 +6,8 @@ let current = 0|bSettings.quiet; //1 alarms //2 silent -const dndSettings = Object.assign( - require('Storage').readJSON("a_dndtoggle.default.json", true) || {}, - require('Storage').readJSON("a_dndtoggle.settings.json", true) || {} - ); +const dndSettings = + require('Storage').readJSON("a_dndtoggle.settings.json", true) || {}; console.log("old: " + current); diff --git a/apps/a_dndtoggle/default.json b/apps/a_dndtoggle/default.json deleted file mode 100644 index 96bf417c5..000000000 --- a/apps/a_dndtoggle/default.json +++ /dev/null @@ -1 +0,0 @@ -{"mode":2} \ No newline at end of file diff --git a/apps/a_dndtoggle/metadata.json b/apps/a_dndtoggle/metadata.json index e7f47d69e..62f0edae9 100644 --- a/apps/a_dndtoggle/metadata.json +++ b/apps/a_dndtoggle/metadata.json @@ -13,7 +13,6 @@ ], "storage": [ {"name":"a_dndtoggle.app.js","url":"a_dndtoggle.app.js"}, - {"name":"a_dndtoggle.default.json","url":"default.json"}, {"name":"a_dndtoggle.settings.js","url":"settings.js"}, {"name":"a_dndtoggle.img","url":"app-icon.js","evaluate":true} ], diff --git a/apps/a_dndtoggle/settings.js b/apps/a_dndtoggle/settings.js index da643667f..aea8d9b60 100644 --- a/apps/a_dndtoggle/settings.js +++ b/apps/a_dndtoggle/settings.js @@ -1,9 +1,7 @@ (function(back) { - const settings = Object.assign( - require('Storage').readJSON("a_dndtoggle.default.json", true) || {}, - require('Storage').readJSON("a_dndtoggle.settings.json", true) || {} - ); + const settings = + require('Storage').readJSON("a_dndtoggle.settings.json", true) || {}; function updateSettings() { require('Storage').writeJSON("a_dndtoggle.settings.json", settings); @@ -15,7 +13,7 @@ '': { 'title': 'A_DND Toggle' }, '< Back': back, /*LANG*/"Quiet Mode": { - value: settings.mode, + value: settings.mode || 2, min: 1, max: modes.length - 1, format: v => modes[v], onchange: v => { From 708c295853bfd3c6fbb4549ec2f1878e0b87d190 Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Sun, 3 Mar 2024 19:23:49 +0100 Subject: [PATCH 43/57] cscsensor: Automatically reconnect on error --- apps/cscsensor/ChangeLog | 1 + apps/cscsensor/cscsensor.app.js | 3 ++- apps/cscsensor/metadata.json | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/cscsensor/ChangeLog b/apps/cscsensor/ChangeLog index 5264e8d42..c01b35503 100644 --- a/apps/cscsensor/ChangeLog +++ b/apps/cscsensor/ChangeLog @@ -7,3 +7,4 @@ Improve connection code 0.07: Make Bangle.js 2 compatible 0.08: Convert Yes/No On/Off in settings to checkboxes +0.09: Automatically reconnect on error diff --git a/apps/cscsensor/cscsensor.app.js b/apps/cscsensor/cscsensor.app.js index 4ebe7d57e..1ad7a9e98 100644 --- a/apps/cscsensor/cscsensor.app.js +++ b/apps/cscsensor/cscsensor.app.js @@ -226,7 +226,7 @@ function getSensorBatteryLevel(gatt) { function connection_setup() { mySensor.screenInit = true; E.showMessage("Scanning for CSC sensor..."); - NRF.requestDevice({ filters: [{services:["1816"]}]}).then(function(d) { + NRF.requestDevice({ filters: [{services:["1816"]}], maxInterval: 100}).then(function(d) { device = d; E.showMessage("Found device"); return device.gatt.connect(); @@ -249,6 +249,7 @@ function connection_setup() { }).catch(function(e) { E.showMessage(e.toString(), "ERROR"); console.log(e); + setTimeout(connection_setup, 1000); }); } diff --git a/apps/cscsensor/metadata.json b/apps/cscsensor/metadata.json index d7c3add53..5d70251da 100644 --- a/apps/cscsensor/metadata.json +++ b/apps/cscsensor/metadata.json @@ -2,7 +2,7 @@ "id": "cscsensor", "name": "Cycling speed sensor", "shortName": "CSCSensor", - "version": "0.08", + "version": "0.09", "description": "Read BLE enabled cycling speed and cadence sensor and display readings on watch", "icon": "icons8-cycling-48.png", "tags": "outdoors,exercise,ble,bluetooth,bike,cycle,bicycle", From a25ed8f6ff97d7cf04475063a7e5da796bee1500 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sat, 2 Mar 2024 16:11:36 +0000 Subject: [PATCH 44/57] widalarmeta: use sched lib and remove template comment --- apps/widalarmeta/widget.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/widalarmeta/widget.js b/apps/widalarmeta/widget.js index c7542ada5..42f47cd5c 100644 --- a/apps/widalarmeta/widget.js +++ b/apps/widalarmeta/widget.js @@ -19,7 +19,10 @@ loadSettings(); function getNextAlarm(date) { - const alarms = (require("Storage").readJSON("sched.json",1) || []).filter(alarm => alarm.on && alarm.hidden !== true); + const alarms = require("sched") + .getAlarms() + .filter(alarm => alarm.on && alarm.hidden !== true); + WIDGETS["widalarmeta"].numActiveAlarms = alarms.length; if (alarms.length > 0) { const times = alarms.map(alarm => require("sched").getTimeToAlarm(alarm, date) || Number.POSITIVE_INFINITY); @@ -116,7 +119,6 @@ } /* draw */ if (config.maxhours > 0) { - // add your widget WIDGETS["widalarmeta"]={ area:"tl", width: 0, // hide by default = assume no timer From 0dd67533acf4234bc5ea39d1948e9019a7963f54 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sun, 3 Mar 2024 19:28:52 +0000 Subject: [PATCH 45/57] sched: emit alarmReload, widalarm reload on alarmReload --- apps/sched/ChangeLog | 1 + apps/sched/lib.js | 5 +---- apps/sched/metadata.json | 2 +- apps/widalarm/ChangeLog | 1 + apps/widalarm/metadata.json | 2 +- apps/widalarm/widget.js | 6 ++++++ 6 files changed, 11 insertions(+), 6 deletions(-) diff --git a/apps/sched/ChangeLog b/apps/sched/ChangeLog index 1d1c53ac1..98cedd5ad 100644 --- a/apps/sched/ChangeLog +++ b/apps/sched/ChangeLog @@ -24,3 +24,4 @@ 0.21: Fix crash in clock_info 0.22: Dated event repeat option 0.23: Allow buzzing forever when an alarm fires +0.24: Emit alarmReload when alarms change (used by widalarm) diff --git a/apps/sched/lib.js b/apps/sched/lib.js index c8961b9e3..02b27e1f8 100644 --- a/apps/sched/lib.js +++ b/apps/sched/lib.js @@ -55,10 +55,7 @@ exports.getTimeToAlarm = function(alarm, time) { /// Force a reload of the current alarms and widget exports.reload = function() { eval(require("Storage").read("sched.boot.js")); - if (global.WIDGETS && WIDGETS["alarm"]) { - WIDGETS["alarm"].reload(); - Bangle.drawWidgets(); - } + Bangle.emit("alarmReload"); }; // Factory that creates a new alarm with default values exports.newDefaultAlarm = function () { diff --git a/apps/sched/metadata.json b/apps/sched/metadata.json index 7f94a0a18..dba3bc160 100644 --- a/apps/sched/metadata.json +++ b/apps/sched/metadata.json @@ -1,7 +1,7 @@ { "id": "sched", "name": "Scheduler", - "version": "0.23", + "version": "0.24", "description": "Scheduling library for alarms and timers", "icon": "app.png", "type": "scheduler", diff --git a/apps/widalarm/ChangeLog b/apps/widalarm/ChangeLog index 63568a9bd..a26c63b9f 100644 --- a/apps/widalarm/ChangeLog +++ b/apps/widalarm/ChangeLog @@ -1 +1,2 @@ 0.01: Moved out of 'alarm' app +0.02: Decouple reloading of widget when alarms change diff --git a/apps/widalarm/metadata.json b/apps/widalarm/metadata.json index b91457138..e3cb2d0c1 100644 --- a/apps/widalarm/metadata.json +++ b/apps/widalarm/metadata.json @@ -1,7 +1,7 @@ { "id": "widalarm", "name": "Alarms Widget", - "version": "0.01", + "version": "0.02", "description": "Displays an alarm icon in the widgets bar if any alarm is active", "icon": "app.png", "type": "widget", diff --git a/apps/widalarm/widget.js b/apps/widalarm/widget.js index 964176fc7..15fb0b9a3 100644 --- a/apps/widalarm/widget.js +++ b/apps/widalarm/widget.js @@ -6,3 +6,9 @@ WIDGETS["alarm"]={area:"tl",width:0,draw:function() { } }; WIDGETS["alarm"].reload(); +Bangle.on("alarmReload", () => { + if (WIDGETS["alarm"]) { + WIDGETS["alarm"].reload(); + Bangle.drawWidgets(); + } +}); From 95105825a762a9212fd6df1a3c5782d573be6bc1 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sun, 3 Mar 2024 19:36:42 +0000 Subject: [PATCH 46/57] sched: interface.html fix row deletion --- apps/sched/interface.html | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/sched/interface.html b/apps/sched/interface.html index 90299ce6b..9c3b9e139 100644 --- a/apps/sched/interface.html +++ b/apps/sched/interface.html @@ -255,6 +255,7 @@ function renderAlarm(alarm, exists) { buttonDelete.onclick = (e => { alarms = alarms.filter(a => a !== alarm); document.getElementById('events').removeChild(tr); + document.getElementById('events').removeChild(tr2); }); document.getElementById('events').appendChild(tr); From 87919639bb4bee3dd2894410702a22bf7a2130fa Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sun, 3 Mar 2024 19:38:27 +0000 Subject: [PATCH 47/57] sched: interface.html move on/off + delete below summary --- apps/sched/interface.html | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/sched/interface.html b/apps/sched/interface.html index 9c3b9e139..ed3026658 100644 --- a/apps/sched/interface.html +++ b/apps/sched/interface.html @@ -7,17 +7,17 @@ height: 100%; /* e.g. day */ } - #events > tr.event-row > td:last-child, - #events > tr.event-row > td:first-child { + .single-row { /* no border between single rowspans, 1st & $th */ border-bottom: none; } - #events > tr:nth-child(2n) > td:nth-child(2) { + .btn-center { justify-content: center; display: flex; } @@ -138,10 +137,10 @@ function renderAlarm(alarm, exists) { const tr2 = document.createElement('tr'); tr.classList.add('event-row'); tr.dataset.uid = alarm.id; + const tdType = document.createElement('td'); tdType.type = "text"; tdType.classList.add('event-summary'); - tr.appendChild(tdType); tdType.rowSpan = 1; const inputTime = document.createElement('input'); if (localDate) { tdType.textContent = "Event"; @@ -181,11 +180,9 @@ function renderAlarm(alarm, exists) { inputTime.classList.add('form-input'); inputTime.dataset.uid = alarm.id; const tdTime = document.createElement('td'); - tr2.appendChild(tdTime); tdTime.rowSpan = 1; tdTime.appendChild(inputTime); const tdDays = document.createElement('td'); - tr.appendChild(tdDays); tdDays.rowSpan = 2; const selectDays = document.createElement('select'); selectDays.multiple = true; selectDays.classList.add('form-input', 'multi-select'); @@ -207,7 +204,6 @@ function renderAlarm(alarm, exists) { tdDays.appendChild(selectDays); const tdSummary = document.createElement('td'); - tr.appendChild(tdSummary); tdSummary.rowSpan = 1; tdSummary.colSpan = 2; const inputSummary = document.createElement('input'); inputSummary.type = "text"; inputSummary.classList.add('event-summary'); @@ -224,9 +220,8 @@ function renderAlarm(alarm, exists) { inputSummary.onchange(); const tdOptions = document.createElement('td'); - tr2.appendChild(tdOptions); tdOptions.rowSpan = 1; - const onOffCheck = document.createElement('input'); + tdOptions.classList.add('btn-center'); onOffCheck.type = 'checkbox'; onOffCheck.checked = alarm.on; onOffCheck.onchange = e => { @@ -242,8 +237,6 @@ function renderAlarm(alarm, exists) { tdOptions.appendChild(onOff); const tdInfo = document.createElement('td'); - tr2.appendChild(tdInfo); tdInfo.rowSpan = 1; - const buttonDelete = document.createElement('button'); buttonDelete.classList.add('btn'); buttonDelete.classList.add('btn-action'); @@ -258,6 +251,13 @@ function renderAlarm(alarm, exists) { document.getElementById('events').removeChild(tr2); }); + tr.appendChild(tdType); tdType.classList.add('single-row'); + tr.appendChild(tdOptions); tdType.classList.add('single-row'); + tr.appendChild(tdInfo); tdType.classList.add('single-row'); + tr2.appendChild(tdTime); tdTime.colSpan = 3; + tr.appendChild(tdDays); tdDays.rowSpan = 2; + tr.appendChild(tdSummary); tdType.classList.add('single-row'); + document.getElementById('events').appendChild(tr); document.getElementById('events').appendChild(tr2); document.getElementById('upload').disabled = false; From 8dbef6041e0e14409a165798242e2ff1a8ceb9f5 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Mon, 4 Mar 2024 07:49:24 +0000 Subject: [PATCH 51/57] sched: interface.html hide days for non-alarms --- apps/sched/interface.html | 55 ++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/apps/sched/interface.html b/apps/sched/interface.html index 041ef9337..81684819a 100644 --- a/apps/sched/interface.html +++ b/apps/sched/interface.html @@ -142,8 +142,9 @@ function renderAlarm(alarm, exists) { tdType.type = "text"; tdType.classList.add('event-summary'); const inputTime = document.createElement('input'); + let type; if (localDate) { - tdType.textContent = "Event"; + type = "Event"; inputTime.type = "datetime-local"; inputTime.value = localDate.toISOString().slice(0,16); inputTime.onchange = (e => { @@ -159,18 +160,19 @@ function renderAlarm(alarm, exists) { inputTime.value = `${hours}:${mins}:${secs}`; if (alarm.timer) { - tdType.textContent = "Timer"; + type = "Timer"; inputTime.onchange = e => { alarm.timer = hmsToMs(inputTime.value); // alarm.t is set on upload }; } else { - tdType.textContent = "Alarm"; + type = "Alarm"; inputTime.onchange = e => { alarm.t = hmsToMs(inputTime.value); }; } } + tdType.textContent = type; if (!exists) { const asterisk = document.createElement('sup'); asterisk.textContent = '*'; @@ -182,26 +184,29 @@ function renderAlarm(alarm, exists) { const tdTime = document.createElement('td'); tdTime.appendChild(inputTime); - const tdDays = document.createElement('td'); - const selectDays = document.createElement('select'); - selectDays.multiple = true; - selectDays.classList.add('form-input', 'multi-select'); - selectDays.dataset.uid = alarm.id; - const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; - const options = days.map((day, i) => { - const option = document.createElement('option'); - option.value = day; - option.text = day; - option.selected = alarm.dow & (1 << i); - if(day !== "Sun") - selectDays.appendChild(option); - return option; - }); - selectDays.appendChild(options.find(o => o.text === "Sun")); - selectDays.onchange = (e => { - alarm.dow = options.reduce((bits, opt, i) => bits | (opt.selected ? 1 << i : 0), 0); - }); - tdDays.appendChild(selectDays); + let tdDays; + if (type === "Alarm") { + tdDays = document.createElement('td'); + const selectDays = document.createElement('select'); + selectDays.multiple = true; + selectDays.classList.add('form-input', 'multi-select'); + selectDays.dataset.uid = alarm.id; + const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; + const options = days.map((day, i) => { + const option = document.createElement('option'); + option.value = day; + option.text = day; + option.selected = alarm.dow & (1 << i); + if(day !== "Sun") + selectDays.appendChild(option); + return option; + }); + selectDays.appendChild(options.find(o => o.text === "Sun")); + selectDays.onchange = (e => { + alarm.dow = options.reduce((bits, opt, i) => bits | (opt.selected ? 1 << i : 0), 0); + }); + tdDays.appendChild(selectDays); + } const tdSummary = document.createElement('td'); const inputSummary = document.createElement('input'); @@ -255,7 +260,9 @@ function renderAlarm(alarm, exists) { tr.appendChild(tdOptions); tdType.classList.add('single-row'); tr.appendChild(tdInfo); tdType.classList.add('single-row'); tr2.appendChild(tdTime); tdTime.colSpan = 3; - tr.appendChild(tdDays); tdDays.rowSpan = 2; + if (tdDays) { + tr.appendChild(tdDays); tdDays.rowSpan = 2; + } tr.appendChild(tdSummary); tdType.classList.add('single-row'); document.getElementById('events').appendChild(tr); From 9791f452d86730438418846575a9245884e945e6 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Mon, 4 Mar 2024 07:57:22 +0000 Subject: [PATCH 52/57] sched: interface.html tweak layout and handle event/timers --- apps/sched/interface.html | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/apps/sched/interface.html b/apps/sched/interface.html index 81684819a..8da4a356f 100644 --- a/apps/sched/interface.html +++ b/apps/sched/interface.html @@ -4,11 +4,12 @@