diff --git a/apps/aiclock/ChangeLog b/apps/aiclock/ChangeLog index 96b389f6e..fb5aed3e3 100644 --- a/apps/aiclock/ChangeLog +++ b/apps/aiclock/ChangeLog @@ -2,3 +2,4 @@ 0.02: Design improvements and fixes. 0.03: Indicate battery level through line occurrence. 0.04: Use widget_utils module. +0.05: Support for clkinfo. \ No newline at end of file diff --git a/apps/aiclock/README.md b/apps/aiclock/README.md index 9e23de3a6..31dd5aa29 100644 --- a/apps/aiclock/README.md +++ b/apps/aiclock/README.md @@ -10,7 +10,9 @@ The original output of stable diffusion is shown here: My implementation is shown below. Note that horizontal lines occur randomly, but the probability is correlated with the battery level. So if your screen contains only -a few lines its time to charge your bangle again ;) +a few lines its time to charge your bangle again ;) Also note that the upper text +implementes the clkinfo module and can be configured via touch left/right/up/down. +Touch at the center to trigger the selected action. ![](impl.png) diff --git a/apps/aiclock/aiclock.app.js b/apps/aiclock/aiclock.app.js index 5d4e98fcd..b5bb30b9d 100644 --- a/apps/aiclock/aiclock.app.js +++ b/apps/aiclock/aiclock.app.js @@ -1,6 +1,14 @@ -/** +/************************************************ * AI Clock */ + const storage = require('Storage'); + const clock_info = require("clock_info"); + + + + /************************************************ + * Assets + */ require("Font7x11Numeric7Seg").add(Graphics); Graphics.prototype.setFontGochiHand = function(scale) { // Actual height 27 (29 - 3) @@ -13,7 +21,7 @@ Graphics.prototype.setFontGochiHand = function(scale) { return this; } -/* +/************************************************ * Set some important constants such as width, height and center */ var W = g.getWidth(),R=W/2; @@ -21,6 +29,120 @@ var H = g.getHeight(); var cx = W/2; var cy = H/2; var drawTimeout; +var lock_input = false; + + +/************************************************ + * SETTINGS + */ +const SETTINGS_FILE = "aiclock.setting.json"; +let settings = { + menuPosX: 0, + menuPosY: 0, +}; +let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; +for (const key in saved_settings) { + settings[key] = saved_settings[key] +} + + +/************************************************ + * Menu + */ +function getDate(){ + var date = new Date(); + return ("0"+date.getDate()).substr(-2) + "/" + ("0"+(date.getMonth()+1)).substr(-2) +} + + +// Custom clockItems menu - therefore, its added here and not in a clkinfo.js file. +var clockItems = { + name: getDate(), + img: null, + items: [ + { name: "Week", + get: () => ({ text: "Week " + weekOfYear(), img: null}), + show: function() { clockItems.items[0].emit("redraw"); }, + hide: function () {} + }, + ] + }; + +function weekOfYear() { + var date = new Date(); + date.setHours(0, 0, 0, 0); + // Thursday in current week decides the year. + date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7); + // January 4 is always in week 1. + var week1 = new Date(date.getFullYear(), 0, 4); + // Adjust to Thursday in week 1 and count number of weeks from date to week1. + return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 + - 3 + (week1.getDay() + 6) % 7) / 7); +} + + + +// Load menu +var menu = clock_info.load(); +menu = menu.concat(clockItems); + + + // Ensure that our settings are still in range (e.g. app uninstall). Otherwise reset the position it. + if(settings.menuPosX >= menu.length || settings.menuPosY > menu[settings.menuPosX].items.length ){ + settings.menuPosX = 0; + settings.menuPosY = 0; + } + + // Set draw functions for each item + menu.forEach((menuItm, x) => { + menuItm.items.forEach((item, y) => { + function drawItem() { + // For the clock, we have a special case, as we don't wanna redraw + // immediately when something changes. Instead, we update data each minute + // to save some battery etc. Therefore, we hide (and disable the listener) + // immedeately after redraw... + item.hide(); + + // After drawing the item, we enable inputs again... + lock_input = false; + + var info = item.get(); + drawMenuItem(info.text, info.img); + } + + item.on('redraw', drawItem); + }) + }); + + + function canRunMenuItem(){ + if(settings.menuPosY == 0){ + return false; + } + + var menuEntry = menu[settings.menuPosX]; + var item = menuEntry.items[settings.menuPosY-1]; + return item.run !== undefined; + } + + + function runMenuItem(){ + if(settings.menuPosY == 0){ + return; + } + + var menuEntry = menu[settings.menuPosX]; + var item = menuEntry.items[settings.menuPosY-1]; + try{ + var ret = item.run(); + if(ret){ + Bangle.buzz(300, 0.6); + } + } catch (ex) { + // Simply ignore it... + } + } + /* * Based on the great multi clock from https://github.com/jeffmer/BangleApps/ @@ -76,7 +198,50 @@ function toAngle(a){ return a } + +function drawMenuItem(text, image){ + if(text == null){ + drawTime(); + return + } + // image = atob("GBiBAAD+AAH+AAH+AAH+AAH/AAOHAAYBgAwAwBgwYBgwYBgwIBAwOBAwOBgYIBgMYBgAYAwAwAYBgAOHAAH/AAH+AAH+AAH+AAD+AA=="); + + text = String(text); + + g.reset().setBgColor("#fff").setColor("#000"); + g.setFontAlign(0,0); + g.setFont("Vector", 20); + + var imgWidth = image == null ? 0 : 24; + var strWidth = g.stringWidth(text); + var strHeight = text.split('\n').length > 1 ? 40 : Math.max(24, imgWidth+2); + var w = imgWidth + strWidth; + + g.clearRect(cx-w/2-8, 40-strHeight/2-1, cx+w/2+4, 40+strHeight/2) + + // Draw right line as designed by stable diffusion + g.drawLine(cx+w/2+5, 40-strHeight/2-1, cx+w/2+5, 40+strHeight/2); + g.drawLine(cx+w/2+6, 40-strHeight/2-1, cx+w/2+6, 40+strHeight/2); + g.drawLine(cx+w/2+7, 40-strHeight/2-1, cx+w/2+7, 40+strHeight/2); + + // And finally the text + g.drawString(text, cx+imgWidth/2, 42); + g.drawString(text, cx+1+imgWidth/2, 41); + + if(image != null) { + var scale = image.width ? imgWidth / image.width : 1; + g.drawImage(image, W/2 + -strWidth/2-4 - parseInt(imgWidth/2), 41-12, {scale: scale}); + } + + drawTime(); +} + + function drawTime(){ + // Draw digital time first + drawDigits(); + + // And now the analog time var drawHourHand = g.drawRotRect.bind(g,8,12,R-38); var drawMinuteHand = g.drawRotRect.bind(g,6,12,R-12 ); @@ -90,13 +255,6 @@ function drawTime(){ h += date.getMinutes()/60.0; h = parseInt(h*360/12); - // Draw minute and hour bg - g.setColor(g.theme.bg); - drawHourHand(toAngle(h-3)); - drawHourHand(toAngle(h+3)); - drawMinuteHand(toAngle(m-2)); - drawMinuteHand(toAngle(m+3)); - // Draw minute and hour fg g.setColor(g.theme.fg); drawHourHand(h); @@ -104,28 +262,6 @@ function drawTime(){ } - -function drawDate(){ - var date = new Date(); - g.setFontAlign(0,0); - g.setFontGochiHand(); - - var text = ("0"+date.getDate()).substr(-2) + "/" + ("0"+(date.getMonth()+1)).substr(-2); - var w = g.stringWidth(text); - g.setColor(g.theme.bg); - g.fillRect(cx-w/2-4, 20, cx+w/2+4, 40+12); - - g.setColor(g.theme.fg); - // Draw right line as designed by stable diffusion - g.drawLine(cx+w/2+5, 20, cx+w/2+5, 40+12); - g.drawLine(cx+w/2+6, 20, cx+w/2+6, 40+12); - g.drawLine(cx+w/2+7, 20, cx+w/2+7, 40+12); - - // And finally the text - g.drawString(text, cx, 40); -} - - function drawDigits(){ var date = new Date(); @@ -156,20 +292,35 @@ function drawDigits(){ } +function drawDate(){ + var menuEntry = menu[settings.menuPosX]; + + // The first entry is the overview... + if(settings.menuPosY == 0){ + drawMenuItem(menuEntry.name, menuEntry.img); + return; + } + + // Draw item if needed + lock_input = true; + var item = menuEntry.items[settings.menuPosY-1]; + item.show(); +} + + + + function draw(){ // Queue draw in one minute queueDraw(); - g.reset(); g.clearRect(0, 0, g.getWidth(), g.getHeight()); - g.setColor(1,1,1); + drawBackground(); drawDate(); - drawDigits(); - drawTime(); drawCircle(Bangle.isLocked()); } @@ -190,6 +341,68 @@ Bangle.on('lock', function(isLocked) { drawCircle(isLocked); }); +Bangle.on('touch', function(btn, e){ + var left = parseInt(g.getWidth() * 0.22); + var right = g.getWidth() - left; + var upper = parseInt(g.getHeight() * 0.22); + var lower = g.getHeight() - upper; + + var is_upper = e.y < upper; + var is_lower = e.y > lower; + var is_left = e.x < left && !is_upper && !is_lower; + var is_right = e.x > right && !is_upper && !is_lower; + var is_center = !is_upper && !is_lower && !is_left && !is_right; + + if(lock_input){ + return; + } + + if(is_lower){ + Bangle.buzz(40, 0.6); + settings.menuPosY = (settings.menuPosY+1) % (menu[settings.menuPosX].items.length+1); + + draw(); + } + + if(is_upper){ + Bangle.buzz(40, 0.6); + settings.menuPosY = settings.menuPosY-1; + settings.menuPosY = settings.menuPosY < 0 ? menu[settings.menuPosX].items.length : settings.menuPosY; + + draw(); + } + + if(is_right){ + Bangle.buzz(40, 0.6); + settings.menuPosX = (settings.menuPosX+1) % menu.length; + settings.menuPosY = 0; + draw(); + } + + if(is_left){ + Bangle.buzz(40, 0.6); + settings.menuPosY = 0; + settings.menuPosX = settings.menuPosX-1; + settings.menuPosX = settings.menuPosX < 0 ? menu.length-1 : settings.menuPosX; + draw(); + } + + if(is_center){ + if(canRunMenuItem()){ + runMenuItem(); + } + } +}); + + +E.on("kill", function(){ + try{ + storage.write(SETTINGS_FILE, settings); + } catch(ex){ + // If this fails, we still kill the app... + } +}); + /* * Some helpers @@ -203,7 +416,6 @@ function queueDraw() { } - /* * Lets start widgets, listen for btn etc. */ @@ -216,6 +428,7 @@ Bangle.loadWidgets(); * area to the top bar doesn't get cleared. */ require('widget_utils').hide(); + // Clear the screen once, at startup and draw clock g.setTheme({bg:"#fff",fg:"#000",dark:false}).clear(); draw(); diff --git a/apps/aiclock/impl.png b/apps/aiclock/impl.png index 92374b680..8a9e43e2d 100644 Binary files a/apps/aiclock/impl.png and b/apps/aiclock/impl.png differ diff --git a/apps/aiclock/impl_2.png b/apps/aiclock/impl_2.png new file mode 100644 index 000000000..be3519a4b Binary files /dev/null and b/apps/aiclock/impl_2.png differ diff --git a/apps/aiclock/impl_3.png b/apps/aiclock/impl_3.png new file mode 100644 index 000000000..c2a036d14 Binary files /dev/null and b/apps/aiclock/impl_3.png differ diff --git a/apps/aiclock/metadata.json b/apps/aiclock/metadata.json index 0da23e8ca..1c3c68609 100644 --- a/apps/aiclock/metadata.json +++ b/apps/aiclock/metadata.json @@ -3,7 +3,7 @@ "name": "AI Clock", "shortName":"AI Clock", "icon": "aiclock.png", - "version":"0.04", + "version":"0.05", "readme": "README.md", "supports": ["BANGLEJS2"], "description": "A watch face that was designed by an AI (stable diffusion) and implemented by a human.", @@ -11,7 +11,9 @@ "tags": "clock", "screenshots": [ {"url":"orig.png"}, - {"url":"impl.png"} + {"url":"impl.png"}, + {"url":"impl_2.png"}, + {"url":"impl_3.png"}, ], "storage": [ {"name":"aiclock.app.js","url":"aiclock.app.js"}, diff --git a/apps/ha/ChangeLog b/apps/ha/ChangeLog index a4865be3f..f9ca3c16d 100644 --- a/apps/ha/ChangeLog +++ b/apps/ha/ChangeLog @@ -2,4 +2,5 @@ 0.02: Includeas the ha.lib.js library that can be used by other apps or clocks. 0.03: Added clkinfo for clocks. 0.04: Feedback if clkinfo run is called. -0.05: Clkinfo improvements. \ No newline at end of file +0.05: Clkinfo improvements. +0.06: Updated clkinfo icon. \ No newline at end of file diff --git a/apps/ha/ha.clkinfo.js b/apps/ha/ha.clkinfo.js index 1b1e468d7..d6a0f72a0 100644 --- a/apps/ha/ha.clkinfo.js +++ b/apps/ha/ha.clkinfo.js @@ -4,7 +4,7 @@ var haItems = { name: "Home", - img: atob("GBiBAf/////////n///D//+B//8A//48T/wkD/gkD/A8D+AYB8AYA4eZ4QyZMOyZN+fb5+D/B+B+B+A8B+AYB+AYB+AYB+AYB+A8Bw=="), + img: atob("GBiBAAAAAAAAAAAAAAAYAAA+AAB+AADD4AHb4APD4Afn8A/n+BxmOD0mnA0ksAwAMA+B8A/D8A/n8A/n8A/n8A/n8AAAAAAAAAAAAA=="), items: [] }; diff --git a/apps/ha/metadata.json b/apps/ha/metadata.json index fad052544..089450f55 100644 --- a/apps/ha/metadata.json +++ b/apps/ha/metadata.json @@ -1,7 +1,7 @@ { "id": "ha", "name": "HomeAssistant", - "version": "0.05", + "version": "0.06", "description": "Integrates your BangleJS into HomeAssistant.", "icon": "ha.png", "type": "app", diff --git a/apps/smpltmr/ChangeLog b/apps/smpltmr/ChangeLog index b09100f50..805e8546f 100644 --- a/apps/smpltmr/ChangeLog +++ b/apps/smpltmr/ChangeLog @@ -1,4 +1,5 @@ 0.01: Release 0.02: Rewrite with new interface 0.03: Added clock infos to expose timer functionality to clocks. -0.04: Improvements of clock infos. \ No newline at end of file +0.04: Improvements of clock infos. +0.05: Updated clkinfo icon. \ No newline at end of file diff --git a/apps/smpltmr/clkinfo.js b/apps/smpltmr/clkinfo.js index 1a63a9b7e..c16e6127e 100644 --- a/apps/smpltmr/clkinfo.js +++ b/apps/smpltmr/clkinfo.js @@ -63,10 +63,9 @@ } catch(ex){ } } - var img = atob("GBiBAeAAB+AAB/v/3/v/3/v/3/v/3/v/n/n/H/z+P/48//85//+b//+b//8p//4E//yCP/kBH/oAn/oAX/oAX/oAX/oAX+AAB+AABw==") var smpltmrItems = { name: "Timer", - img: img, + img: atob("GBiBAAB+AAB+AAAYAAAYAAB+AA3/sA+B8A4AcAwMMBgPGBgPmDAPjDAPzDAPzDP/zDP/zDH/jBn/mBj/GAw8MA4AcAeB4AH/gAB+AA=="), items: [ { name: null, diff --git a/apps/smpltmr/metadata.json b/apps/smpltmr/metadata.json index ce526d1ba..2191902de 100644 --- a/apps/smpltmr/metadata.json +++ b/apps/smpltmr/metadata.json @@ -2,7 +2,7 @@ "id": "smpltmr", "name": "Simple Timer", "shortName": "Simple Timer", - "version": "0.04", + "version": "0.05", "description": "A very simple app to start a timer.", "icon": "app.png", "tags": "tool,alarm,timer,clkinfo", diff --git a/apps/weather/ChangeLog b/apps/weather/ChangeLog index aefb903b9..1b6c1b9b5 100644 --- a/apps/weather/ChangeLog +++ b/apps/weather/ChangeLog @@ -17,3 +17,4 @@ 0.18: Added hasRange to clkinfo. 0.19: Added weather condition to clkinfo. 0.20: Added weather condition with temperature to clkinfo. +0.21: Updated clkinfo icon. \ No newline at end of file diff --git a/apps/weather/clkinfo.js b/apps/weather/clkinfo.js index 339ff39c3..3cdd31c59 100644 --- a/apps/weather/clkinfo.js +++ b/apps/weather/clkinfo.js @@ -28,7 +28,7 @@ //FIXME ranges are somehow arbitrary var weatherItems = { name: "Weather", - img: atob("GBiBAf+///u5//n7//8f/9wHP8gDf/gB//AB/7AH/5AcP/AQH/DwD/uAD84AD/4AA/wAAfAAAfAAAfAAAfgAA/////+bP/+zf/+zfw=="), + img: atob("GBiBAABAAARGAAYEAADgACP4wDf8gAf+AA/+AE/4AG/jwA/v4A8P8AR/8DH/8AH//AP//g///g///g///gf//AAAAABkwABMgABMgA=="), items: [ { name: "conditionWithTemperature", diff --git a/apps/weather/metadata.json b/apps/weather/metadata.json index dd8b6c293..500eac012 100644 --- a/apps/weather/metadata.json +++ b/apps/weather/metadata.json @@ -1,7 +1,7 @@ { "id": "weather", "name": "Weather", - "version": "0.20", + "version": "0.21", "description": "Show Gadgetbridge weather report", "icon": "icon.png", "screenshots": [{"url":"screenshot.png"}], diff --git a/core b/core index 3a953179b..764197500 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 3a953179b7bb9f574d4e77d5f34b6b7deee1e884 +Subproject commit 76419750083a88ee7a569db3975ae1bdd6dc155a diff --git a/modules/clock_info.js b/modules/clock_info.js index 238888b1c..50968311e 100644 --- a/modules/clock_info.js +++ b/modules/clock_info.js @@ -77,7 +77,7 @@ exports.load = function() { // actual menu var menu = [{ name: "Bangle", - img: atob("GBiBAf8B//4B//4B//4B//4A//x4//n+f/P/P+fPn+fPn+fP3+/Px+/Px+fn3+fzn+f/n/P/P/n+f/x4//4A//4B//4B//4B//8B/w=="), + img: atob("GBiBAAD+AAH+AAH+AAH+AAH/AAOHAAYBgAwAwBgwYBgwYBgwIBAwOBAwOBgYIBgMYBgAYAwAwAYBgAOHAAH/AAH+AAH+AAH+AAD+AA=="), items: [ { name : "Battery", hasRange : true,