diff --git a/apps/90sclk/ChangeLog b/apps/90sclk/ChangeLog new file mode 100644 index 000000000..feb008f5f --- /dev/null +++ b/apps/90sclk/ChangeLog @@ -0,0 +1,2 @@ +0.01: New App! +0.02: Fullscreen settings. \ No newline at end of file diff --git a/apps/90sclk/README.md b/apps/90sclk/README.md new file mode 100644 index 000000000..c09c6fe23 --- /dev/null +++ b/apps/90sclk/README.md @@ -0,0 +1,13 @@ +# 90s Clock + +A watch face in 90s style: + +![](screenshot_2.png) + +Fullscreen mode can be enabled in the settings: + +![](screenshot.png) + + +## Creator +- [David Peer](https://github.com/peerdavid) diff --git a/apps/90sclk/app-icon.js b/apps/90sclk/app-icon.js new file mode 100644 index 000000000..28f75c4e6 --- /dev/null +++ b/apps/90sclk/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgc8+fAgEgwAMDvPnz99BYdl2weHtu27ft2AGBiEcuEAhAPDg4jGgECIRMN23fthUNgP374vBAB3gAgc/gAXNjlx4EDxwJEpAjG/6IBjkBL4UAjVgBAJuCgPHBQMFEIkkyQjFhwEClgXBEYNBwkQJoibCBwNFBAUCEAVAQZAjC/8euPHDon//hKB//xEYMP//jBYP/+ARDNYM///+EYIgBj1B/8fCIUhEYQRB//FUIM/EZU4EYMkEYP/8VhEYUH/gRBWAUfI4MD+AjBoAsBwEH8EB/EDwE4HwYjCuEHWAOHgExEYKbBCIZNB8fAEYQHByE/EwPABAY+BgRHDBANyJQXHNwIjD8CSBj/+BwMSTwOOBYK2D/4CCNYZQB/iJBQwYjCCIcAgeBSoOAWYQjEVoIRCNAIjKAQKJBgAFC8ZoCWwJbDABMHGQPAAoMQB5EDx/4A4gqBZwIGCWwIABuBWC4EBZwPgv/AcwS/EAAcIU4IRBVQIRKEwIjBv0ARIUDCJIjD//x/ARK/5HC/+BCJkcI45uDgECUgQjCWAM4WwUBWYanEAA8cTARWBEYUC5RAHw1YgEOFQXADQPHIIkAhgICuARBh0A23blhHBagIKBsOGjNswhHDEYUUAoTUBhkxEYMwKwU503bvuwXILmCEYMYsumWYYjB85lDEYovBEYXm7fs25EBI4kYtOWNwIjD4+8NYsw4YjGz9/2hrEoOGjVBwE4NYdzNYSwBuEDEYcxaIUA8+atugGogjBiVgWAI")) diff --git a/apps/90sclk/app.js b/apps/90sclk/app.js new file mode 100644 index 000000000..6babbfec2 --- /dev/null +++ b/apps/90sclk/app.js @@ -0,0 +1,144 @@ +const SETTINGS_FILE = "90sclk.setting.json"; +const locale = require('locale'); +const storage = require('Storage'); + + +/* + * Load settings + */ +let settings = { + fullscreen: false, +}; + +let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; +for (const key in saved_settings) { + settings[key] = saved_settings[key] +} + + +function getImg() { + return require("heatshrink").decompress(atob("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")); +} + +Graphics.prototype.setFontTime = function(scale) { + // Actual height 54 (56 - 3) + this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAAAPwAAAAAAAA/gAAAAAAAF/AAAAAAAA/8AAAAAAAD/wAAAAAAAP/AAAAAAAA/wAAAAAAAB/AAAAAAAAB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAB+AAAAAAAAf4AAAAAAAH/wAAAAAAB//AAAAAAAf/+AAAAAAH//8AAAAAB///wAAAAAf///gAAAAH///+AAAAB////4AAAAf///+AAAAH////gAAAB////8AAAA/////AAAAP////wAAAD////8AAAA/////AAAAP////gAAAD////4AAAA////+AAAAD////gAAAAP///4AAAAAf//+AAAAAB///gAAAAAD//4AAAAAAP/+AAAAAAAf/gAAAAAAB/wAAAAAAAH8AAAAAAAAPAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/wAAAAAAAf/wAAAAAAH//gAAAAAD///gAAAAAf///AAAAAB///+AAAAgP///8AAAHg////wAAAfn////gAAD/t////AAAP/j///8AAA//D///4AAH//D///gAAf//H//+AAB///H//4AAH//+P//gAAP//+P/+AAA///8f/4AAD///8f/gAAP///8f+AAAf///8/wAAB////w/AAAD////A4AAAH///4BgAAAP///gAAAAAf//8AAAAAA///AAAAAAA//wAAAAAAA/+AAAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfgAAAAAAAD+AAAAAAAAP4AAAAAAAB/gAAAAAAAP+AAAAAAAA/5//////4D/v//////gP+//////+A/7//////4D/v//////gP+//////+A/7//////4D/v//////gP+//////+Af7//////4A/v//////gA+//////+AA7///hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8AAAD/4AAfwAAAf/gAD/AAAH/+AA/8AAA//4AH/wAAP//gA//AAD//+AH/8AA///4Af/wAP///gD//AD///+AP/8Af///4A//wH////gD//B////+AP/8f//7/4A//3///P/gD/////w/+AP////8D/4A/////AP/gD////4A/+AP///+AD/4Af///gAH/gB///4AAf/AD///AAB/8AH//wAAH/wAP/8AAAf/AAf/gAAB/4AA/4AAAAAAAAfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//gAAAf/wD/+AAAB//AP/4AAAH/8A//gAAAf/wD/+AAAB//AP/4AAAH/8A//gAAAf/wB/+AAAAAAAAAB/4A//8A////////wH////////Af///////8A////////wD///+////AP///7///8A////P///wB///8f//+AH///h///4AP//+D///AAf//wH//4AA//+AP//AAB//wAf/4AAD/+AAf/AAAD/gAAfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf+AAAAAAAH//AAAAAAA//+AAAAAAP//8AAAAAB///4AAAAAP///wAAAAA////gAAAAH////AAAAA////8AAAAD////4AAAAf////j//gB////+//+AP///////4A////////gD///////+Af///////4B////////gH///////+Af///////gB//////AAAH8AAAHAAAAAAA//wAAAAAAD//4AAAAAAP//gAAAAAA//+AAAAAAD//4AAAAAAP//gAAAAAA//+AAAAAAD//4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH////AB/AAf///+AP/+B////4A//4H////AD//gf///8AP/+B////4A//4H////gD//gf/////+AAAAAAAP///wP//gA////A//+AD///8D//4AP///wP//gAf//+A//+AB///4D//4AD///gAB/gAH//8AAAAAAP//gAAAAAAf/8AAAAAAA//gAAAAAAA/4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfwAAAAAAAP/8AAAAAAB//8AAAAAAf//8AAAAAD///4AAAAAf///wAAAAD////wAAAAf////AAAAD////+AAAAP////8AAAB/////wAAAP/////gAAA/////+AAAH/////8AAAf/////wAAB//////gAAP/////+AAA//////4AAD//////gAAP/////+AAA//////4AAD//////gAAP//////AAA//////8AAAAf////wAAAAAAP//gAAAAB///+AAAAAH///4AAAAAf///gAAAAB///+AAAAAH///wAAAAAf///AAAAAA///8AAAAAD///gAAAAAH//+AAAAAAP//wAAAAAAf/+AAAAAAA//wAAAAAAB/+AAAAAAAB/gAAAAAAAB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/wAAAAAH///AAAAAAf//8AAAAAB///wAAAAAH///AAAAAAf//8AAAAAB///wAAAAAH///AAAAAAf//8AAAAAA//AAAAAAAAAAAAAAAAwAAP//////A////////8D////////wP////////A////////8D////////wP////////A////////8D////////wP////////A////////8D////////wP////////A////0cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/AAAD/gAH//AAA//gA//+AAP//AH//8AB//+A///4AP//8H///wA///4f///AH///j///+Af///P///4D///9////wP////////A////////8D////////wP///3///+AAAAAAAAAAB/wAAAAAAAP///x4AAAA////P///4D///8////gH///z///+Af///H///4B///8f///gD///g///8AH//8D///wAf//wH//+AA//+AP//wAA//gA//+AAA/4AA//gAAAEAAB/4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP4AAAAAAAH/8AAAAAAB//8AAAAAAP//4AAAAAB///wAAAAAP///gAAAAB////AAAAAP///8AAAAA////4AAAAH////gAAAAf////AAAAD////8AAAAP////wAAAA/////AAAAD////8AAAAH////wAAAAAAAAAAAAAD///+AAAAAP///////AA///////8AD///////wAP///////AA///////8AB///////wAH//////+AAf//////4AA///////gAD//////8AAH//////wAAf/////+AAA//////4AAB//////AAAH/////4AAAP/////AAAAf////4AAAA////+AAAAB////wAAAAB///8AAAAAB///AAAAAAB//wAAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AB8AAAAAH8AP4AAAAA/4B/wAAAAH/gO/AAAAAf+A/8AAAAB/4D/wAAAAH/AP/AAAAAP4AfwAAAAAfAA+AAAAAAQAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="), 46, atob("FionHyIiJiIyJScyFA=="), 58+(scale<<8)+(1<<16)); + return this; +}; + + +Graphics.prototype.setFontDate = function(scale) { + // Actual height 28 (27 - 0) + this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH///wf///B///8H///wf//+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4AAAfwAAB+AAAAAAAAfwAAB/AAAH8AAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAADg8AAfH+AB//4A///gD//+AP//AA/w/gBPf+AB//4A///wB//8AH//AAfw8AAPDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAD4AAAfwAAD/h4B/+HwH/4/Af//+AP5/4A/n/gB8f8ADg/gAAD8AAADgAAAAAAAAAAAAAAAAAAAAAAAAB8AAAP4CAB/gcAH+D4Af4/wB/n+AH9/wAHv+AAB/wAAf8AAD/gAA/54AH/PwAf5/gB+H+ADw/4AEB/gAAH8AAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAP4AB9/wAP//gB///AP//8A///4D///gH//+Af3/wAfP/AAAf8AAB/gAAP/AAB/8AAP/wAAfOAAAQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAD+AAAP4AAA/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBgAH///g////n////f///9/////8AB/fgAH8AAAPAAAAAAAAAAAAAAAAAAAAAAD9/AAf38AB/f///9////z///+H///wP//8AAAAAAAAAAAAAAAAAAAAAAAAFAAAA+AAAH8AAAfwAAB/AAAD8AAAEAAAAAAAAAAAAAAAAAAAAAAAAfAAAB8AAAHwAAAfAAA//wAD//AAP/8AA//wAD//AAAfAAAB8AAAHwAAAfAAAAAAAAAAAAAAAAAAAAAAABkAAAPwAAA/AAAB4AAACAAAAAAAAAAAAAAAAAAAAAD4AAAPgAAA+AAAD4AAAPgAAA+AAAD4AAAPgAAA+AAAD4AAAPgAAA+AAAAAAAAAAAAAAAAAAAAAAACAAAAeAAAD4AAAPgAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAPAAAD+AAA/4AAP/wAD//AB//wAf/8AH//AB//wAf/8AA//AAD/wAAH8AAAeAAAAgAAAAAAAAAAAAAAAAAAAAAAAA8AAAP8AAD/4AEP/wAd//gD9//AP9/8A/9/wD/7/AP/78Af/7wA//CAB/8AAD/AAADwAAAAAAAAAAAAAAAAAAAABwAAAPAAAB8AAAH3//+ff//59///n3//+Pf//4d///gAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAD8B4AfwfgH/B+A/8P4P/w/j//D+//8P//vw//4/D/+B8H/gHwf8AfAfAA8AAAAAAAAAAAAAAfgAPx/AB/H8AH8fwAPwH/f/H///8f///x/+//H/7/8P/H/gf8P8A/APgAAAAAAAAAAAAAAAAAAAAAAAAD8AAA/8AAH/4AA//gAD//AAf/9/h///+H///4f///h//8AAD/gAAP+AAA/4AAD/gAAAAAAAAAAAAAAAAAAAAAAAAf/4PB//g/n/+D+f/4P5/gf/n/B/+f8H/5/wP/AAAf4AAA/AAAAAAAAAAAAAAAAAAAAAAAAAA8AAAP8AAD/8AAf/4AD//wAP//gB//+AH//8A///wD///AP//8A///wAAP/AAD/+AAH/4AAf/AAB/8AAD/gAAH+AAAPgAAAAAAAAAAAAAAAAAAAAeAAD/4AAP/gAA/+AAB/4AAAAAM+f///5////n///+f///5////n///+f5AAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AP4H+B/w/8P/n/4////n///+f///4AAAAH/9/+P///4/+f/j/5/+H/D/wH4H+AAAHgAAAAAAAAAAAAAAAAAAAA/AAAP/AAB/+AAP/4AA//wAH//AAf/8AB//wAH///wf///B///8H///wP//+A///4B///gD//8AP//gAP/4AAf+AAAPAAAAAAAAAAAAAAAAAAAAAAGAwAA8HgAH4+AAfD4AA4HAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAB4+AAPn4AA+PgABwcAAAAAAAAAAAAAAAAAAAAABgAAAOAAAB8AAAf4AAD/wAAf/AAD/+AAfz8AA8HwADgfgAEA+AAABgAAAAAAAAAAAAAAAAAAAAHj4AAfPgAB8+AAHz4AAfPgAB8+AAHz4AAfPgAB8+AAHz4AAfPgAB8+AAHj4AAAAAAAAAAAAAAAAAAAAAAAAAAAYAAQDwADgfgAfD8AB/fgAD/8AAH/wAAP+AAAfwAAA+AAABwAAAAAAAAAAAAAAAAAAAAAAAAAD8AAAf8AAD/wAAf/gAB/+AAH/4AgA//3B///cH//9wf//3A//8YD/+AAH/4AAP+AAAPgAAAAAAAAAAAAAAAAAD8AAA/8AAH/4AA//wAH8fgAfu+AAf98AOf7wA///ADn/8AO//wA///AD//YAP/8AA/gMAB//wAD//AAH/4AAP/AAAPwAAAAAAAAAAAAAAAAAAAAP///h///+P///5////n///+f//AB+D8AH///+f///4////h///+B///4AAAAAAAAAAAAAAAAAAAAAAAf///j////P///8////z////P///8////z///AP///+f///5////D/5/8H/H/gPwH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/gAA//gAH//AA//+AH//8A///4D///gf///B///8H///wf///B/gH8H+Afwf4B/BwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH//8A////D///8P///w////B///8H///gP//+A///wB//+AD//wAD/8AAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAB////n///+f///5////n///+f///5////n/fP+f9+/5/37/n/AP+AAAAAAAAAAAAAAAAAAAAAAAAAAAAf///5////n///+f///5////n///+f///5/z8AH/PwAf8AAAAAAAAAAAAAAAAAAAAAAA/gAAP/wAD//wAf//gD///Af//+B///4P///w////H///8f///x////H///8f4H/x/gf/D+B/8AAHAAAAcAAABwAAAHAAAAAAAAAAAAAAAAAAAAAAABgH///gf//+B///4H///gf//+B///4AB+AAf/9+B///4H///gf//+B///4H///gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8P///w////D///8P///w////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgAAAfAAAB+AAAH4AAAfgAAB+f///5////n///+f///x///8AAAAAAAAAAAAAAAAAAAAAAAAAAANH///8f///x////H///8f///x////H//+AAH/8AA//4AH//wA///gD//+Af//8B///wH///Af//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAX5////n///+f///5////v///+////5//7/gAAP+AAA/4AAD/gAAAAAAAAAAAAAAAAAAAAAAAAAAvh///+P///5////n///+f///5/wAAD+AAAP8AAAfwAAD/AAAP4AAB////n///+f///5////j///+H///4AAAAAAAAAAAAAAAAAAAAAAAH///gf//+B///4H///gf//+B///4B//4AB//4B///4H///gf//+B///4H///gf//+B///4AAAAAAAAAAAAAAAD/AAA//gAH//AA//+AH//8Af//wD///gf//+B///8H///wf///B/z/8H//wAf///B///8H///wf///A///8D///gH//8AP//wAf/+AA//gAA/4AAAAAAAAAAAAAAAAAA/x////H///8f///x////H///8f///x//gAH/+AAf/4AA//gAB/8AAD/gAAH8AAAAAAAAAAAAAAAAAAAAAAAcAAAP8AAD/8AA//8AH//4Af//wD///AP//+B///4H///wf///B///8H//+Af///B///8H///wf///A///8D///gH//+Af//4A///gB//+AB//4AB/PgAAAYAAAAAAAAAAAAAAAAAAAP///5////n///+f///5////n///+P///4////D///+P///4////h/9/+D/gAAD4AAAAAAAAAAAAAAAAAAAAAAAAAADwAAA/wAAH/gAA//AfH/8D8f/4f5////n+P/+f4P/5/g//j8D/8DgH/wAAP8AAAHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwAAAfAAAB8//8H///wf///B///8H///wf//AB8AAAHwAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAB///8H///8f///5////n///+AAAH5////n///+f///x////H///wf/gAAAAAAAAAAAAAAAAQAAAD8AAAP/AAA//wAH//8Af//+B////gf//+AP//4AP//gP//+P///5////n///gP//gA//AAD/gAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///+D///8P///4////j///+PAAfwAAB/AAAH4AAAfw////j//++P//74///vj///8AAB7AAAAAAAAAAAAAAAAAAAAAAAAAAABgeAA+B/AP8P/n/w////j///+H///gH//4D///8P///4////h/4/8H8AfwPAAOAgAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAHwAAAfgAAB/AAAH8H/wf///B///8H///wf///B///8H/8cAfwAAB+AAAHwAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAABwAAAHAAD8cAD/xwD//HH//+f///5////n///+P//w4f/wDh/gAOHgAA4AAADgAAAOAAAAAAAAAAAAAA///+////////////////////////+AAA/wAAD/gAAP+AAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAA/AAAD/AAAf/AAB//gAD//gAD//gAD//gAD//gAD//gAD//AAD/4AAB/AAAB8AAABgAAAAAAAAAAAAAAAAAAOAAAe4AAB7gAAHuAAAe////7////v///+////7////v///YwAAAAAAAA="), 32, atob("HA4NFhEaFwoNDQsRCRALFBMPEBESEBgSExgKCRARERIXEhQVExEPGBMOERYRFhQaExwUExARFRYTFhMPFA4="), 28+(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 drawBorderString(str, x, y, b, fc){ + g.setColor("#000"); + g.drawString(str, x, y+b); + g.drawString(str, x, y-b); + g.drawString(str, x+b, y); + g.drawString(str, x-b, y); + + g.setColor(fc); + g.drawString(str,x+1,y); +} + + +function getSteps() { + try{ + if (WIDGETS.wpedom !== undefined) { + return WIDGETS.wpedom.getSteps(); + } else if (WIDGETS.activepedom !== undefined) { + return WIDGETS.activepedom.getSteps(); + } + } catch(ex) { + // In case we failed, we can only show 0 steps. + } + + return 0; +} + + +function draw() { + // queue draw in one minute + queueDraw(); + + var x = g.getWidth()/2; + var y_offset = settings.fullscreen ? 0 : 10; + var y = g.getHeight()/2-20 + y_offset; + + g.reset().clearRect(0,24,g.getWidth(),g.getHeight()); + g.drawImage(getImg(),0,0); + + // Draw time + var date = new Date(); + var timeStr = locale.time(date,1); + g.setFontAlign(0,0); + g.setFontTime(); + drawBorderString(timeStr, x, y, 5, "#fff"); + + // Draw date + y += 50; + x = x - g.stringWidth(timeStr) / 2 + 5; + g.setFontDate(); + g.setFontAlign(-1,0); + var dateStr = locale.dow(date, true).toUpperCase() + date.getDate(); + var fc = Bangle.isLocked() ? "#0ff" :"#fff"; + fc = E.getBattery() < 50 ? "#f00" : fc; + drawBorderString(dateStr, x, y, 3, fc); + + // Draw steps + g.setFontAlign(1,1); + var steps = parseInt(getSteps() / 1000); + drawBorderString(steps, g.getWidth()-10, g.getHeight()-10, 3, "#f0f"); + + // Draw widgets if not fullscreen + if(settings.fullscreen){ + for (let wd of WIDGETS) {wd.draw=()=>{};wd.area="";} + } else { + Bangle.drawWidgets(); + } +} + +Bangle.loadWidgets(); + +// Clear the screen once, at startup +g.setTheme({bg:"#000",fg:"#fff",dark:false}).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; + } +}); + + +Bangle.on('lock', function(isLocked) { + print("LOCK"); + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + draw(); +}); + + +// Show launcher when middle button pressed +Bangle.setUI("clock"); diff --git a/apps/90sclk/app.png b/apps/90sclk/app.png new file mode 100644 index 000000000..29875b1dc Binary files /dev/null and b/apps/90sclk/app.png differ diff --git a/apps/90sclk/bg.png b/apps/90sclk/bg.png new file mode 100644 index 000000000..4ebf755ad Binary files /dev/null and b/apps/90sclk/bg.png differ diff --git a/apps/90sclk/metadata.json b/apps/90sclk/metadata.json new file mode 100644 index 000000000..fb2824a6f --- /dev/null +++ b/apps/90sclk/metadata.json @@ -0,0 +1,18 @@ +{ + "id": "90sclk", + "name": "90s Clock", + "version": "0.02", + "description": "A 90s style watch-face", + "readme": "README.md", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"},{"url":"screenshot_2.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"90sclk.app.js","url":"app.js"}, + {"name":"90sclk.img","url":"app-icon.js","evaluate":true}, + {"name":"90sclk.settings.js","url":"settings.js"} + ] +} diff --git a/apps/90sclk/screenshot.png b/apps/90sclk/screenshot.png new file mode 100644 index 000000000..182a85321 Binary files /dev/null and b/apps/90sclk/screenshot.png differ diff --git a/apps/90sclk/screenshot_2.png b/apps/90sclk/screenshot_2.png new file mode 100644 index 000000000..9646b1168 Binary files /dev/null and b/apps/90sclk/screenshot_2.png differ diff --git a/apps/90sclk/settings.js b/apps/90sclk/settings.js new file mode 100644 index 000000000..8f97cd317 --- /dev/null +++ b/apps/90sclk/settings.js @@ -0,0 +1,31 @@ +(function(back) { + const SETTINGS_FILE = "90sclk.setting.json"; + + // initialize with default settings... + const storage = require('Storage') + let settings = { + fullscreen: false, + }; + let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; + for (const key in saved_settings) { + settings[key] = saved_settings[key] + } + + function save() { + storage.write(SETTINGS_FILE, settings) + } + + + E.showMenu({ + '': { 'title': '90s Clock' }, + '< Back': back, + 'Full Screen': { + value: settings.fullscreen, + format: () => (settings.fullscreen ? 'Yes' : 'No'), + onchange: () => { + settings.fullscreen = !settings.fullscreen; + save(); + }, + } + }); + }) diff --git a/apps/altimeter/ChangeLog b/apps/altimeter/ChangeLog new file mode 100644 index 000000000..29388520e --- /dev/null +++ b/apps/altimeter/ChangeLog @@ -0,0 +1,2 @@ +0.01: New App! +0.02: Actually upload correct code diff --git a/apps/altimeter/app-icon.js b/apps/altimeter/app-icon.js new file mode 100644 index 000000000..1f8dfb637 --- /dev/null +++ b/apps/altimeter/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4UA///t9TmuV3+GJf4AN+ALVgf8BasP/4LVn//4ALUWgJUJBZUDBYJUIBZcP3/nKhEOt/WBZE5r+VKg0KgEVr9V3wLHqtaqt9sALElWAqoABt1QBZNeBYuq0ILCrVUBYulBYVWBYkCBYgABBZ8K1WVBYlABZegKQWqBQlVqALKqWoKQWpBYtWBZeqKRAAB1WABZZSHAANq0ALLKQ6qC1ALLKQ5UEAH4AG")) diff --git a/apps/altimeter/app.js b/apps/altimeter/app.js new file mode 100644 index 000000000..cac4e80fd --- /dev/null +++ b/apps/altimeter/app.js @@ -0,0 +1,30 @@ +Bangle.setBarometerPower(true, "app"); + +g.clear(1); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +var zero = 0; +var R = Bangle.appRect; +var y = R.y + R.h/2; +var MEDIANLENGTH = 20; +var avr = [], median; +var value = 0; + +Bangle.on('pressure', function(e) { + while (avr.length>MEDIANLENGTH) avr.pop(); + avr.unshift(e.altitude); + median = avr.slice().sort(); + g.reset().clearRect(0,y-30,g.getWidth()-10,y+30); + if (median.length>10) { + var mid = median.length>>1; + value = E.sum(median.slice(mid-4,mid+5)) / 9; + g.setFont("Vector",50).setFontAlign(0,0).drawString((value-zero).toFixed(1), g.getWidth()/2, y); + } +}); + +g.reset(); +g.setFont("6x8").setFontAlign(0,0).drawString(/*LANG*/"ALTITUDE (m)", g.getWidth()/2, y-40); +g.setFont("6x8").setFontAlign(0,0,3).drawString(/*LANG*/"ZERO", g.getWidth()-5, g.getHeight()/2); +setWatch(function() { + zero = value; +}, (process.env.HWVERSION==2) ? BTN1 : BTN2, {repeat:true}); diff --git a/apps/altimeter/app.png b/apps/altimeter/app.png new file mode 100644 index 000000000..9c9d69077 Binary files /dev/null and b/apps/altimeter/app.png differ diff --git a/apps/altimeter/metadata.json b/apps/altimeter/metadata.json new file mode 100644 index 000000000..8bdbf3022 --- /dev/null +++ b/apps/altimeter/metadata.json @@ -0,0 +1,12 @@ +{ "id": "altimeter", + "name": "Altimeter", + "version":"0.02", + "description": "Simple altimeter that can display height changed using Bangle.js 2's built in pressure sensor.", + "icon": "app.png", + "tags": "tool,outdoors", + "supports" : ["BANGLEJS2"], + "storage": [ + {"name":"altimeter.app.js","url":"app.js"}, + {"name":"altimeter.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/bwclk/ChangeLog b/apps/bwclk/ChangeLog new file mode 100644 index 000000000..05a22774f --- /dev/null +++ b/apps/bwclk/ChangeLog @@ -0,0 +1,5 @@ +0.01: New App. +0.02: Use build in function for steps and other improvements. +0.03: Adapt colors based on the theme of the user. +0.04: Steps can be hidden now such that the time is even larger. +0.05: Included icons for information. \ No newline at end of file diff --git a/apps/bwclk/README.md b/apps/bwclk/README.md new file mode 100644 index 000000000..a5b66df71 --- /dev/null +++ b/apps/bwclk/README.md @@ -0,0 +1,16 @@ +# Black & White clock + +![](screenshot.png) + +## Features +- Fullscreen on/off +- The design is adapted to the theme of your bangle. +- Tab left/right of screen to show steps, temperature etc. +- Enable / disable lock icon in the settings. +- If the "sched" app is installed tab top / bottom of the screen to set the timer. + +## Thanks to +Icons created by Flaticon + +## Creator +- [David Peer](https://github.com/peerdavid) diff --git a/apps/bwclk/app-icon.js b/apps/bwclk/app-icon.js new file mode 100644 index 000000000..1df0fa6a5 --- /dev/null +++ b/apps/bwclk/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgIcah0EgEB/H8iFsAoOY4kMBYMDhmGgXkAoUGiWkAoQQBoAFCjgnCAoM4hgFDuEI+wpC8EKyg1C/0eAoMAsEAiQvBAAeAApQAB/4Ao+P4v/wn0P8Pgn/wnkH4Pjv/j/nn9PH//n/nj/IFF4F88AXBAoM88EcAoPHj//jlDAoOf/+Y+YFHjnnjAjBEIIjD+BHDO9IALA==")) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js new file mode 100644 index 000000000..d4e6c50ab --- /dev/null +++ b/apps/bwclk/app.js @@ -0,0 +1,412 @@ +/* + * Includes + */ +const locale = require('locale'); +const storage = require('Storage'); + +/* + * Statics + */ +const SETTINGS_FILE = "bwclk.setting.json"; +const TIMER_IDX = "bwclk"; +const W = g.getWidth(); +const H = g.getHeight(); + +/* + * Settings + */ +let settings = { + fullscreen: false, + showLock: true, + showInfo: 0, +}; + +let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; +for (const key in saved_settings) { + settings[key] = saved_settings[key] +} + + +/* + * Assets + */ + +// Manrope font +Graphics.prototype.setLargeFont = function(scale) { + // Actual height 49 (50 - 2) + this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAAAAAD/AAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD/AAAAAAAAAP8AAAAAAAAA/wAAAAAAAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAfwAAAAAAAAf/AAAAAAAAf/8AAAAAAAf//wAAAAAAP///AAAAAAP///8AAAAAP////wAAAAP////4AAAAP////8AAAAH////8AAAAH////8AAAAB////8AAAAAH///+AAAAAAf//+AAAAAAB//+AAAAAAAH/+AAAAAAAAf+AAAAAAAAB/AAAAAAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///gAAAAAD////4AAAAA/////4AAAAH/////4AAAA//////wAAAH//////gAAA///////AAAH//////+AAA///////4AAD/4AAAH/wAAP+AAAAP/AAB/wAAAAf8AAH/AAAAA/4AAf4AAAAB/gAB/gAAAAH+AAP8AAAAAf4AA/wAAAAB/gAD/AAAAAH+AAP8AAAAAf4AAf4AAAAB/gAB/gAAAAH+AAH+AAAAA/4AAf8AAAAH/AAB/4AAAA/8AAD/4AAAH/wAAP/8AAH/+AAAf//////4AAA///////AAAB//////4AAAD//////AAAAH/////4AAAAP////+AAAAAP////gAAAAAD///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+AAAAAAAAB/wAAAAAAAAH/AAAAAAAAA/4AAAAAAAAH/gAAAAAAAAf8AAAAAAAAD/gAAAAAAAAP+AAAAAAAAB///////8AAH///////wAAf///////AAB///////8AAH///////wAAf///////AAB///////8AAH///////wAAP///////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAfwAAAH8AAAD/AAAB/wAAAf8AAAP/AAAD/wAAB/8AAAf/AAAP/wAAD/8AAB//AAAf/wAAH/8AAD//AAA//gAAf/8AAD/wAAB//wAAf+AAAP//AAB/wAAB//8AAH+AAAP//wAAf4AAB///AAD/AAAP/v8AAP8AAB/8/wAA/wAAP/j/AAD/AAB/8P8AAH+AAH/g/wAAf4AA/8D/AAB/wAH/gP8AAH/AA/+A/wAAf/AP/wD/AAA//D/+AP8AAD////wA/wAAH///+AD/AAAP///wAP8AAAf//+AA/wAAA///wAD/AAAB//+AAP8AAAB//gAA/wAAAB/4AAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4AAAD+AAAAHwAAAf4AAAAfwAAB/gAAAB/gAAH+AAAAP/AAAf4AAAA/8AAB/gAAAD/4AAH+ADAAH/wAAf4AeAAP/AAB/gD+AAP8AAH+Af+AA/4AAf4D/4AB/gAB/gP/AAH+AAH+B/8AAf4AAf4P/wAB/gAB/h//AAH+AAH+P/8AAf4AAf5//wAB/gAB/v//gAP+AAH+//+AA/4AAf//f8AH/AAB//5/8B/8AAH//D////gAAf/4P///+AAB//Af///wAAH/4A///+AAAf/AB///wAAB/4AD//+AAAH/AAH//gAAAP4AAD/4AAAAAAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAAAAA/+AAAAAAAAP/4AAAAAAAH//gAAAAAAB//+AAAAAAAf//4AAAAAAH///gAAAAAB///+AAAAAAf///4AAAAAH//9/gAAAAD///H+AAAAA///wf4AAAAP//8B/gAAAD///AH+AAAA///wAf4AAAH//8AB/gAAAf//AAH+AAAB//gAAf4AAAH/4AAB/gAAAf+AAAH+AAAB/gAf///8AAH4AB////wAAeAAH////AABgAAf///8AAAAAB////wAAAAAH////AAAAAAf///8AAAAAB////wAAAAAH////AAAAAAAAf4AAAAAAAAB/gAAAAAAAAH+AAAAAAAAAfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAeAAAAAf//AB+AAAH///+AP8AAAf///4A/4AAB////gD/wAAH////Af/gAAf///8B/+AAB////wB/8AAH///+AB/wAAf4Af4AD/gAB/gB/AAP+AAH+AP8AAf4AAf4A/wAB/gAB/gD+AAH+AAH+AP4AAf4AAf4A/gAB/gAB/gD/AAH+AAH+AP8AAf4AAf4A/wAD/gAB/gD/gAf8AAH+AH/AD/wAAf4Af/Af+AAB/gB////4AAH+AD////AAAf4AH///8AAB/gAP///gAAH+AA///8AAAAAAA///AAAAAAAB//4AAAAAAAB/+AAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB///gAAAAAB////4AAAAAf////4AAAAH/////4AAAA//////wAAAH//////gAAA///////AAAH//////+AAAf//////4AAD/4D/wH/wAAP+AP8AP/AAB/wB/gAf8AAH/AH8AA/4AAf4A/wAB/gAB/gD/AAH+AAH8AP4AAf4AA/wA/gAB/gAD/AD+AAH+AAH8AP8AAf4AAf4A/wAB/gAB/gD/AAP+AAH+AP+AB/wAAf8Af8AP/AAA/4B/8B/8AAD/gH////gAAP8AP///8AAAfgAf///wAAA8AB///+AAADgAD///wAAAAAAD//+AAAAAAAH//gAAAAAAAH/4AAAAAAAAB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/gAAAAAAAAH+AAAAAAAAAf4AAAAAAAAB/gAAAAAAAAH+AAAAAAAAAf4AAAAADgAB/gAAAAA+AAH+AAAAAf4AAf4AAAAH/gAB/gAAAD/+AAH+AAAA//4AAf4AAAf//gAB/gAAH//+AAH+AAD///wAAf4AA///8AAB/gAf//+AAAH+AH///gAAAf4D///wAAAB/g///8AAAAH+f//+AAAAAf////gAAAAB////wAAAAAH///8AAAAAAf//+AAAAAAB///gAAAAAAH//wAAAAAAAf/8AAAAAAAB/+AAAAAAAAH/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/wAAAAB/wB//wAAAAf/wf//gAAAD//z///AAAAf/////+AAAD//////8AAAf//////4AAD///////gAAP////w//AAB/+f/8Af8AAH/Af/gA/4AAf4A/8AD/gAB/gB/wAH+AAP8AH+AAf4AA/wAf4AB/gAD/AB/gAH+AAP8AH+AAf4AA/wAf4AB/gAB/gB/wAH+AAH+AP/AAf4AAf8A/+AD/gAB/8f/8Af8AAD////4H/wAAP//////+AAAf//////4AAA///////AAAD//////8AAAH//z///gAAAH/+H//4AAAAH/gH//AAAAAAAAH/wAAAAAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfgAAAAAAAAP/wAAAAAAAD//wAAAAAAAf//wAAAAAAH///gABgAAA////AAPAAAD///+AB+AAAf///4AP4AAD////wB/wAAP/AP/AH/AAB/4Af+AP+AAH/AA/4A/4AAf4AB/gB/gAB/gAH+AH+AAP8AAP4Af4AA/wAA/gB/gAD/AAD+AH+AAP8AAP4Af4AA/4AB/gB/gAB/gAH+AH+AAH+AAfwA/4AAf8AD/AH/AAB/4Af4A/8AAD/4H/gP/wAAP//////+AAAf//////wAAA///////AAAB//////4AAAD//////AAAAH/////wAAAAH////+AAAAAH////AAAAAAAf/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf4AP8AAAAAB/gA/wAAAAAH+AD/AAAAAAf4AP8AAAAAB/gA/wAAAAAH+AD/AAAAAAf4AP8AAAAAB/gA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), 46, atob("ExwqHCYlJyYoIicoFg=="), 64+(scale<<8)+(1<<16)); + 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(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//84D//zgP/+GAAAAAAAAAAAAAAAAAAAD4AAAPgAAA+AAAAAAAAAAAAA+AAAD4AAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAg4AAHDgAAcOCABw54AHD/gAf/8AD/8AB//gAP8OAA9w4YCHD/gAcf+AB//gAf/gAP/uAA/w4ADnDgAAcOAABw4AAHAAAAcAAAAAAAAAAAAAAAIAA+A4AH8HwA/4PgHjgOAcHAcBwcBw/BwH78DgfvwOB8HA4HAOBw8A+HngB4P8ADgfgAAAYAAAAAAAAAAB4AAAf4AQB/gDgOHAeA4cDwDhweAOHDwA88eAB/nwAD88AAAHgAAA8AAAHn4AA8/wAHnvgA8cOAHhg4A8GDgHgcOA8B74BgD/AAAH4AAAAAAAAAAAAAAAAAMAAAH8AD8/4Af/3wB/8HgODwOA4HA4DgODgOAcOA4A44DwDzgHAH8AMAPwAQP+AAA/8AAAB4AAADAAAAAA+AAAD4AAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/8AD//+A/+/+H4AD98AAB3gAADIAAAAAAAAAAAAAIAAABwAAAXwAAHPwAB8P8D/gP//4AH/8AAAAAAAAAAAAAAAAAAAAAAAAGAAAA4gAAB/AAAH8AAD/AAAP8AAAH4AAAfwAADiAAAOAAAAAAAAAAAAAAGAAAAYAAABgAAAGAAAAYAAABgAAD/+AAP/4AABgAAAGAAAAYAAABgAAAGAAAAYAAAAAAAAAAAAAADkAAAPwAAA/AAAAAAAAAAAAAAAAAAAAAAAAABgAAAGAAAAYAAABgAAAGAAAAYAAABgAAAGAAAAYAAAAAAAAAAAAAAAAAAAAAAADgAAAOAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAA4AAA/gAA/+AA//AA//AAP/AAA/AAADAAAAAAAAAAAAAAAAAAA//gAP//gB///AHgA8A8AB4DgADgOAAOA4AA4DgADgPAAeAeADwB///AD//4AD/+AAAAAAAAAAAAAAAA4AAAHgAAAcAAADwAAAP//+A///4D///gAAAAAAAAAAAAAAAAAAAAAAYAeADgD4AeAfAD4DwAfgOAD+A4Ae4DgDzgOAeOA4Dw4DweDgH/wOAP+A4AfwDgAAAAAAAAAAAAIAOAA4A4ADwDggHAOHgOA48A4DnwDgO/AOA7uA4D84HgPh/8A8H/gDgH8AAACAAAAAAAAAAAAAHgAAB+AAA/4AAP7gAD+OAA/g4AP4DgA+AOADAA4AAB/+AAH/4AAf/gAADgAAAOAAAAAAAAAAAAAAAAD4cAP/h4A/+HwDw4HgOHAOA4cA4DhwDgOHAOA4cA4Dh4HAOD58A4H/gAAP8AAAGAAAAAAAAAAAAAAAAD/+AAf/8AD//4AePDwDw4HgOHAOA4cA4DhwDgOHAOA4cB4Bw8PAHD/8AIH/gAAH4AAAAAAAAAADgAAAOAAAA4AAYDgAHgOAD+A4B/wDgf4AOP+AA7/AAD/gAAP4AAA8AAAAAAAAAAAAAAAAAAeH8AD+/4Af//wDz8HgOHgOA4OA4Dg4DgODgOA4eA4Dz8HgH//8AP7/gAeH8AAAAAAAAAAAAAAAA+AAAH+AgB/8HAHh4cA8Dg4DgODgOAcOA4Bw4DgODgPA4eAeHDwB///AD//4AD/+AAAAAAAAAAAAAAAAAAAAAAAAAAODgAA4OAADg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAABwA5AHAD8AcAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAB8AAAP4AAB5wAAPDgAB4HAAHAOAAIAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGMAAAYwAABjAAAGMAAAYwAABjAAAGMAAAYwAABjAAAGMAAAYwAABjAAAGMAAAYwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAEAAcA4AB4HAADw4AADnAAAH4AAAPAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAB8AAAHgAAA4AAADgDzgOA/OA4D84DgeAAPHwAAf+AAA/wAAB8AAAAAAAAAAAAAAAAAAD+AAB/+AAP/8AB4B4AOABwBwADgHB8OA4P4cDhxxwMGDDAwYMMDBgwwOHHHA4f4cDh/xwHAHCAcAMAA8AwAB8PAAD/4AAD/AAAAAAAAAAAAAACAAAB4AAB/gAA/8AAf+AAP/wAH/nAA/gcADwBwAPwHAA/4cAA/9wAAf/AAAP/AAAD/gAAB+AAAA4AAAAAAAAAAAAAAD///gP//+A///4DgcDgOBwOA4HA4DgcDgOBwOA4HA4Dg8DgPHwOAf/h4A///AB8f4AAAfAAAAAAAP+AAD/+AAf/8AD4D4AeADwBwAHAOAAOA4AA4DgADgOAAOA4AA4DgADgOAAOAcABwB4APAD4D4AHgPAAOA4AAAAAAAAAAAAAAAP//+A///4D///gOAAOA4AA4DgADgOAAOA4AA4DgADgOAAOA8AB4BwAHAHwB8AP//gAP/4AAP+AAAAAAAAAAAAAAAA///4D///gP//+A4HA4DgcDgOBwOA4HA4DgcDgOBwOA4HA4DgcDgOBgOA4AA4AAAAAAAAAAAAAAD///gP//+A///4DgcAAOBwAA4HAADgcAAOBwAA4HAADgcAAOAwAA4AAAAAAAAAf+AAD/+AA//+ADwB4AeADwDwAHgOAAOA4AA4DgADgOAAOA4AA4DgMDgPAweAcDBwB8MfADw/4AHD/AAAPwAAAAAAAAAAAAAAAP//+A///4D///gABwAAAHAAAAcAAABwAAAHAAAAcAAABwAAAHAAAAcAAABwAA///4D///gP//+AAAAAAAAAAAAAAAAAAAD///gP//+A///4AAAAAAAAAAAADgAAAPAAAA+AAAA4AAADgAAAOAAAA4AAAHgP//8A///wD//8AAAAAAAAAAAAAAAAAAAA///4D///gP//+AAHAAAA+AAAP8AAB54AAPDwAB4HgAPAPAB4AfAPAA+A4AA4DAABgAAACAAAAAAAAAAP//+A///4D///gAAAOAAAA4AAADgAAAOAAAA4AAADgAAAOAAAA4AAADgAAAAAAAAAAAAAAP//+A///4D///gD+AAAD+AAAB+AAAB/AAAB/AAAB/AAAB+AAAH4AAB+AAA/gAAP4AAD+AAA/AAAfwAAD///gP//+A///4AAAAAAAAAAAAAAAAAAAP//+A///4D///gHwAAAPwAAAPgAAAfgAAAfAAAAfAAAA/AAAA+AAAB+AAAB8A///4D///gP//+AAAAAAAAAAAP+AAD/+AAf/8AD4D4AeADwBwAHAOAAOA4AA4DgADgOAAOA4AA4DgADgOAAOAcABwB4APAD4D4AH//AAP/4AAP+AAAAAAAAAAAP//+A///4D///gOAcAA4BwADgHAAOAcAA4BwADgHAAOAcAA4DgAD4eAAH/wAAP+AAAPgAAAAAAAA/4AAP/4AB//wAPgPgB4APAHAAcA4AA4DgADgOAAOA4AA4DgADgOAAOA4AO4BwA/AHgB8APgPwAf//gA//uAA/4QAAAAAAAAAA///4D///gP//+A4BwADgHAAOAcAA4BwADgHAAOAcAA4B8ADgP8APh/8Af/H4A/4HgA+AGAAAAAAAAAAAABgAHwHAA/g+AH/A8A8cBwDg4DgODgOA4OA4DgcDgOBwOA4HA4DwODgHg4cAPh/wAcH+AAwPwAAAAADgAAAOAAAA4AAADgAAAOAAAA4AAAD///gP//+A///4DgAAAOAAAA4AAADgAAAOAAAA4AAADgAAAAAAAAAAAAAAAAAP//AA///AD//+AAAB8AAABwAAADgAAAOAAAA4AAADgAAAOAAAA4AAAHgAAA8A///gD//8AP//gAAAAAAAAAAIAAAA8AAAD+AAAH/AAAD/wAAB/4AAA/8AAAf4AAAPgAAB+AAA/4AAf+AAP/AAH/gAD/wAAP4AAA4AAAAAAAAPAAAA/gAAD/4AAA/+AAAf/AAAH/gAAB+AAAf4AAf/AAf/AAP/gAD/gAAPwAAA/4AAA/+AAAf/AAAH/wAAB/gAAB+AAB/4AA/+AA/+AA/+AAD/AAAPAAAAgAAAAAAAAMAAGA4AA4D4APgHwB8APwfAAPn4AAf+AAAfwAAB/AAAf+AAD4+AA/B8AHwB8A+AD4DgADgMAAGAwAAADwAAAPwAAAPwAAAfgAAAfgAAAf/4AAf/gAH/+AB+AAAPwAAD8AAA/AAADwAAAMAAAAgAAAAAAAAMAACA4AA4DgAPgOAD+A4Af4DgH7gOB+OA4Pw4Dj8DgO/AOA/4A4D+ADgPgAOA4AA4DAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/////////gAAAOAAAA4AAADAAAAAAAAAAAAAAAAAAAAAAA4AAAD+AAAP/gAAH/4AAB/+AAAf+AAAH4AAABgAAAAAAAAADAAAAOAAAA4AAADgAAAP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAADgAAAcAAADgAAAcAAADgAAAcAAAB4AAADwAAADgAAAHAAAAOAAAAYAAAAAAAAAAAAAAAAAAAAMAAAAwAAADAAAAMAAAAwAAADAAAAMAAAAwAAADAAAAMAAAAwAAADAAAAMAAAAwAAADAAAAMAAAAwAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAHH8AA8/4AHzjgAcMOABxwYAHHBgAccOABxwwAHGHAAP/4AA//4AA//gAAAAAAAAAAAAAAAAAAA///4D///gP//+AA4BwAHADgAcAOABwA4AHADgAcAOAB4B4ADwPAAP/8AAf/AAAf4AAAAAAAAAAAAPwAAD/wAAf/gADwPAAeAeABwA4AHADgAcAOABwA4AHADgAeAeAA8DwABwOAADAwAAAAAAAAAAAA/AAAP/AAD//AAPA8AB4B4AHADgAcAOABwA4AHADgAcAOAA4BwD///gP//+A///4AAAAAAAAAAAAAAAAPwAAD/wAAf/gAD2PAAeYeABxg4AHGDgAcYOABxg4AHGDgAeYeAA/jwAB+OAAD4wAABgAAAAAAAAAAABgAAAGAAAB//+Af//4D///gPcAAA5gAADGAAAMYAAAAAAAAAPwAAD/wMA//w4DwPHgeAePBwA4cHADhwcAOHBwA4cHADhwOAcPB///4H///Af//wAAAAAAAAAAAAAAAAAAD///gP//+AA//4ADgAAAcAAABwAAAHAAAAcAAABwAAAHgAAAP/+AAf/4AA//gAAAAAAAAAAAAAAMf/+A5//4Dn//gAAAAAAAAAAAAAAAAAAHAAAAfn///+f//+5///wAAAAAAAAAAAAAAAAAAP//+A///4D///gAAcAAAD8AAAf4AADzwAAeHgAHwPAAeAeABgA4AEABgAAAAAAAAAD///gP//+A///4AAAAAAAAAAAAAAAAAAAAf/+AB//4AH//gAOAAABwAAAHAAAAcAAABwAAAHgAAAP/+AA//4AB//gAOAAABwAAAHAAAAcAAABwAAAHgAAAf/+AA//4AA//gAAAAAAAAAAAAAAAf/+AB//4AD//gAOAAABwAAAHAAAAcAAABwAAAHAAAAeAAAA//4AB//gAD/+AAAAAAAAAAAAAAAAD8AAA/8AAH/4AA8DwAHgHgAcAOABwA4AHADgAcAOABwA4AHgHgAPh8AAf/gAA/8AAA/AAAAAAAAAAAAAAAAB///8H///wf///A4BwAHADgAcAOABwA4AHADgAcAOAB4B4ADwPAAP/8AAf/AAAf4AAAAAAAAAAAAPwAAD/wAA//wADwPAAeAeABwA4AHADgAcAOABwA4AHADgAOAcAB///8H///wf///AAAAAAAAAAAAAAAAAAAH//gAf/+AB//4ADwAAAcAAABwAAAHAAAAcAAAAAAAAAAMAAHw4AA/jwAH+HgAcYOABxw4AHHDgAcMOABw44AHjjgAPH+AA8fwAAw+AAAAAABgAAAGAAAAcAAAf//wB///AH//+ABgA4AGADgAYAOABgA4AAAAAAAAAAAAAAAH/AAAf/wAB//wAAB/AAAAeAAAA4AAADgAAAOAAAA4AAADgAAAcAB//4AH//gAf/+AAAAAAAAAAAAAAABwAAAH4AAAf8AAAP8AAAH+AAAD+AAAD4AAA/gAAf8AAP+AAH/AAAfgAABwAAAAAAAAAAAABwAAAH8AAAf+AAAP/gAAD/gAAB+AAAf4AAP8AAP+AAB/AAAH4AAAf8AAAP+AAAD/gAAB+AAAf4AAf/AAP/AAB/gAAHgAAAQAAABAAIAHADgAeAeAA8HwAB8+AAD/gAAD8AAAPwAAD/gAAfPgADwfAAeAeABwA4AEAAgAAAAABAAAAHgAAAfwAAA/wAAAf4BwAP4/AAP/8AAP+AAD/AAB/wAA/4AAP8AAB+AAAHAAAAQAAAAAAIAHADgAcAeABwD4AHA/gAcHuABx84AHPDgAf4OAB/A4AHwDgAeAOABgA4AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAH4Af//////n//AAAA4AAADgAAAAAAAAAAAAAAAAAP//+A///4D///gAAAAAAAAAAAAAAAAAAA4AAADgAAAOAAAA//5/9////wAH4AAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAeAAAD4AAAOAAAA4AAADgAAAHAAAAcAAAA4AAADgAAAOAAAD4AAAPAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), 32, atob("BgkMGhEZEgYMDAwQCAwICxILEBAREBEOEREJCREVEQ8ZEhEUExAOFBQHDREPGBMUERQSEhEUERsREBIMCwwTEg4QERAREQoREQcHDgcYEREREQoPDBEPFg8PDwwIDBMc"), 28+(scale<<8)+(1<<16)); + return this; +}; + +var imgLock = { + width : 16, height : 16, bpp : 1, + transparent : 0, + buffer : E.toArrayBuffer(atob("A8AH4A5wDDAYGBgYP/w//D/8Pnw+fD58Pnw//D/8P/w=")) +}; + +var imgSteps = { + width : 24, height : 24, bpp : 1, + transparent : 1, + buffer : require("heatshrink").decompress(atob("/H///wv4CBn4CD8ACCj4IBj8f+Eeh/wjgCBngCCg/4nEH//4h/+jEP/gRBAQX+jkf/wgB//8GwP4FoICDHgICCBwIA==")) +}; + +var imgBattery = { + width : 24, height : 24, bpp : 1, + transparent : 1, + buffer : require("heatshrink").decompress(atob("/4AN4EAg4TBgd///9oEAAQv8ARQRDDQQgCEwQ4OA")) +}; + +var imgBpm = { + width : 24, height : 24, bpp : 1, + transparent : 1, + buffer : require("heatshrink").decompress(atob("/4AOn4CD/wCCjgCCv/8jF/wGYgOA5MB//BC4PDAQnjAQPnAQgANA")) +}; + +var imgTemperature = { + width : 24, height : 24, bpp : 1, + transparent : 1, + buffer : require("heatshrink").decompress(atob("//D///wICBjACBngCNkgCP/0kv/+s1//nDn/8wICEBAIOC/08v//IYJECA==")) +}; + +var imgWind = { + 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==")) +}; + +var imgTimer = { + 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==")) +}; + +var imgCharging = { + 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=")) +}; + + + +/* + * Draw timeout + */ +// 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)); +} + + +/* + * Helper + */ +function getSteps() { + try{ + if (WIDGETS.wpedom !== undefined) { + return WIDGETS.wpedom.getSteps(); + } else if (WIDGETS.activepedom !== undefined) { + return WIDGETS.activepedom.getSteps(); + } else { + return Bangle.getHealthStatus("day").steps; + } + } catch(ex) { + // In case we failed, we can only show 0 steps. + } + + return 0; +} + + +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]) + " km/h"; + + return weather + + } catch(ex) { + // Return default + } + + return { + temp: "? °C", + hum: "-", + txt: "-", + wind: "? km/h", + wdir: "-", + wrose: "-" + }; +} + +function isAlarmEnabled(){ + try{ + var alarm = require('sched'); + var alarmObj = alarm.getAlarm(TIMER_IDX); + if(alarmObj===undefined || !alarmObj.on){ + return false; + } + + return true; + + } catch(ex){ } + return false; +} + +function getAlarmMinutes(){ + if(!isAlarmEnabled()){ + return -1; + } + + 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){ } +} + + +/* + * D R A W + */ +function draw() { + // queue draw in one minute + queueDraw(); + + // Set info + var showInfo = settings.showInfo; + if(isAlarmEnabled()){ + showInfo = 100; + } + + if(Bangle.isCharging()){ + showInfo = 101; + } + + + // Draw background + var yOffset = settings.fullscreen ? 0 : 10; + var y = H/5*2 + yOffset; + g.reset().clearRect(0,0,W,W); + g.setColor(g.theme.fg); + g.fillRect(0,y,W,H); + + // Draw date + y -= settings.fullscreen ? 5 : 0; + var date = new Date(); + g.setColor(g.theme.fg); + g.setFontAlign(1,1); + g.setMediumFont(); + var dateStr = date.getDate(); + dateStr = ("0" + dateStr).substr(-2); + g.drawString(dateStr, W/2-1, y+4); + + g.setSmallFont(); + g.setFontAlign(-1,1); + g.drawString(locale.dow(date, true), W/2 + 10, y-23); + g.drawString(locale.month(date, 1), W/2 + 10, y+1); + + // Draw time + g.setColor(g.theme.bg); + g.setFontAlign(0,-1); + var timeStr = locale.time(date,1); + y += settings.fullscreen ? 20 : 10; + + if(showInfo == 0){ + y += 8; + g.setLargeFont(); + } else { + g.setMediumFont(); + } + + g.drawString(timeStr, W/2, y); + + // Draw info or timer + y += H/5*2-5; + g.setFontAlign(0,0); + if(showInfo > 0){ + g.setSmallFont(); + + var infoStr = ""; + var infoImg; + if(showInfo == 100){ + infoStr = getAlarmMinutes() + " min."; + infoImg = imgTimer; + } else if(showInfo == 101){ + infoStr = E.getBattery() + "%"; + infoImg = imgCharging; + } else if (showInfo == 1){ + infoStr = E.getBattery() + "%"; + infoImg = imgBattery; + } else if (showInfo == 2){ + infoStr = getSteps() + infoStr = Math.round(infoStr/100) / 10; // This ensures that we do not show e.g. 15.0k and 15k instead + infoStr = infoStr + "k"; + infoImg = imgSteps; + } else if (showInfo == 3){ + infoStr = Math.round(Bangle.getHealthStatus("day").bpm) + " bpm"; + infoImg = imgBpm; + } else if (showInfo == 4){ + var weather = getWeather(); + infoStr = weather.temp; + infoImg = imgTemperature; + } else if (showInfo == 5){ + var weather = getWeather(); + infoStr = weather.wind; + infoImg = imgWind; + } + + var imgWidth = 0; + if(infoImg !== undefined){ + imgWidth = infoImg.width; + var strWidth = g.stringWidth(infoStr); + g.drawImage(infoImg, W/2 - strWidth/2 - infoImg.width/2 - 5, y - infoImg.height/2); + } + g.drawString(infoStr, W/2 + imgWidth/2, y+3); + } + + // Draw lock + if(settings.showLock && Bangle.isLocked()){ + g.setColor(g.theme.fg); + g.drawImage(imgLock, W-16, 2); + } + + // Draw widgets if not fullscreen + if(settings.fullscreen){ + for (let wd of WIDGETS) {wd.draw=()=>{};wd.area="";} + } else { + Bangle.drawWidgets(); + } +} + +Bangle.loadWidgets(); + +// Clear the screen once, at startup and set the correct theme. +var bgOrig = g.theme.bg +var fgOrig = g.theme.fg +g.setTheme({bg:fgOrig,fg:bgOrig}).clear(); +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; + } +}); + +Bangle.on('lock', function(isLocked) { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + draw(); +}); + +Bangle.on('charging',function(charging) { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + draw(); +}); + +Bangle.on('touch', function(btn, e){ + var left = parseInt(g.getWidth() * 0.2); + var right = g.getWidth() - left; + var upper = parseInt(g.getHeight() * 0.2); + var lower = g.getHeight() - upper; + + var is_left = e.x < left; + var is_right = e.x > right; + var is_upper = e.y < upper; + var is_lower = e.y > lower; + + if(is_upper){ + Bangle.buzz(40, 0.6); + increaseAlarm(); + draw(); + } + + if(is_lower){ + Bangle.buzz(40, 0.6); + decreaseAlarm(); + draw(); + } + + var maxInfo = 6; + if(is_right){ + Bangle.buzz(40, 0.6); + settings.showInfo = (settings.showInfo+1) % maxInfo; + storage.write(SETTINGS_FILE, settings); + draw(); + } + + if(is_left){ + Bangle.buzz(40, 0.6); + settings.showInfo = settings.showInfo-1; + settings.showInfo = settings.showInfo < 0 ? maxInfo-1 : settings.showInfo; + storage.write(SETTINGS_FILE, settings); + draw(); + } +}); + + +// Show launcher when middle button pressed +Bangle.setUI("clock"); diff --git a/apps/bwclk/app.png b/apps/bwclk/app.png new file mode 100644 index 000000000..5073f0ed0 Binary files /dev/null and b/apps/bwclk/app.png differ diff --git a/apps/bwclk/metadata.json b/apps/bwclk/metadata.json new file mode 100644 index 000000000..babaa37bf --- /dev/null +++ b/apps/bwclk/metadata.json @@ -0,0 +1,18 @@ +{ + "id": "bwclk", + "name": "BlackWhite Clock", + "version": "0.05", + "description": "Black and white clock.", + "readme": "README.md", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}, {"url":"screenshot_2.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"bwclk.app.js","url":"app.js"}, + {"name":"bwclk.img","url":"app-icon.js","evaluate":true}, + {"name":"bwclk.settings.js","url":"settings.js"} + ] +} diff --git a/apps/bwclk/screenshot.png b/apps/bwclk/screenshot.png new file mode 100644 index 000000000..02ef7a704 Binary files /dev/null and b/apps/bwclk/screenshot.png differ diff --git a/apps/bwclk/screenshot_2.png b/apps/bwclk/screenshot_2.png new file mode 100644 index 000000000..2f31c8b3c Binary files /dev/null and b/apps/bwclk/screenshot_2.png differ diff --git a/apps/bwclk/settings.js b/apps/bwclk/settings.js new file mode 100644 index 000000000..82d1cad0b --- /dev/null +++ b/apps/bwclk/settings.js @@ -0,0 +1,40 @@ +(function(back) { + const SETTINGS_FILE = "bwclk.setting.json"; + + // initialize with default settings... + const storage = require('Storage') + let settings = { + fullscreen: false, + showLock: true, + }; + let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; + for (const key in saved_settings) { + settings[key] = saved_settings[key] + } + + function save() { + storage.write(SETTINGS_FILE, settings) + } + + + E.showMenu({ + '': { 'title': 'BlackWhite Clock' }, + '< Back': back, + 'Fullscreen': { + value: settings.fullscreen, + format: () => (settings.fullscreen ? 'Yes' : 'No'), + onchange: () => { + settings.fullscreen = !settings.fullscreen; + save(); + }, + }, + 'Show Lock': { + value: settings.showLock, + format: () => (settings.showLock ? 'Yes' : 'No'), + onchange: () => { + settings.showLock = !settings.showLock; + save(); + }, + } + }); + }) diff --git a/apps/compass/ChangeLog b/apps/compass/ChangeLog index 4bb7838ac..d1adafc4c 100644 --- a/apps/compass/ChangeLog +++ b/apps/compass/ChangeLog @@ -3,3 +3,4 @@ 0.03: Eliminate flickering 0.04: Fix for Bangle.js 2 and themes 0.05: Fix bearing not clearing correctly (visible in single or double digit bearings) +0.06: Add button for force compass calibration diff --git a/apps/compass/README.md b/apps/compass/README.md new file mode 100644 index 000000000..d60192f73 --- /dev/null +++ b/apps/compass/README.md @@ -0,0 +1,29 @@ +# Compass + +This app uses Bangle.js's built-in magnetometer as a compass. + +## Usage + +Hold your Bangle.js **face up** (so the display is parallel to the ground), +and the red arrow will point north, with the heading in degrees printed at +the top of the screen. + +This compass app does not include tilt compensation - so much like a real +compass you should always keep it face up when taking a reading. + +The first time you run the compass after your Bangle has booted (or if +you move to an area with a substantially different magnetic field) you will +need to recalibrate your compass (even if a heading is shown). + +## Calibration + +Press the button next to the `RESET` label on the screen. The North/South marker +will disappear and a message will appear asking you to rotate the watch 360 degrees. + +* Hold the watch face up, so the display is parallel to the ground +* Rotate it around slowly, all 360 degrees (with the display still parallel to the ground) +* The `Uncalibrated` message will disappear before you have finished rotating the full 360 degrees - but you should still complete the full rotation in order for the compass to work properly. + +Once you've rotated the full 360 degrees your compass should now work fine, +and calibration is stored between runs of the app. However if you go near +to a strong magnet you may still need to recalibrate. diff --git a/apps/compass/compass.js b/apps/compass/compass.js index 65ad83c4f..4730111ac 100644 --- a/apps/compass/compass.js +++ b/apps/compass/compass.js @@ -38,7 +38,7 @@ Bangle.on('mag', function(m) { if (!wasUncalibrated) { g.clearRect(0,24,W,48); g.setFontAlign(0,-1).setFont("6x8"); - g.drawString("Uncalibrated\nturn 360° around",M,24+4); + g.drawString(/*LANG*/"Uncalibrated\nturn 360° around",M,24+4); wasUncalibrated = true; } } else { @@ -64,7 +64,12 @@ Bangle.on('mag', function(m) { oldHeading = m.heading; }); -g.clear(); +g.clear(1); +g.setFont("6x8").setFontAlign(0,0,3).drawString(/*LANG*/"RESET", g.getWidth()-5, g.getHeight()/2); +setWatch(function() { + Bangle.resetCompass(); +}, (process.env.HWVERSION==2) ? BTN1 : BTN2, {repeat:true}); + Bangle.loadWidgets(); Bangle.drawWidgets(); Bangle.setCompassPower(1); diff --git a/apps/compass/metadata.json b/apps/compass/metadata.json index 318d90c86..3e3b37f72 100644 --- a/apps/compass/metadata.json +++ b/apps/compass/metadata.json @@ -1,12 +1,13 @@ { "id": "compass", "name": "Compass", - "version": "0.05", + "version": "0.06", "description": "Simple compass that points North", "icon": "compass.png", "screenshots": [{"url":"screenshot_compass.png"}], "tags": "tool,outdoors", "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", "storage": [ {"name":"compass.app.js","url":"compass.js"}, {"name":"compass.img","url":"compass-icon.js","evaluate":true} diff --git a/apps/fuzzyw/ChangeLog b/apps/fuzzyw/ChangeLog new file mode 100644 index 000000000..7b83706bf --- /dev/null +++ b/apps/fuzzyw/ChangeLog @@ -0,0 +1 @@ +0.01: First release diff --git a/apps/fuzzyw/README.md b/apps/fuzzyw/README.md new file mode 100644 index 000000000..906eb167b --- /dev/null +++ b/apps/fuzzyw/README.md @@ -0,0 +1,26 @@ +# Fuzzy Text Clock + +An imprecise clock for when you're not in a rush. + +This clock is a remake of one of my favourite Pebble watchfaces, Fuzzy Text International. I use this watch for weekends and holidays, when 'within 5 minutes of the actual time' is close enough! + +By default it will use the language set on the watch, go to settings to pick: +* en_GB - English +* en_US - American +* es_ES - Spanish +* fr_FR - French +* no_NO - Norwegian +* sv_SE - Swedish +* de_DE - German + +Most translations are taken from the original Fuzzy Text International code. + +## TODO +* Bold hour word (as the pebble version has) +* Animation when changing time? + +## References +Based on Pebble app Fuzzy Text International: https://github.com/hallettj/Fuzzy-Text-International + +![](fuzzyw-light.png) +![](fuzzyw-dark.png) diff --git a/apps/fuzzyw/fuzzy_strings.json b/apps/fuzzyw/fuzzy_strings.json new file mode 100644 index 000000000..8594ad554 --- /dev/null +++ b/apps/fuzzyw/fuzzy_strings.json @@ -0,0 +1,163 @@ +{ + "en_GB":{ + "hours":[ + "midnight", "one", "two", "three", "four", "five", + "six", "seven", "eight", "nine", "ten", "eleven", + "twelve", "one", "two", "three", "four", "five", + "six", "seven", "eight", "nine", "ten", "eleven" + ], + "minutes":[ + "*$1 o'clock", + "five past *$1", + "ten past *$1", + "quarter past *$1", + "twenty past *$1", + "twenty five past *$1", + "half past *$1", + "twenty five to *$2", + "twenty to *$2", + "quarter to *$2", + "ten to *$2", + "five to *$2" + ], + "text_scale":3.5 + }, + "en_US":{ + "hours":[ + "midnight", "one", "two", "three", "four", "five", + "six", "seven", "eight", "nine", "ten", "eleven", + "twelve", "one", "two", "three", "four", "five", + "six", "seven", "eight", "nine", "ten", "eleven" + ], + "minutes":[ + "*$1 o'clock", + "five after *$1", + "ten after *$1", + "quarter after *$1", + "twenty after *$1", + "twenty five after *$1", + "half past *$1", + "twenty five to *$2", + "twenty to *$2", + "quarter to *$2", + "ten to *$2", + "five to *$2" + ], + "text_scale":3.5 + }, + "es_ES":{ + "hours":[ + "doce", "una", "dos", "tres", "cuatro", "cinco", + "seis", "siete", "ocho", "nueve", "diez", "once", + "doce", "una", "dos", "tres", "cuatro", "cinco", + "seis", "siete", "ocho", "nueve", "diez", "once" + ], + "minutes":[ + "*$1 en punto", + "*$1 y cinco", + "*$1 y diez", + "*$1 y cuarto", + "*$1 y veinte", + "*$1 y veinti- cinco", + "*$1 y media", + "*$2 menos veinti- cinco", + "*$2 menos veinte", + "*$2 menos cuarto", + "*$2 menos diez", + "*$2 menos cinco" + ], + "text_scale":3.5 + }, + "fr_FR":{ + "hours":[ + "douze", "une", "deux", "trois", "quatre", "cinq", + "six", "sept", "huit", "neuf", "dix", "onze", + "douze", "une", "deux", "trois", "quatre", "cinq", + "six", "sept", "huit", "neuf", "dix", "onze" + ], + "minutes":[ + "*$1 heures", + "*$1 heures cinq", + "*$1 heures dix", + "*$1 heures et quart", + "*$1 heures vingt", + "*$1 heures vingt- cinq", + "*$1 heures et demie", + "*$2 moins vingt- cinq", + "*$2 heures moins vingt", + "*$2 moins le quart", + "*$2 heures moins dix", + "*$2 heures moins cinq" + ], + "text_scale":3.5 + }, + "no_NB":{ + "hours":[ + "tolv", "ett", "to", "tre", "fire", "fem", + "seks", "sju", "åtte", "ni", "ti", "elleve", + "tolv", "ett", "to", "tre", "fire", "fem", + "seks", "sju", "åtte", "ni", "ti", "elleve" + ], + "minutes":[ + "klokka er *$1", + "fem over *$1", + "ti over *$1", + "kvart over *$1", + "ti på halv *$2", + "fem på halv *$2", + "halv *$2", + "fem over halv *$2", + "ti over halv *$2", + "kvart på *$2", + "ti på *$2", + "fem på *$2" + ], + "text_scale":3.5 + }, + "sv_SE":{ + "hours":[ + "tolv", "ett", "två", "tre", "fyra", "fem", + "sex", "sju", "åtta", "nio", "tio", "elva", + "tolv", "ett", "två", "tre", "fyra", "fem", + "sex", "sju", "åtta", "nio", "tio", "elva" + ], + "minutes":[ + "*$1", + "fem över *$1", + "tio över *$1", + "kvart över *$1", + "tjugo över *$1", + "fem i halv *$2", + "halv *$2", + "fem över halv *$2", + "tjugo i *$2", + "kvart i *$2", + "tio i *$2", + "fem i *$2" + ], + "text_scale":3.5 + }, + "de_DE":{ + "hours":[ + "zwölf", "eins", "zwei", "drei", "vier", "fünf", + "sechs", "sieben", "acht", "neun", "zehn", "elf", + "zwölf", "eins", "zwei", "drei", "vier", "fünf", + "sechs", "sieben", "acht", "neun", "zehn", "elf" + ], + "minutes":[ + "*$1 uhr", + "fünf nach *$1", + "zehn nach *$1", + "viertel nach *$1", + "zwanzig nach *$1", + "fünf for halb *$2", + "halb *$2", + "fünf nach halb *$2", + "zwanzig vor *$2", + "viertel vor *$2", + "zehn vor *$2", + "fünf vor *$2" + ], + "text_scale":3.5 + } +} diff --git a/apps/fuzzyw/fuzzyw-dark.png b/apps/fuzzyw/fuzzyw-dark.png new file mode 100644 index 000000000..88220e5c7 Binary files /dev/null and b/apps/fuzzyw/fuzzyw-dark.png differ diff --git a/apps/fuzzyw/fuzzyw-light.png b/apps/fuzzyw/fuzzyw-light.png new file mode 100644 index 000000000..5383e08a4 Binary files /dev/null and b/apps/fuzzyw/fuzzyw-light.png differ diff --git a/apps/fuzzyw/fuzzyw.app.js b/apps/fuzzyw/fuzzyw.app.js new file mode 100644 index 000000000..07b5c4068 --- /dev/null +++ b/apps/fuzzyw/fuzzyw.app.js @@ -0,0 +1,75 @@ +// adapted from https://github.com/hallettj/Fuzzy-Text-International/ +const fuzzy_strings = require("Storage").readJSON("fuzzy_strings.json"); + +const SETTINGS_FILE = "fuzzyw.settings.json"; +let settings = require("Storage").readJSON(SETTINGS_FILE,1)|| {'language': 'System', 'alignment':'Centre'}; + +if (settings.language == 'System') { + settings.language = require('locale').name; +} + +let fuzzy_string = fuzzy_strings[settings.language]; + +let timeout = 2.5*60; +let drawTimeout; + +function queueDraw(seconds) { + let millisecs = seconds * 1000; + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, millisecs - (Date.now() % millisecs)); +} + +const h = g.getHeight(); +const w = g.getWidth(); +let align_mode = 0; +let align_pos = w/2; +if (settings.alignment =='Left') { + align_mode = -1; + align_pos = 0; +} else if (settings.alignment == 'Right') { + align_mode = 1; + align_pos = w; +} + +function getTimeString(date) { + let segment = Math.round((date.getMinutes()*60 + date.getSeconds() + 1)/300); + let hour = date.getHours() + Math.floor(segment/12); + f_string = fuzzy_string.minutes[segment % 12]; + if (f_string.includes('$1')) { + f_string = f_string.replace('$1', fuzzy_string.hours[(hour) % 24]); + } else { + f_string = f_string.replace('$2', fuzzy_string.hours[(hour + 1) % 24]); + } + return f_string; +} + +function draw() { + let time_string = getTimeString(new Date()).replace('*', ''); + // print(time_string); + g.setFont('Vector', (h-24*2)/fuzzy_string.text_scale); + g.setFontAlign(align_mode, 0); + g.clearRect(0, 24, w, h-24); + g.setColor(g.theme.fg); + g.drawString(g.wrapString(time_string, w).join("\n"), align_pos, h/2); + queueDraw(timeout); +} + +g.clear(); +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; + } +}); + +Bangle.setUI('clock'); +Bangle.loadWidgets(); +Bangle.drawWidgets(); diff --git a/apps/fuzzyw/fuzzyw.icon.js b/apps/fuzzyw/fuzzyw.icon.js new file mode 100644 index 000000000..acc7e2fcf --- /dev/null +++ b/apps/fuzzyw/fuzzyw.icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgP/ABX8oYFD+AFE8AFE8IXE8YFKwFCj08h4FBocenEHCIPDjk4CoIFBhlwAoeMuIFEuBSBAoOI+AFD4HxGoQFB+AFD4P4uYFC8P4gYFD/w7BAFEfApfEj+B/Ecg/Ah8A+EMg/Dw0YseHj/Dw/8sfHAoPH/lhDoIFBwFwj4FB40AvkPAoU8v4dCAoIdDw04FIMP4EOgFwh47Bj8EvEfw/DJwgFXABY")) diff --git a/apps/fuzzyw/fuzzyw.png b/apps/fuzzyw/fuzzyw.png new file mode 100644 index 000000000..afd0b0f76 Binary files /dev/null and b/apps/fuzzyw/fuzzyw.png differ diff --git a/apps/fuzzyw/fuzzyw.settings.js b/apps/fuzzyw/fuzzyw.settings.js new file mode 100644 index 000000000..00219accf --- /dev/null +++ b/apps/fuzzyw/fuzzyw.settings.js @@ -0,0 +1,46 @@ +(function(back) { + const SETTINGS_FILE = "fuzzyw.settings.json"; + + var align_options = ['Left','Centre','Right']; + var language_options = ['System', 'en_GB', 'en_US', 'es_ES', 'fr_FR', 'no_NO', 'sv_SE', 'de_DE']; + + // initialize with default settings... + let s = {'language': 'System', 'alignment': 'Centre'}; + + // ...and overwrite them with any saved values + // This way saved values are preserved if a new version adds more settings + const storage = require('Storage') + let settings = storage.readJSON(SETTINGS_FILE, 1) || s; + const saved = settings || {} + for (const key in saved) { + s[key] = saved[key] + } + + function save() { + settings = s + storage.write(SETTINGS_FILE, settings) + } + + E.showMenu({ + '': { 'title': 'Fuzzy Text Clock' }, + '< Back': back, + 'Language': { + value: 0 | language_options.indexOf(s.language), + min: 0, max: language_options.length - 1, + format: v => language_options[v], + onchange: v => { + s.language = language_options[v]; + save(); + } + }, + 'Alignment': { + value: 0 | align_options.indexOf(s.alignment), + min: 0, max: align_options.length - 1, + format: v => align_options[v], + onchange: v => { + s.alignment = align_options[v]; + save(); + } + }, + }); +}) diff --git a/apps/fuzzyw/metadata.json b/apps/fuzzyw/metadata.json new file mode 100644 index 000000000..ebd20e49f --- /dev/null +++ b/apps/fuzzyw/metadata.json @@ -0,0 +1,20 @@ +{ + "id":"fuzzyw", + "name":"Fuzzy Text Clock", + "shortName": "Fuzzy Text", + "version": "0.01", + "description": "An imprecise clock for when you're not in a rush", + "readme": "README.md", + "icon":"fuzzyw.png", + "screenshots": [{"url":"fuzzyw-light.png"},{"url":"fuzzyw-dark.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS", "BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"fuzzyw.app.js","url":"fuzzyw.app.js"}, + {"name":"fuzzyw.settings.js","url":"fuzzyw.settings.js"}, + {"name":"fuzzyw.img","url":"fuzzyw.icon.js","evaluate":true}, + {"name":"fuzzy_strings.json","url":"fuzzy_strings.json"} + ] +} diff --git a/apps/lcars/ChangeLog b/apps/lcars/ChangeLog index 9d43f6575..4935fe714 100644 --- a/apps/lcars/ChangeLog +++ b/apps/lcars/ChangeLog @@ -17,3 +17,4 @@ 0.17: Settings for mph/kph and other minor improvements. 0.18: Fullscreen mode can now be enabled or disabled in the settings. 0.19: Alarms can not go bigger than 100. +0.20: Use alarm for alarm functionality instead of own implementation. \ No newline at end of file diff --git a/apps/lcars/README.md b/apps/lcars/README.md index f979b2304..7024e8edf 100644 --- a/apps/lcars/README.md +++ b/apps/lcars/README.md @@ -3,7 +3,8 @@ A simple LCARS inspired clock. Note: To display the steps, the wpedom app is required. To show weather data such as temperature, humidity or window you BangleJS must be connected -with Gadgetbride and the weather app must be installed. +with Gadgetbride and the weather app must be installed. To use the timer +the "sched" app must be installed on your device. ## Control * Tap left / right to change between screens. @@ -15,7 +16,7 @@ with Gadgetbride and the weather app must be installed. * Tab on left/right to switch between different screens. * Cusomizable data that is shown on screen 1 (steps, weather etc.) * Shows random and real images of planets. - * Tap on top/bottom of screen 1 to activate an alarm. + * Tap on top/bottom of screen 1 to activate an alarm. Depends on widtmr. * The lower orange line indicates the battery level. * Display graphs (day or month) for steps + hrm on the second screen. @@ -36,8 +37,9 @@ Access different screens via tap on the left/ right side of the screen ![](screenshot_1.png) ![](screenshot_2.png) +## Creator +- [David Peer](https://github.com/peerdavid) ## Contributors -- [David Peer](https://github.com/peerdavid). -- [Adam Schmalhofer](https://github.com/adamschmalhofer). -- [Jon Warrington](https://github.com/BartokW). +- [Adam Schmalhofer](https://github.com/adamschmalhofer) +- [Jon Warrington](https://github.com/BartokW) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 433d33427..577955d2e 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -1,6 +1,7 @@ +const TIMER_IDX = "lcars"; const SETTINGS_FILE = "lcars.setting.json"; const locale = require('locale'); -const storage = require('Storage') +const storage = require('Storage'); let settings = { alarm: -1, dataRow1: "Steps", @@ -124,11 +125,16 @@ Graphics.prototype.setFontAntonioLarge = function(scale) { */ var drawTimeout; function queueDraw() { + + // Faster updates during alarm to ensure that it is + // shown correctly... + var timeout = isAlarmEnabled() ? 10000 : 60000; + if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = setTimeout(function() { drawTimeout = undefined; draw(); - }, 60000 - (Date.now() % 60000)); + }, timeout - (Date.now() % timeout)); } /** @@ -238,6 +244,7 @@ function drawInfo(){ return; } + g.setFontAlign(-1, -1, 0); g.setFontAntonioMedium(); g.setColor(cOrange); g.clearRect(120, 10, g.getWidth(), 75); @@ -480,9 +487,6 @@ function draw(){ // Queue draw first to ensure that its called in one minute again. queueDraw(); - // First handle alarm to show this correctly afterwards - handleAlarm(); - // Next draw the watch face g.reset(); g.clearRect(0, 0, g.getWidth(), g.getHeight()); @@ -561,43 +565,57 @@ function getWeather(){ /* * Handle alarm */ -function getCurrentTimeInMinutes(){ - return Math.floor(Date.now() / (1000*60)); -} - function isAlarmEnabled(){ - return settings.alarm >= 0; + try{ + var alarm = require('sched'); + var alarmObj = alarm.getAlarm(TIMER_IDX); + if(alarmObj===undefined || !alarmObj.on){ + return false; + } + + return true; + + } catch(ex){ } + return false; } function getAlarmMinutes(){ - var currentTime = getCurrentTimeInMinutes(); - return settings.alarm - currentTime; + if(!isAlarmEnabled()){ + return -1; + } + + var alarm = require('sched'); + var alarmObj = alarm.getAlarm(TIMER_IDX); + return Math.round(alarm.getTimeToAlarm(alarmObj)/(60*1000)); } -function handleAlarm(){ - if(!isAlarmEnabled()){ - return; - } +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){ } +} - if(getAlarmMinutes() > 0){ - return; - } +function decreaseAlarm(){ + try{ + var minutes = getAlarmMinutes(); + minutes -= 5; - // Alarm - var t = 300; - Bangle.buzz(t, 1) - .then(() => new Promise(resolve => setTimeout(resolve, t))) - .then(() => Bangle.buzz(t, 1)) - .then(() => new Promise(resolve => setTimeout(resolve, t))) - .then(() => Bangle.buzz(t, 1)) - .then(() => new Promise(resolve => setTimeout(resolve, t))) - .then(() => Bangle.buzz(t, 1)) - .then(() => new Promise(resolve => setTimeout(resolve, 5E3))) - .then(() => { - // Update alarm state to disabled - settings.alarm = -1; - storage.writeJSON(SETTINGS_FILE, settings); - }); + var alarm = require('sched') + alarm.setAlarm(TIMER_IDX, undefined); + + if(minutes > 0){ + alarm.setAlarm(TIMER_IDX, { + timer : minutes*60*1000, + }); + } + + alarm.reload(); + } catch(ex){ } } @@ -625,27 +643,6 @@ Bangle.on('charging',function(charging) { }); -function increaseAlarm(){ - if(isAlarmEnabled() && getAlarmMinutes() < 95){ - settings.alarm += 5; - } else { - settings.alarm = getCurrentTimeInMinutes() + 5; - } - - storage.writeJSON(SETTINGS_FILE, settings); -} - - -function decreaseAlarm(){ - if(isAlarmEnabled() && (settings.alarm-5 > getCurrentTimeInMinutes())){ - settings.alarm -= 5; - } else { - settings.alarm = -1; - } - - storage.writeJSON(SETTINGS_FILE, settings); -} - function feedback(){ Bangle.buzz(40, 0.3); } diff --git a/apps/lcars/metadata.json b/apps/lcars/metadata.json index 1335b8e1d..7155442f8 100644 --- a/apps/lcars/metadata.json +++ b/apps/lcars/metadata.json @@ -3,7 +3,7 @@ "name": "LCARS Clock", "shortName":"LCARS", "icon": "lcars.png", - "version":"0.19", + "version":"0.20", "readme": "README.md", "supports": ["BANGLEJS2"], "description": "Library Computer Access Retrieval System (LCARS) clock.", diff --git a/apps/notanalog/ChangeLog b/apps/notanalog/ChangeLog index 574d46609..6515f787c 100644 --- a/apps/notanalog/ChangeLog +++ b/apps/notanalog/ChangeLog @@ -1,3 +1,4 @@ 0.01: Launch app. 0.02: 12k steps are 360 degrees - improves readability of steps. -0.03: Battery improvements through sleep (no minute updates) and partial updates of drawing. \ No newline at end of file +0.03: Battery improvements through sleep (no minute updates) and partial updates of drawing. +0.04: Use alarm for timer instead of own alarm implementation. \ No newline at end of file diff --git a/apps/notanalog/README.md b/apps/notanalog/README.md index 2928fd959..e368f75d2 100644 --- a/apps/notanalog/README.md +++ b/apps/notanalog/README.md @@ -8,8 +8,8 @@ black one the battery level (100% = 360 degrees). The selected theme is also respected. Note that this watch face is in fullscreen mode, but widgets are still loaded in background. -## Other features -- Set a timer - simply touch top (+5min.) or bottom (-5 min.). +## Other Features +- Set a timer - simply touch top (+5min.) or bottom (-5 min.). This only works if "sched" is installed. - If the weather is available through the weather app, the outside temp. will be shown. - Sleep modus at midnight to save more battery (no minute updates). - Icons for charging and GPS. @@ -29,5 +29,5 @@ which helped a lot for this development. Icons from by Freepik - Flaticon -## Contributors +## Creator - [David Peer](https://github.com/peerdavid). \ No newline at end of file diff --git a/apps/notanalog/metadata.json b/apps/notanalog/metadata.json index 5efb6bccf..0a291b180 100644 --- a/apps/notanalog/metadata.json +++ b/apps/notanalog/metadata.json @@ -3,7 +3,7 @@ "name": "Not Analog", "shortName":"Not Analog", "icon": "notanalog.png", - "version":"0.03", + "version":"0.04", "readme": "README.md", "supports": ["BANGLEJS2"], "description": "An analog watch face for people that can not read analog watch faces.", diff --git a/apps/notanalog/notanalog.app.js b/apps/notanalog/notanalog.app.js index cea8072b8..c3dc9308f 100644 --- a/apps/notanalog/notanalog.app.js +++ b/apps/notanalog/notanalog.app.js @@ -1,7 +1,7 @@ /** * NOT ANALOG CLOCK */ - +const TIMER_IDX = "notanalog"; const locale = require('locale'); const storage = require('Storage') const SETTINGS_FILE = "notanalog.setting.json"; @@ -291,7 +291,6 @@ function drawSleep(){ function draw(fastUpdate){ // Execute handlers handleState(fastUpdate); - handleAlarm(); if(state.sleep){ drawSleep(); @@ -377,82 +376,80 @@ Bangle.on('touch', function(btn, e){ * Some helpers */ function queueDraw() { + + // Faster updates during alarm to ensure that it is + // shown correctly... + var timeout = isAlarmEnabled() ? 10000 : 60000; + if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = setTimeout(function() { drawTimeout = undefined; - draw(true); - }, 60000 - (Date.now() % 60000)); + draw(); + }, timeout - (Date.now() % timeout)); } /* * Handle alarm */ -function getCurrentTimeInMinutes(){ - return Math.floor(Date.now() / (1000*60)); -} - function isAlarmEnabled(){ - return settings.alarm >= 0; -} + try{ + var alarm = require('sched'); + var alarmObj = alarm.getAlarm(TIMER_IDX); + if(alarmObj===undefined || !alarmObj.on){ + return false; + } + + return true; + + } catch(ex){ } + return false; + } function getAlarmMinutes(){ - var currentTime = getCurrentTimeInMinutes(); - return settings.alarm - currentTime; -} - -function handleAlarm(){ if(!isAlarmEnabled()){ - return; + return -1; } - if(getAlarmMinutes() > 0){ - return; - } - - // Alarm - var t = 300; - Bangle.buzz(t, 1) - .then(() => new Promise(resolve => setTimeout(resolve, t))) - .then(() => Bangle.buzz(t, 1)) - .then(() => new Promise(resolve => setTimeout(resolve, t))) - .then(() => Bangle.buzz(t, 1)) - .then(() => new Promise(resolve => setTimeout(resolve, t))) - .then(() => Bangle.buzz(t, 1)) - .then(() => new Promise(resolve => setTimeout(resolve, 5E3))) - .then(() => { - // Update alarm state to disabled - settings.alarm = -1; - storage.writeJSON(SETTINGS_FILE, settings); - }); + var alarm = require('sched'); + var alarmObj = alarm.getAlarm(TIMER_IDX); + return Math.round(alarm.getTimeToAlarm(alarmObj)/(60*1000)); } - function increaseAlarm(){ - if(isAlarmEnabled()){ - settings.alarm += 5; - } else { - settings.alarm = getCurrentTimeInMinutes() + 5; - } - - storage.writeJSON(SETTINGS_FILE, settings); + 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(){ - if(isAlarmEnabled() && (settings.alarm-5 > getCurrentTimeInMinutes())){ - settings.alarm -= 5; - } else { - settings.alarm = -1; - } + try{ + var minutes = getAlarmMinutes(); + minutes -= 5; - storage.writeJSON(SETTINGS_FILE, settings); + var alarm = require('sched') + alarm.setAlarm(TIMER_IDX, undefined); + + if(minutes > 0){ + alarm.setAlarm(TIMER_IDX, { + timer : minutes*60*1000, + }); + } + + alarm.reload(); + } catch(ex){ } } function feedback(){ Bangle.buzz(40, 0.6); } + /* * Lets start widgets, listen for btn etc. */ diff --git a/apps/smpltmr/ChangeLog b/apps/smpltmr/ChangeLog new file mode 100644 index 000000000..07afedd21 --- /dev/null +++ b/apps/smpltmr/ChangeLog @@ -0,0 +1 @@ +0.01: Release \ No newline at end of file diff --git a/apps/smpltmr/README.md b/apps/smpltmr/README.md new file mode 100644 index 000000000..1296166e2 --- /dev/null +++ b/apps/smpltmr/README.md @@ -0,0 +1,21 @@ +# Simple Timer + +A simple app to set a timer quickly. Simply tab on top/bottom/left/right +to select the minutes and tab in the middle of the screen to start/stop +the timer. Note that this timer depends on qalarm. + +# Overview +If you open the app, you can simply control the timer +by clicking on top, bottom, left or right of the screen. +If you tab at the middle of the screen, the timer is +started / stopped. + +![](description.png) + + +# Creator +[David Peer](https://github.com/peerdavid) + + +# Thanks to... +Time icon created by CreativeCons - Flaticon \ No newline at end of file diff --git a/apps/smpltmr/app-icon.js b/apps/smpltmr/app-icon.js new file mode 100644 index 000000000..bc4261459 --- /dev/null +++ b/apps/smpltmr/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwMAg//AAXgApcAvAZBhwCBuAFuGoUeAQM4AQM8AQl8Bwn4AQMPgEB+AFBg+AgZYBgED4AHBAoIPBCYIAC/AfCGwQrCGAQ3CAAMcIYQFCJ4QABnoREvIdE/eeAgUB+fPAoUD8/nIIUHz/zJoUPn/5LIUev/8MoU8//+OIU5XwO8AoN7AoPeAoNzAoPOAsrFKg4QBAAPgApYA==")) \ No newline at end of file diff --git a/apps/smpltmr/app.js b/apps/smpltmr/app.js new file mode 100644 index 000000000..eb01e27d0 --- /dev/null +++ b/apps/smpltmr/app.js @@ -0,0 +1,124 @@ +/* + * SIMPLE TIMER + * + * Creator: David Peer + * Date: 02/2022 + */ + +Bangle.loadWidgets(); + + +const alarm = require("sched"); + +const TIMER_IDX = "smpltmr"; +const screenWidth = g.getWidth(); +const screenHeight = g.getHeight(); +const cx = parseInt(screenWidth/2); +const cy = parseInt(screenHeight/2)-12; +var minutes = 5; +var interval; //used for the 1 second interval timer + + +function isTimerEnabled(){ + var alarmObj = alarm.getAlarm(TIMER_IDX); + if(alarmObj===undefined || !alarmObj.on){ + return false; + } + + return true; +} + +function getTimerMin(){ + var alarmObj = alarm.getAlarm(TIMER_IDX); + return Math.round(alarm.getTimeToAlarm(alarmObj)/(60*1000)); +} + +function setTimer(minutes){ + alarm.setAlarm(TIMER_IDX, { + // msg : "Simple Timer", + timer : minutes*60*1000, + }); + alarm.reload(); +} + +function deleteTimer(){ + alarm.setAlarm(TIMER_IDX, undefined); + alarm.reload(); +} + +setWatch(_=>load(), BTN1); +function draw(){ + g.clear(1); + Bangle.drawWidgets(); + + if (interval) { + clearInterval(interval); + } + interval = undefined; + + // Write time + g.setFontAlign(0, 0, 0); + g.setFont("Vector", 32).setFontAlign(0,-1); + + var started = isTimerEnabled(); + var text = minutes + " min."; + if(started){ + var min = getTimerMin(); + text = min + " min."; + } + + var rectWidth = parseInt(g.stringWidth(text) / 2); + + if(started){ + interval = setInterval(draw, 1000); + g.setColor("#ff0000"); + } else { + g.setColor(g.theme.fg); + } + g.fillRect(cx-rectWidth-5, cy-5, cx+rectWidth, cy+30); + + g.setColor(g.theme.bg); + g.drawString(text, cx, cy); +} + + +Bangle.on('touch', function(btn, e){ + var left = parseInt(g.getWidth() * 0.25); + var right = g.getWidth() - left; + var upper = parseInt(g.getHeight() * 0.25); + var lower = g.getHeight() - upper; + + var isLeft = e.x < left; + var isRight = e.x > right; + var isUpper = e.y < upper; + var isLower = e.y > lower; + var isMiddle = !isLeft && !isRight && !isUpper && !isLower; + var started = isTimerEnabled(); + + if(isRight && !started){ + minutes += 1; + Bangle.buzz(40, 0.3); + } else if(isLeft && !started){ + minutes -= 1; + Bangle.buzz(40, 0.3); + } else if(isUpper && !started){ + minutes += 5; + Bangle.buzz(40, 0.3); + } else if(isLower && !started){ + minutes -= 5; + Bangle.buzz(40, 0.3); + } else if(isMiddle) { + if(!started){ + setTimer(minutes); + } else { + deleteTimer(); + } + Bangle.buzz(80, 0.6); + } + minutes = Math.max(0, minutes); + + draw(); +}); + +g.reset(); +draw(); \ No newline at end of file diff --git a/apps/smpltmr/app.png b/apps/smpltmr/app.png new file mode 100644 index 000000000..04ed03751 Binary files /dev/null and b/apps/smpltmr/app.png differ diff --git a/apps/smpltmr/description.png b/apps/smpltmr/description.png new file mode 100644 index 000000000..1286d1ab9 Binary files /dev/null and b/apps/smpltmr/description.png differ diff --git a/apps/smpltmr/metadata.json b/apps/smpltmr/metadata.json new file mode 100644 index 000000000..06bad962d --- /dev/null +++ b/apps/smpltmr/metadata.json @@ -0,0 +1,17 @@ +{ + "id": "smpltmr", + "name": "Simple Timer", + "shortName": "Simple Timer", + "version": "0.01", + "description": "A very simple app to start a timer.", + "icon": "app.png", + "tags": "tool", + "dependencies": {"scheduler":"type"}, + "supports": ["BANGLEJS2"], + "screenshots": [{"url":"screenshot.png"}, {"url": "screenshot_2.png"}], + "readme": "README.md", + "storage": [ + {"name":"smpltmr.app.js","url":"app.js"}, + {"name":"smpltmr.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/smpltmr/screenshot.png b/apps/smpltmr/screenshot.png new file mode 100644 index 000000000..eff94475c Binary files /dev/null and b/apps/smpltmr/screenshot.png differ diff --git a/apps/smpltmr/screenshot_2.png b/apps/smpltmr/screenshot_2.png new file mode 100644 index 000000000..7b5dc9a3d Binary files /dev/null and b/apps/smpltmr/screenshot_2.png differ