diff --git a/README.md b/README.md index ee1c22061..9b0458043 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ Bangle.js App Loader (and Apps) * Try the **release version** at [banglejs.com/apps](https://banglejs.com/apps) * Try the **development version** at [espruino.github.io](https://espruino.github.io/BangleApps/) +The release version is manually refreshed with regular intervals while the development version is continuously updated as new code is committed to this repository. + **All software (including apps) in this repository is MIT Licensed - see [LICENSE](LICENSE)** By submitting code to this repository you confirm that you are happy with it being MIT licensed, and that it is not licensed in another way that would make this impossible. diff --git a/apps/activityreminder/metadata.json b/apps/activityreminder/metadata.json index 7be6fe911..1cbe4683e 100644 --- a/apps/activityreminder/metadata.json +++ b/apps/activityreminder/metadata.json @@ -6,7 +6,7 @@ "version":"0.12", "icon": "app.png", "type": "app", - "tags": "tool,activity", + "tags": "tool,activity,health", "supports": ["BANGLEJS", "BANGLEJS2"], "readme": "README.md", "storage": [ diff --git a/apps/analogquadclk/ChangeLog b/apps/analogquadclk/ChangeLog index 841543254..d1bd8762f 100644 --- a/apps/analogquadclk/ChangeLog +++ b/apps/analogquadclk/ChangeLog @@ -1,2 +1,3 @@ 0.01: New Clock! -0.02: Fix fastloading memory leak and clockinfo overwritten by hands \ No newline at end of file +0.02: Fix fastloading memory leak and clockinfo overwritten by hands +0.03: Use new clockinfo lib with function to render images wirh borders \ No newline at end of file diff --git a/apps/analogquadclk/app.js b/apps/analogquadclk/app.js index 9fd81a6f4..dbaa49825 100644 --- a/apps/analogquadclk/app.js +++ b/apps/analogquadclk/app.js @@ -102,6 +102,7 @@ // Show launcher when middle button pressed Bangle.setUI({ mode: "clock", + redraw : draw, remove: function() { if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; @@ -116,9 +117,6 @@ Bangle.loadWidgets(); require("widget_utils").hide(); - // used for clockinfo image rendering - let clockInfoG = Graphics.createArrayBuffer(28, 28, 2, {msb:true}); - clockInfoG.transparent = 3; // render clockinfos let clockInfoDraw = function(itm, info, options) { // itm: the item containing name/hasRange/etc @@ -139,18 +137,8 @@ fg = g.toColor("#f00"); } - if (info.img) { - //g.drawImage(info.img, left ? 2 : W - 27, top ? 18 : H - 41); // draw the image - // fiddle around colouring the border and inside of the image - clockInfoG.clear(1); - // do a border - images need to be transparent for this - clockInfoG.setColor(2).drawImage(info.img, 1,1).drawImage(info.img, 3,1). - drawImage(info.img, 1,3).drawImage(info.img, 3,3); - clockInfoG.setColor(1).drawImage(info.img, 2,2); // main image - clockInfoG.floodFill(27,27,3); // flood fill edge to transparent - clockInfoG.palette = new Uint16Array([bg,fg,bg/*border*/, g.toColor("#888")]); - g.drawImage(clockInfoG, imgx-1, imgy-1); - } + if (info.img) + require("clock_info").drawBorderedImage(info.img,imgx,imgy); g.setFont("6x8:2").setFontAlign(left ? -1 : 1, -1); g.setColor(bg).drawString(info.text, textx-2, texty). // draw the text background diff --git a/apps/analogquadclk/metadata.json b/apps/analogquadclk/metadata.json index 00d46e160..0afc15e99 100644 --- a/apps/analogquadclk/metadata.json +++ b/apps/analogquadclk/metadata.json @@ -1,7 +1,7 @@ { "id": "analogquadclk", "name": "Analog Quad Clock", "shortName":"Quad Clock", - "version":"0.02", + "version":"0.03", "description": "An analog clock with clockinfos in each of the 4 corners, allowing 4 different data types to be rendered at once", "icon": "icon.png", "screenshots" : [ { "url":"screenshot.png" }, { "url":"screenshot2.png" } ], diff --git a/apps/andark/ChangeLog b/apps/andark/ChangeLog index 341868930..7d7f9567b 100644 --- a/apps/andark/ChangeLog +++ b/apps/andark/ChangeLog @@ -1,4 +1,7 @@ 0.01: Release 0.02: Rename app 0.03: Add type "clock" -0.04: changed update cylce, when locked +0.04: Changed update cylce, when locked +0.05: Fix support for dark theme + support widgets + + add settings for widgets, order of drawing and hour hand length +0.06: Fix issue showing widgets when app is fast-loaded into from launcher with widgets disabled diff --git a/apps/andark/README.md b/apps/andark/README.md index 3770c1017..9034677c2 100644 --- a/apps/andark/README.md +++ b/apps/andark/README.md @@ -1,10 +1,16 @@ -# Analog Clock +# Dark Analog Clock ## Features -* second hand +* second hand (only on unlocked screen) * date -* battery percantage -* no widgets +* battery percentage (showing charge status with color) +* turned off or swipeable widgets (choose in settings)  + +## Settings + +* whether to load widgets, or not; if widgets are loaded, they are swipeable from the top; if not, NO ACTIONS of widgets are available +* date and battery can be printed both below hands (as if hands were physical) and above (more readable) +* hour hand can be made slighly shorter to improve readability when minute hand is behind a number diff --git a/apps/andark/andark_screen.png b/apps/andark/andark_screen.png index 2ac54c1cd..1f0e5b089 100644 Binary files a/apps/andark/andark_screen.png and b/apps/andark/andark_screen.png differ diff --git a/apps/andark/app.js b/apps/andark/app.js index 865e3e708..e6b5204f0 100644 --- a/apps/andark/app.js +++ b/apps/andark/app.js @@ -1,22 +1,43 @@ +const defaultSettings = { + loadWidgets : false, + textAboveHands : false, + shortHrHand : false +}; +const settings = Object.assign(defaultSettings, require('Storage').readJSON('andark.json',1)||{}); + const c={"x":g.getWidth()/2,"y":g.getHeight()/2}; -let zahlpos=[]; + +const zahlpos=(function() { + let z=[]; + let sk=1; + for(let i=-10;i<50;i+=5){ + let win=i*2*Math.PI/60; + let xsk =c.x+2+Math.cos(win)*(c.x-10), + ysk =c.y+2+Math.sin(win)*(c.x-10); + if(sk==3){xsk-=10;} + if(sk==6){ysk-=10;} + if(sk==9){xsk+=10;} + if(sk==12){ysk+=10;} + if(sk==10){xsk+=3;} + z.push([sk,xsk,ysk]); + sk+=1; + } + return z; +})(); + let unlock = false; function zeiger(len,dia,tim){ - const x =c.x+ Math.cos(tim)*len/2, - y =c.y + Math.sin(tim)*len/2, + const x=c.x+ Math.cos(tim)*len/2, + y=c.y + Math.sin(tim)*len/2, d={"d":3,"x":dia/2*Math.cos(tim+Math.PI/2),"y":dia/2*Math.sin(tim+Math.PI/2)}, pol=[c.x-d.x,c.y-d.y,c.x+d.x,c.y+d.y,x+d.x,y+d.y,x-d.x,y-d.y]; return pol; } -function draw(){ - const d=new Date(); +function drawHands(d) { let m=d.getMinutes(), h=d.getHours(), s=d.getSeconds(); - //draw black rectangle in the middle to clear screen from scale and hands - g.setColor(0,0,0); - g.fillRect(10,10,2*c.x-10,2*c.x-10); g.setColor(1,1,1); if(h>12){ @@ -29,30 +50,64 @@ function draw(){ m=2*Math.PI/60*(m)-Math.PI/2; s=2*Math.PI/60*s-Math.PI/2; - g.setFontAlign(0,0); - g.setFont("Vector",10); - let dateStr = " "+require("locale").date(d)+" "; - g.drawString(dateStr, c.x, c.y+20, true); - // g.drawString(d.getDate(),1.4*c.x,c.y,true); - g.drawString(Math.round(E.getBattery()/5)*5+"%",c.x,c.y+40,true); - drawlet(); //g.setColor(1,0,0); - const hz = zeiger(100,5,h); + const hz = zeiger(settings.shortHrHand?88:100,5,h); g.fillPoly(hz,true); - // g.setColor(1,1,1); + //g.setColor(1,1,1); const minz = zeiger(150,5,m); g.fillPoly(minz,true); if (unlock){ - const sekz = zeiger(150,2,s); - g.fillPoly(sekz,true); + const sekz = zeiger(150,2,s); + g.fillPoly(sekz,true); } g.fillCircle(c.x,c.y,4); - - - } + +function drawText(d) { + g.setFont("Vector",10); + g.setBgColor(0,0,0); + g.setColor(1,1,1); + let dateStr = require("locale").date(d); + g.drawString(dateStr, c.x, c.y+20, true); + let batStr = Math.round(E.getBattery()/5)*5+"%"; + if (Bangle.isCharging()) { + g.setBgColor(1,0,0); + } + g.drawString(batStr, c.x, c.y+40, true); +} + +function drawNumbers() { + //draws the numbers on the screen + g.setFont("Vector",20); + g.setColor(1,1,1); + g.setBgColor(0,0,0); + for(let i = 0;i<12;i++){ + g.drawString(zahlpos[i][0],zahlpos[i][1],zahlpos[i][2],true); + } +} + +function draw(){ + // draw black rectangle in the middle to clear screen from scale and hands + g.setColor(0,0,0); + g.fillRect(10,10,2*c.x-10,2*c.x-10); + // prepare for drawing the text + g.setFontAlign(0,0); + // do drawing + drawNumbers(); + const d=new Date(); + if (settings.textAboveHands) { + drawHands(d); drawText(d); + } else { + drawText(d); drawHands(d); + } +} + //draws the scale once the app is startet function drawScale(){ + // clear the screen + g.setBgColor(0,0,0); + g.clear(); + // draw the ticks of the scale for(let i=-14;i<47;i++){ const win=i*2*Math.PI/60; let d=2; @@ -64,61 +119,34 @@ function drawScale(){ } } -//draws the numbers on the screen +//// main running sequence //// -function drawlet(){ - g.setFont("Vector",20); - for(let i = 0;i<12;i++){ - g.drawString(zahlpos[i][0],zahlpos[i][1],zahlpos[i][2]); - } -} -//calcultes the Position of the numbers when app starts and saves them in an array -function setlet(){ - let sk=1; - for(let i=-10;i<50;i+=5){ - let win=i*2*Math.PI/60; - let xsk =c.x+2+Math.cos(win)*(c.x-10), - ysk =c.y+2+Math.sin(win)*(c.x-10); - if(sk==3){xsk-=10;} - if(sk==6){ysk-=10;} - if(sk==9){xsk+=10;} - if(sk==12){ysk+=10;} - if(sk==10){xsk+=3;} - zahlpos.push([sk,xsk,ysk]); - sk+=1; - } -} -setlet(); +// Show launcher when middle button pressed, and widgets that we're clock +Bangle.setUI("clock"); +// Load widgets if needed, and make them show swipeable +if (settings.loadWidgets) { + Bangle.loadWidgets(); + require("widget_utils").swipeOn(); +} else if (global.WIDGETS) require("widget_utils").hide(); // Clear the screen once, at startup -g.setBgColor(0,0,0); -g.clear(); drawScale(); draw(); -let secondInterval= setInterval(draw, 1000); -// Stop updates when LCD is off, restart when on +let secondInterval = setInterval(draw, 1000); +// Stop updates when LCD is off, restart when on Bangle.on('lcdPower',on=>{ if (secondInterval) clearInterval(secondInterval); secondInterval = undefined; if (on) { - secondInterval = setInterval(draw, 1000); - draw(); // draw immediately + secondInterval = setInterval(draw, 1000); + draw(); // draw immediately } }); Bangle.on('lock',on=>{ + unlock = !on; if (secondInterval) clearInterval(secondInterval); - secondInterval = undefined; - if (!on) { - secondInterval = setInterval(draw, 1000); - unlock = true; - draw(); // draw immediately - }else{ - secondInterval = setInterval(draw, 60000); - unlock = false; - draw(); - } - }); - -// Show launcher when middle button pressed -Bangle.setUI("clock"); + secondInterval = setInterval(draw, unlock ? 1000 : 60000); + draw(); // draw immediately +}); +Bangle.on('charging',on=>{draw();}); diff --git a/apps/andark/metadata.json b/apps/andark/metadata.json index 3e2b3116e..fc8872f4b 100644 --- a/apps/andark/metadata.json +++ b/apps/andark/metadata.json @@ -1,15 +1,18 @@ { "id": "andark", "name": "Analog Dark", "shortName":"AnDark", - "version":"0.04", + "version":"0.06", "description": "analog clock face without disturbing widgets", "icon": "andark_icon.png", "type": "clock", "tags": "clock", "supports" : ["BANGLEJS2"], + "screenshots": [{"url":"andark_screen.png"}], "readme": "README.md", "storage": [ {"name":"andark.app.js","url":"app.js"}, + {"name":"andark.settings.js","url":"settings.js"}, {"name":"andark.img","url":"app_icon.js","evaluate":true} - ] + ], + "data": [{"name":"andark.json"}] } diff --git a/apps/andark/settings.js b/apps/andark/settings.js new file mode 100644 index 000000000..708913705 --- /dev/null +++ b/apps/andark/settings.js @@ -0,0 +1,28 @@ +(function(back) { + const defaultSettings = { + loadWidgets : false, + textAboveHands : false, + shortHrHand : false + } + let settings = Object.assign(defaultSettings, require('Storage').readJSON('andark.json',1)||{}); + + const save = () => require('Storage').write('andark.json', settings); + + const appMenu = { + '': {title: 'andark'}, '< Back': back, + /*LANG*/'Load widgets': { + value : !!settings.loadWidgets, + onchange : v => { settings.loadWidgets=v; save();} + }, + /*LANG*/'Text above hands': { + value : !!settings.textAboveHands, + onchange : v => { settings.textAboveHands=v; save();} + }, + /*LANG*/'Short hour hand': { + value : !!settings.shortHrHand, + onchange : v => { settings.shortHrHand=v; save();} + }, + }; + + E.showMenu(appMenu); +}); diff --git a/apps/android/test.js b/apps/android/test.js deleted file mode 100644 index 007b06fc7..000000000 --- a/apps/android/test.js +++ /dev/null @@ -1,153 +0,0 @@ -let result = true; - -function assertTrue(condition, text) { - if (!condition) { - result = false; - print("FAILURE: " + text); - } else print("OK: " + text); -} - -function assertFalse(condition, text) { - assertTrue(!condition, text); -} - -function assertUndefinedOrEmpty(array, text) { - assertTrue(!array || array.length == 0, text); -} - -function assertNotEmpty(array, text) { - assertTrue(array && array.length > 0, text); -} - -let internalOn = () => { - return getPinMode((process.env.HWVERSION==2)?D30:D26) == "input"; -}; - -let sec = { - connected: false -}; - -NRF.getSecurityStatus = () => sec; -// add an empty starting point to make the asserts work -Bangle._PWR={}; - -let teststeps = []; - -teststeps.push(()=>{ - print("Not connected, should use internal GPS"); - assertTrue(!NRF.getSecurityStatus().connected, "Not connected"); - - assertUndefinedOrEmpty(Bangle._PWR.GPS, "No GPS"); - assertFalse(Bangle.isGPSOn(), "isGPSOn"); - - assertTrue(Bangle.setGPSPower(1, "test"), "Switch GPS on"); - - assertNotEmpty(Bangle._PWR.GPS, "GPS"); - assertTrue(Bangle.isGPSOn(), "isGPSOn"); - assertTrue(internalOn(), "Internal GPS on"); - - assertFalse(Bangle.setGPSPower(0, "test"), "Switch GPS off"); - - assertUndefinedOrEmpty(Bangle._PWR.GPS, "No GPS"); - assertFalse(Bangle.isGPSOn(), "isGPSOn"); - assertFalse(internalOn(), "Internal GPS off"); - -}); - -teststeps.push(()=>{ - print("Connected, should use GB GPS"); - sec.connected = true; - - assertTrue(NRF.getSecurityStatus().connected, "Connected"); - - assertUndefinedOrEmpty(Bangle._PWR.GPS, "No GPS"); - assertFalse(Bangle.isGPSOn(), "isGPSOn"); - assertFalse(internalOn(), "Internal GPS off"); - - - print("Internal GPS stays on until the first GadgetBridge event arrives"); - assertTrue(Bangle.setGPSPower(1, "test"), "Switch GPS on"); - - assertNotEmpty(Bangle._PWR.GPS, "GPS"); - assertTrue(Bangle.isGPSOn(), "isGPSOn"); - assertTrue(internalOn(), "Internal GPS on"); - - print("Send minimal GadgetBridge GPS event to trigger switch"); - GB({t:"gps"}); -}); - -teststeps.push(()=>{ - print("GPS should be on, internal off"); - - assertNotEmpty(Bangle._PWR.GPS, "GPS"); - assertTrue(Bangle.isGPSOn(), "isGPSOn"); - assertFalse(internalOn(), "Internal GPS off"); -}); - -teststeps.push(()=>{ - print("Switching GPS off turns both GadgetBridge as well as internal off"); - assertFalse(Bangle.setGPSPower(0, "test"), "Switch GPS off"); - - assertUndefinedOrEmpty(Bangle._PWR.GPS, "No GPS"); - assertFalse(Bangle.isGPSOn(), "isGPSOn"); - assertFalse(internalOn(), "Internal GPS off"); -}); - -teststeps.push(()=>{ - print("Wait for all timeouts to run out"); - return 12000; -}); - -teststeps.push(()=>{ - print("Check auto switch when no GPS event arrives"); - - assertTrue(Bangle.setGPSPower(1, "test"), "Switch GPS on"); - - assertNotEmpty(Bangle._PWR.GPS, "GPS"); - assertTrue(Bangle.isGPSOn(), "isGPSOn"); - assertTrue(internalOn(), "Internal GPS on"); - - print("Send minimal GadgetBridge GPS event to trigger switch"); - GB({t:"gps"}); - - print("Internal should be switched off now"); - - assertNotEmpty(Bangle._PWR.GPS, "GPS"); - assertTrue(Bangle.isGPSOn(), "isGPSOn"); - assertFalse(internalOn(), "Internal GPS off"); - - //wait on next test - return 12000; -}); - -teststeps.push(()=>{ - print("Check state and disable GPS, internal should be on"); - - assertNotEmpty(Bangle._PWR.GPS, "GPS"); - assertTrue(Bangle.isGPSOn(), "isGPSOn"); - assertTrue(internalOn(), "Internal GPS on"); - - assertFalse(Bangle.setGPSPower(0, "test"), "Switch GPS off"); -}); - -teststeps.push(()=>{ - print("Result Overall is " + (result ? "OK" : "FAIL")); -}); - -let wrap = (functions) => { - if (functions.length > 0) { - setTimeout(()=>{ - let waitingTime = functions.shift()(); - if (waitingTime){ - print("WAITING: ", waitingTime); - setTimeout(()=>{wrap(functions);}, waitingTime); - } else - wrap(functions); - },0); - } -}; - -setTimeout(()=>{ - wrap(teststeps); -}, 5000); - diff --git a/apps/android/test.json b/apps/android/test.json new file mode 100644 index 000000000..429fd70fe --- /dev/null +++ b/apps/android/test.json @@ -0,0 +1,99 @@ +{ + "app" : "android", + "setup" : [{ + "id": "default", + "steps" : [ + {"t":"cmd", "js": "Bangle.setGPSPower=(isOn, appID)=>{if (!appID) appID='?';if (!Bangle._PWR) Bangle._PWR={};if (!Bangle._PWR.GPS) Bangle._PWR.GPS=[];if (isOn && !Bangle._PWR.GPS.includes(appID)) Bangle._PWR.GPS.push(appID);if (!isOn && Bangle._PWR.GPS.includes(appID)) Bangle._PWR.GPS.splice(Bangle._PWR.GPS.indexOf(appID),1);return Bangle._PWR.GPS.length>0;};", "text": "Fake the setGPSPower"}, + {"t":"wrap", "fn": "Bangle.setGPSPower", "id": "gpspower"}, + {"t":"cmd", "js": "Serial1.println = () => { }", "text": "Fake the serial port println"}, + {"t":"cmd", "js": "Bluetooth.println = () => { }", "text": "Fake the Bluetooth println"}, + {"t":"cmd", "js": "Bangle._PWR={}", "text": "Prepare an empty _PWR for following asserts"}, + {"t":"cmd", "js": "require('Storage').writeJSON('android.settings.json', {overwriteGps: true})", "text": "Enable GPS overwrite"}, + {"t":"cmd", "js": "eval(require('Storage').read('android.boot.js'))", "text": "Load the boot code"} + ] + },{ + "id": "connected", + "steps" : [ + {"t":"cmd", "js": "NRF.getSecurityStatus = () => { return { connected: true };}", "text": "Control the security status to be connected"} + ] + },{ + "id": "disconnected", + "steps" : [ + {"t":"cmd", "js": "NRF.getSecurityStatus = () => { return { connected: false };}", "text": "Control the security status to be disconnected"} + ] + }], + "tests" : [{ + "description": "Check setGPSPower is replaced", + "steps" : [ + {"t":"cmd", "js": "Serial1.println = () => { }", "text": "Fake the serial port"}, + {"t":"cmd", "js": "Bluetooth.println = () => { }", "text": "Fake the Bluetooth println"}, + {"t":"cmd", "js": "require('Storage').writeJSON('android.settings.json', {overwriteGps: true})", "text": "Enable GPS overwrite"}, + {"t":"cmd", "js": "eval(require('Storage').read('android.boot.js'))", "text": "Load the boot code"}, + {"t":"assert", "js": "Bangle.setGPSPower.toString().includes('native')", "is":"false", "text": "setGPSPower has been replaced"} + ] + },{ + "description": "Test switching hardware GPS on and off", + "steps" : [ + {"t":"setup", "id": "default"}, + {"t":"setup", "id": "connected"}, + {"t":"assertArray", "js": "Bangle._PWR.GPS", "is":"undefinedOrEmpty", "text": "No GPS clients"}, + {"t":"assert", "js": "Bangle.isGPSOn()", "is":"falsy", "text": "isGPSOn shows GPS as off"}, + {"t":"assert", "js": "Bangle.setGPSPower(1, 'test')", "is":"truthy", "text": "setGPSPower returns truthy when switching on"}, + {"t":"assertArray", "js": "Bangle._PWR.GPS", "is":"notEmpty", "text": "GPS clients"}, + {"t":"assert", "js": "Bangle.isGPSOn()", "is":"truthy", "text": "isGPSOn shows GPS as on"}, + {"t":"assertCall", "id": "gpspower", "count": 1, "argAsserts": [ { "t": "assert", "arg": "0", "is": "equal", "to": 1 } ] , "text": "internal GPS switched on"}, + {"t":"assert", "js": "Bangle.setGPSPower(0, 'test')", "is":"falsy", "text": "setGPSPower returns falsy when switching off"}, + {"t":"assertArray", "js": "Bangle._PWR.GPS", "is":"undefinedOrEmpty", "text": "No GPS clients"}, + {"t":"assert", "js": "Bangle.isGPSOn()", "is":"falsy", "text": "isGPSOn shows GPS as off"}, + {"t":"assertCall", "id": "gpspower", "count": 2, "argAsserts": [ { "t": "assert", "arg": "0", "is": "equal", "to": 0 } ] , "text": "internal GPS switched off"} + ] + },{ + "description": "Test switching when GB GPS is available, internal GPS active until GB GPS event arrives", + "steps" : [ + {"t":"setup", "id": "default"}, + {"t":"setup", "id": "connected"}, + {"t":"assertArray", "js": "Bangle._PWR.GPS", "is":"undefinedOrEmpty", "text": "No GPS clients"}, + {"t":"assert", "js": "Bangle.isGPSOn()", "is":"falsy", "text": "isGPSOn shows GPS as off"}, + + {"t":"assert", "js": "Bangle.setGPSPower(1, 'test')", "is":"truthy", "text": "setGPSPower returns truthy when switching on"}, + {"t":"assertArray", "js": "Bangle._PWR.GPS", "is":"notEmpty", "text": "GPS clients"}, + {"t":"assert", "js": "Bangle.isGPSOn()", "is":"truthy", "text": "isGPSOn shows GPS as on"}, + {"t":"assertCall", "id": "gpspower", "count": 1, "argAsserts": [ { "t": "assert", "arg": "0", "is": "equal", "to": 1 } ], "text": "internal GPS switched on"}, + + {"t":"gb", "obj":{"t":"gps"}}, + {"t":"assertArray", "js": "Bangle._PWR.GPS", "is":"notEmpty", "text": "GPS clients still there"}, + {"t":"assert", "js": "Bangle.isGPSOn()", "is":"truthy", "text": "isGPSOn still shows GPS as on"}, + {"t":"assertCall", "id": "gpspower", "count": 2, "argAsserts": [ { "t": "assert", "arg": "0", "is": "equal", "to": 0 } ], "text": "internal GPS switched off"} + ] + },{ + "description": "Test switching when GB GPS is available, internal stays off", + "steps" : [ + {"t":"setup", "id": "default"}, + {"t":"setup", "id": "connected"}, + + {"t":"assert", "js": "Bangle.setGPSPower(1, 'test')", "is":"truthy", "text": "setGPSPower returns truthy when switching on"}, + + {"t":"gb", "obj":{"t":"gps"}}, + {"t":"assertCall", "id": "gpspower", "argAsserts": [ { "t": "assert", "arg": "0", "is": "equal", "to": 0 } ], "text": "internal GPS switched off"}, + + {"t":"assert", "js": "Bangle.setGPSPower(0, 'test')", "is":"falsy", "text": "setGPSPower returns truthy when switching on"}, + {"t":"assertCall", "id": "gpspower", "argAsserts": [ { "t": "assert", "arg": "0", "is": "equal", "to": 0 } ], "text": "internal GPS still switched off"} + ] + },{ + "description": "Test switching when GB GPS is available, but no event arrives", + "steps" : [ + {"t":"setup", "id": "default"}, + {"t":"setup", "id": "connected"}, + + {"t":"assert", "js": "Bangle.setGPSPower(1, 'test')", "is":"truthy", "text": "setGPSPower returns truthy when switching on"}, + + {"t":"resetCall", "id": "gpspower"}, + {"t":"gb", "obj":{"t":"gps"}, "text": "trigger switch"}, + {"t":"assertCall", "id": "gpspower", "argAsserts": [ { "t": "assert", "arg": "0", "is": "equal", "to": 0 } ], "text": "internal GPS switched off"}, + + {"t":"resetCall", "id": "gpspower"}, + {"t":"advanceTimers", "ms":"12000", "text": "wait for fallback"}, + {"t":"assertCall", "id": "gpspower", "argAsserts": [ { "t": "assert", "arg": "0", "is": "equal", "to": 1 } ], "text": "internal GPS switched on caused by missing GB event"} + ] + }] +} diff --git a/apps/antonclk/test.json b/apps/antonclk/test.json new file mode 100644 index 000000000..a719e0a14 --- /dev/null +++ b/apps/antonclk/test.json @@ -0,0 +1,15 @@ +{ + "app" : "antonclk", + "tests" : [{ + "description": "Check memory usage after setUI", + "steps" : [ + {"t":"cmd", "js": "Bangle.loadWidgets()"}, + {"t":"cmd", "js": "eval(require('Storage').read('antonclk.app.js'))"}, + {"t":"cmd", "js": "Bangle.setUI()"}, + {"t":"saveMemoryUsage"}, + {"t":"cmd", "js": "eval(require('Storage').read('antonclk.app.js'))"}, + {"t":"cmd", "js":"Bangle.setUI()"}, + {"t":"checkMemoryUsage"} + ] + }] +} diff --git a/apps/autoreset/ChangeLog b/apps/autoreset/ChangeLog index 5560f00bc..cef136817 100644 --- a/apps/autoreset/ChangeLog +++ b/apps/autoreset/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Add black- and whitelist for apps. Configure the timout time. diff --git a/apps/autoreset/README.md b/apps/autoreset/README.md index 965b2e291..3d086ee0e 100644 --- a/apps/autoreset/README.md +++ b/apps/autoreset/README.md @@ -6,11 +6,11 @@ Sets a timeout to load the clock face. The timeout is stopped and started again Install with app loader and Auto Reset will run in background. If you don't interact with the watch it will time out to the clock face after 10 minutes. +Through the settings apps can be black-/whitelisted and the timeout length can be configured. + ## TODO -- Add settings page - - set how many minutes the timeout should count down. - - whitelist/blacklist for apps. +- per app specific timeout lengths? ## Requests diff --git a/apps/autoreset/boot.js b/apps/autoreset/boot.js index 3302eca08..fc8d9ec0a 100644 --- a/apps/autoreset/boot.js +++ b/apps/autoreset/boot.js @@ -1,12 +1,29 @@ { +const DEFAULTS = { + mode: 0, + apps: [], + timeout: 10 +}; +const settings = require("Storage").readJSON("autoreset.json", 1) || DEFAULTS; + +// Check if the back button should be enabled for the current app. +// app is the src file of the app. +// Derivative of the backswipe app's logic. +function enabledForApp(app) { + if (Bangle.CLOCK==1) return false; + if (!settings) return true; + let isListed = settings.apps.filter((a) => a.files.includes(app)).length > 0; + return settings.mode===0?!isListed:isListed; +} + let timeoutAutoreset; -let resetTimeoutAutoreset = (force)=>{ +const resetTimeoutAutoreset = (force)=>{ if (timeoutAutoreset) clearTimeout(timeoutAutoreset); setTimeout(()=>{ // Short outer timeout to make sure we have time to leave clock face before checking `Bangle.CLOCK!=1`. - if (Bangle.CLOCK!=1) { // Only add timeout if not already on clock face. + if (enabledForApp(global.__FILE__)) { timeoutAutoreset = setTimeout(()=>{ if (Bangle.CLOCK!=1) Bangle.showClock(); - }, 10*60*1000); + }, settings.timeout*60*1000); } },200); }; diff --git a/apps/autoreset/metadata.json b/apps/autoreset/metadata.json index ca35b4d7a..c8866924b 100644 --- a/apps/autoreset/metadata.json +++ b/apps/autoreset/metadata.json @@ -1,6 +1,6 @@ { "id": "autoreset", "name": "Auto Reset", - "version":"0.01", + "version":"0.02", "description": "Sets a timeout to load the clock face. The timeout is stopped and started again upon user input.", "icon": "app.png", "type": "bootloader", @@ -8,6 +8,10 @@ "supports" : ["BANGLEJS2"], "readme": "README.md", "storage": [ - {"name":"autoreset.boot.js","url":"boot.js"} + {"name":"autoreset.boot.js","url":"boot.js"}, + {"name":"autoreset.settings.js","url":"settings.js"} + ], + "data":[ + {"name":"autoreset.json"} ] } diff --git a/apps/autoreset/settings.js b/apps/autoreset/settings.js new file mode 100644 index 000000000..8cbccd6f0 --- /dev/null +++ b/apps/autoreset/settings.js @@ -0,0 +1,115 @@ +(function(back) { + var FILE = 'autoreset.json'; + // Mode can be 'blacklist' or 'whitelist' + // Apps is an array of app info objects, where all the apps that are there are either blocked or allowed, depending on the mode + var DEFAULTS = { + 'mode': 0, + 'apps': [], + 'timeout': 10 + }; + + var settings = {}; + + var loadSettings = function() { + settings = require('Storage').readJSON(FILE, 1) || DEFAULTS; + }; + + var saveSettings = function(settings) { + require('Storage').write(FILE, settings); + }; + + // Get all app info files + var getApps = function() { + var apps = require('Storage').list(/\.info$/).map(appInfoFileName => { + var appInfo = require('Storage').readJSON(appInfoFileName, 1); + return appInfo && { + 'name': appInfo.name, + 'sortorder': appInfo.sortorder, + 'src': appInfo.src, + 'files': appInfo.files + }; + }).filter(app => app && !!app.src); + apps.sort((a, b) => { + var n = (0 | a.sortorder) - (0 | b.sortorder); + if (n) return n; // do sortorder first + if (a.name < b.name) return -1; + if (a.name > b.name) return 1; + return 0; + }); + return apps; + }; + + var showMenu = function() { + var menu = { + '': { 'title': 'Auto Reset' }, + /*LANG*/'< Back': () => { + back(); + }, + /*LANG*/'Mode': { + value: settings.mode, + min: 0, + max: 1, + format: v => ["Blacklist", "Whitelist"][v], + onchange: v => { + settings.mode = v; + saveSettings(settings); + }, + }, + /*LANG*/'App List': () => { + showAppSubMenu(); + }, + /*LANG*/'Timeout [min]': { + value: settings.timeout, + min: 0.25, max: 30, step : 0.25, + format: v => v, + onchange: v => { + settings.timeout = v; + saveSettings(settings); + }, + }, + }; + + E.showMenu(menu); + }; + + var showAppSubMenu = function() { + var menu = { + '': { 'title': 'Auto Reset' }, + '< Back': () => { + showMenu(); + }, + 'Add App': () => { + showAppList(); + } + }; + settings.apps.forEach(app => { + menu[app.name] = () => { + settings.apps.splice(settings.apps.indexOf(app), 1); + saveSettings(settings); + showAppSubMenu(); + } + }); + E.showMenu(menu); + } + + var showAppList = function() { + var apps = getApps(); + var menu = { + '': { 'title': 'Auto Reset' }, + /*LANG*/'< Back': () => { + showMenu(); + } + }; + apps.forEach(app => { + menu[app.name] = () => { + settings.apps.push(app); + saveSettings(settings); + showAppSubMenu(); + } + }); + E.showMenu(menu); + } + + loadSettings(); + showMenu(); +}) diff --git a/apps/backswipe/ChangeLog b/apps/backswipe/ChangeLog index 54ffebfc7..4e81269fe 100644 --- a/apps/backswipe/ChangeLog +++ b/apps/backswipe/ChangeLog @@ -1,3 +1,6 @@ 0.01: New App! 0.02: Don't fire if the app uses swipes already. 0.03: Only count defined handlers in the handler array. +0.04: Fix messages auto opened by `messagegui` could not be blacklisted. Needs + a refresh by deselecting and reselecting the "Messages" app throught Back Swipe + settings. diff --git a/apps/backswipe/boot.js b/apps/backswipe/boot.js index d5d54cd59..8ff277634 100644 --- a/apps/backswipe/boot.js +++ b/apps/backswipe/boot.js @@ -47,9 +47,9 @@ function enabledForApp(app) { if (!settings) return true; if (settings.mode === 0) { - return !(settings.apps.filter((a) => a.src === app).length > 0); + return !(settings.apps.filter((a) => (a.src===app)||(a.files&&a.files.includes(app))).length > 0); // The `a.src===app` and `a.files&&...` checks are for backwards compatibility. Otherwise only `a.files.includes(app)` is needed. } else if (settings.mode === 1) { - return settings.apps.filter((a) => a.src === app).length > 0; + return settings.apps.filter((a) => (a.src===app)||(a.files&&a.files.includes(app))).length > 0; } else { return settings.mode === 2 ? true : false; } diff --git a/apps/backswipe/metadata.json b/apps/backswipe/metadata.json index add609a0f..4324286b5 100644 --- a/apps/backswipe/metadata.json +++ b/apps/backswipe/metadata.json @@ -1,7 +1,7 @@ { "id": "backswipe", "name": "Back Swipe", "shortName":"BackSwipe", - "version":"0.03", + "version":"0.04", "description": "Service that allows you to use an app's back button using left to right swipe gesture", "icon": "app.png", "tags": "back,gesture,swipe", diff --git a/apps/backswipe/settings.js b/apps/backswipe/settings.js index 42ca7ae7d..c98f706eb 100644 --- a/apps/backswipe/settings.js +++ b/apps/backswipe/settings.js @@ -26,7 +26,8 @@ return appInfo && { 'name': appInfo.name, 'sortorder': appInfo.sortorder, - 'src': appInfo.src + 'src': appInfo.src, + 'files': appInfo.files }; }).filter(app => app && !!app.src); apps.sort((a, b) => { diff --git a/apps/boot/ChangeLog b/apps/boot/ChangeLog index 95a9ff2c6..8948002e5 100644 --- a/apps/boot/ChangeLog +++ b/apps/boot/ChangeLog @@ -69,3 +69,4 @@ 0.58: "Make Connectable" temporarily bypasses the whitelist 0.59: Whitelist: Try to resolve peer addresses using NRF.resolveAddress() - for 2v19 or 2v18 cutting edge builds 0.60: Minor code improvements +0.61: Instead of breaking execution with an Exception when updating boot, just use if..else (fix 'Uncaught undefined') \ No newline at end of file diff --git a/apps/boot/bootupdate.js b/apps/boot/bootupdate.js index 315b60723..f8ba22752 100644 --- a/apps/boot/bootupdate.js +++ b/apps/boot/bootupdate.js @@ -14,15 +14,15 @@ if (DEBUG) { } if (require('Storage').hash) { // new in 2v11 - helps ensure files haven't changed let CRC = E.CRC32(require('Storage').read('setting.json'))+require('Storage').hash(/\.boot\.js/)+E.CRC32(process.env.GIT_COMMIT); - boot += `if (E.CRC32(require('Storage').read('setting.json'))+require('Storage').hash(/\\.boot\\.js/)+E.CRC32(process.env.GIT_COMMIT)!=${CRC})`; + boot += `if(E.CRC32(require('Storage').read('setting.json'))+require('Storage').hash(/\\.boot\\.js/)+E.CRC32(process.env.GIT_COMMIT)!=${CRC})`; } else { let CRC = E.CRC32(require('Storage').read('setting.json'))+E.CRC32(require('Storage').list(/\.boot\.js/))+E.CRC32(process.env.GIT_COMMIT); - boot += `if (E.CRC32(require('Storage').read('setting.json'))+E.CRC32(require('Storage').list(/\\.boot\\.js/))+E.CRC32(process.env.GIT_COMMIT)!=${CRC})`; + boot += `if(E.CRC32(require('Storage').read('setting.json'))+E.CRC32(require('Storage').list(/\\.boot\\.js/))+E.CRC32(process.env.GIT_COMMIT)!=${CRC})`; } -boot += ` { eval(require('Storage').read('bootupdate.js')); throw "Storage Updated!"}\n`; +boot += `{eval(require('Storage').read('bootupdate.js'));print("Storage Updated!")}else{\n`; boot += `E.setFlags({pretokenise:1});\n`; boot += `var bleServices = {}, bleServiceOptions = { uart : true};\n`; -bootPost += `NRF.setServices(bleServices, bleServiceOptions);delete bleServices,bleServiceOptions;\n`; // executed after other boot code +bootPost += `NRF.setServices(bleServices,bleServiceOptions);delete bleServices,bleServiceOptions;\n`; // executed after other boot code if (s.ble!==false) { if (s.HID) { // Human interface device if (s.HID=="joy") boot += `Bangle.HID = E.toUint8Array(atob("BQEJBKEBCQGhAAUJGQEpBRUAJQGVBXUBgQKVA3UBgQMFAQkwCTEVgSV/dQiVAoECwMA="));`; @@ -105,7 +105,7 @@ if (!date.toLocalISOString) boot += `Date.prototype.toLocalISOString = function( // show timings if (DEBUG) boot += `print(".boot0",0|(Date.now()-_tm),"ms");_tm=Date.now();\n` // ================================================== BOOT.JS -// Append *.boot.js files. +// Append *.boot.js files. // Name files with a number - eg 'foo.5.boot.js' to enforce order (lowest first). Numbered files get placed before non-numbered // These could change bleServices/bleServiceOptions if needed let bootFiles = require('Storage').list(/\.boot\.js$/).sort((a,b)=>{ @@ -122,6 +122,7 @@ let bootFiles = require('Storage').list(/\.boot\.js$/).sort((a,b)=>{ return a==b ? 0 : (a>b ? 1 : -1); }); // precalculate file size +bootPost += "}"; let fileSize = boot.length + bootPost.length; bootFiles.forEach(bootFile=>{ // match the size of data we're adding below in bootFiles.forEach diff --git a/apps/boot/metadata.json b/apps/boot/metadata.json index 07e999797..60c4e1814 100644 --- a/apps/boot/metadata.json +++ b/apps/boot/metadata.json @@ -1,7 +1,7 @@ { "id": "boot", "name": "Bootloader", - "version": "0.60", + "version": "0.61", "description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings", "icon": "bootloader.png", "type": "bootloader", diff --git a/apps/chargent/ChangeLog b/apps/chargent/ChangeLog index fb3eaa780..349618315 100644 --- a/apps/chargent/ChangeLog +++ b/apps/chargent/ChangeLog @@ -4,3 +4,4 @@ 0.04: Added notification 0.05: Fixed boot 0.06: Allow tap to silence notification/buzzing +0.07: Fix notification-tap silencing and notification length diff --git a/apps/chargent/boot.js b/apps/chargent/boot.js index 198e36f18..42c384711 100644 --- a/apps/chargent/boot.js +++ b/apps/chargent/boot.js @@ -24,8 +24,8 @@ lim = sum / cnt; require('Storage').writeJSON('chargent.json', {limit: lim}); } - const onHide = () => { id = clearInterval(id) }; - require('notify').show({id: 'chargent', title: 'Fully charged', onHide }); + const onHide = () => { if(id) id = clearInterval(id) }; + require('notify').show({id: 'chargent', title: 'Charged', onHide }); // TODO ? customizable Bangle.buzz(500); setTimeout(() => Bangle.buzz(500), 1000); diff --git a/apps/chargent/metadata.json b/apps/chargent/metadata.json index bae35b361..75366ff59 100644 --- a/apps/chargent/metadata.json +++ b/apps/chargent/metadata.json @@ -1,6 +1,6 @@ { "id": "chargent", "name": "Charge Gently", - "version": "0.06", + "version": "0.07", "description": "When charging, reminds you to disconnect the watch to prolong battery life.", "icon": "icon.png", "type": "bootloader", diff --git a/apps/clkinfocal/ChangeLog b/apps/clkinfocal/ChangeLog index 50da8d080..e3c19f0ba 100644 --- a/apps/clkinfocal/ChangeLog +++ b/apps/clkinfocal/ChangeLog @@ -1,3 +1,4 @@ 0.01: New App! 0.02: added settings options to change date format -0.03: Remove un-needed font requirement, now outputs transparent image \ No newline at end of file +0.03: Remove un-needed font requirement, now outputs transparent image +0.04: Fix image after 0.03 regression \ No newline at end of file diff --git a/apps/clkinfocal/clkinfo.js b/apps/clkinfocal/clkinfo.js index da9607bb4..893549399 100644 --- a/apps/clkinfocal/clkinfo.js +++ b/apps/clkinfocal/clkinfo.js @@ -20,7 +20,7 @@ get : () => { let d = new Date(); let g = Graphics.createArrayBuffer(24,24,1,{msb:true}); - g.transparent = 1; + g.transparent = 0; g.drawImage(atob("FhgBDADAMAMP/////////////////////8AADwAAPAAA8AADwAAPAAA8AADwAAPAAA8AADwAAPAAA8AADwAAP///////"),1,0); g.setFont("6x15").setFontAlign(0,0).drawString(d.getDate(),11,17); return { diff --git a/apps/clkinfocal/metadata.json b/apps/clkinfocal/metadata.json index 2f1182883..0bdcb5178 100644 --- a/apps/clkinfocal/metadata.json +++ b/apps/clkinfocal/metadata.json @@ -1,6 +1,6 @@ { "id": "clkinfocal", "name": "Calendar Clockinfo", - "version":"0.03", + "version":"0.04", "description": "For clocks that display 'clockinfo' (messages that can be cycled through using the clock_info module) this displays the day of the month in the icon, and the weekday. There is also a settings menu to select the format of the text", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}], diff --git a/apps/clock_info/ChangeLog b/apps/clock_info/ChangeLog index 81c879311..8276321ac 100644 --- a/apps/clock_info/ChangeLog +++ b/apps/clock_info/ChangeLog @@ -10,3 +10,4 @@ 0.09: Save clkinfo settings on kill and remove 0.10: Fix focus bug when changing focus between two clock infos 0.11: Prepend swipe listener if possible +0.12: Add drawFilledImage to allow drawing icons with a separately coloured middle \ No newline at end of file diff --git a/apps/clock_info/lib.js b/apps/clock_info/lib.js index b44df9b18..a9ca7de31 100644 --- a/apps/clock_info/lib.js +++ b/apps/clock_info/lib.js @@ -371,6 +371,46 @@ exports.addInteractive = function(menu, options) { return options; }; +/* clockinfos usually return a 24x24 image. This draws that image but +recolors it such that it is transparent, with the middle of the image as background +and the image itself as foreground. options is passed to g.drawImage */ +exports.drawFilledImage = function(img,x,y,options) { + if (!img) return; + if (!g.floodFill/*2v18+*/) return g.drawImage(img,x,y,options); + let gfx = exports.imgGfx; + if (!gfx) { + gfx = exports.imgGfx = Graphics.createArrayBuffer(26, 26, 2, {msb:true}); + gfx.transparent = 3; + gfx.palette = new Uint16Array([g.theme.bg, g.theme.fg, g.toColor("#888"), g.toColor("#888")]); + } + /* img is (usually) a black and white transparent image. But we really would like the bits in + the middle of it to be white. So what we do is we draw a slightly bigger rectangle in white, + draw the image, and then flood-fill the rectangle back to the background color. floodFill + was only added in 2v18 so we have to check for it and fallback if not. */ + gfx.clear(1).setColor(1).drawImage(img, 1,1).floodFill(0,0,3); + var scale = (options && options.scale) || 1; + return g.drawImage(gfx, x-scale,y-scale,options); +}; + +/* clockinfos usually return a 24x24 image. This creates a 26x26 gfx of the image but +recolors it such that it is transparent, with the middle and border of the image as background +and the image itself as foreground. options is passed to g.drawImage */ +exports.drawBorderedImage = function(img,x,y,options) { + if (!img) return; + if (!g.floodFill/*2v18+*/) return g.drawImage(img,x,y,options); + let gfx = exports.imgGfxB; + if (!gfx) { + gfx = exports.imgGfxB = Graphics.createArrayBuffer(28, 28, 2, {msb:true}); + gfx.transparent = 3; + gfx.palette = new Uint16Array([g.theme.bg, g.theme.fg, g.theme.bg/*border*/, g.toColor("#888")]); + } + gfx.clear(1).setColor(2).drawImage(img, 1,1).drawImage(img, 3,1).drawImage(img, 1,3).drawImage(img, 3,3); // border + gfx.setColor(1).drawImage(img, 2,2); // main image + gfx.floodFill(27,27,3); // flood fill edge to transparent + var o = ((options && options.scale) || 1)*2; + return g.drawImage(gfx, x-o,y-o,options); +}; + // Code for testing (plots all elements from first list) /* g.clear(); diff --git a/apps/clock_info/metadata.json b/apps/clock_info/metadata.json index 921a6fc4e..3d47c5062 100644 --- a/apps/clock_info/metadata.json +++ b/apps/clock_info/metadata.json @@ -1,11 +1,11 @@ { "id": "clock_info", "name": "Clock Info Module", "shortName": "Clock Info", - "version":"0.11", + "version":"0.12", "description": "A library used by clocks to provide extra information on the clock face (Altitude, BPM, etc)", "icon": "app.png", "type": "module", - "tags": "clkinfo", + "tags": "clkinfo,clockinfo", "supports" : ["BANGLEJS2"], "provides_modules" : ["clock_info"], "readme": "README.md", diff --git a/apps/clockbg/img/ai_flow.jpeg b/apps/clockbg/img/ai_flow.jpeg new file mode 100644 index 000000000..f30f89843 Binary files /dev/null and b/apps/clockbg/img/ai_flow.jpeg differ diff --git a/apps/clockbg/img/ai_horse.jpeg b/apps/clockbg/img/ai_horse.jpeg new file mode 100644 index 000000000..3b7da61f1 Binary files /dev/null and b/apps/clockbg/img/ai_horse.jpeg differ diff --git a/apps/clockbg/img/icons8-australia-480.png b/apps/clockbg/img/icons8-australia-480.png index edf34cdee..3bb1ac09b 100644 Binary files a/apps/clockbg/img/icons8-australia-480.png and b/apps/clockbg/img/icons8-australia-480.png differ diff --git a/apps/clockbg/img/icons8-austria-480.png b/apps/clockbg/img/icons8-austria-480.png index 8450a8840..5431bbd7a 100644 Binary files a/apps/clockbg/img/icons8-austria-480.png and b/apps/clockbg/img/icons8-austria-480.png differ diff --git a/apps/clockbg/img/icons8-belgium-480.png b/apps/clockbg/img/icons8-belgium-480.png index 395fef8d1..f0c6485f9 100644 Binary files a/apps/clockbg/img/icons8-belgium-480.png and b/apps/clockbg/img/icons8-belgium-480.png differ diff --git a/apps/clockbg/img/icons8-brazil-480.png b/apps/clockbg/img/icons8-brazil-480.png index 570ee39f9..505af26ca 100644 Binary files a/apps/clockbg/img/icons8-brazil-480.png and b/apps/clockbg/img/icons8-brazil-480.png differ diff --git a/apps/clockbg/img/icons8-canada-480.png b/apps/clockbg/img/icons8-canada-480.png index 3d3080768..62181468f 100644 Binary files a/apps/clockbg/img/icons8-canada-480.png and b/apps/clockbg/img/icons8-canada-480.png differ diff --git a/apps/clockbg/img/icons8-china-480.png b/apps/clockbg/img/icons8-china-480.png index c3c3faba7..ba56ccc1e 100644 Binary files a/apps/clockbg/img/icons8-china-480.png and b/apps/clockbg/img/icons8-china-480.png differ diff --git a/apps/clockbg/img/icons8-denmark-480.png b/apps/clockbg/img/icons8-denmark-480.png index 2add9dbce..716e15f98 100644 Binary files a/apps/clockbg/img/icons8-denmark-480.png and b/apps/clockbg/img/icons8-denmark-480.png differ diff --git a/apps/clockbg/img/icons8-england-480.png b/apps/clockbg/img/icons8-england-480.png index 5c9a836a6..2343521f3 100644 Binary files a/apps/clockbg/img/icons8-england-480.png and b/apps/clockbg/img/icons8-england-480.png differ diff --git a/apps/clockbg/img/icons8-flag-of-europe-480.png b/apps/clockbg/img/icons8-flag-of-europe-480.png index 654da87ba..616d5fe7a 100644 Binary files a/apps/clockbg/img/icons8-flag-of-europe-480.png and b/apps/clockbg/img/icons8-flag-of-europe-480.png differ diff --git a/apps/clockbg/img/icons8-france-480.png b/apps/clockbg/img/icons8-france-480.png index e3cb56348..09a24c8b1 100644 Binary files a/apps/clockbg/img/icons8-france-480.png and b/apps/clockbg/img/icons8-france-480.png differ diff --git a/apps/clockbg/img/icons8-germany-480.png b/apps/clockbg/img/icons8-germany-480.png index 0f86aa568..dd2b317bb 100644 Binary files a/apps/clockbg/img/icons8-germany-480.png and b/apps/clockbg/img/icons8-germany-480.png differ diff --git a/apps/clockbg/img/icons8-great-britain-480.png b/apps/clockbg/img/icons8-great-britain-480.png index 0acdcc191..f89add414 100644 Binary files a/apps/clockbg/img/icons8-great-britain-480.png and b/apps/clockbg/img/icons8-great-britain-480.png differ diff --git a/apps/clockbg/img/icons8-greece-480.png b/apps/clockbg/img/icons8-greece-480.png index 319cf93cb..eb823b4bc 100644 Binary files a/apps/clockbg/img/icons8-greece-480.png and b/apps/clockbg/img/icons8-greece-480.png differ diff --git a/apps/clockbg/img/icons8-hungary-480.png b/apps/clockbg/img/icons8-hungary-480.png index ab838afea..4097e88d3 100644 Binary files a/apps/clockbg/img/icons8-hungary-480.png and b/apps/clockbg/img/icons8-hungary-480.png differ diff --git a/apps/clockbg/img/icons8-italy-480.png b/apps/clockbg/img/icons8-italy-480.png index f917cd85a..82b1b710e 100644 Binary files a/apps/clockbg/img/icons8-italy-480.png and b/apps/clockbg/img/icons8-italy-480.png differ diff --git a/apps/clockbg/img/icons8-lgbt-flag-480.png b/apps/clockbg/img/icons8-lgbt-flag-480.png index 10f869a0a..2e8bbebb1 100644 Binary files a/apps/clockbg/img/icons8-lgbt-flag-480.png and b/apps/clockbg/img/icons8-lgbt-flag-480.png differ diff --git a/apps/clockbg/img/icons8-netherlands-480.png b/apps/clockbg/img/icons8-netherlands-480.png index b271c5448..4ea397e27 100644 Binary files a/apps/clockbg/img/icons8-netherlands-480.png and b/apps/clockbg/img/icons8-netherlands-480.png differ diff --git a/apps/clockbg/img/icons8-new-zealand-480.png b/apps/clockbg/img/icons8-new-zealand-480.png index fc1ca7ec1..e21fdc574 100644 Binary files a/apps/clockbg/img/icons8-new-zealand-480.png and b/apps/clockbg/img/icons8-new-zealand-480.png differ diff --git a/apps/clockbg/img/icons8-norway-480.png b/apps/clockbg/img/icons8-norway-480.png index 270f5af8b..a57c0f7fb 100644 Binary files a/apps/clockbg/img/icons8-norway-480.png and b/apps/clockbg/img/icons8-norway-480.png differ diff --git a/apps/clockbg/img/icons8-scotland-480.png b/apps/clockbg/img/icons8-scotland-480.png index 991652211..20f08cfbb 100644 Binary files a/apps/clockbg/img/icons8-scotland-480.png and b/apps/clockbg/img/icons8-scotland-480.png differ diff --git a/apps/clockbg/img/icons8-spain-480.png b/apps/clockbg/img/icons8-spain-480.png index 19c8dac04..17fed3360 100644 Binary files a/apps/clockbg/img/icons8-spain-480.png and b/apps/clockbg/img/icons8-spain-480.png differ diff --git a/apps/clockbg/img/icons8-sweden-480.png b/apps/clockbg/img/icons8-sweden-480.png index 60f412840..99299e93a 100644 Binary files a/apps/clockbg/img/icons8-sweden-480.png and b/apps/clockbg/img/icons8-sweden-480.png differ diff --git a/apps/clockbg/img/icons8-switzerland-480.png b/apps/clockbg/img/icons8-switzerland-480.png index 801ba4776..cde8c6ff0 100644 Binary files a/apps/clockbg/img/icons8-switzerland-480.png and b/apps/clockbg/img/icons8-switzerland-480.png differ diff --git a/apps/clockbg/img/icons8-ukraine-480.png b/apps/clockbg/img/icons8-ukraine-480.png index 3762c1112..718695b38 100644 Binary files a/apps/clockbg/img/icons8-ukraine-480.png and b/apps/clockbg/img/icons8-ukraine-480.png differ diff --git a/apps/clockbg/img/icons8-usa-480.png b/apps/clockbg/img/icons8-usa-480.png index d6288404e..a7867f070 100644 Binary files a/apps/clockbg/img/icons8-usa-480.png and b/apps/clockbg/img/icons8-usa-480.png differ diff --git a/apps/clockbg/img/icons8-wales-480.png b/apps/clockbg/img/icons8-wales-480.png index 6c2941342..58233db34 100644 Binary files a/apps/clockbg/img/icons8-wales-480.png and b/apps/clockbg/img/icons8-wales-480.png differ diff --git a/apps/clockbg/interface.html b/apps/clockbg/interface.html index 7fba8ea7b..0ed26c883 100644 --- a/apps/clockbg/interface.html +++ b/apps/clockbg/interface.html @@ -7,8 +7,8 @@ cursor: pointer; } #preview { - width : 176px; - height: 176px; + width : 178px; /* include the border */ + height: 178px; border: 1px solid black; } @@ -19,10 +19,12 @@
If you'd like to contribute images you can add them on GitHub!