From 6bdbd310bcc354b8b18da040138bc9122817ca66 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Tue, 4 Jan 2022 16:41:05 -0800 Subject: [PATCH 01/59] fix light mode not selected color from -10 to -20 --- apps/promenu/boot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/promenu/boot.js b/apps/promenu/boot.js index 002734113..bd813a812 100644 --- a/apps/promenu/boot.js +++ b/apps/promenu/boot.js @@ -70,7 +70,7 @@ E.showMenu = function(items) { if(g.theme.dark){ fillRectRnd(x+2,iy+1,x2,iy+options.fontHeight-3,7,hl ? g.theme.bgH : g.theme.bg+20); }else{ - fillRectRnd(x+2,iy+1,x2,iy+options.fontHeight-3,7,hl ? g.theme.bgH : g.theme.bg-10); + fillRectRnd(x+2,iy+1,x2,iy+options.fontHeight-3,7,hl ? g.theme.bgH : g.theme.bg-20); } g.setColor(hl ? g.theme.fgH : g.theme.fg); g.setFontAlign(-1,-1); From 0b34ffefd58ee58f5d0437b5c4ff568a95eb778d Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Wed, 22 Dec 2021 21:18:55 +0100 Subject: [PATCH 02/59] Anton clock: Update with optional seconds and ISO-8601 date --- apps.json | 8 +- apps/antonclk/ChangeLog | 1 + apps/antonclk/app.js | 176 +++++++++++++++++++++++++++-------- apps/antonclk/app.png | Bin 759 -> 1989 bytes apps/antonclk/screenshot.png | Bin 696 -> 1617 bytes apps/antonclk/settings.js | 87 +++++++++++++++++ 6 files changed, 232 insertions(+), 40 deletions(-) create mode 100644 apps/antonclk/settings.js diff --git a/apps.json b/apps.json index 5cc311413..b0d74926b 100644 --- a/apps.json +++ b/apps.json @@ -4238,8 +4238,8 @@ { "id": "antonclk", "name": "Anton Clock", - "version": "0.03", - "description": "A simple clock using the bold Anton font.", + "version": "0.04", + "description": "A clock using the bold Anton font, optionally showing seconds and date in ISO-8601 format.", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}], "type": "clock", @@ -4248,8 +4248,10 @@ "allow_emulator": true, "storage": [ {"name":"antonclk.app.js","url":"app.js"}, + {"name":"antonclk.settings.js","url":"settings.js"}, {"name":"antonclk.img","url":"app-icon.js","evaluate":true} - ] + ], + "data": [{"name":"antonclk.json"}] }, { "id": "waveclk", diff --git a/apps/antonclk/ChangeLog b/apps/antonclk/ChangeLog index f88276a90..668047d7a 100644 --- a/apps/antonclk/ChangeLog +++ b/apps/antonclk/ChangeLog @@ -1,3 +1,4 @@ 0.01: New App! 0.02: Load widgets after setUI so widclk knows when to hide 0.03: Clock now shows day of week under date. +0.04: Clock can optionally show seconds, date optionally in ISO-8601 format, weekdays and uppercase configurable, too. diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index 7912dfc0f..3b9c14c46 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -1,10 +1,51 @@ +// Clock with large digits using the "Anton" bold font + +var 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)); +}; + +// variables defined from settings +var secondsOnUnlock; +var secondsAlways; +var dateAsISO; +var longDate; +var weekDay; +var upperCase; + +// dynamic variables +var drawTimeout; +var queueMillis=1000; +var withSeconds=true; + +var isBangle1=(g.getWidth()==240); + +/* For development purposes +require('Storage').writeJSON(SETTINGSFILE, { + secondsOnUnlock: false, + secondsAlways: false, + dateAsISO: false, + longDate: true, + weekDay: true, + upperCase: true +}); +*/ + +function def(value,def) { + return (value!==undefined?value:def); } -// timeout used to update every minute -var drawTimeout; +function loadSettings() { + var settings = require('Storage').readJSON(SETTINGSFILE, true) || {}; + secondsOnUnlock = def(settings.secondsOnUnlock,true); + secondsAlways = def(settings.secondsAlways,false); + dateAsISO = def(settings.dateAsISO,true); + longDate = def(settings.longDate,true); + weekDay = def(settings.weekDay,true); + upperCase = def(settings.upperCase,false); +} // schedule a draw for the next minute function queueDraw() { @@ -12,50 +53,111 @@ function queueDraw() { drawTimeout = setTimeout(function() { drawTimeout = undefined; draw(); - }, 60000 - (Date.now() % 60000)); + }, queueMillis - (Date.now() % queueMillis)); } - -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(); - var dowStr = require("locale").dow(date).toUpperCase(); - // draw time - g.setFontAlign(0,0).setFont("Anton"); - g.clearRect(0,y-40,g.getWidth(),y+35); // clear the background - g.drawString(timeStr,x,y); - // draw date - y += 40; - g.setFontAlign(0,0).setFont("6x8",2); - g.clearRect(0,y-8,g.getWidth(),y+8); // clear the background - g.drawString(dateStr,x,y); - //draw day of week - y += 16; - g.clearRect(0,y-8,g.getWidth(),y+8); // clear the background - g.drawString(dowStr,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) { +function updateState() { + if (Bangle.isLCDOn()) { + if ((secondsOnUnlock && !Bangle.isLocked()) || secondsAlways) { + withSeconds=true; + queueMillis=1000; + } else { + withSeconds=false; + queueMillis=60000; + } draw(); // draw immediately, queue redraw } else { // stop draw timer if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; } -}); +} + +function isoStr(date) { + return date.getFullYear()+"-"+("0" + (date.getMonth()+1)).substr(-2)+"-"+("0" + date.getDate()).substr(-2); +} + +function doColor() { + return !isBangle1 && !Bangle.isLocked(); +} + +function draw() { + var x = g.getWidth()/2; + var y = g.getHeight()/2; + if (secondsOnUnlock || secondsAlways) + y-= 25; + g.reset(); + g.clearRect(0,24,g.getWidth(),g.getHeight()); // clear whole background + var date = new Date(); + var timeStr = require("locale").time(date,1); + // draw time + g.setFontAlign(0,0).setFont("Anton"); + g.drawString(timeStr,x,y); + if (withSeconds) { + y+=77; + var secStr = ":"+("0" + date.getSeconds()).substr(-2); + g.setFontAlign(1,0).setFont("Anton"); + if (doColor()) + g.setColor(0,0,1); + g.drawString(secStr,g.getWidth()-(isBangle1?32:2),y); + y-=77; + y+=60; + x=g.getWidth()/4+(isBangle1?12:-4); + var dateStr2=(dateAsISO?isoStr(date):require("locale").date(date,1)); + var year; + var md; + var yearfirst; + if (dateStr2.match(/\d\d\d\d$/)) { + year=dateStr2.slice(-4); + md=dateStr2.slice(0,-4); + if (!md.endsWith(".")) + md=md.slice(0,-1); + yearfirst=false; + } + else { + if (!dateStr2.match(/^\d\d\d\d/)) + dateStr2=isoStr(date); + year=dateStr2.slice(0,4); + md=dateStr2.slice(5); + yearfirst=true; + } + g.setFontAlign(0,0).setFont("Vector",24); + if (doColor()) + g.setColor(1,0,0); + g.drawString(md,x,(yearfirst?y+28:y)); + g.drawString(year,x,(yearfirst?y:y+28)); + } + else { + y+=52; + var dateStr = (dateAsISO?isoStr(date):require("locale").date(date,(longDate?0:1))); + if (upperCase) + dateStr=dateStr.toUpperCase(); + g.setFontAlign(0,0).setFont("Vector",24); + g.drawString(dateStr,x,y); + if (weekDay) { + var dowStr = require("locale").dow(date); + if (upperCase) + dowStr=dowStr.toUpperCase(); + g.drawString(dowStr,x,y+28); + } + } + + // queue next draw + queueDraw(); +} + +// Init the settings of the app +loadSettings(); +// Clear the screen once, at startup +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(); }); // Show launcher when middle button pressed Bangle.setUI("clock"); // Load widgets Bangle.loadWidgets(); Bangle.drawWidgets(); + +// end of file diff --git a/apps/antonclk/app.png b/apps/antonclk/app.png index d96f1775886e280f46652131b7e8c747fd28bf39..a38093c5f3b6f88dbc9b75017422dbe237d4407f 100644 GIT binary patch delta 1986 zcmV;z2R-=r1;r1L8Gix*007uvZqNV#2aHKXK~z}7?O0t*Q&$}S(aJ|1h>ls;g4h+@ zB+AGl)8UNHxGbA|xTyGG;sOsoEFnM;B+-{a7Q@E_V_6nMW&&<;@}SXB3>rlzVu;X< zRWXwk`@zScE!aY#?d`|e!>RXPZf_BAEI#a?lbioJ=XcKe-G6(||Kr>ULI_?bk>E9x z{|Wt1=v8G^xDKDsH!(3`G#X=LV-*U8TrOXDqLGmilgUK&#Kc6EN+kdc4-cEoX0}QQ z*}i?dOePafM8w2kFdRO7m=7x{DH$0V5e0j_-m_=V3Z|{9s&YD=eAwyJrv(^`#S%K3 z2qBxzmYSLx`hN`y3JT`t=0fr3&YhD;M7F-UxtYZ<46||L#$^(^di83!ed+D(C4@{& zOjs-yi^VcGH|KCTl9H16n23l7R(HGIbWWX4$8TSNkjR^LcXzY8Ua#-%?PaT@qoV@@ z0~H&dOV(ykrCQkT3X65OnG@Zi=UX7pnuAvM~@a65=02q*VnUpQc}{o zb?ew_S63H*UcpOeWMo7}M)E(H!{MOHjT<+pQd3j2Oe+(oFOl#G1p(}#J#>U2O z-@eU%9{^UX^}>Y<0168WUuvx{Ar!jtTeog?yWPRTtL6=FZEYMVBWjNgS_V&)sPS%G}B_$%Z5oY6qtTenW{1Nu^g`m} z<4>G8QB+jKf{jMwlP6E8URztc{8*NimDSVJLv{8QshCWryu3WB-@kuHJ4%z_z)>FVmDx>~KaTCMyOIXO8QA0HnT74;HACXwg7ckH-_vDjOOaLMP{&$oTm9qN2UoY*s3j zp$k-3SBvIDeSLkQ;GCQstJS(Np~a>jgpg;?o|ToA30{|B7!pRFK7CqOSGQ-+9vU&4 zo0~=15JIkBzg|&MQBhHG^5n^>si{yvL^#7CggBi}n!+lT%5dRAkoEfg{-~&^mwyJV zg`(%{c5_{|Li5heVRRH03*>SnCSvt!A;4yX)rzSpC=^gC5figulK+bG%P%A?jR3)- zRuhee>z$q^RaIOsK(=io_wFrts9#0e+U70BmOFQXfFFJk2WYhdLRKr$>4@J?2q6v! z`Qs1b^%6qJ>@4Z+CDg1@L7z6pDG^{(i2SkbpPdKwMlnD;pTVci*9=hFgSs zgt0MHSEIZfVy=i!h!F4{kf=Wi^-z~Cfu=;}wcszLg7?YD27=M7%NyqKl1-Cm`wryLQYX}5_n<$Y$t;Rd=@Cijlp`igT z7pA8X8;jgrI2<^029c4dtqtxYA+Xy~SqZxxem@;2l_EMiSR_mQl~P#=wHoig549R) zWtf>+0YAjI`L;Gf2&t&xTJ(C-(h}Cne*HDfRr)^@l?oqxz*T?xiGSU)*;zC{H zE;Kda=byp9j!jSF`|t7mIj3K~jM-Uw_S)K@(Lke_XY-4Z^XGBv7Lt>LRjn4!pHo7A z{t3Gs9uLjDk)4gKEL^_K4gLLhIGynM0N~CYeEB6*D%`pSU~mw5dC1L0ZZ0gAr4fpb z#+z^A-FJgkyB$6sHGlhEyD&AyUdQ2bp|us6nb7Oe-Hnew#wVYEy>UvVFc>g11H1h{ ziS|=dXl%rhBS=q&%Y_36AV}0d{S^-&q4nIc68v%6&MW2&W1#Sn>XQf;(x2J0BqTUEnC3*|HA1l zEy&D-(a5<(Lh$z69KdWwOblM!|B#xBHEXEZd%eW%CT=(JdO4k+urdq>AVk>96Q`5N z<>FSIpHBh-Vlss_`<9lKNk2L}#ngwjPIXiTSuzz@0DyR1QVY3BO*tgz-R4N2842(v2JWwjJb}a{Z?UMX|0QIbl USs20!PXGV_07*qoM6N<$g0gzc;Q#;t delta 746 zcmV#Upe&?7suvS{7$`q%$XUdCYatL*UM&qYkz00_3gdZkp%IXiY3DTK~M*l*UhrGbOTH@s=dXV zf09G{s><3KAL0N6xR{=cL_nHCF0Qe5xz8(%f`4q@m5r`n_Xa#UzVHyArFz-Gc zKm+!|0~`-toKmZ@`fYBHXFhRJxmIAUji{nSriljb1AkP<@icA%+OjwZJs^29h?!Ef z-TemQ2C)dzr(Mf2wV1+4Ie;xTq4hl^_`-nK0TfEH`ypDS7J#jPXdpM>j2NN40NJq# z{&FFNH{#+t0W5K}=m5aZI0(+a83M-^4*{K7!lef}MT5(z_;g8nFi@MU!y9& z0D~Ga2Y=`lS%av@1!#4Vgg00wzKaaIJ2L@bNR#tpBy|nIlrv8rGG@(^FsdRJ-QP{XzCF~qci@anb7w@o;375x%BD_RYP}fDMfEo&3+L6^SSGaoh~4+ z$TC{G#j66=9oYBrc}77;VUgTDWelk_cCxHK`(vE&O}8IO0(v{XR&*Uo8wB1qJ*#jG z=4;wIwv|`|g31@bP&0h$WpisvZdEEkr`;hEFPcka7#vXBt?hE5xty{J^%m!07*qoM6N<$f`mLmfdBvi diff --git a/apps/antonclk/screenshot.png b/apps/antonclk/screenshot.png index c66f8bdd85c6c2acef19f20ff86dab7b1d9c6a3f..e949b8a24a4eac5cbd8f8a01ffdd57b3660b939c 100644 GIT binary patch delta 1612 zcmV-S2DACN1AlTS_;6Lfh=O!<|dqR0_rLj7-Gw6Z=mpp~2Trq^-sN$JXdw$RVuL zh2YN@K!k`6Pvr(ctjI(h8vf-F??mA#V@N4cYlvqI5okD%_;DP$JZ&Vq6!#OKe-2k= zTnY^!SWV;*Zhz&*?VkZ+T^e4FIMl4veaLv{kHiaY8ZJ4eOESUYRxBF6&rgK#5Xh#u zh^d_lGqUH{I#wmxlgh#wCnl!sX>jup40b>oT>LaiC5grV6yh5Y9s#T=rCdP_t1Cx7#uck6xw7CA)cmrN5Z z87(9agn^YANE_|bKkF>#Mh8M)8{$o5Cc8FRku2BfXl|D&q@GEB?SUN zAVavl{C^WbAb>!j%1%GIf&mFAH!(qn65YGTfB^eSxzyv^$ znVJGY8u8OfjN&<1-1>p|YKvQ0+=BCwv6TPI8h=j}(Y+yF1hHNYWjJb$33G_!II4DC zYVYQgVzm5w4K066RQR$ zvwt8Zm9^v%t&H@Hld&C=2LdZkV~V_>mBE*gfqO6qLeCZ&EsxUX*dAgmD-(t+LdIBD z7TmHy4l#+9`?qdRmZG|C)Cpzfh8v!>R7ug!2o7TC+uL5DUQL!?a#=z*HhC~Vr)qVlOVN{y2 zklNJprC*XtHyUc&5!~YRr73`LqoJxb@eOZJ4FZHG4SH=h_X`lCj+~MJ0@MHk_kf20 zxI*nMw_H*_2e}ycP|(HMkbBF0z5e<%9(or`Sg5dpWvA=*b`#zXp8drkAN2RV*MCku z^?-Q(Z1XqWwZ5h7#X}uLbRL-FFuL~(NzMJ{(r4=OEpLZP?_ykel#uZ>096FuUR>L< z9||t3+g@&Qkg^lU5FH4;+Rvk^M14T$`Lb1ilwhc`^UHwg1x(z7M3`-OzIJGsn+dg$ z0S$xGhm%5v`^6g?a>x^Jt{i4z;qd9(eZbJ6z7d?iIaz8J!^HVTx zo9(q;$U}H#Q@rsIJ!F{GjVOA^kfNdF-(`s*Uc>^z>^110uXiK=kikpwc!)Y0WD%jD z2nvLwW4P@LN&@8&;lso_aeu7&T&yhCt);PFdrdySbO84-x`!%T%P5Hpwfi}H`fc7s zO1ffKWuQBZ&3>p&s?%ZLn2L9trF-BI>6BmP3pBu=Lt)VGrBgx%c0I{@_ z`211;5uG+;5CLLcC&7UsL7Dj3re&u9;mm}_0Zcuu0fZ+LF6V67o<%|j6U86bJI}4B z1!gJ* literal 696 zcmeAS@N?(olHy`uVBq!ia0vp^8$g(e8Ax8b$#WJ+v7|ftIx;Y9?C1WI$O_~uBzpw; zGB8xBF)%c=FfjZA3N^f7U???UV0e|lz+g3lfkC`r&aOZkpaf5VPl)UP|Nj{nfCxnV zoVS%9$Y4zJc6VXuV3qX%a@b2eeO=j~a*A_n%Kez1upTJA($mE;B;xSfYk_%(6?oVZ znx=@`mzU45aNRCkV(xU;^}@Uf{u^iKUb%22k=ZHgn#betkjQJ(wHVdc3iO{Um?DvM z`p1?79g#H?tfriI+96!Z*U!BsRg8cA`*^+i+8-jC+ouPvJND@90YimZJatyS5s?c& zt+tgDzj5GhL5XDLnY<58YfnAMc=^fV))bq*ZM!#=oOaa8IaTDs-PyLkAzNAs4m9XOIF3zyu2a|McptHjh`Yyi=a@ZK4iEEpI(UHx3vIVCg!011y7eE back(), + "Seconds...": () => E.showMenu(secmenu), + "ISO8601 date": { + value: (settings.dateAsISO !== undefined ? settings.dateAsISO : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.dateAsISO = v; + writeSettings(); + } + }, + "Long date": { + value: (settings.longDate !== undefined ? settings.longDate : true), + format: v => v ? "On" : "Off", + onchange: v => { + settings.longDate = v; + writeSettings(); + } + }, + "Show Weekday": { + value: (settings.weekDay !== undefined ? settings.weekDay : true), + format: v => v ? "On" : "Off", + onchange: v => { + settings.weekDay = v; + writeSettings(); + } + }, + "Uppercase": { + value: (settings.upperCase !== undefined ? settings.upperCase : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.upperCase = v; + writeSettings(); + } + }, + }; + + // Submenu + var secmenu = { + "": { + "title": "Show seconds..." + }, + "< Back": () => E.showMenu(mainmenu), + "If unlocked": { + value: (settings.secondsOnUnlock !== undefined ? settings.secondsOnUnlock : true), + format: v => v ? "On" : "Off", + onchange: v => { + settings.secondsOnUnlock = v; + if (v) + settings.secondsAlways = false; + writeSettings(); + } + }, + "Always": { + value: (settings.secondsAlways !== undefined ? settings.secondsAlways : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.secondsAlways = v; + if (v) + settings.secondsOnUnlock = false; + writeSettings(); + } + } + }; + + // Actually display the menu + E.showMenu(mainmenu); + +}); + +// end of file From a245fa748d3bb4e8b06c0c298af9122262342914 Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Sat, 25 Dec 2021 21:55:23 +0100 Subject: [PATCH 03/59] Anton clock: Coloured seconds, date format config, small enhancements Result of the feedback on the first version. --- apps/antonclk/app.js | 157 +++++++++++++++++++++----------------- apps/antonclk/settings.js | 38 +++++---- 2 files changed, 111 insertions(+), 84 deletions(-) diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index 3b9c14c46..31ba696b7 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -1,6 +1,6 @@ // Clock with large digits using the "Anton" bold font -var SETTINGSFILE="antonclk.json"; +var SETTINGSFILE = "antonclk.json"; Graphics.prototype.setFontAnton = function(scale) { // Actual height 69 (68 - 0) @@ -10,44 +10,56 @@ Graphics.prototype.setFontAnton = function(scale) { // variables defined from settings var secondsOnUnlock; var secondsAlways; +var secondsColoured; var dateAsISO; +var dateOnSecs; var longDate; var weekDay; var upperCase; // dynamic variables var drawTimeout; -var queueMillis=1000; -var withSeconds=true; +var queueMillis = 1000; +var secondsScreen = true; -var isBangle1=(g.getWidth()==240); +var isBangle1 = (g.getWidth() == 240); /* For development purposes require('Storage').writeJSON(SETTINGSFILE, { secondsOnUnlock: false, secondsAlways: false, + secondsColoured: true, dateAsISO: false, + dateOnSecs: true, longDate: true, weekDay: true, - upperCase: true + upperCase: false, }); -*/ +/* */ -function def(value,def) { - return (value!==undefined?value:def); +/* OR (also for development purposes) +require('Storage').erase(SETTINGSFILE); +/* */ + +// Helper method for loading the settings +function def(value, def) { + return (value !== undefined ? value : def); } +// Load settings function loadSettings() { var settings = require('Storage').readJSON(SETTINGSFILE, true) || {}; - secondsOnUnlock = def(settings.secondsOnUnlock,true); - secondsAlways = def(settings.secondsAlways,false); - dateAsISO = def(settings.dateAsISO,true); - longDate = def(settings.longDate,true); - weekDay = def(settings.weekDay,true); - upperCase = def(settings.upperCase,false); + secondsOnUnlock = def(settings.secondsOnUnlock, false); + secondsAlways = def(settings.secondsAlways, false); + secondsColoured = def(settings.secondsColoured, false); + dateAsISO = def(settings.dateAsISO, false); + dateOnSecs = def(settings.dateOnSecs, true); + longDate = def(settings.longDate, true); + weekDay = def(settings.weekDay, true); + upperCase = def(settings.upperCase, true); } -// schedule a draw for the next minute +// schedule a draw for the next second or minute function queueDraw() { if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = setTimeout(function() { @@ -59,11 +71,11 @@ function queueDraw() { function updateState() { if (Bangle.isLCDOn()) { if ((secondsOnUnlock && !Bangle.isLocked()) || secondsAlways) { - withSeconds=true; - queueMillis=1000; + secondsScreen = true; + queueMillis = 1000; } else { - withSeconds=false; - queueMillis=60000; + secondsScreen = false; + queueMillis = 60000; } draw(); // draw immediately, queue redraw } else { // stop draw timer @@ -73,71 +85,70 @@ function updateState() { } function isoStr(date) { - return date.getFullYear()+"-"+("0" + (date.getMonth()+1)).substr(-2)+"-"+("0" + date.getDate()).substr(-2); + return date.getFullYear() + "-" + ("0" + (date.getMonth() + 1)).substr(-2) + "-" + ("0" + date.getDate()).substr(-2); } function doColor() { - return !isBangle1 && !Bangle.isLocked(); + return !isBangle1 && !Bangle.isLocked() && secondsColoured; } function draw() { - var x = g.getWidth()/2; - var y = g.getHeight()/2; - if (secondsOnUnlock || secondsAlways) - y-= 25; + var x = g.getWidth() / 2; + var y = g.getHeight() / 2 - (secondsOnUnlock || secondsAlways ? 24 : 12); g.reset(); - g.clearRect(0,24,g.getWidth(),g.getHeight()); // clear whole background + g.clearRect(0, 24, g.getWidth(), g.getHeight()); // clear whole background var date = new Date(); - var timeStr = require("locale").time(date,1); + var timeStr = require("locale").time(date, 1); // draw time - g.setFontAlign(0,0).setFont("Anton"); - g.drawString(timeStr,x,y); - if (withSeconds) { - y+=77; - var secStr = ":"+("0" + date.getSeconds()).substr(-2); - g.setFontAlign(1,0).setFont("Anton"); + g.setFontAlign(0, 0).setFont("Anton"); + g.drawString(timeStr, x, y); + if (secondsScreen) { + y += 76; + var secStr = ":" + ("0" + date.getSeconds()).substr(-2); if (doColor()) - g.setColor(0,0,1); - g.drawString(secStr,g.getWidth()-(isBangle1?32:2),y); - y-=77; - y+=60; - x=g.getWidth()/4+(isBangle1?12:-4); - var dateStr2=(dateAsISO?isoStr(date):require("locale").date(date,1)); - var year; - var md; - var yearfirst; - if (dateStr2.match(/\d\d\d\d$/)) { - year=dateStr2.slice(-4); - md=dateStr2.slice(0,-4); - if (!md.endsWith(".")) - md=md.slice(0,-1); - yearfirst=false; + g.setColor(0, 0, 1); + g.setFont("Anton"); + if (dateOnSecs) { + g.setFontAlign(1, 0).drawString(secStr, g.getWidth() - (isBangle1 ? 32 : 2), y); + y -= 16; + x = g.getWidth() / 4 + (isBangle1 ? 12 : -4); + var dateStr2 = (dateAsISO ? isoStr(date) : require("locale").date(date, 1)); + var year; + var md; + var yearfirst; + if (dateStr2.match(/\d\d\d\d$/)) { + year = dateStr2.slice(-4); + md = dateStr2.slice(0, -4); + if (!md.endsWith(".")) + md = md.slice(0, -1); + yearfirst = false; + } else { + if (!dateStr2.match(/^\d\d\d\d/)) + dateStr2 = isoStr(date); + year = dateStr2.slice(0, 4); + md = dateStr2.slice(5); + yearfirst = true; + } + g.setFontAlign(0, 0).setFont("Vector", 24); + if (doColor()) + g.setColor(1, 0, 0); + g.drawString(md, x, (yearfirst ? y + 28 : y)); + g.drawString(year, x, (yearfirst ? y : y + 28)); + } else { + g.setFontAlign(0, 0).drawString(secStr, x, y); } - else { - if (!dateStr2.match(/^\d\d\d\d/)) - dateStr2=isoStr(date); - year=dateStr2.slice(0,4); - md=dateStr2.slice(5); - yearfirst=true; - } - g.setFontAlign(0,0).setFont("Vector",24); - if (doColor()) - g.setColor(1,0,0); - g.drawString(md,x,(yearfirst?y+28:y)); - g.drawString(year,x,(yearfirst?y:y+28)); - } - else { - y+=52; - var dateStr = (dateAsISO?isoStr(date):require("locale").date(date,(longDate?0:1))); + } else { // No seconds screen + y += 50; + var dateStr = (dateAsISO ? isoStr(date) : require("locale").date(date, (longDate ? 0 : 1))); if (upperCase) - dateStr=dateStr.toUpperCase(); - g.setFontAlign(0,0).setFont("Vector",24); - g.drawString(dateStr,x,y); + dateStr = dateStr.toUpperCase(); + g.setFontAlign(0, 0).setFont("Vector", 24); + g.drawString(dateStr, x, y); if (weekDay) { var dowStr = require("locale").dow(date); if (upperCase) - dowStr=dowStr.toUpperCase(); - g.drawString(dowStr,x,y+28); + dowStr = dowStr.toUpperCase(); + g.drawString(dowStr, x, y + 26); } } @@ -152,8 +163,12 @@ 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', on => { + updateState(); +}); +Bangle.on('lock', on => { + updateState(); +}); // Show launcher when middle button pressed Bangle.setUI("clock"); // Load widgets diff --git a/apps/antonclk/settings.js b/apps/antonclk/settings.js index 22cae41fb..2bcc1d7ce 100644 --- a/apps/antonclk/settings.js +++ b/apps/antonclk/settings.js @@ -4,7 +4,7 @@ var FILE = "antonclk.json"; // Load settings var settings = Object.assign({ - secondsOnUnlock: true, + secondsOnUnlock: false, }, require('Storage').readJSON(FILE, true) || {}); function writeSettings() { @@ -57,23 +57,35 @@ "title": "Show seconds..." }, "< Back": () => E.showMenu(mainmenu), - "If unlocked": { - value: (settings.secondsOnUnlock !== undefined ? settings.secondsOnUnlock : true), - format: v => v ? "On" : "Off", - onchange: v => { - settings.secondsOnUnlock = v; - if (v) - settings.secondsAlways = false; - writeSettings(); - } - }, "Always": { value: (settings.secondsAlways !== undefined ? settings.secondsAlways : false), format: v => v ? "On" : "Off", onchange: v => { settings.secondsAlways = v; - if (v) - settings.secondsOnUnlock = false; + writeSettings(); + } + }, + "If unlocked": { + value: (settings.secondsOnUnlock !== undefined ? settings.secondsOnUnlock : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.secondsOnUnlock = v; + writeSettings(); + } + }, + "Coloured": { + value: (settings.secondsColoured !== undefined ? settings.secondsColoured : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.secondsColoured = v; + writeSettings(); + } + }, + "With date": { + value: (settings.dateOnSecs !== undefined ? settings.dateOnSecs : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.dateOnSecs = v; writeSettings(); } } From 322a3a0b5aed5a697347b966ebd7d1e8ccb1370b Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Sat, 25 Dec 2021 21:55:30 +0100 Subject: [PATCH 04/59] Anton clock: README added --- apps.json | 1 + apps/antonclk/README.md | 66 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 apps/antonclk/README.md diff --git a/apps.json b/apps.json index b0d74926b..3411befc8 100644 --- a/apps.json +++ b/apps.json @@ -4240,6 +4240,7 @@ "name": "Anton Clock", "version": "0.04", "description": "A clock using the bold Anton font, optionally showing seconds and date in ISO-8601 format.", + "readme":"README.md", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}], "type": "clock", diff --git a/apps/antonclk/README.md b/apps/antonclk/README.md new file mode 100644 index 000000000..40aa9d457 --- /dev/null +++ b/apps/antonclk/README.md @@ -0,0 +1,66 @@ +# Anton Clock - Large font digital watch with seconds and date + +Anton clock uses the "Anton" bold font to show the time in a clear, easily readable manner. On the Bangle.js 2, the time can be read easily even if the screen is locked and unlit. + +## Features + +The basic time representation only shows hours and minutes of the current time. However, Anton clock can show additional information: + +* Seconds can be shown, either always or only if the screen is unlocked. +* To help easy recognition, the seconds can be coloured in blue on the Bangle.js 2. +* Date can be shown in three different formats: + * ISO-8601: 2021-12-19 + * short local format: 19/12/2021, 19.12.2021 + * long local format (not together with seconds): DEC 19 2021 +* Weekday can be shown (not together with seconds) + +## Usage + +Install Anton clock through the Bangle.js app loader. +Configure it through the default Bangle.js configuration mechanism +(Settings app, "Apps" menu, "Anton clock" submenu). +If you like it, make it your default watch face +(Settings app, "System" menu, "Clock" submenu, select "Anton clock"). + +## Configuration + +Anton clock is configured by the standard settings mechanism of Bangle.js's operating system: +Open the "Settings" app, then the "Apps" submenu and below it the "Anton clock" menu. +You configure Anton clock through several "on/off" switches in two menus. + +### The main menu + +The main menu contains several settings covering Anton clock in general. + +* **Seconds...** - Opens the submenu for configuring the presentation of the current time's seconds. +* **ISO8601 date** - Show the date in ISO-8601 format, irrespective of the current locale. +* **Long date** - Show the date in long format (usually with month in letters instead of number). +Exact format depends on the current locale. _Only evaluated if ISO8601 date is not set._ +* **Show Weekday** - Weekday is shown in the time presentation without seconds. +Weekday name depends on the current locale. +If seconds are shown, the weekday is never shown as there is not enough space on the watch face. +* **Uppercase** - Weekday name and month name in the long format are converted to upper case letters. +This can improve readability. + +### The "Seconds" submenu + +The "Seconds" submenu configures how (and if) seconds are shown on the "Anton" watch face. + +* **Always** - Seconds are _always_ shown, irrespective of the display's unlock state. +If this is enabled, weekdays will never been shown. +_Enabling this option increases power consumption as the watch face will update once per second instead of once per minute._ +* **If unlocked** - Seconds are shown if the display is unlocked. +On a locked display, only hour, minutes, date and weekday are shown. +"Always" overrides this option. +_This option is highly recommended on the Bangle.js 2!_ +* **Coloured** - If enabled, seconds are shown in blue instead of black. +This make the visual orientation much easier on the watch face. +* **With date** - If enabled, the date is shown together with the seconds. +Depending on the "ISO8601 date" settings, ISO8601 or short local format is used. +The date is coloured in red if the "Coloured" option is chosen. + +If neither "Always" nor "If unlocked" is selected, Anton clock does _never_ show seconds. + +## Compatibility + +Anton clock makes use of core Bangle.js 2 features (coloured display, display lock state). It also runs on the Bangle.js 1 but these features are not available there due to the hardware features. From 7829af0ef29837e829d4c13ef9c63f89cfdbb82e Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Sun, 26 Dec 2021 19:42:04 +0100 Subject: [PATCH 05/59] Anton clock: Switch between vector and 6x8 font for date and day of week --- apps/antonclk/README.md | 3 ++ apps/antonclk/app.js | 60 +++++++++++++++++++++++---------------- apps/antonclk/settings.js | 8 ++++++ 3 files changed, 46 insertions(+), 25 deletions(-) diff --git a/apps/antonclk/README.md b/apps/antonclk/README.md index 40aa9d457..cb37d566b 100644 --- a/apps/antonclk/README.md +++ b/apps/antonclk/README.md @@ -41,6 +41,9 @@ Weekday name depends on the current locale. If seconds are shown, the weekday is never shown as there is not enough space on the watch face. * **Uppercase** - Weekday name and month name in the long format are converted to upper case letters. This can improve readability. +* **Vector font** - Use the built-in vector font for dates and weekday. +This can improve readability. +Otherwise, a scaled version of the built-in 6x8 pixels font is used. ### The "Seconds" submenu diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index 31ba696b7..e772d679d 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -16,6 +16,7 @@ var dateOnSecs; var longDate; var weekDay; var upperCase; +var vectorFont; // dynamic variables var drawTimeout; @@ -34,6 +35,7 @@ require('Storage').writeJSON(SETTINGSFILE, { longDate: true, weekDay: true, upperCase: false, + vectorFont: false, }); /* */ @@ -57,6 +59,7 @@ function loadSettings() { longDate = def(settings.longDate, true); weekDay = def(settings.weekDay, true); upperCase = def(settings.upperCase, true); + vectorFont = def(settings.vectorFont, false); } // schedule a draw for the next second or minute @@ -92,63 +95,70 @@ function doColor() { return !isBangle1 && !Bangle.isLocked() && secondsColoured; } +// Actually draw the watch face function draw() { var x = g.getWidth() / 2; - var y = g.getHeight() / 2 - (secondsOnUnlock || secondsAlways ? 24 : 12); + var y = g.getHeight() / 2 - (secondsOnUnlock || secondsAlways ? 24 : (vectorFont ? 12 : 0)); g.reset(); g.clearRect(0, 24, g.getWidth(), g.getHeight()); // clear whole background - var date = new Date(); - var timeStr = require("locale").time(date, 1); - // draw time - g.setFontAlign(0, 0).setFont("Anton"); - g.drawString(timeStr, x, y); + var date = new Date(); // Actually the current date, this one is shown + var timeStr = require("locale").time(date, 1); // Hour and minute + g.setFontAlign(0, 0).setFont("Anton").drawString(timeStr, x, y); // draw time if (secondsScreen) { y += 76; var secStr = ":" + ("0" + date.getSeconds()).substr(-2); if (doColor()) g.setColor(0, 0, 1); g.setFont("Anton"); - if (dateOnSecs) { - g.setFontAlign(1, 0).drawString(secStr, g.getWidth() - (isBangle1 ? 32 : 2), y); - y -= 16; - x = g.getWidth() / 4 + (isBangle1 ? 12 : -4); + if (dateOnSecs) { // A bit of a complex drawing with seconds on the right and date on the left + g.setFontAlign(1, 0).drawString(secStr, g.getWidth() - (isBangle1 ? 32 : 2), y); // seconds + y -= (vectorFont ? 20 : 16); + x = g.getWidth() / 4 + (isBangle1 ? 12 : -6); var dateStr2 = (dateAsISO ? isoStr(date) : require("locale").date(date, 1)); var year; var md; var yearfirst; - if (dateStr2.match(/\d\d\d\d$/)) { + if (dateStr2.match(/\d\d\d\d$/)) { // formatted date ends with year year = dateStr2.slice(-4); md = dateStr2.slice(0, -4); - if (!md.endsWith(".")) + if (!md.endsWith(".")) // keep separator before the year only if it is a dot (31.12. but 31/12) md = md.slice(0, -1); yearfirst = false; - } else { - if (!dateStr2.match(/^\d\d\d\d/)) - dateStr2 = isoStr(date); + } else { // formatted date begins with year + if (!dateStr2.match(/^\d\d\d\d/)) // if year position cannot be detected... + dateStr2 = isoStr(date); // ...use ISO date format instead year = dateStr2.slice(0, 4); - md = dateStr2.slice(5); + md = dateStr2.slice(5); // never keep separator directly after year yearfirst = true; } - g.setFontAlign(0, 0).setFont("Vector", 24); + g.setFontAlign(0, 0); + if (vectorFont) + g.setFont("Vector", 24); + else + g.setFont("6x8", 2); if (doColor()) g.setColor(1, 0, 0); - g.drawString(md, x, (yearfirst ? y + 28 : y)); - g.drawString(year, x, (yearfirst ? y : y + 28)); + g.drawString(md, x, (yearfirst ? y + (vectorFont ? 26 : 16) : y)); + g.drawString(year, x, (yearfirst ? y : y + (vectorFont ? 26 : 16))); } else { - g.setFontAlign(0, 0).drawString(secStr, x, y); + g.setFontAlign(0, 0).drawString(secStr, x, y); // Just the seconds centered } - } else { // No seconds screen - y += 50; + } else { // No seconds screen: Show date and optionally day of week + y += (vectorFont ? 50 : (secondsOnUnlock || secondsAlways) ? 52 : 40); var dateStr = (dateAsISO ? isoStr(date) : require("locale").date(date, (longDate ? 0 : 1))); if (upperCase) dateStr = dateStr.toUpperCase(); - g.setFontAlign(0, 0).setFont("Vector", 24); + g.setFontAlign(0, 0); + if (vectorFont) + g.setFont("Vector", 24); + else + g.setFont("6x8", 2); g.drawString(dateStr, x, y); if (weekDay) { var dowStr = require("locale").dow(date); if (upperCase) dowStr = dowStr.toUpperCase(); - g.drawString(dowStr, x, y + 26); + g.drawString(dowStr, x, y + (vectorFont ? 26 : 16)); } } @@ -175,4 +185,4 @@ Bangle.setUI("clock"); Bangle.loadWidgets(); Bangle.drawWidgets(); -// end of file +// end of file \ No newline at end of file diff --git a/apps/antonclk/settings.js b/apps/antonclk/settings.js index 2bcc1d7ce..3af9df292 100644 --- a/apps/antonclk/settings.js +++ b/apps/antonclk/settings.js @@ -49,6 +49,14 @@ writeSettings(); } }, + "Vector font": { + value: (settings.vectorFont !== undefined ? settings.vectorFont : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.vectorFont = v; + writeSettings(); + } + }, }; // Submenu From d290578af10db777f2b3ff00e68059d3ab884809 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 08:49:36 -0800 Subject: [PATCH 06/59] Update apps.json --- apps.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 89c5f7b70..49397479a 100644 --- a/apps.json +++ b/apps.json @@ -5147,10 +5147,11 @@ "icon": "icon.png", "type": "boot", "tags": "system", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS","BANGLEJS2"] "screenshots": [{"url":"pro-menu-screenshot.png"}], "storage": [ - {"name":"promenu.boot.js","url":"boot.js"}, + {"name":"promenu.boot.js","url":"boot.js","supports": ["BANGLEJS"]}, + {"name":"promenu.bootb2.js","url":"boot.js","supports": ["BANGLEJS2"]}, {"name":"promenu.img","url":"promenuIcon.js","evaluate":true} ] }, From 1adeef592b84dff615a1937ae01216f8d492786f Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 08:51:42 -0800 Subject: [PATCH 07/59] Create bootb2.js --- apps/promenu/bootb2.js | 142 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 apps/promenu/bootb2.js diff --git a/apps/promenu/bootb2.js b/apps/promenu/bootb2.js new file mode 100644 index 000000000..096745f34 --- /dev/null +++ b/apps/promenu/bootb2.js @@ -0,0 +1,142 @@ +E.showMenu = function(items) { + function RectRnd(x1,y1,x2,y2,r) { + pp = []; + pp.push.apply(pp,g.quadraticBezier([x2-r,y1, x2,y1,x2,y1+r])); + pp.push.apply(pp,g.quadraticBezier([x2,y2-r,x2,y2,x2-r,y2])); + pp.push.apply(pp,g.quadraticBezier([x1+r,y2,x1,y2,x1,y2-r])); + pp.push.apply(pp,g.quadraticBezier([x1,y1+r,x1,y1,x1+r,y1])); + return pp; + } + function fillRectRnd(x1,y1,x2,y2,r,c) { + g.setColor(c); + g.fillPoly(RectRnd(x1,y1,x2,y2,r),1); + g.setColor(255,255,255); + } + function drawRectRnd(x1,y1,x2,y2,r,c) { + g.setColor(c); + g.drawPoly(RectRnd(x1,y1,x2,y2,r),1); + g.setColor(255,255,255); + } + g.reset().clearRect(Bangle.appRect); // clear if no menu supplied + Bangle.setLCDPower(1); // ensure screen is on + if (!items) { + Bangle.setUI(); + return; + } + var menuItems = Object.keys(items); + var options = items[""]; + if (options) menuItems.splice(menuItems.indexOf(""),1); + if (!(options instanceof Object)) options = {}; + options.fontHeight = options.fontHeight||25; + if (options.selected === undefined) + options.selected = 0; + var ar = Bangle.appRect; + var x = ar.x; + var x2 = ar.x2; + var y = ar.y; + var y2 = ar.y2 - 12; // padding at end for arrow + if (options.title) + y += 22; + var loc = require("locale"); + var l = { + lastIdx : 0, + draw : function(rowmin,rowmax) { + var rows = 0|Math.min((y2-y) / options.fontHeight,menuItems.length); + var idx = E.clip(options.selected-( rows>>1),0,menuItems.length-rows); + if (idx!=l.lastIdx) rowmin=undefined; // redraw all if we scrolled + l.lastIdx = idx; + var iy = y; + g.reset().setFontAlign(0,-1,0).setFont('12x20'); + if (options.predraw) options.predraw(g); + if (rowmin===undefined && options.title) + g.drawString(options.title,(x+x2)/2,y-21).drawLine(x,y-2,x2,y-2). + setColor(g.theme.fg).setBgColor(g.theme.bg); + iy += 4; + if (rowmin!==undefined) { + if (idxrowmax) { + rows = 1+rowmax-rowmin; + } + } + while (rows--) { + var name = menuItems[idx]; + var item = items[name]; + var hl = (idx==options.selected && !l.selectEdit); + if(g.theme.dark){ + fillRectRnd(x,iy,x2,iy+options.fontHeight-3,7,hl ? g.theme.bgH : g.theme.bg+40); + }else{ + fillRectRnd(x,iy,x2,iy+options.fontHeight-3,7,hl ? g.theme.bgH : g.theme.bg-20); + } + g.setColor(hl ? g.theme.fgH : g.theme.fg); + g.setFontAlign(-1,-1); + var v = item.value; + v = loc.translate(""+v); + if(loc.translate(name).length >= 19-v.length && "object" == typeof item){ + if (item.format) v=item.format(v); + g.drawString(loc.translate(name).substring(0, 12-v.length)+"...",x+3.7,iy+2.7); + }else{ + if(loc.translate(name).length >= 15){ + g.drawString(loc.translate(name).substring(0, 15)+"...",x+3.7,iy+2.7); + }else{ + g.drawString(loc.translate(name),x+3.7,iy+2.7); + } + } + if ("object" == typeof item) { + var xo = x2; + var v = item.value; + if (item.format) v=item.format(v); + v = loc.translate(""+v); + if (l.selectEdit && idx==options.selected) { + xo -= 24 + 1; + g.setColor(g.theme.fgH).drawImage("\x0c\x05\x81\x00 \x07\x00\xF9\xF0\x0E\x00@",xo,iy+(options.fontHeight-10)/2,{scale:2}); + } + g.setFontAlign(1,-1); + g.drawString(v,xo-2,iy+1); + } + g.setColor(g.theme.fg); + iy += options.fontHeight; + idx++; + } + g.setFontAlign(-1,-1); + g.setColor((idxitem.max) item.value = item.wrap ? item.min : item.max; + if (item.onchange) item.onchange(item.value); + l.draw(options.selected,options.selected); + } else { + var lastSelected=options.selected; + options.selected = (dir+options.selected+menuItems.length)%menuItems.length; + l.draw(Math.min(lastSelected,options.selected), Math.max(lastSelected,options.selected)); + } + } + }; + l.draw(); + Bangle.setUI("updown",dir => { + if (dir) l.move(dir); + else l.select(); + }); + return l; +}; From 3cfc5a83458bcd01bf913c2edcdad2a481afb0a5 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 08:53:08 -0800 Subject: [PATCH 08/59] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 01bdaf84f..a7a1c85a1 100644 --- a/apps.json +++ b/apps.json @@ -5163,7 +5163,7 @@ "id": "promenu", "name": "Pro Menu", "version": "0.01", - "description": "Replace Bangle.js 1's built in menu function.", + "description": "Replace the built in menu function. Supports Bangle.js 1 and Bangle.js 2.", "icon": "icon.png", "type": "boot", "tags": "system", From 485fb4a3c2bf9082be4dfb623d7f1a1042cef853 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 08:54:56 -0800 Subject: [PATCH 09/59] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index a7a1c85a1..16beb366a 100644 --- a/apps.json +++ b/apps.json @@ -5167,7 +5167,7 @@ "icon": "icon.png", "type": "boot", "tags": "system", - "supports": ["BANGLEJS","BANGLEJS2"] + "supports": ["BANGLEJS","BANGLEJS2"], "screenshots": [{"url":"pro-menu-screenshot.png"}], "storage": [ {"name":"promenu.boot.js","url":"boot.js","supports": ["BANGLEJS"]}, From d36743032c878bd73fdda87cf0b22d5b8e002b10 Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Wed, 5 Jan 2022 22:21:55 +0100 Subject: [PATCH 10/59] Anton clock: Smaller seconds, weekday with seconds, seconds without colon, cleaner configuration --- apps/antonclk/README.md | 42 ++++++++++++-------- apps/antonclk/app.js | 81 +++++++++++++++++++++++---------------- apps/antonclk/settings.js | 64 ++++++++++++++----------------- 3 files changed, 101 insertions(+), 86 deletions(-) diff --git a/apps/antonclk/README.md b/apps/antonclk/README.md index cb37d566b..41d3e4559 100644 --- a/apps/antonclk/README.md +++ b/apps/antonclk/README.md @@ -11,8 +11,8 @@ The basic time representation only shows hours and minutes of the current time. * Date can be shown in three different formats: * ISO-8601: 2021-12-19 * short local format: 19/12/2021, 19.12.2021 - * long local format (not together with seconds): DEC 19 2021 -* Weekday can be shown (not together with seconds) + * long local format: DEC 19 2021 +* Weekday can be shown (on seconds screen only instead of year) ## Usage @@ -33,9 +33,10 @@ You configure Anton clock through several "on/off" switches in two menus. The main menu contains several settings covering Anton clock in general. * **Seconds...** - Opens the submenu for configuring the presentation of the current time's seconds. -* **ISO8601 date** - Show the date in ISO-8601 format, irrespective of the current locale. -* **Long date** - Show the date in long format (usually with month in letters instead of number). -Exact format depends on the current locale. _Only evaluated if ISO8601 date is not set._ +* **Date** - Format of the date representation. Possible values are + * **Long** - "Long" date format in the current locale. Usually with the month as name, not number. + * **Short** - "Short" date format in the current locale. Usually with the month as number. + * **ISO8601** - Show the date in ISO-8601 format (YYYY-MM-DD), irrespective of the current locale. * **Show Weekday** - Weekday is shown in the time presentation without seconds. Weekday name depends on the current locale. If seconds are shown, the weekday is never shown as there is not enough space on the watch face. @@ -49,21 +50,28 @@ Otherwise, a scaled version of the built-in 6x8 pixels font is used. The "Seconds" submenu configures how (and if) seconds are shown on the "Anton" watch face. -* **Always** - Seconds are _always_ shown, irrespective of the display's unlock state. -If this is enabled, weekdays will never been shown. -_Enabling this option increases power consumption as the watch face will update once per second instead of once per minute._ -* **If unlocked** - Seconds are shown if the display is unlocked. -On a locked display, only hour, minutes, date and weekday are shown. -"Always" overrides this option. +* **Show** - Configure when the seconds should be shown at all: + * **Never** - Seconds are never shown. +In this case, hour and minute are a bit more centered on the screen and the clock will always only update every minute. +This saves battery power. + * **Unlocked** - Seconds are shown if the display is unlocked. +On locked displays, only hour, minutes, date and optionally the weekday are shown. _This option is highly recommended on the Bangle.js 2!_ -* **Coloured** - If enabled, seconds are shown in blue instead of black. + * **Always** - Seconds are _always_ shown, irrespective of the display's unlock state. +_Enabling this option increases power consumption as the watch face will update once per second instead of once per minute._ +* **With ":"** - If enabled, a colon ":" is prepended to the seconds. +This resembles the usual time representation "hh:mm:ss", even though the seconds are printed on a separate line. +* **Color** - If enabled, seconds are shown in blue instead of black. +If the date is shown on the seconds screen, it is colored read instead of black. This make the visual orientation much easier on the watch face. -* **With date** - If enabled, the date is shown together with the seconds. -Depending on the "ISO8601 date" settings, ISO8601 or short local format is used. -The date is coloured in red if the "Coloured" option is chosen. +* **Date** - It is possible to show the date together with the seconds: + * **No** - Date is _not_ shown in the seconds screen. +In this case, the seconds are centered below hour and minute. + * **Year** - Date is shown with day, month, and year. If "Date" in the main settings is configured to _ISO8601_, this is used here, too. Otherwise, the short local format is used. + * **Weekday** - Date is shown with day, month, and weekday. -If neither "Always" nor "If unlocked" is selected, Anton clock does _never_ show seconds. +The date is coloured in red if the "Coloured" option is chosen. ## Compatibility -Anton clock makes use of core Bangle.js 2 features (coloured display, display lock state). It also runs on the Bangle.js 1 but these features are not available there due to the hardware features. +Anton clock makes use of core Bangle.js 2 features (coloured display, display lock state). It also runs on the Bangle.js 1 but these features are not available there due to hardware restrictions. diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index e772d679d..1f3e49792 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -3,17 +3,21 @@ var 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)); + // 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)); +}; + +Graphics.prototype.setFontAntonSmall = function(scale) { + // Actual height 53 (52 - 0) + 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)); }; // variables defined from settings -var secondsOnUnlock; -var secondsAlways; +var secondsMode; var secondsColoured; -var dateAsISO; +var secondsWithColon; +var dateOnMain; var dateOnSecs; -var longDate; var weekDay; var upperCase; var vectorFont; @@ -27,15 +31,14 @@ var isBangle1 = (g.getWidth() == 240); /* For development purposes require('Storage').writeJSON(SETTINGSFILE, { - secondsOnUnlock: false, - secondsAlways: false, + secondsMode: "Always", // "Never", "Unlocked", "Always" secondsColoured: true, - dateAsISO: false, - dateOnSecs: true, - longDate: true, + secondsWithColon: true, + dateOnMain: "Long", // "Short", "Long", "ISO8601" + dateOnSecs: "Year", // "No", "Year", "Weekday", LEGACY: true/false weekDay: true, - upperCase: false, - vectorFont: false, + upperCase: true, + vectorFont: true, }); /* */ @@ -51,15 +54,20 @@ function def(value, def) { // Load settings function loadSettings() { var settings = require('Storage').readJSON(SETTINGSFILE, true) || {}; - secondsOnUnlock = def(settings.secondsOnUnlock, false); - secondsAlways = def(settings.secondsAlways, false); - secondsColoured = def(settings.secondsColoured, false); - dateAsISO = def(settings.dateAsISO, false); - dateOnSecs = def(settings.dateOnSecs, true); - longDate = def(settings.longDate, true); + secondsMode = def(settings.secondsMode, "Never"); + secondsColoured = def(settings.secondsColoured, true); + secondsWithColon = def(settings.secondsWithColon, true); + dateOnMain = def(settings.dateOnMain, "Long"); + dateOnSecs = def(settings.dateOnSecs, "Year"); weekDay = def(settings.weekDay, true); upperCase = def(settings.upperCase, true); vectorFont = def(settings.vectorFont, false); + + // Legacy + if (dateOnSecs === true) + dateOnSecs = "Year"; + if (dateOnSecs === false) + dateOnSecs = "No"; } // schedule a draw for the next second or minute @@ -73,7 +81,7 @@ function queueDraw() { function updateState() { if (Bangle.isLCDOn()) { - if ((secondsOnUnlock && !Bangle.isLocked()) || secondsAlways) { + if ((secondsMode === "Unlocked" && !Bangle.isLocked()) || secondsMode === "Always") { secondsScreen = true; queueMillis = 1000; } else { @@ -98,28 +106,33 @@ function doColor() { // Actually draw the watch face function draw() { var x = g.getWidth() / 2; - var y = g.getHeight() / 2 - (secondsOnUnlock || secondsAlways ? 24 : (vectorFont ? 12 : 0)); + var y = g.getHeight() / 2 - (secondsMode !== "Never" ? 24 : (vectorFont ? 12 : 0)); g.reset(); - g.clearRect(0, 24, g.getWidth(), g.getHeight()); // clear whole background + /* This is to mark the widget areas during development. + g.setColor("#888") + .fillRect(0, 0, g.getWidth(), 23) + .fillRect(0, g.getHeight() - 23, g.getWidth(), g.getHeight()).reset(); + /* */ + g.clearRect(0, 24, g.getWidth(), g.getHeight() - 24); // clear whole background (w/o widgets) var date = new Date(); // Actually the current date, this one is shown var timeStr = require("locale").time(date, 1); // Hour and minute g.setFontAlign(0, 0).setFont("Anton").drawString(timeStr, x, y); // draw time if (secondsScreen) { - y += 76; - var secStr = ":" + ("0" + date.getSeconds()).substr(-2); + y += 65; + var secStr = (secondsWithColon ? ":" : "") + ("0" + date.getSeconds()).substr(-2); if (doColor()) g.setColor(0, 0, 1); - g.setFont("Anton"); - if (dateOnSecs) { // A bit of a complex drawing with seconds on the right and date on the left + g.setFont("AntonSmall"); + if (dateOnSecs !== "No") { // A bit of a complex drawing with seconds on the right and date on the left g.setFontAlign(1, 0).drawString(secStr, g.getWidth() - (isBangle1 ? 32 : 2), y); // seconds - y -= (vectorFont ? 20 : 16); - x = g.getWidth() / 4 + (isBangle1 ? 12 : -6); - var dateStr2 = (dateAsISO ? isoStr(date) : require("locale").date(date, 1)); + y -= (vectorFont ? 15 : 13); + x = g.getWidth() / 4 + (isBangle1 ? 12 : 4) + (secondsWithColon ? 0 : g.stringWidth(":") / 2); + var dateStr2 = (dateOnMain === "ISO8601" ? isoStr(date) : require("locale").date(date, 1)); var year; var md; var yearfirst; if (dateStr2.match(/\d\d\d\d$/)) { // formatted date ends with year - year = dateStr2.slice(-4); + year = (dateOnSecs === "Year" ? dateStr2.slice(-4) : require("locale").dow(date, 1)); md = dateStr2.slice(0, -4); if (!md.endsWith(".")) // keep separator before the year only if it is a dot (31.12. but 31/12) md = md.slice(0, -1); @@ -127,10 +140,12 @@ function draw() { } else { // formatted date begins with year if (!dateStr2.match(/^\d\d\d\d/)) // if year position cannot be detected... dateStr2 = isoStr(date); // ...use ISO date format instead - year = dateStr2.slice(0, 4); + year = (dateOnSecs === "Year" ? dateStr2.slice(0, 4) : require("locale").dow(date, 1)); md = dateStr2.slice(5); // never keep separator directly after year yearfirst = true; } + if (dateOnSecs === "Weekday" && upperCase) + year = year.toUpperCase(); g.setFontAlign(0, 0); if (vectorFont) g.setFont("Vector", 24); @@ -144,8 +159,8 @@ function draw() { g.setFontAlign(0, 0).drawString(secStr, x, y); // Just the seconds centered } } else { // No seconds screen: Show date and optionally day of week - y += (vectorFont ? 50 : (secondsOnUnlock || secondsAlways) ? 52 : 40); - var dateStr = (dateAsISO ? isoStr(date) : require("locale").date(date, (longDate ? 0 : 1))); + y += (vectorFont ? 50 : (secondsMode !== "Never") ? 52 : 40); + var dateStr = (dateOnMain === "ISO8601" ? isoStr(date) : require("locale").date(date, (dateOnMain === "Long" ? 0 : 1))); if (upperCase) dateStr = dateStr.toUpperCase(); g.setFontAlign(0, 0); diff --git a/apps/antonclk/settings.js b/apps/antonclk/settings.js index 3af9df292..08fde512e 100644 --- a/apps/antonclk/settings.js +++ b/apps/antonclk/settings.js @@ -11,28 +11,34 @@ require('Storage').writeJSON(FILE, settings); } + // Helper method which uses int-based menu item for set of string values + function stringItems(startvalue, writer, values) { + return { + value: (startvalue === undefined ? 0 : values.indexOf(startvalue)), + format: v => values[v], + min: 0, + max: values.length - 1, + wrap: true, + step: 1, + onchange: v => { + writer(values[v]); + writeSettings(); + } + }; + } + + // Helper method which breaks string set settings down to local settings object + function stringInSettings(name, values) { + return stringItems(settings[name], v => settings[name] = v, values); + } + var mainmenu = { "": { "title": "Anton clock" }, "< Back": () => back(), "Seconds...": () => E.showMenu(secmenu), - "ISO8601 date": { - value: (settings.dateAsISO !== undefined ? settings.dateAsISO : false), - format: v => v ? "On" : "Off", - onchange: v => { - settings.dateAsISO = v; - writeSettings(); - } - }, - "Long date": { - value: (settings.longDate !== undefined ? settings.longDate : true), - format: v => v ? "On" : "Off", - onchange: v => { - settings.longDate = v; - writeSettings(); - } - }, + "Date": stringInSettings("dateOnMain", ["Short", "Long", "ISO8601"]), "Show Weekday": { value: (settings.weekDay !== undefined ? settings.weekDay : true), format: v => v ? "On" : "Off", @@ -65,23 +71,16 @@ "title": "Show seconds..." }, "< Back": () => E.showMenu(mainmenu), - "Always": { - value: (settings.secondsAlways !== undefined ? settings.secondsAlways : false), + "Show": stringInSettings("secondsMode", ["Never", "Unlocked", "Always"]), + "With \":\"": { + value: (settings.secondsWithColon !== undefined ? settings.secondsWithColon : false), format: v => v ? "On" : "Off", onchange: v => { - settings.secondsAlways = v; + settings.secondsWithColon = v; writeSettings(); } }, - "If unlocked": { - value: (settings.secondsOnUnlock !== undefined ? settings.secondsOnUnlock : false), - format: v => v ? "On" : "Off", - onchange: v => { - settings.secondsOnUnlock = v; - writeSettings(); - } - }, - "Coloured": { + "Color": { value: (settings.secondsColoured !== undefined ? settings.secondsColoured : false), format: v => v ? "On" : "Off", onchange: v => { @@ -89,14 +88,7 @@ writeSettings(); } }, - "With date": { - value: (settings.dateOnSecs !== undefined ? settings.dateOnSecs : false), - format: v => v ? "On" : "Off", - onchange: v => { - settings.dateOnSecs = v; - writeSettings(); - } - } + "Date": stringInSettings("dateOnSecs", ["No", "Year", "Weekday"]) }; // Actually display the menu From ebc7005e372cbd03b6922fcec13d5f8010f0a802 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Wed, 5 Jan 2022 21:27:21 +0000 Subject: [PATCH 11/59] Flipper: switch between light and dark theme and vice versa --- apps.json | 15 ++++++++++++++ apps/flipper/flipper.app.js | 39 +++++++++++++++++++++++++++++++++++ apps/flipper/flipper.icon.js | 1 + apps/flipper/flipper.png | Bin 0 -> 644 bytes 4 files changed, 55 insertions(+) create mode 100644 apps/flipper/flipper.app.js create mode 100644 apps/flipper/flipper.icon.js create mode 100644 apps/flipper/flipper.png diff --git a/apps.json b/apps.json index ebafa9c97..a32522fa2 100644 --- a/apps.json +++ b/apps.json @@ -5427,5 +5427,20 @@ {"name":"puzzle15.img","url":"puzzle15.app-icon.js","evaluate":true} ], "data": [{"name":"puzzle15.json"}] + }, + { + "id": "flipper", + "name": "flipper", + "version": "0.01", + "description": "Switch between dark and light theme and vice versa, combine with pattern launcher and swipe to flip." + "icon": "flipper.png", + "type": "app", + "tags": "game", + "supports": ["BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"flipper.app.js","url":"flipper.app.js"}, + {"name":"flipper.img","url":"flipper.app-icon.js","evaluate":true} + ] } ] diff --git a/apps/flipper/flipper.app.js b/apps/flipper/flipper.app.js new file mode 100644 index 000000000..2e7d3551c --- /dev/null +++ b/apps/flipper/flipper.app.js @@ -0,0 +1,39 @@ +const storage = require('Storage'); +let settings = storage.readJSON('setting.json', 1); + +function cl(x) { return g.setColor(x).getColor(); } + +function upd(th) { + g.theme = th; + settings.theme = th; + storage.write('setting.json', settings); + delete g.reset; + g._reset = g.reset; + g.reset = function(n) { return g._reset().setColor(th.fg).setBgColor(th.bg); }; + g.clear = function(n) { if (n) g.reset(); return g.clearRect(0,0,g.getWidth(),g.getHeight()); }; + g.clear(1); +}; + +function flipTheme() { + if (!g.theme.dark) { + upd({ + fg:cl("#fff"), bg:cl("#000"), + fg2:cl("#0ff"), bg2:cl("#000"), + fgH:cl("#fff"), bgH:cl("#00f"), + dark:true + }); + } else { + upd({ + fg:cl("#000"), bg:cl("#fff"), + fg2:cl("#000"), bg2:cl("#cff"), + fgH:cl("#000"), bgH:cl("#0ff"), + dark:false + }); + } +} + +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +flipTheme(); +setTimeout(load, 20); diff --git a/apps/flipper/flipper.icon.js b/apps/flipper/flipper.icon.js new file mode 100644 index 000000000..16331c09e --- /dev/null +++ b/apps/flipper/flipper.icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4X/AAO/mMUzs975K+ggLKysUAYNVqoLFitUoAKBqtQBYkJBIQABqwLEgQLEqtABggJDqkVBaoNCBZQwEgILWgoJENYsVBIcVBYpDEgpSIBYMBKQg6CuogCBY1UgoLCXAQLDqAsDBYhSBqEJHAoLDoEBcQ4LBEwILIMooLdIg4LaVoyaGERLcFao4LIdRAACYYUQBY5RKAH4Ar")); diff --git a/apps/flipper/flipper.png b/apps/flipper/flipper.png new file mode 100644 index 0000000000000000000000000000000000000000..b91543070be72c6a53a11aabec8d779780d2bc11 GIT binary patch literal 644 zcmV-~0(-0O`Ea$39hd$rSFgp06=YM0Il{S zNt_9?Wo4B{?^|t~pJ#}Zrg02ZoGP${lF_V|5I_%73ZmJuT0&*lfPjaY0kbl|Sb3wL z2iZV)c;Qk98Bz=!?CoNy@mQ250PlrNr2`;lAs6C1E3GII=pLkuXTT=w$hHTa{YLQ` z0?xEdlzJYJ3F=Idm0(>vK^Pg(9sT9im&`Mr3Ts-00mn0N`_RDC^9pvhHpzW_4_+18 zL9D7-+xz_(>FX7?nT)LIEeMMfc@TeKdJw5k&EV#IQrPAaCrd~q@cQg1x6LKi2J!@! zbsCWl%(i2A&pkZvWCw5cpu zQ52!tv*A*c5t$$kc$hi6inbEUj%}3*5RIkQdBFF-Ff#srA^Yik31Y^IS-VB@>t~>A ez&Bk3zIg*Y=-nc5eyO+s0000 Date: Wed, 5 Jan 2022 22:04:50 +0000 Subject: [PATCH 12/59] Flipper: switch between light and dark theme and vice versa --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index a32522fa2..07d9c02ae 100644 --- a/apps.json +++ b/apps.json @@ -5432,7 +5432,7 @@ "id": "flipper", "name": "flipper", "version": "0.01", - "description": "Switch between dark and light theme and vice versa, combine with pattern launcher and swipe to flip." + "description": "Switch between dark and light theme and vice versa, combine with pattern launcher and swipe to flip.", "icon": "flipper.png", "type": "app", "tags": "game", From 71228efb4ba118f8c4c2145174008ca02f329b1c Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Wed, 5 Jan 2022 23:12:16 +0100 Subject: [PATCH 13/59] Update gps-info.js Resolve one FIFO_FULL case and exit App with button press --- apps/gpsinfo/gps-info.js | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/apps/gpsinfo/gps-info.js b/apps/gpsinfo/gps-info.js index a16d4a04e..467d12a95 100644 --- a/apps/gpsinfo/gps-info.js +++ b/apps/gpsinfo/gps-info.js @@ -19,6 +19,7 @@ var lastFix = { var SATinView = 0; var nofBD = 0; var nofGP = 0; +var listenerGPSraw = 1; function formatTime(now) { if (now == undefined) { @@ -93,6 +94,10 @@ function onGPS(fix) { } lastFix = fix; if (fix.fix) { + if (listenerGPSraw == 1) { + Bangle.removeListener('GPS-raw', onGPSraw); + listenerGPSraw = 0; + } var locale = require("locale"); var satellites = fix.satellites; var maidenhead = getMaidenHead(fix.lat,fix.lon); @@ -104,6 +109,10 @@ function onGPS(fix) { layout.sat.label = "Satellites: "+satellites; layout.maidenhead.label = "Maidenhead: "+maidenhead; } else { + if (listenerGPSraw == 0) { + Bangle.on('GPS-raw', onGPSraw); + listenerGPSraw = 1; + } layout.sat.label = fix.satellites; layout.progress.label = "in view: " + SATinView; } @@ -111,15 +120,26 @@ function onGPS(fix) { } function onGPSraw(nmea) { - if (nmea.slice(3,6) == "GSV") { - // console.log(nmea); - if (nmea.slice(0,7) == "$BDGSV,") nofBD = Number(nmea.slice(11,13)); - if (nmea.slice(0,7) == "$GPGSV,") nofGP = Number(nmea.slice(11,13)); - SATinView = nofBD + nofGP; - } + if (nmea.slice(0,7) == "$BDGSV,") nofBD = Number(nmea.slice(11,13)); + if (nmea.slice(0,7) == "$GPGSV,") nofGP = Number(nmea.slice(11,13)); + SATinView = nofBD + nofGP; } + Bangle.loadWidgets(); Bangle.drawWidgets(); Bangle.on('GPS', onGPS); Bangle.on('GPS-raw', onGPSraw); + +function exitApp() { + Bangle.setGPSPower(0, "app"); + Bangle.removeListener('GPS-raw', onGPSraw); + Bangle.removeListener('GPS', onGPS); + load(); +} + +setWatch(_=>exitApp(), BTN1); +if (global.BTN2) { + setWatch(_=>exitApp(), BTN2); + setWatch(_=>exitApp(), BTN3); +} From b2f844f32704d1863f18409f4da9898cef21f416 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Wed, 5 Jan 2022 23:15:27 +0100 Subject: [PATCH 14/59] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index ebafa9c97..7e3d29cdc 100644 --- a/apps.json +++ b/apps.json @@ -1501,7 +1501,7 @@ { "id": "gpsinfo", "name": "GPS Info", - "version": "0.06", + "version": "0.07", "description": "An application that displays information about altitude, lat/lon, satellites and time", "icon": "gps-info.png", "type": "app", From 97200f4ac566881ffa01b245c0da6cab61d08904 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Wed, 5 Jan 2022 23:16:33 +0100 Subject: [PATCH 15/59] Update ChangeLog --- apps/gpsinfo/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/gpsinfo/ChangeLog b/apps/gpsinfo/ChangeLog index 3ff284cb8..284ff7999 100644 --- a/apps/gpsinfo/ChangeLog +++ b/apps/gpsinfo/ChangeLog @@ -3,3 +3,4 @@ 0.04: Add Maidenhead readout of GPS location 0.05: Refactor to use 'layout' library for multi-device support 0.06: Added number of satellites in view and fixed crash with GPS time +0.07: Resolve one FIFO_FULL case and exit App with button press From f167ab829bf4f6fc1e78437cccbfadcfc984310a Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Wed, 5 Jan 2022 23:17:04 +0100 Subject: [PATCH 16/59] Update ChangeLog --- apps/gpsinfo/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/gpsinfo/ChangeLog b/apps/gpsinfo/ChangeLog index 284ff7999..a3a2fc89a 100644 --- a/apps/gpsinfo/ChangeLog +++ b/apps/gpsinfo/ChangeLog @@ -2,5 +2,5 @@ 0.03: Show number of satellites while waiting for fix 0.04: Add Maidenhead readout of GPS location 0.05: Refactor to use 'layout' library for multi-device support -0.06: Added number of satellites in view and fixed crash with GPS time +0.06: Add number of satellites in view and fix crash with GPS time 0.07: Resolve one FIFO_FULL case and exit App with button press From c5f77a06926cabc0fe7c7be4d503bd9c0b0e79e1 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Wed, 5 Jan 2022 22:31:21 +0000 Subject: [PATCH 17/59] Flipper: switch between light and dark theme and vice versa --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 07d9c02ae..e643d1c7d 100644 --- a/apps.json +++ b/apps.json @@ -5440,7 +5440,7 @@ "allow_emulator": true, "storage": [ {"name":"flipper.app.js","url":"flipper.app.js"}, - {"name":"flipper.img","url":"flipper.app-icon.js","evaluate":true} + {"name":"flipper.img","url":"flipper.icon.js","evaluate":true} ] } ] From 4f4cb8aba5eae7542b1f8b5ae7990758592ffc45 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Wed, 5 Jan 2022 22:36:45 +0000 Subject: [PATCH 18/59] Flipper: switch between light and dark theme and vice versa --- apps/flipper/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/flipper/ChangeLog diff --git a/apps/flipper/ChangeLog b/apps/flipper/ChangeLog new file mode 100644 index 000000000..9db0e26c5 --- /dev/null +++ b/apps/flipper/ChangeLog @@ -0,0 +1 @@ +0.01: first release From 1a97767aa32e3c08fe6ee1e7b57be7b639aac5a5 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 15:24:26 -0800 Subject: [PATCH 19/59] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index bd7f77cef..a52355909 100644 --- a/apps.json +++ b/apps.json @@ -5162,7 +5162,7 @@ { "id": "promenu", "name": "Pro Menu", - "version": "0.01", + "version": "0.02", "description": "Replace the built in menu function. Supports Bangle.js 1 and Bangle.js 2.", "icon": "icon.png", "type": "boot", From 3aada0243dbe45da9b43e38aa40f869a751863c3 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 15:25:39 -0800 Subject: [PATCH 20/59] Update ChangeLog --- apps/promenu/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/promenu/ChangeLog b/apps/promenu/ChangeLog index 5560f00bc..8d214723c 100644 --- a/apps/promenu/ChangeLog +++ b/apps/promenu/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Add Bangle.js 2 Support! From 73e3378d25026ed7a268308f031aa8a081d170ba Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 15:29:05 -0800 Subject: [PATCH 21/59] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index a52355909..051764016 100644 --- a/apps.json +++ b/apps.json @@ -5171,7 +5171,7 @@ "screenshots": [{"url":"pro-menu-screenshot.png"}], "storage": [ {"name":"promenu.boot.js","url":"boot.js","supports": ["BANGLEJS"]}, - {"name":"promenu.bootb2.js","url":"boot.js","supports": ["BANGLEJS2"]}, + {"name":"promenu.boot.js","url":"bootb2.js","supports": ["BANGLEJS2"]}, {"name":"promenu.img","url":"promenuIcon.js","evaluate":true} ] }, From d54692117792802f2433922d3df61aac1361b65d Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 15:35:57 -0800 Subject: [PATCH 22/59] fix text overlapping text issue --- apps/promenu/bootb2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/promenu/bootb2.js b/apps/promenu/bootb2.js index 096745f34..c84e0d894 100644 --- a/apps/promenu/bootb2.js +++ b/apps/promenu/bootb2.js @@ -74,7 +74,7 @@ E.showMenu = function(items) { g.setFontAlign(-1,-1); var v = item.value; v = loc.translate(""+v); - if(loc.translate(name).length >= 19-v.length && "object" == typeof item){ + if(loc.translate(name).length >= 17-v.length && "object" == typeof item){ if (item.format) v=item.format(v); g.drawString(loc.translate(name).substring(0, 12-v.length)+"...",x+3.7,iy+2.7); }else{ From d330d6dfd568162eb4ca3dce1978e0963420a04f Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 15:41:48 -0800 Subject: [PATCH 23/59] remove exclamation from change log --- apps/promenu/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/promenu/ChangeLog b/apps/promenu/ChangeLog index 8d214723c..b7287cc80 100644 --- a/apps/promenu/ChangeLog +++ b/apps/promenu/ChangeLog @@ -1,2 +1,2 @@ 0.01: New App! -0.02: Add Bangle.js 2 Support! +0.02: Add Bangle.js 2 Support From 84174a270b695e20f01fab6de5f37920f6422e24 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Wed, 5 Jan 2022 23:45:22 +0000 Subject: [PATCH 24/59] Flipper: added README --- apps.json | 2 ++ apps/flipper/README.md | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 apps/flipper/README.md diff --git a/apps.json b/apps.json index e643d1c7d..e9c4a9f6a 100644 --- a/apps.json +++ b/apps.json @@ -5433,6 +5433,8 @@ "name": "flipper", "version": "0.01", "description": "Switch between dark and light theme and vice versa, combine with pattern launcher and swipe to flip.", + "readme":"README.md", + "screenshots": [{"url":"flipper.png"}], "icon": "flipper.png", "type": "app", "tags": "game", diff --git a/apps/flipper/README.md b/apps/flipper/README.md new file mode 100644 index 000000000..88025b8b2 --- /dev/null +++ b/apps/flipper/README.md @@ -0,0 +1,20 @@ +# Flipper + +![](flipper.png) + + *A utility to switch from the dark to the light theme and vice versa* + +* If the current theme is dark it will switch to the light theme +* If the current theme is light it will switch to the dark theme +* Combine with the awesome pattern launcher and it saves loads of time + + +## Demo Video + +There's no screenshot but there is a [demo video.](https://espruino.microco.sm/api/v1/files/9caa1afef7e4cce1d9b518af2dd271f1a57c5ecc.mp4) + +## Future Enhancements + +* Nothing left to add + +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/) From d305de0bdc274c8c82a4a76556c506b9c6bfcff8 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 01:59:22 +0100 Subject: [PATCH 25/59] Update widget.js Increase screen update rate when charging, as requested by issue https://github.com/espruino/BangleApps/issues/1137 --- apps/widbatpc/widget.js | 59 ++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/apps/widbatpc/widget.js b/apps/widbatpc/widget.js index 5386ffe22..529923386 100644 --- a/apps/widbatpc/widget.js +++ b/apps/widbatpc/widget.js @@ -1,6 +1,9 @@ (function(){ + const intervalLow = 60000; // update time when not charging + const intervalHigh = 2000; // update time when charging + let COLORS = {}; - + if (process.env.HWVERSION == 1) { COLORS = { 'white': -1, // White @@ -17,13 +20,13 @@ 'high': "#0f0", // Green 'ok': "#ff0", // Orange 'low': "#f00", // Red - }; + }; } - const SETTINGS_FILE = 'widbatpc.json' + const SETTINGS_FILE = 'widbatpc.json'; - let settings + let settings; function loadSettings() { - settings = require('Storage').readJSON(SETTINGS_FILE, 1) || {} + settings = require('Storage').readJSON(SETTINGS_FILE, 1) || {}; const DEFAULTS = { 'color': 'By Level', 'percentage': true, @@ -32,17 +35,17 @@ 'alwaysoncharge': false, }; Object.keys(DEFAULTS).forEach(k=>{ - if (settings[k]===undefined) settings[k]=DEFAULTS[k] + if (settings[k]===undefined) settings[k]=DEFAULTS[k]; }); } function setting(key) { - if (!settings) { loadSettings() } + if (!settings) { loadSettings(); } return settings[key]; } const levelColor = (l) => { // "charging" is very bright -> percentage is hard to read, "high" is ok(ish) - const green = setting('percentage') ? COLORS.high : COLORS.charging + const green = setting('percentage') ? COLORS.high : COLORS.charging; switch (setting('color')) { case 'Monochrome': return COLORS.white; // no chance of reading the percentage here :-( case 'Green': return green; @@ -59,10 +62,11 @@ if (l >= 15) return COLORS.ok; return COLORS.low; } - } + }; const chargerColor = () => { - return (setting('color') === 'Monochrome') ? COLORS.white : COLORS.charging - } + return (setting('color') === 'Monochrome') ? COLORS.white : COLORS.charging; + }; + // sets width, returns true if it changed function setWidth() { var w = 40; @@ -77,6 +81,7 @@ WIDGETS["batpc"].width = w; return changed; } + function draw() { // if hidden, don't draw if (!WIDGETS["batpc"].width) return; @@ -106,11 +111,11 @@ if (!setting('percentage')) { return; } - let gfx = g + let gfx = g; if (setting('color') === 'Monochrome') { // draw text inverted on battery level gfx = Graphics.createCallback(g.getWidth(),g.getHeight(), 1, - (x,y) => {g.setPixel(x,y,x<=xl?0:-1)}) + (x,y) => {g.setPixel(x,y,x<=xl?0:-1);}); } gfx.setFontAlign(-1,-1); if (l >= 100) { @@ -122,19 +127,24 @@ gfx.drawString(l, x + 6, y + 4); } } + // reload widget, e.g. when settings have changed function reload() { - loadSettings() + loadSettings(); // need to redraw all widgets, because changing the "charger" setting // can affect the width and mess with the whole widget layout - setWidth() + setWidth(); g.clear(); Bangle.drawWidgets(); } + // update widget - redraw just widget, or all widgets if size changed function update() { if (setWidth()) Bangle.drawWidgets(); else WIDGETS["batpc"].draw(); + + if (Bangle.isCharging()) changeInterval(id, intervalHigh); + else changeInterval(id, intervalLow); } Bangle.on('charging',function(charging) { @@ -142,20 +152,13 @@ update(); g.flip(); }); - var batteryInterval; + Bangle.on('lcdPower', function(on) { - if (on) { - update(); - // refresh once a minute if LCD on - if (!batteryInterval) - batteryInterval = setInterval(update, 60000); - } else { - if (batteryInterval) { - clearInterval(batteryInterval); - batteryInterval = undefined; - } - } + if (on) update(); }); + + var id = setInterval(()=>WIDGETS["batpc"].draw(), intervalLow); + WIDGETS["batpc"]={area:"tr",width:40,draw:draw,reload:reload}; setWidth(); -})() +})(); From d343de172ea4a4a8e8a7b35c1d61af1435ac957e Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 02:01:54 +0100 Subject: [PATCH 26/59] Update ChangeLog --- apps/widbatpc/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/widbatpc/ChangeLog b/apps/widbatpc/ChangeLog index 273e611a4..e70093659 100644 --- a/apps/widbatpc/ChangeLog +++ b/apps/widbatpc/ChangeLog @@ -12,3 +12,4 @@ 0.13: Fillbar setting added, see README 0.14: Fix drawing the bar when charging 0.15: Added option to always display the icon when charging (useful if 'hide if charge greater than' is enabled) +0.16: Increase screen update rate when charging From 50ae67fcd7127d52ebc7d1eda834a02e91e44da2 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 02:03:30 +0100 Subject: [PATCH 27/59] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 7e3d29cdc..e37326674 100644 --- a/apps.json +++ b/apps.json @@ -936,7 +936,7 @@ "id": "widbatpc", "name": "Battery Level Widget (with percentage)", "shortName": "Battery Widget", - "version": "0.15", + "version": "0.16", "description": "Show the current battery level and charging status in the top right of the clock, with charge percentage", "icon": "widget.png", "type": "widget", From b9dcd0a8755dcbd463c45df3aa183f07dfc0c955 Mon Sep 17 00:00:00 2001 From: numerist Date: Wed, 5 Jan 2022 21:09:15 -0500 Subject: [PATCH 28/59] Update README.md This description now fits both Bangle watch versions, 1 and 2. --- apps/doztime/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/doztime/README.md b/apps/doztime/README.md index 075b2f66a..2f5b04780 100644 --- a/apps/doztime/README.md +++ b/apps/doztime/README.md @@ -11,4 +11,4 @@ The year itself begins on the December solstice. Because that always happens, th The epoch (year numbering) begins in the last year when the perihelion coincided with the June solstice, near the beginning of the Holocene era. That astronomical basis makes the calendar free from politics, religion, or geography. -While the year number remains cardinal, BTN5 toggles between cardinal and ordinal for the rest of the calendar segments. BTN4 adds or removes a quickly changing digit to or from the clock. +While the year number remains cardinal, tapping on the right side of the watch face toggles between cardinal and ordinal for the rest of the calendar segments. Tapping on the left adds or removes a quickly changing digit to or from the clock. From c2646e5b9f5fca7090c93cc0dbd3f17086b63231 Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Wed, 5 Jan 2022 22:28:52 -0800 Subject: [PATCH 29/59] Update resourcer.js Improve character shapes. --- apps/pooqround/resourcer.js | 60 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/apps/pooqround/resourcer.js b/apps/pooqround/resourcer.js index 44186e658..17c35a40d 100644 --- a/apps/pooqround/resourcer.js +++ b/apps/pooqround/resourcer.js @@ -1,6 +1,6 @@ // pooqRoman resource maker // -// Copyright (c) 2021 Stephen P Spackman +// Copyright (c) 2021, 2022 Stephen P Spackman // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -147,18 +147,18 @@ res += prepFont('y10', ` xxx xxx -2-------------------------------- - x xx + x xxx xx xxx xxxx xxx xxxxx xxx xxxxxxx xxx xxxx xxx xxx - xxxx xxxx xxx - xxxx xxxx xxx - xxxx xxxxxxxx xxxxxxx - xxxx xxxxxxxxxxxxxxxxxxx + xxxx xxxx xxxx + xxxx xxxxx xxxx + xxxx xxxxxxx xxxxxx + xxxx xxxxxxxxxxxxxxxxx xxxx xxxxxxxxxxxxxx -xxxx xxxxxxxxxx +xxxx xxxxxxxxx -3-------------------------------- xxx x xxx xxx xx xxx @@ -270,10 +270,10 @@ res += prepFont('y1', ` xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -1---------------------------------------------- xxx - xxx - xxx - xxx x - xxx x + xxx x + xxx xx + xxx xx + xxx xxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx @@ -282,18 +282,18 @@ res += prepFont('y1', ` xxx xxx -2---------------------------------------------- - x xx + x xxx xx xxx xxxx xxx - xxxxx xxx - xxxxxxx xxx - xxxx xxxx xxx - xxxx xxxxx xxx - xxxx xxxxxxx xxxx - xxxx xxxxxxxxxxxxx xxxxxxxxxxx - xxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - xxxx xxxxxxxxxxxxxxxxxxxxxxxxx -xxxx xxxxxxxxxxxxxx + xxxxxx xxx + xxxxxxxx xxx + xxxx xxxxx xxx + xxxx xxxxxx xxxx + xxxx xxxxxxxx xxxx + xxxx xxxxxxxxxxx xxxxxxxx + xxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxx xxxxxxxxxxxxxxxxxxxxxxxxx +xxxx xxxxxxxxxxxxxxxxx -3---------------------------------------------- xxx x xxx xxx xx xxx @@ -645,12 +645,12 @@ xxxx xxxx -1---------------------------------------------- -xxx x -xxx xx -xxx xxx -xxx xxx -xxx xxxx -xxx xxxx +xxx +xxx x +xxx xx +xxx xx +xxx xxx +xxx xxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx @@ -993,9 +993,9 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxx - xxxxxxxxxxxxxxxx - xxxxxxxxxxxxxxxx - xxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxx xxxx xxxx xxx From adc5ae007155c61a7bc1ba45c87df40f4ed5c03b Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 6 Jan 2022 09:03:35 +0000 Subject: [PATCH 30/59] fix issues with flipper pr --- apps/flipper/flipper.app.js | 2 +- apps/flipper/flipper.icon.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/flipper/flipper.app.js b/apps/flipper/flipper.app.js index 2e7d3551c..7171306b1 100644 --- a/apps/flipper/flipper.app.js +++ b/apps/flipper/flipper.app.js @@ -12,7 +12,7 @@ function upd(th) { g.reset = function(n) { return g._reset().setColor(th.fg).setBgColor(th.bg); }; g.clear = function(n) { if (n) g.reset(); return g.clearRect(0,0,g.getWidth(),g.getHeight()); }; g.clear(1); -}; +} function flipTheme() { if (!g.theme.dark) { diff --git a/apps/flipper/flipper.icon.js b/apps/flipper/flipper.icon.js index 16331c09e..494072c3c 100644 --- a/apps/flipper/flipper.icon.js +++ b/apps/flipper/flipper.icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEw4X/AAO/mMUzs975K+ggLKysUAYNVqoLFitUoAKBqtQBYkJBIQABqwLEgQLEqtABggJDqkVBaoNCBZQwEgILWgoJENYsVBIcVBYpDEgpSIBYMBKQg6CuogCBY1UgoLCXAQLDqAsDBYhSBqEJHAoLDoEBcQ4LBEwILIMooLdIg4LaVoyaGERLcFao4LIdRAACYYUQBY5RKAH4Ar")); +require("heatshrink").decompress(atob("mEw4X/AAO/mMUzs975K+ggLKysUAYNVqoLFitUoAKBqtQBYkJBIQABqwLEgQLEqtABggJDqkVBaoNCBZQwEgILWgoJENYsVBIcVBYpDEgpSIBYMBKQg6CuogCBY1UgoLCXAQLDqAsDBYhSBqEJHAoLDoEBcQ4LBEwILIMooLdIg4LaVoyaGERLcFao4LIdRAACYYUQBY5RKAH4Ar")) From f6e374838fe654ec27133c2451863acf00e35721 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 11:04:01 +0100 Subject: [PATCH 31/59] Update ChangeLog --- apps/gpsinfo/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/gpsinfo/ChangeLog b/apps/gpsinfo/ChangeLog index a3a2fc89a..8d428ce85 100644 --- a/apps/gpsinfo/ChangeLog +++ b/apps/gpsinfo/ChangeLog @@ -4,3 +4,4 @@ 0.05: Refactor to use 'layout' library for multi-device support 0.06: Add number of satellites in view and fix crash with GPS time 0.07: Resolve one FIFO_FULL case and exit App with button press +0.08: Leave GPS power switched on on exit (will switch off after 0.5 seconds anyway) From f59e97c5fc9eaf1e94a98edaffeec9bd0663782d Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 11:04:14 +0100 Subject: [PATCH 32/59] Update gps-info.js Leave GPS power switched on on exit (will switch off after 0.5 seconds anyway). --- apps/gpsinfo/gps-info.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/gpsinfo/gps-info.js b/apps/gpsinfo/gps-info.js index 467d12a95..fdac3d403 100644 --- a/apps/gpsinfo/gps-info.js +++ b/apps/gpsinfo/gps-info.js @@ -132,9 +132,6 @@ Bangle.on('GPS', onGPS); Bangle.on('GPS-raw', onGPSraw); function exitApp() { - Bangle.setGPSPower(0, "app"); - Bangle.removeListener('GPS-raw', onGPSraw); - Bangle.removeListener('GPS', onGPS); load(); } From 1df9b03a30aa8e8147ca1ec17b157202ea48ab7f Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 11:04:22 +0100 Subject: [PATCH 33/59] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index e37326674..71fcb3ff8 100644 --- a/apps.json +++ b/apps.json @@ -1501,7 +1501,7 @@ { "id": "gpsinfo", "name": "GPS Info", - "version": "0.07", + "version": "0.08", "description": "An application that displays information about altitude, lat/lon, satellites and time", "icon": "gps-info.png", "type": "app", From a9ea028ede2e9fad7e48b4364609c6aaa43f3481 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 6 Jan 2022 12:13:21 +0000 Subject: [PATCH 34/59] fwupdate 0.03: Improve bootloader update safety. Now sets unsafeFlash:1 to allow flash with 2v11 and later Add CRC checks for common bootloaders that we know don't work --- apps.json | 2 +- apps/fwupdate/ChangeLog | 2 ++ apps/fwupdate/custom.html | 23 ++++++++++------------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/apps.json b/apps.json index 33836e05f..8fab1c96e 100644 --- a/apps.json +++ b/apps.json @@ -2,7 +2,7 @@ { "id": "fwupdate", "name": "Firmware Update", - "version": "0.02", + "version": "0.03", "description": "[BETA] Uploads new Espruino firmwares to Bangle.js 2. For now, please use the instructions under https://www.espruino.com/Bangle.js2#firmware-updates", "icon": "app.png", "type": "RAM", diff --git a/apps/fwupdate/ChangeLog b/apps/fwupdate/ChangeLog index 96e7e4e9b..458d695f0 100644 --- a/apps/fwupdate/ChangeLog +++ b/apps/fwupdate/ChangeLog @@ -2,3 +2,5 @@ 0.02: Add support for ZIPs Find and download ZIPs direct from the Espruino website Take 'beta' tag off +0.03: Improve bootloader update safety. Now sets unsafeFlash:1 to allow flash with 2v11 and later + Add CRC checks for common bootloaders that we know don't work diff --git a/apps/fwupdate/custom.html b/apps/fwupdate/custom.html index 8c2008e54..7a1e736e4 100644 --- a/apps/fwupdate/custom.html +++ b/apps/fwupdate/custom.html @@ -60,6 +60,7 @@ function onInit(device) { document.getElementById("fw-unknown").style = "display:none"; document.getElementById("fw-ok").style = ""; } + } function checkForFileOnServer() { @@ -264,6 +265,8 @@ function createJS_app(binary, startAddress, endAddress) { bin32[3] = VERSION; // VERSION! Use this to test ourselves console.log("CRC 0x"+bin32[2].toString(16)); hexJS = "";//`\x10if (E.CRC32(E.memoryArea(${startAddress},${endAddress-startAddress}))==${bin32[2]}) { print("FIRMWARE UP TO DATE!"); load();}\n`; + hexJS += `\x10if (E.CRC32(E.memoryArea(0xF7000,0x7000))==1339551013) { print("BOOTLOADER 2v10.219 needs update"); load();}\n`; + hexJS += `\x10if (E.CRC32(E.memoryArea(0xF7000,0x7000))==1207580954) { print("BOOTLOADER 2v10.236 needs update"); load();}\n`; hexJS += '\x10var s = require("Storage");\n'; hexJS += '\x10s.erase(".firmware");\n'; var CHUNKSIZE = 2048; @@ -291,20 +294,14 @@ function createJS_bootloader(binary, startAddress, endAddress) { var chunk = btoa(new Uint8Array(binary.buffer, binary.byteOffset+i, l)); hexJS += '\x10_fw.set(atob("'+chunk+'"), 0x'+(i).toString(16)+');\n'; } -// hexJS += `\x10(function() { -// if (E.CRC32(_fw)!=${crc}) throw "Invalid CRC!"; -// var f = require("Flash"); -// for (var i=${startAddress};i<${endAddress};i+=4096) f.erasePage(i); -// f.write(_fw,${startAddress}); -// E.reboot(); -// })();\n`; - hexJS += `\x10if (E.CRC32(_fw)!=${crc}) throw "Invalid CRC: 0x"+E.CRC32(_fw).toString(16);\n`; - hexJS += '\x10var f = require("Flash");\n'; + hexJS += `\x10(function() { if (E.CRC32(_fw)!=${crc}) throw "Invalid CRC: 0x"+E.CRC32(_fw).toString(16);\n`; + hexJS += 'E.showMessage("Flashing Bootloader...")\n'; + hexJS += 'E.setFlags({unsafeFlash:1})\n'; + hexJS += 'var f = require("Flash");\n'; for (var i=startAddress;i Date: Thu, 6 Jan 2022 15:15:58 +0100 Subject: [PATCH 35/59] Update ChangeLog --- apps/wid_a_battery_widget/ChangeLog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/wid_a_battery_widget/ChangeLog b/apps/wid_a_battery_widget/ChangeLog index b04824ae8..8a1538479 100644 --- a/apps/wid_a_battery_widget/ChangeLog +++ b/apps/wid_a_battery_widget/ChangeLog @@ -1,3 +1,4 @@ 1.00: Release for Bangle 2 (2021/11/18) 1.01: Internal id update to wid_* as per Gordon's request (2021/11/21) -1.02: Support dark themes \ No newline at end of file +1.02: Support dark themes +1.03: Increase screen update rate when charging From ae27f50a476a4af463c4333a203ac2f118da2373 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 15:17:43 +0100 Subject: [PATCH 36/59] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 958bf71e9..2393e47c3 100644 --- a/apps.json +++ b/apps.json @@ -4477,7 +4477,7 @@ "name": "A Battery Widget (with percentage)", "shortName":"A Battery Widget", "icon": "widget.png", - "version":"1.02", + "version":"1.03", "type": "widget", "supports": ["BANGLEJS", "BANGLEJS2"], "readme": "README.md", From c7fef8134c24ea748d3c60e77e61b331db73bcd6 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 15:20:09 +0100 Subject: [PATCH 37/59] Update widget.js Increase screen update rate when charging. --- apps/wid_a_battery_widget/widget.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/wid_a_battery_widget/widget.js b/apps/wid_a_battery_widget/widget.js index 8ab644ab3..74c76784d 100644 --- a/apps/wid_a_battery_widget/widget.js +++ b/apps/wid_a_battery_widget/widget.js @@ -1,4 +1,7 @@ (function(){ + const intervalLow = 60000; // update time when not charging + const intervalHigh = 2000; // update time when charging + let COLORS = { 'white': g.theme.dark ? "#000" : "#fff", 'black': g.theme.dark ? "#fff" : "#000", @@ -36,10 +39,14 @@ g.setFontAlign(0,0); g.setFont('6x8'); g.drawString(l, x + 14, y + 10); + + if (Bangle.isCharging()) changeInterval(id, intervalHigh); + else changeInterval(id, intervalLow); } + Bangle.on('charging',function(charging) { draw(); }); - setInterval(()=>WIDGETS["wid_a_battery_widget"].draw(), 60000); + var id = setInterval(()=>WIDGETS["wid_a_battery_widget"].draw(), intervalLow); WIDGETS["wid_a_battery_widget"]={area:"tr",width:30,draw:draw}; })(); From fec507c926cef377dbbe95ac701e989328e23b41 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:24:31 +0100 Subject: [PATCH 38/59] Only show plotting of speed if Latitude is available --- apps/recorder/app.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/recorder/app.js b/apps/recorder/app.js index fcd8d6031..5b1c63aef 100644 --- a/apps/recorder/app.js +++ b/apps/recorder/app.js @@ -199,9 +199,10 @@ function viewTrack(filename, info) { menu['Plot Alt.'] = function() { plotGraph(info, "Altitude"); }; - menu['Plot Speed'] = function() { - plotGraph(info, "Speed"); - }; + if (info.fields.includes("Latitude")) + menu['Plot Speed'] = function() { + plotGraph(info, "Speed"); + }; // TODO: steps, heart rate? menu['Erase'] = function() { E.showPrompt("Delete Track?").then(function(v) { From f13aa4f94a40fc20346193c61b08aaada2ec34bf Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:26:57 +0100 Subject: [PATCH 39/59] Adds battery stats --- apps/recorder/widget.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index 4d8cdddb1..b9d372ef8 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -82,7 +82,20 @@ draw : (x,y) => g.setColor(hasBPM?"#f00":"#888").drawImage(atob("DAyBAAAAAD/H/n/n/j/D/B+AYAAAAA=="),x,y) }; }, - + bat:function() { + return { + name : "BAT", + fields : ["Battery Percentage", "Battery Voltage", "Charging"], + getValues : () => { + return [E.getBattery(), NRF.getBattery(), Bangle.isCharging()]; + }, + start : () => { + }, + stop : () => { + }, + draw : (x,y) => g.setColor(Bangle.isCharging() ? "#0f0" : "#ff0").drawImage(atob("DAwBAABgH4G4EYG4H4H4H4GIH4AA"),x,y) + }; + }, temp:function() { var core = 0, skin = 0; var hasCore = false; From e60b27a5b01328a22c4cde0670d234f44516b9b4 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:27:24 +0100 Subject: [PATCH 40/59] Actually interpret the file content instead of the name --- apps/recorder/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index b9d372ef8..14e47a60e 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -151,7 +151,7 @@ } }) */ - require("Storage").list(/^.*\.recorder\.js$/).forEach(fn=>eval(fn)(recorders)); + require("Storage").list(/^.*\.recorder\.js$/).forEach(fn=>eval(require("Storage").read(fn))(recorders)); return recorders; } From d1d478015ec74d36bc520890e4cc199d7b37a950 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 6 Jan 2022 17:04:24 +0000 Subject: [PATCH 41/59] widpedom 0.21: Memory usage improvements, fix widget initial width (fix #1170) --- apps.json | 2 +- apps/widpedom/ChangeLog | 1 + apps/widpedom/widget.js | 53 +++++++++++++++++++---------------------- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/apps.json b/apps.json index 8fab1c96e..c60bdbefc 100644 --- a/apps.json +++ b/apps.json @@ -1590,7 +1590,7 @@ { "id": "widpedom", "name": "Pedometer widget", - "version": "0.20", + "version": "0.21", "description": "Daily pedometer widget", "icon": "widget.png", "type": "widget", diff --git a/apps/widpedom/ChangeLog b/apps/widpedom/ChangeLog index c033ea505..3483c3390 100644 --- a/apps/widpedom/ChangeLog +++ b/apps/widpedom/ChangeLog @@ -20,3 +20,4 @@ Fix issue with widget overwrite in large font mode Memory usage enhancements 0.20: Fix issue where step count would randomly reset +0.21: Memory usage improvements, fix widget initial width (fix #1170) diff --git a/apps/widpedom/widget.js b/apps/widpedom/widget.js index 0ec0780c9..3a079c066 100644 --- a/apps/widpedom/widget.js +++ b/apps/widpedom/widget.js @@ -1,5 +1,4 @@ (() => { - const PEDOMFILE = "wpedom.json" // Last time Bangle.on('step' was called let lastUpdate = new Date(); // Last step count when Bangle.on('step' was called @@ -8,19 +7,14 @@ let settings; function loadSettings() { - const d = require('Storage').readJSON(PEDOMFILE, 1) || {}; - settings = d.settings || {}; - } - - function setting(key) { - if (!settings) { loadSettings() } - const DEFAULTS = { + const d = require('Storage').readJSON("wpedom.json", 1) || {}; + settings = Object.assign({ 'goal': 10000, 'progress': false, 'large': false, 'hide': false - } - return (key in settings) ? settings[key] : DEFAULTS[key]; + }, d.settings || {}); + return d; } Bangle.on('step', stepCount => { @@ -31,10 +25,10 @@ if (lastUpdate.getDate() == date.getDate()){ stp_today += steps; } else { - // TODO: could save this to PEDOMFILE for lastUpdate's day? + // TODO: could save this to "wpedom.json" for lastUpdate's day? stp_today = steps; } - if (stp_today === setting('goal') + if (stp_today === settings.goal && !(require('Storage').readJSON('setting.json',1)||{}).quiet) { let b = 3, buzz = () => { if (b--) Bangle.buzz().then(() => setTimeout(buzz, 100)) @@ -51,29 +45,31 @@ }); // When unloading, save state E.on('kill', () => { - if (!settings) { loadSettings() } - let d = { + require("Storage").writeJSON("wpedom.json",{ lastUpdate : lastUpdate.valueOf(), stepsToday : stp_today, settings : settings, - }; - require("Storage").write(PEDOMFILE,d); + }); }); // add your widget - WIDGETS["wpedom"]={area:"tl",width:26, - redraw:function() { // work out the width, and queue a full redraw if needed - let stps = stp_today.toString(); + WIDGETS["wpedom"]={area:"tl",width:0, + getWidth:function() { let newWidth = 24; - if (setting('hide')) + if (settings.hide) newWidth = 0; else { - if (setting('large')) { + if (settings.large) { newWidth = 12 * stps.length + 3; - if (setting('progress')) + if (settings.progress) newWidth += 24; } } + return newWidth; + }, + redraw:function() { // work out the width, and queue a full redraw if needed + let stps = stp_today.toString(); + let newWidth = this.getWidth(); if (newWidth!=this.width) { // width has changed, re-layout all widgets this.width = newWidth; @@ -84,14 +80,14 @@ } }, draw:function() { - if (setting('hide')) return; + if (settings.hide) return; if (stp_today > 99999) stp_today = stp_today % 100000; // cap to five digits + comma = 6 characters let stps = stp_today.toString(); g.reset().clearRect(this.x, this.y, this.x + this.width, this.y + 23); // erase background - if (setting('progress')) { + if (settings.progress) { const width = 23, half = 11; - const goal = setting('goal'), left = Math.max(goal-stps,0); + const goal = settings.goal, left = Math.max(goal-stps,0); // blue or dark green g.setColor(left ? "#08f" : "#080").fillCircle(this.x + half, this.y + half, half); if (left) { @@ -113,10 +109,10 @@ } g.reset(); } - if (setting('large')) { + if (settings.large) { g.setFont("6x8",2); g.setFontAlign(-1, 0); - g.drawString(stps, this.x + (setting('progress')?28:4), this.y + 12); + g.drawString(stps, this.x + (settings.progress?28:4), this.y + 12); } else { let w = 24; if (stps.length > 3){ @@ -137,11 +133,12 @@ getSteps:()=>stp_today }; // Load data at startup - let pedomData = require("Storage").readJSON(PEDOMFILE,1); + let pedomData = loadSettings(); if (pedomData) { if (pedomData.lastUpdate) lastUpdate = new Date(pedomData.lastUpdate); stp_today = pedomData.stepsToday|0; delete pedomData; } + WIDGETS["wpedom"].width = WIDGETS["wpedom"].getWidth(); })() From c8126f5ce4302c85ddbda9bb4f5993dda72e0d3d Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 19:04:41 +0100 Subject: [PATCH 42/59] Changed icons and colors for better visibility --- apps/recorder/widget.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index 14e47a60e..34a6ca488 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -48,7 +48,7 @@ Bangle.removeListener('GPS', onGPS); Bangle.setGPSPower(0,"recorder"); }, - draw : (x,y) => g.setColor(hasFix?"#0ff":"#888").drawImage(atob("DAyBAAACADgDuBOAeA4AzAHADgAAAA=="),x,y) + draw : (x,y) => g.setColor(hasFix?"#0f0":"#f88").drawImage(atob("DAwBEAKARAKQE4DwHkPqPRGKAEAA"),x,y) }; }, hrm:function() { @@ -79,7 +79,7 @@ Bangle.removeListener('HRM', onHRM); Bangle.setHRMPower(0,"recorder"); }, - draw : (x,y) => g.setColor(hasBPM?"#f00":"#888").drawImage(atob("DAyBAAAAAD/H/n/n/j/D/B+AYAAAAA=="),x,y) + draw : (x,y) => g.setColor(hasBPM?"#f00":"#f88").drawImage(atob("DAwBAAAAMMeef+f+f+P8H4DwBgAA"),x,y) }; }, bat:function() { @@ -119,7 +119,7 @@ hasCore = false; Bangle.removeListener('CoreTemp', onCore); }, - draw : (x,y) => g.setColor(hasCore?"#0f0":"#888").drawImage(atob("DAyBAAHh0js3EuDMA8A8AWBnDj9A8A=="),x,y) + draw : (x,y) => g.setColor(hasCore?"#0f0":"#8f8").drawImage(atob("DAwBAAAOAKPOfgZgZgZgZgfgPAAA"),x,y) }; }, steps:function() { @@ -134,7 +134,7 @@ }, start : () => { lastSteps = Bangle.getStepCount(); }, stop : () => {}, - draw : (x,y) => g.reset().drawImage(atob("DAyBAAADDHnnnnnnnnnnjDmDnDnAAA=="),x,y) + draw : (x,y) => g.reset().drawImage(atob("DAwBAAMMeeeeeeeecOMMAAMMMMAA"),x,y) }; } // TODO: recAltitude from pressure sensor From 2c2141c9ec6beef3590c4082399e5dafe5421d53 Mon Sep 17 00:00:00 2001 From: Marc Englund Date: Thu, 6 Jan 2022 21:20:14 +0200 Subject: [PATCH 43/59] Initial version of Ruuvi Watch Added Ruuvi Watch, an app to watch the status of RuuviTags in range. --- apps.json | 13 +++ apps/ruuviwatch/ChangeLog | 1 + apps/ruuviwatch/README.md | 25 +++++ apps/ruuviwatch/ruuviwatch.app-icon.js | 1 + apps/ruuviwatch/ruuviwatch.app.js | 150 +++++++++++++++++++++++++ apps/ruuviwatch/ruuviwatch.png | Bin 0 -> 692 bytes 6 files changed, 190 insertions(+) create mode 100644 apps/ruuviwatch/ChangeLog create mode 100644 apps/ruuviwatch/README.md create mode 100644 apps/ruuviwatch/ruuviwatch.app-icon.js create mode 100644 apps/ruuviwatch/ruuviwatch.app.js create mode 100644 apps/ruuviwatch/ruuviwatch.png diff --git a/apps.json b/apps.json index 833c3505e..15654f26a 100644 --- a/apps.json +++ b/apps.json @@ -5448,5 +5448,18 @@ {"name":"flipper.app.js","url":"flipper.app.js"}, {"name":"flipper.img","url":"flipper.icon.js","evaluate":true} ] + }, + { "id": "ruuviwatch", + "name": "Ruuvi Watch", + "shortName":"Ruuvi Watch", + "icon": "ruuviwatch.png", + "version":"1.00", + "description": "Keep an eye on RuuviTag devices (https://ruuvi.com). Only shows RuuviTags using the v5 format.", + "readme":"README.md", + "tags": "bluetooth", + "storage": [ + {"name":"ruuviwatch.app.js","url":"ruuviwatch.app.js"}, + {"name":"ruuviwatch.img","url":"ruuviwatch.app-icon.js","evaluate":true} + ] } ] diff --git a/apps/ruuviwatch/ChangeLog b/apps/ruuviwatch/ChangeLog new file mode 100644 index 000000000..8a8ec68d5 --- /dev/null +++ b/apps/ruuviwatch/ChangeLog @@ -0,0 +1 @@ +1.00: Hello Ruuvi Watch! \ No newline at end of file diff --git a/apps/ruuviwatch/README.md b/apps/ruuviwatch/README.md new file mode 100644 index 000000000..bf4358267 --- /dev/null +++ b/apps/ruuviwatch/README.md @@ -0,0 +1,25 @@ +# Ruuvi Watch + +Watch the status of [RuuviTags](https://ruuvi.com) in range. + + - Id + - Temperature (°C) + - Humidity (%) + - Pressure (hPa) + - Battery voltage + + Also shows how "fresh" the data is (age of reading). + + ## Usage + + - Scans for devices when launched and every N seconds. + - Page trough devices with BTN1/BTN3. + - Trigger scan with BTN2. + +## Todo / ideas + + - Allow to "name" known devices + - Prevent flicker when updating + - Include more data + - Support older Ruuvi protocols + diff --git a/apps/ruuviwatch/ruuviwatch.app-icon.js b/apps/ruuviwatch/ruuviwatch.app-icon.js new file mode 100644 index 000000000..7ed27ef6c --- /dev/null +++ b/apps/ruuviwatch/ruuviwatch.app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwhC/AH4A/ABMP/4ACCyIVDAAXwCyoYPIggAFCx4oEDBw/JJJguCBhAwLBZYjKBQQeGCIYNHB45bIBw4gIRgw+NC4wwJJ5YRLC5DzFCJBGMEYoSEFxoMEBQIXEF4gVFF5QcEC553JC5QRITgy/NVxIXGf5QlFIwy4IGBQuFC5JhGCwpGGERZOEBQ4MEDAwJJGAzdJCxLVJFxoYLCxoYICx6/GCqAA/AH4A/ACA")) \ No newline at end of file diff --git a/apps/ruuviwatch/ruuviwatch.app.js b/apps/ruuviwatch/ruuviwatch.app.js new file mode 100644 index 000000000..9f5e03b4c --- /dev/null +++ b/apps/ruuviwatch/ruuviwatch.app.js @@ -0,0 +1,150 @@ +require("Storage").write("ruuviwatch.info",{ + "id":"ruuviwatch", + "name":"Ruuvi Watch", + "src":"ruuviwatch.app.js", + "icon":"ruuviwatch.img" + }); + + const lookup = {}; + const ruuvis = []; + let current = 0; + + function int2Hex (str) { + return ('0' + str.toString(16).toUpperCase()).slice(-2); + } + + function p(data) { + const OFFSET = 7; // 0-4 header, 5-6 Ruuvi id + const robject = {}; + robject.version = data[OFFSET]; + + let temperature = (data[OFFSET+1] << 8) | (data[OFFSET+2] & 0xff); + if (temperature > 32767) { + temperature -= 65534; + } + robject.temperature = temperature / 200.0; + + robject.humidity = (((data[OFFSET+3] & 0xff) << 8) | (data[OFFSET+4] & 0xff)) / 400.0; + robject.pressure = ((((data[OFFSET+5] & 0xff) << 8) | (data[OFFSET+6] & 0xff)) + 50000) / 100.0; + + let accelerationX = (data[OFFSET+7] << 8) | (data[OFFSET+8] & 0xff); + if (accelerationX > 32767) accelerationX -= 65536; // two's complement + robject.accelerationX = accelerationX / 1000.0; + + let accelerationY = (data[OFFSET+9] << 8) | (data[OFFSET+10] & 0xff); + if (accelerationY > 32767) accelerationY -= 65536; // two's complement + robject.accelerationY = accelerationY / 1000.0; + + let accelerationZ = (data[OFFSET+11] << 8) | (data[OFFSET+12] & 0xff); + if (accelerationZ > 32767) accelerationZ -= 65536; // two's complement + robject.accelerationZ = accelerationZ / 1000.0; + + const powerInfo = ((data[OFFSET+13] & 0xff) << 8) | (data[OFFSET+14] & 0xff); + robject.battery = ((powerInfo >>> 5) + 1600) / 1000.0; + robject.txPower = (powerInfo & 0b11111) * 2 - 40; + robject.movementCounter = data[OFFSET+15] & 0xff; + robject.measurementSequenceNumber = ((data[OFFSET+16] & 0xff) << 8) | (data[OFFSET+17] & 0xff); + + robject.mac = [ + int2Hex(data[OFFSET+18]), + int2Hex(data[OFFSET+19]), + int2Hex(data[OFFSET+20]), + int2Hex(data[OFFSET+21]), + int2Hex(data[OFFSET+22]), + int2Hex(data[OFFSET+23]) + ].join(':'); + + robject.name = "Ruuvi " + int2Hex(data[OFFSET+22]) + int2Hex(data[OFFSET+23]); + return robject; + } + + function getAge(created) { + const now = new Date().getTime(); + const ago = ((now - created) / 1000).toFixed(0); + return ago > 0 ? ago + "s ago" : "now"; + } + + function redraw() { + if (ruuvis.length > 0 && ruuvis[current]) { + const ruuvi = ruuvis[current]; + g.clear(); + g.setFontAlign(0,0); + g.setFont("Vector",12); + g.drawString(" (" + (current+1) + "/" + ruuvis.length + ")", g.getWidth()/2, 10); + g.setFont("Vector",20); + g.drawString(ruuvi.name, g.getWidth()/2, 30); + g.setFont("Vector",12); + const age = getAge(ruuvi.time); + if(age > (5*60)) { + g.setColor("#ff0000"); + } else if (age > 60) { + g.setColor("#f39c12"); + } else { + g.setColor("#2ecc71"); + } + g.drawString(age, g.getWidth()/2, 50); + g.setColor("#ffffff"); + g.setFont("Vector",60); + g.drawString(ruuvi.temperature.toFixed(2) + "°c", g.getWidth()/2, g.getHeight()/2); + g.setFontAlign(0,1); + g.setFont("Vector",20); + g.drawString(ruuvi.humidity + "% " + ruuvi.pressure + "hPa ", g.getWidth()/2, g.getHeight()-30); + g.setFont("Vector",12); + g.drawString(ruuvi.battery + "v", g.getWidth()/2, g.getHeight()-10); + } else { + g.clear(); + g.drawImage(require("Storage").read("ruuviwatch.img"), g.getWidth()/2-24, g.getHeight()/2-24); + g.setFontAlign(0,0); + g.setFont("Vector",16); + g.drawString("Looking for Ruuvi...", g.getWidth()/2, g.getHeight()/2 + 50); + } + } + + function scan() { + NRF.findDevices(function(devices) { + let foundNew = false; + devices.forEach(device => { + const data = p(device.data); + data.time = new Date().getTime(); + const idx = lookup[data.name]; + if (idx !== undefined) { + ruuvis[idx] = data; + } else { + lookup[data.name] = ruuvis.push(data)-1; + foundNew = true; + } + }); + redraw(); + if (foundNew) { + Bangle.buzz(); + g.flip(); + } + + }, {timeout : 2000, filters : [{ manufacturerData:{0x0499:{}} }] }); + } + + g.drawImage(require("Storage").read("ruuviwatch.img"), g.getWidth()/2-24, g.getHeight()/2-24); + + var drawInterval = setInterval(redraw, 1000); + var scanInterval = setInterval(scan, 10000); + setWatch(() => { + current--; + if (current < 0) { + current = ruuvis.length-1; + } + redraw(); + }, BTN1, {repeat:true}); + + setWatch(() => { + scan(); + }, BTN2, {repeat:true}); + + setWatch(() => { + current++; + if (current >= ruuvis.length) { + current = 0; + } + redraw(); + }, BTN3, {repeat:true}); + + scan(); \ No newline at end of file diff --git a/apps/ruuviwatch/ruuviwatch.png b/apps/ruuviwatch/ruuviwatch.png new file mode 100644 index 0000000000000000000000000000000000000000..3a5d0954952c77bbe18348240ff7313dcc1e8915 GIT binary patch literal 692 zcmV;l0!#ggP)!VNEuuo9P$>Ll4zvRRj_#*&Ry+IU%mlmf9PGcdKZnENFMS7G;?`N`?20^m``($M zufPX(Heet6Pwj{cc2*`f1=EhsnLZNCRUab>49*^$RhZYr(%**v$3&+M?M(=NjU;X} z^?WfNBb}&eFGAHg#@xgiZ4(maIMG%h&-adY#Obv{ob~HMNZwDQ-wI#5sH`8Y9+CO& zb-_>5{E=`@jgWk$^f!>XfLY|huL3`%8qyMiFDo%2b9X?TG13VxzOH!S7nQp5cREL; zxkUUc@I^eP0&`ni_LhcuK5MWMjhboylpD0A6+qq^mvjjoZg)CKjYoBF<3W4qnG|}1 z%7+oRqy+Pvw}@X8SQOe;<%9RbK9B-zM4|t*a2chBCq_Sc5<)-UImU$cnek~Tqqm+q z5v0R<`iO3w)Bfh<=km00ik<^t=4b{+(3H*rLn#F3E8_Q!S+)4+#xJ z9|`1j!BujC{-kc{vq1b=B$okS{KWW(b#J5Mu9U+ruhX88jOumT*+2I}{X&I8p-?FN abY20-1jwJ!GdeE-0000 Date: Thu, 6 Jan 2022 21:27:40 +0200 Subject: [PATCH 44/59] Add "supports" for Ruuvi Watch Add the "supports" section to apps.json for Ruuvi Watch. --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 15654f26a..f86d3bcf8 100644 --- a/apps.json +++ b/apps.json @@ -5457,6 +5457,7 @@ "description": "Keep an eye on RuuviTag devices (https://ruuvi.com). Only shows RuuviTags using the v5 format.", "readme":"README.md", "tags": "bluetooth", + "supports": ["BANGLEJS"], "storage": [ {"name":"ruuviwatch.app.js","url":"ruuviwatch.app.js"}, {"name":"ruuviwatch.img","url":"ruuviwatch.app-icon.js","evaluate":true} From 28bb2f73e0d9293c717f080889d7f8f946c2ebae Mon Sep 17 00:00:00 2001 From: Marc Englund Date: Thu, 6 Jan 2022 21:42:43 +0200 Subject: [PATCH 45/59] Visual fixes Make apploader logo black. Clear gfx before drawing logo on startup. --- apps.json | 2 +- apps/ruuviwatch/ChangeLog | 3 ++- apps/ruuviwatch/ruuviwatch.app.js | 1 + apps/ruuviwatch/ruuviwatch.png | Bin 692 -> 665 bytes 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index f86d3bcf8..6761dd47e 100644 --- a/apps.json +++ b/apps.json @@ -5453,7 +5453,7 @@ "name": "Ruuvi Watch", "shortName":"Ruuvi Watch", "icon": "ruuviwatch.png", - "version":"1.00", + "version":"1.01", "description": "Keep an eye on RuuviTag devices (https://ruuvi.com). Only shows RuuviTags using the v5 format.", "readme":"README.md", "tags": "bluetooth", diff --git a/apps/ruuviwatch/ChangeLog b/apps/ruuviwatch/ChangeLog index 8a8ec68d5..ebde871fa 100644 --- a/apps/ruuviwatch/ChangeLog +++ b/apps/ruuviwatch/ChangeLog @@ -1 +1,2 @@ -1.00: Hello Ruuvi Watch! \ No newline at end of file +1.00: Hello Ruuvi Watch! +1.01: Clear gfx on startup. \ No newline at end of file diff --git a/apps/ruuviwatch/ruuviwatch.app.js b/apps/ruuviwatch/ruuviwatch.app.js index 9f5e03b4c..46218a323 100644 --- a/apps/ruuviwatch/ruuviwatch.app.js +++ b/apps/ruuviwatch/ruuviwatch.app.js @@ -123,6 +123,7 @@ require("Storage").write("ruuviwatch.info",{ }, {timeout : 2000, filters : [{ manufacturerData:{0x0499:{}} }] }); } + g.clear(); g.drawImage(require("Storage").read("ruuviwatch.img"), g.getWidth()/2-24, g.getHeight()/2-24); var drawInterval = setInterval(redraw, 1000); diff --git a/apps/ruuviwatch/ruuviwatch.png b/apps/ruuviwatch/ruuviwatch.png index 3a5d0954952c77bbe18348240ff7313dcc1e8915..3737a7e8cb955bc7747861ed1eba36682f99885e 100644 GIT binary patch delta 590 zcmV-U0TLBDAveCk^&%HVS#^jDn$zM7sUQo?^paMm!hfAnRwqvYoz)hXvrrKB zy8qqh!{AQU(BL!K^}olUtd8IpvBr#SnTcE`HKw6(37GP~!wgi6^8@Ck#vRTD6};O< z8-cCHb!J_)8u<732J|*fszeDo_?6IJfj_8w(1#qoe`-sWh(O^s6Di%n*D_s2iir8e z$y2z^KuqQb3V($A{@!E10-eMnH1Uy`D5a%sAiKP@$H$r&-y(9-8fj4bIHjA_h&a^a z8?r?j4P?O&+ag3KwTUV3n4%x=`%K^zLQ8GTXix_kUlSFg#cc;8*%8hwgfU1D{uJv9ct&i1iuJLB@Up2FPY$LOrU0hs5~|bmrs)46)}C_ znz7k4^VFDu9phYls61%!TW^+sWCLyw8t|=9Ar1}xS>}xCe^p5o{Fj!?VJRR910 delta 617 zcmV-v0+#)m1+)c_R)0xJL_t(|0qvOWZR0QuhM5gAf;Kphpb@-*Z-Zuoc!PKYcZ1#r zz72dgfxAJv!CMJd(7+`n%6311>H&!Si1?DCJ}sg`p-?FNWDc|g0FLgba#lP0<;(=T z@f_^Gvp4rj?S4r63kT} zBMA)79-LK}*TmA_hX2Pzrw#2*2!4$uZZq|KF&-nGsA(@k)i}o7#2IZ966QG3Rv^#! zj&{W9wL+Zr>q1E0Pov)oU%RNRAFUpd`R#SVPt*L7a88Yoe5Ld^khy?aXmWFvgYp@ZGnrZ)( z8?>brK;9acbO{}9cRERpM|E%GL3`+#6ncZohY`1=1oND?h+h*}6xvqhgZINekOFK( zq5rgS8Ks6NMn8EHLO9aumStOSMU;M=Q zh;?tH;;xj#F0a#`kc{ee+Sxz%Lj6L8LZMJ7{B&Lc$OOor(K9+P00000NkvXXu0mjf Dtw1bu From 33a10e53932fa730c0493a93d6e7c7f08511ed99 Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Thu, 6 Jan 2022 22:58:12 +0100 Subject: [PATCH 46/59] ptlaunch: Improve documentation --- apps/ptlaunch/README.md | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/apps/ptlaunch/README.md b/apps/ptlaunch/README.md index cf75315a9..12c205980 100644 --- a/apps/ptlaunch/README.md +++ b/apps/ptlaunch/README.md @@ -2,11 +2,19 @@ Directly launch apps from the clock screen with custom patterns. -## Usage +## Installation and Usage + +Install Pattern Launcher alongside your main laucher app. +_Do not delete that launcher!_ +Pattern Launcher is designed as an additional app launching utility, not as a replacement for the main launcher. + +In the main launcher, start Pattern Launcher in the app menu to assign the pattern configuration (see below). +Note that this actually among the applications, _not_ in the application settings! Create patterns and link them to apps in the Pattern Launcher app. Then launch the linked apps directly from the clock screen by simply drawing the desired pattern. +Note that this does only work in the clock screen, not if other applications run. ## Add Pattern Screenshots @@ -28,7 +36,8 @@ Then launch the linked apps directly from the clock screen by simply drawing the ## Detailed Steps -From the main menu you can: +The main menu of Pattern Launcher is accessible from the _application_ starter of the main launcher. +From there you can: - Add a new pattern and link it to an app (first entry) - To create a new pattern first select "Add Pattern" @@ -60,6 +69,16 @@ Make sure the watch is unlocked before you start drawing. If this bothers you, y Please note that drawing on the clock screen will not visually show the pattern you drew. It will start the app as soon as the pattern was recognized - this might take 1 or 2 seconds! If still nothing happens, that might be a bug, sorry! +4. Where can I configure the patterns? + +You have to start the "Pattern Launcher" app from the main app launcher's app selection. + +5. Do I have to delete my former app launcher so that Pattern Launcher is the only installed launcher? + +No! Pattern Launcher works alongside another "main" launcher. +If you have deleted that one, you do not have a general purpose app launcher any more and cannot access Pattern Launcher's configuration. +If you already have deleted your main launcher accidentially, just reinstall it from the app loader. + ## Authors Initial creation: [crazysaem](https://github.com/crazysaem) @@ -67,3 +86,5 @@ Initial creation: [crazysaem](https://github.com/crazysaem) Improve pattern detection code readability: [PaddeK](http://forum.espruino.com/profiles/117930/) Improve pattern rendering: [HughB](http://forum.espruino.com/profiles/167235/) + +Doc additions: [dirkhillbrecht](http://forum.espruino.com/profiles/182498/) From 673865b31460864fc4c7d35a603e58a033e02786 Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Thu, 6 Jan 2022 17:23:48 -0800 Subject: [PATCH 47/59] Update app.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove unnecessary keywords. Remove autolight, since the system once again provides this service. Add optional autorotate while charging. Distinguish ‘slow’ second hand from regular second hand, visually. Tweak fonts. --- apps/pooqround/app.js | 195 ++++++++++++++++++++++++------------------ 1 file changed, 111 insertions(+), 84 deletions(-) diff --git a/apps/pooqround/app.js b/apps/pooqround/app.js index 22cf5ff79..b0c7592f2 100644 --- a/apps/pooqround/app.js +++ b/apps/pooqround/app.js @@ -25,8 +25,8 @@ // // This only works for Bangle 2. -const isString = x => typeof x === 'string'; -const imageWidth = i => isString(i) ? i.charCodeAt(0) : i.width; +const isString = x => typeof x === 'string', + imageWidth = i => isString(i) ? i.charCodeAt(0) : i.width; ////////////////////////////////////////////////////////////////////////////// /* System integration */ @@ -115,9 +115,9 @@ class RoundOptions extends Options { onchange: x => this.calendric = x, format: x => ['none', 'day', 'date', 'both', 'month', 'full'][x], }, - 'Auto-Illum.': { - init: _ => this.autolight, - onchange: x => this.autolight = x + 'Autorotate': { + init: _ => this.autorotate, + onchange: x => this.autorotate = x }, Defaults: _ => {this.reset(); this.interact();} }); @@ -133,7 +133,7 @@ RoundOptions.defaults = { calendric: 5, dayFg: '#fff', nightFg: '#000', - autolight: true, + autorotate: true, }; ////////////////////////////////////////////////////////////////////////////// @@ -144,29 +144,29 @@ const dec = x => E.toString(heatshrink.decompress(atob(x))); const y10F = [ dec( 'g///EAh////AA4IIBgPwgE+gAOBg/AngXB+EPAYM8gfggEfgF8D4OAj4dB8EDAYI' + - 'fBBAISBAAMOAYUB4AECnEAkAuBgEQBAPgIYX8IYX/wYDCEwIiMMgUYgECCIZlBAY' + - 'N4CoRUBIoMP8AZBge8CgMB8+BCAPw+F/gf8jxDB/0D4BGBEQMPAYIeBoAfBnEwge' + - 'Ah0cB4MDx4PBgHn4EB8E7LQM8h/eJ4MDBgIpB+H+g/wnE/WwMMO4P8LwM/XAJLBT' + - 'gY7BAAN/wC9CQwV+jwDB/4pBgP/EQKYBBIIxBPQP+SATfCIYIiCO4I9BBwM//hlB' + - 'PQJlCwYGBTAPgIgM4CYM8hwKBMoODegPA8F+gZlBewP4hz/BE4QrBGgM/LAV//4+' + - 'BAYJyBPwM/KQMeGQMPFwM8H4UHBIPwGQNwn4yBnhxBGQJxBGQK5BGQKWDOwUACAM' + - 'D/BDCNYPg///8E5HwR2BIwMDSgK0FSocMAYTLBAAYpBQAPnDwJGBEwK+B/hlB+F8' + - 'TARABTAJABTAPBMoR+BMoKXBDoX5DwIuBMoUPS4THCGwJbBhAaBvh5B+EHwPAOwP' + - 'guA1BvCcB4E8nxlBn1/VoIyBwDKBO4SGCgA=' + 'fBBAISBAAMOAYUB4AECnEAkAuBgEQBAPgIYX8IYX/wYDCEwIiMMgUcgECCIZlBAY' + + 'N4CoRUBIoMP8AZBge8MoMB8+B8B4B+E/gf4jw/B/kD4ADBEQMPSYXgoAfBnEwgeA' + + 'hw7BvEDx4PBgHn4EB8E7LQM8h/eJ4MDBgIpB+H+g/wnE/WwMMG4ReBn4zBJYKcDH' + + '4IABv+AXoSGCv0eAYP/FIMB/4iBTAIJBGIJ6B/yQCb4RDBEQTlBHoIOBn51BwC+B' + + 'MoWDAwKYBRgKYBCYM8hwKBMoODegPA8F+gZlBewP4hz/BE4QrBGgM/LAV//4+BAY' + + 'JyBPwM/KQMeGQMPFwM8H4UHBIPwGQNwZgPwnhxBGQJxBGQK5BGQKWDOwUACALlBI' + + 'YRrB8H///gnI+COwJGBgaUBWgqVDhgDCZYIADFIKAB84eBIwImBXwP8MoPwviYCI' + + 'AKYBIAKYB4JlCPwJlBS4IdC/IeBFwJlCh6XCY4Q2BLYMIDQN8PIPwg+B4B2B8FwG' + + 'oN4TgPAnk+MoM+v6tBGQOAZQJ3CQwUAA' ), 48, dec('hgAI'), 34 ];const y1F = [ dec( - 'g//AAPggE/AoX8gF/AoX+gF8CoU+gHwAoUPgAZBEIQFGCIodFFIo1FIIoADnAFEj' + - 'gFEh0AhA1EiAFCgeAFIf/4A1DFQIED/5MDGB6OEjAECHIIYDhkAuAFCjwFEj6DEn' + - '+AAod74AFD/PgvAtC+Hwv/wgZSBvEfLwc8RISOBGAJsBVAXgggEBE4PgIgJLC8E8' + - 'I4fgXQS/B8IhBGwOA8YFCgfA9+eAoMB4H/j/ACIPA/kPCQJCB/DMDMoMBboYVBKo' + - 'IDBSYeAAoYlCAATpEg/4Xwc/QIcPFoJcBQIP8GILXCDYLXBbId//BeCL4QwDgIwD' + - 'AAIXBDAQfCEYSPBAoaPCPQKPCAoZgBAoYvBAoIXBBAIFB/ALDEoJHBAoaPDaQSPB' + - 'AoKcBJgY9DTQX/EoKmCC4SyCYYJJB+CHBj+Aj8ASYJNBBINwIIOAM4ILDAYN/wAB' + - 'BB4JBBI45vCRYgADApEHL4pHB8AECFIPhAYLCCAggFBAgaNCYwgFEbAkAwAFEc4S' + - 'PCj/+LIKPBv6PEAoRnBFIMDFYLXCKoTLDa4YRDBYIdDh4FDMoQ1DK4ZBBMQIDBJY' + - 'bWBFIMEIIQpBgxxBgZRBh8AAYN8AoQVBjgbBAoTZBvwRCvEBF4IdB+E/OIp9CJgZ' + - 'BCQQUAA=' + 'g//AAPggE/AoX8gF/AoX+gF8CoU+gHwAoUPgAZBEIQFGCIodFFIo1FIIoADnEAgQ' + + 'FCjkAgwFCh0Ahg1EBoIABgeAFIf/4A1DFQIED/5MDGAYADEQYwDRwgMDhAYEH4Nw' + + 'AoUeAok/QYl/wAFD/fAHgUD+PgvAFBj/g+E/4EBLAN4j5SCgE8h4EB/AwCAoOAVA' + + 'PgggeBFoPgQgRLB8E8I4fgXQS/B8KwBMgOA8YFCgfA9+eAoMB4H/j/ACIPA/kPCQ' + + 'JIB/DMDMoJSBboQVBKoIDBSYZOBAAQlCAATpEg/4Xwc/QIZyBwBcBgf//gxBa4Qb' + + 'Ba4LZDv/4LwRfCGAcBGAYABC4IYCD4QjCR4IFDR4R6BR4QFDMAIFDF4IFBC4IIBA' + + 'oLEBBYQlBI4IFDR4ZrBR4QFBTgJMDHoaaCdQSmCC4SyCYYJJB+CHBj+Aj8ASYJNB' + + 'BINwIIOAM4ILDAYN/wABBB4JBBI45vCRYgADApEHL4pHB8AECFIPhAYLCCAggFBA' + + 'gaNCYwgFEbAkAwAFEc4SPCj/+LIKPBv6PEAoRnBFIMDFYLXCKoTLDa4YRDBYIdDh' + + '4FDMoQ1DK4ZBBMQIDBJYbWBFIMEIIQpBgxxBgZRBh8AAYN8AoQVBjgbBAoTZBvwR' + + 'CvEBF4IdB+E/OIp9CJgZBCQQUAA=' ), 48, dec('hgAI'), 48 ];const y10sF = [ dec( @@ -194,20 +194,20 @@ const y10F = [ ];const d1F = [ dec( 'AB1/+AECj///4FCAgP/8EAgf/4F//EAg4CBgf8gEPwAUBn0AhwaCAYMeAoUPgEcA' + - 'oUHAowRFDoopFGopBFJopZGBgIKCABlAIIcA4AFDgIFEgZBCAoMHAohVBAoY6CHg' + - 'U/Aol/AogADGoQFUABEMAQM/AQN8bIRZBRgJ5BLILhBgP3LIcD84rDg/HWYcPw4F' + - 'Dj4PBAoU+Aol8Aon4PocB+CJDgfgAoXgh/ATYX4v+AU4X//w/DbYQFCCwJ3PvDIE' + - 'NYQCCdoJ6CgfAiCGCI4NwgEeFwISCLoMeJwJdCnkfHYd4v4FD+f5AoUB9/BAoUD/' + - '4jCh8HG4IpCh5DBAIMeE4Q/BvjMCfoP8Z4Uf//wCgInB/5lCABs+AoicBAAUDAok' + - 'P9wFDv+OCAjUCHQP4AoY5BAoUHEIIFCv5JBAoLQBLQYqEApQpDArIAJv5IBnBTCV' + - '4McJAQFBcYLvBB4IkBd4N4cYQBBeoLdBCYIFDngFECoIFDOwIdCc4QpCFwIZCjwu' + - 'BEoU8FwIxCvAIBEIPB+AUBJIP/8AmBLYWAd4RnBdx4XCcYf/Dgn//AuEP4LjBXoJ' + - 'AC//vQYT0BBIKDC+CZBOIM/wAFDVYIFCgIrBAoUDPoIdCO4QnBaQYnBGoQVBIIZI' + - 'CJoTNCLIY4CAYIaDAAKRCAASRDAAIaEYAQtDYAI5DRgZFCAAYuCQoQuBAgIFBvEH' + - 'AgIFB+CgBAAMB86lE76EBFwX/GocPNoYmBIwk/HQl8LpIAQRId/SoYDB4ZJCUoPn' + - 'VoUHwP3Y4YYBY4k+Y4h5BdILhBd4YFFCIodFFIo1FIIpNFLIplGAArMFn6oBHYMA' + - 'DYQFBgP5E4IFBgfgUgIFCwBZBEAL1BPYZbDA4Z7DLYRtCBYYlDBoIxCEYMBHoIvC' + - 'HAI7Dh5PBI4X/LIX//7+Dn52Eh4QCA==' + 'oUHAowRFDoopFGopBFJopZGBgIKCAB5BBgA1CAoMBAokDCIgTCAYRTDAoI6CHgU/' + + 'Aol/Aog1GAqgAIhgCBn4CBvjZCLIKMBPIJZBcIMB+4lBMoMD84rDg/HL4cPw4FDj' + + '5rEnwFEvgFE/AFBaYMB+CJCwED8AFC8EP4CbC/F/wCnC//+H4bbCAoQWBO594EAI' + + 'TBgBrCAQTtBPQUD4EQQwRHBuEAjwuBCQRdBjxOBLoU8j47DvF/Aofz/IFCgPv4IF' + + 'Cgf/EYUPg43BFIUPIYIBBjwnCH4N8ZgT9B/jPCj//+AUBE4P/MoQANnwFETgIACg' + + 'YFEh/uAod/xwQEagQ6B/AFDHIIFCg4hBAoV/JIIFBaAJaDFQgFKFIYFZABN/JAM4' + + 'KYSvBjhICAoLjBd4IPBEgLvBvDjCAIL1BboITBAoc8AogVBAoZ2BDoTnCFIQuBDI' + + 'UeFwIlCnguBGIV4BAIhB4PwCgJJB//gEwJbCwDvCM4LuPC4TjD/4cE//4Fwh/BcY' + + 'K9BIAX/96DCegIJBQYXwTIJxBn+AAoarBAoUBFYIFCgZ9BDoR3CE4LSDE4I1CCoJ' + + 'BDJARNCZoRZDHAQDBDQYABSIQACSIYABDQjACFobABHIaMDIoQADFwSFCFwIEBAo' + + 'N4g4EBAoPwUAIABgPnUonfQgIuC/41Dh5tDEwJGEn46EvhdJACCJDv6VDAYPDJIS' + + 'lB86tCg+B+7HDDALHEnzHEPILpBcILvDAooRFDoopFGopBFJopZFMowAFZgs/VAI' + + '7BgAbCAoMB/InBAoMD8CkBAoWALIIgBeoJ7DLYYHDPYZbCNoQLDEoYNBGIQjBgI9' + + 'BF4Q4BHYcPJ4JHC/5ZC///fwc/OwkPCAQA==' ), 48, dec('ikPigAGA'), 48 ];const dowF = [ dec( @@ -220,10 +220,10 @@ const y10F = [ 'kDMIgeBFIQEBBYRTBCAZ3FAggAMg4zEj7LEn7LEv++AodzxwFD+ePAofjw4FVDoo' + 'pFv+eIImcJomYLImAAoZeEAtTyBAAQFEVYIFDSQIvhAojaCFwgABh4YEngFEuAqJ' + 'gPAAocDApYuEgP/fgl/+B9HAAv+Aon8HQMOIAkeAokcAohaDAoM4Aol4AohmDAoJ' + - 'BDAoJsDAo7vhABbJDAo9/AojEFMYbKMArCBDFI41FWIYABggFEgbuCDYMPLIQbBj' + - '//wBdCn0H4DZCvEBb4YZBdYZBBAofgCIQFDDoIFFDoPggYFBF4IFBGoI7B+AFCE4' + - 'NwCIIlCuAdBIYU4gPwn5VBjC7B/y0Dv/4YwcPCwMAjJlCAAM584FDufDCAUA8eBA' + - 'p/zC4n5EYj1BAoc//4RDU4IFDA==' + 'BDAoJsDAo7vhABZuBQYoFDv4FEYgpjDZRgFYGYYpHGoqxDAAMEAokDdwQbBh//DY' + + 'cf/+ALoU+g/AbIV4gLfDDILrDIIIFD8ARCAoYdBAoodB8EDAoIvBAoI1BHYPwAoQ' + + 'nBuARBEoVwDoJDCnEB+E/KoMYXYP+Wgd//DGDh4WBgEZMoQABnPnAodz4YQCgHjw' + + 'IFP+YXE/IjEeoIFDn//CIanBAoY=' ), 48, dec('kElkMljsljw='), 48 ];const mF = [ dec( @@ -322,21 +322,20 @@ class Round { this.r = this.xc - this.minR; } - reset(clear) {this.state = {}; clear && this.g.clear(true);} + reset(clear) {this.state = {}; clear == null || this.g.clear(true).setRotation(clear);} doIcons(which) { this.state[which] = null; - this.render(new Date()); // Not quite right, I think. } enhanceUntil(t) {this.enhance = t;} pie(f, a0, a1, invert) { if (!invert) return this.pie(f, a1, a0 + 1, true); - let t0 = Math.tan(a0 * 2 * Math.PI), t1 = Math.tan(a1 * 2 * Math.PI); + const t0 = Math.tan(a0 * 2 * Math.PI), t1 = Math.tan(a1 * 2 * Math.PI); let i0 = Math.floor(a0 * 4 + 0.5), i1 = Math.floor(a1 * 4 + 0.5); - let x = f.getWidth() / 2, y = f.getHeight() / 2; - let poly = [ + const x = f.getWidth() / 2, y = f.getHeight() / 2; + const poly = [ x + (i1 & 2 ? -x : x) * (i1 & 1 ? 1 : t1), y + (i1 & 2 ? y : -y) / (i1 & 1 ? t1 : 1), x, @@ -348,16 +347,17 @@ class Round { for (i0++; i0 <= i1; i0++) poly.push( 3 * i0 & 2 ? f.getWidth() : 0, i0 & 2 ? f.getHeight() : 0 ); - f.setColor(0).fillPoly(poly); + return f.setColor(0).fillPoly(poly); } hand(t, d, c0, r0, c1, r1) { + const g = this.g; t *= Math.PI / 30; - const r = this.r; - const z = 2 * r0 + 1; - const x = this.xc + r * Math.sin(t), y = this.yc - r * Math.cos(t); - const x0 = x - r0, y0 = y - r0; - d = d ? d[0] : Graphics.createArrayBuffer(z, z, 16, {msb: true}); + const r = this.r, + z = 2 * r0 + 1, + x = this.xc + r * Math.sin(t), y = this.yc - r * Math.cos(t), + x0 = x - r0, y0 = y - r0; + d = d ? d[0] : Graphics.createArrayBuffer(z, z, 4, {msb: true}); for (let i = 0; i < z; i++) for (let j = 0; j < z; j++) { d.setPixel(i, j, g.getPixel(x0 + i, y0 + j)); } @@ -366,24 +366,20 @@ class Round { return [d, x0, y0]; } - render(d) { - const g = this.g; - const b = this.b, bI = this.bI; - const c = this.c, cI = this.cI; - const e = d < this.enhance; - const state = this.state; - const options = this.options; - const cal = options.calendric; - const res = options.resolution; - const dow = (e || cal == 1 || cal > 2) && d.getDay(); - const ts = res < 2 && d.getSeconds(); - const tm = (e || res < 3) && d.getMinutes() + ts / 60; - const th = d.getHours() + d.getMinutes() / 60; - const dd = (e || cal > 1) && d.getDate(); - const dm = (e || cal > 3) && d.getMonth(); - const dy = (e || cal > 4) && d.getFullYear(); - const xc = this.xc, yc = this.yc, r = this.r; - const dlr = xc * 3/4, dlw = 8, dlhw = 4; + render(d, rate) { + const g = this.g, b = this.b, bI = this.bI, c = this.c, cI = this.cI, + e = d < this.enhance, + state = this.state, options = this.options, + cal = options.calendric, res = options.resolution, + dow = (e || cal === 1 || cal > 2) && d.getDay(), + ts = res < 2 && d.getSeconds(), + tm = (e || res < 3) && d.getMinutes() + ts / 60, + th = d.getHours() + d.getMinutes() / 60, + dd = (e || cal > 1) && d.getDate(), + dm = (e || cal > 3) && d.getMonth(), + dy = (e || cal > 4) && d.getFullYear(); + const xc = this.xc, yc = this.yc, r = this.r, + dlr = xc * 3/4, dlw = 8, dlhw = 4; // Restore saveunders for fast-moving, overdrawing indicators. if (state.sd) g.drawImage.apply(g, state.sd); @@ -397,10 +393,10 @@ class Round { state.dow = dow; } - const locked = Bangle.isLocked(); - const charging = Bangle.isCharging(); - const battery = E.getBattery(); - const HRMOn = Bangle.isHRMOn(); + const locked = Bangle.isLocked(), + charging = Bangle.isCharging(), + battery = E.getBattery(), + HRMOn = Bangle.isHRMOn(); if (dy !== state.dy || locked !== state.locked || charging !== state.charging || @@ -463,6 +459,7 @@ class Round { this.hand(tm, state.md, g.theme.bg, this.minR, g.theme.fg, this.minR - 1) : null; state.sd = ts === +ts ? + rate > 1000 ? this.hand(ts, state.sd, g.theme.fg2, this.secR, g.theme.bg, 2) : this.hand(ts, state.sd, g.theme.fg2, this.secR) : null; } @@ -482,7 +479,18 @@ class Clock { this.listeners = { lcdPower: on => on ? this.active() : this.inactive(), - charging: () => {face.doIcons('charging'); this.active();}, + charging: on => { + face.doIcons('charging'); + if (on) { + this.listeners.accel = + a => this.orientation(a) === this.attitude || this.active(); + Bangle.on('accel', this.listeners.accel); + } else { + Bangle.removeListener('accel', this.listeners.accel); + delete this.listeners.accel; + } + this.active(); + }, lock: () => {face.doIcons('locked'); this.active();}, faceUp: up => { this.conservative = !up; @@ -498,20 +506,23 @@ class Clock { if (e.y - this.e0.y < -50) { this.options.resolution > 0 && this.options.resolution--; this.rates.clock = this.timescales[this.options.resolution]; + this.ack(); this.active(); } else if (e.y - this.e0.y > 50) { this.options.resolution < this.timescales.length - 1 && this.options.resolution++; this.rates.clock = this.timescales[this.options.resolution]; + this.ack(); this.active(); } else if (this.yX - this.yN < 20) { const now = new Date(); if (now - this.t0 < 250) { + this.ack(); face.enhanceUntil(now + 30000); - face.render(now); + this.active(); } else if (now - this.t0 > 500) { this.stop(); - this.options.interact(); + this.ack().then(_ => this.options.interact()); } } this.t0 = null; @@ -524,9 +535,25 @@ class Clock { }; } + ack() { + return Bangle.buzz(33); + } + + orientation(a) { + return Math.abs(a.z) < 0.85 ? + Math.abs(a.y) > Math.abs(a.x) ? a.y < 0 ? 0 : 2 : a.x > 0 ? 1 : 3 : + 0; + } + + rotation() { + return this.options.autorotate && Bangle.isCharging() ? + this.orientation(Bangle.getAccel()) : + 0; + } + redraw(rate) { const now = this.updated = new Date(); - if (this.refresh) this.face.reset(true); + if (this.refresh) this.face.reset(this.attitude = this.rotation()); this.refresh = false; rate = this.face.render(now, rate); if (rate !== this.rates.face) { @@ -541,13 +568,13 @@ class Clock { this.exception && clearTimeout(this.exception); this.interval && clearInterval(this.interval); this.timeout = this.exception = this.interval = this.rate = null; - this.face.reset(false); // Cancel any ongoing background rendering + this.face.reset(); // Cancel any ongoing background rendering return this; } active() { - const prev = this.rate; - const now = Date.now(); + const prev = this.rate, + now = Date.now(); let rate = Infinity; for (const k in this.rates) { let r = this.rates[k]; From b878ae1f24b7e384851b3ea5a63785748cd87456 Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Thu, 6 Jan 2022 17:25:01 -0800 Subject: [PATCH 48/59] Update ChangeLog --- apps/pooqround/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/pooqround/ChangeLog b/apps/pooqround/ChangeLog index 8eb91cf97..17004449d 100644 --- a/apps/pooqround/ChangeLog +++ b/apps/pooqround/ChangeLog @@ -1,2 +1,3 @@ 0.00: Initial check-in. 0.01: Add tap-to-decorate feature. Bugfixes. +0.02: Add autorotate while charging. Remove autolight. Tweak fonts. From 3068a647d63f0425751305f0da08f03e039d582e Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Thu, 6 Jan 2022 17:28:32 -0800 Subject: [PATCH 49/59] Update README.md --- apps/pooqround/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/pooqround/README.md b/apps/pooqround/README.md index d413fd88e..6f6bafa69 100644 --- a/apps/pooqround/README.md +++ b/apps/pooqround/README.md @@ -20,8 +20,7 @@ you can quickly alter the number of ‘hands’ on the display. When the watch i or down to remove the distraction. There's also a setting that displays the second hand, but only if the watch is perfectly face-to-the-sky, in case you want the ability to check the _exact_ time, hands free, without the impact on battery life this usually entails. -In some versions of the Bangle.js firmware, the backlight doesn't come on automatically when you twist your wrist. There's currently a workaround -for this integrated into the watchface; you can disable it in the menu, if you prefer. +While charging the main display automatically rotates so that noon is up. This can be disabled. ## Limitations From 9811ada68d1c62e55cd8b18d87beea1d7e00639e Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Thu, 6 Jan 2022 17:29:39 -0800 Subject: [PATCH 50/59] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 8b4e86d52..40e92d201 100644 --- a/apps.json +++ b/apps.json @@ -4943,7 +4943,7 @@ { "id": "pooqround", "name": "pooq Round watch face", "shortName":"pooq Round", - "version":"0.01", + "version":"0.02", "description": "A 24 hour analogue watchface with high legibility and a novel style.", "icon": "app.png", "type": "clock", From 99c7dba8f2100d247afabaec694e874a448bb06b Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Thu, 6 Jan 2022 17:43:05 -0800 Subject: [PATCH 51/59] Update ChangeLog --- apps/pooqround/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/pooqround/ChangeLog b/apps/pooqround/ChangeLog index 17004449d..bc35b69df 100644 --- a/apps/pooqround/ChangeLog +++ b/apps/pooqround/ChangeLog @@ -1,3 +1,3 @@ 0.00: Initial check-in. 0.01: Add tap-to-decorate feature. Bugfixes. -0.02: Add autorotate while charging. Remove autolight. Tweak fonts. +0.02: Add autorotate while charging. Remove autolight. Tweak fonts. Add some haptic feedback on touchscreen operations. From 328f2d0e09163b93ba238ddbd8751500b14dc88a Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Thu, 6 Jan 2022 22:40:34 -0800 Subject: [PATCH 52/59] Update app.js Remove internal autolight logic. --- apps/pooqround/app.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/pooqround/app.js b/apps/pooqround/app.js index b0c7592f2..06e208e61 100644 --- a/apps/pooqround/app.js +++ b/apps/pooqround/app.js @@ -496,7 +496,6 @@ class Clock { this.conservative = !up; this.active(); }, - twist: _ => this.options.autolight && Bangle.setLCDPower(true), drag: e => { if (this.t0) { if (e.b) { From 341080e09b3ad310cd2eb9e0f74f117bf121fd01 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 7 Jan 2022 08:53:32 +0000 Subject: [PATCH 53/59] widpedom 0.22: Fix 'stps' regression for 0.21 (fix #1233) --- apps.json | 2 +- apps/widpedom/ChangeLog | 1 + apps/widpedom/widget.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 7fc5145aa..6b81f6a41 100644 --- a/apps.json +++ b/apps.json @@ -1590,7 +1590,7 @@ { "id": "widpedom", "name": "Pedometer widget", - "version": "0.21", + "version": "0.22", "description": "Daily pedometer widget", "icon": "widget.png", "type": "widget", diff --git a/apps/widpedom/ChangeLog b/apps/widpedom/ChangeLog index 3483c3390..54f6b203b 100644 --- a/apps/widpedom/ChangeLog +++ b/apps/widpedom/ChangeLog @@ -21,3 +21,4 @@ Memory usage enhancements 0.20: Fix issue where step count would randomly reset 0.21: Memory usage improvements, fix widget initial width (fix #1170) +0.22: Fix 'stps' regression for 0.21 (fix #1233) diff --git a/apps/widpedom/widget.js b/apps/widpedom/widget.js index 3a079c066..cc7fdb579 100644 --- a/apps/widpedom/widget.js +++ b/apps/widpedom/widget.js @@ -55,6 +55,7 @@ // add your widget WIDGETS["wpedom"]={area:"tl",width:0, getWidth:function() { + let stps = stp_today.toString(); let newWidth = 24; if (settings.hide) newWidth = 0; @@ -68,7 +69,6 @@ return newWidth; }, redraw:function() { // work out the width, and queue a full redraw if needed - let stps = stp_today.toString(); let newWidth = this.getWidth(); if (newWidth!=this.width) { // width has changed, re-layout all widgets From 95c3b70af4c8d0873b5ec61636136738ca508477 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 19:06:07 +0100 Subject: [PATCH 54/59] Log confidence alongside heartrate instead of discarding confidence 0 samples --- apps/recorder/widget.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index 34a6ca488..8f82f1f37 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -53,33 +53,29 @@ }, hrm:function() { var bpm = 0, bpmConfidence = 0; - var hasBPM = false; function onHRM(h) { if (h.confidence >= bpmConfidence) { bpmConfidence = h.confidence; bpm = h.bpm; - if (bpmConfidence) hasBPM = true; } } return { name : "HR", - fields : ["Heartrate"], + fields : ["Heartrate", "Confidence"], getValues : () => { - var r = [bpmConfidence?bpm:""]; + var r = [bpm,bpmConfidence]; bpm = 0; bpmConfidence = 0; return r; }, start : () => { - hasBPM = false; Bangle.on('HRM', onHRM); Bangle.setHRMPower(1,"recorder"); }, stop : () => { - hasBPM = false; Bangle.removeListener('HRM', onHRM); Bangle.setHRMPower(0,"recorder"); }, - draw : (x,y) => g.setColor(hasBPM?"#f00":"#f88").drawImage(atob("DAwBAAAAMMeef+f+f+P8H4DwBgAA"),x,y) + draw : (x,y) => g.setColor(Bangle.isHRMOn()?"#f00":"#f88").drawImage(atob("DAwBAAAAMMeef+f+f+P8H4DwBgAA"),x,y) }; }, bat:function() { From 089f0cd4386c24a9d05fd9bd258ed436fd375253 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:39:39 +0100 Subject: [PATCH 55/59] Emit additional BTHRM event and allow overwriting HRM optionally --- apps.json | 3 +- apps/bthrm/boot.js | 65 ++++++++++++++++++++++++++++++++---------- apps/bthrm/settings.js | 33 +++++++++++++++++++++ 3 files changed, 85 insertions(+), 16 deletions(-) create mode 100644 apps/bthrm/settings.js diff --git a/apps.json b/apps.json index 95c7b4bbc..6aa109142 100644 --- a/apps.json +++ b/apps.json @@ -1049,7 +1049,8 @@ "readme": "README.md", "storage": [ {"name":"bthrm.boot.js","url":"boot.js"}, - {"name":"bthrm.img","url":"app-icon.js","evaluate":true} + {"name":"bthrm.img","url":"app-icon.js","evaluate":true}, + {"name":"bthrm.settings.js","url":"settings.js"} ] }, { diff --git a/apps/bthrm/boot.js b/apps/bthrm/boot.js index 88e574480..0aa8d5c96 100644 --- a/apps/bthrm/boot.js +++ b/apps/bthrm/boot.js @@ -2,24 +2,43 @@ var log = function() {};//print var gatt; var status; - - Bangle.isHRMOn = function() { + + var origIsHRMOn = Bangle.isHRMOn; + + Bangle.isBTHRMOn = function(){ return (status=="searching" || status=="connecting") || (gatt!==undefined); } - Bangle.setHRMPower = function(isOn, app) { + + Bangle.isHRMOn = function() { + var settings = require('Storage').readJSON("bthrm.json", true) || {}; + + print(settings); + if (settings.enabled && !settings.replace){ + return origIsHRMOn(); + } else if (settings.enabled && settings.replace){ + return Bangle.isBTHRMOn(); + } + return origIsHRMOn() || Bangle.isBTHRMOn(); + } + + Bangle.setBTHRMPower = function(isOn, app) { + + + var settings = require('Storage').readJSON("bthrm.json", true) || {}; + // Do app power handling if (!app) app="?"; - log("setHRMPower ->", isOn, app); + log("setBTHRMPower ->", isOn, app); if (Bangle._PWR===undefined) Bangle._PWR={}; - if (Bangle._PWR.HRM===undefined) Bangle._PWR.HRM=[]; - if (isOn && !Bangle._PWR.HRM.includes(app)) Bangle._PWR.HRM.push(app); - if (!isOn && Bangle._PWR.HRM.includes(app)) Bangle._PWR.HRM = Bangle._PWR.HRM.filter(a=>a!=app); - isOn = Bangle._PWR.HRM.length; + if (Bangle._PWR.BTHRM===undefined) Bangle._PWR.BTHRM=[]; + if (isOn && !Bangle._PWR.BTHRM.includes(app)) Bangle._PWR.BTHRM.push(app); + if (!isOn && Bangle._PWR.BTHRM.includes(app)) Bangle._PWR.BTHRM = Bangle._PWR.BTHRM.filter(a=>a!=app); + isOn = Bangle._PWR.BTHRM.length; // so now we know if we're really on if (isOn) { - log("setHRMPower on", app); - if (!Bangle.isHRMOn()) { - log("HRM not already on"); + log("setBTHRMPower on", app); + if (!Bangle.isBTHRMOn()) { + log("BTHRM not already on"); status = "searching"; NRF.requestDevice({ filters: [{ services: ['180D'] }] }).then(function(device) { log("Found device "+device.id); @@ -49,7 +68,11 @@ if (flags&16) { var interval = dv.getUint16(idx,1); // in milliseconds }*/ - Bangle.emit('HRM',{ + + + var eventName = settings.replace ? "HRM" : "BTHRM"; + + Bangle.emit(eventName, { bpm:bpm, confidence:100 }); @@ -65,15 +88,27 @@ }); } } else { // not on - log("setHRMPower off", app); + log("setBTHRMPower off", app); if (gatt) { - log("HRM connected - disconnecting"); + log("BTHRM connected - disconnecting"); status = undefined; try {gatt.disconnect();}catch(e) { - log("HRM disconnect error", e); + log("BTHRM disconnect error", e); } gatt = undefined; } } }; + + var origSetHRMPower = Bangle.setHRMPower; + + Bangle.setHRMPower = function(isOn, app) { + var settings = require('Storage').readJSON("bthrm.json", true) || {}; + if (settings.enabled || !isOn){ + Bangle.setBTHRMPower(isOn, app); + } + if (settings.enabled && !settings.replace || !isOn){ + origSetHRMPower(isOn, app); + } + } })(); diff --git a/apps/bthrm/settings.js b/apps/bthrm/settings.js new file mode 100644 index 000000000..8cb00614e --- /dev/null +++ b/apps/bthrm/settings.js @@ -0,0 +1,33 @@ +(function(back) { + var FILE = "bthrm.json"; + + var settings = Object.assign({ + enabled: true, + replace: true, + }, require('Storage').readJSON(FILE, true) || {}); + + function writeSettings() { + require('Storage').writeJSON(FILE, settings); + } + + E.showMenu({ + '': { 'title': 'Bluetooth HRM' }, + '< Back': back, + 'Use BT HRM': { + value: !!settings.enabled, + format: v => settings.enabled ? "On" : "Off", + onchange: v => { + settings.enabled = v; + writeSettings(); + } + }, + 'Use HRM event': { + value: !!settings.replace, + format: v => settings.replace ? "On" : "Off", + onchange: v => { + settings.replace = v; + writeSettings(); + } + } + }); +}) From 55c7ed5dd8b7273baae42606e66b926126592ebd Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:41:26 +0100 Subject: [PATCH 56/59] Adds app to check status of BT/HRM --- apps.json | 3 ++- apps/bthrm/bthrm.js | 61 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 apps/bthrm/bthrm.js diff --git a/apps.json b/apps.json index 6aa109142..c3001a31d 100644 --- a/apps.json +++ b/apps.json @@ -1043,11 +1043,12 @@ "version": "0.01", "description": "Overrides Bangle.js's build in heart rate monitor with an external Bluetooth one.", "icon": "app.png", - "type": "boot", + "type": "app", "tags": "health,bluetooth", "supports": ["BANGLEJS","BANGLEJS2"], "readme": "README.md", "storage": [ + {"name":"bthrm.app.js","url":"bthrm.js"}, {"name":"bthrm.boot.js","url":"boot.js"}, {"name":"bthrm.img","url":"app-icon.js","evaluate":true}, {"name":"bthrm.settings.js","url":"settings.js"} diff --git a/apps/bthrm/bthrm.js b/apps/bthrm/bthrm.js new file mode 100644 index 000000000..7c80c735f --- /dev/null +++ b/apps/bthrm/bthrm.js @@ -0,0 +1,61 @@ +var btm = g.getHeight()-1; +var eventInt = null; +var eventBt = null; +var counterInt = 0; +var counterBt = 0; + + +function draw(y, event, type, counter) { + var px = g.getWidth()/2; + g.reset(); + g.setFontAlign(0,0); + g.clearRect(0,y,g.getWidth(),y+80); + if (type == null || event == null || counter == 0) return; + var str = event.bpm + ""; + g.setFontVector(40).drawString(str,px,y+20); + str = "Confidence: " + event.confidence; + g.setFontVector(12).drawString(str,px,y+50); + str = "Event: " + type; + g.setFontVector(12).drawString(str,px,y+60); +} + +function onBtHrm(e) { + print("Event for BT " + JSON.stringify(e)); + counterBt += 5; + eventBt = e; +} + +function onHrm(e) { + print("Event for Int " + JSON.stringify(e)); + counterInt += 5; + eventInt = e; +} + +Bangle.on('BTHRM', onBtHrm); +Bangle.on('HRM', onHrm); + +Bangle.setHRMPower(1,'bthrm') +Bangle.setBTHRMPower(1,'bthrm') + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +g.reset().setFont("6x8",2).setFontAlign(0,0); +g.drawString("Please wait...",g.getWidth()/2,g.getHeight()/2 - 16); + +function drawInt(){ + counterInt--; + if (counterInt < 0) counterInt = 0; + if (counterInt > 5) counterInt = 5; + draw(24, eventInt, "HRM", counterInt); +} +function drawBt(){ + counterBt--; + if (counterBt < 0) counterBt = 0; + if (counterBt > 5) counterBt = 5; + draw(100, eventBt, "BTHRM", counterBt); +} + +var interval = setInterval(drawInt, 1000); +var interval = setInterval(drawBt, 1000); From 3baf11613b242807dcdd9060eab60b1e9ddf4645 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:42:29 +0100 Subject: [PATCH 57/59] Adds recorder app plugin to record the BTHRM event --- apps.json | 1 + apps/bthrm/recorder.js | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 apps/bthrm/recorder.js diff --git a/apps.json b/apps.json index c3001a31d..7c9cbffdd 100644 --- a/apps.json +++ b/apps.json @@ -1049,6 +1049,7 @@ "readme": "README.md", "storage": [ {"name":"bthrm.app.js","url":"bthrm.js"}, + {"name":"bthrm.recorder.js","url":"recorder.js"}, {"name":"bthrm.boot.js","url":"boot.js"}, {"name":"bthrm.img","url":"app-icon.js","evaluate":true}, {"name":"bthrm.settings.js","url":"settings.js"} diff --git a/apps/bthrm/recorder.js b/apps/bthrm/recorder.js new file mode 100644 index 000000000..40f64a676 --- /dev/null +++ b/apps/bthrm/recorder.js @@ -0,0 +1,27 @@ +(function(recorders) { + recorders.bthrm = function() { + var bpm = 0; + function onHRM(h) { + bpm = h.bpm; + } + return { + name : "BTHR", + fields : ["BT Heartrate"], + getValues : () => { + result = [bpm]; + bpm = 0; + return result; + }, + start : () => { + Bangle.on('BTHRM', onHRM); + Bangle.setBTHRMPower(1,"recorder"); + }, + stop : () => { + Bangle.removeListener('BTHRM', onHRM); + Bangle.setBTHRMPower(0,"recorder"); + }, + draw : (x,y) => g.setColor(Bangle.isBTHRMOn()?"#00f":"#88f").drawImage(atob("DAwBAAAAMMeef+f+f+P8H4DwBgAA"),x,y) + }; + } +}) + From 47cc9434a30c299eb49820ee95a76e258a021592 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:32:25 +0100 Subject: [PATCH 58/59] Bump version and changelog --- apps.json | 2 +- apps/recorder/ChangeLog | 4 ++++ apps/recorder/README.md | 5 +++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 958bf71e9..95c7b4bbc 100644 --- a/apps.json +++ b/apps.json @@ -768,7 +768,7 @@ "id": "recorder", "name": "Recorder (BETA)", "shortName": "Recorder", - "version": "0.05", + "version": "0.06", "description": "Record GPS position, heart rate and more in the background, then download to your PC.", "icon": "app.png", "tags": "tool,outdoors,gps,widget", diff --git a/apps/recorder/ChangeLog b/apps/recorder/ChangeLog index bedc63141..dbf086f7d 100644 --- a/apps/recorder/ChangeLog +++ b/apps/recorder/ChangeLog @@ -4,3 +4,7 @@ 0.03: Fix theme and maps/graphing if no GPS 0.04: Multiple bugfixes 0.05: Add recording for coresensor +0.06: Add recording for battery stats + Fix execution of other recorders (*.recorder.js) + Modified icons and colors for better visibility + Only show plotting speed if Latitude is available diff --git a/apps/recorder/README.md b/apps/recorder/README.md index 4a4561f1c..87be34424 100644 --- a/apps/recorder/README.md +++ b/apps/recorder/README.md @@ -16,7 +16,8 @@ You can record * **Time** The current time * **GPS** GPS Latitude, Longitude and Altitude * **Steps** Steps counted by the step counter -* **HR** Heart rate +* **HR** Heart rate and confidence +* **BAT** Battery percentage and voltage * **Core** CoreTemp body temperature **Note:** It is possible for other apps to record information using this app @@ -25,4 +26,4 @@ function in `widget.js` for more information. ## Tips -When recording GPS, it usually takes several minutes for the watch to get a [GPS fix](https://en.wikipedia.org/wiki/Time_to_first_fix). There is a grey satellite symbol, which you will see turn red when you get an actual GPS Fix. You can [upload assistant files](https://banglejs.com/apps/#assisted%20gps%20update) to speed up the time spent on getting a GPS fix. +When recording GPS, it usually takes several minutes for the watch to get a [GPS fix](https://en.wikipedia.org/wiki/Time_to_first_fix). There is a red satellite symbol, which you will see turn green when you get an actual GPS Fix. You can [upload assistant files](https://banglejs.com/apps/#assisted%20gps%20update) to speed up the time spent on getting a GPS fix. From 01d236b761c61819aa16d5fa75dd55877dd9289a Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:44:44 +0100 Subject: [PATCH 59/59] Bump version and changelog --- apps.json | 2 +- apps/bthrm/ChangeLog | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 7c9cbffdd..3601aeca4 100644 --- a/apps.json +++ b/apps.json @@ -1040,7 +1040,7 @@ "id": "bthrm", "name": "Bluetooth Heart Rate Monitor", "shortName": "BT HRM", - "version": "0.01", + "version": "0.02", "description": "Overrides Bangle.js's build in heart rate monitor with an external Bluetooth one.", "icon": "app.png", "type": "app", diff --git a/apps/bthrm/ChangeLog b/apps/bthrm/ChangeLog index 5560f00bc..27a58dd78 100644 --- a/apps/bthrm/ChangeLog +++ b/apps/bthrm/ChangeLog @@ -1 +1,4 @@ 0.01: New App! +0.02: Make overriding the HRM event optional + Emit BTHRM event for external sensor + Add recorder app plugin