From 5f147027aaacb78b2a3908a11f67291eddcf7cb8 Mon Sep 17 00:00:00 2001 From: Zach Dixon Date: Mon, 9 May 2022 20:45:22 -0700 Subject: [PATCH 001/163] 12h clock format, option to disable autocycle --- apps/rebble/rebble.app.js | 25 +++++++++++++++++++++++-- apps/rebble/rebble.settings.js | 10 +++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/apps/rebble/rebble.app.js b/apps/rebble/rebble.app.js index 7c7d57939..03680eca8 100644 --- a/apps/rebble/rebble.app.js +++ b/apps/rebble/rebble.app.js @@ -1,8 +1,10 @@ var SunCalc = require("https://raw.githubusercontent.com/mourner/suncalc/master/suncalc.js"); const SETTINGS_FILE = "rebble.json"; const LOCATION_FILE = "mylocation.json"; +const GLOBAL_SETTINGS = "setting.json"; let settings; let location; +let is12Hour; Graphics.prototype.setFontLECO1976Regular22 = function(scale) { // Actual height 22 (21 - 0) @@ -34,11 +36,25 @@ function loadLocation() { function loadSettings() { settings = require("Storage").readJSON(SETTINGS_FILE,1)|| {'bg': '#0f0', 'color': 'Green'}; + is12Hour = (require("Storage").readJSON(GLOBAL_SETTINGS, 1) || {})["12hour"] || false; +} + +function formatHours(hh) { + if (is12Hour) { + let hours = parseInt(hh,10); + if (hours == 0) { + hours = 12; + } else if (hours >= 12) { + if (hours>12) hours -= 12; + } + hh = (" "+hours).substr(-2); + } + return hh; } function extractTime(d){ var h = d.getHours(), m = d.getMinutes(); - return(("0"+h).substr(-2) + ":" + ("0"+m).substr(-2)); + return(formatHours(("0"+h).substr(-2)) + ":" + ("0"+m).substr(-2)); } function updateSunRiseSunSet(lat, lon){ @@ -81,6 +97,9 @@ function draw() { let da = date.toString().split(" "); let hh = da[4].substr(0,2); let mm = da[4].substr(3,2); + + hh = formatHours(hh); + //const t = 6; if (drawCount % 60 == 0) @@ -260,7 +279,9 @@ function queueDraw() { if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = setTimeout(function() { drawTimeout = undefined; - nextSidebar(); + if (!settings.autoCycle) { + nextSidebar(); + } draw(); }, 60000 - (Date.now() % 60000)); } diff --git a/apps/rebble/rebble.settings.js b/apps/rebble/rebble.settings.js index db3bab878..b4d96644d 100644 --- a/apps/rebble/rebble.settings.js +++ b/apps/rebble/rebble.settings.js @@ -2,7 +2,7 @@ const SETTINGS_FILE = "rebble.json"; // initialize with default settings... - let s = {'bg': '#0f0', 'color': 'Green'} + let s = {'bg': '#0f0', 'color': 'Green', 'autoCycle': true} // ...and overwrite them with any saved values // This way saved values are preserved if a new version adds more settings @@ -33,6 +33,14 @@ s.bg = bg_code[v]; save(); }, + }, + 'Auto Cycle': { + value: "autoCycle" in s ? s.autoCycle : true, + format: () => (s.autoCycle ? 'Yes' : 'No'), + onchange: () => { + s.autoCycle = !s.autoCycle; + save(); + } } }); }) From 7822c4489d0ffadcbe8b0cad518cc89c76dafa96 Mon Sep 17 00:00:00 2001 From: Zach Dixon Date: Mon, 9 May 2022 22:30:20 -0700 Subject: [PATCH 002/163] Fix settings variable conflict and updated version --- apps/rebble/ChangeLog | 3 ++- apps/rebble/metadata.json | 2 +- apps/rebble/rebble.app.js | 2 +- apps/rebble/rebble.settings.js | 20 ++++++++++---------- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/apps/rebble/ChangeLog b/apps/rebble/ChangeLog index b80dfef94..667dc0ad0 100644 --- a/apps/rebble/ChangeLog +++ b/apps/rebble/ChangeLog @@ -2,4 +2,5 @@ 0.02: Fix typo to Purple 0.03: Added dependancy on Pedometer Widget 0.04: Fixed icon and png to 48x48 pixels -0.05: added charging icon \ No newline at end of file +0.05: added charging icon +0.06: Add 12h support and autocycle control \ No newline at end of file diff --git a/apps/rebble/metadata.json b/apps/rebble/metadata.json index b26fb6a27..c44d1c279 100644 --- a/apps/rebble/metadata.json +++ b/apps/rebble/metadata.json @@ -2,7 +2,7 @@ "id": "rebble", "name": "Rebble Clock", "shortName": "Rebble", - "version": "0.05", + "version": "0.06", "description": "A Pebble style clock, with configurable background, three sidebars including steps, day, date, sunrise, sunset, long live the rebellion", "readme": "README.md", "icon": "rebble.png", diff --git a/apps/rebble/rebble.app.js b/apps/rebble/rebble.app.js index 03680eca8..251087ae1 100644 --- a/apps/rebble/rebble.app.js +++ b/apps/rebble/rebble.app.js @@ -35,7 +35,7 @@ function loadLocation() { } function loadSettings() { - settings = require("Storage").readJSON(SETTINGS_FILE,1)|| {'bg': '#0f0', 'color': 'Green'}; + settings = require("Storage").readJSON(SETTINGS_FILE,1)|| {'bg': '#0f0', 'color': 'Green', 'autoCycle': true}; is12Hour = (require("Storage").readJSON(GLOBAL_SETTINGS, 1) || {})["12hour"] || false; } diff --git a/apps/rebble/rebble.settings.js b/apps/rebble/rebble.settings.js index b4d96644d..91142d72d 100644 --- a/apps/rebble/rebble.settings.js +++ b/apps/rebble/rebble.settings.js @@ -2,19 +2,19 @@ const SETTINGS_FILE = "rebble.json"; // initialize with default settings... - let s = {'bg': '#0f0', 'color': 'Green', 'autoCycle': true} + let localSettings = {'bg': '#0f0', 'color': 'Green', 'autoCycle': true} // ...and overwrite them with any saved values // This way saved values are preserved if a new version adds more settings const storage = require('Storage') - let settings = storage.readJSON(SETTINGS_FILE, 1) || s; + let settings = storage.readJSON(SETTINGS_FILE, 1) || localSettings; const saved = settings || {} for (const key in saved) { - s[key] = saved[key] + localSettings[key] = saved[key] } function save() { - settings = s + settings = localSettings storage.write(SETTINGS_FILE, settings) } @@ -25,20 +25,20 @@ '': { 'title': 'Rebble Clock' }, '< Back': back, 'Colour': { - value: 0 | color_options.indexOf(s.color), + value: 0 | color_options.indexOf(localSettings.color), min: 0, max: 5, format: v => color_options[v], onchange: v => { - s.color = color_options[v]; - s.bg = bg_code[v]; + localSettings.color = color_options[v]; + localSettings.bg = bg_code[v]; save(); }, }, 'Auto Cycle': { - value: "autoCycle" in s ? s.autoCycle : true, - format: () => (s.autoCycle ? 'Yes' : 'No'), + value: "autoCycle" in localSettings ? localSettings.autoCycle : true, + format: () => (localSettings.autoCycle ? 'Yes' : 'No'), onchange: () => { - s.autoCycle = !s.autoCycle; + localSettings.autoCycle = !localSettings.autoCycle; save(); } } From 24634330a50a64c07e9e1f7f6dafb70e9883bb44 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 11 May 2022 17:56:36 +0200 Subject: [PATCH 003/163] Update ChangeLog --- apps/kbmulti/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/kbmulti/ChangeLog b/apps/kbmulti/ChangeLog index 04b2430bb..894a609ec 100644 --- a/apps/kbmulti/ChangeLog +++ b/apps/kbmulti/ChangeLog @@ -1 +1,2 @@ 0.01: New keyboard +0.02: Introduce setting "Show help button". Remove the firstLaunch setting from settings.js. From da2aaaf16dd963d23d8be211bb8b55931f5c05b4 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 11 May 2022 18:21:20 +0200 Subject: [PATCH 004/163] Update settings.js --- apps/kbmulti/settings.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/kbmulti/settings.js b/apps/kbmulti/settings.js index d3148eca7..c698aca8a 100644 --- a/apps/kbmulti/settings.js +++ b/apps/kbmulti/settings.js @@ -21,11 +21,11 @@ format: v => v, onchange: v => updateSetting("charTimeout", v), }, - /*LANG*/'Show help on first launch': { - value: !!settings().firstLaunch, + /*LANG*/'Show help button': { + value: !!settings().showHelpBtn, format: v => v?"Yes":"No", - onchange: v => updateSetting("firstLaunch", v) + onchange: v => updateSetting("showHelpBtn", v) } }; E.showMenu(mainmenu); - }) \ No newline at end of file + }) From 824ab9859ec524be2ebc4c7a7fc1021199938b54 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 11 May 2022 18:21:47 +0200 Subject: [PATCH 005/163] Update metadata.json --- apps/kbmulti/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/kbmulti/metadata.json b/apps/kbmulti/metadata.json index 6c813e321..1efdb8847 100644 --- a/apps/kbmulti/metadata.json +++ b/apps/kbmulti/metadata.json @@ -1,6 +1,6 @@ { "id": "kbmulti", "name": "Multitap keyboard", - "version":"0.01", + "version":"0.02", "description": "A library for text input via multitap/T9 style keypad", "icon": "app.png", "type":"textinput", From 87756ece9ef8fec132409303756d0ab3e0d371c2 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 11 May 2022 18:23:31 +0200 Subject: [PATCH 006/163] Update lib.js --- apps/kbmulti/lib.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/kbmulti/lib.js b/apps/kbmulti/lib.js index 79c2d861a..ff987c2cc 100644 --- a/apps/kbmulti/lib.js +++ b/apps/kbmulti/lib.js @@ -6,8 +6,9 @@ exports.input = function(options) { if ("string"!=typeof text) text=""; var settings = require('Storage').readJSON("kbmulti.settings.json", true) || {}; - if (settings.firstLaunch===undefined) { settings.firstLaunch = true; } + //if (settings.firstLaunch===undefined) { settings.firstLaunch = true; } if (settings.charTimeout===undefined) { settings.charTimeout = 500; } + if (settings.showHelpBtn===undefined) { settings.showHelpBtn = true; } var fontSize = "6x15"; var Layout = require("Layout"); @@ -104,7 +105,7 @@ exports.input = function(options) { type:"v", c: [ {type:"h", c: [ {type:"txt", font:"12x20", label:text.slice(-12), id:"text", fillx:1}, - {type:"btn", font:'6x8', label:'?', cb: l=>onHelp(resolve,reject), filly:1 }, + (settings.showHelpBtn ? {type:"btn", font:'6x8', label:'?', cb: l=>onHelp(resolve,reject), filly:1 } : {}), ]}, {type:"h", c: [ {type:"btn", font:fontSize, label:letters[1], cb: l=>onKeyPad(1), id:'1', fillx:1, filly:1 }, @@ -132,7 +133,7 @@ exports.input = function(options) { return new Promise((resolve,reject) => { g.clearRect(Bangle.appRect); - if (settings.firstLaunch) { + if (!settings.firstLaunch) { onHelp(resolve,reject); settings.firstLaunch = false; require('Storage').writeJSON("kbmulti.settings.json", settings); From d6db4e6be355486fbee91a6ae0b83e81b285e6df Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 11 May 2022 19:49:40 +0200 Subject: [PATCH 007/163] Update lib.js --- apps/kbmulti/lib.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/kbmulti/lib.js b/apps/kbmulti/lib.js index ff987c2cc..052fd86a1 100644 --- a/apps/kbmulti/lib.js +++ b/apps/kbmulti/lib.js @@ -1,14 +1,14 @@ //Multitap logic originally from here: http://www.espruino.com/Morse+Code+Texting exports.input = function(options) { - options = options||{}; + var options = options||{}; var text = options.text; if ("string"!=typeof text) text=""; var settings = require('Storage').readJSON("kbmulti.settings.json", true) || {}; //if (settings.firstLaunch===undefined) { settings.firstLaunch = true; } if (settings.charTimeout===undefined) { settings.charTimeout = 500; } - if (settings.showHelpBtn===undefined) { settings.showHelpBtn = true; } + if (settings.showHelpBtn===undefined) { settings.showHelpBtn = false; } var fontSize = "6x15"; var Layout = require("Layout"); @@ -25,9 +25,9 @@ exports.input = function(options) { var caps = true; var layout; - function displayText() { + function displayText(charTimeout) { layout.clear(layout.text); - layout.text.label = text.slice(-12); + layout.text.label = text.slice(settings.showHelpBtn ? -12 : -13) + (charTimeout ? " " : "_"); layout.render(layout.text); } @@ -70,12 +70,12 @@ exports.input = function(options) { } var newLetter = letters[charCurrent][charIndex]; text += (caps ? newLetter.toUpperCase() : newLetter.toLowerCase()); - displayText(); // set a timeout charTimeout = setTimeout(function() { charTimeout = undefined; newCharacter(); }, settings.charTimeout); + displayText(charTimeout); } function onSwipe(dirLeftRight, dirUpDown) { @@ -139,6 +139,7 @@ exports.input = function(options) { require('Storage').writeJSON("kbmulti.settings.json", settings); } else { generateLayout(resolve,reject); + displayText(false); Bangle.on('swipe', onSwipe); layout.render(); } From b34a3415b9b9e1a85a1fb25d5a156d80310e00e1 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 11 May 2022 19:54:37 +0200 Subject: [PATCH 008/163] Update ChangeLog --- apps/kbmulti/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/kbmulti/ChangeLog b/apps/kbmulti/ChangeLog index 894a609ec..191517b30 100644 --- a/apps/kbmulti/ChangeLog +++ b/apps/kbmulti/ChangeLog @@ -1,2 +1,2 @@ 0.01: New keyboard -0.02: Introduce setting "Show help button". Remove the firstLaunch setting from settings.js. +0.02: Introduce setting "Show help button". Make setting firstLaunch invisible by removing corresponding code from settings.js. Add marker that shows when character selection timeout has run out. From 7b1bcd8b76dbc1da8b8db937546d46a021bdd0ca Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 11 May 2022 20:01:49 +0200 Subject: [PATCH 009/163] Update lib.js --- apps/kbmulti/lib.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/kbmulti/lib.js b/apps/kbmulti/lib.js index 052fd86a1..d578a81b0 100644 --- a/apps/kbmulti/lib.js +++ b/apps/kbmulti/lib.js @@ -6,7 +6,7 @@ exports.input = function(options) { if ("string"!=typeof text) text=""; var settings = require('Storage').readJSON("kbmulti.settings.json", true) || {}; - //if (settings.firstLaunch===undefined) { settings.firstLaunch = true; } + if (settings.firstLaunch===undefined) { settings.firstLaunch = true; } if (settings.charTimeout===undefined) { settings.charTimeout = 500; } if (settings.showHelpBtn===undefined) { settings.showHelpBtn = false; } @@ -133,13 +133,13 @@ exports.input = function(options) { return new Promise((resolve,reject) => { g.clearRect(Bangle.appRect); - if (!settings.firstLaunch) { + if (settings.firstLaunch==true) { onHelp(resolve,reject); settings.firstLaunch = false; require('Storage').writeJSON("kbmulti.settings.json", settings); } else { generateLayout(resolve,reject); - displayText(false); + displayText(true); Bangle.on('swipe', onSwipe); layout.render(); } From 8eefdaa706eb560a4cfd9a12d97080ec45a4fbc6 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 11 May 2022 20:11:08 +0200 Subject: [PATCH 010/163] Update lib.js --- apps/kbmulti/lib.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/kbmulti/lib.js b/apps/kbmulti/lib.js index d578a81b0..8dd92d6f3 100644 --- a/apps/kbmulti/lib.js +++ b/apps/kbmulti/lib.js @@ -1,7 +1,7 @@ //Multitap logic originally from here: http://www.espruino.com/Morse+Code+Texting exports.input = function(options) { - var options = options||{}; + options = options||{}; var text = options.text; if ("string"!=typeof text) text=""; From ad63cafec6dfb12a69dddb6397b93ef77a0bfff3 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 11 May 2022 20:14:37 +0200 Subject: [PATCH 011/163] Update lib.js --- apps/kbmulti/lib.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/kbmulti/lib.js b/apps/kbmulti/lib.js index 8dd92d6f3..54d600fcb 100644 --- a/apps/kbmulti/lib.js +++ b/apps/kbmulti/lib.js @@ -6,7 +6,7 @@ exports.input = function(options) { if ("string"!=typeof text) text=""; var settings = require('Storage').readJSON("kbmulti.settings.json", true) || {}; - if (settings.firstLaunch===undefined) { settings.firstLaunch = true; } + //if (settings.firstLaunch===undefined) { settings.firstLaunch = true; } if (settings.charTimeout===undefined) { settings.charTimeout = 500; } if (settings.showHelpBtn===undefined) { settings.showHelpBtn = false; } @@ -133,7 +133,7 @@ exports.input = function(options) { return new Promise((resolve,reject) => { g.clearRect(Bangle.appRect); - if (settings.firstLaunch==true) { + if (!settings.firstLaunch) { onHelp(resolve,reject); settings.firstLaunch = false; require('Storage').writeJSON("kbmulti.settings.json", settings); From 8dec7e503be0a22ef2c2f66e99e86b1ec9e5ce97 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 11 May 2022 20:17:15 +0200 Subject: [PATCH 012/163] Update lib.js --- apps/kbmulti/lib.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/kbmulti/lib.js b/apps/kbmulti/lib.js index 54d600fcb..b0d6ae3eb 100644 --- a/apps/kbmulti/lib.js +++ b/apps/kbmulti/lib.js @@ -8,7 +8,7 @@ exports.input = function(options) { var settings = require('Storage').readJSON("kbmulti.settings.json", true) || {}; //if (settings.firstLaunch===undefined) { settings.firstLaunch = true; } if (settings.charTimeout===undefined) { settings.charTimeout = 500; } - if (settings.showHelpBtn===undefined) { settings.showHelpBtn = false; } + if (settings.showHelpBtn===undefined) { settings.showHelpBtn = true; } var fontSize = "6x15"; var Layout = require("Layout"); From c8b1d166973aa47c3c1f46e497181261a4b511c6 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 11 May 2022 20:18:09 +0200 Subject: [PATCH 013/163] Update lib.js --- apps/kbmulti/lib.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/kbmulti/lib.js b/apps/kbmulti/lib.js index b0d6ae3eb..da3894f0b 100644 --- a/apps/kbmulti/lib.js +++ b/apps/kbmulti/lib.js @@ -27,7 +27,7 @@ exports.input = function(options) { function displayText(charTimeout) { layout.clear(layout.text); - layout.text.label = text.slice(settings.showHelpBtn ? -12 : -13) + (charTimeout ? " " : "_"); + layout.text.label = text.slice(settings.showHelpBtn ? -11 : -13) + (charTimeout ? " " : "_"); layout.render(layout.text); } From efa1254673a84231f5a997dfc1a74609777aaed8 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 11 May 2022 20:24:30 +0200 Subject: [PATCH 014/163] Update lib.js --- apps/kbmulti/lib.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/kbmulti/lib.js b/apps/kbmulti/lib.js index da3894f0b..f1f706216 100644 --- a/apps/kbmulti/lib.js +++ b/apps/kbmulti/lib.js @@ -124,6 +124,7 @@ exports.input = function(options) { ]}, ] },{back: ()=>{ + charTimeout = undefined; Bangle.setUI(); Bangle.removeListener("swipe", onSwipe); g.clearRect(Bangle.appRect); From 7c747889ab718731b4c2bc7edd14e56df9bfbab4 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 11 May 2022 20:38:41 +0200 Subject: [PATCH 015/163] Update lib.js --- apps/kbmulti/lib.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/kbmulti/lib.js b/apps/kbmulti/lib.js index f1f706216..0d5b73d5f 100644 --- a/apps/kbmulti/lib.js +++ b/apps/kbmulti/lib.js @@ -6,7 +6,7 @@ exports.input = function(options) { if ("string"!=typeof text) text=""; var settings = require('Storage').readJSON("kbmulti.settings.json", true) || {}; - //if (settings.firstLaunch===undefined) { settings.firstLaunch = true; } + //if (settings.firstLaunch===undefined) { settings.firstLaunch = true; } // Unnecessary if doing if(!settings.firstLaunch) down inside the promise. But maybe it's good to keep it as in v0.01 for readability? if (settings.charTimeout===undefined) { settings.charTimeout = 500; } if (settings.showHelpBtn===undefined) { settings.showHelpBtn = true; } @@ -27,7 +27,7 @@ exports.input = function(options) { function displayText(charTimeout) { layout.clear(layout.text); - layout.text.label = text.slice(settings.showHelpBtn ? -11 : -13) + (charTimeout ? " " : "_"); + layout.text.label = text.slice(settings.showHelpBtn ? -11 : -13) + (charTimeout ? " " : "_"); // Implemented marker here. layout.render(layout.text); } @@ -124,7 +124,7 @@ exports.input = function(options) { ]}, ] },{back: ()=>{ - charTimeout = undefined; + // charTimeout = undefined; // Tried this to see if it would stop the text from being drawn after closing keyboard when doing it too soon after pressing a key. It didn't help. This problem goes back to how I've implemented the marker above. Bangle.setUI(); Bangle.removeListener("swipe", onSwipe); g.clearRect(Bangle.appRect); From c4647bfc68c45ef9e3627785c2673cd3041cf320 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 11 May 2022 20:43:01 +0200 Subject: [PATCH 016/163] Update settings.js --- apps/kbmulti/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/kbmulti/settings.js b/apps/kbmulti/settings.js index c698aca8a..4fad8a428 100644 --- a/apps/kbmulti/settings.js +++ b/apps/kbmulti/settings.js @@ -1,7 +1,7 @@ (function(back) { function settings() { var settings = require('Storage').readJSON("kbmulti.settings.json", true) || {}; - if (settings.firstLaunch===undefined) { settings.firstLaunch = true; } + if (settings.showHelpBtn===undefined) { settings.firstLaunch = true; } if (settings.charTimeout===undefined) { settings.charTimeout = 500; } return settings; } From cb6d46d9c8aa787296e21c07c1055ad322ab498d Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 11 May 2022 20:50:02 +0200 Subject: [PATCH 017/163] Update lib.js --- apps/kbmulti/lib.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/kbmulti/lib.js b/apps/kbmulti/lib.js index 0d5b73d5f..2d38539e8 100644 --- a/apps/kbmulti/lib.js +++ b/apps/kbmulti/lib.js @@ -6,7 +6,7 @@ exports.input = function(options) { if ("string"!=typeof text) text=""; var settings = require('Storage').readJSON("kbmulti.settings.json", true) || {}; - //if (settings.firstLaunch===undefined) { settings.firstLaunch = true; } // Unnecessary if doing if(!settings.firstLaunch) down inside the promise. But maybe it's good to keep it as in v0.01 for readability? + if (settings.firstLaunch===undefined) { settings.firstLaunch = true; } if (settings.charTimeout===undefined) { settings.charTimeout = 500; } if (settings.showHelpBtn===undefined) { settings.showHelpBtn = true; } @@ -134,7 +134,7 @@ exports.input = function(options) { return new Promise((resolve,reject) => { g.clearRect(Bangle.appRect); - if (!settings.firstLaunch) { + if (settings.firstLaunch) { onHelp(resolve,reject); settings.firstLaunch = false; require('Storage').writeJSON("kbmulti.settings.json", settings); From 04679ba3243b2686be809a7d9af1525cbbb42636 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 11 May 2022 20:55:11 +0200 Subject: [PATCH 018/163] Update settings.js --- apps/kbmulti/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/kbmulti/settings.js b/apps/kbmulti/settings.js index 4fad8a428..ab0e26806 100644 --- a/apps/kbmulti/settings.js +++ b/apps/kbmulti/settings.js @@ -1,7 +1,7 @@ (function(back) { function settings() { var settings = require('Storage').readJSON("kbmulti.settings.json", true) || {}; - if (settings.showHelpBtn===undefined) { settings.firstLaunch = true; } + if (settings.showHelpBtn===undefined) { settings.showHelpBtn = true; } if (settings.charTimeout===undefined) { settings.charTimeout = 500; } return settings; } From 28c6103242a0ad6a168cf43de5314b6c2b82fb03 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 11 May 2022 20:55:54 +0200 Subject: [PATCH 019/163] Update settings.js --- apps/kbmulti/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/kbmulti/settings.js b/apps/kbmulti/settings.js index ab0e26806..8a66cd8f0 100644 --- a/apps/kbmulti/settings.js +++ b/apps/kbmulti/settings.js @@ -21,7 +21,7 @@ format: v => v, onchange: v => updateSetting("charTimeout", v), }, - /*LANG*/'Show help button': { + /*LANG*/'Show help button?': { value: !!settings().showHelpBtn, format: v => v?"Yes":"No", onchange: v => updateSetting("showHelpBtn", v) From 4f296ac43438e8ca744b3556e262e55b75bc9788 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 11 May 2022 20:59:49 +0200 Subject: [PATCH 020/163] Update ChangeLog --- apps/kbmulti/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/kbmulti/ChangeLog b/apps/kbmulti/ChangeLog index 191517b30..4d2380bfa 100644 --- a/apps/kbmulti/ChangeLog +++ b/apps/kbmulti/ChangeLog @@ -1,2 +1,2 @@ 0.01: New keyboard -0.02: Introduce setting "Show help button". Make setting firstLaunch invisible by removing corresponding code from settings.js. Add marker that shows when character selection timeout has run out. +0.02: Introduce setting "Show help button". Make setting firstLaunch invisible by removing corresponding code from settings.js. Add marker that shows when character selection timeout has run out. Display opened text on launch when editing existing text string. From 8fae68bccc2271c2c9c1e77e6e647631874fabd3 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 11 May 2022 21:19:09 +0200 Subject: [PATCH 021/163] Update ChangeLog --- apps/kbmulti/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/kbmulti/ChangeLog b/apps/kbmulti/ChangeLog index 4d2380bfa..c6c606bff 100644 --- a/apps/kbmulti/ChangeLog +++ b/apps/kbmulti/ChangeLog @@ -1,2 +1,2 @@ 0.01: New keyboard -0.02: Introduce setting "Show help button". Make setting firstLaunch invisible by removing corresponding code from settings.js. Add marker that shows when character selection timeout has run out. Display opened text on launch when editing existing text string. +0.02: Introduce setting "Show help button?". Make setting firstLaunch invisible by removing corresponding code from settings.js. Add marker that shows when character selection timeout has run out. Display opened text on launch when editing existing text string. From 94690a81ee6fd651d078f8ee213bbe7eb4a76907 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Wed, 11 May 2022 23:03:10 +0200 Subject: [PATCH 022/163] Add new time_utils module and move some functions from sched module to it --- apps/sched/ChangeLog | 1 + apps/sched/lib.js | 17 ------------ apps/sched/metadata.json | 2 +- apps/sched/sched.js | 4 +-- modules/time_utils.js | 57 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 61 insertions(+), 20 deletions(-) create mode 100644 modules/time_utils.js diff --git a/apps/sched/ChangeLog b/apps/sched/ChangeLog index 914bd7002..c68653a76 100644 --- a/apps/sched/ChangeLog +++ b/apps/sched/ChangeLog @@ -7,3 +7,4 @@ 0.07: Update settings Correct `decodeTime(t)` to return a more likely expected time 0.08: add day of week check to getActiveAlarms() +0.09: Move some functions to new time_utils module diff --git a/apps/sched/lib.js b/apps/sched/lib.js index ff35c94cb..fb1a7e4d6 100644 --- a/apps/sched/lib.js +++ b/apps/sched/lib.js @@ -113,20 +113,3 @@ exports.getSettings = function () { exports.setSettings = function(settings) { require("Storage").writeJSON("sched.settings.json", settings); }; - -// time in ms -> { hrs, mins } -exports.decodeTime = function(t) { - t = Math.ceil(t / 60000); // sanitise to full minutes - let hrs = 0 | (t / 60); - return { hrs: hrs, mins: t - hrs * 60 }; -} - -// time in { hrs, mins } -> ms -exports.encodeTime = function(o) { - return o.hrs * 3600000 + o.mins * 60000; -} - -exports.formatTime = function(t) { - let o = exports.decodeTime(t); - return o.hrs + ":" + ("0" + o.mins).substr(-2); -} diff --git a/apps/sched/metadata.json b/apps/sched/metadata.json index 089fffe31..b962326e3 100644 --- a/apps/sched/metadata.json +++ b/apps/sched/metadata.json @@ -1,7 +1,7 @@ { "id": "sched", "name": "Scheduler", - "version": "0.08", + "version": "0.09", "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 7c97600d9..f4d1bc9ad 100644 --- a/apps/sched/sched.js +++ b/apps/sched/sched.js @@ -9,7 +9,7 @@ function showAlarm(alarm) { const settings = require("sched").getSettings(); let msg = ""; - msg += alarm.timer ? require("sched").formatTime(alarm.timer) : require("sched").formatTime(alarm.t); + msg += require("time_utils").formatTime(alarm.timer ? alarm.timer : alarm.t); if (alarm.msg) { msg += "\n"+alarm.msg; } else { @@ -26,7 +26,7 @@ function showAlarm(alarm) { E.showPrompt(msg,{ title:alarm.timer ? /*LANG*/"TIMER!" : /*LANG*/"ALARM!", - buttons : {/*LANG*/"Snooze":true,/*LANG*/"Ok":false} // default is sleep so it'll come back in 10 mins + buttons : {/*LANG*/"Snooze":true,/*LANG*/"Stop":false} // default is sleep so it'll come back in 10 mins }).then(function(sleep) { buzzCount = 0; if (sleep) { diff --git a/modules/time_utils.js b/modules/time_utils.js new file mode 100644 index 000000000..152de2fd0 --- /dev/null +++ b/modules/time_utils.js @@ -0,0 +1,57 @@ +// module "time_utils" +// +// Utility functions useful to work with time and durations. +// Functions usually receive or return a {h, m} object or a +// number of milliseconds representing a time or a duration. +// + +/** + * @param {object} time {h, m} + * @returns the milliseconds contained in the passed time object + */ +exports.encodeTime = (time) => time.h * 3600000 + time.m * 60000; + +/** + * @param {int} millis the number of milliseconds + * @returns a time object {h, m} built from the milliseconds + */ +exports.decodeTime = (millis) => { + millis = Math.ceil(millis / 60000); + var h = 0 | (millis / 60); + return { + h: h, + m: millis - h * 60 + }; +} + +/** + * @param {object|int} value {h,m} object or milliseconds + * @returns an human-readable time string like "10:25" + */ +exports.formatTime = (value) => { + var time = (value.h === undefined || value.m === undefined) ? exports.decodeTime(value) : value; + return time.h + ":" + ("0" + time.m).substr(-2); +} + +/** + * @param {object|int} value {h,m} object or milliseconds + * @returns an human-readable duration string like "1h 10m" + */ +exports.formatDuration = (value) => { + var duration; + + var time = (value.h === undefined || value.m === undefined) ? exports.decodeTime(value) : value; + + if (time.h == 0) { + duration = time.m + "m" + } else { + duration = time.h + "h" + (time.m ? (" " + time.m + "m") : "") + } + + return duration +} + +exports.getCurrentTimeMillis = () => { + var time = new Date(); + return (time.getHours() * 3600 + time.getMinutes() * 60 + time.getSeconds()) * 1000; +} From ee663ef1691f94172d3d5b60bfa54ebb4f5b38a8 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Thu, 12 May 2022 22:51:41 +0200 Subject: [PATCH 023/163] [sleepphasealarm] Update to new time_utils module --- apps/sleepphasealarm/ChangeLog | 1 + apps/sleepphasealarm/app.js | 4 ++-- apps/sleepphasealarm/metadata.json | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/sleepphasealarm/ChangeLog b/apps/sleepphasealarm/ChangeLog index ec3fe3a23..208058472 100644 --- a/apps/sleepphasealarm/ChangeLog +++ b/apps/sleepphasealarm/ChangeLog @@ -6,3 +6,4 @@ 0.06: Add logging use Layout library and display ETA 0.07: Add check for day of week +0.08: Update to new time_utils module diff --git a/apps/sleepphasealarm/app.js b/apps/sleepphasealarm/app.js index 8ccd43eb2..febc8a259 100644 --- a/apps/sleepphasealarm/app.js +++ b/apps/sleepphasealarm/app.js @@ -46,8 +46,8 @@ function calc_ess(acc_magn) { var nextAlarm; active.forEach(alarm => { const now = new Date(); - const t = require("sched").decodeTime(alarm.t); - var dateAlarm = new Date(now.getFullYear(), now.getMonth(), now.getDate(), t.hrs, t.mins); + const time = require("time_utils").decodeTime(alarm.t); + var dateAlarm = new Date(now.getFullYear(), now.getMonth(), now.getDate(), time.h, time.m); if (dateAlarm < now) { // dateAlarm in the past, add 24h dateAlarm.setTime(dateAlarm.getTime() + (24*60*60*1000)); } diff --git a/apps/sleepphasealarm/metadata.json b/apps/sleepphasealarm/metadata.json index d74590704..c74a617ab 100644 --- a/apps/sleepphasealarm/metadata.json +++ b/apps/sleepphasealarm/metadata.json @@ -2,7 +2,7 @@ "id": "sleepphasealarm", "name": "SleepPhaseAlarm", "shortName": "SleepPhaseAlarm", - "version": "0.07", + "version": "0.08", "description": "Uses the accelerometer to estimate sleep and wake states with the principle of Estimation of Stationary Sleep-segments (ESS, see https://ubicomp.eti.uni-siegen.de/home/datasets/ichi14/index.html.en). This app will read the next alarm from the alarm application and will wake you up to 30 minutes early at the best guessed time when you are almost already awake.", "icon": "app.png", "tags": "alarm", From f22f113687a2a3cf9943806ff73e28a8257c1777 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Thu, 12 May 2022 22:59:03 +0200 Subject: [PATCH 024/163] [Alarms & Timers] Full UI rewrite --- apps/alarm/ChangeLog | 1 + apps/alarm/app.js | 488 +++++++++++++++++++++++---------------- apps/alarm/metadata.json | 2 +- apps/sched/lib.js | 6 +- 4 files changed, 288 insertions(+), 209 deletions(-) diff --git a/apps/alarm/ChangeLog b/apps/alarm/ChangeLog index ca1417b5b..b952b1dcd 100644 --- a/apps/alarm/ChangeLog +++ b/apps/alarm/ChangeLog @@ -26,3 +26,4 @@ Add "Enable All", "Disable All" and "Remove All" actions 0.25: Fix redrawing selected Alarm/Timer entry inside edit submenu 0.26: Add support for Monday as first day of the week (#1780) +0.27: New UI! diff --git a/apps/alarm/app.js b/apps/alarm/app.js index cf46823d6..0cf1f3d6f 100644 --- a/apps/alarm/app.js +++ b/apps/alarm/app.js @@ -1,20 +1,160 @@ Bangle.loadWidgets(); Bangle.drawWidgets(); +// 0 = Sunday (default), 1 = Monday +const firstDayOfWeek = (require("Storage").readJSON("setting.json", true) || {}).firstDayOfWeek || 0; +const WORKDAYS = 62 +const WEEKEND = firstDayOfWeek ? 192 : 65; +const EVERY_DAY = firstDayOfWeek ? 254 : 127; + +const iconAlarmOn = "\0" + atob("GBiBAAAAAAAAAAYAYA4AcBx+ODn/nAP/wAf/4A/n8A/n8B/n+B/n+B/n+B/n+B/h+B/4+A/+8A//8Af/4AP/wAH/gAB+AAAAAAAAAA=="); +const iconAlarmOff = "\0" + (g.theme.dark + ? atob("GBjBAP////8AAAAAAAAGAGAOAHAcfjg5/5wD/8AH/+AP5/AP5/Af5/gf5/gf5wAf5gAf4Hgf+f4P+bYP8wMH84cD84cB8wMAebYAAf4AAHg=") + : atob("GBjBAP//AAAAAAAAAAAGAGAOAHAcfjg5/5wD/8AH/+AP5/AP5/Af5/gf5/gf5wAf5gAf4Hgf+f4P+bYP8wMH84cD84cB8wMAebYAAf4AAHg=")); + +const iconTimerOn = "\0" + (g.theme.dark + ? atob("GBjBAP////8AAAAAAAAAAAAH/+AH/+ABgYABgYABgYAA/wAA/wAAfgAAPAAAPAAAfgAA5wAAwwABgYABgYABgYAH/+AH/+AAAAAAAAAAAAA=") + : atob("GBjBAP//AAAAAAAAAAAAAAAH/+AH/+ABgYABgYABgYAA/wAA/wAAfgAAPAAAPAAAfgAA5wAAwwABgYABgYABgYAH/+AH/+AAAAAAAAAAAAA=")); +const iconTimerOff = "\0" + (g.theme.dark + ? atob("GBjBAP////8AAAAAAAAAAAAH/+AH/+ABgYABgYABgYAA/wAA/wAAfgAAPAAAPAAAfgAA5HgAwf4BgbYBgwMBg4cH84cH8wMAAbYAAf4AAHg=") + : atob("GBjBAP//AAAAAAAAAAAAAAAH/+AH/+ABgYABgYABgYAA/wAA/wAAfgAAPAAAPAAAfgAA5HgAwf4BgbYBgwMBg4cH84cH8wMAAbYAAf4AAHg=")); + // An array of alarm objects (see sched/README.md) var alarms = require("sched").getAlarms(); -// 0 = Sunday -// 1 = Monday -var firstDayOfWeek = (require("Storage").readJSON("setting.json", true) || {}).firstDayOfWeek || 0; +function handleFirstDayOfWeek(dow) { + if (firstDayOfWeek == 1) { + if ((dow & 1) == 1) { + // In the scheduler API Sunday is 1. + // Here the week starts on Monday and Sunday is ON so + // when I read the dow I need to move Sunday to 128... + dow += 127; + } else if ((dow & 128) == 128) { + // ... and then when I write the dow I need to move Sunday back to 1. + dow -= 127; + } + } + return dow; +} -function getCurrentTime() { - var time = new Date(); - return ( - time.getHours() * 3600000 + - time.getMinutes() * 60000 + - time.getSeconds() * 1000 - ); +// Check the first day of week and update the dow field accordingly. +alarms.forEach(alarm => alarm.dow = handleFirstDayOfWeek(alarm.dow)); + +function showMainMenu() { + const menu = { + "": { "title": /*LANG*/"Alarms & Timers" }, + "< Back": () => load(), + /*LANG*/"New...": () => showNewMenu() + }; + + alarms.forEach((e, index) => { + var label = e.timer + ? require("time_utils").formatDuration(e.timer) + : require("time_utils").formatTime(e.t) + (e.dow > 0 ? (" " + decodeDOW(e)) : ""); + menu[label] = { + value: e.on ? (e.timer ? iconTimerOn : iconAlarmOn) : (e.timer ? iconTimerOff : iconAlarmOff), + onchange: () => setTimeout(e.timer ? showEditTimerMenu : showEditAlarmMenu, 10, e, index) + }; + }); + + menu[/*LANG*/"Advanced"] = () => showAdvancedMenu(); + + E.showMenu(menu); +} + +function showNewMenu() { + E.showMenu({ + "": { "title": /*LANG*/"New..." }, + "< Back": () => showMainMenu(), + /*LANG*/"Alarm": () => showEditAlarmMenu(undefined, undefined), + /*LANG*/"Timer": () => showEditTimerMenu(undefined, undefined) + }); +} + +function showEditAlarmMenu(selectedAlarm, alarmIndex) { + var isNew = alarmIndex === undefined; + + var alarm = require("sched").newDefaultAlarm(); + alarm.dow = handleFirstDayOfWeek(alarm.dow); + + if (selectedAlarm) { + Object.assign(alarm, selectedAlarm); + } + + var time = require("time_utils").decodeTime(alarm.t); + + const menu = { + "": { "title": isNew ? /*LANG*/"New Alarm" : /*LANG*/"Edit Alarm" }, + "< Back": () => { + saveAlarm(alarm, alarmIndex, time); + showMainMenu(); + }, + /*LANG*/"Hour": { + value: time.h, + format: v => ("0" + v).substr(-2), + min: 0, + max: 23, + wrap: true, + onchange: v => time.h = v + }, + /*LANG*/"Minute": { + value: time.m, + format: v => ("0" + v).substr(-2), + min: 0, + max: 59, + wrap: true, + onchange: v => time.m = v + }, + /*LANG*/"Enabled": { + value: alarm.on, + onchange: v => alarm.on = v + }, + /*LANG*/"Repeat": { + value: decodeDOW(alarm), + onchange: () => setTimeout(showEditRepeatMenu, 100, alarm.dow, dow => { + alarm.rp = dow > 0; + alarm.dow = dow; + alarm.t = require("time_utils").encodeTime(time); + setTimeout(showEditAlarmMenu, 10, alarm, alarmIndex); + }) + }, + /*LANG*/"Vibrate": require("buzz_menu").pattern(alarm.vibrate, v => alarm.vibrate = v), + /*LANG*/"Auto Snooze": { + value: alarm.as, + onchange: v => alarm.as = v + }, + /*LANG*/"Cancel": () => showMainMenu() + }; + + if (!isNew) { + menu[/*LANG*/"Delete"] = () => { + E.showPrompt(/*LANG*/"Are you sure?", { title: /*LANG*/"Delete Alarm" }).then((confirm) => { + if (confirm) { + alarms.splice(alarmIndex, 1); + saveAndReload(); + showMainMenu(); + } else { + alarm.t = require("time_utils").encodeTime(time); + setTimeout(showEditAlarmMenu, 10, alarm, alarmIndex); + } + }); + }; + } + + E.showMenu(menu); +} + +function saveAlarm(alarm, alarmIndex, time) { + alarm.t = require("time_utils").encodeTime(time); + alarm.last = alarm.t < require("time_utils").getCurrentTimeMillis() ? new Date().getDate() : 0; + + if (alarmIndex === undefined) { + alarms.push(alarm); + } else { + alarms[alarmIndex] = alarm; + } + + saveAndReload(); } function saveAndReload() { @@ -23,249 +163,187 @@ function saveAndReload() { require("sched").setAlarms(alarms); require("sched").reload(); + + // Fix after save + alarms.forEach(a => a.dow = handleFirstDayOfWeek(a.dow, firstDayOfWeek)); } -function showMainMenu() { - // Timer img "\0"+atob("DhKBAP////MDDAwwMGGBzgPwB4AeAPwHOBhgwMMzDez////w") - // Alarm img "\0"+atob("FBSBAABgA4YcMPDGP8Zn/mx/48//PP/zD/8A//AP/wD/8A//AP/wH/+D//w//8AAAADwAAYA") - const menu = { - '': { 'title': /*LANG*/'Alarms&Timers' }, - /*LANG*/'< Back': () => { load(); }, - /*LANG*/'New Alarm': () => editAlarm(-1), - /*LANG*/'New Timer': () => editTimer(-1) - }; - alarms.forEach((alarm, idx) => { - alarm.dow = handleFirstDayOfWeek(alarm.dow, firstDayOfWeek); +function decodeDOW(alarm) { + return alarm.rp + ? require("date_utils") + .dows(firstDayOfWeek, 2) + .map((day, index) => alarm.dow & (1 << (index + firstDayOfWeek)) ? day : "_") + .join("") + .toLowerCase() + : "Once" +} - var type, txt; // a leading space is currently required (JS error in Espruino 2v12) - if (alarm.timer) { - type = /*LANG*/"Timer"; - txt = " " + require("sched").formatTime(alarm.timer); - } else { - type = /*LANG*/"Alarm"; - txt = " " + require("sched").formatTime(alarm.t); +function showEditRepeatMenu(dow, dowChangeCallback) { + var originalDow = dow; + var isCustom = dow > 0 && dow != WORKDAYS && dow != WEEKEND && dow != EVERY_DAY; + + const menu = { + "": { "title": /*LANG*/"Repeat Alarm" }, + "< Back": () => dowChangeCallback(dow), + /*LANG*/"Once": { // No days set: the alarm will fire once + value: dow == 0, + onchange: () => dowChangeCallback(0) + }, + /*LANG*/"Workdays": { + value: dow == WORKDAYS, + onchange: () => dowChangeCallback(WORKDAYS) + }, + /*LANG*/"Weekends": { + value: dow == WEEKEND, + onchange: () => dowChangeCallback(WEEKEND) + }, + /*LANG*/"Every Day": { + value: dow == EVERY_DAY, + onchange: () => dowChangeCallback(EVERY_DAY) + }, + /*LANG*/"Custom": { + value: isCustom ? decodeDOW({ rp: true, dow: dow }) : false, + onchange: () => setTimeout(showCustomDaysMenu, 10, isCustom ? dow : EVERY_DAY, dowChangeCallback, originalDow) } - if (alarm.rp) txt += "\0" + atob("FBaBAAABgAAcAAHn//////wAHsABzAAYwAAMAADAAAAAAwAAMAADGAAzgAN4AD//////54AAOAABgAA="); - // rename duplicate alarms - if (menu[type + txt]) { - var n = 2; - while (menu[type + " " + n + txt]) n++; - txt = type + " " + n + txt; - } else txt = type + txt; - // add to menu - menu[txt] = { - value: "\0" + atob(alarm.on ? "EhKBAH//v/////////////5//x//j//H+eP+Mf/A//h//z//////////3//g" : "EhKBAH//v//8AA8AA8AA8AA8AA8AA8AA8AA8AA8AA8AA8AA8AA8AA///3//g"), - onchange: function () { - setTimeout(alarm.timer ? editTimer : editAlarm, 10, idx, alarm); - } - }; - }); + }; - if (alarms.some(e => !e.on)) { - menu[/*LANG*/"Enable All"] = () => enableAll(true); - } - if (alarms.some(e => e.on)) { - menu[/*LANG*/"Disable All"] = () => enableAll(false); - } - if (alarms.length > 0) { - menu[/*LANG*/"Delete All"] = () => deleteAll(); - } - - if (WIDGETS["alarm"]) WIDGETS["alarm"].reload(); - return E.showMenu(menu); + E.showMenu(menu); } -function editDOW(dow, onchange) { +function showCustomDaysMenu(dow, dowChangeCallback, originalDow) { const menu = { - '': { 'title': /*LANG*/'Days of Week' }, - /*LANG*/'< Back': () => onchange(dow) + "": { "title": /*LANG*/"Custom Days" }, + "< Back": () => dowChangeCallback(dow), }; require("date_utils").dows(firstDayOfWeek).forEach((day, i) => { menu[day] = { value: !!(dow & (1 << (i + firstDayOfWeek))), - format: v => v ? /*LANG*/"Yes" : /*LANG*/"No", onchange: v => v ? (dow |= 1 << (i + firstDayOfWeek)) : (dow &= ~(1 << (i + firstDayOfWeek))) }; }); + menu[/*LANG*/"Cancel"] = () => setTimeout(showEditRepeatMenu, 10, originalDow, dowChangeCallback) + E.showMenu(menu); } -function editAlarm(alarmIndex, alarm) { - var newAlarm = alarmIndex < 0; - var a = require("sched").newDefaultAlarm(); - a.dow = handleFirstDayOfWeek(a.dow, firstDayOfWeek); +function showEditTimerMenu(selectedTimer, timerIndex) { + var isNew = timerIndex === undefined; - if (!newAlarm) Object.assign(a, alarms[alarmIndex]); - if (alarm) Object.assign(a, alarm); - var t = require("sched").decodeTime(a.t); + var timer = require("sched").newDefaultTimer(); + + if (selectedTimer) { + Object.assign(timer, selectedTimer); + } + + var time = require("time_utils").decodeTime(timer.timer); const menu = { - '': { 'title': /*LANG*/'Alarm' }, - /*LANG*/'< Back': () => { - saveAlarm(newAlarm, alarmIndex, a, t); + "": { "title": isNew ? /*LANG*/"New Timer" : /*LANG*/"Edit Timer" }, + "< Back": () => { + saveTimer(timer, timerIndex, time); showMainMenu(); }, - /*LANG*/'Hours': { - value: t.hrs, min: 0, max: 23, wrap: true, - onchange: v => t.hrs = v + /*LANG*/"Hours": { + value: time.h, + min: 0, + max: 23, + wrap: true, + onchange: v => time.h = v }, - /*LANG*/'Minutes': { - value: t.mins, min: 0, max: 59, wrap: true, - onchange: v => t.mins = v + /*LANG*/"Minutes": { + value: time.m, + min: 0, + max: 59, + wrap: true, + onchange: v => time.m = v }, - /*LANG*/'Enabled': { - value: a.on, - format: v => v ? /*LANG*/"On" : /*LANG*/"Off", - onchange: v => a.on = v + /*LANG*/"Enabled": { + value: timer.on, + onchange: v => timer.on = v }, - /*LANG*/'Repeat': { - value: a.rp, - format: v => v ? /*LANG*/"Yes" : /*LANG*/"No", - onchange: v => a.rp = v - }, - /*LANG*/'Days': { - value: decodeDOW(a.dow), - onchange: () => setTimeout(editDOW, 100, a.dow, d => { - a.dow = d; - a.t = require("sched").encodeTime(t); - editAlarm(alarmIndex, a); - }) - }, - /*LANG*/'Vibrate': require("buzz_menu").pattern(a.vibrate, v => a.vibrate = v), - /*LANG*/'Auto Snooze': { - value: a.as, - format: v => v ? /*LANG*/"Yes" : /*LANG*/"No", - onchange: v => a.as = v - } + /*LANG*/"Vibrate": require("buzz_menu").pattern(timer.vibrate, v => timer.vibrate = v), }; - menu[/*LANG*/"Cancel"] = () => showMainMenu(); - - if (!newAlarm) { - menu[/*LANG*/"Delete"] = function () { - alarms.splice(alarmIndex, 1); - saveAndReload(); - showMainMenu(); + if (!isNew) { + menu[/*LANG*/"Delete"] = () => { + E.showPrompt(/*LANG*/"Are you sure?", { title: /*LANG*/"Delete Timer" }).then((confirm) => { + if (confirm) { + alarms.splice(timerIndex, 1); + saveAndReload(); + showMainMenu(); + } else { + timer.timer = require("time_utils").encodeTime(time); + setTimeout(showEditTimerMenu, 10, timer, timerIndex) + } + }); }; } - return E.showMenu(menu); + E.showMenu(menu); } -function saveAlarm(newAlarm, alarmIndex, a, t) { - a.t = require("sched").encodeTime(t); - a.last = (a.t < getCurrentTime()) ? (new Date()).getDate() : 0; +function saveTimer(timer, timerIndex, time) { + timer.timer = require("time_utils").encodeTime(time); + timer.t = require("time_utils").getCurrentTimeMillis() + timer.timer; + timer.last = 0; - if (newAlarm) { - alarms.push(a); + if (timerIndex === undefined) { + alarms.push(timer); } else { - alarms[alarmIndex] = a; + alarms[timerIndex] = timer; } saveAndReload(); } -function editTimer(alarmIndex, alarm) { - var newAlarm = alarmIndex < 0; - var a = require("sched").newDefaultTimer(); - if (!newAlarm) Object.assign(a, alarms[alarmIndex]); - if (alarm) Object.assign(a, alarm); - var t = require("sched").decodeTime(a.timer); - - const menu = { - '': { 'title': /*LANG*/'Timer' }, - /*LANG*/'< Back': () => { - saveTimer(newAlarm, alarmIndex, a, t); - showMainMenu(); - }, - /*LANG*/'Hours': { - value: t.hrs, min: 0, max: 23, wrap: true, - onchange: v => t.hrs = v - }, - /*LANG*/'Minutes': { - value: t.mins, min: 0, max: 59, wrap: true, - onchange: v => t.mins = v - }, - /*LANG*/'Enabled': { - value: a.on, - format: v => v ? /*LANG*/"On" : /*LANG*/"Off", - onchange: v => a.on = v - }, - /*LANG*/'Vibrate': require("buzz_menu").pattern(a.vibrate, v => a.vibrate = v), - }; - - menu[/*LANG*/"Cancel"] = () => showMainMenu(); - - if (!newAlarm) { - menu[/*LANG*/"Delete"] = function () { - alarms.splice(alarmIndex, 1); - saveAndReload(); - showMainMenu(); - }; - } - return E.showMenu(menu); -} - -function saveTimer(newAlarm, alarmIndex, a, t) { - a.timer = require("sched").encodeTime(t); - a.t = getCurrentTime() + a.timer; - a.last = 0; - - if (newAlarm) { - alarms.push(a); - } else { - alarms[alarmIndex] = a; - } - - saveAndReload(); -} - -function handleFirstDayOfWeek(dow, firstDayOfWeek) { - if (firstDayOfWeek == 1) { - if ((dow & 1) == 1) { - // By default 1 = Sunday. - // Here the week starts on Monday and Sunday is ON so move Sunday to 128. - dow += 127; - } else if ((dow & 128) == 128) { - dow -= 127; - } - } - return dow; -} - -function decodeDOW(dow) { - return require("date_utils") - .dows(firstDayOfWeek, 2) - .map((day, index) => dow & (1 << (index + firstDayOfWeek)) ? day : "_") - .join(""); +function showAdvancedMenu() { + E.showMenu({ + "": { "title": /*LANG*/"Advanced" }, + "< Back": () => showMainMenu(), + /*LANG*/"Scheduler Settings": () => eval(require("Storage").read("sched.settings.js"))(() => showAdvancedMenu()), + /*LANG*/"Enable All": () => enableAll(true), + /*LANG*/"Disable All": () => enableAll(false), + /*LANG*/"Delete All": () => deleteAll() + }); } function enableAll(on) { - E.showPrompt(/*LANG*/"Are you sure?", { - title: on ? /*LANG*/"Enable All" : /*LANG*/"Disable All" - }).then((confirm) => { - if (confirm) { - alarms.forEach(alarm => alarm.on = on); - saveAndReload(); - } - - showMainMenu(); - }); + if (alarms.filter(e => e.on == !on).length == 0) { + E.showPrompt(on ? /*LANG*/"Nothing to Enable" : /*LANG*/"Nothing to Disable", { + title: on ? /*LANG*/"Enable All" : /*LANG*/"Disable All", + buttons: { /*LANG*/"Ok": true } + }).then(() => showAdvancedMenu()); + } else { + E.showPrompt(/*LANG*/"Are you sure?", { title: on ? "/*LANG*/Enable All" : /*LANG*/"Disable All" }).then((confirm) => { + if (confirm) { + alarms.forEach(alarm => alarm.on = on); + saveAndReload(); + showMainMenu(); + } else { + showAdvancedMenu(); + } + }); + } } function deleteAll() { - E.showPrompt(/*LANG*/"Are you sure?", { - title: /*LANG*/"Delete All" - }).then((confirm) => { - if (confirm) { - alarms = []; - saveAndReload(); - } - - showMainMenu(); - }); + if (alarms.length == 0) { + E.showPrompt(/*LANG*/"Nothing to delete", { title: /*LANG*/"Delete All", buttons: { /*LANG*/"Ok": true } }).then(() => showAdvancedMenu()); + } else { + E.showPrompt(/*LANG*/"Are you sure?", { + title: /*LANG*/"Delete All" + }).then((confirm) => { + if (confirm) { + alarms = []; + saveAndReload(); + showMainMenu(); + } else { + showAdvancedMenu(); + } + }); + } } showMainMenu(); diff --git a/apps/alarm/metadata.json b/apps/alarm/metadata.json index c062b030d..d51e9fa19 100644 --- a/apps/alarm/metadata.json +++ b/apps/alarm/metadata.json @@ -2,7 +2,7 @@ "id": "alarm", "name": "Alarms & Timers", "shortName": "Alarms", - "version": "0.26", + "version": "0.27", "description": "Set alarms and timers on your Bangle", "icon": "app.png", "tags": "tool,alarm,widget", diff --git a/apps/sched/lib.js b/apps/sched/lib.js index fb1a7e4d6..063402e3d 100644 --- a/apps/sched/lib.js +++ b/apps/sched/lib.js @@ -61,12 +61,12 @@ exports.reload = function() { exports.newDefaultAlarm = function () { const settings = exports.getSettings(); - let alarm = { + var alarm = { t: 12 * 3600000, // Default to 12:00 on: true, rp: settings.defaultRepeat, as: settings.defaultAutoSnooze, - dow: 0b1111111, + dow: settings.defaultRepeat ? 0b1111111 : 0b0000000, last: 0, vibrate: settings.defaultAlarmPattern, }; @@ -79,7 +79,7 @@ exports.newDefaultAlarm = function () { exports.newDefaultTimer = function () { const settings = exports.getSettings(); - let timer = { + var timer = { timer: 5 * 60 * 1000, // 5 minutes on: true, rp: false, From dc0c8d7f0cf42bdf63026c08973dd524a4052135 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Fri, 13 May 2022 12:05:23 +0200 Subject: [PATCH 025/163] [Alarms & Timers] Add screenshots --- apps/alarm/metadata.json | 23 ++++++++++++++++++----- apps/alarm/screenshot-1.png | Bin 0 -> 1752 bytes apps/alarm/screenshot-10.png | Bin 0 -> 1979 bytes apps/alarm/screenshot-11.png | Bin 0 -> 2326 bytes apps/alarm/screenshot-2.png | Bin 0 -> 1451 bytes apps/alarm/screenshot-3.png | Bin 0 -> 2402 bytes apps/alarm/screenshot-4.png | Bin 0 -> 2053 bytes apps/alarm/screenshot-5.png | Bin 0 -> 1948 bytes apps/alarm/screenshot-6.png | Bin 0 -> 2277 bytes apps/alarm/screenshot-7.png | Bin 0 -> 2144 bytes apps/alarm/screenshot-8.png | Bin 0 -> 2360 bytes apps/alarm/screenshot-9.png | Bin 0 -> 2274 bytes 12 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 apps/alarm/screenshot-1.png create mode 100644 apps/alarm/screenshot-10.png create mode 100644 apps/alarm/screenshot-11.png create mode 100644 apps/alarm/screenshot-2.png create mode 100644 apps/alarm/screenshot-3.png create mode 100644 apps/alarm/screenshot-4.png create mode 100644 apps/alarm/screenshot-5.png create mode 100644 apps/alarm/screenshot-6.png create mode 100644 apps/alarm/screenshot-7.png create mode 100644 apps/alarm/screenshot-8.png create mode 100644 apps/alarm/screenshot-9.png diff --git a/apps/alarm/metadata.json b/apps/alarm/metadata.json index d51e9fa19..b9ce55756 100644 --- a/apps/alarm/metadata.json +++ b/apps/alarm/metadata.json @@ -6,12 +6,25 @@ "description": "Set alarms and timers on your Bangle", "icon": "app.png", "tags": "tool,alarm,widget", - "supports": ["BANGLEJS","BANGLEJS2"], + "supports": [ "BANGLEJS", "BANGLEJS2" ], "readme": "README.md", - "dependencies": {"scheduler":"type"}, + "dependencies": { "scheduler":"type" }, "storage": [ - {"name":"alarm.app.js","url":"app.js"}, - {"name":"alarm.img","url":"app-icon.js","evaluate":true}, - {"name":"alarm.wid.js","url":"widget.js"} + { "name": "alarm.app.js", "url": "app.js" }, + { "name": "alarm.img", "url": "app-icon.js", "evaluate": true }, + { "name": "alarm.wid.js", "url": "widget.js" } + ], + "screenshots": [ + { "url": "screenshot-1.png" }, + { "url": "screenshot-2.png" }, + { "url": "screenshot-3.png" }, + { "url": "screenshot-4.png" }, + { "url": "screenshot-5.png" }, + { "url": "screenshot-6.png" }, + { "url": "screenshot-7.png" }, + { "url": "screenshot-8.png" }, + { "url": "screenshot-9.png" }, + { "url": "screenshot-10.png" }, + { "url": "screenshot-11.png" } ] } diff --git a/apps/alarm/screenshot-1.png b/apps/alarm/screenshot-1.png new file mode 100644 index 0000000000000000000000000000000000000000..d2bd3a409955c711e18d5e3f093ab488df21a64a GIT binary patch literal 1752 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 literal 0 HcmV?d00001 diff --git a/apps/alarm/screenshot-11.png b/apps/alarm/screenshot-11.png new file mode 100644 index 0000000000000000000000000000000000000000..197c8419449afd37afa1482a31903d8975e2afd5 GIT binary patch literal 2326 zcmZvedpHw}7suV3HLTa%!fd2Ql)IS3$o=PD$#RKYD|=nCScI&Z+bEP~6w4*%-NPvZfCLKu4NFN!KI%^0NG=vJ% zGNs_hl$R*cwP!)x%uUsJb67xvxX4R2c~;sfi?6;QsCvtKUlS81sIZV=9=UHvOt}ib zMJN#V&~+U+c0O9}o6DH-$81yw%;!q{<^x&b_UMDf8*>>OFC&y=XCK*G(F9{0wZwA2 zqB4mxyTckrq^O7cMDz_}0#e#;eg?lY0acmjn4k_oT8#bptfCkmhgUNH2t^IIlEOK< zn|xfW$jQ4O7*UBBdZe~Tgho7!Rk`96BW1pzh-Tm4dF=aGGn#MnSmcES1TMf7HtS9E$Xp5%BpZF z1m{)?YQXeKFxG12CR+h;?_@Zs=;(JfVO_?aE3#o(#CWIkY2t>2O65Y`K3#uJlh2)U8=ey; zClrm+w4`z;iB06&UG_(Ci5Q$%LH!lUefIB`>sBwjK*8X~<@yZ2LZRo1@}cAAS=z11 z#wYeoD7~`#4wgfcJFfsbZ6DM!o^znrwugQtrTR5O-d=(@+=z;jJw}~|5Kwf-831G{&waAD@Lnh z&w=d~^_@|xRyoZGp*R zg;#ZqT!!8sT**+7CQ9O6>j+@fk~DUEtjLTyQoo(kd>cxcwo`A7T(!GgyukJe_DOV< zCmHNb8>oXT?VzpdFVwjm$6eH3md5zS+pyCo-q!vge^Bgq58tvuCvJuw8(dT>#pdO9 z9=yHYl~h8NX2gCU7_I#=o?t$;QnIs^wzk%(RLZSrx=?~L>+4gYcw9#=S(UC?c+Sf@ zz6E^FjqR}lElqb1VM)Bi@WxX?QqG*_)9^Y5acqZJU~|J#j#Nf2tkPoIX&9p&6(aK@ zdpFeFKtUrg0^bZovK$I0MOrO(_m!~r@_IayaV z^?jcEAwzh}8`EZvb2L%>Rk*$aXqV!e|D{e*pdi8(;Dr#$N&b^I0CvN$++Y7b7$)5P zR|-f(PaKj2aT`_L^y020kj zS)r%CZQ~8C`<8*L<5lA-8_`T|n8rFHHSYpFLzgb91*H}v#FK}Hv4>O1U}6yP)Ax!f zZ)3Imsuj`@rfd)UP-L6;!YJhVnZ~K(z&9R3Li0WYT>Gm!q)TA$IJ0myYtuVSXa&UOHv!_Zv z+wOZ){X;K@?J}7Ze|~H7)jTFL3d1NSLpjCmtq$CA5}tplrkSQKH|TNsizP{q|?Z}0n_~Q{7d}S0;J32#Ww7MUIAMI(SD1$*Z{$8RzphfUD45K56QOFRO>aR zI!%Shl*&iPhE^ox!QUWlT+QgsR2B<8_vD^WkmCG3P%EXdEy!Pe-1watPG=-QNT@}) z#zUMu_B+q~3tnM-5*{U>P@^kK7Q_oEcol&EXAe;T4(Q7+^c66@(AffRA@+X*0Kj&4 zcxTcIMehecoyreN6!1gPXzLy zZNnAi-;Okf_V)qZf@dFP6;*;|F|1ietagGt(gt^(Ngw^k<1A)$YbYqDKal7BLnk(K zZJX<_vG)Bl@SC!dgZk?-vbIN$sk}_-SnaU|*y?OP&@IyhX%O|=5BV_6vfH!FJ@|>w zYg!E5$AjUpZd90ccM~l(QgyAY!!$n$wWBkDmcux;4nX}W4mwhQK>7_9A)*BldgY&` z!2#{M`O~^on6RLrUXIn%U>HF_;VvPmH%163sQ2610k9PnyA=y_MOE)>yZ?@W{Yhu* JT9kjve*rl9J~{vZ literal 0 HcmV?d00001 diff --git a/apps/alarm/screenshot-2.png b/apps/alarm/screenshot-2.png new file mode 100644 index 0000000000000000000000000000000000000000..1cbc255a92c2d568765feb3cbf104f10a33d013b GIT binary patch literal 1451 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 L+7UxXdnWuB4r*zu literal 0 HcmV?d00001 diff --git a/apps/alarm/screenshot-4.png b/apps/alarm/screenshot-4.png new file mode 100644 index 0000000000000000000000000000000000000000..7fd7e99b65434752c2a7886124ee704c2ce3b8f1 GIT binary patch literal 2053 zcmai#dpy&N8^`4~#C)k3EtwYO(rF>HWiGR#<5EbuavQ~Q&g=Di{a)v<-yhHOyq-Uve?Fh*{XD4`Y|hC@DN6|n3CUPm znA`2vn!iIrcsHx^gC&K8KpabRQ-_G0uel?XB2@raJMd%Y7hPHP&dM}lhSwtbCGWZF z*>4i&<%)|tq$H~22*j6Jh@Gi}_-0llcOlAz zL6B*KHv(Hsm3tedr0$|W^m4ByC)-+m8z>vxT7#%-VonAz;rl79(K$j+e;EJk_~Z*L z={i<1x+^~@e>l%9=yrNtfp*!YvkL&x(s=>J#&C@U+P405(;c5^uBNM&!Q@dZgAm4e z)uGrg?On@~`UW$0)S+b`zLuj3Z^1G|3_T_JTV!?G&y}_9K_~Gu>8$FwOm6hMvfLRY zGu@+u)&~ENBu?KhFy)o>jWGSCR|Pl4)KqZ3k8@-M4^8u4fu@e}hBerRNd>lL_!OF& zZo9rXMJ=S*5J$H4Fzsf+j9a8odMy@OtqE2nr{eOpEF#mCjBo2!8nY&lX?PRVuYWlJ^=f$M^kfh*yo!0e>guHD3lBikH z`|YDC?~dZBFV?%FWbeo)j=464k9|Qb9DGNWJt$5#iN{{vgcdRg4?AvFv6_$h`xmK@ zQ*J)L*YBWUWc77^7T~ev!9-B8BgFeqHg^9b1?XhJ9ID|@6jQ?)g3X*z@(OCinmeD3 z!|=AObNAYQDbSb+g3q{fE)(X~^W%m%l3A|j zS)mPHQenF@TbDXuV}(R81?h5!o@^@zojf$Zs=E)oBrbC!54v+~Usn&ffI}pvpaa*= z6KGOOv+`GKX?DD@71hw(ky5B|Kv&5+How6EjT8+@#O5PKJ12l+;6101qG{M$(%^(i zK-K;oB9uIq_H0o`3n>cENCL~x02!?iVe4zsdn7Bc`Kh)OK*p_q%?>XDo83DRoFv!p zuI-K`-+oZ+6pW@h^))ZC6QT`MD_&@RI2T>^Wi+k=n^C#!yf6ct=)P)J&(>X?Ka*uG zk`i6Gq70tuKa<55;09B9xZ;5sVwCkW_FbJvGGLh{4~HOutv^ zwnxE4d!6qNanp)J3_OVJZ4*pP>7uI4B~Zzs6ggknk(Z+>L>ZpnifZL&s&q%ZU);xd zwNNxu!=c&yBQQ`nh+SMJbU@4mxw<{)k2jr_y`*u2Drj^RDP1h0rpsTC4x=hL7_@4?RPzgk>qty@8Ec8Or#l&jqGDE)V9uGTj*GAelG0t0ExqQe1a@k%HRgKnaUh z*afJtN1()hvXD}cRe|K+LQ;VLDRbn*H6ReYm~{=22!^f_IB$qr;NsGe2|3Fk2H8+%yy_R>N(uUJ9ogb+S^lQTlBC&vNz^og|SV4=+u_e?@h34XYPJ@DSeza z>Xxc~N+T_=3WFz6&K(E5_TCeGuJo^)_W>7(T0FQ53(>wG_xR>4bQV}T@N4G_XF*6L z<97QCSM6ehwHyLdf2|5TXz!qJEhZebU6wF!rv*Zhn);`&x|4_kdW1_>4P#4)d<-8b zkpx1SU(vaQ5~N46g|JRB$~kI+YAS3f?w3)dlAfAu_kp(8F5!s9 z5nG?{Ae}oPSrjSARJqwP$yZPp4B0w0#SZua5R%z7?H4`-aIBx=G$T)PUz{%@X?B02 zzddAszhiRWn&anmYKLE+#$C79x3LWJRdIJDGdjc{t{5Ulz9kA3X2DE$VJAvty!pq$ zPDGOW?zWpan_1*zO@#3hdI<|6S2LFULD;3g+$!_tCrse(g5t>$`v(<(x@o=HCf)_-RIz9>Z zYPtByrk8Vp-h$PoaoSmDB45k(7}Z*3@+D!>#`E!-E@?k|GS;kz$fsxx$)4Tod_C5El@{JdfbSQhP?X~$IMBqo zfi{*x#Oyt;G`0nOJ6UZHM#KkLRwo*eY#iU8WXMJqpK_~>y#w;Ws9g@7Dn^*cT-rNL zI33mN_hbmP5vC{0&$dM|?-#nU^A)BRMS zb7U6i3YSj8xb$%oYaL3kt!Rlu*Yk;V{9Mvzf_BJB*?&3qzr$zvym!}p`E8Lm?(j#w T$r{bO?_J0eXJcMvcJ20G*^k@2 literal 0 HcmV?d00001 diff --git a/apps/alarm/screenshot-5.png b/apps/alarm/screenshot-5.png new file mode 100644 index 0000000000000000000000000000000000000000..4174c5670eb9800beb19a71ca3e1acc8f58132a6 GIT binary patch literal 1948 zcmZ9NdpHw{8^;-GmdmuwQ7$u=W6Q0fC?jSrb0ktT5jNt8A-QzXT39yXungsrN2eU- zPVTwoHYGX8F-7hqQcgzO>hSyh&htCZ`Qv@xzuxzG-p}{_J}=Y7*N2)|z1!b?HZcvs%(Ud=|JlD~0T2}d@4T-*>f z8$p=TuD{7?22~MeZ_jAyY5zu4=0W>Mt0Xi^nNqp-Dv(jr2cO#O%twI0!fD3@v}=8+ zN)OK3gwdC=?iEox2iv!)rMAwzf$vY`V=iZjCk5p%z6dvL^jDWRuUSq2rB{X_S=zF6 z;L5AgBc7S)cDCyBi~lBE5SUGq1sVJ zFfT@TI&g*fF##S~gpoxGK?PBs5$iGbPF4b0%i1DFSV zKMs-4WP^(upSv*3Cy?X5rz%7g_-|l~dur9vO4T~s0W1&LoIgFhf~c+5X-uFhy00A| z+lF1@oh;O!g^|zP+Vf{YW+&GRUv-eqNNc#`IyS{|EZlpN5OIO(H^>i1(XEtueRbYf zH{^0`wk}-5_?p8sII_sD;qY@6btG3tA`wq99Fc;~1etB8UCfERgZ*`k`z)%~w_BQS zW`!uJCADA^Zr+A2tYZ;7gNkhVj`J8DKT3^-m#0&C24%B6x@;v^;`POwMHc!wn{}}P zE?D3xC(=Ja5TSq&7oZ+U{3udVkuIhj;Y5NVC6Nw40e5M>KveER_EiONA^~)--Myo1PSTx6h20OGUqM3z|38d!cEpN3EKV{)l0d+c-?DSBhr! zD`sj%ii!yPa3RGHN#?eG-F~^bBnegmA zq*#4$4U;Pe^jpADa490K!KPJ1zqQ|85$D+0BiX;&?P{OO__#P>d@h zPRLG$2al5S@Lr@}^U1^d5P!M1=Mk*u^Z{uDclk?YSHh}~S0jou5BwQiB-+>A6iQ^@ zh^TqXtydaL;%AQBC`$3{LAA9*+zQ??QU4bK3P{G%Wd8x%CKXk>%RfkZ*XeP`BncfV z0BEU=FWb2QTwwLTqyDd!Ay2WyFoM3!Q1%D&M6L=!pt|P0r3y7(c>A)G&$&-oP|4I( zizv+*@Bf)tBICk1-|IGwu*>7#g%%>zyS}YSOn$SpL-gcx(NjxG6FseT}&0dlwwf+ARVOe1G0k1 z#&>?L8DA|!xiW}Mdt^fT>VSK?#$dPFj1jf0uBIt#;Bzx1a$`eZ=ypW5`Rhrz;YcjS zbi%gRrJ;T#zS(p#^oC)uK(%a8IN;Ja(B`*w;8@~%ePG4BhdkGa#WEOb!6A;;NTO@4 zy-pkfktT!=DW8i&F?=L0`p~)>J=+#Hm`kQ?u`#X);nO_OP%Ob+X-Wb%Q`zEUR?IwhiYOzqeDeE0W3u^A zl&NLYld1PD%;v^kev8c*@5TilGs-DqvHO))nmM%WR^uZd@3Q>(zCAf8Ou=_x*UD`?{Xzx}G2Reckug(>=?Zx!vjQPV=&Ic0RkP{sP9QlsE^~a}*)t4f3Y$3X zdq%R?NM8mjtUc3C*0|} zxk5EIfQsyHga;~KNTBeg&oxzgHoItwgrBf##+21pkTaZX9FUg0p zbV}J*9;Hb9p#^2VFlt$NnXU%+{%t#7(!^;RqnCtgI2tBs%@2xB=O{_)r|UJ+A`N+` z%0j;Ms-pW^3=Oumkiy~coBhpA6D~r}4RjXV4BY*)tx2)WA}M_PDe)=w8>H9){cDJt z`hcg$x9U-Q^Eag~xTk=8jdJ_+GCMBme{z z`Od;XeV1fh3!sV>&)emZw>J7ygZsa+wyX|=E;hLjdm4oE%`rXXgW zCw%zdNhK zE0J?juWT(uQv{M*-MTwmXpW-JEI@K}gY?+D6q$3Fg)c%;p7p7?D$XiLBQYcj%TcLs zyF*2Dv3LKHaagoPF=a{F0TPfAUr%fTyO}IyroEUi-xY*Q^_iT#*5#B_L?dDmxt@t{>(@vkRe2d7B}| z@4KfWDRMD`dH%8~Ip!WGPgJ8(0vCw5#mS06ks$@% zi5kV6d8ECz)(4j3M?-2Zviow-^&;q@{pjcDjH&kX%!)lx<%8LDA#|2kwI_zf4NcMC zL~TEp7WIS9K-{)!)qH6C(9TIULRHV8e-gsGE2*|qS1Dmbvfw?fj&diQx^+G{wK|f( z(<~8oDq>(2P0oeuujV|sO(8extvmK?CHy&Dr(Gg!F!0i?xX!62aPf_CjS(&)xm;7C zDNrpn2P$yIrs?^(3+g(%7GCA()!L9b-XNy*oXTt!gqD{ss4d-ROYh74K|bXtJ3FP< z^kgSsN$Q1L`gg6{q2bi1&_6^wZQxLmHC8--Dzm`JSYBgtGm0e&iYX* z8ZHLa+oee#2Xmi+cDV3oO&fm^GkvIpnKEMrd}};L zPSRKnHq%X7%Xgg##d zn_)$53bdpmR(#z#ALl5mT&3sR>K-WPzGi6w@LcD?sEtB^Dh literal 0 HcmV?d00001 diff --git a/apps/alarm/screenshot-7.png b/apps/alarm/screenshot-7.png new file mode 100644 index 0000000000000000000000000000000000000000..49da44710d70b2d5882b399dffade0827a9ed76e GIT binary patch literal 2144 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 Ug0Ds8;B(+HH?cy|khjAA0;8-7=l}o! literal 0 HcmV?d00001 diff --git a/apps/alarm/screenshot-8.png b/apps/alarm/screenshot-8.png new file mode 100644 index 0000000000000000000000000000000000000000..86d69cd93ca3141b1b3c47cab200e5a4bcfc129a GIT binary patch literal 2360 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 literal 0 HcmV?d00001 diff --git a/apps/alarm/screenshot-9.png b/apps/alarm/screenshot-9.png new file mode 100644 index 0000000000000000000000000000000000000000..2d8c7fc83045f4ce09531eec84c155eb314406e6 GIT binary patch literal 2274 zcmV<82p#u{P)V{QoaA4|X8|62cv=vmdgm1p_D?kk(k|oRP8C7-Ndrz{#j@qRn@R>wFG$ zjz`dR6O#@hdr^1<^U#j-j+^*tbX1!ejH7Vj`)=Y#NNaEhW^)Z`_QH4H#838UvpcW= zwoi<>i60>wIF^D=bnq!ScCNgJfk;flTJ_aU^Kthsd;EL4s1W`%JWyz^k@kt|htG6i^EZ^~5aGHALzNtc81~sL+WhQ|X-VzrTBKIrL){*2cr0T>B9>5lMCWy^p`g0;x#kx+zyf6Cu^;>k6*Y%^?ygBE+$SH z*-?A_$&Isz@}@?q6hhO~cZ?4(eGQS~yAC(;hsWhPJ4*F`Mw66W0ilL%WZe#I^;A?H zV%O*wuH7|fS6$`kTz@3I2hO?v1%Xgu&FRHfH&;xP{Zn zA;3JasGP!cpEx!wD)smoJ)5+?K1#AvmA;GYZS~QMO0MXWH-d)jnQmZ-jcWC94qcl4ATy+^0jwba0UhE94v`0Q_{P**IeDuMYY0HVlmQ6n5P*OV z0SK86VPSvFhG0<%2t*-H=&i7Obpi?j2v7)ECwbN>9%S}8!&L9h@*eJ+ z?a${uaIKJA_jIeo-w`AFsZ$95XF4d0qq9Flv3gJlj#Q_|D1`ay1lL35bLBi551LT| zg^0NCSNMGxc%Qu+7_Jz3Z7`yrCn>}b5AU;tOGLk^Qd9!Q&p3rhb{(u?cP#WC!n4wS3w<4g z`aj)9+}B5Z9A)ov!#;$NqzuMT}5e0uZoPSgH0Aze6iZLq-mEro?fpBxcMYL0Zr(EGHERg&d8#UA#^yCd z?HnnW+g693x}9L}CM=6n*)W$!$MybeJs9S9n};V_!kRdh#qkt9@n`xk6NA#P68vhR z)`PE4TOGo6%tLL&eFf&lsf@}q%nZ~PK~heQ%4#d3wv=ZvcBhg&c3SiI1Sr_cQ$E$X z>~SNWE2mbJ-du;TW)w?5)3(9+!5dTWdCI6_*i**K?EO%>yC%&RaVp!XdLsW#eoGf%&(q*nCJt@eaEG}`rXDxnZ3v*F9Fp46v|&J*g;Q}bFDDMZ>^v$1AUe1w;5lI)@C z^YCIG%_r(dg`qiDA?}M3#CIa`7!)y}ggBLX58;fM^RLMhwj%wyE2;x`HRP+bT_Mtz z=IcL7Ar{1d>W^gAJibp3RHadfRKlk#1eeD!zgK$Dv_(EwUxxz~!qvp7RK=KzQmwUV zD(As4zgKz?+LABjify;OuV zCL28?tu0%JU@0KfLGZ9wA+9T6X)E$0gz;0ehWM_}z0LN!vLEKSoZ2%_YdrMVp{;KH z_AYu^oXR`HcX&Exq-y$dxsUT_X-aAH&|inPx{XzcMR6*>K3se}>=UI(l<|H*>R&8f z@Nmbt^uH=S6kAd7Ag Date: Fri, 13 May 2022 15:04:46 +0200 Subject: [PATCH 026/163] [Alarms & Timers] Update README --- apps/alarm/README.md | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/apps/alarm/README.md b/apps/alarm/README.md index e979dbaf1..741946b0c 100644 --- a/apps/alarm/README.md +++ b/apps/alarm/README.md @@ -1,7 +1,31 @@ -Alarms & Timers -=============== +# Alarms & Timers This app allows you to add/modify any alarms and timers. -It uses the [`sched` library](https://github.com/espruino/BangleApps/blob/master/apps/sched) -to handle the alarm scheduling in an efficient way that can work alongside other apps. +It uses the [`sched` library](https://github.com/espruino/BangleApps/blob/master/apps/sched) to handle the alarm scheduling in an efficient way that can work alongside other apps. + +## Menu overview + +- `New...` + - `New Alarm` → Configure a new alarm + - `Repeat` → Select when the alarm will fire. You can select a predefined option (_Once_, _Every Day_, _Workdays_ or _Weekends_ or you can configure the days freely) + - `New Timer` → Configure a new timer +- `Advanced` + - `Scheduler settings` → Open the [Scheduler](https://github.com/espruino/BangleApps/tree/master/apps/sched) settings page, see its [README](https://github.com/espruino/BangleApps/blob/master/apps/sched/README.md) for details + - `Enable All` → Enable _all_ disabled alarms & timers + - `Disable All` → Disable _all_ enabled alarms & timers + - `Delete All` → Delete _all_ alarms & timers + +## Creator + +- [Gordon Williams](https://github.com/gfwilliams) + +## Main Contributors + +- [Alessandro Cocco](https://github.com/alessandrococco) - New UI, full rewrite, new features +- [Sabin Iacob](https://github.com/m0n5t3r) - Auto snooze support +- [storm64](https://github.com/storm64) - Fix redrawing in submenus + +## Attributions + +All icons used in this app are from [icons8](https://icons8.com). From 229d0dc1580b423385a1a82c809233094dcee889 Mon Sep 17 00:00:00 2001 From: kirktrekkie Date: Sat, 14 May 2022 10:05:42 +0200 Subject: [PATCH 027/163] Adding Dice-n-Roll app. --- apps/diceroll/ChangeLog | 1 + apps/diceroll/app-icon.js | 1 + apps/diceroll/app.js | 108 ++++++++++++++++++++++++++ apps/diceroll/app.png | Bin 0 -> 637 bytes apps/diceroll/diceroll_screenshot.png | Bin 0 -> 2408 bytes apps/diceroll/metadata.json | 14 ++++ 6 files changed, 124 insertions(+) create mode 100644 apps/diceroll/ChangeLog create mode 100644 apps/diceroll/app-icon.js create mode 100644 apps/diceroll/app.js create mode 100644 apps/diceroll/app.png create mode 100644 apps/diceroll/diceroll_screenshot.png create mode 100644 apps/diceroll/metadata.json diff --git a/apps/diceroll/ChangeLog b/apps/diceroll/ChangeLog new file mode 100644 index 000000000..89dff4011 --- /dev/null +++ b/apps/diceroll/ChangeLog @@ -0,0 +1 @@ +0.01: App created \ No newline at end of file diff --git a/apps/diceroll/app-icon.js b/apps/diceroll/app-icon.js new file mode 100644 index 000000000..4d6e7da16 --- /dev/null +++ b/apps/diceroll/app-icon.js @@ -0,0 +1 @@ +E.toArrayBuffer(atob("ICABAAAAAAAAAAAAAAAAAAHAAAAP8AAAfn4AA/APwA+DwfAPg8HwD+AH8Az4HzAMPnwwDAfgMAwBgDAMCYAwDA2YMAwhmDAMIZAwDCGDMA2BgzAMgYAwDAGAMA8BgPADwYPAAPGPgAB9ngAAH/gAAAfgAAABgAAAAAAAAAAAAAAAAAA=")) diff --git a/apps/diceroll/app.js b/apps/diceroll/app.js new file mode 100644 index 000000000..d514ce92f --- /dev/null +++ b/apps/diceroll/app.js @@ -0,0 +1,108 @@ +var init_message = true; +var acc_data; +var die_roll = 1; +var selected_die = 0; +var roll = 0; +const dices = [4, 6, 10, 12, 20]; + +g.setFontAlign(0,0); + +Bangle.on('touch', function(button, xy) { + // Change die if not rolling + if(roll < 1){ + if(selected_die <= 3){ + selected_die++; + }else{ + selected_die = 0; + } + } + //Disable initial message + init_message = false; +}); + +function rect(){ + x1 = g.getWidth()/2 - 35; + x2 = g.getWidth()/2 + 35; + y1 = g.getHeight()/2 - 35; + y2 = g.getHeight()/2 + 35; + g.drawRect(x1, y1, x2, y2); +} + +function pentagon(){ + x1 = g.getWidth()/2; + y1 = g.getHeight()/2 - 50; + x2 = g.getWidth()/2 - 50; + y2 = g.getHeight()/2 - 10; + x3 = g.getWidth()/2 - 30; + y3 = g.getHeight()/2 + 30; + x4 = g.getWidth()/2 + 30; + y4 = g.getHeight()/2 + 30; + x5 = g.getWidth()/2 + 50; + y5 = g.getHeight()/2 - 10; + g.drawPoly([x1, y1, x2, y2, x3, y3, x4, y4, x5, y5], true); +} + +function triangle(){ + x1 = g.getWidth()/2; + y1 = g.getHeight()/2 - 57; + x2 = g.getWidth()/2 - 50; + y2 = g.getHeight()/2 + 23; + x3 = g.getWidth()/2 + 50; + y3 = g.getHeight()/2 + 23; + g.drawPoly([x1, y1, x2, y2, x3, y3], true); +} + +function drawDie(variant) { + if(variant == 1){ + //Rect, 6 + rect(); + }else if(variant == 3){ + //Pentagon, 12 + pentagon(); + }else{ + //Triangle, 4, 10, 20 + triangle(); + } +} + +function initMessage(){ + g.setFont("6x8", 2); + g.drawString("Dice-n-Roll", g.getWidth()/2, 20); + g.drawString("Shake to roll", g.getWidth()/2, 60); + g.drawString("Tap to change", g.getWidth()/2, 80); + g.drawString("Tap to start", g.getWidth()/2, 150); +} + +function rollDie(){ + acc_data = Bangle.getAccel(); + if(acc_data.diff > 0.3){ + roll = 3; + } + //Mange the die "roll" by chaning the number a few times + if(roll > 0){ + g.drawString("Rolling!", g.getWidth()/2, 150); + die_roll = Math.abs(E.hwRand()) % dices[selected_die] + 1; + roll--; + } + //Draw dice graphics + drawDie(selected_die); + //Draw dice number + g.setFontAlign(0,0); + g.setFont("Vector", 45); + g.drawString(die_roll, g.getWidth()/2, g.getHeight()/2); + //Draw selected die in right corner + g.setFont("6x8", 2); + g.drawString(dices[selected_die], g.getWidth()-15, 15); +} + +function main() { + g.clear(); + if(init_message){ + initMessage(); + }else{ + rollDie(); + } + Bangle.setLCDPower(1); +} + +var interval = setInterval(main, 300); \ No newline at end of file diff --git a/apps/diceroll/app.png b/apps/diceroll/app.png new file mode 100644 index 0000000000000000000000000000000000000000..b695b7080ae9fb84e30140aa653c221fc2c7aecd GIT binary patch literal 637 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 LA>Lvy%K3i-A)as# literal 0 HcmV?d00001 diff --git a/apps/diceroll/metadata.json b/apps/diceroll/metadata.json new file mode 100644 index 000000000..81a2f8bfd --- /dev/null +++ b/apps/diceroll/metadata.json @@ -0,0 +1,14 @@ +{ "id": "diceroll", + "name": "Dice-n-Roll", + "shortName":"Dice-n-Roll", + "icon": "app.png", + "version":"0.01", + "description": "A dice app with a few different dice.", + "screenshots": [{"url":"diceroll_screenshot.png"}], + "tags": "game", + "supports": ["BANGLEJS2"], + "storage": [ + {"name":"diceroll.app.js","url":"app.js"}, + {"name":"diceroll.img","url":"app-icon.js","evaluate":true} + ] + } \ No newline at end of file From 71ebe9bca52239b4e8a1820c9c59d12f3909bcc1 Mon Sep 17 00:00:00 2001 From: Iakov Davydov Date: Sat, 14 May 2022 10:38:37 +0200 Subject: [PATCH 028/163] widbt: option to hide when no connection --- apps/widbt/ChangeLog | 1 + apps/widbt/app-icon.js | 1 + apps/widbt/metadata.json | 9 ++++++--- apps/widbt/settings.js | 22 ++++++++++++++++++++++ apps/widbt/widget.js | 24 ++++++++++++++++++++---- 5 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 apps/widbt/app-icon.js create mode 100644 apps/widbt/settings.js diff --git a/apps/widbt/ChangeLog b/apps/widbt/ChangeLog index 4c2132122..55bdf4730 100644 --- a/apps/widbt/ChangeLog +++ b/apps/widbt/ChangeLog @@ -5,3 +5,4 @@ 0.06: Tweaking colors for dark/light themes and low bpp screens 0.07: Memory usage improvements 0.08: Disable LCD on, on bluetooth status change +0.09: Hide widget when disconnected (a setting) diff --git a/apps/widbt/app-icon.js b/apps/widbt/app-icon.js new file mode 100644 index 000000000..131db3a39 --- /dev/null +++ b/apps/widbt/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwMB/4AG/YFE/IFE/AFFv4FEn4FEj4FEg4FEgYFEHIn4oAFEsAqD/FwFQXx/F4h4FB+H4vgwC+F4vARC/E4uAdC/kYsAiC/0IoIvDgBBEwBNE4AuCAAPgL4nwNYgFFCIodFFIo1EIIpNFLIplF8BxEPoQFC/aJESo6hFVoq5FYorRFborpFeon5Aon7AogADA=")) diff --git a/apps/widbt/metadata.json b/apps/widbt/metadata.json index e2d5082a5..098d6a37e 100644 --- a/apps/widbt/metadata.json +++ b/apps/widbt/metadata.json @@ -1,13 +1,16 @@ { "id": "widbt", "name": "Bluetooth Widget", - "version": "0.08", + "version": "0.09", "description": "Show the current Bluetooth connection status in the top right of the clock", "icon": "widget.png", "type": "widget", "tags": "widget,bluetooth", "supports": ["BANGLEJS","BANGLEJS2"], "storage": [ - {"name":"widbt.wid.js","url":"widget.js"} - ] + {"name":"widbt.wid.js","url":"widget.js"}, + {"name":"widbt.settings.js","url":"settings.js"}, + {"name":"widbt.img","url":"app-icon.js","evaluate":true} + ], + "data": [{"name":"widbt.json"}] } diff --git a/apps/widbt/settings.js b/apps/widbt/settings.js new file mode 100644 index 000000000..0400a2eec --- /dev/null +++ b/apps/widbt/settings.js @@ -0,0 +1,22 @@ +(function(back) { + var FILE = "widbt.json"; + var settings = require('Storage').readJSON(FILE, true) || {}; + + function writeSettings() { + require('Storage').writeJSON(FILE, settings); + } + + E.showMenu({ + "" : { "title" : "Bluetooth Widget" }, + "< Back" : () => back(), + 'No conn. widget': { + value: !!settings.hideDisconnected, + format: v => v?"Hide":"Show", + onchange: v => { + settings.hideDisconnected = v; + writeSettings(); + if (WIDGETS.bluetooth) WIDGETS.bluetooth.changed(); + } + }, + }); +}) diff --git a/apps/widbt/widget.js b/apps/widbt/widget.js index c7ef8c0ad..24779c29d 100644 --- a/apps/widbt/widget.js +++ b/apps/widbt/widget.js @@ -1,12 +1,28 @@ -WIDGETS["bluetooth"]={area:"tr",width:15,draw:function() { +WIDGETS["bluetooth"]={area:"tr",draw:function() { + if (WIDGETS.bluetooth.width==0) + return; g.reset(); if (NRF.getSecurityStatus().connected) g.setColor((g.getBPP()>8) ? "#07f" : (g.theme.dark ? "#0ff" : "#00f")); else g.setColor(g.theme.dark ? "#666" : "#999"); g.drawImage(atob("CxQBBgDgFgJgR4jZMawfAcA4D4NYybEYIwTAsBwDAA=="),2+this.x,2+this.y); +},getWidth:function(){ + if (!NRF.getSecurityStatus().connected) { + const settings = require('Storage').readJSON("widbt.json", true) || {}; + if (settings.hideDisconnected) + return 0; + } + return 15; },changed:function() { - WIDGETS["bluetooth"].draw(); + const newWidth = WIDGETS.bluetooth.getWidth(); + if (WIDGETS.bluetooth.width != newWidth) { + WIDGETS.bluetooth.width = newWidth; + Bangle.drawWidgets(); + } else { + WIDGETS.bluetooth.draw(); + } }}; -NRF.on('connect',WIDGETS["bluetooth"].changed); -NRF.on('disconnect',WIDGETS["bluetooth"].changed); +WIDGETS.bluetooth.width = WIDGETS.bluetooth.getWidth(); +NRF.on('connect',WIDGETS.bluetooth.changed); +NRF.on('disconnect',WIDGETS.bluetooth.changed); From 6c88688a5011b76f278e2509091dcb8b550aca2a Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Sat, 14 May 2022 11:23:22 -0700 Subject: [PATCH 029/163] Create app.js --- apps/multitimer/app.js | 660 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 660 insertions(+) create mode 100644 apps/multitimer/app.js diff --git a/apps/multitimer/app.js b/apps/multitimer/app.js new file mode 100644 index 000000000..caf2637f0 --- /dev/null +++ b/apps/multitimer/app.js @@ -0,0 +1,660 @@ +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +var R = Bangle.appRect; +var layer; +var drag; +var timerInt1 = []; +var timerInt2 = []; + +function getCurrentTime() { + let time = new Date(); + return ( + time.getHours() * 3600000 + + time.getMinutes() * 60000 + + time.getSeconds() * 1000 + ); +} + +function decodeTime(t) { + let hrs = 0 | Math.floor(t / 3600000 % 24); + let mins = 0 | Math.floor(t / 60000 % 60); + let secs = 0 | Math.floor(t / 1000 % 60); + return { hrs: hrs, mins: mins, secs: secs }; +} + +function encodeTime(o) { + return o.hrs * 3600000 + o.mins * 60000 + o.secs * 1000; +} + +function formatTime(t) { + let o = decodeTime(t); + return o.hrs + ":" + ("0" + o.mins).substr(-2) + ":" + ("0" + o.secs).substr(-2); +} + +function decodeTimeDecis(t) { + let hrs = 0 | Math.floor(t / 3600000 % 24); + let mins = 0 | Math.floor(t / 60000 % 60); + let secs = 0 | Math.floor(t / 1000 % 60); + let decis = 0 | Math.floor(t / 100 % 100); + return { hrs: hrs, mins: mins, secs: secs, decis: decis }; +} + +function formatTimeDecis(t) { + let o = decodeTimeDecis(t); + return o.hrs + ":" + ("0" + o.mins).substr(-2) + ":" + ("0" + o.secs).substr(-2) + "." + ("0" + o.decis).substr(-1); +} + +function clearInt() { + for (let i = 0; i < timerInt1.length; i++) { + if (timerInt1[i]) clearTimeout(timerInt1[i]); + } + for (let i = 0; i < timerInt2.length; i++) { + if (timerInt2[i]) clearInterval(timerInt2[i]); + } + timerInt1 = []; + timerInt2 = []; +} + +function drawTimers() { + layer = 0; + var timers = require("sched").getAlarms().filter(a => a.timer && a.appid == "multitimer"); + var alarms = require("sched").getAlarms(); + + function updateTimers(idx) { + if (!timerInt1[idx]) timerInt1[idx] = setTimeout(function() { + s.drawItem(idx+1); + if (!timerInt2[idx]) timerInt2[idx] = setInterval(function(){ + s.drawItem(idx+1); + }, 1000); + }, 1000 - (timers[idx].t % 1000)); + } + + var s = E.showScroller({ + h : 40, c : timers.length+2, + back : function() {load();}, + draw : (idx, r) => { + function drawMenuItem(a) { + g.setClipRect(R.x,R.y,R.x2,R.y2); + if (idx > 0 && timers[idx-1].msg) msg = "\n"+(timers[idx-1].msg.length > 10 ? + timers[idx-1].msg.substring(0, 10)+"..." : timers[idx-1].msg); + else msg = ""; + return g.setColor(g.theme.bg2).fillRect({x:r.x+4,y:r.y+2,w:r.w-8, h:r.h-4, r:5}) + .setColor(g.theme.fg2).setFont("6x8:2").setFontAlign(-1,0).drawString(a+msg,r.x+12,r.y+(r.h/2)); + } + + if (idx == 0) { + drawMenuItem("+ New Timer"); + } + if (idx == timers.length+1) { + g.setColor(g.theme.bg).fillRect({x:r.x+4,y:r.y+2,w:r.w-8, h:r.h-4, r:5}) + .setColor(g.theme.fg).setFont("6x8:2").setFontAlign(0,0).drawString("< Swipe >",r.x+(r.w/2),r.y+(r.h/2)); + } + else if (idx > 0 && idx < timers.length+1) { + if (timers[idx-1].on == true) { + drawMenuItem(formatTime(timers[idx-1].t-getCurrentTime())); + updateTimers(idx-1); + } + else drawMenuItem(formatTime(timers[idx-1].timer)); + } + }, + select : (idx) => { + clearInt(); + if (idx == 0) editTimer(-1); + else if (idx > 0 && idx < timers.length+1) timerMenu(idx-1); + } + }); +} + +function timerMenu(idx) { + layer = -1; + var timers = require("sched").getAlarms(); + var timerIdx = []; + var j = 0; + for (let i = 0; i < timers.length; i++) { + if (timers[i].timer && timers[i].appid == "multitimer") { + a = i; + timerIdx.push(a); + j++; + } + } + var a = timers[timerIdx[idx]]; + var msg = ""; + + function updateTimer() { + if (timerInt1[0] == undefined) timerInt1[0] = setTimeout(function() { + s.drawItem(0); + if (timerInt2[0] == undefined) timerInt2[0] = setInterval(function(){ + s.drawItem(0); + }, 1000); + }, 1000 - (a.t % 1000)); + } + + var s = E.showScroller({ + h : 40, c : 5, + back : function() { + clearInt(); + drawTimers(); + }, + draw : (i, r) => { + + function drawMenuItem(b) { + return g.setClipRect(R.x,R.y,R.x2,R.y2).setColor(g.theme.bg2) + .fillRect({x:r.x+4,y:r.y+2,w:r.w-8, h:r.h-4, r:5}) + .setColor(g.theme.fg2).setFont("6x8:2").setFontAlign(-1,0).drawString(b,r.x+12,r.y+(r.h/2)); + } + + if (i == 0) { + if (a.msg) msg = "\n"+(a.msg.length > 10 ? a.msg.substring(0, 10)+"..." : a.msg); + if (a.on == true) { + drawMenuItem(formatTime(a.t-getCurrentTime())+msg); + updateTimer(); + } + else { + clearInt(); + drawMenuItem(formatTime(a.timer)+msg); + } + } + if (i == 1) { + if (a.on == true) drawMenuItem("Pause"); + else drawMenuItem("Start"); + } + if (i == 2) drawMenuItem("Reset"); + if (i == 3) drawMenuItem("Edit"); + if (i == 4) drawMenuItem("Delete"); + }, + select : (i) => { + + function saveAndReload() { + require("sched").setAlarms(timers); + require("sched").reload(); + s.draw(); + } + + //pause/start + if (i == 1) { + if (a.on == true) { + clearInt(); + a.timer = a.t-getCurrentTime(); + a.on = false; + timers[timerIdx[idx]] = a; + saveAndReload(); + } + else { + a.t = a.timer+getCurrentTime(); + a.on = true; + timers[timerIdx[idx]] = a; + saveAndReload(); + } + } + //reset + if (i == 2) { + clearInt(); + a.timer = a.data; + if (a.on == true) a.on = false; + saveAndReload(); + } + //edit + if (i == 3) { + clearInt(); + editTimer(idx); + } + //delete + if (i == 4) { + clearInt(); + timers.splice(timerIdx[idx], 1); + saveAndReload(); + drawTimers(); + } + } + }); +} + +function editTimer(idx, a) { + layer = -1; + var timers = require("sched").getAlarms().filter(a => a.timer && a.appid == "multitimer"); + var alarms = require("sched").getAlarms(); + var timerIdx = []; + var j = 0; + for (let i = 0; i < alarms.length; i++) { + if (alarms[i].timer && alarms[i].appid == "multitimer") { + b = i; + timerIdx.push(b); + j++; + } + } + if (!a) { + if (idx < 0) a = require("sched").newDefaultTimer(); + else a = timers[idx]; + } + var t = decodeTime(a.timer); + + function editMsg(idx, a) { + g.clear(); + idx < 0 ? msg = "" : msg = a.msg; + require("textinput").input({text:msg}).then(result => { + if (result != "") { + a.msg = result; + } + else delete a.msg; + editTimer(idx, a); + }); + } + + function kbAlert() { + E.showAlert("Must install keyboard app").then(function() { + editTimer(idx, a); + }); + } + + var menu = { + "": { "title": "Timer" }, + "< Back": () => { + a.t = getCurrentTime() + a.timer; + a.last = 0; + a.data = a.timer; + a.appid = "multitimer"; + a.js = "load('multitimer.alarm.js')"; + if (idx < 0) alarms.push(a); + else alarms[timerIdx[idx]] = a; + require("sched").setAlarms(alarms); + require("sched").reload(); + drawTimers(); + }, + "Enabled": { + value: a.on, + format: v => v ? "On" : "Off", + onchange: v => a.on = v + }, + "Hours": { + value: t.hrs, min: 0, max: 23, wrap: true, + onchange: v => { + t.hrs = v; + a.timer = encodeTime(t); + } + }, + "Minutes": { + value: t.mins, min: 0, max: 59, wrap: true, + onchange: v => { + t.mins = v; + a.timer = encodeTime(t); + } + }, + "Seconds": { + value: t.secs, min: 0, max: 59, wrap: true, + onchange: v => { + t.secs = v; + a.timer = encodeTime(t); + } + }, + "Vibrate": require("buzz_menu").pattern(a.vibrate, v => a.vibrate = v), + "Msg": { + value: !a.msg ? "" : a.msg.length > 6 ? a.msg.substring(0, 6)+"..." : a.msg, + //menu glitch? setTimeout required here + onchange: () => { + var kbapp = require("Storage").read("textinput"); + if (kbapp != undefined) setTimeout(editMsg, 0, idx, a); + else setTimeout(kbAlert, 0); + } + }, + "Cancel": () => { + if (idx >= 0) timerMenu(idx); + else drawTimers(); + }, + }; + + E.showMenu(menu); +} + +function drawSw() { + layer = 1; + var sw = require("Storage").readJSON("multitimer.json", true) || []; + + function updateTimers(idx) { + if (!timerInt1[idx]) timerInt1[idx] = setTimeout(function() { + s.drawItem(idx+1); + if (!timerInt2[idx]) timerInt2[idx] = setInterval(function(){ + s.drawItem(idx+1); + }, 1000); + }, 1000 - (sw[idx].t % 1000)); + } + + var s = E.showScroller({ + h : 40, c : sw.length+2, + back : function() {load();}, + draw : (idx, r) => { + + function drawMenuItem(a) { + g.setClipRect(R.x,R.y,R.x2,R.y2); + if (idx > 0 && sw[idx-1].msg) msg = "\n"+(sw[idx-1].msg.length > 10 ? + sw[idx-1].msg.substring(0, 10)+"..." : sw[idx-1].msg); + else msg = ""; + return g.setColor(g.theme.bg2).fillRect({x:r.x+4,y:r.y+2,w:r.w-8, h:r.h-4, r:5}) + .setColor(g.theme.fg2).setFont("6x8:2").setFontAlign(-1,0).drawString(a+msg,r.x+12,r.y+(r.h/2)); + } + + if (idx == 0) { + drawMenuItem("+ New Chrono"); + } + if (idx == sw.length+1) { + g.setColor(g.theme.bg).fillRect({x:r.x+4,y:r.y+2,w:r.w-8, h:r.h-4, r:5}) + .setColor(g.theme.fg).setFont("6x8:2").setFontAlign(0,0).drawString("< Swipe >",r.x+(r.w/2),r.y+(r.h/2)); + } + else if (idx > 0 && idx < sw.length+1) { + if (sw[idx-1].on == true) { + drawMenuItem(formatTime(Date.now()-sw[idx-1].t)); + updateTimers(idx-1); + } + else drawMenuItem(formatTime(sw[idx-1].t)); + } + }, + select : (idx) => { + clearInt(); + if (idx == 0) swMenu(sw.length); + else if (idx > 0 && idx < sw.length+1) swMenu(idx-1); + } + }); +} + +function swMenu(idx, a) { + layer = -1; + var sw = require("Storage").readJSON("multitimer.json", true) || []; + if (sw[idx]) a = sw[idx]; + else { + a = {"t" : 0, "on" : false, "msg" : ""}; + sw[idx] = a; + require("Storage").writeJSON("multitimer.json", sw); + } + + function updateTimer() { + if (timerInt1[0] == undefined) timerInt1[0] = setTimeout(function() { + s.drawItem(0); + if (timerInt2[0] == undefined) timerInt2[0] = setInterval(function(){ + s.drawItem(0); + }, 100); + }, 100 - (a.t % 100)); + } + + function editMsg(idx, a) { + g.clear(); + msg = a.msg; + require("textinput").input({text:msg}).then(result => { + if (result != "") { + a.msg = result; + } + else delete a.msg; + sw[idx] = a; + require("Storage").writeJSON("multitimer.json", sw); + swMenu(idx, a); + }); + } + + function kbAlert() { + E.showAlert("Must install keyboard app").then(function() { + swMenu(idx, a); + }); + } + + var s = E.showScroller({ + h : 40, c : 5, + back : function() { + clearInt(); + drawSw(); + }, + draw : (i, r) => { + + function drawMenuItem(b) { + return g.setClipRect(R.x,R.y,R.x2,R.y2).setColor(g.theme.bg2) + .fillRect({x:r.x+4,y:r.y+2,w:r.w-8, h:r.h-4, r:5}) + .setColor(g.theme.fg2).setFont("6x8:2").setFontAlign(-1,0).drawString(b,r.x+12,r.y+(r.h/2)); + } + + if (i == 0) { + if (a.msg) msg = "\n"+(a.msg.length > 10 ? a.msg.substring(0, 10)+"..." : a.msg); + else msg = ""; + if (a.on == true) { + drawMenuItem(formatTimeDecis(Date.now()-a.t)+msg); + updateTimer(); + } + else { + clearInt(); + drawMenuItem(formatTimeDecis(a.t)+msg); + } + } + if (i == 1) { + if (a.on == true) drawMenuItem("Pause"); + else drawMenuItem("Start"); + } + if (i == 2) drawMenuItem("Reset"); + if (i == 3) drawMenuItem("Msg"); + if (i == 4) drawMenuItem("Delete"); + }, + select : (i) => { + + function saveAndReload() { + require("Storage").writeJSON("multitimer.json", sw); + s.draw(); + } + + //pause/start + if (i == 1) { + if (a.on == true) { + clearInt(); + a.t = Date.now()-a.t; + a.on = false; + sw[idx] = a; + saveAndReload(); + } + else { + a.t == 0 ? a.t = Date.now() : a.t = Date.now()-a.t; + a.on = true; + sw[idx] = a; + saveAndReload(); + } + } + //reset + if (i == 2) { + clearInt(); + a.t = 0; + if (a.on == true) a.on = false; + saveAndReload(); + } + //edit message + if (i == 3) { + clearInt(); + var kbapp = require("Storage").read("textinput"); + if (kbapp != undefined) editMsg(idx, a); + else kbAlert(); + } + //delete + if (i == 4) { + clearInt(); + sw.splice(idx, 1); + saveAndReload(); + drawSw(); + } + } + }); +} + +function drawAlarms() { + layer = 2; + var alarms = require("sched").getAlarms().filter(a => !a.timer); + + var s = E.showScroller({ + h : 40, c : alarms.length+2, + back : function() {load();}, + draw : (idx, r) => { + + function drawMenuItem(a) { + g.setClipRect(R.x,R.y,R.x2,R.y2); + var on = ""; + var dow = ""; + if (idx > 0 && alarms[idx-1].on == true) on = " - on"; + else if (idx > 0 && alarms[idx-1].on == false) on = " - off"; + if (idx > 0 && idx < alarms.length+1) dow = "\n"+"SMTWTFS".split("").map((d,n)=>alarms[idx-1].dow&(1<",r.x+(r.w/2),r.y+(r.h/2)); + } + else if (idx > 0 && idx < alarms.length+1){ + var str = formatTime(alarms[idx-1].t); + drawMenuItem(str.slice(0, -3)); + } + }, + select : (idx) => { + clearInt(); + if (idx == 0) editAlarm(-1); + else if (idx > 0 && idx < alarms.length+1) editAlarm(idx-1); + } + }); +} + +function editDOW(dow, onchange) { + const menu = { + '': { 'title': 'Days of Week' }, + '< Back' : () => onchange(dow) + }; + for (var i = 0; i < 7; i++) (i => { + var dayOfWeek = require("locale").dow({ getDay: () => i }); + menu[dayOfWeek] = { + value: !!(dow&(1< v ? "Yes" : "No", + onchange: v => v ? dow |= 1<= 0) a = alarms[alarmIdx[idx]]; + else a = require("sched").newDefaultAlarm(); + } + var t = decodeTime(a.t); + + function editMsg(idx, a) { + g.clear(); + idx < 0 ? msg = "" : msg = a.msg; + require("textinput").input({text:msg}).then(result => { + if (result != "") { + a.msg = result; + } + else delete a.msg; + editAlarm(idx, a); + }); + } + + function kbAlert() { + E.showAlert("Must install keyboard app").then(function() { + editAlarm(idx, a); + }); + } + + var menu = { + "": { "title": "Alarm" }, + "< Back": () => { + if (idx >= 0) alarms[alarmIdx[idx]] = a; + else alarms.push(a); + require("sched").setAlarms(alarms); + require("sched").reload(); + drawAlarms(); + }, + "Enabled": { + value: a.on, + format: v => v ? "On" : "Off", + onchange: v => a.on = v + }, + "Hours": { + value: t.hrs, min: 0, max: 23, wrap: true, + onchange: v => { + t.hrs = v; + a.t = encodeTime(t); + } + }, + "Minutes": { + value: t.mins, min: 0, max: 59, wrap: true, + onchange: v => { + t.mins = v; + a.t = encodeTime(t); + } + }, + "Repeat": { + value: a.rp, + format: v => v ? "Yes" : "No", + onchange: v => a.rp = v + }, + "Days": { + value: "SMTWTFS".split("").map((d,n)=>a.dow&(1< editDOW(a.dow, d=>{a.dow=d;editAlarm(idx,a);}) + }, + "Vibrate": require("buzz_menu").pattern(a.vibrate, v => a.vibrate = v), + "Auto Snooze": { + value: a.as, + format: v => v ? "Yes" : "No", + onchange: v => a.as = v + }, + "Msg": { + value: !a.msg ? "" : a.msg.length > 6 ? a.msg.substring(0, 6)+"..." : a.msg, + //menu glitch? setTimeout required here + onchange: () => { + var kbapp = require("Storage").read("textinput"); + if (kbapp != undefined) setTimeout(editMsg, 0, idx, a); + else setTimeout(kbAlert, 0); + } + }, + "Delete": () => { + if (idx >= 0) { + alarms.splice(alarmIdx[idx], 1); + require("sched").setAlarms(alarms); + require("sched").reload(); + } + drawAlarms(); + }, + }; + + E.showMenu(menu); +} + +drawTimers(); + +Bangle.on("drag", e=>{ + if (layer < 0) return; + if (!drag) { // start dragging + drag = {x: e.x, y: e.y}; + } + else if (!e.b) { // released + const dx = e.x-drag.x, dy = e.y-drag.y; + drag = null; + if (dx == 0) return; + //horizontal swipes + if (Math.abs(dx)>Math.abs(dy)+10) { + //swipe left + if (dx<0) layer == 2 ? layer = 0 : layer++; + //swipe right + if (dx>0) layer == 0 ? layer = 2 : layer--; + clearInt(); + if (layer == 0) drawTimers(); + else if (layer == 1) drawSw(); + else if (layer == 2) drawAlarms(); + } + } +}); From 29354d6a51c615b03fc86a64d9b190325b832770 Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Sat, 14 May 2022 11:23:50 -0700 Subject: [PATCH 030/163] Add files via upload --- apps/multitimer/ChangeLog | 1 + apps/multitimer/README.md | 8 ++++ apps/multitimer/alarm.js | 77 ++++++++++++++++++++++++++++++++ apps/multitimer/app-icon.js | 1 + apps/multitimer/app.png | Bin 0 -> 971 bytes apps/multitimer/metadata.json | 22 +++++++++ apps/multitimer/screenshot1.png | Bin 0 -> 3337 bytes apps/multitimer/screenshot2.png | Bin 0 -> 2970 bytes apps/multitimer/screenshot3.png | Bin 0 -> 3476 bytes 9 files changed, 109 insertions(+) create mode 100644 apps/multitimer/ChangeLog create mode 100644 apps/multitimer/README.md create mode 100644 apps/multitimer/alarm.js create mode 100644 apps/multitimer/app-icon.js create mode 100644 apps/multitimer/app.png create mode 100644 apps/multitimer/metadata.json create mode 100644 apps/multitimer/screenshot1.png create mode 100644 apps/multitimer/screenshot2.png create mode 100644 apps/multitimer/screenshot3.png diff --git a/apps/multitimer/ChangeLog b/apps/multitimer/ChangeLog new file mode 100644 index 000000000..624f1b0fb --- /dev/null +++ b/apps/multitimer/ChangeLog @@ -0,0 +1 @@ +0.01: Initial version \ No newline at end of file diff --git a/apps/multitimer/README.md b/apps/multitimer/README.md new file mode 100644 index 000000000..0cc747c28 --- /dev/null +++ b/apps/multitimer/README.md @@ -0,0 +1,8 @@ +# Multi Timer +With this app, you can set timers and chronographs (stopwatches) and watch them count down/up in real time. You can also set alarms - swipe left or right to switch between the three functions. + +## WARNING +* Editing timers in another app (such as the default Alarm app) is not recommended. Editing alarms should not be a problem. +* This app uses the [Scheduler library](https://banglejs.com/apps/?id=sched). +* To avoid potential conflicts with other apps that uses sched (especially ones that make use of the data field), this app only lists timers that it created - all other timers will be ignored. +* A keyboard app is only used for adding messages to timers and is therefore not strictly needed. \ No newline at end of file diff --git a/apps/multitimer/alarm.js b/apps/multitimer/alarm.js new file mode 100644 index 000000000..96e5ade89 --- /dev/null +++ b/apps/multitimer/alarm.js @@ -0,0 +1,77 @@ +//sched.js, modified +// Chances are boot0.js got run already and scheduled *another* +// 'load(sched.js)' - so let's remove it first! +if (Bangle.SCHED) { + clearInterval(Bangle.SCHED); + delete Bangle.SCHED; +} + +function showAlarm(alarm) { + const settings = require("sched").getSettings(); + + let msg = ""; + msg += require("sched").formatTime(alarm.timer); + if (alarm.msg) { + msg += "\n"+alarm.msg; + } + else msg = atob("ACQswgD//33vRcGHIQAAABVVVAAAAAAAABVVVAAAAAAAABVVVAAAAAAAABVVVAAAAAAAABVVVAAAAAAAABVVVAAAAAAAAAP/wAAAAAAAAAP/wAAAAAAAAAqqoAPAAAAAAqqqqoP8AAAAKqqqqqv/AAACqqqqqqq/wAAKqqqlWqqvwAAqqqqlVaqrAACqqqqlVVqqAAKqqqqlVVaqgAKqaqqlVVWqgAqpWqqlVVVqoAqlWqqlVVVaoCqlV6qlVVVaqCqVVfqlVVVWqCqVVf6lVVVWqKpVVX/lVVVVqqpVVV/+VVVVqqpVVV//lVVVqqpVVVfr1VVVqqpVVVfr1VVVqqpVVVb/lVVVqqpVVVW+VVVVqqpVVVVVVVVVqiqVVVVVVVVWqCqVVVVVVVVWqCqlVVVVVVVaqAqlVVVVVVVaoAqpVVVVVVVqoAKqVVVVVVWqgAKqlVVVVVaqgACqpVVVVVqqAAAqqlVVVaqoAAAKqqVVWqqgAAACqqqqqqqAAAAAKqqqqqgAAAAAAqqqqoAAAAAAAAqqoAAAAA==")+" "+msg; + + Bangle.loadWidgets(); + Bangle.drawWidgets(); + + let buzzCount = settings.buzzCount; + + E.showPrompt(msg,{ + title: "TIMER!", + buttons : {"Snooze":true,"Ok":false} // default is sleep so it'll come back in 10 mins + }).then(function(sleep) { + buzzCount = 0; + if (sleep) { + if(alarm.ot===undefined) alarm.ot = alarm.t; + alarm.t += settings.defaultSnoozeMillis; + } else { + if (!alarm.timer) alarm.last = (new Date()).getDate(); + if (alarm.ot!==undefined) { + alarm.t = alarm.ot; + delete alarm.ot; + } + if (!alarm.rp) alarm.on = false; + } + //reset timer value + alarm.timer = alarm.data; + // alarm is still a member of 'alarms', so writing to array writes changes back directly + require("sched").setAlarms(alarms); + load(); + }); + + function buzz() { + if (settings.unlockAtBuzz) { + Bangle.setLocked(false); + } + + require("buzz").pattern(alarm.vibrate === undefined ? ".." : alarm.vibrate).then(() => { + if (buzzCount--) { + setTimeout(buzz, settings.buzzIntervalMillis); + } else if (alarm.as) { // auto-snooze + buzzCount = settings.buzzCount; + setTimeout(buzz, settings.defaultSnoozeMillis); + } + }); + } + + if ((require("Storage").readJSON("setting.json", 1) || {}).quiet > 1) + return; + + buzz(); +} + +// Check for alarms +let alarms = require("sched").getAlarms(); +let active = require("sched").getActiveAlarms(alarms); +if (active.length) { + // if there's an alarm, show it + showAlarm(active[0]); +} else { + // otherwise just go back to default app + setTimeout(load, 100); +} \ No newline at end of file diff --git a/apps/multitimer/app-icon.js b/apps/multitimer/app-icon.js new file mode 100644 index 000000000..6eac4ab31 --- /dev/null +++ b/apps/multitimer/app-icon.js @@ -0,0 +1 @@ +atob("MDCBAYAAAAAAfwAAAAAAPz//////Pz//////Pz//////Pz//////Pz//////PwAAAAAAPwAAAAAAPz//////Pz//////Pz//////Pz//////Pz//////Pz48AAAfPz4YAAAPPz//////Pz//////Pz//////Pz48AAAfPz4YAAAPPz//////Pz//////Pz//////Pz4YAAAPPz4YAAAfPz//////vz///////z///////z4YAAH4Pz48AAP4Dz////95hz////594z////x/8T////zP+T////nH+D////nj/AAAADnw/AAAABn4/P////n4/P////n//P////n/+f////z/+f////x/8/////4/4/////8Ph/////+AH//////gfw==") \ No newline at end of file diff --git a/apps/multitimer/app.png b/apps/multitimer/app.png new file mode 100644 index 0000000000000000000000000000000000000000..3006b0a2697673f59fba9fc1facff92f14be4112 GIT binary patch literal 971 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 BTc7{{ literal 0 HcmV?d00001 diff --git a/apps/multitimer/screenshot2.png b/apps/multitimer/screenshot2.png new file mode 100644 index 0000000000000000000000000000000000000000..23a0d4c222288b45c19532ae5e30b7798c26d971 GIT binary patch literal 2970 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 literal 0 HcmV?d00001 From 1b993fb09987043f6e124f794fa50c264d3a5b4c Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Sun, 15 May 2022 00:24:18 +0200 Subject: [PATCH 031/163] Update lib.js --- apps/kbmulti/lib.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/kbmulti/lib.js b/apps/kbmulti/lib.js index 2d38539e8..d06e2bb7d 100644 --- a/apps/kbmulti/lib.js +++ b/apps/kbmulti/lib.js @@ -17,7 +17,7 @@ exports.input = function(options) { "4":"GHI4","5":"JKL5","6":"MNO6", "7":"PQRS7","8":"TUV80","9":"WXYZ9", }; - var helpMessage = 'swipe:\nRight: Space\nLeft:Backspace\nUp/Down: Caps lock\n'; + var helpMessage = 'Swipe:\nRight: Space\nLeft:Backspace\nUp/Down: Caps lock\n'; var charTimeout; // timeout after a key is pressed var charCurrent; // current character (index in letters) From 687eaaab4b3457d1cd227e0b0049a9a50ae772c3 Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Sat, 14 May 2022 22:16:15 -0700 Subject: [PATCH 032/163] Update app.js --- apps/multitimer/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/multitimer/app.js b/apps/multitimer/app.js index caf2637f0..faafc00a3 100644 --- a/apps/multitimer/app.js +++ b/apps/multitimer/app.js @@ -17,7 +17,7 @@ function getCurrentTime() { } function decodeTime(t) { - let hrs = 0 | Math.floor(t / 3600000 % 24); + let hrs = 0 | Math.floor(t / 3600000); let mins = 0 | Math.floor(t / 60000 % 60); let secs = 0 | Math.floor(t / 1000 % 60); return { hrs: hrs, mins: mins, secs: secs }; @@ -33,7 +33,7 @@ function formatTime(t) { } function decodeTimeDecis(t) { - let hrs = 0 | Math.floor(t / 3600000 % 24); + let hrs = 0 | Math.floor(t / 3600000); let mins = 0 | Math.floor(t / 60000 % 60); let secs = 0 | Math.floor(t / 1000 % 60); let decis = 0 | Math.floor(t / 100 % 100); From 1f175ecd9fa0662ac042f1fbbf59d9cef0f4da10 Mon Sep 17 00:00:00 2001 From: JuliusS123 <42714028+JuliusS123@users.noreply.github.com> Date: Sun, 15 May 2022 10:11:56 +0200 Subject: [PATCH 033/163] Create app.js --- apps/homework/app.js | 238 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 apps/homework/app.js diff --git a/apps/homework/app.js b/apps/homework/app.js new file mode 100644 index 000000000..032560ec5 --- /dev/null +++ b/apps/homework/app.js @@ -0,0 +1,238 @@ +var Layout = require("Layout"); + +var homework = require("Storage").readJSON("homework.txt", "r"); +//var hwfile = require("Storage").open("homework.txt", "w"); +var mainCheckHomeworkMenu; +console.log(homework); +//subjects = require("Storage").open("subjects.txt", "r"); + +var mode = "mainmenu"; +var statusmsg; +var mainMenu = { + "": { + title: "--Main Menu--" + }, + "New Homework": function() { + E.showMenu(nhwmn); + mode = "newhomework"; + }, + "Check Homework": function() { + checkUnfinishedHomeworkAssembler(); + }, + "Reset Homework": function() { + E.showPrompt("Are you sure you want to delete homework.txt?", { + buttons: { + "No": false, + "Yes": true + } + }).then(function(v) { + if (v) { + require("Storage").write("homework.txt", '{"homework":[]}'); + homework = require("Storage").readJSON("homework.txt", "r"); + E.showMenu(mainMenu); + + }else{ + E.showMenu(mainMenu); + } + }); + }, +}; + + +var nhwmn = { // New homework Menu + "": { + "title": "New HW Subject:" + }, + "German": function() { + addNewHomework("German"); + }, + "English": function() { + addNewHomework("English"); + }, + "Maths": function() { + addNewHomework("Maths"); + }, + "French": function() { + addNewHomework("French"); + }, + "Chemistry": function() { + addNewHomework("Chemistry"); + }, + "Physics": function() { + addNewHomework("Physics"); + }, + "Religion": function() { + addNewHomework("Religion"); + }, + "Biology": function() { + addNewHomework("Biology"); + }, + "Music": function() { + addNewHomework("Music"); + }, + "History": function() { + addNewHomework("History"); + }, + "Arts": function() { + addNewHomework("Arts"); + }, + "Sports": function() { + addNewHomework("Sports"); + }, + + "Back": function() { + mode = "mainmenu"; + E.showMenu(mainMenu); + }, + + +}; + + +function checkUnfinishedHomeworkAssembler() { + homework = require("Storage").readJSON("homework.txt", "r"); + var hwcount = Object.keys(homework.homework).length; + mainCheckHomeworkMenu = { + '': { + 'title': 'Unfinished HW:' + } + }; + // This code snippet gets the unfinished HW and puts it in mainCheckHomeworkMenu + // btw mainCheckHomeworkMenu displays all the homework, when tapping on it you get more details with checkPreciseHomework function (currently being written) + for (var i = 0; i < hwcount; ++i) { + if (homework.homework[i].done === false) { + var currentsubject = i; //attempting to pass i + mainCheckHomeworkMenu[homework.homework[i].subject] = function() { + checkPreciseHomework(currentsubject); + }; + } + + } + mainCheckHomeworkMenu["See Archived HW"] = function() { + checkFinishedHomeworkAssembler(); + }; + mainCheckHomeworkMenu["Back to Main Menu"] = function() { + mode = "mainmenu"; + E.showMenu(mainMenu); + }; + E.showMenu(mainCheckHomeworkMenu); +} + +function checkFinishedHomeworkAssembler() { + homework = require("Storage").readJSON("homework.txt", "r"); + var hwcount = Object.keys(homework.homework).length; + mainCheckHomeworkMenu = { + '': { + 'title': 'Unfinished HW:' + } + }; + // This code snippet gets the unfinished HW and puts it in mainCheckHomeworkMenu + // btw mainCheckHomeworkMenu displays all the homework, when tapping on it you get more details with checkPreciseHomework function (currently being written) + for (var i = 0; i < hwcount; ++i) { + if (homework.homework[i].done === true) { + var currentsubject = i; //attempting to pass i + mainCheckHomeworkMenu[homework.homework[i].subject] = function() { + checkPreciseHomework(currentsubject); + }; + } + + } + mainCheckHomeworkMenu["Back"] = function() { + mode = "mainmenu"; + E.showMenu(mainMenu); + }; + E.showMenu(mainCheckHomeworkMenu); +} + +function checkPreciseHomework(subjectnum) { // P A I N + homework = require("Storage").read("homework.txt", "r"); + homework = JSON.parse(homework); + var subject = homework.homework[subjectnum].subject; + var task = homework.homework[subjectnum].task; + var taskmsg = "Task: " + homework.homework[subjectnum].task; + if (homework.homework[subjectnum].done === false) { + statusmsg = "Status: Unfinished"; + } else { + statusmsg = "Status: Finished"; + } + var datetimerecieved = homework.homework[subjectnum].datetimerecievehw; + var datetimerecievedmsg = "Recieved: " + homework.homework[subjectnum].datetimerecievehw; + var checkPreciseHomeworkMenu = { + '': { + 'title': subject + }, + }; + checkPreciseHomeworkMenu[subject] = function() {}, + checkPreciseHomeworkMenu[taskmsg] = function() {}, + checkPreciseHomeworkMenu[statusmsg] = function() { + status = "Status: Finished"; + var d = new Date(); + var currenttime = require("locale").time(d, 1); + var currentdate = require("locale").date(d); + var datetime = (currenttime + " " + currentdate); + delete homework.homework[subjectnum]; + homework.homework.push({ + subject: subject, + task: task, + done: true, + datetimerecievehw: datetimerecieved, + datetimehwdone: datetime + }); + require("Storage").write("homework.txt", JSON.stringify(homework)); + checkUnfinishedHomeworkAssembler(); + }, + checkPreciseHomeworkMenu[datetimerecievedmsg] = function() {}, + checkPreciseHomeworkMenu["Back"] = function() { + checkUnfinishedHomeworkAssembler(); + }, + + E.showMenu(checkPreciseHomeworkMenu); + + +} + +function pushHomework(subject, status, datetimehwdone) { + homework = require("Storage").readJSON("homework.txt", "r"); + +} + +function addNewHomework(subject) { // Pass subject + require("textinput").input().then(result => { + if (result === "") { + mode = "newhomework"; + E.showMenu(nhwmn); + } else { + var d = new Date(); + // update time and date + var currenttime = require("locale").time(d, 1); + var currentdate = require("locale").date(d); + var datetime = (currenttime + " " + currentdate); + homework.homework.push({ + subject: subject, + task: result, + done: false, + datetimerecievehw: datetime + }); // TODO: when HW is done, add datetimeendhw !!! + //homework.homework[subject] = result; + require("Storage").write("homework.txt", JSON.stringify(homework)); + E.showMenu(mainMenu); + + } + }); + +} + +function main() { // why does this still exist + if (mode === "mainmenu") { + E.showMenu(mainMenu); + + } else if (mode === "newhomework") { + E.showMenu(nhwmn); + + } +} +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +main(); +//loop = setInterval(main, 1); From a6cdee8a40ac6348f8e7b9361025f1d20a283da9 Mon Sep 17 00:00:00 2001 From: JuliusS123 <42714028+JuliusS123@users.noreply.github.com> Date: Sun, 15 May 2022 10:16:41 +0200 Subject: [PATCH 034/163] Create app-icon.js --- apps/homework/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/homework/app-icon.js diff --git a/apps/homework/app-icon.js b/apps/homework/app-icon.js new file mode 100644 index 000000000..7eeb41f50 --- /dev/null +++ b/apps/homework/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4cA///43hg3ytVN/UF61hsvR2kEKf4AzgMgCJ9JkmACBsSCIOSCBkEyQRCpBELBwIRCpJKKEAYmDJRBEFJRQdHJRBEDIIgIIhJlIFgYRGKBQRFIgMN23YOgwREHYQRHJQIFDhADCCI5KBIA4RIAAsW7doCIsf5LHGCNMbkmQRwIRhGpy6BCMI1RCP4R9UITXOCKJZvAH4AoA=")) From bd69f2136195b99bb3ac4d96f92b354063995e93 Mon Sep 17 00:00:00 2001 From: JuliusS123 <42714028+JuliusS123@users.noreply.github.com> Date: Sun, 15 May 2022 10:22:52 +0200 Subject: [PATCH 035/163] Create metadata.json --- apps/homework/metadata.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 apps/homework/metadata.json diff --git a/apps/homework/metadata.json b/apps/homework/metadata.json new file mode 100644 index 000000000..a8f7909ea --- /dev/null +++ b/apps/homework/metadata.json @@ -0,0 +1,15 @@ + +{ "id": "homework", + "name": "Homework", + "shortName":"Homwork", + "version":"0.1", + "description": "A simple app to manage homework", + "icon": "app-icon.js", + "tags": "tool", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"homework.app.js","url":"app.js"}, + {"name":"homework.img","url":"app-icon.js","evaluate":true} + ] +} From 35f7f3d630fbba02b78efdbd6ddaa1ed454f224e Mon Sep 17 00:00:00 2001 From: JuliusS123 <42714028+JuliusS123@users.noreply.github.com> Date: Sun, 15 May 2022 10:44:38 +0200 Subject: [PATCH 036/163] Create README.md --- apps/homework/README.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 apps/homework/README.md diff --git a/apps/homework/README.md b/apps/homework/README.md new file mode 100644 index 000000000..adad4ef39 --- /dev/null +++ b/apps/homework/README.md @@ -0,0 +1,4 @@ +# This is a simple homework app +Use the touchscreen to navigate. + +Requires the "textinput" library. (Tap keyboard) From 558f219ccf99796bf0e779395996bc353de9045e Mon Sep 17 00:00:00 2001 From: JuliusS123 <42714028+JuliusS123@users.noreply.github.com> Date: Sun, 15 May 2022 10:47:25 +0200 Subject: [PATCH 037/163] Update app-icon.js --- apps/homework/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/homework/app-icon.js b/apps/homework/app-icon.js index 7eeb41f50..7fe731b3a 100644 --- a/apps/homework/app-icon.js +++ b/apps/homework/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEw4cA///43hg3ytVN/UF61hsvR2kEKf4AzgMgCJ9JkmACBsSCIOSCBkEyQRCpBELBwIRCpJKKEAYmDJRBEFJRQdHJRBEDIIgIIhJlIFgYRGKBQRFIgMN23YOgwREHYQRHJQIFDhADCCI5KBIA4RIAAsW7doCIsf5LHGCNMbkmQRwIRhGpy6BCMI1RCP4R9UITXOCKJZvAH4AoA=")) +require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AG27y4ttAAYttGM4tJGMYsMGMCJLSsIhPGLodTGLIYI3ZFhFxQtOJJgURFqQxKCR4tGm83nAACGKQQNLZAvTGIjWMBRIvVERgAMFYOHAAQcWABUtltSAAQvRisVjgACF7KPPF/4AHrFYvgACF5OXy+7AAQHBFYNkAAQv/R6IvHX8/C4XJAAQv/R/4v/F/4v/F/4v/ABNYrF8AAQHBFYOHAAQHB4XC5IACA4IrBsgACF/6//F/4vRAH4A/AH4A/ACwA==")) From f69cd6e5ef91a16e07e303c174927116c06527ed Mon Sep 17 00:00:00 2001 From: JuliusS123 <42714028+JuliusS123@users.noreply.github.com> Date: Sun, 15 May 2022 10:49:53 +0200 Subject: [PATCH 038/163] Add files via upload --- apps/homework/app.png | Bin 0 -> 684 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/homework/app.png diff --git a/apps/homework/app.png b/apps/homework/app.png new file mode 100644 index 0000000000000000000000000000000000000000..e6174d46bfdb46eaa36f1f742ff1c8fd390efc04 GIT binary patch literal 684 zcmV;d0#p5oP)UKDB{`}XjR+#5) z0JzBsjeJK!1%{@HV|TV+qEzNYftZR`+d!XQvp? zTzyb2n~dl_I3hvf2w23}L)~`Y1Uo8E)(8MHg^aJgeP>&ElhAF~0Z<>BMisz42#SaZ zgcd#za!$`i43SU)2JC^Mb^_<{tc^THs^NQ zognlM+_?Ch0HAm#>uY~z-;z_{)2-2tcVX4vzP`fEpJW%B;_&Ms0HBAyjC8Tk{`-iM z5t;$>auEQKJ%7^QVT%p2Un&s*6f(zs?WcC#(GnRioqFc9uYX4%_tBUE=ff8OK=E6a z6Pb|D`v8C)ta1XUk@6DrSXo{k{is~>ckH^;!7(`+OK4U;9UK4v3O@$Yb1(c1D1o$5 z0%@ZJ(niW*ZgLk6UTE6b1|aYyR);wbyu%#tLc{$M&v2Mq_!(Gu0fj=LNSEI_v-0fT SL+0E70000 Date: Sun, 15 May 2022 10:50:21 +0200 Subject: [PATCH 039/163] Update metadata.json --- apps/homework/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/homework/metadata.json b/apps/homework/metadata.json index a8f7909ea..a6f9b1207 100644 --- a/apps/homework/metadata.json +++ b/apps/homework/metadata.json @@ -4,7 +4,7 @@ "shortName":"Homwork", "version":"0.1", "description": "A simple app to manage homework", - "icon": "app-icon.js", + "icon": "app.png", "tags": "tool", "supports" : ["BANGLEJS2"], "readme": "README.md", From 831a8635bf97467019d2452332fd480abddd2e57 Mon Sep 17 00:00:00 2001 From: JuliusS123 <42714028+JuliusS123@users.noreply.github.com> Date: Sun, 15 May 2022 10:52:54 +0200 Subject: [PATCH 040/163] Update app-icon.js --- apps/homework/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/homework/app-icon.js b/apps/homework/app-icon.js index 7fe731b3a..7dab2103b 100644 --- a/apps/homework/app-icon.js +++ b/apps/homework/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AG27y4ttAAYttGM4tJGMYsMGMCJLSsIhPGLodTGLIYI3ZFhFxQtOJJgURFqQxKCR4tGm83nAACGKQQNLZAvTGIjWMBRIvVERgAMFYOHAAQcWABUtltSAAQvRisVjgACF7KPPF/4AHrFYvgACF5OXy+7AAQHBFYNkAAQv/R6IvHX8/C4XJAAQv/R/4v/F/4v/F/4v/ABNYrF8AAQHBFYOHAAQHB4XC5IACA4IrBsgACF/6//F/4vRAH4A/AH4A/ACwA==")) +require("heatshrink").decompress(atob("mEwhH+AH4A/AH4A/AGu7y4ttAAYttGM4tJGMYsMGMCJLSsIhPGLodTGLIYI3ZFhFxQtOJJgURFqQxKCR4tGm83nAACGKQQNLZAvTGIjWMBRIvVERgAMFYOHAAQcWABUtltSAAQvRisVjgACF7KPPF/4AHrFYvgACF5OXy+7AAQHBFYNkAAQv/R6IvHX8/C4XJAAQv/R/4v/F/4v/F/4v/ABNYrF8AAQHBFYOHAAQHB4XC5IACA4IrBsgACF/6//F/4vRAH4A/AH4A/ACwA==")) From afbaf2b90e08a0f0bcefc27e725e89ef278cf190 Mon Sep 17 00:00:00 2001 From: JuliusS123 <42714028+JuliusS123@users.noreply.github.com> Date: Sun, 15 May 2022 10:56:27 +0200 Subject: [PATCH 041/163] Update app-icon.js --- apps/homework/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/homework/app-icon.js b/apps/homework/app-icon.js index 7dab2103b..23a974ef3 100644 --- a/apps/homework/app-icon.js +++ b/apps/homework/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwhH+AH4A/AH4A/AGu7y4ttAAYttGM4tJGMYsMGMCJLSsIhPGLodTGLIYI3ZFhFxQtOJJgURFqQxKCR4tGm83nAACGKQQNLZAvTGIjWMBRIvVERgAMFYOHAAQcWABUtltSAAQvRisVjgACF7KPPF/4AHrFYvgACF5OXy+7AAQHBFYNkAAQv/R6IvHX8/C4XJAAQv/R/4v/F/4v/F/4v/ABNYrF8AAQHBFYOHAAQHB4XC5IACA4IrBsgACF/6//F/4vRAH4A/AH4A/ACwA==")) +require("heatshrink").decompress(atob("mEwxH+AH4A/AH4AVvNPp95F1tPqujF9IuCvPO5wspAAXHF84uFp4uBL84xEvPN5q+rqtiCBl6F7tiAAY9LvQDBF86cDvQvCGLYvEGAr7EF4IwDF7c4GQwuERwIACqpecrlcF4lWLw4ACF7s3F58rGDIvEA4VcFwtWL4ovSCwwvHFoiOHGCQXHXYdcBwQuIDIwsMI5QwEGIKNERgh6JFpIuKAAOAGIYvCqpYJAwUyFxaNIGAovEXBheOF5pfCrl6RYjoTVAYvMRwYOKF76NDwAveGBaNEF8AwLFzgvHeRovoqtWFxtVDQbwSF44KBqouLDYzAYqz8OPg5gSD6K9FGCIvJVoIdLdoxgUDop9NF7gcEPZwvZJgwvnbiwTHF54bLMCEsAAIvVTRBEOF7zBSF7StPGDB1HPpyMVDAgZFbxztWAH4A/AGw")) From 38475eaa1191ed5c7ce2a384b8290481825b5f46 Mon Sep 17 00:00:00 2001 From: JuliusS123 <42714028+JuliusS123@users.noreply.github.com> Date: Sun, 15 May 2022 11:06:26 +0200 Subject: [PATCH 042/163] attempting to properly display app image --- apps/homework/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/homework/app-icon.js b/apps/homework/app-icon.js index 23a974ef3..202b52b09 100644 --- a/apps/homework/app-icon.js +++ b/apps/homework/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwxH+AH4A/AH4AVvNPp95F1tPqujF9IuCvPO5wspAAXHF84uFp4uBL84xEvPN5q+rqtiCBl6F7tiAAY9LvQDBF86cDvQvCGLYvEGAr7EF4IwDF7c4GQwuERwIACqpecrlcF4lWLw4ACF7s3F58rGDIvEA4VcFwtWL4ovSCwwvHFoiOHGCQXHXYdcBwQuIDIwsMI5QwEGIKNERgh6JFpIuKAAOAGIYvCqpYJAwUyFxaNIGAovEXBheOF5pfCrl6RYjoTVAYvMRwYOKF76NDwAveGBaNEF8AwLFzgvHeRovoqtWFxtVDQbwSF44KBqouLDYzAYqz8OPg5gSD6K9FGCIvJVoIdLdoxgUDop9NF7gcEPZwvZJgwvnbiwTHF54bLMCEsAAIvVTRBEOF7zBSF7StPGDB1HPpyMVDAgZFbxztWAH4A/AGw")) +require("heatshrink").decompress(atob("mEwwhC/AH4AbhvQCyvd7oYTCwQYTCwgYRCwwYPIgpKQCA4YOBxIYMBhYLLHhgYEC5BsKDAYXHCwUBiUikAYIC4wtDC5IYCA4pEEC5QYBYRUCkQXJAA8K1Wq0AXHhGIxGAC5ZHHC8ZDDC4cM5qaBC8ZHHC68N6czmAXrL94X/C/4XHgUiCYIDDa54XXO/4XHAH4A/ABY=")) From bd7d5cf7e4928e683e04b3b34c6b7e024ff53c9b Mon Sep 17 00:00:00 2001 From: JuliusS123 <42714028+JuliusS123@users.noreply.github.com> Date: Sun, 15 May 2022 11:12:19 +0200 Subject: [PATCH 043/163] Update metadata.json --- apps/homework/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/homework/metadata.json b/apps/homework/metadata.json index a6f9b1207..07279c4ea 100644 --- a/apps/homework/metadata.json +++ b/apps/homework/metadata.json @@ -1,7 +1,7 @@ { "id": "homework", "name": "Homework", - "shortName":"Homwork", + "shortName":"Homework", "version":"0.1", "description": "A simple app to manage homework", "icon": "app.png", From 4415325703bdc111848d4e734169f37caa363a0c Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Sun, 15 May 2022 11:52:07 +0200 Subject: [PATCH 044/163] Update lib.js --- apps/kbmulti/lib.js | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/apps/kbmulti/lib.js b/apps/kbmulti/lib.js index d06e2bb7d..db18948b8 100644 --- a/apps/kbmulti/lib.js +++ b/apps/kbmulti/lib.js @@ -25,18 +25,21 @@ exports.input = function(options) { var caps = true; var layout; - function displayText(charTimeout) { + function displayText(hideMarker) { layout.clear(layout.text); - layout.text.label = text.slice(settings.showHelpBtn ? -11 : -13) + (charTimeout ? " " : "_"); // Implemented marker here. + layout.text.label = text.slice(settings.showHelpBtn ? -11 : -13) + (!hideMarker ? "_" : " "); layout.render(layout.text); } - function backspace() { - // remove the timeout if we had one + function deactivateTimeout(charTimeout) { if (charTimeout!==undefined) { clearTimeout(charTimeout); charTimeout = undefined; } + } + + function backspace() { + deactivateTimeout(charTimeout); text = text.slice(0, -1); newCharacter(); } @@ -56,11 +59,7 @@ exports.input = function(options) { } function onKeyPad(key) { - // remove the timeout if we had one - if (charTimeout!==undefined) { - clearTimeout(charTimeout); - charTimeout = undefined; - } + deactivateTimeout(charTimeout); // work out which char was pressed if (key==charCurrent) { charIndex = (charIndex+1) % letters[charCurrent].length; @@ -124,7 +123,7 @@ exports.input = function(options) { ]}, ] },{back: ()=>{ - // charTimeout = undefined; // Tried this to see if it would stop the text from being drawn after closing keyboard when doing it too soon after pressing a key. It didn't help. This problem goes back to how I've implemented the marker above. + deactivateTimeout(charTimeout); Bangle.setUI(); Bangle.removeListener("swipe", onSwipe); g.clearRect(Bangle.appRect); @@ -134,13 +133,13 @@ exports.input = function(options) { return new Promise((resolve,reject) => { g.clearRect(Bangle.appRect); - if (settings.firstLaunch) { - onHelp(resolve,reject); + if (settings.firstLaunch) { + onHelp(resolve,reject); settings.firstLaunch = false; require('Storage').writeJSON("kbmulti.settings.json", settings); } else { generateLayout(resolve,reject); - displayText(true); + displayText(false); Bangle.on('swipe', onSwipe); layout.render(); } From 29be42c6063ecfc505c55bb8e987597d2ba24748 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Sun, 15 May 2022 11:53:51 +0200 Subject: [PATCH 045/163] Update lib.js --- apps/kbmulti/lib.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/kbmulti/lib.js b/apps/kbmulti/lib.js index db18948b8..c8abf98b4 100644 --- a/apps/kbmulti/lib.js +++ b/apps/kbmulti/lib.js @@ -27,7 +27,7 @@ exports.input = function(options) { function displayText(hideMarker) { layout.clear(layout.text); - layout.text.label = text.slice(settings.showHelpBtn ? -11 : -13) + (!hideMarker ? "_" : " "); + layout.text.label = text.slice(settings.showHelpBtn ? -11 : -13) + (hideMarker ? " " : "_"); layout.render(layout.text); } From 134a9e2369c0a5f82abed9208c58ef3ca3a21992 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Sun, 15 May 2022 12:19:29 +0200 Subject: [PATCH 046/163] Update README.md --- apps/kbmulti/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/kbmulti/README.md b/apps/kbmulti/README.md index d40b2dd07..4c83d378e 100644 --- a/apps/kbmulti/README.md +++ b/apps/kbmulti/README.md @@ -10,7 +10,8 @@ Uses the multitap keypad logic originally from here: http://www.espruino.com/Mor ![](screenshot_1.png) ![](screenshot_2.png) +![](screenshot_3.png) Written by: [Sir Indy](https://github.com/sir-indy) and [Thyttan](https://github.com/thyttan) -For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) \ No newline at end of file +For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) From 5e564db73186325732b1a92859d8a6a6599641b8 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Sun, 15 May 2022 12:23:29 +0200 Subject: [PATCH 047/163] Add files via upload --- apps/kbmulti/screenshot_3.png | Bin 0 -> 3674 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/kbmulti/screenshot_3.png diff --git a/apps/kbmulti/screenshot_3.png b/apps/kbmulti/screenshot_3.png new file mode 100644 index 0000000000000000000000000000000000000000..e0da184baa34c29285e7cd5b76d93638450a6cf4 GIT binary patch literal 3674 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 literal 0 HcmV?d00001 From f0a7ea0ee97f58f83a045a24f21a546aac95303d Mon Sep 17 00:00:00 2001 From: JuliusS123 <42714028+JuliusS123@users.noreply.github.com> Date: Sun, 15 May 2022 12:29:11 +0200 Subject: [PATCH 048/163] Update app.js --- apps/homework/app.js | 104 ++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 65 deletions(-) diff --git a/apps/homework/app.js b/apps/homework/app.js index 032560ec5..c7e04ba9f 100644 --- a/apps/homework/app.js +++ b/apps/homework/app.js @@ -1,11 +1,35 @@ var Layout = require("Layout"); var homework = require("Storage").readJSON("homework.txt", "r"); -//var hwfile = require("Storage").open("homework.txt", "w"); var mainCheckHomeworkMenu; -console.log(homework); -//subjects = require("Storage").open("subjects.txt", "r"); +var nhwmn = { // New homework Menu + "": { + "title": "New HW Subject:" + } + +}; + + + +function newHomeworkMenu() { + E.showMessage("Getting subjects..."); + var rawsubjects = require("Storage").read("subjects.txt"); // This code reads out the subjects list and removes the newline character at the end + var splitsubjects = rawsubjects.split(","); + var lastItem = splitsubjects[splitsubjects.length - 1]; + var thiscurrentsubject; + var command; + lastItem = lastItem.slice(0, -1); + splitsubjects[splitsubjects.length - 1] = lastItem; + for (let i = 0; i < splitsubjects.length; i++) { // loop through array and add to menu + thiscurrentsubject = splitsubjects[i]; + command = addNewHomework(thiscurrentsubject); + nhwmn[splitsubjects[i]] = addNewHomework.bind(null, thiscurrentsubject); + } + nhwmn["Back"] = function() {E.showMenu(mainMenu);}; + console.log(nhwmn); + E.showMenu(nhwmn); +} var mode = "mainmenu"; var statusmsg; var mainMenu = { @@ -13,7 +37,7 @@ var mainMenu = { title: "--Main Menu--" }, "New Homework": function() { - E.showMenu(nhwmn); + newHomeworkMenu(); mode = "newhomework"; }, "Check Homework": function() { @@ -38,73 +62,20 @@ var mainMenu = { }, }; - -var nhwmn = { // New homework Menu - "": { - "title": "New HW Subject:" - }, - "German": function() { - addNewHomework("German"); - }, - "English": function() { - addNewHomework("English"); - }, - "Maths": function() { - addNewHomework("Maths"); - }, - "French": function() { - addNewHomework("French"); - }, - "Chemistry": function() { - addNewHomework("Chemistry"); - }, - "Physics": function() { - addNewHomework("Physics"); - }, - "Religion": function() { - addNewHomework("Religion"); - }, - "Biology": function() { - addNewHomework("Biology"); - }, - "Music": function() { - addNewHomework("Music"); - }, - "History": function() { - addNewHomework("History"); - }, - "Arts": function() { - addNewHomework("Arts"); - }, - "Sports": function() { - addNewHomework("Sports"); - }, - - "Back": function() { - mode = "mainmenu"; - E.showMenu(mainMenu); - }, - - -}; - - function checkUnfinishedHomeworkAssembler() { homework = require("Storage").readJSON("homework.txt", "r"); var hwcount = Object.keys(homework.homework).length; mainCheckHomeworkMenu = { '': { - 'title': 'Unfinished HW:' + 'title': 'Archived HW:' } }; // This code snippet gets the unfinished HW and puts it in mainCheckHomeworkMenu - // btw mainCheckHomeworkMenu displays all the homework, when tapping on it you get more details with checkPreciseHomework function (currently being written) + // btw mainCheckHomeworkMenu displays all the homework, when tapping on it you get more details with checkPreciseHomework function for (var i = 0; i < hwcount; ++i) { if (homework.homework[i].done === false) { var currentsubject = i; //attempting to pass i - mainCheckHomeworkMenu[homework.homework[i].subject] = function() { - checkPreciseHomework(currentsubject); - }; + mainCheckHomeworkMenu[homework.homework[i].subject] = checkPreciseHomework.bind(null, currentsubject); } } @@ -115,6 +86,7 @@ function checkUnfinishedHomeworkAssembler() { mode = "mainmenu"; E.showMenu(mainMenu); }; + console.log(mainCheckHomeworkMenu); E.showMenu(mainCheckHomeworkMenu); } @@ -126,14 +98,13 @@ function checkFinishedHomeworkAssembler() { 'title': 'Unfinished HW:' } }; + // This code snippet gets the unfinished HW and puts it in mainCheckHomeworkMenu // btw mainCheckHomeworkMenu displays all the homework, when tapping on it you get more details with checkPreciseHomework function (currently being written) for (var i = 0; i < hwcount; ++i) { if (homework.homework[i].done === true) { var currentsubject = i; //attempting to pass i - mainCheckHomeworkMenu[homework.homework[i].subject] = function() { - checkPreciseHomework(currentsubject); - }; + mainCheckHomeworkMenu[homework.homework[i].subject] = checkPreciseHomework.bind(null, currentsubject); } } @@ -197,10 +168,11 @@ function pushHomework(subject, status, datetimehwdone) { } function addNewHomework(subject) { // Pass subject + console.log(subject); require("textinput").input().then(result => { if (result === "") { mode = "newhomework"; - E.showMenu(nhwmn); + newHomeworkMenu(); } else { var d = new Date(); // update time and date @@ -213,6 +185,8 @@ function addNewHomework(subject) { // Pass subject done: false, datetimerecievehw: datetime }); // TODO: when HW is done, add datetimeendhw !!! + console.log("subject is" + subject); + //homework.homework[subject] = result; require("Storage").write("homework.txt", JSON.stringify(homework)); E.showMenu(mainMenu); @@ -227,7 +201,7 @@ function main() { // why does this still exist E.showMenu(mainMenu); } else if (mode === "newhomework") { - E.showMenu(nhwmn); + newHomeworkMenu() } } From 6992c6f2f052f9108c209e3b0985bc5e3c6ed3e6 Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Sun, 15 May 2022 04:51:58 -0700 Subject: [PATCH 049/163] Update alarm.js --- apps/multitimer/alarm.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/multitimer/alarm.js b/apps/multitimer/alarm.js index 96e5ade89..208c374b6 100644 --- a/apps/multitimer/alarm.js +++ b/apps/multitimer/alarm.js @@ -38,7 +38,7 @@ function showAlarm(alarm) { if (!alarm.rp) alarm.on = false; } //reset timer value - alarm.timer = alarm.data; + alarm.timer = alarm.data.ot; // alarm is still a member of 'alarms', so writing to array writes changes back directly require("sched").setAlarms(alarms); load(); @@ -74,4 +74,4 @@ if (active.length) { } else { // otherwise just go back to default app setTimeout(load, 100); -} \ No newline at end of file +} From cfe8887b6ac5ad16006e26a1294ce32fa438029d Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Sun, 15 May 2022 04:52:11 -0700 Subject: [PATCH 050/163] Update app.js --- apps/multitimer/app.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/multitimer/app.js b/apps/multitimer/app.js index faafc00a3..b514126f0 100644 --- a/apps/multitimer/app.js +++ b/apps/multitimer/app.js @@ -190,7 +190,7 @@ function timerMenu(idx) { //reset if (i == 2) { clearInt(); - a.timer = a.data; + a.timer = a.data.ot; if (a.on == true) a.on = false; saveAndReload(); } @@ -252,7 +252,8 @@ function editTimer(idx, a) { "< Back": () => { a.t = getCurrentTime() + a.timer; a.last = 0; - a.data = a.timer; + if (!a.data) a.data = {}; + a.data.ot = a.timer; a.appid = "multitimer"; a.js = "load('multitimer.alarm.js')"; if (idx < 0) alarms.push(a); From 1f7178150afdd14feb8341557effaaca6648665c Mon Sep 17 00:00:00 2001 From: JuliusS123 <42714028+JuliusS123@users.noreply.github.com> Date: Sun, 15 May 2022 14:22:01 +0200 Subject: [PATCH 051/163] Add files via upload --- apps/homework/subjects.html | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 apps/homework/subjects.html diff --git a/apps/homework/subjects.html b/apps/homework/subjects.html new file mode 100644 index 000000000..622719e2d --- /dev/null +++ b/apps/homework/subjects.html @@ -0,0 +1,30 @@ + + + + + + +

Subjects:

+

Click

+ + + + + + From 27d63037837b9c7d9478d491b5d5d96b1e4dffe2 Mon Sep 17 00:00:00 2001 From: JuliusS123 <42714028+JuliusS123@users.noreply.github.com> Date: Sun, 15 May 2022 14:23:13 +0200 Subject: [PATCH 052/163] Update metadata.json --- apps/homework/metadata.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/homework/metadata.json b/apps/homework/metadata.json index 07279c4ea..2ba1e918f 100644 --- a/apps/homework/metadata.json +++ b/apps/homework/metadata.json @@ -8,6 +8,7 @@ "tags": "tool", "supports" : ["BANGLEJS2"], "readme": "README.md", + "custom": "subjects.html", "storage": [ {"name":"homework.app.js","url":"app.js"}, {"name":"homework.img","url":"app-icon.js","evaluate":true} From 60f4cd8f9d3b4f4dc645e5d6d8c5713bc79cb2c6 Mon Sep 17 00:00:00 2001 From: JuliusS123 <42714028+JuliusS123@users.noreply.github.com> Date: Sun, 15 May 2022 14:26:51 +0200 Subject: [PATCH 053/163] Update app.js --- apps/homework/app.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/homework/app.js b/apps/homework/app.js index c7e04ba9f..4ba786690 100644 --- a/apps/homework/app.js +++ b/apps/homework/app.js @@ -67,11 +67,11 @@ function checkUnfinishedHomeworkAssembler() { var hwcount = Object.keys(homework.homework).length; mainCheckHomeworkMenu = { '': { - 'title': 'Archived HW:' + 'title': 'Unfinished HW:' } }; // This code snippet gets the unfinished HW and puts it in mainCheckHomeworkMenu - // btw mainCheckHomeworkMenu displays all the homework, when tapping on it you get more details with checkPreciseHomework function + // btw mainCheckHomeworkMenu displays all the homework, when tapping on it you get more details with checkPreciseHomework function for (var i = 0; i < hwcount; ++i) { if (homework.homework[i].done === false) { var currentsubject = i; //attempting to pass i @@ -95,7 +95,7 @@ function checkFinishedHomeworkAssembler() { var hwcount = Object.keys(homework.homework).length; mainCheckHomeworkMenu = { '': { - 'title': 'Unfinished HW:' + 'title': 'Archived HW:' } }; From a1335bfe225419154009a4dcd5f7107fe59465e9 Mon Sep 17 00:00:00 2001 From: JuliusS123 <42714028+JuliusS123@users.noreply.github.com> Date: Sun, 15 May 2022 14:29:17 +0200 Subject: [PATCH 054/163] Update subjects.html --- apps/homework/subjects.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/homework/subjects.html b/apps/homework/subjects.html index 622719e2d..d3bf7a400 100644 --- a/apps/homework/subjects.html +++ b/apps/homework/subjects.html @@ -4,7 +4,7 @@ -

Subjects:

+

Subjects:

Click

From 117b52cc080eca4d621d4525bd70d8d96555901c Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Sun, 15 May 2022 07:40:13 -0700 Subject: [PATCH 055/163] Update alarm.js --- apps/multitimer/alarm.js | 117 ++++++++++++++++++++++++++++++++------- 1 file changed, 96 insertions(+), 21 deletions(-) diff --git a/apps/multitimer/alarm.js b/apps/multitimer/alarm.js index 208c374b6..7daa0d45a 100644 --- a/apps/multitimer/alarm.js +++ b/apps/multitimer/alarm.js @@ -6,6 +6,73 @@ if (Bangle.SCHED) { delete Bangle.SCHED; } +function hardMode(tries, max) { + var R = Bangle.appRect; + + function adv() { + tries++; + hardMode(tries, max); + } + + function random(min, max) { // min and max included + return Math.floor(Math.random() * (max - min + 1) + min); + } + + if (tries < max) { + g.clear(); + g.reset(); + g.setClipRect(R.x,R.y,R.x2,R.y2); + var code = Math.abs(E.hwRand()%4); + if (code == 0) dir = "up"; + else if (code == 1) dir = "right"; + else if (code == 2) dir = "down"; + else dir = "left"; + g.setFont("6x8:2").setFontAlign(0,0).drawString(tries+"/"+max+"\nSwipe "+dir, (R.x2-R.x)/2, (R.y2-R.y)/2); + var drag; + Bangle.setUI({ + mode : "custom", + drag : e=>{ + if (!drag) { // start dragging + drag = {x: e.x, y: e.y}; + } else if (!e.b) { // released + const dx = e.x-drag.x, dy = e.y-drag.y; + drag = null; + //horizontal swipes + if (Math.abs(dx)>Math.abs(dy)+10) { + //left + if (dx<0 && code == 3) adv(); + //right + else if (dx>0 && code == 1) adv(); + //wrong swipe - reset + else startHM(); + } + //vertical swipes + else if (Math.abs(dy)>Math.abs(dx)+10) { + //up + if (dy<0 && code == 0) adv(); + //down + else if (dy>0 && code == 2) adv(); + //wrong swipe - reset + else startHM(); + } + } + } + }); + } + else { + if (!active[0].timer) active[0].last = (new Date()).getDate(); + if (!active[0].rp) active[0].on = false; + if (active[0].timer) active[0].timer = active[0].data.ot; + require("sched").setAlarms(alarms); + load(); + } +} + +function startHM() { + //between 5-8 random swipes + hardMode(0, Math.abs(E.hwRand()%4)+5); +} + function showAlarm(alarm) { const settings = require("sched").getSettings(); @@ -21,28 +88,36 @@ function showAlarm(alarm) { let buzzCount = settings.buzzCount; - E.showPrompt(msg,{ - title: "TIMER!", - buttons : {"Snooze":true,"Ok":false} // default is sleep so it'll come back in 10 mins - }).then(function(sleep) { - buzzCount = 0; - if (sleep) { - if(alarm.ot===undefined) alarm.ot = alarm.t; - alarm.t += settings.defaultSnoozeMillis; - } else { - if (!alarm.timer) alarm.last = (new Date()).getDate(); - if (alarm.ot!==undefined) { - alarm.t = alarm.ot; - delete alarm.ot; + if (alarm.data.hm && alarm.data.hm == true) { + //hard mode extends auto-snooze time + buzzCount = buzzCount * 2; + startHM(); + } + + else { + E.showPrompt(msg,{ + title: "TIMER!", + buttons : {"Snooze":true,"Ok":false} // default is sleep so it'll come back in 10 mins + }).then(function(sleep) { + buzzCount = 0; + if (sleep) { + if(alarm.ot===undefined) alarm.ot = alarm.t; + alarm.t += settings.defaultSnoozeMillis; + } else { + if (!alarm.timer) alarm.last = (new Date()).getDate(); + if (alarm.ot!==undefined) { + alarm.t = alarm.ot; + delete alarm.ot; + } + if (!alarm.rp) alarm.on = false; } - if (!alarm.rp) alarm.on = false; - } - //reset timer value - alarm.timer = alarm.data.ot; - // alarm is still a member of 'alarms', so writing to array writes changes back directly - require("sched").setAlarms(alarms); - load(); - }); + //reset timer value + if (alarm.timer) alarm.timer = alarm.data.ot; + // alarm is still a member of 'alarms', so writing to array writes changes back directly + require("sched").setAlarms(alarms); + load(); + }); + } function buzz() { if (settings.unlockAtBuzz) { From 2e36770a706e4b8e7177bf1163c11ac87706b3c1 Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Sun, 15 May 2022 07:40:32 -0700 Subject: [PATCH 056/163] Update app.js --- apps/multitimer/app.js | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/apps/multitimer/app.js b/apps/multitimer/app.js index b514126f0..becaf6169 100644 --- a/apps/multitimer/app.js +++ b/apps/multitimer/app.js @@ -227,6 +227,10 @@ function editTimer(idx, a) { if (idx < 0) a = require("sched").newDefaultTimer(); else a = timers[idx]; } + if (!a.data) { + a.data = {}; + a.data.hm = false; + } var t = decodeTime(a.timer); function editMsg(idx, a) { @@ -252,7 +256,6 @@ function editTimer(idx, a) { "< Back": () => { a.t = getCurrentTime() + a.timer; a.last = 0; - if (!a.data) a.data = {}; a.data.ot = a.timer; a.appid = "multitimer"; a.js = "load('multitimer.alarm.js')"; @@ -288,6 +291,11 @@ function editTimer(idx, a) { a.timer = encodeTime(t); } }, + "Hard Mode": { + value: a.data.hm, + format: v => v ? "On" : "Off", + onchange: v => a.data.hm = v + }, "Vibrate": require("buzz_menu").pattern(a.vibrate, v => a.vibrate = v), "Msg": { value: !a.msg ? "" : a.msg.length > 6 ? a.msg.substring(0, 6)+"..." : a.msg, @@ -550,6 +558,10 @@ function editAlarm(idx, a) { if (idx >= 0) a = alarms[alarmIdx[idx]]; else a = require("sched").newDefaultAlarm(); } + if (!a.data) { + a.data = {}; + a.data.hm = false; + } var t = decodeTime(a.t); function editMsg(idx, a) { @@ -573,6 +585,8 @@ function editAlarm(idx, a) { var menu = { "": { "title": "Alarm" }, "< Back": () => { + if (a.data.hm == true) a.js = "load('multitimer.alarm.js')"; + if (a.data.hm == false && a.js) delete a.js; if (idx >= 0) alarms[alarmIdx[idx]] = a; else alarms.push(a); require("sched").setAlarms(alarms); @@ -607,6 +621,11 @@ function editAlarm(idx, a) { value: "SMTWTFS".split("").map((d,n)=>a.dow&(1< editDOW(a.dow, d=>{a.dow=d;editAlarm(idx,a);}) }, + "Hard Mode": { + value: a.data.hm, + format: v => v ? "On" : "Off", + onchange: v => a.data.hm = v + }, "Vibrate": require("buzz_menu").pattern(a.vibrate, v => a.vibrate = v), "Auto Snooze": { value: a.as, From 9cc825b93da6b47c918899d3ac4002bb9cbd5989 Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Sun, 15 May 2022 07:40:55 -0700 Subject: [PATCH 057/163] Update README.md --- apps/multitimer/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/multitimer/README.md b/apps/multitimer/README.md index 0cc747c28..f8e14f518 100644 --- a/apps/multitimer/README.md +++ b/apps/multitimer/README.md @@ -1,8 +1,10 @@ # Multi Timer With this app, you can set timers and chronographs (stopwatches) and watch them count down/up in real time. You can also set alarms - swipe left or right to switch between the three functions. +"Hard mode" is also available for timers and alarms. It will double the number of buzz counts and you will have to swipe the screen five to eight times correctly - make a mistake, and you will need to start over. + ## WARNING -* Editing timers in another app (such as the default Alarm app) is not recommended. Editing alarms should not be a problem. +* Editing timers in another app (such as the default Alarm app) is not recommended. Editing alarms should not be a problem (in theory). * This app uses the [Scheduler library](https://banglejs.com/apps/?id=sched). -* To avoid potential conflicts with other apps that uses sched (especially ones that make use of the data field), this app only lists timers that it created - all other timers will be ignored. -* A keyboard app is only used for adding messages to timers and is therefore not strictly needed. \ No newline at end of file +* To avoid potential conflicts with other apps that uses sched (especially ones that make use of the data and js field), this app only lists timers and alarms that it created - any made outside the app will be ignored. +* A keyboard app is only used for adding messages to timers and is therefore not strictly needed. From fc164df525f3617a1315e23b9d959be462202b36 Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Sun, 15 May 2022 08:42:24 -0700 Subject: [PATCH 058/163] Update README.md --- apps/multitimer/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/multitimer/README.md b/apps/multitimer/README.md index f8e14f518..f1e2eb281 100644 --- a/apps/multitimer/README.md +++ b/apps/multitimer/README.md @@ -6,5 +6,5 @@ With this app, you can set timers and chronographs (stopwatches) and watch them ## WARNING * Editing timers in another app (such as the default Alarm app) is not recommended. Editing alarms should not be a problem (in theory). * This app uses the [Scheduler library](https://banglejs.com/apps/?id=sched). -* To avoid potential conflicts with other apps that uses sched (especially ones that make use of the data and js field), this app only lists timers and alarms that it created - any made outside the app will be ignored. +* To avoid potential conflicts with other apps that uses sched (especially ones that make use of the data and js field), this app only lists timers and alarms that it created - any made outside the app will be ignored. GB alarms are currently an exception as they do not make use of the data and js field. * A keyboard app is only used for adding messages to timers and is therefore not strictly needed. From 15f395f5768a5385d98537875858d299bf0b9eba Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Sun, 15 May 2022 08:49:06 -0700 Subject: [PATCH 059/163] Update alarm.js --- apps/multitimer/alarm.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/multitimer/alarm.js b/apps/multitimer/alarm.js index 7daa0d45a..fc0195455 100644 --- a/apps/multitimer/alarm.js +++ b/apps/multitimer/alarm.js @@ -14,10 +14,6 @@ function hardMode(tries, max) { hardMode(tries, max); } - function random(min, max) { // min and max included - return Math.floor(Math.random() * (max - min + 1) + min); - } - if (tries < max) { g.clear(); g.reset(); From 12f84357caabca9855645299a8aaa48ed3213567 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Thu, 12 May 2022 23:19:43 +0200 Subject: [PATCH 060/163] add ClockFace module --- modules/ClockFace.js | 103 ++++++++++++++++++++++++++++++++++++++++ modules/ClockFace.md | 110 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 213 insertions(+) create mode 100644 modules/ClockFace.js create mode 100644 modules/ClockFace.md diff --git a/modules/ClockFace.js b/modules/ClockFace.js new file mode 100644 index 000000000..9818ae4e3 --- /dev/null +++ b/modules/ClockFace.js @@ -0,0 +1,103 @@ +/* +Most of the boilerplate needed to run a clock. +See ClockFace.md for documentation +*/ +function ClockFace(options) { + if ("function"=== typeof options) options = {draw: options}; // simple usage + // some validation, in the hopes of at least catching typos/basic mistakes + Object.keys(options).forEach(k => { + if (![ + "precision", + "init", "draw", "update", + "pause", "resume", + "up", "down", "upDown" + ].includes(k)) throw `Invalid ClockFace option: ${k}`; + }); + if (!options.draw && !options.update) throw "ClockFace needs at least one of draw() or update() functions"; + this.draw = options.draw || (t=> { + options.update.apply(this, [t, {d: true, h: true, m: true, s: true}]); + }); + this.update = options.update || (t => { + g.clear(); + options.draw.apply(this, [t, {d: true, h: true, m: true, s: true}]); + }); + if (options.precision===1000||options.precision===60000) throw "ClockFace precision is in seconds, not ms"; + this.precision = (options.precision || 60); + if (options.init) this.init = options.init; + if (options.pause) this._pause = options.pause; + if (options.resume) this._resume = options.resume; + if ((options.up || options.down) && options.upDown) throw "ClockFace up/down and upDown cannot be used together"; + if (options.up || options.down) this._upDown = (dir) => { + if (dir<0 && options.up) options.up.apply(this); + if (dir>0 && options.down) options.down.apply(this); + }; + if (options.upDown) this._upDown = options.upDown; +} + +ClockFace.prototype.tick = function() { + const time = new Date(); + const now = { + d: `${time.getFullYear()}-${time.getMonth()}-${time.getDate()}`, + h: time.getHours(), + m: time.getMinutes(), + s: time.getSeconds(), + }; + if (!this._last) { + g.clear(true); + Bangle.drawWidgets(); + g.reset(); + this.draw.apply(this, [time, {d: true, h: true, m: true, s: true}]); + } else { + let c = {d: false, h: false, m: false, s: false}; // changed + if (now.d!==this._last.d) c.d = c.h = c.m = c.s = true; + else if (now.h!==this._last.h) c.h = c.m = c.s = true; + else if (now.m!==this._last.m) c.m = c.s = true; + else if (now.s!==this._last.s) c.s = true; + g.reset(); + this.update.apply(this, [time, c]); + } + this._last = now; + if (this.paused) return; // called redraw() while still paused + // figure out timeout: if e.g. precision=60s, update at the start of a new minute + const interval = this.precision*1000; + this._timeout = setTimeout(() => this.tick(), interval-(Date.now()%interval)); +}; + +ClockFace.prototype.start = function() { + Bangle.loadWidgets(); + if (this.init) this.init.apply(this); + if (this._upDown) Bangle.setUI("clockupdown", d=>this._upDown.apply(this,[d])); + else Bangle.setUI("clock"); + delete this._last; + this.tick(); + + Bangle.on("lcdPower", on => { + if (on) this.resume(); + else this.pause(); + }); +}; + +ClockFace.prototype.pause = function() { + if (!this._timeout) return; // already paused + clearTimeout(this._timeout); + delete this._timeout; + this.paused = true; // apps might want to check this + if (this._pause) this._pause.apply(this); +}; +ClockFace.prototype.resume = function() { + if (this._timeout) return; // not paused + delete this._last; + delete this.paused; + if (this._resume) this._resume.apply(this); + this.tick(true); +}; + +/** + * Force a complete redraw + */ +ClockFace.prototype.redraw = function() { + delete this._last; + this.tick(); +}; + +exports = ClockFace; \ No newline at end of file diff --git a/modules/ClockFace.md b/modules/ClockFace.md new file mode 100644 index 000000000..1da6e6020 --- /dev/null +++ b/modules/ClockFace.md @@ -0,0 +1,110 @@ +ClockFace +========= + +This module handles most of the tasks needed to set up a clock, so you can +concentrate on drawing the time. + +Example +------- +Tthe [tutorial clock](https://www.espruino.com/Bangle.js+Clock) converted to use +this module: + +```js + +// Load fonts +require("Font7x11Numeric7Seg").add(Graphics); +// position on screen +const X = 160, Y = 140; + +var ClockFace = require("ClockFace"); +var clock = new ClockFace({ + precision: 1, // update every second + draw: function(d) { + // work out how to display the current time + var h = d.getHours(), m = d.getMinutes(); + var time = (" "+h).substr(-2)+":"+("0"+m).substr(-2); + // draw the current time (4x size 7 segment) + g.setFont("7x11Numeric7Seg", 4); + g.setFontAlign(1, 1); // align right bottom + g.drawString(time, X, Y, true /*clear background*/); + // draw the seconds (2x size 7 segment) + g.setFont("7x11Numeric7Seg", 2); + g.drawString(("0"+d.getSeconds()).substr(-2), X+30, Y, true /*clear background*/); + // draw the date, in a normal font + g.setFont("6x8"); + g.setFontAlign(0, 1); // align center bottom + // pad the date - this clears the background if the date were to change length + var dateStr = " "+require("locale").date(d)+" "; + g.drawString(dateStr, g.getWidth()/2, Y+15, true /*clear background*/); + } +}); +clock.start(); + +``` + + + +Complete Usage +-------------- + +```js + +var ClockFace = require("ClockFace"); +var clock = new ClockFace({ + precision: 1, // optional, defaults to 60: how often to call update(), in seconds + init: function() { // optional + // called only once before starting the clock, but after setting up the + // screen/widgets, so you can use Bangle.appRect + }, + draw: function(time, changed) { // at least draw or update is required + // (re)draw entire clockface, time is a Date object + // `changed` is the same format as for update() below, but always all true + }, + // The difference between draw() and update() is that the screen is cleared + // before draw() is called, so it needs to always redraw the entire clock + update: function(time, changed) { // at least draw or update is required + // redraw date/time, time is a Date object + // if you want, you can only redraw the changed parts: + if (changed.d) // redraw date (changed.h/m/s will also all be true) + if (changed.h) // redraw hours + if (changed.m) // redraw minutes + if (changed.s) // redraw seconds + }, + pause: function() { // optional, called when the screen turns off + // for example: turn off GPS/compass if the watch used it + }, + resume: function() { // optional, called when the screen turns on + // for example: turn GPS/compass back on + }, + up: function() { // optional, up handler + }, + down: function() { // optional, down handler + }, + upDown: function(dir) { // optional, combined up/down handler + if (dir === -1) // Up + else // (dir === 1): Down + }, + }); +clock.start(); + +``` + + +Simple Usage +------------ +Basic clocks can pass just a function to redraw the entire screen every minute: + +```js + +var ClockFace = require("ClockFace"); +var clock = new ClockFace(function(time) { + // draw the current time at the center of the screen + g.setFont("Vector:50").setFontAlign(0, 0) + .drawString( + require("locale").time(time, true), + Bangle.appRect.w/2, Bangle.appRect.h/2 + ); +}); +clock.start(); + +``` \ No newline at end of file From 8f342e27cc172b3694edc5227dba724810395396 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Sun, 15 May 2022 18:25:18 +0200 Subject: [PATCH 061/163] barclock: Use ClockFace library --- apps/barclock/ChangeLog | 1 + apps/barclock/clock-bar.js | 105 ++++++++++++++++-------------------- apps/barclock/metadata.json | 2 +- 3 files changed, 48 insertions(+), 60 deletions(-) diff --git a/apps/barclock/ChangeLog b/apps/barclock/ChangeLog index 316660fc6..0b8470b6a 100644 --- a/apps/barclock/ChangeLog +++ b/apps/barclock/ChangeLog @@ -7,3 +7,4 @@ 0.07: Update to use Bangle.setUI instead of setWatch 0.08: Use theme colors, Layout library 0.09: Fix time/date disappearing after fullscreen notification +0.10: Use ClockFace library diff --git a/apps/barclock/clock-bar.js b/apps/barclock/clock-bar.js index 5d46a1cb4..a465bb692 100644 --- a/apps/barclock/clock-bar.js +++ b/apps/barclock/clock-bar.js @@ -11,13 +11,9 @@ let locale = require("locale"); date.setMonth(1, 3); // februari: months are zero-indexed const localized = locale.date(date, true); locale.dayFirst = /3.*2/.test(localized); - - locale.hasMeridian = false; - if (typeof locale.meridian==="function") { // function does not exist if languages app is not installed - locale.hasMeridian = (locale.meridian(date)!==""); - } + locale.hasMeridian = (locale.meridian(date)!==""); } -Bangle.loadWidgets(); + function renderBar(l) { if (!this.fraction) { // zero-size fillRect stills draws one line of pixels, we don't want that @@ -27,32 +23,6 @@ function renderBar(l) { g.fillRect(l.x, l.y, l.x+width-1, l.y+l.height-1); } -const Layout = require("Layout"); -const layout = new Layout({ - type: "v", c: [ - { - type: "h", c: [ - {id: "time", label: "88:88", type: "txt", font: "6x8:5", bgCol: g.theme.bg}, // size updated below - {id: "ampm", label: " ", type: "txt", font: "6x8:2", bgCol: g.theme.bg}, - ], - }, - {id: "bar", type: "custom", fraction: 0, fillx: 1, height: 6, col: g.theme.fg2, render: renderBar}, - {height: 40}, - {id: "date", type: "txt", font: "10%", valign: 1}, - ], -}, {lazy: true}); -// adjustments based on screen size and whether we display am/pm -let thickness; // bar thickness, same as time font "pixel block" size -if (is12Hour) { - // Maximum font size = ( - ) / (5chars * 6px) - thickness = Math.floor((g.getWidth()-24)/(5*6)); -} else { - layout.ampm.label = ""; - thickness = Math.floor(g.getWidth()/(5*6)); -} -layout.bar.height = thickness+1; -layout.time.font = "6x8:"+thickness; -layout.update(); function timeText(date) { if (!is12Hour) { @@ -78,31 +48,48 @@ function dateText(date) { return `${dayName} ${dayMonth}`; } -draw = function draw(force) { - if (!Bangle.isLCDOn()) {return;} // no drawing, also no new update scheduled - const date = new Date(); - layout.time.label = timeText(date); - layout.ampm.label = ampmText(date); - layout.date.label = dateText(date); - const SECONDS_PER_MINUTE = 60; - layout.bar.fraction = date.getSeconds()/SECONDS_PER_MINUTE; - if (force) { - Bangle.drawWidgets(); - layout.forgetLazyState(); - } - layout.render(); - // schedule update at start of next second - const millis = date.getMilliseconds(); - setTimeout(draw, 1000-millis); -}; -// Show launcher when button pressed -Bangle.setUI("clock"); -Bangle.on("lcdPower", function(on) { - if (on) { - draw(true); - } -}); -g.reset().clear(); -Bangle.drawWidgets(); -draw(); +const ClockFace = require("ClockFace"), + clock = new ClockFace({ + precision:1, + init: function() { + const Layout = require("Layout"); + this.layout = new Layout({ + type: "v", c: [ + { + type: "h", c: [ + {id: "time", label: "88:88", type: "txt", font: "6x8:5", col:g.theme.fg, bgCol: g.theme.bg}, // size updated below + {id: "ampm", label: " ", type: "txt", font: "6x8:2", col:g.theme.fg, bgCol: g.theme.bg}, + ], + }, + {id: "bar", type: "custom", fraction: 0, fillx: 1, height: 6, col: g.theme.fg2, render: renderBar}, + {height: 40}, + {id: "date", type: "txt", font: "10%", valign: 1}, + ], + }, {lazy: true}); + // adjustments based on screen size and whether we display am/pm + let thickness; // bar thickness, same as time font "pixel block" size + if (is12Hour) { + // Maximum font size = ( - ) / (5chars * 6px) + thickness = Math.floor((Bangle.appRect.w-24)/(5*6)); + } else { + this.layout.ampm.label = ""; + thickness = Math.floor(Bangle.appRect.w/(5*6)); + } + this.layout.bar.height = thickness+1; + this.layout.time.font = "6x8:"+thickness; + this.layout.update(); + }, + update: function(date, c) { + if (c.m) this.layout.time.label = timeText(date); + if (c.h) this.layout.ampm.label = ampmText(date); + if (c.d) this.layout.date.label = dateText(date); + const SECONDS_PER_MINUTE = 60; + if (c.s) this.layout.bar.fraction = date.getSeconds()/SECONDS_PER_MINUTE; + this.layout.render(); + }, + resume: function() { + this.layout.forgetLazyState(); + }, + }); +clock.start(); diff --git a/apps/barclock/metadata.json b/apps/barclock/metadata.json index 2b7be355f..3ee7ccb3a 100644 --- a/apps/barclock/metadata.json +++ b/apps/barclock/metadata.json @@ -1,7 +1,7 @@ { "id": "barclock", "name": "Bar Clock", - "version": "0.09", + "version": "0.10", "description": "A simple digital clock showing seconds as a bar", "icon": "clock-bar.png", "screenshots": [{"url":"screenshot.png"},{"url":"screenshot_pm.png"}], From 6f68e07d665c82289680304aa2afc4804c21ff9c Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Sun, 15 May 2022 19:27:40 +0200 Subject: [PATCH 062/163] Don't change page if doing swipe-to-exit --- apps/dtlaunch/app-b2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dtlaunch/app-b2.js b/apps/dtlaunch/app-b2.js index 8466a7414..46194ec5d 100644 --- a/apps/dtlaunch/app-b2.js +++ b/apps/dtlaunch/app-b2.js @@ -93,7 +93,7 @@ Bangle.on("swipe",(dirLeftRight, dirUpDown)=>{ if (dirUpDown==-1||dirLeftRight==-1){ ++page; if (page>maxPage) page=0; drawPage(page); - } else if (dirUpDown==1||dirLeftRight==1){ + } else if (dirUpDown==1||(dirLeftRight==1 && !settings.swipeExit)){ --page; if (page<0) page=maxPage; drawPage(page); } From 3f29aff90a59827226e56b659c506913ae68ac63 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Sun, 15 May 2022 19:32:37 +0200 Subject: [PATCH 063/163] Up and down also moves pages --- apps/dtlaunch/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/dtlaunch/README.md b/apps/dtlaunch/README.md index bea20ef65..55c9f53b8 100644 --- a/apps/dtlaunch/README.md +++ b/apps/dtlaunch/README.md @@ -29,6 +29,6 @@ Bangle 2: **Touch** - icon to select, scond touch launches app -**Swipe Left** - move to next page of app icons +**Swipe Left/Up** - move to next page of app icons -**Swipe Right** - move to previous page of app icons +**Swipe Right/Down** - move to previous page of app icons From 7a6aa8158b80c23778accd5e5e0bf34355ad5c2b Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Sun, 15 May 2022 19:36:22 +0200 Subject: [PATCH 064/163] Don't change page if doing swipe-to-exit --- apps/dtlaunch/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/dtlaunch/ChangeLog b/apps/dtlaunch/ChangeLog index 95952b9fe..09804b82e 100644 --- a/apps/dtlaunch/ChangeLog +++ b/apps/dtlaunch/ChangeLog @@ -11,3 +11,4 @@ 0.11: Fix bangle.js 1 white icons not displaying 0.12: On Bangle 2 change to swiping up/down to move between pages as to match page indicator. Swiping from left to right now loads the clock. 0.13: Added swipeExit setting so that left-right to exit is an option +0.14: Don't move pages when doing exit swipe. From f9af4b064010b9e361b6255a05969b6fe7e30e44 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Sun, 15 May 2022 19:36:46 +0200 Subject: [PATCH 065/163] Update metadata.json --- apps/dtlaunch/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dtlaunch/metadata.json b/apps/dtlaunch/metadata.json index 7784972ca..4a0b8067c 100644 --- a/apps/dtlaunch/metadata.json +++ b/apps/dtlaunch/metadata.json @@ -1,7 +1,7 @@ { "id": "dtlaunch", "name": "Desktop Launcher", - "version": "0.13", + "version": "0.14", "description": "Desktop style App Launcher with six (four for Bangle 2) apps per page - fast access if you have lots of apps installed.", "screenshots": [{"url":"shot1.png"},{"url":"shot2.png"},{"url":"shot3.png"}], "icon": "icon.png", From 275f6a87d5e043a37baafb1644e96f3c9e33b318 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Mon, 16 May 2022 11:51:59 +0200 Subject: [PATCH 066/163] add fixed and equal button width for all buttons replaced fillx:1 with width:btnWidth --- apps/kbmulti/lib.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/apps/kbmulti/lib.js b/apps/kbmulti/lib.js index c8abf98b4..b099603cb 100644 --- a/apps/kbmulti/lib.js +++ b/apps/kbmulti/lib.js @@ -24,6 +24,7 @@ exports.input = function(options) { var charIndex; // index in letters[charCurrent] var caps = true; var layout; + var btnWidth = g.getWidth()/3 function displayText(hideMarker) { layout.clear(layout.text); @@ -107,19 +108,19 @@ exports.input = function(options) { (settings.showHelpBtn ? {type:"btn", font:'6x8', label:'?', cb: l=>onHelp(resolve,reject), filly:1 } : {}), ]}, {type:"h", c: [ - {type:"btn", font:fontSize, label:letters[1], cb: l=>onKeyPad(1), id:'1', fillx:1, filly:1 }, - {type:"btn", font:fontSize, label:letters[2], cb: l=>onKeyPad(2), id:'2', fillx:1, filly:1 }, - {type:"btn", font:fontSize, label:letters[3], cb: l=>onKeyPad(3), id:'3', fillx:1, filly:1 }, + {type:"btn", font:fontSize, label:letters[1], cb: l=>onKeyPad(1), id:'1', width:btnWidth, filly:1 }, + {type:"btn", font:fontSize, label:letters[2], cb: l=>onKeyPad(2), id:'2', width:btnWidth, filly:1 }, + {type:"btn", font:fontSize, label:letters[3], cb: l=>onKeyPad(3), id:'3', width:btnWidth, filly:1 }, ]}, {type:"h", filly:1, c: [ - {type:"btn", font:fontSize, label:letters[4], cb: l=>onKeyPad(4), id:'4', fillx:1, filly:1 }, - {type:"btn", font:fontSize, label:letters[5], cb: l=>onKeyPad(5), id:'5', fillx:1, filly:1 }, - {type:"btn", font:fontSize, label:letters[6], cb: l=>onKeyPad(6), id:'6', fillx:1, filly:1 }, + {type:"btn", font:fontSize, label:letters[4], cb: l=>onKeyPad(4), id:'4', width:btnWidth, filly:1 }, + {type:"btn", font:fontSize, label:letters[5], cb: l=>onKeyPad(5), id:'5', width:btnWidth, filly:1 }, + {type:"btn", font:fontSize, label:letters[6], cb: l=>onKeyPad(6), id:'6', width:btnWidth, filly:1 }, ]}, {type:"h", filly:1, c: [ - {type:"btn", font:fontSize, label:letters[7], cb: l=>onKeyPad(7), id:'7', fillx:1, filly:1 }, - {type:"btn", font:fontSize, label:letters[8], cb: l=>onKeyPad(8), id:'8', fillx:1, filly:1 }, - {type:"btn", font:fontSize, label:letters[9], cb: l=>onKeyPad(9), id:'9', fillx:1, filly:1 }, + {type:"btn", font:fontSize, label:letters[7], cb: l=>onKeyPad(7), id:'7', width:btnWidth, filly:1 }, + {type:"btn", font:fontSize, label:letters[8], cb: l=>onKeyPad(8), id:'8', width:btnWidth, filly:1 }, + {type:"btn", font:fontSize, label:letters[9], cb: l=>onKeyPad(9), id:'9', width:btnWidth, filly:1 }, ]}, ] },{back: ()=>{ From 9a98a518dea0f8ce6a36f37f632eb07d5e8000fb Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Mon, 16 May 2022 11:52:59 +0200 Subject: [PATCH 067/163] Update lib.js --- apps/kbmulti/lib.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/kbmulti/lib.js b/apps/kbmulti/lib.js index b099603cb..5ccab4204 100644 --- a/apps/kbmulti/lib.js +++ b/apps/kbmulti/lib.js @@ -115,7 +115,7 @@ exports.input = function(options) { {type:"h", filly:1, c: [ {type:"btn", font:fontSize, label:letters[4], cb: l=>onKeyPad(4), id:'4', width:btnWidth, filly:1 }, {type:"btn", font:fontSize, label:letters[5], cb: l=>onKeyPad(5), id:'5', width:btnWidth, filly:1 }, - {type:"btn", font:fontSize, label:letters[6], cb: l=>onKeyPad(6), id:'6', width:btnWidth, filly:1 }, + {type:"btn", font:fontSize, label:letters[6], cb: l=>onKeyPad(6), id:'6', width:btnWidth, filly:1 }, ]}, {type:"h", filly:1, c: [ {type:"btn", font:fontSize, label:letters[7], cb: l=>onKeyPad(7), id:'7', width:btnWidth, filly:1 }, From fd35af1bd67cae273d1278961328e16db80346be Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Mon, 16 May 2022 12:34:46 +0200 Subject: [PATCH 068/163] Update ChangeLog --- apps/kbmulti/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/kbmulti/ChangeLog b/apps/kbmulti/ChangeLog index c6c606bff..709aa3203 100644 --- a/apps/kbmulti/ChangeLog +++ b/apps/kbmulti/ChangeLog @@ -1,2 +1,2 @@ 0.01: New keyboard -0.02: Introduce setting "Show help button?". Make setting firstLaunch invisible by removing corresponding code from settings.js. Add marker that shows when character selection timeout has run out. Display opened text on launch when editing existing text string. +0.02: Introduce setting "Show help button?". Make setting firstLaunch invisible by removing corresponding code from settings.js. Add marker that shows when character selection timeout has run out. Display opened text on launch when editing existing text string. Perfect horizontal alignment of buttons. Tweak help message letter casing. From b4b6d424ecc18b85554cf84b88f23a341ac4fc86 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Mon, 16 May 2022 12:42:07 +0200 Subject: [PATCH 069/163] perfect horizontal button alignment --- apps/kbmulti/screenshot_3.png | Bin 3674 -> 3503 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/kbmulti/screenshot_3.png b/apps/kbmulti/screenshot_3.png index e0da184baa34c29285e7cd5b76d93638450a6cf4..882ea73862fe0c46c8a984fbc9b6c63afe1dc4a9 100644 GIT binary patch delta 3489 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 From 7f9bf3a758c090b8d69839f2a5e871796cf6377e Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 16 May 2022 14:32:35 +0100 Subject: [PATCH 070/163] Add option to use lower write size for phones with potentially iffy Bluetooth stacks (fix #)1834 --- index.html | 4 ++++ loader.js | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/index.html b/index.html index de7facd5a..b141cffc9 100644 --- a/index.html +++ b/index.html @@ -147,6 +147,10 @@ Always update time when we connect +