diff --git a/.gitignore b/.gitignore index a9398e871..f4588ac6f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ tests/Layout/testresult.bmp apps.local.json _site .jekyll-cache +.owncloudsync.log +Desktop.ini +.sync_*.db* diff --git a/apps/7x7dotsclock/7x7dotsclock.app.js b/apps/7x7dotsclock/7x7dotsclock.app.js index aa174b2d2..aa6672a4f 100644 --- a/apps/7x7dotsclock/7x7dotsclock.app.js +++ b/apps/7x7dotsclock/7x7dotsclock.app.js @@ -149,11 +149,11 @@ function drawHSeg(x1,y1,x2,y2,Num,Color,Size) { if (Color == "fg") { g.setColor(g.theme.fg); } else { - g.setColor(mColor[0],mColor[1],mColor[2]); + g.setColor(mColor[0],mColor[1],mColor[2]); } g.fillCircle(x1+Dx+(i-1)*(x2-x1)/7,y1+Dy+(j-1)*(y2-y1)/7,Size); } else { - g.setColor(bColor[0],bColor[1],bColor[2]); + g.setColor(bColor[0],bColor[1],bColor[2]); g.fillCircle(x1+Dx+(i-1)*(x2-x1)/7,y1+Dy+(j-1)*(y2-y1)/7,1); } } @@ -166,7 +166,7 @@ function drawSSeg(x1,y1,x2,y2,Num,Color,Size) { for (let j = 1; j < 8; j++) { if (Font[Num][j-1][i-1] == 1) { if (Color == "fg") { - g.setColor(sColor[0],sColor[1],sColor[2]); + g.setColor(sColor[0],sColor[1],sColor[2]); } else { g.setColor(g.theme.fg); //g.setColor(0.7,0.7,0.7); @@ -253,8 +253,8 @@ function actions(v){ if(BTN1.read() === true) { print("BTN pressed"); Bangle.showLauncher(); - } - + } + if(v==-1){ print("up swipe event"); if(settings.swupApp != "") load(settings.swupApp); @@ -269,7 +269,7 @@ function actions(v){ } // Get Messages status -var messages = require("Storage").readJSON("messages.json",1)||[]; +var messages_installed = require("Storage").read("messages") !== undefined; //var BTconnected = NRF.getSecurityStatus().connected; //NRF.on('connect',BTconnected = NRF.getSecurityStatus().connected); @@ -289,27 +289,27 @@ function drawWidgeds() { g.setColor((g.getBPP()>8) ? "#07f" : (g.theme.dark ? "#0ff" : "#00f")); else g.setColor(g.theme.dark ? "#666" : "#999"); - g.drawImage(atob("CxQBBgDgFgJgR4jZMawfAcA4D4NYybEYIwTAsBwDAA=="),x1Bt,y1Bt); + g.drawImage(atob("CxQBBgDgFgJgR4jZMawfAcA4D4NYybEYIwTAsBwDAA=="),x1Bt,y1Bt); + - //Battery //print(E.getBattery()); //print(Bangle.isCharging()); - + var x1B = 130; var y1B = 2; var x2B = x1B + 20; var y2B = y1B + 15; - + g.setColor(g.theme.bg); g.clearRect(x1B,y1B,x2B,y2B); - + g.setColor(g.theme.fg); g.drawRect(x1B,y1B,x2B,y2B); g.fillRect(x1B,y1B,x1B+(E.getBattery()*(x2B-x1B)/100),y2B); g.fillRect(x2B,y1B+(y2B-y1B)/2-3,x2B+4,y1B+(y2B-y1B)/2+3); - + //Messages @@ -318,25 +318,25 @@ function drawWidgeds() { var x2M = x1M + 25; var y2M = y2B; - if (messages.some(m=>m.new)) { + if (messages_installed && require("messages").status() == "new") { g.setColor(g.theme.fg); g.fillRect(x1M,y1M,x2M,y2M); g.setColor(g.theme.bg); g.drawLine(x1M,y1M,x1M+(x2M-x1M)/2,y1M+(y2M-y1M)/2); g.drawLine(x1M+(x2M-x1M)/2,y1M+(y2M-y1M)/2,x2M,y1M); } - + var strDow = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']; var d = new Date(); var dow = d.getDay(),day = d.getDate(), month = d.getMonth() + 1, year = d.getFullYear(); print(strDow[dow] + ' ' + day + '.' + month + ' ' + year); - + g.setColor(g.theme.fg); g.setFontAlign(-1, -1,0); g.setFont("Vector", 20); g.drawString(strDow[dow] + ' ' + day, 0, 0, true); - + } @@ -354,7 +354,7 @@ function SetFull(on) { } else { Ys = 30; Bangle.setUI("updown",actions); - Bangle.on('swipe', function(direction) { + Bangle.on('swipe', function(direction) { switch (direction) { case 1: print("swipe left event"); @@ -362,7 +362,7 @@ function SetFull(on) { print(settings.swleftApp); break; case -1: - print("swipe right event"); + print("swipe right event"); if(settings.swrightApp != "") load(settings.swrightApp); print(settings.swrightApp); break; @@ -374,7 +374,7 @@ function SetFull(on) { SegH = (Ye-Ys)/2; Dy = SegH/16; - + draw(); if (on != true) { diff --git a/apps/7x7dotsclock/ChangeLog b/apps/7x7dotsclock/ChangeLog index d2c98a472..5e8e48b0b 100644 --- a/apps/7x7dotsclock/ChangeLog +++ b/apps/7x7dotsclock/ChangeLog @@ -1,2 +1,3 @@ 0.01: Initial version for upload -0.02: better theme support, configurable colors, small improvements +0.02: Better theme support, configurable colors, small improvements +0.03: Use `messages` library to check for new messages \ No newline at end of file diff --git a/apps/7x7dotsclock/metadata.json b/apps/7x7dotsclock/metadata.json index 41f0836d3..ba1996544 100644 --- a/apps/7x7dotsclock/metadata.json +++ b/apps/7x7dotsclock/metadata.json @@ -1,7 +1,7 @@ { "id": "7x7dotsclock", "name": "7x7 Dots Clock", "shortName":"7x7 Dots Clock", - "version":"0.02", + "version":"0.03", "description": "A clock with a big 7x7 dots Font", "icon": "dotsfontclock.png", "tags": "clock", diff --git a/apps/90sclk/ChangeLog b/apps/90sclk/ChangeLog index feb008f5f..057d6ff73 100644 --- a/apps/90sclk/ChangeLog +++ b/apps/90sclk/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! -0.02: Fullscreen settings. \ No newline at end of file +0.02: Fullscreen settings. +0.03: Tell clock widgets to hide. diff --git a/apps/90sclk/app.js b/apps/90sclk/app.js index 6babbfec2..351c235e0 100644 --- a/apps/90sclk/app.js +++ b/apps/90sclk/app.js @@ -115,6 +115,9 @@ function draw() { } } +// Show launcher when middle button pressed +Bangle.setUI("clock"); + Bangle.loadWidgets(); // Clear the screen once, at startup @@ -140,5 +143,3 @@ Bangle.on('lock', function(isLocked) { }); -// Show launcher when middle button pressed -Bangle.setUI("clock"); diff --git a/apps/90sclk/metadata.json b/apps/90sclk/metadata.json index fb2824a6f..59b627427 100644 --- a/apps/90sclk/metadata.json +++ b/apps/90sclk/metadata.json @@ -1,7 +1,7 @@ { "id": "90sclk", "name": "90s Clock", - "version": "0.02", + "version": "0.03", "description": "A 90s style watch-face", "readme": "README.md", "icon": "app.png", diff --git a/apps/a_dndtoggle/ChangeLog b/apps/a_dndtoggle/ChangeLog new file mode 100644 index 000000000..ec66c5568 --- /dev/null +++ b/apps/a_dndtoggle/ChangeLog @@ -0,0 +1 @@ +0.01: Initial version diff --git a/apps/a_dndtoggle/README.md b/apps/a_dndtoggle/README.md new file mode 100644 index 000000000..bd0981c5b --- /dev/null +++ b/apps/a_dndtoggle/README.md @@ -0,0 +1,13 @@ +# a_dndtoggle - Toggle Quiet Mode of the watch + +When Quiet mode is off, just start this app to set quiet mode. Start it again to turn off quiet mode. +Work in progress. + +#ToDo +Settings page, current status indicator. + +## Creator + +Hank - contact at http://forum.espruino.com + + diff --git a/apps/a_dndtoggle/a_dndtoggle.app.js b/apps/a_dndtoggle/a_dndtoggle.app.js new file mode 100644 index 000000000..c0b968f2c --- /dev/null +++ b/apps/a_dndtoggle/a_dndtoggle.app.js @@ -0,0 +1,43 @@ + +const modeNames = [/*LANG*/"Noisy", /*LANG*/"Alarms", /*LANG*/"Silent"]; +let bSettings = require('Storage').readJSON('setting.json',true)||{}; +let current = 0|bSettings.quiet; +//0 off +//1 alarms +//2 silent + +console.log("old: " + current); + +switch (current) { + case 0: + bSettings.quiet = 2; + Bangle.buzz(); + setTimeout('Bangle.buzz();',500); + break; + case 1: + bSettings.quiet = 0; + Bangle.buzz(); + break; + case 2: + bSettings.quiet = 0; + Bangle.buzz(); + break; + default: + bSettings.quiet = 0; + Bangle.buzz(); +} + +console.log("new: " + bSettings.quiet); + +E.showMessage(modeNames[current] + " -> " + modeNames[bSettings.quiet]); +setTimeout('exitApp();', 2000); + + +function exitApp(){ + +require("Storage").writeJSON("setting.json", bSettings); +// reload clocks with new theme, otherwise just wait for user to switch apps + +load() + +} \ No newline at end of file diff --git a/apps/a_dndtoggle/a_dndtoggle.png b/apps/a_dndtoggle/a_dndtoggle.png new file mode 100644 index 000000000..4c8b74c0c Binary files /dev/null and b/apps/a_dndtoggle/a_dndtoggle.png differ diff --git a/apps/a_dndtoggle/app-icon.js b/apps/a_dndtoggle/app-icon.js new file mode 100644 index 000000000..0b08cc65b --- /dev/null +++ b/apps/a_dndtoggle/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwJC/AAl/Agf/AAUAgIFDwEHAofgh/g/0Ag/wj+AnwVB/EegEfEIN4nkAh+AgE8vgVBAoV4Aoce/EAgfADQIFcjwpFHYIFCnxBFJopZBn5ZCMopxFPoqJFSowA/gA=")) \ No newline at end of file diff --git a/apps/a_dndtoggle/metadata.json b/apps/a_dndtoggle/metadata.json new file mode 100644 index 000000000..f5ae9cc31 --- /dev/null +++ b/apps/a_dndtoggle/metadata.json @@ -0,0 +1,16 @@ +{ + "id": "a_dndtoggle", + "name": "a_dndtoggle - Toggle Quiet Mode of the watch", + "shortName": "A_DND Toggle", + "version": "0.01", + "description": "Toggle Quiet Mode of the watch just by starting this app.", + "icon": "a_dndtoggle.png", + "type": "app", + "tags": "tool", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"a_dndtoggle.app.js","url":"a_dndtoggle.app.js"}, + {"name":"a_dndtoggle.img","url":"app-icon.js","evaluate":true} + ], + "readme": "README.md" +} diff --git a/apps/about/ChangeLog b/apps/about/ChangeLog index f5638fdd2..ffe9de081 100644 --- a/apps/about/ChangeLog +++ b/apps/about/ChangeLog @@ -10,3 +10,4 @@ 0.10: Added separate Bangle.js 2 file with Bangle.js 2 kickstarter pixels (as of 28 Oct 2021) 0.11: Bangle.js2: New pixels, btn1 to exit 0.12: Actual pixels as of 29th Nov 2021 +0.13: Bangle.js 2: Use setUI to add software back button diff --git a/apps/about/app-bangle2.js b/apps/about/app-bangle2.js index 978d36193..0c40314a8 100644 --- a/apps/about/app-bangle2.js +++ b/apps/about/app-bangle2.js @@ -69,4 +69,7 @@ function drawImage() { // TODO: a nice little animation before setTimeout(drawInfo, 1000); -setWatch(_=>load(), BTN1); +Bangle.setUI({ + mode : "custom", + back : load +}); diff --git a/apps/about/metadata.json b/apps/about/metadata.json index 6c22bdc56..648576576 100644 --- a/apps/about/metadata.json +++ b/apps/about/metadata.json @@ -1,7 +1,7 @@ { "id": "about", "name": "About", - "version": "0.12", + "version": "0.13", "description": "Bangle.js About page - showing software version, stats, and a collaborative mural from the Bangle.js KickStarter backers", "icon": "app.png", "tags": "tool,system", diff --git a/apps/activityreminder/ChangeLog b/apps/activityreminder/ChangeLog index 37820dce6..3811425ac 100644 --- a/apps/activityreminder/ChangeLog +++ b/apps/activityreminder/ChangeLog @@ -6,3 +6,5 @@ 0.06: Add a temperature threshold to detect (and not alert) if the BJS isn't worn. Better support for the peoples using the app at night 0.07: Fix bug on the cutting edge firmware 0.08: Use default Bangle formatter for booleans +0.09: New app screen (instead of showing settings or the alert) and some optimisations +0.10: Add software back button via setUI diff --git a/apps/activityreminder/alert.js b/apps/activityreminder/alert.js new file mode 100644 index 000000000..96a9b76c4 --- /dev/null +++ b/apps/activityreminder/alert.js @@ -0,0 +1,37 @@ +(function () { + // load variable before defining functions cause it can trigger a ReferenceError + const activityreminder = require("activityreminder"); + const storage = require("Storage"); + let activityreminder_data = activityreminder.loadData(); + + function run() { + E.showPrompt("Inactivity detected", { + title: "Activity reminder", + buttons: { "Ok": 1, "Dismiss": 2, "Pause": 3 } + }).then(function (v) { + if (v == 1) { + activityreminder_data.okDate = new Date(); + } + if (v == 2) { + activityreminder_data.dismissDate = new Date(); + } + if (v == 3) { + activityreminder_data.pauseDate = new Date(); + } + activityreminder.saveData(activityreminder_data); + load(); + }); + + // Obey system quiet mode: + if (!(storage.readJSON('setting.json', 1) || {}).quiet) { + Bangle.buzz(400); + } + setTimeout(load, 20000); + } + + g.clear(); + Bangle.loadWidgets(); + Bangle.drawWidgets(); + run(); + +})(); \ No newline at end of file diff --git a/apps/activityreminder/app.js b/apps/activityreminder/app.js index c2b626fb3..81e10d8dd 100644 --- a/apps/activityreminder/app.js +++ b/apps/activityreminder/app.js @@ -1,46 +1,58 @@ (function () { - // load variable before defining functions cause it can trigger a ReferenceError - const activityreminder = require("activityreminder"); - const storage = require("Storage"); - const activityreminder_settings = activityreminder.loadSettings(); - let activityreminder_data = activityreminder.loadData(); + // load variable before defining functions cause it can trigger a ReferenceError + const activityreminder = require("activityreminder"); + let activityreminder_data = activityreminder.loadData(); + let W = g.getWidth(); + // let H = g.getHeight(); - function drawAlert() { - E.showPrompt("Inactivity detected", { - title: "Activity reminder", - buttons: { "Ok": 1, "Dismiss": 2, "Pause": 3 } - }).then(function (v) { - if (v == 1) { - activityreminder_data.okDate = new Date(); - } - if (v == 2) { - activityreminder_data.dismissDate = new Date(); - } - if (v == 3) { - activityreminder_data.pauseDate = new Date(); - } - activityreminder.saveData(activityreminder_data); - load(); - }); - - // Obey system quiet mode: - if (!(storage.readJSON('setting.json', 1) || {}).quiet) { - Bangle.buzz(400); - } - setTimeout(load, 20000); - } - - function run() { - if (activityreminder.mustAlert(activityreminder_data, activityreminder_settings)) { - drawAlert(); - } else { - eval(storage.read("activityreminder.settings.js"))(() => load()); - } - } + function getHoursMins(date){ + var h = date.getHours(); + var m = date.getMinutes(); + return (""+h).substr(-2) + ":" + ("0"+m).substr(-2); + } + function drawData(name, value, y){ + g.drawString(name, 10, y); + g.drawString(value, 100, y); + } + + function drawInfo() { + var h=18, y = h; + g.setColor(g.theme.fg); + g.setFont("Vector",h).setFontAlign(-1,-1); + + // Header + g.drawLine(0,25,W,25); + g.drawLine(0,26,W,26); + + g.drawString("Current Cycle", 10, y+=h); + drawData("Start", getHoursMins(activityreminder_data.stepsDate), y+=h); + drawData("Steps", getCurrentSteps(), y+=h); + + /* + g.drawString("Button Press", 10, y+=h*2); + drawData("Ok", getHoursMins(activityreminder_data.okDate), y+=h); + drawData("Dismiss", getHoursMins(activityreminder_data.dismissDate), y+=h); + drawData("Pause", getHoursMins(activityreminder_data.pauseDate), y+=h); + */ + } + + function getCurrentSteps(){ + let health = Bangle.getHealthStatus("day"); + return health.steps - activityreminder_data.stepsOnDate; + } + + function run() { g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); - run(); - -})(); \ No newline at end of file + drawInfo(); + Bangle.setUI({ + mode : "custom", + back : load + }) + } + + run(); + +})(); diff --git a/apps/activityreminder/boot.js b/apps/activityreminder/boot.js index f97cf274d..5a11d73b8 100644 --- a/apps/activityreminder/boot.js +++ b/apps/activityreminder/boot.js @@ -1,70 +1,81 @@ (function () { - // load variable before defining functions cause it can trigger a ReferenceError - const activityreminder = require("activityreminder"); - const activityreminder_settings = activityreminder.loadSettings(); - let activityreminder_data = activityreminder.loadData(); - - if (activityreminder_data.firstLoad) { - activityreminder_data.firstLoad = false; + // load variable before defining functions cause it can trigger a ReferenceError + const activityreminder = require("activityreminder"); + const activityreminder_settings = activityreminder.loadSettings(); + let activityreminder_data = activityreminder.loadData(); + + if (activityreminder_data.firstLoad) { + activityreminder_data.firstLoad = false; + activityreminder.saveData(activityreminder_data); + } + + function run() { + if (isNotWorn()) return; + let now = new Date(); + let h = now.getHours(); + + if (isDuringAlertHours(h)) { + let health = Bangle.getHealthStatus("day"); + if (health.steps - activityreminder_data.stepsOnDate >= activityreminder_settings.minSteps // more steps made than needed + || health.steps < activityreminder_data.stepsOnDate) { // new day or reboot of the watch + activityreminder_data.stepsOnDate = health.steps; + activityreminder_data.stepsDate = now; activityreminder.saveData(activityreminder_data); - } - - function run() { - if (isNotWorn()) return; - let now = new Date(); - let h = now.getHours(); - - if (isDuringAlertHours(h)) { - let health = Bangle.getHealthStatus("day"); - if (health.steps - activityreminder_data.stepsOnDate >= activityreminder_settings.minSteps // more steps made than needed - || health.steps < activityreminder_data.stepsOnDate) { // new day or reboot of the watch - activityreminder_data.stepsOnDate = health.steps; - activityreminder_data.stepsDate = now; - activityreminder.saveData(activityreminder_data); - /* todo in a futur release - Add settimer to trigger like 30 secs after going in this part cause the person have been walking - (pass some argument to run() to handle long walks and not triggering so often) - */ - } - - if (activityreminder.mustAlert(activityreminder_data, activityreminder_settings)) { - load('activityreminder.app.js'); - } - } - - } - - function isNotWorn() { - return (Bangle.isCharging() || activityreminder_settings.tempThreshold >= E.getTemperature()); - } - - function isDuringAlertHours(h) { - if (activityreminder_settings.startHour < activityreminder_settings.endHour) { // not passing through midnight - return (h >= activityreminder_settings.startHour && h < activityreminder_settings.endHour); - } else { // passing through midnight - return (h >= activityreminder_settings.startHour || h < activityreminder_settings.endHour); - } - } - - Bangle.on('midnight', function () { - /* - Usefull trick to have the app working smothly for people using it at night - */ - let now = new Date(); - let h = now.getHours(); - if (activityreminder_settings.enabled && isDuringAlertHours(h)) { - // updating only the steps and keeping the original stepsDate on purpose - activityreminder_data.stepsOnDate = 0; - activityreminder.saveData(activityreminder_data); - } - }); - - - if (activityreminder_settings.enabled) { - setInterval(run, 60000); /* todo in a futur release - increase setInterval time to something that is still sensible (5 mins ?) - when we added a settimer + Add settimer to trigger like 30 secs after going in this part cause the person have been walking + (pass some argument to run() to handle long walks and not triggering so often) */ + } + + if (mustAlert(now)) { + load('activityreminder.alert.js'); + } } + + } + + function isNotWorn() { + return (Bangle.isCharging() || activityreminder_settings.tempThreshold >= E.getTemperature()); + } + + function isDuringAlertHours(h) { + if (activityreminder_settings.startHour < activityreminder_settings.endHour) { // not passing through midnight + return (h >= activityreminder_settings.startHour && h < activityreminder_settings.endHour); + } else { // passing through midnight + return (h >= activityreminder_settings.startHour || h < activityreminder_settings.endHour); + } + } + + function mustAlert(now) { + if ((now - activityreminder_data.stepsDate) / 60000 > activityreminder_settings.maxInnactivityMin) { // inactivity detected + if ((now - activityreminder_data.okDate) / 60000 > 3 && // last alert anwsered with ok was more than 3 min ago + (now - activityreminder_data.dismissDate) / 60000 > activityreminder_settings.dismissDelayMin && // last alert was more than dismissDelayMin ago + (now - activityreminder_data.pauseDate) / 60000 > activityreminder_settings.pauseDelayMin) { // last alert was more than pauseDelayMin ago + return true; + } + } + return false; + } + + Bangle.on('midnight', function () { + /* + Usefull trick to have the app working smothly for people using it at night + */ + let now = new Date(); + let h = now.getHours(); + if (activityreminder_settings.enabled && isDuringAlertHours(h)) { + // updating only the steps and keeping the original stepsDate on purpose + activityreminder_data.stepsOnDate = 0; + activityreminder.saveData(activityreminder_data); + } + }); + + + if (activityreminder_settings.enabled) { + setInterval(run, 60000); + /* todo in a futur release + increase setInterval time to something that is still sensible (5 mins ?) + when we added a settimer + */ + } })(); diff --git a/apps/activityreminder/lib.js b/apps/activityreminder/lib.js index 704d35641..a5c35190c 100644 --- a/apps/activityreminder/lib.js +++ b/apps/activityreminder/lib.js @@ -1,56 +1,44 @@ exports.loadSettings = function () { - return Object.assign({ - enabled: true, - startHour: 9, - endHour: 20, - maxInnactivityMin: 30, - dismissDelayMin: 15, - pauseDelayMin: 120, - minSteps: 50, - tempThreshold: 27 - }, require("Storage").readJSON("activityreminder.s.json", true) || {}); + return Object.assign({ + enabled: true, + startHour: 9, + endHour: 20, + maxInnactivityMin: 30, + dismissDelayMin: 15, + pauseDelayMin: 120, + minSteps: 50, + tempThreshold: 27 + }, require("Storage").readJSON("activityreminder.s.json", true) || {}); }; exports.writeSettings = function (settings) { - require("Storage").writeJSON("activityreminder.s.json", settings); + require("Storage").writeJSON("activityreminder.s.json", settings); }; exports.saveData = function (data) { - require("Storage").writeJSON("activityreminder.data.json", data); + require("Storage").writeJSON("activityreminder.data.json", data); }; exports.loadData = function () { - let health = Bangle.getHealthStatus("day"); - let data = Object.assign({ - firstLoad: true, - stepsDate: new Date(), - stepsOnDate: health.steps, - okDate: new Date(1970), - dismissDate: new Date(1970), - pauseDate: new Date(1970), - }, + let health = Bangle.getHealthStatus("day"); + let data = Object.assign({ + firstLoad: true, + stepsDate: new Date(), + stepsOnDate: health.steps, + okDate: new Date(1970), + dismissDate: new Date(1970), + pauseDate: new Date(1970), + }, require("Storage").readJSON("activityreminder.data.json") || {}); - if(typeof(data.stepsDate) == "string") - data.stepsDate = new Date(data.stepsDate); - if(typeof(data.okDate) == "string") - data.okDate = new Date(data.okDate); - if(typeof(data.dismissDate) == "string") - data.dismissDate = new Date(data.dismissDate); - if(typeof(data.pauseDate) == "string") - data.pauseDate = new Date(data.pauseDate); + if (typeof (data.stepsDate) == "string") + data.stepsDate = new Date(data.stepsDate); + if (typeof (data.okDate) == "string") + data.okDate = new Date(data.okDate); + if (typeof (data.dismissDate) == "string") + data.dismissDate = new Date(data.dismissDate); + if (typeof (data.pauseDate) == "string") + data.pauseDate = new Date(data.pauseDate); - return data; + return data; }; - -exports.mustAlert = function(activityreminder_data, activityreminder_settings) { - let now = new Date(); - if ((now - activityreminder_data.stepsDate) / 60000 > activityreminder_settings.maxInnactivityMin) { // inactivity detected - if ((now - activityreminder_data.okDate) / 60000 > 3 && // last alert anwsered with ok was more than 3 min ago - (now - activityreminder_data.dismissDate) / 60000 > activityreminder_settings.dismissDelayMin && // last alert was more than dismissDelayMin ago - (now - activityreminder_data.pauseDate) / 60000 > activityreminder_settings.pauseDelayMin) { // last alert was more than pauseDelayMin ago - return true; - } - } - return false; -} \ No newline at end of file diff --git a/apps/activityreminder/metadata.json b/apps/activityreminder/metadata.json index 75ebf80b2..a7fb0c487 100644 --- a/apps/activityreminder/metadata.json +++ b/apps/activityreminder/metadata.json @@ -3,7 +3,7 @@ "name": "Activity Reminder", "shortName":"Activity Reminder", "description": "A reminder to take short walks for the ones with a sedentary lifestyle", - "version":"0.08", + "version":"0.10", "icon": "app.png", "type": "app", "tags": "tool,activity", @@ -13,11 +13,12 @@ {"name": "activityreminder.app.js", "url":"app.js"}, {"name": "activityreminder.boot.js", "url": "boot.js"}, {"name": "activityreminder.settings.js", "url": "settings.js"}, + {"name": "activityreminder.alert.js", "url": "alert.js"}, {"name": "activityreminder", "url": "lib.js"}, {"name": "activityreminder.img", "url": "app-icon.js", "evaluate": true} ], "data": [ {"name": "activityreminder.s.json"}, - {"name": "activityreminder.data.json"} + {"name": "activityreminder.data.json", "storageFile": true} ] } diff --git a/apps/activityreminder/settings.js b/apps/activityreminder/settings.js index de490b796..051c0dcd8 100644 --- a/apps/activityreminder/settings.js +++ b/apps/activityreminder/settings.js @@ -1,80 +1,86 @@ (function (back) { - // Load settings - const activityreminder = require("activityreminder"); - let settings = activityreminder.loadSettings(); + // Load settings + const activityreminder = require("activityreminder"); + let settings = activityreminder.loadSettings(); - // Show the menu - E.showMenu({ - "": { "title": "Activity Reminder" }, - "< Back": () => back(), - 'Enable': { - value: settings.enabled, - onchange: v => { - settings.enabled = v; - activityreminder.writeSettings(settings); - } - }, - 'Start hour': { - value: settings.startHour, - min: 0, max: 24, - onchange: v => { - settings.startHour = v; - activityreminder.writeSettings(settings); - } - }, - 'End hour': { - value: settings.endHour, - min: 0, max: 24, - onchange: v => { - settings.endHour = v; - activityreminder.writeSettings(settings); - } - }, - 'Max inactivity': { - value: settings.maxInnactivityMin, - min: 15, max: 120, - onchange: v => { - settings.maxInnactivityMin = v; - activityreminder.writeSettings(settings); - }, - format: x => x + "m" - }, - 'Dismiss delay': { - value: settings.dismissDelayMin, - min: 5, max: 60, - onchange: v => { - settings.dismissDelayMin = v; - activityreminder.writeSettings(settings); - }, - format: x => x + "m" - }, - 'Pause delay': { - value: settings.pauseDelayMin, - min: 30, max: 240, step: 5, - onchange: v => { - settings.pauseDelayMin = v; - activityreminder.writeSettings(settings); - }, - format: x => { - return x + "m"; - } - }, - 'Min steps': { - value: settings.minSteps, - min: 10, max: 500, step: 10, - onchange: v => { - settings.minSteps = v; - activityreminder.writeSettings(settings); - } - }, - 'Temp Threshold': { - value: settings.tempThreshold, - min: 20, max: 40, step: 0.5, - format: v => v + "°C", - onchange: v => { - settings.tempThreshold = v; - activityreminder.writeSettings(settings); - } + function getMainMenu(){ + var mainMenu = { + "": { "title": "Activity Reminder" }, + "< Back": () => back(), + 'Enable': { + value: settings.enabled, + onchange: v => { + settings.enabled = v; + activityreminder.writeSettings(settings); } - }); + }, + 'Start hour': { + value: settings.startHour, + min: 0, max: 24, + onchange: v => { + settings.startHour = v; + activityreminder.writeSettings(settings); + } + }, + 'End hour': { + value: settings.endHour, + min: 0, max: 24, + onchange: v => { + settings.endHour = v; + activityreminder.writeSettings(settings); + } + }, + 'Max inactivity': { + value: settings.maxInnactivityMin, + min: 15, max: 120, + onchange: v => { + settings.maxInnactivityMin = v; + activityreminder.writeSettings(settings); + }, + format: x => x + "m" + }, + 'Dismiss delay': { + value: settings.dismissDelayMin, + min: 5, max: 60, + onchange: v => { + settings.dismissDelayMin = v; + activityreminder.writeSettings(settings); + }, + format: x => x + "m" + }, + 'Pause delay': { + value: settings.pauseDelayMin, + min: 30, max: 240, step: 5, + onchange: v => { + settings.pauseDelayMin = v; + activityreminder.writeSettings(settings); + }, + format: x => { + return x + "m"; + } + }, + 'Min steps': { + value: settings.minSteps, + min: 10, max: 500, step: 10, + onchange: v => { + settings.minSteps = v; + activityreminder.writeSettings(settings); + } + }, + 'Temp Threshold': { + value: settings.tempThreshold, + min: 20, max: 40, step: 0.5, + format: v => v + "°C", + onchange: v => { + settings.tempThreshold = v; + activityreminder.writeSettings(settings); + } + } + }; + + return mainMenu; + } + + // Show the menu + E.showMenu(getMainMenu()); }) diff --git a/apps/advcasio/ChangeLog b/apps/advcasio/ChangeLog index 7de176672..a1b528cf6 100644 --- a/apps/advcasio/ChangeLog +++ b/apps/advcasio/ChangeLog @@ -1 +1,3 @@ 0.01: AdvCasio first version +0.02: Remove un-needed fonts to improve memory usage +0.03: Tell clock widgets to hide. diff --git a/apps/advcasio/app.js b/apps/advcasio/app.js index 8c27b7823..8cb904f90 100644 --- a/apps/advcasio/app.js +++ b/apps/advcasio/app.js @@ -1,7 +1,5 @@ const storage = require('Storage'); -require("Font6x12").add(Graphics); -require("Font6x8").add(Graphics); require("Font8x12").add(Graphics); require("Font7x11Numeric7Seg").add(Graphics); @@ -257,7 +255,6 @@ function draw() { g.setColor(0, 0, 0); - g.setFont("6x12"); if(dataJson && dataJson.weather) drawWeather(dataJson.weather); if(dataJson && dataJson.tasks) drawTasks(dataJson.tasks); @@ -297,9 +294,10 @@ Bangle.on("lock", (locked) => { }); +Bangle.setUI("clock"); + // Load widgets, but don't show them Bangle.loadWidgets(); -Bangle.setUI("clock"); g.reset(); g.clear(); diff --git a/apps/advcasio/metadata.json b/apps/advcasio/metadata.json index 0f0c75c07..152f47132 100644 --- a/apps/advcasio/metadata.json +++ b/apps/advcasio/metadata.json @@ -1,7 +1,7 @@ { "id": "advcasio", "name": "Advanced Casio Clock", "shortName":"advcasio", - "version":"0.01", + "version":"0.03", "description": "An over-engineered clock inspired by Casio watches. It has a 4 days weather, a timer using swipe and a scratchpad. Can be updated using a dedicated webapp.", "icon": "app.png", "tags": "clock", diff --git a/apps/agenda/ChangeLog b/apps/agenda/ChangeLog index ae650deeb..16a90242b 100644 --- a/apps/agenda/ChangeLog +++ b/apps/agenda/ChangeLog @@ -1,2 +1,6 @@ 0.01: Basic agenda with events from GB 0.02: Added settings page to force calendar sync +0.03: Disable past events display from settings +0.04: Added awareness of allDay field +0.05: Displaying calendar colour and name +0.06: Added clkinfo for clocks. \ No newline at end of file diff --git a/apps/agenda/README.md b/apps/agenda/README.md index a546e0a89..7063a70a2 100644 --- a/apps/agenda/README.md +++ b/apps/agenda/README.md @@ -1,3 +1,20 @@ # Agenda -Basic agenda reading the events synchronised from GadgetBridge +Basic agenda reading the events synchronised from GadgetBridge. + +### Functionalities + +* List all events in the next week (or whatever is synchronized) +* Optionally view past events (until GB removes them) +* Show start time and location of the events in the list +* Show the colour of the calendar in the list +* Display description, location and calendar name after tapping on events + +### Report a bug + +You can easily open an issue in the espruino repo, but I won't be notified and it might take time. +If you want a (hopefully) quicker response, just report [on my fork](https://github.com/glemco/BangleApps). + +### Known Problems + +Any all-day event lasts just one day: that is a GB limitation that we will likely fix in the future. diff --git a/apps/agenda/agenda.clkinfo.js b/apps/agenda/agenda.clkinfo.js new file mode 100644 index 000000000..a80c09002 --- /dev/null +++ b/apps/agenda/agenda.clkinfo.js @@ -0,0 +1,29 @@ +(function() { + var agendaItems = { + name: "Agenda", + img: atob("GBiBAf////////85z/AAAPAAAPgAAP////AAAPAAAPAAAPAAAOAAAeAAAeAAAcAAA8AAAoAABgAADP//+P//8PAAAPAAAPgAAf///w=="), + items: [] + }; + + var now = new Date(); + var agenda = storage.readJSON("android.calendar.json") + .filter(ev=>ev.timestamp + ev.durationInSeconds > now/1000) + .sort((a,b)=>a.timestamp - b.timestamp); + + agenda.forEach((entry, i) => { + + var title = entry.title.slice(0,18); + var date = new Date(entry.timestamp*1000); + var dateStr = locale.date(date).replace(/\d\d\d\d/,""); + dateStr += entry.durationInSeconds < 86400 ? "/ " + locale.time(date,1) : ""; + + agendaItems.items.push({ + name: "agendaEntry-" + i, + get: () => ({ text: title + "\n" + dateStr, img: null}), + show: function() { agendaItems.items[i].emit("redraw"); }, + hide: function () {} + }); + }); + + return agendaItems; +}) \ No newline at end of file diff --git a/apps/agenda/agenda.js b/apps/agenda/agenda.js index f39e31c75..9cffe0265 100644 --- a/apps/agenda/agenda.js +++ b/apps/agenda/agenda.js @@ -6,6 +6,8 @@ title, description, location, + color:int, + calName, allDay: bool, } */ @@ -24,19 +26,23 @@ var fontLarge = g.getFonts().includes("6x15")?"6x15:2":"6x8:4"; //FIXME maybe write the end from GB already? Not durationInSeconds here (or do while receiving?) var CALENDAR = require("Storage").readJSON("android.calendar.json",true)||[]; +var settings = require("Storage").readJSON("agenda.settings.json",true)||{}; -CALENDAR=CALENDAR.sort((a,b)=>a.timestamp - b.timestamp) +CALENDAR=CALENDAR.sort((a,b)=>a.timestamp - b.timestamp); function getDate(timestamp) { return new Date(timestamp*1000); } -function formatDateLong(date, includeDay) { - if(includeDay) - return Locale.date(date)+" "+Locale.time(date,1); - return Locale.time(date,1); +function formatDateLong(date, includeDay, allDay) { + let shortTime = Locale.time(date,1)+Locale.meridian(date); + if(allDay) shortTime = ""; + if(includeDay || allDay) + return Locale.date(date)+" "+shortTime; + return shortTime; } -function formatDateShort(date) { - return Locale.date(date).replace(/\d\d\d\d/,"")+Locale.time(date,1); +function formatDateShort(date, allDay) { + return Locale.date(date).replace(/\d\d\d\d/,"")+(allDay? + "" : Locale.time(date,1)+Locale.meridian(date)); } var lines = []; @@ -45,7 +51,7 @@ function showEvent(ev) { if(!ev) return; g.setFont(bodyFont); //var lines = []; - if (ev.title) lines = g.wrapString(ev.title, g.getWidth()-10) + if (ev.title) lines = g.wrapString(ev.title, g.getWidth()-10); var titleCnt = lines.length; var start = getDate(ev.timestamp); var end = getDate((+ev.timestamp) + (+ev.durationInSeconds)); @@ -53,22 +59,24 @@ function showEvent(ev) { if (titleCnt) lines.push(""); // add blank line after title if(start.getDay() == end.getDay() && start.getMonth() == end.getMonth()) includeDay = false; - if(includeDay) { + if(includeDay || ev.allDay) { lines = lines.concat( /*LANG*/"Start:", - g.wrapString(formatDateLong(start, includeDay), g.getWidth()-10), + g.wrapString(formatDateLong(start, includeDay, ev.allDay), g.getWidth()-10), /*LANG*/"End:", - g.wrapString(formatDateLong(end, includeDay), g.getWidth()-10)); + g.wrapString(formatDateLong(end, includeDay, ev.allDay), g.getWidth()-10)); } else { lines = lines.concat( g.wrapString(Locale.date(start), g.getWidth()-10), - g.wrapString(/*LANG*/"Start"+": "+formatDateLong(start, includeDay), g.getWidth()-10), - g.wrapString(/*LANG*/"End"+": "+formatDateLong(end, includeDay), g.getWidth()-10)); + g.wrapString(/*LANG*/"Start"+": "+formatDateLong(start, includeDay, ev.allDay), g.getWidth()-10), + g.wrapString(/*LANG*/"End"+": "+formatDateLong(end, includeDay, ev.allDay), g.getWidth()-10)); } if(ev.location) lines = lines.concat(/*LANG*/"Location"+": ", g.wrapString(ev.location, g.getWidth()-10)); if(ev.description) lines = lines.concat("",g.wrapString(ev.description, g.getWidth()-10)); + if(ev.calName) + lines = lines.concat(/*LANG*/"Calendar"+": ", g.wrapString(ev.calName, g.getWidth()-10)); lines = lines.concat(["",/*LANG*/"< Back"]); E.showScroller({ h : g.getFontHeight(), // height of each menu item in pixels @@ -89,6 +97,12 @@ function showEvent(ev) { } function showList() { + //it might take time for GB to delete old events, decide whether to show them grayed out or hide entirely + if(!settings.pastEvents) { + let now = new Date(); + //TODO add threshold here? + CALENDAR = CALENDAR.filter(ev=>ev.timestamp + ev.durationInSeconds > now/1000); + } if(CALENDAR.length == 0) { E.showMessage("No events"); return; @@ -101,24 +115,21 @@ function showList() { g.setColor(g.theme.fg); g.clearRect(r.x,r.y,r.x+r.w, r.y+r.h); if (!ev) return; - var isPast = ev.timestamp + ev.durationInSeconds < (new Date())/1000; + var isPast = false; var x = r.x+2, title = ev.title; - var body = formatDateShort(getDate(ev.timestamp))+"\n"+ev.location; - var m = ev.title+"\n"+ev.location, longBody=false; + var body = formatDateShort(getDate(ev.timestamp),ev.allDay)+"\n"+(ev.location?ev.location:/*LANG*/"No location"); + if(settings.pastEvents) isPast = ev.timestamp + ev.durationInSeconds < (new Date())/1000; if (title) g.setFontAlign(-1,-1).setFont(fontBig) - .setColor(isPast ? "#888" : g.theme.fg).drawString(title, x,r.y+2); + .setColor(isPast ? "#888" : g.theme.fg).drawString(title, x+4,r.y+2); if (body) { g.setFontAlign(-1,-1).setFont(fontMedium).setColor(isPast ? "#888" : g.theme.fg); - var l = g.wrapString(body, r.w-(x+14)); - if (l.length>3) { - l = l.slice(0,3); - l[l.length-1]+="..."; - } - longBody = l.length>2; - g.drawString(l.join("\n"), x+10,r.y+20); + g.drawString(body, x+10,r.y+20); } - //if (!longBody && msg.src) g.setFontAlign(1,1).setFont("6x8").drawString(msg.src, r.x+r.w-2, r.y+r.h-2); g.setColor("#888").fillRect(r.x,r.y+r.h-1,r.x+r.w-1,r.y+r.h-1); // dividing line between items + if(ev.color) { + g.setColor("#"+(0x1000000+Number(ev.color)).toString(16).padStart(6,"0")); + g.fillRect(r.x,r.y+4,r.x+3, r.y+r.h-4); + } }, select : idx => showEvent(CALENDAR[idx]), back : () => load() diff --git a/apps/agenda/metadata.json b/apps/agenda/metadata.json index ce8438686..2bce8ca56 100644 --- a/apps/agenda/metadata.json +++ b/apps/agenda/metadata.json @@ -1,7 +1,7 @@ { "id": "agenda", "name": "Agenda", - "version": "0.02", + "version": "0.06", "description": "Simple agenda", "icon": "agenda.png", "screenshots": [{"url":"screenshot_agenda_overview.png"}, {"url":"screenshot_agenda_event1.png"}, {"url":"screenshot_agenda_event2.png"}], @@ -12,6 +12,8 @@ "storage": [ {"name":"agenda.app.js","url":"agenda.js"}, {"name":"agenda.settings.js","url":"settings.js"}, + {"name":"agenda.clkinfo.js","url":"agenda.clkinfo.js"}, {"name":"agenda.img","url":"agenda-icon.js","evaluate":true} - ] + ], + "data": [{"name":"agenda.settings.json"}] } diff --git a/apps/agenda/settings.js b/apps/agenda/settings.js index fe9dab2d8..4220fcb63 100644 --- a/apps/agenda/settings.js +++ b/apps/agenda/settings.js @@ -3,6 +3,10 @@ Bluetooth.println(""); Bluetooth.println(JSON.stringify(message)); } + var settings = require("Storage").readJSON("agenda.settings.json",1)||{}; + function updateSettings() { + require("Storage").writeJSON("agenda.settings.json", settings); + } var CALENDAR = require("Storage").readJSON("android.calendar.json",true)||[]; var mainmenu = { "" : { "title" : "Agenda" }, @@ -32,6 +36,13 @@ E.showAlert(/*LANG*/"You are not connected").then(()=>E.showMenu(mainmenu)); } }, + /*LANG*/"Show past events" : { + value : !!settings.pastEvents, + onchange: v => { + settings.pastEvents = v; + updateSettings(); + } + }, }; E.showMenu(mainmenu); }) diff --git a/apps/agpsdata/metadata.json b/apps/agpsdata/metadata.json index d3863be52..e2f818d97 100644 --- a/apps/agpsdata/metadata.json +++ b/apps/agpsdata/metadata.json @@ -1,9 +1,9 @@ { "id": "agpsdata", - "name": "A-GPS Data", + "name": "A-GPS Data Downloader App", "shortName":"A-GPS Data", "icon": "agpsdata.png", "version":"0.02", - "description": "Download assisted GPS (A-GPS) data directly to your Bangle.js **using Gadgetbridge**", + "description": "Once installed, this app allows you to download assisted GPS (A-GPS) data directly to your Bangle.js **via Gadgetbridge on an Android phone** when you run the app. If you just want to upload the latest AGPS data from this app loader, please use the `Assisted GPS Update (AGPS)` app.", "tags": "boot,tool,assisted,gps,agps,http", "allow_emulator":true, "supports": ["BANGLEJS2"], diff --git a/apps/android/ChangeLog b/apps/android/ChangeLog index 76658af49..0cc7aedd4 100644 --- a/apps/android/ChangeLog +++ b/apps/android/ChangeLog @@ -11,4 +11,5 @@ 0.10: Fix SMS bug 0.12: Use default Bangle formatter for booleans 0.13: Added Bangle.http function (see Readme file for more info) -0.14: Fix timeout of http function not beeing cleaned up +0.14: Fix timeout of http function not being cleaned up +0.15: Allow method/body/headers to be specified for `http` (needs Gadgetbridge 0.68.0b or later) diff --git a/apps/android/boot.js b/apps/android/boot.js index 99d4dbb2c..bc8e3032d 100644 --- a/apps/android/boot.js +++ b/apps/android/boot.js @@ -150,6 +150,9 @@ //send the request var req = {t: "http", url:url, id:options.id}; if (options.xpath) req.xpath = options.xpath; + if (options.method) req.method = options.method; + if (options.body) req.body = options.body; + if (options.headers) req.headers = options.headers; gbSend(req); //create the promise var promise = new Promise(function(resolve,reject) { diff --git a/apps/android/metadata.json b/apps/android/metadata.json index 91f74c36f..5d1b2f561 100644 --- a/apps/android/metadata.json +++ b/apps/android/metadata.json @@ -2,7 +2,7 @@ "id": "android", "name": "Android Integration", "shortName": "Android", - "version": "0.14", + "version": "0.15", "description": "Display notifications/music/etc sent from the Gadgetbridge app on Android. This replaces the old 'Gadgetbridge' Bangle.js widget.", "icon": "app.png", "tags": "tool,system,messages,notifications,gadgetbridge", diff --git a/apps/animclk/ChangeLog b/apps/animclk/ChangeLog index 348448c34..76d15bdb1 100644 --- a/apps/animclk/ChangeLog +++ b/apps/animclk/ChangeLog @@ -1,3 +1,5 @@ 0.01: New App! 0.02: Fix bug if image clock wasn't installed 0.03: Update to use setUI +0.04: Tell clock widgets to hide. Move loadWidgets() so it only runs on +startup and not on every draw. diff --git a/apps/animclk/app.js b/apps/animclk/app.js index 4bf63daf6..bdc399fbe 100644 --- a/apps/animclk/app.js +++ b/apps/animclk/app.js @@ -87,7 +87,6 @@ if (g.drawImages) { draw(); var secondInterval = setInterval(draw,100); // load widgets - Bangle.loadWidgets(); Bangle.drawWidgets(); // Stop when LCD goes off Bangle.on('lcdPower',on=>{ @@ -104,3 +103,5 @@ if (g.drawImages) { } // Show launcher when button pressed Bangle.setUI("clock"); + +Bangle.loadWidgets(); diff --git a/apps/animclk/metadata.json b/apps/animclk/metadata.json index 31dfe453f..0b426a37d 100644 --- a/apps/animclk/metadata.json +++ b/apps/animclk/metadata.json @@ -2,7 +2,7 @@ "id": "animclk", "name": "Animated Clock", "shortName": "Anim Clock", - "version": "0.03", + "version": "0.04", "description": "An animated clock face using Mark Ferrari's amazing 8 bit game art and palette cycling: http://www.markferrari.com/art/8bit-game-art", "icon": "app.png", "type": "clock", diff --git a/apps/antonclk/ChangeLog b/apps/antonclk/ChangeLog index f7e95b5fa..9e75d889a 100644 --- a/apps/antonclk/ChangeLog +++ b/apps/antonclk/ChangeLog @@ -10,4 +10,5 @@ week is buffered until date or timezone changes 0.07: align default settings with app.js (otherwise the initial displayed settings will be confusing to users) 0.08: fixed calendar weeknumber not shortened to two digits -0.09: Use default Bangle formatter for booleans \ No newline at end of file +0.09: Use default Bangle formatter for booleans +0.10: Use Bangle.setUI({remove:...}) to allow loading the launcher without a full reset on 2v16 diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index 4b1e71bda..07f67f696 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -1,7 +1,4 @@ // Clock with large digits using the "Anton" bold font - -const SETTINGSFILE = "antonclk.json"; - Graphics.prototype.setFontAnton = function(scale) { // Actual height 69 (68 - 0) g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAA/gAAAAAAAAAAP/gAAAAAAAAAH//gAAAAAAAAB///gAAAAAAAAf///gAAAAAAAP////gAAAAAAD/////gAAAAAA//////gAAAAAP//////gAAAAH///////gAAAB////////gAAAf////////gAAP/////////gAD//////////AA//////////gAA/////////4AAA////////+AAAA////////gAAAA///////wAAAAA//////8AAAAAA//////AAAAAAA/////gAAAAAAA////4AAAAAAAA///+AAAAAAAAA///gAAAAAAAAA//wAAAAAAAAAA/8AAAAAAAAAAA/AAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////AAAAAB///////8AAAAH////////AAAAf////////wAAA/////////4AAB/////////8AAD/////////+AAH//////////AAP//////////gAP//////////gAP//////////gAf//////////wAf//////////wAf//////////wAf//////////wA//8AAAAAB//4A//wAAAAAAf/4A//gAAAAAAP/4A//gAAAAAAP/4A//gAAAAAAP/4A//wAAAAAAf/4A///////////4Af//////////wAf//////////wAf//////////wAf//////////wAP//////////gAP//////////gAH//////////AAH//////////AAD/////////+AAB/////////8AAA/////////4AAAP////////gAAAD///////+AAAAAf//////4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gAAAAAAAAAAP/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/AAAAAAAAAAA//AAAAAAAAAAA/+AAAAAAAAAAB/8AAAAAAAAAAD//////////gAH//////////gAP//////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/4AAAAB/gAAD//4AAAAf/gAAP//4AAAB//gAA///4AAAH//gAB///4AAAf//gAD///4AAA///gAH///4AAD///gAP///4AAH///gAP///4AAP///gAf///4AAf///gAf///4AB////gAf///4AD////gA////4AH////gA////4Af////gA////4A/////gA//wAAB/////gA//gAAH/////gA//gAAP/////gA//gAA///8//gA//gAD///w//gA//wA////g//gA////////A//gA///////8A//gA///////4A//gAf//////wA//gAf//////gA//gAf/////+AA//gAP/////8AA//gAP/////4AA//gAH/////gAA//gAD/////AAA//gAB////8AAA//gAA////wAAA//gAAP///AAAA//gAAD//8AAAA//gAAAP+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/+AAAAAD/wAAB//8AAAAP/wAAB///AAAA//wAAB///wAAB//wAAB///4AAD//wAAB///8AAH//wAAB///+AAP//wAAB///+AAP//wAAB////AAf//wAAB////AAf//wAAB////gAf//wAAB////gA///wAAB////gA///wAAB////gA///w//AAf//wA//4A//AAA//wA//gA//AAAf/wA//gB//gAAf/wA//gB//gAAf/wA//gD//wAA//wA//wH//8AB//wA///////////gA///////////gA///////////gA///////////gAf//////////AAf//////////AAP//////////AAP/////////+AAH/////////8AAH///+/////4AAD///+f////wAAA///8P////gAAAf//4H///+AAAAH//gB///wAAAAAP4AAH/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/wAAAAAAAAAA//wAAAAAAAAAP//wAAAAAAAAB///wAAAAAAAAf///wAAAAAAAH////wAAAAAAA/////wAAAAAAP/////wAAAAAB//////wAAAAAf//////wAAAAH///////wAAAA////////wAAAP////////wAAA///////H/wAAA//////wH/wAAA/////8AH/wAAA/////AAH/wAAA////gAAH/wAAA///4AAAH/wAAA//+AAAAH/wAAA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gAAAAAAAAH/4AAAAAAAAAAH/wAAAAAAAAAAH/wAAAAAAAAAAH/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//8AAA/////+B///AAA/////+B///wAA/////+B///4AA/////+B///8AA/////+B///8AA/////+B///+AA/////+B////AA/////+B////AA/////+B////AA/////+B////gA/////+B////gA/////+B////gA/////+A////gA//gP/gAAB//wA//gf/AAAA//wA//gf/AAAAf/wA//g//AAAAf/wA//g//AAAA//wA//g//gAAA//wA//g//+AAP//wA//g////////gA//g////////gA//g////////gA//g////////gA//g////////AA//gf///////AA//gf//////+AA//gP//////+AA//gH//////8AA//gD//////4AA//gB//////wAA//gA//////AAAAAAAH////8AAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////gAAAAB///////+AAAAH////////gAAAf////////4AAB/////////8AAD/////////+AAH//////////AAH//////////gAP//////////gAP//////////gAf//////////wAf//////////wAf//////////wAf//////////wAf//////////4A//wAD/4AAf/4A//gAH/wAAP/4A//gAH/wAAP/4A//gAP/wAAP/4A//gAP/4AAf/4A//wAP/+AD//4A///wP//////4Af//4P//////wAf//4P//////wAf//4P//////wAf//4P//////wAP//4P//////gAP//4H//////gAH//4H//////AAH//4D/////+AAD//4D/////8AAB//4B/////4AAA//4A/////wAAAP/4AP////AAAAB/4AD///4AAAAAAAAAH/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//AAAAAAAAAAA//gAAAAAAAAAA//gAAAAAAAAAA//gAAAAAAADgA//gAAAAAAP/gA//gAAAAAH//gA//gAAAAB///gA//gAAAAP///gA//gAAAD////gA//gAAAf////gA//gAAB/////gA//gAAP/////gA//gAB//////gA//gAH//////gA//gA///////gA//gD///////gA//gf///////gA//h////////gA//n////////gA//////////gAA/////////AAAA////////wAAAA///////4AAAAA///////AAAAAA//////4AAAAAA//////AAAAAAA/////4AAAAAAA/////AAAAAAAA////8AAAAAAAA////gAAAAAAAA///+AAAAAAAAA///4AAAAAAAAA///AAAAAAAAAA//4AAAAAAAAAA/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//gB///wAAAAP//4H///+AAAA///8P////gAAB///+f////4AAD///+/////8AAH/////////+AAH//////////AAP//////////gAP//////////gAf//////////gAf//////////wAf//////////wAf//////////wA///////////wA//4D//wAB//4A//wB//gAA//4A//gA//gAAf/4A//gA//AAAf/4A//gA//gAAf/4A//wB//gAA//4A///P//8AH//4Af//////////wAf//////////wAf//////////wAf//////////wAf//////////gAP//////////gAP//////////AAH//////////AAD/////////+AAD///+/////8AAB///8f////wAAAf//4P////AAAAH//wD///8AAAAA/+AAf//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH//gAAAAAAAAB///+AA/+AAAAP////gA//wAAAf////wA//4AAB/////4A//8AAD/////8A//+AAD/////+A///AAH/////+A///AAP//////A///gAP//////A///gAf//////A///wAf//////A///wAf//////A///wAf//////A///wA///////AB//4A//4AD//AAP/4A//gAB//AAP/4A//gAA//AAP/4A//gAA/+AAP/4A//gAB/8AAP/4A//wAB/8AAf/4Af//////////wAf//////////wAf//////////wAf//////////wAf//////////wAP//////////gAP//////////gAH//////////AAH/////////+AAD/////////8AAB/////////4AAAf////////wAAAP////////AAAAB///////4AAAAAD/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/AAB/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("EiAnGicnJycnJycnEw=="), 78 + (scale << 8) + (1 << 16)); @@ -12,23 +9,28 @@ Graphics.prototype.setFontAntonSmall = function(scale) { g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAAAAAAAAAAAAAMAAAAAAAAD8AAAAAAAA/8AAAAAAAf/8AAAAAAH//8AAAAAB///8AAAAA////8AAAAP////8AAAD/////8AAB//////8AAf//////8AH///////4A///////+AA///////AAA//////wAAA/////8AAAA////+AAAAA////gAAAAA///4AAAAAA//8AAAAAAA//AAAAAAAA/wAAAAAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/////wAAA//////8AAB//////+AAH///////gAH///////gAP///////wAf///////4Af///////4A////////8A////////8A////////8A//AAAAD/8A/8AAAAA/8A/8AAAAA/8A/8AAAAA/8A/+AAAAB/8A////////8A////////8A////////8Af///////4Af///////4AP///////wAP///////wAH///////gAD///////AAA//////8AAAP/////wAAAAAAAAAAAAAAAAAAAAAAAfwAAAAAAAA/4AAAAAAAA/4AAAAAAAB/wAAAAAAAB/wAAAAAAAD/wAAAAAAAD/gAAAAAAAH///////8AP///////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/4AAAP8AA//4AAA/8AB//4AAH/8AH//4AAP/8AP//4AA//8AP//4AB//8Af//4AD//8Af//4AP//8A///4Af//8A///4A///8A///4D///8A//AAH///8A/8AAP///8A/8AA//+/8A/8AD//8/8A/+Af//w/8A//////g/8A/////+A/8A/////8A/8Af////4A/8Af////wA/8AP////AA/8AP///+AA/8AH///8AA/8AD///wAA/8AA///AAA/8AAP/4AAA/8AAAAAAAAAAAAAAAAAAAAAAH4AAf/gAAA/4AAf/8AAD/4AAf//AAH/4AAf//gAP/4AAf//wAP/4AAf//wAf/4AAf//4Af/4AAf//4A//4AAf//8A//4AAf//8A//4AAP//8A//A/8AB/8A/8A/8AA/8A/8B/8AA/8A/8B/8AA/8A/+D//AB/8A////////8A////////8A////////8Af///////4Af///////4Af///////wAP///////gAH//9////gAD//4///+AAB//wf//4AAAP/AH//gAAAAAAAAAAAAAAAAAAAAAAAAAAAH/wAAAAAAB//wAAAAAAP//wAAAAAD///wAAAAA////wAAAAH////wAAAB/////wAAAf/////wAAD//////wAA///////wAA/////h/wAA////wB/wAA///8AB/wAA///AAB/wAA//gAAB/wAA////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8AAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAP/4AA////4P/+AA////4P//AA////4P//gA////4P//wA////4P//wA////4P//4A////4P//4A////4P//8A////4P//8A////4P//8A/8H/AAB/8A/8H+AAA/8A/8P+AAA/8A/8P+AAA/8A/8P/gAD/8A/8P/////8A/8P/////8A/8P/////8A/8P/////4A/8H/////4A/8H/////wA/8D/////wA/8B/////gA/8A////+AA/8AP///4AAAAAB///AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////wAAAf/////8AAB///////AAH///////gAP///////wAP///////wAf///////4Af///////4A////////8A////////8A////////8A/+AH/AB/8A/8AP+AA/8A/4Af+AA/8A/8Af+AA/8A/8Af/gH/8A//4f////8A//4f////8A//4f////8Af/4f////4Af/4f////4AP/4P////wAP/4P////gAH/4H////AAD/4D///+AAB/4B///4AAAP4AP//gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8AAAAAAAA/8AAAAAAAA/8AAAAAB8A/8AAAAB/8A/8AAAAf/8A/8AAAH//8A/8AAA///8A/8AAH///8A/8AA////8A/8AD////8A/8Af////8A/8B/////8A/8P/////8A/8//////8A////////AA///////AAA//////gAAA/////4AAAA/////AAAAA////4AAAAA////AAAAAA///8AAAAAA///gAAAAAA//+AAAAAAA//wAAAAAAA/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/gD//gAAA//4P//8AAD//8f///AAH//+////gAH///////wAP///////4AP///////8Af///////8Af///////+Af///////+A////////+A//B//AB/+A/+A/+AA/+A/8Af+AA/+A/+Af+AA/+A//A//AB/+A////////+Af///////+Af///////+Af///////8Af///////8AP///////4AH///////4AH//+////wAD//+////AAA//4P//+AAAP/gH//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH//gAfgAAA///8A/8AAB///+A//AAH////A//gAH////g//wAP////g//wAf////w//4Af////w//4A/////w//8A/////w//8A/////w//8A//gP/wA/8A/8AD/wA/8A/8AD/wAf8A/8AD/gA/8A/+AH/AB/8A////////8A////////8A////////8Af///////4Af///////4Af///////wAP///////wAH///////gAD//////+AAA//////4AAAP/////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("DhgeFB4eHh4eHh4eDw=="), 60 + (scale << 8) + (1 << 16)); }; +{ // must be inside our own scope here so that when we are unloaded everything disappears + +const SETTINGSFILE = "antonclk.json"; +const isBangle1 = (process.env.HWVERSION == 1); + // variables defined from settings -var secondsMode; -var secondsColoured; -var secondsWithColon; -var dateOnMain; -var dateOnSecs; -var weekDay; -var calWeek; -var upperCase; -var vectorFont; +let secondsMode; +let secondsColoured; +let secondsWithColon; +let dateOnMain; +let dateOnSecs; +let weekDay; +let calWeek; +let upperCase; +let vectorFont; // dynamic variables -var drawTimeout; -var queueMillis = 1000; -var secondsScreen = true; +let drawTimeout; +let queueMillis = 1000; +let secondsScreen = true; + -var isBangle1 = (process.env.HWVERSION == 1); //For development purposes /* @@ -102,7 +104,7 @@ function isoStr(date) { return date.getFullYear() + "-" + ("0" + (date.getMonth() + 1)).slice(-2) + "-" + ("0" + date.getDate()).slice(-2); } -var calWeekBuffer = [false,false,false]; //buffer tz, date, week no (once calculated until other tz or date is requested) +let calWeekBuffer = [false,false,false]; //buffer tz, date, week no (once calculated until other tz or date is requested) function ISO8601calWeek(date) { //copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480 dateNoTime = date; dateNoTime.setHours(0,0,0,0); if (calWeekBuffer[0] === date.getTimezoneOffset() && calWeekBuffer[1] === dateNoTime) return calWeekBuffer[2]; @@ -215,16 +217,21 @@ g.clear(); // Set dynamic state and perform initial drawing updateState(); // Register hooks for LCD on/off event and screen lock on/off event -Bangle.on('lcdPower', on => { - updateState(); -}); -Bangle.on('lock', on => { - updateState(); -}); +Bangle.on('lcdPower', updateState); +Bangle.on('lock', updateState); // Show launcher when middle button pressed -Bangle.setUI("clock"); +Bangle.setUI({ + mode : "clock", + remove : function() { + // Called to unload all of the clock app + Bangle.removeListener('lcdPower', updateState); + Bangle.removeListener('lock', updateState); + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + delete Graphics.prototype.setFontAnton; + delete Graphics.prototype.setFontAntonSmall; + }}); // Load widgets Bangle.loadWidgets(); Bangle.drawWidgets(); - -// end of file \ No newline at end of file +} diff --git a/apps/antonclk/metadata.json b/apps/antonclk/metadata.json index 16bdf3aa8..b6134d1a1 100644 --- a/apps/antonclk/metadata.json +++ b/apps/antonclk/metadata.json @@ -1,7 +1,7 @@ { "id": "antonclk", "name": "Anton Clock", - "version": "0.09", + "version": "0.10", "description": "A clock using the bold Anton font, optionally showing seconds and date in ISO-8601 format.", "readme":"README.md", "icon": "app.png", diff --git a/apps/assistedgps/metadata.json b/apps/assistedgps/metadata.json index 1dbc42c87..4c91dcd35 100644 --- a/apps/assistedgps/metadata.json +++ b/apps/assistedgps/metadata.json @@ -1,11 +1,12 @@ { "id": "assistedgps", - "name": "Assisted GPS Update (AGPS)", + "name": "Assisted GPS Updater (AGPS)", "version": "0.03", - "description": "Downloads assisted GPS (AGPS) data to Bangle.js 1 or 2 for faster GPS startup and more accurate fixes. **No app will be installed**, this just uploads new data to the GPS chip.", + "description": "Downloads assisted GPS (AGPS) data to Bangle.js for faster GPS startup and more accurate fixes. **No app will be installed**, this just uploads new data to the GPS chip.", + "sortorder": -1, "icon": "app.png", "type": "RAM", - "tags": "tool,outdoors,agps", + "tags": "tool,outdoors,agps,gps,a-gps", "supports": ["BANGLEJS","BANGLEJS2"], "custom": "custom.html", "customConnect": true, diff --git a/apps/astral/ChangeLog b/apps/astral/ChangeLog index a51c96760..c93c2b6c2 100644 --- a/apps/astral/ChangeLog +++ b/apps/astral/ChangeLog @@ -1,3 +1,4 @@ 0.01: Create astral clock app 0.02: Fixed Whirlpool galaxy RA/DA, larger compass display, fixed moonphase overlapping battery widget 0.03: Update to use Bangle.setUI instead of setWatch +0.04: Tell clock widgets to hide. diff --git a/apps/astral/app.js b/apps/astral/app.js index c445463f2..c4339bc09 100644 --- a/apps/astral/app.js +++ b/apps/astral/app.js @@ -767,6 +767,24 @@ function draw() { g.clear(); current_moonphase = getMoonPhase(); +Bangle.setUI("clockupdown", btn => { + if (btn==0) { + if (!processing) { + if (!modeswitch) { + modeswitch = true; + if (mode == "planetary") mode = "extras"; + else mode = "planetary"; + } + else + modeswitch = false; + } + } else { + if (!processing) + ready_to_compute = true; + } +}); + + // Load widgets Bangle.loadWidgets(); Bangle.drawWidgets(); @@ -799,23 +817,6 @@ Bangle.setGPSPower(1); // Show launcher when button pressed Bangle.setClockMode(); -Bangle.setUI("clockupdown", btn => { - if (btn==0) { - if (!processing) { - if (!modeswitch) { - modeswitch = true; - if (mode == "planetary") mode = "extras"; - else mode = "planetary"; - } - else - modeswitch = false; - } - } else { - if (!processing) - ready_to_compute = true; - } -}); - setWatch(function () { if (!astral_settings.astral_default) { colours_switched = true; diff --git a/apps/astral/metadata.json b/apps/astral/metadata.json index 3317092db..d7120878b 100644 --- a/apps/astral/metadata.json +++ b/apps/astral/metadata.json @@ -1,7 +1,7 @@ { "id": "astral", "name": "Astral Clock", - "version": "0.03", + "version": "0.04", "description": "Clock that calculates and displays Alt Az positions of all planets, Sun as well as several other astronomy targets (customizable) and current Moon phase. Coordinates are calculated by GPS & time and onscreen compass assists orienting. See Readme before using.", "icon": "app-icon.png", "type": "clock", diff --git a/apps/banglexercise/ChangeLog b/apps/banglexercise/ChangeLog index 5f1d3bd7d..6cf589541 100644 --- a/apps/banglexercise/ChangeLog +++ b/apps/banglexercise/ChangeLog @@ -2,3 +2,4 @@ 0.02: Add sit ups Add more feedback to the user about the exercises Clean up code +0.03: Add software back button on main menu diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js index bc6e35f07..9659ee81f 100644 --- a/apps/banglexercise/app.js +++ b/apps/banglexercise/app.js @@ -71,7 +71,8 @@ function showMainMenu() { let menu; menu = { "": { - title: "BanglExercise" + title: "BanglExercise", + back: load } }; @@ -381,4 +382,5 @@ Bangle.on('HRM', function(hrm) { }); g.clear(1); +Bangle.loadWidgets(); showMainMenu(); diff --git a/apps/banglexercise/metadata.json b/apps/banglexercise/metadata.json index 9bb93f112..f4ce1894b 100644 --- a/apps/banglexercise/metadata.json +++ b/apps/banglexercise/metadata.json @@ -1,7 +1,7 @@ { "id": "banglexercise", "name": "BanglExercise", "shortName":"BanglExercise", - "version":"0.02", + "version":"0.03", "description": "Can automatically track exercises while wearing the Bangle.js watch.", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}], diff --git a/apps/barcode/ChangeLog b/apps/barcode/ChangeLog index 4f99f15ac..7ab5d8587 100644 --- a/apps/barcode/ChangeLog +++ b/apps/barcode/ChangeLog @@ -7,3 +7,4 @@ 0.07: Step count resets at midnight 0.08: Step count stored in memory to survive reloads. Now shows step count daily and since last reboot. 0.09: NOW it really should reset daily (instead of every other day...) +0.10: Tell clock widgets to hide. diff --git a/apps/barcode/barcode.app.js b/apps/barcode/barcode.app.js index 89419f33c..0d9df78d5 100644 --- a/apps/barcode/barcode.app.js +++ b/apps/barcode/barcode.app.js @@ -416,13 +416,13 @@ var layout = new Layout( { // Clear the screen once, at startup g.clear(); +Bangle.setUI("clock"); Bangle.loadWidgets(); Bangle.drawWidgets(); -Bangle.setUI("clock"); layout.render(); Bangle.on('lock', function(locked) { if(!locked) { layout.render(); } -}); \ No newline at end of file +}); diff --git a/apps/barcode/metadata.json b/apps/barcode/metadata.json index cef267b2b..3f6bf06e6 100644 --- a/apps/barcode/metadata.json +++ b/apps/barcode/metadata.json @@ -2,7 +2,7 @@ "name": "Barcode clock", "shortName":"Barcode clock", "icon": "barcode.icon.png", - "version":"0.09", + "version":"0.10", "description": "EAN-8 compatible barcode clock.", "tags": "barcode,ean,ean-8,watchface,clock,clockface", "type": "clock", diff --git a/apps/batclock/ChangeLog b/apps/batclock/ChangeLog index e6e21b146..2a2d91b74 100644 --- a/apps/batclock/ChangeLog +++ b/apps/batclock/ChangeLog @@ -1,2 +1,3 @@ 0.01: App Created! 0.02: Update to use Bangle.setUI instead of setWatch +0.03: Tell clock widgets to hide. diff --git a/apps/batclock/bat-clock.app.js b/apps/batclock/bat-clock.app.js index 31b8f5b9b..dc649160f 100644 --- a/apps/batclock/bat-clock.app.js +++ b/apps/batclock/bat-clock.app.js @@ -249,6 +249,9 @@ g.clear(); g.setColor(0, 0.5, 0).drawImage(bg_crack); g.setColor(1, 1, 1).drawImage(batman); +// Show launcher when button pressed +Bangle.setUI("clock"); + Bangle.loadWidgets(); Bangle.drawWidgets(); @@ -256,5 +259,3 @@ Bangle.drawWidgets(); timeInterval = setInterval(showTime, 1000); showTime(); -// Show launcher when button pressed -Bangle.setUI("clock"); diff --git a/apps/batclock/metadata.json b/apps/batclock/metadata.json index 8aa115780..e6520cb90 100644 --- a/apps/batclock/metadata.json +++ b/apps/batclock/metadata.json @@ -2,7 +2,7 @@ "id": "batclock", "name": "Bat Clock", "shortName": "Bat Clock", - "version": "0.02", + "version": "0.03", "description": "Morphing Clock, with an awesome \"The Dark Knight\" themed logo.", "icon": "bat-clock.png", "screenshots": [{"url":"screenshot.png"}], diff --git a/apps/bclock/ChangeLog b/apps/bclock/ChangeLog index 5b2cf598c..79c198431 100644 --- a/apps/bclock/ChangeLog +++ b/apps/bclock/ChangeLog @@ -1,2 +1,3 @@ 0.02: Modified for use with new bootloader and firmware 0.03: Update to use Bangle.setUI instead of setWatch +0.04: Tell clock widgets to hide. diff --git a/apps/bclock/clock-binary.js b/apps/bclock/clock-binary.js index fdf945ee6..c08a7abe6 100644 --- a/apps/bclock/clock-binary.js +++ b/apps/bclock/clock-binary.js @@ -100,10 +100,12 @@ Bangle.on('lcdPower', on => { if (on) drawClock(); }); +// Show launcher when button pressed +Bangle.setUI("clock"); + g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); setInterval(() => { drawClock(); }, 1000); drawClock(); -// Show launcher when button pressed -Bangle.setUI("clock"); + diff --git a/apps/bclock/metadata.json b/apps/bclock/metadata.json index 94219a30b..c6a24d89f 100644 --- a/apps/bclock/metadata.json +++ b/apps/bclock/metadata.json @@ -1,7 +1,7 @@ { "id": "bclock", "name": "Binary Clock", - "version": "0.03", + "version": "0.04", "description": "A simple binary clock watch face", "icon": "clock-binary.png", "type": "clock", diff --git a/apps/bigdclock/ChangeLog b/apps/bigdclock/ChangeLog index 09cc978fb..c92d139bb 100644 --- a/apps/bigdclock/ChangeLog +++ b/apps/bigdclock/ChangeLog @@ -3,3 +3,5 @@ 0.03: Internationalisation; bug fix - battery icon responds promptly to charging state 0.04: bug fix 0.05: proper fix for the race condition in queueDraw() +0.06: Tell clock widgets to hide. +0.07: Better battery graphic - now has green, yellow and red sections; battery status reflected in the bar across the middle of the screen; current battery state checked only once every 15 minutes, leading to longer-lasting battery charge diff --git a/apps/bigdclock/bigdclock.app.js b/apps/bigdclock/bigdclock.app.js index c013c6188..a8e2b38df 100644 --- a/apps/bigdclock/bigdclock.app.js +++ b/apps/bigdclock/bigdclock.app.js @@ -11,6 +11,8 @@ Graphics.prototype.setFontOpenSans = function(scale) { }; var drawTimeout; +var lastBattCheck = 0; +var width = 0; function queueDraw(millis_now) { if (drawTimeout) clearTimeout(drawTimeout); @@ -24,12 +26,15 @@ function draw() { var date = new Date(); var h = date.getHours(), m = date.getMinutes(); - var d = date.getDate(), - w = date.getDay(); // d=1..31; w=0..6 - const level = E.getBattery(); - const width = level + (level/2); + var d = date.getDate(); var is12Hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"]; - var dows = require("date_utils").dows(0,1); + var dow = require("date_utils").dows(0,1)[date.getDay()]; + + if ((date.getTime() >= lastBattCheck + 15*60000) || Bangle.isCharging()) { + lastBattcheck = date.getTime(); + width = E.getBattery(); + width += width/2; + } g.reset(); g.clear(); @@ -47,24 +52,35 @@ function draw() { g.drawString(d, g.getWidth() -6, 98); g.setFont('Vector', 52); g.setFontAlign(-1, -1); - g.drawString(dows[w].slice(0,2).toUpperCase(), 6, 103); + g.drawString(dow.slice(0,2).toUpperCase(), 6, 103); g.fillRect(9,159,166,171); g.fillRect(167,163,170,167); if (Bangle.isCharging()) { g.setColor(1,1,0); - } else if (level > 40) { - g.setColor(0,1,0); + g.fillRect(12,162,12+width,168); } else { g.setColor(1,0,0); + g.fillRect(12,162,57,168); + g.setColor(1,1,0); + g.fillRect(58,162,72,168); + g.setColor(0,1,0); + g.fillRect(73,162,162,168); } - g.fillRect(12,162,12+width,168); - if (level < 100) { + if (width < 150) { g.setColor(g.theme.bg); g.fillRect(12+width+1,162,162,168); } - g.setColor(0, 1, 0); + if (Bangle.isCharging()) { + g.setColor(1,1,0); + } else if (width <= 45) { + g.setColor(1,0,0); + } else if (width <= 60) { + g.setColor(1,1,0); + } else { + g.setColor(0, 1, 0); + } g.fillRect(0, 90, g.getWidth(), 94); // widget redraw @@ -85,7 +101,8 @@ Bangle.on('charging', (charging) => { draw(); }); +Bangle.setUI("clock"); + Bangle.loadWidgets(); draw(); -Bangle.setUI("clock"); diff --git a/apps/bigdclock/metadata.json b/apps/bigdclock/metadata.json index 7359bcf20..30352ca1a 100644 --- a/apps/bigdclock/metadata.json +++ b/apps/bigdclock/metadata.json @@ -1,7 +1,7 @@ { "id": "bigdclock", "name": "Big digit clock containing just the essentials", "shortName":"Big digit clk", - "version":"0.05", + "version":"0.07", "description": "A clock containing just the essentials, made as easy to read as possible for those of us that need glasses. It contains the time, the day-of-week, the day-of-month, and the current battery state-of-charge.", "icon": "bigdclock.png", "type": "clock", diff --git a/apps/bigdclock/screenshot.png b/apps/bigdclock/screenshot.png index 8a12b266e..acac53ea9 100644 Binary files a/apps/bigdclock/screenshot.png and b/apps/bigdclock/screenshot.png differ diff --git a/apps/binclock/ChangeLog b/apps/binclock/ChangeLog index dc4ed8308..7c31cc0d3 100644 --- a/apps/binclock/ChangeLog +++ b/apps/binclock/ChangeLog @@ -1,3 +1,4 @@ 0.01: New App! 0.02: Fixed bug where screen didn't clear so incorrect time displayed. 0.03: Update to use Bangle.setUI instead of setWatch +0.04: Tell clock widgets to hide. diff --git a/apps/binclock/app.js b/apps/binclock/app.js index f8cbe8dd5..d9c74e6ce 100644 --- a/apps/binclock/app.js +++ b/apps/binclock/app.js @@ -164,9 +164,6 @@ Bangle.on('lcdPower',on=>{ draw(); // draw immediately } }); -// Load widgets -Bangle.loadWidgets(); -Bangle.drawWidgets(); // Show launcher when button pressed Bangle.setUI("clockupdown", btn=>{ if (btn!=1) return; @@ -176,3 +173,6 @@ Bangle.setUI("clockupdown", btn=>{ displayTime = 0; } }); +// Load widgets +Bangle.loadWidgets(); +Bangle.drawWidgets(); diff --git a/apps/binclock/metadata.json b/apps/binclock/metadata.json index d17045868..2ca2755a6 100644 --- a/apps/binclock/metadata.json +++ b/apps/binclock/metadata.json @@ -2,7 +2,7 @@ "id": "binclock", "name": "Binary Clock", "shortName": "Binary Clock", - "version": "0.03", + "version": "0.04", "description": "A binary clock with hours and minutes. BTN1 toggles a digital clock.", "icon": "app.png", "type": "clock", diff --git a/apps/binwatch/ChangeLog b/apps/binwatch/ChangeLog index 1e54f489c..e355155b3 100644 --- a/apps/binwatch/ChangeLog +++ b/apps/binwatch/ChangeLog @@ -2,3 +2,5 @@ 0.02: first running version for BangleJs2 0.03: corrected icon, added screen shot, extended description 0.04: corrected format of background image (raw binary) +0.05: move setUI() up before draw() as to not have a false positive 'sanity +check' when building on github. diff --git a/apps/binwatch/app.js b/apps/binwatch/app.js index 28d7a06a5..153bebb32 100644 --- a/apps/binwatch/app.js +++ b/apps/binwatch/app.js @@ -334,6 +334,7 @@ function setRuntimeValues(resolution) { var hour = 0, minute = 1, second = 50; var batVLevel = 20; +Bangle.setUI("clock"); function draw() { var d = new Date(); @@ -371,7 +372,6 @@ function draw() { } // Show launcher when button pressed -Bangle.setUI("clock"); setRuntimeValues(g.getWidth()); g.reset().clear(); Bangle.loadWidgets(); diff --git a/apps/binwatch/metadata.json b/apps/binwatch/metadata.json index 0b5fb2c72..0b4dbc697 100644 --- a/apps/binwatch/metadata.json +++ b/apps/binwatch/metadata.json @@ -3,7 +3,7 @@ "shortName":"BinWatch", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}], - "version":"0.04", + "version":"0.05", "supports": ["BANGLEJS2"], "readme": "README.md", "allow_emulator":true, diff --git a/apps/blobclk/ChangeLog b/apps/blobclk/ChangeLog index 9c4ef5b7b..193eb5024 100644 --- a/apps/blobclk/ChangeLog +++ b/apps/blobclk/ChangeLog @@ -5,3 +5,4 @@ 0.04: Modified to account for changes in the behavior of Graphics.fillPoly 0.05: Slight increase to draw speed after LCD on 0.06: Update to use Bangle.setUI instead of setWatch, allow themes and different size screens +0.07: Tell clock widgets to hide. diff --git a/apps/blobclk/clock-blob.js b/apps/blobclk/clock-blob.js index c84b8a1e6..d23e18ff9 100644 --- a/apps/blobclk/clock-blob.js +++ b/apps/blobclk/clock-blob.js @@ -99,6 +99,10 @@ function startTimers() { Bangle.drawWidgets(); intervalRef = setInterval(redraw,1000); } + +// Show launcher when button pressed +Bangle.setUI("clock"); + Bangle.loadWidgets(); startTimers(); Bangle.on('lcdPower',function(on) { @@ -108,5 +112,3 @@ Bangle.on('lcdPower',function(on) { clearTimers(); } }); -// Show launcher when button pressed -Bangle.setUI("clock"); diff --git a/apps/blobclk/metadata.json b/apps/blobclk/metadata.json index 85d7deabe..3ae8de222 100644 --- a/apps/blobclk/metadata.json +++ b/apps/blobclk/metadata.json @@ -2,7 +2,7 @@ "id": "blobclk", "name": "Large Digit Blob Clock", "shortName": "Blob Clock", - "version": "0.06", + "version": "0.07", "description": "A clock with big digits", "icon": "clock-blob.png", "type": "clock", diff --git a/apps/boldclk/ChangeLog b/apps/boldclk/ChangeLog index 30ac31c61..0c6e8cb52 100644 --- a/apps/boldclk/ChangeLog +++ b/apps/boldclk/ChangeLog @@ -3,3 +3,4 @@ 0.04: Work with themes, smaller screens 0.05: Adjust hand lengths to be within 'tick' points 0.06: Removed "wake LCD on face-up"-feature: A watch-face should not set things like "wake LCD on face-up". +0.07: Tell clock widgets to hide. diff --git a/apps/boldclk/bold_clock.js b/apps/boldclk/bold_clock.js index 9d3ea0756..763530a32 100644 --- a/apps/boldclk/bold_clock.js +++ b/apps/boldclk/bold_clock.js @@ -130,9 +130,10 @@ Bangle.on('lcdPower', (on) => { } }); +// Show launcher when button pressed +Bangle.setUI("clock"); + g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); startTimers(); -// Show launcher when button pressed -Bangle.setUI("clock"); diff --git a/apps/boldclk/metadata.json b/apps/boldclk/metadata.json index cf961347d..086203142 100644 --- a/apps/boldclk/metadata.json +++ b/apps/boldclk/metadata.json @@ -1,7 +1,7 @@ { "id": "boldclk", "name": "Bold Clock", - "version": "0.06", + "version": "0.07", "description": "Simple, readable and practical clock", "icon": "bold_clock.png", "screenshots": [{"url":"screenshot_bold.png"}], diff --git a/apps/bwclk/ChangeLog b/apps/bwclk/ChangeLog index 8a6fe4f9a..546c83894 100644 --- a/apps/bwclk/ChangeLog +++ b/apps/bwclk/ChangeLog @@ -10,4 +10,14 @@ 0.10: HomeAssistant integration if HomeAssistant is installed. 0.11: Performance improvements. 0.12: Implements a 2D menu. -0.13: Clicks < 24px are for widgets, if fullscreen mode is disabled. \ No newline at end of file +0.13: Clicks < 24px are for widgets, if fullscreen mode is disabled. +0.14: Adds humidity to weather data. +0.15: Added option for a dynamic mode to show widgets only if unlocked. +0.16: You can now show your agenda if your calendar is synced with Gadgetbridge. +0.17: Fix - Step count was no more shown in the menu. +0.18: Set timer for an agenda entry by simply clicking in the middle of the screen. Only one timer can be set. +0.19: Fix - Compatibility with "Digital clock widget" +0.20: Better handling of async data such as getPressure. +0.21: On the default menu the week of year can be shown. +0.22: Use the new clkinfo module for the menu. +0.23: Feedback of apps after run is now optional and decided by the corresponding clkinfo. \ No newline at end of file diff --git a/apps/bwclk/README.md b/apps/bwclk/README.md index eb5356a7e..d869fa2cf 100644 --- a/apps/bwclk/README.md +++ b/apps/bwclk/README.md @@ -1,46 +1,49 @@ # BW Clock -A very minimalistic clock with date and time in focus. +A very minimalistic clock.  ## Features -The BW clock provides many features as well as 3rd party integrations: +The BW clock implements features that are exposed by other apps through the `clkinfo` module. +For example, if you install the HomeAssistant app, this menu item will be shown if you click right +and additionally allows you to send triggers directly from the clock (select triggers via up/down and +send via click center). Here are examples of other apps that are integrated: + - Bangle data such as steps, heart rate, battery or charging state. -- A timer can be set directly. *Requirement: Scheduler library* +- Show agenda entries. A timer for an agenda entry can also be set by simply clicking in the middle of the screen. This can be used to not forget a meeting etc. Note that only one agenda-timer can be set at a time. *Requirement: Gadgetbridge calendar sync enabled* - Weather temperature as well as the wind speed can be shown. *Requirement: Weather app* - HomeAssistant triggers can be executed directly. *Requirement: HomeAssistant app* Note: If some apps are not installed (e.gt. weather app), then this menu item is hidden. -## Menu -2D menu allows you to display lots of different data including data from 3rd party apps and it's also possible to control things e.g. to set a timer or send a HomeAssistant trigger. - -Simply click left / right to go through the menu entries such as Bangle, Timer etc. -and click up/down to move into this sub-menu. You can then click in the middle of the screen -to e.g. send a trigger via HomeAssistant once you selected it. - -``` - +5min - | - Bangle -- Timer[Optional] -- Weather[Optional] -- HomeAssistant [Optional] - | | | | - Bpm -5min Temperature Trigger1 - | | | - Steps ... ... - | - Battery -``` - ## Settings -- Fullscreen on/off (widgets are still loaded). -- Enable/disable lock icon in the settings. Useful if fullscreen is on. +- Screen: Normal (widgets shown), Dynamic (widgets shown if unlocked) or Full (widgets are hidden). +- Enable/disable lock icon in the settings. Useful if fullscreen mode is on. - The colon (e.g. 7:35 = 735) can be hidden in the settings for an even larger time font to improve readability further. -- There are no design settings, as your bangle sys settings are used. +- Your bangle uses the sys color settings so you can change the color too. + +## Menu structure +2D menu allows you to display lots of different data including data from 3rd party apps and it's also possible to control things e.g. to trigger HomeAssistant. + +Simply click left / right to go through the menu entries such as Bangle, Weather etc. +and click up/down to move into this sub-menu. You can then click in the middle of the screen +to e.g. send a trigger via HomeAssistant once you selected it. The actions really depend +on the app that provide this sub-menu through the `clkinfo` module. + +``` + Bangle -- Agenda -- Weather -- HomeAssistant + | | | | + Battery Entry 1 Temperature Trigger1 + | | | | + Steps ... ... ... + | + ... +``` ## Thanks to -Icons created by Flaticon - +- Thanks to Gordon Williams not only for the great BangleJs, but specifically also for the implementation of `clkinfo` which simplified the BWClock a lot and moved complexety to the apps where it should be located. +- Icons created by Flaticon ## Creator [David Peer](https://github.com/peerdavid) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index 2d629abe8..7dcca9d75 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -1,22 +1,25 @@ -/************ +/************************************************ * Includes */ const locale = require('locale'); const storage = require('Storage'); +const clock_info = require("clock_info"); -/************ - * Statics + +/************************************************ + * Globals */ const SETTINGS_FILE = "bwclk.setting.json"; -const TIMER_IDX = "bwclk"; const W = g.getWidth(); const H = g.getHeight(); +var lock_input = false; -/************ + +/************************************************ * Settings */ let settings = { - fullscreen: false, + screen: "Normal", showLock: true, hideColon: false, menuPosX: 0, @@ -28,22 +31,10 @@ for (const key in saved_settings) { settings[key] = saved_settings[key] } - -/************ +/************************************************ * Assets */ // Manrope font -Graphics.prototype.setXLargeFont = function(scale) { - // Actual height 53 (55 - 3) - this.setFontCustom( - E.toString(require('heatshrink').decompress(atob('AHM/8AIG/+AA4sD/wQGh/4EWQA/AC8YA40HNA0BRY8/RY0P/6LFgf//4iFA4IiFj4HBEQkHCAQiDHIIZGv4HCFQY5BDAo5CAAIpDDAfACA3wLYv//hsFKYxcCMgoiBOooiBQwwiBS40AHIgA/ACS/DLYjYCBAjQEBAYQDBAgHDUAbyDZQi3CegoHEVQQZFagUfW4Y0DaAgECaIJSEFYMPbIYNDv5ACGAIrBCgJ1EFYILCAAQWCj4zDGgILCegcDEQRNDHIIiCHgZ2BEQShFIqUDFYidCh5ODg4NCn40DAgd/AYR5BDILZEAAIMDAAYVCh7aHdYhKDbQg4Dv7rGBAihFCAwIDCAgA/AB3/eoa7GAAk/dgbVGDJrvCDK67DDIjaGdYpbCdYonCcQjjDEVUBEQ4A/AEMcAYV/NAUHcYUDawd/cYUPRYSmBBgaLBToP8BgYiBSgIiCj4iCg//EQSuDW4IMDVwYiCBgIiBBgrRDCATeBaIYqCv70DCgT4CEQMfIgQZBBoRnDv/3EQIvBDIffEQMHFwReBRYUfOgX/+IiDKIeHEQRRECwUHKwIuB8AiDIoJEBCwZFCv/4HIZaBIgPAEQS2CUYQiCD4SABEQcfOwIZBEQaHBO4RcEAAI/BEQQgBSIQiDTIRZBEQZuBVYQiDHoKWCEQQICFQIiDBAQeCEQQA/AANwA40BLIJ5BO4JWCBAUPAYR5En7RBUIQECN4SYCQQIiEh6CCEQk/BoQiBgYeCBoTrCAgT0CCgIfCFYQiBg4IBGgIiDj6rBg4rCBYLRDFYIiBbYIfBLgQiBIQYiD4JCCLgf/bQIWDBYV/EQV/BYXz/5FBgIiD5//IowZBD4M/NAX/BIPgDIJoC//5GgKUDn//4f/8KLE/wTBAAI8BEQPwj4HBVwYmBDgIZDN4QZCGYKJCHQP/JoSgCBATrCh5dBKITVDG4gICAAbvDAH5SCL4QADK4J5CCAiTCCAp1BCAqCDCAgiGCAIiFCAQiFeoIiFg6/FCAgiECAXnEQgQB/kfEQYQC4F/EQYQCgIiDfoIQBg4iDCAUAEQZUCcgIiDDIIQBEQhuBBoIiENoYiFDwQiECAQiFwEBPQQNCAQKDDEYMDDoMfRh4iGUwqvEESBiBaQ5oEbgr0FNAo+EEIwA+oAHGgJoFRAMHe4L0CAALNBBAT0BfwScDCAXweAL0DWgUPQYQiDwF/QYQiC/zTB+C0FBAL0CEQYIBGgMPCgIxBg4rCJIKsCh5IBBwTPCj4WBgYLBZ4V/MAIiBBQQrBEQYtCBYQiCO4QLFCwgiDIQIiGIoMHEQpFBn5FFD4JoENwRoGDgSUCAoKfBw//DgIiCT4auCFwN/T4RRET4TaCEQKoCDIQiCGgK/DAAQICdYQACHoIqCBAoQFEwIhFAH4AFQIROEj4IGXwIIGNwIACbgIhEBAiRCVwoqDTogHEW4QZFXgIZB/z9Cv49CF4MPBwI0Ca4LlB8ATCJoP4AoINDfQPAg7PBg4cBBwUfD4MfFYILCCwgOCf4QLEwEPCwILCgJaBn4WBBYQxCIQQiD+EDCYI5CBYRQBIo4fBMQIuBC4N/NAv8AoIcBSgU/FYIIBZIYrCW4hOCXIQZCgYUBv7jEh4uBZAscewZ8CgEgUYT0EEoQIBA4gICFQQIEHYQA+KQzdDAArdCAArpCEScHaIQiEvwiGe4QiFUwQiEbgIiFYIL0DEQTkBEQrJEEQc/cYYiCg4HBDIQiCfoRoEHQLaDEQQHBbQYiBCAT8Dn/BCAoXBJYP/OgZKC/6OEEARLCEQZLEEQZLEEQjKFEQI6EEQZLDEQbsGEQLjGYYYA/JIxzEg/AfgJSDAoPgfgiDC8COFAoPnaQj6CAAR+CW4TCFA4i6CDIqhCDIfwHoYHCYIN/GgKuBJ4JDBFYUf/C5CBYIZBv/Ag4ZBg4rBBYQTBAQIcBg4FBn5UBAQUfFwIfCEQeAgYfBAQUBFAKbCAQQiCGwIiE+A2BwBFNwE/AoM/EQJoIWwKCCh4cBFYKUERYV/W46uHFYIZGaJA0B/glBGYT0JIITiEMIJvCFQQAEHYQA/ABBlEOIhdGQAIRFSgQIBgQICn4IB8EAjiBCUYglCbQYeBEoQZCTwM/CYIZD/gEBUwIzBJ4UHYAU/EwIrBh4rCAoIXCn4rBCgUDAQN/FYMfBYIXBCYJnCBYXggf8HgQLCwEPEQQuBgJOECwILDCwgiLHIUHBYJFGD4IxBgYWCn4rBBwJoFDIYNBCgPADgKHBRYfDBQN/GAIrBToTLDVwYACDILiCWAb8DAAYzBYAjTCAAI9BAARNCBAoqCBAgQDFgbYCAH4AufgQACf4T8CAAT/CfgQACBwITCAAYOBCYQioh4iEAHQA=='))), - 46, - atob("FR4uHyopKyksJSssGA=="), - 70+(scale<<8)+(1<<16) - ); -}; - - Graphics.prototype.setLargeFont = function(scale) { // Actual height 47 (48 - 2) this.setFontCustom( @@ -55,14 +46,12 @@ Graphics.prototype.setLargeFont = function(scale) { return this; }; - Graphics.prototype.setMediumFont = function(scale) { // Actual height 41 (42 - 2) this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAA/AAAAAAAA/AAAAAAAA/AAAAAAAA/AAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAAAB/AAAAAAAP/AAAAAAD//AAAAAA///AAAAAP///AAAAB///8AAAAf///AAAAH///wAAAB///+AAAAH///gAAAAH//4AAAAAH/+AAAAAAH/wAAAAAAH8AAAAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///8AAAAH////AAAAP////wAAAf////4AAA/////8AAB/////+AAD/gAAH+AAD+AAAD/AAH8AAAB/AAH4AAAA/gAH4AAAAfgAH4AAAAfgAPwAAAAfgAPwAAAAfgAPwAAAAfgAHwAAAAfgAH4AAAAfgAH4AAAA/gAH8AAAA/AAD+AAAD/AAD/gAAH/AAB/////+AAB/////8AAA/////4AAAf////wAAAH////gAAAB///+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAAAAAfwAAAAAAA/gAAAAAAA/AAAAAAAB/AAAAAAAD+AAAAAAAD8AAAAAAAH8AAAAAAAH//////AAH//////AAH//////AAH//////AAH//////AAH//////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAA/AAAP4AAB/AAAf4AAD/AAA/4AAD/AAB/4AAH/AAD/4AAP/AAH/AAAf/AAH8AAA//AAH4AAB//AAP4AAD//AAPwAAH+/AAPwAAP8/AAPwAAf4/AAPwAA/4/AAPwAA/w/AAPwAB/g/AAPwAD/A/AAP4AH+A/AAH8AP8A/AAH/A/4A/AAD///wA/AAD///gA/AAB///AA/AAA//+AA/AAAP/8AA/AAAD/wAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAH4AAAHwAAH4AAAH4AAH4AAAH8AAH4AAAP+AAH4AAAH+AAH4A4AB/AAH4A+AA/AAH4B/AA/gAH4D/AAfgAH4H+AAfgAH4P+AAfgAH4f+AAfgAH4/+AAfgAH5/+AAfgAH5//AAfgAH7+/AA/gAH/8/gB/AAH/4f4H/AAH/wf//+AAH/gP//8AAH/AH//8AAH+AD//wAAH8AB//gAAD4AAf+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAD/AAAAAAAP/AAAAAAB//AAAAAAH//AAAAAAf//AAAAAB///AAAAAH///AAAAAf/8/AAAAB//w/AAAAH/+A/AAAA//4A/AAAD//gA/AAAH/+AA/AAAH/4AA/AAAH/gAA/AAAH+AAA/AAAHwAAA/AAAHAAf///AAEAAf///AAAAAf///AAAAAf///AAAAAf///AAAAAf///AAAAAAA/AAAAAAAA/AAAAAAAA/AAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAP/AHgAAH///AP4AAH///gP8AAH///gP8AAH///gP+AAH///gD/AAH/A/AB/AAH4A/AA/gAH4A+AAfgAH4B+AAfgAH4B+AAfgAH4B8AAfgAH4B8AAfgAH4B+AAfgAH4B+AAfgAH4B+AA/gAH4B/AA/AAH4A/gD/AAH4A/4H+AAH4Af//+AAH4AP//8AAH4AP//4AAHwAD//wAAAAAB//AAAAAAAf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///8AAAAD////AAAAP////wAAAf////4AAA/////8AAB/////+AAD/gP4H+AAD/AfgD/AAH8A/AB/AAH8A/AA/gAH4B+AAfgAH4B+AAfgAPwB8AAfgAPwB8AAfgAPwB+AAfgAPwB+AAfgAH4B+AAfgAH4B/AA/gAH8B/AB/AAH+A/wD/AAD+A/8P+AAB8Af//+AAB4AP//8AAAwAH//4AAAAAD//gAAAAAA//AAAAAAAP4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPwAAAAAAAPwAAAAAAAPwAAAAAAAPwAAAAAAAPwAAAAHAAPwAAAA/AAPwAAAD/AAPwAAAf/AAPwAAB//AAPwAAP//AAPwAA//8AAPwAH//wAAPwAf/+AAAPwB//4AAAPwP//AAAAPw//8AAAAP3//gAAAAP//+AAAAAP//wAAAAAP//AAAAAAP/4AAAAAAP/gAAAAAAP+AAAAAAAHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+AAAAH+A//gAAAf/h//4AAA//z//8AAB/////+AAD/////+AAD///+H/AAH+H/4B/AAH8B/wA/gAH4A/gAfgAH4A/gAfgAPwA/AAfgAPwA/AAfgAPwA/AAfgAPwA/AAfgAH4A/gAfgAH4A/gAfgAH8B/wA/gAH/H/4B/AAD///+H/AAD/////+AAB/////+AAA//z//8AAAf/h//4AAAH+A//gAAAAAAH+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/gAAAAAAD/8AAAAAAP/+AAAAAAf//AAcAAA///gA8AAB///wB+AAD/x/4B/AAD+AP4B/AAH8AH8A/gAH4AH8A/gAH4AD8AfgAP4AD8AfgAPwAB8AfgAPwAB8AfgAPwAB8AfgAPwAB8AfgAH4AD8AfgAH4AD4A/gAH8AH4B/AAD+APwD/AAD/g/wP+AAB/////+AAA/////8AAAf////4AAAP////wAAAH////AAAAA///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8APwAAAAD8APwAAAAD8APwAAAAD8APwAAAAD8APwAAAAD8APwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("DxcjFyAfISAiHCAiEg=="), 54+(scale<<8)+(1<<16)); return this; }; - Graphics.prototype.setSmallFont = function(scale) { // Actual height 28 (27 - 0) this.setFontCustom( @@ -74,6 +63,16 @@ Graphics.prototype.setSmallFont = function(scale) { return this; }; +Graphics.prototype.setMiniFont = function(scale) { + // Actual height 16 (15 - 0) + this.setFontCustom( + atob('AAAAAAAAAAAAAP+w/5AAAAAA4ADgAOAA4AAAAAAAAAABgBmAGbAb8D+A+YDZ8B/wf4D5gJmAGQAQAAAAAAAeOD8cMwzxj/GPMYwc/Az4AAAAAHAA+DDIYMjA+YBzAAYADeA7MHMw4zDD4ADAAAAz4H/wzjDHMMMwwbBj4APgADAAAAAA4ADgAAAAAAAAAAfwH/54B+ABAAAAAOABeAcf/gfwAAAAACAAaAD4APgAOABgAAAAAAACAAIAAgA/wAMAAgACAAAAAAAAPAA4AAAAAAIAAgACAAIAAgAAAAAAADAAMAAAAAAAcAfwf4D4AIAAAAA/wH/gwDDAMMAwwDB/4D/AAAAAAGAAwAD/8P/wAAAAAHAw8HDA8MHww7DnMH4wGBAAAMBgyHDcMPww/DDv4MfAAAAAAAHgD+A+YPhgwGAH8AfwAEAAAAAA/GD8cMwwzDDMMM5wx+ABgAAAP8B/4MwwzDDMMMwwx+ADwAAAgADAAMBwwfDPgP4A8ADAAAAAe+D/8M4wxjDGMP5wf+ABwAAAfAB+cMYwwjDCMMYwf+A/wAAAAAAAAAxgBCAAAAAAAAAYPBA4AAAAAAAAAgAHAA+AHMAYYAAAAAAAAAAAAAAJAAkACQAJAAkACQAJAAkAAAAAAAAAAAAAABhgHMAPgAcAAgAAAAAAAABgAOAAwbDDsMYA/AA4AAAAAAAD4A/wGBgxzDPsMyQjJDPkM+wYIBxgD+AAAAAAABAA8A/gf8DwwODA/sAfwAHwADAAAP/w//DGMMYwxjDOMP9we+ABwA8AP8Bw4MAwwDDAMMAwwDDgcHDgMMAAAAAA//D/8MAwwDDAMMAw4HB/4D/AAAAAAP/w//DGMMYwxjDGMMQwgBAAAP/w//DDAMMAwwDDAMAADwA/wHDgwDDAMMAwwDDCMOJwc+ADwAAA//D/8AMAAwADAAMAAwD/8P/wAAAAAP/w//AAAABgAHAAMAAwAHD/4P+AAAAAAP/w//AOAB+AOcBw4MBwgDAAEAAA//D/8AAwADAAMAAwADAAAP/w//A8AA8AA+AA8AHwB8AeAHgA//D/8AAAAAD/8P/wcAAcAA8AA4AB4P/w//AAAA8AP8Bw4MAwwDDAMMAwwDDgcH/gP8AAAAAA//D/8MMAwwDDAMYA7gB8ABgADwA/wHDgwDDAMMAwwDDA8ODwf/A/8AAAAAD/8P/wwwDDAMMAx4Dv4HxwEBAAAHjg/HDMMMYwxjDGMONwc+ABwMAAwADAAMAA//D/8MAAwADAAIAAAAD/wP/gAHAAMAAwADAAMAHg/8AAAMAA+AA/AAfgAPAA8AfgPwD4AMAAwAD4AD+AA/AA8A/g/gDwAP4AH8AB8APwH8D8AMAAgBDAMPDgO8APAB8AOcDw8MAwgBCAAOAAeAAeAAfwH/B4AOAAwAAAAMAwwPDB8Mew3jD4MPAwwDAAAAAAAAB//3//QABAAAAAAADgAP4AH+AB8AAQAABAAEAAf/9//wAAAAAAAAAAGAAwAGAAwABgADAAGAAAAAAAAAQABAAEAAQABAAEAAQABAAEAAQABAAAAAAAAAAAAAAAAAAAAAAAQA3wHbAZMBswGzAf4A/wAAAAAP/w//AYMBgwGDAYMA/gB8AAAAEAD+Ae8BgwGDAYMBgwDGAAAAMAD+Ae8BgwGDAYMBhw//D/8AAAAYAP4B/wGTAZMBkwGTAP4AcAEAAYAP/w//CQAJAAAwAP4hz3GDMQMxAzGHcf/h/8AAAAAP/w//AYABgAGAAYAA/wB/AAAAAA3/Df8AAAAAOf/9//AAAAAP/w//ADgAfADGAYMBAQAAD/8P/wAAAAAB/wH/AYABgAGAAf8A/wGAAYABgAH/AP8AAAAAAf8B/wGAAYABgAGAAP8AfwAAADAA/gHvAYMBgwGDAYMA/gB8AAAAAAH/8f/xgwGDAYMBgwD+AHwAAAAwAP4B7wGDAYMBgwGHAf/x//AAAAAB/wH/AYABgAEAAAAA5gHzAbMBkwGbAd8AzgEAAYAP/wf/AQMBAwAAAAAB/gH/AAMAAwADAAcB/wH/AAABAAHgAPwAHwAPAH4B8AGAAQAB8AB+AA8APwHwAeAA/AAPAD8B+AHAAQEBgwHOAHwAOAD+AccBAwAAAQAB4AD4EB/wB8A/APgBwAAAAAEBgwGPAZ8B8wHjAcMBAQAAAAAABgf/9/n2AAAAAAAP/w//AAAEAAYAB/nz//AGAAAAAAAAAAAAcABgAGAAcAAwAHAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'), + 32, + atob("AwUHDwoOCwQHBwcJBAcEBgoGCQkKCQoICQoFBQoMCgkPCgoMCwkICwsECAoIDgsMCgwKCgoLCg8KCQoHBgcLCwgJCgkKCQYKCgQECAQOCgoKCgYIBwoIDAkJCAcEBwsQ"), + 16+(scale<<8)+(1<<16) + ); + return this; +}; function imgLock(){ return { @@ -83,279 +82,100 @@ function imgLock(){ } } -function imgSteps(){ - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("/H///wv4CBn4CD8ACCj4IBj8f+Eeh/wjgCBngCCg/4nEH//4h/+jEP/gRBAQX+jkf/wgB//8GwP4FoICDHgICCBwIA==")) - } -} -function imgBattery(){ - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("/4AN4EAg4TBgd///9oEAAQv8ARQRDDQQgCEwQ4OA")) - } -} - -function imgCharging() { - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("//+v///k///4AQPwBANgBoMxBoMb/P+h/w/kH8H4gfB+EBwfggHH4EAt4CBn4CBj4CBh4FCCIO/8EB//Agf/wEH/8Gh//x////fAQIA=")) - } -} - -function imgBpm() { - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("/4AOn4CD/wCCjgCCv/8jF/wGYgOA5MB//BC4PDAQnjAQPnAQgANA")) - } -} - -function imgTemperature() { - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("//D///wICBjACBngCNkgCP/0kv/+s1//nDn/8wICEBAIOC/08v//IYJECA==")) - } -} - -function imgWeather(){ - return { - width : 24, height : 24, bpp : 1, - transparent : 0, - buffer : require("heatshrink").decompress(atob("AAcYAQ0MgEwAQUAngLB/8AgP/wACCgf/4Fz//OAQQICCIoaCEAQpGHA4ACA=")) - } -} - -function imgWind () { - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("/0f//8h///Pn//zAQXzwf/88B//mvGAh18gEevn/DIICB/PwgEBAQMHBAIADFwM/wEAGAP/54CD84CE+eP//wIQU/A==")) - } -} - -function imgTimer() { - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("/+B/4CD84CEBAPygFP+F+h/x/+P+fz5/n+HnAQNn5/wuYCBmYCC5kAAQfOgFz80As/ngHn+fD54mC/F+j/+gF/HAQA==")) - } -} - -function imgWatch() { - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("/8B//+ARANB/l4//5/1/+f/n/n5+fAQnf9/P44CC8/n7/n+YOB/+fDQQgCEwQsCHBBEC")) - } -} - -function imgHomeAssistant() { - return { - width : 48, height : 48, bpp : 1, - transparent : 0, - buffer : require("heatshrink").decompress(atob("AD8BwAFDg/gAocP+AFDj4FEn/8Aod//wFD/1+FAf4j+8AoMD+EPDAUH+OPAoUP+fPAoUfBYk/C4l/EYIwC//8n//FwIFEgYFD4EH+E8nkP8BdBAonjjk44/wj/nzk58/4gAFDF4PgCIMHAoPwhkwh4FB/EEkEfIIWAHwIFC4A+BAoXgg4FDL4IFDL4IFDLIYFkAEQA==")) - } -} - - -/************ - * 2D MENU with entries of: - * [name, icon, opt[customDownFun], opt[customUpFun], opt[customCenterFun]] - * +/************************************************ + * Menu */ -var menu = [ - [ - function(){ return [ null, null ] }, - ], - [ - function(){ return [ "Bangle", imgWatch() ] }, - function(){ return [ E.getBattery() + "%", Bangle.isCharging() ? imgCharging() : imgBattery() ] }, - function(){ return [ getSteps(), imgSteps() ] }, - function(){ return [ Math.round(Bangle.getHealthStatus("last").bpm) + " bpm", imgBpm()] }, +// Custom bwItems menu - therefore, its added here and not in a clkinfo.js file. +var bwItems = { + name: null, + img: null, + items: [ + { name: "WeekOfYear", + get: () => ({ text: "Week " + weekOfYear(), img: null}), + show: function() { bwItems.items[0].emit("redraw"); }, + hide: function () {} + }, ] -] +}; -/* - * Timer Menu - */ -try{ - require('sched'); - menu.push([ - function(){ - var text = isAlarmEnabled() ? getAlarmMinutes() + " min." : "Timer"; - return [text, imgTimer(), () => decreaseAlarm(), () => increaseAlarm(), null ] - }, - ]); -} catch(ex) { - // If sched is not installed, we hide this menu item -} - -/* - * WEATHER MENU - */ -if(storage.readJSON('weather.json') !== undefined){ - menu.push([ - function(){ return [ "Weather", imgWeather() ] }, - function(){ return [ getWeather().temp, imgTemperature() ] }, - function(){ return [ getWeather().wind, imgWind() ] }, - ]); +function weekOfYear() { + var date = new Date(); + date.setHours(0, 0, 0, 0); + // Thursday in current week decides the year. + date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7); + // January 4 is always in week 1. + var week1 = new Date(date.getFullYear(), 0, 4); + // Adjust to Thursday in week 1 and count number of weeks from date to week1. + return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 + - 3 + (week1.getDay() + 6) % 7) / 7); } -/* - * HOME ASSISTANT MENU - */ -try{ - var triggers = require("ha.lib.js").getTriggers(); - var haMenu = [ - function(){ return [ "Home", imgHomeAssistant() ] }, - ]; +// Load menu +var menu = clock_info.load(); +menu = menu.concat(bwItems); - triggers.forEach(trigger => { - haMenu.push(function(){ - return [trigger.display, trigger.getIcon(), () => {}, () => {}, function(){ - var ha = require("ha.lib.js"); - ha.sendTrigger("TRIGGER_BW"); - ha.sendTrigger(trigger.trigger); - }] - }); + +// Ensure that our settings are still in range (e.g. app uninstall). Otherwise reset the position it. +if(settings.menuPosX >= menu.length || settings.menuPosY > menu[settings.menuPosX].items.length ){ + settings.menuPosX = 0; + settings.menuPosY = 0; +} + +// Set draw functions for each item +menu.forEach((menuItm, x) => { + menuItm.items.forEach((item, y) => { + function drawItem() { + // For the clock, we have a special case, as we don't wanna redraw + // immediately when something changes. Instead, we update data each minute + // to save some battery etc. Therefore, we hide (and disable the listener) + // immedeately after redraw... + item.hide(); + + // After drawing the item, we enable inputs again... + lock_input = false; + + var info = item.get(); + drawMenuItem(info.text, info.img); + } + + item.on('redraw', drawItem); }) - menu.push(haMenu); -} catch(ex){ - // If HomeAssistant is not installed, we hide this item -} +}); -function getMenuEntry(){ - // In case the user removes HomeAssistant entries, showInfo - // could be larger than infoArray.length... - settings.menuPosX = settings.menuPosX % menu.length; - settings.menuPosY = settings.menuPosY % menu[settings.menuPosX].length; - return menu[settings.menuPosX][settings.menuPosY](); -} - - -/************ - * Helper - */ -function getSteps() { - var steps = 0; - try{ - if (WIDGETS.wpedom !== undefined) { - steps = WIDGETS.wpedom.getSteps(); - } else if (WIDGETS.activepedom !== undefined) { - steps = WIDGETS.activepedom.getSteps(); - } else { - steps = Bangle.getHealthStatus("day").steps; - } - } catch(ex) { - // In case we failed, we can only show 0 steps. +function canRunMenuItem(){ + if(settings.menuPosY == 0){ + return false; } - steps = Math.round(steps/100) / 10; // This ensures that we do not show e.g. 15.0k and 15k instead - return steps + "k"; + var menuEntry = menu[settings.menuPosX]; + var item = menuEntry.items[settings.menuPosY-1]; + return item.run !== undefined; } -function getWeather(){ - var weatherJson; - - try { - weatherJson = storage.readJSON('weather.json'); - var weather = weatherJson.weather; - - // Temperature - weather.temp = locale.temp(weather.temp-273.15); - - // Humidity - weather.hum = weather.hum + "%"; - - // Wind - const wind = locale.speed(weather.wind).match(/^(\D*\d*)(.*)$/); - weather.wind = Math.round(wind[1]) + "kph"; - - return weather - - } catch(ex) { - // Return default +function runMenuItem(){ + if(settings.menuPosY == 0){ + return; } - return { - temp: " ? ", - hum: " ? ", - txt: " ? ", - wind: " ? ", - wdir: " ? ", - wrose: " ? " - }; -} - - -function isAlarmEnabled(){ + var menuEntry = menu[settings.menuPosX]; + var item = menuEntry.items[settings.menuPosY-1]; try{ - var alarm = require('sched'); - var alarmObj = alarm.getAlarm(TIMER_IDX); - if(alarmObj===undefined || !alarmObj.on){ - return false; + var ret = item.run(); + if(ret){ + Bangle.buzz(300, 0.6); } - - return true; - - } catch(ex){ } - return false; -} - - -function getAlarmMinutes(){ - if(!isAlarmEnabled()){ - return -1; + } catch (ex) { + // Simply ignore it... } - - var alarm = require('sched'); - var alarmObj = alarm.getAlarm(TIMER_IDX); - return Math.round(alarm.getTimeToAlarm(alarmObj)/(60*1000)); } -function increaseAlarm(){ - try{ - var minutes = isAlarmEnabled() ? getAlarmMinutes() : 0; - var alarm = require('sched') - alarm.setAlarm(TIMER_IDX, { - timer : (minutes+5)*60*1000, - }); - alarm.reload(); - } catch(ex){ } -} - - -function decreaseAlarm(){ - try{ - var minutes = getAlarmMinutes(); - minutes -= 5; - - var alarm = require('sched') - alarm.setAlarm(TIMER_IDX, undefined); - - if(minutes > 0){ - alarm.setAlarm(TIMER_IDX, { - timer : minutes*60*1000, - }); - } - - alarm.reload(); - } catch(ex){ } -} - - -/************ - * DRAW +/************************************************ + * Draw */ function draw() { // Queue draw again @@ -363,7 +183,7 @@ function draw() { // Draw clock drawDate(); - drawTime(); + drawMenuAndTime(); drawLock(); drawWidgets(); } @@ -371,12 +191,12 @@ function draw() { function drawDate(){ // Draw background - var y = H/5*2; - g.reset().clearRect(0,0,W,W); + var y = H/5*2 + (isFullscreen() ? 0 : 8); + g.reset().clearRect(0,0,W,y); // Draw date y = parseInt(y/2)+4; - y += settings.fullscreen ? 0 : 13; + y += isFullscreen() ? 0 : 8; var date = new Date(); var dateStr = date.getDate(); dateStr = ("0" + dateStr).substr(-2); @@ -395,15 +215,12 @@ function drawDate(){ g.setMediumFont(); g.setColor(g.theme.fg); - g.drawString(dateStr, W/2 - fullDateW / 2, y+1); + g.drawString(dateStr, W/2 - fullDateW / 2, y+2); } -function drawTime(){ +function drawTime(y, smallText){ // Draw background - var y = H/5*2 + (settings.fullscreen ? 0 : 8); - g.setColor(g.theme.fg); - g.fillRect(0,y,W,H); var date = new Date(); // Draw time @@ -419,45 +236,65 @@ function drawTime(){ // Set y coordinates correctly y += parseInt((H - y)/2) + 5; - var menuEntry = getMenuEntry(); - var menuName = menuEntry[0]; - var menuImg = menuEntry[1]; - var printImgLeft = settings.menuPosY != 0; - // Show large or small time depending on info entry - if(menuName == null){ - if(settings.hideColon){ - g.setXLargeFont(); - } else { - g.setLargeFont(); - } - } else { + if(smallText){ y -= 15; g.setMediumFont(); + } else { + g.setLargeFont(); } g.drawString(timeStr, W/2, y); +} - // Draw menu if set - if(menuName == null){ +function drawMenuItem(text, image){ + // First clear the time region + var y = H/5*2 + (isFullscreen() ? 0 : 8); + + g.setColor(g.theme.fg); + g.fillRect(0,y,W,H); + + // Draw menu text + var hasText = (text != null && text != ""); + if(hasText){ + g.setFontAlign(0,0); + + // For multiline text we show an even smaller font... + text = String(text); + if(text.split('\n').length > 1){ + g.setMiniFont(); + } else { + g.setSmallFont(); + } + + var imgWidth = image == null ? 0 : 24; + var strWidth = g.stringWidth(text); + g.setColor(g.theme.fg).fillRect(0, 149-14, W, H); + g.setColor(g.theme.bg).drawString(text, W/2 + imgWidth/2 + 2, 149+3); + + if(image != null){ + var scale = imgWidth / image.width; + g.drawImage(image, W/2 + -strWidth/2-4 - parseInt(imgWidth/2), 149 - parseInt(imgWidth/2), {scale: scale}); + } + } + + // Draw time + drawTime(y, hasText); +} + + +function drawMenuAndTime(){ + var menuEntry = menu[settings.menuPosX]; + + // The first entry is the overview... + if(settings.menuPosY == 0){ + drawMenuItem(menuEntry.name, menuEntry.img); return; } - y += 35; - g.setFontAlign(0,0); - g.setSmallFont(); - var imgWidth = 0; - if(menuImg !== undefined){ - imgWidth = 24.0; - var strWidth = g.stringWidth(menuName); - var scale = imgWidth / menuImg.width; - g.drawImage( - menuImg, - W/2 + (printImgLeft ? -strWidth/2-2 : strWidth/2+2) - parseInt(imgWidth/2), - y - parseInt(imgWidth/2), - { scale: scale } - ); - } - g.drawString(menuName, printImgLeft ? W/2 + imgWidth/2 + 2 : W/2 - imgWidth/2 - 2, y+3); + // Draw item if needed + lock_input = true; + var item = menuEntry.items[settings.menuPosY-1]; + item.show(); } @@ -470,7 +307,7 @@ function drawLock(){ function drawWidgets(){ - if(settings.fullscreen){ + if(isFullscreen()){ for (let wd of WIDGETS) {wd.draw=()=>{};wd.area="";} } else { Bangle.drawWidgets(); @@ -478,9 +315,19 @@ function drawWidgets(){ } +function isFullscreen(){ + var s = settings.screen.toLowerCase(); + if(s == "dynamic"){ + return Bangle.isLocked() + } else { + return s == "full" + } +} -/* - * Draw timeout + + +/************************************************ + * Listener */ // timeout used to update every minute var drawTimeout; @@ -508,6 +355,13 @@ Bangle.on('lcdPower',on=>{ Bangle.on('lock', function(isLocked) { if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; + + if(!isLocked && settings.screen.toLowerCase() == "dynamic"){ + // If we have to show the widgets again, we load it from our + // cache and not through Bangle.loadWidgets as its much faster! + for (let wd of WIDGETS) {wd.draw=wd._draw;wd.area=wd._area;} + } + draw(); }); @@ -516,13 +370,13 @@ Bangle.on('charging',function(charging) { drawTimeout = undefined; // Jump to battery - settings.menuPosX = 1; + settings.menuPosX = 0; settings.menuPosY = 1; draw(); }); Bangle.on('touch', function(btn, e){ - var widget_size = settings.fullscreen ? 0 : 20; // Its not exactly 24px -- empirically it seems that 20 worked better... + var widget_size = isFullscreen() ? 0 : 20; // Its not exactly 24px -- empirically it seems that 20 worked better... var left = parseInt(g.getWidth() * 0.22); var right = g.getWidth() - left; var upper = parseInt(g.getHeight() * 0.22) + widget_size; @@ -534,17 +388,15 @@ Bangle.on('touch', function(btn, e){ var is_right = e.x > right && !is_upper && !is_lower; var is_center = !is_upper && !is_lower && !is_left && !is_right; + if(lock_input){ + return; + } + if(is_lower){ Bangle.buzz(40, 0.6); - settings.menuPosY = (settings.menuPosY+1) % menu[settings.menuPosX].length; + settings.menuPosY = (settings.menuPosY+1) % (menu[settings.menuPosX].items.length+1); - // Handle custom menu entry function - var menuEntry = getMenuEntry(); - if(menuEntry.length > 2){ - menuEntry[2](); - } - - drawTime(); + drawMenuAndTime(); } if(is_upper){ @@ -554,22 +406,16 @@ Bangle.on('touch', function(btn, e){ Bangle.buzz(40, 0.6); settings.menuPosY = settings.menuPosY-1; - settings.menuPosY = settings.menuPosY < 0 ? menu[settings.menuPosX].length-1 : settings.menuPosY; + settings.menuPosY = settings.menuPosY < 0 ? menu[settings.menuPosX].items.length : settings.menuPosY; - // Handle custom menu entry function - var menuEntry = getMenuEntry(); - if(menuEntry.length > 3){ - menuEntry[3](); - } - - drawTime(); + drawMenuAndTime(); } if(is_right){ Bangle.buzz(40, 0.6); settings.menuPosX = (settings.menuPosX+1) % menu.length; settings.menuPosY = 0; - drawTime(); + drawMenuAndTime(); } if(is_left){ @@ -577,23 +423,12 @@ Bangle.on('touch', function(btn, e){ settings.menuPosY = 0; settings.menuPosX = settings.menuPosX-1; settings.menuPosX = settings.menuPosX < 0 ? menu.length-1 : settings.menuPosX; - drawTime(); + drawMenuAndTime(); } if(is_center){ - var menuEntry = getMenuEntry(); - if(menuEntry.length > 4){ - Bangle.buzz(80, 0.6).then(()=>{ - try{ - menuEntry[4](); - setTimeout(()=>{ - Bangle.buzz(80, 0.6); - }, 250); - } catch(ex){ - // In case it fails, we simply ignore it. - } - } - ); + if(canRunMenuItem()){ + runMenuItem(); } } }); @@ -608,17 +443,24 @@ E.on("kill", function(){ }); -/* - * Draw clock the first time +/************************************************ + * Startup Clock */ + // The upper part is inverse i.e. light if dark and dark if light theme // is enabled. In order to draw the widgets correctly, we invert the // dark/light theme as well as the colors. g.setTheme({bg:g.theme.fg,fg:g.theme.bg, dark:!g.theme.dark}).clear(); -// Load widgets and draw clock the first time -Bangle.loadWidgets(); -draw(); - // Show launcher when middle button pressed Bangle.setUI("clock"); + +// Load widgets and draw clock the first time +Bangle.loadWidgets(); + +// Cache draw function for dynamic screen to hide / show widgets +// Bangle.loadWidgets() could also be called later on but its much slower! +for (let wd of WIDGETS) {wd._draw=wd.draw; wd._area=wd.area;} + +// Draw first time +draw(); diff --git a/apps/bwclk/metadata.json b/apps/bwclk/metadata.json index 45d337ebf..fbae0e1e7 100644 --- a/apps/bwclk/metadata.json +++ b/apps/bwclk/metadata.json @@ -1,8 +1,8 @@ { "id": "bwclk", "name": "BW Clock", - "version": "0.13", - "description": "A very minimalistic clock with date and time in focus.", + "version": "0.23", + "description": "A very minimalistic clock to mainly show date and time.", "readme": "README.md", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}, {"url":"screenshot_2.png"}, {"url":"screenshot_3.png"}, {"url":"screenshot_4.png"}], diff --git a/apps/bwclk/screenshot_3.png b/apps/bwclk/screenshot_3.png index f9a9a7d3f..8d982cac4 100644 Binary files a/apps/bwclk/screenshot_3.png and b/apps/bwclk/screenshot_3.png differ diff --git a/apps/bwclk/settings.js b/apps/bwclk/settings.js index a421e81a9..116253fda 100644 --- a/apps/bwclk/settings.js +++ b/apps/bwclk/settings.js @@ -4,7 +4,7 @@ // initialize with default settings... const storage = require('Storage') let settings = { - fullscreen: false, + screen: "Normal", showLock: true, hideColon: false, }; @@ -17,15 +17,16 @@ storage.write(SETTINGS_FILE, settings) } - + var screenOptions = ["Normal", "Dynamic", "Full"]; E.showMenu({ '': { 'title': 'BW Clock' }, '< Back': back, - 'Fullscreen': { - value: settings.fullscreen, - format: () => (settings.fullscreen ? 'Yes' : 'No'), - onchange: () => { - settings.fullscreen = !settings.fullscreen; + 'Screen': { + value: 0 | screenOptions.indexOf(settings.screen), + min: 0, max: 2, + format: v => screenOptions[v], + onchange: v => { + settings.screen = screenOptions[v]; save(); }, }, diff --git a/apps/calclock/ChangeLog b/apps/calclock/ChangeLog new file mode 100644 index 000000000..b67f29e94 --- /dev/null +++ b/apps/calclock/ChangeLog @@ -0,0 +1,3 @@ +0.01: Initial version +0.02: More compact rendering & app icon +0.03: Tell clock widgets to hide. diff --git a/apps/calclock/README.md b/apps/calclock/README.md new file mode 100644 index 000000000..2b4e93a0c --- /dev/null +++ b/apps/calclock/README.md @@ -0,0 +1,9 @@ +# Calendar Clock - Your day at a glance + +This clock shows a chronological view of your current and future events. +It uses events synced from Gadgetbridge to achieve this. + +The current time and date is highlighted in cyan. + +## Screenshot + diff --git a/apps/calclock/calclock-icon.js b/apps/calclock/calclock-icon.js new file mode 100644 index 000000000..9d5514d80 --- /dev/null +++ b/apps/calclock/calclock-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwgpm5gAB4AVRhgWCAAQWWDCARC/4ACJR4uB54WDAAP8DBotFGIgXLFwv4GAouQC4gwMLooXF/gXJOowXGJBIXBCIgXQxgXLMAIXXMAmIC5OIx4XJhH/wAXIxnIC78IxGIHoIABI44MBC4wQBEQIDB5gXGPAJgEC6IxBC5oABC4wwDa4YTCxAWD5nPDAzvGFYgAB5AXWJBK+GcAq5CGBIuBC5X4GBIJBdoQXB/GIx4CDPJAuEC5JoCDAgWBFwYXJxCBIFwYXKYwoACCwZ3IPQoWIC5YABGYIABCwpHKAQYMBCwwX/C5QAMC8R3/R/4XNhAXNwAXHgGIABgWIAFwA==")) diff --git a/apps/calclock/calclock.js b/apps/calclock/calclock.js new file mode 100644 index 000000000..343d95c04 --- /dev/null +++ b/apps/calclock/calclock.js @@ -0,0 +1,119 @@ +var calendar = []; +var current = []; +var next = []; + +function updateCalendar() { + calendar = require("Storage").readJSON("android.calendar.json",true)||[]; + calendar = calendar.filter(e => isActive(e) || getTime() <= e.timestamp); + calendar.sort((a,b) => a.timestamp - b.timestamp); + + current = calendar.filter(isActive); + next = calendar.filter(e=>!isActive(e)); +} + +function isActive(event) { + var timeActive = getTime() - event.timestamp; + return timeActive >= 0 && timeActive <= event.durationInSeconds; +} +function zp(str) { + return ("0"+str).substr(-2); +} + +function drawEventHeader(event, y) { + g.setFont("Vector", 24); + + var time = isActive(event) ? new Date() : new Date(event.timestamp * 1000); + var timeStr = zp(time.getHours()) + ":" + zp(time.getMinutes()); + g.drawString(timeStr, 5, y); + y += 24; + + g.setFont("12x20", 1); + if (isActive(event)) { + g.drawString(zp(time.getDate())+". " + require("locale").month(time,1),15*timeStr.length,y-21); + } else { + var offset = 0-time.getTimezoneOffset()/1440; + var days = Math.floor((time.getTime()/1000)/86400+offset)-Math.floor(getTime()/86400+offset); + if(days > 0) { + var daysStr = days===1?/*LANG*/"tomorrow":/*LANG*/"in "+days+/*LANG*/" days"; + g.drawString(daysStr,15*timeStr.length,y-21); + } + } + return y; +} + +function drawEventBody(event, y) { + g.setFont("12x20", 1); + var lines = g.wrapString(event.title, g.getWidth()-10); + if (lines.length > 2) { + lines = lines.slice(0,2); + lines[1] = lines[1].slice(0,-3)+"..."; + } + g.drawString(lines.join('\n'), 5, y); + y+=20 * lines.length; + if(event.location) { + g.drawImage(atob("DBSBAA8D/H/nDuB+B+B+B3Dn/j/B+A8A8AYAYAYAAAAAAA=="),5,y); + g.drawString(event.location, 20, y); + y+=20; + } + y+=5; + return y; +} + +function drawEvent(event, y) { + y = drawEventHeader(event, y); + y = drawEventBody(event, y); + return y; +} + +var curEventHeight = 0; + +function drawCurrentEvents(y) { + g.setColor("#0ff"); + g.clearRect(5, y, g.getWidth() - 5, y + curEventHeight); + curEventHeight = y; + + if(current.length === 0) { + y = drawEvent({timestamp: getTime(), durationInSeconds: 100}, y); + } else { + y = drawEventHeader(current[0], y); + for (var e of current) { + y = drawEventBody(e, y); + } + } + curEventHeight = y - curEventHeight; + return y; +} + +function drawFutureEvents(y) { + g.setColor(g.theme.fg); + for (var e of next) { + y = drawEvent(e, y); + if(y>g.getHeight())break; + } + return y; +} + +function fullRedraw() { + g.clearRect(5,24,g.getWidth()-5,g.getHeight()); + updateCalendar(); + var y = 30; + y = drawCurrentEvents(y); + drawFutureEvents(y); +} + +function redraw() { + g.reset(); + if (current.find(e=>!isActive(e)) || next.find(isActive)) { + fullRedraw(); + } else { + drawCurrentEvents(30); + } +} + +g.clear(); +fullRedraw(); +var minuteInterval = setInterval(redraw, 60 * 1000); + +Bangle.setUI("clock"); +Bangle.loadWidgets(); +Bangle.drawWidgets(); diff --git a/apps/calclock/calclock.png b/apps/calclock/calclock.png new file mode 100644 index 000000000..5f953c1ee Binary files /dev/null and b/apps/calclock/calclock.png differ diff --git a/apps/calclock/location.png b/apps/calclock/location.png new file mode 100644 index 000000000..619e55775 Binary files /dev/null and b/apps/calclock/location.png differ diff --git a/apps/calclock/metadata.json b/apps/calclock/metadata.json new file mode 100644 index 000000000..7bac5c721 --- /dev/null +++ b/apps/calclock/metadata.json @@ -0,0 +1,17 @@ +{ + "id": "calclock", + "name": "Calendar Clock", + "shortName": "CalClock", + "version": "0.03", + "description": "Show the current and upcoming events synchronized from Gadgetbridge", + "icon": "calclock.png", + "type": "clock", + "tags": "clock agenda", + "supports": ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"calclock.app.js","url":"calclock.js"}, + {"name":"calclock.img","url":"calclock-icon.js","evaluate":true} + ], + "screenshots": [{"url":"screenshot.png"}] +} diff --git a/apps/calclock/screenshot.png b/apps/calclock/screenshot.png new file mode 100644 index 000000000..4ab503f2b Binary files /dev/null and b/apps/calclock/screenshot.png differ diff --git a/apps/cassioWatch/ChangeLog b/apps/cassioWatch/ChangeLog index 419810021..883bd2585 100644 --- a/apps/cassioWatch/ChangeLog +++ b/apps/cassioWatch/ChangeLog @@ -8,4 +8,5 @@ 0.7: Update Rocket Sequences Scope to not use memory all time 0.8: Update Some Variable Scopes to not use memory until need 0.9: Remove ESLint spaces -0.10: Show daily steps, heartrate and the temperature if weather information is available. \ No newline at end of file +0.10: Show daily steps, heartrate and the temperature if weather information is available. +0.11: Tell clock widgets to hide. diff --git a/apps/cassioWatch/app.js b/apps/cassioWatch/app.js index 6bbb9e823..91f6737ad 100644 --- a/apps/cassioWatch/app.js +++ b/apps/cassioWatch/app.js @@ -165,11 +165,11 @@ Bangle.on("lock", (locked) => { } }); +Bangle.setUI("clock"); // Load widgets, but don't show them Bangle.loadWidgets(); -Bangle.setUI("clock"); g.reset(); g.clear(); -draw(); \ No newline at end of file +draw(); diff --git a/apps/cassioWatch/metadata.json b/apps/cassioWatch/metadata.json index dabdc2c93..abfee9b93 100644 --- a/apps/cassioWatch/metadata.json +++ b/apps/cassioWatch/metadata.json @@ -4,7 +4,7 @@ "description": "Animated Clock with Space Cassio Watch Style", "screenshots": [{ "url": "screens/screen_night.png" },{ "url": "screens/screen_day.png" }], "icon": "app.png", - "version": "0.10", + "version": "0.11", "type": "clock", "tags": "clock, weather, cassio, retro", "supports": ["BANGLEJS2"], diff --git a/apps/chimer/ChangeLog b/apps/chimer/ChangeLog new file mode 100644 index 000000000..01bd00a0a --- /dev/null +++ b/apps/chimer/ChangeLog @@ -0,0 +1,2 @@ +0.01: Initial Creation +0.02: Fixed some sleep bugs. Added a sleep mode toggle \ No newline at end of file diff --git a/apps/chimer/README.MD b/apps/chimer/README.MD new file mode 100644 index 000000000..a78c677f2 --- /dev/null +++ b/apps/chimer/README.MD @@ -0,0 +1,11 @@ +# Chimer - For the BangleJS + +A fork of [Hour Chime](https://github.com/espruino/BangleApps/tree/master/apps/widchime) that adds extra features such as: + +- Buzz or beep on every 60, 30 or 15 minutes. +- Repeat Chime up to 3 times +- Set hours to disable chime + +Setting the hours you don't want your watch to chime for is done by setting the hour you want it to stop, and the hour you want it to start. + +Hours range from 0 - 23. diff --git a/apps/chimer/icon.txt b/apps/chimer/icon.txt new file mode 100644 index 000000000..cc969bc81 --- /dev/null +++ b/apps/chimer/icon.txt @@ -0,0 +1,2 @@ + +widget.png: "https://icons8.com/icon/114436/alarm" \ No newline at end of file diff --git a/apps/chimer/metadata.json b/apps/chimer/metadata.json new file mode 100644 index 000000000..d5bc04950 --- /dev/null +++ b/apps/chimer/metadata.json @@ -0,0 +1,16 @@ +{ + "id": "chimer", + "name": "Chimer", + "version": "0.02", + "description": "A fork of Hour Chime that adds extra features such as: \n - Buzz or beep on every 60, 30 or 15 minutes. \n - Reapeat Chime up to 3 times \n - Set hours to disable chime", + "icon": "widget.png", + "type": "widget", + "tags": "widget", + "supports": ["BANGLEJS", "BANGLEJS2"], + "readme": "README.MD", + "storage": [ + { "name": "chimer.wid.js", "url": "widget.js" }, + { "name": "chimer.settings.js", "url": "settings.js" } + ], + "data": [{ "name": "chimer.json" }] +} diff --git a/apps/chimer/settings.js b/apps/chimer/settings.js new file mode 100644 index 000000000..55160c9be --- /dev/null +++ b/apps/chimer/settings.js @@ -0,0 +1,94 @@ +/** + * @param {function} back Use back() to return to settings menu + */ + +(function (back) { + // default to buzzing + var FILE = "chimer.json"; + var settings = {}; + const chimes = ["Off", "Buzz", "Beep", "Both"]; + const frequency = ["60 min", "30 min", "15 min", "1 min"]; + + var showMainMenu = () => { + E.showMenu({ + "": { title: "Chimer" }, + "< Back": () => back(), + "Chime Type": { + value: settings.type, + min: 0, + max: 2, // both is just silly + format: (v) => chimes[v], + onchange: (v) => { + settings.type = v; + writeSettings(settings); + }, + }, + Frequency: { + value: settings.freq, + min: 0, + max: 2, + format: (v) => frequency[v], + onchange: (v) => { + settings.freq = v; + writeSettings(settings); + }, + }, + Repetition: { + value: settings.repeat, + min: 1, + max: 5, + format: (v) => v, + onchange: (v) => { + settings.repeat = v; + writeSettings(settings); + }, + }, + "Sleep Mode": { + value: !!settings.sleep, + onchange: (v) => { + settings.sleep = v; + writeSettings(settings); + }, + }, + "Sleep Start": { + value: settings.start, + min: 0, + max: 23, + format: (v) => v, + onchange: (v) => { + settings.start = v; + writeSettings(settings); + }, + }, + "Sleep End": { + value: settings.end, + min: 0, + max: 23, + format: (v) => v, + onchange: (v) => { + settings.end = v; + writeSettings(settings); + }, + }, + }); + }; + + var readSettings = () => { + var settings = require("Storage").readJSON(FILE, 1) || { + type: 1, + freq: 0, + repeat: 1, + sleep: true, + start: 6, + end: 22, + }; + return settings; + }; + + var writeSettings = (settings) => { + require("Storage").writeJSON(FILE, settings); + }; + + settings = readSettings(); + showMainMenu(); +}); diff --git a/apps/chimer/widget.js b/apps/chimer/widget.js new file mode 100644 index 000000000..18358df9e --- /dev/null +++ b/apps/chimer/widget.js @@ -0,0 +1,134 @@ +(function () { + // 0: off, 1: buzz, 2: beep, 3: both + var FILE = "chimer.json"; + + var readSettings = () => { + var settings = require("Storage").readJSON(FILE, 1) || { + type: 1, + freq: 0, + repeat: 1, + sleep: true, + start: 6, + end: 22, + }; + return settings; + }; + + var settings = readSettings(); + + function sleep(milliseconds) { + const date = Date.now(); + let currentDate = null; + do { + currentDate = Date.now(); + } while (currentDate - date < milliseconds); + } + + function chime() { + for (var i = 0; i < settings.repeat; i++) { + if (settings.type === 1) { + Bangle.buzz(100); + } else if (settings.type === 2) { + Bangle.beep(); + } else { + return; + } + sleep(150); + } + } + + let lastHour = new Date().getHours(); + let lastMinute = new Date().getMinutes(); // don't chime when (re)loaded at a whole hour + function check() { + const now = new Date(), + h = now.getHours(), + m = now.getMinutes(), + s = now.getSeconds(), + ms = now.getMilliseconds(); + if ( + (settings.sleep && h > settings.end) || + (settings.sleep && h >= settings.end && m !== 0) || + (settings.sleep && h < settings.start) + ) { + var mLeft = 60 - m, + sLeft = mLeft * 60 - s, + msLeft = sLeft * 1000 - ms; + setTimeout(check, msLeft); + return; + } + if (settings.freq === 1) { + if ((m !== lastMinute && m === 0) || (m !== lastMinute && m === 30)) + chime(); + lastHour = h; + lastMinute = m; + // check again in 30 minutes + switch (true) { + case m / 30 >= 1: + var mLeft = 30 - (m - 30), + sLeft = mLeft * 60 - s, + msLeft = sLeft * 1000 - ms; + break; + case m / 30 < 1: + var mLeft = 30 - m, + sLeft = mLeft * 60 - s, + msLeft = sLeft * 1000 - ms; + break; + } + setTimeout(check, msLeft); + } else if (settings.freq === 2) { + if ( + (m !== lastMinute && m === 0) || + (m !== lastMinute && m === 15) || + (m !== lastMinute && m === 30) || + (m !== lastMinute && m === 45) + ) + chime(); + lastHour = h; + lastMinute = m; + // check again in 15 minutes + switch (true) { + case m / 15 >= 3: + var mLeft = 15 - (m - 45), + sLeft = mLeft * 60 - s, + msLeft = sLeft * 1000 - ms; + break; + case m / 15 >= 2: + var mLeft = 15 - (m - 30), + sLeft = mLeft * 60 - s, + msLeft = sLeft * 1000 - ms; + break; + case m / 15 >= 1: + var mLeft = 15 - (m - 15), + sLeft = mLeft * 60 - s, + msLeft = sLeft * 1000 - ms; + break; + case m / 15 < 1: + var mLeft = 15 - m, + sLeft = mLeft * 60 - s, + msLeft = sLeft * 1000 - ms; + break; + } + setTimeout(check, msLeft); + } else if (settings.freq === 3) { + if (m !== lastMinute) chime(); + lastHour = h; + lastMinute = m; + // check again in 1 minute + + var mLeft = 1, + sLeft = mLeft * 60 - s, + msLeft = sLeft * 1000 - ms; + setTimeout(check, msLeft); + } else { + if (h !== lastHour && m === 0) chime(); + lastHour = h; + // check again in 60 minutes + var mLeft = 60 - m, + sLeft = mLeft * 60 - s, + msLeft = sLeft * 1000 - ms; + setTimeout(check, msLeft); + } + } + + check(); +})(); diff --git a/apps/chimer/widget.png b/apps/chimer/widget.png new file mode 100644 index 000000000..14edf4150 Binary files /dev/null and b/apps/chimer/widget.png differ diff --git a/apps/clockcal/ChangeLog b/apps/clockcal/ChangeLog index 20a46b5b7..27d4fc7f4 100644 --- a/apps/clockcal/ChangeLog +++ b/apps/clockcal/ChangeLog @@ -2,3 +2,5 @@ 0.02: Added scrollable calendar and swipe gestures 0.03: Configurable drag gestures 0.04: Use default Bangle formatter for booleans +0.05: Improved colors (connected vs disconnected) +0.06: Tell clock widgets to hide. diff --git a/apps/clockcal/app.js b/apps/clockcal/app.js index 5e8c7f796..58ddd7ef5 100644 --- a/apps/clockcal/app.js +++ b/apps/clockcal/app.js @@ -1,3 +1,4 @@ +Bangle.setUI("clock"); Bangle.loadWidgets(); var s = Object.assign({ @@ -123,7 +124,7 @@ function drawMinutes() { var d = new Date(); var hours = s.MODE24 ? d.getHours().toString().padStart(2, ' ') : ((d.getHours() + 24) % 12 || 12).toString().padStart(2, ' '); var minutes = d.getMinutes().toString().padStart(2, '0'); - var textColor = NRF.getSecurityStatus().connected ? '#fff' : '#f00'; + var textColor = NRF.getSecurityStatus().connected ? '#99f' : '#fff'; var size = 50; var clock_x = (w - 20) / 2; if (dimSeconds) { @@ -307,4 +308,4 @@ NRF.on('disconnect', BTevent); dimSeconds = Bangle.isLocked(); drawWatch(); -Bangle.setUI("clock"); + diff --git a/apps/clockcal/metadata.json b/apps/clockcal/metadata.json index 6d547a7a3..872211495 100644 --- a/apps/clockcal/metadata.json +++ b/apps/clockcal/metadata.json @@ -1,7 +1,7 @@ { "id": "clockcal", "name": "Clock & Calendar", - "version": "0.04", + "version": "0.06", "description": "Clock with Calendar", "readme":"README.md", "icon": "app.png", diff --git a/apps/colorful_clock/ChangeLog b/apps/colorful_clock/ChangeLog index c72634017..54ee389e3 100644 --- a/apps/colorful_clock/ChangeLog +++ b/apps/colorful_clock/ChangeLog @@ -1,2 +1,3 @@ ... 0.03: First update with ChangeLog Added +0.04: Tell clock widgets to hide. diff --git a/apps/colorful_clock/app.js b/apps/colorful_clock/app.js index afc6b321f..ba6272e9b 100644 --- a/apps/colorful_clock/app.js +++ b/apps/colorful_clock/app.js @@ -3,6 +3,8 @@ let outerRadius = Math.min(CenterX,CenterY) * 0.9; + Bangle.setUI('clock'); + Bangle.loadWidgets(); /**** updateClockFaceSize ****/ @@ -241,7 +243,3 @@ refreshDisplay(); } }); - - Bangle.loadWidgets(); - - Bangle.setUI('clock'); diff --git a/apps/colorful_clock/metadata.json b/apps/colorful_clock/metadata.json index 5b6dbe87e..237acf81c 100644 --- a/apps/colorful_clock/metadata.json +++ b/apps/colorful_clock/metadata.json @@ -1,7 +1,7 @@ { "id": "colorful_clock", "name": "Colorful Analog Clock", "shortName":"Colorful Clock", - "version":"0.03", + "version":"0.04", "description": "a colorful analog clock", "icon": "app-icon.png", "type": "clock", diff --git a/apps/configurable_clock/ChangeLog b/apps/configurable_clock/ChangeLog index 84e7affed..9d55c1a91 100644 --- a/apps/configurable_clock/ChangeLog +++ b/apps/configurable_clock/ChangeLog @@ -1,2 +1,3 @@ ... 0.02: First update with ChangeLog Added +0.03: Tell clock widgets to hide. diff --git a/apps/configurable_clock/app.js b/apps/configurable_clock/app.js index 157d57741..45c86c7e9 100644 --- a/apps/configurable_clock/app.js +++ b/apps/configurable_clock/app.js @@ -5,6 +5,7 @@ let ScreenWidth = g.getWidth(), CenterX; let ScreenHeight = g.getHeight(), CenterY, outerRadius; + Bangle.setUI('clock'); Bangle.loadWidgets(); /**** updateClockFaceSize ****/ @@ -1377,4 +1378,3 @@ } }); - Bangle.setUI('clock'); diff --git a/apps/configurable_clock/metadata.json b/apps/configurable_clock/metadata.json index 28feae7e4..687a5b212 100644 --- a/apps/configurable_clock/metadata.json +++ b/apps/configurable_clock/metadata.json @@ -1,7 +1,7 @@ { "id": "configurable_clock", "name": "Configurable Analog Clock", "shortName":"Configurable Clock", - "version":"0.02", + "version":"0.03", "description": "an analog clock with several kinds of faces, hands and colors to choose from", "icon": "app-icon.png", "type": "clock", diff --git a/apps/crowclk/ChangeLog b/apps/crowclk/ChangeLog index 4f48bdd14..1c4f6f43b 100644 --- a/apps/crowclk/ChangeLog +++ b/apps/crowclk/ChangeLog @@ -1,3 +1,4 @@ 0.01: New App! 0.02: Removed "wake LCD on face-up"-feature: A watch-face should not set things like "wake LCD on face-up". 0.03: Fix the clock for dark mode. +0.04: Tell clock widgets to hide. diff --git a/apps/crowclk/crow_clock.js b/apps/crowclk/crow_clock.js index eee1653cb..7e608ef19 100644 --- a/apps/crowclk/crow_clock.js +++ b/apps/crowclk/crow_clock.js @@ -136,9 +136,9 @@ Bangle.on('lcdPower', (on) => { g.clear(); +// Show launcher when button pressed +Bangle.setUI("clock"); Bangle.loadWidgets(); Bangle.drawWidgets(); startTimers(); -// Show launcher when button pressed -Bangle.setUI("clock"); diff --git a/apps/crowclk/metadata.json b/apps/crowclk/metadata.json index 6985cf11a..265a0398b 100644 --- a/apps/crowclk/metadata.json +++ b/apps/crowclk/metadata.json @@ -1,7 +1,7 @@ { "id": "crowclk", "name": "Crow Clock", - "version": "0.03", + "version": "0.04", "description": "A simple clock based on Bold Clock that has MST3K's Crow T. Robot for a face", "icon": "crow_clock.png", "screenshots": [{"url":"screenshot_crow.png"}], diff --git a/apps/daisy/ChangeLog b/apps/daisy/ChangeLog index 829ff3d13..b13ce261b 100644 --- a/apps/daisy/ChangeLog +++ b/apps/daisy/ChangeLog @@ -5,3 +5,4 @@ 0.05: changed text to uppercase, just looks better, removed colons on text 0.06: better contrast for light theme, use fg color instead of dithered for ring 0.07: Use default Bangle formatter for booleans +0.08: fix idle timer always getting set to true diff --git a/apps/daisy/app.js b/apps/daisy/app.js index 7c513726f..848cd1801 100644 --- a/apps/daisy/app.js +++ b/apps/daisy/app.js @@ -83,7 +83,7 @@ function loadSettings() { settings = require("Storage").readJSON(SETTINGS_FILE,1)||{}; settings.gy = settings.gy||'#020'; settings.fg = settings.fg||'#0f0'; - settings.idle_check = settings.idle_check||true; + settings.idle_check = (settings.idle_check === undefined ? true : settings.idle_check); assignPalettes(); } diff --git a/apps/daisy/metadata.json b/apps/daisy/metadata.json index 802ba6834..c6cc93620 100644 --- a/apps/daisy/metadata.json +++ b/apps/daisy/metadata.json @@ -1,6 +1,6 @@ { "id": "daisy", "name": "Daisy", - "version":"0.07", + "version":"0.08", "dependencies": {"mylocation":"app"}, "description": "A beautiful digital clock with large ring guage, idle timer and a cyclic information line that includes, day, date, steps, battery, sunrise and sunset times", "icon": "app.png", diff --git a/apps/deko/Building_Typeface.ttf b/apps/deko/Building_Typeface.ttf new file mode 100644 index 000000000..d5a3933ab Binary files /dev/null and b/apps/deko/Building_Typeface.ttf differ diff --git a/apps/deko/ChangeLog b/apps/deko/ChangeLog new file mode 100644 index 000000000..9db0e26c5 --- /dev/null +++ b/apps/deko/ChangeLog @@ -0,0 +1 @@ +0.01: first release diff --git a/apps/deko/README.md b/apps/deko/README.md new file mode 100644 index 000000000..91e83bd23 --- /dev/null +++ b/apps/deko/README.md @@ -0,0 +1,10 @@ +# Deko Clock + +A simple clock with an Art Deko font + +The font was obtained from https://dafonttop.com/building.font and is free for personal use + + + + +Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) diff --git a/apps/deko/app-icon.js b/apps/deko/app-icon.js new file mode 100644 index 000000000..06f93e2ef --- /dev/null +++ b/apps/deko/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwIdah/wAof//4ECgYFB4AFBg4FB8AFBj/wh/4AoM/wEB/gFBvwCEBAU/AQP4gfAj8AgPwAoMPwED8AFBg/AAYIBDA4ngg4TB4EBApkPKgJSBJQIFTMgIFCJIIFDKoIFEvgFBGoMAnw7DP4IFEh+BAoItBg+DNIQwBMIaeCKoKxCPoIzCEgKVHUIqtFXIrFFaIrdFdIwAV")) diff --git a/apps/deko/app.js b/apps/deko/app.js new file mode 100644 index 000000000..8ae2c1d31 --- /dev/null +++ b/apps/deko/app.js @@ -0,0 +1,64 @@ +Graphics.prototype.setFontBuildingTypeface = function(scale) { + // Actual height 100 (102 - 3) + this.setFontCustom( + atob('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf+AAAAAAAAAAAAAAAAAAAf+AAAAAAAAAAAAAAAAAAAf+AAAAAAAAAAAAAAAAAAAf+AAAAAAAAAAAAAAAAAAAf+AAAAAAAAAAAAAAAAAAAf+AAAAAAAAAAAAAAAAAAAf+AAAAAAAAAAAAAAAAAAAf+AAAAAAAAAAAAAAAAAAAf+AAAAAAAAAAAAAAAAAAAf+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgAAAAAAAAAAAAAAAAAAH/gAAAAAAAAAAAAAAAAAH//gAAAAAAAAAAAAAAAAD///gAAAAAAAAAAAAAAAD////gAAAAAAAAAAAAAAD/////gAAAAAAAAAAAAAB//////gAAAAAAAAAAAAB///////gAAAAAAAAAAAB////////gAAAAAAAAAAA////////4AAAAAAAAAAA////////4AAAAAAAAAAAf///////8AAAAAAAAAAAf///////8AAAAAAAAAAAf///////8AAAAAAAAAAAP///////+AAAAAAAAAAAP///////+AAAAAAAAAAAP///////+AAAAAAAAAAAH////////AAAAAAAAAAAAH///////AAAAAAAAAAAAAH//////AAAAAAAAAAAAAAH/////gAAAAAAAAAAAAAAH////gAAAAAAAAAAAAAAAH///wAAAAAAAAAAAAAAAAH//wAAAAAAAAAAAAAAAAAH/wAAAAAAAAAAAAAAAAAAH4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////AAAAAAAD/////////////wAAAAAAP/////////////4AAAAAAP/////////////8AAAAAAf/////////////+AAAAAAf/////////////+AAAAAA///////////////AAAAAA///////////////AAAAAA///////////////AAAAAA/4AAAAAAAAAAAH/AAAAAA/4AAAAAAAAAAAH/AAAAAA/4AAAAAAAAAAAH/AAAAAA/4AAAAAAAAAAAH/AAAAAA/4AAAAAAAAAAAH/AAAAAA/4AAAAAAAAAAAH/AAAAAA/4AAAAAAAAAAAH/AAAAAA/4AAAAAAAAAAAH/AAAAAA/4AAAAAAAAAAAH/AAAAAA/4AAAAAAAAAAAH/AAAAAA/4AAAAAAAAAAAH/AAAAAA/4AAAAAAAAAAAH/AAAAAA///////////////AAAAAA///////////////AAAAAA///////////////AAAAAA///////////////AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAP/////////////8AAAAAAH/////////////4AAAAAAD/////////////wAAAAAAA/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP4AAAAAAAAAAAAAAAAAAAf4AAAAAAAAAAAAAAAAAAA/4AAAAAAAAAAAAAAAAAAB/4AAAAAAAAAAAAAAAAAAD/4AAAAAAAAAAAAAAAAAAH/4AAAAAAAAAAAAAAAAAAf/4AAAAAAAAAAAAAAAAAAf/////////////+AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/wAAf///////+AAAAAAB//wAB////////+AAAAAAH//wAD////////+AAAAAAH//wAH////////+AAAAAAP//wAP////////+AAAAAAf//wAP////////+AAAAAAf//wAP////////+AAAAAAf//wAf////////+AAAAAAf//wAf////////+AAAAAAf8AAAf8AAAAAAP+AAAAAAf8AAAf8AAAAAAP+AAAAAAf8AAAf8AAAAAAP+AAAAAAf8AAAf8AAAAAAP+AAAAAAf8AAAf8AAAAAAP+AAAAAAf8AAAf8AAAAAAP+AAAAAAf8AAAf8AAAAAAP+AAAAAAf8AAAf8AAAAAAP+AAAAAAf8AAAf8AAAAAAP+AAAAAAf8AAAf8AAAAAAP+AAAAAAf8AAAf8AAAAAAP+AAAAAAf8AAAf8AAAAAAP+AAAAAAf/////8AAAA///+AAAAAAf/////8AAAA///+AAAAAAf/////8AAAA///+AAAAAAf/////8AAAA///+AAAAAAP/////8AAAA///+AAAAAAH/////8AAAA///+AAAAAAH/////8AAAA///+AAAAAAB/////8AAAA///+AAAAAAAf////8AAAA///+AAAAAAAAAAAAAAAAA///+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf//gAAAAAAAf//+AAAAAAf//wAAAAAAA///+AAAAAAf//wAAAAAAA///+AAAAAAf//wAAAAAAA///+AAAAAAf//wAAAAAAA///+AAAAAAf//wAAAAAAA///+AAAAAAf//wAAAAAAA///+AAAAAAf//wAAAAAAA///+AAAAAAf//wAAAAAAA///+AAAAAAf//wAAAAAAA///+AAAAAAf8AAAAAAAAAAAP+AAAAAAf8AAAAAAAAAAAP+AAAAAAf8AAAAAAAAAAAP+AAAAAAf8AAAAEAAAAAAP+AAAAAAf8AAAB8AAAAAAP+AAAAAAf8AAAP8AAAAAAP+AAAAAAf8AAD/8AAAAAAP+AAAAAAf8AA//8AAAAAAP+AAAAAAf8AP//8AAAAAAP+AAAAAAf8B///8AAAAAAP+AAAAAAf8f///8AAAAAAP+AAAAAAf/////8AAAAAAP+AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAf///8P////////+AAAAAAf///gH////////+AAAAAAf//4AD////////+AAAAAAf/+AAB////////+AAAAAAf/gAAA////////+AAAAAAfwAAAAD///////+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gAAAAAAAAAAAAAAAAAB//gAAAAAAAAAAAAAAAAAH//gAAAAAAAAAAAAAAAAA///gAAAAAAAAAAAAAAAAH///gAAAAAAAAAAAAAAAAf///gAAAAAAAAAAAAAAAD////gAAAAAAAAAAAAAAAf////gAAAAAAAAAAAAAAB/////gAAAAAAAAAAAAAAP///z/gAAAAAAAAAAAAAB///+D/gAAAAAAAAAAAAAH///wD/gAAAAAAAAAAAAA///+AD/gAAAAAAAAAAAAH///wAD/gAAAAAAAAAAAAf//+AAD/gAAAAAAAAAAAD///wAAD/gAAAAAAAAAAAf///AAAD/gAAAAAAAAAAB///4AAAD/gAAAAAAAAAAP///AAAAD/gAAAAAAAAAB///4AAAAD/gAAAAAAAAAH///AAAAAD/gAAAAAAAAAf/////////////+AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAAAAAAAAAAD/gAAAAAAAAAAAAAAAAAAD/gAAAAAAAAAAAAAAAAAAD/gAAAAAAAAAAAAAAAAAAD/gAAAAAAAAAAAAAAAAAAD/gAAAAAAAAAAAAAAAAAAD/gAAAAAAAAAAAAAAAAAAD/gAAAAAAAAAAAAAAAAAAD/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//+AAAAAAAf/////8AAAA///wAAAAAAf/////8AAAA///4AAAAAAf/////8AAAA///8AAAAAAf/////8AAAA///+AAAAAAf/////8AAAA///+AAAAAAf/////8AAAA///+AAAAAAf/////8AAAA////AAAAAAf/////8AAAA////AAAAAAf/////8AAAA////AAAAAAf8AAAf8AAAAAAH/AAAAAAf8AAAf8AAAAAAH/AAAAAAf8AAAf8AAAAAAH/AAAAAAf8AAAf8AAAAAAH/AAAAAAf8AAAf8AAAAAAH/AAAAAAf8AAAf8AAAAAAH/AAAAAAf8AAAf8AAAAAAH/AAAAAAf8AAAf8AAAAAAH/AAAAAAf8AAAf8AAAAAAH/AAAAAAf8AAAf8AAAAAAH/AAAAAAf8AAAf8AAAAAAH/AAAAAAf//wAf8AAAAAAH/AAAAAAf//wAf/////////AAAAAAf//wAf/////////AAAAAAf//wAf/////////AAAAAAf//wAf////////+AAAAAAf//wAP////////+AAAAAAf//wAP////////8AAAAAAf//wAH////////8AAAAAAf//wAD////////wAAAAAAf//wAA////////gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////AAAAAAAD/////////////wAAAAAAP/////////////4AAAAAAP/////////////8AAAAAAf/////////////+AAAAAAf/////////////+AAAAAA///////////////AAAAAA///////////////AAAAAA///////////////AAAAAA/4AAAf8AAAAAAH/AAAAAA/4AAAf8AAAAAAH/AAAAAA/4AAAf8AAAAAAH/AAAAAA/4AAAf8AAAAAAH/AAAAAA/4AAAf8AAAAAAH/AAAAAA/4AAAf8AAAAAAH/AAAAAA/4AAAf8AAAAAAH/AAAAAA/4AAAf8AAAAAAH/AAAAAA/4AAAf8AAAAAAH/AAAAAA/4AAAf8AAAAAAH/AAAAAA/4AAAf8AAAAAAH/AAAAAA///wAf8AAAAAAH/AAAAAA///wAf/////////AAAAAA///wAf/////////AAAAAA///wAf/////////AAAAAAf//wAf/////////AAAAAAf//wAP////////+AAAAAAP//wAP////////+AAAAAAH//wAH////////8AAAAAAB//wAD////////4AAAAAAAf/wAB////////wAAAAAAAAAAAAf///////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf//wAAAAAAAAAAAAAAAAAf//wAAAAAAAAAAAAAAAAAf//wAAAAAAAAAAeAAAAAAf//wAAAAAAAAAP+AAAAAAf//wAAAAAAAAD/+AAAAAAf//wAAAAAAAA//+AAAAAAf//wAAAAAAAf//+AAAAAAf//wAAAAAAH///+AAAAAAf//wAAAAAD////+AAAAAAf8AAAAAAA/////+AAAAAAf8AAAAAAP/////+AAAAAAf8AAAAAH//////8AAAAAAf8AAAAB///////AAAAAAAf8AAAAf//////wAAAAAAAf8AAAP//////4AAAAAAAAf8AAD//////+AAAAAAAAAf8AB///////gAAAAAAAAAf8Af//////4AAAAAAAAAAf8H//////+AAAAAAAAAAAf////////gAAAAAAAAAAAf///////wAAAAAAAAAAAAf//////8AAAAAAAAAAAAAf//////AAAAAAAAAAAAAAf/////wAAAAAAAAAAAAAAf////8AAAAAAAAAAAAAAAf////AAAAAAAAAAAAAAAAf///wAAAAAAAAAAAAAAAAf//4AAAAAAAAAAAAAAAAAf/+AAAAAAAAAAAAAAAAAAf/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///gf//////+AAAAAAAB////4////////wAAAAAAH////9////////4AAAAAAP/////////////8AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAf/////////////+AAAAAA///////////////AAAAAA///////////////AAAAAA//////4AAAAAAH/AAAAAA/4AAA/4AAAAAAH/AAAAAA/4AAA/4AAAAAAH/AAAAAA/4AAA/4AAAAAAH/AAAAAA/4AAA/4AAAAAAH/AAAAAA/4AAA/4AAAAAAH/AAAAAA/4AAA/4AAAAAAH/AAAAAA/4AAA/4AAAAAAH/AAAAAA/4AAA/4AAAAAAH/AAAAAA/4AAA/4AAAAAAH/AAAAAA/4AAA/4AAAAAAH/AAAAAA/4AAA/4AAAAAAH/AAAAAA///////////////AAAAAA///////////////AAAAAA///////////////AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAP/////////////+AAAAAAP/////////////8AAAAAAH////9////////4AAAAAAB////4////////gAAAAAAAH///gP//////+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///////+AAAAAAAAAAAAD////////gAD//AAAAAAAP////////wAD//wAAAAAAP////////4AD//4AAAAAAf////////8AD//8AAAAAAf////////8AD//+AAAAAA/////////+AD//+AAAAAA/////////+AD///AAAAAA/////////+AD///AAAAAA/4AAAAAAP+AD///AAAAAA/4AAAAAAP+AAAH/AAAAAA/4AAAAAAP+AAAH/AAAAAA/4AAAAAAP+AAAH/AAAAAA/4AAAAAAP+AAAH/AAAAAA/4AAAAAAP+AAAH/AAAAAA/4AAAAAAP+AAAH/AAAAAA/4AAAAAAP+AAAH/AAAAAA/4AAAAAAP+AAAH/AAAAAA/4AAAAAAP+AAAH/AAAAAA/4AAAAAAP+AAAH/AAAAAA/4AAAAAAP+AAAH/AAAAAA/4AAAAAAP+AAAH/AAAAAA///////////////AAAAAA///////////////AAAAAA///////////////AAAAAAf/////////////+AAAAAAf/////////////+AAAAAAP/////////////8AAAAAAP/////////////4AAAAAAD/////////////wAAAAAAA/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/wAAAf+AAAAAAAAAAAAAD/wAAAf+AAAAAAAAAAAAAD/wAAAf+AAAAAAAAAAAAAD/wAAAf+AAAAAAAAAAAAAD/wAAAf+AAAAAAAAAAAAAD/wAAAf+AAAAAAAAAAAAAD/wAAAf+AAAAAAAAAAAAAD/wAAAf+AAAAAAAAAAAAAD/wAAAf+AAAAAAAAAAAAAD/wAAAf+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='), + 46, + atob("FCYpGigoKigoJykoFA=="), + 126+(scale<<8)+(1<<16) + ); + return this; +}; + + + +// timeout used to update every minute +var drawTimeout; + +// schedule a draw for the next minute +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +} + + +function draw() { + var x = g.getWidth()/2; + var y = g.getHeight()/2; + g.reset(); + var date = new Date(); + var timeStr = require("locale").time(date,1); + var dateStr = require("locale").date(date).toUpperCase(); + // draw time + g.setFontAlign(0,0).setFont("BuildingTypeface"); + g.clearRect(0, 24, g.getWidth(), y+35); // clear the background + g.drawString(timeStr,x,y); + // draw date + y += 60; + g.setFontAlign(0,0).setFont("6x8",2); + g.clearRect(0,y-8,g.getWidth(),y+8); // clear the background + g.drawString(dateStr,x,y); + // queue draw in one minute + queueDraw(); +} + +// Clear the screen once, at startup +g.clear(); +// draw immediately at first, queue update +draw(); +// Stop updates when LCD is off, restart when on +Bangle.on('lcdPower',on=>{ + if (on) { + draw(); // draw immediately, queue redraw + } else { // stop draw timer + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } +}); +// Show launcher when middle button pressed +Bangle.setUI("clock"); +// Load widgets +Bangle.loadWidgets(); +Bangle.drawWidgets(); diff --git a/apps/deko/app.png b/apps/deko/app.png new file mode 100644 index 000000000..6f11e7019 Binary files /dev/null and b/apps/deko/app.png differ diff --git a/apps/deko/metadata.json b/apps/deko/metadata.json new file mode 100644 index 000000000..9bdd15429 --- /dev/null +++ b/apps/deko/metadata.json @@ -0,0 +1,16 @@ +{ + "id": "deko", + "name": "Deko Clock", + "version": "0.01", + "description": "Clock with Art Deko font", + "readme": "README.md", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"deko.app.js","url":"app.js"}, + {"name":"deko.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/deko/screenshot.png b/apps/deko/screenshot.png new file mode 100644 index 000000000..91ce2ea38 Binary files /dev/null and b/apps/deko/screenshot.png differ diff --git a/apps/distortclk/ChangeLog b/apps/distortclk/ChangeLog new file mode 100644 index 000000000..4c7291526 --- /dev/null +++ b/apps/distortclk/ChangeLog @@ -0,0 +1,2 @@ +0.01: New face! +0.02: Improved clock diff --git a/apps/distortclk/README.md b/apps/distortclk/README.md new file mode 100644 index 000000000..8c7c433c1 --- /dev/null +++ b/apps/distortclk/README.md @@ -0,0 +1,17 @@ +# Distort Watchface +Was playing around with custom fonts and made something with it +Made for Bangle.js 2 + + + +## Features + +Has a dark mode + +## Requests + +If you have any issues or would like to suggest a feature, click here to send a message -> [here](https://github.com/elykittytee/BangleApps/issues/new?title=Poketch%20Clock%20Bug). + +## Creator + +Eleanor Tayam diff --git a/apps/distortclk/app-icon.js b/apps/distortclk/app-icon.js new file mode 100644 index 000000000..c375de96e --- /dev/null +++ b/apps/distortclk/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("j0ewkBiIAxHIQMJiBJEIxAaCAIQfHDgIUFDwwNCHYgVFiAVBHYgIDEghKCCIQGCFYoaDAYgORGIJ2DBwYIBHgQOPgAOIPIYOGAgQOFFgh7DHZQeDBwhoFQgh3JEAgOFFoqkHYRzgOfx4bCJ4gNGSIaJEABA7EAGA")) diff --git a/apps/distortclk/app.js b/apps/distortclk/app.js new file mode 100644 index 000000000..a9fdd1ef2 --- /dev/null +++ b/apps/distortclk/app.js @@ -0,0 +1,65 @@ +Graphics.prototype.setFontSixCaps = function(scale) { + // Actual height 60 (59 - 0) + this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMzMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMzMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0VniarM3u4AAAAAAAAAAAAAAAAAAAAAAAAAAABEZoiqzN3u////////8AAAAAAAAAAAAAAAAAAAJFZ4iqzN3u////////////////8AAAAAAAAAAARGZ4mrzd7v////////////////////////8AAAAAAAqszd7v////////////////////////////7u3MoAAAAAAA//////////////////////////7t3MqohmRCAAAAAAAAAA//////////////////7t3MqohmRAAAAAAAAAAAAAAAAAAA/////////+7dzKqYdlQwAAAAAAAAAAAAAAAAAAAAAAAAAA/+7dzKqIZkQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZkQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWazMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMqVAAAAAAAAAa7//////////////////////////////////+oQAAAAAAC/////////////////////////////////////+wAAAAAAf//////////////////////////////////////3AAAAAA3///7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u///9AAAAAA///GREREREREREREREREREREREREREREREREbP//AAAAAA//8wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///AAAAAA///GREREREREREREREREREREREREREREREREbP//AAAAAA3///7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u///9AAAAAAf//////////////////////////////////////3AAAAAAC/////////////////////////////////////+wAAAAAAAa7//////////////////////////////////+oQAAAAAAAAWazMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMqVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACqoAAAAAAA//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8AAAAAAA//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8AAAAAAA//3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3/8AAAAAAA//////////////////////////////////////8AAAAAAA//////////////////////////////////////8AAAAAAA//////////////////////////////////////8AAAAAAA3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADu4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAes3d3d3d0AAAAAAAAAAAAAAAAAAAAAAAADVorAAAAAAAA8////////8AAAAAAAAAAAAAAAAAAAAlaKze///wAAAAAAHf////////8AAAAAAAAAAAAAAAFGis3v///////wAAAAAAn/////////8AAAAAAAAAAARom83v///////////wAAAAAA7//+3d3d3d0AAAAAAEV5rN7//////////////v/wAAAAAA//xTAAAAAAAAA1eKze//////////////7cqXVP/wAAAAAA//UAAAAAFGis3v/////////////+3Kl2QAAAAP/wAAAAAA//6XZoq83v/////////////+26hkEAAAAAAAAP/wAAAAAA3//////////////////tyoZSAAAAAAAAAAAAAP/wAAAAAAb//////////////tuoZAAAAAAAAAAAAAAAAAAP/wAAAAAACv/////////tuXUwAAAAAAAAAAAAAAAAAAAAAP/wAAAAAAAI3////9yoZAAAAAAAAAAAAAAAAAAAAAAAAAAP/wAAAAAAAAJ4qodRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqgAAAAAAAAWazMzMzMzMzAAAAAAAAAAAAAzMzMzMzMzMqVAAAAAAAAAa7//////////wAAAAAAAAAAAA///////////+oQAAAAAADP///////////wAAAAAAAAAAAA/////////////AAAAAAAf////////////wAAAAiIgAAAAA/////////////3AAAAAA3///7u7u7u7u7gAAAA//8AAAAA7u7u7u7u7u///9AAAAAA//11RERERERERAAAAA//8AAAAAREREREREREV9//AAAAAA//QAAAAAAAAAAAAAAB//8QAAAAAAAAAAAAAAAE//AAAAAA//11RERERERERERERa//+lREREREREREREREV9//AAAAAA3///7u7u7u7u7u7u7/////7u7u7u7u7u7u7u///9AAAAAAf//////////////////////////////////////3AAAAAAC/////////////////+q//////////////////+wAAAAAAAa7///////////////0i3////////////////+oQAAAAAAAAWazMzMzMzMzMzMyoIAKKzMzMzMzMzMzMzMqVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkRGZniIqqoAAAAAAAAAAAAAAAAAAAAAAkRGZniIqqrMzd3u7v//////8AAAAAAAAAAAAAAAqqrMzd3u7v////////////////////8AAAAAAAAAAAAAAA//////////////////////////////8AAAAAAAAAAAAAAA//////////////////////////////8AAAAAAAAAAAAAAA///////////////+7t3czKqpiHZm//8AAAAAAAAAAAAAAA//7u3dzMuqqIhmZUQwAAAAAAAAAA//8AAAAAAAAAAAAAAAZmREAAAAAAAAAARERERERERERERE//9EREREREQAAAAAAAAAAAAAAAAAAAAA7u7u7u7u7u7u7u///u7u7u7u4AAAAAAAAAAAAAAAAAAAAA////////////////////////8AAAAAAAAAAAAAAAAAAAAA////////////////////////8AAAAAAAAAAAAAAAAAAAAA////////////////////////8AAAAAAAAAAAAAAAAAAAAAzMzMzMzMzMzMzMzMzMzMzMzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARERERERERERERERERERAAABEREREREREREREAAAAAAAAAA7u7u7u7u7u7u7u7u7u7gAADu7u7u7u7u7u7u2TAAAAAAAA///////////////////wAAD//////////////+YAAAAAAA///////////////////wAAD///////////////4wAAAAAA///////////////////wAAD///////////////+gAAAAAA//zMzMzMzMzMzMzM3//AAADMzMzMzMzMzMzM7//wAAAAAA//AAAAAAAAAAAAAG//cAAAAAAAAAAAAAAAAAKf/wAAAAAA//AAAAAAAAAAAAAN//UAAAAAAAAAAAAAAAAAB//wAAAAAA//AAAAAAAAAAAAAP//6qqqqqqqqqqqqqqqqqv//wAAAAAA//AAAAAAAAAAAAAP///////////////////////AAAAAAA//AAAAAAAAAAAAAN//////////////////////9AAAAAAA//AAAAAAAAAAAAAF7/////////////////////gAAAAAAA//AAAAAAAAAAAAAAWu//////////////////7GAAAAAAAAZmAAAAAAAAAAAAAAADZmZmZmZmZmZmZmZmZmQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADREREREREREREREREREREREREREREREREMAAAAAAAAAADne7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7ZMAAAAAAABd////////////////////////////////////1QAAAAAALv/////////////////////////////////////iAAAAAAr//////////////////////////////////////6AAAAAA///szMzMzMzMzMzMzP//zMzMzMzMzMzMzMzM3///AAAAAA//ogAAAAAAAAAAAAC//5AAAAAAAAAAAAAAAACf//AAAAAA//cAAAAAAAAAAAAAD//zAAAAAAAAAAAAAAAABf//AAAAAA//+6qqqqqqqqAAAAD//8qqqqqqqqqqqqqqqqrv//AAAAAAz///////////AAAAD//////////////////////8AAAAAAT///////////AAAADv/////////////////////0AAAAAACP//////////AAAAB/////////////////////+AAAAAAAAGzv////////AAAAAGzv/////////////////sYAAAAAAAAABGZmZmZmZmAAAAAABGZmZmZmZmZmZmZmZmZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAAAA//AAAAAAAAAAAAAAAAAAAAAAAAACRGZ4iqrM3e4AAAAAAA//AAAAAAAAAAAAAAACRGZ4iqrM3e7v////////8AAAAAAA//AAAAACRGZ4iqrM3e7v//////////////////8AAAAAAA//iqrM3e7v////////////////////////////8AAAAAAA//////////////////////////////////7u3cwAAAAAAA///////////////////////+7t3MyqmIZmRCAAAAAAAAAA/////////////u3dzLqoiGZUQgAAAAAAAAAAAAAAAAAAAA//7t3cyqqIhmVEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZlRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWazMzMzMqphjAAAAAAAAAARniqrMzMzMzMqVAAAAAAAAAa7//////////+yWEAAAAVi97////////////+oQAAAAAAC///////////////2VAGrf////////////////+wAAAAAAf////////////////+vP///////////////////3AAAAAA3///7u7u7u7/////////////////7u7u7u7u///9AAAAAA///GRERERERmis3////////typhmREREREREbP//AAAAAA//8wAAAAAAAAAAJ8/////8hgAAAAAAAAAAAAA///AAAAAA///GRERERERWis3////////typhmREREREREbP//AAAAAA3///7u7u7u7/////////////////7u7u7u7u///9AAAAAAf////////////////+vP///////////////////3AAAAAAC///////////////2VAGrf////////////////+wAAAAAAAa7//////////+yWIAAAAVi97////////////+oQAAAAAAAAWazMzMzMqphjAAAAAAAAAARniqrMzMzMzMqVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1ZmZmZmZmZmZmZmZmQgAAAAAAZmZmZmZmYwAAAAAAAAAFvv////////////////7rUAAAAA/////////rUAAAAAAAB+////////////////////9gAAAA//////////9wAAAAAAP//////////////////////gAAAA///////////zAAAAAAv//////////////////////wAAAA///////////7AAAAAA///7qqqqqqqqqqqqqqqq3//wAAAAqqqqqqqqrP//AAAAAA//9wAAAAAAAAAAAAAAAAT//wAAAAAAAAAAAAAH//AAAAAA//9wAAAAAAAAAAAAAAAAn//AAAAAAAAAAAAAAZ//AAAAAA///8zMzMzMzMzMzMzMzM///MzMzMzMzMzMzMzf//AAAAAAv//////////////////////////////////////7AAAAAAP//////////////////////////////////////zAAAAAABu////////////////////////////////////5gAAAAAAAEre7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7aQAAAAAAAAAAUREREREREREREREREREREREREREREREREQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMzMwAAAAAAAAAAAzMzAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//8AAAAAAAAAAA///wAAAAAAAAAAAAAAAAAAAAAAAAAAAP//8AAAAAAAAAAA///wAAAAAAAAAAAAAAAAAAAAAAAAAAAP//8AAAAAAAAAAA///wAAAAAAAAAAAAAAAAAAAAAAAAAAAP//8AAAAAAAAAAA///wAAAAAAAAAAAAAAAAAAAAAAAAAAAMzMwAAAAAAAAAAAzMzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("CAwODQ4PDw8QDA8QCA=="), 69+(scale<<8)+(4<<16)); + return this; +}; + +const offset = 25; +const width = g.getWidth(); +const height = g.getHeight(); + +var drawTimeout; +var fgTime = 0xf800; +var bgTime = 0x3333ff; +var dayDate = 0x000; + +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +} + +function time() { + require("Font4x5").add(Graphics); + var d = new Date(); + var day = d.getDate(); + var time = require("locale").time(d,1); + var date = require("locale").date(d); + var mo = require("date_utils").month(d.getMonth()+1,0); + + g.setFontAlign(0,0); + g.setFontSixCaps(2).setColor(fgTime).drawString(time, width/2, height/2+10); + + g.setFont("4x5",2); + g.setFontAlign(0,0); + g.setColor(dayDate).drawString(mo,width-55, height-16); + g.drawString(day,width-10, height-16); +} + +function draw() { + g.setColor(bgTime).fillRect(0,40,width,height-offset); + time(); + queueDraw(); +} + +//program start +g.clear(); // Clear the screen once, at startup + +if (g.theme.dark==true){ + dayDate = 0xffff; +} +else { + dayDate=0x000; +} + +draw(); // draw immediately at first + + + +// Show launcher when middle button pressed +Bangle.setUI("clock"); +// Load widgets +Bangle.loadWidgets(); +Bangle.drawWidgets(); diff --git a/apps/distortclk/app.png b/apps/distortclk/app.png new file mode 100644 index 000000000..b82a0913e Binary files /dev/null and b/apps/distortclk/app.png differ diff --git a/apps/distortclk/metadata.json b/apps/distortclk/metadata.json new file mode 100644 index 000000000..125dac590 --- /dev/null +++ b/apps/distortclk/metadata.json @@ -0,0 +1,17 @@ +{ + "id": "distortclk", + "name": "Distort Clock", + "shortName":"Distort Clock", + "version": "0.02", + "description": "A clockface", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS2"], + "allow_emulator": true, + "readme":"README.md", + "storage": [ + {"name":"distortclk.app.js","url":"app.js"}, + {"name":"distortclk.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/distortclk/screenshot.png b/apps/distortclk/screenshot.png new file mode 100644 index 000000000..3207b4e1e Binary files /dev/null and b/apps/distortclk/screenshot.png differ diff --git a/apps/espruinoprog/ChangeLog b/apps/espruinoprog/ChangeLog index 5560f00bc..6fdcad1d6 100644 --- a/apps/espruinoprog/ChangeLog +++ b/apps/espruinoprog/ChangeLog @@ -1 +1,4 @@ 0.01: New App! +0.02: Add 'pre' code that can erase the device + Wait more between sending code snippets + Now force use of 'Storage' (assume 2v00 or later) diff --git a/apps/espruinoprog/README.md b/apps/espruinoprog/README.md index a8f15d3e9..aef4cccad 100644 --- a/apps/espruinoprog/README.md +++ b/apps/espruinoprog/README.md @@ -13,6 +13,9 @@ Click on the Customise button in the app loader to set up the programmer. * First you need to choose the kind of devices you want to upload to. This is the text that should match the Bluetooth advertising name. So `Puck.js` for Puck.js devices, or `Bangle.js` for Bangles. +* In the next box, you have code to run before the upload of the main code. By default +the code `require("Storage").list().forEach(f=>require("Storage").erase(f));reset();` will +erase all files on the device and reset it. * Now paste in the code you want to write to the device. This is automatically written to flash (`.bootcde`). See https://www.espruino.com/Saving#save-on-send-to-flash- for more information. @@ -35,8 +38,6 @@ To stop scanning, long-press the button to return to the clock. ## Notes -* Right now the Espruino Tools used here are unaware of the device they're writing to, -and as a result they don't use Storage and so the size of the files you can -write to the device are quite limited. You should be find with up to 4k of code. +* This assumes the device being written to is at least version 2v00 of Espruino * Currently, code is not minified before upload (so you need to supply pre-minified code if you want that) diff --git a/apps/espruinoprog/app.js b/apps/espruinoprog/app.js index b939d4007..58fac4a0b 100644 --- a/apps/espruinoprog/app.js +++ b/apps/espruinoprog/app.js @@ -58,21 +58,31 @@ function scanAndConnect() { term.print("Connected...\r\n"); uart.removeAllListeners(); uart.on('data', function(d) { term.print(d); }); - uart.write(json.code+"\n").then(() => { - term.print("\r\nUpload Complete...\r\n"); - // main upload completed - wait a bit + term.print("Upload initial...\r\n"); + uart.write((json.pre||"")+"\n").then(() => { + term.print("\r\Done.\r\n"); uploadTimeout = setTimeout(function() { - term.print("\r\nFinal Upload...\r\n"); - // now upload the code to run after... - uart.write(json.post+"\n").then(() => { - term.print("\r\nDone.\r\n"); - // now wait and disconnect (if not already done!) + uploadTimeout = undefined; + term.print("\r\nUpload Code...\r\n"); + uart.write((json.code||"")+"\n").then(() => { + term.print("\r\Done.\r\n"); + // main upload completed - wait a bit uploadTimeout = setTimeout(function() { - term.print("\r\nDisconnecting...\r\n"); - if (uart) uart.disconnect(); - }, 500); + uploadTimeout = undefined; + term.print("\r\Upload final...\r\n"); + // now upload the code to run after... + uart.write((json.post||"")+"\n").then(() => { + term.print("\r\nDone.\r\n"); + // now wait and disconnect (if not already done!) + uploadTimeout = setTimeout(function() { + uploadTimeout = undefined; + term.print("\r\nDisconnecting...\r\n"); + if (uart) uart.disconnect(); + }, 500); + }); + }, 2000); }); - }, 1000); + }, 2000); }); }); }).catch(err => { diff --git a/apps/espruinoprog/custom.html b/apps/espruinoprog/custom.html index c994aaea7..a12189707 100644 --- a/apps/espruinoprog/custom.html +++ b/apps/espruinoprog/custom.html @@ -17,6 +17,8 @@
Upload code to devices with names starting with:
+Enter the code to send before upload here:
+Enter your program to upload here:
Enter the code to send after upload here:
@@ -24,12 +26,17 @@Then click
Click here to reset to defaults.