From f520a8ae7b0fc16c28fa1c8c0727168b46c0b5a2 Mon Sep 17 00:00:00 2001 From: Ian Ward Date: Sat, 20 Jul 2024 18:56:34 +0100 Subject: [PATCH] initial commit --- apps/quarterclock/app-icon.js | 1 + apps/quarterclock/app.js | 139 +++++++++++++++++++++++++++++++ apps/quarterclock/app.png | Bin 0 -> 252 bytes apps/quarterclock/metadata.json | 20 +++++ apps/quarterclock/screenshot.png | Bin 0 -> 1475 bytes apps/quarterclock/settings.js | 66 +++++++++++++++ 6 files changed, 226 insertions(+) create mode 100644 apps/quarterclock/app-icon.js create mode 100644 apps/quarterclock/app.js create mode 100644 apps/quarterclock/app.png create mode 100644 apps/quarterclock/metadata.json create mode 100644 apps/quarterclock/screenshot.png create mode 100644 apps/quarterclock/settings.js diff --git a/apps/quarterclock/app-icon.js b/apps/quarterclock/app-icon.js new file mode 100644 index 000000000..d6ed783ec --- /dev/null +++ b/apps/quarterclock/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4X/AwX48AFCqoAEC4oL/Bf4L/Bf4LTAH4A/ADGqAAIL/Bf4LD")) diff --git a/apps/quarterclock/app.js b/apps/quarterclock/app.js new file mode 100644 index 000000000..da7efed16 --- /dev/null +++ b/apps/quarterclock/app.js @@ -0,0 +1,139 @@ +{ + const minute_boxes = [ + {x:0.5, y:0}, + {x:0.5, y:0.5}, + {x:0, y:0.5}, + {x:0, y:0}, + ]; + + const hour_boxes = [ + {x:0.5, y:0}, + {x:0.75, y:0}, + {x:0.75, y:0.25}, + {x:0.75, y:0.5}, + {x:0.75, y:0.75}, + {x:0.5, y:0.75}, + {x:0.25, y:0.75}, + {x:0, y:0.75}, + {x:0, y:0.5}, + {x:0, y:0.25}, + {x:0, y:0}, + {x:0.25, y:0}, + ]; + + let drawTimeout; + + // schedule a draw for the next 15 minute period + let queueDraw = function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, (60000 * 15) - (Date.now() % (60000 * 15))); + }; + + // Main draw function + let draw = function draw() { + var d = new Date(); + var h = d.getHours(), m = d.getMinutes(); + + g.setBgColor(settings.backgroundColour); + g.clearRect(Bangle.appRect); + + if (settings.showBattery) { + drawBattery(); + } + + // Draw minute box + drawBox(Math.floor(m/15), minute_boxes, Bangle.appRect.h/2, settings.minuteColour); + + // Draw an hour box or write the number + if (settings.digital) { + g.setColor(settings.hourColour); + g.setFont("Vector:60"); + g.setFontAlign(0,0); + g.drawString(h, Bangle.appRect.x + Bangle.appRect.w/2, Bangle.appRect.y + Bangle.appRect.h/2); + } else { + drawBox(h % 12, hour_boxes, Bangle.appRect.h/4, settings.hourColour); + } + + queueDraw(); + }; + + // Draw battery box + let drawBattery = function drawBattery() { + // Round battery up to 10% interval + let battery = (Math.floor(E.getBattery()/10)+1)/10; + + // Maximum battery box + let batterySize = 30; + + // Draw outer box at full brightness + g.setColor(settings.batteryColour); + g.drawRect( + (Bangle.appRect.w / 2) - batterySize, + (Bangle.appRect.h / 2) - batterySize + Bangle.appRect.y, + (Bangle.appRect.w / 2) + batterySize, + (Bangle.appRect.h / 2) + batterySize + Bangle.appRect.y + ); + + // Fade battery colour and draw inner box + g.setColor(settings.batteryColour.split('').map((c) => { + return c=='f' ? Math.ceil(15 * battery).toString(16) : c; + }).join('')); + g.fillRect( + (Bangle.appRect.w / 2) - (batterySize * battery), + (Bangle.appRect.h / 2) - (batterySize * battery) + Bangle.appRect.y, + (Bangle.appRect.w / 2) + (batterySize * battery), + (Bangle.appRect.h / 2) + (batterySize * battery) + Bangle.appRect.y + ); + }; + + // Draw hour or minute boxes + let drawBox = function drawBox(current, boxes, size, colour) { + x1 = (boxes[current].x * Bangle.appRect.h) + (Bangle.appRect.y/2); + y1 = (boxes[current].y * Bangle.appRect.h) + Bangle.appRect.y; + x2 = x1 + size; + y2 = y1 + size; + g.setColor(colour); + g.fillRect(x1, y1, x2, y2); + }; + + let settings = Object.assign({ + // Default values + minuteColour: '#f00', + hourColour: '#ff0', + backgroundColour: 'theme', + showWidgets: true, + showBattery: true, + digital: false, + batteryColour: '#0f0' + }, require('Storage').readJSON('quarterclock.json', true) || {}); + + if (settings.backgroundColour == 'theme') { + settings.backgroundColour = g.theme.bg; + } + + // Set minuteColour to a darker shade if same as hourColour + if (settings.minuteColour == settings.hourColour) { + settings.minuteColour = settings.minuteColour.split('').map((c) => { + return c=='f' ? '7' : c; + }).join(''); + } + + // Show launcher when middle button pressed + // Remove handler to allow fast loading + Bangle.setUI({mode:"clock", remove:function() { + if (drawTimeout) clearTimeout(drawTimeout); + }}); + + // Load and display widgets + if (settings.showWidgets) { + Bangle.loadWidgets(); + Bangle.drawWidgets(); + } + + // draw initial boxes and queue subsequent redraws + draw(); +} + diff --git a/apps/quarterclock/app.png b/apps/quarterclock/app.png new file mode 100644 index 0000000000000000000000000000000000000000..e2a1c7fc0db4e32f7602bbb68af544cf5a7b665b GIT binary patch literal 252 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC#^NA%Cx&(BWL^R}TRdGHLo%G- z&T!;vFyLXi{oj7qC4P&R6vu)+%h-%}OE3AorZnus&4c&0e=TEBSi{8P!7Zrh{KxNr zt_xowci^!*PA(lb*VafUF=cd|T+}v$W8(2yrOrMKyoQli1cVhoMQqON;7qVNqFtl! z!d&)RJm5>x>feoD_Av`AEQw{k)Ut9v7YgfdG1r_&{k_aS(JrjZI>UaibeMYMOQq-x owWzntnL?8;Kd)bYfZ1YM{L6~#HK{=NGkCiCxvXFWXG+iEl@n0-z_3Z#iizdjjafDd4i6Yp+)G$E?rb!zbZ9uhe4_6Khro{H>`x60 zjqDR-FA6FY9KZI2k&%gC!FrLh!-KxHCz+X8f?+~=;!N>H?{lAm%%koY32m1B0*|UBBl^hbBWPBSAxUWC|l=DpE zVore{FTU=yX|yabVPuluYd2lpfW1%6;lbkT&p)v|J8+SOqvp%6n0W_eEM^^e&GDxz zKe8(4`|SEX(+=owxWFGTe}9AihbqoLvD~f?^0(a-k6gi2Z=4^WyKw!tDqE)?ZML%* z8vEn!t52_==&r^j{3C;j#jdKB%O`_pLjc9`&ZhY`x%h%l`R4-Ce8W-rv8c{I80&j;%oV zqj7oA1ML-eD~^S_u6nxn*F5vMlcM3l57ITR3E3B`v+irU)tep@yKT33&DGa?KYGc7 zZD)K|JYwMBocTO6A5WSLT^Z3=KyRnae z7WRg}lKgS=>7CfP^9Ro70d`FNq7(`FoKKD+OPAlDt;C}5(KpDeng+2=vu+x*7s{ru~{1atiF ze9as7pl>5E5sFqE`Sy{2PXB}krt$*O9m%T?C~xDEX%2h9w*ev>)|h;O>kcDO`C6v_ z8(IZCzr6n?Ec@C{{34pso+?BU%-R)3;x-j4|$Ncp6kxW&6A6U$I^uK-60p>3( z?-Yc0B>&!e{y_8f(spGIn;T6` labels[v], + min: 0, + max: values.length - 1, + wrap: true, + step: 1, + onchange: v => { + setSetting(key,values[v]); + } + }; + } + + // Helper method which breaks string set settings down to local settings object + function stringInSettings(name, values, labels) { + return stringItems(name,settings[name], values, labels); + } + + // Show the menu + E.showMenu({ + '' : { 'title' : 'Quarter Clock' }, + '< Back' : () => back(), + 'Hour Colour': stringInSettings('hourColour', ['#f00', '#0f0', '#00f', '#ff0', '#0ff', '#f0f'], ['Red', 'Green', 'Blue', 'Yellow', 'Cyan', 'Magenta']), + 'Minute Colour': stringInSettings('minuteColour', ['#f00', '#0f0', '#00f', '#ff0', '#0ff', '#f0f'], ['Red', 'Green', 'Blue', 'Yellow', 'Cyan', 'Magenta']), + 'Background Colour': stringInSettings('backgroundColour', ['theme', '#000', '#fff'],['theme', 'Black', 'White']), + 'Digital': { + value: !!settings.digital, // !! converts undefined to false + onchange: v => { + setSetting('digital', v); + }, + }, + 'Show Widgets': { + value: !!settings.showWidgets, + onchange: v => { + setSetting('showWidgets', v); + }, + }, + 'Show Battery': { + value: !!settings.showBattery, + onchange: v => { + setSetting('showBattery', v); + }, + }, + 'Battery Colour': stringInSettings('batteryColour', ['#f00', '#0f0', '#00f', '#ff0', '#0ff', '#f0f'], ['Red', 'Green', 'Blue', 'Yellow', 'Cyan', 'Magenta']), + }); +})