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 01/10] 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 02/10] 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 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 03/10] 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 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 04/10] 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 05/10] 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 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 06/10] 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 07/10] 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 08/10] 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 09/10] 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 10/10] 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();