From 6edcae393cf856320afffca097a84eae5b12e21a Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Mon, 29 May 2023 12:00:48 +0100 Subject: [PATCH 01/17] multitimer: allow one-shot alarms (delete after) --- apps/multitimer/ChangeLog | 1 + apps/multitimer/README.md | 1 + apps/multitimer/alarm.js | 8 +++++++- apps/multitimer/app.js | 22 ++++++++++++++-------- apps/multitimer/metadata.json | 2 +- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/apps/multitimer/ChangeLog b/apps/multitimer/ChangeLog index 9a2ab0ff4..c682077e4 100644 --- a/apps/multitimer/ChangeLog +++ b/apps/multitimer/ChangeLog @@ -1,3 +1,4 @@ 0.01: Initial version 0.02: Update for time_utils module 0.03: Use default Bangle formatter for booleans +0.04: Add "Oneshot" setting to delete an alarm/timer after it sounds diff --git a/apps/multitimer/README.md b/apps/multitimer/README.md index f1e2eb281..4dcc4a8fd 100644 --- a/apps/multitimer/README.md +++ b/apps/multitimer/README.md @@ -2,6 +2,7 @@ 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. +"Oneshot" can be set on timers and alarms to have it delete itself once it's sounded. ## WARNING * Editing timers in another app (such as the default Alarm app) is not recommended. Editing alarms should not be a problem (in theory). diff --git a/apps/multitimer/alarm.js b/apps/multitimer/alarm.js index eb1b3b259..8c3b1cdd4 100644 --- a/apps/multitimer/alarm.js +++ b/apps/multitimer/alarm.js @@ -105,7 +105,13 @@ function showAlarm(alarm) { alarm.t = alarm.ot; delete alarm.ot; } - if (!alarm.rp) alarm.on = false; + if (!alarm.rp) { + alarm.on = false; + if (alarm.data.oneshot) { + const i = alarms.indexOf(alarm); + if (i >= 0) alarms.splice(i, 1); + } + } } //reset timer value if (alarm.timer) alarm.timer = alarm.data.ot; diff --git a/apps/multitimer/app.js b/apps/multitimer/app.js index 8832d1a25..b066607be 100644 --- a/apps/multitimer/app.js +++ b/apps/multitimer/app.js @@ -228,8 +228,7 @@ function editTimer(idx, a) { else a = timers[idx]; } if (!a.data) { - a.data = {}; - a.data.hm = false; + a.data = { hm: false, oneshot: false }; } var t = decodeTime(a.timer); @@ -291,10 +290,14 @@ function editTimer(idx, a) { } }, "Hard Mode": { - value: a.data.hm, + value: !!a.data.hm, onchange: v => a.data.hm = v }, "Vibrate": require("buzz_menu").pattern(a.vibrate, v => a.vibrate = v), + "Oneshot": { + value: !!a.data.oneshot, + onchange: v => a.data.oneshot = v + }, "Msg": { value: !a.msg ? "" : a.msg.length > 6 ? a.msg.substring(0, 6)+"..." : a.msg, //menu glitch? setTimeout required here @@ -556,8 +559,7 @@ function editAlarm(idx, a) { else a = require("sched").newDefaultAlarm(); } if (!a.data) { - a.data = {}; - a.data.hm = false; + a.data = { hm: false, oneshot: false }; } var t = decodeTime(a.t); @@ -582,8 +584,8 @@ function editAlarm(idx, a) { var menu = { "": { "title": "Alarm" }, "< Back": () => { - if (a.data.hm == true) a.js = "(require('Storage').read('multitimer.alarm.js') !== undefined) ? load('multitimer.alarm.js') : load('sched.js')"; - if (a.data.hm == false && a.js) delete a.js; + if (a.data.hm || a.data.oneshot) a.js = "(require('Storage').read('multitimer.alarm.js') !== undefined) ? load('multitimer.alarm.js') : load('sched.js')"; + else if (a.js) delete a.js; if (idx >= 0) alarms[alarmIdx[idx]] = a; else alarms.push(a); require("sched").setAlarms(alarms); @@ -617,10 +619,14 @@ function editAlarm(idx, a) { onchange: () => editDOW(a.dow, d=>{a.dow=d;editAlarm(idx,a);}) }, "Hard Mode": { - value: a.data.hm, + value: !!a.data.hm, onchange: v => a.data.hm = v }, "Vibrate": require("buzz_menu").pattern(a.vibrate, v => a.vibrate = v), + "Oneshot": { + value: !!a.data.oneshot, + onchange: v => a.data.oneshot = v + }, "Auto Snooze": { value: a.as, onchange: v => a.as = v diff --git a/apps/multitimer/metadata.json b/apps/multitimer/metadata.json index ee77d2ecb..0c9eddc9e 100644 --- a/apps/multitimer/metadata.json +++ b/apps/multitimer/metadata.json @@ -1,7 +1,7 @@ { "id": "multitimer", "name": "Multi Timer", - "version": "0.03", + "version": "0.04", "description": "Set timers and chronographs (stopwatches) and watch them count down in real time. Pause, create, edit, and delete timers and chronos, and add custom labels/messages. Also sets alarms.", "icon": "app.png", "screenshots": [ From 3aaff4b460e74d692d45e306c2e28069cd9e1e4c Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 7 Jun 2023 17:45:05 +0100 Subject: [PATCH 02/17] multitimer: update from sched.js --- apps/multitimer/alarm.js | 91 ++++++++++++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 23 deletions(-) diff --git a/apps/multitimer/alarm.js b/apps/multitimer/alarm.js index 8c3b1cdd4..77aa416b9 100644 --- a/apps/multitimer/alarm.js +++ b/apps/multitimer/alarm.js @@ -70,14 +70,19 @@ function startHM() { } function showAlarm(alarm) { + const alarmIndex = alarms.indexOf(alarm); const settings = require("sched").getSettings(); - let msg = ""; - if (alarm.timer) msg += require("time_utils").formatTime(alarm.timer); + let message = ""; + message += alarm.timer ? require("time_utils").formatDuration(alarm.timer) : require("time_utils").formatTime(alarm.t); if (alarm.msg) { - msg += "\n"+alarm.msg; + message += "\n" + alarm.msg; + } else { + message = (alarm.timer + ? atob("ACQswgD//33vRcGHIQAAABVVVAAAAAAAABVVVAAAAAAAABVVVAAAAAAAABVVVAAAAAAAABVVVAAAAAAAABVVVAAAAAAAAAP/wAAAAAAAAAP/wAAAAAAAAAqqoAPAAAAAAqqqqoP8AAAAKqqqqqv/AAACqqqqqqq/wAAKqqqlWqqvwAAqqqqlVaqrAACqqqqlVVqqAAKqqqqlVVaqgAKqaqqlVVWqgAqpWqqlVVVqoAqlWqqlVVVaoCqlV6qlVVVaqCqVVfqlVVVWqCqVVf6lVVVWqKpVVX/lVVVVqqpVVV/+VVVVqqpVVV//lVVVqqpVVVfr1VVVqqpVVVfr1VVVqqpVVVb/lVVVqqpVVVW+VVVVqqpVVVVVVVVVqiqVVVVVVVVWqCqVVVVVVVVWqCqlVVVVVVVaqAqlVVVVVVVaoAqpVVVVVVVqoAKqVVVVVVWqgAKqlVVVVVaqgACqpVVVVVqqAAAqqlVVVaqoAAAKqqVVWqqgAAACqqqqqqqAAAAAKqqqqqgAAAAAAqqqqoAAAAAAAAqqoAAAAA==") + : atob("AC0swgF97///RcEpMlVVVVVVf9VVVVVVVVX/9VVf9VVf/1VVV///1Vf9VX///VVX///VWqqlV///1Vf//9aqqqqpf//9V///2qqqqqqn///V///6qqqqqqr///X//+qqoAAKqqv//3//6qoAAAAKqr//3//qqAAAAAAqq//3/+qoAADwAAKqv/3/+qgAADwAACqv/3/aqAAADwAAAqp/19qoAAADwAAAKqfV1qgAAADwAAACqXVWqgAAADwAAACqlVWqAAAADwAAAAqlVWqAAAADwAAAAqlVWqAAAADwAAAAqlVaoAAAADwAAAAKpVaoAAAADwAAAAKpVaoAAAADwAAAAKpVaoAAAAOsAAAAKpVaoAAAAOsAAAAKpVaoAAAAL/AAAAKpVaoAAAAgPwAAAKpVaoAAACAD8AAAKpVWqAAAIAA/AAAqlVWqAAAgAAPwAAqlVWqAACAAADwAAqlVWqgAIAAAAAACqlVVqgAgAAAAAACqVVVqoAAAAAAAAKqVVVaqAAAAAAAAqpVVVWqgAAAAAACqlVVVWqoAAAAAAKqlVVVVqqAAAAAAqqVVVVVaqoAAAAKqpVVVVVeqqoAAKqqtVVVVV/6qqqqqqr/VVVVX/2qqqqqqn/1VVVf/VaqqqqpV/9VVVf9VVWqqlVVf9VVVf1VVVVVVVVX9VQ==") + ) + " " + message } - else msg = atob("ACQswgD//33vRcGHIQAAABVVVAAAAAAAABVVVAAAAAAAABVVVAAAAAAAABVVVAAAAAAAABVVVAAAAAAAABVVVAAAAAAAAAP/wAAAAAAAAAP/wAAAAAAAAAqqoAPAAAAAAqqqqoP8AAAAKqqqqqv/AAACqqqqqqq/wAAKqqqlWqqvwAAqqqqlVaqrAACqqqqlVVqqAAKqqqqlVVaqgAKqaqqlVVWqgAqpWqqlVVVqoAqlWqqlVVVaoCqlV6qlVVVaqCqVVfqlVVVWqCqVVf6lVVVWqKpVVX/lVVVVqqpVVV/+VVVVqqpVVV//lVVVqqpVVVfr1VVVqqpVVVfr1VVVqqpVVVb/lVVVqqpVVVW+VVVVqqpVVVVVVVVVqiqVVVVVVVVWqCqVVVVVVVVWqCqlVVVVVVVaqAqlVVVVVVVaoAqpVVVVVVVqoAKqVVVVVVWqgAKqlVVVVVaqgACqpVVVVVqqAAAqqlVVVaqoAAAKqqVVWqqgAAACqqqqqqqAAAAAKqqqqqgAAAAAAqqqqoAAAAAAAAqqoAAAAA==")+" "+msg; Bangle.loadWidgets(); Bangle.drawWidgets(); @@ -91,31 +96,42 @@ function showAlarm(alarm) { } 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) { + E.showPrompt(message, { + title: alarm.timer ? /*LANG*/"TIMER!" : /*LANG*/"ALARM!", + buttons: { /*LANG*/"Snooze": true, /*LANG*/"Stop": false } // default is sleep so it'll come back in some 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.ot === undefined) { + alarm.ot = alarm.t; } - if (!alarm.rp) { - alarm.on = false; - if (alarm.data.oneshot) { - const i = alarms.indexOf(alarm); - if (i >= 0) alarms.splice(i, 1); + alarm.t += settings.defaultSnoozeMillis; + Bangle.emit("alarmSnooze", alarm); + } else { + let del = alarm.del === undefined ? settings.defaultDeleteExpiredTimers : alarm.del; + if (del) { + if (alarmIndex >= 0) alarms.splice(alarmIndex, 1); + } else { + if (alarm.date && alarm.rp) { + setNextRepeatDate(alarm); + } 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; } } + Bangle.emit("alarmDismiss", alarm); } //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 + // The updated alarm is still a member of 'alarms' + // so writing to array writes changes back directly require("sched").setAlarms(alarms); load(); }); @@ -126,7 +142,8 @@ function showAlarm(alarm) { Bangle.setLocked(false); } - require("buzz").pattern(alarm.vibrate === undefined ? "::" : alarm.vibrate).then(() => { + const pattern = alarm.vibrate || (alarm.timer ? settings.defaultTimerPattern : settings.defaultAlarmPattern); + require("buzz").pattern(pattern).then(() => { if (buzzCount--) { setTimeout(buzz, settings.buzzIntervalMillis); } else if (alarm.as) { // auto-snooze @@ -136,13 +153,41 @@ function showAlarm(alarm) { }); } + function setNextRepeatDate(alarm) { + let date = new Date(alarm.date); + let rp = alarm.rp; + if (rp===true) { // fallback in case rp is set wrong + date.setDate(date.getDate() + 1); + } else switch(rp.interval) { // rp is an object + case "day": + date.setDate(date.getDate() + rp.num); + break; + case "week": + date.setDate(date.getDate() + (rp.num * 7)); + break; + case "month": + if (!alarm.od) alarm.od = date.getDate(); + date = new Date(date.getFullYear(), date.getMonth() + rp.num, alarm.od); + if (date.getDate() != alarm.od) date.setDate(0); + break; + case "year": + if (!alarm.od) alarm.od = date.getDate(); + date = new Date(date.getFullYear() + rp.num, date.getMonth(), alarm.od); + if (date.getDate() != alarm.od) date.setDate(0); + break; + default: + console.log(`sched: unknown repeat '${JSON.stringify(rp)}'`); + break; + } + alarm.date = date.toLocalISOString().slice(0,10); + } + 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) { From 508808cc3d86edcb7c8803c098638c9106fe06e3 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 7 Jun 2023 17:57:00 +0100 Subject: [PATCH 03/17] sched: only splice out alarm, if it's present in alarms --- apps/sched/sched.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sched/sched.js b/apps/sched/sched.js index 3deb9d1f0..6eea4add5 100644 --- a/apps/sched/sched.js +++ b/apps/sched/sched.js @@ -40,7 +40,7 @@ function showAlarm(alarm) { } else { let del = alarm.del === undefined ? settings.defaultDeleteExpiredTimers : alarm.del; if (del) { - alarms.splice(alarmIndex, 1); + if (alarmIndex >= 0) alarms.splice(alarmIndex, 1); } else { if (alarm.date && alarm.rp) { setNextRepeatDate(alarm); From 70ea8df149688d7f45ce2ca4e5dc0da1bc31f7c8 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 7 Jun 2023 17:57:43 +0100 Subject: [PATCH 04/17] multitimer: align with alarm app --- apps/multitimer/ChangeLog | 2 +- apps/multitimer/README.md | 2 +- apps/multitimer/app.js | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/multitimer/ChangeLog b/apps/multitimer/ChangeLog index c682077e4..3100146e9 100644 --- a/apps/multitimer/ChangeLog +++ b/apps/multitimer/ChangeLog @@ -1,4 +1,4 @@ 0.01: Initial version 0.02: Update for time_utils module 0.03: Use default Bangle formatter for booleans -0.04: Add "Oneshot" setting to delete an alarm/timer after it sounds +0.04: Merge in alarm app's newer changes: diff --git a/apps/multitimer/README.md b/apps/multitimer/README.md index 4dcc4a8fd..d5bf957a6 100644 --- a/apps/multitimer/README.md +++ b/apps/multitimer/README.md @@ -2,7 +2,7 @@ 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. -"Oneshot" can be set on timers and alarms to have it delete itself once it's sounded. +"Oneshot" can be set on timers and alarms to have it delete itself once it's sounded (uses the "Delete after expiration" setting from the alarm app). ## WARNING * Editing timers in another app (such as the default Alarm app) is not recommended. Editing alarms should not be a problem (in theory). diff --git a/apps/multitimer/app.js b/apps/multitimer/app.js index b066607be..d8459eaa6 100644 --- a/apps/multitimer/app.js +++ b/apps/multitimer/app.js @@ -228,7 +228,7 @@ function editTimer(idx, a) { else a = timers[idx]; } if (!a.data) { - a.data = { hm: false, oneshot: false }; + a.data = { hm: false }; } var t = decodeTime(a.timer); @@ -295,8 +295,8 @@ function editTimer(idx, a) { }, "Vibrate": require("buzz_menu").pattern(a.vibrate, v => a.vibrate = v), "Oneshot": { - value: !!a.data.oneshot, - onchange: v => a.data.oneshot = v + value: !!a.del, + onchange: v => a.del = v }, "Msg": { value: !a.msg ? "" : a.msg.length > 6 ? a.msg.substring(0, 6)+"..." : a.msg, @@ -584,7 +584,7 @@ function editAlarm(idx, a) { var menu = { "": { "title": "Alarm" }, "< Back": () => { - if (a.data.hm || a.data.oneshot) a.js = "(require('Storage').read('multitimer.alarm.js') !== undefined) ? load('multitimer.alarm.js') : load('sched.js')"; + if (a.data.hm) a.js = "(require('Storage').read('multitimer.alarm.js') !== undefined) ? load('multitimer.alarm.js') : load('sched.js')"; else if (a.js) delete a.js; if (idx >= 0) alarms[alarmIdx[idx]] = a; else alarms.push(a); @@ -624,8 +624,8 @@ function editAlarm(idx, a) { }, "Vibrate": require("buzz_menu").pattern(a.vibrate, v => a.vibrate = v), "Oneshot": { - value: !!a.data.oneshot, - onchange: v => a.data.oneshot = v + value: !!a.del, + onchange: v => a.del = v }, "Auto Snooze": { value: a.as, From e6f61ccc6b9c2ccd1d168137d604760c2a81a4c9 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 7 Jun 2023 17:57:52 +0100 Subject: [PATCH 05/17] multitimer: trim whitespace --- apps/multitimer/README.md | 2 +- apps/multitimer/app.js | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/multitimer/README.md b/apps/multitimer/README.md index d5bf957a6..cbbe5c92c 100644 --- a/apps/multitimer/README.md +++ b/apps/multitimer/README.md @@ -6,6 +6,6 @@ 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). +* 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. 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. diff --git a/apps/multitimer/app.js b/apps/multitimer/app.js index d8459eaa6..841b7b6e9 100644 --- a/apps/multitimer/app.js +++ b/apps/multitimer/app.js @@ -232,7 +232,7 @@ function editTimer(idx, a) { } var t = decodeTime(a.timer); - function editMsg(idx, a) { + function editMsg(idx, a) { g.clear(); idx < 0 ? msg = "" : msg = a.msg; require("textinput").input({text:msg}).then(result => { @@ -385,7 +385,7 @@ function swMenu(idx, a) { }, 100 - (a.t % 100)); } - function editMsg(idx, a) { + function editMsg(idx, a) { g.clear(); msg = a.msg; require("textinput").input({text:msg}).then(result => { @@ -559,11 +559,11 @@ function editAlarm(idx, a) { else a = require("sched").newDefaultAlarm(); } if (!a.data) { - a.data = { hm: false, oneshot: false }; + a.data = { hm: false }; } var t = decodeTime(a.t); - function editMsg(idx, a) { + function editMsg(idx, a) { g.clear(); idx < 0 ? msg = "" : msg = a.msg; require("textinput").input({text:msg}).then(result => { @@ -659,7 +659,7 @@ 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; From b56865a136bc236e7e59d3c506328d9fc58b4783 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sun, 11 Jun 2023 19:29:44 +0100 Subject: [PATCH 06/17] multitimer/sched: use triggercheck for pre-alarm code --- apps/multitimer/alarm.js | 199 ---------------------------------- apps/multitimer/app.js | 25 ++++- apps/multitimer/boot.js | 8 ++ apps/multitimer/ext.js | 64 +++++++++++ apps/multitimer/metadata.json | 3 +- apps/sched/sched.js | 86 ++++++++------- typescript/types/sched.d.ts | 4 + 7 files changed, 148 insertions(+), 241 deletions(-) delete mode 100644 apps/multitimer/alarm.js create mode 100644 apps/multitimer/boot.js create mode 100644 apps/multitimer/ext.js diff --git a/apps/multitimer/alarm.js b/apps/multitimer/alarm.js deleted file mode 100644 index 77aa416b9..000000000 --- a/apps/multitimer/alarm.js +++ /dev/null @@ -1,199 +0,0 @@ -//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 hardMode(tries, max) { - var R = Bangle.appRect; - - function adv() { - tries++; - hardMode(tries, max); - } - - 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 alarmIndex = alarms.indexOf(alarm); - const settings = require("sched").getSettings(); - - let message = ""; - message += alarm.timer ? require("time_utils").formatDuration(alarm.timer) : require("time_utils").formatTime(alarm.t); - if (alarm.msg) { - message += "\n" + alarm.msg; - } else { - message = (alarm.timer - ? atob("ACQswgD//33vRcGHIQAAABVVVAAAAAAAABVVVAAAAAAAABVVVAAAAAAAABVVVAAAAAAAABVVVAAAAAAAABVVVAAAAAAAAAP/wAAAAAAAAAP/wAAAAAAAAAqqoAPAAAAAAqqqqoP8AAAAKqqqqqv/AAACqqqqqqq/wAAKqqqlWqqvwAAqqqqlVaqrAACqqqqlVVqqAAKqqqqlVVaqgAKqaqqlVVWqgAqpWqqlVVVqoAqlWqqlVVVaoCqlV6qlVVVaqCqVVfqlVVVWqCqVVf6lVVVWqKpVVX/lVVVVqqpVVV/+VVVVqqpVVV//lVVVqqpVVVfr1VVVqqpVVVfr1VVVqqpVVVb/lVVVqqpVVVW+VVVVqqpVVVVVVVVVqiqVVVVVVVVWqCqVVVVVVVVWqCqlVVVVVVVaqAqlVVVVVVVaoAqpVVVVVVVqoAKqVVVVVVWqgAKqlVVVVVaqgACqpVVVVVqqAAAqqlVVVaqoAAAKqqVVWqqgAAACqqqqqqqAAAAAKqqqqqgAAAAAAqqqqoAAAAAAAAqqoAAAAA==") - : atob("AC0swgF97///RcEpMlVVVVVVf9VVVVVVVVX/9VVf9VVf/1VVV///1Vf9VX///VVX///VWqqlV///1Vf//9aqqqqpf//9V///2qqqqqqn///V///6qqqqqqr///X//+qqoAAKqqv//3//6qoAAAAKqr//3//qqAAAAAAqq//3/+qoAADwAAKqv/3/+qgAADwAACqv/3/aqAAADwAAAqp/19qoAAADwAAAKqfV1qgAAADwAAACqXVWqgAAADwAAACqlVWqAAAADwAAAAqlVWqAAAADwAAAAqlVWqAAAADwAAAAqlVaoAAAADwAAAAKpVaoAAAADwAAAAKpVaoAAAADwAAAAKpVaoAAAAOsAAAAKpVaoAAAAOsAAAAKpVaoAAAAL/AAAAKpVaoAAAAgPwAAAKpVaoAAACAD8AAAKpVWqAAAIAA/AAAqlVWqAAAgAAPwAAqlVWqAACAAADwAAqlVWqgAIAAAAAACqlVVqgAgAAAAAACqVVVqoAAAAAAAAKqVVVaqAAAAAAAAqpVVVWqgAAAAAACqlVVVWqoAAAAAAKqlVVVVqqAAAAAAqqVVVVVaqoAAAAKqpVVVVVeqqoAAKqqtVVVVV/6qqqqqqr/VVVVX/2qqqqqqn/1VVVf/VaqqqqpV/9VVVf9VVWqqlVVf9VVVf1VVVVVVVVX9VQ==") - ) + " " + message - } - - Bangle.loadWidgets(); - Bangle.drawWidgets(); - - let buzzCount = settings.buzzCount; - - if (alarm.data.hm && alarm.data.hm == true) { - //hard mode extends auto-snooze time - buzzCount = buzzCount * 3; - startHM(); - } - - else { - E.showPrompt(message, { - title: alarm.timer ? /*LANG*/"TIMER!" : /*LANG*/"ALARM!", - buttons: { /*LANG*/"Snooze": true, /*LANG*/"Stop": false } // default is sleep so it'll come back in some mins - }).then(function (sleep) { - buzzCount = 0; - - if (sleep) { - if (alarm.ot === undefined) { - alarm.ot = alarm.t; - } - alarm.t += settings.defaultSnoozeMillis; - Bangle.emit("alarmSnooze", alarm); - } else { - let del = alarm.del === undefined ? settings.defaultDeleteExpiredTimers : alarm.del; - if (del) { - if (alarmIndex >= 0) alarms.splice(alarmIndex, 1); - } else { - if (alarm.date && alarm.rp) { - setNextRepeatDate(alarm); - } 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; - } - } - Bangle.emit("alarmDismiss", alarm); - } - //reset timer value - if (alarm.timer) alarm.timer = alarm.data.ot; - // The updated 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); - } - - const pattern = alarm.vibrate || (alarm.timer ? settings.defaultTimerPattern : settings.defaultAlarmPattern); - require("buzz").pattern(pattern).then(() => { - if (buzzCount--) { - setTimeout(buzz, settings.buzzIntervalMillis); - } else if (alarm.as) { // auto-snooze - buzzCount = settings.buzzCount; - setTimeout(buzz, settings.defaultSnoozeMillis); - } - }); - } - - function setNextRepeatDate(alarm) { - let date = new Date(alarm.date); - let rp = alarm.rp; - if (rp===true) { // fallback in case rp is set wrong - date.setDate(date.getDate() + 1); - } else switch(rp.interval) { // rp is an object - case "day": - date.setDate(date.getDate() + rp.num); - break; - case "week": - date.setDate(date.getDate() + (rp.num * 7)); - break; - case "month": - if (!alarm.od) alarm.od = date.getDate(); - date = new Date(date.getFullYear(), date.getMonth() + rp.num, alarm.od); - if (date.getDate() != alarm.od) date.setDate(0); - break; - case "year": - if (!alarm.od) alarm.od = date.getDate(); - date = new Date(date.getFullYear() + rp.num, date.getMonth(), alarm.od); - if (date.getDate() != alarm.od) date.setDate(0); - break; - default: - console.log(`sched: unknown repeat '${JSON.stringify(rp)}'`); - break; - } - alarm.date = date.toLocalISOString().slice(0,10); - } - - if ((require("Storage").readJSON("setting.json", 1) || {}).quiet > 1) - return; - - buzz(); -} - -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); -} diff --git a/apps/multitimer/app.js b/apps/multitimer/app.js index 841b7b6e9..c3b9aa629 100644 --- a/apps/multitimer/app.js +++ b/apps/multitimer/app.js @@ -1,6 +1,13 @@ Bangle.loadWidgets(); Bangle.drawWidgets(); +const triggercheck = ` + eval(require("Storage").read("multitimer.ext.js")); + buzzCount *= 3; + startHM(); + "skipPrompt" +`; + var R = Bangle.appRect; var layer; var drag; @@ -290,8 +297,13 @@ function editTimer(idx, a) { } }, "Hard Mode": { - value: !!a.data.hm, - onchange: v => a.data.hm = v + value: !!a.triggercheck, + onchange: v => { + if (v) + a.triggercheck = triggercheck; + else + delete a.triggercheck; + }, }, "Vibrate": require("buzz_menu").pattern(a.vibrate, v => a.vibrate = v), "Oneshot": { @@ -619,8 +631,13 @@ function editAlarm(idx, a) { onchange: () => editDOW(a.dow, d=>{a.dow=d;editAlarm(idx,a);}) }, "Hard Mode": { - value: !!a.data.hm, - onchange: v => a.data.hm = v + value: !!a.triggercheck, + onchange: v => { + if (v) + a.triggercheck = triggercheck; + else + delete a.triggercheck; + }, }, "Vibrate": require("buzz_menu").pattern(a.vibrate, v => a.vibrate = v), "Oneshot": { diff --git a/apps/multitimer/boot.js b/apps/multitimer/boot.js new file mode 100644 index 000000000..13f1d6363 --- /dev/null +++ b/apps/multitimer/boot.js @@ -0,0 +1,8 @@ +{ + const resetTimer = alarm => { + if (alarm.timer) alarm.timer = alarm.data.ot; + }; + + Bangle.on("alarmSnooze", resetTimer); + Bangle.on("alarmDismiss", resetTimer); +} diff --git a/apps/multitimer/ext.js b/apps/multitimer/ext.js new file mode 100644 index 000000000..6e29e737d --- /dev/null +++ b/apps/multitimer/ext.js @@ -0,0 +1,64 @@ +// called by alarm.triggercheck + +function hardMode(tries, max) { + var R = Bangle.appRect; + + function adv() { + tries++; + hardMode(tries, max); + } + + 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); +} diff --git a/apps/multitimer/metadata.json b/apps/multitimer/metadata.json index 0c9eddc9e..6ae92fbdc 100644 --- a/apps/multitimer/metadata.json +++ b/apps/multitimer/metadata.json @@ -14,7 +14,8 @@ "readme": "README.md", "storage": [ {"name":"multitimer.app.js","url":"app.js"}, - {"name":"multitimer.alarm.js","url":"alarm.js"}, + {"name":"multitimer.boot.js","url":"boot.js"}, + {"name":"multitimer.ext.js","url":"ext.js"}, {"name":"multitimer.img","url":"app-icon.js","evaluate":true} ], "data": [{"name":"multitimer.json"}], diff --git a/apps/sched/sched.js b/apps/sched/sched.js index 6eea4add5..9b5bb149c 100644 --- a/apps/sched/sched.js +++ b/apps/sched/sched.js @@ -24,45 +24,57 @@ function showAlarm(alarm) { Bangle.drawWidgets(); let buzzCount = settings.buzzCount; + let showPrompt = true; - E.showPrompt(message, { - title: alarm.timer ? /*LANG*/"TIMER!" : /*LANG*/"ALARM!", - buttons: { /*LANG*/"Snooze": true, /*LANG*/"Stop": false } // default is sleep so it'll come back in some mins - }).then(function (sleep) { - buzzCount = 0; - - if (sleep) { - if (alarm.ot === undefined) { - alarm.ot = alarm.t; - } - alarm.t += settings.defaultSnoozeMillis; - Bangle.emit("alarmSnooze", alarm); - } else { - let del = alarm.del === undefined ? settings.defaultDeleteExpiredTimers : alarm.del; - if (del) { - if (alarmIndex >= 0) alarms.splice(alarmIndex, 1); - } else { - if (alarm.date && alarm.rp) { - setNextRepeatDate(alarm); - } 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; - } - } - Bangle.emit("alarmDismiss", alarm); + if (alarm.triggercheck) { + try { + const action = eval(alarm.triggercheck); + if (action === "skipPrompt") + showPrompt = false; + } catch (e) { + // ignore errors, continue } + } + if (showPrompt) { + E.showPrompt(message, { + title: alarm.timer ? /*LANG*/"TIMER!" : /*LANG*/"ALARM!", + buttons: { /*LANG*/"Snooze": true, /*LANG*/"Stop": false } // default is sleep so it'll come back in some mins + }).then(function (sleep) { + buzzCount = 0; - // The updated alarm is still a member of 'alarms' - // so writing to array writes changes back directly - require("sched").setAlarms(alarms); - load(); - }); + if (sleep) { + if (alarm.ot === undefined) { + alarm.ot = alarm.t; + } + alarm.t += settings.defaultSnoozeMillis; + Bangle.emit("alarmSnooze", alarm); + } else { + let del = alarm.del === undefined ? settings.defaultDeleteExpiredTimers : alarm.del; + if (del) { + if (alarmIndex >= 0) alarms.splice(alarmIndex, 1); + } else { + if (alarm.date && alarm.rp) { + setNextRepeatDate(alarm); + } 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; + } + } + Bangle.emit("alarmDismiss", alarm); + } + + // The updated 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) { @@ -102,7 +114,7 @@ function showAlarm(alarm) { date = new Date(date.getFullYear() + rp.num, date.getMonth(), alarm.od); if (date.getDate() != alarm.od) date.setDate(0); break; - default: + default: console.log(`sched: unknown repeat '${JSON.stringify(rp)}'`); break; } diff --git a/typescript/types/sched.d.ts b/typescript/types/sched.d.ts index 78ad0c8d4..f12e425db 100644 --- a/typescript/types/sched.d.ts +++ b/typescript/types/sched.d.ts @@ -65,6 +65,10 @@ declare module Sched { js?: string, data?: unknown, + // optional features + triggercheck?: string, // code that's eval'd when the alarm is triggered, + // may return "skipPrompt" to cancel the default behaviour + // set by sched last?: number, } & ( From 8a63039b4661b46c8787380bb792893fc77d19e2 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sun, 11 Jun 2023 19:29:54 +0100 Subject: [PATCH 07/17] multitimer/sched: version bump --- apps/multitimer/ChangeLog | 2 +- apps/sched/ChangeLog | 1 + apps/sched/metadata.json | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/multitimer/ChangeLog b/apps/multitimer/ChangeLog index 3100146e9..252d8a227 100644 --- a/apps/multitimer/ChangeLog +++ b/apps/multitimer/ChangeLog @@ -1,4 +1,4 @@ 0.01: Initial version 0.02: Update for time_utils module 0.03: Use default Bangle formatter for booleans -0.04: Merge in alarm app's newer changes: +0.04: Use sched's triggercheck to run hardmode, and listeners for timer reset diff --git a/apps/sched/ChangeLog b/apps/sched/ChangeLog index 92b04fb32..951f4e2cc 100644 --- a/apps/sched/ChangeLog +++ b/apps/sched/ChangeLog @@ -23,3 +23,4 @@ 0.20: Alarm dismiss and snooze events 0.21: Fix crash in clock_info 0.22: Dated event repeat option +0.23: Allow alarms to run custom code (and disable the default prompt) when triggered diff --git a/apps/sched/metadata.json b/apps/sched/metadata.json index aa286ce6a..7f94a0a18 100644 --- a/apps/sched/metadata.json +++ b/apps/sched/metadata.json @@ -1,7 +1,7 @@ { "id": "sched", "name": "Scheduler", - "version": "0.22", + "version": "0.23", "description": "Scheduling library for alarms and timers", "icon": "app.png", "type": "scheduler", From b61ede2ba86ece92fbb80bd9e356c5c59ca6d332 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Fri, 30 Jun 2023 12:20:00 +0100 Subject: [PATCH 08/17] multitimer: remove unused code --- apps/multitimer/app.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/multitimer/app.js b/apps/multitimer/app.js index c3b9aa629..251ef8d90 100644 --- a/apps/multitimer/app.js +++ b/apps/multitimer/app.js @@ -596,8 +596,6 @@ function editAlarm(idx, a) { var menu = { "": { "title": "Alarm" }, "< Back": () => { - if (a.data.hm) a.js = "(require('Storage').read('multitimer.alarm.js') !== undefined) ? load('multitimer.alarm.js') : load('sched.js')"; - else if (a.js) delete a.js; if (idx >= 0) alarms[alarmIdx[idx]] = a; else alarms.push(a); require("sched").setAlarms(alarms); From 01992960b97162ca6c1fc19473245469fb38f589 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Fri, 30 Jun 2023 12:20:14 +0100 Subject: [PATCH 09/17] multitimer: update hardmode --- apps/multitimer/app.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/multitimer/app.js b/apps/multitimer/app.js index 251ef8d90..adf85f05a 100644 --- a/apps/multitimer/app.js +++ b/apps/multitimer/app.js @@ -303,6 +303,7 @@ function editTimer(idx, a) { a.triggercheck = triggercheck; else delete a.triggercheck; + a.data.hm = v; }, }, "Vibrate": require("buzz_menu").pattern(a.vibrate, v => a.vibrate = v), @@ -635,6 +636,7 @@ function editAlarm(idx, a) { a.triggercheck = triggercheck; else delete a.triggercheck; + a.data.hm = v; }, }, "Vibrate": require("buzz_menu").pattern(a.vibrate, v => a.vibrate = v), From b47c3a6c8308e18171d9c17c1e4632e4c93f7695 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Fri, 30 Jun 2023 12:20:29 +0100 Subject: [PATCH 10/17] multitimer: update menu title for `del` --- 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 adf85f05a..73b1dec2e 100644 --- a/apps/multitimer/app.js +++ b/apps/multitimer/app.js @@ -307,7 +307,7 @@ function editTimer(idx, a) { }, }, "Vibrate": require("buzz_menu").pattern(a.vibrate, v => a.vibrate = v), - "Oneshot": { + "Delete After Expiration": { value: !!a.del, onchange: v => a.del = v }, @@ -640,7 +640,7 @@ function editAlarm(idx, a) { }, }, "Vibrate": require("buzz_menu").pattern(a.vibrate, v => a.vibrate = v), - "Oneshot": { + "Delete After Expiration": { value: !!a.del, onchange: v => a.del = v }, From c930936b39d0c157cada21c55d622c377e11ddd5 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Fri, 30 Jun 2023 18:09:11 +0100 Subject: [PATCH 11/17] sched: drop alarm index guard --- apps/sched/sched.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sched/sched.js b/apps/sched/sched.js index 9b5bb149c..eac91c1c3 100644 --- a/apps/sched/sched.js +++ b/apps/sched/sched.js @@ -51,7 +51,7 @@ function showAlarm(alarm) { } else { let del = alarm.del === undefined ? settings.defaultDeleteExpiredTimers : alarm.del; if (del) { - if (alarmIndex >= 0) alarms.splice(alarmIndex, 1); + alarms.splice(alarmIndex, 1); } else { if (alarm.date && alarm.rp) { setNextRepeatDate(alarm); From 27bf21466ac97452beb0ab61358744da6a206ab1 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Fri, 30 Jun 2023 18:47:20 +0100 Subject: [PATCH 12/17] multitimer: revert triggercheck, tailcall sched after hardmode alarms --- apps/multitimer/{ext.js => alarm.js} | 21 ++++++- apps/multitimer/app.js | 28 ++++------ apps/multitimer/metadata.json | 2 +- apps/sched/sched.js | 82 ++++++++++++---------------- 4 files changed, 68 insertions(+), 65 deletions(-) rename apps/multitimer/{ext.js => alarm.js} (72%) diff --git a/apps/multitimer/ext.js b/apps/multitimer/alarm.js similarity index 72% rename from apps/multitimer/ext.js rename to apps/multitimer/alarm.js index 6e29e737d..1fbcc7955 100644 --- a/apps/multitimer/ext.js +++ b/apps/multitimer/alarm.js @@ -1,4 +1,4 @@ -// called by alarm.triggercheck +// called by getActiveAlarms(...)[0].js function hardMode(tries, max) { var R = Bangle.appRect; @@ -62,3 +62,22 @@ function startHM() { //between 5-8 random swipes hardMode(0, Math.abs(E.hwRand()%4)+5); } + +function buzz() { + let buzzCount = 3 * require("sched").getSettings().buzzCount; + + 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); + } + }); +} + +let alarms = require("sched").getAlarms(); +let active = require("sched").getActiveAlarms(alarms); +// active[0] is a HM alarm (otherwise we'd have triggered sched.js instead of this file) +startHM(); +buzz(); diff --git a/apps/multitimer/app.js b/apps/multitimer/app.js index 73b1dec2e..d5173a8ef 100644 --- a/apps/multitimer/app.js +++ b/apps/multitimer/app.js @@ -63,6 +63,14 @@ function clearInt() { timerInt2 = []; } +function setHM(alarm, on) { + if (on) + alarm.js = "(require('Storage').read('multitimer.alarm.js') !== undefined) ? load('multitimer.alarm.js') : load('sched.js')"; + else + delete alarm.js; + alarm.data.hm = on; +} + function drawTimers() { layer = 0; var timers = require("sched").getAlarms().filter(a => a.timer && a.appid == "multitimer"); @@ -297,14 +305,8 @@ function editTimer(idx, a) { } }, "Hard Mode": { - value: !!a.triggercheck, - onchange: v => { - if (v) - a.triggercheck = triggercheck; - else - delete a.triggercheck; - a.data.hm = v; - }, + value: a.data.hm, + onchange: v => setHM(a, v), }, "Vibrate": require("buzz_menu").pattern(a.vibrate, v => a.vibrate = v), "Delete After Expiration": { @@ -630,14 +632,8 @@ function editAlarm(idx, a) { onchange: () => editDOW(a.dow, d=>{a.dow=d;editAlarm(idx,a);}) }, "Hard Mode": { - value: !!a.triggercheck, - onchange: v => { - if (v) - a.triggercheck = triggercheck; - else - delete a.triggercheck; - a.data.hm = v; - }, + value: a.data.hm, + onchange: v => setHM(a, v), }, "Vibrate": require("buzz_menu").pattern(a.vibrate, v => a.vibrate = v), "Delete After Expiration": { diff --git a/apps/multitimer/metadata.json b/apps/multitimer/metadata.json index 6ae92fbdc..7a23052c9 100644 --- a/apps/multitimer/metadata.json +++ b/apps/multitimer/metadata.json @@ -15,7 +15,7 @@ "storage": [ {"name":"multitimer.app.js","url":"app.js"}, {"name":"multitimer.boot.js","url":"boot.js"}, - {"name":"multitimer.ext.js","url":"ext.js"}, + {"name":"multitimer.alarm.js","url":"alarm.js"}, {"name":"multitimer.img","url":"app-icon.js","evaluate":true} ], "data": [{"name":"multitimer.json"}], diff --git a/apps/sched/sched.js b/apps/sched/sched.js index eac91c1c3..bd84c3e47 100644 --- a/apps/sched/sched.js +++ b/apps/sched/sched.js @@ -24,57 +24,45 @@ function showAlarm(alarm) { Bangle.drawWidgets(); let buzzCount = settings.buzzCount; - let showPrompt = true; - if (alarm.triggercheck) { - try { - const action = eval(alarm.triggercheck); - if (action === "skipPrompt") - showPrompt = false; - } catch (e) { - // ignore errors, continue - } - } - if (showPrompt) { - E.showPrompt(message, { - title: alarm.timer ? /*LANG*/"TIMER!" : /*LANG*/"ALARM!", - buttons: { /*LANG*/"Snooze": true, /*LANG*/"Stop": false } // default is sleep so it'll come back in some mins - }).then(function (sleep) { - buzzCount = 0; + E.showPrompt(message, { + title: alarm.timer ? /*LANG*/"TIMER!" : /*LANG*/"ALARM!", + buttons: { /*LANG*/"Snooze": true, /*LANG*/"Stop": false } // default is sleep so it'll come back in some mins + }).then(function (sleep) { + buzzCount = 0; - if (sleep) { - if (alarm.ot === undefined) { - alarm.ot = alarm.t; - } - alarm.t += settings.defaultSnoozeMillis; - Bangle.emit("alarmSnooze", alarm); - } else { - let del = alarm.del === undefined ? settings.defaultDeleteExpiredTimers : alarm.del; - if (del) { - alarms.splice(alarmIndex, 1); - } else { - if (alarm.date && alarm.rp) { - setNextRepeatDate(alarm); - } 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; - } - } - Bangle.emit("alarmDismiss", alarm); + if (sleep) { + if (alarm.ot === undefined) { + alarm.ot = alarm.t; } + alarm.t += settings.defaultSnoozeMillis; + Bangle.emit("alarmSnooze", alarm); + } else { + let del = alarm.del === undefined ? settings.defaultDeleteExpiredTimers : alarm.del; + if (del) { + alarms.splice(alarmIndex, 1); + } else { + if (alarm.date && alarm.rp) { + setNextRepeatDate(alarm); + } 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; + } + } + Bangle.emit("alarmDismiss", alarm); + } - // The updated alarm is still a member of 'alarms' - // so writing to array writes changes back directly - require("sched").setAlarms(alarms); - load(); - }); - } + // The updated 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 887acfe346a732263ba2954be007999e836d0c0e Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Fri, 30 Jun 2023 21:03:34 +0100 Subject: [PATCH 13/17] multitimer: changelog update --- apps/multitimer/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/multitimer/ChangeLog b/apps/multitimer/ChangeLog index 252d8a227..842384c8d 100644 --- a/apps/multitimer/ChangeLog +++ b/apps/multitimer/ChangeLog @@ -1,4 +1,4 @@ 0.01: Initial version 0.02: Update for time_utils module 0.03: Use default Bangle formatter for booleans -0.04: Use sched's triggercheck to run hardmode, and listeners for timer reset +0.04: Remove copied sched alarm.js & import newer features (oneshot alarms) From 56401ea1831888e106681a4f1414852ad1738fb7 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Fri, 30 Jun 2023 21:04:20 +0100 Subject: [PATCH 14/17] multitimer: fix `settings` & `alarm` scope --- apps/multitimer/alarm.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/multitimer/alarm.js b/apps/multitimer/alarm.js index 1fbcc7955..389f8a873 100644 --- a/apps/multitimer/alarm.js +++ b/apps/multitimer/alarm.js @@ -64,7 +64,8 @@ function startHM() { } function buzz() { - let buzzCount = 3 * require("sched").getSettings().buzzCount; + const settings = require("sched").getSettings(); + let buzzCount = 3 * settings.buzzCount; require("buzz").pattern(alarm.vibrate === undefined ? "::" : alarm.vibrate).then(() => { if (buzzCount--) { @@ -78,6 +79,7 @@ function buzz() { let alarms = require("sched").getAlarms(); let active = require("sched").getActiveAlarms(alarms); +let alarm = active[0]; // active[0] is a HM alarm (otherwise we'd have triggered sched.js instead of this file) startHM(); buzz(); From 03a0c5264dbd0b1acd7a7adb81266f2c27f5068d Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Fri, 30 Jun 2023 21:04:31 +0100 Subject: [PATCH 15/17] multitimer: disable sched on load --- apps/multitimer/alarm.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/multitimer/alarm.js b/apps/multitimer/alarm.js index 389f8a873..b202ae662 100644 --- a/apps/multitimer/alarm.js +++ b/apps/multitimer/alarm.js @@ -1,4 +1,8 @@ // called by getActiveAlarms(...)[0].js +if (Bangle.SCHED) { + clearInterval(Bangle.SCHED); + delete Bangle.SCHED; +} function hardMode(tries, max) { var R = Bangle.appRect; From 8cf0782d936c81e086760124a007ef9483d8aee9 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Fri, 30 Jun 2023 21:05:32 +0100 Subject: [PATCH 16/17] multitimer: reset alarm's last sounding time when enabling --- apps/multitimer/app.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/apps/multitimer/app.js b/apps/multitimer/app.js index d5173a8ef..e133820b0 100644 --- a/apps/multitimer/app.js +++ b/apps/multitimer/app.js @@ -281,7 +281,10 @@ function editTimer(idx, a) { }, "Enabled": { value: a.on, - onchange: v => a.on = v + onchange: v => { + delete a.last; + a.on = v; + } }, "Hours": { value: t.hrs, min: 0, max: 23, wrap: true, @@ -607,7 +610,10 @@ function editAlarm(idx, a) { }, "Enabled": { value: a.on, - onchange: v => a.on = v + onchange: v => { + delete a.last; + a.on = v; + } }, "Hours": { value: t.hrs, min: 0, max: 23, wrap: true, From b2e74d91e3bdbd5555a0b70d3cab5ce19566e522 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Fri, 30 Jun 2023 21:13:31 +0100 Subject: [PATCH 17/17] multitimer: readme update, remove dead code, restore sched --- apps/multitimer/README.md | 2 +- apps/multitimer/app.js | 7 ------- apps/multitimer/boot.js | 10 +++++----- apps/sched/ChangeLog | 1 - apps/sched/metadata.json | 2 +- typescript/types/sched.d.ts | 4 ---- 6 files changed, 7 insertions(+), 19 deletions(-) diff --git a/apps/multitimer/README.md b/apps/multitimer/README.md index cbbe5c92c..04bdf4a6e 100644 --- a/apps/multitimer/README.md +++ b/apps/multitimer/README.md @@ -2,7 +2,7 @@ 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. -"Oneshot" can be set on timers and alarms to have it delete itself once it's sounded (uses the "Delete after expiration" setting from the alarm app). +"Delete after expiration" can be set on a timer/alarm to have it delete itself once it's sounded (the same as the alarm app). ## WARNING * Editing timers in another app (such as the default Alarm app) is not recommended. Editing alarms should not be a problem (in theory). diff --git a/apps/multitimer/app.js b/apps/multitimer/app.js index e133820b0..ae8647db0 100644 --- a/apps/multitimer/app.js +++ b/apps/multitimer/app.js @@ -1,13 +1,6 @@ Bangle.loadWidgets(); Bangle.drawWidgets(); -const triggercheck = ` - eval(require("Storage").read("multitimer.ext.js")); - buzzCount *= 3; - startHM(); - "skipPrompt" -`; - var R = Bangle.appRect; var layer; var drag; diff --git a/apps/multitimer/boot.js b/apps/multitimer/boot.js index 13f1d6363..70b9032f6 100644 --- a/apps/multitimer/boot.js +++ b/apps/multitimer/boot.js @@ -1,8 +1,8 @@ { - const resetTimer = alarm => { - if (alarm.timer) alarm.timer = alarm.data.ot; - }; + const resetTimer = alarm => { + if (alarm.timer) alarm.timer = alarm.data.ot; + }; - Bangle.on("alarmSnooze", resetTimer); - Bangle.on("alarmDismiss", resetTimer); + Bangle.on("alarmSnooze", resetTimer); + Bangle.on("alarmDismiss", resetTimer); } diff --git a/apps/sched/ChangeLog b/apps/sched/ChangeLog index 951f4e2cc..92b04fb32 100644 --- a/apps/sched/ChangeLog +++ b/apps/sched/ChangeLog @@ -23,4 +23,3 @@ 0.20: Alarm dismiss and snooze events 0.21: Fix crash in clock_info 0.22: Dated event repeat option -0.23: Allow alarms to run custom code (and disable the default prompt) when triggered diff --git a/apps/sched/metadata.json b/apps/sched/metadata.json index 7f94a0a18..aa286ce6a 100644 --- a/apps/sched/metadata.json +++ b/apps/sched/metadata.json @@ -1,7 +1,7 @@ { "id": "sched", "name": "Scheduler", - "version": "0.23", + "version": "0.22", "description": "Scheduling library for alarms and timers", "icon": "app.png", "type": "scheduler", diff --git a/typescript/types/sched.d.ts b/typescript/types/sched.d.ts index f12e425db..78ad0c8d4 100644 --- a/typescript/types/sched.d.ts +++ b/typescript/types/sched.d.ts @@ -65,10 +65,6 @@ declare module Sched { js?: string, data?: unknown, - // optional features - triggercheck?: string, // code that's eval'd when the alarm is triggered, - // may return "skipPrompt" to cancel the default behaviour - // set by sched last?: number, } & (