From 308ebf1d0fe9ced9cb91cc1de7913a61f4f0efef Mon Sep 17 00:00:00 2001 From: steeb-k <133536278+steeb-k@users.noreply.github.com> Date: Sun, 25 May 2025 21:47:16 -0700 Subject: [PATCH 1/3] Adding mosaic-plus --- apps/mosaic-plus/ChangeLog | 5 + apps/mosaic-plus/README.md | 22 +++ apps/mosaic-plus/metadata.json | 22 +++ apps/mosaic-plus/mosaic-plus-scr0.png | Bin 0 -> 3980 bytes apps/mosaic-plus/mosaic-plus-scr1.png | Bin 0 -> 3909 bytes apps/mosaic-plus/mosaic-plus.app.js | 196 +++++++++++++++++++++++ apps/mosaic-plus/mosaic-plus.icon.js | 1 + apps/mosaic-plus/mosaic-plus.png | Bin 0 -> 4533 bytes apps/mosaic-plus/mosaic-plus.settings.js | 43 +++++ apps/mosaic-plus/pixel digits.xcf | Bin 0 -> 1480 bytes 10 files changed, 289 insertions(+) create mode 100644 apps/mosaic-plus/ChangeLog create mode 100644 apps/mosaic-plus/README.md create mode 100644 apps/mosaic-plus/metadata.json create mode 100644 apps/mosaic-plus/mosaic-plus-scr0.png create mode 100644 apps/mosaic-plus/mosaic-plus-scr1.png create mode 100644 apps/mosaic-plus/mosaic-plus.app.js create mode 100644 apps/mosaic-plus/mosaic-plus.icon.js create mode 100644 apps/mosaic-plus/mosaic-plus.png create mode 100644 apps/mosaic-plus/mosaic-plus.settings.js create mode 100644 apps/mosaic-plus/pixel digits.xcf diff --git a/apps/mosaic-plus/ChangeLog b/apps/mosaic-plus/ChangeLog new file mode 100644 index 0000000000..8397929d3e --- /dev/null +++ b/apps/mosaic-plus/ChangeLog @@ -0,0 +1,5 @@ +0.01: First release +0.02: Use locale time +0.03: Change for fast loading, use widget_utils to hide widgets +0.04: Minor code improvements +0.05: Forked from mosaic. Added battery gauge and weekday. diff --git a/apps/mosaic-plus/README.md b/apps/mosaic-plus/README.md new file mode 100644 index 0000000000..253cea35a6 --- /dev/null +++ b/apps/mosaic-plus/README.md @@ -0,0 +1,22 @@ +# Mosaic Clock + + +A fabulously colourful clock, now with battery bar and day of the week! + +Based on Mosaic Clock by [Sir Indy](https://github.com/sir-indy), with some slight modifcations. + +Original features: +* Clearly shows the time on a colourful background that changes every minute. +* Dark and Light theme compatible, with a setting to override the digit colour scheme. +* Show or hide widgets with a setting (default hides widgets, swipe down to show them thanks to `widget_utils`). + +PLUS: +* Battery bar +* Three-digit weekday + +![](mosaic-plus-scr0.png) +![](mosaic-plus-scr1.png) + +This clock is inspired by the mosaic watchface for pebble: https://apps.rebble.io/en_US/application/55386bcd2aead62b16000028 + +Written by: [Sir Indy](https://github.com/sir-indy) +Modified by: [steeb-k](https://github.com/steeb-k) diff --git a/apps/mosaic-plus/metadata.json b/apps/mosaic-plus/metadata.json new file mode 100644 index 0000000000..cc47c91fc4 --- /dev/null +++ b/apps/mosaic-plus/metadata.json @@ -0,0 +1,22 @@ +{ + "id":"mosaic-plus", + "name":"Mosaic Clock +", + "shortName": "Mosaic Clock +", + "version": "0.5", + "description": "A fabulously colourful clock - plus weekday and battery bar.", + "readme": "README.md", + "icon":"mosaic-plus.png", + "screenshots": [{"url":"mosaic-plus-scr0.png"},{"url":"mosaic-plus-scr1.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"mosaic-plus.app.js","url":"mosaic-plus.app.js"}, + {"name":"mosaic-plus.settings.js","url":"mosaic-plus.settings.js"}, + {"name":"mosaic-plus.img","url":"mosaic-plus.icon.js","evaluate":true} + ], + "data": [ + {"name":"mosaic-plus.settings.json"} + ] + } diff --git a/apps/mosaic-plus/mosaic-plus-scr0.png b/apps/mosaic-plus/mosaic-plus-scr0.png new file mode 100644 index 0000000000000000000000000000000000000000..aa318a75148c206a545d4f542b77ead8b38e0232 GIT binary patch literal 3980 zcmW-kc|26_7sv0+Wo$FZI(B1_#4wB{B%$m}rI2l?Fp;gXm2G6-DrCu0)>cfGLBx%r zBuh#W-%MoUYa5ZD6n@k9k9*HQ&wcLeIp=)d&*!8&+FPJ_C3yh=Kv`LupJqqu--jE) zemAs!^JE9u)zcQHK>e`vA^-@Sv@$>L6y>>6wp7scR48d~*Ng1SbJ>Wn^&X})@ZrzI z^}4kapk4SW5w6r%bL%k+4hOc!xRG#H;a2J6G6i{nkK0Rzf=b9MK=1qQH6-sx?)|zW z+AObbVRlsWEMZTLw00Hkcw{#+>IYQ;B-0ID*iz(vc@ys?qM6R3NXU}~*zK&r*F|gxZ zyb&GZyp=(TZ4a{y#Z%Lj`;&YaBZUH_%c`hAezh@3qu*Sjd+W#o=y?QBMQ`JC6kT0x zKpU_ry{KlZno>h?;1apzuD#PqIlSB9p0-?kpZGIZU<{hyyNxJ7Y&D82>HR#>2lZh- ze}JOh1kxpot+KoAuJd*Yhz-gn&G2*3M0$)@5{6JB7gn=&drEv*o4?gb36Bg)tfp@m z+v-unK~1FT-Ju;vuS(H`H-2Kf2tfNs@jxgSaa(hxEC}#jk!K7&3K9N2+ScWel-m;IdN`{rp@cHJclzgXTjh{2jBnN&;BLlTYM%U_Oki;nlAW_leSq>v#ti0|)hX%LRQSMxJTLdmmsqz}i_jNbPA`G=rgiG_lIWvQH464*e2~kg1 zzE%plAdyd-#u09KO*ruihM&Fh=s_{?Q(~Uc2uuwj2Hum;cz%c@|F)JibZi(Ri;JUz zmPFOQoN7)PeY;#ePcmh-QMb-VzLe=dy`|cX{o-CxE;kkE@3*xdA@Ii)#mO+3p-Clt zH_JQRWBiTf2QMNi9;@ShqL<7y6)94OS?0vELJj!MzHcR=C%6yr~5I~^4rUBe&$nR-Oy5giN-t(&z}SrpgD#Pvan3%|8|7`%WDDEvBhH&2~yE6$Qa-Aual!JMEdVlVDsG5M9;@oRqfufZLV5?C&w@vQ8-j- zTGG%=hZXlPsCH$)MY5L`a3s#;~qtYgszD`)tQ{ zdhf!_@**rKYn8^6^2YL`yM7MqPMarCE2%&8wyEr&>F^hq734-Wv>z?=hc`axgCbIz zecygutKzHkVYJ78otS!FMNI;VyJYK)e1gC5>yL$=v~csN?RZCL7lf036?*1Wy(SDg z%$iGX8!9CcSc=Ovlx|_jhlpoALbB!U%hTWO*6|LSHpkJW2TiD*tG~#A-X)?2I(Y9o zOFQ%jWq?P7R=zzF!_b5Md-U8Q*z2mXaknJiOI>T~WRSi`Wde6Cayi^*a|Rm<1BWkY z9z3GS{qD`$pf)$ILnLeJkShv$*B*Brv!GAEYu!rzGn}5~#ia=g9wryGViCHH z!mG(tiHU1+W~R>rP=CB516mwxkw`e-2J4l?ggtj7%`cWV$ou;W;2V7qq1^tilHC^9 zyueIKX6(49>HVPD32*FubQ?9>7HM=`y@&9(9UmZ1T;wS0%B1`v5-(fmTUB1i$U0>y z4-Q%+{w=7zvLHlOvd7V90qu1a#2y0S8|(T>D9(Ff8F?j;P+HMkpx5%Nt*E!)YF3pO z=i>Au3}Kk+zLzEW%kWL&lmei)KJsduW~|v!nrkj!*j_h2rTQ*MD<@90{_)}mL0OVh zZvXsvw1!?P&blI_RP-^7if(HjnCpgZ$0CgLZoEG67^YcXGe%hYu$E7vLw+)grRh^g zt-s?*MB@_jN5F-x9on}Wt+kS{wHiPS6b~Ho^eN9FQ>A5!D<$=L8D|7DDHd4D5N+Nx z|JH~OmDAHkVR=yWk~u1&4`L&yx){+9B~@|kO4pOBtk}f2&|z7?{%*S$gb1>GIYOC! zud5!l?IzFFc34q-W5zJ}^s-#*~XNs-bF;Te5h_b^v5JDW&im^z;}Om>`FMmJ9O*GNu0 zS^fFnsy?W}NCezB2C?VVZI^9j+?6o3vF`L+>&^$qhA#y>wSSvwx9YS05>d*`^?&Ng zyM}97)iPYN5}=b`oj+%``1=vAleuv@wd37rFZtzz_r~WDgC~rhQ-8?-O*u_sB3K{- zymn0$8=Uepv?!qY=p8kL?uC6rpgeC&TJ{to=P6xjv`pP5lY*TJMmz8GCrGrOkccY# zIi6~OPtTyNt4nr+j3so@YsBf3lIY&kl5K>ukG+ZTu??*;h-E$<&p|~`?C_H(H*WEr zaVm|W=by!OLFTZzF>$!D6*<{B^y7$N0b|DLy4-Q~tjU%(t zR(ob>4rjp&odveGOk6bnckckWfx^J4Kuqm;H3e(EwcAL(c)5-et9z6-5Py>0Ot^1} zK<8WEc~imI{~15%FBbtd)_peB#d{FwvaEi_Vxd?>SPmj}l8;Z<$q+`V)6M`oY@yWA5a@mIm6;GEqk+)H?1}^_l2;1yqbl=!jJ*S|84~2vs&1 z@t&@WRycb8&d|z1qjX_#s_8|Jkm=t8w_kSd5KQM!l)EumSSV1cg zQM{r9R=LW9mU=7Oic0}lH%6lWqXcWrW}^w_c_WvAl7s9LKR4%@?hnlHGRxwccI5fY z1D!u92co`(J*^n`8lf|V($2GvSl7Fo zaLq1%Ph=qfSqZ5uN|VopC>OI0NdU{rpk(G%>lq0B7$V`-FvR_n=qL|7{9$7>&k+Ki)@6{z8!KG83++CB+7~EO6>aEmI@&g>eKX>!x1fu8W=-PuKXJa9#zyd@K=UN} zc;_4^Ba!cAE$!w@BtwABD)+`mXij2(5+8Ou_R;4q`)Xv&KpgQkBUw9?MZ!}h9x~11 zt^&UqGOy0Pfo?mz#^EOG?NV3r1ryKy2La(iDIR7vLN=fY|1?TfqQ{F}KjTTd@Z<*^ zf_C5hJ(?NNFyMdHD(o4;Gqs7s2d@b$0|IXf65-BIDBtDw{Mqin1}r2{U-kUGGBNNk zbW$h~bdez>>?J^CHk%x~T|86QBD?2~KA%I1*WegXzL>n7w; zkH=>4MoeWRKIKk2NB2QTMsAXw;Byj|4V)onEas%zZ>-s=984T`#~UBwy-_wl>jXso z6Zr}5f(*=2BZ!g|DwlahG8A=ZA6f&2(!4f4mY}$_!`QwLBLE#0dNeCmz=xP<%f@H^ zj}`yb<`x(zd~YH@nQfS5zF|F(G3ubOVC!E)HwJC_&6?uqcMUqDkGla?>&aEp*AXET zX}0HL_R0zkr(rGaC8qz19Wt8>OBDzl|Ba;E!E800EN2P;;;VY+>Q)oin61MeHTy47 zuq)XjJS(A}llv5~k*2iA(l0864o;dMF1gdz%nRQk#2%K&uR=;Ma-0^kKfCtvNYl@Rs^&gLda_bk-{K}XQ*eJs25Auv}oG@9H7XQ#u55&st2^xYtJE!gKzB+9r7 z4=i1}W%|R4kHsZ+ftiV%%#hh0B4fCpc;V&)qFd!^xqI&oF-5jrcgl`F4>IYvLL1@N zm2^+*Js!)yIm*8TZ?g$&?2#z4+zM$;yoBb`G&w+mlKP(=87!kSMPC~2+1CFAeD@nOJyU0$VA2AKbf&SX-S(5}c%gs_m6rFA-G&?s$QGQF9= z`jLLVpJNQt)nW_YEZBs@25fjh%@OMl0<^`ynU?lRB~EZ?mO9OP+p)!ApCe7yk&ifo z|2r#kXoO)-=cKX6Egwe9mqLN8`I33-Kb?FB-pQ*z;f^uoh&ZTaTw(qAh603Tas64& Wj(Skb-NzoU0jm@C=Jlq;#Qy_%k17iQ literal 0 HcmV?d00001 diff --git a/apps/mosaic-plus/mosaic-plus-scr1.png b/apps/mosaic-plus/mosaic-plus-scr1.png new file mode 100644 index 0000000000000000000000000000000000000000..91ffe731db2867c189d44095a02ac52a00a7f25d GIT binary patch literal 3909 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 H1uph~|DH48 literal 0 HcmV?d00001 diff --git a/apps/mosaic-plus/mosaic-plus.app.js b/apps/mosaic-plus/mosaic-plus.app.js new file mode 100644 index 0000000000..eaccae322d --- /dev/null +++ b/apps/mosaic-plus/mosaic-plus.app.js @@ -0,0 +1,196 @@ +Array.prototype.sample = function(){ + return this[Math.floor(Math.random()*this.length)]; +}; + +{ +const SETTINGS_FILE = "mosaic.settings.json"; +let settings; +let theme; +let timeout = 60; +let drawTimeout; +let colours = [ + '#f00', '#00f', '#0f0', '#ff0', '#f0f', '#0ff', + '#8f0', '#f08', '#f80', '#80f', '#0f8', '#08f', +]; +let digits = [ + E.toArrayBuffer(atob("BQcB/Gtax+A=")), + E.toArrayBuffer(atob("BQeCAX9c1zXNc1zX9A==")), + E.toArrayBuffer(atob("BQcB/Hsbx+A=")), + E.toArrayBuffer(atob("BQcB/Hsex+A=")), + E.toArrayBuffer(atob("BQeCAf/zPM8D/Nc1/A==")), + E.toArrayBuffer(atob("BQcB/G8ex+A=")), + E.toArrayBuffer(atob("BQcB/G8ax+A=")), + E.toArrayBuffer(atob("BQeCAf/wP81zXNc1/A==")), + E.toArrayBuffer(atob("BQcB/Gsax+A=")), + E.toArrayBuffer(atob("BQcB/Gsex+A=")) +]; + +// Day of week abbreviations +const days = ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT']; + +let loadSettings = function() { + settings = require("Storage").readJSON(SETTINGS_FILE,1)|| {'showWidgets': false, 'theme':'System'}; +} + +let loadThemeColors = function() { + theme = {fg: g.theme.fg, bg: g.theme.bg}; + if (settings.theme === "Dark") { + theme.fg = g.toColor(1,1,1); + theme.bg = g.toColor(0,0,0); + } + else if (settings.theme === "Light") { + theme.fg = g.toColor(0,0,0); + theme.bg = g.toColor(1,1,1); + } +} + +let queueDraw = function(seconds) { + let millisecs = seconds * 1000; + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, millisecs - (Date.now() % millisecs)); +} + +let draw = function() { + // draw colourful grid + for (let i_x = 0; i_x < num_squares_w; i_x++) { + for (let i_y = 0; i_y < num_squares_h; i_y++) { + g.setColor(colours.sample()).fillRect( + o_w+i_x*s, o_h+i_y*s, o_w+i_x*s+s, o_h+i_y*s+s + ); + } + } + + let now = new Date(); + let t = require("locale").time(now, 1); + let hour = parseInt(t.split(":")[0]); + let minute = parseInt(t.split(":")[1]); + let dayOfWeek = days[now.getDay()]; + + // Draw time (shifted left) + g.setBgColor(theme.fg); + g.setColor(theme.bg); + g.drawImage(digits[Math.floor(hour/10)], (mid_x-7)*s+o_w, (mid_y-7)*s+o_h, {scale:s}); + g.drawImage(digits[hour % 10], (mid_x-1)*s+o_w, (mid_y-7)*s+o_h, {scale:s}); + g.drawImage(digits[Math.floor(minute/10)], (mid_x-7)*s+o_w, (mid_y+1)*s+o_h, {scale:s}); + g.drawImage(digits[minute % 10], (mid_x-1)*s+o_w, (mid_y+1)*s+o_h, {scale:s}); + + // Draw day of week (vertical to the right of time) + g.setFontAlign(0, 0); + g.setFont("Vector", 30); // Scalable vector font, clean and large + + // Calculate position for each character + let dayX = (mid_x + 7) * s + o_w; // unchanged + let lineSpacing = 3 * s; + let timeBottom = (mid_y + 1) * s + o_h + 7 * s; + let dayY = timeBottom - (dayOfWeek.length * lineSpacing) + lineSpacing / 2; + + // Draw each character vertically with matching time style + for (let i = 0; i < dayOfWeek.length; i++) { + let y = dayY + i * 3 * s; + // Draw filled background box + g.setColor(theme.bg); + g.fillRect(dayX - 15, y - 16, dayX + 10, y + 14); // Adjust box size as needed + // Draw character + g.setColor(theme.fg); + //drawBoldText(dayOfWeek[i], dayX, y); + g.drawString(dayOfWeek[i], dayX, y); + } + const boxLeft = dayX - 15; + const boxRight = dayX + 10; + const boxWidth = boxRight - boxLeft; + + let batt = E.getBattery(); // battery % + batt = Math.max(10, batt); // clamp to 10% minimum for visibility + + let batteryGap = 0; + let padding = 4; + + // Box dimensions + let batteryTop = (mid_y - 7) * s + o_h; // top of time digits + let batteryBottom = dayY - lineSpacing + 6; // above top of day text + + // Ensure correct vertical direction + let topY = Math.min(batteryTop, batteryBottom); + let bottomY = Math.max(batteryTop, batteryBottom); + let batteryHeight = bottomY - topY; + + let innerTop = topY + padding; + let innerBottom = bottomY - padding; + let innerHeight = innerBottom - innerTop; + let batteryFillHeight = Math.round((batt / 100) * innerHeight); + + // Choose battery color + let fillColor = + batt > 75 ? "#0F0" : // Green + batt > 25 ? "#FF0" : // Yellow + "#F00"; // Red + + // Outer white background + g.setColor(theme.bg); + g.fillRect(boxLeft, topY, boxRight, bottomY); + + // Border + g.setColor(theme.bg); + g.drawRect(boxLeft, topY, boxRight, bottomY); + + // Inner fill (bottom-up) + g.setColor(fillColor); + g.fillRect( + boxLeft + padding, + innerBottom - batteryFillHeight, + boxRight - padding, + innerBottom + ); + + + queueDraw(timeout); +} + +g.clear(); +loadSettings(); +loadThemeColors(); + +const offset_widgets = settings.showWidgets ? 24 : 0; +let available_height = g.getHeight() - offset_widgets; + +// Calculate grid size and offsets +let s = Math.floor(available_height/17); +let num_squares_w = Math.round(g.getWidth()/s) - 1; +let num_squares_h = Math.round(available_height/s) - 1; +let o_w = Math.floor((g.getWidth() - num_squares_w * s)/2); +let o_h = Math.floor((g.getHeight() - num_squares_h * s+offset_widgets)/2); +let mid_x = Math.floor(num_squares_w/2); +let mid_y = Math.floor((num_squares_h-1)/2); + +Bangle.on('lcdPower',on=>{ + if (on) { + draw(); // draw immediately, queue redraw + } else { // stop draw timer + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } +}); + +Bangle.setUI({ + mode : 'clock', + remove : function() { + // Called to unload all of the clock app + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + delete Array.prototype.sample; + require('widget_utils').show(); // re-show widgets + } +}); + +Bangle.loadWidgets(); +if (settings.showWidgets) { + Bangle.drawWidgets(); +} else { + require("widget_utils").swipeOn(); // hide widgets, make them visible with a swipe +} + +draw(); +} diff --git a/apps/mosaic-plus/mosaic-plus.icon.js b/apps/mosaic-plus/mosaic-plus.icon.js new file mode 100644 index 0000000000..445423e9fa --- /dev/null +++ b/apps/mosaic-plus/mosaic-plus.icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4n/AAIIC/H/g/gg9fgkfxEf/FA/kfgHgx8R/Hg//xg4jDqoAEkQAEu4AEogAEC/4X/kURAAgXQkIXFi4XpcoYX53YAEzOZyIXFjGIxHMAAgX/C8WxaQoXEAAoXFBgwXKjgXdiASDABQX/C5dmAAIXRjLPBC/4XLa6AXdsIXQCwIXDAAWq1WhC4sXu93CgQX/C8UzAAmIxGBC4sd7vdkQAEC/4XRAAgXoxAXFCwIXPAAQUCC/4XoA=")) \ No newline at end of file diff --git a/apps/mosaic-plus/mosaic-plus.png b/apps/mosaic-plus/mosaic-plus.png new file mode 100644 index 0000000000000000000000000000000000000000..49242fd8fd5f63e8c2913101388fcdcd3e9a2fe6 GIT binary patch literal 4533 zcmeHKeQZMt4 zX^OP|muFqy^UgizchCLZbB}#DHY}>k)6CIe7?$UDIhH_A$!*4T_+G01`gsgf6`&S( z!0j%_W`Hgi6xo<6ZKoP1t5sQ87U=t+<*U@#Z0LUhZ8qp-d%4X~O;h@PAU~Xz4}&~E zZ6o{B;F|~i05k^V0_aae6P{1a`yt5kGeh~ zXLK~B)0+X2VhkK*;1~l=8#zYL8T6PM`&nNORt!GhKvTUw7B9SJp8IE7H}CLzu>YxG zw>P-$c03Xl140mCSh9c3&uy-gRV72MjW1{mXXQS7am!BbgFTzfeIO_K$n1 z^Vc@1_63TsI#vu{X&(A)X*Sh6cP3s=H||)tr|*lB)>~iP_)7QQyGPD`Yx!pDk>6oE zTqV8%ewO&q+2GUMCu=S}RN>a#u-tf~x~TNoj|Z-O`S2&ZPO8t&EZ%n0`pkxw$GZ-F zcw)bQ@B8Q8=bh*0x1Ju@9~rr{zj@XEc>Ue?+Ey-Kc7^*rU3zH4qi^6fwRxziZEnrm zwVO7w*H78*?0$KHQ@3peqN0z#t|{!hoO5s8M;BgQ|JL5^1utgx6#f0~4|4_*J%J0q zI=(qH*sZ?3qo?A)^>>VGKdArnry=4e**C?kqQ8bbBU!q{+J8LuBc`ktqYP7-q(pF+>6?Uuuc2<;BhT3_-)#y1`p+l*inbz zS{+4=s~0u-R(JX=e(i!vjWx*uKnO`Zo(u)UF)nG-D!3fTvYOQ5iiy-|)3!ji*~KWr zSskmR2xn60VziYS+#2-lQZ;Yc!(NazxJofvH=X^X`|QVhv31XvKU z?y$rsiEwP543WZcpqMWzL?l5B<1!}i72}dktA%lVG`>*8V`&zE4>HL|NLojc zp%6LVBPKb!03;pIcY4H{x+92Of?{Gk>O;;h6qe?Vhw%F{{*ibzs4U0tBT*2Az%&N4 z(i5hX&t=9#rl4I2MHDX}dxE7T1jfjk5Su)rEN6Tm;GV&qU_H8a#TcwS9?l{9;&OOy zhfOQb&-q24;O7*PGO=DWg=oTPqWuJGworrxF)TsREJOQvBdO9H#4-}4~|B!o?s0$Pnf-YfS?$Q*=q_|^t69GM153%tmK2^qmrTg0L7Rs$jtHv zA`oCK1Z&a*sMp96Mze`VNbl7nOF)Un@8fF4Xo!dH6heGEA|v5;Wk4pJt8Q@Hw2Y1# z(=-HmDF6;O?NdTHo*Wx!5<;j^;$=2z6AKG5uzG{hz!(kmm{Bu|#vl`AOr^pqBl5Oz zuoxhgm-7?=6g{kkQ_83qZ4$+xO`ECBnPCqcCqFOo4yft?nyJ=Jqt%+AOdOR8UxxFD zej(8PzpUlMgImEKw%jGeBr)2ps8T1Y5j~T7OT7jK!@D%j#LOB#Lz6w5&=Cj5Uf{kA}o4efS`?(LC<(u+CZ5U7Bc8DF(4)Q zD5`D;9)T-JPvv(EpRa6G*+lC^2a7aN)EhIC=FwGgn`+Yv?z4$(-!11X`CdKa*T~l;Tih)TPPi5B>U6W#9QpQu+ z^?##FGj^RqVfYu6fXhio5R@Hvnkh`5%;Fiba3ZmQ&-1zn)b zk=!0<&edtfMMb6~mdlqxRV+DMB)b@r|CM9+-MN?c { + settings.showWidgets = !settings.showWidgets; + save(); + } + }, + 'Theme': { + value: 0 | theme_options.indexOf(s.theme), + min: 0, max: theme_options.length - 1, + format: v => theme_options[v], + onchange: v => { + s.theme = theme_options[v]; + save(); + } + }, + }); +}) diff --git a/apps/mosaic-plus/pixel digits.xcf b/apps/mosaic-plus/pixel digits.xcf new file mode 100644 index 0000000000000000000000000000000000000000..f2c05891c971874a0ead8743a4211ae9a6d5bb2d GIT binary patch literal 1480 zcmd^7TW-@p6dgPCkv35&FY(cjDYQ~5HBy`n@X-&11X8x(I*#iqi7VTE2<M=bpK9=Z=$fb|G(~iM$#Ffq<<68ziugz%Jl<7#;(g zCs-n2Pk;wN7kE~2>Yf7MfNp}+{V1Ew;&};QF!<;skHaz^%j>i}lds>r8!_@wOVe4H z#Qh{s$6TZOQ?Do&(^wYSG#wvp^(IM_O|x9~^wiIj(@+ld7aSpcx*{A%{V{w~T!c|N zPh>EFw`h2k)4!ajrA+71SzK^OHklN0DYf3=hBn2l*)i|jaV#Bzu(!NhcN7+E#M^KY z=M?xHVCw+;s(^j+SMM>R_W;+qxm|Hg;)TQa9KPjn>F{lbcO1@lWPaKXu&I>#tUXgS zW6XaDSlt0RbgcEI!|lIebqLY?YcuQ7Hlxz`A6CS;=hm*{AmIZ&<%^#R{lVu8PvbY8 z+Ow;ie;6S~?rqW6JIR$;Q(tPI8EWy0TsX6F%J-!hc}%{R`f9UiEryo*gQdGAH Date: Tue, 3 Jun 2025 15:06:58 -0700 Subject: [PATCH 2/3] Update metadata.json Oopsied on the version number. --- apps/mosaic-plus/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/mosaic-plus/metadata.json b/apps/mosaic-plus/metadata.json index cc47c91fc4..6665c18cb1 100644 --- a/apps/mosaic-plus/metadata.json +++ b/apps/mosaic-plus/metadata.json @@ -2,7 +2,7 @@ "id":"mosaic-plus", "name":"Mosaic Clock +", "shortName": "Mosaic Clock +", - "version": "0.5", + "version": "0.05", "description": "A fabulously colourful clock - plus weekday and battery bar.", "readme": "README.md", "icon":"mosaic-plus.png", From 5bf262ec7335daa830ca3bef34c9cb885ae6acc3 Mon Sep 17 00:00:00 2001 From: steeb-k <133536278+steeb-k@users.noreply.github.com> Date: Tue, 3 Jun 2025 20:52:42 -0700 Subject: [PATCH 3/3] Update mosaic-plus.app.js --- apps/mosaic-plus/mosaic-plus.app.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/mosaic-plus/mosaic-plus.app.js b/apps/mosaic-plus/mosaic-plus.app.js index eaccae322d..87afbe6426 100644 --- a/apps/mosaic-plus/mosaic-plus.app.js +++ b/apps/mosaic-plus/mosaic-plus.app.js @@ -100,12 +100,12 @@ let draw = function() { } const boxLeft = dayX - 15; const boxRight = dayX + 10; - const boxWidth = boxRight - boxLeft; + //const boxWidth = boxRight - boxLeft; let batt = E.getBattery(); // battery % batt = Math.max(10, batt); // clamp to 10% minimum for visibility - let batteryGap = 0; + //let batteryGap = 0; let padding = 4; // Box dimensions @@ -115,7 +115,7 @@ let draw = function() { // Ensure correct vertical direction let topY = Math.min(batteryTop, batteryBottom); let bottomY = Math.max(batteryTop, batteryBottom); - let batteryHeight = bottomY - topY; + //let batteryHeight = bottomY - topY; let innerTop = topY + padding; let innerBottom = bottomY - padding;