diff --git a/apps.json b/apps.json index b0c91f619..8f0ace1d3 100644 --- a/apps.json +++ b/apps.json @@ -3059,5 +3059,23 @@ {"name":"waypoints.json","url":"waypoints.json","evaluate":false}, {"name":"kitchen.img","url":"kitchen.icon.js","evaluate":true} ] -} +}, + { "id": "qmsched", + "name": "Quiet Mode Schedule", + "shortName":"Quiet Mode", + "icon": "app.png", + "version":"0.01", + "description": "Automatically turn Quiet Mode on or off at set times", + "readme": "README.md", + "tags": "tool", + "storage": [ + {"name":"qmsched","url":"lib.js"}, + {"name":"qmsched.app.js","url":"app.js"}, + {"name":"qmsched.boot.js","url":"boot.js"}, + {"name":"qmsched.img","url":"icon.js","evaluate":true} + ], + "data": [ + {"name":"qmsched.json"} + ] + } ] diff --git a/apps/qmsched/ChangeLog b/apps/qmsched/ChangeLog new file mode 100644 index 000000000..7f837e50e --- /dev/null +++ b/apps/qmsched/ChangeLog @@ -0,0 +1 @@ +0.01: First version diff --git a/apps/qmsched/README.md b/apps/qmsched/README.md new file mode 100644 index 000000000..1ccddbf8c --- /dev/null +++ b/apps/qmsched/README.md @@ -0,0 +1,5 @@ +# Quiet Mode Schedule + +Automatically turn Quiet Mode on or off at set times. + +![Main menu](screenshot_main.png) ![Edit Schedule menu](screenshot_edit.png) diff --git a/apps/qmsched/app.js b/apps/qmsched/app.js new file mode 100644 index 000000000..7761be31c --- /dev/null +++ b/apps/qmsched/app.js @@ -0,0 +1,133 @@ +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +const modeNames = ["Off", "Alarms", "Silent"]; +let scheds = require("Storage").readJSON("qmsched.json", 1); +/*scheds = [ + { hr : 6.5, // hours + minutes/60 + last : 0, // last day of the month we fired on - so we don't switch twice in one day! + mode : 1, // quiet mode (0/1/2) + } +];*/ +if (!scheds) { + // set default schedule on first load of app + scheds = [ + {"hr": 8, "mode": 0, "last": 25}, + {"hr": 22, "mode": 1, "last": 25}, + ]; + require("Storage").writeJSON("qmsched.json", scheds); +} + +function formatTime(t) { + const hrs = 0|t; + const mins = Math.round((t-hrs)*60); + return (" "+hrs).substr(-2)+":"+("0"+mins).substr(-2); +} + +function getCurrentHr() { + const time = new Date(); + return time.getHours()+(time.getMinutes()/60)+(time.getSeconds()/3600); +} + +function showMainMenu() { + const menu = { + "": {"title": "Quiet Mode"}, + "Current Mode": { + value: (require("Storage").readJSON("setting.json", 1) || {}).quiet|0, + format: v => modeNames[v], + onchange: function(v) { + if (v<0) v = 2; + if (v>2) v = 0; + require("qmsched").setMode(v); + this.value = v; + }, + }, + }; + scheds.sort((a, b) => (a.hr-b.hr)); + scheds.forEach((sched, idx) => { + const name = modeNames[sched.mode]; + const txt = formatTime(sched.hr)+" ".repeat(14-name.length)+name; + menu[txt] = function() { + showEditMenu(idx); + }; + }); + menu["Add Schedule"] = () => showEditMenu(-1); + menu["< Back"] = () => {load();}; + return E.showMenu(menu); +} + +function showEditMenu(index) { + const isNew = index<0; + let hrs = 12, mins = 0; + let mode = 1; + if (!isNew) { + const s = scheds[index]; + hrs = 0|s.hr; + mins = Math.round((s.hr-hrs)*60); + mode = s.mode; + } + const menu = { + "": {"title": (isNew ? "Add" : "Edit")+" Schedule"}, + "Hours": { + value: hrs, + onchange: function(v) { + if (v<0) v = 23; + if (v>23) v = 0; + hrs = v; + this.value = v; + }, // no arrow fn -> preserve 'this' + }, + "Minutes": { + value: mins, + onchange: function(v) { + if (v<0) v = 59; + if (v>59) v = 0; + mins = v; + this.value = v; + }, // no arrow fn -> preserve 'this' + }, + "Switch to": { + value: mode, + format: v => modeNames[v], + onchange: function(v) { + if (v<0) v = 2; + if (v>2) v = 0; + mode = v; + this.value = v; + }, // no arrow fn -> preserve 'this' + }, + }; + function getSched() { + const hr = hrs+(mins/60); + let day = 0; + // If schedule is for tomorrow not today (eg, in the past), set day + if (hr Save"] = function() { + if (isNew) { + scheds.push(getSched()); + } else { + scheds[index] = getSched(); + } + require("Storage").writeJSON("qmsched.json", scheds); + showMainMenu(); + }; + if (!isNew) { + menu["> Delete"] = function() { + scheds.splice(index, 1); + require("Storage").writeJSON("qmsched.json", scheds); + showMainMenu(); + }; + } + menu["< Cancel"] = showMainMenu; + return E.showMenu(menu); +} + +showMainMenu(); diff --git a/apps/qmsched/app.png b/apps/qmsched/app.png new file mode 100644 index 000000000..cf1fc29bc Binary files /dev/null and b/apps/qmsched/app.png differ diff --git a/apps/qmsched/boot.js b/apps/qmsched/boot.js new file mode 100644 index 000000000..3c53ef3f7 --- /dev/null +++ b/apps/qmsched/boot.js @@ -0,0 +1,24 @@ +// apply Quiet Mode schedules +(function qm() { + let scheds = require("Storage").readJSON("qmsched.json", 1) || []; + if (!scheds.length) return; + let next,idx; + scheds.forEach(function(s, i) { + if (!next || (s.hr+s.last*24)<(next.hr+next.last*24)) { + next = s; + idx = i; + } + }); + const now = new Date(), + hr = now.getHours()+(now.getMinutes()/60)+(now.getSeconds()/3600); + let t = 3600000*(next.hr-hr); + if (next.last===now.getDate()) t += 86400000; + /* update quiet mode at the correct time. */ + setTimeout(function() { + let scheds = require("Storage").readJSON("qmsched.json", 1) || []; + require("qmsched").setMode(scheds[idx].mode); + scheds[idx].last = (new Date()).getDate(); + require("Storage").writeJSON("qmsched.json", scheds); + qm(); // schedule next update + }, t); +})(); diff --git a/apps/qmsched/icon.js b/apps/qmsched/icon.js new file mode 100644 index 000000000..c0f4e2b66 --- /dev/null +++ b/apps/qmsched/icon.js @@ -0,0 +1,2 @@ +// https://icons8.com/icon/19324/no-reminders +require("heatshrink").decompress(atob("mEwxH+AH4A/AH4AElksF1wwtF4YwO0WiGFguBGFovfGB3MAAgwnFooxfGBAuJGEguLGEV/F5owh0YvpGH4vhGCQvd0YwQF7vMGCAveGCAvfGB4vgGBwvhGBouhGFLkIGEouIGEwvKGBguiGEQuNGEHN5owa5ouQ53P5/O5wyOGA3NDAIbBLyAUCAAQzCNBQwF0gVDXiQoBGQgAEEIILE0iSJdiozCFQw1FGBJgSABSVIeg7wQGSDDMFyQ0VCQQwdAAWcAAwPHGD4vPGD+iAAwRJGEgRLGEQRNeTwARF1wA/AH4AX")) \ No newline at end of file diff --git a/apps/qmsched/lib.js b/apps/qmsched/lib.js new file mode 100644 index 000000000..6cdf4f181 --- /dev/null +++ b/apps/qmsched/lib.js @@ -0,0 +1,17 @@ +/** + * Set new Quiet Mode and apply Bangle options + * @param {int} mode Quiet Mode + */ +exports.setMode = function(mode) { + let s = require("Storage").readJSON("setting.json", 1) || {}; + s.quiet = mode; + require("Storage").writeJSON("setting.json", s); + if (s.options) Bangle.setOptions(s.options); + if (mode && s.qmOptions) Bangle.setOptions(s.qmOptions); + if (mode && s.qmBrightness) { + if (s.qmBrightness!=1) Bangle.setLCDBrightness(s.qmBrightness); + } else { + if (s.brightness && s.brightness!=1) Bangle.setLCDBrightness(s.brightness); + } + if (mode && s.qmTimeout) Bangle.setLCDTimeout(s.qmTimeout); +}; \ No newline at end of file diff --git a/apps/qmsched/screenshot_edit.png b/apps/qmsched/screenshot_edit.png new file mode 100644 index 000000000..88b7fcad4 Binary files /dev/null and b/apps/qmsched/screenshot_edit.png differ diff --git a/apps/qmsched/screenshot_main.png b/apps/qmsched/screenshot_main.png new file mode 100644 index 000000000..634abd633 Binary files /dev/null and b/apps/qmsched/screenshot_main.png differ