From 973b8e1565bc1183546fc6e5f6f22fe1eb03d38e Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 7 Dec 2022 09:58:45 +0000 Subject: [PATCH] circlesclock 0.19: Remove old code and fixing clkinfo handling (fix HRM and other items that change) --- apps/circlesclock/ChangeLog | 1 + apps/circlesclock/app.js | 693 +++----------------------------- apps/circlesclock/metadata.json | 2 +- apps/circlesclock/settings.js | 8 +- 4 files changed, 66 insertions(+), 638 deletions(-) diff --git a/apps/circlesclock/ChangeLog b/apps/circlesclock/ChangeLog index 8ec578fb6..b1b5637ad 100644 --- a/apps/circlesclock/ChangeLog +++ b/apps/circlesclock/ChangeLog @@ -32,3 +32,4 @@ Use widget_utils if available 0.17: Load circles from clkinfo 0.18: Improved clkinfo handling and using it for the weather circle +0.19: Remove old code and fixing clkinfo handling (fix HRM and other items that change) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index ee6741398..11036dcfc 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -18,7 +18,6 @@ let settings = Object.assign( storage.readJSON("circlesclock.default.json", true) || {}, storage.readJSON(SETTINGS_FILE, true) || {} ); - //TODO deprecate this (and perhaps use in the clkinfo module) // Load step goal from health app and pedometer widget as fallback if (settings.stepGoal == undefined) { @@ -31,17 +30,7 @@ if (settings.stepGoal == undefined) { } } -let timerHrm; //TODO deprecate this let drawTimeout; - -/* - * Read location from myLocation app - */ -function getLocation() { - return storage.readJSON("mylocation.json", 1) || undefined; -} -let location = getLocation(); - let showWidgets = settings.showWidgets || false; let circleCount = settings.circleCount || 3; let showBigWeather = settings.showBigWeather || false; @@ -106,39 +95,9 @@ let circleItemNum = [ 2, // circle3 3, // circle4 ]; -let weatherCircleNum = 0; -let weatherCircleDataNum = 0; -let weatherCircleCondNum = 0; -let weatherCircleTempNum = 0; - -function hideWidgets() { - /* - * we are not drawing the widgets as we are taking over the whole screen - * so we will blank out the draw() functions of each widget and change the - * area to the top bar doesn't get cleared. - */ - if (WIDGETS && typeof WIDGETS === "object") { - for (let wd of WIDGETS) { - wd.draw = () => {}; - wd.area = ""; - } - } -} function draw() { - g.clear(true); - let widgetUtils; - - try { - widgetUtils = require("widget_utils"); - } catch (e) { - } - if (!showWidgets) { - if (widgetUtils) widgetUtils.hide(); else hideWidgets(); - } else { - if (widgetUtils) widgetUtils.show(); - Bangle.drawWidgets(); - } + g.reset().clearRect(Bangle.appRect); g.setColor(colorBg); g.fillRect(0, widgetOffset, w, h2 + 22); @@ -180,117 +139,18 @@ function draw() { if (icon) g.drawImage(icon, w - 48, h1, {scale:0.75}); } - drawCircle(1); - drawCircle(2); - drawCircle(3); - if (circleCount >= 4) drawCircle(4); + // FIXME do we really need to redraw circles every time? + for (var i=1;i<=circleCount;i++) + drawCircle(i); queueDraw(); } -function drawCircle(index) { - let type = settings['circle' + index]; - if (!type) type = defaultCircleTypes[index - 1]; - let w = getCircleXPosition(type); - - switch (type) { - case "weather": - drawWeather(w); - break; - case "sunprogress": - case "sunProgress": - drawSunProgress(w); - break; - //TODO those are going to be deprecated, keep for backwards compatibility for now - //ideally all data should come from some clkinfo - case "steps": - drawSteps(w); - break; - case "stepsDist": - drawStepsDistance(w); - break; - case "hr": - drawHeartRate(w); - break; - case "battery": - drawBattery(w); - break; - case "temperature": - drawTemperature(w); - break; - case "pressure": - drawPressure(w); - break; - case "altitude": - drawAltitude(w); - break; - //end deprecated - case "empty": - // we draw nothing here - return; - default: - drawClkInfo(index, w); - } -} - -// serves as cache for quicker lookup of circle positions -let circlePositionsCache = []; -/* - * Looks in the following order if a circle with the given type is somewhere visible/configured - * 1. circlePositionsCache - * 2. settings - * 3. defaultCircleTypes - * - * In case 2 and 3 the circlePositionsCache will be updated - */ -function getCirclePosition(type) { - if (circlePositionsCache[type] >= 0) { - return circlePositionsCache[type]; - } - for (let i = 1; i <= circleCount; i++) { - let setting = settings['circle' + i]; - if (setting == type) { - circlePositionsCache[type] = i - 1; - return i - 1; - } - } - for (let i = 0; i < defaultCircleTypes.length; i++) { - if (type == defaultCircleTypes[i] && (!settings || settings['circle' + (i + 1)] == undefined)) { - circlePositionsCache[type] = i; - return i; - } - } - return undefined; -} - -function getCircleXPosition(type) { - let circlePos = getCirclePosition(type); - if (circlePos != undefined) { - return circlePosX[circlePos]; - } - return undefined; -} - -function isCircleEnabled(type) { - return getCirclePosition(type) != undefined; -} - -function getCircleColor(type) { - let pos = getCirclePosition(type); - let color = settings["circle" + (pos + 1) + "color"]; +function getCircleColor(index) { + let color = settings["circle" + index + "color"]; if (color && color != "") return color; } -function getCircleIconColor(type, color, percent) { - let pos = getCirclePosition(type); - let colorizeIcon = settings["circle" + (pos + 1) + "colorizeIcon"] == true; - if (colorizeIcon) { - return getGradientColor(color, percent); - } else { - return ""; - } -} - function getGradientColor(color, percent) { if (isNaN(percent)) percent = 0; if (percent > 1) percent = 1; @@ -311,422 +171,15 @@ function getGradientColor(color, percent) { return color; } -function getImage(graphic, color) { - if (!color || color == "") { - return graphic; +function getCircleIconColor(index, color, percent) { + let colorizeIcon = settings["circle" + index + "colorizeIcon"] == true; + if (colorizeIcon) { + return getGradientColor(color, percent); } else { - return { - width: 16, - height: 16, - bpp: 1, - transparent: 0, - buffer: E.toArrayBuffer(graphic), - palette: new Uint16Array([colorBg, g.toColor(color)]) - }; + return ""; } } -function drawWeather(w) { - if (!w) w = getCircleXPosition("weather"); - let weatherInfo = menu[weatherCircleNum]; - let weatherCond = weatherCircleCondNum >= 0? weatherInfo.items[weatherCircleCondNum]: undefined; - let weatherData = weatherCircleDataNum >= 0? weatherInfo.items[weatherCircleDataNum]: undefined; - let weatherTemp = weatherCircleTempNum >= 0? weatherInfo.items[weatherCircleTempNum]: undefined; - let color = getCircleColor("weather"); - let percent = 0; - let data = settings.weatherCircleData; - let tempString = "?", icon = undefined; - let scale = 16/24; //our icons are 16x16 while clkinfo's are 24x24 - - if(weatherCond) { - weatherCond.show() - weatherCond.hide() - let data = weatherCond.get() - if(settings.legacyWeatherIcons) { //may disappear in future - icon = getWeatherIconByCode(data.v); - scale = 1; - } else - icon = data.img; - } - if(weatherTemp) { - weatherTemp.show() - weatherTemp.hide() - tempString = weatherTemp.get().text; - } - - drawCircleBackground(w); - - if(weatherData) { - weatherData.show(); - weatherData.hide(); - let data = weatherData.get(); - if(weatherData.hasRange) percent = (data.v-data.min) / (data.max-data.min); - drawGauge(w, h3, percent, color); - } - - drawInnerCircleAndTriangle(w); - - writeCircleText(w, tempString); - - if(icon) { - g.setColor(getCircleIconColor("weather", color, percent)) - .drawImage(icon, w - iconOffset, h3 + radiusOuter - iconOffset, {scale: scale}); - } else { - g.drawString("?", w, h3 + radiusOuter); - } -} -function drawWeatherOld(w) { - if (!w) w = getCircleXPosition("weather"); - let weather = getWeather(); - let tempString = weather ? locale.temp(weather.temp - 273.15) : undefined; - let code = weather ? weather.code : -1; - - drawCircleBackground(w); - - let color = getCircleColor("weather"); - let percent; - let data = settings.weatherCircleData; - switch (data) { - case "humidity": - let humidity = weather ? weather.hum : undefined; - if (humidity >= 0) { - percent = humidity / 100; - drawGauge(w, h3, percent, color); - } - break; - case "wind": - if (weather) { - let wind = locale.speed(weather.wind).match(/^(\D*\d*)(.*)$/); - if (wind[1] >= 0) { - if (wind[2] == "kmh") { - wind[1] = windAsBeaufort(wind[1]); - } - // wind goes from 0 to 12 (see https://en.wikipedia.org/wiki/Beaufort_scale) - percent = wind[1] / 12; - drawGauge(w, h3, percent, color); - } - } - break; - case "empty": - break; - } - - drawInnerCircleAndTriangle(w); - - writeCircleText(w, tempString ? tempString : "?"); - - if (code > 0) { - let icon = getWeatherIconByCode(code); - if (icon) g.drawImage(getImage(icon, getCircleIconColor("weather", color, percent)), w - iconOffset, h3 + radiusOuter - iconOffset); - } else { - g.drawString("?", w, h3 + radiusOuter); - } -} - -function drawSunProgress(w) { - if (!w) w = getCircleXPosition("sunprogress"); - let percent = getSunProgress(); - - // sunset icons: - let sunSetDown = atob("EBCBAAAAAAABgAAAAAATyAZoBCB//gAAAAAGYAPAAYAAAAAA"); - let sunSetUp = atob("EBCBAAAAAAABgAAAAAATyAZoBCB//gAAAAABgAPABmAAAAAA"); - - drawCircleBackground(w); - - let color = getCircleColor("sunprogress"); - - drawGauge(w, h3, percent, color); - - drawInnerCircleAndTriangle(w); - - let icon = sunSetDown; - let text = "?"; - let times = getSunData(); - if (times != undefined) { - let sunRise = Math.round(times.sunrise.getTime() / 1000); - let sunSet = Math.round(times.sunset.getTime() / 1000); - if (!isDay()) { - // night - if (now > sunRise) { - // after sunRise - let upcomingSunRise = sunRise + 60 * 60 * 24; - text = formatSeconds(upcomingSunRise - now); - } else { - text = formatSeconds(sunRise - now); - } - icon = sunSetUp; - } else { - // day, approx sunrise tomorrow: - text = formatSeconds(sunSet - now); - icon = sunSetDown; - } - } - - writeCircleText(w, text); - - g.drawImage(getImage(icon, getCircleIconColor("sunprogress", color, percent)), w - iconOffset, h3 + radiusOuter - iconOffset); -} - -/* - * Deprecated but nice as references for clkinfo - */ - -function drawSteps(w) { - if (!w) w = getCircleXPosition("steps"); - let steps = getSteps(); - - drawCircleBackground(w); - - let color = getCircleColor("steps"); - - let percent; - let stepGoal = settings.stepGoal; - if (stepGoal > 0) { - percent = steps / stepGoal; - if (stepGoal < steps) percent = 1; - drawGauge(w, h3, percent, color); - } - - drawInnerCircleAndTriangle(w); - - writeCircleText(w, shortValue(steps)); - - g.drawImage(getImage(atob("EBCBAAAACAAcAB4AHgAeABwwADgGeAZ4AHgAMAAAAHAAIAAA"), getCircleIconColor("steps", color, percent)), w - iconOffset, h3 + radiusOuter - iconOffset); -} - -function drawStepsDistance(w) { - if (!w) w = getCircleXPosition("stepsDistance"); - let steps = getSteps(); - let stepDistance = settings.stepLength; - let stepsDistance = Math.round(steps * stepDistance); - - drawCircleBackground(w); - - let color = getCircleColor("stepsDistance"); - - let percent; - let stepDistanceGoal = settings.stepDistanceGoal; - if (stepDistanceGoal > 0) { - percent = stepsDistance / stepDistanceGoal; - if (stepDistanceGoal < stepsDistance) percent = 1; - drawGauge(w, h3, percent, color); - } - - drawInnerCircleAndTriangle(w); - - writeCircleText(w, shortValue(stepsDistance)); - - g.drawImage(getImage(atob("EBCBAAAACAAcAB4AHgAeABwwADgGeAZ4AHgAMAAAAHAAIAAA"), getCircleIconColor("stepsDistance", color, percent)), w - iconOffset, h3 + radiusOuter - iconOffset); -} - -function drawHeartRate(w) { - if (!w) w = getCircleXPosition("hr"); - - let heartIcon = atob("EBCBAAAAAAAeeD/8P/x//n/+P/w//B/4D/AH4APAAYAAAAAA"); - - drawCircleBackground(w); - - let color = getCircleColor("hr"); - - let percent; - if (hrtValue != undefined) { - let minHR = settings.minHR; - let maxHR = settings.maxHR; - percent = (hrtValue - minHR) / (maxHR - minHR); - if (isNaN(percent)) percent = 0; - drawGauge(w, h3, percent, color); - } - - drawInnerCircleAndTriangle(w); - - writeCircleText(w, hrtValue != undefined ? hrtValue : "-"); - - g.drawImage(getImage(heartIcon, getCircleIconColor("hr", color, percent)), w - iconOffset, h3 + radiusOuter - iconOffset); -} - -function drawBattery(w) { - if (!w) w = getCircleXPosition("battery"); - let battery = E.getBattery(); - - let powerIcon = atob("EBCBAAAAA8ADwA/wD/AP8A/wD/AP8A/wD/AP8A/wD/AH4AAA"); - - drawCircleBackground(w); - - let color = getCircleColor("battery"); - - let percent; - if (battery > 0) { - percent = battery / 100; - drawGauge(w, h3, percent, color); - } - - drawInnerCircleAndTriangle(w); - - if (Bangle.isCharging()) { - color = colorGreen; - } else { - if (settings.batteryWarn != undefined && battery <= settings.batteryWarn) { - color = colorRed; - } - } - writeCircleText(w, battery + '%'); - - g.drawImage(getImage(powerIcon, getCircleIconColor("battery", color, percent)), w - iconOffset, h3 + radiusOuter - iconOffset); -} -function drawTemperature(w) { - if (!w) w = getCircleXPosition("temperature"); - - getPressureValue("temperature").then((temperature) => { - drawCircleBackground(w); - - let color = getCircleColor("temperature"); - - let percent; - if (temperature) { - let min = -40; - let max = 85; - percent = (temperature - min) / (max - min); - drawGauge(w, h3, percent, color); - } - - drawInnerCircleAndTriangle(w); - - if (temperature) - writeCircleText(w, locale.temp(temperature)); - - g.drawImage(getImage(atob("EBCBAAAAAYADwAJAAkADwAPAA8ADwAfgB+AH4AfgA8ABgAAA"), getCircleIconColor("temperature", color, percent)), w - iconOffset, h3 + radiusOuter - iconOffset); - - }); -} - -function drawPressure(w) { - if (!w) w = getCircleXPosition("pressure"); - - getPressureValue("pressure").then((pressure) => { - drawCircleBackground(w); - - let color = getCircleColor("pressure"); - - let percent; - if (pressure && pressure > 0) { - let minPressure = 950; - let maxPressure = 1050; - percent = (pressure - minPressure) / (maxPressure - minPressure); - drawGauge(w, h3, percent, color); - } - - drawInnerCircleAndTriangle(w); - - if (pressure) - writeCircleText(w, Math.round(pressure)); - - g.drawImage(getImage(atob("EBCBAAAAAYADwAJAAkADwAPAA8ADwAfgB+AH4AfgA8ABgAAA"), getCircleIconColor("pressure", color, percent)), w - iconOffset, h3 + radiusOuter - iconOffset); - - }); -} - -function drawAltitude(w) { - if (!w) w = getCircleXPosition("altitude"); - - getPressureValue("altitude").then((altitude) => { - drawCircleBackground(w); - - let color = getCircleColor("altitude"); - - let percent; - if (altitude) { - let min = 0; - let max = 10000; - percent = (altitude - min) / (max - min); - drawGauge(w, h3, percent, color); - } - - drawInnerCircleAndTriangle(w); - - if (altitude) - writeCircleText(w, locale.distance(Math.round(altitude))); - - g.drawImage(getImage(atob("EBCBAAAAAYADwAJAAkADwAPAA8ADwAfgB+AH4AfgA8ABgAAA"), getCircleIconColor("altitude", color, percent)), w - iconOffset, h3 + radiusOuter - iconOffset); - - }); -} - -function shortValue(v) { - if (isNaN(v)) return '-'; - if (v <= 999) return v; - if (v >= 1000 && v < 10000) { - v = Math.floor(v / 100) * 100; - return (v / 1000).toFixed(1).replace(/\.0$/, '') + 'k'; - } - if (v >= 10000) { - v = Math.floor(v / 1000) * 1000; - return (v / 1000).toFixed(1).replace(/\.0$/, '') + 'k'; - } -} - -function getSteps() { - if (Bangle.getHealthStatus) { - return Bangle.getHealthStatus("day").steps; - } - if (WIDGETS && WIDGETS.wpedom !== undefined) { - return WIDGETS.wpedom.getSteps(); - } - return 0; -} - -function getPressureValue(type) { - return new Promise((resolve) => { - if (Bangle.getPressure) { - if (!pressureLocked) { - pressureLocked = true; - if (pressureCache && pressureCache[type]) { - resolve(pressureCache[type]); - } - Bangle.getPressure().then(function(d) { - pressureLocked = false; - if (d) { - pressureCache = d; - if (d[type]) { - resolve(d[type]); - } - } - }).catch(() => {}); - } else { - if (pressureCache && pressureCache[type]) { - resolve(pressureCache[type]); - } - } - } - }); -} - -/* - * end deprecated - */ - -var menu = null; -function reloadMenu() { - menu = clock_info.load(); - for(var i=1; i<5; i++) - if(settings['circle'+i].includes("/")) { - let parts = settings['circle'+i].split("/"); - let infoName = parts[0], itemName = parts[1]; - let infoNum = menu.findIndex(e=>e.name==infoName); - let itemNum = 0; //get first if dynamic - if(!menu[infoNum].dynamic) - itemNum = menu[infoNum].items.findIndex(it=>it.name==itemName); - circleInfoNum[i-1] = infoNum; - circleItemNum[i-1] = itemNum; - } else if(settings['circle'+i] == "weather") { - weatherCircleNum = menu.findIndex(e=>e.name.toLowerCase() == "weather"); - weatherCircleDataNum = menu[weatherCircleNum].items.findIndex(it=>it.name==settings.weatherCircleData); - weatherCircleCondNum = menu[weatherCircleNum].items.findIndex(it=>it.name=="condition"); - weatherCircleTempNum = menu[weatherCircleNum].items.findIndex(it=>it.name=="temperature"); - } -} -//reload periodically for changes? -reloadMenu(); - function drawEmpty(img, w, color) { drawGauge(w, h3, 0, color); drawInnerCircleAndTriangle(w); @@ -736,45 +189,32 @@ function drawEmpty(img, w, color) { .drawImage(img, w - iconOffset, h3 + radiusOuter - iconOffset, {scale: 16/24}); } -function drawClkInfo(index, w) { +function drawCircle(index) { var info = menu[circleInfoNum[index-1]]; var type = settings['circle'+index]; - if (!w) w = getCircleXPosition(type); + var w = circlePosX[index-1]; drawCircleBackground(w); - const color = getCircleColor(type); - var item = info.items[circleItemNum[index-1]]; + const color = getCircleColor(index); + var item = info && info.items[circleItemNum[index-1]]; if(!info || !item) { drawEmpty(info? info.img : null, w, color); return; } - item.show(); - item.hide(); var data=item.get(); var img = data.img; var percent = 1; //fill up if no range - var txt = data.text; + var txt = ""+data.text; + if (txt.endsWith(" bpm")) txt=txt.slice(0,-4); // hack for heart rate - remove the 'bpm' text if(!img) img = info.img; if(item.hasRange) percent = (data.v-data.min) / (data.max-data.min); if(data.short) txt = data.short; drawGauge(w, h3, percent, color); drawInnerCircleAndTriangle(w); writeCircleText(w, txt); - g.setColor(getCircleIconColor(type, color, percent)) + g.setColor(getCircleIconColor(index, color, percent)) .drawImage(img, w - iconOffset, h3 + radiusOuter - iconOffset, {scale: 16/24}); } -/* - * wind goes from 0 to 12 (see https://en.wikipedia.org/wiki/Beaufort_scale) - */ -function windAsBeaufort(windInKmh) { - let beaufort = [2, 6, 12, 20, 29, 39, 50, 62, 75, 89, 103, 118]; - let l = 0; - while (l < beaufort.length && beaufort[l] < windInKmh) { - l++; - } - return l; -} - /* * Choose weather icon to display based on weather conditition code @@ -795,7 +235,7 @@ function getWeatherIconByCode(code, big) { let weatherFoggy = big ? atob("QEDBAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAwADwADAAAAHgAPAAeAAAAfAA8AD4AAAA+ADwAfAAAAB8APAD4AAAAD4B+AfAAAAAHw//D4AAAAAPv//fAAAAAAf///4AAAAAA/4H/AAAAAAB+AH4AAAAAAPgAHwAAAAAA8AAPAAAAAAHwAA+AAAAAAeAAB4AAAAAB4AAHgAAAAAPAAAPAAAAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//8AD///AADwAAAP//8AAeAAAA///wAB4AAAD///AAPgAAAAAAAAA8AAAAAAAAAHwAAAAAAAAB+AAAAAAAAAf8AAAAD///D/4AAAAP//8P3wAAAA///w8PgAAAD///CAfAAAAAAAAAA+AAAAAAAAAB8AAAAAAAAAD4AAAAAAAAAHgAAP//8PAAMAAA///w8AAAAAD///DwAAAAAP//8PAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAPAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : atob("EBCBAAAAAAADwAZgDDA4EGAcQAZAAgAAf74AAAAAd/4AAAAA"); let weatherStormy = big ? atob("QEDBAP//wxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAAAAB//gAAAAAAAP//gAAAAAAD///AAAAAAAf4H+AAAAAAD8AD8AAAAAAfgAH4AAAAAB8AAPwAAAAAPgAAf/AAAAB8AAA//AAAAHgAAB/+AAAAeAAAH/8AAAH4AAAIH4AAB/AAAAAHwAAf8AAAAAPgAD/wAAAAAeAAPwAAAAAB4AB8AAAAAADwAHgAAAAAAPAA+AAAAAAA8ADwAAAAAADwA/AAAAAAAPAH8AAAAAAA8A/wAAAAAAHwH4AAAAAAAfg+AAAAAAAAfHwAAAAAAAA+eAAAAAAAAB54AAAAD/AAHvAAAAAf4AAP8AAAAB/gAA/wAAAAP8AAD/AAAAA/gAAP8AAAAH+AAA/wAAAAfwAAD3gAAAD/AAAeeAAAAP4AAB58AAAB/AAAPj4AAAH8AAB8H4AAA/gAAfgP//+D//D/8Af//4f/4P/gA///B//B/8AAf/8P/8P+AAAAAAAPgAAAAAAAAB8AAAAAAAAAHwAAAAAAAAA+AAAAAAAAADwAAAAAAAAAfAAAAAAAAAB4AAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : atob("EBCBAAAAAYAH4AwwOBBgGEAOQMJAgjmOGcgAgACAAAAAAAAA"); let unknown = big ? atob("QEDBAP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAAAAAf/4AAAAAAAH//4AAAAAAA///wAAAAAAH+B/gAAAAAA/AA/AAAAAAH4AB+AAAAAA/AAD4AAAAAD4H4HwAAAAAfB/4PgAAAAB8P/weAAAAAHg//h4AAAAA+Hw+HwAAAAD4eB8PAAAAAP/wDw8AAAAA//APDwAAAAD/8A8PAAAAAH/gDw8AAAAAAAAfDwAAAAAAAH4fAAAAAAAB/B4AAAAAAAf4HgAAAAAAD/A+AAAAAAAfwHwAAAAAAD8A+AAAAAAAPgH4AAAAAAB8B/AAAAAAAHgf4AAAAAAA+H+AAAAAAADwfwAAAAAAAPD8AAAAAAAA8PAAAAAAAAD/8AAAAAAAAP/wAAAAAAAA//AAAAAAAAB/4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf+AAAAAAAAD/8AAAAAAAAP/wAAAAAAAA//AAAAAAAADw8AAAAAAAAPDwAAAAAAAA8PAAAAAAAADw8AAAAAAAAP/wAAAAAAAA//AAAAAAAAD/8AAAAAAAAH/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") : undefined; - + switch (codeGroup) { case 2: return weatherStormy; @@ -823,7 +263,9 @@ function getWeatherIconByCode(code, big) { case 8: switch (code) { case 800: - return isDay() ? weatherSunny : weatherMoon; + var hr = (new Date()).getHours(); + var isDay = (hr>6) && (hr<=18); // fixme we don't want to include ALL of suncalc just to choose one icon + return isDay ? weatherSunny : weatherMoon; case 801: return weatherPartlyCloudy; case 802: @@ -836,16 +278,6 @@ function getWeatherIconByCode(code, big) { } } - -function isDay() { - let times = getSunData(); - if (times == undefined) return true; - let sunRise = Math.round(times.sunrise.getTime() / 1000); - let sunSet = Math.round(times.sunset.getTime() / 1000); - - return (now > sunRise && now < sunSet); -} - function formatSeconds(s) { if (s > 60 * 60) { // hours return Math.round(s / (60 * 60)) + "h"; @@ -856,45 +288,6 @@ function formatSeconds(s) { return "<1m"; } -function getSunData() { - if (location != undefined && location.lat != undefined) { - let SunCalc = require("https://raw.githubusercontent.com/mourner/suncalc/master/suncalc.js"); - // get today's sunlight times for lat/lon - return SunCalc ? SunCalc.getTimes(new Date(), location.lat, location.lon) : undefined; - } - return undefined; -} - -/* - * Calculated progress of the sun between sunrise and sunset in percent - * - * Taken from rebble app and modified - */ -function getSunProgress() { - let times = getSunData(); - if (times == undefined) return 0; - let sunRise = Math.round(times.sunrise.getTime() / 1000); - let sunSet = Math.round(times.sunset.getTime() / 1000); - - if (isDay()) { - // during day - let dayLength = sunSet - sunRise; - if (now > sunRise) { - return (now - sunRise) / dayLength; - } else { - return (sunRise - now) / dayLength; - } - } else { - // during night - if (now < sunRise) { - let prevSunSet = sunSet - 60 * 60 * 24; - return 1 - (sunRise - now) / (sunRise - prevSunSet); - } else { - let upcomingSunRise = sunRise + 60 * 60 * 24; - return (upcomingSunRise - now) / (upcomingSunRise - sunSet); - } - } -} /* * Draws the background and the grey circle @@ -961,18 +354,54 @@ function getWeather() { return jsonWeather && jsonWeather.weather ? jsonWeather.weather : undefined; } + +var menu = clock_info.load(); +for(var i=1; i<5; i++) { + var circleType = settings['circle'+i]; + if(circleType.includes("/")) { + let parts = circleType.split("/"); + let infoName = parts[0], itemName = parts[1]; + let infoNum = menu.findIndex(e=>e.name==infoName); + if (infoNum<0) infoNum=0; // not found! + let itemNum = 0; //get first if dynamic + if(!menu[infoNum].dynamic) + itemNum = menu[infoNum].items.findIndex(it=>it.name==itemName); + if (itemNum<0) itemNum=0; + circleInfoNum[i-1] = infoNum; + circleItemNum[i-1] = itemNum; + let menuItem = menu[infoNum].items[itemNum]; + if (menuItem) { + (function(i){ + menuItem.on('redraw', function() { + drawCircle(i); + }); + })(i); + menuItem.show(); + } + } else { // empty? + circleInfoNum[i-1] = -1; + circleItemNum[i-1] = -1; + } +} + Bangle.setUI({ mode : "clock", - remove : function() { + /*remove : function() { + THIS CLOCK IS NOT YET ABLE TO UNLOAD ALL OF ITSELF. + DO NOT UNCOMMENT THIS WITOUT FIXING IT + OR THERE WILL BE HUGE MEMORY LEAKS // Called to unload all of the clock app if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; - + // must call clkinfo.hide here for any showing clkinfo delete Graphics.prototype.setFontRobotoRegular50NumericOnly; delete Graphics.prototype.setFontRobotoRegular21; - }}); + }*/ +}); Bangle.loadWidgets(); +if (!showWidgets) require("widget_utils").hide(); +else Bangle.drawWidgets(); // schedule a draw for the next second or minute function queueDraw() { diff --git a/apps/circlesclock/metadata.json b/apps/circlesclock/metadata.json index fb743ae4c..3b436a032 100644 --- a/apps/circlesclock/metadata.json +++ b/apps/circlesclock/metadata.json @@ -1,7 +1,7 @@ { "id": "circlesclock", "name": "Circles clock", "shortName":"Circles clock", - "version":"0.18", + "version":"0.19", "description": "A clock with three or four circles for different data at the bottom in a probably familiar style", "icon": "app.png", "screenshots": [{"url":"screenshot-dark.png"}, {"url":"screenshot-light.png"}, {"url":"screenshot-dark-4.png"}, {"url":"screenshot-light-4.png"}], diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index 2ab655f01..2e9506a98 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -12,17 +12,15 @@ storage.write(SETTINGS_FILE, settings); } - //const valuesCircleTypes = ["empty", "steps", "stepsDist", "hr", "battery", "weather", "sunprogress", "temperature", "pressure", "altitude", "timer"]; - //const namesCircleTypes = ["empty", "steps", "distance", "heart", "battery", "weather", "sun", "temperature", "pressure", "altitude", "timer"]; - var valuesCircleTypes = ["empty","weather", "sunprogress"]; - var namesCircleTypes = ["empty","weather", "sun"]; + var valuesCircleTypes = ["empty"]; + var namesCircleTypes = ["empty"]; clock_info.load().forEach(e=>{ if(e.dynamic) { valuesCircleTypes = valuesCircleTypes.concat([e.name+"/"]); namesCircleTypes = namesCircleTypes.concat([e.name]); } else { let values = e.items.map(i=>e.name+"/"+i.name); - let names =e.name=="Bangle" ? e.items.map(i=>i.name) : values; + let names = e.name=="Bangle" ? e.items.map(i=>i.name) : values; valuesCircleTypes = valuesCircleTypes.concat(values); namesCircleTypes = namesCircleTypes.concat(names); }