From 19bf4b4cdf6a07bd175d04e1e96519123cbd014b Mon Sep 17 00:00:00 2001 From: Tom Wallroth Date: Fri, 24 May 2024 23:04:44 +0200 Subject: [PATCH 1/4] supaclockpro wip --- apps/supaclockpro/app.js | 200 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 apps/supaclockpro/app.js diff --git a/apps/supaclockpro/app.js b/apps/supaclockpro/app.js new file mode 100644 index 000000000..074425cef --- /dev/null +++ b/apps/supaclockpro/app.js @@ -0,0 +1,200 @@ +{ // 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 drawTimeout; + +Graphics.prototype.setFontPlayfairDisplay = function() { + // https://www.espruino.com/Font+Converter + // + // 60pt, 2bpp, Numeric + // Actual height 62 (67 - 6) + return this.setFontCustom( + E.toString(require('heatshrink').decompress(atob('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'))), + 46, + atob("ExouGyYjJiEoISgoFQ=="), + 70|65536 + ); +} + +Graphics.prototype.setFontPlayfairDisplaySm = function() { + // Actual height 18 (17 - 0) + // + // 18pt, 1bpp, ASCII capitals + return this.setFontCustom( + E.toString(require('heatshrink').decompress(atob('ABU/weP/3j/E4BAMIgEH4EB8EAkEAjwICgGADYcQgFEgEX4EeoEBBANHgE9gEEBAYABjl8h+Gg/woM+iFP4n///En1Bw/wvH4CgIXBgfggP4glDg0QoUH+cA/MAgO+gGf4HEiHBwlAn8Ah5NCgeAgPwh3+g/j4MQuFEzkc+cHmXA7+wg/8gO3g9hwP44Fv8ETEARbCPoMfPoIIDgf8gf/4P//nwh9gBgUEAQPwg8f//D//An6gBgEUJ4SoBgP+gF/wAqBgfwgFIZAqaBEwMBAwKjB/4IGCIStDJ4ISBEgIADmEAhhXBAwLcBBAYhCAAcBBoNwXgYWDfwPAQgIgBDI0AW4Mf8EPQwOHgGAoEgiEMhiPBOAUPEoZbCoEfSAKhCMoZEDCQPA4Eg+EMvkD+75B4EcKAtAhEQgUIoODmFA/1wn/8h8+WgIpDb4M4gEWgEJwEMuEH/+D/7EBJwLQCR4Mg8kInMGh1Dgef4Hn8F4/EAjB/Ej/Aj/4h//gfh4OQiFGhkh/8In7uB4EOYAOAGQPwnH+h1/gewgDWBZILiDgfPwP7+F/gkT8MEvlB//wvv8ghtBAAMPFwPwgf+kHBxEgkkMj6qBwF/4EPNYYAB8PAnFwhzyERgIIBjrgBQgLDDAQIeBlEAicAglAgUQgGCgFgwAFBAAkSCIOAgK3BpAILGA1AwEIkECVgNEGoUCSwUAGIYgBLQLqB8WAnGBh0xwZxBgKjBeIMAjzSBsEQgkIgGEn0in/Iz/yo0IyMOkl/5Mf+FHIAMCgZIBv5PFgfAgcQg2Ah0gg/ogP/gE//gECj6aBH4MMDYMEgDXCv/8j//gkQoICBdIIIBg/v4HzOAN4G4X+HwPAn/4CIUB4KABoAdBgIsBS4Mgvl8KYosBGoUH/4aIoPAuAsBh/+gI1BSYIABCIIaCLIZWDoM/EYUcg8HQwI6DDRsfKYNAGAMHcgLaBh/wHwMD/+B+HwsBQDhFBWYNA/kIn0H5/AgQ1LVQZNBQAdBI44LBAAYUBR4gRBDoQAChKHBv//z//4//8IdEdJdAg5wB8ETFgMP4JsBoEcHwbOLFIQRCoEAuEAdIQ1EvhZB4EH/kAv/gAgU8gEcgE4AIJrNHwsBgfggF+YoPAgP4gE/VoLFBNYYbBcAMfa4nB4FwFgLXCKAOAmF4ngRDEoOAgaaEPpMCTYOEiFgg/4gJoBnyjBeoQjCj/6FgOHw/hwE4WwI+B4kAvPAn1//eP/3h/84j6JBa5tBBYND8BHC9/A/PwjAcBYoUAuPwn0Mj/BKANBj0QofEiH/gYLB8akBkBWBg+AgOAcYIyBgbFEHwKYFeIb+D//gv/4KAUB4CACBwQCBwP/4FAgEYGoaYBv/Ai/+AgUD+EAnEAuEE8AkCDQJsBg72BCoXwJwKxB4MB8Fw4EfwEH/hHCp4vCDYMBhxZCHwLpEsEMj0Hg/DoP9iFffoP4DgMBk/wuF8jEPMQJrCsBHFRgKPBgZHDh/wrgRCDQIACvEcjEfgi8Bj/wr/kj/hg/goPgmFgVYcAE4IAEJAIlCHwMGAgNwCQLGBNQL7CgTHCAAiCBAAQA='))), + 32, + atob("BAUHCwsNEQQGBgkKBQkFBwwHCgkKCQoJCgoFBQsLCwkQDAwNDgwLDQ8HBw0LEQ0PDA8NCwwMDBINCwsGBwY="), + 18|65536 + ); +} + +const supaClockImg = { + width : 95, height : 13, bpp : 1, + buffer : atob("wL7B+Dhf4/C+4P//f328z0+/OZ9zPv/+/vt9fr99/X7e3f/8Bfb6/X77+vw9e///6+wMAv339fu+4DD/25v79Pv32/e4HNvAePf37BAweC+3+7f////////////P4B////////////////////////////7UEYf///////////2qrW////////////tdxh////////////iLtaA="), + palette: new Uint16Array([0, g.toColor("#fff")]), +} +const is12Hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"]; + +const interpolatePos = function(pos1, pos2, factor, easing) { + if (easing !== undefined) { + factor = Math.pow(factor, easing); + } + return {x: (pos1.x*(1-factor) + pos2.x*factor)/2, y: (pos1.y*(1-factor) + pos2.y*factor)/2} +} + +let drawSplashScreen = function (t, total) { + g.reset().setColor(g.theme.fg).setBgColor(g.theme.bg); + const startPos = {x: -200, y: R.h/2}; + const endPos = {x: 100, y: R.h/2}; + const lastPos = interpolatePos(startPos, endPos, (t-1)/total) + const pos = interpolatePos(startPos, endPos, t/total) + + g.setFontAlign(0, 1).setColor('#888').setFont("4x6:3").drawString('ULTRA', 100, t*18); + g.setFontAlign(0, 1).setColor('#888').setFont("4x6:3").drawString('PRO', 40, R.x2 - t*18); + + g.clearRect(0, pos.y-5, R.x2, pos.y + supaClockImg.height+5); + g.drawImage(supaClockImg, pos.x, pos.y, {scale: 2}); + +} + +let splashScreen = function () { + g.clearRect(R.x,R.y, R.x2, R.y2); + return new Promise((resolve, reject) => { + let t = 0; + function tick() { + drawSplashScreen(t, 10); + t += 1; + if (t < 20) { + setTimeout(tick, 100); + } else { + resolve(); + } + } + tick(); + }) +} + +// Actually draw the watch face +let draw = function() { + g.reset().setColor(g.theme.fg).setBgColor(g.theme.bg); + g.clearRect(R.x,R.y, R.x2, R.y2 - 60); + var date = new Date(); + let minutes = date.getMinutes(); + minutes = (minutes < 10 ? '0' : '') + minutes; + + g.setColor(g.theme.fg) + // Time + const yt = R.y + 92 - 20 - 30 + 6 + 10; + const xt = R.w/2; + let hours = date.getHours()+''; + + g.setFontAlign(1, 0).setFontPlayfairDisplay().drawString(hours, xt - 8, yt); + g.setFontAlign(0, 0).setFontPlayfairDisplay().drawString(':', xt, yt); + g.setFontAlign(-1, 0).setFontPlayfairDisplay().drawString(minutes, xt + 8, yt); + + g.drawImage(supaClockImg, R.x2 - supaClockImg.width - 2, R.y + 2); + // Day of week + + let dateStr = require("locale").dow(date).toUpperCase() + '\n' + require("locale").month(date, 2).toUpperCase() + ' ' + date.getDate(); + g.setFont('6x8').setFontAlign(-1, 0).drawString(dateStr, R.x2 - supaClockImg.width - 2, R.y + 42 - 30 + 8); + + g.drawLine(0, upperCI, R.x2, upperCI); + + // queue next draw + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +}; + +let clockInfoDraw = (itm, info, options) => { + g.reset().setFontPlayfairDisplaySm().setColor(g.theme.fg).setBgColor(g.theme.bg); + if (options.focus) g.setBgColor("#FF0"); + g.clearRect({x:options.x,y:options.y,w:options.w,h:options.h}); + + if (info.img) { + g.drawImage(info.img, options.x+1,options.y+2); + } + var text = info.text.toString().toUpperCase(); + if (g.setFontPlayfairDisplaySm().stringWidth(text)+24-2>options.w) g.setFont("8x12"); + g.setFontAlign(-1,-1).drawString(text, options.x+24+3, options.y+6); +}; + +let clockInfoDrawR = (itm, info, options) => { + g.reset().setFontPlayfairDisplaySm().setColor(g.theme.fg).setBgColor(g.theme.bg); + if (options.focus) g.setBgColor("#FF0"); + g.clearRect({x:options.x,y:options.y,w:options.w,h:options.h}); + + if (info.img) { + g.drawImage(info.img, options.x + options.w-1-24,options.y+2); + } + var text = info.text.toString().toUpperCase(); + if (g.setFontPlayfairDisplaySm().stringWidth(text)+24-2>options.w) g.setFont("8x12"); + g.setFontAlign(1,-1).drawString(text, options.x+options.w-24-3, options.y+6); +}; + +// Show launcher when middle button pressed +Bangle.setUI({ + mode : "clock", + remove : function() { + // Called to unload all of the clock app + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + // remove info menu + clockInfoMenu.remove(); + delete clockInfoMenu; + clockInfoMenu2.remove(); + delete clockInfoMenu2; + clockInfoMenu3.remove(); + delete clockInfoMenu3; + clockInfoMenu4.remove(); + delete clockInfoMenu4; + // reset theme + g.setTheme(oldTheme); + }}); +// Load widgets +Bangle.loadWidgets(); + +(() => { + function draw() { + g.reset(); // reset the graphics context to defaults (color/font/etc) + // add your code + g.drawString("XABCDEF", this.x, this.y); + } + + // add your widget + WIDGETS["mywidget"]={ + area:"tl", // tl (top left), tr (top right), bl (bottom left), br (bottom right), be aware that not all apps support widgets at the bottom of the screen + width: 28, // how wide is the widget? You can change this and call Bangle.drawWidgets() to re-layout + draw:draw // called to draw the widget + }; +})() + +// Work out sizes +let R = Bangle.appRect; +let midX = R.x+R.w/2; +let upperCI = R.y2-28-28; +let lowerCI = R.y2-28; + +// Clear the screen once, at startup +let oldTheme = g.theme; +g.clearRect(R.x, R.y, R.x2, R.y2); + +splashScreen().then(() => { + g.clearRect(R.x, 0, R.x2, R.y2); + draw(); + Bangle.drawWidgets(); + // Allocate and draw clockinfos + g.drawString('Loading Clock Info Modules...', R.x + 10, upperCI); + setTimeout(() => { + // delay loading of clock info, so that the clock face appears quicker + g.clearRect(R.x, upperCI, R.x2, upperCI+10); // clear loading text + let clockInfoItems = require("clock_info").load(); + let clockInfoMenu = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:R.x+1, y:upperCI, w:midX-2, h:28, draw : clockInfoDraw}); + let clockInfoMenu2 = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:midX+1, y:upperCI, w:midX-2, h:28, draw : clockInfoDrawR}); + let clockInfoMenu3 = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:R.x+1, y:lowerCI, w:midX-2, h:28, draw : clockInfoDraw}); + let clockInfoMenu4 = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:midX+1, y:lowerCI, w:midX-2, h:28, draw : clockInfoDrawR}); + }, 1); +}); + +} From be770a02dc39e7217bfc0813c9ca9df116046cce Mon Sep 17 00:00:00 2001 From: Tom Wallroth Date: Thu, 30 May 2024 15:13:42 +0200 Subject: [PATCH 2/4] Initial version done! --- apps/supaclk/ChangeLog | 1 + apps/supaclk/README.md | 25 ++++ apps/supaclk/app-icon.js | 1 + apps/{supaclockpro => supaclk}/app.js | 169 +++++++++++++------------- apps/supaclk/app.png | Bin 0 -> 3964 bytes apps/supaclk/metadata.json | 16 +++ apps/supaclk/screenshot.png | Bin 0 -> 3964 bytes apps/supaclk/screenshot2.png | Bin 0 -> 4206 bytes 8 files changed, 125 insertions(+), 87 deletions(-) create mode 100644 apps/supaclk/ChangeLog create mode 100644 apps/supaclk/README.md create mode 100644 apps/supaclk/app-icon.js rename apps/{supaclockpro => supaclk}/app.js (78%) create mode 100644 apps/supaclk/app.png create mode 100644 apps/supaclk/metadata.json create mode 100644 apps/supaclk/screenshot.png create mode 100644 apps/supaclk/screenshot2.png diff --git a/apps/supaclk/ChangeLog b/apps/supaclk/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/supaclk/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/supaclk/README.md b/apps/supaclk/README.md new file mode 100644 index 000000000..fc8f1a096 --- /dev/null +++ b/apps/supaclk/README.md @@ -0,0 +1,25 @@ +# SUPACLOCK Pro ULTRA + +A nice clock, with four ClockInfo areas at the bottom. Tap them and swipe up/down and left/right to toggle between different information. + + - Supports Light and Dark Themes. + - It has a useless splash-screen for increased ULTRAness + - Lazy Loading of Clock-Info, shows clock-face faster + - Uses locale module to display of day and month + + +Based on [LCD Clock Plus](https://banglejs.com/apps/?id=lcdclockplus) + +## Screenshots + +Light theme + +![light](screenshot.png) + +Dark theme + +![dark](screenshot2.png) + +## Credits + +Written by devsnd diff --git a/apps/supaclk/app-icon.js b/apps/supaclk/app-icon.js new file mode 100644 index 000000000..77598357b --- /dev/null +++ b/apps/supaclk/app-icon.js @@ -0,0 +1 @@ +atob("MDAB/////////////////////////////////gX2D8H//f328z3//f32+v3//AX2+v3///X2BgH///bm/v3/+A8e/v3//////////hf4/C+/+ffnM+5/+/ff1+3/+/ff1+H/+/ff1+7/+ffvt+9//BAweC+//////////4B//////AAf////+P+P////8+fH////48/H////45/H////8R/F////8x+A/////j8A/8H//j4APwD//AAYDjD//EA5HHD/+EByOHDf+EDkOGCf8OfkAAA/8P/4AAB/4P/8AAD/4f/8HAP/+///////////////55OAADx/55OTBxh/55OTD5k/55PTQDM/55PzxnAf4BAzzyOf8DAT7yff////////") diff --git a/apps/supaclockpro/app.js b/apps/supaclk/app.js similarity index 78% rename from apps/supaclockpro/app.js rename to apps/supaclk/app.js index 074425cef..c6731849f 100644 --- a/apps/supaclockpro/app.js +++ b/apps/supaclk/app.js @@ -2,6 +2,59 @@ // we also define functions using 'let fn = function() {..}' for the same reason. function decls are global let drawTimeout; +const supaClockImg = { + width : 95, height : 13, bpp : 1, + buffer : atob("wL7B+Dhf4/C+4P//f328z0+/OZ9zPv/+/vt9fr99/X7e3f/8Bfb6/X77+vw9e///6+wMAv339fu+4DD/25v79Pv32/e4HNvAePf37BAweC+3+7f////////////P4B////////////////////////////7UEYf///////////2qrW////////////tdxh////////////iLtaA="), + palette: new Uint16Array(g.theme.dark ? [g.toColor("#fff"), 0] : [0, g.toColor("#fff")]), +} +// todo +// const is12Hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"]; + +const interpolatePos = function(pos1, pos2, factor, easing) { + if (easing !== undefined) { + factor = Math.pow(factor, easing); + } + return {x: (pos1.x*(1-factor) + pos2.x*factor)/2, y: (pos1.y*(1-factor) + pos2.y*factor)/2} +} + +let drawSplashScreen = function (frame, total) { + const R = Bangle.appRect; + g.reset().setColor(g.theme.fg).setBgColor(g.theme.bg); + const startPos = {x: -200, y: R.h/2}; + const endPos = {x: R.x2 - supaClockImg.width*2 + 30, y: R.h/2}; + const pos = interpolatePos(startPos, endPos, frame/total, 0.1) + g.setFontAlign(0, 1).setColor('#888').setFont("4x6:3").drawString('ULTRA', 100, frame*18); + g.setFontAlign(0, 1).setColor('#888').setFont("4x6:3").drawString('PRO', 40, R.x2 - frame*18); + g.clearRect(0, pos.y-5, R.x2, pos.y + supaClockImg.height+25); + var date = new Date(); + let minutes = date.getMinutes(); + minutes = (minutes < 10 ? '0' : '') + minutes; + let hours = date.getHours()+''; + g.drawImage(supaClockImg, pos.x, pos.y, {scale: 2}); + g.setColor(0).setFont('6x8:2').setFontAlign(0, 1).drawString(hours + ':' + minutes, R.x2/2, pos.y + supaClockImg.height + 25) +} + +// for fast startup-feeling, draw the splash screen once directly once +drawSplashScreen(0, 20); + +let splashScreen = function () { + g.clearRect(R.x,R.y, R.x2, R.y2); + return new Promise((resolve, reject) => { + let frame = 0; + function tick() { + drawSplashScreen(frame, 20); + frame += 1; + if (frame < 20) { + setTimeout(tick, 50); + } else { + resolve(); + } + } + tick(); + }) +} + + Graphics.prototype.setFontPlayfairDisplay = function() { // https://www.espruino.com/Font+Converter // @@ -27,52 +80,6 @@ Graphics.prototype.setFontPlayfairDisplaySm = function() { ); } -const supaClockImg = { - width : 95, height : 13, bpp : 1, - buffer : atob("wL7B+Dhf4/C+4P//f328z0+/OZ9zPv/+/vt9fr99/X7e3f/8Bfb6/X77+vw9e///6+wMAv339fu+4DD/25v79Pv32/e4HNvAePf37BAweC+3+7f////////////P4B////////////////////////////7UEYf///////////2qrW////////////tdxh////////////iLtaA="), - palette: new Uint16Array([0, g.toColor("#fff")]), -} -const is12Hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"]; - -const interpolatePos = function(pos1, pos2, factor, easing) { - if (easing !== undefined) { - factor = Math.pow(factor, easing); - } - return {x: (pos1.x*(1-factor) + pos2.x*factor)/2, y: (pos1.y*(1-factor) + pos2.y*factor)/2} -} - -let drawSplashScreen = function (t, total) { - g.reset().setColor(g.theme.fg).setBgColor(g.theme.bg); - const startPos = {x: -200, y: R.h/2}; - const endPos = {x: 100, y: R.h/2}; - const lastPos = interpolatePos(startPos, endPos, (t-1)/total) - const pos = interpolatePos(startPos, endPos, t/total) - - g.setFontAlign(0, 1).setColor('#888').setFont("4x6:3").drawString('ULTRA', 100, t*18); - g.setFontAlign(0, 1).setColor('#888').setFont("4x6:3").drawString('PRO', 40, R.x2 - t*18); - - g.clearRect(0, pos.y-5, R.x2, pos.y + supaClockImg.height+5); - g.drawImage(supaClockImg, pos.x, pos.y, {scale: 2}); - -} - -let splashScreen = function () { - g.clearRect(R.x,R.y, R.x2, R.y2); - return new Promise((resolve, reject) => { - let t = 0; - function tick() { - drawSplashScreen(t, 10); - t += 1; - if (t < 20) { - setTimeout(tick, 100); - } else { - resolve(); - } - } - tick(); - }) -} - // Actually draw the watch face let draw = function() { g.reset().setColor(g.theme.fg).setBgColor(g.theme.bg); @@ -84,22 +91,17 @@ let draw = function() { g.setColor(g.theme.fg) // Time const yt = R.y + 92 - 20 - 30 + 6 + 10; - const xt = R.w/2; + const xt = R.w/2 - 5; let hours = date.getHours()+''; - g.setFontAlign(1, 0).setFontPlayfairDisplay().drawString(hours, xt - 8, yt); g.setFontAlign(0, 0).setFontPlayfairDisplay().drawString(':', xt, yt); g.setFontAlign(-1, 0).setFontPlayfairDisplay().drawString(minutes, xt + 8, yt); - + // logo g.drawImage(supaClockImg, R.x2 - supaClockImg.width - 2, R.y + 2); - // Day of week - + // dow + date let dateStr = require("locale").dow(date).toUpperCase() + '\n' + require("locale").month(date, 2).toUpperCase() + ' ' + date.getDate(); g.setFont('6x8').setFontAlign(-1, 0).drawString(dateStr, R.x2 - supaClockImg.width - 2, R.y + 42 - 30 + 8); - g.drawLine(0, upperCI, R.x2, upperCI); - - // queue next draw if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = setTimeout(function() { drawTimeout = undefined; @@ -133,67 +135,60 @@ let clockInfoDrawR = (itm, info, options) => { g.setFontAlign(1,-1).drawString(text, options.x+options.w-24-3, options.y+6); }; + +let clockInfoItems; +let clockInfoMenu1; +let clockInfoMenu2; +let clockInfoMenu3; +let clockInfoMenu4; + // Show launcher when middle button pressed Bangle.setUI({ mode : "clock", - remove : function() { - // Called to unload all of the clock app + remove : function() { // for fastloading, clear the app memory if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; - // remove info menu - clockInfoMenu.remove(); - delete clockInfoMenu; + delete Graphics.prototype.setFontPlayfairDisplay + delete Graphics.prototype.setFontPlayfairDisplaySm + delete clockInfoItems; + clockInfoMenu1.remove(); + delete clockInfoMenu1; clockInfoMenu2.remove(); delete clockInfoMenu2; clockInfoMenu3.remove(); delete clockInfoMenu3; clockInfoMenu4.remove(); delete clockInfoMenu4; - // reset theme - g.setTheme(oldTheme); }}); -// Load widgets + Bangle.loadWidgets(); -(() => { - function draw() { - g.reset(); // reset the graphics context to defaults (color/font/etc) - // add your code - g.drawString("XABCDEF", this.x, this.y); - } - - // add your widget - WIDGETS["mywidget"]={ - area:"tl", // tl (top left), tr (top right), bl (bottom left), br (bottom right), be aware that not all apps support widgets at the bottom of the screen - width: 28, // how wide is the widget? You can change this and call Bangle.drawWidgets() to re-layout - draw:draw // called to draw the widget - }; -})() - -// Work out sizes let R = Bangle.appRect; let midX = R.x+R.w/2; let upperCI = R.y2-28-28; let lowerCI = R.y2-28; -// Clear the screen once, at startup -let oldTheme = g.theme; g.clearRect(R.x, R.y, R.x2, R.y2); - splashScreen().then(() => { g.clearRect(R.x, 0, R.x2, R.y2); draw(); Bangle.drawWidgets(); // Allocate and draw clockinfos - g.drawString('Loading Clock Info Modules...', R.x + 10, upperCI); + g.setFontAlign(1, 1).setFont('6x8').drawString('Loading Clock Info Modules...', R.x + 10, upperCI); setTimeout(() => { // delay loading of clock info, so that the clock face appears quicker g.clearRect(R.x, upperCI, R.x2, upperCI+10); // clear loading text - let clockInfoItems = require("clock_info").load(); - let clockInfoMenu = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:R.x+1, y:upperCI, w:midX-2, h:28, draw : clockInfoDraw}); - let clockInfoMenu2 = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:midX+1, y:upperCI, w:midX-2, h:28, draw : clockInfoDrawR}); - let clockInfoMenu3 = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:R.x+1, y:lowerCI, w:midX-2, h:28, draw : clockInfoDraw}); - let clockInfoMenu4 = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:midX+1, y:lowerCI, w:midX-2, h:28, draw : clockInfoDrawR}); + try { + clockInfoItems = require("clock_info").load(); + clockInfoMenu1 = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:R.x+1, y:upperCI, w:midX-2, h:28, draw : clockInfoDraw}); + clockInfoMenu2 = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:midX+1, y:upperCI, w:midX-2, h:28, draw : clockInfoDrawR}); + clockInfoMenu3 = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:R.x+1, y:lowerCI, w:midX-2, h:28, draw : clockInfoDraw}); + clockInfoMenu4 = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:midX+1, y:lowerCI, w:midX-2, h:28, draw : clockInfoDrawR}); + } catch(err) { + if ((err + '').includes('Module "clock_info" not found' )) { + g.setFont('6x8').drawString('Please install\nclockinfo module!', R.x + 10, upperCI); + } + } }, 1); }); diff --git a/apps/supaclk/app.png b/apps/supaclk/app.png new file mode 100644 index 0000000000000000000000000000000000000000..54f2047a58f4193aebeae3d8a83842d088ccb2d9 GIT binary patch literal 3964 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 WMWWKyoVMox00000J~ literal 0 HcmV?d00001 diff --git a/apps/supaclk/metadata.json b/apps/supaclk/metadata.json new file mode 100644 index 000000000..016182545 --- /dev/null +++ b/apps/supaclk/metadata.json @@ -0,0 +1,16 @@ +{ "id": "supaclk", + "name": "SUPACLOCK Pro ULTRA", + "version": "0.01", + "description": "SUPACLOCK Pro ULTRA, with four ClockInfo areas at the bottom. Tap them and swipe up/down and left/right to toggle between different information.", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"},{"url":"screenshot2.png"}], + "type": "clock", + "tags": "clock,clkinfo,clockinfo", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "dependencies" : { "clock_info":"module" }, + "storage": [ + {"name":"supaclk.app.js","url":"app.js"}, + {"name":"supaclk.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/supaclk/screenshot.png b/apps/supaclk/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..54f2047a58f4193aebeae3d8a83842d088ccb2d9 GIT binary patch literal 3964 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 WMWWKyoVMox00000J~ literal 0 HcmV?d00001 diff --git a/apps/supaclk/screenshot2.png b/apps/supaclk/screenshot2.png new file mode 100644 index 0000000000000000000000000000000000000000..46d04a1661dc2d931a1d36801d052064a89858a2 GIT binary patch literal 4206 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 Ef>;jwKmY&$ literal 0 HcmV?d00001 From 249a119e12c06c5019173e70ef625be3ee51ce22 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Sat, 1 Jun 2024 13:41:35 +0200 Subject: [PATCH 3/4] supaclk: misc suggested fixes and changes - clear screen including widgets before drawing splash screen. - change from a font that's not defined to one that is. - make it so the splash screen can be cut short to load the launcher. --- apps/supaclk/app.js | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/apps/supaclk/app.js b/apps/supaclk/app.js index c6731849f..b9ac0ba5b 100644 --- a/apps/supaclk/app.js +++ b/apps/supaclk/app.js @@ -1,5 +1,6 @@ { // 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 + // we also define functions using 'let fn = function() {..}' for the same reason. function decls are globalj +let removeHasNotRun = true; let drawTimeout; const supaClockImg = { @@ -35,6 +36,7 @@ let drawSplashScreen = function (frame, total) { } // for fast startup-feeling, draw the splash screen once directly once +g.clear() drawSplashScreen(0, 20); let splashScreen = function () { @@ -42,9 +44,11 @@ let splashScreen = function () { return new Promise((resolve, reject) => { let frame = 0; function tick() { - drawSplashScreen(frame, 20); + if (removeHasNotRun) drawSplashScreen(frame, 20); frame += 1; - if (frame < 20) { + if (!removeHasNotRun) { + reject(); + } else if (frame < 20) { setTimeout(tick, 50); } else { resolve(); @@ -118,7 +122,7 @@ let clockInfoDraw = (itm, info, options) => { g.drawImage(info.img, options.x+1,options.y+2); } var text = info.text.toString().toUpperCase(); - if (g.setFontPlayfairDisplaySm().stringWidth(text)+24-2>options.w) g.setFont("8x12"); + if (g.setFontPlayfairDisplaySm().stringWidth(text)+24-2>options.w) g.setFont("4x6:2"); g.setFontAlign(-1,-1).drawString(text, options.x+24+3, options.y+6); }; @@ -131,7 +135,7 @@ let clockInfoDrawR = (itm, info, options) => { g.drawImage(info.img, options.x + options.w-1-24,options.y+2); } var text = info.text.toString().toUpperCase(); - if (g.setFontPlayfairDisplaySm().stringWidth(text)+24-2>options.w) g.setFont("8x12"); + if (g.setFontPlayfairDisplaySm().stringWidth(text)+24-2>options.w) g.setFont("4x6:2"); g.setFontAlign(1,-1).drawString(text, options.x+options.w-24-3, options.y+6); }; @@ -146,18 +150,19 @@ let clockInfoMenu4; Bangle.setUI({ mode : "clock", remove : function() { // for fastloading, clear the app memory + removeHasNotRun = false; if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; delete Graphics.prototype.setFontPlayfairDisplay delete Graphics.prototype.setFontPlayfairDisplaySm delete clockInfoItems; - clockInfoMenu1.remove(); + clockInfoMenu1&&clockInfoMenu1.remove(); delete clockInfoMenu1; - clockInfoMenu2.remove(); + clockInfoMenu2&&clockInfoMenu2.remove(); delete clockInfoMenu2; - clockInfoMenu3.remove(); + clockInfoMenu3&&clockInfoMenu3.remove(); delete clockInfoMenu3; - clockInfoMenu4.remove(); + clockInfoMenu4&&clockInfoMenu4.remove(); delete clockInfoMenu4; }}); @@ -190,6 +195,6 @@ splashScreen().then(() => { } } }, 1); -}); +},() => {}); } From 82a5ab5724116f903d4b4d28703f204d21876c99 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Sat, 1 Jun 2024 15:12:01 +0200 Subject: [PATCH 4/4] supaclk: remove unnecessary delete in remove funct since they are initiatied with let inside the outer curly braces they should be cleared automatically like all other let-ibles. --- apps/supaclk/app.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/apps/supaclk/app.js b/apps/supaclk/app.js index b9ac0ba5b..f0bf32ae5 100644 --- a/apps/supaclk/app.js +++ b/apps/supaclk/app.js @@ -155,15 +155,10 @@ Bangle.setUI({ drawTimeout = undefined; delete Graphics.prototype.setFontPlayfairDisplay delete Graphics.prototype.setFontPlayfairDisplaySm - delete clockInfoItems; clockInfoMenu1&&clockInfoMenu1.remove(); - delete clockInfoMenu1; clockInfoMenu2&&clockInfoMenu2.remove(); - delete clockInfoMenu2; clockInfoMenu3&&clockInfoMenu3.remove(); - delete clockInfoMenu3; clockInfoMenu4&&clockInfoMenu4.remove(); - delete clockInfoMenu4; }}); Bangle.loadWidgets();