Merge pull request #2160 from halemmerich/imageclock

imageclock - Fix the clock not refreshing completely after switch
master
Gordon Williams 2022-10-04 10:37:15 +01:00 committed by GitHub
commit 9ba91f9ab8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 88 additions and 72 deletions

View File

@ -9,3 +9,4 @@
Show/Hide widgets with swipe up or down Show/Hide widgets with swipe up or down
0.08: Use default Bangle formatter for booleans 0.08: Use default Bangle formatter for booleans
0.09: Support new fast app switching 0.09: Support new fast app switching
0.10: Fix clock not correctly refreshing when drawing in timeouts option is not on

View File

@ -1,8 +1,21 @@
let unlockedDrawInterval = []; let unlockedDrawInterval = [];
let lockedDrawInterval = []; let lockedDrawInterval = [];
let showWidgets = false; let showWidgets = false;
let firstDraw = true;
{ {
let x = g.getWidth()/2;
let y = g.getHeight()/2;
g.setColor(g.theme.bg);
g.fillRect(x-49, y-19, x+49, y+19);
g.setColor(g.theme.fg);
g.drawRect(x-50, y-20, x+50, y+20);
y -= 4;
x -= 4*6;
g.setFont("6x8");
g.setFontAlign(-1,-1);
g.drawString("Loading...", x, y);
let watchface = require("Storage").readJSON("imageclock.face.json"); let watchface = require("Storage").readJSON("imageclock.face.json");
let watchfaceResources = require("Storage").readJSON("imageclock.resources.json"); let watchfaceResources = require("Storage").readJSON("imageclock.resources.json");
let precompiledJs = eval(require("Storage").read("imageclock.draw.js")); let precompiledJs = eval(require("Storage").read("imageclock.draw.js"));
@ -49,12 +62,12 @@ let showWidgets = false;
let p1; let p1;
if (settings.perflog){ if (settings.perflog){
startPerfLog = function(name){ Bangle.startPerfLog = function(name){
let time = getTime(); let time = getTime();
if (!performanceLog.start) performanceLog.start={}; if (!performanceLog.start) performanceLog.start={};
performanceLog.start[name] = time; performanceLog.start[name] = time;
}; };
endPerfLog = function (name){ Bangle.endPerfLog = function (name){
let time = getTime(); let time = getTime();
if (!performanceLog.last) performanceLog.last={}; if (!performanceLog.last) performanceLog.last={};
let duration = time - performanceLog.start[name]; let duration = time - performanceLog.start[name];
@ -67,7 +80,7 @@ let showWidgets = false;
performanceLog.count[name]++; performanceLog.count[name]++;
}; };
printPerfLog = function(){ Bangle.printPerfLog = function(){
let result = ""; let result = "";
let keys = []; let keys = [];
for (let c in performanceLog.cum){ for (let c in performanceLog.cum){
@ -82,20 +95,20 @@ let showWidgets = false;
let delayTimeouts = []; let delayTimeouts = [];
function delay(t) { let delay = function(t) {
return new Promise(function (resolve) { return new Promise(function (resolve) {
delayTimeouts.push(setTimeout(resolve, t)); delayTimeouts.push(setTimeout(resolve, t));
}); });
} };
function cleanupDelays(){ let cleanupDelays = function(){
for (let t of delayTimeouts){ for (let t of delayTimeouts){
clearTimeout(t); clearTimeout(t);
} }
delayTimeouts = []; delayTimeouts = [];
} };
function prepareImg(resource){ let prepareImg = function(resource){
startPerfLog("prepareImg"); startPerfLog("prepareImg");
//print("prepareImg: ", resource); //print("prepareImg: ", resource);
@ -110,9 +123,9 @@ let showWidgets = false;
} }
endPerfLog("prepareImg"); endPerfLog("prepareImg");
return resource; return resource;
} };
function getByPath(object, path, lastElem){ let getByPath = function(object, path, lastElem){
startPerfLog("getByPath"); startPerfLog("getByPath");
//print("getByPath", path,lastElem); //print("getByPath", path,lastElem);
let current = object; let current = object;
@ -133,21 +146,21 @@ let showWidgets = false;
return undefined; return undefined;
} }
return current; return current;
} };
function splitNumberToDigits(num){ let splitNumberToDigits = function(num){
return String(num).split('').map(item => Number(item)); return String(num).split('').map(item => Number(item));
} };
function isChangedNumber(element){ let isChangedNumber = function(element){
return element.lastDrawnValue != getValue(element.Value); return element.lastDrawnValue != getValue(element.Value);
} };
function isChangedMultistate(element){ let isChangedMultistate = function(element){
return element.lastDrawnValue != getMultistate(element.Value); return element.lastDrawnValue != getMultistate(element.Value);
} };
function drawNumber(graphics, resources, element){ let drawNumber = function(graphics, resources, element){
startPerfLog("drawNumber"); startPerfLog("drawNumber");
let number = getValue(element.Value); let number = getValue(element.Value);
let spacing = element.Spacing ? element.Spacing : 0; let spacing = element.Spacing ? element.Spacing : 0;
@ -258,9 +271,9 @@ let showWidgets = false;
element.lastDrawnValue = number; element.lastDrawnValue = number;
endPerfLog("drawNumber"); endPerfLog("drawNumber");
} };
function drawElement(graphics, resources, pos, element, lastElem){ let drawElement = function(graphics, resources, pos, element, lastElem){
startPerfLog("drawElement"); startPerfLog("drawElement");
let cacheKey = "_"+(lastElem?lastElem:"nole"); let cacheKey = "_"+(lastElem?lastElem:"nole");
if (!element.cachedImage) element.cachedImage={}; if (!element.cachedImage) element.cachedImage={};
@ -304,26 +317,26 @@ let showWidgets = false;
endPerfLog("drawElement_g.drawImage"); endPerfLog("drawElement_g.drawImage");
} }
endPerfLog("drawElement"); endPerfLog("drawElement");
} };
function getValue(value, defaultValue){ let getValue = function(value, defaultValue){
if (typeof value == "string"){ if (typeof value == "string"){
return numbers[value](); return numbers[value]();
} }
if (value == undefined) return defaultValue; if (value == undefined) return defaultValue;
return value; return value;
} };
function getMultistate(name, defaultValue){ let getMultistate = function(name, defaultValue){
if (typeof name == "string"){ if (typeof name == "string"){
return multistates[name](); return multistates[name]();
} else { } else {
if (name == undefined) return defaultValue; if (name == undefined) return defaultValue;
} }
return undefined; return undefined;
} };
function drawScale(graphics, resources, scale){ let drawScale = function(graphics, resources, scale){
startPerfLog("drawScale"); startPerfLog("drawScale");
//print("drawScale", scale); //print("drawScale", scale);
let segments = scale.Segments; let segments = scale.Segments;
@ -341,9 +354,9 @@ let showWidgets = false;
scale.lastDrawnValue = segmentsToDraw; scale.lastDrawnValue = segmentsToDraw;
endPerfLog("drawScale"); endPerfLog("drawScale");
} };
function drawImage(graphics, resources, image, name){ let drawImage = function(graphics, resources, image, name){
startPerfLog("drawImage"); startPerfLog("drawImage");
//print("drawImage", image.X, image.Y, name); //print("drawImage", image.X, image.Y, name);
if (image.Value && image.Steps){ if (image.Value && image.Steps){
@ -357,9 +370,9 @@ let showWidgets = false;
} }
endPerfLog("drawImage"); endPerfLog("drawImage");
} };
function drawCodedImage(graphics, resources, image){ let drawCodedImage = function(graphics, resources, image){
startPerfLog("drawCodedImage"); startPerfLog("drawCodedImage");
let code = getValue(image.Value); let code = getValue(image.Value);
//print("drawCodedImage", image, code); //print("drawCodedImage", image, code);
@ -386,9 +399,9 @@ let showWidgets = false;
image.lastDrawnValue = code; image.lastDrawnValue = code;
startPerfLog("drawCodedImage"); startPerfLog("drawCodedImage");
} };
function getWeatherCode(){ let getWeatherCode = function(){
let jsonWeather = require("Storage").readJSON('weather.json'); let jsonWeather = require("Storage").readJSON('weather.json');
let weather = (jsonWeather && jsonWeather.weather) ? jsonWeather.weather : undefined; let weather = (jsonWeather && jsonWeather.weather) ? jsonWeather.weather : undefined;
@ -396,9 +409,9 @@ let showWidgets = false;
return weather.code; return weather.code;
} }
return undefined; return undefined;
} };
function getWeatherTemperature(){ let getWeatherTemperature = function(){
let jsonWeather = require("Storage").readJSON('weather.json'); let jsonWeather = require("Storage").readJSON('weather.json');
let weather = (jsonWeather && jsonWeather.weather) ? jsonWeather.weather : undefined; let weather = (jsonWeather && jsonWeather.weather) ? jsonWeather.weather : undefined;
@ -415,25 +428,25 @@ let showWidgets = false;
} }
} }
return result; return result;
} };
function scaledown(value, min, max){ let scaledown = function(value, min, max){
//print("scaledown", value, min, max); //print("scaledown", value, min, max);
let scaled = E.clip(getValue(value),getValue(min,0),getValue(max,1)); let scaled = E.clip(getValue(value),getValue(min,0),getValue(max,1));
scaled -= getValue(min,0); scaled -= getValue(min,0);
scaled /= getValue(max,1); scaled /= getValue(max,1);
return scaled; return scaled;
} };
function radians(rotation){ let radians = function(rotation){
let value = scaledown(rotation.RotationValue, rotation.MinRotationValue, rotation.MaxRotationValue); let value = scaledown(rotation.RotationValue, rotation.MinRotationValue, rotation.MaxRotationValue);
value -= rotation.RotationOffset ? rotation.RotationOffset : 0; value -= rotation.RotationOffset ? rotation.RotationOffset : 0;
value *= 360; value *= 360;
value *= Math.PI / 180; value *= Math.PI / 180;
return value; return value;
} };
function drawPoly(graphics, resources, element){ let drawPoly = function(graphics, resources, element){
startPerfLog("drawPoly"); startPerfLog("drawPoly");
let vertices = []; let vertices = [];
@ -463,9 +476,9 @@ let showWidgets = false;
} }
endPerfLog("drawPoly"); endPerfLog("drawPoly");
} };
function drawRect(graphics, resources, element){ let drawRect = function(graphics, resources, element){
startPerfLog("drawRect"); startPerfLog("drawRect");
let vertices = []; let vertices = [];
@ -479,9 +492,9 @@ let showWidgets = false;
endPerfLog("drawRect_g.fillRect"); endPerfLog("drawRect_g.fillRect");
} }
endPerfLog("drawRect"); endPerfLog("drawRect");
} };
function drawCircle(graphics, resources, element){ let drawCircle = function(graphics, resources, element){
startPerfLog("drawCircle"); startPerfLog("drawCircle");
if (element.Filled){ if (element.Filled){
@ -494,7 +507,7 @@ let showWidgets = false;
endPerfLog("drawCircle_g.drawCircle"); endPerfLog("drawCircle_g.drawCircle");
} }
endPerfLog("drawCircle"); endPerfLog("drawCircle");
} };
let numbers = {}; let numbers = {};
numbers.Hour = () => { return new Date().getHours(); }; numbers.Hour = () => { return new Date().getHours(); };
@ -547,7 +560,7 @@ let showWidgets = false;
multistates.WeatherTemperatureUnit = () => { return getWeatherTemperature().unit; }; multistates.WeatherTemperatureUnit = () => { return getWeatherTemperature().unit; };
multistates.StepsGoal = () => { return (numbers.Steps() >= (settings.stepsgoal || 10000)) ? "on": "off"; }; multistates.StepsGoal = () => { return (numbers.Steps() >= (settings.stepsgoal || 10000)) ? "on": "off"; };
function drawMultiState(graphics, resources, element){ let drawMultiState = function(graphics, resources, element){
startPerfLog("drawMultiState"); startPerfLog("drawMultiState");
//print("drawMultiState", element); //print("drawMultiState", element);
let value = multistates[element.Value](); let value = multistates[element.Value]();
@ -555,7 +568,7 @@ let showWidgets = false;
drawImage(graphics, resources, element, value); drawImage(graphics, resources, element, value);
element.lastDrawnValue = value; element.lastDrawnValue = value;
endPerfLog("drawMultiState"); endPerfLog("drawMultiState");
} };
let pulse,alt,temp,press; let pulse,alt,temp,press;
@ -569,7 +582,7 @@ let showWidgets = false;
let deferredTimout; let deferredTimout;
function initialDraw(resources, face){ let initialDraw = function(resources, face){
//print("Free memory", process.memory(false).free); //print("Free memory", process.memory(false).free);
requestedDraws++; requestedDraws++;
if (!isDrawing){ if (!isDrawing){
@ -613,9 +626,9 @@ let showWidgets = false;
} //else { } //else {
//print("queued draw"); //print("queued draw");
//} //}
} };
function handleHrm(e){ let handleHrm = function(e){
if (e.confidence > 70){ if (e.confidence > 70){
pulse = e.bpm; pulse = e.bpm;
if (!redrawEvents || redrawEvents.includes("HRM") && !Bangle.isLocked()){ if (!redrawEvents || redrawEvents.includes("HRM") && !Bangle.isLocked()){
@ -623,9 +636,9 @@ let showWidgets = false;
initialDraw(watchfaceResources, watchface); initialDraw(watchfaceResources, watchface);
} }
} }
} };
function handlePressure(e){ let handlePressure = function(e){
alt = e.altitude; alt = e.altitude;
temp = e.temperature; temp = e.temperature;
press = e.pressure; press = e.pressure;
@ -633,23 +646,23 @@ let showWidgets = false;
//print("Redrawing on pressure"); //print("Redrawing on pressure");
initialDraw(watchfaceResources, watchface); initialDraw(watchfaceResources, watchface);
} }
} };
function handleCharging(e){ let handleCharging = function(e){
if (!redrawEvents || redrawEvents.includes("charging") && !Bangle.isLocked()){ if (!redrawEvents || redrawEvents.includes("charging") && !Bangle.isLocked()){
//print("Redrawing on charging"); //print("Redrawing on charging");
initialDraw(watchfaceResources, watchface); initialDraw(watchfaceResources, watchface);
} }
} };
function getMatchedWaitingTime(time){ let getMatchedWaitingTime = function(time){
let result = time - (Date.now() % time); let result = time - (Date.now() % time);
//print("Matched timeout", time, result); //print("Matched timeout", time, result);
return result; return result;
} };
function setMatchedInterval(callable, time, intervalHandler, delay){ let setMatchedInterval = function(callable, time, intervalHandler, delay){
//print("Setting matched interval for", time, intervalHandler); //print("Setting matched interval for", time, intervalHandler);
let matchedTime = getMatchedWaitingTime(time + delay); let matchedTime = getMatchedWaitingTime(time + delay);
return setTimeout(()=>{ return setTimeout(()=>{
@ -657,11 +670,10 @@ let showWidgets = false;
if (intervalHandler) intervalHandler(interval); if (intervalHandler) intervalHandler(interval);
callable(); callable();
}, matchedTime); }, matchedTime);
} };
let lastDrawTime = 0; let lastDrawTime = 0;
let firstDraw = true;
let lockedRedraw = getByPath(watchface, ["Properties","Redraw","Locked"]) || 60000; let lockedRedraw = getByPath(watchface, ["Properties","Redraw","Locked"]) || 60000;
let unlockedRedraw = getByPath(watchface, ["Properties","Redraw","Unlocked"]) || 1000; let unlockedRedraw = getByPath(watchface, ["Properties","Redraw","Unlocked"]) || 1000;
@ -676,7 +688,7 @@ let showWidgets = false;
let initialDrawTimeoutUnlocked; let initialDrawTimeoutUnlocked;
let initialDrawTimeoutLocked; let initialDrawTimeoutLocked;
function handleLock(isLocked, forceRedraw){ let handleLock = function(isLocked, forceRedraw){
//print("isLocked", Bangle.isLocked()); //print("isLocked", Bangle.isLocked());
for (let i of unlockedDrawInterval){ for (let i of unlockedDrawInterval){
//print("Clearing unlocked", i); //print("Clearing unlocked", i);
@ -694,6 +706,7 @@ let showWidgets = false;
//print("Redrawing on unlock", isLocked); //print("Redrawing on unlock", isLocked);
initialDraw(watchfaceResources, watchface); initialDraw(watchfaceResources, watchface);
} }
if (initialDrawTimeoutUnlocked) clearTimeout(initialDrawTimeoutUnlocked);
initialDrawTimeoutUnlocked = setMatchedInterval(()=>{ initialDrawTimeoutUnlocked = setMatchedInterval(()=>{
//print("Redrawing on unlocked interval"); //print("Redrawing on unlocked interval");
initialDraw(watchfaceResources, watchface); initialDraw(watchfaceResources, watchface);
@ -708,6 +721,7 @@ let showWidgets = false;
//print("Redrawing on lock", isLocked); //print("Redrawing on lock", isLocked);
initialDraw(watchfaceResources, watchface); initialDraw(watchfaceResources, watchface);
} }
if (initialDrawTimeoutLocked) clearTimeout(initialDrawTimeoutLocked);
initialDrawTimeoutLocked = setMatchedInterval(()=>{ initialDrawTimeoutLocked = setMatchedInterval(()=>{
//print("Redrawing on locked interval"); //print("Redrawing on locked interval");
initialDraw(watchfaceResources, watchface); initialDraw(watchfaceResources, watchface);
@ -718,13 +732,13 @@ let showWidgets = false;
Bangle.setHRMPower(0, "imageclock"); Bangle.setHRMPower(0, "imageclock");
Bangle.setBarometerPower(0, 'imageclock'); Bangle.setBarometerPower(0, 'imageclock');
} }
} };
let showWidgetsChanged = false; let showWidgetsChanged = false;
let currentDragDistance = 0; let currentDragDistance = 0;
function restoreWidgetDraw(){ let restoreWidgetDraw = function(){
if (global.WIDGETS) { if (global.WIDGETS) {
for (let w in global.WIDGETS) { for (let w in global.WIDGETS) {
let wd = global.WIDGETS[w]; let wd = global.WIDGETS[w];
@ -732,9 +746,9 @@ let showWidgets = false;
wd.area = originalWidgetArea[w]; wd.area = originalWidgetArea[w];
} }
} }
} };
function handleDrag(e){ let handleDrag = function(e){
//print("handleDrag"); //print("handleDrag");
currentDragDistance += e.dy; currentDragDistance += e.dy;
if (Math.abs(currentDragDistance) < 10) return; if (Math.abs(currentDragDistance) < 10) return;
@ -757,7 +771,7 @@ let showWidgets = false;
showWidgets = dragDown; showWidgets = dragDown;
initialDraw(); initialDraw();
} }
} };
Bangle.on('drag', handleDrag); Bangle.on('drag', handleDrag);
@ -783,7 +797,7 @@ let showWidgets = false;
let originalWidgetDraw = {}; let originalWidgetDraw = {};
let originalWidgetArea = {}; let originalWidgetArea = {};
function clearWidgetsDraw(){ let clearWidgetsDraw = function(){
//print("Clear widget draw calls"); //print("Clear widget draw calls");
if (global.WIDGETS) { if (global.WIDGETS) {
originalWidgetDraw = {}; originalWidgetDraw = {};
@ -798,10 +812,7 @@ let showWidgets = false;
} }
} }
if (!global.WIDGETS) Bangle.loadWidgets(); handleLock(Bangle.isLocked(), true);
clearWidgetsDraw();
handleLock(Bangle.isLocked());
Bangle.setUI({ Bangle.setUI({
mode : "clock", mode : "clock",
@ -832,9 +843,13 @@ let showWidgets = false;
} }
delete lockedDrawInterval; delete lockedDrawInterval;
delete showWidgets; delete showWidgets;
delete firstDraw;
cleanupDelays(); cleanupDelays();
restoreWidgetDraw(); restoreWidgetDraw();
} }
}); });
Bangle.loadWidgets();
clearWidgetsDraw();
} }

View File

@ -2,7 +2,7 @@
"id": "imageclock", "id": "imageclock",
"name": "Imageclock", "name": "Imageclock",
"shortName": "Imageclock", "shortName": "Imageclock",
"version": "0.09", "version": "0.10",
"type": "clock", "type": "clock",
"description": "BETA!!! File formats still subject to change --- This app is a highly customizable watchface. To use it, you need to select a watchface. You can build the watchfaces yourself without programming anything. All you need to do is write some json and create image files.", "description": "BETA!!! File formats still subject to change --- This app is a highly customizable watchface. To use it, you need to select a watchface. You can build the watchfaces yourself without programming anything. All you need to do is write some json and create image files.",
"icon": "app.png", "icon": "app.png",