From 7114d646bc14dc422d239c41f80d6a9f63ba6d3a Mon Sep 17 00:00:00 2001 From: Hugh Barney Date: Mon, 5 Dec 2022 20:31:58 +0000 Subject: [PATCH 01/13] Prime Lato: changed to a prime icon --- apps/primetimelato/ChangeLog | 1 + apps/primetimelato/icon.js | 2 +- apps/primetimelato/metadata.json | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/primetimelato/ChangeLog b/apps/primetimelato/ChangeLog index 1be18255b..7781e93a1 100644 --- a/apps/primetimelato/ChangeLog +++ b/apps/primetimelato/ChangeLog @@ -1,3 +1,4 @@ 0.01: first release 0.02: added option to buzz on prime, with settings 0.03: added option to debug settings and test fw 2.15.93 load speed ups +0.04: changed icon diff --git a/apps/primetimelato/icon.js b/apps/primetimelato/icon.js index 06f93e2ef..7c8d5380b 100644 --- a/apps/primetimelato/icon.js +++ b/apps/primetimelato/icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwwIdah/wAof//4ECgYFB4AFBg4FB8AFBj/wh/4AoM/wEB/gFBvwCEBAU/AQP4gfAj8AgPwAoMPwED8AFBg/AAYIBDA4ngg4TB4EBApkPKgJSBJQIFTMgIFCJIIFDKoIFEvgFBGoMAnw7DP4IFEh+BAoItBg+DNIQwBMIaeCKoKxCPoIzCEgKVHUIqtFXIrFFaIrdFdIwAV")) +require("heatshrink").decompress(atob("mEw4X/AAIHB8cYttrJf4AR1gKJgdYBZMCBZdcBZMNsALKuALJhNABZMFwALJmvAAwkOqvAmtAkwSF83+uEV4EMOIpZBznWII5NB7mXGo5BB7Z0HkpBB6x0HFYXVNA4rC6pcFAANXDQhSFqgaEBZGYaBLfIaAUBBZUJNQ4jCm+cHZPcBZFXgdwzELBg1W/PAy/rBY3VPAOVTY863kAnaPHAH4A/ADAA==")) diff --git a/apps/primetimelato/metadata.json b/apps/primetimelato/metadata.json index dd200e5d3..400220b10 100644 --- a/apps/primetimelato/metadata.json +++ b/apps/primetimelato/metadata.json @@ -1,6 +1,6 @@ { "id": "primetimelato", - "name": "Prime Time Lato", - "version": "0.03", + "name": "Prime Lato", + "version": "0.04", "type": "clock", "description": "A clock that tells you the primes of the time in the Lato font", "icon": "app.png", From 22b97ac96298d4d8680624f377f6029e88aef799 Mon Sep 17 00:00:00 2001 From: Hugh Barney Date: Mon, 5 Dec 2022 20:41:42 +0000 Subject: [PATCH 02/13] Prime Lato: changed to a prime icon --- apps/primetimelato/README.md | 2 +- apps/primetimelato/app.png | Bin 710 -> 1455 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/primetimelato/README.md b/apps/primetimelato/README.md index 924a6fae6..0ffd5a3fa 100644 --- a/apps/primetimelato/README.md +++ b/apps/primetimelato/README.md @@ -1,4 +1,4 @@ -# Prime Time Lato (clock) +# Prime Lato (clock) A watchface that displays time and its prime factors in the Lato font. For example when the time is 21:05, the prime factors are 5,421. diff --git a/apps/primetimelato/app.png b/apps/primetimelato/app.png index 2a84c62a07e71744a3721a4a7f8e3caa3721d71c..e5762b97cbfbc9ecfb0bf3c51c5c83947529359f 100644 GIT binary patch literal 1455 zcmV;g1yK5lP)Px)X-PyuRA@u(SZPR&q@sG*rwZs8B@N2Nw22BC;h zKhgv-C6^zHC{z-emQ)BWC>bf`R%EUSfq|mt9%`Hm?=Yh?-#70xLkjc!aeU{#_nz}C z=Xvg!tgf!EViTK*k-$HWo-qRdH~`r25%}`u3!I#suw%y#wZ7WW1bTaW5f&B(Yin!7 z#>V2>wQJbEeY*;g4Nc(ErAsI;FUQKtiU9ul^=o)}d2J2?Gcz;r_4UQ4PoD%}e}8|} z)zx9wu3ejhz{igtar*RW{P^($rlzLI$;m-hR+jjzY#TC#m@-vWRY*%q!`$2)9336; z>eVZ_ySuL|xI z=L{|;@~}d_J}6Kv{-BO9sx3y4jnoq8q<|4 zR}|V_U0tmfw8n&2^M&jb8W|ZuL_`F-y1HOyW`^9{T->~QQ{$Pbsj0Ys|31vk%|%f% zo%pw-qeCU#94p6CE8bij$z!nQ{tAz2MHBJ3?0VWwHpodGiK=fq@Ed78VwYXlPQ3g@pxN zxNt#8BG-6(dyCH;&h%xn2;}GIt9Xx*P*=PXxbg9E#Kgql?c2BFR#j0^A*5HICW`=D zI+a6N;{FQ^WtIfS#>U{_-~i6}E-o(m#4qnsf9%*XusP9KxZl2g(+KAG@87t7{ko!Q zu{*O1>)W)B02S!Kfdd#E926Kh9=v$*VjUi-9ymfU=Otse<%pnf)0)8Y@-p`A+b49K zcIwnAG&VM>#WOoQi<2i$;{E&gLT*VaI5-$DU%u2ge(h6;AXuNwxOMB6;vD{FbMfLu@juD1OLI+BRFs&1copQ7N&>tRN&>(r zG9sLhxNhwbD2IqF0`2YX@bU2h6^5SQy?Zyp!^4HfvuL}!yM=7B!SOrFD7*E~pFhPK zf+pDd`g*WV%F4=c=FAz5*F|lJ$RfZ(=FHDYlqMA@KXaVmSj{V-t*x#2o&`?=)PH5$ zxpSwe2NwF@nk)i5jN?H`NeP}me~yWX3E|QG`}Yf3O-xK&hlfhV`z^b&ot+(cUF1kj zMf<IZDlYK6plC9#C2_7H34NN*1f&$wCm3D!(usgB2N~)e zBLPEsR@;4z5zy9ChFWKgfT29A?Y_ncXzM9MtusczP@dIx-#_QO0-mUQetiG{002ov JPDHLkV1k&)$d>>B literal 710 zcmV;%0y+JOP)Px%fJsC_R9Hvtm^+TbFc5|(bXUD~@YEpQpp&!1vedHBEsjPT^cG zM;ybcdbe!c0b3UI$(&QzDXb~rLc)cF3yHL2;5Q1RAQ}#bY@%AN((!nFiCZidxfVfv zq8@m6zu)su!T0{Zv>2;NWb5I8d`y=R4S}elv5oT zp@7cHvoaD^fhBfzqXILTObFX76JR{ETrNp=IeN$>g@uvANx-k1=n7-f;;h%}JSysL zCJB~1XHvi?g~U6+dIzBR{eF)eohZ9Tz)=(9)udA$MNK+2bW#IGKE=$J^n=tSX-$t| zbzi6hOL`P&gasz8WR#?^Fjg3b;uemmED^O32&9AUmcGzol?iP_O(r z;Iv2Ke=3Yr)#-G?>I~TgUpu8*)7!rp1#1eQPN#>@ut-yCZq?hLLR$ewZGe(d77XNN zwYb;YpTZi~5=joEw%u;GwApOJ599iWa%m^o%Pg&_OR|)WrYo3fC#-~osWThTIba(q sW){O~!&=J{S%8WU7sF|*{dEfe0H(cp6H7fzivR!s07*qoM6N<$f*j~OtpET3 From b29a2c4d0b9d10b4d66c41a402c051236ecc2f68 Mon Sep 17 00:00:00 2001 From: Hugh Barney Date: Tue, 6 Dec 2022 23:12:14 +0000 Subject: [PATCH 03/13] Added simplestpp, basic clock with fast load and clock_info support --- apps/simplestpp/README.md | 54 ++++++++++++++++ apps/simplestpp/app.js | 108 ++++++++++++++++++++++++++++++++ apps/simplestpp/app.png | Bin 0 -> 994 bytes apps/simplestpp/icon.js | 1 + apps/simplestpp/metadata.json | 16 +++++ apps/simplestpp/screenshot1.png | Bin 0 -> 2411 bytes apps/simplestpp/screenshot2.png | Bin 0 -> 2444 bytes apps/simplestpp/screenshot3.png | Bin 0 -> 2622 bytes 8 files changed, 179 insertions(+) create mode 100644 apps/simplestpp/README.md create mode 100644 apps/simplestpp/app.js create mode 100644 apps/simplestpp/app.png create mode 100644 apps/simplestpp/icon.js create mode 100644 apps/simplestpp/metadata.json create mode 100644 apps/simplestpp/screenshot1.png create mode 100644 apps/simplestpp/screenshot2.png create mode 100644 apps/simplestpp/screenshot3.png diff --git a/apps/simplestpp/README.md b/apps/simplestpp/README.md new file mode 100644 index 000000000..4b459bda1 --- /dev/null +++ b/apps/simplestpp/README.md @@ -0,0 +1,54 @@ +# Simplest++ Clock + +The simplest working clock, with fast load and clock_info + +![](screenshot1.png) +![](screenshot2.png) +![](screenshot3.png) + + +Simplest++ has 1 clock info menu that is displayed as a single line at the bottom of the screen. + +This provides a working demo of how to use the clock_info modules. + + +## Usage + +* When the screen is unlocked, tap at the bottom of the csreen on the information text. + It should change color showing it is selected. + +* Swipe up or down to cycle through the info screens that can be displayed + when you have finished tap again towards the centre of the screen to unselect. + +* Swipe left or right to change the type of info screens displayed (by default + there is only one type of data so this will have no effect) + +* Settings are saved automatically and reloaded along with the clock. + +## About Clock Info's + +* The clock info modules enable all clocks to add the display of information to the clock face. + +* The default clock_info module provides a display of battery %, Steps, Heart Rate and Altitude. + +* Installing the [Sunrise ClockInfo](https://banglejs.com/apps/?id=clkinfosunrise) adds Sunrise and Sunset times into the list of info's. + + +## References + +* [What is Fast Load and how does it work](http://www.espruino.com/Bangle.js+Fast+Load) + +* [Clock Info Tutorial](http://www.espruino.com/Bangle.js+Clock+Info) + +* [How to load modules through the IDE](https://github.com/espruino/BangleApps/blob/master/modules/README.md) + + +## With Thanks + +* Gordon for support +* David Peer for his work on BW Clock + + +Written by: [Hugh Barney](https://github.com/hughbarney) For support +and discussion please post in the [Bangle JS +Forum](http://forum.espruino.com/microcosms/1424/) diff --git a/apps/simplestpp/app.js b/apps/simplestpp/app.js new file mode 100644 index 000000000..c07fdbcbb --- /dev/null +++ b/apps/simplestpp/app.js @@ -0,0 +1,108 @@ +/** + * + * Simplestpp Clock + * + * The entire clock code is contained within the block below this + * supports 'fast load' + * + * To add support for clock_info_supprt we add the code marked at [1] and [2] + * + */ + +{ + // must be inside our own scope here so that when we are unloaded everything disappears + // we also define functions using 'let fn = function() {..}' for the same reason. function decls are global + + let draw = function() { + var date = new Date(); + var timeStr = require("locale").time(date,1); + var h = g.getHeight(); + var w = g.getWidth(); + + g.reset(); + g.setColor(g.theme.bg); + g.fillRect(Bangle.appRect); + + g.setFont('Vector', w/3); + g.setFontAlign(0, 0); + g.setColor(g.theme.fg); + g.drawString(timeStr, w/2, h/2); + clockInfoMenu.redraw(); // clock_info_support + + // schedule a draw for the next minute + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); + }; + + /** + * clock_info_support + * this is the callback function that get invoked by clockInfoMenu.redraw(); + * + * We will display the image and text on the same line and centre the combined + * length of the image+text + * + * + */ + let clockInfoDraw = (itm, info, options) => { + + g.reset().setFont('Vector',24).setBgColor(options.bg).setColor(options.fg); + + //use info.text.toString(), steps does not have length defined + var text_w = g.stringWidth(info.text.toString()); + // gap between image and text + var gap = 10; + // width of the image and text combined + var w = gap + (info.img ? 24 :0) + text_w; + // different fg color if we tapped on the menu + if (options.focus) g.setColor(options.hl); + + // clear the whole info line + g.clearRect(0, options.y -1, g.getWidth(), options.y+24); + + // draw the image if we have one + if (info.img) { + // image start + var x = (g.getWidth() / 2) - (w/2); + g.drawImage(info.img, x, options.y); + // draw the text to the side of the image (left/centre alignment) + g.setFontAlign(-1,0).drawString(info.text, x + 23 + gap, options.y+12); + } else { + // text only option, not tested yet + g.setFontAlign(0,0).drawString(info.text, g.getWidth() / 2, options.y+12); + } + + }; + + // clock_info_support + // retrieve all the clock_info modules that are installed + let clockInfoItems = require("clock_info").load(); + + // clock_info_support + // setup the way we wish to interact with the menu + // the hl property defines the color the of the info when the menu is selected after tapping on it + let clockInfoMenu = require("clock_info").addInteractive(clockInfoItems, { x:64, y:132, w:50, h:40, draw : clockInfoDraw, bg : g.theme.bg, fg : g.theme.fg, hl : "#0ff"} ); + + // timeout used to update every minute + var drawTimeout; + g.clear(); + + // Show launcher when middle button pressed, add updown button handlers + Bangle.setUI({ + mode : "clock", + remove : function() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + // remove info menu + clockInfoMenu.remove(); + delete clockInfoMenu; + } + }); + + // Load widgets + Bangle.loadWidgets(); + draw(); + setTimeout(Bangle.drawWidgets,0); +} // end of clock diff --git a/apps/simplestpp/app.png b/apps/simplestpp/app.png new file mode 100644 index 0000000000000000000000000000000000000000..814306471485b135eb105e2d63304b06565e4d7e GIT binary patch literal 994 zcmV<810DQ{P)D(Dg!Z*3O znLFp6^F8m~bKkk=at|HxP-=a{P$oUwaS#Wv2an<5RWjFc2^a7U&S4>w{Y_yM)A$N2 zXjj@TwD3!6tu$7ZS-~8RC0zqU6UXs;h0FrZ;0PXHhtO#H?`V=;tjzxnub|Oq?k4e5 z#qbw6v`NEFynxw?zIjY!VY&)KcnizP(06z$qy8!UkaREM4f*0z6Yp1)pTKY~h)N-0h3jV;ZY}D#w zhj{C4yx#5PNwF4}3})G^hp7sW+PhOzxmBL%k-)pD^@6t(mmk%PhvUkvve(__@6>uh zLy&Ld<&A_#m0#E#`+N=uV87sW1tXmVr8O@1X_*`&&z8I`Ja3J+x50F&1m`nY$ z#X!}8J*l4`7@h8MKJ~lT`twimnsT0wa>f8`6U+PR>OY3@j|h^S$n5|@ennb6#cuO} z$oOv5Q1Fg8+|#cCi?!I`D1kpBosR?op%=Yi0{YGPh{!CUY$j17qt6 zowIe*=@$jJ*-k>o>Iij#oDLKZ_edw9QBi1ZV{Zndxg2;}aJp=RBPCHKZi`ywRyow4 zPn=$=J7GRenCa1Yj;D(sx5Wvsxahu? z##YPBiri*1ZxH#eGRH(|@)=Pe+a)RoRa_M(sf!|?pOgO#o*fUSb`R^}U&vwyOs<=L Q@Bjb+07*qoM6N<$f{4=I_5c6? literal 0 HcmV?d00001 diff --git a/apps/simplestpp/icon.js b/apps/simplestpp/icon.js new file mode 100644 index 000000000..bec6c9752 --- /dev/null +++ b/apps/simplestpp/icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4UA///E8MBqtVoALHBQIABBQ0FqgDBitQCwwEIFoISEgoxEiodFFAQEGCQoiFEgsBLQwHDgplHD4UUCYwIDBZY6DBYgsCBZQGEAgwLXLwhvFqALmirvDXIQLPI9ibja677MBZZgELwhnHA4sBHgY6DCYatCAAcVAhASGEgoiEAANVAhASCDwUVIIwTBAARlHgIKBMgwAV")) diff --git a/apps/simplestpp/metadata.json b/apps/simplestpp/metadata.json new file mode 100644 index 000000000..10f756e32 --- /dev/null +++ b/apps/simplestpp/metadata.json @@ -0,0 +1,16 @@ +{ + "id": "simplestpp", + "name": "Simplest++ Clock", + "version": "0.01", + "description": "The simplest working clock, with fast load and clock_info, acts as a tutorial piece", + "readme": "README.md", + "icon": "app.png", + "screenshots": [{"url":"screenshot3.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS2"], + "storage": [ + {"name":"simplestpp.app.js","url":"app.js"}, + {"name":"simplestpp.img","url":"icon.js","evaluate":true} + ] +} diff --git a/apps/simplestpp/screenshot1.png b/apps/simplestpp/screenshot1.png new file mode 100644 index 0000000000000000000000000000000000000000..94cb35cd604fd3648c679f135feb4df9101ee5d2 GIT binary patch literal 2411 zcmdT`dpOe#8=ha2ZK*~~4q?r_yzHx&P`3Ichmd30u#u9F$k1wtZI$wx-}AeEl`*IRM2;Ldy@9p~v>VEW0g>Z}S~lFJ z^Ye?DE6cIlMH?cmlUjFp&7GLw*wVFB@36kpdcb9*PWw;a!7O;+(9*rW{dvr>P?rEeeu7F}(#J9cGSB$9LBuXJJ%Jh`Wi<>v5 zUfV2Fp_D#sKDHSGJr3(B}}?q(eMgr0%U*%GXKv!DBwpA$n|@J=xJ z4d@jGpM#T`f1l!utOfa=O&V)CpPlPor=iCU9)x2T)`63at!oEtX)=falzI8H z@AYEL4ug|wVVc7mE;-i2c5SwN9}A#GPv#>vke zdC82%Me98s*PyjvN;+e>Ec=7bx}I6hDc(e$P2JhL^1rS6-^^~;+ycH9oY`)T7)#pC z@KKRgs`=I@?ezr^_wf#m>I(3NFr`y9aP)qc)L0V$ac*E+%NeA8RQAqgG8{ehWY^Vp zRU4`4Z!;AL{VH!F;toC$@;%*8Rj~;yW1wEE@)dustK~VPM6` z;d`bE@E+Box5+So`u|1v%2nFcoJoAIH_Yt36VX-rHewf@m8;le`f=>J%5L#g4t6f` zgC8L(#R!)up7ND%lerjSsga|!UR+JpRf@j6gQ5*iyb3qa#YaWxT7lt`>Marugwyce zG(yNIdg?wMhL6I04FzjiG{qi%&@cQNsH2dBv)Pwn)+WaGk;2{-vieE5DQ~mC{2cdX zXiMmT$*qByybhX5XmENy%K=G>+a-?9g3pPJ>~kNVrL%M<*D7duFkD+L&4j(vNvGR? zNkq-hwXka|D~-07CgBmZxK2)6+GH|>AhnJ-(Nr#}eteg`v+{i=ap9&?HO9$rG4-4W z)0Ob~Wq=D$j~mjyjTGyN8VYg^*VO>2lFTX0K<`U)e`%=aOv)l6{|76Bv<>*?bED%J zFE1+Ifu#pnC4BG*AXZ>jc(klTZaaKH662dJC!_>AC@Dbf80hLTx0ep58C6gY7Eh35olfZ$l+$2A{e zD=iPcIZ9dh2;f`Shk;=Ek)9JR7Dvh!5AMCixHS+ad{VsLUlJo#p48m#KxZuyR${J> zT8}M`Mej0PP-dB@J;(~FgK7s0P$Uy~4R9PY^&b)a87?v?d9V5WQ30twB8qy0ny*Un z4HVdmrVhXL10vp|g=r_3LIv7=1b4WP>QICyowfUA%mZ=7GeSm7eIC^D!px$iwhpjn z5K0;>-DUgn$6dSKSe#{Sm96p0gUGw|$K0#YqdPf+`c<|_(BAob&7gpcFg2?jcM5M~ zSHBJ>PI+Q(Kqx#jFw?6kb=Ush@-RDDk2jJ3Yw_ODQc}zLy5_7|rf|Zz*R4euEiG zY5=0#qp($O@X?0rfhYwy*~l|UZvF`Bk-gVofC=YuwLBOaDzNu#VW7Hm|B$Lp;OHRw z7&cL^F66=s;+95cJYNIWT7ydM3su)x8C#@8f5PFkzER&%Sg!aqXfB&^6?A4UA}<+?^AV2tj8>@_`@5BnFACd&qoxrR=)>;`yt4-;i$qqUvz= z(%JUD<=&to5*{3=?#mqlyA66!n1jl^&d!dwi<`T36vKMkO7e_u`v+GG>AmI)DkJ0H zqo02%Ak#|Pac=|V=luPYs{tpLOumagc#gM38^A`XH#Wvda{$3hZSFxAh9EUqiT{W3 zhizVY6S3>wdc|}6qV)OiDK;|})Zs4K%1O#-oYJ9Yt=NqNst>=uEAifZF`m=>^__cW zd3KuFw}-iFisZL;e}$(08hF+!oK;n>If`4-{}Su^lLi(oMen)NRm*_^dtUUupdwdw z!8je9-&yk}q5^y_or4Tfy~KywtkhUa(6VHim9n9dzX=to&`j@4a( z0hJGXEW|1{Qo2!2sGjROlx{CXX52bU0e5?QH1x--uU~ Ytg!jVig__2`S%2KvUjuN+Xi0w7v-!_{Qv*} literal 0 HcmV?d00001 diff --git a/apps/simplestpp/screenshot2.png b/apps/simplestpp/screenshot2.png new file mode 100644 index 0000000000000000000000000000000000000000..d24d55b029b7bbb2ba5f918188ab2df741526690 GIT binary patch literal 2444 zcmeHJ{X5eOAD&qm4vkt)Wtf-K(>2ReEDIY7qe5P1V&o-^@-j@`I^R>|UD75?JVJ#H z#WuCku5{{>jl7H^YbW89jb-JfH;;3j>-iU+>-pjN;d9?V+@Jft?(6f@r|_f~K}T!1 z76=5=@o;zX-Q&=LVchh(O4j%P5<=A* z^9h%q$cG1ARkoo=f(C^%?zl$bB=6^urIWG7TAV~=qrj3@n7kv?c69HSTsekmer!RR zBVfl%{cC10?W#rr3`IQp*0&7akG z!|xZ{N}=?(TK(I>_({8=WXXp=#W5s+%}=t5Elt`bzUxnL*}qF9N<`Y^#pzeg4U6h? zOvgoVdih+065kaqLEc-dm{UE-F{|&N7+9FtQ>9Q8oH^KxJwBpGb=_Q^pfr2-jVvqA zkoZ-F(ceN@7BMKRDk0->m*!{CT}CkHYB(j>*6VZlPB^X`Ds z1;$b;n0PS+ZR{~3)fi;WL&c$J)f#*mM)YJ*)a?j#-5RY{inuh?E}^?%lpi0pbC<=n<7A6t|1bVwmhcKJKHnU<2} z3MRf-&}W3Sc^tI}lPsV2m7Qo~+T~9Ht^K}eW6#l32O7o!p|orRVN01AiY^a+cJl9L zOB`$pVpLOp_N@fFR7G)_uU|)~Ct72`gb8bXqNk$eO&;jecSiytyp*E2F1_pr3B13$ z7$Qx6-X%J1HrudI7rEQ=J1Pd&j~(Wi?*s*ebcSro!}O;OVLLnkXJlFfOTAFAXW{cOL%^% z8Un*s9*WP~?j%cUJaPShS#+U%H%(HkUi+M@Mh-8Wy?sO`WVk@(-`oBW9?WNI0qRo{ zR7bjl{qhCRqcSG|on-9y@ICB`F1oEgk9T<=P1f^D0$GvwGDCA_ zufK=13H(Tq-eR0~RvCT2tcA9BC=c5uoOi3)vlla>F0yyi_f>&tX@rWWi!;H=l11OZ z-aakXbegGoSq2A=R7zj-FFUq^h}6vaek0pFAt9Ey%?W2O-UBvP(aT(kbz!qTVzjs# zeT&wE+`=`2XVU&415MMk_}U%Ry)`QdJ?zK_{}lK}m+kQiZ!eK1>xr+t8-r#WG{A#0 zaTC<4BH6p@$bSG?7IMUr8mqzpz(s8!tZRfle3uoJIb>y^dDr0*p$|W1%wc!;!%EVO1!-bvkGDBW+tTEio9YuAyyk_$IemipeTBr!AOv@K9fpXUky? zS_yPwr*?d<{+;hSyzxwLvMAHyY{l#rF8$~y3IvwHDf14r0(+0YkUV#mN$l{X9;gH9 zC=sOr5Es^>KAS3|bVAvN5HfqFQc^6e#H4ak{(Gh$YE~wS69F$xIGgVk$ivmkrR_-g GZ~q31IDNPP literal 0 HcmV?d00001 diff --git a/apps/simplestpp/screenshot3.png b/apps/simplestpp/screenshot3.png new file mode 100644 index 0000000000000000000000000000000000000000..af7ae7249bcc816643c766973237ca6472143124 GIT binary patch literal 2622 zcmdUx=|9wu7RUK!)R%OR2P930RsQ^Sjw!rgv89LXUg4;zNWwkQIZbN+Q3h)-mpkI=9pRktL^r;IsDys7{kC|GPo(-@T#ur*A zgP*Qb8B;Gn^mfCH8ueCXVYhZ*rhYi14sg#4m6n%Zb88@J;!B-z3LeABaOM6m)wnR+ z#*l}R%}@(f3ldYN_cmyIcg}?ejvZ1U+Q*k7E`~AQRg_=Hc1@rmP%0!98$D5 z#`&_m7!N4HKi~_k-xTTh{lfkMT1*@271sU&MKRsGTKeRlAPS(^Jxqxvoz6MxIumDS zpiQtUENboR5!E!B^@|YNRtS7}vNRpsLGROqwy)m|44@f#>8nVK4aBx9qqS0-uL!3gyK^98w~pWdTIfC2exL832&aO!dxmut&Gp$h?hOZ+*9KrO0*+q%lK+QIn_*MBM`{ z-f}L58nc0~=I|Qu|26iQbPY3Z-uLg>Pc)|ONlHew1G+xC1>(Si)CjuWLu2+H3-ft7 z2(XgR0pa!0x)O|37ayXO(Zqop(;1Zu_7|t}nn>_1-gcuoTcB~#-g1_X^!*|S)u}B< zyr(gr%dCEACh=hsQCOUMQ3X&*80gAF6v(D(0mYgY>0t&oA`Mq$juZ}?MBEoCUDgY# z2;x0nKpcqu0L_q{rMf4+)PHx$r5BDv^Npw`9u%6U>9s5V ziHL4XuGbKGcyi=fnOVl_mp(d?uGbd%CxpBMC&J@b1e!iaf9ytUSfO^#*_9xVJ)@9~ zS?64F+;6^>vWlgc7c;~amDahwpJ-~lV~espp{Y-D%Nk)yMi{FrwceFsjOdJV`Of=< zrpRPvZ+owRS34Y|1%o2TaZzvQ^{J8j7*6dbf(T5ywx-pkZ2h^CN`KzM=yIn<=3tT& z{@alkK#IbPg)>XTCmBC74(`{21-A0e{1F9UWltIh+SM_lVI{OrxGL`Sbk4ZwTM0n^ z)VZN{8uLmvw#wr*_l~#MIBrh$Re@&m<#NzsR1s$jcO0)=_<*HGJ;Iv9@V>l8NPg=S z!aF4kT<%J_+It@6CeMKGg3VFq+b7}cMTKf}@?2)4%*~bdDVMPW#vQiGWo2`FQw1nM z$`6r$PuZV;`Cv|Xu3y<)C^Q}C^jSu+UK3UOd!W7l=A|iLqGGl5<;`yn9@wRlKgRE_ z@nNzBP_;H+1~&Y+RkSk2KFC@8(77~R-edq7%5sd*9_~A+uJ$#uQl)C$#qfZ$)Aonn zCn#*MD4x4Y+b~IiAAfp*?c$=SB6)r*@^(nJb(#P6slT~kxy)+Eq4ixtm%vZ5U&o|4 zzp{3bcBBWus$W}Op;NFSV$N;!XdBAJG^J5VI`bOu>A)LG%e+3s1Id~E;dNc9Z9;sF z^T9OzRq*i?qJYcjFa?}>yDvObq>+vYA5)r=>Q62+wARJ5?u6kyse1T^9&2k`Npvco z#7%GA9g@>*0>C00pi@R8y)p)t@LnFVVw!VDPNTL(>3@10#yzNwi^oUw?!&Z86z*cSZHZu$IIV-d-#`<5!dZ)B_P$9{~x!hiJ1^ZCuYPwt|B#4Wc#q@(+)Dx6H=iu1t;Od9{YK9awY342hsnqn7~>fKl7JTty?^Bk{`D{Dxjx z5ZdBp3FQz(pu8oX>oZ9=HJz^2dUp|nD;b$EXk0XU-L-Lkm+=9yGXZ-Tn^nmcXo*0N|&%mcNW z$rX5JFG+;);AuAnjJskbwdQ6LN=??qmcJw++0a+~$uR zT;xV?OCT=4w5~re6LaFDyO(g!`Qk9D*HUHC2$st?c)}B{>aEF2zwdw>%Sz@hR=+#D zYSUhM4=n`|&zmuyE zCgM{47L^_kiNzQ=%2R=A`mZEf08yO&p4RsYtR(#P*uc&vsfX0xR9N#Djl;Afwmf)U mt3+UJSgN=~_5XTppA$@wb>`Tlh_fF;4pSp5! Date: Tue, 6 Dec 2022 23:19:28 +0000 Subject: [PATCH 04/13] Added simplestpp, updated icon --- apps/simplestpp/icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/simplestpp/icon.js b/apps/simplestpp/icon.js index bec6c9752..92e0fa271 100644 --- a/apps/simplestpp/icon.js +++ b/apps/simplestpp/icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEw4UA///E8MBqtVoALHBQIABBQ0FqgDBitQCwwEIFoISEgoxEiodFFAQEGCQoiFEgsBLQwHDgplHD4UUCYwIDBZY6DBYgsCBZQGEAgwLXLwhvFqALmirvDXIQLPI9ibja677MBZZgELwhnHA4sBHgY6DCYatCAAcVAhASGEgoiEAANVAhASCDwUVIIwTBAARlHgIKBMgwAV")) +require("heatshrink").decompress(atob("mEwwIROj/4Aof//4ECgfgg/AAoMPAQPwAQMcAQM4AQNwAQMOAQPgAQMHgEBDQUDwEBwAFBAYMDGQfAgwJCgFgAosMAocwAosYAocYApcwAocMAqUHO4PgAo4jWJqJrLQZaVFUIqtFXIrFGaIrdFdIr1FgEf/AFDABIA=")) From c5086ad9351d7f30ecc0302a6c6a3e917221d4bd Mon Sep 17 00:00:00 2001 From: Hugh Barney Date: Tue, 6 Dec 2022 23:28:06 +0000 Subject: [PATCH 05/13] Added simplestpp, updated icon --- apps/simplestpp/icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/simplestpp/icon.js b/apps/simplestpp/icon.js index 92e0fa271..f8186ffce 100644 --- a/apps/simplestpp/icon.js +++ b/apps/simplestpp/icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwwIROj/4Aof//4ECgfgg/AAoMPAQPwAQMcAQM4AQNwAQMOAQPgAQMHgEBDQUDwEBwAFBAYMDGQfAgwJCgFgAosMAocwAosYAocYApcwAocMAqUHO4PgAo4jWJqJrLQZaVFUIqtFXIrFGaIrdFdIr1FgEf/AFDABIA=")) +require("heatshrink").decompress(atob("mEwwMB/4AW/ggDn/4Aocf+IQDx/zAofPArP+v4F+NgUfAo5N/U7QFDaIrdFdIr/PAA4=")) From 8f535ff067a3515dd410233868a8ef7095275092 Mon Sep 17 00:00:00 2001 From: Hugh Barney Date: Tue, 6 Dec 2022 23:43:07 +0000 Subject: [PATCH 06/13] Added simplestpp, updated icon --- apps/simplestpp/icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/simplestpp/icon.js b/apps/simplestpp/icon.js index f8186ffce..e4e40c82c 100644 --- a/apps/simplestpp/icon.js +++ b/apps/simplestpp/icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwwMB/4AW/ggDn/4Aocf+IQDx/zAofPArP+v4F+NgUfAo5N/U7QFDaIrdFdIr/PAA4=")) +require("heatshrink").decompress(atob("mEw4X/AAIHBqOM997IGkq1AKIltVqt4BQ0DBQIAB4ALFktVv/9qtYBYvVA4Ulq4KEgNVwAEBgVVoALDgtcAoc1qAFDitgAocJqguEGoowDgVWBYuVGoUBFwgwCHgUNGgUNuBCCAYY6CBYcJCYUlDYYLCgJxCmozCBYcCG4UVG4QLDgBgCBZeXBY/WBYcC1WtvWqGoILEVAIACJoILQgf/+tf/7jBBYg7JL66DLTZazLZZbjLfZcA6oLFq4EDio8CHQReCGgQwEmpCCHgVVFIUCVAQAD6plCkouEA4VVv/9qoPCAAcDZYa/BAAstBQN4BQwABlWoBRAAr")) From 55ca187d5dc91ee52d57aa42f5d6a07c5bb20b0a Mon Sep 17 00:00:00 2001 From: Hugh Barney Date: Thu, 8 Dec 2022 20:12:47 +0000 Subject: [PATCH 07/13] Lato version of Simplepp Clock --- apps/lato/README.md | 54 +++++++++++++++ apps/lato/app.js | 138 +++++++++++++++++++++++++++++++++++++ apps/lato/app.png | Bin 0 -> 1139 bytes apps/lato/icon.js | 1 + apps/lato/metadata.json | 16 +++++ apps/lato/screenshot1..png | Bin 0 -> 2666 bytes apps/lato/screenshot2.png | Bin 0 -> 2741 bytes apps/lato/screenshot3.png | Bin 0 -> 2723 bytes 8 files changed, 209 insertions(+) create mode 100644 apps/lato/README.md create mode 100644 apps/lato/app.js create mode 100644 apps/lato/app.png create mode 100644 apps/lato/icon.js create mode 100644 apps/lato/metadata.json create mode 100644 apps/lato/screenshot1..png create mode 100644 apps/lato/screenshot2.png create mode 100644 apps/lato/screenshot3.png diff --git a/apps/lato/README.md b/apps/lato/README.md new file mode 100644 index 000000000..556ee6fbc --- /dev/null +++ b/apps/lato/README.md @@ -0,0 +1,54 @@ +# Lato + +A simple clock with the Lato font, with fast load and clock_info + +![](screenshot1.png) +![](screenshot2.png) +![](screenshot3.png) + +This clock is a Lato version of Simplest++. Simplest++ provided the +smallest example of a clock that supports 'fast load' and 'clock +info'. Lato takes this one step further and adds the lovely Lato +font. The clock is derived from Simplest++ and inspired by the +Pastel Clock. + +## Usage + +* When the screen is unlocked, tap at the bottom of the csreen on the information text. + It should change color showing it is selected. + +* Swipe up or down to cycle through the info screens that can be displayed + when you have finished tap again towards the centre of the screen to unselect. + +* Swipe left or right to change the type of info screens displayed (by default + there is only one type of data so this will have no effect) + +* Settings are saved automatically and reloaded along with the clock. + +## About Clock Info's + +* The clock info modules enable all clocks to add the display of information to the clock face. + +* The default clock_info module provides a display of battery %, Steps, Heart Rate and Altitude. + +* Installing the [Sunrise ClockInfo](https://banglejs.com/apps/?id=clkinfosunrise) adds Sunrise and Sunset times into the list of info's. + + +## References + +* [What is Fast Load and how does it work](http://www.espruino.com/Bangle.js+Fast+Load) + +* [Clock Info Tutorial](http://www.espruino.com/Bangle.js+Clock+Info) + +* [How to load modules through the IDE](https://github.com/espruino/BangleApps/blob/master/modules/README.md) + + +## With Thanks + +* Gordon for support +* David Peer for his work on BW Clock + + +Written by: [Hugh Barney](https://github.com/hughbarney) For support +and discussion please post in the [Bangle JS +Forum](http://forum.espruino.com/microcosms/1424/) diff --git a/apps/lato/app.js b/apps/lato/app.js new file mode 100644 index 000000000..6045d7f17 --- /dev/null +++ b/apps/lato/app.js @@ -0,0 +1,138 @@ +/** + * + * Lato Clock + * + * The entire clock code is contained within the block below this + * supports 'fast load' + * + * To add support for clock_info_supprt we add the code marked at [1] and [2] + * + */ + +Graphics.prototype.setFontLato = function(scale) { + // Actual height 50 (54 - 5) + this.setFontCustom( + E.toString(require('heatshrink').decompress(atob('ADkD8AHFg/wA4sP/AHVD44HHgPALD0OA40+F43+H4wHGn/8A4v/L4sH/5PFj//CxkD/6eFCw9/GooWHh//wAWLgP/TgoWHn5rFCw41BMYqCHaRDKGgzLYKAJgFv//LIhQBAAI7DWgIABU4adBAAJTDn4HCVAaOCQQhvDAYQuBDYaxBgJEDh4HBgYzDPgUDIYYECA5DUDgIHBg4HEEgIHfF44/EA45HDL4xvHP46PHT5CvHX47PDGYcDb4zvHf5AA/AA9wA4yoDZYq/DXAgHDXYQHEXYQHEj4HHXYQHDn6UCA4d/e4sAXYYHCd4gHCXwbADA86DFA/4HGAGA3Db40HA4UDe40Hc4YHCh7nDA4UfA4X/A4U/A4b/Cv7vGX4UB/A+CZ4YaCgf9A4sH+IHCHwfjA4JWDj/DA4s/wYHFv4kCA4f+A4pKBA4sD/AHCG4R9BA4YCBj/gA4s/4AECN4R5BA4f/gf/Mgn///+A4wZBA4d//6JBA4c/VATHEVASUEEwIHEAAbnDAGbyCAAg+DgKwDA4S4DLQSlCSYQHCn4HDFAV/bAX/4ADFCYgbCh4zHZ4SlBR4iSEA46XCe4QHCDgJWCngHOnwHGvwHRG4iFBI4ppBA4f4OIRnCN4MD9+AO4f///v8CHCDoP/54CBS4f/44CBU4f/wYHBX4f/EQLHDh6gB/6jDZQaTDAEUcA40/A4xODYoYHGgYHGh4HGNIIuG74uGz4uGj4uF/gHFh/4A4sf+AHFn/AA4q0BA4kBVgIHEFwIHFFwIHFj7jBA4guBA4rjCA4YuCA4guCA4r0BAATgBA75SEa4wHvAEEBA40DUYIAEg4HDgZ0Bh67BXAQHCZYJMBA4UHA4KPCA4SXEAgQHL4IEBgIHC/AMCgP4CQUDFgIHoIQY3DA4wCEDggHFO4YHB/iHDCQX+gE/S4IHCOIP/U4IHCv6CBA4k/A4K1CEQKpBEIIHDh//HILSDTQK+CAAd/f64Amn4GFgLxCAAZfBSIIADN4heDP4YeDR4Z5CEwN/U4IABg4NBj6ADEwLHDIoQtBVgQuCHoIHDFwIHBe4QLB/14A4kH/i1BeQQuB/AHFn/wA4pLBA4guBwAHELoMAA4o9BA4Q3BgYFBJ4gCCA4pqBvxvDf4T2Bh4HCIIc/R4MCKISfBS4aQCU4gHDX4ioBY4paBNwQAD/6uDAAUOf4wAjO4QHNdQYHYmAHGW4gUEA4kPA4z7BA4v/A4qYBY4QHCh63CA4c/V4QHDV4Y6DV4YHCDwYHDDwYHDv7ODA4MBZwgHBcwL1DA4MfdogHBDwgHB+LtFgf3DwhMCDwgHCDwhcFA4geEA4IeFA4IeFd5AArj77EsCgB/gGCg5QBOQkf/6oB/77D//DA4JrCv//44HB4DkC//n/E/MgIcCRIMPA4X8RIUHegQCBFoL8DA4cBA4QaBv4HGvwHBTgMHHQM+HgIHhF44HFJ5RfGN45/Bz6NBP4SPHT4XnT4ivHX47PHgCQCb4bvIAHxdBMgRfD/58CKgf/WgIADP4JlFR4J1ET4QHCiACBQwQEBuC/CDIIHBX4QtBn+Aa4sfZ4bvCh+Ah4HGUAUHA4d/AgIHEa4QHDwJyCA4eDKIQHDx5pCA4bPDG4c/RIRPCjwuCA4aJBUwZnCRAcBP4SgE/+D/7+ET4ImDA4jIEX4KvFh7HGgbXGgF+f6oAggZeBSgShEb4RYCagQHGh5iDA5QXEE443HADoA=='))), + 46, + atob("DhglJSUlJSUlJSUlEA=="), + 64+(scale<<8)+(1<<16) + ); + return this; +} + + +Graphics.prototype.setFontLatoSmall = function(scale) { + // Actual height 25 (24 - 0) + this.setFontCustom( + E.toString(require('heatshrink').decompress(atob('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'))), + 32, + atob("BQkKDw8UEgYICAoPBQkFCQ8PDw8PDw8PDw8GBg8PDwoVERAREw8OEhMICxENFxMUDxQQDQ8SERkQEBAICQgPCggNDgwODQgNDgYGDQYVDg4ODgoLCQ4NEw0NDAgICA8AAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAADAAFCQ8PDw8IDQgUCQwPABQICg8ICAgOEQcICAoMEhISChERERERERcRDw8PDwgICAgUExQUFBQUDxQSEhISEA8PDQ0NDQ0NFAwNDQ0NBgYGBg4ODg4ODg4PDg4ODg4NDg0="), + 25+(scale<<8)+(1<<16) + ); + return this; +} + + + +{ + // must be inside our own scope here so that when we are unloaded everything disappears + // we also define functions using 'let fn = function() {..}' for the same reason. function decls are global + + let draw = function() { + var date = new Date(); + var timeStr = require("locale").time(date,1); + var h = g.getHeight(); + var w = g.getWidth(); + + g.reset(); + g.setColor(g.theme.bg); + g.fillRect(Bangle.appRect); + + //g.setFont('Vector', w/3); + g.setFontLato(); + g.setFontAlign(0, 0); + g.setColor(g.theme.fg); + g.drawString(timeStr, w/2, h/2); + clockInfoMenu.redraw(); // clock_info_support + + // schedule a draw for the next minute + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); + }; + + /** + * clock_info_support + * this is the callback function that get invoked by clockInfoMenu.redraw(); + * + * We will display the image and text on the same line and centre the combined + * length of the image+text + * + * + */ + let clockInfoDraw = (itm, info, options) => { + //g.reset().setFont('Vector',24).setBgColor(options.bg).setColor(options.fg); + g.reset().setFontLatoSmall(); + g.setBgColor(options.bg).setColor(options.fg); + + //use info.text.toString(), steps does not have length defined + var text_w = g.stringWidth(info.text.toString()); + // gap between image and text + var gap = 10; + // width of the image and text combined + var w = gap + (info.img ? 24 :0) + text_w; + // different fg color if we tapped on the menu + if (options.focus) g.setColor(options.hl); + + // clear the whole info line, allow additional 2 pixels in case LatoFont overflows area + g.clearRect(0, options.y -2, g.getWidth(), options.y+ 23 + 2); + + // draw the image if we have one + if (info.img) { + // image start + var x = (g.getWidth() / 2) - (w/2); + g.drawImage(info.img, x, options.y); + // draw the text to the side of the image (left/centre alignment) + g.setFontAlign(-1,0).drawString(info.text, x + 23 + gap, options.y+12); + } else { + // text only option, not tested yet + g.setFontAlign(0,0).drawString(info.text, g.getWidth() / 2, options.y+12); + } + + }; + + // clock_info_support + // retrieve all the clock_info modules that are installed + let clockInfoItems = require("clock_info").load(); + + // clock_info_support + // setup the way we wish to interact with the menu + // the hl property defines the color the of the info when the menu is selected after tapping on it + let clockInfoMenu = require("clock_info").addInteractive(clockInfoItems, { x:64, y:132, w:50, h:40, draw : clockInfoDraw, bg : g.theme.bg, fg : g.theme.fg, hl : "#0ff"} ); + + // timeout used to update every minute + var drawTimeout; + g.clear(); + + // Show launcher when middle button pressed, add updown button handlers + Bangle.setUI({ + mode : "clock", + remove : function() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + // remove info menu + clockInfoMenu.remove(); + delete clockInfoMenu; + // delete the custom fonts + delete Graphics.prototype.setFontLato; + delete Graphics.prototype.setFontLatoSmall; + } + }); + + // Load widgets + Bangle.loadWidgets(); + draw(); + setTimeout(Bangle.drawWidgets,0); +} // end of clock diff --git a/apps/lato/app.png b/apps/lato/app.png new file mode 100644 index 0000000000000000000000000000000000000000..02a4031a3555201deaa5c5cc5a37aba65189d090 GIT binary patch literal 1139 zcmV-(1dRKMP)w5uAyjC1NY_IGq@RUQVM8hu9vLxRL#E^s|tPU~I(-=}G@-uK{#5YVHe) zgTM2C-!cJk2-I*l?UBFpC7Jr{XiY=o`sUVl&}_b0PWq33J`nh6 z-<#naCW1W=(t|O#)W`f)4UOxY+df=?1^~^rwC!KLc3s!^mAOfX)*``_<>tB?HIH7a z_U>;7C;;);WKZ|0v7r$Fwe@w)ufAO2b^=sOYx@W9gd@?LRdef!Y_}F%p}wH#-L*lj zO*}UF#YdkE1}{&irl(WWL;b&YetaMvn*;!Q*^Zsh_VtSkCeaX4g~rC|_xC-d#yo3& zy0uA-Pkhytypzm!P9>Aye0_ZPyL$kb#HQZ!z1?Rx_133{O6r{YeGyg2Q`0!#fP$;i zrN-l<;d{+jMnh`gUhXN$N?%#qc(3_BfjE0LXSJ!ZLS@~cs0G}!7ZqjR%~@@n{XxTk z0MN5W76KecG?E-yN*JXCVUyT3%onhPU!-);$@& z6_3Xz8HTA}{b<|UUWc;+Kx!&=wR~(*7kckw?F$)C1%JUb03;^)%-EB6T z^PH)vl<(l-;LjJta$$ZvE)U2=43srQ3Y1+a|0NI{ygaaR%jU<{G&ns@0MYBwflK}V z)4g&!EtU(}dr)*64P;ryu^gAYeS40{##<#x>N#=x+oRpGECHZt#$+mGS$1xwRIxnI za-6|H07SPZ85+xJ%rI7thhAUg^M!&wgB)(sg_+;bvp7KH>ma}3B2`FqxeJE@3LHrx zQ$~E2k|ad@)u+JFO~ zGM5ZRCmtFft~pHF%{_+&t1Ans_e$*~@Vkd*wRG z2>HHQGRw!AjTlr;DTH|(5$bXc=iU;w7YBd+fs**#)`%r9@bVf&f&GE!Cx6waC02Q2 zi+75$DkkN+Uck$@M;<_i;(At*W=GhDG-7y<@zwUku2}&@ecZe!Fb;Y2u>IRo?TLo6 z=avcKB=lS-+&qCC@nsZqAuAUr-Ve$FH@H=`25N=)4qi|axiLoy=sH}S(rT8;JYN|7d2cI8vzkz-FOsD#)*|A0Z z;An$b%^9+`L@hA&46*2etwyHTu|#O#XVRZUva_fr)G~>1WPUDoG>18Dh~`e8wOX$= zi@Q9a4wZ@+L!OZqzGFR~qvHgzj|bJCACeSg-CW*VK~$}NieIn}y&^xBKXdDZs*7H} zDEZj%Aa=hXDMOlg3Ln+w_`Lp2C2e<59?0$UQuN3Xx1>DllcjKwy6c?~cU^9xTXyML z$Jz=2ggo>}MU(qz^!1dq(Lp;F0CF0~BAsb(tSGxJd|5S)0Xs^#>08mErPBM3 zPtU^G9-M47w*V@AU)0NL?=*zD&wzXTy)P@N^dQaYSqUSzC;!mR5-Apwg9vZayZ6vB zukay^t5Ki>hQu>+hRgoHw;vYAv6?MGcyt|u^9hcOw4zy9T$wo*ErK?wJR1zsyFG2e z?YNH{P~zisLadqJ$ng#lCC-Q6$b<*&BY5lpn36>&%OOi>AOFRA4hqvfvDdd+u@0*v^m62ri-NY!*^$$1@_puyu&4V@$7^Mc|I%Z3$hu#|N4)xK zWJMVR2S6}^%bFiGZ&23nUytf7_akm=x2U|9z9T!HyncX|F`oMPAXIT_zD5FMUaHzP zzqw+{**3oUJI%S6X`zsE(UWBJg7vE{GRDS|*E#_Un9?l)X_tP=-@=pbr>}638iM(j zamawvtq_Vp-j=}8sSw9Gpe8<(DlfF_Ei1re7F?%_ zW>R}HfgJ~YHlL_~UUfy|!&JcrTMuqcPde=>{%w&$v#iIc^E-ksfJ)j45N>y@5?`=^ ze)78hBbR)kMJeF8fLDX7* zQi87{S0KKQ&d@^S2^q2ObU*6xT|&KeQ876 znXLFNOsp*6Z<)|fkh0Mg%eli28`hS;c^BRhj5b&_F?N$|An~KXP^xVrsHMw zex?h&cq6%)t>p|+v*-Knnr|2*{?L9 zbO9fk9;W2tLb*cz@Y*uEqAR_NAWrdX>xX=6UCS<|d`tD-+RqLlo{E1pR<(8&>IUeQ);Nvt-lj6Ah+eUk;olM~?7 z8INA?ix$1d?>+8+3nyeN;!QFYJzNaC4p_mopf; zmwgpG0IO`CX4f7b&u#hdX5BDq0;k#gz4>zeCt^pipqgt8DElYodf8}l^*zXrC}<;e zE#_7Gd`Nreg4%A;g}%$U8JI#qr2V{+8wjlS$n0X?t^&W;sd!HA-RBXow{^0q!UZJ%4PfNx A&j0`b literal 0 HcmV?d00001 diff --git a/apps/lato/screenshot2.png b/apps/lato/screenshot2.png new file mode 100644 index 0000000000000000000000000000000000000000..f40495c79a26a8cfb53c699f536072adaf38e8eb GIT binary patch literal 2741 zcmdUx`BxHX7sr)B1#QN}T~SNG4FwY|cdcAdTb*1Ga!gH|+ymTA@XfK*G&c&@3TrI) z&_PX;92XLo%t^BpcP+&baVxD}-ap{|^*!gk=REhG=id9A`^$Yk=X>ki8P}g>HDo0u zBz|_oI(dp?!+#D)TI}mt3;yCDN%V9*AyGF3{UjkF8|CJ7{6f6{TG>c!rR4#q(H}oX z=%ZF1G`)bL%6x@$2@!Z&J*w+9{ne`2_B-qdZgYpWAuM&b= z2RdZ7f&cg_Sn39(INUiL8as0;dQe$%!Jzm7oQl~rXCWlN6+EO}KJRHD3C_-c(?SEn zqq)xv3=1hh7q{OD9so$oWn7_>yCZ;6X5DOdr5%HXdK60&n8dr8LP%OS&ixC z$f`&_&+#hLG4hMmVUW#|f)|Q#orHj}e@!e@cdzL+_9%25-0pP_V-FY>pM1jRNMmjd z-(h8OK-`<%=f5j|aUvR8ow%==t!IblRUp4@xsZqC`$tPI2A{>El42O58oTpSF8MVp zSI6FC8`X{&&+vw8OWTEJs*ED8diL)Cd`VDw=XT%`9Tj?`Zd&bf={M;=ja0{87yw)s z21#kPO3Gc05VfA(nVW2dQH`D_`X@o&X!m^#xf$J*;MKS%3c%m}`0T2yRSAkT5RFApX*G@(G%sImPIaWiYuCIPD-e0tW7BDKS=dj}lV^ltwU zJA<8NI_K0_g`IJ^H!%4Tr?J)z*>&iOqm3upHv~U{#FOk<*Zj8ORGA+kXc5V_nwdCu zi%?m#VWw@WgN`OsZPUDRi`d7z6rx`~njE!WUgBjRIs9y#1C8R*Ewrbo75}6#mIt#5 zRUGjZ*|6~Kw|b7?7(*U+vm2uJph-hyp1_zoh8g}90_NYpoYMG`Z=BQApW%YIH6#i* zVD`@E99(%(aTTW;Zc!h;?+PwWU;JcL)*E6?uwaJo_kl{KlohVwMpv#SHDZY4Lbbh+ zZnd=-0j6*Q1}sncJV^;t3sV^M=AzUB)0-%|`}efxeP`uIP(lamL4`h~ubhH=2KW)Zqnn6p)WfY$2Az_z(b5W|gFr@xM+sB6WOw*MMhq_=(; zdd^#=z0%HLH0QMz1ZNu)(bN%q{EdIiLJck7Tw(>O5p%ciwOZE5q5rOq|GWj%E|Y}y zYym>BzK0#&JaCPx%5qOmrA|Z{!y9(;(ORidRAhNeb>v%bnI;sJJo82_T@$LTsI@#e zlvqIFJ>40*4Mn?b_*ERPNcwULnp*!$^5*LW1u1IkU+fRe7h8IlHd`%JXJh8>g~=vw z9y*rT+>{PYS^T3vprc>I?Ivk9&z$q#Rm32i$=_`Q;MqnzRs8aW1!&^t<8C5ym~Vm^ z54_&BJg&N11@l&tRfsp48_|-qf+blW-k`+6eL_BiyS}&P`G2if!qs!$$;W6(xe(tM zm|$4cc86maFuw}ux86}lqlb})M;a>w>wdy*y$+LW-!Tof<0M25;=kU!;TmK{oS0I4 z_2|8==YEo0yJMhAxDq!JQAB@^YH1$A<_r+>NduI(o~J|0J*v!FGtw2yhPb2RS47f8HWv`HUg9ZKz(%H-lkGC|lG-3D2k40ei? ze`nyYJ7qzm;Oa^Ij3VXgt5zU=!S`j4-K7A_x%lclu_iD(mtNxG2pC?heajJR0`;n{LGcbRZ;V|H20-o|xG=jU zmI%azFbgwD@G0r1(M0iYXl-xSpi_W)KY6wMx3TN;_pL(lHqu7PVjU{s=6uGf?nFS^ FzX7Jd162S3 literal 0 HcmV?d00001 diff --git a/apps/lato/screenshot3.png b/apps/lato/screenshot3.png new file mode 100644 index 0000000000000000000000000000000000000000..1cf135a60bdeb64bea4957f56bbd923fd9ebe87c GIT binary patch literal 2723 zcmdT``#%#38=sxk*`kw8ZYOuWyj@ENG{1H z%VI8*r9(ALDnn&w$FL9^ayz*k@1OAg^nTtSp6B~{et16LU!L#x`DXd~p!V+haSs3h z*z4u#=D&mN{}g!lPH*5&gzbP5*&pQ!cr4VJ1_1Wpz1&U&CWXzFe!N;`ud?gi_V%C+ zlj9>(-Tg+i_dqSL`CxCgt5&ipB{em5bA9}Kpe9`5D!GlxecA~zIBXPJ0sw}$T{GGC zmN?&NroU(yP8sQR7B9%bA>@^DR8PQLB6JO!16w`-?ts#cFik@a(W1#WKoU zp<*&M1y+G3ZL+K4yAEcp{Lz>ZqL1Q9$*+p>UIh7tVw}`$DvD%?_{({0m2*bEreZK9 zf(8lBCrB%~zP;Hd)Q;Pfm+}r+h-pdcyEE9`M(z+5Xv<^$>QXEBXVu@g_!Dro$(AP=!c

cQOwCI~PFrxa zEfk{q(c}a7uPr>;oxv{<^r=Vx$|pWEbP=~^FoiV%k}=YFv$#XALtLlT!29m2APlcE zz7DC~rzm^%Hih8p(&I{?r!8-~+`KnRwRv8wtTbs>Qjx*ePVOsZ0Jf_y2paF?p8`

>P) zP5S>JRUD(PZZWDBACl0uzWUtmmfLc3Aic2Xo6NVJfa+eElH(pmG~{hqh*ISoyri-p zeJP@W0A=?Ejjca=5V;!n)aN{1of0V`X^wm#99>7o5q}#QuMGo-NFN-j?K3Yq$>a-m z+hmm+$`MAE2xAy(J#j**(V3@aYEIIxA-jU((e)NAuR0?i?X!CD4M+ zIETe@L>L+x`T{t=`AP8lz#+0#aBDUp)Rf)SDp(rEumrcd1wqi~g=CM;=hK4fi{Wq} zYN9_ry=lL07g}jvHE241G@)G^JA^pMhRY9J<*Mi|FabpO4}!C%RGZeo_Xpu@BYAt8 zdRDUjCu@Rpbi!0UEr+q}d;uqP2&566idvM$7R;?>QXkv1$1iuglM=2EL<>$ksW&M@ct}=L z7R{|a_5{YNvb8~m%MOe(ieouil%wq8ZOhqwLCtY}fbdt{IX=3(Y!VEeB-r^shfw#K zq4dId`&#mj-){2g9*r->X1G^IEEg0#YEJT6PPUFI;izLx#j2YolcG;Vwk_{mZJt1iF*1DiOnCc5(Z9s1m;`riNTME z9ntY)0?vB9y#jU`^i_L%%_(`|oUC-25QSI8;92WjIe&IbCJUBBfsTop&LUN*Bs7KIM*vis##-y$-tN zLpaA-H{@F%ilyFR{X>@%sSfE0ba#otU*Hyr|9q5!l^|i)Vthey&w2Y$TTaZzOYps2>d-|_&Cq0X1aS%} zMSp2G>KWAIIt3Ivx=J_$9mToaRY{e`)8Me#kBzIcp;k(SQpbOI5io>bnW-~M z!Z8RTzT}lO?>MRDGY@V$y)ZLwojmiv}45eNf7b>Wbxk_MV(ZS^_*ja;kMNqe< zMutymYwPF2T4uQ?p55l{h>a92EJR@L2_5lxapD#iI+B81)*u~Zz{@NYgU2FsI#Ll! zj`k}_bhohBG3g<5#oxcPf5OTxVe`D_%2J-#>u-r;gj@J$y4K-7l8%t|U<|ssjVAF??h7CHYK}KBBVEehMEff#2zHo_jx(IiQ+E;f?$j<2zodyk?dd8Ln&OaW?D} zL4Kx!qimUp8OBCX+P;*nm1}`@IznMff!ZQ(HyQ4c#oI^GmQRGR5yqe6S5{<2pZRrQ zff_}f;BJ3}1lItPu=CbH;y~l9ttKu{eLCN&H#hOC-%Y-zdeB@%;T?2bKKb0T)~v7* ze*LRqu5m^rL%M{VZXEmc?npf{CRHzQnDHi^$SUb%09K6|NWTtD@ zC#rko+qM3w&kZj^ZrF*BV_i~aR6!bXOwD|FpXiF92$~WVOs>DC8nj0_yj#*_?W|D=MicYU6orSoDzTyE^D6x<`|^$jcYmQwUt1~lV10sJHHx~AVL_Y z@gvP3|4Ih{>Gy>tkvsRO0;hVYx=5h!ahz-bu&Bc14R|LYq}xXqLR}=*`Jf+90H`QG zV!t&I9D0-CVhlD=fM-}Z4*<2-4|V~h1kyWEdZhQiBHaRV-;9MsKM^0;Nu2;McOSRM Iu7vb|09r^G=>Px# literal 0 HcmV?d00001 From 5a519e372da882aeb1858af651d6602df02e8b2f Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.comā©> Date: Thu, 8 Dec 2022 23:12:30 +0100 Subject: [PATCH 08/13] remove remnant of merge conflict --- apps/weather/ChangeLog | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/weather/ChangeLog b/apps/weather/ChangeLog index 359cb8635..f1d001c81 100644 --- a/apps/weather/ChangeLog +++ b/apps/weather/ChangeLog @@ -19,4 +19,3 @@ 0.20: Added weather condition with temperature to clkinfo. 0.21: Updated clkinfo icon. 0.22: Automatic translation of strings, some left untranslated. ->>>>>>> b37fcacd1 (weather - autotranslate strings) From aa1e485db8dbd1483db4928a9934189a5dca9dcb Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 9 Dec 2022 08:34:50 +0000 Subject: [PATCH 09/13] 0.59: Ensure we do write messages if messages app can't be fast loaded (see #2373) --- apps/messagegui/ChangeLog | 1 + apps/messagegui/lib.js | 5 ++++- apps/messagegui/metadata.json | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/messagegui/ChangeLog b/apps/messagegui/ChangeLog index 3e18b9885..3f5ff70fd 100644 --- a/apps/messagegui/ChangeLog +++ b/apps/messagegui/ChangeLog @@ -81,3 +81,4 @@ 0.57: Fix "unread Timeout" = off (previously defaulted to 60s) 0.58: Fast load messages without writing to flash Don't write messages to flash until the app closes +0.59: Ensure we do write messages if messages app can't be fast loaded (see #2373) diff --git a/apps/messagegui/lib.js b/apps/messagegui/lib.js index 4e1e7e11d..f9919c01c 100644 --- a/apps/messagegui/lib.js +++ b/apps/messagegui/lib.js @@ -18,8 +18,11 @@ exports.listener = function(type, msg) { if (Bangle.CLOCK && msg.state && msg.title && appSettings.openMusic) loadMessages = true; else return; } - if (Bangle.load === load) { + if (Bangle.load === load || !Bangle.uiRemove) { // no fast loading: store message to flash + /* FIXME: Maybe we need a better way of deciding if an app will + be fast loaded than just hard-coding a Bangle.uiRemove check. + Bangle.load could return a bool (as the load doesn't happen immediately). */ require("messages").save(msg); } else { if (!Bangle.MESSAGES) Bangle.MESSAGES = []; diff --git a/apps/messagegui/metadata.json b/apps/messagegui/metadata.json index ad7a87675..3ed22d356 100644 --- a/apps/messagegui/metadata.json +++ b/apps/messagegui/metadata.json @@ -1,7 +1,8 @@ { "id": "messagegui", "name": "Message UI", - "version": "0.58", + "sortName": "Messages", + "version": "0.59", "description": "Default app to display notifications from iOS and Gadgetbridge/Android", "icon": "app.png", "type": "app", From 7b18f54a76e9265c648ef7aab826a2fa83db73ac Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 9 Dec 2022 08:44:11 +0000 Subject: [PATCH 10/13] oops --- apps/messagegui/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/messagegui/metadata.json b/apps/messagegui/metadata.json index 3ed22d356..80b362551 100644 --- a/apps/messagegui/metadata.json +++ b/apps/messagegui/metadata.json @@ -1,7 +1,7 @@ { "id": "messagegui", "name": "Message UI", - "sortName": "Messages", + "shortName": "Messages", "version": "0.59", "description": "Default app to display notifications from iOS and Gadgetbridge/Android", "icon": "app.png", From 00a022c7c1102ab6bb22b0a78f28a71a01e7f3da Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 9 Dec 2022 09:49:33 +0000 Subject: [PATCH 11/13] Use 'modules/suncalc.js' to avoid it being copied 8 times for different apps --- apps/astrocalc/ChangeLog | 1 + apps/astrocalc/astrocalc-app.js | 4 +- apps/astrocalc/metadata.json | 3 +- apps/astrocalc/suncalc.js | 328 -------------------------- apps/daisy/ChangeLog | 1 + apps/daisy/app.js | 20 +- apps/daisy/metadata.json | 2 +- apps/hworldclock/ChangeLog | 1 + apps/hworldclock/app.js | 60 +++-- apps/hworldclock/hsuncalc.js | 298 ----------------------- apps/hworldclock/metadata.json | 9 +- apps/pastel/ChangeLog | 1 + apps/pastel/metadata.json | 2 +- apps/pastel/pastel.app.js | 22 +- apps/rebble/ChangeLog | 7 +- apps/rebble/metadata.json | 5 +- apps/rebble/rebble.app.js | 30 +-- apps/rebble/suncalc.js | 143 ----------- apps/sunclock/ChangeLog | 2 + apps/sunclock/app.js | 20 +- apps/sunclock/metadata.json | 5 +- apps/timerclk/ChangeLog | 1 + apps/timerclk/app.js | 6 +- apps/timerclk/metadata.json | 4 +- {apps/sunclock => modules}/suncalc.js | 83 +++++-- 25 files changed, 171 insertions(+), 887 deletions(-) delete mode 100644 apps/astrocalc/suncalc.js delete mode 100644 apps/hworldclock/hsuncalc.js delete mode 100644 apps/rebble/suncalc.js create mode 100644 apps/sunclock/ChangeLog rename {apps/sunclock => modules}/suncalc.js (76%) diff --git a/apps/astrocalc/ChangeLog b/apps/astrocalc/ChangeLog index 60ef5da0a..746ab2162 100644 --- a/apps/astrocalc/ChangeLog +++ b/apps/astrocalc/ChangeLog @@ -1,2 +1,3 @@ 0.01: Create astrocalc app 0.02: Store last GPS lock, can be used instead of waiting for new GPS on start +0.03: Use 'modules/suncalc.js' to avoid it being copied 8 times for different apps diff --git a/apps/astrocalc/astrocalc-app.js b/apps/astrocalc/astrocalc-app.js index 4e7aa0b40..46fb855ec 100644 --- a/apps/astrocalc/astrocalc-app.js +++ b/apps/astrocalc/astrocalc-app.js @@ -9,7 +9,7 @@ * Calculate the Sun and Moon positions based on watch GPS and display graphically */ -const SunCalc = require("suncalc.js"); +const SunCalc = require("suncalc"); // from modules folder const storage = require("Storage"); const LAST_GPS_FILE = "astrocalc.gps.json"; let lastGPS = (storage.readJSON(LAST_GPS_FILE, 1) || null); @@ -385,4 +385,4 @@ function init() { } let m; -init(); \ No newline at end of file +init(); diff --git a/apps/astrocalc/metadata.json b/apps/astrocalc/metadata.json index 384c7fa1e..d77474700 100644 --- a/apps/astrocalc/metadata.json +++ b/apps/astrocalc/metadata.json @@ -1,7 +1,7 @@ { "id": "astrocalc", "name": "Astrocalc", - "version": "0.02", + "version": "0.03", "description": "Calculates interesting information on the sun and moon cycles for the current day based on your location.", "icon": "astrocalc.png", "tags": "app,sun,moon,cycles,tool,outdoors", @@ -9,7 +9,6 @@ "allow_emulator": true, "storage": [ {"name":"astrocalc.app.js","url":"astrocalc-app.js"}, - {"name":"suncalc.js","url":"suncalc.js"}, {"name":"astrocalc.img","url":"astrocalc-icon.js","evaluate":true}, {"name":"first-quarter.img","url":"first-quarter-icon.js","evaluate":true}, {"name":"last-quarter.img","url":"last-quarter-icon.js","evaluate":true}, diff --git a/apps/astrocalc/suncalc.js b/apps/astrocalc/suncalc.js deleted file mode 100644 index e2beaedca..000000000 --- a/apps/astrocalc/suncalc.js +++ /dev/null @@ -1,328 +0,0 @@ -/* - (c) 2011-2015, Vladimir Agafonkin - SunCalc is a JavaScript library for calculating sun/moon position and light phases. - https://github.com/mourner/suncalc -*/ - -(function () { 'use strict'; - - // shortcuts for easier to read formulas - - var PI = Math.PI, - sin = Math.sin, - cos = Math.cos, - tan = Math.tan, - asin = Math.asin, - atan = Math.atan2, - acos = Math.acos, - rad = PI / 180; - - // sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas - - - // date/time constants and conversions - - var dayMs = 1000 * 60 * 60 * 24, - J1970 = 2440588, - J2000 = 2451545; - - function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } - function fromJulian(j) { return (j + 0.5 - J1970) * dayMs; } - function toDays(date) { return toJulian(date) - J2000; } - - - // general calculations for position - - var e = rad * 23.4397; // obliquity of the Earth - - function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } - function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } - - function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } - function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } - - function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } - - function astroRefraction(h) { - if (h < 0) // the following formula works for positive altitudes only. - h = 0; // if h = -0.08901179 a div/0 would occur. - - // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. - // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: - return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); - } - - // general sun calculations - - function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } - - function eclipticLongitude(M) { - - var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center - P = rad * 102.9372; // perihelion of the Earth - - return M + C + P + PI; - } - - function sunCoords(d) { - - var M = solarMeanAnomaly(d), - L = eclipticLongitude(M); - - return { - dec: declination(L, 0), - ra: rightAscension(L, 0) - }; - } - - - var SunCalc = {}; - - - // calculates sun position for a given date and latitude/longitude - - SunCalc.getPosition = function (date, lat, lng) { - - var lw = rad * -lng, - phi = rad * lat, - d = toDays(date), - - c = sunCoords(d), - H = siderealTime(d, lw) - c.ra; - - return { - azimuth: azimuth(H, phi, c.dec), - altitude: altitude(H, phi, c.dec) - }; - }; - - - // sun times configuration (angle, morning name, evening name) - - var times = SunCalc.times = [ - [-0.833, 'sunrise', 'sunset' ], - [ -0.3, 'sunriseEnd', 'sunsetStart' ], - [ -6, 'dawn', 'dusk' ], - [ -12, 'nauticalDawn', 'nauticalDusk'], - [ -18, 'nightEnd', 'night' ], - [ 6, 'goldenHourEnd', 'goldenHour' ] - ]; - - // adds a custom time to the times config - - SunCalc.addTime = function (angle, riseName, setName) { - times.push([angle, riseName, setName]); - }; - - - // calculations for sun times - - var J0 = 0.0009; - - function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } - - function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } - function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } - - function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } - function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } - - // returns set time for the given sun altitude - function getSetJ(h, lw, phi, dec, n, M, L) { - - var w = hourAngle(h, phi, dec), - a = approxTransit(w, lw, n); - return solarTransitJ(a, M, L); - } - - - // calculates sun times for a given date, latitude/longitude, and, optionally, - // the observer height (in meters) relative to the horizon - - SunCalc.getTimes = function (date, lat, lng, height) { - - height = height || 0; - - var lw = rad * -lng, - phi = rad * lat, - - dh = observerAngle(height), - - d = toDays(date), - n = julianCycle(d, lw), - ds = approxTransit(0, lw, n), - - M = solarMeanAnomaly(ds), - L = eclipticLongitude(M), - dec = declination(L, 0), - - Jnoon = solarTransitJ(ds, M, L), - - i, len, time, h0, Jset, Jrise; - - - var result = { - solarNoon: new Date(fromJulian(Jnoon)), - nadir: new Date(fromJulian(Jnoon - 0.5)) - }; - - for (i = 0, len = times.length; i < len; i += 1) { - time = times[i]; - h0 = (time[0] + dh) * rad; - - Jset = getSetJ(h0, lw, phi, dec, n, M, L); - Jrise = Jnoon - (Jset - Jnoon); - - result[time[1]] = new Date(fromJulian(Jrise) - (dayMs / 2)); - result[time[2]] = new Date(fromJulian(Jset) + (dayMs / 2)); - } - - return result; - }; - - - // moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas - - function moonCoords(d) { // geocentric ecliptic coordinates of the moon - - var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude - M = rad * (134.963 + 13.064993 * d), // mean anomaly - F = rad * (93.272 + 13.229350 * d), // mean distance - - l = L + rad * 6.289 * sin(M), // longitude - b = rad * 5.128 * sin(F), // latitude - dt = 385001 - 20905 * cos(M); // distance to the moon in km - - return { - ra: rightAscension(l, b), - dec: declination(l, b), - dist: dt - }; - } - - SunCalc.getMoonPosition = function (date, lat, lng) { - - var lw = rad * -lng, - phi = rad * lat, - d = toDays(date), - - c = moonCoords(d), - H = siderealTime(d, lw) - c.ra, - h = altitude(H, phi, c.dec), - // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. - pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); - - h = h + astroRefraction(h); // altitude correction for refraction - - return { - azimuth: azimuth(H, phi, c.dec), - altitude: h, - distance: c.dist, - parallacticAngle: pa - }; - }; - - - // calculations for illumination parameters of the moon, - // based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and - // Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. - - // Function updated from gist: https://gist.github.com/endel/dfe6bb2fbe679781948c - - SunCalc.getMoonIllumination = function (date) { - let month = date.getMonth(); - let year = date.getFullYear(); - let day = date.getDate(); - - let c = 0; - let e = 0; - let jd = 0; - let b = 0; - - if (month < 3) { - year--; - month += 12; - } - - ++month; - c = 365.25 * year; - e = 30.6 * month; - jd = c + e + day - 694039.09; // jd is total days elapsed - jd /= 29.5305882; // divide by the moon cycle - b = parseInt(jd); // int(jd) -> b, take integer part of jd - jd -= b; // subtract integer part to leave fractional part of original jd - b = Math.round(jd * 8); // scale fraction from 0-8 and round - - if (b >= 8) b = 0; // 0 and 8 are the same so turn 8 into 0 - - return {phase: b}; - }; - - - function hoursLater(date, h) { - return new Date(date.valueOf() + h * dayMs / 24); - } - - // calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article - - SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { - var t = date; - if (inUTC) t.setUTCHours(0, 0, 0, 0); - else t.setHours(0, 0, 0, 0); - - var hc = 0.133 * rad, - h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, - h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; - - // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) - for (var i = 1; i <= 24; i += 2) { - h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; - h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; - - a = (h0 + h2) / 2 - h1; - b = (h2 - h0) / 2; - xe = -b / (2 * a); - ye = (a * xe + b) * xe + h1; - d = b * b - 4 * a * h1; - roots = 0; - - if (d >= 0) { - dx = Math.sqrt(d) / (Math.abs(a) * 2); - x1 = xe - dx; - x2 = xe + dx; - if (Math.abs(x1) <= 1) roots++; - if (Math.abs(x2) <= 1) roots++; - if (x1 < -1) x1 = x2; - } - - if (roots === 1) { - if (h0 < 0) rise = i + x1; - else set = i + x1; - - } else if (roots === 2) { - rise = i + (ye < 0 ? x2 : x1); - set = i + (ye < 0 ? x1 : x2); - } - - if (rise && set) break; - - h0 = h2; - } - - var result = {}; - - if (rise) result.rise = hoursLater(t, rise); - if (set) result.set = hoursLater(t, set); - - if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; - - return result; - }; - - - // export as Node module / AMD module / browser variable - if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; - else if (typeof define === 'function' && define.amd) define(SunCalc); - else global.SunCalc = SunCalc; - -}()); diff --git a/apps/daisy/ChangeLog b/apps/daisy/ChangeLog index b13ce261b..61a09a18d 100644 --- a/apps/daisy/ChangeLog +++ b/apps/daisy/ChangeLog @@ -6,3 +6,4 @@ 0.06: better contrast for light theme, use fg color instead of dithered for ring 0.07: Use default Bangle formatter for booleans 0.08: fix idle timer always getting set to true +0.09: Use 'modules/suncalc.js' to avoid it being copied 8 times for different apps diff --git a/apps/daisy/app.js b/apps/daisy/app.js index 848cd1801..c99b19228 100644 --- a/apps/daisy/app.js +++ b/apps/daisy/app.js @@ -1,4 +1,4 @@ -var SunCalc = require("https://raw.githubusercontent.com/mourner/suncalc/master/suncalc.js"); +var SunCalc = require("suncalc"); // from modules folder const storage = require('Storage'); const locale = require("locale"); const SETTINGS_FILE = "daisy.json"; @@ -70,7 +70,7 @@ function getSteps() { try { return Bangle.getHealthStatus("day").steps; } catch (e) { - if (WIDGETS.wpedom !== undefined) + if (WIDGETS.wpedom !== undefined) return WIDGETS.wpedom.getSteps(); else return 0; @@ -151,7 +151,7 @@ function prevInfo() { function clearInfo() { g.setColor(g.theme.bg); //g.setColor(g.theme.fg); - g.fillRect((w/2) - infoWidth, infoLine - infoHeight, (w/2) + infoWidth, infoLine + infoHeight); + g.fillRect((w/2) - infoWidth, infoLine - infoHeight, (w/2) + infoWidth, infoLine + infoHeight); } function drawInfo() { @@ -202,7 +202,7 @@ function drawClock() { var mm = da[4].substr(3,2); var steps = getSteps(); var p_steps = Math.round(100*(steps/10000)); - + g.reset(); g.setColor(g.theme.bg); g.fillRect(0, 0, w, h); @@ -218,7 +218,7 @@ function drawClock() { g.drawString(mm, (w/2) + 1, h/2); drawInfo(); - + // recalc sunrise / sunset every hour if (drawCount % 60 == 0) updateSunRiseSunSet(new Date(), location.lat, location.lon); @@ -254,7 +254,7 @@ function resetHrm() { Bangle.on('HRM', function(hrm) { hrmCurrent = hrm.bpm; hrmConfidence = hrm.confidence; - log_debug("HRM=" + hrm.bpm + " (" + hrm.confidence + ")"); + log_debug("HRM=" + hrm.bpm + " (" + hrm.confidence + ")"); if (infoMode == "ID_HRM" ) drawHrm(); }); @@ -360,7 +360,7 @@ function getGaugeImage(p) { palette : pal2, buffer : require("heatshrink").decompress(atob("AH4A/AH4AChWq1WpqtUFUgpBFYYABoApggQqDFYlVqBVjFYxZfFQorGLLrWCFZbgbVguoBQcFLD8qFQYMHiosDKzoOJFgZYYKwYPLFgZWawARMLDJWCawgAJcAZWYCZ6FCLCkKFQOgCZ8BFYNUFaZWSLAlAQShWQLAiESQQRtTLAKESFQOoFacFQiSCCwArTgCESQSyEUlTZTboyCnQiSCYQiSCYQiSCZQgdAVxwqYQgSwMVwOoFbMFWBquaWCArBVzKwDbRoqaWATcKbQKuaWAbcKbQKuaWAbcKVzqwNFYIqcWATaKVziwDbhDaebhjaebhgrBbTrcCFZDafbheqFcTcHbT7cDFY0CbT7cDqArxhWqwArfgFVqgrHFUDcBFY0qFcdVFY2oFcMFFY2qFclAFYugFcMBFYsCFctQFYuAFcMAFYsKFctUFYoqigEVFeEqFctVFYmoFccFFYmqFc1AcIdQFccBFf4rbGAoAhKQYr/Fa8FFc9UFYYqkgEVFf4r/FYwDDAEZTDFf4r/Ff4rbqorooArBqArlgIr/Ff4r/Ff4r/Ff4r/Ff4r/Ff4r/Ff4rbqgrlgorCioroAYIr/Ff4r/FbYDDAEZTDFf4r/FYtAFclVFYUBFc9QFf4rZAgoAgKQor/FbFUFccFFYkVFcwFDioFEAD4lFGIorgPogrtWoYAfqorEgIrlqArFAwgAdEg4rlPgqKFADrUHcQorfA4sVA4wAbEY4zHFbh7GRY4AbaY7jBqAqfERArrMBAAZUxNVbkEVFZAJBFcJhRAC6lJFYLcebQIrIBRTaXJhIrhUhLcfD5YLBbjtVFZTceZ5jceJRpkLVyaiLWDpJNFYKwaUIIrMSIKwaDhw6OVx50NFYKwZDZ6waOaCTBQjBGBZZw8CQi4ZBOR6EYeySEYQSCEaQSITDH6BvGIaKEWQSSEEbqQVVQgRYSKwLGUQgRCQKwTFUC4RYQKwSCTDAhEONQTwULAqcNCARWVLAhGMB55YPDhQqDKy4dFFhAMMLCzgFawZWbEI4AIGogAYFZtAFbgsMFTyyGVkBZOKr7gJazoA/AHIA=")) }; - + // p90 if (p >= 90 && p < 100) return { width : 176, height : 176, bpp : 2, @@ -410,7 +410,7 @@ function BUTTON(name,x,y,w,h,c,f,tx) { // if pressed the callback BUTTON.prototype.check = function(x,y) { //console.log(this.name + ":check() x=" + x + " y=" + y +"\n"); - + if (x>= this.x && x<= (this.x + this.w) && y>= this.y && y<= (this.y + this.h)) { log_debug(this.name + ":callback\n"); this.callback(); @@ -472,7 +472,7 @@ function checkIdle() { warned = false; return; } - + let hour = (new Date()).getHours(); let active = (hour >= 9 && hour < 21); //let active = true; @@ -501,7 +501,7 @@ function buzzer(n) { if (n-- < 1) return; Bangle.buzz(250); - + if (buzzTimeout) clearTimeout(buzzTimeout); buzzTimeout = setTimeout(function() { buzzTimeout = undefined; diff --git a/apps/daisy/metadata.json b/apps/daisy/metadata.json index c6cc93620..0bad50151 100644 --- a/apps/daisy/metadata.json +++ b/apps/daisy/metadata.json @@ -1,6 +1,6 @@ { "id": "daisy", "name": "Daisy", - "version":"0.08", + "version":"0.09", "dependencies": {"mylocation":"app"}, "description": "A beautiful digital clock with large ring guage, idle timer and a cyclic information line that includes, day, date, steps, battery, sunrise and sunset times", "icon": "app.png", diff --git a/apps/hworldclock/ChangeLog b/apps/hworldclock/ChangeLog index c029b432f..13e3fa809 100644 --- a/apps/hworldclock/ChangeLog +++ b/apps/hworldclock/ChangeLog @@ -12,3 +12,4 @@ 0.26: BJS2: Swipe down to rotate 180 degree 0.27: BJS2: Changed swipe down to swipe up 0.28: Reverted changes to implementation of 0.25 +0.29: Use 'modules/suncalc.js' to avoid it being copied 8 times for different apps diff --git a/apps/hworldclock/app.js b/apps/hworldclock/app.js index c80b712da..6bd30be8e 100644 --- a/apps/hworldclock/app.js +++ b/apps/hworldclock/app.js @@ -15,7 +15,7 @@ require("Font5x9Numeric7Seg").add(Graphics); require("FontTeletext10x18Ascii").add(Graphics); // Font for single secondary time -const secondaryTimeFontSize = 4; +const secondaryTimeFontSize = 4; const secondaryTimeZoneFontSize = 2; // Font / columns for multiple secondary times @@ -39,14 +39,14 @@ const yposWorld = big ? 170 : 120; const OFFSET_TIME_ZONE = 0; const OFFSET_HOURS = 1; -var PosInterval = 0; +var PosInterval = 0; var offsets = require("Storage").readJSON("hworldclock.settings.json") || []; //=======Sun setting = require("Storage").readJSON("setting.json",1); E.setTimeZone(setting.timezone); // timezone = 1 for MEZ, = 2 for MESZ -SunCalc = require("hsuncalc.js"); +SunCalc = require("suncalc"); // from modules folder const LOCATION_FILE = "mylocation.json"; var rise = "read"; var set = "..."; @@ -87,7 +87,7 @@ const mockOffsets = { //offsets = mockOffsets.fourOffsets; // should render in columns // END TESTING CODE - + // Load settings function loadMySettings() { @@ -141,11 +141,9 @@ function getCurrentTimeFromOffset(dt, offset) { function updatePos() { coord = require("Storage").readJSON(LOCATION_FILE,1)|| {"lat":0,"lon":0,"location":"-"}; //{"lat":53.3,"lon":10.1,"location":"Pattensen"}; if (coord.lat != 0 && coord.lon != 0) { - //pos = SunCalc.getPosition(Date.now(), coord.lat, coord.lon); times = SunCalc.getTimes(Date.now(), coord.lat, coord.lon); rise = "^" + times.sunrise.toString().split(" ")[4].substr(0,5); set = "v" + times.sunset.toString().split(" ")[4].substr(0,5); - //noonpos = SunCalc.getPosition(times.solarNoon, coord.lat, coord.lon); } else { rise = null; set = null; @@ -179,7 +177,7 @@ function drawSeconds() { //console.log(seconds); if (Bangle.isLocked() && secondsMode != "always") seconds = seconds.slice(0, -1) + ':::'; // we use :: as the font does not have an x //console.log(seconds); - g.drawString(`${seconds}`, xyCenterSeconds, yposTime+14, true); + g.drawString(`${seconds}`, xyCenterSeconds, yposTime+14, true); queueDrawSeconds(); } @@ -196,18 +194,18 @@ function draw() { let time = da[4].split(":"); let hours = time[0], minutes = time[1]; - - + + if (_12hour){ //do 12 hour stuff if (hours > 12) { ampm = "PM"; - hours = hours - 12; - if (hours < 10) hours = doublenum(hours); + hours = hours - 12; + if (hours < 10) hours = doublenum(hours); } else { - ampm = "AM"; - } - } + ampm = "AM"; + } + } //g.setFont(font, primaryTimeFontSize); g.setFont("5x9Numeric7Seg",primaryTimeFontSize); @@ -221,18 +219,18 @@ function draw() { g.setColor(g.theme.fg); } g.drawString(`${hours}:${minutes}`, xyCenter-10, yposTime, true); - + // am / PM ? if (_12hour){ //do 12 hour stuff //let ampm = require("locale").medidian(new Date()); Not working g.setFont("Vector", 17); g.drawString(ampm, xyCenterSeconds, yAmPm, true); - } + } if (secondsMode != "none") drawSeconds(); // To make sure... - - // draw Day, name of month, Date + + // draw Day, name of month, Date //DATE let localDate = require("locale").date(new Date(), 1); localDate = localDate.substring(0, localDate.length - 5); @@ -251,7 +249,7 @@ function draw() { if (offsets.length === 1) { - let date = [require("locale").dow(new Date(), 1), require("locale").date(new Date(), 1)]; + let date = [require("locale").dow(new Date(), 1), require("locale").date(new Date(), 1)]; // For a single secondary timezone, draw it bigger and drop time zone to second line const xOffset = 30; g.setFont(font, secondaryTimeFontSize).drawString(`${hours}:${minutes}`, xyCenter, yposTime2, true); @@ -277,7 +275,7 @@ function draw() { g.setFontAlign(-1, 0).setFont("Vector",12).drawString(`${rise}`, 10, 3 + yposWorld + 3 * 15, true); // draw rise g.setFontAlign(1, 0).drawString(`${set}`, xcol2, 3 + yposWorld + 3 * 15, true); // draw set } else { - g.setFontAlign(-1, 0).setFont("Vector",11).drawString("set city in \'my location\' app!", 10, 3 + yposWorld + 3 * 15, true); + g.setFontAlign(-1, 0).setFont("Vector",11).drawString("set city in \'my location\' app!", 10, 3 + yposWorld + 3 * 15, true); } } //debug settings @@ -287,7 +285,7 @@ function draw() { //g.drawString(colorWhenDark, xcol2, 3 + yposWorld + 3 * 15, true); queueDraw(); - + if (secondsMode != "none") queueDrawSeconds(); } @@ -307,7 +305,7 @@ Bangle.setUI({ if (drawTimeoutSeconds) clearTimeout(drawTimeoutSeconds); drawTimeoutSeconds = undefined; if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = undefined; + drawTimeout = undefined; }}); Bangle.loadWidgets(); Bangle.drawWidgets(); @@ -328,15 +326,15 @@ if (!Bangle.isLocked()) { // Initial state if (secondsMode != "none") { if (drawTimeoutSeconds) clearTimeout(drawTimeoutSeconds); drawTimeoutSeconds = undefined; - } + } if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; draw(); // draw immediately, queue redraw - + }else{ if (secondsMode == "always") secondsTimeout = 1000; if (secondsMode == "when unlocked") secondsTimeout = 10 * 1000; - + if (secondsMode != "none") { if (drawTimeoutSeconds) clearTimeout(drawTimeoutSeconds); drawTimeoutSeconds = undefined; @@ -350,9 +348,9 @@ if (!Bangle.isLocked()) { // Initial state updatePos(); } draw(); // draw immediately, queue redraw - + } - + Bangle.on('lock',on=>{ if (!on) { // UNlocked @@ -366,7 +364,7 @@ Bangle.on('lock',on=>{ if (secondsMode != "none") { if (drawTimeoutSeconds) clearTimeout(drawTimeoutSeconds); drawTimeoutSeconds = undefined; - } + } if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; @@ -375,7 +373,7 @@ Bangle.on('lock',on=>{ if (secondsMode == "always") secondsTimeout = 1000; if (secondsMode == "when unlocked") secondsTimeout = 10 * 1000; - + if (secondsMode != "none") { if (drawTimeoutSeconds) clearTimeout(drawTimeoutSeconds); drawTimeoutSeconds = undefined; @@ -388,7 +386,7 @@ Bangle.on('lock',on=>{ PosInterval = setInterval(updatePos, 60*60E3); // refesh every 60 mins updatePos(); } - draw(); // draw immediately, queue redraw + draw(); // draw immediately, queue redraw } }); -} \ No newline at end of file +} diff --git a/apps/hworldclock/hsuncalc.js b/apps/hworldclock/hsuncalc.js deleted file mode 100644 index b1af0a0d9..000000000 --- a/apps/hworldclock/hsuncalc.js +++ /dev/null @@ -1,298 +0,0 @@ -/* Module suncalc.js - (c) 2011-2015, Vladimir Agafonkin - SunCalc is a JavaScript library for calculating sun/moon position and light phases. - https://github.com/mourner/suncalc - -PB: Usage: -E.setTimeZone(2); // 1 = MEZ, 2 = MESZ -SunCalc = require("suncalc.js"); -pos = SunCalc.getPosition(Date.now(), 53.3, 10.1); -times = SunCalc.getTimes(Date.now(), 53.3, 10.1); -rise = times.sunrise; // Date object -rise_str = rise.getHours() + ':' + rise.getMinutes(); //hh:mm -*/ -var exports={}; - -// shortcuts for easier to read formulas - -var PI = Math.PI, - sin = Math.sin, - cos = Math.cos, - tan = Math.tan, - asin = Math.asin, - atan = Math.atan2, - acos = Math.acos, - rad = PI / 180; - -// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas - -// date/time constants and conversions - -var dayMs = 1000 * 60 * 60 * 24, - J1970 = 2440588, - J2000 = 2451545; - -function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } -function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } // PB: onece removed + 0.5; included it again 4 Jan 2021 -function toDays(date) { return toJulian(date) - J2000; } - - -// general calculations for position - -var e = rad * 23.4397; // obliquity of the Earth - -function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } -function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } - -function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } -function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } - -function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } - -function astroRefraction(h) { - if (h < 0) // the following formula works for positive altitudes only. - h = 0; // if h = -0.08901179 a div/0 would occur. - - // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. - // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: - return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); -} - -// general sun calculations - -function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } - -function eclipticLongitude(M) { - - var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center - P = rad * 102.9372; // perihelion of the Earth - - return M + C + P + PI; -} - -function sunCoords(d) { - - var M = solarMeanAnomaly(d), - L = eclipticLongitude(M); - - return { - dec: declination(L, 0), - ra: rightAscension(L, 0) - }; -} - -// calculates sun position for a given date and latitude/longitude - -exports.getPosition = function (date, lat, lng) { - - var lw = rad * -lng, - phi = rad * lat, - d = toDays(date), - - c = sunCoords(d), - H = siderealTime(d, lw) - c.ra; - - return { - azimuth: Math.round((azimuth(H, phi, c.dec) / rad + 180) % 360), // PB: converted to deg - altitude: Math.round( altitude(H, phi, c.dec) / rad) // PB: converted to deg - }; -}; - - -// sun times configuration (angle, morning name, evening name) - -var times = [ - [-0.833, 'sunrise', 'sunset' ] -]; - -// calculations for sun times -var J0 = 0.0009; - -function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } - -function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } -function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } - -function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } -function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } - -// returns set time for the given sun altitude -function getSetJ(h, lw, phi, dec, n, M, L) { - - var w = hourAngle(h, phi, dec), - a = approxTransit(w, lw, n); - return solarTransitJ(a, M, L); -} - - -// calculates sun times for a given date, latitude/longitude, and, optionally, -// the observer height (in meters) relative to the horizon - -exports.getTimes = function (date, lat, lng, height) { - - height = height || 0; - - var lw = rad * -lng, - phi = rad * lat, - - dh = observerAngle(height), - - d = toDays(date), - n = julianCycle(d, lw), - ds = approxTransit(0, lw, n), - - M = solarMeanAnomaly(ds), - L = eclipticLongitude(M), - dec = declination(L, 0), - - Jnoon = solarTransitJ(ds, M, L), - - i, len, time, h0, Jset, Jrise; - - - var result = { - solarNoon: fromJulian(Jnoon), - nadir: fromJulian(Jnoon - 0.5) - }; - - for (i = 0, len = times.length; i < len; i += 1) { - time = times[i]; - h0 = (time[0] + dh) * rad; - - Jset = getSetJ(h0, lw, phi, dec, n, M, L); - Jrise = Jnoon - (Jset - Jnoon); - - result[time[1]] = fromJulian(Jrise); - result[time[2]] = fromJulian(Jset); - } - - return result; -}; - - -// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas - -function moonCoords(d) { // geocentric ecliptic coordinates of the moon - - var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude - M = rad * (134.963 + 13.064993 * d), // mean anomaly - F = rad * (93.272 + 13.229350 * d), // mean distance - - l = L + rad * 6.289 * sin(M), // longitude - b = rad * 5.128 * sin(F), // latitude - dt = 385001 - 20905 * cos(M); // distance to the moon in km - - return { - ra: rightAscension(l, b), - dec: declination(l, b), - dist: dt - }; -} - -getMoonPosition = function (date, lat, lng) { - - var lw = rad * -lng, - phi = rad * lat, - d = toDays(date), - - c = moonCoords(d), - H = siderealTime(d, lw) - c.ra, - h = altitude(H, phi, c.dec), - // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. - pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); - - h = h + astroRefraction(h); // altitude correction for refraction - - return { - azimuth: azimuth(H, phi, c.dec), - altitude: h, - distance: c.dist, - parallacticAngle: pa - }; -}; - - -// calculations for illumination parameters of the moon, -// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and -// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. - -getMoonIllumination = function (date) { - - var d = toDays(date || new Date()), - s = sunCoords(d), - m = moonCoords(d), - - sdist = 149598000, // distance from Earth to Sun in km - - phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), - inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), - angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - - cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); - - return { - fraction: (1 + cos(inc)) / 2, - phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, - angle: angle - }; -}; - - -function hoursLater(date, h) { - return new Date(date.valueOf() + h * dayMs / 24); -} - -// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article - -getMoonTimes = function (date, lat, lng, inUTC) { - var t = new Date(date); - if (inUTC) t.setUTCHours(0, 0, 0, 0); - else t.setHours(0, 0, 0, 0); - - var hc = 0.133 * rad, - h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, - h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; - - // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) - for (var i = 1; i <= 24; i += 2) { - h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; - h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; - - a = (h0 + h2) / 2 - h1; - b = (h2 - h0) / 2; - xe = -b / (2 * a); - ye = (a * xe + b) * xe + h1; - d = b * b - 4 * a * h1; - roots = 0; - - if (d >= 0) { - dx = Math.sqrt(d) / (Math.abs(a) * 2); - x1 = xe - dx; - x2 = xe + dx; - if (Math.abs(x1) <= 1) roots++; - if (Math.abs(x2) <= 1) roots++; - if (x1 < -1) x1 = x2; - } - - if (roots === 1) { - if (h0 < 0) rise = i + x1; - else set = i + x1; - - } else if (roots === 2) { - rise = i + (ye < 0 ? x2 : x1); - set = i + (ye < 0 ? x1 : x2); - } - - if (rise && set) break; - - h0 = h2; - } - - var result = {}; - - if (rise) result.rise = hoursLater(t, rise); - if (set) result.set = hoursLater(t, set); - - if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; - - return result; -}; \ No newline at end of file diff --git a/apps/hworldclock/metadata.json b/apps/hworldclock/metadata.json index 587c05067..3b633ead7 100644 --- a/apps/hworldclock/metadata.json +++ b/apps/hworldclock/metadata.json @@ -2,7 +2,7 @@ "id": "hworldclock", "name": "Hanks World Clock", "shortName": "Hanks World Clock", - "version": "0.28", + "version": "0.29", "description": "Current time zone plus up to three others", "allow_emulator":true, "icon": "app.png", @@ -15,11 +15,10 @@ "storage": [ {"name":"hworldclock.app.js","url":"app.js"}, {"name":"hworldclock.img","url":"hworldclock-icon.js","evaluate":true}, - {"name":"hworldclock.settings.js","url":"settings.js"}, - {"name":"hsuncalc.js","url":"hsuncalc.js"} + {"name":"hworldclock.settings.js","url":"settings.js"} ], "data": [ {"name":"hworldclock.settings.json"}, - {"name":"hworldclock.json"} + {"name":"hworldclock.json"} ] -} \ No newline at end of file +} diff --git a/apps/pastel/ChangeLog b/apps/pastel/ChangeLog index 28dcc0c28..02cef7774 100644 --- a/apps/pastel/ChangeLog +++ b/apps/pastel/ChangeLog @@ -19,3 +19,4 @@ 0.16: make check_idle boolean setting work properly with new B2 menu 0.17: Use default Bangle formatter for booleans 0.18: fix idle option always getting defaulted to true +0.19: Use 'modules/suncalc.js' to avoid it being copied 8 times for different apps diff --git a/apps/pastel/metadata.json b/apps/pastel/metadata.json index 860ed833b..cf4bbbe9b 100644 --- a/apps/pastel/metadata.json +++ b/apps/pastel/metadata.json @@ -2,7 +2,7 @@ "id": "pastel", "name": "Pastel Clock", "shortName": "Pastel", - "version": "0.18", + "version": "0.19", "description": "A Configurable clock with custom fonts, background and weather display. Has a cyclic information line that includes, day, date, battery, sunrise and sunset times", "icon": "pastel.png", "dependencies": {"mylocation":"app","weather":"app"}, diff --git a/apps/pastel/pastel.app.js b/apps/pastel/pastel.app.js index 05c0e2367..bc41588d8 100644 --- a/apps/pastel/pastel.app.js +++ b/apps/pastel/pastel.app.js @@ -1,4 +1,4 @@ -var SunCalc = require("https://raw.githubusercontent.com/mourner/suncalc/master/suncalc.js"); +var SunCalc = require("suncalc"); // from modules folder require("f_latosmall").add(Graphics); const storage = require('Storage'); const locale = require("locale"); @@ -85,7 +85,7 @@ function getSteps() { try { return Bangle.getHealthStatus("day").steps; } catch (e) { - if (WIDGETS.wpedom !== undefined) + if (WIDGETS.wpedom !== undefined) return WIDGETS.wpedom.getSteps(); else return '???'; @@ -181,12 +181,12 @@ function drawClock() { var d = new Date(); var da = d.toString().split(" "); var time = da[4].substr(0,5); - + var hh = da[4].substr(0,2); var mm = da[4].substr(3,2); var day = da[0]; var month_day = da[1] + " " + da[2]; - + // fix hh for 12hr clock var h2 = "0" + parseInt(hh) % 12 || 12; if (parseInt(hh) > 12) @@ -215,12 +215,12 @@ function drawClock() { g.reset(); g.setColor(g.theme.bg); g.fillRect(Bangle.appRect); - + // draw a grid like graph paper if (settings.grid && process.env.HWVERSION !=1) { g.setColor("#0f0"); for (var gx=20; gx <= w; gx += 20) - g.drawLine(gx, 30, gx, h - 24); + g.drawLine(gx, 30, gx, h - 24); for (var gy=30; gy <= h - 24; gy += 20) g.drawLine(0, gy, w, gy); } @@ -238,7 +238,7 @@ function drawClock() { g.drawString( (w_wind.split(' ').slice(0, 2).join(' ')), (w/2) + 6, 24 + ((y - 24)/2)); // display first 2 words of the wind string eg '4 mph' } - + if (settings.font == "Architect") g.setFontArchitect(); else if (settings.font == "GochiHand") @@ -253,7 +253,7 @@ function drawClock() { g.setFontSpecialElite(); else g.setFontLato(); - + g.setFontAlign(1,-1); // right aligned g.drawString(hh, x - 6, y); g.setFontAlign(-1,-1); // left aligned @@ -310,7 +310,7 @@ function BUTTON(name,x,y,w,h,c,f,tx) { // if pressed the callback BUTTON.prototype.check = function(x,y) { //console.log(this.name + ":check() x=" + x + " y=" + y +"\n"); - + if (x>= this.x && x<= (this.x + this.w) && y>= this.y && y<= (this.y + this.h)) { log_debug(this.name + ":callback\n"); this.callback(); @@ -366,7 +366,7 @@ function checkIdle() { warned = false; return; } - + let hour = (new Date()).getHours(); let active = (hour >= 9 && hour < 21); //let active = true; @@ -397,7 +397,7 @@ function buzzer(n) { if (n-- < 1) return; Bangle.buzz(250); - + if (buzzTimeout) clearTimeout(buzzTimeout); buzzTimeout = setTimeout(function() { buzzTimeout = undefined; diff --git a/apps/rebble/ChangeLog b/apps/rebble/ChangeLog index c009a4ec1..78ba0c5da 100644 --- a/apps/rebble/ChangeLog +++ b/apps/rebble/ChangeLog @@ -9,7 +9,8 @@ 0.09: fix battery icon size 0.10: Tell clock widgets to hide. 0.11: fix issue https://github.com/espruino/BangleApps/issues/2128 (#2128) ( settings undefined ) -0.12: implemented widget_utils +0.12: implemented widget_utils 0.13: convert var/function into let -0.14: cleanup code and fix fastload issue -0.15: fix draw before widget hide \ No newline at end of file +0.14: cleanup code and fix fastload issue +0.15: fix draw before widget hide +0.16: Use 'modules/suncalc.js' to avoid it being copied 8 times for different apps diff --git a/apps/rebble/metadata.json b/apps/rebble/metadata.json index 7042fcb95..c380204a4 100644 --- a/apps/rebble/metadata.json +++ b/apps/rebble/metadata.json @@ -2,7 +2,7 @@ "id": "rebble", "name": "Rebble Clock", "shortName": "Rebble", - "version": "0.15", + "version": "0.16", "description": "A Pebble style clock, with configurable background, three sidebars including steps, day, date, sunrise, sunset, long live the rebellion", "readme": "README.md", "icon": "rebble.png", @@ -14,7 +14,6 @@ "storage": [ {"name":"rebble.app.js","url":"rebble.app.js"}, {"name":"rebble.settings.js","url":"rebble.settings.js"}, - {"name":"rebble.img","url":"rebble.icon.js","evaluate":true}, - {"name":"suncalc","url":"suncalc.js"} + {"name":"rebble.img","url":"rebble.icon.js","evaluate":true} ] } diff --git a/apps/rebble/rebble.app.js b/apps/rebble/rebble.app.js index fd0c8f7f9..445c30125 100644 --- a/apps/rebble/rebble.app.js +++ b/apps/rebble/rebble.app.js @@ -11,7 +11,7 @@ Graphics.prototype.setFontKdamThmor = function(scale) { { - let SunCalc = require("suncalc"); + let SunCalc = require("suncalc"); // from modules folder const SETTINGS_FILE = "rebble.json"; const LOCATION_FILE = "mylocation.json"; const GLOBAL_SETTINGS = "setting.json"; @@ -49,7 +49,7 @@ Graphics.prototype.setFontKdamThmor = function(scale) { } if(settings.sideTap!=0) - sideBar=parseInt(settings.sideTap)-1; //tab to + sideBar=parseInt(settings.sideTap)-1; //tab to is12Hour = (require("Storage").readJSON(GLOBAL_SETTINGS, 1) || {})["12hour"] || false; } @@ -110,15 +110,15 @@ Graphics.prototype.setFontKdamThmor = function(scale) { let date = new Date(); let hh = date.getHours(); let mm = date.getMinutes(); - + hh = formatHours(hh); mm = zeroPad(mm,2); - + //const t = 6; if (drawCount % 60 == 0) updateSunRiseSunSet(location.lat, location.lon); - + g.reset(); g.setColor(g.theme.bg); g.fillRect(0, 0, w2, h); @@ -143,7 +143,7 @@ Graphics.prototype.setFontKdamThmor = function(scale) { drawSideBar3(); break; } - + drawCount++; queueDraw(); } @@ -154,14 +154,14 @@ Graphics.prototype.setFontKdamThmor = function(scale) { let dd=date.getDate(); let mm=require("date_utils").month(date.getMonth()+1,1).toUpperCase(); - + drawBattery(w2 + (w-w2-wb)/2, h/10, wb, 17); setTextColor(); g.setFont('Vector', 20); g.setFontAlign(0, -1); g.drawString(E.getBattery() + '%', w3, (h/10) + 17 + 7); - + drawDateAndCalendar(w3, h/2, dy, dd, mm); } @@ -250,7 +250,7 @@ Graphics.prototype.setFontKdamThmor = function(scale) { } } - + // format steps so they fit in the place let formatSteps=function() { let s = Bangle.getHealthStatus("day").steps; @@ -292,8 +292,8 @@ Graphics.prototype.setFontKdamThmor = function(scale) { - let chargingListener= function(charging) { - + let chargingListener= function(charging) { + //redraw the sidebar ( with the battery ) switch(sideBar) { case 0: @@ -304,7 +304,7 @@ Graphics.prototype.setFontKdamThmor = function(scale) { break; } } - + let deleteAll=function() { // Called to unload all of the clock app @@ -320,7 +320,7 @@ Graphics.prototype.setFontKdamThmor = function(scale) { log_debug("starting.."); loadSettings(); loadLocation(); - + if(settings.autoCycle || settings.sideTap==0) { Bangle.setUI({ @@ -332,7 +332,7 @@ Graphics.prototype.setFontKdamThmor = function(scale) { if (btn>0) nextSidebar(); draw(); }); - + } else{ Bangle.setUI({ @@ -354,4 +354,4 @@ Graphics.prototype.setFontKdamThmor = function(scale) { main(); -} \ No newline at end of file +} diff --git a/apps/rebble/suncalc.js b/apps/rebble/suncalc.js deleted file mode 100644 index d86f039c5..000000000 --- a/apps/rebble/suncalc.js +++ /dev/null @@ -1,143 +0,0 @@ -/* - (c) 2011-2015, Vladimir Agafonkin - SunCalc is a JavaScript library for calculating sun/moon position and light phases. - https://github.com/mourner/suncalc - - edit for banglejs -*/ - -(function () { 'use strict'; - -// shortcuts for easier to read formulas - -var PI = Math.PI, - sin = Math.sin, - cos = Math.cos, - tan = Math.tan, - asin = Math.asin, - atan = Math.atan2, - acos = Math.acos, - rad = PI / 180; - -// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas - - -// date/time constants and conversions - -var dayMs = 1000 * 60 * 60 * 24, - J1970 = 2440588, - J2000 = 2451545; - -function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } -function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } -function toDays(date) { return toJulian(date) - J2000; } - - -// general calculations for position - -var e = rad * 23.4397; // obliquity of the Earth - -function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } - - -// general sun calculations - -function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } - -function eclipticLongitude(M) { - - var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center - P = rad * 102.9372; // perihelion of the Earth - - return M + C + P + PI; -} - -var SunCalc = {}; - - -// sun times configuration (angle, morning name, evening name) - -var times = SunCalc.times = [ - [-0.833, 'sunrise', 'sunset' ], - [ -0.3, 'sunriseEnd', 'sunsetStart' ], - [ -6, 'dawn', 'dusk' ], - [ -12, 'nauticalDawn', 'nauticalDusk'], - [ -18, 'nightEnd', 'night' ], - [ 6, 'goldenHourEnd', 'goldenHour' ] -]; - - - -// calculations for sun times - -var J0 = 0.0009; - -function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } - -function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } -function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } - -function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } -function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } - -// returns set time for the given sun altitude -function getSetJ(h, lw, phi, dec, n, M, L) { - - var w = hourAngle(h, phi, dec), - a = approxTransit(w, lw, n); - return solarTransitJ(a, M, L); -} - - -// calculates sun times for a given date, latitude/longitude, and, optionally, -// the observer height (in meters) relative to the horizon - -SunCalc.getTimes = function (date, lat, lng, height) { - - height = height || 0; - - var lw = rad * -lng, - phi = rad * lat, - - dh = observerAngle(height), - - d = toDays(date), - n = julianCycle(d, lw), - ds = approxTransit(0, lw, n), - - M = solarMeanAnomaly(ds), - L = eclipticLongitude(M), - dec = declination(L, 0), - - Jnoon = solarTransitJ(ds, M, L), - - i, len, time, h0, Jset, Jrise; - - - var result = { - solarNoon: fromJulian(Jnoon), - nadir: fromJulian(Jnoon - 0.5) - }; - - for (i = 0, len = times.length; i < len; i += 1) { - time = times[i]; - h0 = (time[0] + dh) * rad; - - Jset = getSetJ(h0, lw, phi, dec, n, M, L); - Jrise = Jnoon - (Jset - Jnoon); - - result[time[1]] = fromJulian(Jrise); - result[time[2]] = fromJulian(Jset); - } - - return result; -}; - - -// export as Node module / AMD module / browser variable -if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; -else if (typeof define === 'function' && define.amd) define(SunCalc); -else window.SunCalc = SunCalc; - - -}()); \ No newline at end of file diff --git a/apps/sunclock/ChangeLog b/apps/sunclock/ChangeLog new file mode 100644 index 000000000..d63f1567e --- /dev/null +++ b/apps/sunclock/ChangeLog @@ -0,0 +1,2 @@ +0.01: First commit +0.02: Use 'modules/suncalc.js' to avoid it being copied 8 times for different apps diff --git a/apps/sunclock/app.js b/apps/sunclock/app.js index 4609565a2..1685bc218 100644 --- a/apps/sunclock/app.js +++ b/apps/sunclock/app.js @@ -9,8 +9,8 @@ SunCalc = require("suncalc.js"); loc = require('locale'); const LOCATION_FILE = "mylocation.json"; const xyCenter = g.getWidth() / 2 + 3; -const yposTime = 60; -const yposDate = 100; +const yposTime = 60; +const yposDate = 100; const yposRS = 135; const yposPos = 160; var rise = "07:00"; @@ -19,13 +19,21 @@ var pos = {altitude: 20, azimuth: 135}; var noonpos = {altitude: 37, azimuth: 180}; let idTimeout = null; + + function updatePos() { + function radToDeg(pos) { + return { // instead of mofidying suncalc + azimuth: Math.round((pos.azimuth / rad + 180) % 360), + altitude: Math.round( pos.altitude / rad) + }; + } coord = require("Storage").readJSON(LOCATION_FILE,1)|| {"lat":53.3,"lon":10.1,"location":"Pattensen"}; - pos = SunCalc.getPosition(Date.now(), coord.lat, coord.lon); + pos = radToDeg(SunCalc.getPosition(Date.now(), coord.lat, coord.lon)); times = SunCalc.getTimes(Date.now(), coord.lat, coord.lon); rise = times.sunrise.toString().split(" ")[4].substr(0,5); set = times.sunset.toString().split(" ")[4].substr(0,5); - noonpos = SunCalc.getPosition(times.solarNoon, coord.lat, coord.lon); + noonpos = radToDeg(SunCalc.getPosition(times.solarNoon, coord.lat, coord.lon)); } function drawSimpleClock() { @@ -38,7 +46,7 @@ function drawSimpleClock() { var time = da[4].substr(0, 5); // draw time - g.setFont("Vector",60); + g.setFont("Vector",60); g.drawString(time, xyCenter, yposTime, true); var date = [loc.dow(new Date(),1), loc.date(d,1)].join(" "); // draw day of week, date @@ -51,7 +59,7 @@ function drawSimpleClock() { g.setFont("Vector",21); g.drawString(`H${pos.altitude}/${noonpos.altitude} Az${pos.azimuth}`, xyCenter, yposPos, true); // draw sun pos - + let t = d.getSeconds()*1000 + d.getMilliseconds(); idTimeout = setTimeout(drawSimpleClock, 60000 - t); // time till next minute } diff --git a/apps/sunclock/metadata.json b/apps/sunclock/metadata.json index 617d76821..a9155f6f6 100644 --- a/apps/sunclock/metadata.json +++ b/apps/sunclock/metadata.json @@ -1,7 +1,7 @@ { "id": "sunclock", "name": "Sun Clock", - "version": "0.01", + "version": "0.02", "description": "A clock with sunset/sunrise, sun height/azimuth", "icon": "app.png", "type": "clock", @@ -11,7 +11,6 @@ "allow_emulator": true, "storage": [ {"name":"sunclock.app.js","url":"app.js"}, - {"name":"sunclock.img","url":"app-icon.js","evaluate":true}, - {"name":"suncalc.js","url":"suncalc.js"} + {"name":"sunclock.img","url":"app-icon.js","evaluate":true} ] } diff --git a/apps/timerclk/ChangeLog b/apps/timerclk/ChangeLog index 7a357b1aa..5a954d58c 100644 --- a/apps/timerclk/ChangeLog +++ b/apps/timerclk/ChangeLog @@ -1,3 +1,4 @@ 0.01: New App! 0.02: Add sunrise/sunset. Fix timer bugs. 0.03: Use default Bangle formatter for booleans +0.04: Use 'modules/suncalc.js' to avoid it being copied 8 times for different apps diff --git a/apps/timerclk/app.js b/apps/timerclk/app.js index c750fcfde..ee30b059a 100644 --- a/apps/timerclk/app.js +++ b/apps/timerclk/app.js @@ -3,7 +3,7 @@ Graphics.prototype.setFontAnton = function(scale) { 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)); }; -var SunCalc = require("https://raw.githubusercontent.com/mourner/suncalc/master/suncalc.js"); +var SunCalc = require("suncalc"); // from modules folder const LOCATION_FILE = "mylocation.json"; let location; var sunRise = "--:--"; @@ -72,7 +72,7 @@ function drawSpecial() { g.setFontAlign(0,0).setFont(settings.specialFont, settings.specialFontSize); var y = Bangle.appRect.y + g.stringMetrics("00:00").height/2; g.clearRect(Bangle.appRect.x, Bangle.appRect.y, Bangle.appRect.x2, Bangle.appRect.y+g.stringMetrics("00:00").height); - + if (stopwatches.length) { time = timerclk.getTime(stopwatches[stopwatch]); g.drawString(timerclk.formatTime(time, true), x, y); @@ -111,7 +111,7 @@ function draw() { var dateStr = require("locale").date(date,settings.shortDate).toUpperCase(); var dowStr = require("locale").dow(date).toUpperCase(); var srssStr = sunRise + sunIcons + sunSet; - + // draw time if (settings.timeFont == "Anton") { g.setFontAlign(0,0).setFont("Anton"); diff --git a/apps/timerclk/metadata.json b/apps/timerclk/metadata.json index 899eda59d..5bd6bee24 100644 --- a/apps/timerclk/metadata.json +++ b/apps/timerclk/metadata.json @@ -1,8 +1,8 @@ -{ +{ "id": "timerclk", "name": "Timer Clock", "shortName":"Timer Clock", - "version":"0.03", + "version":"0.04", "description": "A clock with stopwatches, timers and alarms build in.", "icon": "app-icon.png", "type": "clock", diff --git a/apps/sunclock/suncalc.js b/modules/suncalc.js similarity index 76% rename from apps/sunclock/suncalc.js rename to modules/suncalc.js index b1af0a0d9..0c22c6cb2 100644 --- a/apps/sunclock/suncalc.js +++ b/modules/suncalc.js @@ -1,17 +1,34 @@ -/* Module suncalc.js +/* (c) 2011-2015, Vladimir Agafonkin SunCalc is a JavaScript library for calculating sun/moon position and light phases. https://github.com/mourner/suncalc -PB: Usage: -E.setTimeZone(2); // 1 = MEZ, 2 = MESZ -SunCalc = require("suncalc.js"); -pos = SunCalc.getPosition(Date.now(), 53.3, 10.1); -times = SunCalc.getTimes(Date.now(), 53.3, 10.1); -rise = times.sunrise; // Date object -rise_str = rise.getHours() + ':' + rise.getMinutes(); //hh:mm +Copyright (c) 2014, Vladimir Agafonkin +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ -var exports={}; + +(function () { 'use strict'; // shortcuts for easier to read formulas @@ -26,6 +43,7 @@ var PI = Math.PI, // sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + // date/time constants and conversions var dayMs = 1000 * 60 * 60 * 24, @@ -33,7 +51,7 @@ var dayMs = 1000 * 60 * 60 * 24, J2000 = 2451545; function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } -function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } // PB: onece removed + 0.5; included it again 4 Jan 2021 +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } function toDays(date) { return toJulian(date) - J2000; } @@ -81,9 +99,13 @@ function sunCoords(d) { }; } + +var SunCalc = {}; + + // calculates sun position for a given date and latitude/longitude -exports.getPosition = function (date, lat, lng) { +SunCalc.getPosition = function (date, lat, lng) { var lw = rad * -lng, phi = rad * lat, @@ -93,19 +115,32 @@ exports.getPosition = function (date, lat, lng) { H = siderealTime(d, lw) - c.ra; return { - azimuth: Math.round((azimuth(H, phi, c.dec) / rad + 180) % 360), // PB: converted to deg - altitude: Math.round( altitude(H, phi, c.dec) / rad) // PB: converted to deg + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) }; }; // sun times configuration (angle, morning name, evening name) -var times = [ - [-0.833, 'sunrise', 'sunset' ] +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] ]; +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + // calculations for sun times + var J0 = 0.0009; function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } @@ -128,7 +163,7 @@ function getSetJ(h, lw, phi, dec, n, M, L) { // calculates sun times for a given date, latitude/longitude, and, optionally, // the observer height (in meters) relative to the horizon -exports.getTimes = function (date, lat, lng, height) { +SunCalc.getTimes = function (date, lat, lng, height) { height = height || 0; @@ -189,7 +224,7 @@ function moonCoords(d) { // geocentric ecliptic coordinates of the moon }; } -getMoonPosition = function (date, lat, lng) { +SunCalc.getMoonPosition = function (date, lat, lng) { var lw = rad * -lng, phi = rad * lat, @@ -216,7 +251,7 @@ getMoonPosition = function (date, lat, lng) { // based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and // Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. -getMoonIllumination = function (date) { +SunCalc.getMoonIllumination = function (date) { var d = toDays(date || new Date()), s = sunCoords(d), @@ -243,7 +278,7 @@ function hoursLater(date, h) { // calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article -getMoonTimes = function (date, lat, lng, inUTC) { +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { var t = new Date(date); if (inUTC) t.setUTCHours(0, 0, 0, 0); else t.setHours(0, 0, 0, 0); @@ -295,4 +330,12 @@ getMoonTimes = function (date, lat, lng, inUTC) { if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; return result; -}; \ No newline at end of file +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + +}()); From 7a2af0e61d9cd4260d3f30d382a0946ce2fb7e93 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 9 Dec 2022 09:52:34 +0000 Subject: [PATCH 12/13] Fixing warnings --- apps/espruinoprog/metadata.json | 3 ++- apps/hourstrike/metadata.json | 3 ++- apps/imageclock/app.js | 2 +- apps/presentor/metadata.json | 3 ++- bin/sanitycheck.js | 1 + 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/espruinoprog/metadata.json b/apps/espruinoprog/metadata.json index ebb55b23d..7371e005d 100644 --- a/apps/espruinoprog/metadata.json +++ b/apps/espruinoprog/metadata.json @@ -11,7 +11,8 @@ "custom": "custom.html", "storage": [ {"name":"espruinoprog.app.js","url":"app.js"}, - {"name":"espruinoprog.img","url":"app-icon.js","evaluate":true}, + {"name":"espruinoprog.img","url":"app-icon.js","evaluate":true} + ], "data": [ {"name":"espruinoprog.json"} ] } diff --git a/apps/hourstrike/metadata.json b/apps/hourstrike/metadata.json index 614db54e4..d0ddb511a 100644 --- a/apps/hourstrike/metadata.json +++ b/apps/hourstrike/metadata.json @@ -11,7 +11,8 @@ "storage": [ {"name":"hourstrike.app.js","url":"app.js"}, {"name":"hourstrike.boot.js","url":"boot.js"}, - {"name":"hourstrike.img","url":"app-icon.js","evaluate":true}, + {"name":"hourstrike.img","url":"app-icon.js","evaluate":true} + ], "data" : [ {"name":"hourstrike.json","url":"hourstrike.json"} ] } diff --git a/apps/imageclock/app.js b/apps/imageclock/app.js index 374e73070..dc21d7162 100644 --- a/apps/imageclock/app.js +++ b/apps/imageclock/app.js @@ -622,7 +622,7 @@ s.pl = {}; endPerfLog("fullDraw", true); if (!Bangle.uiRemove){ - setUi(); + setUi(); // Calls Bangle.setUI() (this comment also fixes lint warning) let orig = Bangle.drawWidgets; Bangle.drawWidgets = ()=>{}; Bangle.loadWidgets(); diff --git a/apps/presentor/metadata.json b/apps/presentor/metadata.json index e5b5e289f..2d0a22102 100644 --- a/apps/presentor/metadata.json +++ b/apps/presentor/metadata.json @@ -12,7 +12,8 @@ "allow_emulator": true, "storage": [ {"name":"presentor.app.js","url":"app.js"}, - {"name":"presentor.img","url":"app-icon.js","evaluate":true}, + {"name":"presentor.img","url":"app-icon.js","evaluate":true} + ], "data": [ {"name":"presentor.json","url":"settings.json"} ] } diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index 5af6f1aa1..8bec3a9a1 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -94,6 +94,7 @@ const INTERNAL_FILES_IN_APP_TYPE = { // list of app types and files they SHOULD var KNOWN_WARNINGS = [ "App gpsrec data file wildcard .gpsrc? does not include app ID", "App widmessages storage file messagewidget is also listed as storage file for app widmsggrid", +"App owmweather data file weather.json is also listed as data file for app weather", ]; function globToRegex(pattern) { From a0d3d15dbf5997e9b5741f3b26281fb4a98bb203 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 9 Dec 2022 09:52:44 +0000 Subject: [PATCH 13/13] Use 'modules/suncalc.js' to avoid it being copied 8 times for different apps + Add a 'time' clockinfo that also displays a percentage of day left --- apps/clkinfosunrise/ChangeLog | 2 + apps/clkinfosunrise/clkinfo.js | 64 ++++++++++++++++++++++++------- apps/clkinfosunrise/metadata.json | 2 +- 3 files changed, 53 insertions(+), 15 deletions(-) diff --git a/apps/clkinfosunrise/ChangeLog b/apps/clkinfosunrise/ChangeLog index 5560f00bc..9854c6b53 100644 --- a/apps/clkinfosunrise/ChangeLog +++ b/apps/clkinfosunrise/ChangeLog @@ -1 +1,3 @@ 0.01: New App! +0.02: Use 'modules/suncalc.js' to avoid it being copied 8 times for different apps + Add a 'time' clockinfo that also displays a percentage of day left diff --git a/apps/clkinfosunrise/clkinfo.js b/apps/clkinfosunrise/clkinfo.js index 1454a83f3..93bdfad41 100644 --- a/apps/clkinfosunrise/clkinfo.js +++ b/apps/clkinfosunrise/clkinfo.js @@ -1,32 +1,68 @@ (function() { // get today's sunlight times for lat/lon - var sunrise, sunset; + var sunrise, sunset, date; + var SunCalc = require("suncalc"); // from modules folder + const locale = require("locale"); function calculate() { - var SunCalc = require("https://raw.githubusercontent.com/mourner/suncalc/master/suncalc.js"); - const locale = require("locale"); var location = require("Storage").readJSON("mylocation.json",1)||{}; location.lat = location.lat||51.5072; - location.lon = location.lon||0.1276; - location.location = location.location||"London"; - var times = SunCalc.getTimes(new Date(), location.lat, location.lon); - sunrise = locale.time(times.sunrise,1); - sunset = locale.time(times.sunset,1); + location.lon = location.lon||0.1276; // London + date = new Date(Date.now()); + var times = SunCalc.getTimes(date, location.lat, location.lon); + sunrise = times.sunrise; + sunset = times.sunset; /* do we want to re-calculate this every day? Or we just assume that 'show' will get called once a day? */ } + function show() { + this.interval = setTimeout(()=>{ + this.emit("redraw"); + this.interval = setInterval(()=>{ + this.emit("redraw"); + }, 60000); + }, 60000 - (Date.now() % 60000)); + } + function hide() { + clearInterval(this.interval); + this.interval = undefined; + } + return { name: "Bangle", items: [ { name : "Sunrise", - get : () => ({ text : sunrise, - img : atob("GBiBAAAAAAAAAAAAAAAYAAA8AAB+AAD/AAAAAAAAAAAAAAAYAAAYAAQYIA4AcAYAYAA8AAB+AAD/AAH/gD///D///AAAAAAAAAAAAA==") }), - show : calculate, hide : () => {} + get : () => { calculate(); + return { text : locale.time(sunrise,1), + img : atob("GBiBAAAAAAAAAAAAAAAYAAA8AAB+AAD/AAAAAAAAAAAAAAAYAAAYAAQYIA4AcAYAYAA8AAB+AAD/AAH/gD///D///AAAAAAAAAAAAA==") }}, + show : show, hide : hide }, { name : "Sunset", - get : () => ({ text : sunset, - img : atob("GBiBAAAAAAAAAAAAAAB+AAA8AAAYAAAYAAAAAAAAAAAAAAAYAAAYAAQYIA4AcAYAYAA8AAB+AAD/AAH/gD///D///AAAAAAAAAAAAA==") }), - show : calculate, hide : () => {} + get : () => { calculate(); + return { text : locale.time(sunset,1), + img : atob("GBiBAAAAAAAAAAAAAAB+AAA8AAAYAAAYAAAAAAAAAAAAAAAYAAAYAAQYIA4AcAYAYAA8AAB+AAD/AAH/gD///D///AAAAAAAAAAAAA==") }}, + show : show, hide : hide + }, { name : "Time", // Time in day (uses v/min/max to show percentage through day) + get : () => { + calculate(); + let day = true; + let v = 0; + let d = date.getTime(); + let dayLength = sunset.getTime()-sunrise.getTime(); + if (d < sunrise.getTime()) { + day = false; // early morning + v = 100 - Math.round(100 * (sunrise.getTime()-d) / (86400000-dayLength)); + } else if (d > sunset.getTime()) { + day = false; // evening + v = Math.round(100 * (d-sunset.getTime()) / (86400000-dayLength)); + } else { // day! + v = Math.round(100 * (d-sunrise.getTime()) / dayLength); + } + return { text : locale.time(date,1), v : v, min : 0, max : 100, + img : day ? atob("GBiBAAAYAAAYAAAYAAgAEBwAOAx+MAD/AAH/gAP/wAf/4Af/4Of/5+f/5wf/4Af/4AP/wAH/gAD/AAx+MBwAOAgAEAAYAAAYAAAYAA==") : atob("GBiBAAfwAA/8AAP/AAH/gAD/wAB/wAB/4AA/8AA/8AA/8AAf8AAf8AAf8AAf8AA/8AA/8AA/4AB/4AB/wAD/wAH/gAf/AA/8AAfwAA==") + } + }, + show : show, hide : hide } ] }; diff --git a/apps/clkinfosunrise/metadata.json b/apps/clkinfosunrise/metadata.json index f8b68e11f..74877c523 100644 --- a/apps/clkinfosunrise/metadata.json +++ b/apps/clkinfosunrise/metadata.json @@ -1,6 +1,6 @@ { "id": "clkinfosunrise", "name": "Sunrise Clockinfo", - "version":"0.01", + "version":"0.02", "description": "For clocks that display 'clockinfo' (messages that can be cycled through using the clock_info module) this displays sunrise and sunset based on the location from the 'My Location' app", "icon": "app.png", "type": "clkinfo",