From 86c90c81ca15c9a186fa1ca861a89adf51f8badd Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 17 Dec 2021 21:57:26 +0000 Subject: [PATCH 001/489] 93dub: fix issue with light theme so that this dark does not end up with a white strip at the top --- apps.json | 2 +- apps/93dub/ChangeLog | 1 + apps/93dub/app.js | 8 +++++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 4a333cdbd..2179e766b 100644 --- a/apps.json +++ b/apps.json @@ -4620,7 +4620,7 @@ "shortName":"93 Dub", "icon": "93dub.png", "screenshots": [{"url":"screenshot.png"}], - "version":"0.05", + "version":"0.06", "description": "Fan recreation of orviwan's 91 Dub app for the Pebble smartwatch. Uses assets from his 91-Dub-v2.0 repo", "tags": "clock", "type": "clock", diff --git a/apps/93dub/ChangeLog b/apps/93dub/ChangeLog index c1b2588bb..1c18ca59b 100644 --- a/apps/93dub/ChangeLog +++ b/apps/93dub/ChangeLog @@ -3,3 +3,4 @@ 0.03: Code style cleanup 0.04: Set 00:00 to 12:00 for 12 hour time 0.05: Display time, even on Thursday +0.06: Fix light theme issue, where widgets would end up on a light strip diff --git a/apps/93dub/app.js b/apps/93dub/app.js index 1b0f69a94..f970eec5d 100644 --- a/apps/93dub/app.js +++ b/apps/93dub/app.js @@ -122,7 +122,13 @@ function draw(){ queueDraw(); } - +/** + * This watch is mostly dark, it does not make sense to respect the + * light theme as you end up with a white strip at the top for the + * widgets and black watch. So set the colours to the dark theme. + * + */ +g.setTheme({bg:"#000",fg:"#fff",dark:true}).clear(); draw(); //the following section is also from waveclk From d75940b9e617595c0a20d89474876a7e5cb2abdb Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Fri, 17 Dec 2021 22:57:09 +0100 Subject: [PATCH 002/489] Ported cprassist to Banglejs2 --- apps.json | 4 ++-- apps/cprassist/ChangeLog | 1 + apps/cprassist/cprassist.js | 17 +++++++++-------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/apps.json b/apps.json index 8b4e86d52..4f966bbdd 100644 --- a/apps.json +++ b/apps.json @@ -2970,11 +2970,11 @@ { "id": "cprassist", "name": "CPR Assist", - "version": "0.01", + "version": "0.02", "description": "Provides assistance while performing a CPR", "icon": "cprassist-icon.png", "tags": "tool,firstaid", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS", "BANGLEJS2"], "readme": "README.md", "allow_emulator": true, "screenshots": [{"url":"bangle1-CPR-assist-screenshot.png"}], diff --git a/apps/cprassist/ChangeLog b/apps/cprassist/ChangeLog index 5560f00bc..529010aa8 100644 --- a/apps/cprassist/ChangeLog +++ b/apps/cprassist/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Ported to Banglejs2 diff --git a/apps/cprassist/cprassist.js b/apps/cprassist/cprassist.js index 862ae54d6..3e34ea171 100644 --- a/apps/cprassist/cprassist.js +++ b/apps/cprassist/cprassist.js @@ -35,23 +35,24 @@ function provideFeedback() { } function drawHeart() { - g.fillCircle(40, 92, 12); - g.fillCircle(60, 92, 12); - g.fillPoly([29, 98, 50, 120, 71, 98]); + var lowestPoint = g.getHeight()*3/5; + g.fillCircle(40, lowestPoint-29, 12); + g.fillCircle(60, lowestPoint-29, 12); + g.fillPoly([29, lowestPoint-22, 50, lowestPoint, 71, lowestPoint-22]); } function updateScreen() { const colors = [0xFFFF, 0x9492]; - g.reset().clearRect(0, 50, 250, 150); + g.reset().clearRect(0, 0, 250, g.getHeight()*5/6); if (counter > 0) { g.setFont("Vector", 40).setFontAlign(0, 0); g.setColor(colors[counter%2]); drawHeart(); - g.drawString(counter + "", g.getWidth()/2, 100); + g.drawString(counter, 120, g.getHeight()*3/5-20); } else { g.setFont("Vector", 20).setFontAlign(0, 0); - g.drawString("RESCUE", g.getWidth()/2, 70); - g.drawString("BREATHS", g.getWidth()/2, 120); + g.drawString("RESCUE", g.getWidth()/2, g.getHeight()/3); + g.drawString("BREATHS", g.getWidth()/2, g.getHeight()*3/5); } } @@ -73,7 +74,7 @@ function tick() { interval = setInterval(tick, 60000/setting('compression_rpm')); g.clear(1).setFont("6x8"); -g.drawString(setting('compression_count') + ' / ' + setting('breath_count'), 30, 200); +g.drawString(setting('compression_count') + ' / ' + setting('breath_count'), 30, g.getHeight()*5/6); Bangle.loadWidgets(); Bangle.drawWidgets(); From d241cebeb04178e08edd993d7208f04166471a04 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Fri, 17 Dec 2021 23:23:13 +0100 Subject: [PATCH 003/489] cpassist: work with different bgcolors --- apps/cprassist/cprassist.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/cprassist/cprassist.js b/apps/cprassist/cprassist.js index 3e34ea171..ee5b06131 100644 --- a/apps/cprassist/cprassist.js +++ b/apps/cprassist/cprassist.js @@ -42,7 +42,7 @@ function drawHeart() { } function updateScreen() { - const colors = [0xFFFF, 0x9492]; + const colors = [0xFFFF-g.getBgColor(), 0x9492]; g.reset().clearRect(0, 0, 250, g.getHeight()*5/6); if (counter > 0) { g.setFont("Vector", 40).setFontAlign(0, 0); From c5303ef657c7b788da37cd952230573406794d7a Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sat, 18 Dec 2021 01:00:22 +0100 Subject: [PATCH 004/489] Don't blank widgets --- apps.json | 2 +- apps/cprassist/cprassist.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 4f966bbdd..64abacef2 100644 --- a/apps.json +++ b/apps.json @@ -2970,7 +2970,7 @@ { "id": "cprassist", "name": "CPR Assist", - "version": "0.02", + "version": "0.02-rc1", "description": "Provides assistance while performing a CPR", "icon": "cprassist-icon.png", "tags": "tool,firstaid", diff --git a/apps/cprassist/cprassist.js b/apps/cprassist/cprassist.js index ee5b06131..128ae7407 100644 --- a/apps/cprassist/cprassist.js +++ b/apps/cprassist/cprassist.js @@ -43,7 +43,7 @@ function drawHeart() { function updateScreen() { const colors = [0xFFFF-g.getBgColor(), 0x9492]; - g.reset().clearRect(0, 0, 250, g.getHeight()*5/6); + g.reset().clearRect(0, 24, g.getWidth(), g.getHeight()*5/6); if (counter > 0) { g.setFont("Vector", 40).setFontAlign(0, 0); g.setColor(colors[counter%2]); From e95a8a0fdb68896682492ad9d337869aef259c1d Mon Sep 17 00:00:00 2001 From: numerist Date: Fri, 17 Dec 2021 22:27:33 -0500 Subject: [PATCH 005/489] Create doztime2.app.js --- apps/doztime2.app.js | 243 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 apps/doztime2.app.js diff --git a/apps/doztime2.app.js b/apps/doztime2.app.js new file mode 100644 index 000000000..f1866c9fc --- /dev/null +++ b/apps/doztime2.app.js @@ -0,0 +1,243 @@ +// Positioning values for graphics buffers +const g_height = 80; // total graphics height +const g_x_off = 0; // position from left was 16, then 8 here +const g_y_off = (184 - g_height)/2; // vertical center for graphics region was 240 +const g_width = 240 - 2 * g_x_off; // total graphics width +const g_height_d = 28; // height of date region was 32 +const g_y_off_d = 0; // y position of date region within graphics region +const spacing = 0; // space between date and time in graphics region +const g_y_off_t = g_y_off_d + g_height_d + spacing; // y position of time within graphics region +const g_height_t = 44; // height of time region was 48 + +// Other vars +const A1 = [30,30,30,30,31,31,31,31,31,31,30,30]; +const B1 = [30,30,30,30,30,31,31,31,31,31,30,30]; +const B2 = [30,30,30,30,31,31,31,31,31,30,30,30]; +const timeColour = "#000000"; +const dateColours = ["#ff0000","#ffa500","#ffff00","#00b800","#0000ff","#ff00ff","#ff0080"]; +const calen10 = {"size":26,"pt0":[18-g_x_off,16],"step":[16,0],"dx":-4.5,"dy":-4.5}; // positioning for usual calendar line ft w 32, 32-g, step 20 +const calen7 = {"size":26,"pt0":[48-g_x_off,16],"step":[16,0],"dx":-4.5,"dy":-4.5}; // positioning for S-day calendar line ft w 32, 62-g, step 20 +const time5 = {"size":42,"pt0":[39-g_x_off,24],"step":[26,0],"dx":-6.5,"dy":-6.5}; // positioning for lull time line ft w 48, 64-g, step 30 +const time6 = {"size":42,"pt0":[26-g_x_off,24],"step":[26,0],"dx":-6.5,"dy":-6.5}; // positioning for twinkling time line ft w 48, 48-g, step 30 +const baseYear = 11584; +const baseDate = Date(2020,11,21); // month values run from 0 to 11 +let accum = new Date(baseDate.getTime()); +let sequence = []; +let timeActiveUntil; +let addTimeDigit = false; +let dateFormat = false; +let lastX = 999999999; +let res = {}; +//var last_time_log = 0; + +var drawtime_timeout; + +// Date and time graphics buffers +var dateColour = "#ffffff"; // override later +var timeColour2 = timeColour; +var g_d = Graphics.createArrayBuffer(g_width,g_height_d,1,{'msb':true}); +var g_t = Graphics.createArrayBuffer(g_width,g_height_t,1,{'msb':true}); +// Set screen mode and function to write graphics buffers +//Bangle.setLCDMode(); +g.clear(); // start with blank screen +g.flip = function() +{ + g.setBgColor(0.5,0.5,0.5); + g.setColor(dateColour); + g.drawImage( + { + width:g_width, + height:g_height_d, + buffer:g_d.buffer + }, g_x_off, g_y_off + g_y_off_d); + g.setColor(timeColour2); + g.drawImage( + { + width:g_width, + height:g_height_t, + buffer:g_t.buffer + }, g_x_off, g_y_off + g_y_off_t); +}; + +setWatch(function(){ modeTime(); }, BTN, {repeat:true} ); //was BTN1 +setWatch(function(){ Bangle.showLauncher(); }, BTN, { repeat: false, edge: "falling" }); //was BTN2 +//setWatch(function(){ modeWeather(); }, BTN3, {repeat:true}); +//setWatch(function(){ toggleTimeDigits(); }, BTN4, {repeat:true}); +//setWatch(function(){ toggleDateFormat(); }, BTN5, {repeat:true}); + +Bangle.on('touch', function(button, xy) { //from Gordon Williams + if (button==1) toggleTimeDigits(); + if (button==2) toggleDateFormat(); +}); + +function buildSequence(targ){ + for(let i=0;i n > dt)-1; + let year = baseYear+parseInt(index/12); + let month = index % 12; + let day = parseInt((dt-sequence[index])/86400000); + let colour = dateColours[day % 6]; + if(day==30){ colour=dateColours[6]; } + return({"year":year,"month":month,"day":day,"colour":colour}); +} +function toggleTimeDigits(){ + addTimeDigit = !addTimeDigit; + modeTime(); +} +function toggleDateFormat(){ + dateFormat = !dateFormat; + modeTime(); +} +function formatDate(res,dateFormat){ + let yyyy = res.year.toString(12); + calenDef = calen10; + if(!dateFormat){ //ordinal format + let mm = ("0"+(res.month+1).toString(12)).substr(-2); + let dd = ("0"+(res.day+1).toString(12)).substr(-2); + if(res.day==30){ + calenDef = calen7; + let m = ((res.month+1).toString(12)).substr(-2); + return(yyyy+"-"+"S"+m); // ordinal format + } + return(yyyy+"-"+mm+"-"+dd); + } + let m = res.month.toString(12); // cardinal format + let w = parseInt(res.day/6); + let d = res.day%6; + //return(yyyy+"-"+res.month+"-"+w+"-"+d); + return(yyyy+"-"+m+"-"+w+"-"+d); +} + +function writeDozTime(text,def){ + let pts = def.pts; + let x=def.pt0[0]; + let y=def.pt0[1]; + g_t.clear(); + g_t.setFont("Vector",def.size); + for(let i in text){ + if(text[i]=="a"){ g_t.setFontAlign(0,0,2); g_t.drawString("2",x+1+def.dx,y+1+def.dy); } //+1s new + else if(text[i]=="b"){ g_t.setFontAlign(0,0,2); g_t.drawString("3",x+1+def.dx,y+1+def.dy); } //+1s new + else{ g_t.setFontAlign(0,0,0); g_t.drawString(text[i],x,y); } + x = x+def.step[0]; + y = y+def.step[1]; + } +} +function writeDozDate(text,def,colour){ + + dateColour = colour; + let pts = def.pts; + let x=def.pt0[0]; + let y=def.pt0[1]; + g_d.clear(); + g_d.setFont("Vector",def.size); + for(let i in text){ + if(text[i]=="a"){ g_d.setFontAlign(0,0,2); g_d.drawString("2",x+1+def.dx,y+1+def.dy); } //+1s new + else if(text[i]=="b"){ g_d.setFontAlign(0,0,2); g_d.drawString("3",x+1+def.dx,y+1+def.dy); } //+1s new + else{ g_d.setFontAlign(0,0,0); g_d.drawString(text[i],x,y); } + x = x+def.step[0]; + y = y+def.step[1]; + } +} + +// Functions for time mode +function drawTime() +{ + let dt = new Date(); + let date = ""; + let timeDef; + let x = 0; + dt.setDate(dt.getDate()); + if(addTimeDigit){ + x = + 10368*dt.getHours()+172.8*dt.getMinutes()+2.88*dt.getSeconds()+0.00288*dt.getMilliseconds(); + let msg = "00000"+Math.floor(x).toString(12); + let time = msg.substr(-5,3)+"."+msg.substr(-2); + let wait = 347*(1-(x%1)); + timeDef = time6; + } else { + x = + 864*dt.getHours()+14.4*dt.getMinutes()+0.24*dt.getSeconds()+0.00024*dt.getMilliseconds(); + let msg = "0000"+Math.floor(x).toString(12); + let time = msg.substr(-4,3)+"."+msg.substr(-1); + let wait = 4167*(1-(x%1)); + timeDef = time5; + } + if(lastX > x){ res = getDate(dt); } // calculate date once at start-up and once when turning over to a new day + date = formatDate(res,dateFormat); + if(dt2200)) { + } else { + // We have a GPS time. Set time + setTime(g.time.getTime()/1000); + } + }); + Bangle.setGPSPower(1,"time"); + setTimeout(fixTime, 10*60*1000); // every 10 minutes +} +// Start time fixing with GPS on next 10 minute interval +setTimeout(fixTime, ((60-(new Date()).getMinutes()) % 10) * 60 * 1000); From b2a4ede70aff4818435333ec5ae84a9cbf2c3139 Mon Sep 17 00:00:00 2001 From: numerist Date: Fri, 17 Dec 2021 22:43:14 -0500 Subject: [PATCH 006/489] Create app2-icon.js --- app2-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 app2-icon.js diff --git a/app2-icon.js b/app2-icon.js new file mode 100644 index 000000000..19e81c45d --- /dev/null +++ b/app2-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("lEowggdkUiCKIADCJcCkUjmYACmUikAlKB4ImDAoQSJkYhBFAQECAQI5HBQU//4AC+YUCHowzBCQfzAYYKCEw8vEgYqD+QoGgQbBHAYADCwIoBCYkiEwhPEBAIoBHgY6BExHyHwQhBFAQ6BkYTHDgcyHgcCHRZlDCYQsBTYg6GDAJQDPoI6LAAIPBCYRiHHQhkDCYRiHHQhkCCYKKBCYzzBA4yMBCYTVEGYITEBYITZHY5PHUAJjITIJjHRZINBIYoTDWZAoFWYbbJFALbHgUyX4oPDXIcjMQITBmZkHFYszCYZkJMQoTCKAQ8IHQZOCHgYoKkQ6DHgYoEcIgmBHQg8CFAIPCCYfzBQQSEFAbrFCQImHFAQUCkczmYECAQISGHoYzBAAQFCCRA9BEwYoDHI4pFAAgRLCooRPABg=")) From 028d23654927aaf24ffbad4b51b32b5bf18eab52 Mon Sep 17 00:00:00 2001 From: numerist Date: Fri, 17 Dec 2021 22:48:54 -0500 Subject: [PATCH 007/489] Update apps.json --- apps.json | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 3e0ab4181..1c8f1fff8 100644 --- a/apps.json +++ b/apps.json @@ -3194,4 +3194,19 @@ {"name":"doztime.img","url":"app-icon.js","evaluate":true} ] } -] \ No newline at end of file +] +}, +{ "id": "doztime2", + "name": "Dozenal Time 2", + "shortName":"Dozenal Time 2", + "icon": "app.png", + "version":"0.01", + "description": "A dozenal Holocene calendar and dozenal diurnal clock for Bangle.js2", + "tags": "clock", + "type":"clock" + "storage": [ + {"name":"doztime2.app.js","url":"app.js"}, + {"name":"doztime2.img","url":"app2-icon.js","evaluate":true} + ] +} +] From 8a898a7054f57f3846d5182fbe374cebaa3987cf Mon Sep 17 00:00:00 2001 From: numerist Date: Fri, 17 Dec 2021 23:25:09 -0500 Subject: [PATCH 008/489] Delete doztime2.app.js --- apps/doztime2.app.js | 243 ------------------------------------------- 1 file changed, 243 deletions(-) delete mode 100644 apps/doztime2.app.js diff --git a/apps/doztime2.app.js b/apps/doztime2.app.js deleted file mode 100644 index f1866c9fc..000000000 --- a/apps/doztime2.app.js +++ /dev/null @@ -1,243 +0,0 @@ -// Positioning values for graphics buffers -const g_height = 80; // total graphics height -const g_x_off = 0; // position from left was 16, then 8 here -const g_y_off = (184 - g_height)/2; // vertical center for graphics region was 240 -const g_width = 240 - 2 * g_x_off; // total graphics width -const g_height_d = 28; // height of date region was 32 -const g_y_off_d = 0; // y position of date region within graphics region -const spacing = 0; // space between date and time in graphics region -const g_y_off_t = g_y_off_d + g_height_d + spacing; // y position of time within graphics region -const g_height_t = 44; // height of time region was 48 - -// Other vars -const A1 = [30,30,30,30,31,31,31,31,31,31,30,30]; -const B1 = [30,30,30,30,30,31,31,31,31,31,30,30]; -const B2 = [30,30,30,30,31,31,31,31,31,30,30,30]; -const timeColour = "#000000"; -const dateColours = ["#ff0000","#ffa500","#ffff00","#00b800","#0000ff","#ff00ff","#ff0080"]; -const calen10 = {"size":26,"pt0":[18-g_x_off,16],"step":[16,0],"dx":-4.5,"dy":-4.5}; // positioning for usual calendar line ft w 32, 32-g, step 20 -const calen7 = {"size":26,"pt0":[48-g_x_off,16],"step":[16,0],"dx":-4.5,"dy":-4.5}; // positioning for S-day calendar line ft w 32, 62-g, step 20 -const time5 = {"size":42,"pt0":[39-g_x_off,24],"step":[26,0],"dx":-6.5,"dy":-6.5}; // positioning for lull time line ft w 48, 64-g, step 30 -const time6 = {"size":42,"pt0":[26-g_x_off,24],"step":[26,0],"dx":-6.5,"dy":-6.5}; // positioning for twinkling time line ft w 48, 48-g, step 30 -const baseYear = 11584; -const baseDate = Date(2020,11,21); // month values run from 0 to 11 -let accum = new Date(baseDate.getTime()); -let sequence = []; -let timeActiveUntil; -let addTimeDigit = false; -let dateFormat = false; -let lastX = 999999999; -let res = {}; -//var last_time_log = 0; - -var drawtime_timeout; - -// Date and time graphics buffers -var dateColour = "#ffffff"; // override later -var timeColour2 = timeColour; -var g_d = Graphics.createArrayBuffer(g_width,g_height_d,1,{'msb':true}); -var g_t = Graphics.createArrayBuffer(g_width,g_height_t,1,{'msb':true}); -// Set screen mode and function to write graphics buffers -//Bangle.setLCDMode(); -g.clear(); // start with blank screen -g.flip = function() -{ - g.setBgColor(0.5,0.5,0.5); - g.setColor(dateColour); - g.drawImage( - { - width:g_width, - height:g_height_d, - buffer:g_d.buffer - }, g_x_off, g_y_off + g_y_off_d); - g.setColor(timeColour2); - g.drawImage( - { - width:g_width, - height:g_height_t, - buffer:g_t.buffer - }, g_x_off, g_y_off + g_y_off_t); -}; - -setWatch(function(){ modeTime(); }, BTN, {repeat:true} ); //was BTN1 -setWatch(function(){ Bangle.showLauncher(); }, BTN, { repeat: false, edge: "falling" }); //was BTN2 -//setWatch(function(){ modeWeather(); }, BTN3, {repeat:true}); -//setWatch(function(){ toggleTimeDigits(); }, BTN4, {repeat:true}); -//setWatch(function(){ toggleDateFormat(); }, BTN5, {repeat:true}); - -Bangle.on('touch', function(button, xy) { //from Gordon Williams - if (button==1) toggleTimeDigits(); - if (button==2) toggleDateFormat(); -}); - -function buildSequence(targ){ - for(let i=0;i n > dt)-1; - let year = baseYear+parseInt(index/12); - let month = index % 12; - let day = parseInt((dt-sequence[index])/86400000); - let colour = dateColours[day % 6]; - if(day==30){ colour=dateColours[6]; } - return({"year":year,"month":month,"day":day,"colour":colour}); -} -function toggleTimeDigits(){ - addTimeDigit = !addTimeDigit; - modeTime(); -} -function toggleDateFormat(){ - dateFormat = !dateFormat; - modeTime(); -} -function formatDate(res,dateFormat){ - let yyyy = res.year.toString(12); - calenDef = calen10; - if(!dateFormat){ //ordinal format - let mm = ("0"+(res.month+1).toString(12)).substr(-2); - let dd = ("0"+(res.day+1).toString(12)).substr(-2); - if(res.day==30){ - calenDef = calen7; - let m = ((res.month+1).toString(12)).substr(-2); - return(yyyy+"-"+"S"+m); // ordinal format - } - return(yyyy+"-"+mm+"-"+dd); - } - let m = res.month.toString(12); // cardinal format - let w = parseInt(res.day/6); - let d = res.day%6; - //return(yyyy+"-"+res.month+"-"+w+"-"+d); - return(yyyy+"-"+m+"-"+w+"-"+d); -} - -function writeDozTime(text,def){ - let pts = def.pts; - let x=def.pt0[0]; - let y=def.pt0[1]; - g_t.clear(); - g_t.setFont("Vector",def.size); - for(let i in text){ - if(text[i]=="a"){ g_t.setFontAlign(0,0,2); g_t.drawString("2",x+1+def.dx,y+1+def.dy); } //+1s new - else if(text[i]=="b"){ g_t.setFontAlign(0,0,2); g_t.drawString("3",x+1+def.dx,y+1+def.dy); } //+1s new - else{ g_t.setFontAlign(0,0,0); g_t.drawString(text[i],x,y); } - x = x+def.step[0]; - y = y+def.step[1]; - } -} -function writeDozDate(text,def,colour){ - - dateColour = colour; - let pts = def.pts; - let x=def.pt0[0]; - let y=def.pt0[1]; - g_d.clear(); - g_d.setFont("Vector",def.size); - for(let i in text){ - if(text[i]=="a"){ g_d.setFontAlign(0,0,2); g_d.drawString("2",x+1+def.dx,y+1+def.dy); } //+1s new - else if(text[i]=="b"){ g_d.setFontAlign(0,0,2); g_d.drawString("3",x+1+def.dx,y+1+def.dy); } //+1s new - else{ g_d.setFontAlign(0,0,0); g_d.drawString(text[i],x,y); } - x = x+def.step[0]; - y = y+def.step[1]; - } -} - -// Functions for time mode -function drawTime() -{ - let dt = new Date(); - let date = ""; - let timeDef; - let x = 0; - dt.setDate(dt.getDate()); - if(addTimeDigit){ - x = - 10368*dt.getHours()+172.8*dt.getMinutes()+2.88*dt.getSeconds()+0.00288*dt.getMilliseconds(); - let msg = "00000"+Math.floor(x).toString(12); - let time = msg.substr(-5,3)+"."+msg.substr(-2); - let wait = 347*(1-(x%1)); - timeDef = time6; - } else { - x = - 864*dt.getHours()+14.4*dt.getMinutes()+0.24*dt.getSeconds()+0.00024*dt.getMilliseconds(); - let msg = "0000"+Math.floor(x).toString(12); - let time = msg.substr(-4,3)+"."+msg.substr(-1); - let wait = 4167*(1-(x%1)); - timeDef = time5; - } - if(lastX > x){ res = getDate(dt); } // calculate date once at start-up and once when turning over to a new day - date = formatDate(res,dateFormat); - if(dt2200)) { - } else { - // We have a GPS time. Set time - setTime(g.time.getTime()/1000); - } - }); - Bangle.setGPSPower(1,"time"); - setTimeout(fixTime, 10*60*1000); // every 10 minutes -} -// Start time fixing with GPS on next 10 minute interval -setTimeout(fixTime, ((60-(new Date()).getMinutes()) % 10) * 60 * 1000); From d689849f256decbfde076d74f7c51988b11a8d60 Mon Sep 17 00:00:00 2001 From: numerist Date: Fri, 17 Dec 2021 23:26:17 -0500 Subject: [PATCH 009/489] Update apps.json --- apps.json | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/apps.json b/apps.json index 1c8f1fff8..df7c28af6 100644 --- a/apps.json +++ b/apps.json @@ -3195,18 +3195,3 @@ ] } ] -}, -{ "id": "doztime2", - "name": "Dozenal Time 2", - "shortName":"Dozenal Time 2", - "icon": "app.png", - "version":"0.01", - "description": "A dozenal Holocene calendar and dozenal diurnal clock for Bangle.js2", - "tags": "clock", - "type":"clock" - "storage": [ - {"name":"doztime2.app.js","url":"app.js"}, - {"name":"doztime2.img","url":"app2-icon.js","evaluate":true} - ] -} -] From 87f0ffcd96ee6c71432523b5d4ec3440fa757d96 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sat, 18 Dec 2021 00:08:04 +0100 Subject: [PATCH 010/489] widhwt: Ported to Bangle.js2 Tactically all that was needed was to state that it works with Bangle.js2. However the swipe gesture interfered with using the menu on Bangle.js2. So it has been deactivated and we recommend using Pattern Launcher instead. --- apps.json | 7 ++++--- apps/widhwt/ChangeLog | 1 + apps/widhwt/app.js | 11 +++++++++++ apps/widhwt/widget.js | 14 ++++++++++---- 4 files changed, 26 insertions(+), 7 deletions(-) create mode 100644 apps/widhwt/app.js diff --git a/apps.json b/apps.json index 8b4e86d52..f69889d50 100644 --- a/apps.json +++ b/apps.json @@ -1889,12 +1889,13 @@ { "id": "widhwt", "name": "Hand Wash Timer", - "version": "0.01", - "description": "Swipe your wrist over the watch face to start your personal Bangle.js hand wash timer for 35 sec. Start washing after the short buzz and stop after the long buzz.", + "version": "0.02-rc6", + "description": "On Bangle.js 1 swipe your wrist over the watch face to start your personal Bangle.js 1 hand wash timer. On Bangle.js2 the Pattern Launcher is recommended to start the timer. Start washing after the short buzz and stop after the long buzz 35sec. later.", "icon": "widget.png", "type": "widget", "tags": "widget,tool", - "supports": ["BANGLEJS"], + "allow_emulator": true, + "supports": ["BANGLEJS", "BANGLEJS2"], "storage": [ {"name":"widhwt.wid.js","url":"widget.js"} ] diff --git a/apps/widhwt/ChangeLog b/apps/widhwt/ChangeLog index 4c21f3ace..76c4fcec9 100644 --- a/apps/widhwt/ChangeLog +++ b/apps/widhwt/ChangeLog @@ -1 +1,2 @@ 0.01: New Widget! +0.02: Ported to Bangle.js2 diff --git a/apps/widhwt/app.js b/apps/widhwt/app.js new file mode 100644 index 000000000..68555d21d --- /dev/null +++ b/apps/widhwt/app.js @@ -0,0 +1,11 @@ +// Replace the "Loading..." box +// with our own message +g.clearRect(38, 68, 138, 108); +g.drawRect(38, 68, 138, 108); +g.setFontVector(13).drawString("Wash...", 60, 82); + +Bangle.buzz(); +setTimeout(() => { + Bangle.buzz(1E3, 1); + setTimeout(() => load(), 2E3); +}, 35E3); diff --git a/apps/widhwt/widget.js b/apps/widhwt/widget.js index d178a5b5d..5e1f95a41 100644 --- a/apps/widhwt/widget.js +++ b/apps/widhwt/widget.js @@ -6,9 +6,7 @@ g.reset().setColor(color).drawImage(require("heatshrink").decompress(atob("jEYwIKHgwCBhwCBh4CEggPCkACBmAXDBwVZ+EB+F4gEsjl8EgMP+EChk/gEMh+ehkA+YIBxwxBnF/4HggH/wEAj0AA==")), this.x + 1, 0); } - WIDGETS["widhwt"] = { area: "tr", width: 26, draw: draw }; - - Bangle.on('swipe', function() { + function startTimer() { color = 0x41f; Bangle.buzz(); Bangle.drawWidgets(); @@ -17,6 +15,14 @@ Bangle.buzz(1E3, 1); Bangle.drawWidgets(); }, 35E3); + } - }); + if (process.env.HWVERSION == 1) { + WIDGETS["widhwt"] = { + area: "tr", + width: 26, + draw: draw, + }; + Bangle.on('swipe', startTimer); + } })(); From d51c6679fe342ccb6058184b345ebc4e4816a98c Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sat, 18 Dec 2021 14:57:19 +0100 Subject: [PATCH 011/489] Bumped hwt version number --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index f69889d50..b4acc8f0c 100644 --- a/apps.json +++ b/apps.json @@ -1889,7 +1889,7 @@ { "id": "widhwt", "name": "Hand Wash Timer", - "version": "0.02-rc6", + "version": "0.02-rc7", "description": "On Bangle.js 1 swipe your wrist over the watch face to start your personal Bangle.js 1 hand wash timer. On Bangle.js2 the Pattern Launcher is recommended to start the timer. Start washing after the short buzz and stop after the long buzz 35sec. later.", "icon": "widget.png", "type": "widget", From c5536ee49a6508da2e7a1fac1298bdf9ed00ddba Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sat, 18 Dec 2021 17:37:04 +0100 Subject: [PATCH 012/489] hwt: Center "Wash ..." text properly --- apps.json | 2 +- apps/widhwt/app.js | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index b4acc8f0c..092584ecf 100644 --- a/apps.json +++ b/apps.json @@ -1889,7 +1889,7 @@ { "id": "widhwt", "name": "Hand Wash Timer", - "version": "0.02-rc7", + "version": "0.02-rc8", "description": "On Bangle.js 1 swipe your wrist over the watch face to start your personal Bangle.js 1 hand wash timer. On Bangle.js2 the Pattern Launcher is recommended to start the timer. Start washing after the short buzz and stop after the long buzz 35sec. later.", "icon": "widget.png", "type": "widget", diff --git a/apps/widhwt/app.js b/apps/widhwt/app.js index 68555d21d..2aaf7f08a 100644 --- a/apps/widhwt/app.js +++ b/apps/widhwt/app.js @@ -2,7 +2,9 @@ // with our own message g.clearRect(38, 68, 138, 108); g.drawRect(38, 68, 138, 108); -g.setFontVector(13).drawString("Wash...", 60, 82); +g.setFontVector(13).setFontAlign(0, 0, 0).drawString("Wash...", + g.getWidth()/2, + g.getHeight()/2); Bangle.buzz(); setTimeout(() => { From 51422c44c0fc89874b96fc893b3d06014de0f771 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sat, 18 Dec 2021 18:46:16 +0100 Subject: [PATCH 013/489] hwt: Reduce line lenght --- apps.json | 2 +- apps/widhwt/app.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps.json b/apps.json index 092584ecf..cb991dbed 100644 --- a/apps.json +++ b/apps.json @@ -1889,7 +1889,7 @@ { "id": "widhwt", "name": "Hand Wash Timer", - "version": "0.02-rc8", + "version": "0.02-rc9", "description": "On Bangle.js 1 swipe your wrist over the watch face to start your personal Bangle.js 1 hand wash timer. On Bangle.js2 the Pattern Launcher is recommended to start the timer. Start washing after the short buzz and stop after the long buzz 35sec. later.", "icon": "widget.png", "type": "widget", diff --git a/apps/widhwt/app.js b/apps/widhwt/app.js index 2aaf7f08a..f18e78643 100644 --- a/apps/widhwt/app.js +++ b/apps/widhwt/app.js @@ -2,9 +2,9 @@ // with our own message g.clearRect(38, 68, 138, 108); g.drawRect(38, 68, 138, 108); -g.setFontVector(13).setFontAlign(0, 0, 0).drawString("Wash...", - g.getWidth()/2, - g.getHeight()/2); +g.setFontVector(13); +g.setFontAlign(0, 0, 0); +g.drawString("Wash...", g.getWidth()/2, g.getHeight()/2); Bangle.buzz(); setTimeout(() => { From 505ed38753a1a6611b9f5da7f4aa32789f0f69a0 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sat, 18 Dec 2021 22:14:26 +0100 Subject: [PATCH 014/489] hwt: Add app.js to apps.json --- apps.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index cb991dbed..d572a9aad 100644 --- a/apps.json +++ b/apps.json @@ -1889,7 +1889,7 @@ { "id": "widhwt", "name": "Hand Wash Timer", - "version": "0.02-rc9", + "version": "0.02-rc10", "description": "On Bangle.js 1 swipe your wrist over the watch face to start your personal Bangle.js 1 hand wash timer. On Bangle.js2 the Pattern Launcher is recommended to start the timer. Start washing after the short buzz and stop after the long buzz 35sec. later.", "icon": "widget.png", "type": "widget", @@ -1897,6 +1897,7 @@ "allow_emulator": true, "supports": ["BANGLEJS", "BANGLEJS2"], "storage": [ + {"name":"widhwt.app.js","url":"app.js"}, {"name":"widhwt.wid.js","url":"widget.js"} ] }, From 514bd0e92c1de30b999390beb6dc615e9fcad047 Mon Sep 17 00:00:00 2001 From: numerist Date: Sat, 18 Dec 2021 18:59:52 -0500 Subject: [PATCH 015/489] Delete app2-icon.js --- app2-icon.js | 1 - 1 file changed, 1 deletion(-) delete mode 100644 app2-icon.js diff --git a/app2-icon.js b/app2-icon.js deleted file mode 100644 index 19e81c45d..000000000 --- a/app2-icon.js +++ /dev/null @@ -1 +0,0 @@ -require("heatshrink").decompress(atob("lEowggdkUiCKIADCJcCkUjmYACmUikAlKB4ImDAoQSJkYhBFAQECAQI5HBQU//4AC+YUCHowzBCQfzAYYKCEw8vEgYqD+QoGgQbBHAYADCwIoBCYkiEwhPEBAIoBHgY6BExHyHwQhBFAQ6BkYTHDgcyHgcCHRZlDCYQsBTYg6GDAJQDPoI6LAAIPBCYRiHHQhkDCYRiHHQhkCCYKKBCYzzBA4yMBCYTVEGYITEBYITZHY5PHUAJjITIJjHRZINBIYoTDWZAoFWYbbJFALbHgUyX4oPDXIcjMQITBmZkHFYszCYZkJMQoTCKAQ8IHQZOCHgYoKkQ6DHgYoEcIgmBHQg8CFAIPCCYfzBQQSEFAbrFCQImHFAQUCkczmYECAQISGHoYzBAAQFCCRA9BEwYoDHI4pFAAgRLCooRPABg=")) From 6e720393f657e9d5d29de4925381ddb5c1155839 Mon Sep 17 00:00:00 2001 From: numerist Date: Sat, 18 Dec 2021 19:02:15 -0500 Subject: [PATCH 016/489] Create doztime2.app.js --- apps/doztime2.app.js | 244 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 apps/doztime2.app.js diff --git a/apps/doztime2.app.js b/apps/doztime2.app.js new file mode 100644 index 000000000..855ec9aaf --- /dev/null +++ b/apps/doztime2.app.js @@ -0,0 +1,244 @@ +// Positioning values for graphics buffers +const g_height = 80; // total graphics height +const g_x_off = 0; // position from left was 16, then 8 here +const g_y_off = (184 - g_height)/2; // vertical center for graphics region was 240 +const g_width = 240 - 2 * g_x_off; // total graphics width +const g_height_d = 28; // height of date region was 32 +const g_y_off_d = 0; // y position of date region within graphics region +const spacing = 0; // space between date and time in graphics region +const g_y_off_t = g_y_off_d + g_height_d + spacing; // y position of time within graphics region +const g_height_t = 44; // height of time region was 48 + +// Other vars +const A1 = [30,30,30,30,31,31,31,31,31,31,30,30]; +const B1 = [30,30,30,30,30,31,31,31,31,31,30,30]; +const B2 = [30,30,30,30,31,31,31,31,31,30,30,30]; +const timeColour = "#ffffff"; +const dateColours = ["#ff0000","#ffa500","#ffff00","#00b800","#8383ff","#ff00ff","#ff0080"]; //blue was 0000ff +const calen10 = {"size":26,"pt0":[18-g_x_off,16],"step":[16,0],"dx":-4.5,"dy":-4.5}; // positioning for usual calendar line ft w 32, 32-g, step 20 +const calen7 = {"size":26,"pt0":[48-g_x_off,16],"step":[16,0],"dx":-4.5,"dy":-4.5}; // positioning for S-day calendar line ft w 32, 62-g, step 20 +const time5 = {"size":42,"pt0":[39-g_x_off,24],"step":[26,0],"dx":-6.5,"dy":-6.5}; // positioning for lull time line ft w 48, 64-g, step 30 +const time6 = {"size":42,"pt0":[26-g_x_off,24],"step":[26,0],"dx":-6.5,"dy":-6.5}; // positioning for twinkling time line ft w 48, 48-g, step 30 +const baseYear = 11584; +const baseDate = Date(2020,11,21); // month values run from 0 to 11 +let accum = new Date(baseDate.getTime()); +let sequence = []; +let timeActiveUntil; +let addTimeDigit = false; +let dateFormat = false; +let lastX = 999999999; +let res = {}; +//var last_time_log = 0; + +var drawtime_timeout; + +// Date and time graphics buffers +var dateColour = "#ffffff"; // override later +var timeColour2 = timeColour; +var g_d = Graphics.createArrayBuffer(g_width,g_height_d,1,{'msb':true}); +var g_t = Graphics.createArrayBuffer(g_width,g_height_t,1,{'msb':true}); +// Set screen mode and function to write graphics buffers +//Bangle.setLCDMode(); +g.clear(); // start with blank screen +g.flip = function() +{ + g.setBgColor(0,0,0); + g.setColor(dateColour); + g.drawImage( + { + width:g_width, + height:g_height_d, + buffer:g_d.buffer + }, g_x_off, g_y_off + g_y_off_d); + g.setColor(timeColour2); + g.drawImage( + { + width:g_width, + height:g_height_t, + buffer:g_t.buffer + }, g_x_off, g_y_off + g_y_off_t); +}; + +setWatch(function(){ modeTime(); }, BTN, {repeat:true} ); //was BTN1 +setWatch(function(){ Bangle.showLauncher(); }, BTN, { repeat: false, edge: "falling" }); //was BTN2 +//setWatch(function(){ modeWeather(); }, BTN3, {repeat:true}); +//setWatch(function(){ toggleTimeDigits(); }, BTN4, {repeat:true}); +//setWatch(function(){ toggleDateFormat(); }, BTN5, {repeat:true}); + +Bangle.on('touch', function(button, xy) { //from Gordon Williams + if (button==1) toggleTimeDigits(); + if (button==2) toggleDateFormat(); +}); + +function buildSequence(targ){ + for(let i=0;i n > dt)-1; + let year = baseYear+parseInt(index/12); + let month = index % 12; + let day = parseInt((dt-sequence[index])/86400000); + let colour = dateColours[day % 6]; + if(day==30){ colour=dateColours[6]; } + return({"year":year,"month":month,"day":day,"colour":colour}); +} +function toggleTimeDigits(){ + addTimeDigit = !addTimeDigit; + modeTime(); +} +function toggleDateFormat(){ + dateFormat = !dateFormat; + modeTime(); +} +function formatDate(res,dateFormat){ + let yyyy = res.year.toString(12); + calenDef = calen10; + if(!dateFormat){ //ordinal format + let mm = ("0"+(res.month+1).toString(12)).substr(-2); + let dd = ("0"+(res.day+1).toString(12)).substr(-2); + if(res.day==30){ + calenDef = calen7; + let m = ((res.month+1).toString(12)).substr(-2); + return(yyyy+"-"+"S"+m); // ordinal format + } + return(yyyy+"-"+mm+"-"+dd); + } + let m = res.month.toString(12); // cardinal format + let w = parseInt(res.day/6); + let d = res.day%6; + //return(yyyy+"-"+res.month+"-"+w+"-"+d); + return(yyyy+"-"+m+"-"+w+"-"+d); +} + +function writeDozTime(text,def){ + let pts = def.pts; + let x=def.pt0[0]; + let y=def.pt0[1]; + g_t.clear(); + g_t.setFont("Vector",def.size); + for(let i in text){ + if(text[i]=="a"){ g_t.setFontAlign(0,0,2); g_t.drawString("2",x+1+def.dx,y+1+def.dy); } //+1s are new + else if(text[i]=="b"){ g_t.setFontAlign(0,0,2); g_t.drawString("3",x+1+def.dx,y+1+def.dy); } //+1s are new + else{ g_t.setFontAlign(0,0,0); g_t.drawString(text[i],x,y); } + x = x+def.step[0]; + y = y+def.step[1]; + } +} +function writeDozDate(text,def,colour){ + + dateColour = colour; + let pts = def.pts; + let x=def.pt0[0]; + let y=def.pt0[1]; + g_d.clear(); + g_d.setFont("Vector",def.size); + for(let i in text){ + if(text[i]=="a"){ g_d.setFontAlign(0,0,2); g_d.drawString("2",x+1+def.dx,y+1+def.dy); } //+1s new + else if(text[i]=="b"){ g_d.setFontAlign(0,0,2); g_d.drawString("3",x+1+def.dx,y+1+def.dy); } //+1s new + else{ g_d.setFontAlign(0,0,0); g_d.drawString(text[i],x,y); } + x = x+def.step[0]; + y = y+def.step[1]; + } +} + +// Functions for time mode +function drawTime() +{ + let dt = new Date(); + let date = ""; + let timeDef; + let x = 0; + dt.setDate(dt.getDate()); + if(addTimeDigit){ + x = + 10368*dt.getHours()+172.8*dt.getMinutes()+2.88*dt.getSeconds()+0.00288*dt.getMilliseconds(); + let msg = "00000"+Math.floor(x).toString(12); + let time = msg.substr(-5,3)+"."+msg.substr(-2); + let wait = 347*(1-(x%1)); + timeDef = time6; + } else { + x = + 864*dt.getHours()+14.4*dt.getMinutes()+0.24*dt.getSeconds()+0.00024*dt.getMilliseconds(); + let msg = "0000"+Math.floor(x).toString(12); + let time = msg.substr(-4,3)+"."+msg.substr(-1); + let wait = 4167*(1-(x%1)); + timeDef = time5; + } + if(lastX > x){ res = getDate(dt); } // calculate date once at start-up and once when turning over to a new day + date = formatDate(res,dateFormat); + if(dt2200)) { + } else { + // We have a GPS time. Set time + setTime(g.time.getTime()/1000); + } + }); + Bangle.setGPSPower(1,"time"); + setTimeout(fixTime, 10*60*1000); // every 10 minutes +} +// Start time fixing with GPS on next 10 minute interval +setTimeout(fixTime, ((60-(new Date()).getMinutes()) % 10) * 60 * 1000); From eba6ef6524bec5db94d077882a1bb3666f2dd169 Mon Sep 17 00:00:00 2001 From: numerist Date: Sat, 18 Dec 2021 19:05:18 -0500 Subject: [PATCH 017/489] Create app.js --- apps/doztime2/app.js | 244 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 apps/doztime2/app.js diff --git a/apps/doztime2/app.js b/apps/doztime2/app.js new file mode 100644 index 000000000..855ec9aaf --- /dev/null +++ b/apps/doztime2/app.js @@ -0,0 +1,244 @@ +// Positioning values for graphics buffers +const g_height = 80; // total graphics height +const g_x_off = 0; // position from left was 16, then 8 here +const g_y_off = (184 - g_height)/2; // vertical center for graphics region was 240 +const g_width = 240 - 2 * g_x_off; // total graphics width +const g_height_d = 28; // height of date region was 32 +const g_y_off_d = 0; // y position of date region within graphics region +const spacing = 0; // space between date and time in graphics region +const g_y_off_t = g_y_off_d + g_height_d + spacing; // y position of time within graphics region +const g_height_t = 44; // height of time region was 48 + +// Other vars +const A1 = [30,30,30,30,31,31,31,31,31,31,30,30]; +const B1 = [30,30,30,30,30,31,31,31,31,31,30,30]; +const B2 = [30,30,30,30,31,31,31,31,31,30,30,30]; +const timeColour = "#ffffff"; +const dateColours = ["#ff0000","#ffa500","#ffff00","#00b800","#8383ff","#ff00ff","#ff0080"]; //blue was 0000ff +const calen10 = {"size":26,"pt0":[18-g_x_off,16],"step":[16,0],"dx":-4.5,"dy":-4.5}; // positioning for usual calendar line ft w 32, 32-g, step 20 +const calen7 = {"size":26,"pt0":[48-g_x_off,16],"step":[16,0],"dx":-4.5,"dy":-4.5}; // positioning for S-day calendar line ft w 32, 62-g, step 20 +const time5 = {"size":42,"pt0":[39-g_x_off,24],"step":[26,0],"dx":-6.5,"dy":-6.5}; // positioning for lull time line ft w 48, 64-g, step 30 +const time6 = {"size":42,"pt0":[26-g_x_off,24],"step":[26,0],"dx":-6.5,"dy":-6.5}; // positioning for twinkling time line ft w 48, 48-g, step 30 +const baseYear = 11584; +const baseDate = Date(2020,11,21); // month values run from 0 to 11 +let accum = new Date(baseDate.getTime()); +let sequence = []; +let timeActiveUntil; +let addTimeDigit = false; +let dateFormat = false; +let lastX = 999999999; +let res = {}; +//var last_time_log = 0; + +var drawtime_timeout; + +// Date and time graphics buffers +var dateColour = "#ffffff"; // override later +var timeColour2 = timeColour; +var g_d = Graphics.createArrayBuffer(g_width,g_height_d,1,{'msb':true}); +var g_t = Graphics.createArrayBuffer(g_width,g_height_t,1,{'msb':true}); +// Set screen mode and function to write graphics buffers +//Bangle.setLCDMode(); +g.clear(); // start with blank screen +g.flip = function() +{ + g.setBgColor(0,0,0); + g.setColor(dateColour); + g.drawImage( + { + width:g_width, + height:g_height_d, + buffer:g_d.buffer + }, g_x_off, g_y_off + g_y_off_d); + g.setColor(timeColour2); + g.drawImage( + { + width:g_width, + height:g_height_t, + buffer:g_t.buffer + }, g_x_off, g_y_off + g_y_off_t); +}; + +setWatch(function(){ modeTime(); }, BTN, {repeat:true} ); //was BTN1 +setWatch(function(){ Bangle.showLauncher(); }, BTN, { repeat: false, edge: "falling" }); //was BTN2 +//setWatch(function(){ modeWeather(); }, BTN3, {repeat:true}); +//setWatch(function(){ toggleTimeDigits(); }, BTN4, {repeat:true}); +//setWatch(function(){ toggleDateFormat(); }, BTN5, {repeat:true}); + +Bangle.on('touch', function(button, xy) { //from Gordon Williams + if (button==1) toggleTimeDigits(); + if (button==2) toggleDateFormat(); +}); + +function buildSequence(targ){ + for(let i=0;i n > dt)-1; + let year = baseYear+parseInt(index/12); + let month = index % 12; + let day = parseInt((dt-sequence[index])/86400000); + let colour = dateColours[day % 6]; + if(day==30){ colour=dateColours[6]; } + return({"year":year,"month":month,"day":day,"colour":colour}); +} +function toggleTimeDigits(){ + addTimeDigit = !addTimeDigit; + modeTime(); +} +function toggleDateFormat(){ + dateFormat = !dateFormat; + modeTime(); +} +function formatDate(res,dateFormat){ + let yyyy = res.year.toString(12); + calenDef = calen10; + if(!dateFormat){ //ordinal format + let mm = ("0"+(res.month+1).toString(12)).substr(-2); + let dd = ("0"+(res.day+1).toString(12)).substr(-2); + if(res.day==30){ + calenDef = calen7; + let m = ((res.month+1).toString(12)).substr(-2); + return(yyyy+"-"+"S"+m); // ordinal format + } + return(yyyy+"-"+mm+"-"+dd); + } + let m = res.month.toString(12); // cardinal format + let w = parseInt(res.day/6); + let d = res.day%6; + //return(yyyy+"-"+res.month+"-"+w+"-"+d); + return(yyyy+"-"+m+"-"+w+"-"+d); +} + +function writeDozTime(text,def){ + let pts = def.pts; + let x=def.pt0[0]; + let y=def.pt0[1]; + g_t.clear(); + g_t.setFont("Vector",def.size); + for(let i in text){ + if(text[i]=="a"){ g_t.setFontAlign(0,0,2); g_t.drawString("2",x+1+def.dx,y+1+def.dy); } //+1s are new + else if(text[i]=="b"){ g_t.setFontAlign(0,0,2); g_t.drawString("3",x+1+def.dx,y+1+def.dy); } //+1s are new + else{ g_t.setFontAlign(0,0,0); g_t.drawString(text[i],x,y); } + x = x+def.step[0]; + y = y+def.step[1]; + } +} +function writeDozDate(text,def,colour){ + + dateColour = colour; + let pts = def.pts; + let x=def.pt0[0]; + let y=def.pt0[1]; + g_d.clear(); + g_d.setFont("Vector",def.size); + for(let i in text){ + if(text[i]=="a"){ g_d.setFontAlign(0,0,2); g_d.drawString("2",x+1+def.dx,y+1+def.dy); } //+1s new + else if(text[i]=="b"){ g_d.setFontAlign(0,0,2); g_d.drawString("3",x+1+def.dx,y+1+def.dy); } //+1s new + else{ g_d.setFontAlign(0,0,0); g_d.drawString(text[i],x,y); } + x = x+def.step[0]; + y = y+def.step[1]; + } +} + +// Functions for time mode +function drawTime() +{ + let dt = new Date(); + let date = ""; + let timeDef; + let x = 0; + dt.setDate(dt.getDate()); + if(addTimeDigit){ + x = + 10368*dt.getHours()+172.8*dt.getMinutes()+2.88*dt.getSeconds()+0.00288*dt.getMilliseconds(); + let msg = "00000"+Math.floor(x).toString(12); + let time = msg.substr(-5,3)+"."+msg.substr(-2); + let wait = 347*(1-(x%1)); + timeDef = time6; + } else { + x = + 864*dt.getHours()+14.4*dt.getMinutes()+0.24*dt.getSeconds()+0.00024*dt.getMilliseconds(); + let msg = "0000"+Math.floor(x).toString(12); + let time = msg.substr(-4,3)+"."+msg.substr(-1); + let wait = 4167*(1-(x%1)); + timeDef = time5; + } + if(lastX > x){ res = getDate(dt); } // calculate date once at start-up and once when turning over to a new day + date = formatDate(res,dateFormat); + if(dt2200)) { + } else { + // We have a GPS time. Set time + setTime(g.time.getTime()/1000); + } + }); + Bangle.setGPSPower(1,"time"); + setTimeout(fixTime, 10*60*1000); // every 10 minutes +} +// Start time fixing with GPS on next 10 minute interval +setTimeout(fixTime, ((60-(new Date()).getMinutes()) % 10) * 60 * 1000); From 3e7ac2a2491b80daaaf86f24664fb2f0da45b5c7 Mon Sep 17 00:00:00 2001 From: numerist Date: Sat, 18 Dec 2021 19:07:58 -0500 Subject: [PATCH 018/489] Add files via upload --- apps/doztime2/app.png | Bin 0 -> 2500 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/doztime2/app.png diff --git a/apps/doztime2/app.png b/apps/doztime2/app.png new file mode 100644 index 0000000000000000000000000000000000000000..363537a58cf0ba55de061d555c4501f34d53279e GIT binary patch literal 2500 zcmV;#2|MxUxKLUMAqh<|nF-|;LRvx^$2fKdl30=* zTf&MZTh`URdw2W65B!j0C#D_#-|pSB=l<^Qo;|w<_>POrrE`5lbD2r36_OB@93%w5 zHPSQyK_ZYuha%`FJDyo}=Kls*_vo&2L6yx^!X_@nLVyTWQw+P!CdpKxfB>_YrRQ=y zryD9D2q99t5WESDZQK3ay6*o8V0}Y#858_TB4IO?sVMRJRBy2tg@uKXBq?tn&N))4 zG?K|A;=Kve;ubg;FIfzYd!Jw1^Q{5aJ-+7w0552&s#H`|sD7UhTyP|lN%Z%ppl37C z^&E000|01>3{A7a;V6LHQv{F43yBcK;|X*|It{~MhJf|R?x$~kaZZ4@HNNeT4B7-D z)`!Dk5)1|iV+_$q4Dm!9mStfeV0;NyJ%6R>U260jdr2CI|g@w z4I5U@$MUKYcnfV~eKNWM04T7jWAFOXIu0H0#r6+QB9+M@5C|X?3SwYj5MQ(%H!O=C zA+oV*XXE<*Sp(kI__l*G`F%x}YinvRQzc14dwT~=J&U_;x&*72g(1_4>n@`kIQmr= z0HF4wzywGDFd4@?hdS}vdtXA;?5M1&1hXt0YiZ3HX6`>~CUZl+k<7cgC4)9mN^5Is zFH<=eXlZGIOBLAi%WH7kig{DuX7ksIETQh2`PlM{Yv52gT8 zA9kCHit=LIczFO{oJ!)v$u5+Ym%-z4(|EkMs`9#@b$5L9*Uu*m*7%3|hUPLN$P1xx zn7EuSoai_Kw?n~WcU}&=CZA)>hE-rwr@#TgKMx+o!Oz>^un(_ShbH6kyDx{=rK0_K zJDg4@f}xNEB5kQ_*i|wuAQSvaRa2BuFhC;F7;@PmJbBNRaM)&sn@(RRQ`ouh09Idr zHG-wz8+&ipWc+616)^NHB9R!vp&(RMQ2_cxUckCXca;+fn=2|RRK^&(yJNWPrb|%b zaa=H*5CU7b?}M+{jn&s*HKo1O>%g5qycpfxT`&v-72&W(K<=w=XfB%qD5$cT%2fD$ zK13tKTgmEW;R}WXfPEhw##fOu*tFqCkm;1=4ggratO9PQhFGi%e!mY?rosf4sa$Zx6LD-`O$97>CaBR5}eoleI(PT`fe_G2(J1dqEAH(z(fjD5!Y zFDouUHanauZJH(-IX(0Zpb##Z$`k-hX2EGwX3VXV_3F<3=uZy<0CG8V#;Kj^Uk0-* z0DvsZ6d*2Onp`XeoUmysve_*D-O_PR`^o+@Ivd+78Dkb827r+%CJ?c#u5$pe*=*?P8ya&mTU9Td zhd=!KJ^;XucR$8UuQvk#uBy58oRFjH>C3=AlB@Nc&WRwAF+fg8yOA?g&N&>80<@k^ z&KfMA>TkIg0A>X_s$-|m!tN-5WpNleQza7b7z0!U{e;0nI-Q2wQ-t>R9`vPk6whHV zJRiuul#bJ9QmCvfLpqfLAYdBOL11JJ?s#U^8A*~(^z|j-@pwTg#i6#|3x*rj`kSxC z4a=9{RbPb9xp=8F(rL)D zjPgJ^UfcgAdXhtPhMZ2_eHr}iy)O|61fePlIy)nV;Nr#cm--1CwZ+hA7|e*qx$x<2j6*iO=7%l z-Yiqsu=jOYq3f0|sZ}}WIQ~T&+)f2gY`PMq-uzd9+2-!Z_mScv+t;3q0`T1;p0RVp7_?BBRwOOX}(nX7^RF}(%&dwOR zy1L+TY1r_C1z28Hg5shXN*^g5pC0eUn;)DUj@Cc`;cyTG>5yK5^U{PtidB!xpk7>0pptP5W!;;<}^`DI0@p65YnaRHq6k>XL-L{DD^$4;Nc z=`$%%D#7RTBN!Tv)@US(Xe`DB$KTVMnAJ&YUBjOHK%_0IDytRY3f1rT zfeV3TGKo|wh3rrU*{lwe4WH)}nZj Date: Sat, 18 Dec 2021 19:12:14 -0500 Subject: [PATCH 019/489] Create app-icon.js --- apps/doztime2/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/doztime2/app-icon.js diff --git a/apps/doztime2/app-icon.js b/apps/doztime2/app-icon.js new file mode 100644 index 000000000..6154ac923 --- /dev/null +++ b/apps/doztime2/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("lEoxH+AHNYAAQjirwAEFbYkExIAGFTIkEJYoFDFQhMTDIODEQeI1gACxAJDwYpBKSAmDCoNe1nXABGsBwQoQHgRMBJQIhGFoxUBCoYoLGoImDJJBVIFAZRLJwQmJAA+CFwQoCKBSIDEyGsq+zKIijCEzfXq6tFFBR1CrDCGABOBwLMGXQInIOqmtZZGJE4p2CrDhIOpARI1hGCFAgnBA4J1XAAYfDOyzrFPBzQCYp2zOpLJDEASeFryeM1ldq9dB5ggCKATGF1gqJEwInKC4TIGE9R3PFIIQLO4zHSXQIoLY4xQBAwNeE5woMDoKYBE4gIBrAnPFBYfDE4rIDFCOzTwzGFPCwfCOxxQDwdYZJ5XJrGDJwx4DKCYAE2ZOCE44obExZ5EFComNE4KEBFBWsYQ50CC4IbBE5JQDFATMGE4+IJoTEIKJBhDrxJHFoYOCCQQmNFAo8CAoOIJwIABJQIJCwYmSPYgpBe4QABEQQACBYYlSKQgqEAAouDEyoqIKYokZFZIjgADI")) From a82c24c969495a349b251b22d923d857e664a14b Mon Sep 17 00:00:00 2001 From: numerist Date: Sat, 18 Dec 2021 19:19:47 -0500 Subject: [PATCH 020/489] Update apps.json --- apps.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/apps.json b/apps.json index df7c28af6..16b82ba38 100644 --- a/apps.json +++ b/apps.json @@ -3195,3 +3195,20 @@ ] } ] +}, +{ "id":"doztime2", + "name":"Dozenal Time 2", + "shortName":"Dozenal 2", + "icon":"app.png", + "version":"0.01", + "description":"A dozenal Holocene calendar and dozenal diurnal clock for Bangle.js 2", + "tags":"clock", + "type":"clock", + "allow_emulator":true, + "readme": "README.md", + "storage": [ + {"name":"doztime2.app.js","url":"app.js"}, + {"name":"doztime2.img","url":"app-icon.js","evaluate":true} + ] +} +] From 2d5e2dd180fbfcf924e260d148a456ad7187079d Mon Sep 17 00:00:00 2001 From: numerist Date: Sat, 18 Dec 2021 19:26:21 -0500 Subject: [PATCH 021/489] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 16b82ba38..556cecc50 100644 --- a/apps.json +++ b/apps.json @@ -3198,7 +3198,7 @@ }, { "id":"doztime2", "name":"Dozenal Time 2", - "shortName":"Dozenal 2", + "shortName":"Dozenal Time 2", "icon":"app.png", "version":"0.01", "description":"A dozenal Holocene calendar and dozenal diurnal clock for Bangle.js 2", From 3e3d7599c5ce5d2e2334fad2a39d4b800dbda95b Mon Sep 17 00:00:00 2001 From: numerist Date: Sat, 18 Dec 2021 19:48:41 -0500 Subject: [PATCH 022/489] Update apps.json --- apps.json | 1 - 1 file changed, 1 deletion(-) diff --git a/apps.json b/apps.json index 556cecc50..d694e82ed 100644 --- a/apps.json +++ b/apps.json @@ -3205,7 +3205,6 @@ "tags":"clock", "type":"clock", "allow_emulator":true, - "readme": "README.md", "storage": [ {"name":"doztime2.app.js","url":"app.js"}, {"name":"doztime2.img","url":"app-icon.js","evaluate":true} From 0673803d1b42f48241d9fb56a5efba6645119923 Mon Sep 17 00:00:00 2001 From: numerist Date: Sat, 18 Dec 2021 23:10:00 -0500 Subject: [PATCH 023/489] Update app.js --- apps/doztime2/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/doztime2/app.js b/apps/doztime2/app.js index 855ec9aaf..a0ddfd4d0 100644 --- a/apps/doztime2/app.js +++ b/apps/doztime2/app.js @@ -14,7 +14,7 @@ const A1 = [30,30,30,30,31,31,31,31,31,31,30,30]; const B1 = [30,30,30,30,30,31,31,31,31,31,30,30]; const B2 = [30,30,30,30,31,31,31,31,31,30,30,30]; const timeColour = "#ffffff"; -const dateColours = ["#ff0000","#ffa500","#ffff00","#00b800","#8383ff","#ff00ff","#ff0080"]; //blue was 0000ff +const dateColours = ["#ff0000","#ff8000","#ffff00","#00ff00","#0080ff","#ff00ff","#ffffff"]; const calen10 = {"size":26,"pt0":[18-g_x_off,16],"step":[16,0],"dx":-4.5,"dy":-4.5}; // positioning for usual calendar line ft w 32, 32-g, step 20 const calen7 = {"size":26,"pt0":[48-g_x_off,16],"step":[16,0],"dx":-4.5,"dy":-4.5}; // positioning for S-day calendar line ft w 32, 62-g, step 20 const time5 = {"size":42,"pt0":[39-g_x_off,24],"step":[26,0],"dx":-6.5,"dy":-6.5}; // positioning for lull time line ft w 48, 64-g, step 30 From 03a295a4ff40d9c664f155324d139ffb007e76eb Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 12:00:43 +0100 Subject: [PATCH 024/489] wohrm: prepare porting to Bangle.js2 --- apps.json | 4 ++-- apps/wohrm/README.md | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index e5e9f8f02..07c773725 100644 --- a/apps.json +++ b/apps.json @@ -1714,12 +1714,12 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.08", + "version": "0.09-rc1", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app", "tags": "hrm,workout", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS", "BANGLEJS2"], "readme": "README.md", "allow_emulator": true, "screenshots": [{"url":"bangle1-workout-HRM-screenshot.png"}], diff --git a/apps/wohrm/README.md b/apps/wohrm/README.md index ad9e82525..87b1a65da 100644 --- a/apps/wohrm/README.md +++ b/apps/wohrm/README.md @@ -8,6 +8,9 @@ and will notify you with a buzz whenever your heart rate falls below or jumps ab [Try it out](https://www.espruino.com/ide/emulator.html?codeurl=https://raw.githubusercontent.com/msdeibel/BangleApps/master/apps/wohrm/app.js&upload) using the [online Espruino emulator](https://www.espruino.com/ide/emulator.html). ## Setting the limits + +Use the settings menu to set the limits. On the Bangle.js1 these can in addition be set with the buttons: + For setting the lower limit press button 4 (left part of the watch's touch screen). Then adjust the value with the buttons 1 (top) and 3 (bottom) of the watch. @@ -22,7 +25,7 @@ the received value: For 85% and above the bars are green, between 84% and 50% th and below 50% they turn red. ## Closing the app -Pressing button 2 (middle) will switch off the HRM of the watch and return you to the launcher. +Pressing middle button will switch off the HRM of the watch and return you to the launcher. # HRM usage The HRM is switched on when the app is started. It stays switch on while the app is running, even From e91324c16bc9b10dde21e14468933a5500979d05 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 12:11:27 +0100 Subject: [PATCH 025/489] wohrm: Prevent crash on BangleJs2 --- apps/wohrm/app.js | 655 +++++++++++++++++++++++----------------------- 1 file changed, 328 insertions(+), 327 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index c9c060e99..01fcca63e 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -1,327 +1,328 @@ -/* eslint-disable no-undef */ -const Setter = { - NONE: "none", - UPPER: 'upper', - LOWER: 'lower' -}; - -const shortBuzzTimeInMs = 80; -const longBuzzTimeInMs = 400; - -let upperLimit = 130; -let upperLimitChanged = true; - -let lowerLimit = 100; -let lowerLimitChanged = true; - -let limitSetter = Setter.NONE; - -let currentHeartRate = 0; -let hrConfidence = -1; -let hrChanged = true; -let confidenceChanged = true; - -let setterHighlightTimeout; - -function renderUpperLimitBackground() { - g.setColor(1,0,0); - g.fillRect(125,40, 210, 70); - g.fillRect(180,70, 210, 200); - - //Round top left corner - g.fillEllipse(115,40,135,70); - - //Round top right corner - g.setColor(0,0,0); - g.fillRect(205,40, 210, 45); - g.setColor(1,0,0); - g.fillEllipse(190,40,210,50); - - //Round inner corner - g.fillRect(174,71, 179, 76); - g.setColor(0,0,0); - g.fillEllipse(160,71,179,82); - - //Round bottom - g.setColor(1,0,0); - g.fillEllipse(180,190, 210, 210); -} - -function renderLowerLimitBackground() { - g.setColor(0,0,1); - g.fillRect(10, 180, 100, 210); - g.fillRect(10, 50, 40, 180); - - //Rounded top - g.setColor(0,0,1); - g.fillEllipse(10,40, 40, 60); - - //Round bottom right corner - g.setColor(0,0,1); - g.fillEllipse(90,180,110,210); - - //Round inner corner - g.setColor(0,0,1); - g.fillRect(40,175,45,180); - g.setColor(0,0,0); - g.fillEllipse(41,170,60,179); - - //Round bottom left corner - g.setColor(0,0,0); - g.fillRect(10,205, 15, 210); - g.setColor(0,0,1); - g.fillEllipse(10,200,30,210); -} - -function drawTrainingHeartRate() { - //Only redraw if the display is on - if (Bangle.isLCDOn()) { - renderUpperLimit(); - - renderCurrentHeartRate(); - - renderLowerLimit(); - - renderConfidenceBars(); - } - - buzz(); -} - -function renderUpperLimit() { - if(!upperLimitChanged) { return; } - - g.setColor(1,0,0); - g.fillRect(125,40, 210, 70); - - if(limitSetter === Setter.UPPER){ - g.setColor(255,255, 0); - } else { - g.setColor(255,255,255); - } - g.setFontVector(13); - g.drawString("Upper: " + upperLimit, 125, 50); - - upperLimitChanged = false; -} - -function renderCurrentHeartRate() { - if(!hrChanged) { return; } - - g.setColor(255,255,255); - g.fillRect(55, 110, 165, 150); - - g.setColor(0,0,0); - g.setFontVector(24); - g.setFontAlign(1, -1, 0); - g.drawString(currentHeartRate, 130, 117); - - //Reset alignment to defaults - g.setFontAlign(-1, -1, 0); - - hrChanged = false; -} - -function renderLowerLimit() { - if(!lowerLimitChanged) { return; } - - g.setColor(0,0,1); - g.fillRect(10, 180, 100, 210); - - if(limitSetter === Setter.LOWER){ - g.setColor(255,255, 0); - } else { - g.setColor(255,255,255); - } - g.setFontVector(13); - g.drawString("Lower: " + lowerLimit, 20,190); - - lowerLimitChanged = false; -} - -function renderConfidenceBars(){ - if(!confidenceChanged) { return; } - - if(hrConfidence >= 85){ - g.setColor(0, 255, 0); - } else if (hrConfidence >= 50) { - g.setColor(255, 255, 0); - } else if(hrConfidence >= 0){ - g.setColor(255, 0, 0); - } else { - g.setColor(255, 255, 255); - } - - g.fillRect(45, 110, 55, 150); - g.fillRect(165, 110, 175, 150); - - confidenceChanged = false; -} - -function renderPlusMinusIcons() { - if (limitSetter === Setter.NONE) { - g.setColor(0, 0, 0); - } else { - g.setColor(1, 1, 1); - } - - g.setFontVector(14); - - //+ for Btn1 - g.drawString("+", 222, 50); - - //- for Btn3 - g.drawString("-", 222,165); - - return; -} - -function renderHomeIcon() { - //Home for Btn2 - g.setColor(1, 1, 1); - g.drawLine(220, 118, 227, 110); - g.drawLine(227, 110, 234, 118); - - g.drawPoly([222,117,222,125,232,125,232,117], false); - g.drawRect(226,120,229,125); -} - -function buzz() { - // Do not buzz if not confident - if(hrConfidence < 85) { return; } - - if(currentHeartRate > upperLimit) - { - Bangle.buzz(shortBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs * 2); - } - - if(currentHeartRate < lowerLimit) - { - Bangle.buzz(longBuzzTimeInMs); - } -} - -function onHrm(hrm){ - if(currentHeartRate !== hrm.bpm){ - currentHeartRate = hrm.bpm; - hrChanged = true; - } - - if(hrConfidence !== hrm.confidence) { - hrConfidence = hrm.confidence; - confidenceChanged = true; - } -} - -function setLimitSetterToLower() { - resetHighlightTimeout(); - - limitSetter = Setter.LOWER; - - upperLimitChanged = true; - lowerLimitChanged = true; - - renderUpperLimit(); - renderLowerLimit(); - renderPlusMinusIcons(); -} - -function setLimitSetterToUpper() { - resetHighlightTimeout(); - - limitSetter = Setter.UPPER; - - upperLimitChanged = true; - lowerLimitChanged = true; - - renderLowerLimit(); - renderUpperLimit(); - renderPlusMinusIcons(); -} - -function setLimitSetterToNone() { - limitSetter = Setter.NONE; - - upperLimitChanged = true; - lowerLimitChanged = true; - - renderLowerLimit(); - renderUpperLimit(); - renderPlusMinusIcons(); -} - -function incrementLimit() { - resetHighlightTimeout(); - - if (limitSetter === Setter.UPPER) { - upperLimit++; - renderUpperLimit(); - upperLimitChanged = true; - } else if(limitSetter === Setter.LOWER) { - lowerLimit++; - renderLowerLimit(); - lowerLimitChanged = true; - } -} - -function decrementLimit(){ - resetHighlightTimeout(); - - if (limitSetter === Setter.UPPER) { - upperLimit--; - renderUpperLimit(); - upperLimitChanged = true; - } else if(limitSetter === Setter.LOWER) { - lowerLimit--; - renderLowerLimit(); - lowerLimitChanged = true; - } -} - -function resetHighlightTimeout() { - if (setterHighlightTimeout) { - clearTimeout(setterHighlightTimeout); - } - - setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000); -} - -function switchOffApp(){ - Bangle.setHRMPower(0,"wohrm"); - Bangle.showLauncher(); -} - -Bangle.on('lcdPower', (on) => { - g.clear(); - if (on) { - Bangle.drawWidgets(); - - renderHomeIcon(); - renderLowerLimitBackground(); - renderUpperLimitBackground(); - lowerLimitChanged = true; - upperLimitChanged = true; - drawTrainingHeartRate(); - } -}); - -Bangle.setHRMPower(1,"wohrm"); -Bangle.on('HRM', onHrm); - -setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); -setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true}); -setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true}); -setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); - -setWatch(switchOffApp, BTN2, {edge:"falling", debounce:50, repeat:true}); - -g.clear(); -Bangle.loadWidgets(); -Bangle.drawWidgets(); - -renderHomeIcon(); -renderLowerLimitBackground(); -renderUpperLimitBackground(); - -setInterval(drawTrainingHeartRate, 1000); +/* eslint-disable no-undef */ +const Setter = { + NONE: "none", + UPPER: 'upper', + LOWER: 'lower' +}; + +const shortBuzzTimeInMs = 80; +const longBuzzTimeInMs = 400; + +let upperLimit = 130; +let upperLimitChanged = true; + +let lowerLimit = 100; +let lowerLimitChanged = true; + +let limitSetter = Setter.NONE; + +let currentHeartRate = 0; +let hrConfidence = -1; +let hrChanged = true; +let confidenceChanged = true; + +let setterHighlightTimeout; + +function renderUpperLimitBackground() { + g.setColor(1,0,0); + g.fillRect(125,40, 210, 70); + g.fillRect(180,70, 210, 200); + + //Round top left corner + g.fillEllipse(115,40,135,70); + + //Round top right corner + g.setColor(0,0,0); + g.fillRect(205,40, 210, 45); + g.setColor(1,0,0); + g.fillEllipse(190,40,210,50); + + //Round inner corner + g.fillRect(174,71, 179, 76); + g.setColor(0,0,0); + g.fillEllipse(160,71,179,82); + + //Round bottom + g.setColor(1,0,0); + g.fillEllipse(180,190, 210, 210); +} + +function renderLowerLimitBackground() { + g.setColor(0,0,1); + g.fillRect(10, 180, 100, 210); + g.fillRect(10, 50, 40, 180); + + //Rounded top + g.setColor(0,0,1); + g.fillEllipse(10,40, 40, 60); + + //Round bottom right corner + g.setColor(0,0,1); + g.fillEllipse(90,180,110,210); + + //Round inner corner + g.setColor(0,0,1); + g.fillRect(40,175,45,180); + g.setColor(0,0,0); + g.fillEllipse(41,170,60,179); + + //Round bottom left corner + g.setColor(0,0,0); + g.fillRect(10,205, 15, 210); + g.setColor(0,0,1); + g.fillEllipse(10,200,30,210); +} + +function drawTrainingHeartRate() { + //Only redraw if the display is on + if (Bangle.isLCDOn()) { + renderUpperLimit(); + + renderCurrentHeartRate(); + + renderLowerLimit(); + + renderConfidenceBars(); + } + + buzz(); +} + +function renderUpperLimit() { + if(!upperLimitChanged) { return; } + + g.setColor(1,0,0); + g.fillRect(125,40, 210, 70); + + if(limitSetter === Setter.UPPER){ + g.setColor(255,255, 0); + } else { + g.setColor(255,255,255); + } + g.setFontVector(13); + g.drawString("Upper: " + upperLimit, 125, 50); + + upperLimitChanged = false; +} + +function renderCurrentHeartRate() { + if(!hrChanged) { return; } + + g.setColor(255,255,255); + g.fillRect(55, 110, 165, 150); + + g.setColor(0,0,0); + g.setFontVector(24); + g.setFontAlign(1, -1, 0); + g.drawString(currentHeartRate, 130, 117); + + //Reset alignment to defaults + g.setFontAlign(-1, -1, 0); + + hrChanged = false; +} + +function renderLowerLimit() { + if(!lowerLimitChanged) { return; } + + g.setColor(0,0,1); + g.fillRect(10, 180, 100, 210); + + if(limitSetter === Setter.LOWER){ + g.setColor(255,255, 0); + } else { + g.setColor(255,255,255); + } + g.setFontVector(13); + g.drawString("Lower: " + lowerLimit, 20,190); + + lowerLimitChanged = false; +} + +function renderConfidenceBars(){ + if(!confidenceChanged) { return; } + + if(hrConfidence >= 85){ + g.setColor(0, 255, 0); + } else if (hrConfidence >= 50) { + g.setColor(255, 255, 0); + } else if(hrConfidence >= 0){ + g.setColor(255, 0, 0); + } else { + g.setColor(255, 255, 255); + } + + g.fillRect(45, 110, 55, 150); + g.fillRect(165, 110, 175, 150); + + confidenceChanged = false; +} + +function renderPlusMinusIcons() { + if (limitSetter === Setter.NONE) { + g.setColor(0, 0, 0); + } else { + g.setColor(1, 1, 1); + } + + g.setFontVector(14); + + //+ for Btn1 + g.drawString("+", 222, 50); + + //- for Btn3 + g.drawString("-", 222,165); + + return; +} + +function renderHomeIcon() { + //Home for Btn2 + g.setColor(1, 1, 1); + g.drawLine(220, 118, 227, 110); + g.drawLine(227, 110, 234, 118); + + g.drawPoly([222,117,222,125,232,125,232,117], false); + g.drawRect(226,120,229,125); +} + +function buzz() { + // Do not buzz if not confident + if(hrConfidence < 85) { return; } + + if(currentHeartRate > upperLimit) + { + Bangle.buzz(shortBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs * 2); + } + + if(currentHeartRate < lowerLimit) + { + Bangle.buzz(longBuzzTimeInMs); + } +} + +function onHrm(hrm){ + if(currentHeartRate !== hrm.bpm){ + currentHeartRate = hrm.bpm; + hrChanged = true; + } + + if(hrConfidence !== hrm.confidence) { + hrConfidence = hrm.confidence; + confidenceChanged = true; + } +} + +function setLimitSetterToLower() { + resetHighlightTimeout(); + + limitSetter = Setter.LOWER; + + upperLimitChanged = true; + lowerLimitChanged = true; + + renderUpperLimit(); + renderLowerLimit(); + renderPlusMinusIcons(); +} + +function setLimitSetterToUpper() { + resetHighlightTimeout(); + + limitSetter = Setter.UPPER; + + upperLimitChanged = true; + lowerLimitChanged = true; + + renderLowerLimit(); + renderUpperLimit(); + renderPlusMinusIcons(); +} + +function setLimitSetterToNone() { + limitSetter = Setter.NONE; + + upperLimitChanged = true; + lowerLimitChanged = true; + + renderLowerLimit(); + renderUpperLimit(); + renderPlusMinusIcons(); +} + +function incrementLimit() { + resetHighlightTimeout(); + + if (limitSetter === Setter.UPPER) { + upperLimit++; + renderUpperLimit(); + upperLimitChanged = true; + } else if(limitSetter === Setter.LOWER) { + lowerLimit++; + renderLowerLimit(); + lowerLimitChanged = true; + } +} + +function decrementLimit(){ + resetHighlightTimeout(); + + if (limitSetter === Setter.UPPER) { + upperLimit--; + renderUpperLimit(); + upperLimitChanged = true; + } else if(limitSetter === Setter.LOWER) { + lowerLimit--; + renderLowerLimit(); + lowerLimitChanged = true; + } +} + +function resetHighlightTimeout() { + if (setterHighlightTimeout) { + clearTimeout(setterHighlightTimeout); + } + + setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000); +} + +function switchOffApp(){ + Bangle.setHRMPower(0,"wohrm"); + Bangle.showLauncher(); +} + +Bangle.on('lcdPower', (on) => { + g.clear(); + if (on) { + Bangle.drawWidgets(); + + renderHomeIcon(); + renderLowerLimitBackground(); + renderUpperLimitBackground(); + lowerLimitChanged = true; + upperLimitChanged = true; + drawTrainingHeartRate(); + } +}); + +Bangle.setHRMPower(1,"wohrm"); +Bangle.on('HRM', onHrm); + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +renderLowerLimitBackground(); +renderUpperLimitBackground(); + +if (typeof(BTN5) !== typeof(undefined)) { + renderHomeIcon(); + setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); + setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true}); + setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true}); + setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); + + setWatch(switchOffApp, BTN2, {edge:"falling", debounce:50, repeat:true}); +} + +setInterval(drawTrainingHeartRate, 1000); From e98690a8533eefd23d23cd017b65c3b2def73aa1 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 14:10:08 +0100 Subject: [PATCH 026/489] wohrm: parameterized renderUpperLimitBackground() --- apps/wohrm/app.js | 44 +++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 01fcca63e..ba037fc7c 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -24,27 +24,45 @@ let confidenceChanged = true; let setterHighlightTimeout; function renderUpperLimitBackground() { - g.setColor(1,0,0); - g.fillRect(125,40, 210, 70); - g.fillRect(180,70, 210, 200); + var minX=125; + var maxX=210; + var minY=40; + var maxY=210; + var rectWidth=30; + var cornerRoundness=5; + var bgColor = 0; + var fgColor = '#f00'; + g.setColor(fgColor); + + g.fillRect(minX,minY, maxX, minY+rectWidth); + g.fillRect(maxX-rectWidth, minY+rectWidth, maxX, maxY-cornerRoundness*2); //Round top left corner - g.fillEllipse(115,40,135,70); + g.fillEllipse(minX-cornerRoundness*2, + minY, + minX+cornerRoundness*2, + minY+rectWidth); //Round top right corner - g.setColor(0,0,0); - g.fillRect(205,40, 210, 45); - g.setColor(1,0,0); - g.fillEllipse(190,40,210,50); + g.setColor(bgColor); + g.fillRect(maxX-cornerRoundness,minY, maxX, minY+cornerRoundness); + g.setColor(fgColor); + g.fillEllipse(maxX-cornerRoundness*4,minY,maxX,minY+cornerRoundness*2); //Round inner corner - g.fillRect(174,71, 179, 76); - g.setColor(0,0,0); - g.fillEllipse(160,71,179,82); + g.fillRect(maxX-rectWidth-cornerRoundness-1, + minY+rectWidth+1, + maxX-rectWidth-1, + minY+rectWidth+cornerRoundness-1); + g.setColor(bgColor); + g.fillEllipse(maxX-rectWidth-cornerRoundness*4, + minY+rectWidth+1, + maxX-rectWidth-1, + minY+rectWidth+cornerRoundness*3-1); //Round bottom - g.setColor(1,0,0); - g.fillEllipse(180,190, 210, 210); + g.setColor(fgColor); + g.fillEllipse(maxX-rectWidth,maxY-cornerRoundness*4, maxX, maxY); } function renderLowerLimitBackground() { From 8c4f37e991fc3ab17ea6c24b7d15d813dc343b53 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 14:30:12 +0100 Subject: [PATCH 027/489] wohrm: renderLshape() from renderUpperLimitBackground() --- apps/wohrm/app.js | 69 ++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index ba037fc7c..e73307773 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -23,46 +23,49 @@ let confidenceChanged = true; let setterHighlightTimeout; -function renderUpperLimitBackground() { - var minX=125; - var maxX=210; - var minY=40; - var maxY=210; - var rectWidth=30; - var cornerRoundness=5; - var bgColor = 0; - var fgColor = '#f00'; - g.setColor(fgColor); +const upperLshape = { + minX: 125, + maxX: 210, + minY: 40, + maxY: 210, + rectWidth: 30, + cornerRoundness: 5, + bgColor: 0, + fgColor: '#f00' +}; - g.fillRect(minX,minY, maxX, minY+rectWidth); - g.fillRect(maxX-rectWidth, minY+rectWidth, maxX, maxY-cornerRoundness*2); +function renderLshape(p) { + g.setColor(p.fgColor); + + g.fillRect(p.minX,p.minY, p.maxX, p.minY+p.rectWidth); + g.fillRect(p.maxX-p.rectWidth, p.minY+p.rectWidth, p.maxX, p.maxY-p.cornerRoundness*2); //Round top left corner - g.fillEllipse(minX-cornerRoundness*2, - minY, - minX+cornerRoundness*2, - minY+rectWidth); + g.fillEllipse(p.minX-p.cornerRoundness*2, + p.minY, + p.minX+p.cornerRoundness*2, + p.minY+p.rectWidth); //Round top right corner - g.setColor(bgColor); - g.fillRect(maxX-cornerRoundness,minY, maxX, minY+cornerRoundness); - g.setColor(fgColor); - g.fillEllipse(maxX-cornerRoundness*4,minY,maxX,minY+cornerRoundness*2); + g.setColor(p.bgColor); + g.fillRect(p.maxX-p.cornerRoundness,p.minY, p.maxX, p.minY+p.cornerRoundness); + g.setColor(p.fgColor); + g.fillEllipse(p.maxX-p.cornerRoundness*4,p.minY,p.maxX,p.minY+p.cornerRoundness*2); //Round inner corner - g.fillRect(maxX-rectWidth-cornerRoundness-1, - minY+rectWidth+1, - maxX-rectWidth-1, - minY+rectWidth+cornerRoundness-1); - g.setColor(bgColor); - g.fillEllipse(maxX-rectWidth-cornerRoundness*4, - minY+rectWidth+1, - maxX-rectWidth-1, - minY+rectWidth+cornerRoundness*3-1); + g.fillRect(p.maxX-p.rectWidth-p.cornerRoundness-1, + p.minY+p.rectWidth+1, + p.maxX-p.rectWidth-1, + p.minY+p.rectWidth+p.cornerRoundness-1); + g.setColor(p.bgColor); + g.fillEllipse(p.maxX-p.rectWidth-p.cornerRoundness*4, + p.minY+p.rectWidth+1, + p.maxX-p.rectWidth-1, + p.minY+p.rectWidth+p.cornerRoundness*3-1); //Round bottom - g.setColor(fgColor); - g.fillEllipse(maxX-rectWidth,maxY-cornerRoundness*4, maxX, maxY); + g.setColor(p.fgColor); + g.fillEllipse(p.maxX-p.rectWidth,p.maxY-p.cornerRoundness*4, p.maxX, p.maxY); } function renderLowerLimitBackground() { @@ -317,7 +320,7 @@ Bangle.on('lcdPower', (on) => { renderHomeIcon(); renderLowerLimitBackground(); - renderUpperLimitBackground(); + renderLshape(upperLshape); lowerLimitChanged = true; upperLimitChanged = true; drawTrainingHeartRate(); @@ -331,7 +334,7 @@ g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); renderLowerLimitBackground(); -renderUpperLimitBackground(); +renderLshape(upperLshape); if (typeof(BTN5) !== typeof(undefined)) { renderHomeIcon(); From f4a7a4f77e78a24cb26490f100e29bdf75e02676 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 15:28:26 +0100 Subject: [PATCH 028/489] wohrt: removed renderLowerLimitBackground() --- apps/wohrm/app.js | 102 ++++++++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 48 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index e73307773..638627e17 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -30,68 +30,74 @@ const upperLshape = { maxY: 210, rectWidth: 30, cornerRoundness: 5, + orientation: -1, bgColor: 0, fgColor: '#f00' }; +const lowerLshape = { + maxX: 10, + minX: 100, + minY: 210, + maxY: 40, + rectWidth: 30, + cornerRoundness: 5, + orientation: 1, + bgColor: 0, + fgColor: '#00f' +}; + +function fillEllipse(x, y, x2, y2) { + g.fillEllipse(Math.min(x, x2), + Math.min(y, y2), + Math.max(x, x2), + Math.max(y, y2)); +} + function renderLshape(p) { g.setColor(p.fgColor); - g.fillRect(p.minX,p.minY, p.maxX, p.minY+p.rectWidth); - g.fillRect(p.maxX-p.rectWidth, p.minY+p.rectWidth, p.maxX, p.maxY-p.cornerRoundness*2); + g.fillRect(p.minX, p.minY, p.maxX, p.minY-p.orientation*p.rectWidth); + g.fillRect(p.maxX+p.orientation*p.rectWidth, + p.minY-p.orientation*p.rectWidth, + p.maxX, + p.maxY+p.orientation*p.cornerRoundness*2); - //Round top left corner - g.fillEllipse(p.minX-p.cornerRoundness*2, - p.minY, - p.minX+p.cornerRoundness*2, - p.minY+p.rectWidth); + //Round end of small line + fillEllipse(p.minX+p.orientation*p.cornerRoundness*2, + p.minY, + p.minX-p.orientation*p.cornerRoundness*2, + p.minY-p.orientation*p.rectWidth); - //Round top right corner + //Round outer corner g.setColor(p.bgColor); - g.fillRect(p.maxX-p.cornerRoundness,p.minY, p.maxX, p.minY+p.cornerRoundness); + g.fillRect(p.maxX+p.orientation*p.cornerRoundness, + p.minY, + p.maxX, + p.minY-p.orientation*p.cornerRoundness); g.setColor(p.fgColor); - g.fillEllipse(p.maxX-p.cornerRoundness*4,p.minY,p.maxX,p.minY+p.cornerRoundness*2); + fillEllipse(p.maxX+p.orientation*p.cornerRoundness*4, + p.minY, + p.maxX, + p.minY-p.orientation*p.cornerRoundness*2); //Round inner corner - g.fillRect(p.maxX-p.rectWidth-p.cornerRoundness-1, - p.minY+p.rectWidth+1, - p.maxX-p.rectWidth-1, - p.minY+p.rectWidth+p.cornerRoundness-1); + g.fillRect(p.maxX+p.orientation*(p.rectWidth+p.cornerRoundness+1), + p.minY-p.orientation*(p.rectWidth+1), + p.maxX+p.orientation*(p.rectWidth+1), + p.minY-p.orientation*(p.rectWidth+p.cornerRoundness-1)); g.setColor(p.bgColor); - g.fillEllipse(p.maxX-p.rectWidth-p.cornerRoundness*4, - p.minY+p.rectWidth+1, - p.maxX-p.rectWidth-1, - p.minY+p.rectWidth+p.cornerRoundness*3-1); + fillEllipse(p.maxX+p.orientation*(p.rectWidth+p.cornerRoundness*4), + p.minY-p.orientation*(p.rectWidth+1), + p.maxX+p.orientation*(p.rectWidth+1), + p.minY-p.orientation*(p.rectWidth+p.cornerRoundness*3-1)); - //Round bottom + //Round end of long line g.setColor(p.fgColor); - g.fillEllipse(p.maxX-p.rectWidth,p.maxY-p.cornerRoundness*4, p.maxX, p.maxY); -} - -function renderLowerLimitBackground() { - g.setColor(0,0,1); - g.fillRect(10, 180, 100, 210); - g.fillRect(10, 50, 40, 180); - - //Rounded top - g.setColor(0,0,1); - g.fillEllipse(10,40, 40, 60); - - //Round bottom right corner - g.setColor(0,0,1); - g.fillEllipse(90,180,110,210); - - //Round inner corner - g.setColor(0,0,1); - g.fillRect(40,175,45,180); - g.setColor(0,0,0); - g.fillEllipse(41,170,60,179); - - //Round bottom left corner - g.setColor(0,0,0); - g.fillRect(10,205, 15, 210); - g.setColor(0,0,1); - g.fillEllipse(10,200,30,210); + fillEllipse(p.maxX+p.orientation*p.rectWidth, + p.maxY+p.orientation*p.cornerRoundness*4, + p.maxX, + p.maxY); } function drawTrainingHeartRate() { @@ -319,7 +325,7 @@ Bangle.on('lcdPower', (on) => { Bangle.drawWidgets(); renderHomeIcon(); - renderLowerLimitBackground(); + renderLshape(lowerLshape); renderLshape(upperLshape); lowerLimitChanged = true; upperLimitChanged = true; @@ -333,7 +339,7 @@ Bangle.on('HRM', onHrm); g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); -renderLowerLimitBackground(); +renderLshape(lowerLshape); renderLshape(upperLshape); if (typeof(BTN5) !== typeof(undefined)) { From 3e0e590b86a3a2282fd22ca03c37232410a35d94 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 15:41:06 +0100 Subject: [PATCH 029/489] Add home buttom for Bangle.js2 --- apps/wohrm/app.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 638627e17..de3db14e2 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -350,6 +350,8 @@ if (typeof(BTN5) !== typeof(undefined)) { setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); setWatch(switchOffApp, BTN2, {edge:"falling", debounce:50, repeat:true}); +} else { + setWatch(switchOffApp, BTN1, {edge:"falling", debounce:50, repeat:true}); } setInterval(drawTrainingHeartRate, 1000); From 616f1f784f8780adce5f586ecc51e54b0c8a1a2a Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 15:46:56 +0100 Subject: [PATCH 030/489] wohrm: Don't draw home-icon on Banglejs2 --- apps/wohrm/app.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index de3db14e2..8e041fa98 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -320,11 +320,13 @@ function switchOffApp(){ } Bangle.on('lcdPower', (on) => { - g.clear(); if (on) { + g.clear(); Bangle.drawWidgets(); - renderHomeIcon(); + if (typeof(BTN5) !== typeof(undefined)) { + renderHomeIcon(); + } renderLshape(lowerLshape); renderLshape(upperLshape); lowerLimitChanged = true; From 9f33ded981cb117537350698292509eac4f4e24b Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 15:56:03 +0100 Subject: [PATCH 031/489] wohrm: Fixed rounding of outer corner --- apps/wohrm/app.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 8e041fa98..0681a3b33 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -118,8 +118,7 @@ function drawTrainingHeartRate() { function renderUpperLimit() { if(!upperLimitChanged) { return; } - g.setColor(1,0,0); - g.fillRect(125,40, 210, 70); + renderLshape(upperLshape); if(limitSetter === Setter.UPPER){ g.setColor(255,255, 0); @@ -152,8 +151,7 @@ function renderCurrentHeartRate() { function renderLowerLimit() { if(!lowerLimitChanged) { return; } - g.setColor(0,0,1); - g.fillRect(10, 180, 100, 210); + renderLshape(lowerLshape); if(limitSetter === Setter.LOWER){ g.setColor(255,255, 0); @@ -341,8 +339,6 @@ Bangle.on('HRM', onHrm); g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); -renderLshape(lowerLshape); -renderLshape(upperLshape); if (typeof(BTN5) !== typeof(undefined)) { renderHomeIcon(); From 9189be084c9381bd6842585ce84e65aa49a5b1ab Mon Sep 17 00:00:00 2001 From: numerist Date: Sun, 19 Dec 2021 10:11:30 -0500 Subject: [PATCH 032/489] Update app.js --- apps/doztime2/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/doztime2/app.js b/apps/doztime2/app.js index a0ddfd4d0..f57fc386c 100644 --- a/apps/doztime2/app.js +++ b/apps/doztime2/app.js @@ -17,8 +17,8 @@ const timeColour = "#ffffff"; const dateColours = ["#ff0000","#ff8000","#ffff00","#00ff00","#0080ff","#ff00ff","#ffffff"]; const calen10 = {"size":26,"pt0":[18-g_x_off,16],"step":[16,0],"dx":-4.5,"dy":-4.5}; // positioning for usual calendar line ft w 32, 32-g, step 20 const calen7 = {"size":26,"pt0":[48-g_x_off,16],"step":[16,0],"dx":-4.5,"dy":-4.5}; // positioning for S-day calendar line ft w 32, 62-g, step 20 -const time5 = {"size":42,"pt0":[39-g_x_off,24],"step":[26,0],"dx":-6.5,"dy":-6.5}; // positioning for lull time line ft w 48, 64-g, step 30 -const time6 = {"size":42,"pt0":[26-g_x_off,24],"step":[26,0],"dx":-6.5,"dy":-6.5}; // positioning for twinkling time line ft w 48, 48-g, step 30 +const time5 = {"size":36,"pt0":[46-g_x_off,24],"step":[22,0],"dx":-6.5,"dy":-6.5}; // positioning for lull time line ft w 48, 64-g, step 30 +const time6 = {"size":36,"pt0":[36-g_x_off,24],"step":[22,0],"dx":-6.5,"dy":-6.5}; // positioning for twinkling time line ft w 48, 48-g, step 30 const baseYear = 11584; const baseDate = Date(2020,11,21); // month values run from 0 to 11 let accum = new Date(baseDate.getTime()); From 0d172f1db04b957f6b9520b61affde4f6952e92c Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 16:23:56 +0100 Subject: [PATCH 033/489] wohrm: place Upper/Lower relative to "L" --- apps/wohrm/app.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 0681a3b33..f761c421e 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -125,8 +125,10 @@ function renderUpperLimit() { } else { g.setColor(255,255,255); } - g.setFontVector(13); - g.drawString("Upper: " + upperLimit, 125, 50); + g.setFontVector(13).setFontAlign(-1, 0, 0); + g.drawString("Upper: " + upperLimit, + upperLshape.minX, + upperLshape.minY+upperLshape.rectWidth/2); upperLimitChanged = false; } @@ -158,8 +160,10 @@ function renderLowerLimit() { } else { g.setColor(255,255,255); } - g.setFontVector(13); - g.drawString("Lower: " + lowerLimit, 20,190); + g.setFontVector(13).setFontAlign(-1, 0, 0); + g.drawString("Lower: " + lowerLimit, + lowerLshape.maxX + lowerLshape.rectWidth/2, + lowerLshape.minY - lowerLshape.rectWidth/2); lowerLimitChanged = false; } From 09e7330ae0547eaa5270e2a175756167e04ccb2d Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 17:25:05 +0100 Subject: [PATCH 034/489] wohrm: parameterized centerBar --- apps/wohrm/app.js | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index f761c421e..ef4a3013d 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -47,6 +47,14 @@ const lowerLshape = { fgColor: '#00f' }; +const centerBar = { + minY: (upperLshape.minY + upperLshape.maxY - upperLshape.rectWidth)/2, + maxY: (upperLshape.minY + upperLshape.maxY + upperLshape.rectWidth)/2, + confidenceWidth: 10, + minX: 55, + maxX: 165 +}; + function fillEllipse(x, y, x2, y2) { g.fillEllipse(Math.min(x, x2), Math.min(y, y2), @@ -136,13 +144,16 @@ function renderUpperLimit() { function renderCurrentHeartRate() { if(!hrChanged) { return; } - g.setColor(255,255,255); - g.fillRect(55, 110, 165, 150); + g.setColor(1, 1, 1); + g.fillRect(centerBar.minX, centerBar.minY, + centerBar.maxX, centerBar.maxY); g.setColor(0,0,0); g.setFontVector(24); - g.setFontAlign(1, -1, 0); - g.drawString(currentHeartRate, 130, 117); + g.setFontAlign(1, 0, 0); + g.drawString(currentHeartRate, + upperLshape.minX+upperLshape.cornerRoundness, + (centerBar.minY+centerBar.maxY)/2); //Reset alignment to defaults g.setFontAlign(-1, -1, 0); @@ -181,8 +192,8 @@ function renderConfidenceBars(){ g.setColor(255, 255, 255); } - g.fillRect(45, 110, 55, 150); - g.fillRect(165, 110, 175, 150); + g.fillRect(centerBar.minX-centerBar.confidenceWidth, centerBar.minY, centerBar.minX, centerBar.maxY); + g.fillRect(centerBar.maxX, centerBar.minY, centerBar.maxX+centerBar.confidenceWidth, centerBar.maxY); confidenceChanged = false; } From 0456843385231a1e817100386adf24026065204a Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 17:45:38 +0100 Subject: [PATCH 035/489] wohrm: Use theme colors --- apps/wohrm/app.js | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index ef4a3013d..63194f390 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -31,8 +31,7 @@ const upperLshape = { rectWidth: 30, cornerRoundness: 5, orientation: -1, - bgColor: 0, - fgColor: '#f00' + color: '#f00' }; const lowerLshape = { @@ -43,8 +42,7 @@ const lowerLshape = { rectWidth: 30, cornerRoundness: 5, orientation: 1, - bgColor: 0, - fgColor: '#00f' + color: '#00f' }; const centerBar = { @@ -63,7 +61,7 @@ function fillEllipse(x, y, x2, y2) { } function renderLshape(p) { - g.setColor(p.fgColor); + g.setColor(p.color); g.fillRect(p.minX, p.minY, p.maxX, p.minY-p.orientation*p.rectWidth); g.fillRect(p.maxX+p.orientation*p.rectWidth, @@ -78,12 +76,12 @@ function renderLshape(p) { p.minY-p.orientation*p.rectWidth); //Round outer corner - g.setColor(p.bgColor); + g.setColor(g.theme.bg); g.fillRect(p.maxX+p.orientation*p.cornerRoundness, p.minY, p.maxX, p.minY-p.orientation*p.cornerRoundness); - g.setColor(p.fgColor); + g.setColor(p.color); fillEllipse(p.maxX+p.orientation*p.cornerRoundness*4, p.minY, p.maxX, @@ -94,14 +92,14 @@ function renderLshape(p) { p.minY-p.orientation*(p.rectWidth+1), p.maxX+p.orientation*(p.rectWidth+1), p.minY-p.orientation*(p.rectWidth+p.cornerRoundness-1)); - g.setColor(p.bgColor); + g.setColor(g.theme.bg); fillEllipse(p.maxX+p.orientation*(p.rectWidth+p.cornerRoundness*4), p.minY-p.orientation*(p.rectWidth+1), p.maxX+p.orientation*(p.rectWidth+1), p.minY-p.orientation*(p.rectWidth+p.cornerRoundness*3-1)); //Round end of long line - g.setColor(p.fgColor); + g.setColor(p.color); fillEllipse(p.maxX+p.orientation*p.rectWidth, p.maxY+p.orientation*p.cornerRoundness*4, p.maxX, @@ -129,9 +127,9 @@ function renderUpperLimit() { renderLshape(upperLshape); if(limitSetter === Setter.UPPER){ - g.setColor(255,255, 0); + g.setColor(1,1,0); } else { - g.setColor(255,255,255); + g.setColor(g.theme.fg); } g.setFontVector(13).setFontAlign(-1, 0, 0); g.drawString("Upper: " + upperLimit, @@ -144,11 +142,11 @@ function renderUpperLimit() { function renderCurrentHeartRate() { if(!hrChanged) { return; } - g.setColor(1, 1, 1); + g.setColor(g.theme.fg); g.fillRect(centerBar.minX, centerBar.minY, centerBar.maxX, centerBar.maxY); - g.setColor(0,0,0); + g.setColor(g.theme.bg); g.setFontVector(24); g.setFontAlign(1, 0, 0); g.drawString(currentHeartRate, @@ -167,9 +165,9 @@ function renderLowerLimit() { renderLshape(lowerLshape); if(limitSetter === Setter.LOWER){ - g.setColor(255,255, 0); + g.setColor(1,1,0); } else { - g.setColor(255,255,255); + g.setColor(g.theme.fg); } g.setFontVector(13).setFontAlign(-1, 0, 0); g.drawString("Lower: " + lowerLimit, @@ -183,13 +181,13 @@ function renderConfidenceBars(){ if(!confidenceChanged) { return; } if(hrConfidence >= 85){ - g.setColor(0, 255, 0); + g.setColor(0, 1, 0); } else if (hrConfidence >= 50) { - g.setColor(255, 255, 0); + g.setColor(1, 1, 0); } else if(hrConfidence >= 0){ - g.setColor(255, 0, 0); + g.setColor(1, 0, 0); } else { - g.setColor(255, 255, 255); + g.setColor(g.theme.fg); } g.fillRect(centerBar.minX-centerBar.confidenceWidth, centerBar.minY, centerBar.minX, centerBar.maxY); @@ -200,9 +198,9 @@ function renderConfidenceBars(){ function renderPlusMinusIcons() { if (limitSetter === Setter.NONE) { - g.setColor(0, 0, 0); + g.setColor(g.theme.bg); } else { - g.setColor(1, 1, 1); + g.setColor(g.theme.fg); } g.setFontVector(14); From b513772692f129ad676b8f1dac15ecdf1419ce8f Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 17:51:55 +0100 Subject: [PATCH 036/489] wohrm: parameterized font sizes --- apps/wohrm/app.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 63194f390..bb21b5d59 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -53,6 +53,11 @@ const centerBar = { maxX: 165 }; +const fontSizes = { + limits: 13, + heartRate: 24 +}; + function fillEllipse(x, y, x2, y2) { g.fillEllipse(Math.min(x, x2), Math.min(y, y2), @@ -131,7 +136,7 @@ function renderUpperLimit() { } else { g.setColor(g.theme.fg); } - g.setFontVector(13).setFontAlign(-1, 0, 0); + g.setFontVector(fontSizes.limits).setFontAlign(-1, 0, 0); g.drawString("Upper: " + upperLimit, upperLshape.minX, upperLshape.minY+upperLshape.rectWidth/2); @@ -147,7 +152,7 @@ function renderCurrentHeartRate() { centerBar.maxX, centerBar.maxY); g.setColor(g.theme.bg); - g.setFontVector(24); + g.setFontVector(fontSizes.heartRate); g.setFontAlign(1, 0, 0); g.drawString(currentHeartRate, upperLshape.minX+upperLshape.cornerRoundness, @@ -169,7 +174,7 @@ function renderLowerLimit() { } else { g.setColor(g.theme.fg); } - g.setFontVector(13).setFontAlign(-1, 0, 0); + g.setFontVector(fontSizes.limits).setFontAlign(-1, 0, 0); g.drawString("Lower: " + lowerLimit, lowerLshape.maxX + lowerLshape.rectWidth/2, lowerLshape.minY - lowerLshape.rectWidth/2); From d5e08477e1692a7867f0c715070e58f0b7fddffd Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 17:59:57 +0100 Subject: [PATCH 037/489] wohrm: deduplicate --- apps/wohrm/app.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index bb21b5d59..6ebcdabc3 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -37,10 +37,10 @@ const upperLshape = { const lowerLshape = { maxX: 10, minX: 100, - minY: 210, - maxY: 40, - rectWidth: 30, - cornerRoundness: 5, + minY: upperLshape.maxY, + maxY: upperLshape.minY, + rectWidth: upperLshape.rectWidth, + cornerRoundness: upperLshape.cornerRoundness, orientation: 1, color: '#00f' }; From b120f7572f454426ab8bb912830e758f177134dd Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 19:32:19 +0100 Subject: [PATCH 038/489] wohrm: resize on Bangls.js2 --- apps/wohrm/app.js | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 6ebcdabc3..75d48c7ff 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -23,7 +23,8 @@ let confidenceChanged = true; let setterHighlightTimeout; -const upperLshape = { +const isB1 = process.env.HWVERSION==1; +const upperLshape = isB1 ? { minX: 125, maxX: 210, minY: 40, @@ -32,10 +33,19 @@ const upperLshape = { cornerRoundness: 5, orientation: -1, color: '#f00' +} : { + minX: Bangle.appRect.x2-100, + maxX: Bangle.appRect.x2, + minY: Bangle.appRect.y, + maxY: Bangle.appRect.y2, + rectWidth: 26, + cornerRoundness: 4, + orientation: -1, + color: '#f00' }; const lowerLshape = { - maxX: 10, + maxX: isB1 ? 10 : Bangle.appRect.x, minX: 100, minY: upperLshape.maxY, maxY: upperLshape.minY, @@ -48,14 +58,17 @@ const lowerLshape = { const centerBar = { minY: (upperLshape.minY + upperLshape.maxY - upperLshape.rectWidth)/2, maxY: (upperLshape.minY + upperLshape.maxY + upperLshape.rectWidth)/2, - confidenceWidth: 10, - minX: 55, - maxX: 165 + confidenceWidth: isB1 ? 10 : 8, + minX: isB1 ? 55 : upperLshape.rectWidth + 14, + maxX: isB1 ? 165 : Bangle.appRect.x2 - upperLshape.rectWidth - 14 }; -const fontSizes = { - limits: 13, - heartRate: 24 +const fontSizes = isB1 ? { + limits: 13, + heartRate: 24 +} : { + limits: 12, + heartRate: 20 }; function fillEllipse(x, y, x2, y2) { @@ -155,7 +168,8 @@ function renderCurrentHeartRate() { g.setFontVector(fontSizes.heartRate); g.setFontAlign(1, 0, 0); g.drawString(currentHeartRate, - upperLshape.minX+upperLshape.cornerRoundness, + Math.max(upperLshape.minX+upperLshape.cornerRoundness, + lowerLshape.minX-lowerLshape.cornerRoundness), (centerBar.minY+centerBar.maxY)/2); //Reset alignment to defaults From 3ae35376fcd3db363c33030b01d88e254a0781d5 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 20:45:11 +0100 Subject: [PATCH 039/489] wohrm: fixes after running on Bangle.js2 - set to dark theme as doesn't look good with white in the corners) - leave space for widgets --- apps.json | 2 +- apps/wohrm/app.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 07c773725..2acd3b981 100644 --- a/apps.json +++ b/apps.json @@ -1714,7 +1714,7 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.09-rc1", + "version": "0.09-rc2", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app", diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 75d48c7ff..429b9f565 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -36,7 +36,7 @@ const upperLshape = isB1 ? { } : { minX: Bangle.appRect.x2-100, maxX: Bangle.appRect.x2, - minY: Bangle.appRect.y, + minY: 24, maxY: Bangle.appRect.y2, rectWidth: 26, cornerRoundness: 4, @@ -368,7 +368,7 @@ Bangle.on('lcdPower', (on) => { Bangle.setHRMPower(1,"wohrm"); Bangle.on('HRM', onHrm); -g.clear(); +g.setTheme({bg:"#000",fg:"#fff",dark:true}).clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); From dd9520d1862f68573114c941787c9dc8d5de530b Mon Sep 17 00:00:00 2001 From: numerist Date: Sun, 19 Dec 2021 15:04:17 -0500 Subject: [PATCH 040/489] Update app.js --- apps/doztime2/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/doztime2/app.js b/apps/doztime2/app.js index f57fc386c..ac67954d3 100644 --- a/apps/doztime2/app.js +++ b/apps/doztime2/app.js @@ -134,8 +134,8 @@ function writeDozTime(text,def){ g_t.clear(); g_t.setFont("Vector",def.size); for(let i in text){ - if(text[i]=="a"){ g_t.setFontAlign(0,0,2); g_t.drawString("2",x+1+def.dx,y+1+def.dy); } //+1s are new - else if(text[i]=="b"){ g_t.setFontAlign(0,0,2); g_t.drawString("3",x+1+def.dx,y+1+def.dy); } //+1s are new + if(text[i]=="a"){ g_t.setFontAlign(0,0,2); g_t.drawString("2",x+2+def.dx,y+1+def.dy); } //+1s are new + else if(text[i]=="b"){ g_t.setFontAlign(0,0,2); g_t.drawString("3",x+2+def.dx,y+1+def.dy); } //+1s are new else{ g_t.setFontAlign(0,0,0); g_t.drawString(text[i],x,y); } x = x+def.step[0]; y = y+def.step[1]; From 9e1dd8eda39fb1bc76b9c52e1851072158cb4982 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 21:01:47 +0100 Subject: [PATCH 041/489] wohrm: Fix bgcolor --- apps.json | 2 +- apps/wohrm/app.js | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 2acd3b981..ed616c952 100644 --- a/apps.json +++ b/apps.json @@ -1714,7 +1714,7 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.09-rc2", + "version": "0.09-rc3", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app", diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 429b9f565..115849fa6 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -351,7 +351,6 @@ function switchOffApp(){ Bangle.on('lcdPower', (on) => { if (on) { - g.clear(); Bangle.drawWidgets(); if (typeof(BTN5) !== typeof(undefined)) { @@ -368,7 +367,9 @@ Bangle.on('lcdPower', (on) => { Bangle.setHRMPower(1,"wohrm"); Bangle.on('HRM', onHrm); -g.setTheme({bg:"#000",fg:"#fff",dark:true}).clear(); +g.setTheme({bg:"#000",fg:"#fff",dark:true}); +g.reset() +g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); From 288a204b9d608d90bb33cf82ec005f8a980df01e Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 21:13:39 +0100 Subject: [PATCH 042/489] wohrm: Add ChangeLog entry --- apps/wohrm/ChangeLog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/wohrm/ChangeLog b/apps/wohrm/ChangeLog index 084ca6ed5..156d32740 100644 --- a/apps/wohrm/ChangeLog +++ b/apps/wohrm/ChangeLog @@ -5,4 +5,5 @@ 0.05: Improved buzz timing and rendering 0.06: Removed debug outputs, fixed rendering for upper limit, improved rendering for +/- icons, changelog version order fixed 0.07: Home button fixed and README added -0.08: tag HRM power requests to allow this ot work alongside other widgets/apps (fix #799) +0.08: tag HRM power requests to allow this to work alongside other widgets/apps (fix #799) +0.09: Ported to Bangle.js2 From 15df1205060eaf866fb3b2eb0c4db861a0d7bc90 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 21:29:16 +0100 Subject: [PATCH 043/489] wohrm: Home returns to clock, instead of menu --- apps.json | 2 +- apps/wohrm/ChangeLog | 1 + apps/wohrm/app.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index ed616c952..4d98ce731 100644 --- a/apps.json +++ b/apps.json @@ -1714,7 +1714,7 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.09-rc3", + "version": "0.09-rc4", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app", diff --git a/apps/wohrm/ChangeLog b/apps/wohrm/ChangeLog index 156d32740..b177c1902 100644 --- a/apps/wohrm/ChangeLog +++ b/apps/wohrm/ChangeLog @@ -7,3 +7,4 @@ 0.07: Home button fixed and README added 0.08: tag HRM power requests to allow this to work alongside other widgets/apps (fix #799) 0.09: Ported to Bangle.js2 + Home returns to clock, instead of menu diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 115849fa6..646dab58f 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -346,7 +346,7 @@ function resetHighlightTimeout() { function switchOffApp(){ Bangle.setHRMPower(0,"wohrm"); - Bangle.showLauncher(); + load(); } Bangle.on('lcdPower', (on) => { From 200f9e19b58c6691b8ba5cffe4a61c9ee7fedaeb Mon Sep 17 00:00:00 2001 From: hughbarney Date: Sun, 19 Dec 2021 21:09:00 +0000 Subject: [PATCH 044/489] Pastel: added weather, change to queueDraw() update once per minute --- apps/pastel/pastel.app.js | 139 +++++++++++++++++++++++++++------ apps/pastel/pastel.settings.js | 13 ++- 2 files changed, 124 insertions(+), 28 deletions(-) diff --git a/apps/pastel/pastel.app.js b/apps/pastel/pastel.app.js index aa4f6abf8..e0c7df831 100644 --- a/apps/pastel/pastel.app.js +++ b/apps/pastel/pastel.app.js @@ -1,10 +1,22 @@ var SunCalc = require("https://raw.githubusercontent.com/mourner/suncalc/master/suncalc.js"); require("f_latosmall").add(Graphics); +const storage = require('Storage'); +const locale = require("locale"); const SETTINGS_FILE = "pastel.json"; const LOCATION_FILE = "mylocation.json"; let settings; let location; +// cloud, sun, partSun, snow, rain, storm, error +// create 1 bit, max contrast, brightness set to 85 +var cloudIcon = require("heatshrink").decompress(atob("kEggIfcj+AAYM/8ADBuFwAYPAmADCCAMBwEf8ADBhFwg4aBnEPAYMYjAVBhgDDDoQDHCYc4jwDB+EP///FYIDBMTgA==")); +var sunIcon = require("heatshrink").decompress(atob("kEggILIgOAAZkDAYPAgeBwPAgIFBBgPhw4TBp/yAYMcnADBnEcAYMwhgDBsEGgE/AYP8AYYLDCYgbDEYYrD8fHIwI7CIYZLDL54AHA==")); +var sunPartIcon = require("heatshrink").decompress(atob("kEggIHEmADJjEwsEAjkw8EAh0B4EAg35wEAgP+CYMDwv8AYMDBAP2g8HgH+g0DBYMMgPwAYX8gOMEwMG3kAg8OvgSBjg2BgcYGQIcBAY5CBg0Av//HAM///4MYgNBEIMOCoUMDoUAnBwGkEA")); +var snowIcon = require("heatshrink").decompress(atob("kEggITQj/AAYM98ADBsEwAYPAjADCj+AgOAj/gAYMIuEHwEAjEPAYQVChk4AYQhCAYcYBYQTDnEPgEB+EH///IAQACE4IAB8EICIPghwDB4EeBYNAjgDBg8EAYQYCg4bCgZuFA==")); +var rainIcon = require("heatshrink").decompress(atob("kEggIPMh+AAYM/8ADBuFwAYPgmADB4EbAYOAj/ggOAhnwg4aBnAeCjEcCIMMjADCDoQDHjAPCnAXCuEP///8EDAYJECAAXBwkAgPDhwDBwUMgEEhkggEOjFgFgMQLYQAOA==")); +var errIcon = require("heatshrink").decompress(atob("kEggILIgOAAYsD4ADBg/gAYMGsADBhkwAYsYjADCjgDBmEMAYNxxwDBsOGAYPBwYDEgOBwOAgYDB4EDHYPAgwDBsADDhgDBFIcwjAHBjE4AYMcmADBhhNCKIcG/4AGOw4A==")); + + function loadSettings() { settings = require("Storage").readJSON(SETTINGS_FILE,1)||{}; settings.grid = settings.grid||false; @@ -93,6 +105,50 @@ function prevInfo() { } } + +/** +Choose weather icon to display based on condition. +Based on function from the Bangle weather app so it should handle all of the conditions +sent from gadget bridge. +*/ +function chooseIcon(condition) { + condition = condition.toLowerCase(); + if (condition.includes("thunderstorm")) return stormIcon; + if (condition.includes("freezing")||condition.includes("snow")|| + condition.includes("sleet")) { + return snowIcon; + } + if (condition.includes("drizzle")|| + condition.includes("shower")) { + return rainIcon; + } + if (condition.includes("rain")) return rainIcon; + if (condition.includes("clear")) return sunIcon; + if (condition.includes("few clouds")) return partSunIcon; + if (condition.includes("scattered clouds")) return cloudIcon; + if (condition.includes("clouds")) return cloudIcon; + if (condition.includes("mist") || + condition.includes("smoke") || + condition.includes("haze") || + condition.includes("sand") || + condition.includes("dust") || + condition.includes("fog") || + condition.includes("ash") || + condition.includes("squalls") || + condition.includes("tornado")) { + return cloudIcon; + } + return cloudIcon; +} + +/** +Get weather stored in json file by weather app. +*/ +function getWeather() { + let jsonWeather = storage.readJSON('weather.json'); + return jsonWeather; +} + var mm_prev = "xx"; function draw() { @@ -114,7 +170,25 @@ function draw() { var h = g.getHeight(); var x = (g.getWidth()/2); var y = (g.getHeight()/3); - + + var weatherJson = getWeather(); + var w_temp; + var w_icon; + var w_wind; + + if (settings.weather && weatherJson && weatherJson.weather) { + var currentWeather = weatherJson.weather; + const temp = locale.temp(currentWeather.temp-273.15).match(/^(\D*\d*)(.*)$/); + w_temp = temp[1] + " " + temp[2]; + w_icon = chooseIcon(currentWeather.txt); + const wind = locale.speed(currentWeather.wind).match(/^(\D*\d*)(.*)$/); + w_wind = wind[1] + " " + wind[2] + " " + (currentWeather.wrose||'').toUpperCase(); + } else { + w_temp = "Err"; + w_wind = "???"; + w_icon = errIcon; + } + g.reset(); if (process.env.HWVERSION == 1) { @@ -139,6 +213,18 @@ function draw() { g.setColor(g.theme.fg); + // draw weather line + if (settings.weather) { + g.drawImage(w_icon, (w/2) - 40, 24); + g.setFontLatoSmall(); + g.setFontAlign(-1,0); // left aligned + if (drawCount % 2 == 0) + g.drawString(w_temp, (w/2) + 6, 24 + ((y - 24)/2)); + else + g.drawString( (w_wind.split(' ').slice(0, 2).join(' ')), (w/2) + 6, 24 + ((y - 24)/2)); + // display first 2 words of the wind string eg '4 mph' + } + if (settings.font == "Architect") g.setFontArchitect(); else if (settings.font == "GochiHand") @@ -161,36 +247,39 @@ function draw() { // for the colon g.setFontAlign(0,-1); // centre aligned - - if (d.getSeconds()&1) { - g.drawString(":", x,y); - } else { - // on bangle 1, we are not using clearRect(), hide : by printing over it in reverse color - if (process.env.HWVERSION == 1) { - g.setColor(g.theme.bg); - g.drawString(":", x,y); - g.setColor(g.theme.fg); - } - } - + g.drawString(":", x,y); g.setFontLatoSmall(); g.setFontAlign(0, -1); g.drawString((infoData[infoMode].calc()), w/2, h - 24 - 24); - if (drawCount % 3600 == 0) + // recalc sunrise / sunset every hour + if (drawCount % 60 == 0) updateSunRiseSunSet(new Date(), location.lat, location.lon); drawCount++; + queueDraw(); } -// Only update when display turns on -if (process.env.BOARD!="SMAQ3") // hack for Q3 which is always-on -Bangle.on('lcdPower', function(on) { - if (secondInterval) - clearInterval(secondInterval); - secondInterval = undefined; - if (on) - secondInterval = setInterval(draw, 1000); - draw(); +// timeout used to update every minute +var drawTimeout; + +// schedule a draw for the next minute +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + nextInfo(); + draw(); + }, 60000 - (Date.now() % 60000)); +} + +// Stop updates when LCD is off, restart when on +Bangle.on('lcdPower',on=>{ + if (on) { + draw(); // draw immediately, queue redraw + } else { // stop draw timer + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } }); Bangle.setUI("clockupdown", btn=> { @@ -204,8 +293,6 @@ loadFonts(); loadLocation(); g.clear(); -var secondInterval = setInterval(draw, 1000); -draw(); - Bangle.loadWidgets(); Bangle.drawWidgets(); +draw(); diff --git a/apps/pastel/pastel.settings.js b/apps/pastel/pastel.settings.js index fad36964d..bf83fa7c2 100644 --- a/apps/pastel/pastel.settings.js +++ b/apps/pastel/pastel.settings.js @@ -4,6 +4,7 @@ // initialize with default settings... let s = { 'grid': false, + 'weather': false, 'font': "Lato" } @@ -39,8 +40,16 @@ value: s.grid, format: () => (s.grid ? 'Yes' : 'No'), onchange: () => { - s.grid = !s.grid - save() + s.grid = !s.grid; + save(); + }, + }, + 'Show Weather': { + value: s.weather, + format: () => (s.weather ? 'Yes' : 'No'), + onchange: () => { + s.weather = !s.weather; + save(); }, } }) From 0caa10b7052a639ba80d2f35d061b6026cef6bf7 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 22:01:08 +0100 Subject: [PATCH 045/489] wohrm: Add settings --- apps.json | 3 ++- apps/wohrm/ChangeLog | 1 + apps/wohrm/app.js | 26 ++++++++++++++------------ apps/wohrm/settings.js | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 13 deletions(-) create mode 100644 apps/wohrm/settings.js diff --git a/apps.json b/apps.json index 4d98ce731..1d4f98c1e 100644 --- a/apps.json +++ b/apps.json @@ -1714,7 +1714,7 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.09-rc4", + "version": "0.09-rc7", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app", @@ -1725,6 +1725,7 @@ "screenshots": [{"url":"bangle1-workout-HRM-screenshot.png"}], "storage": [ {"name":"wohrm.app.js","url":"app.js"}, + {"name":"wohrm.settings.js","url":"settings.js"}, {"name":"wohrm.img","url":"app-icon.js","evaluate":true} ] }, diff --git a/apps/wohrm/ChangeLog b/apps/wohrm/ChangeLog index b177c1902..2ca405365 100644 --- a/apps/wohrm/ChangeLog +++ b/apps/wohrm/ChangeLog @@ -8,3 +8,4 @@ 0.08: tag HRM power requests to allow this to work alongside other widgets/apps (fix #799) 0.09: Ported to Bangle.js2 Home returns to clock, instead of menu + Add settings diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 646dab58f..26e7b7eae 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -4,14 +4,16 @@ const Setter = { UPPER: 'upper', LOWER: 'lower' }; +const SETTINGS_FILE = "wohrm.setting.json"; +var settings = require('Storage').readJSON(SETTINGS_FILE, 1) || { + upperLimit: 130, + lowerLimit: 100 +}; const shortBuzzTimeInMs = 80; const longBuzzTimeInMs = 400; -let upperLimit = 130; let upperLimitChanged = true; - -let lowerLimit = 100; let lowerLimitChanged = true; let limitSetter = Setter.NONE; @@ -150,7 +152,7 @@ function renderUpperLimit() { g.setColor(g.theme.fg); } g.setFontVector(fontSizes.limits).setFontAlign(-1, 0, 0); - g.drawString("Upper: " + upperLimit, + g.drawString("Upper: " + settings.upperLimit, upperLshape.minX, upperLshape.minY+upperLshape.rectWidth/2); @@ -189,7 +191,7 @@ function renderLowerLimit() { g.setColor(g.theme.fg); } g.setFontVector(fontSizes.limits).setFontAlign(-1, 0, 0); - g.drawString("Lower: " + lowerLimit, + g.drawString("Lower: " + settings.lowerLimit, lowerLshape.maxX + lowerLshape.rectWidth/2, lowerLshape.minY - lowerLshape.rectWidth/2); @@ -247,13 +249,13 @@ function buzz() { // Do not buzz if not confident if(hrConfidence < 85) { return; } - if(currentHeartRate > upperLimit) + if(currentHeartRate > settings.upperLimit) { Bangle.buzz(shortBuzzTimeInMs); setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs * 2); } - if(currentHeartRate < lowerLimit) + if(currentHeartRate < settings.lowerLimit) { Bangle.buzz(longBuzzTimeInMs); } @@ -312,11 +314,11 @@ function incrementLimit() { resetHighlightTimeout(); if (limitSetter === Setter.UPPER) { - upperLimit++; + settings.upperLimit++; renderUpperLimit(); upperLimitChanged = true; } else if(limitSetter === Setter.LOWER) { - lowerLimit++; + settings.lowerLimit++; renderLowerLimit(); lowerLimitChanged = true; } @@ -326,11 +328,11 @@ function decrementLimit(){ resetHighlightTimeout(); if (limitSetter === Setter.UPPER) { - upperLimit--; + settings.upperLimit--; renderUpperLimit(); upperLimitChanged = true; } else if(limitSetter === Setter.LOWER) { - lowerLimit--; + settings.lowerLimit--; renderLowerLimit(); lowerLimitChanged = true; } @@ -368,7 +370,7 @@ Bangle.setHRMPower(1,"wohrm"); Bangle.on('HRM', onHrm); g.setTheme({bg:"#000",fg:"#fff",dark:true}); -g.reset() +g.reset(); g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); diff --git a/apps/wohrm/settings.js b/apps/wohrm/settings.js new file mode 100644 index 000000000..6d31688f4 --- /dev/null +++ b/apps/wohrm/settings.js @@ -0,0 +1,35 @@ +(function menu(back) { + const SETTINGS_FILE = "wohrm.setting.json"; + + // initialize with default settings... + const storage = require('Storage'); + var settings = storage.readJSON(SETTINGS_FILE, 1) || { + upperLimit: 130, + lowerLimit: 100 + }; + + function save() { + storage.write(SETTINGS_FILE, settings); + } + + E.showMenu({ + '': { 'title': 'Workout HRM' }, + '< Back': back, + 'Upper limit': { + value: settings.upperLimit, + min: 100, max: 200, + onchange: v => { + settings.upperLimit = v; + save(); + } + }, + 'Lower limit': { + value: settings.lowerLimit, + min: 50, max: 150, + onchange: v => { + settings.lowerLimit = v; + save(); + } + } + }); +}) From 9d180064f54ca3e5decebca46e990a50c9b88661 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Sun, 19 Dec 2021 22:25:18 +0000 Subject: [PATCH 046/489] Pastel: added dependancy on weather, fix issues on a B1, extend support to B1 for Pebble and Widbata --- apps.json | 8 ++++---- apps/pastel/ChangeLog | 1 + apps/pastel/pastel.app.js | 16 ++-------------- 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/apps.json b/apps.json index 909c4793a..214b8b350 100644 --- a/apps.json +++ b/apps.json @@ -4210,10 +4210,10 @@ "id": "pastel", "name": "Pastel Clock", "shortName": "Pastel", - "version": "0.09", + "version": "0.10", "description": "A Configurable clock with custom fonts and background. Has a cyclic information line that includes, day, date, battery, sunrise and sunset times", "icon": "pastel.png", - "dependencies": {"mylocation":"app", "widpedom":"app"}, + "dependencies": {"mylocation":"app", "widpedom":"app","weather":"app"}, "screenshots": [{"url":"screenshot_pastel.png"}], "type": "clock", "tags": "clock", @@ -4733,7 +4733,7 @@ "screenshots": [{"url":"pebble_screenshot.png"}], "type": "clock", "tags": "clock", - "supports": ["BANGLEJS2"], + "supports": ["BANGLEJS", "BANGLEJS2"], "storage": [ {"name":"pebble.app.js","url":"pebble.app.js"}, {"name":"pebble.settings.js","url":"pebble.settings.js"}, @@ -4767,7 +4767,7 @@ "screenshots": [{"url":"screenshot_widbata_1.png"}], "version":"0.01", "type": "widget", - "supports": ["BANGLEJS2"], + "supports": ["BANGLEJS", "BANGLEJS2"], "readme": "README.md", "description": "Shows the current battery level status in the top right using the clocks colour theme", "tags": "widget,battery", diff --git a/apps/pastel/ChangeLog b/apps/pastel/ChangeLog index afeb305c5..627531f03 100644 --- a/apps/pastel/ChangeLog +++ b/apps/pastel/ChangeLog @@ -7,3 +7,4 @@ 0.07: Added info line that cycles on BTN1/BTN3 (or vitual buttons on a bangle 2) 0.08: Added dependancy on MyLocation 0.09: Added dependancy on Pedometer Widget +0.10: Added Weather line, fixed issues on a Bangle 1, update every minute diff --git a/apps/pastel/pastel.app.js b/apps/pastel/pastel.app.js index e0c7df831..db60a2738 100644 --- a/apps/pastel/pastel.app.js +++ b/apps/pastel/pastel.app.js @@ -149,8 +149,6 @@ function getWeather() { return jsonWeather; } -var mm_prev = "xx"; - function draw() { var d = new Date(); var da = d.toString().split(" "); @@ -190,18 +188,8 @@ function draw() { } g.reset(); - - if (process.env.HWVERSION == 1) { - // avoid flicker on a bangle 1 by comparing with previous minute - if (mm_prev != mm) { - mm_prev = mm; - g.clearRect(0, 30, w, h - 24); - } - } else { - // on a b2 safe to just clear anyway as there is no flicker - g.clearRect(0, 30, w, h - 24); - } - + g.clearRect(0, 30, w, h - 24); + // draw a grid like graph paper if (settings.grid && process.env.HWVERSION !=1) { g.setColor("#0f0"); From 6e48dc66f1576a690c54f143b52ae31e053fdd5a Mon Sep 17 00:00:00 2001 From: numerist Date: Sun, 19 Dec 2021 20:47:47 -0500 Subject: [PATCH 047/489] Update app.js --- apps/doztime2/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/doztime2/app.js b/apps/doztime2/app.js index ac67954d3..313ad9e48 100644 --- a/apps/doztime2/app.js +++ b/apps/doztime2/app.js @@ -150,8 +150,8 @@ function writeDozDate(text,def,colour){ g_d.clear(); g_d.setFont("Vector",def.size); for(let i in text){ - if(text[i]=="a"){ g_d.setFontAlign(0,0,2); g_d.drawString("2",x+1+def.dx,y+1+def.dy); } //+1s new - else if(text[i]=="b"){ g_d.setFontAlign(0,0,2); g_d.drawString("3",x+1+def.dx,y+1+def.dy); } //+1s new + if(text[i]=="a"){ g_d.setFontAlign(0,0,2); g_d.drawString("2",x+2+def.dx,y+1+def.dy); } //+1s new + else if(text[i]=="b"){ g_d.setFontAlign(0,0,2); g_d.drawString("3",x+2+def.dx,y+1+def.dy); } //+1s new else{ g_d.setFontAlign(0,0,0); g_d.drawString(text[i],x,y); } x = x+def.step[0]; y = y+def.step[1]; From 1f48b21540706dad021ff6706d0b9d6393afaa94 Mon Sep 17 00:00:00 2001 From: numerist Date: Mon, 20 Dec 2021 11:05:36 -0500 Subject: [PATCH 048/489] Update apps.json --- apps.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 7cc91cae5..d099146ea 100644 --- a/apps.json +++ b/apps.json @@ -4716,8 +4716,6 @@ {"name":"doztime.app.js","url":"app.js"}, {"name":"doztime.img","url":"app-icon.js","evaluate":true} ] -} -] }, { "id":"doztime2", "name":"Dozenal Time 2", @@ -4732,7 +4730,7 @@ {"name":"doztime2.app.js","url":"app.js"}, {"name":"doztime2.img","url":"app-icon.js","evaluate":true} ] -} +}, { "id": "mylocation", "name": "My Location", "shortName":"My Location", From 3ceef9afd5a38054f60f70a9d23bb26035479a35 Mon Sep 17 00:00:00 2001 From: numerist Date: Mon, 20 Dec 2021 15:42:36 -0500 Subject: [PATCH 049/489] Update apps.json --- apps.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps.json b/apps.json index d099146ea..5dc306a6f 100644 --- a/apps.json +++ b/apps.json @@ -4710,6 +4710,7 @@ "description":"A dozenal Holocene calendar and dozenal diurnal clock", "tags":"clock", "type":"clock", + "supports":["BANGLEJS"], "allow_emulator":true, "readme": "README.md", "storage": [ @@ -4725,6 +4726,7 @@ "description":"A dozenal Holocene calendar and dozenal diurnal clock for Bangle.js 2", "tags":"clock", "type":"clock", + "supports":["BANGLEJS2"], "allow_emulator":true, "storage": [ {"name":"doztime2.app.js","url":"app.js"}, From 964fa27bfb9a5b1ef72a612d9b90e0891b21b9b0 Mon Sep 17 00:00:00 2001 From: The Dod Date: Tue, 21 Dec 2021 01:01:10 +0200 Subject: [PATCH 050/489] Add Four Twenty Clock app --- apps.json | 18 ++ apps/ftclock/ChangeLog | 1 + apps/ftclock/app-icon.js | 1 + apps/ftclock/app.js | 52 ++++ apps/ftclock/app.png | Bin 0 -> 6742 bytes apps/ftclock/fourTwenty.js | 45 +++ apps/ftclock/fourTwentyTz.js | 536 +++++++++++++++++++++++++++++++++ apps/ftclock/mkFourTwentyTz.py | 46 +++ apps/ftclock/screenshot.png | Bin 0 -> 17635 bytes 9 files changed, 699 insertions(+) create mode 100644 apps/ftclock/ChangeLog create mode 100644 apps/ftclock/app-icon.js create mode 100644 apps/ftclock/app.js create mode 100644 apps/ftclock/app.png create mode 100644 apps/ftclock/fourTwenty.js create mode 100644 apps/ftclock/fourTwentyTz.js create mode 100644 apps/ftclock/mkFourTwentyTz.py create mode 100644 apps/ftclock/screenshot.png diff --git a/apps.json b/apps.json index e5e9f8f02..3dc4c3577 100644 --- a/apps.json +++ b/apps.json @@ -5062,5 +5062,23 @@ {"name":"ltherm.app.js","url":"app.js"}, {"name":"ltherm.img","url":"icon.js","evaluate":true} ] + }, + { + "id": "ftclock", + "name": "Four Twenty Clock", + "version": "0.01", + "description": "A clock that tells when and where it's going to be 4:20 next", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"ftclock.app.js","url":"app.js"}, + {"name":"fourTwenty","url":"fourTwenty.js"}, + {"name":"fourTwentyTz","url":"fourTwentyTz.js"}, + {"name":"ftclock.img","url":"app-icon.js","evaluate":true} + ] } ] diff --git a/apps/ftclock/ChangeLog b/apps/ftclock/ChangeLog new file mode 100644 index 000000000..9db0e26c5 --- /dev/null +++ b/apps/ftclock/ChangeLog @@ -0,0 +1 @@ +0.01: first release diff --git a/apps/ftclock/app-icon.js b/apps/ftclock/app-icon.js new file mode 100644 index 000000000..297847e95 --- /dev/null +++ b/apps/ftclock/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwghC/AH4A/AH4A/AAMHu4ACuwHBs4HDsEGBIQLCsADBgwPDCAQGEuwXFBwI0GEAMHuAGCCoMHC4pMHEAIXEAgIGEBwI9BC4wSCC8IVCMAwIBs4XKUQJfITQgXCDwp8EHAqaECoLFEu4cDBIggBs6uFZozuGBAVmC4g+FMgZQEZQ5vGC4iRIC5IrDN4h5EC5J3BCoIKGgyaEC44VBC46yEDgoeDgxqLC5SCMAgoTFY47GFC4xFBdwwPBD4oWFAH4A/AH4A/AH4AjA==")) diff --git a/apps/ftclock/app.js b/apps/ftclock/app.js new file mode 100644 index 000000000..1aed8da54 --- /dev/null +++ b/apps/ftclock/app.js @@ -0,0 +1,52 @@ +let getNextFourTwenty = require("fourTwenty").getNextFourTwenty; +require("FontTeletext10x18Ascii").add(Graphics); +let leaf_img = "\x17\x18\x81\x00\x00\x10\x00\x00 \x00\x00@\x00\x01\xc0\x00\x03\x80\x00\x0f\x80\x00\x1f\x00\x00>\x00\x00|\x00\xc0\xf8\x19\xe1\xf0\xf1\xe3\xe3\xc3\xf7\xdf\x83\xff\xfe\x03\xff\xf8\x03\xff\xe0\x03\xff\x80\x03\xfe\x00\x7f\xff\xc0\xff\xff\xc0\x06\xe0\x00\x18\xc0\x00 \x80\x00\x00\x00"; + +// timeout used to update every minute +let drawTimeout; + +// schedule a draw for the next minute +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +} + + +function draw() { + g.reset(); + g.setBgColor("#ffffff"); + let date = new Date(); + let timeStr = require("locale").time(date,1); + let next420 = getNextFourTwenty(); + g.clearRect(0,26,g.getWidth(),g.getHeight()); + g.setColor("#00ff00").setFontAlign(0,-1).setFont("Teletext10x18Ascii",2); + g.drawString(next420.minutes? timeStr: `\0${leaf_img}${timeStr}\0${leaf_img}`, g.getWidth()/2, 28); + g.setColor("#000000"); + g.setFontAlign(-1,-1).setFont("Teletext10x18Ascii"); + g.drawString(g.wrapString(next420.text, g.getWidth()-8).join("\n"),4,60); + + // queue draw in one minute + queueDraw(); +} + +// Clear the screen once, at startup +g.clear(); +// Load widgets +Bangle.loadWidgets(); +Bangle.drawWidgets(); +// draw immediately at first, queue update +draw(); +// Stop updates when LCD is off, restart when on +Bangle.on('lcdPower',on=>{ + if (on) { + draw(); // draw immediately, queue redraw + } else { // stop draw timer + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } +}); +// Show launcher when middle button pressed +Bangle.setUI("clock"); diff --git a/apps/ftclock/app.png b/apps/ftclock/app.png new file mode 100644 index 0000000000000000000000000000000000000000..0553837ca47ff2061105cd49c40a86d8f66d4b7b GIT binary patch literal 6742 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 && current_min<25) { + current_time -= current_min-20; // 5 minutes grace period + } + let offset = 16*60+20-current_time; + if (offset<0) { + offset += 24*60; + } + return offset; +} + +function makeFourTwentyText(minutes, places) { + //let plural = minutes==1? "": "s"; + //let msgprefix = minutes? `${minutes} minute${plural} to`: "It is now"; + let msgprefix = minutes? `${minutes}m to`: "It is now"; + let msgsuffix = places.length>1? ", and other fine places": ""; + let msgplace = places[Math.floor(Math.random()*places.length)]; + return `${msgprefix} 4:20 at ${msgplace}${msgsuffix}.`; +} + +function getNextFourTwenty() { + let offs = get420offset(); + for (let i=0; i2: # e.g. America/North_Dakota/New_Salem + country = parts[1] # e.g. North Dakota + else: # e.g. America/Denver + country = countries[r[1]] # e.g. United States + if country==city: # Avoid awkward searches like "Anguilla, Anguilla" + country = r[1] # Use code instead + zones[int(r[0])] = {"name":', '.join((city,country))} +now = int(time.time()) +for r in csv.reader(open("timezone.csv")): + code = int(r[0]) + if code not in zones: + continue + starttime = int(r[2] or "0") # Bugger. They're feeding us blanks for UTC now + offs = int(r[3]) + if offs < 0: + offs += 60*60*24 + d = zones[code] + if starttime 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 W_a_}>UQb*A0000 Date: Tue, 21 Dec 2021 01:34:30 +0200 Subject: [PATCH 051/489] ftclock README and better screenshots --- apps.json | 3 ++- apps/ftclock/README.md | 16 ++++++++++++++++ apps/ftclock/mkFourTwentyTz.py | 4 ++-- apps/ftclock/screenshot.png | Bin 17635 -> 15457 bytes apps/ftclock/screenshot1.png | Bin 0 -> 19973 bytes 5 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 apps/ftclock/README.md create mode 100644 apps/ftclock/screenshot1.png diff --git a/apps.json b/apps.json index 3dc4c3577..6a9fc7309 100644 --- a/apps.json +++ b/apps.json @@ -5069,11 +5069,12 @@ "version": "0.01", "description": "A clock that tells when and where it's going to be 4:20 next", "icon": "app.png", - "screenshots": [{"url":"screenshot.png"}], + "screenshots": [{"url":"screenshot.png"}, {"url":"screenshot1.png"}], "type": "clock", "tags": "clock", "supports": ["BANGLEJS","BANGLEJS2"], "allow_emulator": true, + "readme": "README.md", "storage": [ {"name":"ftclock.app.js","url":"app.js"}, {"name":"fourTwenty","url":"fourTwenty.js"}, diff --git a/apps/ftclock/README.md b/apps/ftclock/README.md new file mode 100644 index 000000000..ed3b7b3bd --- /dev/null +++ b/apps/ftclock/README.md @@ -0,0 +1,16 @@ +# Four Twenty Clock + +A clock that tells when and where it's going to be [4:20](https://en.wikipedia.org/wiki/420_(cannabis_culture%29) next + +![screensot](screenshot.png) ![screenshot at 4:20](screenshot1.png) + +## Note + +Once in a while, there'd be updates to the [timezone database](https://timezonedb.com/download) which +would require updating `fourTwentyTz.js`. I'll do my best to release a new version every time this happens, +but if you ever need to do this yourself, just run `python mkFourTwentyTz.py` (after downloading the timezone CSV files. +See comment at the top of the script). + +## Creator + +[Nimrod Kerrett](zzzen.com) diff --git a/apps/ftclock/mkFourTwentyTz.py b/apps/ftclock/mkFourTwentyTz.py index 4de17c3cf..713b68059 100644 --- a/apps/ftclock/mkFourTwentyTz.py +++ b/apps/ftclock/mkFourTwentyTz.py @@ -1,4 +1,4 @@ -# Generates tz.js[on] from time zone csv files +# Generates fourTwentyTz.js from time zone csv files # get latest files from https://timezonedb.com/download import csv,json,time,os,math countries = {} @@ -35,7 +35,7 @@ for k in zones: continue offsdict[d["offs"]] = offsdict.get(d["offs"],[])+[d["name"]] res = sorted([[k,sorted(offsdict[k])] for k in offsdict],key=lambda x:-x[0]) -js = open("tz.js","w") +js = open("fourTwentyTz.js","w") js.write("// Generated by mk420tz.py - see https://github.com/thedod/BangleApps/420clock\n") js.write("// (version: {0})\n".format(time.ctime(time.time()))) js.write("// Data source: https://timezonedb.com/files/timezonedb.csv.zip\n") diff --git a/apps/ftclock/screenshot.png b/apps/ftclock/screenshot.png index e04f766463b05d0ff9826cbc8b8f10c1034d8307..9247e0e04a55b533955a24369e4d29d293f3b38d 100644 GIT binary patch literal 15457 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 X3LR-t-PP6E00000NkvXXu0mjf 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 W_a_}>UQb*A0000 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 ULn*~EGXMYp07*qoM6N<$f|JYjo&W#< literal 0 HcmV?d00001 From d80ebe08ede97b367932925bce540d8ed5a14d33 Mon Sep 17 00:00:00 2001 From: The Dod Date: Tue, 21 Dec 2021 10:56:37 +0200 Subject: [PATCH 052/489] README edit (gh markdown chokes on "(" in url) --- apps/ftclock/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ftclock/README.md b/apps/ftclock/README.md index ed3b7b3bd..665a7693d 100644 --- a/apps/ftclock/README.md +++ b/apps/ftclock/README.md @@ -1,6 +1,6 @@ # Four Twenty Clock -A clock that tells when and where it's going to be [4:20](https://en.wikipedia.org/wiki/420_(cannabis_culture%29) next +A clock that tells when and where it's going to be [4:20](https://en.wikipedia.org/wiki/420_%28cannabis_culture%29) next ![screensot](screenshot.png) ![screenshot at 4:20](screenshot1.png) From 4f16d6ce35cfc3ea49075a5fa0c4d9cda9c67754 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Mon, 20 Dec 2021 11:08:08 +0100 Subject: [PATCH 053/489] wohrm: Refactor renderLshape() rename variables and document renderLshape() --- apps.json | 2 +- apps/wohrm/app.js | 110 +++++++++++++++++++++++++--------------------- 2 files changed, 61 insertions(+), 51 deletions(-) diff --git a/apps.json b/apps.json index 1d4f98c1e..7898ba786 100644 --- a/apps.json +++ b/apps.json @@ -1714,7 +1714,7 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.09-rc7", + "version": "0.09-rc10", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app", diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 26e7b7eae..ab579463c 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -27,30 +27,30 @@ let setterHighlightTimeout; const isB1 = process.env.HWVERSION==1; const upperLshape = isB1 ? { - minX: 125, - maxX: 210, - minY: 40, - maxY: 210, + right: 125, + left: 210, + bottom: 40, + top: 210, rectWidth: 30, cornerRoundness: 5, orientation: -1, color: '#f00' } : { - minX: Bangle.appRect.x2-100, - maxX: Bangle.appRect.x2, - minY: 24, - maxY: Bangle.appRect.y2, + right: Bangle.appRect.x2-100, + left: Bangle.appRect.x2, + bottom: 24, + top: Bangle.appRect.y2, rectWidth: 26, cornerRoundness: 4, - orientation: -1, + orientation: -1, // rotated 180° color: '#f00' }; const lowerLshape = { - maxX: isB1 ? 10 : Bangle.appRect.x, - minX: 100, - minY: upperLshape.maxY, - maxY: upperLshape.minY, + left: isB1 ? 10 : Bangle.appRect.x, + right: 100, + bottom: upperLshape.top, + top: upperLshape.bottom, rectWidth: upperLshape.rectWidth, cornerRoundness: upperLshape.cornerRoundness, orientation: 1, @@ -58,8 +58,8 @@ const lowerLshape = { }; const centerBar = { - minY: (upperLshape.minY + upperLshape.maxY - upperLshape.rectWidth)/2, - maxY: (upperLshape.minY + upperLshape.maxY + upperLshape.rectWidth)/2, + minY: (upperLshape.bottom + upperLshape.top - upperLshape.rectWidth)/2, + maxY: (upperLshape.bottom + upperLshape.top + upperLshape.rectWidth)/2, confidenceWidth: isB1 ? 10 : 8, minX: isB1 ? 55 : upperLshape.rectWidth + 14, maxX: isB1 ? 165 : Bangle.appRect.x2 - upperLshape.rectWidth - 14 @@ -80,50 +80,60 @@ function fillEllipse(x, y, x2, y2) { Math.max(y, y2)); } +/** + * @param p.left: the X coordinate of the left side of the L in its orientation + * @param p.right: the X coordinate of the right side of the L in its orientation + * @param p.top: the Y coordinate of the top side of the L in its orientation + * @param p.bottom: the Y coordinate of the bottom side of the L in its orientation + * @param p.strokeWidth: how thick we draw the letter. + * @param p.cornerRoundness: how much the corners should be rounded + * @param p.orientation: 1 == turned 0°; -1 == turned 180° + * @param p.color: the color to draw the shape + */ function renderLshape(p) { g.setColor(p.color); - g.fillRect(p.minX, p.minY, p.maxX, p.minY-p.orientation*p.rectWidth); - g.fillRect(p.maxX+p.orientation*p.rectWidth, - p.minY-p.orientation*p.rectWidth, - p.maxX, - p.maxY+p.orientation*p.cornerRoundness*2); + g.fillRect(p.right, p.bottom, p.left, p.bottom-p.orientation*p.rectWidth); + g.fillRect(p.left+p.orientation*p.rectWidth, + p.bottom-p.orientation*p.rectWidth, + p.left, + p.top+p.orientation*p.cornerRoundness*2); //Round end of small line - fillEllipse(p.minX+p.orientation*p.cornerRoundness*2, - p.minY, - p.minX-p.orientation*p.cornerRoundness*2, - p.minY-p.orientation*p.rectWidth); + fillEllipse(p.right+p.orientation*p.cornerRoundness*2, + p.bottom, + p.right-p.orientation*p.cornerRoundness*2, + p.bottom-p.orientation*p.rectWidth); //Round outer corner g.setColor(g.theme.bg); - g.fillRect(p.maxX+p.orientation*p.cornerRoundness, - p.minY, - p.maxX, - p.minY-p.orientation*p.cornerRoundness); + g.fillRect(p.left+p.orientation*p.cornerRoundness, + p.bottom, + p.left, + p.bottom-p.orientation*p.cornerRoundness); g.setColor(p.color); - fillEllipse(p.maxX+p.orientation*p.cornerRoundness*4, - p.minY, - p.maxX, - p.minY-p.orientation*p.cornerRoundness*2); + fillEllipse(p.left+p.orientation*p.cornerRoundness*4, + p.bottom, + p.left, + p.bottom-p.orientation*p.cornerRoundness*2); //Round inner corner - g.fillRect(p.maxX+p.orientation*(p.rectWidth+p.cornerRoundness+1), - p.minY-p.orientation*(p.rectWidth+1), - p.maxX+p.orientation*(p.rectWidth+1), - p.minY-p.orientation*(p.rectWidth+p.cornerRoundness-1)); + g.fillRect(p.left+p.orientation*(p.rectWidth+p.cornerRoundness+1), + p.bottom-p.orientation*(p.rectWidth+1), + p.left+p.orientation*(p.rectWidth+1), + p.bottom-p.orientation*(p.rectWidth+p.cornerRoundness-1)); g.setColor(g.theme.bg); - fillEllipse(p.maxX+p.orientation*(p.rectWidth+p.cornerRoundness*4), - p.minY-p.orientation*(p.rectWidth+1), - p.maxX+p.orientation*(p.rectWidth+1), - p.minY-p.orientation*(p.rectWidth+p.cornerRoundness*3-1)); + fillEllipse(p.left+p.orientation*(p.rectWidth+p.cornerRoundness*4), + p.bottom-p.orientation*(p.rectWidth+1), + p.left+p.orientation*(p.rectWidth+1), + p.bottom-p.orientation*(p.rectWidth+p.cornerRoundness*3-1)); //Round end of long line g.setColor(p.color); - fillEllipse(p.maxX+p.orientation*p.rectWidth, - p.maxY+p.orientation*p.cornerRoundness*4, - p.maxX, - p.maxY); + fillEllipse(p.left+p.orientation*p.rectWidth, + p.top+p.orientation*p.cornerRoundness*4, + p.left, + p.top); } function drawTrainingHeartRate() { @@ -153,8 +163,8 @@ function renderUpperLimit() { } g.setFontVector(fontSizes.limits).setFontAlign(-1, 0, 0); g.drawString("Upper: " + settings.upperLimit, - upperLshape.minX, - upperLshape.minY+upperLshape.rectWidth/2); + upperLshape.right, + upperLshape.bottom+upperLshape.rectWidth/2); upperLimitChanged = false; } @@ -170,8 +180,8 @@ function renderCurrentHeartRate() { g.setFontVector(fontSizes.heartRate); g.setFontAlign(1, 0, 0); g.drawString(currentHeartRate, - Math.max(upperLshape.minX+upperLshape.cornerRoundness, - lowerLshape.minX-lowerLshape.cornerRoundness), + Math.max(upperLshape.right+upperLshape.cornerRoundness, + lowerLshape.right-lowerLshape.cornerRoundness), (centerBar.minY+centerBar.maxY)/2); //Reset alignment to defaults @@ -192,8 +202,8 @@ function renderLowerLimit() { } g.setFontVector(fontSizes.limits).setFontAlign(-1, 0, 0); g.drawString("Lower: " + settings.lowerLimit, - lowerLshape.maxX + lowerLshape.rectWidth/2, - lowerLshape.minY - lowerLshape.rectWidth/2); + lowerLshape.left + lowerLshape.rectWidth/2, + lowerLshape.bottom - lowerLshape.rectWidth/2); lowerLimitChanged = false; } From d0eb56597670be1db6905d66a436cbbe84d4153d Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Fri, 24 Dec 2021 12:31:00 +0100 Subject: [PATCH 054/489] grocery: Prepare porting to BJS2 --- apps.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index e5e9f8f02..261c9aeb7 100644 --- a/apps.json +++ b/apps.json @@ -1749,8 +1749,9 @@ "icon": "grocery.png", "type": "app", "tags": "tool,outdoors,shopping,list", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS", "BANGLEJS2"], "custom": "grocery.html", + "allow_emulator": true, "storage": [ {"name":"grocery.app.js","url":"app.js"}, {"name":"grocery.img","url":"grocery-icon.js","evaluate":true} From 165d1f7b999079aaf98d18ab09b5abdc681f68db Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 24 Dec 2021 12:44:06 +0000 Subject: [PATCH 055/489] Pastel: updated README and screenshots --- apps.json | 4 +-- apps/pastel/README.md | 46 ++++++++++++++++++++++++------ apps/pastel/screenshot_pastel.png | Bin 4014 -> 2993 bytes apps/pastel/weather_icons.png | Bin 0 -> 1506 bytes 4 files changed, 39 insertions(+), 11 deletions(-) create mode 100644 apps/pastel/weather_icons.png diff --git a/apps.json b/apps.json index 214b8b350..a3f2788ee 100644 --- a/apps.json +++ b/apps.json @@ -4214,9 +4214,9 @@ "description": "A Configurable clock with custom fonts and background. Has a cyclic information line that includes, day, date, battery, sunrise and sunset times", "icon": "pastel.png", "dependencies": {"mylocation":"app", "widpedom":"app","weather":"app"}, - "screenshots": [{"url":"screenshot_pastel.png"}], + "screenshots": [{"url":"screenshot_pastel.png"}, {"url":"weather_icons.png"}], "type": "clock", - "tags": "clock", + "tags": "clock, weather, tool", "supports": ["BANGLEJS","BANGLEJS2"], "readme": "README.md", "storage": [ diff --git a/apps/pastel/README.md b/apps/pastel/README.md index 66ae0e189..7dbfbe9a1 100644 --- a/apps/pastel/README.md +++ b/apps/pastel/README.md @@ -1,45 +1,73 @@ # Pastel Clock - *a configurable clock with custom fonts and background. Has a cyclic information line that includes, day, date, battery, sunrise and sunset times* + *a configurable clock with custom fonts, background and optional weather icons. Has a cyclic information line that includes, day, date, battery, sunrise and sunset times* * Designed specifically for Bangle 1 and Bangle 2 * A choice of 7 different custom fonts * Supports the Light and Dark themes -* Has a settings menu, change font, enable/disable the grid +* Has a settings menu, change font, enable/disable the grid, weather icons * On Bangle 1 use BTN1,BTN3 to cycle through the info display (Date, ID, Batt %, Ram % etc) * On Bangle 2 touch the top right/top left to cycle through the info display (Date, ID, Batt %, Ram % etc) * Uses mylocation.json from MyLocation app to calculate sunrise and sunset times for your location * Uses pedometer widget to get latest step count +* Use the wesather widget to get weather status * Dependant apps are installed when Pastel installs I came up with the name Pastel due to the shade of the grid background. Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) -## Lato + +## Weather Support + + +![](screenshot_pastel.png) + +Pastel installs the weather app and weather widget. You may want to +hide the weather widget display, this can be done through the weather +widget settings. You should first get the weather app working. If +the weather App is not working, then it is not going to work for +Pastel. + +The following weather icons are supported. + +![](weather_icons.png) + +Mostly cloudy, Sunny, Mostly Sunny, Snow, Rain. + +The triangle icon shows there is a problem connecting to GadgetBridge and the weather service. +You should follow the setup and trouble shooting guide for the Weather App. + +If you find the weather / gadgetbridge service unreliable you can +disable weather updates to pastel through the settings app. + + +## Fonts + +### Lato ![](screenshot_lato.png) -## Architect +### Architect ![](screenshot_architect.png) -## Gochihand +### Gochihand ![](screenshot_gochihand.png) -## Monoton +### Monoton ![](screenshot_monoton.png) -## Elite +### Elite ![](screenshot_elite.png) -## Cabin Sketch +### Cabin Sketch ![](screenshot_cabinsketch.png) -## Orbitron +### Orbitron ![](screenshot_orbitron.png) diff --git a/apps/pastel/screenshot_pastel.png b/apps/pastel/screenshot_pastel.png index d489f19143b598f426b309b2e07904b222d1108f..c792ada8d932feabe3eba3feed17b61de7ed87c5 100644 GIT binary patch literal 2993 zcmc(h={M938^?dY8H}YwOxZ>vnLA}4TXtiRrA!#x43$s{*#~7*vW~cwB14v2s~KW$ zWSgFlijj4!6Oy4ZOm=eT@%#tRInRsdI_J7R=X}rkyt!U|)6O~D?iZC41pr{by&W36 z$EyFVu+ZM6)y)w007hVKtpF-hVIBa)g6+|kuCW9jWh{KgP#n$L-R)%~Lto+C&!eZ0 z=U6cN+oS~{`6&{|9+~=n-J9Jhb63Cff-S=Q3Z^#ih@h~RrLfy1m#ePFHX07{P-0vO z-`KZf%)mlMbBNMQa@M2gjgvocIEL^0>BZQap(*_+~53-rYL{kHFOs{_S4`az~iYxtCRqun#fkz^Y)JtaKFV;q$3ia%f7a}Mgyq=n2rAt>Q*tNZ#b~`%4nCF?<^7G*A12GyXkUNSnH*0moe8ceS!Le zQInz>DKr#Kc=1cw=IW7!H*bah3~omW#Oi!izPDnkRf?sc%*{LNPorXJt$K)I9pl2r zR`;tjrhH_@>bV!)ceuqaexg+mZu`F#Vn6q8xO^+`M|R{SXXy|AhV94Ek>rZjK)IOT zt&kn7(^rPQKu8n)rehJ1n^Xx`Vt9{zm=V#E{jcI6!K&5D#!AYyf&_U|j;4C$vY={r z-DbA$RQ_PgneL$#7Q|0Pcs}A){Sa4g%MMV1ZRB#ON{?V3I-8_@_`u|Y&5NRi0(rB) zdf>Yn3ZPle+IptR_QObZMuA3_A{EYhDC9Bb_SaaYK<Qta==mabf%kc? zM(}4a;SeE0tXVhn3zZyxg~ZA$8nHoIkW^g#Gg;C~44QopS!IusCv-Z3MI|O#<(v-5 zJqp8Rzo7($`N4e=--HE)!|tYM{w#n9Y@+5HZrp_k7+TqM#5#eHor2YILn{!XP@;UP zsR96RImLx2lvo%u@>^#^;C}6ewe<0u{foTN9#aa=kda5z3dm@==V6Quax!2B4ha)L+TL)vNPC=nh}|h?7EgO#X`pGq=v9sv zdozAjvZ}PpcKy@K3vSmDa2@b(X5jOUR#Ivwwa*pb!I_kmB9{VmyZy)Rz9e0Od%R7Yj@tD{7M2A1z09W4 z#qb~E3xYhRW9az49NmingT-(b_wxcDGbb+;hQ=*R&ot9jgGKp9?qWs3~C-rs5G_xqLSdM%2|^%pmJUv9o>F+1sL{rHLkvGcP@8(ARt zu9d|Q>9p>I9PFd^t415^%VNE`P^K*n@lE;bs>2fo&C z&-idg)S(3K>t{wvlEJ!DgPBr8UMHPOU16BXhv+{q+OfR5R|p%@P5IyM+KlM{w(>HF z95u8Gw;G;28S> zlME1jhPoOyfAohej;oRAx}vvehfSH)Pw5MpiK-)*PGUOHetNf ze<1&*cwv6wAd(w}Y#aHh9>sPv3po($3R`D0UqAJrc_Stl-hSCeaoL@o6G^(x`E_AS zYo2vWDw@3KId1obFuYMU4%;_0wHDz~kW8l-mhw|&aPLjDO(V9l_yKyTRUqHE>H)vH zVSs3ojfNbS{d`^uLX$p%A}kA$RjMT#dXQ?m4D7TVhzUNGTsG^Ks4m;kXlFD&sEX$d zt}Mo7Fk3^Wa&g6}1om4WAkcC_5+x;YO!G=&&(zNX#2_+Tds!qlakGZWC^-LIQZWgg zu4Z`*zohLo+9<}5G*dR)d&^*&N=BZARhwlXvHJoQQdJ&W{z#YhF8~v&UbI+|#LT@f z=p!&aIP1&3ehVJ^9+NsRBD-(vEQRSp=*(^T{^G%bhI6PQsmfKpb=>0jyQJ zlbb+2c@QP0%0S(`ejW~nT#D+p5(#ti9dorIjd|c}&OvjN#-&y9cm zUVGXvTx|twf&QSzXAL>5EH*rGr`&XaUL&5ceVY0>DbONrNtnY-TpVu9g4wZEZBs|a zV*_7vI{oA5EV=tf3ci0#Vs2J4=ZA+Dv$?rZ~=SU%Z6o2hr z@aQt;wDKNx8x*aPLW`mO-M3dz6@zt*XH)U6_+R-ef0pR_o PiUamG&Sh$~K5uQkuL!te52-`kE&MoXgQ+6$%% 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 diff --git a/apps/pastel/weather_icons.png b/apps/pastel/weather_icons.png new file mode 100644 index 0000000000000000000000000000000000000000..59d4f007f51ed9a607e3765edbf0c5fb525ee619 GIT binary patch literal 1506 zcmb7E`#;kQ0Nr;sn-Nx_&08uZ2}!19=CQehqGb_RM-ELDNc`9@cz2 zn4J^tmbFJdmv~6ttTcAR-0#08;QE}Ecc%y8N^ezi8vSyRRYCekHZD+eV?Qqfh37`r z1}S{fb<|Nu?eN`4we>lSvQ&y)Ip+~9?>ac^Y%0gaoa?>a9d@X=0U;8wH1D1_1mx zcD`##=gN7X{gxI|bMBDJ>5JC{%`d9cTX^y|`ImgWRKV7CAmjcZ23@k@GJsL1Ck3v3 zIb?sH-6;_*JTrXTd+u37A(BcT$Fo3@--_=^prRvw?S>NC;{z|)3JT?Jp^BBo!FaR) z8g$YhJ)G&PnP#aa$c{2RxLoqsj!F1hpgSISpM`=W3*QzCa#$V(vopO17t+$hPPUTx zNUQBhnD2C|Joi>F3yV5&TWTP9d2NDaX3q})60veR1<$TpgIQ3ds2GYFn--K20fzaT z*T+bf`X&?hm0D>xq_P5AHGh0pR&5Pjt&GdPL5ku!Db#RY#_grsx>`ggO2$e{x4isB z3kZ#xYlvrv!2>WBGGsz?eOQ7acp4LYhjrDNz3Cx<5jsYyc4iTjt`ZwFk2Cwp0a3aJ z_lEm8<*@dY4$A4)gEm~V?hMPR!{=-P!<`Fx6*mC(8II(#H|INWb#xj#Vv3WA(;_Mm zvCG=aqo0_%C|L!Rts1vk!`FQf@)hVn3mfK`&U?SQ+z z3ny&6AA&~RojcdD7L38y{Ym!dgpE@ydk#5uw^5=yN=q(%ay!`%dEQ*hIdFT9ni!Q) zrDkIrv0-DZxDvS*GZGnoz3BMF`*=e|@PwO|Q3J1&YUW}>HA@|_pLsZ=2$p%!hQT4% zorGefaU82OLDc0D!z$iBHoik0cwn^nsuNY=`nLP*YS#1DPZ)OV080V8GLp_&zd1p2-ouq(65%cB;arr`x1h8dPZKiwDJSHES>lN+WiYxY> zc63qWCnsHuG&jY?42KY+aV{x3+H`Pa9P~Xk`qxpve&M?5F)R^Yx0s; zQy5Ml&1-vi%*qiP0>JrV$%9jSGhPQgX^fdxcVK|xm04QKf2>6TrZAno04D>?uXK1L z&8`s4T0KIqgOK`Uruh!%Myguu{ErlMzC>ej z+oPJ*Kvk`ey$B10{|fgRhm@wd-r>6MgRO7oO-;KH!me;M@`E+KHUPgnu@>tAv8wuMv0zM(l`Z=b=dnNgclvheqyc}C zo-#Le$*(I~emXZ%LCWftQ55mh;xC)+9cM>2Ml-fd=4e>AP(dO4?UQC?gPlL>Kmmy1 z035ZpZk)AsGo9QtpZ*Oxwdy#A!2{eB#n6S&{}(-dM6aI-QY|w0@4G>s?mlj9_^_;h E0d)$;RR910 literal 0 HcmV?d00001 From 39adcc7fa6a5c399361b8ebfd347d4d5c558b815 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 24 Dec 2021 13:00:31 +0000 Subject: [PATCH 056/489] Pastel: updated README and screenshots --- apps.json | 2 +- apps/pastel/README.md | 12 +++++++++++- apps/pastel/screenshot_grid.png | Bin 0 -> 3921 bytes 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 apps/pastel/screenshot_grid.png diff --git a/apps.json b/apps.json index a3f2788ee..8a0d86b97 100644 --- a/apps.json +++ b/apps.json @@ -4211,7 +4211,7 @@ "name": "Pastel Clock", "shortName": "Pastel", "version": "0.10", - "description": "A Configurable clock with custom fonts and background. Has a cyclic information line that includes, day, date, battery, sunrise and sunset times", + "description": "A Configurable clock with custom fonts, background and weather display. Has a cyclic information line that includes, day, date, battery, sunrise and sunset times", "icon": "pastel.png", "dependencies": {"mylocation":"app", "widpedom":"app","weather":"app"}, "screenshots": [{"url":"screenshot_pastel.png"}, {"url":"weather_icons.png"}], diff --git a/apps/pastel/README.md b/apps/pastel/README.md index 7dbfbe9a1..b396386af 100644 --- a/apps/pastel/README.md +++ b/apps/pastel/README.md @@ -8,10 +8,13 @@ * Has a settings menu, change font, enable/disable the grid, weather icons * On Bangle 1 use BTN1,BTN3 to cycle through the info display (Date, ID, Batt %, Ram % etc) * On Bangle 2 touch the top right/top left to cycle through the info display (Date, ID, Batt %, Ram % etc) +* The information display will cycle on each screen update * Uses mylocation.json from MyLocation app to calculate sunrise and sunset times for your location * Uses pedometer widget to get latest step count -* Use the wesather widget to get weather status +* Use the weather widget to get weather status * Dependant apps are installed when Pastel installs +* The screen is updated every minute to save battery power +* The weather display will display temperature and wind speed on alternate screen refreshes I came up with the name Pastel due to the shade of the grid background. @@ -71,3 +74,10 @@ disable weather updates to pastel through the settings app. ### Orbitron ![](screenshot_orbitron.png) +### The Grid + +Setting the grid on provides a graph paper style background to the App. +The grid is not supported on a Bangle 1 due to flicker issues. + +![](screenshot_grid.png) + diff --git a/apps/pastel/screenshot_grid.png b/apps/pastel/screenshot_grid.png new file mode 100644 index 0000000000000000000000000000000000000000..7b993353b533d4ceab374d6cd7272133aa740597 GIT binary patch literal 3921 zcmd5<*H_bv(*30n3C&PM5JZY}kQht=rAw14C^Z6+5|HjejtYbX5o-WxL4y=U5s}`4 z(n2|cAmku5att{HkrJ9z!NBEP>wCNZzx&u)r|^004w9*jTt6 zVAcNxKkOh^(x!b502J+FZ4Oin$j$-4VZjR)W|wdIEapv6I2uA0P5b*r(Qc?k+513g z#@&?b{hTwfw{@am-=Dj;4CPFARQXPo(kp@1;OT%(I}k_<;c{e~$8%VWob)XBK+rp< zTZ6jaK*FTyl+X2hv4pBcJ^RhEl-d1!{hvOO*Kr1ODZ>kEN)YTyM3VeRPeS&A!tTB{ zsff4sqWQ;>xN)t1yJW8`gFxKb5YPxDW}ik$mwZ}jp5T77xL1N3zQpMvU_hg>9N~d9uAC%kg_n+eE?>P^;%e+6%Gpa0pldaMz6QNi z>GdZPSXRALqjTu$tBo^&Qumc$%6W`Sd2BsJAx`ieNo_7uae~ zYN_(b)mtw99LhMJ7(kG7&e+(A&od`O#{~s50*!#U#jB9pW1DW$QiI98^p<`JFG$?g z>WW&tL9H{HzcjS%hzATO*x|EM9-7X*5;0X~%*R0=38o;@g~$UP^BKTDlBe{N(Q{03 z!Rg^Cs)EnN{3$wR!A-c=hk^ezYGH;clw7AQ?(E76G)F2Id5V`4e?&RCl~s`Bf_;rT z9`CA>jvii_UxKqol$slf;9ILeY+B~ndAywkW* zpZnFlk4gxyCFj##_|wPKg9Pc~wt^iFsCSMP#(U3@SB*Fnj9!6Id<7!U5*(kI@AL&z-qzZBqsneHeZQ?W`nkwqmXJq z!~zQ(>WYhy+z(;f7_48Nyur>#ILmBRDobYzZ>y(8Dnd`vB&x|=JwkdXU;d}R!&h? zW_bQ;8z1DSwFl7g`|Y(T+-)=$qc}xz22C2OkF1A4NRIj z>q>*^p=%*I;l5l61I>`cgx;|n#Xtx(#*PG;S@=>2?hC{7I|F$DeKMHG%S6J^^c7q1S`BsR5 zFN)nJ5EkwcG?k74P9M3yGI`?sa=WA_{5ZRlu&-XeYCYBv@^(Fq7ra~67~u5aA6?PW z9p^<|;)n1C-@)^Q-2NrAYM)Y=RZXUKw{rodl<5~}KWx1m8R4-r%sn4ox_SIJ{B9=* z@B6Y2{NbUP*x)0tA9iyk1UjNp#f?}}Pz17CH032UobPKO6x;{G3}pJF-1f;2${Siv zh#CIOx!~+;4UkifT$U@3?fl!`>i@5CQlW@7VAU<9T$+8FdA)q^B2gD))g3^n|Ed%$ z(nl{FVhMGV*JL|&+c7T~#zBGc-zWj0=Iio)-L<6ky_Q_|7u_g!Q?r(Q34OF$?5k6` z<71#BY)VRIOMD=-AjnXsuqUP;n!^`$uTu%II=tz;JGl3x@UsB2GiQPd1&v@y_q9YkSmxMvwbCud0#!6=ELw}fcd$_h4%fTjk zMrLxdKK?uqv5^>1)}wx5G3b*Qwn7Otrxt07K-@Og*&mO0`)5jEO?Vf zCD@phh)6^V9U|c>veWe^xBIwCH3|7g=_5cL~U>ErmVmU=BcZa!oYJ7GSofPT%K2lLjDmR zBc^Qr9FClFibNfUAtAC;5<@3)Q(73cs2{zQv}eka)D2Oonw^^8*8ca#?XwZ+Lrm(C z>r3;%mTAvDJ;4uKkH7)Z67=9E1psU1U49p*I_%z0U1^GNmO&|4g;h)S?3{zHIL!== zmwX?M^R{kb1Tt4O+??Nl7g5}vSq@qpoDkqE5bTtLprp7R%fgop6WP8u*?13K`xiWggZNB7RP3}2a=0?=K^tb5ju)-oNB~sfTlertdQi6L?!z?uIxox; z=)t-=Nzhev@b54G29ucIKa9vFzVws>XPy{2{E*LYK^uisl+2tnt{F0u))&NKE{)n& zk&`q}s({CDeJ>FbQS`u@rpu>7Z%*pX$Gw^f>J#fKeyxjy@GH6r7YCb4%UE}kgAp5g zahX=~u9FkrKfw z(F!L@KbM_eXlQ8(Snd4eHj1j*?jo=rB++w<8)pP60XYB(7J>jDZkJ>u$lBV$PvDQY zlg2wp6PnKualIJN&4bSJx%w8+w8kE^_U^@8Xcg}t6;wMEX&zeXuqyTr_z1PUK|RK1 zIe%rX%-**_8bHc5BClfGr9C0K^+<5f*cT$ZTETDfnzWQ9K9(fYw#YWJ?JG@;gDcj& z=&xZ=r)PaEfFj+uBdNbPpQ5iw%F{sGSvRN3)KEm)7T7*A9?NdgZXJ51i3lI4G5OSB z7sMt!O;=WjKW0Q^C3@E=u6nh?Hr0Z(2Om^TG|r|-est_JF4bW-oB@Bbe)+dbD%_0K ziCX@4+XXl^Q~;_5PTl(aS-vu*=NqYSGv~LksAfyR$4;-sC!gx=g~Q;)XXIzXQJm;< zep$2wAJX=#Z|)JdI=`-@r-UE?K!SV>`?Ni|E1fbkVQ2;Fx0h_ z6%oTb*b?!db>i<%hxVsN=Iz&L92jbiKpQm z0yvHM-U9^`k7>vIx-8=hP)LIpORyg9o&XMHua2B}q;^pF7A8qQiL8ZVb~9r2c7L~B zG{3VQlD{sOWw0LooYmwrI@u3$j3CW6K5Lv~zb}^5wHy0^KGYg?GZ=o=i2i%@_i7tB z495BxobYRAc}|s)>4XmR+|^o7-@AC+*Pqu?+kItiZ~h|Z>NfRH%93`QC^3$j2aa+g z<;;M`rR)S_WkVw|!~e zBEe!;Gv?adaEQB#Tpwd`xrER!lrX(UmozjYh1#*Li!m&oU;dtTTj?6e_H=^I$o4-8KNXW?=vv+wIkHk%A9aa(@f*TzR3Del+Yw%5L8v{#? zLjxh?(Yy9lA(}QD_e7$&BUGtiVm^1b6@Sye>rw}y-0xMJ?-(O1F|OVZt)D7{GYbm; z`SjBl4TFaL{ZjYiwD%6gvu)=N>8$PQMu5V?#UEim)i*_F=fdj!-yKtPQ{j$$4J1k$ z`jD7M3ddTnykv5B>#u35K)ohtFB3kAy}Tb4ezbp>zUx&k5cS>vW($`!;av-0V``69 zEQ#iWo@YC@0(=PK5JMirOMJ^V)Yx}k)TQ6bbZYr&>_7;Wz|HF&8ExQ(xTM Date: Sat, 25 Dec 2021 23:58:46 +0100 Subject: [PATCH 057/489] added ISO weeknumber * update changelog, screenshots and readme * created a settings dialog --- apps/ffcniftya/ChangeLog | 1 + apps/ffcniftya/README.md | 5 +++ apps/ffcniftya/app.js | 37 +++++++++++++------ apps/ffcniftya/ffcniftya.settings.js | 25 +++++++++++++ apps/ffcniftya/screenshot_nifty.png | Bin 3487 -> 52362 bytes apps/ffcniftya/screenshot_settings_nifty.png | Bin 0 -> 46504 bytes 6 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 apps/ffcniftya/ffcniftya.settings.js create mode 100644 apps/ffcniftya/screenshot_settings_nifty.png diff --git a/apps/ffcniftya/ChangeLog b/apps/ffcniftya/ChangeLog index 18bc264a3..bf70a213b 100644 --- a/apps/ffcniftya/ChangeLog +++ b/apps/ffcniftya/ChangeLog @@ -1 +1,2 @@ 0.01: New Clock Nifty A +0.02: Shows the current week number, can be disabled via settings "" diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index f1fee9b1f..5ec8ab681 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,4 +1,9 @@ # Nifty-A Clock +## This is the clock ![](screenshot_nifty.png) +## The week number can be turned On/Off via settings +![](screenshot_settings_nifty.png) +default is "On" + diff --git a/apps/ffcniftya/app.js b/apps/ffcniftya/app.js index 31742f64a..33722b3a3 100644 --- a/apps/ffcniftya/app.js +++ b/apps/ffcniftya/app.js @@ -1,5 +1,6 @@ const locale = require("locale"); const is12Hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"]; +const CFG = require('Storage').readJSON("ffcniftya.json", true) || {showWeek: true}; /* Clock *********************************************/ const scale = g.getWidth() / 176; @@ -16,6 +17,18 @@ const center = { y: Math.round(((viewport.height - widget) / 2) + widget), } +function ISO8601_week_no(date) { //copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480 + var tdt = new Date(date.valueOf()); + var dayn = (date.getDay() + 6) % 7; + tdt.setDate(tdt.getDate() - dayn + 3); + var firstThursday = tdt.valueOf(); + tdt.setMonth(0, 1); + if (tdt.getDay() !== 4) { + tdt.setMonth(0, 1 + ((4 - tdt.getDay()) + 7) % 7); + } + return 1 + Math.ceil((firstThursday - tdt) / 604800000); +} + function d02(value) { return ('0' + value).substr(-2); } @@ -29,23 +42,25 @@ function draw() { const minutes = d02(now.getMinutes()); const day = d02(now.getDate()); const month = d02(now.getMonth() + 1); - const year = now.getFullYear(); - - const month2 = locale.month(now, 3); - const day2 = locale.dow(now, 3); + const year = now.getFullYear(now); + const monthName = locale.month(now, 3); + const dayName = locale.dow(now, 3); + const centerTimeScaleX = center.x + 32 * scale; g.setFontAlign(1, 0).setFont("Vector", 90 * scale); - g.drawString(hour, center.x + 32 * scale, center.y - 31 * scale); - g.drawString(minutes, center.x + 32 * scale, center.y + 46 * scale); + g.drawString(hour, centerTimeScaleX, center.y - 31 * scale); + g.drawString(minutes, centerTimeScaleX, center.y + 46 * scale); g.fillRect(center.x + 30 * scale, center.y - 72 * scale, center.x + 32 * scale, center.y + 74 * scale); + const centerDatesScaleX = center.x + 40 * scale; g.setFontAlign(-1, 0).setFont("Vector", 16 * scale); - g.drawString(year, center.x + 40 * scale, center.y - 62 * scale); - g.drawString(month, center.x + 40 * scale, center.y - 44 * scale); - g.drawString(day, center.x + 40 * scale, center.y - 26 * scale); - g.drawString(month2, center.x + 40 * scale, center.y + 48 * scale); - g.drawString(day2, center.x + 40 * scale, center.y + 66 * scale); + g.drawString(year, centerDatesScaleX, center.y - 62 * scale); + g.drawString(month, centerDatesScaleX, center.y - 44 * scale); + g.drawString(day, centerDatesScaleX, center.y - 26 * scale); + if (CFG.showWeek) g.drawString(d02(ISO8601_week_no(now)), centerDatesScaleX, center.y + 15 * scale); + g.drawString(monthName, centerDatesScaleX, center.y + 48 * scale); + g.drawString(dayName, centerDatesScaleX, center.y + 66 * scale); } diff --git a/apps/ffcniftya/ffcniftya.settings.js b/apps/ffcniftya/ffcniftya.settings.js new file mode 100644 index 000000000..d9a1c9fca --- /dev/null +++ b/apps/ffcniftya/ffcniftya.settings.js @@ -0,0 +1,25 @@ +(function(back) { + var FILE = "\ffcniftya.json"; + // Load settings + var cfg = Object.assign({ + showWeekNum: true, + }, require('Storage').readJSON(FILE, true) || {}); + + function writeSettings() { + require('Storage').writeJSON(FILE, cfg); + } + + // Show the menu + E.showMenu({ + "" : { "title" : "Nifty-A Clock" }, + "< Back" : () => back(), + 'week number?': { + value: cfg.showWeekNum, + format: v => v?"On":"Off", + onchange: v => { + cfg.showWeekNum = v; + writeSettings(); + } + } + }); +}) \ No newline at end of file diff --git a/apps/ffcniftya/screenshot_nifty.png b/apps/ffcniftya/screenshot_nifty.png index 0df056223c087638f940b2095330944c87df9906..3e394dced2b1a7907ff52ce3006ea83bed111d22 100644 GIT binary patch literal 52362 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 AM*si- diff --git a/apps/ffcniftya/screenshot_settings_nifty.png b/apps/ffcniftya/screenshot_settings_nifty.png new file mode 100644 index 0000000000000000000000000000000000000000..a13f6c16f0c70ab52566343e9ce842b57422ce3a GIT binary patch literal 46504 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 literal 0 HcmV?d00001 From 5ad730fb87a50a975a72be55acf766e06e915d45 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 01:04:59 +0100 Subject: [PATCH 058/489] fix settings + added screenshots and changed README --- apps/ffcniftya/README.md | 16 ++++++++++++++-- apps/ffcniftya/ffcniftya.settings.js | 2 +- apps/ffcniftya/photo_nifty.png | Bin 0 -> 52362 bytes apps/ffcniftya/photo_settings_nifty.png | Bin 0 -> 46504 bytes apps/ffcniftya/screenshot_nifty.png | Bin 52362 -> 2379 bytes apps/ffcniftya/screenshot_settings_nifty.png | Bin 46504 -> 1431 bytes 6 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 apps/ffcniftya/photo_nifty.png create mode 100644 apps/ffcniftya/photo_settings_nifty.png diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index 5ec8ab681..122483243 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,21 @@ # Nifty-A Clock +Colors are black/white - photos have non correct camera color "blue" + ## This is the clock ![](screenshot_nifty.png) +[i]emulated[/i] + +![](phptp_nifty.png) +[i]photo[/i] + +## The week number can be turned of in settings +(default is [b]"On"[/b]) -## The week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) -default is "On" +[i]emulated[/i] + +![](photo_settings_nifty.png) +[i]photo[/i] + diff --git a/apps/ffcniftya/ffcniftya.settings.js b/apps/ffcniftya/ffcniftya.settings.js index d9a1c9fca..f4112c9d7 100644 --- a/apps/ffcniftya/ffcniftya.settings.js +++ b/apps/ffcniftya/ffcniftya.settings.js @@ -22,4 +22,4 @@ } } }); -}) \ No newline at end of file +})(load); \ No newline at end of file diff --git a/apps/ffcniftya/photo_nifty.png b/apps/ffcniftya/photo_nifty.png new file mode 100644 index 0000000000000000000000000000000000000000..3e394dced2b1a7907ff52ce3006ea83bed111d22 GIT binary patch literal 52362 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 literal 0 HcmV?d00001 diff --git a/apps/ffcniftya/screenshot_nifty.png b/apps/ffcniftya/screenshot_nifty.png index 3e394dced2b1a7907ff52ce3006ea83bed111d22..de6ba651d3a25034c1fc4006efb5e3ca4dfdc860 100644 GIT binary patch literal 2379 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 Pg(-ultDnm{r-UW|MyW+1 literal 46504 zcmZ^qWmHsO)c@%L>F$sYrKLNS4h4}^K)PYbAp}H}ke2T58ahQ%>6~Hch9L$RVu**| z|NrKB^Q?8xJ?osk&$@5!z2|#Ad+%sH9d*KIbkESx&;7xFI8XQ5mMx2? z4&BQ@T?wsboMHcIfMutst%!zJACG_c5&LP3=lO z?;aitf9!%*+NB^a@Hr&J>7;Su=JAnj!7^lbdT-C(^uq_oA^K7 z%(;-y2rTW|)8o?NX&U&CxU($V9dYIY{0t0j5p9@7PVhIoS-Sf}8$3XPXM8yeC3ZWI z;l1xb*elMk@$&mSyo|aa>eX-yzY$>H#Jw3pn~+T!A(J_#&?oE7T&zU%i?#imPs7IPcHS8SE}} znfv8j;<(pG)s-hMCRXxL{qn_&(a);*{zTt>m+~p(zG)>A{-LV>GhD_mG}nVY^`RWB z>aJ?-9HfPK`IBZU*^W!8TDm9xU$sXcbAkPX}>+dkwcS8|_z9TevB9{4# zrw;1;zRb7tPvM3mwm~SVIAqx{IwZMOe7Sr=p zrZ1yr*IxepJ#~@0Sl?rggwsP{EwH)Zwb)wwD3|vO^EIY3^EKu!Ce%d?<87auJG<^D zzL^ks|HZ_0eu(8AZ=5g-$D*Vyc)uRLRkI`=EHPm zBeluG!Y}?#l!FxY-E_zcIEfFYI62+|Q*5#tgV3b-zYi)deLe}hL0$@&Ezb|v2VbjO zu3FqB?lz@m2kHdgwAr;hUgthc08uWw&AOnqa~A`h^e~1=5@Ji2d^kj8^$)p* zQic2~o&~iyhom(b_w4+E148yF;pukSu!rlb6&RIGsn8Niazd`FYx~hp+qBuW(WpD{ zZS8QyEjC8)a+OWec%qxDYstUA2L`a13$wlJ=a>rx&O?!|A|fJ~OLcsGSarI4tDSox zR}FA@yQb@@3M=a;OJ{61)YumimmSsSF^dCDm9Jb$?A=&J1VuSg(mhAXGM)SAMBYtG z6k)vxVFgCx&stfMty?ghxL^N96lVX8|8>gabooa4{cXWUanu9lxT6w-grFVz>RsV3 zxaEGNwpm-kqjETKiCG*Y8+Rg96O_B)iAf2*D ztb0la_A(n%*;M8ctdP)Fd^t_dsZVpfs&&yq%})NaYbx{o0$o#;5G)!aP>=h{He7`H z-XL(>$zpQ8#uA1+hAj|jF}t_B{(g@du?%twd|VBwHV5_<=OiyywKq07<%#y9O4Omu z_YVLH7_z0M^YYRK7!3aB$QPzfMQsO}xLc-&9(SF?bwhS*o4$+SMVF|Yf3MgJb=I65 zOs`_JE)$C-t{nU29BS=-RGC{7bN*`(Gf>b0k9ARO^B*|+LA_eqEa$}_9b0I%p`FeQ z_wBYwmBd`vo-*G>?{BUKI*&g?li@P0$+V539?I+vESUHa3ZZcz+%rM5j?b~IOMSrg z$g~zy*VaOp#k%}dU!J%=A(ky8jgJLzLa3`7b_Jf-J{pY$R>waB!>r5 zTSED7kA2|K)wXsQiK9B;Nj7m)r9e+T%n$YwUL$>MkgU2tU(>Zy0)&B0Gmw`qX<&L3 zQmbW5pbHH1p2>zIGfyTXq}I9^$Ih&YWv6zC{}S2Q>2`e^=VhBIjF*|;Y4&X~Y>XvI z){pN0jrTX$>&;~=OOo?K&XSmXC6JKfx}I|X#dr-NGPt}YcFT#FYLtK#)% zF=7i;7ds}WqJj)nMm5OGPOhBZrZsJfF>?hvHYaKU*bgh-C6#Q#iP~8r_xw*P?!F+W zhc)ZmFA}vRKC5L&g-Y4i!QYoxqqnaOILEu2RfRDEWo{$F@nzg!oWS5sDibvpw%{nV z?S|FKp4WI7MU9P=*R5n8ZC{*BQcC0AnLIXjNYA398ysNhE-+V6#n2Q4^EHW{a)|GGb%XXa$GcG;}~xh#yEyEG#Q z>4_G$rV^#9=R!FQH>Yd5KL?_=L#|NpW787{Hes1Kdf7aIRkxlqrx2JNk~nwzS;6aS zc^qoc*wSRzQEx-EBK0-{zGsOC9QDgjLK1bj$F~(0u2l#6dHmj~_|(PeA$q+3u7Gvw zJ2=2mgZxu}yO7=_ZVx8lGbA(kC8O_C!3<}s0}`ohMTV5)i}%5w&!<^2EWR$ zZV7E-=qli|wcnV$4=`eZ)X`rtX)&FIwb{EDrX0sW6x}iUxEOIU+7Zj<6HEC^(!KdQN!i)l`bIV8xmE1>K1t%~@mrb}#0 zhtHV)(@r4X+&Cd;p0E?@x?wDw=%AKBmh*0tmKu8 zX4L+m%|EfRN2EOE9bejnM3%H8_Vvp zYSRw2_G)Jl6!Cj5b;~6@bw=h~XX=~~TNF}Uz;!};w=H9mGTLEmafq`BY;9+XK)~zl0DUf z)?3Hp`0563L^F<_xJox`9IZ4P@8^Iu_j6!@%U5d{nh#2*%^$*FNU10j6Ok%YkB>)^ ze-dEsqV$5Yfz_D>TIl==2%E~sLcfR)ae&aPHr^D-&*-y!Z0os&bU@S}&%D}40$l?C z@J&pmmN}3KpQ%CcEj$BIXSt|!B;awA84B`sb|aSS?zpeL3aVjj{AiB4vAp$|u+&kW zci?~q^nXRBgf3HJFW}HUXDG}_VzxFNR83dw1$u6KDwf&)5hIG&c+{0U8K|k zZO|JU2*2y9svA)o@UNbi$pup`H(-iC9z8}?=G}b_yE zkXLlFL|K!33+;JWeb5Ztwe0SJ1&qO7{mST5VP=h!_|W>UvNUM-@5ZyS)2LMcO3yjo z_2Ke1{dzvWZQf!>hr;Yk8EpY`Z2e?<4rB%m$SBa9^osrcQH%y4cd7zAO8INYac3>e z9R`PIRJu)Rc=|$t|El2?e6EhhX23$^;sQ@szWFVz5=tI_a_T{Dni|C%U>4VR`D90=47M2VKX`P=X#2qYV{QVu$PxJStn8QhX|5IcL~TD_1AOEr7$Wc6-d zp7r2mi(FOpG!pzE=t4d#HqnNt!uVpqd3tc^1OZ*itsJ*)=7@o;Y*EWx0?zdDGFl0s zx2BXB{Z(7?YxQP59}Bw7b%F*>N}W2lk}IrVEP>s1LF)^(_SE*!)3lS@Y_YZgGbx5s zF_tMx05pOHXc)7SQLl zshfNVX`g=f_EDs8vymj6X&nEUsB=$45p@f-k8KRJCeB>B0p6&8k7t!nYU{)e3Ts*2 zrYDX8>V3@@*zL1$-16RD!`Dj$EV zJAIi96`zVkD7rAyd~3U*Ju8uqQ_|>2bxi^6j!i!|{fZ~~oA_a}5_-6`RU5L|=6OvG zHg+KETnAXLh<%LYd$q*n_*jpz6NoZD|d{?QnD+2BMpLlrL9 zuPWe&gzp6nCEs(6|D74$Fm2zM)FR{OeANlh8ujYLvdGG&S14^4EPq;$M@ghnA^&h~{dA;6C~03rJ_*uHr-mtG@EO$`M8nHZ{lZI= z#2;wM?FaqK*>veFl7Bc*j1Ohpr=~L^B3h=5>V6*}kHs#$ z&aUEvjNcph2N1I=Nc7YaYsbiL6XNThq@5;Xp2|&&8J4cu8%`ZoQX=hcf6_^|@GrGN z6G=2y#cMmhTHqE#O#zd^05>4RJKq`1Yze@lLvrbRC}K z60a_qoJKV0g%@$mbNiSiNbgX04mm@= z^{oj?OUhHI&U|PLXvP*dH=jf>$`taKvUVGCiks^H+bpR9DXOU`J2byxRE>bog% zTNBkQ%?WT0+-cNt@m;+SWsFd)SEg0F@1IP>S@!wM5LWg>-Pu42ARPAo`J%ALL7%23 zz9%HK#Asi!>6nwy)4H~sv7Fg(Yo#vuNq}#;-b4oo=X-nP<`q?&H|Lw5&hbGP$gW58Nxi|B+K2}4vm-qp&LnJIOQp@>%G<_w>p+1}XT7pk)5Q@EPIUOhCX^txN zeQ-4us>u|aqDk}eJ9$B;()r41VfdI0UK+fy4X=KD7=jGR-4=sGR=rIt1Hkx|3stVt zIg1N5*T)?2$J>cV^}uyL%h_=Wkage!>Y)y_KDO#`1w+*_vsRll8nsqZWK;Vj0Xq>zGzYc;U_xi;t1zbVe^{^ee`*`mAA8P}-K<8R21r)g}#Yr2pmcV3IrJb9uNMf?&e$@FsHe-3qpO>u%9uJ0|2ZBSa4=v5vo33(TGGQ@~lzW@*n9b8!@34N!-+dHF)S@B6^_Iq>h! zQ4U|U!9MgQ5L&yOsqU+;%AjSRp=>A=6Uyv#1-r8ExIK`DEa&V4A?2BnB>{gUXroPfV@`;S!>5j(y-&6^Bmxyh**ntoV=RU zTWP9DPA>7IVlGZ~sHA{jFzOT_S3GAE(s7j&1%dgltRA-=<|ErCf~)VxPwqXTbsid( zus-0Q?S*FON$V4GK1cQ*KBIomCYY)CES+pM-if)V0tP&U!Mow{O?(0!#pZ!?V5I!& zB^c}oQ-Ox8S)uN@x*>5=K@D9;gaViB8=vpWwCN#UIp>{7u8>om8A#{$Vp!K#BAJ-K z*Cx(OS8e^Zy#e1sE>B%r4r@Ao7r(_2olF<4%R)=T^Oo=kAWp{VyCh4_{Dv#GSK6~o zc@9k8$v89FiB^`$Lu+j;VcJEbX7V5So5=co2c4kEn0~B5BAs6+r?|90v6}tJBVTri ztPI2q#YYbCH9xL2x;5P|ggk_0`1gF7h>huA6NR|}o@qYf^5)Mt;NRH%F=W}`AN7sU>2B7$=a|`VwEpnS0Ul-C)LhW#I5Nc|X3^}Z9k{ll zJ{RIEeUnU%GuHENcK-WWRWxzkTt$})i#6fwb=qnuxjbesecOIXhYW!a)>Z(0Vi-mr zDN&(@;A%uV2~Ld*y5CA}Ma{27&)p@)n=-e-QU-wPSMnl1d-=-O*p|p_4wnAeZ)#y5 zn+!J?NW1*vd^E~0NpgOVY(Bo^)0TL*ufLnC0@(U^aI`23dDs$PnX|Yboq_7!_s9F~ z7bgKMKtKOzc5$iLStW6O0YW+MM~FuiHB}Cuah75);sO}f)xPiOSha1 z`mL%d#SGR#vt|`FK90o(O`*4nB?V1=d`nIqigTT6;;{b}ua9{H4b<6-w)YJ;>0W!|LfQ|3J`&!te=ECZ9}FC-P^4M$*%jQ z4!3;J5gT<=q^vZ=?eTb`rHzBha+9I>2Z1dYCu^a2gET_I5_nqp=^8g`lh0iS*Ib%c z>RCQD%6a{xF^)fjx_jVRh2oY$j$-oBB7>QGl|U0M<^^7@tCqGp=*HOR-PYeU8P8pZ zrA`}*zA1+Lh`~(P$<26SF$DoBVT)m_Hi~!E)P6+=m;y`(Hq+(P_v)FPKaGrZ*|Ebu zn0o|sYTPjG6)i8C0{nafV(qmWDbdxQsE1Onlo=scc(_cBJ3Nwd(m zuU`X6TxrL@mlaSHcjLek-oho)A0#!jv~;-tSj`#vR&$#SxtDnT+y-X~R%~txRgn0O zJbND6XM8`5OPc4$%0_CPBeOCUX4$zB1qSxSkKeN! zQ9;heivrg8KMEf28{+m1)Cwd%g8{RF7$b2Kub|I!iQcFUPG4d4TPv+oV@)FR8$RCQ z9ZYW0Z5pyX2@4(5QU%Ed!mosv>dcVWyFM*Cqmg9X$M=O;#N;)?G^BNzZAFvTdMZ%w z%P0>VH8LIAR;bb9Qr(B$;T28eCLXB+F31lFZE>%qA&7ki8|#|;f$MK~t%&eRBh1j? zM8%-c=x82oT)B63TcySlCfTaLEia0RcN>Q3f^*&%=ENw-~$?KBbpxHm~O5222VR8lWDwhPRUv#rM);thgjJbxB%QH+ulGZv74nqZ&GCX+c6Un!@iqaB-@C z4wBmba#mj))v784%xkiQs&ekE`cN!A}%hu;p|Ut;pB! z=jko;OJ~#{SmOObNfB0%a}qYE#1h;svz1S3W-vM% z7^r08AF%bAKM7sE7SHB?P?@KBKWbsI>N#w?fvubT%NQ0WK%s`RnZeze{du~oJP4<;W4{#YIRO}Udv@$$z zFV4{?`9A#wrs!hsFO)9rrYIht?=4{47X}L|G+o+bJhc8~@!1b~z4D0vHVwCpfjW;t za+--DFMeSHlLwGTo=3=N@Y^C;ks6>b&?}mP;K9$z;D)C%hD05T> zk{@_5++tII$p4MaxES! z^p&I7i@6M6=NH-tbH*nf#Dz%4bBTRuRIn-H{#H&eYAtG5tII1THT?ji_fYy&5Pq9E zKC=+T?BM5_K>YUcOH;9c!lS|-N3N*o>qFh}T3)j}*VX}Dm;3=&F|+7-Ou)%$9<9aj z=J4VfIv{XTp#6{JJNGu$eZ8UX;{?hfZQ2K!zX}bIY0{VY@!iE}Cv-sTs(Rjf0k`bUzvs1l#`tV43gN`?>OJc-^wsW5*tDPd9?8rBAgl`C3m`8G6XEH<%g^*=Dbe363(Od|NXla zp!%oV2STbkAt6K zTv8u6At|5ad%fq>7?Ba`xw-q#`pJjh%wm(#mX~G||5DOSiA}2r5>YqN1LZNBD`*R@ zU6i@XpkJ5I`9=4ed6*qeuSDfBD zV$_1YhodyP_{(wvEK@i8EPj|~`<~p7{phdR)R}L$2}FI&hA}9rLtws=GTAi;@W-?n zuMU31t(zc`g!A=t!d(cz@1=?fcOc?$I>c7wRElX5n8~8)o0W7cL8>5GtG=VDm)aVE zDG;(0jW`vubRFF4TsECu61;OF?ra(W06zCtSW8O^d$;)wV+a`G=Jf6YNQk?>mew=b<`vO4Q6=vY6W+SS_KTeg2@spJ9H{0ewExz@=D;D_b; zmgOok2hYyvSWYjpwiAL$-lDNwB-~;p0lv&cISMF-UeFd9=%p*)$}(ol-JL+zMUy`d z;~x(m-_|`6#!g0y7!bc*F+mUPdG6|tc5n+qNsMq2GMzpGA+MIce+n5xV1H;p`3Q3<5iFxxK}yNO~@uVax<<2E=xq55b_}&gPZf6!I`;dvnF zbU@~Ds~~Gu1`zP?1=;-E!ko=_VoYz_Rk$ksElzCj>v=J@zYw+Ed5bwyIwe4DAvxkn zd)qqp{2r!c@kajH%u0`k^(Rv%hQ>lX+A2riX+(AV+G(B6a{bUYP6Eg1r zDU+o{IcCoIw?6k`46*oJrE-2GHWa;zbk~XvMdEb(bQH75q1euh04Q&MMwOvu2b{Jakc-r{8l_5k)qr3@qy10 zChxnyAoe%!6vdRgEP4An(cE{4M&*X4mQ9*w;OIGk#g4>yrff4S9JW%EvoOSo*%ndw zOLTFSlF$|)Oj_T*orKf)3UDRv_UmbDR2ppM?FD2usC(Ne^9v4#a^18ot;2;*Or^W> z06JOBq14n85+H2p*l1=JLA>u#BZtJazi2#IA$zO7D$c*fj}^$d1Z17GzLhjl>#~!m zp7VEv;lEs+or+nVj5~*{D4V>%6r*IU#p!RnXOHS&ov;&VH$wjG7qr6Dbzh`MxBZAd5A4<2!h_xk1!5hMbDjtVX(7*ms+_gY^YrSJ@nr}Ww20= z9>_!dAWd!{NpUl2w0l3a#-`##m^(_*RZeeI`WaB^J|EN5z0{OI<*lEG);NFHax{}T z_3XkG=|a(_?1GjYPSyhRdgKe5*@OtibsdOUMR6Mb@AGt-9*ysvdXz6M1bH)l8HgE; zrsWIjP+q=lV;m9}Y=SP?xQ(2os8V|*r8!)GQCOK;W4H43>>n~twe-2j%}gW8maU_V zkCT+0)Dm(DxiF{ARI`<)_k5$)qRDwU$ozV8idkx%>y<-gNcZ8FiR0%2@mUUQ);4H} z)8Z}bAgkF|1w29aDa0&=L3-BfQg_NomP>Z>>VO{Q5IW-!#@^MekR>wAaNl$GNMbgf zHSV9gF1+{8Tf1N}Zw35m{4Cs`2lQ5*O80xdwSYtAWedBgL^OTtgkM+&o4dvA>%4o$ zDje=$yEc`Aemxh%xBYf~B4e&l^;$u*VT8qLUhC%1DI=<+xGW+`a5DL2vanx4UME*_ zsCa?k7e?9-cRaRho$Sv5b`kQJc=a^2z0r$39!&A!h!wteXx=G5 z>mlOdXGjQL-&c=pdqA#_Rxv##4fia?3pPdsSANKDbv{q&Z zB6^-t)tk`fMJfj{B#doxwB^ldi@Ki@axw&OW`_p-mg5Q<8Cm1==#7#jK=dOvpU;FyP@!3@Cx<8b&XUV%Qm#^;Ewbsp zM$U^dfLf#51Vr6~DJadu9rkNCU1V$psdB%d(a_j$W&y#&)jt%~sYA=GO24L}=B<*V zn7r>OzHgwSYfk_xQ5+ z``uL1ZGbo(-BP2czp9mU>s!u@M#q1=4d;pm2hsDBFEjHSG2(B}82^d{nOC3EN;AX* zL*tbRulCHd5trNRn$7omjMV5dm3birO4n7R-sBavw`f@24ywfaRWeC#$zhv@OuuXc z9?d$|+ohq~X=czkDa5yok7NwC`6_k~*0^q6$2G`5#90eOGHpGKJ^q@~0W*W(vs1!$ zBIBm_u!nUwxp}6pN4$_W(ePNq$=n4j*NYc~ z)~Xb=ZmlG;zEy|bl6rWM;c*r6YE%eFAwKLRGdP)DSJ|tuubf9x(FvoGHwfhRDh%>; zpX&LXZq0CMYOpoUXs5 zEPKMPU}wn&+1;ZgX#B%C+i831gSyn)?I(@-1Hc6hKkSyF@Fb zK@A!vpIfvz^(i%EGjP(uN&2EfyM=V7w2;jeIF;_KIDfD(SnPWjF9Txyr)$elR3Jfv z-6VZ5TsJ!tU-sF&x3HF9eQn&L&&zTI$L)k~``ezP$#Z)v;?RfC!a~Hbw&59{oz1eJ z0d^c$(rKG+U(RU}fo@jZNths0T*;3;tyw@T^%|L%x?)f3L^xpm9372wBIwHD*Pc?7 zMFi)VY=}lWiIzseb_AGz@3X884l9^iCQApAa241y9Zgs!PZ@i+K?z$dAS?SBO^HUk zD0a4PSo>^R8{Mr*TX&+_skXZd21I4UxgMVw>RhF4ykwX#e;=aLQO9mF2Qc3TqQJasBlTKE#~rtNa-oSrqeEjIf=vqbyB)#9DrRc@+^3R4@%2JCs1c4B zb9IECJiU6?x(|7-I0uKCnv?5jpF|BVY*!Hf#Fw8F$=&kj{wP?hKa0Z26;qouSzig* z#e@%<9?vy*!90gB;a^RU9a>g`Ljw2u7!9lpL>LqJrZ*N3Ajj>G^}rdID{!Xk>PmNy zxqmUSJTjRPGNo~Monyw35nnnRtgEkt`ISIduDJu|KLqj=E=pD0&r?L_3Xj6vz)FTk zRGe?A2&nz^wEJ=K+=tz;i_6fMTI!X%GFQA;DYFA)1oNWLBR@*(!lSGI?UtZ!ib*#f zPQE&mI!gm)KD~vrA;W!OK<_)URw9d{htN_;#2V#TQg$B4n8znYfzcEVrn%~j57lzb z@y+lHdAomdE_=?ge-}k7+qcQk-+KfMI0|xdQGw$D>J;@?jK8L|^RwQHf77H}ki3C( z-VO`%I=z|)E$qcEtj;|}J@S#Mxqix~Js&l`R&wA4{;@X#cdQNP4C5sAzxCi8G5&(+ z(<1KOQwc6@J;5MtkbKOt`6d+DCXb>*!jIWByiVt{4CB*xzx=9HpIVciK;C0dyt_97HLtuF%2hL zN+RK{*&4p$Enzmp?kA^EZ4*KwN83n-zR-X4l?|3_q}sQi7{1JO-=n$^HOV4rE7@9} z63$U6yOar%if6q0!4)ZSS)uN_eFuNj60GHQ=m$Eh%^NGUwP$nur-s6&@ozs(ls{ue zn0suM3q1T5@4A_DafBta(PR`5gp!7ST;kwqZgA<@d=9&pUs2-{J@>|}x4U`(JMFF@ zw~_)O;op;2A9k)F@m-g(@I7+z0OmiW%N|2aOK~voh^v1?OkOt7CI^tTkxyp4bd9;s z6roGN#4&Js#ME}V7&xI#+?46o-PN_OUF*1;_vZWhWpgc=i?3F`O^X%XmD8iInEf%yG`P!p$!j= zk5s&j^7?tjC`+wY$RVcJ9}4+dF^0{KO@qrKR^(htx|opS$-dR)R4ad-j>Vx~&7ICL zsGp;_i%}|Xf;jei+@bs|S3xdkAf)JUk;;169K8H`se zKr1C<2&rc+%Xgwqh?5;3cR=UkRrjbONqr}w;&@UyH&iO<`RSDJ{VcgSvO~@k_;X{W zkP}Vxr^iLJTabzL(YIGrSXSW$D>VWqZA3GiVxR{k(S>OXZ6%3W2NcfR?(m76J@^i`(&E9c?Z9jjV?dASR4scOd zWePezEg61W2Uq^cBryz?(P_PGh2W`3qIG#u&>(|N8SWS*oI_gRj_f!$YU|F{%xY} z+)Ic1+sPZ+(&~=y(<|{vbUa$25OxBI=xSSA0*>_YD{F4i6Al<(xBC^)2BQF&d%(G+ zbX#H^nXzKV2(c+!vbDc-ajtpa*c&uksBt!8o=8bAz5*$orb=T)oy;Uw8b!vI2U-CG z%tJWfH1r!>HEa z5gOjIywHt^KBuJp7EtI?%DTxV|IiHlanRxxQUvo~2#42n9J^hu-0O85#&vY1?R3~) z9j|g_yr86v94Kk!3uiMLm8*|KOHbD-8Dd_Z8-ETFD4QE0Pp> z_^DLxEzUZT z-_vqo76piNi&F+3)78f2hq_C#L|tWeZlJI^?a1mZzjQz?J44klb6_!jZAT%@{~ivH z*o=3{jF%t1UqspVJWFQ6H5zYZ_?0*drOHr|oL96<^-zDoNjjy-qc-$;k$2L!fAYXG z0bOP}Qb6iV(#->5wWDMi;*tuP8|h<1(5s8);rSKpeR3qRonmBK%a1aq+rB}#9h6sQ zmP(y*^QvZk8==x`SC4*e%H z-hoMOrp=$~?r65@e`JD&(;b_sC0^SPp2EKe<+&+B!{a-zl3Y9jy0cNEUfy;lC>}XA z0|5ncq0jea`jJ4ZfSx^Gj52{S8yo`b@0na!rZ|u9zq87bM=`&WxoQ@0cDpTScD20Q z5Qk>B$mW?C5z|}?ca0xo!qE0Oi3LaSB7s=VA77KYW6c6JI~~hyPxm90ZGKFZ{_a)z zJY%3C>4SEO*;(Uc$zLNC#?oF%1kn3Vt_rZn?Gr8<&lB~`2ob+tOWY-5GII_m7*RIm z<_)(Tvg%}A>neG4#P}KTj;z6w(;%BU;c#Nryd=qWWYl%DZL(p4*Tg_G@B!&E) z!WxEF=~y75j9?s%n2Ay6R^pF^#tn>&S-bDYaC!U16;&0zd>ltYm;h==T+^@q2R*XA zZ$Y@*fLs}>G7k*4eYfK+4eAm$jgvASN}dGE+sFJOs2YB#c*(G!Gm=nwFd4pv#kikK zuRMr(liyKh>l;@nfi0QU<=Qz%P2{u?+p=)itI4t8Cw*dQ=_Z2e;ASi0rVHg3AyYqp z&c+p@=chg`%f&NxT@7|+!xNFq_?P&KH0r%CH|o0S zsUnQBWSb0h%_S)?^~4B>6sWTLYsF6QDXP4-n!M0QqQv-U{d0c+L7iO&Odji_(U|g7 z``t8e(F8_2_x}XHHrPWKY+!5jyc-p6aUzrk!MEp2vf2!#jVur!^Z=Z^z zBHjEH1E-vFS3jo_HKlbQW5Xo{WJ^KU;khova<^}x9VZG;AP$P0_UnU3c3sI$cVFM&zmi}mIES|VfRAupwVe0d!ob1zx4`*E3BV41`BgyMhUk~f z;c!i_rx1RiYvARf<=n&e@7-ooxAvh@7O@h>3h#r%-RL(J!U@F%KSbe(y}voezqbOU z1EYS261cqe-muxpuM}f^q-(WQD3S8iuo-wWMoa!WRo%yZy)WnI4CeTozWSu{SQ#BM zI;>}_%ESBiyU^KEir3ei+9n08d434f3A*nXOA#PY0B!T_Cu+ZW6pfaKg_p!45%-!$ zQu{`;{5gII_X~37TpAayoYpzZ@(_iw$H79e_awN1>})K&n%p{sO~)6S>Me0kQZxYLw<2ANa zOFL^zBa5sdAJuE!$Sa4SJWs_&HC+d4k7TI(D_ICr@HNj=$Xm?D$>5`xwLV)r)#aEd zJILbfd+E!nr0uf523eo$U1T5jz`)B};M^P(QlBZ_{L1NYffrMvzjs8Gg`n=x>mzlR z3Qy>Yv#MZJ{NLI5Z6Q5yBD}Iu_*Ls<{3d#`A@O18#AoTy;H^gMQQ9}kfVMnzb!2`g z`Ckp&`Qfmb4+YWRJ0k(MUxiUx&qmHH+d0#39!n8noX zSex7`RMKCjqy>bz9seP|+275yBDMLWW-_LQ{iu?JdWQV{7JYb}czrRoAbw@DAR6N` z0E1X&G4Zv9{o|!Le_GrCk8&-L`4kqy{{`4jl5H zOOBYav^M)YAnf{_@kfg0MBvMD{-Iwlu^579IUn8s)*^z%%OW5GaGm8&W z^%dVmk5p8_)6AlyOXp0nMizvhMtDAC9lutyH;9kF@kLydgHG1>s{{0%*g{aTe5sCX zL}3OLI4b}Q63&swe#J!yKzNbvy%gTWAo7Suxv`3kI|e=CZ{!RHm>ly(0K=cKn6-;& z4;kw}W1y6CVL1WoQHN-fZwCS~pO@-4{*YMLYqVB{JQT#%WGf=%^wD5)144ZxdFUAp zx6C(EyXth6aZ}Nuk!}v#1ba_#Uis|1Sty{Z(EP5_49w@xEkd=3)7zG(Ac_ev4R?ql z?+p*Sz{C}O_(gGDF?4oUj(csIlVNt+?;$}xSpS00TQn|f(8`*rXm%e*pKR$D8V8r~ z{{XE(Qoq%iE|asi4vGgVmz^z+kcs@P2-)XXUyfwE(-2))#WJZ~Ma$tI!!$3^f`oq_?uA@T7tVGo2=jwD8ER}BxSmh*A|vNReeofC{ZlA0Psw&E5ozK1sfrq_T9?R z4_-ct{_r<1M^+nLlqEDX4(??PKL}76cFaVce$-Dvp@IZZ%1q<98zb_PHfOh<9XO5{ zddYx^Xw!??$H@VP^s{~S_pDYcO9%sx3Pe)2zpgL)-HPJf*x?_@*!3mDxBh#qA*sIb_gicxi!T-)vW{GN?JY~}HETb@ zP{R)t<)GkBP}c?>r5Om!hSF-Yk=2ed0Xs3>_1~C;uXlzSJhl||`KrRJJLXY-8WlR^ z)t5V7r!p?ff1MYjNbx{{+Oo)z<&?DXyT~P~{v;~w-GD6W2Y(ELV_^_SGPRei+l#@sjHB_B!#$-`fPb`%uCfFiW0APQ~ z%`Ouv+b?WY9I6j=Shi!gtcId4nPkV#kpLXp+d-8ro9ZZA9@XK%{KzFM46j0>1z6FA zphF;JV?xnn;j2A0deskH7GM0we74Df89YZUx~YVdnYr>XL5Rvp@XlD20qg@*G!R&F zsf8l+?b>myI63=OJ`BnPI4F8knq3^{@EDnXH7P2Zb=@Vjq6c!oMEx01mXJh*lD}j$ zs4s>G%-8>_mH&&Dc!-97O9T2iu5i8YR2paSDxs7CHY?$ITOvZ97~->kZoxmyh|PI- zwPe!DqIM6e9YH!nQ^2wgATtrsWzqA4l8!Gj^zm^}Xu;F;1<(a>Jmia($m@5jC6Obz z=^=ymw~Erp%sDK0K+?zl zg2&E0fn}mC$PVnKX=h>}6SBY$pR|m+e50w9$v<)}4on9V#dsKoyt?V4z7MVwQ3w&W zA>y~Gmf>M+8&s&04PE(HXgHhFMJa#v^>??~y}R1WUi57LfS={)ko&wDh?+LEmRuz> zRDqH|tA#Qhwyw^30Pt-T%O;Gc(Gj4I!NI7UmO#H6%bu<+wBV!Zos>^R}vs(UN z_R?o+&ntO5*+M@~5eJEVlLt~a=)=HSi`qKzbPF6Nn?Yy`JRK8G(b2?KFc{T}arq_N z+KwH&9QDwb6>Dm8y#4SGzrr%ib}I^;5?lg(8N&;iBHuvHYN#?VAarXX8a?1Ic zgYA-wF7uJ7_uy(IaGZYHiR}e1IHT>~x5s@FSa>bg+ssY|Ee$gA#n-jZeCSJUZhF>(!y`;Y%HA7@JRu%s zsOM6R@h}6vv{UE604{cJm zFr?9i)u(ReuwJbmw4sOZbp+(;Pk=ZmXWcj3+WDWquwC(;%i0TH{QP$IInQn9y!d(T z#8b~`fAHIX-EQ1=M;o77CG=YDfPMS+iB1I`_{V91(z|S@iC2|ktII=bg<|jsPg+Y| z5vm&oj$4E-K`rnAG*eV$)^pPbcr{h=@V<{A3X z;Y^uF`yBbPJ>qzhx8V4=|F|M3AE~c!#it|cn~h4|;TZ9GI_kLepHB*Q@0)91`piY` z;XChYfB0wrt!+N`u(tV_4ehw2*0s~mIJ*7uJN~%6{SQCXZoTGK-}A7A;>H$Rqm*qe z-q;Y`k=3Ik{@&_^A&sQ0s!KReH(-9+CIh)%it$qVN-dWwbu+N`uyt)}YRU}L-yl5h z{`r_Y4<~p@hrJ-bipg?}(QrH*e^PC#sIADsIy=Tl-b0C|4Wye)qO2b`6Vk&5p2Fj2 z{8_5F8MTwia4QsHCZ;B3Z1H1Xh1Lv$@(ch@pza2Y5@&!k&O-!cveKW&wA?5{n@88Y z+rcLVu#Nj*8{J?m@&QD)fpUzg)pBIvaMQGE)hf~81B*-s@TI++4f&C2OtMa{n(E{o zZ&R!4SKe#u!>JD2f|aVDav$2jU$btte_w4p29{2VB*C#2` zLxOXu#uJ=LiA~8PqhI9FnC*IMzWwvNKh;h>WsBsU@>^tcGyB_uwg(fk)v+fX)gFCv zx?OPIH$65hWT%zm*h2QxH9obvty;aVtzC1N?HO4KLiXD$ue@Q2O2Bux%I{Uo-+u3- zZG#N7^~6nhie|u4yYHTd+pgVvy2yLb?J zOg?D1YtP=cTF!I!3(k~56&fW za~!A1D5o42H6i-G0fp+B-k^hwaGC#UtPdr}2Vj>KQ*)U;F@FxG9qlX9x_=Dqp;6`-EM$KRDBV z^{0QU{mOrMUHj2re6xQzoqADnK-@h$(SGTz|4)1Kt50q}`|Cg7ZomD0`PDvusDYb$ zKJDx+gz&d)Il4X1`{ikm7raOF>+cyr?owwCEVlRl^(WdD7hWT$WY0U&ZoK~c?dxB> zPcH#+}+i}Mo+fG0Ily=|tN83mK*JpL}B4%o137ei-(%$y^_T6t^+DyqefNT^+qSE2Xq%2Y%54}( z*!)+GtQKZTiR)7oa#>`e^@*h=5+V2=yuON zkGDVi&3CjX9(-KUl;gMIO$tU`SXj~i>}~I9-~H-E8nn^&XMgm*_SMgRLpK{Iw-Zl3 zz5UfYKGr_`o_`jvE$yQpI2J1G+HQU4TUWJD{`2SBS!bT!&N%H9UuT_ldOKcroXutmJzo>oJVRGCf+VRJ4Y$u*_O#7|h|JC-D&tKH8{2reqp7Zi5cH&)+efbud zr=Hlaf&G@)&$nOt&p#{2t9_?e2uny*kg;@Se|qGR8|1KC+E($|eB62|zqy@s!cpy) zfA#0u%;IGG%4ff$eX9mT6LQ0<_3fb2(zm;*Vz5MiM0@g;E44gNu4${aH1koVt(%W+ zr=5PBobuRq_=b(r=_sutC$>NMlizBe`uI27r59Y~bKkuOrWMtv+KJ+Q+?FHSiCP}F zY(27VIsVA@fBxK$x5GDXZ6AEkrxhS(+Y?XDwDUf8e%mMq{l#DUDapJ+5q4uc`IMvE z>)-g2_On0tGwm<`^u6t#?>}J2nOuE%d-%S+?OR{Hq<#HM=eM{2&);)|KKbP1uoG)G?ApE4_X~c5P1`+AJNTs{ zcw%=>vSy~Ib+4o`&?>n!GA3s|T9f~TwpIF_bn>yfj%g>Kezf+`ztcYOkLR^pufEZ; zI5Ovj56<6MZY_kwq@E>&edQ-U_N8`UdZwLl!ZFf_kNs##6;q6|AAIk>XfU?4^@mS6qO$bQ=x&yGIyY`Qyd98JeC3nh&^|~rT}vm&J2(KJ zncDf}zV`V~eoYf-Rr~3G_a^P>u#sfylm{@54J1H@BMv`8QCty23bEJYYm{d8OTO6| z?Yp#ZU9+}*;-A0N9@_qZmUQirMQ23%a?|ML7y60_ZC=|2Ufjoi^?ve-HY-O3cmQ(5k*nMKBR014zxdsD_igvK z+i!cYed)93YsEN0`&mV9PB=t&-`;()|6Due^pg~|A8FtEl2$#*JU%|zZolQOcEOjw zshhL6Y2Q2Q7ow(hw>~F+657t-EtcdaZ{CuZcMb0T{zL80|M+j(|M=}+Zl^tyuP&%l z6>KkyI{Km;-pErt+ea(vqUb3uYZCE5LEAEHrqxp3?iZs7Bm^K{fy9Z~s^FM*E;*^t zU8aqDhdQQ}Gpm7UPSB#=-y9@-zEqICF0WtWe{&i`wuRhVY|&)hxp$=f^9MdB96tPD zx+~jmE!W$%wC>rt&tFOhi~52*RMW)JQqRZd;mtBY$GV}JsGB&=sQQjzmXHw*`Wk;& zkaJlc9r7VR27u_we({JSH`-yn57NctVVm-Zmdr1F<{OHl$Fv{+$=9oGz8yF)ZxzncuILw3HPg}3NDfz_V@ z_6?>fs@}%bYM^Zo&VfFhI`B9d2do<%K2B2)GdOl)5);Xx%Z=@nwh-)pad@25&-H!N z!ek9!-VEugkXU_#Lj!} zd9uC#Z$8rA_ItmgRq7b)fPBcz%I5buYz;Y}F22}sNe;yO!JIz$t5RhECNN)ih$HYu zA~)dJg{P9fu@WA~eY_XJO&l-xa9n3!kS@rFNXX70;_UPC8{`KUxd}kz>tv?o&srV4y-^K$I~!}7 zL8<<&(j>w_p4Au$908G*nOxr@q)DQiIGl;^^qSKE;~0LiIy}@39cn1;(;f&6#UJvF z%RXgXZc6KjacXLnCW~TJCj-lN?#4l6@Ns%>ZlGhGbn$rkyWhQ{efz@8+r{6#wq1F} z&Fy;^UDLk(tt;9k-@9Ca<;ga!!RMw$Q>GocX|BI!J z{NwG<|LENsv)i?$ImWo?iXHukU*Kq|y0R}zJ=-hM6jy&`l+Z|hbSmEH&lvM=h&puo z$QiLMlba3#B0s=K?Gs=E_%OUIi|Pq5UK#ag$5cJG1S+pu@tr%M@zi+dV_kM&qTim~ z2NZo*+4~ti91A7=LbHUbP)}6m{FiTqwoMGMMrYX&G3nnit@~12GD!hPG9m|=7$?7 zU0j@NZ-2*sYw!8s+uQ#A`;CY5Gd8rxp{YZ+j9DF1vGQpf=|u}#byNnvkiBO%Z|O$l zM|%JrnOry=UzF{eThYgEj02ICr-j_aPfs7PZ%JD9#F5EElGPQ}#h1Qa-HcXbc!Q5$ zN|yS_28w%@NDSUFV0qyyG7s>5X4=25m9stbnY!D3_Q~zJ&pXXGOlQc*XPkL_J5zhA zV~;;V``h)}A8Vf|;ZM?j4V&s zS3t_3A?><#?58DPx6JeA9XBY?de+J9RNeTU@r*jW*Yn1VEgy-Y&!8aAMWV0WsMz+N*ET4JFHY0s~tJoG%Vfp8aV>^umEJdXujS zUOJIy;^Ri>4U;;ZfG1-m*<@Jkh?Da%vHEbW#>DOLsV9o{t)jf0SPyC7&(R~e;Bm2{ zc|2qQ?5m8&6xr0K4YUR%vj7B;Q51u)r{pvMX3VVF*#rK#5#P?uN8;J<_*+!ew_e)d zBRTSsCh{WYPBrj0+K6&d(QJ@L4f7)tqHcIJ9F#!u#mT zrS?-l^&|fMh6f*bOw0Q!??E8QNnR0aEnS zQt6`^;c`Rw6kh=N;G^m%!Bht?W+sll;fTrh)BoSLo>)Rz4Z<8^&vzB3{?}WB3Y=5Sv zR+~lb=M=SP>p?*FV7yt8H z+vbxux96RGVtdQa{Aj!A+gHe;=i8dKYvdS;SaKMi+RaI}yYITcZNK*s-z+n*aPmY% zKIz6&GcUE$71=cJ#J`>naxujxCZ^io{MD!0U;M$lac|RLoVf|&VgeI%a0+znLmWFc z?MH9ho9L-YHm4wk&v2^2%Iz(cJQ|!6PgvLf`)~i3_N@!9X!~~U*DAC|_bjX0+O?}S z!N=NlS6tW5dd8;q)4%YO;!$Hv041o*&hgMg)>HvnMD$gw>I}X1_|o&?hjz64wm;Z* zDjM8+``yYv(jLD5p?2yi$F?8*k=OW$=Q(Ge(BAwLZ)pGYk_^x(tPB(wtFiJoK=QCc1A353H`m=9VbenGf_?~~!a?i^vwGu>x_J6t!Xd>@TNKNp;I^m;jn4B2XQcz*g8I0(F1(64@(+La zX|Wk;t0q@#fYfnB%b=9seC(!n(&<|?<2mS?N>xTP5a{&6Qf=x zh(tt*T{~vl_wTr;Z9HaO+q`*G8B738)0N!ZFyC?WeTvfy?OD%1-A6Vyyzz)k;_<+f zZO6k;w9}rkxvkP(o>0Yk^S#?2R`dX$W3yU1$5%|Y)w*e0w@yyB`RI19bU19?L_6WM z6EzVQ+r78mFZq_*NoO73W*0~NHM4Wmd)g^yovMkwqfN`n{2@|I15HL)blEDLcIt6$ z{f0HZuV7!tne^_b_O<)&eaI64T((v8!>KsX-=aP8uAK+k2qz~ZGl?P}GEBDmcXxk`%z(+=|z53QAwsY)Ha4_!V*}Jh9#+jHAFv{Ko z<6t8%TS~K(11xXS9~3LcJ~7K1I4A=j@3UE=)$U^|_3_7b^cSPhWn4=s#3-{J0IIF( zSgJ+d#v-cmt?@|0fbg5Z$imW2hQo0ln$-TUWb(PN`Z7rwR0d*9_?~Qbidt?NKz`1O zBPsgeFsv4^;DiNQev~SHoGei9Z-iII$9Lk%#dn4I(Y)}`ndRF*f+8MlgM6PLx}3t$ z#@R0uux@IQO0uba;6T_wJmPSquJ3F}*$y;C|JFTVA$pdx)wZ#gXOEG1gjOGjxDP(~ zU_18MV{HrCIRoM6BmnvUM0!3xJi6X;4w z@2}aOa6a#Sc_;J8b=z(gziu-QGbxbo&VmUF+0#YHH+8}RI7$PUNjM3(2+x2)D}70= z0FnYqRAm4UDB~4`Z|YJ`UFs1U(bOw~7d0JX-K!I||8GWp^K zE|ZLi#J&$6OrVk<oyzq21>}4k}!B(H`AC zekLRG0%^k*0A((gbD9_^PFAvyB=zc~!NjS{vCDSQj?Do0GXbdM#3wvS;n(LGh|Iwa zPQRXf^oXP8#dpxXC)Qu~u^wmP&?ovq4rgC3NBEMb9$wVJ2Ogw2F7>q<7=6$$eZb@L zQ$sl+fJ1tq1lWi^j^M&$b*5jwn5D0uh`J7afRU@Oxfv~706>BXS{G?b^?yb z!ngfIoE0l8JbaPII$U#&BCzQcQy|9S>KiIhbS#|tM7$Ol!3_9 zmk~(+J}ug~QkTB;E4_z0^lhHL-~s8Iw)6>*r!O?%#f=4yw=vvW1InvZy8TAAD z^!s!vhep3XK>xG@&;&}JL!E)EPir~tTz#6P=nLSur5}g-d0C|f5MwfM3mwX|FYh0IT+7>wPPO;#1H|EwyWbaj!A&``1&0*Jf|Dn(wp8?4 z&V%wm9``wPtiuZ@ripyf*0xM`_7(&F;4s-#&o+a8*eUiO*>){k2n`^!0Ul86F&YT5 z4EptjH*_$7I+TfE$&*qB`aDQWp`p?Kcf5i0;RP$csz#9LPp5~R2dWrzj_%)9ysS12`j!2<_e@<94MU4MW&pkGEn3`||xfj*t& zQxAYoUEh(@mNfl=q`=eh$5`B~0T`3>Ne#JiV-p~{f*<;E6d*LI3thl3{}AcnEgBrH zEw>GQ*e}y3e5eb6OB=Yf*NF)y9<|5r^9DknI?jjvrGDKc;v%{M^vgxGCH2vkXom(g z!=E}*Xu&%)f{R_qtJ06YWyPvPF14${WoY8O=m36RqN0!Ag_!RG!M1B}6#c&Ei?GSa zup(%|djPQvSih~9QjS9xAT$sKmc#No%3RQnVFJmA@4y%WD=CF6zbKrb9lEiFCz(X4QI?zu$DPOiSF{w!+ zl0GXYvI^htJqXtiLUfbpKAm1XR6BCx5q@CB2PFIege`w|!*0ypG8Q(8i=74SjCX>bw-(inevb3GJZ` z=#vyaKqdwJVx!Q8PhWS-)Zx-^WRxva^`Sm#=r1pmh8BP{IHb3%OalF14^@zV*oQPX zakbr$O#0*92=?!)lALP4_8LWCQDuyn`P{?-YBIMW>l&cGK%}VyNWdxne{v z+UXy=5G|?W<2-R1fPVdac!m#YKN6=e^?Vx*@0dV$Fo05{zV=D7c5?6@17k$r9OXfi zEsCA2E7KmJ9{^qC0&pbjpbI&3QJ?;i1Dwb#6bpq)v^zl2#6I z`lu}e2S0#Eu7L!=4UYh2c=d4rct)nk^K_8@rC8xu&K?h-&pYkmnfml0gYI()8ye_#QC*l_L-Jav#YaKFH=i@Y01Ha0-BWaOsoaLq7E4WYn964Lt{xz1tb~&N zKY70z3WK@p>&?=UtHu{Grk5frg4_z)~NE8NAALj{fzYn-v;P}CUx_W;u z=Pd^t@*%pCXCB6R0qSsWc*nl!2amE>;gDzR;E`j1|m23!3&MlCm%zS0(~6;aQpPQ0;!K)p@9wJ6aa0x!aI5R;S41s{plk<^wYrM z5sSJ>@*~vFkqgvUGyrIXE__plCNiZheNzT6_Cba|odU*(iChjw1hi~Q*l$N~E@&`$ z&^^3ElYWp4E;OjiShH6Tgg+MW`Le*})OWN4&@f3|{L}?Kyp`Zd93608^>OD244`;I zd5A;UZ^TpA)l&y9eZ#o$D~iT|NWcL!FT{|izV^$-n~Q!alLx2phDM~m=*L*ak1Orr z89bohHxS1PPI&d{0R6i3r;e*HAM}z3pNZ#oB8$pIRX)+}Z+;h!X|WpVZ)rge%gu=< zyh^sSBz~yVIZXr#-mA@$ZqS-8W+D%li-XsR>lFQeS*3&?G>zy>O&fdz}NT z03%t^9g2Azt|AZ6CmNL?0g} z$%if%Jp1MJMPAzaI`#WRCm?bI!J$w31Ed%;bb;_i4Pisb_28I>%HUe7L0+~INt_hB z&_f)J?|m`!1kr;&Opbo!k8I?*kS#ZMktsUUMigWlP|UCqOR;W9=jXJPGk$gR1kb$d z0R3FhqrcmAAx9i5yx;?F@vnU3i!83|qO*+xei!ZgPQ18S`(OHEC)-8f_lA`px#sE{ z9D$*7@L(AoNGAx97ET$#&9{kPhfj(e zb>0{v0ffmL^Yr1)I)X>207i;X)YBIr599QqKL)SIgUEr<7;Ct^n6K!CSByfLJSp;q zXHw{9ua>AnK56Lm2buclv0P@LWE?seeE{m|>vtN2KO71^>?#M7USrxe2}6B!Q{uBB z$z>j$^U*Gcvcq?}Mo0J~N9+-q=oeh-`gSl)<&l+kY{B?4sbV*944Pp?x9|c#JYxr- zFGKi-27w5`kNlMb!UHEd0O6T5yuj_J$W8R+DI?_3fj&c;B}ex*S`i--&W#+x>2fHk zLFGm)Oc9&DEK5-$0&t}aAP{x^iP2XEI>i$~dE>v9rvNfhPTxL+R@$R%ZCU>V4oM&R&#`B}fPo5oKiIKm-8-%MB65JwVD+7lAxT z%7ah8zVHBL@=OK<<%+Y^ov_i=&J(ZVv%GKkhPVC+NUM#A4jz4j6a45xKD0pkAWu7GV6eaIIRMb_M@ruqDfMxZ7Di4c5$ zFk1>9pZaEv@1PT1&d`eoL}Ul@s)IkrM6m(9`(u(cc7s;NiMq5yn||aYe|?4xdsaUH zoNV8MpRp^u562M*57Itg0$un}AKB7QTV%qy+1`=njXEIhK*?K=ps9~6lxxz+7sX@n zB#w?Clv7j`Mu@&b6cfJfTG zKeF&5PQGh`I#TLOtm@zI3xJbJLK`XePFXz$-Db_(L(Z~-U6p4`x93K^`%HNHkI)CdW zPHh=FXV)LR_z5o{e8L0SGx;JfKpW*uD9gn?izWrzKgw;Ch*k1J2Pa22%7M^doqd(=^nh_mKKl52e2b+W^tVn6^%Ly@iN? z5gK5*1?r}%6jxtC5e6@P{DN}V&jNv{HsFwYL0@P9MSv&<%>cquAE-SneTrY`3=LWa z%fLXJJ6Q&iGNfxyUlR^lIIg3Oj|_!>j8uEC(wDw~ngp5DN}(fu^)VMY<%A}haIqin zJG{@4j@*zT{m_Rraz{q`p*sUl9ao%;n;a$tIHl+C z+%|L$)puAIpbP|0HL9bA|FSL(d%`_f3Q zIso(>fkB2S3R0QQbwdYZI(Jc5V4ug~p-!m+Sxo9ezN@ERLSC+pW{^&Ypg>p+o4< zPFvc;n=86zD-|3dPgH^Qrw{ZAIJFgWv+6tFpdCU|tzO;J4!~voaZ-Z=2l!D) zztE0=FdcSAP-bq;{0i$O7&ul=Wfg32e}+l;jvgIj@B=YK(W;}Bv{PR^i+;afAc_Pq z4BCTBq^o6;K_vQQPe`BQn}LiR0O@d|)(a?<^VqW9OBGEy6_cQ3tdW33WaT??89%vz z_QAUOGM=1RGIJ6Uhl*A>Jli8WF(911Vqc;e{TOh5?iJ|k4Gm;OUT~79o)p=st4T0g zAG|~+(PX<402hE406uld>As>t8*~BMxUlo6mWHzJQ2)q9n!2GM6_0G$GEUS($GR&e zn9v74uJ7m#{HWUxS9y3WN8R8QA{`14rWloBhEHR_1Hkpcw;aWLk*=MTHn3m-J_1Fs z2*nj4XzQnuC3w^W7Fgv@IM-LP1|`u}jn3o5(FvN7fxPJmpoxJ!KyoNvsHtN+qI4OG zB@mXvHoaQ1`!-ngPY&?ym3=1wi7(Y=!pWi?t%LryNuqPfFC5XJAK!A0T_y zS~-S+1R9ZvyayN8mD<*=n~f{NEF8&=&dcpO-l$9NJpHujyPCiWe^0QgDM~p zBVzo1zg$EjWZ;P({=(iTV`ZhSnT2q9R0;sI17WLYJO z-=YgHg9R>hhE9`}$Y=(5h~fapGAreY8hWv>!zlsiLX(GZu?05r&(Vr5I#xg^=k!2B zUwuL!d(khvVx#1#FY$&B7$-?N_9hQd4}De!^0WsRngBd-9v*$iw(tVNBebcHttj(U zuIyj3s(K)IfO6p;svl+gdQx`I+t*zY_(nT0vcS}p;tN9L zLtQCUgA#yd6ey+2D9{A@^r02{K!1Noio?=GIY1x!Lz8+2D0zTL!`&?qnFEm>{LJ)z z-^dZ*2mkPzlBM`&E5+8zdMNK>Gs!{Zu|ujak(f^%@J;ZX8`rj?c)Nek9>5^-h(2{( z*fImp#2XvO?j>jJ%GiMyT`i-o-~dUX72Z@)hA;YIH+WKpCVJ2g6#x1@2=aCFR;wZO zYP&SNIb-sI8yTVNJdWycE1A@ndThe}mlup&mMq=tlx!g|#8BBN8G@A`?mfV%s~m&h zsX!rTt(dT6;YA9%tm7qm#B0fZ-fsEZ*YtF-IdhXX=e`u7b7WH9Li ze`ExQzR`s|IMIhPd4QBMc>Gu)gVEQClLR3QWOf}@%JcqjBE0Y9)z|029X=_L6uICZ zxyZwxi@N1D=69$GMu8xvg1NWvSAB^2s7pEgBWK1a;JgSP z94YxdAv8|hWLky}2mPQ&o(uY+M?WS4Wxhm&AD5v$eFKbHoZn;Hjbq6T!p~cX622Rdj!}eyXb~9>YB4WoiV^zYBNAQitJJi> zQyIq{)F~f_p$tBClp{yVR!)4#_YF^4=fhRbQ4#&YqmDs|!MUi<1%Fc7F-T+rB3I}X z{W5mi*b>a@UO|oSZ+)b;@l=ObbD~ios^XVM>z1`X&ZP2V^Y_2fe@wqupfE0yrY)&LWk zIxehBAIl_@)K8lc=;~bvwh`{5{>$Zso+onM#7Qv_)v<4k2n{h(APi~m@0$x~>$U=- z#U2J4>7)M+>5m}p)d@vC#u(stKwI%c)SrvG*n%>BGM=SRtqcqrc&wIi!Uh@p$Q2nvyXc@Bep0rkU*ziB z3;w*c1SfFlA0Qum^0S=YtSDKT#M!Eb7ImZ}H(Xy2GAMMU1_BT3%E=%+RDc1B;CzII zPpg(u(#9W7obU1S7NQdZ2u&P`dM@h1BX}_!xLmycmpZP{B#*)S^vPqC0Ckk%8G6*A zGjxFTp^oYk+Z`smsS6THYG!|$BlfsfXJ0H5PkrC$oEs)=|`86r2-5; zD+>;`rY^Dr=7F28#<8#TD-H%qx3qy98N&W^`x$wD3SwN z;(Yi6bl}D1e(a%TFIKRrsd@*3K7mAX`l)9ZfrWqxg*y-~NR$DHLo84XiI^}L?on_I z3^7!+BCCZ|3&La{oc9D!i0HwMP7H5684$kYxndmfGlQX{b|BOC? zJ`aF$>_Js*kg*=}8cs5RI@-WRKFVBUV@&q)0R*rkYgIy4Q8SIc&ao|RrB6*3KM+$j z`cbxS9fWV{i1x@nave8ub~KDTbQYlMhBFc%5A!GsQT=bGT;qzy-Va(Z`ioAdFhT*L zmv>+(b63t$6#N+Uynz%x)JF!Ch-~nW@%svc8=T;gf*1bgs~Mes>4U7)QzlPczdii8 zc*w$5f+Y^Supb^ocm6cV&4(K~rJ)C{3@G(LbV*$e@-X^wTsQn8a@C6#Z?0K>KGiHa z=nueyKG5Py9Txx|vXD{-jXcgyJwV^(HnOvIH0^AXGheM_1o$b89v9<#Sa3Spa}E_k4_nwKEW^o&3CXo zitU!9Ft=n%Vwf19PX_~~oC(5}JSqIaN&oPsFGh*1p+h@;XoEKp9jF7S4}NqbO?~jF zqc4Cgu?-h|7-ZTbt3f(@Kvb5tZE?Pi^CCBZ?3pZm*@DB$MA>#&V$WXoAj;*v+~qdv z%M9HH2qeT;Xu>}|MkwP0JFhJx<0qu(y@{mn*iW}vs@3p2*$Lpz3MszN@ZLvMnX0dbqI5SatI+<00mPHE_jGpUtG*h zi-b@)Mu<@`Lhibu!9{xpCG`wS$^iW-M?U%hq`{3`eaB+(s3RX4A_wKv#mT@;WCb#D zkPm=foGvoCj{Uy-qc1j-(~A}W%|7qQLmt|Zoz(p_xI{3vYj!T}DTB*}Oe&fNeMq^Y zHvoRo8%}JlI?jVvIRkZlT!1_PZ`!MjZxqj>GmOaer!5l=fMeeU~n z-})Az&VH`WZ0GDtM@-5V|b5_Y38;5ig5O2NTa+w+^qT`ER*p+63M7dET!Sbd4jr)|W_koqDQ5T9FN9fKyzaTiCNVQ0Dr+Y;C5<>1A;ilV zYRKnsKk+kvRgV;RtuEB){k>zvSpr>3d`bTcs3uw7`wKv?0W&Hk%)bae+GEAef5|x` z)+4IXPczc94>_)W0=4?0D1Y^5K~WC}AW=C$A&zGDlolxf;U_IFLco^k)xg$54aDF4 zG3n|UhK`BU8y-n~9-jx-uk;asUC7=5fOaS$Bq>@>yeX?IBcM&3B9Ue6#QPJoU-eo` z(v?caEb8dMI`koR)2w#*9@R53@vb(-B`&0L*a8g2O}=3~ZIUdahw*$)mb4ID{q zwfz|Hc){cKPM>Iwuei-y{ZVPE@S~cTR@9b04J%Ot*n>@JQ$^2$Rd+T)86js(o8lFR z3rz1P0kSL+!AL1nt3=VkMwx_5?+{XeB&tpWdw73@5yvYsk1q)xzBXcPwYpgc%;b$r z(cGiwNH;-a0f$S0QO0$t=&`~R8o%Tc{+pqSBf~HVFl^DuZl_h0C6&=3~Qa|uMMJ9i$ThoJlVh)-! zS$nTjYsr~Vw0$bAVEwBYbJw~3F)cphW&szuf%TyqkMwF=Hb>TEtOLJPc;MNy_TN&t z%}qjC*I0^&$u9wbADx4A777n<7IK4yCU8PB=GXJm6@C}~>y**nH|(cCgPkz$(2py!gTNWD=- zb_`&l?iX#^r0#(y_TM$@7y7yYJOaMu2p(zT{;6AI|1>~Vf9*>*-Re2nTH+L$Je@ma zEm`=U=N(f4-%QU9q53+e-QkA?wDa;QN2oHZl&r^ch6x9Sk3|Q~UY}Zwm<)e@*XH$~ z0{?x&bSoy^4s#G3D2n`yK*vJf#dbg{X|vv?*I5Tmn8{1-gosPRp9pl`hs3ht4-LQ@ z&sDHKjfr8#9t_@qfOA*)!Ioa5iXMU&cu!C7UwQW&y3zLEs$yj94bJrmq8jjF=PL3x zz^!eaMHmy!Q2Q`vq8xbQ_MA4M)VRLjAaN}J;Xcj~H*?&hy_~CLKMK;_fB=YVz@N1A zj(_7xLhm09jQ)c@ZhQAOlmny&0A{3JcHFWTGa9W%!2%nNF|X8GFW&s6ylG{b93kMP z<|1d`C??!bTvX}DtAUwMYp%b;b@Y%-xG?l*@CurHpVq{5t982mVX2?ar{N*@1F5A* z4Vw7JCOdix5x6N{vtWAvG+GWmcP~ap5?}n6I9k<5!g{3)E)!mJO?fE`pr_M6x4!!+ zyn2eB3M9F;f@`k|YAj`=71smo5rr|&s>eUMv43dW_&y|Q4%^I@w<$+Lqra+^@SI+I zZ&39*)#1F#4b_W$^-x#_c7ZDTVIvRZfZ60%xBNp{b>uFz@&Ny%5dwk)0lsvn(zo`1 z{I;5*P|S(IC5SL`Ppw|CG@oNKTle%>f6b`!uc5N1SHt^nuK-!DE($W|6o)|N12ikd zK_fJfh6U*y!>c5m#%q49%1GVbWjkNS3>fmCBAHrxg$WFeJsc(%+bjy7P_l$#flMEI zRM5qBf3<(_`MfK3e%U_5=;~wt{@JATXHkJCtyaDRD|bUGiu)4I@TdC#4RYc0#7c>w zB?QhBs1~!a63$%+@m9`Zt@mHYeYopJ8{lZjhfjyeaSAVfD`n@A+K?VrUWqOY)F zF}QB{JNjAM!U2cWI3`9>&*hadlVSk-0%Oy%o>lnxQ$D9B*~|3sQ|ZW40TIvOOz$n= zH|N(jvO{a2312!AT1>#!Nfs-O8r8Z@8;K66!pyW1Qcwrqg1)UTbuiA}2%acOl=M_P zAJbTX_GJEqs%FWX3~)i$(sNY%GjSx}{b<8Qo!n}-%PmM$Oz14JS1#yHW$l|={SR}k z2?acdB!IV$(V?`RrPfv>@^E?);jXRbgEkZu#|vH1QLkY;;P^~pPrQEt)Tf@zKU=KMExV8RJO3sZ+woJ<;$bP*vnH_q=WG zuXvWG$s)e_^sdc%cq@=%pii3@uIHI*;>iq#j7Zz*`DSL$P6MM8egccf^psv8HqUoD z7MSVbp+PA(5?_PnmZ#f-r*xt}DPh6%;PfQ8ZePP+*u9Bv%$DQi6W-9@Hf3Pm4=>_Y z?6vEW`XEyAuAAm=$Mg+O?`KE;|C&yU9jqMzND!})!TSh-fBS4@AqFiGoWg(JEK6TJ zx?^&kEZ5A$4{>rclzFfXBQC5PIK$rdjRmS(z|*N#R=V%AJn2HXlQ~4a!vQ`SU?Df% zeR!?r^bVXfaaSt)kJrst%)6yFu$(PmVjcEs{Lxp+QHEDE9F+m?Le|MQH3@e+>zc~c zvhvb}-3h6rCTkveoL2G;yp-RmsZhlpFa*YN4A-_mD(}nzsys#@N+ATawhs7g6af2fQ z;Dq!}?s-6aTc<@6S8LVME2Pg&_Ya*=`_p>1#MK#dk(#d4pW9&U;!%fI--c=S7auKg z6Np$K0?BE1P~xRA^t!_HyZAuQi^vg^8!g(lS665q!934NoKmiPO9DH8bn)NDZbTXe z%Lw~m%s($b{0R&EFDy})39t#remKdrqk%>Z5Vp3IkW-r{lBN|t(WqbF^OCfaPR@}V z#AwA20L1yaGi1plcboFO5m+i;`rPa}cAD%w%N>8244#i`pe2(LZD^v}gRE!UuQT25 ztR5T`G#RcrT|5Z0o|k@&MG}w4jkS&E=#AWx*Z9@U#cGO8gcKb32dJWtj4ux?DDk zhyVxpeR=E*s<)~mXJAgF02{ikSMea3n7p~1!_>!_-!}PL@&u+SF zpFDM5P;&l>q~($^TlXun?M8&j^P9NaESgF>{!c0XN&%^wojkvlf4t7Q=8b+bgn(1d1hS|oJr!om?3!5 zK1($L(}Z^1LoMRkIi4>q<9;d0=bX0rCy2Ohb46C*J88~|yr=k7)b;tQ-0;z%gvwW* zpV#6p%6=oj2aPRl8zS6e0T1Nlkk!js7?OyD#lT$+xLGJJ1BtJ+l%zuv-lzb9;_g@H zsUD->CuSn*&cJB|C>pR&@M^z4b>#Js{iO}JdN%JB<|hv{{U<_uO7)9V;@U#7ZVK8L z=;i#l^j9uN(!bT8<&C;^a6wES|UeW_Oqy=-&~5-k$+ze7x~Z$;|ZA7b8~q zFu^I^VJL#(ZWCI?x?>Ds%)Nx$&n&pw^4j|hI-NB$gI*0%cchI#Y6(j`fIm|H-zNI- zk9I58ox6q`HVp1KUt>9QBh~>N_D5Nt2IBD=n&Eu3ZT&cIV?9!5&q&3G=Gv?N>%q`` zS(}fo_pdSKQiu6_^;F%{-M=6-khL~d~5Aq1D+Kne{0&r3OOD1`sMx>0yH1(|NU%A6<(g%K@n-aq zk#Tz(a~fyU!+!--qSpw89O2*iLTa~;iN;ZTE6);41U^duH`RvSLTrB{6W-bm@|~uT zcrSxn|9(c%1IWDc@>$9#){@lx+zR%hFwelMvBC#?R?}y_@IIP5B7%s$F^~41dsPUG z-o#u%da~C+p3)=KEA3#IA5N*bL01}emkK(VM%|ABcQ*Q&G@-boWi=A+Mh=K#aUUei z|I^u#SgCqZ0o8S37UYY_2vOl9ivhcp6n2DK{Z#%NfCG(m;0moG{(zA8N% z3U~5~HG&QiuyT!AwVodIivkj&-a9+f$H(-Q^v9c_s|qGTh`q%qh9#M~4di0a?j zEOl-ZyI37^Wf+&CJV&hOz-DOqCL_75K{b9)7eK4@6jOb~MZp{2hR&@ck)=;DBh$~U zr_H-XmP;X`>gs+iSt3vL?`qp+m|A4v6@cVg1u(XHn85C-eqrizbILywShxm0)Af5q z!TmU5e*S+0Dv#Y`MI?p+kJTrOuNYo3X%-;_u$8<9kxg=F*`5bRKN}sgWG}4DNCI}K zxd6b<5}W)ltSMZt*Rj~sJG#WKpYm8^Oukndawr?LySKNxLY{k&OrD)^N`LP}cS%Jv z$<_L0=AKS;KZKp(0by`aK=#6?`CZ!Q?9R$ByoW9oB>+;P=cP2PptwfQ-=gIgk}Fvh zgT4UE2iVR1zGoYdXJ3W=8}0Ms*2adba$(GryP86wXvQGNw&b*B2s4{%hXNEqrgKL| zEK`v~d7z=*a8ac+5ZzY_u+>l11*NAw^)sHWLb~u|yx0Ap`?oz+sISY~kQt5`QIbt; zjMCvt{BC`&33PmZ6ie@Kv!XUjikCp@)45M|_YU%}M+EEv<|}1ub}nJ;0lbPhF#gGU z9V0<`9xCV5!kePJ?w2hW6@7RQ%azY5L&<-XJYxl5=J}X;TNhjs$l#cMJ0|l2wbkvjE>RcKMwH+!wi`pW)lRC&^!*2gvsY;hmWO0?=Nw8X#5x@9$Mp7$BPlL+}b zpfkres%pyK_`Pv;^Q9y8$;*ip&8q<-_{k7h$sju@RtJ_m!(Ln}QgrdOF|{e(1LXEc zDbvHtm-dM+M!Z;eG|^v$i$Ax2d>B5ZXmMU8l@952UH(2v!tv3D!p&u2485M$*n86`#6 zI=R>_EroBH{f8z4io4y!$^C+`uE{w zw>sFpd!m1Tun|d5pF94V(pHVGzV%oacw|tmi<*}|xf8(u;L8QBz0e0v*BPFp`91{6 zoJ1J`9CKYwm3t9Gs#Bv_N_wWmAexTZJMu#fSYg#G{%OPkm$Xg^nbT$nJf%E|V*eZ- z3{{>~PSR%c;a?ac%=0D|m|X-te3qiSZ+AW6J@hk+nfK(^REU{l;9Jzf30kH03=iD* zvi^{P4X6GpU~j3yv%-%mQizIg)?=_jX^XFX9c?9c2t8%;RjwTHW;rvQJVKY?3ApZg z$4Wp;D{0dx?-BJ9Z(%7^FLEv(?in*`OIC#}HrX8*+U`q{+ly#F#3ygSQ%EKV`X9|) z?s*<}K~|+$`>X8J{#*evHXhU<$IIcPq>W0iQOgJ5N*)|s?A+~p3f^-z_qe_cq*X?x z=-yrY6s~j<`q~B_oBQDt@i(jBs4e?fiyv4iVaRx*Bj#P4ha% z7rhs$u@{oh3*5p>T>f+?wY~-oyA4=d)4RxMhl`ct)q3qGLr(PgdZE$FIgz~>`1R<1 zG60bR-iiL}{pXsL00f{P&$Qhpgn=$7Zx^@b;u3Rjtz>A@N1Kyz=A4Au*&|ll%`|>` zs%@~e>yfGHf^|yX$f_Y-upL0cWx;Be)lrw$>`tRn*b^C?ju7Py$^^`lXmXTPdnWM6 z&;RNVeyh8Tn<<6dh9YEN%1Aau*pd$z;rHtqCJ=U=CgfYKYoYke@@;~_t(`8*nzF5bGig6yY5 z93he?N};#b`B=qL9KY88wq5E`kzt#Xlx0dnsWuZo-i>m*8%gJ3z?qSK2w-)-%8T_L zIjeHr{u&kWGg@`AWN#yB6ODm-fxtF@-&m@7RH)Q}zRDXr#NAD9{e`y=-2CJE z+XIfjRP*OF8C0g$S91*vgnj>!_h=behKwObM!!fkto*fHjKWHiEI3Z;?JhE;xqOEg za>^yEyZmoc?^e}ZgAkA~y{x|W;V|gLtLS-Itqgpj8Zr|cBFAxhmqwshS5-xd3I=}* z5wrh$>9;ihtCjxLMh>R~|EM$1 zw1qkMEoJ!z-~kh5kb8}gei2qTtGNZWJ+|Ohj4Qpah}Tt$akwq=av`H^`Js1cA{eBvxxiiAf`9JiYp=I z7u9H7Yvton6W7SOy3?Cdr+_1HC4-88@oV7aZC_DOf3`9d%AvUc?ymakQn!Mk7i*!+ z6<+^6%EF|$uYkb6)e|GcW{GST_`QnWcWheEkFD+jIh8@#5ntP5W{hvdE~ub3zGT@x z?3lXjEbKOICdcr*OEcv(enN)G6VtgSC=`b}U?X(U(N!S)Xg6jLz>t+OO`=V@eA*%% zgq1b=2gpHrVO3F);i-$233NpXz$#vF_<*Bu)loWmMHZ-_Ym7-@9OO$db`F9z(y!VO z#e!1QPviBGyxyak;&H*)G6u%xQFT~!!a=2gZ>1RGPiiB=f27BP#jYF6a>?jK&rqmBnR%H za-DipN~3EQ@Fc4&HVqON8>Qy4vSP(@C3=2oQqcq$q5U7BNZ6*{#Dl8YkM7W;ns1VEL=LWNX^xmkC&{%48>B5D!SGV%QR@gqxS88a=uxZU1#L-?xuWQ_u z8Uvy(;}KOQj=$clK;&~z{~Sap?`hZD`E=JtYznv^7}@SEl|fJ4Bj*LUuhS?~rgm7Z8)xdMkOwAAmIQxXuT*;rBFJh>uX3tC3neY$T zQw5YlRJ7C+RgrFW8|8i6j_)M$&9!ScW-T(u`>r^Fd}|dN_3w!73&tn=o=UNry?e3$ z7ZXm8JK;dw2|e&{+|y$NfNr$DsbBFGi~W1zWLIL&jR+p~qP#{Z7xnBDQF=Pn`Zu<(et0~MneVFXp4*r816E65dZ7#D`P!8f zycAlW-3hWm?_z%sKNwlu6l~*g=@g0;WqwjY*RXZ*oluBkHkV{#Nw!i^%Kq2ge}HY& z?<`q+4dS8}O#&%5g9>!&On)+a@^l?rR6-6w3>=V}jX32m%;)WleRdYg8;x}JO!`-U ziNgSP4dG&1yntn`pObKYEr?!yxg?p(`Hwxows1%!TL`xGl_hMKjPT6uT{388;L?$w z!UUHE{KFh0>}61E1S-BTfg4hiT^w|Gt5E+ntXa7}WKQ<&iD|DB9C{kAbssi=|#$tosOsUmqFR_U3b zqttxPQdK5`mF3Pi^%3@z6xa)?xK;yF%+ywz?*@0^Qp5VO$(b`Q<$%g~ni1&5-T5`a zLClPRaVkX$fjVe{U^#673ApiVYbFSCzX3=kn!?u{8M^;_qC_$*JVRX6&13{5kIsPw zn!(uym>E|lwg7JuM;Ab&eZ7p?Ac8nN7?+Ol+xt|xeILfF@+%!G$uwfzAD0qX0Weo% zMGsbl0?y;{XL7=5AYO(sWM(a7_(NBYoL1$7%gdrn%%C2sIJ6*i+NM&I`>1hgEdu|o z@!7A#n9N5Ha$}qOU?2K--H{d1-!IJpcRR#6jcavt8exVdkjf?AMs4eR#g=B;;Y1Uo zaR=KbKDUOa!L=0oR?hW>uGh#DHL)Uz?1nH&mH_PVFh0%9haRkAwxDT(+N(pn;Dlu7 zD1Yr5WrOIpx6Fh`9!(nwC*ZJW=>AQV`5W->KkHp%7HmFLSe>^JnwdPek;)E0 z*=KbaG$@;LN^1DF9WA)^s;Bj$Qt1vN^3Fca3~(XoJRI!t-}$gJZNq^l3gTut=`2Lh zW?2$}7>J5ebDIZ;9oI`4jsG>aH;1TScY-6`c5&m9bCQRJFmj70G{cZh( z@`0JRBds_@CT-T&I2*9h=mC^gG`u;tlPYZTu5HvX`pD{@Xp zgDKCdrEcTVy_v!+6oCS_6`dGJBSN?gI@n%}E&!df8$Zw>GyqkYOq0oTIe9=0gB!8I z>Eex79yrRA&DfC0NNb2n^dscT0WvNXlT}9&_Pw0!o1M%~qtJgV-}971u@E-kFO5^^ zKVwR^Sj3S%BxzVj;kpQ*^_?KkB z`qkNxPM+7w9t(us4OqWaR*<*rr_KP1@SMJ-$oM2mW{+C4@UVo|-@|07a%6B_Bna1T|_V4h%tCY+_k~4B)5EX~6gW z%}S1uJ0o#n0YS(Lum1YaJL*Q+cGX7`J|^C7^SbXSE(m~F`M#y!#`b0C(~`z)QYZSv z)3K-ZziKtW>^^y7d5YKuH!HvUQ)$Oa73|%+GigC zs8eq9ko)e#eeuGkk-qz zYp2eTrQ*LlJAk`SXbyJnD$}l*!Nb`R`UBTr>0P+#LV;M)%pIj~J0?%UOhv`hjU?~m zfqHGTcY%bZ(bqBm>}-`mFo4522lh8%;fLyoK3Jt!d_}}|Z1bAT?&e(8cblv~xv$pBsX;H16244ia8m9J&WY&y0!wY=#YSM_(ucJ~h zy0Vt7%DSosQR8A>AzWSy)Ia}EM_9Jb$?TM)0gK$f0GS6ohPTly%Ey$}G&*OoIWCGj z%q*hCN0onkT+IZHHa^R?mH(9T+KFlbwQT`wE_lbX|>m@>91h^=mOr0i7`(?7#wm25#o}5~YoT z&q8ej(jk_H`AJ0i!EWMBWTvUe%lCI{y{Er5s?2&Hy$})wNX?mFVgL!o*DVjCsvH?C zWK>aOt}EC;@6#NYl4o=HXWsJTndR^4n{|u)jq=GGcQbvIR>{iP;K@&Y+4Mw5q~e-0 zVpb*5s`d&NSpV(`hjvJ7;hCrOl_@Ilh^><3^FFVaKbBajr{f}f&VO6Cw-8=5Qt30< zTDq;|JUj8xQL(|?0KA}x9o~Ym$}6oMO>8aaS#Xdm1o`@Bi>1{m4)BH}Ck+A;x1h}y zs0_&5WLCmO&4ePMWM~TFNE-x}F)_gf&a#~8(rp9@rv%YVKM^S8x~Rj4!G@eXcW!_6 zs}W)kfGk!>d=DUO%@U+#_W!C6k=f9}hS~m#d&`B4hG(;CYuTtR*&(sIgTtABGmvf1 ztE+c-4mUqP5smH<9@@g6Ml>q%;mWL|7H^TBGnk0<%@;-VG`rXqyNEUCJ8%0;i zO7~Gxtw6CHdW-&;JcmM(iW!@bm1evEzY|xG}yL>K4`Fz zB$Z)l5eDynIp_~Ry49Vjkad2XI}AR!-@z+o4`LH2f4~6T_C*wPKnzCZdktU5Mdw6* zIeR+T=wJyrxY8Z+jb%aD#E+dGs+#@24jX)h^<5|JbP$}6RN7^IiRAUBr(+{Z_8{#{0Vy_k~3YZfe4fuCm=grLhT? zDZIFKy6_@x`tAb@5q#7cj{2cOrz`KZNqF=T38rKHSlw`jY0zS@B61SuA%JW>NiDV& z;Yov3dg})*_#tIMUbBHWKDRBg^{iMK)N3p2x~xC-g&f*mDifl;CT($|-@jCVy_B#u zUh{F8XjB=p{qpk6W-1B5W9PYs?+X7_UUY7}a@Y0W{g;BWAf1L9-%?#EVo&$;AI>%4 z>otiZ)7r5fi^qV#l-(}penunsh}xd6b-dIg>xciHUTdX1VEBGiHzsu+EA>xl_T9_< zyoTHfV;8kWq)xRZ{oanUnsY9jW&U)##7u=dOSqg@HN!m-VFi%HMc&u8;!afqMkriD zn4KHkP!-`8+pJW&p1}Vi++M9aZ9xa*eoQj3L{PDETO-@sRuTZ^k$@}z6@Dx!j;AlE zM3p(V)bw3RmMf>a;(m`y=&Wod%;(!*-fiP?;%s%0I<9&W=6iraK1(M+S&`ZAK+4pN|BuB!|HE2`t(+QY7q3me>os{ zQjkx#BYb~_o$uTXSi|l1+{}3^BsJgos~F}mj*VqV8x|FeiAaqaB)(g=0jDH6XlvBx z_fX38WUm8GfON*;!IikVmwo3$$8#LeXh3yBe0)6RdzkbQD)@j?`PAHB!0a557m$+A zt=aO(-Nw?CAtx5}#~4FwGNU%|)c@U#jar-vx1isb)1Nahp_?^N)D0%^2*CcbEfh|4 z`p!4=3|vECep1dTmV5tm40zvuEgKsJKaUIWO`Zvn-v}JpQw0YQPMSBTIDXXwEEwwiKpXySr z^+h01%2#P{Y4X4YLnQ0QK{LidBQ^xd);5J5ZAEKKxe_jyqcO?O;>VI?ZjN5QwVQT$U{ej+ z^#B=u{N~Pe4&gv$I-Sq)2%vuR@pYFXj-=Xnzo0OPWSk>yLXpDvwA9fwCW4v&2qdvd zB>g9YVibt13{GGAtxP6Bmj6M8(koj0tZ5E)8<@ZU%0h6=SLoznaOy9lK-#q1AVppXSk5EhW3KPN-cB77pyPv@S*yL`qQJ9 zASxOmKNnl{kFoSWwgBG<#&O`!xg&1W@)D4m-x|E&BUlqqq<{^m*B@FNPkE)Xv@0wO zUkmy>7IeE&F$Apr@9&ne@s@*3Ifw4*O)|0}RD8=^%!|UKTqK=#xV*#%eZNF#Qi8+Hb33lIxI-bcAPB9edsEk%6* z#*$6KLptOiIgLM0F$WMYnm>ZNMx3pqNU;bchERL4VjnS=wqChp$w15ao%ots;Tbz; z#zq^A)H%z1bc)8G2J1FJQr@|K-(+OpqLbF)3X@XOpr5&pL5wZPjbH%se)R_;%ksS# z1pekCyGa>l`X-wpw1zUv=C!pTf5?9& zML15TYdd3>+FBdaKi+<1&=s66F3Ql1j93WhySYAsV`9%|F|+z-yp0DFZCOS7)aIOv zk&mBYMOe>95BqbMd^4#dQ)G%GMV7ctrA`?~6t|E!cs~WH#CHFC%&8ooOKO{gozp#s z^bmCc|I+k}1*R{}+w!JHB`ntEafGeqQH>i|pP8;Gh0-V1Ql5_x;L@ z(yjw_vX7P>02e!`NE|akoIZ47ol7qx7pISAClN2);!Z&g-92EAMA1!wDZ)=L$^F~K zZr)&X8*qCqhyTM);wioIK!V)x>2`EzHaf(}dj?;Jc@Uf+cwVz7GuV8l>@Jmys&Sqp z0X#G7s>8oyn|bAnr9)c0%EKQQt8+ciU(j*MQ=@T}ukk)qxsvU`S^qNAkFe5|2@yWj z?01YlKRD>8ePfGcRCxg_2aGydw&c_p8Dfm@$oeyxU)HamLRSu^BAE@(f*>= zg^Ch$nxt>hl71+~e=pM+^FO4gBi1fF6xpf+W*|mT?*l(xh4T;|xNAaOIS$uG16p1} z;VgJP*!u_~%%?q*S8x$XkhQM-W_O!JTofAR*w#*GGmf1cz6Qz$w%d-oRrFCm zK1k4S#$3mqVQnkM*IV3YW}0nU`$T_&pzh8f#rYtY)pS3oN4*fzRyz`z{aoLszY4Zh z%n2iqG)p`x4}~S*Rq^3Z%HzEiUMNz^9=?X7NYg830yeIk_*99CbRlOst_5M0ddC@G z1wn}@QYdqzQ+Y`0n0=0G*G(QIlp(NpNIyRl$bittRPw9W^?#18_qwZ>Iwl?J4WAi$Zwm zd_54Fdw*uKUJes&Erc^O{Y=T#WFFrku67z5<~@EZWx4-+c>CrWE6s)scuH3gSX$28 z{hMvxR--1Vs~j5{Ks7B|=Az%Vki39?q%>Fov7A~!#3@{q@RNv%0P=f|oB#j- From ece0c1c1de6403821fefd5ef94f149327f5cafc1 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 01:13:55 +0100 Subject: [PATCH 059/489] fix settings, missing in apps.json --- apps.json | 4 +++- apps/ffcniftya/ffcniftya.settings.js | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index e5e9f8f02..f2c5bbce0 100644 --- a/apps.json +++ b/apps.json @@ -4328,7 +4328,9 @@ "storage": [ {"name":"ffcniftya.app.js","url":"app.js"}, {"name":"ffcniftya.img","url":"app-icon.js","evaluate":true} - ] + {"name":"ffcniftya.settings.js","url":"settings.js"}, + ], + "data": [{"name":"ffcniftya.json"}] }, { "id": "ffcniftyb", diff --git a/apps/ffcniftya/ffcniftya.settings.js b/apps/ffcniftya/ffcniftya.settings.js index f4112c9d7..03d9f76f9 100644 --- a/apps/ffcniftya/ffcniftya.settings.js +++ b/apps/ffcniftya/ffcniftya.settings.js @@ -22,4 +22,4 @@ } } }); -})(load); \ No newline at end of file +}); \ No newline at end of file From 026a55f4fe96264953744e04bd2a4f740f5fe5c1 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 01:18:14 +0100 Subject: [PATCH 060/489] settings and apps.json --- apps.json | 4 ++-- apps/ffcniftya/ffcniftya.settings.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index f2c5bbce0..6c516bae5 100644 --- a/apps.json +++ b/apps.json @@ -4327,8 +4327,8 @@ "allow_emulator": true, "storage": [ {"name":"ffcniftya.app.js","url":"app.js"}, - {"name":"ffcniftya.img","url":"app-icon.js","evaluate":true} - {"name":"ffcniftya.settings.js","url":"settings.js"}, + {"name":"ffcniftya.img","url":"app-icon.js","evaluate":true}, + {"name":"ffcniftya.settings.js","url":"settings.js"} ], "data": [{"name":"ffcniftya.json"}] }, diff --git a/apps/ffcniftya/ffcniftya.settings.js b/apps/ffcniftya/ffcniftya.settings.js index 03d9f76f9..d9a1c9fca 100644 --- a/apps/ffcniftya/ffcniftya.settings.js +++ b/apps/ffcniftya/ffcniftya.settings.js @@ -22,4 +22,4 @@ } } }); -}); \ No newline at end of file +}) \ No newline at end of file From 1fb1489577a09e24a6f9b23ee734f795e4475d00 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 01:27:13 +0100 Subject: [PATCH 061/489] fix settings filename --- apps/ffcniftya/{ffcniftya.settings.js => settings.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/ffcniftya/{ffcniftya.settings.js => settings.js} (100%) diff --git a/apps/ffcniftya/ffcniftya.settings.js b/apps/ffcniftya/settings.js similarity index 100% rename from apps/ffcniftya/ffcniftya.settings.js rename to apps/ffcniftya/settings.js From aadc5eb65dde7a4f6f3b0ab3aff8975ca180f7a4 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 01:30:48 +0100 Subject: [PATCH 062/489] Update README.md --- apps/ffcniftya/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index 122483243..0c5e88b3d 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -4,18 +4,18 @@ Colors are black/white - photos have non correct camera color "blue" ## This is the clock ![](screenshot_nifty.png) -[i]emulated[/i] +*emulated* -![](phptp_nifty.png) -[i]photo[/i] +![](photo_nifty.png) +*photo* ## The week number can be turned of in settings (default is [b]"On"[/b]) ![](screenshot_settings_nifty.png) -[i]emulated[/i] +*emulated* ![](photo_settings_nifty.png) -[i]photo[/i] +*photo* From 85b4468e818620e2bd0d13aacf1d7f5c455e4b66 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 02:40:32 +0100 Subject: [PATCH 063/489] Update README.md --- apps/ffcniftya/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index 0c5e88b3d..a4ef073dd 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -10,7 +10,7 @@ Colors are black/white - photos have non correct camera color "blue" *photo* ## The week number can be turned of in settings -(default is [b]"On"[/b]) +(default is **"On"**) ![](screenshot_settings_nifty.png) *emulated* From 12d5fb28ef2ced37f854eb4a632cf3d453bff6f9 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 02:47:01 +0100 Subject: [PATCH 064/489] Update screenshot_nifty.png --- apps/ffcniftya/screenshot_nifty.png | Bin 2379 -> 2159 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/ffcniftya/screenshot_nifty.png b/apps/ffcniftya/screenshot_nifty.png index de6ba651d3a25034c1fc4006efb5e3ca4dfdc860..bbee9e27cc3554f596fd9478068376001cc1740e 100644 GIT binary patch literal 2159 zcmcJRdpHyNAIC={VN54oFdCJ_{7Q4%a+ym+NUk$t$1t~Y*EZxDr!r1GE=Mlw2=AWJqfPp zWB@?z*^iLZJnoha04M>^IiY;7URs<|@tLwxy^dYj*%`&0=Y`!$)_-w3gS9nWJ#IAe z+;bHTZQyV0*!IaKtO<8^HaL{NYh91P1+P zq4XQIjpF?}N*^cfUdHcH$)0vS9wgAm#lN?68Jmt9dCsklU2Uwju#0~BuDD@xBL>5= zKu>oI`wSBn@e?;2#+R3d2v(U{bZ#%5Hxumy@kqV{yKKKqpbO6=X3cfLhHjiPg^Y-Y z)^%NeI#@g=+)e61tpukYZ7B&rW@ZKEMZ2t=sHznZ+cuj<)w9S~`_)^>6gfF1E!zf{ zSKEY!$)(Gf3YfJ}#W(9>Bmp$2uLCSL5XY-$6 zr@Dd&wimA!3tmgg7%MuKxCOjDAXgE1_#blJO9YFMJkXy~v(tdXcb)!fzI~RhYr6aB zcQi(dizvF!zgJAL35HbNm#&rdQB$@I4e;OQ{0iNk1Y{j{WPf%%qO#*`Ih)A?7BM_tqhdS!zt|u5k1;2WeDYNd%p5IwXN}=C%+ce-sba`hc?wdBZ z@MQ_Ps~m<1^3qsZSe2l_aO%?GH>Ba|H(RR`ENC7w(s|HEneM=m1mvgA!GO8jYAW z%HeM$8Z>(EZcs9qM*l4QN8$f%!{3z6uT$l07jfde?e?5Xitl4Ey{@+uP>cdE{Y33> z%S*GYAco4f4AzGi`r^u=?q|rNh>FCvBFY}8d~Djx#q^lW&NJO#V@nP2{~10m9nT>Z zl!`QH*EMfs`VUa&J()vbT7h$6D|}_rP#<5`v_DW<+wv(me?$$1sZQ_U&AN$0!*x)` z?YV<0D1Nq3zLXrISEsm5bgUM8MUf=F8GigSw*HO{ zkBj27T$!?sd|P~T`Y&)>#GwT|*+l-VC2~*$h3N=qKfjZuE^$+FE%i(qs*baU(2V8Bn|#G zZskbN6-WRldGJgV4sGQv=u`1{HPN_6YL)P|+`0)`8$D#hXw6bCxgbDs`9#L;_*&T& zKx?{%WFy^p4n&);8R>N^$8*!_oBmk(Mg$EmLAw&n(^%Ew_*&i0d@?sogEn44uijN) zs|RT{)9Unnz0V>BI0BX%)XeoiD2mKirS|ST*?_Go+9TEC+5W0%>k3WA2D}H-Dm+%4 zl5d=^YIyQm3QhH{O9H37Eme{O`|*FRF8(xyjzlY?dySyXRdrEH+Ov?2B#hy#!AhOO!+oz#}Z7!j`j4A4WQ64 zs}YNxWZl(SP9p5bP+eb8n$bq>k_W>Fruh8Oc5pSfu7uGk`y>F)IeR*_IfUi@7n-mH AkpKVy literal 2379 zcmds(c~lbU7QnG`Dod+zQZvX(6C0Pt9Z)gN#L^&jGM6+7l@wQy+_lou!f=Ul($XfE za>HD(QA{*b5ETX;#l$sKEHm82{n0<~yno(*@2_{x@7{avIrpA>zVF`qo$tYABtl+J zRSp0E$X~Ftagy2rsci1qA=Ov^)>1>%y!7xSIcEXKsLW zLC}YRrJ9h4g+X%&(w@9J3s;-0qHWs*|DB78Kb$=j`skRN$p2uTdZ*eK8cp;|a8IUC zbZRP`_vGgzSk*TEkg%`Df5khioSuBTbX`jksgs*?W~HTG?YH{RZ~x3Rr{Im~Ue-D~9)nmvZ0dDLD1)o0n1^)mfEJF?v!b1H zIj{JV64z zO5ZaWAKUy?LRd1iUT43o#rmY}5wOm{RpwR{%;Ijx2SYaGkXAe|(KkcdoBX8NTWUe? zwnGHVwL`|I@v&aes-eC*k_I!mwSf%REi8A87g1PqQN`7$sC!mp8HD4^EEq#0AG#t_&j7kR5Vm((sylDTC;%HY={&uU&Qv+I}RU?T{h<{)T z*2@H*a_wt<*+ASeE-}ZDw0|6f2ALCt+mL^?4ycR728Ppdcg|CQy)&P4*5zL?$;)EkmiEcxf;jxuy85S$*23#i)a9D4%)@^@8Cx zl5j|n8%7Cx)ilN>-&S@eN9gUe;2N_bVM)?SFM|$Ot1Mb}XbC@F73Gyh=&b>!;mt7N z_+y$Uk(?p)xemJ^C)7aD+kp9;_Qs&-To4#KK%7u9c34(dT=)ml&f}b5vLK(*Q0<%2 zIJ0-auq5D&WcZLZ>%X9oppDt^9q5fsclj8hSi=45q3@xDhBvt+1&>-JsW}ije7W;5 zGp&VOOCNq3pg&5=RifXF^^6V;bDn^Fw`ts}ktl`ed1#bk)GKbx%O!4zWV;><+2XJs zZ(^Wme#f5O?P)@MXBchU#rA7ZE1cAZK6>CL)E!3Ibb5_ACV%ehXES#kv4;CoVlNO={kw$S@ihwmL5qgb-uK35t0fft&qS_E2d zX>$$@bbayc9;o%dNfCf?9m;ymDS3LjuiL;lWrb4AUxQEgl1h%1H5s_W7P_Bc2p(N# z!+|MQoB|8xR&lgxvDrvlWu*};dMiKGk8<~%`yDnISFAOoj`m+H%)}I2F5r~juyTjO zsU_#1+D71^a2n*EDDG=<##>mUQ4*^=QnnQs;#KJS3o&wQ9fVTezpgKKi^)D$rs@@~ zr1Xz-FjTdIhRj&0QK1kvfNi~CYNx1cAYS%7mFPi2&zhz(R*42O$v_;IC6SQ)P62CY zSXuWa>^IMc>3+AJcV96Oynn_g ziG%1CMSCsTHJ93n{1cBvTKO}tJHKbFV&rn}PIEpVt1c%8=$c4?4(Q0$BA&;7KM&AR ze8ZYt!HG-h9lb^FAe_hkxbzfCJ7enfaT}|JaaWpA_p731hPdA{|LN^-+#B4vNu{2q zNcrb5=}K34_698aXDB%qPIuMUu{acwqMlvV5Us$8{PbSI*!+Z-gir^vAqcHf2C zG0~lr2W@c4LeWY+rxp(j;90sC7z9j`8R{;EAOFcZA$LM#)%_ V>F&$)YUu|EaN#`ChHCA7_g`( Date: Sun, 26 Dec 2021 02:56:59 +0100 Subject: [PATCH 065/489] Update README.md --- apps/ffcniftya/README.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index a4ef073dd..769cbcb74 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -3,19 +3,16 @@ Colors are black/white - photos have non correct camera color "blue" ## This is the clock -![](screenshot_nifty.png) -*emulated* +![](screenshot_nifty.png) (*emulated*) -![](photo_nifty.png) -*photo* + +![](photo_nifty.png) (*photo*) ## The week number can be turned of in settings (default is **"On"**) -![](screenshot_settings_nifty.png) -*emulated* +![](screenshot_settings_nifty.png) (*emulated*) -![](photo_settings_nifty.png) -*photo* +![](photo_settings_nifty.png) (*photo*) From f9c3827596c8b9a2e380009990a9a8dd8b71777e Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 03:17:48 +0100 Subject: [PATCH 066/489] Update app.js --- apps/ffcniftya/app.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/ffcniftya/app.js b/apps/ffcniftya/app.js index 33722b3a3..5f23599a0 100644 --- a/apps/ffcniftya/app.js +++ b/apps/ffcniftya/app.js @@ -1,6 +1,6 @@ const locale = require("locale"); const is12Hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"]; -const CFG = require('Storage').readJSON("ffcniftya.json", true) || {showWeek: true}; +const CFG = require('Storage').readJSON("ffcniftya.json", 1) || {showWeek: true}; /* Clock *********************************************/ const scale = g.getWidth() / 176; @@ -43,6 +43,7 @@ function draw() { const day = d02(now.getDate()); const month = d02(now.getMonth() + 1); const year = now.getFullYear(now); + const weekNum = d02(ISO8601_week_no(now)); const monthName = locale.month(now, 3); const dayName = locale.dow(now, 3); From 8d6a16dc7446671b5ca201234eaf2f23b544253c Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 03:30:19 +0100 Subject: [PATCH 067/489] settings showWeekNum --- apps/ffcniftya/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/app.js b/apps/ffcniftya/app.js index 5f23599a0..5da1ec48e 100644 --- a/apps/ffcniftya/app.js +++ b/apps/ffcniftya/app.js @@ -1,6 +1,6 @@ const locale = require("locale"); const is12Hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"]; -const CFG = require('Storage').readJSON("ffcniftya.json", 1) || {showWeek: true}; +const CFG = require('Storage').readJSON("ffcniftya.json", 1) || {showWeekNum: true}; /* Clock *********************************************/ const scale = g.getWidth() / 176; @@ -59,7 +59,7 @@ function draw() { g.drawString(year, centerDatesScaleX, center.y - 62 * scale); g.drawString(month, centerDatesScaleX, center.y - 44 * scale); g.drawString(day, centerDatesScaleX, center.y - 26 * scale); - if (CFG.showWeek) g.drawString(d02(ISO8601_week_no(now)), centerDatesScaleX, center.y + 15 * scale); + if (CFG.showWeekNum) g.drawString(d02(ISO8601_week_no(now)), centerDatesScaleX, center.y + 15 * scale); g.drawString(monthName, centerDatesScaleX, center.y + 48 * scale); g.drawString(dayName, centerDatesScaleX, center.y + 66 * scale); } From 13483ee80cc5d6a09dd89f9f5373d8b59df289c4 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 03:38:26 +0100 Subject: [PATCH 068/489] Update settings.js --- apps/ffcniftya/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ffcniftya/settings.js b/apps/ffcniftya/settings.js index d9a1c9fca..3e69f08dc 100644 --- a/apps/ffcniftya/settings.js +++ b/apps/ffcniftya/settings.js @@ -3,7 +3,7 @@ // Load settings var cfg = Object.assign({ showWeekNum: true, - }, require('Storage').readJSON(FILE, true) || {}); + }, require('Storage').readJSON(FILE, 1) || {}); function writeSettings() { require('Storage').writeJSON(FILE, cfg); From 69276a06babd56e57cd82454ad652f9c4ba9a07e Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 16:04:51 +0100 Subject: [PATCH 069/489] Update settings.js --- apps/ffcniftya/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ffcniftya/settings.js b/apps/ffcniftya/settings.js index 3e69f08dc..65b6486b1 100644 --- a/apps/ffcniftya/settings.js +++ b/apps/ffcniftya/settings.js @@ -1,5 +1,5 @@ (function(back) { - var FILE = "\ffcniftya.json"; + var FILE = "ffcniftya.json"; // Load settings var cfg = Object.assign({ showWeekNum: true, From 9d30fe8139aff7613ffcfad17b75f1ef2a52cf5d Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 16:17:42 +0100 Subject: [PATCH 070/489] settings name typo --- apps/ffcniftya/settings.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/ffcniftya/settings.js b/apps/ffcniftya/settings.js index 65b6486b1..46e4ef5aa 100644 --- a/apps/ffcniftya/settings.js +++ b/apps/ffcniftya/settings.js @@ -1,9 +1,7 @@ (function(back) { var FILE = "ffcniftya.json"; // Load settings - var cfg = Object.assign({ - showWeekNum: true, - }, require('Storage').readJSON(FILE, 1) || {}); + var cfg = require('Storage').readJSON(FILE, 1) || { showWeekNum: true }; function writeSettings() { require('Storage').writeJSON(FILE, cfg); From d03749ed92fd10fa690a7e79c6a5da857a826297 Mon Sep 17 00:00:00 2001 From: 7kasper <7kasper@users.noreply.github.com> Date: Sun, 26 Dec 2021 17:14:08 +0100 Subject: [PATCH 071/489] Initial release of presentor app. --- apps/presentor/app.js | 277 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 apps/presentor/app.js diff --git a/apps/presentor/app.js b/apps/presentor/app.js new file mode 100644 index 000000000..d9b032bd0 --- /dev/null +++ b/apps/presentor/app.js @@ -0,0 +1,277 @@ +// Presentor by 7kasper +// Licensed under MIT. +// Version 2.1 + +const MouseReport = new Uint8Array([ + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x02, // USAGE (Mouse) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, 0x01, // REPORT_ID (1) + 0x09, 0x01, // USAGE (Pointer) + 0xa1, 0x00, // COLLECTION (Physical) + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x01, // USAGE_MINIMUM (Button 1) + 0x29, 0x05, // USAGE_MAXIMUM (Button 5) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x95, 0x05, // REPORT_COUNT (5) + 0x75, 0x01, // REPORT_SIZE (1) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x03, // REPORT_SIZE (3) + 0x81, 0x03, // INPUT (Cnst,Var,Abs) + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x30, // USAGE (X) + 0x09, 0x31, // USAGE (Y) + 0x09, 0x38, // USAGE (Wheel) + 0x15, 0x81, // LOGICAL_MINIMUM (-127) + 0x25, 0x7f, // LOGICAL_MAXIMUM (127) + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, 0x03, // REPORT_COUNT (3) + 0x81, 0x06, // INPUT (Data,Var,Rel) + 0x05, 0x0c, // USAGE_PAGE (Consumer Devices) + 0x0a, 0x38, 0x02, // USAGE (AC Pan) + 0x15, 0x81, // LOGICAL_MINIMUM (-127) + 0x25, 0x7f, // LOGICAL_MAXIMUM (127) + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, 0x01, // REPORT_COUNT (1) + 0x81, 0x06, // INPUT (Data,Var,Rel) + 0xc0, // END_COLLECTION + 0xc0, // END_COLLECTION + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x06, // USAGE (Keyboard) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, 0x02, // REPORT_ID (2) + 0x05, 0x07, // USAGE_PAGE (Keyboard) + 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) + 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x08, // REPORT_COUNT (8) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, 0x01, // REPORT_COUNT (1) + 0x81, 0x01, // INPUT (Cnst,Ary,Abs) + 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) + 0x29, 0x73, // USAGE_MAXIMUM (Keyboard F24) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x73, // LOGICAL_MAXIMUM (115) + 0x95, 0x05, // REPORT_COUNT (5) + 0x75, 0x08, // REPORT_SIZE (8) + 0x81, 0x00, // INPUT (Data,Ary,Abs) + 0xc0 // END_COLLECTION +]); + +const MouseButton = { + NONE : 0, + LEFT : 1, + RIGHT : 2, + MIDDLE : 4, + BACK : 8, + FORWARD: 16 +}; + +const kb = require("ble_hid_keyboard"); + +function drawMain() { + g.clear(); + E.showMessage('Presentor'); +} + +let HIDenabled = true; +let lastx = 0; +let lasty = 0; +let timeoutId = -1; +let holding = false; +let timeoutHolding = -1; + +let homeRoll = 0; +let homePitch = 0; + +let trackPadMode = false; + +let mCal = 0; + +let clearToSend = true; +let mttl = 0; +let cttl = 0; + +NRF.setServices(undefined, { hid : MouseReport }); +NRF.on('HID', function() { + HIDenabled = true; +}); + +function moveMouse(x,y,b,wheel,hwheel,callback) { + if (!HIDenabled) return; + if (!b) b = 0; + if (!wheel) wheel = 0; + if (!hwheel) hwheel = 0; + NRF.sendHIDReport([1,b,x,y,wheel,hwheel,0,0], function() { + if (callback) callback(); + }); +} + +function getSign(x) { + return ((x > 0) - (x < 0)) || +x; +} + +function scroll(wheel,hwheel,callback) { + moveMouse(0,0,0,wheel,hwheel,callback); +} + +// Single click a certain button (immidiatly release). +function clickMouse(b, callback) { + if (!HIDenabled) return; + NRF.sendHIDReport([1,b,0,0,0,0,0,0], function() { + NRF.sendHIDReport([1,0,0,0,0,0,0,0], function() { + if (callback) callback(); + }); + }); +} + +function pressKey(keyCode, modifiers, callback) { + if (!HIDenabled) return; + if (!modifiers) modifiers = 0; + NRF.sendHIDReport([2, modifiers,0,keyCode,0,0,0,0], function() { + NRF.sendHIDReport([2,0,0,0,0,0,0,0], function() { + if (callback) callback(); + }); + }); +} + +function handleAcc(acc) { + let rRoll = acc.y * -50; + let rPitch = acc.x * -100; + if (mCal > 10) { + //console.log("x: " + (rRoll - homeRoll) + " y:" + (rPitch - homePitch)); + moveMouse(acc.y * -50 - homeRoll, acc.x * -100 - homePitch); + } else { + //console.log("homeroll: " +homeRoll +"homepitch: " + homePitch); + homeRoll = rRoll * 0.7 + homeRoll * 0.3; + homePitch = rPitch * 0.7 + homePitch * 0.3; + mCal = mCal + 1; + } +} +Bangle.on('lock', function(on) { + if (on && holding) { + Bangle.setLocked(false); + Bangle.setLCDPower(1); + } +}); + +function startHolding() { + pressKey(kb.KEY.F10); + holding = true; + Bangle.buzz(); + E.showMessage('Holding'); + Bangle.on('accel', handleAcc); + Bangle.setLCDPower(1); +} +function stopHolding() { + clearTimeout(timeoutId); + if (holding) { + pressKey(kb.KEY.F10); + homePitch = 0; + homeRoll = 0; + holding = false; + mCal = 0; + Bangle.removeListener('accel', handleAcc); + Bangle.buzz(); + drawMain(); + } else { + timeoutId = setTimeout(drawMain, 1000); + } + clearTimeout(timeoutHolding); + timeoutHolding = -1; +} + +Bangle.on('drag', function(e) { + if (cttl == 0) { cttl = getTime(); } + if (trackPadMode) { + if (lastx + lasty == 0) { + lastx = e.x; + lasty = e.y; + mttl = getTime(); + } + if (clearToSend) { + clearToSend = false; + let difX = e.x - lastx, difY = e.y - lasty; + let dT = getTime() - mttl; + let vX = difX / dT, vY = difY / dT; + //let qX = getSign(difX) * Math.pow(Math.abs(difX), 1.2); + //let qY = getSign(difY) * Math.pow(Math.abs(difY), 1.2); + let qX = difX + 0.02 * vX, qY = difY + 0.02 * vY; + moveMouse(qX, qY, 0, 0, 0, function() { + setTimeout(function() {clearToSend = true;}, 50); + }); + lastx = e.x; + lasty = e.y; + mttl = getTime(); + console.log("Dx: " + (qX) + " Dy: " + (qY)); + } + if (!e.b) { + // short press + if (getTime() - cttl < 0.2) { + clickMouse(MouseButton.LEFT); + console.log("click left"); + } + // longer press in center + else if (getTime() - cttl < 0.6 && e.x > g.getWidth()/4 && e.x < 3 * g.getWidth()/4 && e.y > g.getHeight() / 4 && e.y < 3 * g.getHeight() / 4) { + clickMouse(MouseButton.RIGHT); + console.log("click right"); + } + cttl = 0; + lastx = 0; + lasty = 0; + } + } else { + if(!e.b){ + Bangle.buzz(100); + if(lasty > 40){ + E.showMessage('down'); + scroll(0,1); + } else if(lasty < -40){ + E.showMessage(kb.KEY.A); + pressKey(kb.KEY.A); + } else if(lastx > 40){ + E.showMessage('right'); + //kb.tap(kb.KEY.RIGHT, 0); + scroll(-1); + } else if(lastx < -40){ + E.showMessage('left'); + //kb.tap(kb.KEY.LEFT, 0); + scroll(1); + } else if(lastx==0 && lasty==0 && holding == false){ + E.showMessage('press'); + clickMouse(MouseButton.LEFT); + } + stopHolding(); + lastx = 0; + lasty = 0; + } else{ + lastx = lastx + e.dx; + lasty = lasty + e.dy; + if (timeoutHolding == -1) { + timeoutHolding = setTimeout(startHolding, 500); + } + } + } +}); + + +function onBtn() { + if (trackPadMode) { + trackPadMode = false; + stopHolding(); + drawMain(); + } else { + clearToSend = true; + trackPadMode = true; + E.showMessage('Mouse'); + } + Bangle.buzz(); +} +setWatch(onBtn, (process.env.HWVERSION==2) ? BTN1 : BTN2, {repeat: true}); + +drawMain(); From 5f5b32eb148af5d44c15247576c010d5ea2691cc Mon Sep 17 00:00:00 2001 From: 7kasper <7kasper@users.noreply.github.com> Date: Sun, 26 Dec 2021 17:28:22 +0100 Subject: [PATCH 072/489] Add app image. --- apps/presentor/app.png | Bin 0 -> 2208 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/presentor/app.png diff --git a/apps/presentor/app.png b/apps/presentor/app.png new file mode 100644 index 0000000000000000000000000000000000000000..d29cf7be6f4ce71b2de84afbb97cc8c3085dc3bb GIT binary patch literal 2208 zcmV;R2w(S!P)VL{@Xy-X{om%s;f+QiB#6t8QqDST47r zc@(s*wfJf0zFqH4?{~@U!1NgUv~?mLYi+BnkM2^*pic;~r=q6rR6N%9;ko@TnH^ZU z`CgyT@He9w5%7^AvTq!1*>h^DeQje?qkvb0(2pEzY5vR9_m|8L4BvaJs^}T3LQst0 zdrHeE!qJ9E@v5s14t2Ms6S3ADaQl@iL=bL+C0PD9jJ*qW7?kG>x^76~BTq^i=Tbgcm4b>Vl z-Mfms?sfz5?%Hdc?#kD{eczw|+fkmlL2KTTj`@$(TYp{*AeSYcLW|(qMED+9q7+)w z_`p^ncs=6F8YMo5vXGaMUm7Dex0ct`cPC=4AJ=WWKTxu~;osqC{Y@1s8^+^3t;cC^ z*YSqvKf|_vyWy%0@mTBL)9vkUc};yrz`gNU>$8h4U`^u#Tcyx%M0{Bz7Ey+HM%2q+YOHW3>24w}o)@(S@OS{I)kq-D2Os(8T#|xHyBjcO|>7prt;~OPBl$^Hp=4eE@&N?4)68(8A(aTGlEgu0YC~tk>8-$ zrzs1}T)(lDq9?AhO6Z?-w(NRwuHRfR0n_14kDvZ=Nx>O8N8k4I&p33sb^9LCm zA7fcy=A4C!xL^V6wlv)gycY3ijgU2&^MfgY&l}*c4{gDef>;03%?m9Z45YGLQRL;m z8^2ED#%df_air%Id){ixIro^Y=^1n~uI8G2*NzK1#JS)N%VgMwrt3Fi8Ir#pIL?c2 zw)5NSa^BpqoO^Vdov*a=_R&5}LsGY@imI}robwm?1>umiOvEqpG0a;)E_l;2$vB#f zquI1Nf~z#owj5(;^fJCv5+pP>M5D~`Gb_uUy+_Z^<@NaU{*KaUjdmAQKt6Z?M`?l{ z6R%~^Ka#{%ny-btlWpk~0JWB;cQ}dTDjZkw#^IA>b07}en!yR>xLQBCU;@@OKCl&d zE#jLA4`2w%M8?5!6_Mh}mHoudOtyJE033HAQsl)nB#H49XpJ$AWW-kVCY-EN;?Ayp z%|{kQKp_>@XMrUJZQZA_49WMuRl{Skem=1?_{+i^)do*xJpAa|bpRYXK0tB6kER?fZ&;yW7MyXaNi9Z0r+zu>r>jN2AkLpqfzc<@kCAwyvrc05k7dNqmhFSjo?Jb?V{{Xf_Ow?3IQ z`c5Z3IN2;I+XkSs-(fVB-^+ynHmCBo;=|L8t9mKq-N7|wh|Tnu=a#WBxE#KnS#IV`^r5f>943aDALiMZJCP+-x` zB_fUYqQk>^{JFdSn)|DyM;tN?ak(X2k<1#77HnV4B2`G7*V}OU)xY!?1(H7mQSJ)y iO4q-h?p`dgLgW8Yi`ZcrY`y>h0000 Date: Sun, 26 Dec 2021 17:31:16 +0100 Subject: [PATCH 073/489] Add app icon file. --- apps/presentor/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/presentor/app-icon.js diff --git a/apps/presentor/app-icon.js b/apps/presentor/app-icon.js new file mode 100644 index 000000000..76939d548 --- /dev/null +++ b/apps/presentor/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AH4ASlgADGmIxwLV4wqGQowfWZQwjKw4wJF7ghBmVWmQlELYoweFwYABGAwrHF7IuFGAwrIF7AuHMJADGF0AwHAYovWFxaSHADQuDEgIADYZYucAQOB1fQ1eBmQwiFwlX6AAE1gqBGD6MEmQqBwIICwIGB0rDeWYksFAIuBz+fvQHC6D0dcQssEwIuB4fC4V0M4VXF7YuFDYLqBlnDF4WeHAYugL5N6L4I4BF0IvB0vQvdQGAJeBY4YucmQxEAgJgBvYOBdwYQDFzUzmZ/EllXFIKKBAYVXBwSMaller7fFAoKSBAAOBFQK7dPoJfFEoYADRjgmEeIzFFdUQAOdUIumdRLtDAAIufdRQKCr8zCQjqmE4NeF4YudWxpqCFyovBK5LqiF6DqdR6D0BdTYwJGg5sBdTQwKEAIwHdTQwMSpQueYaAufGBouiGBYukGBIumGA4uoGAouqGAYABF1QAl")) From 1bac672658ea5b37a6220729a1bf429768893657 Mon Sep 17 00:00:00 2001 From: 7kasper <7kasper@users.noreply.github.com> Date: Sun, 26 Dec 2021 17:35:12 +0100 Subject: [PATCH 074/489] Create ChangeLog --- apps/presentor/ChangeLog | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 apps/presentor/ChangeLog diff --git a/apps/presentor/ChangeLog b/apps/presentor/ChangeLog new file mode 100644 index 000000000..a7d747684 --- /dev/null +++ b/apps/presentor/ChangeLog @@ -0,0 +1,6 @@ +0.1: Start of app. +0.5: BLE keyboard functionality. +1.0: BLE mouse functionality to scroll back/forward. +1.5: Added accelerator style mouse. +2.0: Added touchpad style mouse. +2.1: Initial internal git(hub) release. Added icon and such. From 6a25e7901fd1e9a90359fb30bc3b1f9baedebcfa Mon Sep 17 00:00:00 2001 From: 7kasper <7kasper@users.noreply.github.com> Date: Sun, 26 Dec 2021 17:57:56 +0100 Subject: [PATCH 075/489] Add presentor to the banglejs app repository. --- apps.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/apps.json b/apps.json index e5e9f8f02..e4e53470d 100644 --- a/apps.json +++ b/apps.json @@ -5062,5 +5062,22 @@ {"name":"ltherm.app.js","url":"app.js"}, {"name":"ltherm.img","url":"icon.js","evaluate":true} ] + }, + { + "id": "presentor", + "name": "Presentor", + "version": "2.1", + "description": "Use your Bangle to present!", + "icon": "app.png", + "type": "app", + "tags": "tool,outdoors", + "interface": "interface.html", + "readme":"README.md", + "supports": ["BANGLEJS", "BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"presentor.app.js","url":"app.js"}, + {"name":"presentor.img","url":"app-icon.js","evaluate":true} + ] } ] From 3b4cfe038d305974e4333ff6a940acd05bb5b2d1 Mon Sep 17 00:00:00 2001 From: 7kasper <7kasper@users.noreply.github.com> Date: Sun, 26 Dec 2021 18:03:55 +0100 Subject: [PATCH 076/489] Changed outdoor to bluetooth catagory >.< --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index e4e53470d..97cd97e4d 100644 --- a/apps.json +++ b/apps.json @@ -5070,7 +5070,7 @@ "description": "Use your Bangle to present!", "icon": "app.png", "type": "app", - "tags": "tool,outdoors", + "tags": "tool,bluetooth", "interface": "interface.html", "readme":"README.md", "supports": ["BANGLEJS", "BANGLEJS2"], From efd6e531c5023a645331ab9f72eb22b6f7e8b2d7 Mon Sep 17 00:00:00 2001 From: 7kasper <7kasper@users.noreply.github.com> Date: Sun, 26 Dec 2021 23:29:31 +0100 Subject: [PATCH 077/489] Test gestures on BS2.. :F --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 97cd97e4d..317b809dd 100644 --- a/apps.json +++ b/apps.json @@ -1324,7 +1324,7 @@ "icon": "gesture.png", "type": "app", "tags": "gesture,ai", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS", "BANGLEJS2"], "storage": [ {"name":"gesture.app.js","url":"gesture.js"}, {"name":".tfnames","url":"gesture-tfnames.js","evaluate":true}, From 604f6f6c476c3bf2cc963a75bfdff1bf9c2b1cb1 Mon Sep 17 00:00:00 2001 From: phil Date: Mon, 27 Dec 2021 14:33:53 -0500 Subject: [PATCH 078/489] Add time and life app --- apps.json | 17 +++ apps/timeandlife/ChangeLog | 1 + apps/timeandlife/README.md | 7 + apps/timeandlife/app-icon.js | 1 + apps/timeandlife/app.js | 278 +++++++++++++++++++++++++++++++++++ apps/timeandlife/app.png | Bin 0 -> 605 bytes 6 files changed, 304 insertions(+) create mode 100644 apps/timeandlife/ChangeLog create mode 100644 apps/timeandlife/README.md create mode 100644 apps/timeandlife/app-icon.js create mode 100644 apps/timeandlife/app.js create mode 100644 apps/timeandlife/app.png diff --git a/apps.json b/apps.json index e5e9f8f02..02ee3d469 100644 --- a/apps.json +++ b/apps.json @@ -5062,5 +5062,22 @@ {"name":"ltherm.app.js","url":"app.js"}, {"name":"ltherm.img","url":"icon.js","evaluate":true} ] + }, + { + "id": "timeandlife", + "name": "Time and Life", + "shortName":"Time and Lfie", + "icon": "app.png", + "version":"0.0.1", + "description": "A simple watchface which displays the time when the screen is tapped and decay according to the rules of Conway's game of life.", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS2"], + "allow_emulator":true, + "readme": "README.md", + "storage": [ + {"name":"timeandlife.app.js","url":"app.js"}, + {"name":"timeandlife.img","url":"app-icon.js","evaluate":true} + ] } ] diff --git a/apps/timeandlife/ChangeLog b/apps/timeandlife/ChangeLog new file mode 100644 index 000000000..115067b80 --- /dev/null +++ b/apps/timeandlife/ChangeLog @@ -0,0 +1 @@ +0.01: New app diff --git a/apps/timeandlife/README.md b/apps/timeandlife/README.md new file mode 100644 index 000000000..af92d8cb8 --- /dev/null +++ b/apps/timeandlife/README.md @@ -0,0 +1,7 @@ +# Time and Life + +A simple watchface which displays the time when the screen is tapped and decay according to the rules of [Conway's game of life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life). + +![](screenshot1.png) +![](screenshot2.png) +![](screenshot3.png) diff --git a/apps/timeandlife/app-icon.js b/apps/timeandlife/app-icon.js new file mode 100644 index 000000000..d7608fca4 --- /dev/null +++ b/apps/timeandlife/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwkB/4AGCY4PHC/4X/C/4X/C/4XvJ/4X/C/4X/C/4X3AH4A/AH4A/AH4A/")) diff --git a/apps/timeandlife/app.js b/apps/timeandlife/app.js new file mode 100644 index 000000000..905ec3031 --- /dev/null +++ b/apps/timeandlife/app.js @@ -0,0 +1,278 @@ +// Globals +const X = 176, + Y = 176; // screen resolution of bangle 2 +const STEP_TIMEOUT = 1000; +const PAUSE_TIME = 3000; + +// Each of my pixels is an 8x8 square. +const ON = { + width: 8, + height: 8, + bpp: 1, + transparent: 0, + buffer: new Uint8Array([ + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + ]).buffer, + state: 1, +}; +const OFF = { + width: 8, + height: 8, + bpp: 1, + transparent: 1, + buffer: new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + ]).buffer, + state: 0, +}; + +const ONE = [ + [0, 1, 0], + [1, 1, 0], + [0, 1, 0], + [0, 1, 0], + [0, 1, 0], + [0, 1, 0], + [1, 1, 1], +]; +const TWO = [ + [0, 1, 0], + [1, 0, 1], + [0, 0, 1], + [0, 1, 0], + [1, 0, 0], + [1, 0, 0], + [1, 1, 1], +]; +const THREE = [ + [0, 1, 0], + [1, 0, 1], + [0, 0, 1], + [0, 1, 0], + [0, 0, 1], + [1, 0, 1], + [0, 1, 0], +]; +const FOUR = [ + [0, 0, 1], + [1, 0, 1], + [1, 0, 1], + [1, 1, 1], + [0, 0, 1], + [0, 0, 1], + [0, 0, 1], +]; +const FIVE = [ + [1, 1, 1], + [1, 0, 0], + [1, 0, 0], + [0, 1, 0], + [0, 0, 1], + [1, 0, 1], + [0, 1, 0], +]; +const SIX = [ + [0, 1, 0], + [1, 0, 1], + [1, 0, 0], + [1, 1, 0], + [1, 0, 1], + [1, 0, 1], + [0, 1, 0], +]; +const SEVEN = [ + [1, 1, 1], + [1, 0, 1], + [0, 0, 1], + [0, 1, 0], + [0, 1, 0], + [0, 1, 0], + [0, 1, 0], +]; +const EIGHT = [ + [0, 1, 0], + [1, 0, 1], + [1, 0, 1], + [0, 1, 0], + [1, 0, 1], + [1, 0, 1], + [0, 1, 0], +]; +const NINE = [ + [0, 1, 0], + [1, 0, 1], + [1, 0, 1], + [0, 1, 1], + [0, 0, 1], + [1, 0, 1], + [0, 1, 0], +]; +const ZERO = [ + [0, 1, 0], + [1, 0, 1], + [1, 0, 1], + [1, 0, 1], + [1, 0, 1], + [1, 0, 1], + [0, 1, 0], +]; +const NUMBERS = [ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE]; + +// Arraybuffers to store game state +// 484 8 bit integers that are either 1 or 0 form the 22 x 22 grid +let emptySeed = []; +for (i = 0; i < 484; i++) { + emptySeed.push(0); +} +let data = E.toUint8Array(emptySeed); +let nextData = E.toUint8Array(emptySeed); +const dataAddr = E.getAddressOf(data, true); +const nextDataAddr = E.getAddressOf(nextData, true); + +let lastPaused = new Date(); + +const forAllElements = fn => { + let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]; + numbers.forEach(i => { + numbers.forEach(j => { + fn(i, j); + }); + }); +}; + +// Conway's game of life +// if < 2 neighbours, set off +// if 2 or 3 neighbours, set on +// if > 3 neighbours, set off +const updateStateC = E.compiledC(` +// void run(int, int) +void run(char* n, char* m){ + // n is a pointer to the first byte in data, m is for nextdata + int count = 0; + for (int i=0;i<484;i++) { + // Add 8 neighbours, wrapping around + count = + *(n+(i+484-23)%484) + + *(n+(i+484-22)%484) + + *(n+(i+484-21)%484) + + *(n+(i+484-1)%484) + + *(n+(i+484+1)%484) + + *(n+(i+484+21)%484) + + *(n+(i+484+22)%484) + + *(n+(i+484+23)%484); + if (count < 2 || count > 3) { + *(m+i) = 0; + } else { + *(m+i) = 1; + } + } +} +`); +const copyStateC = E.compiledC(` +// void run(int, int) +void run(char* n, char* m){ + // n is a pointer to the first byte in data, m is for nextdata + for (int i=0;i<484;i++) { + *(n+i) = *(m+i); + } +} +`); + +const step = () => { + if (new Date() - lastPaused < PAUSE_TIME) { + return; + } + let startTime = new Date(); + updateStateC.run(dataAddr, nextDataAddr); + nextData.forEach((e, i) => { + if (e && !data[i]) { + g.drawImage(ON, Math.floor(i / 22) * 8, i % 22 * 8); + } else if (data[i]) { + g.drawImage(OFF, Math.floor(i / 22) * 8, i % 22 * 8); + } + }); + copyStateC.run(dataAddr, nextDataAddr); +}; + +const drawPixel = (i, j, value) => { + g.drawImage(value, j * 8, i * 8); + data[j * 22 + i] = value.state; + nextData[j * 22 + i] = value.state; +}; + +const drawNum = (character, i, j) => { + const startJ = j; + character.forEach(row => { + j = startJ; + row.forEach(pixel => { + if (pixel) { + drawPixel(i, j, ON); + } + j++; + }); + i++; + }); +}; + +const drawDots = () => { + drawPixel(10, 10, ON); + drawPixel(12, 10, ON); +}; + +const drawTime = () => { + lastPaused = new Date(); + g.clear(); + data.forEach((el, i) => { + data[i] = 0; + }); + const d = new Date(); + const hourTens = Math.floor(d.getHours() / 10); + const hourOnes = d.getHours() % 10; + const minuteTens = Math.floor(d.getMinutes() / 10); + const minuteOnes = d.getMinutes() % 10; + drawNum(NUMBERS[hourTens], 8, 1); + drawNum(NUMBERS[hourOnes], 8, 6); + drawDots(); + drawNum(NUMBERS[minuteTens], 8, 13); + drawNum(NUMBERS[minuteOnes], 8, 18); +}; + +const start = () => { + Bangle.setUI("clock"); // Show launcher when middle button pressed + g.clear(); + Bangle.setLCDTimeout(20); // backlight/lock timeout in seconds + let stepInterval = setInterval(step, STEP_TIMEOUT); + + // Handlers + Bangle.on('touch', drawTime); + + // Sleep mode + Bangle.on('lock', isLocked => { + if (stepInterval) { + clearInterval(stepInterval); + } + stepInterval = undefined; + if (!isLocked) { + drawTime(); + stepInterval = setInterval(step, STEP_TIMEOUT); + } + }); + + drawTime(); +}; + +start(); diff --git a/apps/timeandlife/app.png b/apps/timeandlife/app.png new file mode 100644 index 0000000000000000000000000000000000000000..b1e837d258215458c7427ee87669e9bbac4a6cff GIT binary patch literal 605 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1SD@Hc}*5j~)%+dI0Z`UZ9TaH&0ol7?IxJKYaYEcX0Eb^M5Usybh)`_$$my-IXYqFW{daW%a!F zk%YE4*GJ2bGaSWL>YnU+^GW*oq{DUdB#k%Ctb8P~G2m6w&hE&Y0iDY`9(Sz@+-LuM z)1k`l%~5MNf3y9`eV8>jb>?f6_KAm-rYSfz^jK-FIONn6)+-_`dCR}*2fOTk551W& zq6S4e3)n;_J!b#keE;sOqbE7dHRrH2>2LdM$kbBS7$1N0nDxpV8r5TsRNT2Pd=c+H@LRGrSgzw9Q*Cx${@dC)b_|iP zv}&1UWSADKo{IZkQJ!C(|9@WQ_wUTwQbk=Q7Cfhb(ZX5a5n0T@pr;JNj1^1m%YcIH zC7!;n>`!^5g?X8JOXb~wLXst}5hc#~xw)x%B@E6*sfi`2DGKG8B^e6tp1uL$jeO!j zMed$1jv*0;-(EY&$)Lc);&}dFb)V@ScbByLLhPSB)6z^;SKizH`FoX)0vIf~@0j_1 o>aXTcb(@SJA_|_9RAS#UOgP19!;<*A7ic7dr>mdKI;Vst02rI_VgLXD literal 0 HcmV?d00001 From fb14142593aff4a48411251d593cf26a386a60da Mon Sep 17 00:00:00 2001 From: phil Date: Mon, 27 Dec 2021 14:38:57 -0500 Subject: [PATCH 079/489] fix screenshot --- apps/timeandlife/README.md | 4 +--- apps/timeandlife/screenshot.png | Bin 0 -> 811 bytes 2 files changed, 1 insertion(+), 3 deletions(-) create mode 100644 apps/timeandlife/screenshot.png diff --git a/apps/timeandlife/README.md b/apps/timeandlife/README.md index af92d8cb8..b03cbf2fb 100644 --- a/apps/timeandlife/README.md +++ b/apps/timeandlife/README.md @@ -2,6 +2,4 @@ A simple watchface which displays the time when the screen is tapped and decay according to the rules of [Conway's game of life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life). -![](screenshot1.png) -![](screenshot2.png) -![](screenshot3.png) +![](screenshot.png) diff --git a/apps/timeandlife/screenshot.png b/apps/timeandlife/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..5ffda5bf052b411fab011024b6e8cf9a6b4aedb0 GIT binary patch literal 811 zcmeAS@N?(olHy`uVBq!ia0vp^`+;~L2OE$~*>-O+kYXuz@(kesf*OvL4j^B$#5JNM zI6tkVJh3R1Aw4fYH&wSdxhOR?uQ(&WkRs=z)Wnj^{5*w_%-mE4Um(NC zT)`zZS;5G_$WXz+$jaEl%D_?~z*qO>a-g+L9iA?ZAr*7p-gV46Y#`upan+Z9(?1=& zBE6;C@x+t;+j&*Iew;~4dh^xh{J*9JTfd9hd*0v9&#=8?zRt(Vs&$)=_)q(BQpi5? zk-GPvl+M8`Sm(FzXVmNS*T3IWx34?%^L*XED_{PoVYvHR#`*fHe(Tce^R>6W{J#6I zcG>gUMn5q;=vMvjcJ;08)_dLSfBzTBx1WC!BN$4*?6b}P{_XcEpS%0w{@ZUqpZ*CW zylTJ9tKX$Q?;n3bb^qUQzrWo{!>Z>0w%g}-{{3S6cM2A3zFO}2cExzz_4$UF&b+ox jzxpH==MTb2t79xWAF@BqJ@q&+Av1Wo`njxgN@xNAJLr-e literal 0 HcmV?d00001 From 27be246c82c14f31943567875392469b548cbb2d Mon Sep 17 00:00:00 2001 From: phil Date: Mon, 27 Dec 2021 14:43:37 -0500 Subject: [PATCH 080/489] fix screenshot and description --- apps.json | 2 +- apps/timeandlife/README.md | 2 +- apps/timeandlife/screenshot.png | Bin 811 -> 1634 bytes 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 02ee3d469..62e78b8da 100644 --- a/apps.json +++ b/apps.json @@ -5069,7 +5069,7 @@ "shortName":"Time and Lfie", "icon": "app.png", "version":"0.0.1", - "description": "A simple watchface which displays the time when the screen is tapped and decay according to the rules of Conway's game of life.", + "description": "A simple watchface which displays the time when the screen is tapped and decays according to the rules of Conway's game of life.", "type": "clock", "tags": "clock", "supports": ["BANGLEJS2"], diff --git a/apps/timeandlife/README.md b/apps/timeandlife/README.md index b03cbf2fb..4a638c952 100644 --- a/apps/timeandlife/README.md +++ b/apps/timeandlife/README.md @@ -1,5 +1,5 @@ # Time and Life -A simple watchface which displays the time when the screen is tapped and decay according to the rules of [Conway's game of life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life). +A simple watchface which displays the time when the screen is tapped and decays according to the rules of [Conway's game of life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life). ![](screenshot.png) diff --git a/apps/timeandlife/screenshot.png b/apps/timeandlife/screenshot.png index 5ffda5bf052b411fab011024b6e8cf9a6b4aedb0..3058c9346bbcb23f5348729b81179b6d6b80f37a 100644 GIT binary patch literal 1634 zcmeHIZA@Bc6utsQvBj^}W}*_hR!C)GC#$-1|oh&)E>oL(CuCH=%fOR`#=Rksa|_HeHk9@bbzPZ ze?c(;KS|^x#fxruwmzncRwO-;Pi*%aVP>N^>K0v8ZTW+Js@i*`@P<0;(kb&;PzY=F zTHJw6Q{}*2qH13eHsIHx)_?;II@%Kg9mZ$IF2CU`k3$Z5!8X;DjYckQL6nQe%idiFjU{bm(i(t*KC~zu+1)Tf2 z%XoRakyjPm#s4I8>5RXWc1On@73BAZVGqxLu^S<}&uDP=!laTfO?aHFL}y~#{W?sC zHsqL%{*e&-jX`R4eDt(~EFNS1G;j6OZ6);C3}{->aD!TpiHG!4YE_1-d3pi(Ah*1o))?Yv+!?^jBo{$GA>%jwMfJYA zoX)s@n1tssu=oYouVV^2n9wR@b2_%pU`HfP6Vy7Q^4fz;PX1tk_Txm;GD9F429sWS z93tc`gO2G{;YFp5Qdi<=$YRpBfkW9WZlI@+Sz~k7O17Y{<$%%-#xhWZ+wi+=J1jTC zdnv&poFHE!LIrZBcvbi5sbFtYg$vnVVnMJmVS+$*V){-{V zZ2A1rJ?$#6zH8eH~hTgZsal^9Z5qyfHj{ z#TlB|PpmHvst(?plyxH=S0arH(X)GXxhbixLk;+~(s5!lkQkGDQZ0ZIP^UD-!-t%AJ2YtW;C(BEA(jq N#RVlCRUZGde*iBqFmwO_ literal 811 zcmeAS@N?(olHy`uVBq!ia0vp^`+;~L2OE$~*>-O+kYXuz@(kesf*OvL4j^B$#5JNM zI6tkVJh3R1Aw4fYH&wSdxhOR?uQ(&WkRs=z)Wnj^{5*w_%-mE4Um(NC zT)`zZS;5G_$WXz+$jaEl%D_?~z*qO>a-g+L9iA?ZAr*7p-gV46Y#`upan+Z9(?1=& zBE6;C@x+t;+j&*Iew;~4dh^xh{J*9JTfd9hd*0v9&#=8?zRt(Vs&$)=_)q(BQpi5? zk-GPvl+M8`Sm(FzXVmNS*T3IWx34?%^L*XED_{PoVYvHR#`*fHe(Tce^R>6W{J#6I zcG>gUMn5q;=vMvjcJ;08)_dLSfBzTBx1WC!BN$4*?6b}P{_XcEpS%0w{@ZUqpZ*CW zylTJ9tKX$Q?;n3bb^qUQzrWo{!>Z>0w%g}-{{3S6cM2A3zFO}2cExzz_4$UF&b+ox jzxpH==MTb2t79xWAF@BqJ@q&+Av1Wo`njxgN@xNAJLr-e From b9cda9b829e29a7075d49eaf56e3d8110ae19f9f Mon Sep 17 00:00:00 2001 From: phil Date: Mon, 27 Dec 2021 14:55:22 -0500 Subject: [PATCH 081/489] version number --- apps.json | 2 +- apps/timeandlife/ChangeLog | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 62e78b8da..15d3005c6 100644 --- a/apps.json +++ b/apps.json @@ -5068,7 +5068,7 @@ "name": "Time and Life", "shortName":"Time and Lfie", "icon": "app.png", - "version":"0.0.1", + "version":"0.1", "description": "A simple watchface which displays the time when the screen is tapped and decays according to the rules of Conway's game of life.", "type": "clock", "tags": "clock", diff --git a/apps/timeandlife/ChangeLog b/apps/timeandlife/ChangeLog index 115067b80..c7b309a74 100644 --- a/apps/timeandlife/ChangeLog +++ b/apps/timeandlife/ChangeLog @@ -1 +1 @@ -0.01: New app +0.1: New app From 77d785bb68d3fdc1380110d58a8e6dec9ff0831c Mon Sep 17 00:00:00 2001 From: phil Date: Wed, 29 Dec 2021 22:31:58 -0500 Subject: [PATCH 082/489] remove unused code --- apps/timeandlife/app.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/apps/timeandlife/app.js b/apps/timeandlife/app.js index 905ec3031..7532f9bc8 100644 --- a/apps/timeandlife/app.js +++ b/apps/timeandlife/app.js @@ -145,15 +145,6 @@ const nextDataAddr = E.getAddressOf(nextData, true); let lastPaused = new Date(); -const forAllElements = fn => { - let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]; - numbers.forEach(i => { - numbers.forEach(j => { - fn(i, j); - }); - }); -}; - // Conway's game of life // if < 2 neighbours, set off // if 2 or 3 neighbours, set on From c6f43446906e873a226a93e766cdcd8999d30a41 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 31 Dec 2021 22:14:24 +0000 Subject: [PATCH 083/489] Pebble: foxed icon to 48x48 --- apps.json | 2 +- apps/pebble/ChangeLog | 1 + apps/pebble/pebble.icon.js | 2 +- apps/pebble/pebble.png | Bin 1213 -> 1365 bytes 4 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 8a0d86b97..f78098b3a 100644 --- a/apps.json +++ b/apps.json @@ -4725,7 +4725,7 @@ "id": "pebble", "name": "Pebble Clock", "shortName": "Pebble", - "version": "0.06", + "version": "0.07", "description": "A pebble style clock to keep the rebellion going", "dependencies": {"widpedom":"app"}, "readme": "README.md", diff --git a/apps/pebble/ChangeLog b/apps/pebble/ChangeLog index d92be5e9c..0cba5a2b2 100644 --- a/apps/pebble/ChangeLog +++ b/apps/pebble/ChangeLog @@ -4,3 +4,4 @@ 0.04: Fix widget hiding code (fix #1046) 0.05: Fix typo in settings - Purple 0.06: Added dependancy on Pedometer Widget +0.07: Fixed icon and ong file to 48x48 diff --git a/apps/pebble/pebble.icon.js b/apps/pebble/pebble.icon.js index ecd7feb7f..1c1166156 100644 --- a/apps/pebble/pebble.icon.js +++ b/apps/pebble/pebble.icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("oFAwgNKiIAIFqofegIf/DAUzAAMyAwUQD60T/4ACD7Q/cPxIf/YCofcDhYiSXYYfuUZgf/D/4f/D6USkUgD/4fuogAID6vtDw/UD6vu6geF73kb6vuEAtN9wfYMIneD7JADDwIfaIAJdBD7YgBHwQfbAAgfkf6Qf/D/4feogAID6oAND/4f/iAdJD/4f/D/4fUDxYABD74iODiAftTZgfnYYczAAMyD7UT/4ACH/S+bD8DAKD9Y=")) +require("heatshrink").decompress(atob("mEw4UA///ssp4XthFCBwUBqoABqAaGBZcFBZdX1W1qgLHrwLKqv/6oLJAAILHioLJn5qBAAYLEBQoLeHQQABv4LjGAgLYq2qAAOlBbBHFBdPAKcQLdWcb7jAAoLcn4LKgEVHQVUBQsAgoLLq//6oLIr2q2oXJBZQvCqALGgILTA=")) diff --git a/apps/pebble/pebble.png b/apps/pebble/pebble.png index 10f5adb56b224f3e4d037c4d195fbd9efc81b959..368e08750d5ede99497d54b310fe9b91e03d9c10 100644 GIT binary patch literal 1365 zcmV-b1*-aqP)Px)4@pEpRA@upn$J%oWf;f5@65Ech+x zv{2{Lr1SoGKJW9q@AEwGGXxf&j*gBFO6h${sg)5nRaJf3O2^bb#OfezZEaUYQ5<26 zhgpeNqlqU<|a5!MM+tXy)-`__( z9#8#$LlA_fU@-V^J`k4nfTAcL1GvSlA&<$o1wnW%7!2OaV+?Bo$g<3Zznss+0AlfY z{JrJnjL8}`p4TwIc*HA2YF(Z&`TV|N3A zz$du?84BR>cxDJ8uUk3qa}k8M36YTEp zVrM5|vZwa&)vv9sO$dJk(C_#AZ`$UZ?XIgKO%tB)k~ zeOsM?$OPbWxe^*+jQ#2LdS5(s4KNT?RZs-3hq1m%@Nml*fG*HbV6|8N+4QG#d;Sbsoppz&lSeLBj3C!9cC9YdJ} zgjOVc_*FUp_XC8G&!(rRuMH0mI|MRySs0P!{IVQ$id*?;AX)$vDvuA$b@u1 zkaUa|#*v-02h4zE(?HQ2+5ZCIsS1i;M#9*O7@ow(6eEcYp%ok6|03NF6iov>l&Ekr zd~>M?YqU0q$(nx@?Wa7n*j z*EFq$Qd)@X_31z$&}T~Wqeg}RnFecZZM`K3LTMB@G65)x@)3aBW^T8$tmZbQ^wp)M zrTe+8cxqcq8c-DFO#r+!bgan7E0wm?91_5}EAq9pv^*zC(r>9{)}f&xw70jXm02ey zCNMfWn!0$4s;a({&*~>qSE~akin0peS-pR@Lign4Bp$&|E$>&@`<(6bhZ)rv|btUl9c1rWOBiEEs&!V)H@V+` XI5?_a++oDw00000NkvXXu0mjfkw}hY literal 1213 zcmV;u1Va0XP)POM$%3@Whhhyn@nYhxDeg-e<-cZ zYFr2k?%buN)IY$D3u)c7&`lO@rMoJkr~#QIf+Nxtsa1-};Ey=&+{^zdH@zOnM{mX zvjtWIh=|(&%XQtCm^E8qH2}cN%z6O8ZE6bK^H45MbUEA#JEV9`wMn*=ov6V^% zySuwkO0~5~DF?#<%d&1sDYbW0Hk-xj>T1XM!^1;VDwVeD28LA&YzBCqmmwl;+y4GO zgb;{C^xd7DoZ$HQ*iU*PlgY#ig+iSt(^m8u_dq(G-UG14rPmA*y;>|5zciuESp-cK zzzd8G0~P~16+jM57D5&SEX%sZrKQ7UAq-RlmX?-oDy4Ra==sOnq?EQ&YLqXv|L}5|Ola!1|954-`%Wb(F@@^;gu`v9KmHh$=b zz?A|0PN3hg)_~-=MDC3mBG9he1EGlU<1aQo_~dDZ%=}?Bz_u0A^B$@-pn9+O6{;nG zYf}<`Kd>0H)5AUs5CP97fT*MJ>ls1HVDZr?Fg>Z@^Z2lhdcFPy5q)~`|M@n#Ym7~U z@i=f}MB(%|LZi#=!uS}FOsYUTu4=XV)%yDS`#mKI!$r`xf!P^_vHy8YA_Oo!r7#)r z!*gJK77zlsHtGN2E=(GYo6bbfrL6?V#{kEEG$bCJKfoG|15-%_#@%gTE_Ep!jRH5W zKPrx~n8GvTm)X0XOWzAv5#aiC_;mso1HT!XnVETOb91x#hsS?5Ha6yc10G}G4G==a z0W_D;`+?$l(-}Oj4Cr?P{buM5U@d|Tm+;LG`eQJ?aQA2PHJY`D-~SMJ@1qG$N#hLt z5V$g+-wE`afj8jn?CfJ9#B)u53qj%sekt5&H16ecxu1HCANV^UEJJTVs3G8Y_SYob z=a51f;5ZH($KlGQF9aO|PtK#9bBHKZPJs*{qGFiNOdzGa6DB^;5D-GVDW%+j=2&bW z4obR2luslQ`(eacDoQGqdX0!a=g{)uPN`Hf^6CuNH258Wo{y_`LBW(Tivi_w`7Z!> zIka>rrJig9&iR&6s|Cxlj2XbW7bpP8>Kf+e=CHQ52Fud_-hX;}itX)f?MqVtJlnQI zRr*e_8K9IZ_^r}bR#vdQyxcMV;NU>}(iDKQsrQ8d-aFu;5Vn2IdwY9OO8KrDkB*Ky zy)$y0J8xG=4+z` b5C9$mizYm;5j?(%00000NkvXXu0mjfggZkP From 0516b13669b272d9e48169e17b996e05ad4a85ec Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 31 Dec 2021 22:29:02 +0000 Subject: [PATCH 084/489] Rebble: fixed icon to 48x48 --- apps.json | 2 +- apps/rebble/ChangeLog | 1 + apps/rebble/README.md | 1 + apps/rebble/rebble.icon.js | 2 +- apps/rebble/rebble.png | Bin 4570 -> 4067 bytes 5 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index f78098b3a..e4f280a0b 100644 --- a/apps.json +++ b/apps.json @@ -4879,7 +4879,7 @@ "id": "rebble", "name": "Rebble Clock", "shortName": "Rebble", - "version": "0.03", + "version": "0.04", "description": "A Pebble style clock, with configurable background, three sidebars including steps, day, date, sunrise, sunset, long live the rebellion", "readme": "README.md", "icon": "rebble.png", diff --git a/apps/rebble/ChangeLog b/apps/rebble/ChangeLog index 16e65d4f9..b9c26b4e3 100644 --- a/apps/rebble/ChangeLog +++ b/apps/rebble/ChangeLog @@ -1,3 +1,4 @@ 0.01: First release 0.02: Fix typo to Purple 0.03: Added dependancy on Pedometer Widget +0.04: Fixed icon and png to 48x48 pixels diff --git a/apps/rebble/README.md b/apps/rebble/README.md index 712fa4e9b..0ecb51d7a 100644 --- a/apps/rebble/README.md +++ b/apps/rebble/README.md @@ -11,6 +11,7 @@ * Uses pedometer widget to get latest step count * Dependant apps are installed when Rebble installs * Uses the whole screen, widgets are made invisible but still run in the background +* The icon is James Dean - 'Rebel Without a Cause' ![](screenshot_rebble.png) ![](screenshot_rebble2.png) diff --git a/apps/rebble/rebble.icon.js b/apps/rebble/rebble.icon.js index 4c898974e..3fc45b820 100644 --- a/apps/rebble/rebble.icon.js +++ b/apps/rebble/rebble.icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("oFA4X/AAIHBw3Aiv3HmE/HQQAF/gPEnWqAAOpy2VqoFB3gPIBoIABtQPJ1PVqv1q3qB5OlrNVEIQPK2tlBwOptQPIyvdH4VtrQPI3tbqtdB4OaB5FVH4NV0pgBB5F13//MIIPJ1O2TgWV/o/I1fbB4WpqoPI1NvB4REBJ5APD/wPBD5JOBB4WVqwPH0oPE0oPJ/NX//6AoNVF5HZq3pq2qSYIPI6tX+pNBB5Ol6v6B4IABH5P7//b1oPBN5GlLwPr9IPK1IPC/SvK1QPCOAIPL6te//5B5lW/5ABL5APB/wPB3IPJ1Y/C/yuBF5APC9X+yo/K34LB3QPBtQPJ//23SPB1QPI3eVs2qJwIPJ1flqyeBtQPJtZPBLwIPKzf/1ROCB5OWAQJOBB5QsBAAQGBf5FlB5tVvoPMNQO9B4daB5O+B4aPIqtX35tBB5M1qtbB4i/HB4WvOAjvGB4IpBIQIADB46aBB4t8B49VB54AFB6zrB1Wm1RTBywPI0oPCeQOaB4+ltOlq2V02VqwPOrQPIF5w/PFQIvPB71pH4uqX8g")) +require("heatshrink").decompress(atob("mEw4X/AoOG4EV+/I+dVAAVUCgcFBIYABpIJBgcFoIKEqkQgEH6EH0ILEqAhCgkBqEVBYdAhUBBoU9GAlAlw5CgERgILDIocEgEGoALDlEHwEAlkUg8EBYfAFwVA+BgEqmQjWrBgMQhgvDqmA9Wq1WsNoMALweDBQIAB4E8BYdTpwLD/kA4AXDjwKC1f/IAILDnQLC1//4ALEHQQLCKgILDFwYLB6EATgVABYe///MNgdA3kQEoILGqCNBlfQh//4NAPAVQ+YLBQYM/ocABYfAiEqgE0g6DBF4eAlFrYQZHDoOu1Xo8lgBYtCKIOo9aOBAAJrCBYWv9X/+gXEqSZC/f//4LHz/6DQIjEBYOhgG6BY1a1WggDCB3ojErYTBoEOa4QLF1X9jWrXwILGKYOvBYtfKYX+17iBHYdX1WQgf/34LBUwQLB1cLWIJqCBYdV9W+1+//oLBWQVVqnuD4M/KQoAB/+kBYJGBCwYLCI4P/DQILFnwLCEQ1Vp+q/46CBYtDXgJ1FAAVwfI4ABqAUCBY8A9gLIqEA9ALEKYYLB9YLERwQ=")) diff --git a/apps/rebble/rebble.png b/apps/rebble/rebble.png index 69653015cfec75e34382125a56c258c7e9074f5b..acfd37400804494014976eea6bf456b1bdc2fcf6 100644 GIT binary patch literal 4067 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 Voil!`qIv)T002ovPDHLkV1j)J*pL7K literal 4570 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 Date: Fri, 31 Dec 2021 22:52:28 +0000 Subject: [PATCH 085/489] GPStouch: enhanced icon image, it was a but wishy washy --- apps.json | 2 +- apps/gpstouch/Changelog | 1 + apps/gpstouch/gpstouch.icon.js | 2 +- apps/gpstouch/gpstouch.png | Bin 1571 -> 1443 bytes 4 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index e4f280a0b..b4364166e 100644 --- a/apps.json +++ b/apps.json @@ -4382,7 +4382,7 @@ { "id": "gpstouch", "name": "GPS Touch", - "version": "0.01", + "version": "0.02", "description": "A touch based GPS watch, shows OS map reference", "icon": "gpstouch.png", "screenshots": [{"url":"screenshot4.png"},{"url":"screenshot2.png"},{"url":"screenshot3.png"},{"url":"screenshot1.png"}], diff --git a/apps/gpstouch/Changelog b/apps/gpstouch/Changelog index 7f837e50e..e4a0bdfe8 100644 --- a/apps/gpstouch/Changelog +++ b/apps/gpstouch/Changelog @@ -1 +1,2 @@ 0.01: First version +0.02: Enchanced contrast of icon image diff --git a/apps/gpstouch/gpstouch.icon.js b/apps/gpstouch/gpstouch.icon.js index c4cf85676..3e05da0ff 100644 --- a/apps/gpstouch/gpstouch.icon.js +++ b/apps/gpstouch/gpstouch.icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEw4UA///j+EAYO/uYDB//wCYcPBA4AFh/ABZMDBbkX6gLIgtX6tQBY9VBYNVBY0BBYdABYsFqoACEgQLDitVtWpqtUBYtVq2q1WVGAQLErQLB0oLFHQNqBYIkBHgMDIwYKBAAJIDIweqz/2BYJtDBYI6Bv/9HgILHYwILGh4gBBYWfbooLF6AjPBYW//wLGL4Wv/RfGNZaDIBYibEBYizIBYjLDBYzXBd4TXCBZ60BBYRqEBZpUBBYRSFJAQLCA4b7BHgQLFgYLGIwYLEgoLBHQYLEgILBHQYLEgALBAoYLFi/UBZMHBZUD6ALKApQAFBbHwBZMP/4ABBwgIDA=")) +require("heatshrink").decompress(atob("mEw4UA///iADCn+EqoAWqAuJgoLcn/8BZENGwNwBY/VBYNXBY0DJ4fABYoiCEggLDmtX1Wq6tcBYvVrQLB0owCBYdVtQLB1NVBYg6BBQIABHgQLCgIuCGAVABYcNqwtBGIOVJAILFyoCCBY5eBBdo7IgIIB1t6BYJfENZaDB9QKB1aDFBYKbEBYizBrwLB2qnFdwSmCX401cYdUBZTjGfYgHCBZB2BBYhUBAARSBBYhICAAIGCBYkVBQJSCBYpICIwQLFHgQ6CBYo8CHQQLFHgQFDBYsVQIQLHgo6DBY0BHQYLGgY6DBYwAFBbCjDACY")) diff --git a/apps/gpstouch/gpstouch.png b/apps/gpstouch/gpstouch.png index c411356ae69347a83882fe195782df211aa629e9..a40419a3f15ca9a07e80397db537ca307fba02a1 100644 GIT binary patch delta 1425 zcmV;C1#bGI45JH>B!3BTNLh0L01m_e01m_fl`9S#000G5Nkl93g^E$p2PSi7 zxZt%9rL|&hEGG71Olz$eL1GIPvv^sXozsUg>dwq&XJ$8*^nZgu=0E@C`M(OF%@B{P98T4;p&=mZhtW(#d98x}3iK?pH7q# ziN@0iCNxwpdnsoQr&`(IWfG6K8YWE0e7<`xg@2ZlXRL0IaOlJt+`FI3uuYuku2wd< z7SPkvJJV__D$0ER<9at*_N24sXxZJ1D_!0F<^X_XvbW4FFV_MB0lJsVCm6_`t|$<2 zQ|qofRvrWlA0GJ4YP)|w^LfhTQdF-Wnl(qw`k|OIxwPLL05EJ=;Idm@Ugp5BR>QSx znSakk!64SYxiD*jwW}8)7|eVFSFbv{4v2s@tKs5ByVI-lXXDiOE3jtc$Vaw!J{*Z} zTi?JdFWA@2jt+YcB6mwD;9(inG@P>9E?ok;yMb}zGVL!u{~Q*~E5o);w*Ua+o*A97 z{`cYLO`x;WUdu3W)-^A;j-e1;V3rv#JbxV4kw^fkl--|*P&#%DO2>|IB>&(6kVu$0 zo&>Y}(=gClZ~+f-$ZDvs*U{YUEFv3HDd6BiVBI?VjugOQce_y&UIpxCmbT=zwL13g z1Fm1souI1=*t-{~t8*j|rO@bwkf%ev5OgILQzrl{v5wW(n}nL0B&JUXCQUN8&VPV; z2I%TC=S*#_GjRZ5mOltV=e=<9b1Na4Wu*|h;|AL4pyB~>uK}LV#E}S{2XM@5TrM!n z^WiX#c#ZRQs86Ty0kiZlZF55@Z1i(S*i9*#a zXp1Qvro&3%y=>$0xD-Orr-iIp@E%ztLVMzIDXey8`B6Abp7%N~5LE-w>}FP*`*O$Q z>Jz0@f!nxd?z~z|xv*)|KPQP0*txUFSM#EOn7j+xrLB!32COGiWi{{a60|De66lK=n(*hxe|RA_7!JOvVz*38;=4<&H5LVRE7i!wE@)hpWulvKu;xEMTMGS7!-*xS1GdF+PWqH zWMt@9fSV%xV1F1K_Il;lRORe<0ZJ+H`*{N>Hw-36Y&~rc-Ex6krC2C}-|tuTfY zVCqyDJ^B&7QgHJoT)YT%bjfX}Bi;4>gAwr#=$ShEJ^ z&+ifc2qKV^0}B>FX(_l8KlPc0!QSp1reV!lVdR3nB_eoZ?JgHAUL5(C%|Zm0EP?Uk6E^$IaA>H@AVJe<0|Aw< z6v5s$U5Anq7&FDfA%F)r$N#l)Xawm>^ zXn%7$Ar$JQz5S7&rb(_@U8W0gIOKs+40J3k*K$|rpbM?x=a@^WQd~y znBCjf-X6IVJ#dZ7CL?_?ZT}?BpP4=w*SPE`TYEdCrRk)lMVYUd)n%m*T#hwdzaD+< z)OA+9xiBfgsuhdS_2@fr?OHL`;oEdC*?{%IT{%Cw1@$^tOu3pZ| z&rgr@zj!g8L&V$=3KkwAP2;3tMBD1?p}84Gjf%FvIC~m%XXVn|atDA>BZftd|2?>M z3oa#?0~iKpOzSf1SXLuwwDL8ZpLZNtn5g~izaI!}ZPbj{lBND6P*JFPg27hPG z>aw~XsE#$NAj*U#60ovLk!t3iJ#Xbf>k4G$RS=!l^ z*b2NtlHwa1BR_!F*2r5qGt+dMfPYmnme<5yubcypSdBA*b8a_>tp?dz)Q7`-09fd@ zeM2eM+u0+sRe;YYe<;Prc4CuYpVuq#b8Qo_y)TrNg%?t?&EBGEyl*$yb^+_wNl4Rp z7wE9d(T&w*Wpc}IuvSo787wNV7k4FyJ2`nnvzNDbEGJmLvBHutJ z*;O!U65B=i)@qzmTuMu0z1_S9GD#Hq{XQQkE|zdt7t4W03t@M3ou!*LNn3yOr{sXc z=aauQjb*?+6YgQd;O#A2q#+f#Q+7gARwloR@D32}!*%V}t#T|?c~g4C?hRGq%ec01E&B07*qoM6N<$ Ef*6AFy8r+H From 9f1e978822d5f4321ba9414114de89993f987b99 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 31 Dec 2021 23:02:01 +0000 Subject: [PATCH 086/489] MyLocation: enhanced icon image, it was a but wishy washy --- apps.json | 2 +- apps/mylocation/ChangeLog | 1 + apps/mylocation/mylocation.icon.js | 2 +- apps/mylocation/mylocation.png | Bin 1909 -> 1664 bytes 4 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index b4364166e..427b86fbb 100644 --- a/apps.json +++ b/apps.json @@ -4708,7 +4708,7 @@ "icon": "mylocation.png", "type": "app", "screenshots": [{"url":"screenshot_1.png"}], - "version":"0.01", + "version":"0.02", "description": "Sets and stores the lat and long of your preferred City or it can be set from the GPS. mylocation.json can be used by other apps that need your main location lat and lon. See README", "readme": "README.md", "tags": "tool,utility", diff --git a/apps/mylocation/ChangeLog b/apps/mylocation/ChangeLog index 7b83706bf..653f859ae 100644 --- a/apps/mylocation/ChangeLog +++ b/apps/mylocation/ChangeLog @@ -1 +1,2 @@ 0.01: First release +0.02: Enhanced icon, make it bolder diff --git a/apps/mylocation/mylocation.icon.js b/apps/mylocation/mylocation.icon.js index bfb38d5ac..b79f5875f 100644 --- a/apps/mylocation/mylocation.icon.js +++ b/apps/mylocation/mylocation.icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEw4UA///t/7j/P3/vB4cBqtVoAbHBQIABBQ0FBYdQBYsVBYdUERIkGHIQADHoguEGAwuEGAwKFBZg8DHQw8EBYNf/1Vq3/8oLDIwNf/Wpv//0oLG9Wq3/qBYJUCBYuqBaBqBBYW+BepHEBbybCBYP+BYSnErYLDyoLFAANq/r8Ga5T7MBZZUBAAhSCfhA6DBZhIGBQg8FHQg8GHQgwGFwowFBQwwDFwwLMlS7Bqta1AKEn2q1K1C1WgBYf/1WqBYIDB1QKCgYLC0taBYoXB/QICBY0//7vBAAQ8EEgIABCwwME9QVEA")) +require("heatshrink").decompress(atob("mEw4UA///gH4AYPO/QPDgNVqtADY/1BYNfBQ0PBQIAB+ALFmoLDrgLF6oLDq4KEgYKDBYPABYcNBYlVuAuIGAwuEAANUBYYKFHgg6Bq4ZCr4DBHgQLBvWq2te1WlBYZGBBYOr1Wq1qSDBYNqBIILDKgQLLgoLHqBqDBfJHLBZBrOgKPCBYiPCU4NaBYe1WYrABBQLCCfgYGCrwVBa4kAirvKNgIAErgLDKgIAEKQQ8EAAY6DBZhIDIww8GHQg8GHQgwGFwowEFwx5EOog8GHQ0AlWpBYNq1AKFWIILBAYOgBYbICytWAgQKCgTgDcwYXGAAgvGAAY8EEgYWGBgoVEA==")) diff --git a/apps/mylocation/mylocation.png b/apps/mylocation/mylocation.png index 7148990a42a1c8858d933d2a4cb35b80123a5505..038ee177e660e3bf643c74bbaa5f549b382fd5f8 100644 GIT binary patch delta 1647 zcmV-#29Wvn4uB1iB!3BTNLh0L01m_e01m_fl`9S#000IuNkl@VZEXpa*ivG=AYh3x2EhdI$|X`njXdCkmyi%brALOq-o4Du%-;ukg_-Hj?soenCx4qgm;d>F=bV`{=KxU> zIlo*-0ELuxR;`Lwzbqo?qRLbx3I`Bpdl!!UcuS2d_jwTr)B|3TIi3CCGK6J-oK6mG z#y3ca--H5@54UpwKuw*BA^$9Od*7gnWE(o^wK;w6Z6`!27i>UU1 z{>bE)kn3(Ab^D0AeMFsJjqbU9)N<-FbshYPf(2y{wF#8%BhR@eaw>uPQlOt$97>yu5M8vGXu7?`#+-sO2sI@ScUD(nLvHc=0KT?p&u4w&*^3B8z43-{GN;z(YG>Ds$RCf0gl-s=_{7fH=t?07;}Uz zgC&HH7;{W6#<}&f^$i5Ib5jZvme>`&Tzvy`Q_oB(i&cq|4;?pJ^on#1u+5u;*jaTm z(tmz=j)OfeqKl7V(FJz&sH#_D{59I$S7lUWb9YVLkPH}86L~zHZr3jy4o)3S|Z0PMw9^*^5BW0ODQuz{>%>j=^-y@c}<(xb7nPRtwUuU&T|$ zegL=k3w;hz^1-kDV#sMG5~V{{4j}&0T7T+1R8KelxJG}s2dL?`OdcrauqDl!J!jYC@E1rrbbYakUkuknctT0Ip^Sa*Iz`YGXxt((g!%E1t6W z06<%cQc0Blor0xvgSHgu9$KPrBEMuFiBeA#;rnT8>B5-6kDACUT1}!PM*&_Yv1nyX z;YUs6N*hU(!oPMGC5`eNA5IJWsDBAj+7W?)&!!drs+*E7-I1RkEI-g_6@I9^?%3tq zfkjRCC@~TSOQ(&dcK?&aaXC!GQes#F;Qnq&gsihCk^b@ekm9%x|BCk4R*(PIZXw_= z2K>qM>hTvIPiTvpfhMB3S$*2qc7c7+?bQ;80tUA`M94aG66v3qo9H@JkAGXMa`X=h zW4Z)JwJ&Da8W>}y*GZ;PTtw+KNZ0KGO9cSWpo(6%XF|@5*i}uC~2s$c9vt>sm+8QsS zZROg~;Q@eAP7*JhPN`|Mn}2=5)hTiO37(DhsuIvMq+&3jK_!#MM6mVu0}PNKNwx+) z7NmpcwWVgy#H3MMduWASpd;}D%Y1+jz97LXYw#-sStXE}A!||?@T0~lj>Q>?x6LYs zJS;8l;Bq03-)*-)Zt&hObD1x)u;vlTxeoIqr#MiC7FpK z9V5fKv}q-ZN4NSm&#`5Uv4xC776+v8982UFY>a_p02l)sk~O&c)qVgfz=i{s$=F#a@%Xstf=C002ovPDHLkV1l2V6!8E6 delta 1894 zcmV-s2buVQ4fPI?B!32COGiWi{{a60|De66lK=n*DoI2^RA_AsG@S#b$cuP-3VG$dGK&`PKY(kne zs5N3l1xZZX*iyvOh*i1M%Pza@_3XLLnR%an*kyOm?wr{(=YK4T{U;}9=6x>j|3B}% zGtc{uFh$VRFTVr&05N+hmOTqw5{SsKRq^~hp6S9jhcVu7mJ0i>}op)z!;xQ{&^&`R#GVw zH9WEaeQfJ>B!3g{l8DW&jG%%sfDUzMTOa}57Thk3yHXzC@XsiGA_>sPw%$c!{Y%&( zSKW0XlOOtbi^Jr{bs4iE9)o1v(9g1lOup}vDcmDZtoy^13(!>CeN1cEGdeNH8WqwR z7|cM?t2E^>1A)2(v@}612F57u9m{3=Q->=GuZaBPPk*nZq3#g2ZA~y{bI{ulo*#|) z1ST>x8Zie3GUpMqOm=L(FlpFi4!WVOnd!-PVotKeU=+H0hXh<6yhl2ItGt-XhdE8W zqT|uvygq@v@569!-`IrL&=BU8#Mqm{9LkP>rnX(rwB#|yR0DMN zKrRoK#fA0jh|g#Oz*nU>SRntwM>L&1Mf0goadO#`eC`!jFnH59D1Pw^Sks%ZV>U9J zw*OB@S-9`za#UQ5&Xe6+x`T{PS!tI1qU42>$$t%z2MP=3kB|pQ=anAUMi(und(mRV z7+O9)PRobKFmvbPee)(_Gnx?~K1@36D!HN|S5(~V7IWpn{S!nFBaT@20KbkVz;V7k za%>d(M#~j{+-=jB^-&!?SIeSj(PB=tUQ5!kSUh92Ov)9N&a{tbv?PbILn;!{`^pIj zoPPtFN;MI4MsLpaVCbaPvX)X5eWiWCn?Sw-EYnmf@L~r~Vo9zkxqZ@sLmL@=Ia4xH z5s;v}@TDL_nWvE4IC7YG!H-xTl!5D2#~uKYuLd;-3s4!YG_zB4^#LN+%44D064V?l zz>@gLv0JRA+slq%0mh8h2>+J?ly+d~$$wMjtebL()fv1pVZ6WL_XDVL{Nn$U!JAveQlhfaa_0~HSmVYck z9hX94mEa8syO5`@w;MZOz{%&Bb?kjCuk6b*N8Y?zmS$N2fUbSy1>nIj zpRp)RZz0{fke)9uV&L;vBO)xE83Tc0cR$XX2WdQeigXk8A+i zs_A_SuwHg<-WKLC`J%q##516Wri@bM_#-pp+b46XY+vZ7kIu)_zXP*srd1hwu>7xw zE#@y_@(}=J`&0ix`2m%$U21`%`amV*p+W%wvTO5x;F+pvRoszmlU-Y0tAEtJVgUej zoOl?OHzJd&6v6>!#2$?n5)t~7jV(CVUx90)#!iAy@yv30uB|spP_z*MVt<`HyXCjFaHvVZ@lI{{+lJJE%-nhVqQ++De(u$y>wkXW z$bYrI77me~LPyT$uU5-iBZd_!EC*TvP^I;q{meO9(N`flm)ywtTkjZKYoAv5i@?O2{@t}o851ACmgxICu{06g)+CiDy;|iGv|YF5f`t&fq%2NuL)i#jN&k& z+m_Cczak=`b1XDVhw2<1)Q=O6v;cGu`t;>P@~Lvw+pjbG*!zLzuCFcS+^Rb#BR?je z>>Ko*d%v|%%6?`FoddZ(^YkV108L4YfX{rR5aHZyt2w{wPKphUBh79@Bj;AF=G<+o zD<=;ix~9Q)?+SGZGk>1!FW%7{v){1Cd|LGtdNV$Q1rxsOqDp*V00i8|rf9@RleF8m zSrIlTCe3=LS63z+-Bahtf^q!F6_u=O$a{+G>s0Q6c>=#TmiO?o`St$_bFBEXobD{% z;>7Hq#T{;TET&slX{Z98uXqMLqxi%Bc~>b^wn3H#4hy{IiC_21@&)z(t|X|cO`9{S zb@ce(wJo_>M7|;xtrj%fmegB9Tm(x15hUXpItKg!zz4~Ic7a|%rBjd-ia9C5@zV?9 gAKfbw`P1kB0CUi}Aa6C17XSbN07*qoM6N<$f-G^U(f|Me From 54475bf5e6123ca4c5983556948400c45b65e8f0 Mon Sep 17 00:00:00 2001 From: 7kasper <7kasper@users.noreply.github.com> Date: Sat, 1 Jan 2022 16:27:31 +0100 Subject: [PATCH 087/489] Create template.html --- apps/presentor/template.html | 73 ++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 apps/presentor/template.html diff --git a/apps/presentor/template.html b/apps/presentor/template.html new file mode 100644 index 000000000..e3a5f71ef --- /dev/null +++ b/apps/presentor/template.html @@ -0,0 +1,73 @@ + + + + + + + +
+ + + + + + + From cfcf7908decd1cd661749bd6836b6414cc3c7bac Mon Sep 17 00:00:00 2001 From: 7kasper Date: Sat, 1 Jan 2022 20:00:08 +0100 Subject: [PATCH 088/489] Create basic UI for adding subjects. --- apps/presentor/template.html | 281 ++++++++++++++++++++++++++++------- 1 file changed, 225 insertions(+), 56 deletions(-) diff --git a/apps/presentor/template.html b/apps/presentor/template.html index e3a5f71ef..2b0ddc1ec 100644 --- a/apps/presentor/template.html +++ b/apps/presentor/template.html @@ -2,71 +2,240 @@ + + -
- - +
+

Presentor

+
+
+
+
+
+
#
+
Subject
+
Time
+
Notes
+
+
Loading...
+
+
+
+
+ + +
From aec3df87450e68418f7064002115f31cfec95def Mon Sep 17 00:00:00 2001 From: 7kasper Date: Sat, 1 Jan 2022 20:11:25 +0100 Subject: [PATCH 089/489] Hehe oops --- apps/presentor/{template.html => interface.html} | 8 ++++++++ 1 file changed, 8 insertions(+) rename apps/presentor/{template.html => interface.html} (97%) diff --git a/apps/presentor/template.html b/apps/presentor/interface.html similarity index 97% rename from apps/presentor/template.html rename to apps/presentor/interface.html index 2b0ddc1ec..a3c0fd890 100644 --- a/apps/presentor/template.html +++ b/apps/presentor/interface.html @@ -72,6 +72,14 @@ } .icon-cross { color: #e85600; + cursor: pointer; + transition: transform 0.2s ease-in-out; + } + .icon-cross:hover { + transform: scale(1.1); + } + .draghandle { + cursor: grab; } From b82b65198b3912d79393840c884026ed88a478bb Mon Sep 17 00:00:00 2001 From: 7kasper Date: Sat, 1 Jan 2022 20:18:19 +0100 Subject: [PATCH 090/489] Add actual watch interface --- apps/presentor/interface.html | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/apps/presentor/interface.html b/apps/presentor/interface.html index a3c0fd890..ac748a9f9 100644 --- a/apps/presentor/interface.html +++ b/apps/presentor/interface.html @@ -135,7 +135,12 @@ } function save() { - cmpStr = getJSON(); + let savestr = getJSON(); + Util.showModal('Saving...'); + Puck.write(`\x10require('Storage').writeJSON(${JSON.stringify('presentor.json')},${savestr})\n`,()=>{ + Util.hideModal(); + }); + cmpStr = savestr; } function loadJSON(str) { @@ -146,6 +151,14 @@ } } + function load() { + Util.showModal('Loading...'); + Puck.eval(`require('Storage').readJSON(${JSON.stringify('presentor.json')})`,data => { + Util.hideModal(); + loadJSON(data); + }); + } + function addFormPPart(partData = {}) { let part = document.createElement('div'); part.classList.add('ppartrow'); @@ -241,8 +254,9 @@ document.getElementById('loader').style.display = 'none'; // load from watch first. - let qq = `[{"subject":"Hello","minutes":55,"seconds":4,"notes":""},{"subject":"dsfafds","minutes":4,"seconds":33,"notes":"fdasdfsafasfsd"},{"subject":"dsadsf","minutes":0,"seconds":4,"notes":""},{"subject":"sdasf","minutes":0,"seconds":0,"notes":""}]`; - loadJSON(qq); + // let qq = `[{"subject":"Hello","minutes":55,"seconds":4,"notes":""},{"subject":"dsfafds","minutes":4,"seconds":33,"notes":"fdasdfsafasfsd"},{"subject":"dsadsf","minutes":0,"seconds":4,"notes":""},{"subject":"sdasf","minutes":0,"seconds":0,"notes":""}]`; + // loadJSON(qq); + load(); addFormPPart(); // load empty element on startup From 02c432124f78745b6f1920b258af789223cc9b8e Mon Sep 17 00:00:00 2001 From: 7kasper Date: Sat, 1 Jan 2022 20:22:13 +0100 Subject: [PATCH 091/489] Bit more spacing for the drag thing. --- apps/presentor/interface.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/presentor/interface.html b/apps/presentor/interface.html index ac748a9f9..aefbdf2c2 100644 --- a/apps/presentor/interface.html +++ b/apps/presentor/interface.html @@ -49,7 +49,7 @@ width: 45%; } .pp-order { - width: calc(50% / 14); + width: calc(100% / 14); display: flex; justify-content: space-between; align-items: center; @@ -65,7 +65,7 @@ width: calc(200% / 14); } .pp-notes { - width: calc(800% / 14); + width: calc(750% / 14); } input { height: 1.5rem; From ce6d4d76fdc1f83035e1e457793a2ddd4c6c2b1a Mon Sep 17 00:00:00 2001 From: 7kasper Date: Sat, 1 Jan 2022 20:23:43 +0100 Subject: [PATCH 092/489] Add readme --- apps/presentor/README.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 apps/presentor/README.md diff --git a/apps/presentor/README.md b/apps/presentor/README.md new file mode 100644 index 000000000..8b22eb228 --- /dev/null +++ b/apps/presentor/README.md @@ -0,0 +1,2 @@ +# Presentor +Use your Bangle to present! From aa55094e227082dc9aebdbcaeca27ded82516a96 Mon Sep 17 00:00:00 2001 From: 7kasper Date: Sat, 1 Jan 2022 21:46:40 +0100 Subject: [PATCH 093/489] rrr --- apps/presentor/interface.html | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/presentor/interface.html b/apps/presentor/interface.html index aefbdf2c2..ed265e2f6 100644 --- a/apps/presentor/interface.html +++ b/apps/presentor/interface.html @@ -49,7 +49,7 @@ width: 45%; } .pp-order { - width: calc(100% / 14); + width: calc(150% / 14); display: flex; justify-content: space-between; align-items: center; @@ -65,7 +65,7 @@ width: calc(200% / 14); } .pp-notes { - width: calc(750% / 14); + width: calc(700% / 14); } input { height: 1.5rem; @@ -253,11 +253,15 @@ document.getElementById('loader').style.display = 'none'; + function onInit() { + load(); + addFormPPart(); // add empty element on startup + } // load from watch first. // let qq = `[{"subject":"Hello","minutes":55,"seconds":4,"notes":""},{"subject":"dsfafds","minutes":4,"seconds":33,"notes":"fdasdfsafasfsd"},{"subject":"dsadsf","minutes":0,"seconds":4,"notes":""},{"subject":"sdasf","minutes":0,"seconds":0,"notes":""}]`; // loadJSON(qq); - load(); - addFormPPart(); // load empty element on startup + + From 6eed1b5760f303b8b76117cc0d72236dd50c9888 Mon Sep 17 00:00:00 2001 From: 7kasper Date: Sat, 1 Jan 2022 21:59:58 +0100 Subject: [PATCH 094/489] No double json parse >.< --- apps/presentor/interface.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/presentor/interface.html b/apps/presentor/interface.html index ed265e2f6..9b79221d3 100644 --- a/apps/presentor/interface.html +++ b/apps/presentor/interface.html @@ -153,7 +153,7 @@ function load() { Util.showModal('Loading...'); - Puck.eval(`require('Storage').readJSON(${JSON.stringify('presentor.json')})`,data => { + Puck.eval(`require('Storage').read(${JSON.stringify('presentor.json')})`,data => { Util.hideModal(); loadJSON(data); }); From d3a2bb4375aa938946280077a071ca17ebdda894 Mon Sep 17 00:00:00 2001 From: 7kasper Date: Sat, 1 Jan 2022 22:06:17 +0100 Subject: [PATCH 095/489] Fix the empty element being loaded in wrongly. --- apps/presentor/interface.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/presentor/interface.html b/apps/presentor/interface.html index 9b79221d3..82bb85f57 100644 --- a/apps/presentor/interface.html +++ b/apps/presentor/interface.html @@ -149,6 +149,7 @@ for (let i = 0; i < jparts.length; i++) { addFormPPart(jparts[i]); } + addFormPPart(); // add empty element on startup } function load() { @@ -255,7 +256,6 @@ function onInit() { load(); - addFormPPart(); // add empty element on startup } // load from watch first. // let qq = `[{"subject":"Hello","minutes":55,"seconds":4,"notes":""},{"subject":"dsfafds","minutes":4,"seconds":33,"notes":"fdasdfsafasfsd"},{"subject":"dsadsf","minutes":0,"seconds":4,"notes":""},{"subject":"sdasf","minutes":0,"seconds":0,"notes":""}]`; From b279d3bf69ef3d1a27d0f9720129b0588ac6a560 Mon Sep 17 00:00:00 2001 From: 7kasper Date: Sat, 1 Jan 2022 22:07:45 +0100 Subject: [PATCH 096/489] Bit more time for timer. --- apps/presentor/interface.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/presentor/interface.html b/apps/presentor/interface.html index 82bb85f57..460102388 100644 --- a/apps/presentor/interface.html +++ b/apps/presentor/interface.html @@ -59,10 +59,10 @@ padding-right: 0.25rem; } .pp-subject { - width: calc(350% / 14); + width: calc(300% / 14); } .pp-timer { - width: calc(200% / 14); + width: calc(250% / 14); } .pp-notes { width: calc(700% / 14); From c1fdac99929285a603078e67ef1c381a8625de7e Mon Sep 17 00:00:00 2001 From: 7kasper Date: Sat, 1 Jan 2022 22:28:30 +0100 Subject: [PATCH 097/489] Futureproof the settings format. --- apps.json | 5 +++-- apps/presentor/ChangeLog | 1 + apps/presentor/interface.html | 12 +++++++++--- apps/presentor/settings.json | 17 +++++++++++++++++ 4 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 apps/presentor/settings.json diff --git a/apps.json b/apps.json index 317b809dd..74a24d290 100644 --- a/apps.json +++ b/apps.json @@ -5066,7 +5066,7 @@ { "id": "presentor", "name": "Presentor", - "version": "2.1", + "version": "2.2", "description": "Use your Bangle to present!", "icon": "app.png", "type": "app", @@ -5077,7 +5077,8 @@ "allow_emulator": true, "storage": [ {"name":"presentor.app.js","url":"app.js"}, - {"name":"presentor.img","url":"app-icon.js","evaluate":true} + {"name":"presentor.img","url":"app-icon.js","evaluate":true}, + {"name":"presentor.json","url":"settings.json"} ] } ] diff --git a/apps/presentor/ChangeLog b/apps/presentor/ChangeLog index a7d747684..2e3409855 100644 --- a/apps/presentor/ChangeLog +++ b/apps/presentor/ChangeLog @@ -4,3 +4,4 @@ 1.5: Added accelerator style mouse. 2.0: Added touchpad style mouse. 2.1: Initial internal git(hub) release. Added icon and such. +2.2: Begin work on presentation parts. diff --git a/apps/presentor/interface.html b/apps/presentor/interface.html index 460102388..1af0041fb 100644 --- a/apps/presentor/interface.html +++ b/apps/presentor/interface.html @@ -119,7 +119,11 @@ } function getJSON() { - let ret = []; + let ret = { + pparts: [], + sversion: 2.2 + } + let jparts = []; let pparts = subber.children; for (let i = 0; i < pparts.length; i++) { let rpart = {}; @@ -129,8 +133,9 @@ rpart.minutes = ppart.getElementsByClassName('pp-timer')[0].children[0].value | 0; rpart.seconds = ppart.getElementsByClassName('pp-timer')[0].children[2].value | 0; rpart.notes = ppart.getElementsByClassName('pp-notes')[0].value; - ret.push(rpart); + jparts.push(rpart); } + ret.pparts = jparts; return JSON.stringify(ret); } @@ -145,7 +150,8 @@ function loadJSON(str) { cmpStr = str; - let jparts = JSON.parse(str); + let settings = JSON.parse(str); + let jparts = settings.pparts; for (let i = 0; i < jparts.length; i++) { addFormPPart(jparts[i]); } diff --git a/apps/presentor/settings.json b/apps/presentor/settings.json new file mode 100644 index 000000000..7e8d29876 --- /dev/null +++ b/apps/presentor/settings.json @@ -0,0 +1,17 @@ +{ + "pparts": [ + { + "subject":"#1", + "minutes":10, + "seconds":0, + "notes":"This is a note." + }, + { + "subject":"#2", + "minutes":2, + "seconds":50, + "notes":"Change in the app!" + } + ], + "sversion": 2.2 +} \ No newline at end of file From b5ae5c291ee0d1fc62adcd47f3b75a4721c33e4a Mon Sep 17 00:00:00 2001 From: 7kasper Date: Sat, 1 Jan 2022 22:35:48 +0100 Subject: [PATCH 098/489] Add small credits on the page. --- apps/presentor/interface.html | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/apps/presentor/interface.html b/apps/presentor/interface.html index 1af0041fb..377703898 100644 --- a/apps/presentor/interface.html +++ b/apps/presentor/interface.html @@ -1,6 +1,9 @@ + + + @@ -81,6 +84,13 @@ .draghandle { cursor: grab; } + footer { + display: inline-block; + width: 100%; + text-align: center; + font-size: 0.6rem; + color: grey; + } @@ -104,6 +114,7 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + BangleApps/app.js at master · psbest/BangleApps + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ + + +
+ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + psbest  /   + BangleApps  /   + +
+ + + + Type # for issues and pull requests, > for commands, and ? for help + + + Type # for issues, pull requests, and projects, > for commands, and ? for help + + + Type # for issues, pull requests, and projects, / for files, and > for commands + + +
+ +
+
+ We’ve encountered an error and some results aren't available at this time. Type a new search or try again later. +
+
+ + No results matched your search + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + Search for issues and pull requests + + # + + + + Search for issues, pull requests, discussions, and projects + + # + + + + Search for organizations, repositories, and users + + @ + + + + Search for projects + + ! + + + + Search for files + + / + + + + Activate command mode + + > + + + + Search your issues, pull requests, and discussions + + # author:@me + + + + Search your issues, pull requests, and discussions + + # author:@me + + + + Filter to pull requests + + # is:pr + + + + Filter to issues + + # is:issue + + + + Filter to discussions + + # is:discussion + + + + Filter to projects + + # is:project + + + + Filter to open issues, pull requests, and discussions + + # is:open + + + + + + + + + + + + + + + + +
+
+
+ +
+ + + + + + + + + + +
+ + + + +
+
+
+ + + + + + + + + + +
+ +
+ +
+

+ + + / + + BangleApps + + + Public +

+ + forked from espruino/BangleApps + + +
+ +
    + +
  • + +
    + + + + + + + Watch + + + 0 + + + +
    +
    +

    Notifications

    + +
    + +
    +
    + + + + + + + + +
    + + +
    + + + + + Get push notifications on iOS or Android. + +
    +
    +
    +
    + + +
    +
    +
    + + + +
  • + + +
  • + + +
  • + +
  • + +
    +
    + +
    +
    + +
    +
    + + + + + +
    + +
    +
    + + + + + + + +
    + +
    +
    +
    +
    +
    +
  • + + +
  • + + +
  • +
+ +
+ +
+
+ + + + +
+ + + +
+
+ + Open in github.dev + Open in a new github.dev tab + + + + + + + +
+ + + + + Permalink + + +
+ +
+
+ + + master + + + + +
+
+
+ Switch branches/tags + +
+ + + +
+ +
+ +
+ + +
+ +
+ + + + + + + + + + + + + + + + +
+ + +
+
+
+
+ +
+ +
+ + + + Go to file + + +
+ + + + +
+
+
+ + + + +
+ +
+
+
 
+
+ +
+
 
+ Cannot retrieve contributors at this time +
+
+ + + + + + + + + + + +
+ +
+ + +
+ + 198 lines (178 sloc) + + 4.59 KB +
+ +
+ + + + +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+
+ +
+ +
+
+ + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
//MMind
+
//set vars
const H = g.getWidth();
const W = g.getHeight();
var touch_actions = [];
var cols = ["#FF0000","#00FF00","#0000FF", "#FF00FF", "#FFFF00", "#00FFFF", "#000000","#FFFFFF"];
var turn = 0;
var col_menu = false;
//pinsRow = 6;
//pinsThick = 10;
//pinsRow = 5;
//pinsThick = 10;
var pinsRow = 4;
var pinsThick = 10;
var play = [-1, -1, -1, -1];
+
var pinsCol = 5;
var playx = -1;
var sx = (W - 30 )/pinsRow;
var sy = (H - 20 )/7;
var touch_actions = [];
var secret = [];
var secret_no_dub = true;
var endgame = false;
+
g.clear();
g.setColor("#FFFFFF");
g.fillRect(0, 0, H, W);
g.setFont("Vector12",45);
+
function draw() {
touch_actions = [];
g.clear();
g.setColor("#FFFFFF");
g.fillRect(0, 0, H, W);
g.setColor("#000000");
//draw scores
for (y=0;y<game.length;y+=1) {
pp = game[y][0];
ps = game[y][1];
g.setColor("#000000");
//g.fillRect(W-30,10, W-30, 15);
g.setColor("#000000");
g.setFont("Vector30",10);
g.drawString(ps[0],W-31,y*sy+8);
g.setColor("#000000");
g.drawString(ps[1],W-15,y*sy+8);
g.setColor("#000000");
for (x=0;x<pinsRow;x+=1) {
xx = sx*x + pinsThick + 5;
yy = sy*y+20;
xc = pp[x];
g.setColor(cols[xc]);
g.fillCircle(xx,yy , pinsThick );
g.setColor("#000000");
g.drawCircle(xx,yy,pinsThick+1);
g.drawCircle(xx,yy,pinsThick);
}
}
//draw play input
for (k=0; k<pinsRow; k+=1){
xx = sx*k + pinsThick + 5;
yy = sy*7;
touch_actions.push([[xx-pinsThick-5, yy-pinsThick-10, xx+pinsThick+5, yy+pinsThick+20],[1,k]]);
if (play[k] < 0) {
//col not choisen, draw small dot
g.setColor("#000000");
g.fillCircle(xx,yy , 3 );
} else {
g.setColor(cols[play[k]]);
g.fillCircle(xx,yy , pinsThick );
+
}
}
// draw action button
// score, men
if (!endgame) {
if (col_menu) {
draw_col_choice();
} else {
// check if all pins are set yet
if (Math.min.apply(null,play) < 0) {
g.setColor("#FF0000");
} else {
g.setColor("#00FF00");
touch_actions.push([[W-30, H-30,192, 190], [3,1]]);
}
g.fillRect(W-30, H-30, W-1, H-10);
}
} else {
g.setColor("#0000FF");
touch_actions.push([[W-30, H-30,192, 190], [4,1]]);
g.fillRect(W-30, H-30, W-1, H-10);
}
}
+
function get_secret() {
//secret=[];
for (i=0; i<pinsRow; i+=1) {
s = Math.round(Math.random()*pinsCol);
if (secret_no_dub)
while(secret.indexOf(s) >= 0) s = Math.round(Math.random()*pinsCol);
secret[i]= s;
}
}
+
function score() {
bScore = 0;
wScore = 0;
for (i=0; i<pinsRow; i+=1) {
if (secret[i] == play[i]) {
bScore +=1;
}
else {
for (s=0; s<pinsRow; s+=1) {
if (secret[i] == play[s]) {
wScore +=1;
break;
}
}
}
}
+
return([bScore, wScore]);
}
+
function draw_col_choice(){
var cc = g.getColor();
var boxw = 30;
var boxh = H/pinsRow-20;
for (i=0; i<=pinsCol; i+=1) {
g.setColor(cols[i]);
g.fillRect(W-boxw, i*boxh, W-1, i*boxh+boxh);
touch_actions.push([[150, i*boxh, 191, i*boxh+boxh], [2,i]]);
g.setColor(cc);
}
+
}
+
Bangle.on('touch', function(zone,e) {
//console.log(e.x, e.y);
// check touch actions array to see what to do
for(i=0; i<touch_actions.length; i+=1) {
if (e.x > touch_actions[i][0][0] && e.x < touch_actions[i][0][2] &&
e.y > touch_actions[i][0][1] && e.y < touch_actions[i][0][3]) {
// a action is hit, add acctions here, todo: start, stop, new, etc.
switch (touch_actions[i][1][0]) {
case 1:
//get pins col menu
col_menu = 1;
playx = touch_actions[i][1][1];
break;
case 2:
//copy choice col to play
play[playx] = touch_actions[i][1][1];
col_menu = 0;
break;
case 3:
//score play
var sc;
sc = score();
game.push([play, sc]);
play = [-1,-1,-1,-1];
turn+=1;
if (turn==6 || sc[0]==pinsRow) {
play = secret;
col_menu = 0;
endgame = true;
}
break;
case 4:
//new game
play = [-1,-1,-1,-1];
game = [];
endgame=false;
break;
}
}
}
//console.log(touch_actions[i][1][0], touch_actions[i][1][1]);
draw();
}
);
+
+
game = [];
get_secret();
draw();
//Bangle.loadWidgets();
//Bangle.drawWidgets();
+
+
+
+
+
+ + + +
+ +
+ + + + +
+ + +
+ + +
+
+ + + + +
+ + + +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/mmind/mmind.png b/apps/mmind/mmind.png new file mode 100644 index 0000000000000000000000000000000000000000..8afcc26974bc8eaa2239927b33b4d566e8df42ba GIT binary patch literal 1546 zcmV+l2KD)gP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1)oVoK~z{r?U-F? z6Im3;PqV{V8ipugkQ7?8+6Es=Ed5|9Qi@bXs_cUgVqsSiDSZ$>=tC$=D3KD;4QZii z_aQWYinyuOH0vSU0pqX{J70#8yOkFCQYcjt?fT08+MKe z0zQWJBjn4MFIDcULX3dyl@}KmSrn((t?0hSQ0pGoMbj5EvIon-q-?~(8)kx$ZXCk?HItTvuF43->3XPinTZhcM)>?_U)RQ8q5r*v%9`hzx>~6b==u?AkS3Dn*NSbW|K2Ej$$og~L)XNMo6db+Di^>}58av8Zvv z9zTBE)YPn+3xsd96bp{B5q(eQe`XU?3NpP$cUGVk8K!~AFsMRQS5$t<@|qcY2^Mr9RAjmkDQ zqNak#pr$6PR#~z_qq12GR~drez<9-F!b;k?bLZIDSZizRsZ*!uV0Jvz#5F2Qt2Biq z%^H=_-YOD_LSMYioYbgHPH(BQmX;PQrhE79(S!mg1Lh$!*{`MZ~vWp^Wbk>AQBNxrmiDL4jeeZoa^iBmoHy_@#4j0uoc;GuF z*ksVWJ5$z`jU(h|e3?}YHTd58<_$IQO@7A?#ihskI>gwB-+&1%k)>AB%62y-B85p9 zody0O#F5{>s3e5%i{zP~Cyk9tS0J)Xrlz?6`%F*sF5jFqAvbZWeKL_#B*i*Xe$8jY z&R@8j)6t>o3dC;beihH3KcAVI;SI*t3DFu#;GrT3$uy*S1BvrbPEj+V=?n3qFr}fP z;o!l8yrBn8NW?>h0D?(f>~tSTMNw1K^et{GT)K3rv$K;obiw(1NnT>16ZD z`CGeWe{nbG!2=?Sn-flYdbt1lY`tV$Wig0dhwErKz|jF6N~$U%0ON|$0#LjgL-&Q? w=1pqU)j@l^;?iSo4*L4It;N`m`91*u1O9JFJ2Em3SpWb407*qoM6N<$g6%QmuK)l5 literal 0 HcmV?d00001 From ff363e10955cb4b82ecd53b10d697f30b8b4c39b Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 15:27:45 +0100 Subject: [PATCH 124/489] Update apps.json --- apps.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps.json b/apps.json index 28dcf6912..6f435fb82 100644 --- a/apps.json +++ b/apps.json @@ -5067,15 +5067,15 @@ "id": "mmind", "name": "Classic Mind Game", "shortName":"Master Mind", - "icon": "app.png", + "icon": "mmind.png", "version":"0.01", "description": "This is a classic mind game", "type": "game", - "tags": "mastermind, game, bangle 2", + "tags": "master mind, game, classic", "supports": ["BANGLEJS2"], "storage": [ - {"name":"mmind.app.js","url":"app.js"}, - {"name":"mmind.img","url":"app-icon.js","evaluate":true} + {"name":"mmind.app.js","url":"mmind.app.js"}, + {"name":"mmind.img","url":"mmind.icon.js","evaluate":true} ] } ] From 4e40afbc87ef1c616c80e49d6cf0220b63310341 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 15:44:09 +0100 Subject: [PATCH 125/489] Update apps.json --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 6f435fb82..50b2f3752 100644 --- a/apps.json +++ b/apps.json @@ -5069,9 +5069,9 @@ "shortName":"Master Mind", "icon": "mmind.png", "version":"0.01", - "description": "This is a classic mind game", + "description": "This is the classic game for masterminds", "type": "game", - "tags": "master mind, game, classic", + "tags": "mastermind, game, classic", "supports": ["BANGLEJS2"], "storage": [ {"name":"mmind.app.js","url":"mmind.app.js"}, From a6e7011b0d74fbbeb6b96f4c20dd3f43b60e7248 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 15:58:29 +0100 Subject: [PATCH 126/489] create changelog --- apps/mmind/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/mmind/ChangeLog diff --git a/apps/mmind/ChangeLog b/apps/mmind/ChangeLog new file mode 100644 index 000000000..939ac3b5d --- /dev/null +++ b/apps/mmind/ChangeLog @@ -0,0 +1 @@ +0.01: First release From d12c58a6c6f07b1c8b47ebda14eadaf690510815 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 17:07:29 +0100 Subject: [PATCH 127/489] Delete app-icon.js --- apps/mmind/app-icon.js | 1 - 1 file changed, 1 deletion(-) delete mode 100644 apps/mmind/app-icon.js diff --git a/apps/mmind/app-icon.js b/apps/mmind/app-icon.js deleted file mode 100644 index 9bcedc5f3..000000000 --- a/apps/mmind/app-icon.js +++ /dev/null @@ -1 +0,0 @@ -E.toArrayBuffer(atob("mEwgn/AF/ykYEMmUvAYPzAIX/rnMBIPzu93n4EB1OZBIW73U/+cQ/8Qn/05nM4f/+wXBt//+OZzOv//63e7j/zmI1Bn/1C4f3C4NzCQIXByf/nYXBDgPxKQM/+IvGv4XFF4QXF+ZfGAgQXBAgPyC4JpBC4QJBmEBQoUggQECmAEDBIR3BgURCgNnFQerEoXzp3kAgWIxBCBgMD+cC+JyD+JVD+nu91PBIIXBj/yj8h+MCOQSKCC4OzC4fj/84C4OPC4UiiQvEQogXCof//AvFgMBRQoXBAgVO9yPCL4cfiUziP/mMSQoUyiYECmguBAAMxkYDBkMf/4FCAH4A/AH4A/AH4A/AH4A/AH4Ap5gACAoM/BIXzAhgXE+MDBoXwh4EC+IEDBIYXE+UfBoXyl4ELI4pfXACPdAASrv")) From b33d629065fc0a57bbe3787ea2a61c2f29b1d667 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 17:07:53 +0100 Subject: [PATCH 128/489] Add files via upload --- apps/mmind/mmind.icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/mmind/mmind.icon.js diff --git a/apps/mmind/mmind.icon.js b/apps/mmind/mmind.icon.js new file mode 100644 index 000000000..c6f72ca38 --- /dev/null +++ b/apps/mmind/mmind.icon.js @@ -0,0 +1 @@ +E.toArrayBuffer(atob("2GwxH+64A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A6gAAFEf5I/VtpEcEcZI/Dw4PbCQu0AApnZDIUeAAqLaDQUFAApIc3IAFEabHPa6StJWLKtJWLStJWLKtJWKieFChIPPCYquKWAZmUVxSwDV6quKWAYjUVxSwDVqQUIB56uTWCiuOWCquOWCiuOWByaFV5oPLVyiwSVyCwTVyCwSVyCwNTIqvMB5iv/V/6vQUpQPTVyqwQVySwRVySwQVySwNT6Kv/V/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V/6vvWCZBSV0CwUJCSuhV/6v/V/4PPWCBBRWCIjSWCJIUV0CvfWB6KTWB4jUWB5IWVz6viWBYdPEZCuMV6ywLJDCuMV+SxLRKyxMEbKxKJDitXCAQALB6AoTRS4jkJHyvoFRCJZEcxI8V9DyZEdpI/ZaQpTB4W0AApnZDIUFAAqLaDQXSAApIckYAFEaTLPbaatJWLKtJWLStJWLKtJWKaeKDAgPPEgyuKWAZmUVxSwDV6quKWAYjUVxSwDV7AZDB56uSWCiuOWCquOWCiuOWByWJBAoPPVyiwSVyCwTVyCwSVyCwNSpIKLB5qv/V/6vuVySwQVySwRVySwQVySwMV/6v/V/6uRV/6v/V8wNDV/6v/V9SuJV/6v/V8atEV/6v/V9KtLV/6v/V8SuNWCiKPWCYjQWCZISVzavSVopGLV/6v/V8RDPVz6wSEaSwRJCiuaV6KuSWCCKTWB4jUWB5IWVzKvKVAyuTCgauMMyqwLEaokDVxhIWVxgjNT46uKIiytcWJojZWJRIcVqygGAA4OOFhYUUJbIjYJH4bOV7AaIRLIjmJH4bMV7QA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+goAHEbUeAA5s/ADO0ADitRWLStIWP6v/VxywWVxiw/V/quOWCiuOWH6v7VyCwSVyCw/V/6v/AH6vpVySwQVySw/V/6v/ABMAAAaXeEa6v/V+SKEWDwjYV/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V+SMFVzgjZV/6vzAHaviWCZHQV36v/V/6v/V/awRJCSu/V/6vLWB5JUV36v/V5awNJSyu/V/6vLWJRMaVv6v/V5YA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4AkA=")) \ No newline at end of file From 503b64e817b3c98a5dcea565888db4d0e26a99b3 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 17:10:50 +0100 Subject: [PATCH 129/489] Update mmind.icon.js --- apps/mmind/mmind.icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/mmind/mmind.icon.js b/apps/mmind/mmind.icon.js index c6f72ca38..976243b48 100644 --- a/apps/mmind/mmind.icon.js +++ b/apps/mmind/mmind.icon.js @@ -1 +1 @@ -E.toArrayBuffer(atob("2GwxH+64A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A6gAAFEf5I/VtpEcEcZI/Dw4PbCQu0AApnZDIUeAAqLaDQUFAApIc3IAFEabHPa6StJWLKtJWLStJWLKtJWKieFChIPPCYquKWAZmUVxSwDV6quKWAYjUVxSwDVqQUIB56uTWCiuOWCquOWCiuOWByaFV5oPLVyiwSVyCwTVyCwSVyCwNTIqvMB5iv/V/6vQUpQPTVyqwQVySwRVySwQVySwNT6Kv/V/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V/6vvWCZBSV0CwUJCSuhV/6v/V/4PPWCBBRWCIjSWCJIUV0CvfWB6KTWB4jUWB5IWVz6viWBYdPEZCuMV6ywLJDCuMV+SxLRKyxMEbKxKJDitXCAQALB6AoTRS4jkJHyvoFRCJZEcxI8V9DyZEdpI/ZaQpTB4W0AApnZDIUFAAqLaDQXSAApIckYAFEaTLPbaatJWLKtJWLStJWLKtJWKaeKDAgPPEgyuKWAZmUVxSwDV6quKWAYjUVxSwDV7AZDB56uSWCiuOWCquOWCiuOWByWJBAoPPVyiwSVyCwTVyCwSVyCwNSpIKLB5qv/V/6vuVySwQVySwRVySwQVySwMV/6v/V/6uRV/6v/V8wNDV/6v/V9SuJV/6v/V8atEV/6v/V9KtLV/6v/V8SuNWCiKPWCYjQWCZISVzavSVopGLV/6v/V8RDPVz6wSEaSwRJCiuaV6KuSWCCKTWB4jUWB5IWVzKvKVAyuTCgauMMyqwLEaokDVxhIWVxgjNT46uKIiytcWJojZWJRIcVqygGAA4OOFhYUUJbIjYJH4bOV7AaIRLIjmJH4bMV7QA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+goAHEbUeAA5s/ADO0ADitRWLStIWP6v/VxywWVxiw/V/quOWCiuOWH6v7VyCwSVyCw/V/6v/AH6vpVySwQVySw/V/6v/ABMAAAaXeEa6v/V+SKEWDwjYV/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V+SMFVzgjZV/6vzAHaviWCZHQV36v/V/6v/V/awRJCSu/V/6vLWB5JUV36v/V5awNJSyu/V/6vLWJRMaVv6v/V5YA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4AkA=")) \ No newline at end of file +require("heatshrink").decompress(atob("2GwxH+64A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A6gAAFEf5I/VtpEcEcZI/Dw4PbCQu0AApnZDIUeAAqLaDQUFAApIc3IAFEabHPa6StJWLKtJWLStJWLKtJWKieFChIPPCYquKWAZmUVxSwDV6quKWAYjUVxSwDVqQUIB56uTWCiuOWCquOWCiuOWByaFV5oPLVyiwSVyCwTVyCwSVyCwNTIqvMB5iv/V/6vQUpQPTVyqwQVySwRVySwQVySwNT6Kv/V/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V/6vvWCZBSV0CwUJCSuhV/6v/V/4PPWCBBRWCIjSWCJIUV0CvfWB6KTWB4jUWB5IWVz6viWBYdPEZCuMV6ywLJDCuMV+SxLRKyxMEbKxKJDitXCAQALB6AoTRS4jkJHyvoFRCJZEcxI8V9DyZEdpI/ZaQpTB4W0AApnZDIUFAAqLaDQXSAApIckYAFEaTLPbaatJWLKtJWLStJWLKtJWKaeKDAgPPEgyuKWAZmUVxSwDV6quKWAYjUVxSwDV7AZDB56uSWCiuOWCquOWCiuOWByWJBAoPPVyiwSVyCwTVyCwSVyCwNSpIKLB5qv/V/6vuVySwQVySwRVySwQVySwMV/6v/V/6uRV/6v/V8wNDV/6v/V9SuJV/6v/V8atEV/6v/V9KtLV/6v/V8SuNWCiKPWCYjQWCZISVzavSVopGLV/6v/V8RDPVz6wSEaSwRJCiuaV6KuSWCCKTWB4jUWB5IWVzKvKVAyuTCgauMMyqwLEaokDVxhIWVxgjNT46uKIiytcWJojZWJRIcVqygGAA4OOFhYUUJbIjYJH4bOV7AaIRLIjmJH4bMV7QA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+goAHEbUeAA5s/ADO0ADitRWLStIWP6v/VxywWVxiw/V/quOWCiuOWH6v7VyCwSVyCw/V/6v/AH6vpVySwQVySw/V/6v/ABMAAAaXeEa6v/V+SKEWDwjYV/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V+SMFVzgjZV/6vzAHaviWCZHQV36v/V/6v/V/awRJCSu/V/6vLWB5JUV36v/V5awNJSyu/V/6vLWJRMaVv6v/V5YA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4AkA=")) From d0583def6bcfb19282b827ae1deae61e84b9f5c7 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 17:16:27 +0100 Subject: [PATCH 130/489] Delete mmind.app.js --- apps/mmind/mmind.app.js | 3395 --------------------------------------- 1 file changed, 3395 deletions(-) delete mode 100644 apps/mmind/mmind.app.js diff --git a/apps/mmind/mmind.app.js b/apps/mmind/mmind.app.js deleted file mode 100644 index 52a566ca9..000000000 --- a/apps/mmind/mmind.app.js +++ /dev/null @@ -1,3395 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - BangleApps/app.js at master · psbest/BangleApps - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
- - - -
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- -
- - - psbest  /   - BangleApps  /   - -
- - - - Type # for issues and pull requests, > for commands, and ? for help - - - Type # for issues, pull requests, and projects, > for commands, and ? for help - - - Type # for issues, pull requests, and projects, / for files, and > for commands - - -
- -
-
- We’ve encountered an error and some results aren't available at this time. Type a new search or try again later. -
-
- - No results matched your search - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - Search for issues and pull requests - - # - - - - Search for issues, pull requests, discussions, and projects - - # - - - - Search for organizations, repositories, and users - - @ - - - - Search for projects - - ! - - - - Search for files - - / - - - - Activate command mode - - > - - - - Search your issues, pull requests, and discussions - - # author:@me - - - - Search your issues, pull requests, and discussions - - # author:@me - - - - Filter to pull requests - - # is:pr - - - - Filter to issues - - # is:issue - - - - Filter to discussions - - # is:discussion - - - - Filter to projects - - # is:project - - - - Filter to open issues, pull requests, and discussions - - # is:open - - - - - - - - - - - - - - - - -
-
-
- -
- - - - - - - - - - -
- - - - -
-
-
- - - - - - - - - - -
- -
- -
-

- - - / - - BangleApps - - - Public -

- - forked from espruino/BangleApps - - -
- -
    - -
  • - -
    - - - - - - - Watch - - - 0 - - - -
    -
    -

    Notifications

    - -
    - -
    -
    - - - - - - - - -
    - - -
    - - - - - Get push notifications on iOS or Android. - -
    -
    -
    -
    - - -
    -
    -
    - - - -
  • - - -
  • - - -
  • - -
  • - -
    -
    - -
    -
    - -
    -
    - - - - - -
    - -
    -
    - - - - - - - -
    - -
    -
    -
    -
    -
    -
  • - - -
  • - - -
  • -
- -
- -
-
- - - - -
- - - -
-
- - Open in github.dev - Open in a new github.dev tab - - - - - - - -
- - - - - Permalink - - -
- -
-
- - - master - - - - -
-
-
- Switch branches/tags - -
- - - -
- -
- -
- - -
- -
- - - - - - - - - - - - - - - - -
- - -
-
-
-
- -
- -
- - - - Go to file - - -
- - - - -
-
-
- - - - -
- -
-
-
 
-
- -
-
 
- Cannot retrieve contributors at this time -
-
- - - - - - - - - - - -
- -
- - -
- - 198 lines (178 sloc) - - 4.59 KB -
- -
- - - - -
- - - - - - - - - - - - - - - -
- -
-
- -
-
- -
- -
-
- - - -
- - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//MMind
-
//set vars
const H = g.getWidth();
const W = g.getHeight();
var touch_actions = [];
var cols = ["#FF0000","#00FF00","#0000FF", "#FF00FF", "#FFFF00", "#00FFFF", "#000000","#FFFFFF"];
var turn = 0;
var col_menu = false;
//pinsRow = 6;
//pinsThick = 10;
//pinsRow = 5;
//pinsThick = 10;
var pinsRow = 4;
var pinsThick = 10;
var play = [-1, -1, -1, -1];
-
var pinsCol = 5;
var playx = -1;
var sx = (W - 30 )/pinsRow;
var sy = (H - 20 )/7;
var touch_actions = [];
var secret = [];
var secret_no_dub = true;
var endgame = false;
-
g.clear();
g.setColor("#FFFFFF");
g.fillRect(0, 0, H, W);
g.setFont("Vector12",45);
-
function draw() {
touch_actions = [];
g.clear();
g.setColor("#FFFFFF");
g.fillRect(0, 0, H, W);
g.setColor("#000000");
//draw scores
for (y=0;y<game.length;y+=1) {
pp = game[y][0];
ps = game[y][1];
g.setColor("#000000");
//g.fillRect(W-30,10, W-30, 15);
g.setColor("#000000");
g.setFont("Vector30",10);
g.drawString(ps[0],W-31,y*sy+8);
g.setColor("#000000");
g.drawString(ps[1],W-15,y*sy+8);
g.setColor("#000000");
for (x=0;x<pinsRow;x+=1) {
xx = sx*x + pinsThick + 5;
yy = sy*y+20;
xc = pp[x];
g.setColor(cols[xc]);
g.fillCircle(xx,yy , pinsThick );
g.setColor("#000000");
g.drawCircle(xx,yy,pinsThick+1);
g.drawCircle(xx,yy,pinsThick);
}
}
//draw play input
for (k=0; k<pinsRow; k+=1){
xx = sx*k + pinsThick + 5;
yy = sy*7;
touch_actions.push([[xx-pinsThick-5, yy-pinsThick-10, xx+pinsThick+5, yy+pinsThick+20],[1,k]]);
if (play[k] < 0) {
//col not choisen, draw small dot
g.setColor("#000000");
g.fillCircle(xx,yy , 3 );
} else {
g.setColor(cols[play[k]]);
g.fillCircle(xx,yy , pinsThick );
-
}
}
// draw action button
// score, men
if (!endgame) {
if (col_menu) {
draw_col_choice();
} else {
// check if all pins are set yet
if (Math.min.apply(null,play) < 0) {
g.setColor("#FF0000");
} else {
g.setColor("#00FF00");
touch_actions.push([[W-30, H-30,192, 190], [3,1]]);
}
g.fillRect(W-30, H-30, W-1, H-10);
}
} else {
g.setColor("#0000FF");
touch_actions.push([[W-30, H-30,192, 190], [4,1]]);
g.fillRect(W-30, H-30, W-1, H-10);
}
}
-
function get_secret() {
//secret=[];
for (i=0; i<pinsRow; i+=1) {
s = Math.round(Math.random()*pinsCol);
if (secret_no_dub)
while(secret.indexOf(s) >= 0) s = Math.round(Math.random()*pinsCol);
secret[i]= s;
}
}
-
function score() {
bScore = 0;
wScore = 0;
for (i=0; i<pinsRow; i+=1) {
if (secret[i] == play[i]) {
bScore +=1;
}
else {
for (s=0; s<pinsRow; s+=1) {
if (secret[i] == play[s]) {
wScore +=1;
break;
}
}
}
}
-
return([bScore, wScore]);
}
-
function draw_col_choice(){
var cc = g.getColor();
var boxw = 30;
var boxh = H/pinsRow-20;
for (i=0; i<=pinsCol; i+=1) {
g.setColor(cols[i]);
g.fillRect(W-boxw, i*boxh, W-1, i*boxh+boxh);
touch_actions.push([[150, i*boxh, 191, i*boxh+boxh], [2,i]]);
g.setColor(cc);
}
-
}
-
Bangle.on('touch', function(zone,e) {
//console.log(e.x, e.y);
// check touch actions array to see what to do
for(i=0; i<touch_actions.length; i+=1) {
if (e.x > touch_actions[i][0][0] && e.x < touch_actions[i][0][2] &&
e.y > touch_actions[i][0][1] && e.y < touch_actions[i][0][3]) {
// a action is hit, add acctions here, todo: start, stop, new, etc.
switch (touch_actions[i][1][0]) {
case 1:
//get pins col menu
col_menu = 1;
playx = touch_actions[i][1][1];
break;
case 2:
//copy choice col to play
play[playx] = touch_actions[i][1][1];
col_menu = 0;
break;
case 3:
//score play
var sc;
sc = score();
game.push([play, sc]);
play = [-1,-1,-1,-1];
turn+=1;
if (turn==6 || sc[0]==pinsRow) {
play = secret;
col_menu = 0;
endgame = true;
}
break;
case 4:
//new game
play = [-1,-1,-1,-1];
game = [];
endgame=false;
break;
}
}
}
//console.log(touch_actions[i][1][0], touch_actions[i][1][1]);
draw();
}
);
-
-
game = [];
get_secret();
draw();
//Bangle.loadWidgets();
//Bangle.drawWidgets();
-
-
-
-
-
- - - -
- -
- - - - -
- - -
- - -
-
- - - - -
- - - -
-
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - From ade75a3e7ce323cad8f862213fe1d68ec20aafce Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 17:18:11 +0100 Subject: [PATCH 131/489] Add files via upload --- apps/mmind/mmind.app.js | 198 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 apps/mmind/mmind.app.js diff --git a/apps/mmind/mmind.app.js b/apps/mmind/mmind.app.js new file mode 100644 index 000000000..e7def025d --- /dev/null +++ b/apps/mmind/mmind.app.js @@ -0,0 +1,198 @@ +//MMind + +//set vars +const H = g.getWidth(); +const W = g.getHeight(); +var touch_actions = []; +var cols = ["#FF0000","#00FF00","#0000FF", "#FF00FF", "#FFFF00", "#00FFFF", "#000000","#FFFFFF"]; +var turn = 0; +var col_menu = false; +//pinsRow = 6; +//pinsThick = 10; +//pinsRow = 5; +//pinsThick = 10; +var pinsRow = 4; +var pinsThick = 10; +var play = [-1, -1, -1, -1]; + +var pinsCol = 5; +var playx = -1; +var sx = (W - 30 )/pinsRow; +var sy = (H - 20 )/7; +var touch_actions = []; +var secret = []; +var secret_no_dub = true; +var endgame = false; + +g.clear(); +g.setColor("#FFFFFF"); +g.fillRect(0, 0, H, W); +g.setFont("Vector12",45); + +function draw() { + touch_actions = []; + g.clear(); + g.setColor("#FFFFFF"); + g.fillRect(0, 0, H, W); + g.setColor("#000000"); + //draw scores + for (y=0;y= 0) s = Math.round(Math.random()*pinsCol); + secret[i]= s; + } + } + +function score() { + bScore = 0; + wScore = 0; + for (i=0; i touch_actions[i][0][0] && e.x < touch_actions[i][0][2] && + e.y > touch_actions[i][0][1] && e.y < touch_actions[i][0][3]) { + // a action is hit, add acctions here, todo: start, stop, new, etc. + switch (touch_actions[i][1][0]) { + case 1: + //get pins col menu + col_menu = 1; + playx = touch_actions[i][1][1]; + break; + case 2: + //copy choice col to play + play[playx] = touch_actions[i][1][1]; + col_menu = 0; + break; + case 3: + //score play + var sc; + sc = score(); + game.push([play, sc]); + play = [-1,-1,-1,-1]; + turn+=1; + if (turn==6 || sc[0]==pinsRow) { + play = secret; + col_menu = 0; + endgame = true; + } + break; + case 4: + //new game + play = [-1,-1,-1,-1]; + game = []; + endgame=false; + break; + } + } + } + //console.log(touch_actions[i][1][0], touch_actions[i][1][1]); + + draw(); + } +); + + +game = []; +get_secret(); +draw(); +//Bangle.loadWidgets(); +//Bangle.drawWidgets(); + + + + + From 383d183fa8fa302b8ac1db20b5f1b80935978806 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 17:33:12 +0100 Subject: [PATCH 132/489] Update apps.json --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 50b2f3752..b195a5ee3 100644 --- a/apps.json +++ b/apps.json @@ -5073,6 +5073,7 @@ "type": "game", "tags": "mastermind, game, classic", "supports": ["BANGLEJS2"], + "allow_emulator": true, "storage": [ {"name":"mmind.app.js","url":"mmind.app.js"}, {"name":"mmind.img","url":"mmind.icon.js","evaluate":true} From 1241dba5e4833d57b72d5fcdec13218213a7cc44 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 17:51:01 +0100 Subject: [PATCH 133/489] Update apps.json --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index b195a5ee3..eaab9e297 100644 --- a/apps.json +++ b/apps.json @@ -5072,6 +5072,7 @@ "description": "This is the classic game for masterminds", "type": "game", "tags": "mastermind, game, classic", + "readme":"README.md", "supports": ["BANGLEJS2"], "allow_emulator": true, "storage": [ From 3909c912bcb30389f42b9be6f9d7d1eb61096a45 Mon Sep 17 00:00:00 2001 From: Jeroen Peters Date: Mon, 3 Jan 2022 19:57:42 +0100 Subject: [PATCH 134/489] WIDGET widbatpc: 0.15: Added option to always display the icon when charging (useful if 'hide if charge greater than' is enabled) --- apps.json | 2 +- apps/widbatpc/ChangeLog | 1 + apps/widbatpc/settings.js | 6 ++++++ apps/widbatpc/widget.js | 3 ++- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 7d8faec91..073c6ded5 100644 --- a/apps.json +++ b/apps.json @@ -936,7 +936,7 @@ "id": "widbatpc", "name": "Battery Level Widget (with percentage)", "shortName": "Battery Widget", - "version": "0.14", + "version": "0.15", "description": "Show the current battery level and charging status in the top right of the clock, with charge percentage", "icon": "widget.png", "type": "widget", diff --git a/apps/widbatpc/ChangeLog b/apps/widbatpc/ChangeLog index 99822b5a9..273e611a4 100644 --- a/apps/widbatpc/ChangeLog +++ b/apps/widbatpc/ChangeLog @@ -11,3 +11,4 @@ 0.12: Fixed for Bangle 2 0.13: Fillbar setting added, see README 0.14: Fix drawing the bar when charging +0.15: Added option to always display the icon when charging (useful if 'hide if charge greater than' is enabled) diff --git a/apps/widbatpc/settings.js b/apps/widbatpc/settings.js index b7a5db9e6..b45fc6749 100644 --- a/apps/widbatpc/settings.js +++ b/apps/widbatpc/settings.js @@ -13,6 +13,7 @@ 'fillbar': false, 'charger': true, 'hideifmorethan': 100, + 'alwaysoncharge': false, } // ...and overwrite them with any saved values // This way saved values are preserved if a new version adds more settings @@ -68,6 +69,11 @@ format: x => x+"%", onchange: save('hideifmorethan'), }, + 'Show on charge': { // Not sure if this is readable enough in the 'big' menu + value: s.alwaysoncharge, + format: onOffFormat, + onchange: save('alwaysoncharge'), + }, } E.showMenu(menu) }) diff --git a/apps/widbatpc/widget.js b/apps/widbatpc/widget.js index 3e5ff47b4..8791b9fe3 100644 --- a/apps/widbatpc/widget.js +++ b/apps/widbatpc/widget.js @@ -29,6 +29,7 @@ 'percentage': true, 'charger': true, 'hideifmorethan': 100, + 'alwaysoncharge': false, }; Object.keys(DEFAULTS).forEach(k=>{ if (settings[k]===undefined) settings[k]=DEFAULTS[k] @@ -67,7 +68,7 @@ var w = 40; if (Bangle.isCharging() && setting('charger')) w += 16; - if (E.getBattery() > setting('hideifmorethan')) + if (setting('alwaysoncharge') == false && E.getBattery() > setting('hideifmorethan')) w = 0; var changed = WIDGETS["batpc"].width != w; WIDGETS["batpc"].width = w; From 61797894afbc096a6a1bd327297ae8fe01d0e9b2 Mon Sep 17 00:00:00 2001 From: Jeroen Peters Date: Mon, 3 Jan 2022 20:28:10 +0100 Subject: [PATCH 135/489] WIDGET widbatpc: 0.15: Added option to always display the icon when charging (useful if 'hide if charge greater than' is enabled) --- apps/widbatpc/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/widbatpc/widget.js b/apps/widbatpc/widget.js index 8791b9fe3..16aea5dae 100644 --- a/apps/widbatpc/widget.js +++ b/apps/widbatpc/widget.js @@ -68,7 +68,7 @@ var w = 40; if (Bangle.isCharging() && setting('charger')) w += 16; - if (setting('alwaysoncharge') == false && E.getBattery() > setting('hideifmorethan')) + if ((setting('alwaysoncharge') == false && Bangle.isCharging()) && E.getBattery() > setting('hideifmorethan')) w = 0; var changed = WIDGETS["batpc"].width != w; WIDGETS["batpc"].width = w; From 37c8fa092185659a73bc37aa65db343675eb7d14 Mon Sep 17 00:00:00 2001 From: Jeroen Peters Date: Mon, 3 Jan 2022 22:41:40 +0100 Subject: [PATCH 136/489] WIDGET widbatpc: 0.15: Added option to always display the icon when charging (useful if 'hide if charge greater than' is enabled) --- apps/widbatpc/widget.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/widbatpc/widget.js b/apps/widbatpc/widget.js index 16aea5dae..5386ffe22 100644 --- a/apps/widbatpc/widget.js +++ b/apps/widbatpc/widget.js @@ -68,8 +68,11 @@ var w = 40; if (Bangle.isCharging() && setting('charger')) w += 16; - if ((setting('alwaysoncharge') == false && Bangle.isCharging()) && E.getBattery() > setting('hideifmorethan')) + if (E.getBattery() > setting('hideifmorethan')) { w = 0; + if( Bangle.isCharging() && setting('alwaysoncharge') === true) + w = 56; + } var changed = WIDGETS["batpc"].width != w; WIDGETS["batpc"].width = w; return changed; From 8c10eb12dd05715ba96d1297b15143e249b1a325 Mon Sep 17 00:00:00 2001 From: Jeroen Peters Date: Mon, 3 Jan 2022 23:19:15 +0100 Subject: [PATCH 137/489] APP ios: 0.08: Added more app identifiers, added 'cannot display' in case a message goes empty because of replacements --- apps.json | 2 +- apps/ios/ChangeLog | 8 +++----- apps/ios/boot.js | 7 ++++++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/apps.json b/apps.json index ed4eb25a8..609b7e002 100644 --- a/apps.json +++ b/apps.json @@ -116,7 +116,7 @@ { "id": "ios", "name": "iOS Integration", - "version": "0.07", + "version": "0.08", "description": "Display notifications/music/etc from iOS devices", "icon": "app.png", "tags": "tool,system,ios,apple,messages,notifications", diff --git a/apps/ios/ChangeLog b/apps/ios/ChangeLog index 5e60068aa..1873649f9 100644 --- a/apps/ios/ChangeLog +++ b/apps/ios/ChangeLog @@ -2,9 +2,7 @@ 0.02: Remove messages on disconnect 0.03: Handling of message actions (ok/clear) 0.04: Added common bundleId's -0.05: Added more bundleId's (app-id's which can be used to - determine a friendly app name in the notifications) +0.05: Added more bundleId's (app-id's which can be used to determine a friendly app name in the notifications) 0.06: Fix (not) popupping up old messages -0.07: Added more details from music (instead of Undefined) - Added more app identifiers - +0.07: Added more details from music (instead of Undefined), added more app identifiers +0.08: Added more app identifiers, added 'cannot display' in case a message goes empty because of replacements diff --git a/apps/ios/boot.js b/apps/ios/boot.js index 8ccfb617d..d317c23b0 100644 --- a/apps/ios/boot.js +++ b/apps/ios/boot.js @@ -66,6 +66,7 @@ E.on('notify',msg=>{ "com.apple.mobilecal": "Calendar", "com.apple.mobilemail": "Mail", "com.apple.mobilephone": "Phone", + "com.apple.mobileslideshow": "Pictures", "com.apple.MobileSMS": "SMS Message", "com.apple.Passbook": "iOS Wallet", "com.apple.podcasts": "Podcasts", @@ -83,6 +84,7 @@ E.on('notify',msg=>{ "com.ifttt.ifttt" : "IFTTT", "com.jumbo.app" : "Jumbo", "com.linkedin.LinkedIn" : "LinkedIn", + "com.marktplaats.iphone": "Marktplaats", "com.microsoft.Office.Outlook" : "Outlook Mail", "com.nestlabs.jasper.release" : "Nest", "com.netflix.Netflix" : "Netflix", @@ -90,6 +92,7 @@ E.on('notify',msg=>{ "com.skype.skype": "Skype", "com.skype.SkypeForiPad": "Skype", "com.spotify.client": "Spotify", + "com.storytel.iphone": "Storytel", "com.strava.stravaride": "Strava", "com.tinyspeck.chatlyio": "Slack", "com.toyopagroup.picaboo": "Snapchat", @@ -98,6 +101,8 @@ E.on('notify',msg=>{ "com.vilcsak.bitcoin2": "Coinbase", "com.wordfeud.free": "WordFeud", "com.zhiliaoapp.musically": "TikTok", + "io.robbie.HomeAssistant": "Home Assistant", + "net.weks.prowl": "Prowl", "net.whatsapp.WhatsApp": "WhatsApp", "nl.ah.Appie": "Albert Heijn", "nl.postnl.TrackNTrace": "PostNL", @@ -118,7 +123,7 @@ E.on('notify',msg=>{ new : msg.new, title : msg.title&&E.decodeUTF8(msg.title, unicodeRemap, replacer), subject : msg.subtitle&&E.decodeUTF8(msg.subtitle, unicodeRemap, replacer), - body : msg.message&&E.decodeUTF8(msg.message, unicodeRemap, replacer) + body : msg.message&&E.decodeUTF8(msg.message, unicodeRemap, replacer) || "Cannot display" }); // TODO: posaction/negaction? }); From 2d7245943373113cb4bc7e07ee3d46a9efe39d34 Mon Sep 17 00:00:00 2001 From: Jeroen Peters Date: Tue, 4 Jan 2022 00:44:48 +0100 Subject: [PATCH 138/489] APP ios: 0.08: Added more app identifiers, added 'cannot display' in case a message goes empty because of replacements --- apps.json | 2 +- apps/messages/ChangeLog | 1 + apps/messages/app.js | 1 + apps/messages/widget.js | 13 +++++++------ 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/apps.json b/apps.json index 609b7e002..179579cb9 100644 --- a/apps.json +++ b/apps.json @@ -77,7 +77,7 @@ { "id": "messages", "name": "Messages", - "version": "0.14", + "version": "0.15", "description": "App to display notifications from iOS and Gadgetbridge", "icon": "app.png", "type": "app", diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index 94848a26c..4049f3724 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -21,3 +21,4 @@ Add 'Delete All' option to message options Now update correctly when 'require("messages").clearAll()' is called 0.14: Hide widget when all unread notifications are dismissed from phone +0.15: Fix: Get dynamic dimensions of notify icon, fixed notification font diff --git a/apps/messages/app.js b/apps/messages/app.js index 79009e77e..345d2115a 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -243,6 +243,7 @@ function showMessage(msgid) { checkMessages({clockIfNoMsg:1,clockIfAllRead:1,showMsgIfUnread:1}); }}); } + g.setFont(fontMedium); lines = g.wrapString(msg.body, g.getWidth()-10); var body = (lines.length>4) ? lines.slice(0,4).join("\n")+"..." : lines.join("\n"); layout = new Layout({ type:"v", c: [ diff --git a/apps/messages/widget.js b/apps/messages/widget.js index f01d22ec7..05622b162 100644 --- a/apps/messages/widget.js +++ b/apps/messages/widget.js @@ -1,9 +1,10 @@ -WIDGETS["messages"]={area:"tl",width:0,draw:function() { +WIDGETS["messages"]={area:"tl", width:0, ICONS:[atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+DAADDAADDAADDwAPD8A/DOBzDDn/DA//DAHvDAPvjAPvjAPvjAPvh///gf/vAAD+AAB8AAAAA=="),atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+D///D///A//8CP/xDj/HD48DD+B8D/D+D/3vD/vvj/vvj/vvj/vvh/v/gfnvAAD+AAB8AAAAA==")], //icons should be equal size or first larger +draw:function() { Bangle.removeListener('touch', this.touch); if (!this.width) return; var c = (Date.now()-this.t)/1000; - g.reset().clearRect(this.x,this.y,this.x+this.width,this.y+23); - g.drawImage((c&1) ? atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+DAADDAADDAADDwAPD8A/DOBzDDn/DA//DAHvDAPvjAPvjAPvjAPvh///gf/vAAD+AAB8AAAAA==") : atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+D///D///A//8CP/xDj/HD48DD+B8D/D+D/3vD/vvj/vvj/vvj/vvh/v/gfnvAAD+AAB8AAAAA=="), this.x, this.y); + g.reset().clearRect(this.x, this.y, this.x+this.width, this.y+this.ICONS[0].charCodeAt(1)); + g.drawImage(this.ICONS[c&1], this.x, this.y); //if (c<60) Bangle.setLCDPower(1); // keep LCD on for 1 minute let settings = require('Storage').readJSON("messages.settings.json", true) || {}; if (settings.repeat===undefined) settings.repeat = 4; @@ -17,7 +18,7 @@ WIDGETS["messages"]={area:"tl",width:0,draw:function() { WIDGETS["messages"].t=Date.now(); // first time WIDGETS["messages"].l=Date.now()-10000; // last buzz if (quiet) WIDGETS["messages"].t -= 500000; // if quiet, set last time in the past so there is no buzzing - WIDGETS["messages"].width=64; + WIDGETS["messages"].width=this.ICONS[0].charCodeAt(0); Bangle.drawWidgets(); Bangle.setLCDPower(1);// turns screen on },hide:function() { @@ -36,7 +37,7 @@ WIDGETS["messages"]={area:"tl",width:0,draw:function() { b(); },touch:function(b,c) { var w=WIDGETS["messages"]; - if (!w||!w.width||c.xw.x+w.width||c.yw.y+23) return; + if (!w||!w.width||c.xw.x+w.width||c.yw.y+w.ICONS[0].charCodeAt(1)) return; load("messages.app.js"); }}; /* We might have returned here if we were in the Messages app for a @@ -45,4 +46,4 @@ want to buzz but should still show that there are unread messages. */ if (global.MESSAGES===undefined) (function() { var messages = require("Storage").readJSON("messages.json",1)||[]; if (messages.some(m=>m.new)) WIDGETS["messages"].show(true); -})(); +})(); \ No newline at end of file From e66210b85d9351612d1a960af464a7f9ddcdde9b Mon Sep 17 00:00:00 2001 From: kyleplo <31634240+kyleplo@users.noreply.github.com> Date: Mon, 3 Jan 2022 19:50:09 -0500 Subject: [PATCH 139/489] Create touchmenu.boot.js --- apps/touchmenu.boot.js | 197 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 apps/touchmenu.boot.js diff --git a/apps/touchmenu.boot.js b/apps/touchmenu.boot.js new file mode 100644 index 000000000..93a0ba1c8 --- /dev/null +++ b/apps/touchmenu.boot.js @@ -0,0 +1,197 @@ +E.showMenu = function(items) { + const gw = g.getWidth(); + const gh = g.getHeight(); + Bangle.removeAllListeners("drag"); + if(!items){ + delete m; + g.clearRect(0, 30, gw, gh - 30); + return false; + } + var loc = require("locale"); + var m = { + info: { + title: "Menu", + cB: g.theme.bg, + cF: g.theme.fg, + cHB: g.theme.bgH, + cHF: g.theme.fgH, + cAB: g.theme.bg2, + cAF: g.theme.fg2, + predraw : () => {}, + preflip : () => {} + }, + scroll: 0, + items: [], + selected: -1, + draw: () => { + g.reset().setFont('12x20'); + m.info.predraw(g); + g.setColor(m.info.cB).fillRect(0, 50, gw, gh - 30).setColor(m.info.cF); + m.items.forEach((e, i) => { + const s = (i * 48) - m.scroll + 50; + if(s < 30 || s > gh - 74){ + return false; + } + if(i == m.selected){ + g.setColor(m.info.cHB).fillRect(0, s, gw, Math.min(s + 48, gh - 30)).setColor(m.info.cHF); + }else{ + g.setColor(m.info.cF); + } + g.drawString(e.title, (e.icon ? 30 : 10), s + 5); + if(e.icon){ + g.drawImage(e.icon, 5, s + 5); + } + if(e.type && s < gh - 72){ + if(e.format){ + g.setFontAlign(1, -1, 0).drawString(e.format(e.value), gw - 10, s + 25).setFontAlign(-1, -1, 0); + }else{ + g.setFontAlign(1, -1, 0).drawString(e.value, gw - 10, s + 25).setFontAlign(-1, -1, 0); + } + } + }); + g.setColor(m.info.cAB).fillRect(0, 30, gw, 50); + g.setColor(m.info.cAF).drawString(m.info.title, (m.back ? 30 : 10), 32); + if(m.back){ + g.drawLine(5, 40, 20, 40); + g.drawLine(5, 40, 15, 33); + g.drawLine(5, 40, 15, 47); + } + m.info.preflip(g, m.scroll > 0, m.scroll < (m.items.length - 1) * 48); + }, + select: (x, y) => { + if(m.selected == -1 || m.selected !== Math.max(Math.min(Math.floor((y + m.scroll - 50) / 48), m.items.length - 1), 0)){ + if(y){ + if(y < 50 || y > gh - 30){ + return false; + }else{ + m.selected = Math.max(Math.min(Math.floor((y + m.scroll - 50) / 48), m.items.length - 1), 0); + } + }else{ + m.selected = Math.floor(m.scroll / 48); + } + m.draw(); + }else{ + if(m.items[m.selected].type && m.items[m.selected].type === "boolean"){ + m.items[m.selected].value = !m.items[m.selected].value; + m.items[m.selected].onchange(m.items[m.selected].value); + m.draw(); + }else if(m.items[m.selected].type && m.items[m.selected].type === "number"){ + if(x && x < (gw / 2)){ + m.items[m.selected].value = m.items[m.selected].value - (m.items[m.selected].step ? m.items[m.selected].step : 1); + }else{ + m.items[m.selected].value = m.items[m.selected].value + (m.items[m.selected].step ? m.items[m.selected].step : 1); + } + if(m.items[m.selected].value > (m.items[m.selected].max ? m.items[m.selected].max : Infinity)){ + m.items[m.selected].value = m.items[m.selected].min ? m.items[m.selected].min : 0; + } + if(m.items[m.selected].value < (m.items[m.selected].min ? m.items[m.selected].min : 0)){ + m.items[m.selected].value = m.items[m.selected].max ? m.items[m.selected].max : 10; + } + m.items[m.selected].onchange(m.items[m.selected].value); + m.draw(); + }else{ + if(m.items[m.selected]){ + m.items[m.selected](); + } + } + } + }, + move: d => { + m.scroll += (d * 48); + m.scroll = Math.min(Math.max(m.scroll, 0), (m.items.length - 1) * 48); + m.selected = Math.max(Math.min(Math.floor((m.scroll - 50) / 48), m.items.length - 1), 0); + m.draw(); + }, + }; + Object.keys(items).forEach(i => { + if(i == ""){ + m.info = Object.assign(m.info, items[i]); + }else if(i === "< Back" && items[i]){ + m.back = items[i]; + }else if(items[i]){ + m.items.push(items[i]); + m.items[m.items.length - 1].title = loc.translate(i); + if(items[i].hasOwnProperty("value")){ + if(typeof items[i].value === "boolean"){ + m.items[m.items.length - 1].type = "boolean"; + }else{ + m.items[m.items.length - 1].type = "number"; + } + } + } + }); + m.info.title = loc.translate(m.info.title); + m.draw(); + Bangle.on("drag", d => { + if(!d.b){ + return false; + } + if(d.dx == 0 && d.dy == 0){ + if(d.x < 30 && d.y < 50){ + m.back(); + return false; + } + m.select(d.x, d.y); + }else{ + m.selected = -1; + m.scroll -= d.dy; + m.scroll = Math.min(Math.max(m.scroll, 0), (m.items.length - 1) * 48); + m.draw(); + } + }); + return m; +}; + +E.showAlert = function (e, t){ + if(!e){ + E.showMenu(); + return false; + } + return new Promise(r => { + const menu = { + "": { + "title": (t ? t : "Alert") + }, + Ok: () => { + E.showMenu(); + r(); + } + }; + menu[e] = () => {}; + E.showMenu(menu); + }); +}; +E.showMessage = E.showAlert; + +E.showPrompt = function (e, t){ + if(!e){ + E.showMenu(); + return false; + } + return new Promise(r => { + const menu = { + "": { + "title": (t && t.title ? t.title : "Choose") + } + }; + menu[e] = () => {}; + if(t && t.buttons){ + Object.keys(t.buttons).forEach(b => { + menu[b] = () => { + E.showMenu(); + r(t.buttons[b]); + }; + }); + }else{ + menu.Yes = () => { + E.showMenu(); + r(true); + }; + menu.No = () => { + E.showMenu(); + r(false); + }; + } + E.showMenu(menu); + }); +}; From 3fdd87e728413699ae64bd2f2911325769245c72 Mon Sep 17 00:00:00 2001 From: kyleplo <31634240+kyleplo@users.noreply.github.com> Date: Mon, 3 Jan 2022 19:52:34 -0500 Subject: [PATCH 140/489] Rename apps/touchmenu.boot.js to apps/touchmenu/touchmenu.boot.js --- apps/{ => touchmenu}/touchmenu.boot.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/{ => touchmenu}/touchmenu.boot.js (100%) diff --git a/apps/touchmenu.boot.js b/apps/touchmenu/touchmenu.boot.js similarity index 100% rename from apps/touchmenu.boot.js rename to apps/touchmenu/touchmenu.boot.js From 868e5af855f2f2516979d86b60dfc50e04266373 Mon Sep 17 00:00:00 2001 From: kyleplo <31634240+kyleplo@users.noreply.github.com> Date: Mon, 3 Jan 2022 19:53:25 -0500 Subject: [PATCH 141/489] Create ChangeLog --- apps/touchmenu/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/touchmenu/ChangeLog diff --git a/apps/touchmenu/ChangeLog b/apps/touchmenu/ChangeLog new file mode 100644 index 000000000..c5277e465 --- /dev/null +++ b/apps/touchmenu/ChangeLog @@ -0,0 +1 @@ +0.01: App launched From d03fa628053b4acba96182bd716190846b0aab67 Mon Sep 17 00:00:00 2001 From: kyleplo <31634240+kyleplo@users.noreply.github.com> Date: Mon, 3 Jan 2022 19:58:37 -0500 Subject: [PATCH 142/489] Add files via upload --- apps/touchmenu/touchmenu.png | Bin 0 -> 1355 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/touchmenu/touchmenu.png diff --git a/apps/touchmenu/touchmenu.png b/apps/touchmenu/touchmenu.png new file mode 100644 index 0000000000000000000000000000000000000000..58733cbc758c4597c2da0e508af523288e0a427d GIT binary patch literal 1355 zcmV-R1+@B!P)BE1ZQLxAY_vg;$?V;oX(lt{{G@3qJ`_O^!KmPq;Qw2}Cn0L9?Tam?khm;cmfj@-EE=vY<#k5o0f^m&*sM6pBI0EL{uRZtU4R5Z z`^X8`V)zNfJ8YaF;u6EP09P2E5Ad?jnUOMxUqvh^s*L``+lU9}BlcPZ2XpY-jyyG} zttleQMaed+noc9ry@UIIwng1*#M^^UkFzj+6yF25_LnMhmf?pGpH<}CbcnAmX|u%; z|7E#p3GpKUUAw%6atiT2#A8)^yd3Cssj4^8z$>TJnP(8+gLrkpJj%xIMEtceUz`ec zeo~wa<_{hK;NmJRuzL3+9o0iVC08s$)vACv7|KExH6jmbd4gn8^0FkllzkRT6fd|P0n zrwSVAXrbt(XrcJk;OyVRDf#{Yw^VBW$m{6QFhZvPBk<6w!tZERBfJcLd1$M3&)TehHS09YRtkN(Z(GDi^F2;vKBX;HY+Q*UEnTqUvgh@A9J5aYSek}G;8j! zqp=F+X_rylpF&#LEj%b>g+0Q~5^H*5N-?MwSLAe5T{?GXqX;9WfX;*4pXw6&V*io?m|<6;W0GAb4f<-njQ>$>Q>9MPr@ zwU=n+0I+*9IKpp9{{0u*d8K7@p9VPmCp-6AwmA>rtOL;dXv;Q$XXCx^0IWWyc=l3w zC&Xgk0yx!!!@*Zi8qcdA>-AfBZYACT*nGWS|NH%Vee(m<-vGFv{{#Oecnig2*2@3@ z061k>NoGw=04e|g00;m9hiL!=000010000Q0000000N)_00aO40096105G5f00aO4 z0096105AXm008*^PBs7l0JKR&K~!i3?btC6f;^IyoAU!P|eDqsjiKmY**5J14Mz!!nTE#e{-b Date: Mon, 3 Jan 2022 20:01:59 -0500 Subject: [PATCH 143/489] Update apps.json --- apps.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/apps.json b/apps.json index e5e9f8f02..3fc319361 100644 --- a/apps.json +++ b/apps.json @@ -5062,5 +5062,18 @@ {"name":"ltherm.app.js","url":"app.js"}, {"name":"ltherm.img","url":"icon.js","evaluate":true} ] + }, + { + "id": "touchmenu", + "name": "TouchMenu", + "version": "0.01", + "description": "Redesigned menu that uses the full touchscreen on the Bangle.js 2", + "icon": "touchmenu.png", + "type": "bootloader", + "tags": "tool", + "supports": ["BANGLEJS2"], + "storage": [ + {"name":"touchmenu.boot.js","url":"touchmenu.js"}, + ] } ] From deb46f9aa7fdb2b5efd544309c35a99d7516a531 Mon Sep 17 00:00:00 2001 From: kyleplo <31634240+kyleplo@users.noreply.github.com> Date: Mon, 3 Jan 2022 20:14:00 -0500 Subject: [PATCH 144/489] Create README.md --- apps/touchmenu/README.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 apps/touchmenu/README.md diff --git a/apps/touchmenu/README.md b/apps/touchmenu/README.md new file mode 100644 index 000000000..dfc65a754 --- /dev/null +++ b/apps/touchmenu/README.md @@ -0,0 +1,38 @@ +# TouchMenu + +A redesign of the built-in `E.showMenu()` to take advantage of the full touch screen on the Bangle.js 2. + +## Features + +- All of the features of the built-in `E.showMenu()` +- Icon support for menu items: + ```javascript + menu.items[0].icon = Graphics.createImage(...); + ``` +- Custom accent colors: + ```javascript + E.showMenu({ + "": { + cAB: g.theme.bg2, // Accent background + cAF: g.theme.fg2 // Accent foreground + } + }) + ``` +- Automatic back button detection - name a button `< Back` and it will be given a special position and icon + +## Controls + +- Scroll through the options +- Tap on an option to select it +- Tap on a button again to use it +- Tap on a selected Boolean to toggle it +- Tap on a selected number to change - tap the right side of the screen to decrease, left side to increase +- If detected, tap on the back button in the upper left to go back + +## Requests + +Contact information is on my website: [kyleplo](https://kyleplo.com) + +## Creator + +[kyleplo](https://kyleplo.com) From 6da9121f24ec5655b84c92bb35c83e9f58ca83df Mon Sep 17 00:00:00 2001 From: Joseph Moroney Date: Tue, 4 Jan 2022 13:39:50 +1000 Subject: [PATCH 145/489] v1.00 - Added sonic clock app --- apps.json | 17 +++ apps/sonicclk/Changelog | 1 + apps/sonicclk/README.md | 13 ++ apps/sonicclk/app-icon.js | 1 + apps/sonicclk/app.js | 282 +++++++++++++++++++++++++++++++++++ apps/sonicclk/app.png | Bin 0 -> 372 bytes apps/sonicclk/screenshot.png | Bin 0 -> 6515 bytes 7 files changed, 314 insertions(+) create mode 100644 apps/sonicclk/Changelog create mode 100644 apps/sonicclk/README.md create mode 100644 apps/sonicclk/app-icon.js create mode 100644 apps/sonicclk/app.js create mode 100644 apps/sonicclk/app.png create mode 100644 apps/sonicclk/screenshot.png diff --git a/apps.json b/apps.json index e5e9f8f02..5856486c0 100644 --- a/apps.json +++ b/apps.json @@ -5062,5 +5062,22 @@ {"name":"ltherm.app.js","url":"app.js"}, {"name":"ltherm.img","url":"icon.js","evaluate":true} ] + }, + { + "id": "sonicclk", + "name": "Sonic Clock", + "version": "1.00", + "description": "A classic sonic clock featuring run, stop and wait animations.", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS2"], + "allow_emulator": true, + "readme": "README.md", + "storage": [ + {"name":"sonicclk.app.js","url":"app.js"}, + {"name":"sonicclk.img","url":"app-icon.js","evaluate":true} + ] } ] diff --git a/apps/sonicclk/Changelog b/apps/sonicclk/Changelog new file mode 100644 index 000000000..396b6b3f4 --- /dev/null +++ b/apps/sonicclk/Changelog @@ -0,0 +1 @@ +1.00 Added sonic clock app \ No newline at end of file diff --git a/apps/sonicclk/README.md b/apps/sonicclk/README.md new file mode 100644 index 000000000..a381e0a07 --- /dev/null +++ b/apps/sonicclk/README.md @@ -0,0 +1,13 @@ +# Sonic Clock + +A classic sonic clock featuring run, stop and wait animations. + +![Sonic Clock screenshot](screenshot.png) + +## Usage + +- Sonic will run when the screen is unlocked +- Sonic will stop when the screen is locked +- Sonic will wait when looking at your watch face (when `Bangle.on("twist", fn)` is fired). + +### Made with love by [Joseph](https://github.com/Johoseph) 🤗 diff --git a/apps/sonicclk/app-icon.js b/apps/sonicclk/app-icon.js new file mode 100644 index 000000000..33e22971b --- /dev/null +++ b/apps/sonicclk/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwkBiIA/AE0ZzIACBIgFFC7oTCylEzOIDYeZogX6LwWd7oYCAAOJC82UpoXFAAKnMC6x2CpIVFC/gSCxOYAYP///4C4X/DBIXWIIwWBDAWPAYIXedQJwG/8AgEP//wgAX2CwIADRoQXmSIoXtJAeEoi+C+lEoAcBogX7zOUondolEpvdAAQXgYIgXCAAwXlAAIYC6ENLx4XtAYMZDAvd6gWJC7IKJABgX/C74A/ADY")) diff --git a/apps/sonicclk/app.js b/apps/sonicclk/app.js new file mode 100644 index 000000000..7cd8ef448 --- /dev/null +++ b/apps/sonicclk/app.js @@ -0,0 +1,282 @@ +const vw = g.getWidth(); +const bgWidth = 384; + +const sonic = { + bpp: 4, + transparent: 1, +}; + +const defaultSonic = { + width: 36, + height: 62, + buffer: require("heatshrink").decompress(atob("iIADzIACA4gNECKYOComZxAVDogRXBQfdCQQABCLITCogRFCQIRYLAgAFCQwRQBoQCC///AYYRWGAoMBAAgRYCYf/gEAB4ICBCKrDDCL4UECMA3DolEB4IDBAAQRb7oMB7vdHIIRWCAYRCAAoRWCoozDCBQRRBQI3FERIRPPIbGBPIQiICKAQCdQRZDAYIRXCQIJB/4RDEhQRQGYP//7FEGpARQCAYREgEzERQRNAAIRCLIKkBCLg4CYoIABB5IRWAQQRcBoIODCRYRQB4INECLkRgH/ZAMACRgRSmbGBCIIFBmYWCCLAAC7oCBdgNEAgIRWBQY2B7oTBAwMzCYoRUBIIQBCQQGBHIYRUABwRRA=")), +}; + +const startingBuffers = [ + { + width: 49, + height: 63, + buffer: require("heatshrink").decompress(atob("iIAFzIAEyMRjICBABkZDAogCCxgRBxAACzOUpIzDFxmYC4WJzNEGYgyQzOd6lIDoJiNGQYwB7tEDoQxQI4NN7BPDGJ54BondQAgvPGCjDDGCQVCCAVESAOIx/4GJYuCSIQwBFwX/GJbyEAAmDn///AwJjLyDAAsz/4xBGBAvJGAfwhIwHF5QwDgAwHXwYADGB6+DAAY2EGBYzHGA8P+EAgLyKGBIBBgD3ObwVPGAMEoAwIe4+ZolEGAVEGBRfDAYOUpvd6gaBpvQF5IuBFoOJDANE7vdC4IEBF5h8DGAQABGQNBF5YuCGAgyDYZwxE6lDmcxR5gAFGINEmczF6IxCob1B+YxIF5AxCeoQxJzLNBAAQFBhOUoEDGAIxJjOQC4cJAoIvBgAwCGJIwWiEAgcwglEpOZGwgvCGBANBmcAaIJ2BC4cPC4QwIga3BmEIeoIwBDoJhDF4j5DBgIABgGIGAROBMIYvEilBGAgvDAARIBGQL0FA4IwFF4YABJQIyBoczF4lEGA0JCwWUEoPd7qBCzIwDgAwGF4YXBpvd6iyBzORGAVAgLEEF4YwCF4IwEMYMzGAjECC4YwBF4IwEycxic0GAsN7vRiMZDIQvDBwItBS4IqBGAgQBAgIXCzovCLwItBS4MwgAwCF4XTn/xGIiODF4QwCF40z/4xERwYvCGAQvF7vf+CUEEobvCAAJgEF4Xd/6UEXgTvDAANAMAwwFCwgwESBAwFC4owCF43f/vUoaSCABAvCMAv/aQKSDAA8UF4JgG7/0oIWJGAhgG/9EC5YwCSA5eKFQiQIC5sQF4QwD6hfMGpAvBL5g1IhovVGAQvUGAMEF6owBF6owB")), + }, + { + width: 42, + height: 62, + buffer: require("heatshrink").decompress(atob("iIADzIAEA4QNEAAwUSBwOIAAWZogXECjgWFzPdogECCj5pDondIggUeSAYUjCISRDCQX/CpIUTXQgAEmf/CoIUaCZIUDgAUZRoYADCkIXHCg4BBgAUZX4y+BogUCogUccwgTB7vdCwIEBFA4UTHQYACCgQACogoJCiYAFCoYTHCigTHCoQnICioaJCRwUUHYbhBHpwUTXoQTCmczCpgUTcwYUB/8zAIIUfgDeBCoQUC/4UeRYQPBCoITCHxQUXCYMAgAVBmboKCjCUCAAQPFToIUaMgOIAAIUGBoIUYCoS9DNYIVECYwUWmYVBcIYVBokRBQIUbBoLhB7pjFOYQTGCixpCAwidCCY4UVCoYGFCYIUeBwLaGCZYUVDQ4TRChA")), + }, + { + width: 34, + height: 60, + buffer: require("heatshrink").decompress(atob("iIADzIADBAgOECCALBxAABAYIUDxAQVCQQNBogVFCDAAB7oRFCCwPCogQcNoQQCBoP/CI4QPS4gACmf/CIQQTBwwQEgGIfoQQPfIg1ECC6XFCA4ACCCYRFolECAVECCq5CbobeBAAPdCCgPECAYADoggHCCIRFB4YQQXYwSDOgwQPAAoQDBwMzmYRICB5SCGIYQZB4h0CEBoQKmf/oj/CCQQgHCB4PBAAJ1CxAWBEBAQRmYPBAgJCKCCIyCfoYQXCIKQBB4ndGoIQWiL4BgDaBS4IPBGw4QPBwQSCAgMzCoScECCg4FAAQQVB4IREABAQSAAQtGCCoRDOQYiMCBpxGCCoA==")), + }, + { + width: 44, + height: 62, + buffer: require("heatshrink").decompress(atob("iIAEzIADBAgPFCrIQBxAABAYIZDxAVfC4QSBogaFCsQAB7oWFCsAUCogVmSAQVCCQP/CxgVUYggACmf/CwQVdCYwVEgGIgAVbSoQADCsgYGCowACCroWFolECoVECr7wCAALyB7oXBAYJCJCqgUECoYADokzmYWFCrYWFNoIVceQwXDS4QUBCrYACRwQVDAoIXBCrznCMwRAFAAYpFCqf/mf/CgKZFohQGCrIACS4hFCCQ3dIgIVXIQIUDxAVIBAIVXCYJAFxGITIIVfCwMziOZAIIXEAAIVeAAQFBgBFEDITADCrUAAAoeDCwP/IAX/CrAPBog/CJQoWBHwJsFCrAWBCYpqCCgQNECqwUBCpJrCBooVUIBgABEQwVWokzChRPDCrA/NKIgxJCp4FEAB4VVA")), + }, + { + width: 38, + height: 62, + buffer: require("heatshrink").decompress(atob("iIADzIADBAgOECSgNBxAABAYIWDxASZCgQPBogXFCTgAB7oTFCTQRCogSgPYQSCB4P/CZISRVIgACmf/CYQSXCAwSEgGIgASVdgbvDCToVGCQwACCS4TFolECQVECTLPCe4b4BAAPdCTARECQYADogkJCSYTFCIoSSaIwUDEYwSTAATKCCQa4GCSwRC/8zog3CehASYaIkAmYTGCSYTBCIISEBIITGCSStEZ4YSceo7PBQpASSBAQVFaBISRgChBAIIRCxAkKCSAPBeQI5CK4ITG7oJBCSgRCPoYSFCIISVTwaiEzIREEAISTABH/AAIDBG4YSce4IAB/43MCSQRD7q1CEhwSQRwS1CCTqzDWwgSTA==")), + }, + { + width: 40, + height: 60, + buffer: require("heatshrink").decompress(atob("iIADzIAEA4QNEAAoTRBoOIAAWZogWECbQVFzPdogECCbpkDondIIgTcRIYThCASKDCIX/ChATSWIgAEmf/CgITYCRITDgATXQwYADCb4WHCY4BBgATXWwy1BogTCogTabYgSB7vdCoIDBEwwTSG4YACB4QACogmICaQAFCgYSGCaYSHCgQlHCagZIWIISNCaQ5DmYTB/8zCbq0DogThbYgTDExwTQWIszmazKCagWFbQNEgATcHwpoBomZgAULCaYUFgA8SCZlE7q5DHIITdBQPda4ITDRpQTXMQoUJCbLhCCgUzCgwTWCgIJFMxATVCgQABBYoACCa4IEBQwAICZwA=")), + }, + { + width: 36, + height: 60, + buffer: require("heatshrink").decompress(atob("iIANzIPOCI+ZABWICKwTDxGZogDBAAIRaHAfdCQoRXKQdECLhWCBIQRBAgP/CQwRQB4YAFmf/CQQRUK4YRIgGIgARUdIoReCQgRGAAQRVCQtEogRCogRXBoLqEdYIAB7oRWCAczmYRCAAdEEQ4RNOIR4CCQoQECKJxBogQCCIJcCPYPdCKo1CCIwIBG4QRUSYZ8BGgszUoQRSFIQSBdQbGDQQIVBCKIQCGILJCCAYRBRIKuCCKf/xARIiIRYK4ZYExBYDCKjDBxGICQdEAYQQCCKjcBBQKjFGgayDCKYAGT4gRSCQYRICAgRVCRYRYcIIRdCQSZCG44YFCKArCEiARQAAYTCChwRKA==")), + }, + { + width: 34, + height: 60, + buffer: require("heatshrink").decompress(atob("iIADzIADBAgOECCALBxAABAYIUDxAQVCQQNBogVFCDAAB7oRFCCwPCogQcNoQQCBoP/CI4QPS4gACmf/CIQQTBwwQEgGIfoQQPfIg1ECC6XFCA4ACCCYRFolECAVECCq5C7oADCQLABCCgPBBwkACgogECBwJFCAoPDCCAPFJgJ5BKYJjECCBqBBwf/mYQBAoMzmYRCCCIpCBAIPCA4gQSB4RrBboY6CoggGCCC+DB4YQBOogQRXwYQGU4YQUSYRTEdQgQTWYQzDB4gQVKooABBwYQSRAIQECYgQCHoQQWHQIQDXYLdDCB4RELYQPDCCyOGXYIPKCCAPGCAIgOCBpBLCCKyDBxYQMA==")), + }, + { + width: 36, + height: 60, + buffer: require("heatshrink").decompress(atob("iIANzIPOCI+ZABWICKwTDxGZogDBAAIRaHAfdCQoRXKQdECLhWCBIQRBAgP/CQwRQB4YAFmf/CQQRUK4YRIgGIgARUdIoReCQgRGAAQRVCQtEogRCogRXBoLqEdYIAB7oRWCAczmYRCAAdEEQ4RNOIR4CCQoQECKJxBogQCCIJcCPYwRRGoQRGBAITCCKoACPgI0FUYQSGCJpNDdQbGDQQQRTJooQECIIMBCMMRCKhwDPIMALAoZBCLQADxAABCAQRXogOBUYgUBCLTIDAAQSB/4RYB4oAB/4QDWQYROYowADgDHCCLASGCIYJDCKI2MDQwRQCQgcGQwwRRBAIAGB44RPA==")), + }, + { + width: 34, + height: 60, + buffer: require("heatshrink").decompress(atob("iIADzIADBAgOECCALBxAABAYIUDxAQVCQQNBogVFCDAAB7oRFCCwPCogQcNoQQCBoP/CI4QPS4gACmf/CIQQTBwwQEgGIfoQQPfIg1ECC6XFCA4ACCCYRFolECAVECCq5CbobeBAAPdCCgPDmczCAQADoggGCBkAA4RPBCIoPDCCAPDCAZXCOgoQQJYgQEBwJbBCIQQUBAIxFCCgPDboi7DEA4QPXwYPDCAJ1GCDQJCA4YQPB4hTEdQYQXgCXDB4YQVawQDBxAFBBwYQVAAYQBGAoABCCCqBBAcAAAIQGXYQQPCIcAYApACCCgPFAAX/XoQ5FCCwPBGQIPFCCIREmYOCB44QRTAabHCCAA==")), + }, +]; + +const stoppingBuffers = [ + { + width: 44, + height: 60, + buffer: require("heatshrink").decompress(atob("iIAEzIACA4gOFAAwVTCQVEzOIDIdECsAWC7oWCAAIVkogVFCwIVgNggAECsARCAQX//4VC/4WJCqg8FCgIWCAQIVdM43/gEACYICBCriVBAAQVmIg4VmIQdETAVEogZBogVhzNE7oTB7oACCoYbBCrCbECQgVFIoIVeCwcACg4VbN4xrGCrgCBBwMAC4QNBBwYVeM4IABIYYABBgIUGCqv/iK1CCQOINwdEAwIVDC4QVVmf/G4QNBCooFCCoRRBCqv//4WBCpJsECrb0DC4QVDYYgHBCq8zCohEDNAIGBCrgTBCob4DZAQGCCgYZBCqoICAAqUBdwQUCKYLaCCsACBCwP/IAP/IBQVVCgQECCgRrBmYVfAAhACe4QUOCqzwCCoKCLCrYWDCiIVWeQYVY")), + }, + { + width: 48, + height: 60, + buffer: require("heatshrink").decompress(atob("iIAEzIAFBIYQFAAwXXDAVEzOIxAaCogXlDAPdDAYZBC8wPBC4oYBC8h2FC84VBB4QCB///C4X/DBQXWIIwWBDAQCBC8AWGCQMAgAVBAQIXgOwR4DC9JLGC83/JIuIoimColEDYNEC7wYCHYIACondCoPdAAQXDDoIXYCoT7CC4gAFC4RLBC7IWHDAkACw4XZToY9CJI51EC7ZICAoIJBCAMADIQJCC8IADCAQXDbIJHBDgIWJC7AABCgOIPAdEAwIXDDJIXWCwQXFAoQXCcIIXnOwgXjDIQXDaogHBC8JKDOQIGBC8zaGAwQWDDYIXeDYkADAIPBUoX/IxAXeAQIYB/5GB/5GMC64WCAgQWCOoMzC8YAEIwVEapIXhDANEC4KONC7oYDCyYXYDAIABC7QA==")), + }, +]; + +const waitingBuffers = [ + { + width: 36, + height: 62, + offset: -1, + buffer: require("heatshrink").decompress(atob("iIADzIACA4gNECKYOComZxAVDogRXBQfdCQQABCLITCogRFCQIRYLAgAFCQwRQBoR7C/5aECKwwF/4ABBAQDBCK4TD/8AgH/HQYRUYYYRGzICCCKgUECIoDBCLA3DolEB4IDBAAQRb7oMB7vdHIIRWCAYRCAAoRWCoozDCBQRRBQI3FERIRPPIbGBPIQiICKAQCdQRZDAYIRXCQIJB/4RDEhQRQGYP//7FEGpARQCAYREgEzERQRNAAIRCLIKkBCLg4CYoIABB5IRWAQQRcBoIODCRYRQB4INECLkRgH/ZAMACRgRSmbGBCIIFBmYWCCLAAC7oCBdgNEAgIRWBQY2B7oTBAwMzCYoRUBIIQBCQQGBHIYRUABwRRA")), + }, + { + width: 38, + height: 62, + offset: 1, + buffer: require("heatshrink").decompress(atob("iIADzIACA4gNECSoPComZxAWDogSZBYfdCYQABCTYUCogSFCYISaLogAFCY4SRBwSCC/5fECTAzF/4ABBAQDBCTIUD/8AgH/HoYSWZwYSGzICCCSwVECQoDBCTQ6DolECAIDBAAQSd7oNB7vdHgISYCIYSCAAoSYCwo2DCJYSSBYI6FEhQSQQAbRBQAQkJCSIRCe4ReDAYISZCYIKB/4SDExYSRGwP//7QEHBISRCIYSEgEzEhYSOAAISCLwKtBCTw7CaAIABCBQSXAQQSeBwIPDCZgSRCAIOECT0RgH/aYMACYUzAgQSambRBBoIFBmdEgAAECSwAC7oCBfINECgIABCSwLDHIPdCgIRDEYgSWBYIRBCYSFBQwwSTABKpICR4A=")), + }, +]; + +const bg = { + width: 384, + height: 153, + bpp: 8, + transparent: 254, + buffer: require("heatshrink").decompress(atob("i4ASj0evF4pFIDKYA/AEp//AH5//AH5//AH5//AH5//AH5//AH5//AH5//AH5//AH5//AH5//AH5//AH5//AH5//AH5//AH5//AH5//AH5//AH5//AH5//AH5/bx+PB5vX64RFC54v3P/4v/P/4v/P/4v/P/4v/P/4v7CY5/VHIKxZACYvvP/4v/P/4v/P4/GAAR/BAAJP/P/5P/P/5P/F8sjkYnBO4oAHP64vHGKJfdF7p//P/5//P/4dTP4dIpB//P/5//P/5//F+p/TIIpDXMIohLF95//P/5//P/4APj0eP/5//P/5//P/4vxB4Z/XAH4AfP/4A/P/4A/P/4A/P/4A/P/4A/AB5/JTIaXJWZobFDpovvP/5//P/5//P/5//P/5//P/5//AAIPFCpp/JEpoABIIZHBL7IvvR45//P/5//P/5//P/5//P/5//P/IbTP6IAbJIpLXF+Z//F/5//F/5//F/5//F/5//F/5/tAH5//AH5//AH5//AH5//AH5//AH5//AH5//AH5//AH4AP4wACP4IABI/5//I/5//I/5//I/5//I/5//I/6B7PoNIpBF/P/5F/P/5F/P/5F/P/5F/P/5F/AHMejx//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//P/5//AHfGAAR/BAAJH/P/5H/P/5H/P/5H/P/5H/P/5H/QPZ9BpFIIv5//Iv4Aj6XSP/4A/P/4A/P/4A96XSP/4A/ACcejx//P/5//AEplB6XSAYJ//AH5//AH5//AHJlB6XSAYJ//AH5//AH5//AGPSAARhBA4oABA4ILBA4p//AH5//AH5//AE/SAARhBA4oABA4ILBA4p//AH5//AH5//AE5dB6QACAofX64HFAoZ//AH5//AH5//AFJdB6QACAofX64HFAoZ//AH5//AH5//AFJdB6XS6/XAYIFLCYJ//AH5//AH5//AFJdB6XS6/XAYIFLCYJ//AH5//AH5//AFZfB6XS6/XhgAEA4ILBB4J//AH5//AH5//AFpfB6XS6/XhgAEA4ILBB4J//AH5//AH5//AE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")), +}; + +const topSpeed = 15; +const timeout = 200; +let currentSpeed = 0; +let currentSonic = -1; + +let drawTimeout, drawInterval; +let bgScroll = [0, null]; + +const start = () => { + if (drawTimeout) clearTimeout(drawTimeout); + if (drawInterval) clearInterval(drawInterval); + + drawInterval = setInterval(() => { + draw("start"); + bgScroll[0] += currentSpeed; + if (bgScroll[1]) bgScroll[1] += currentSpeed; + if (currentSpeed < topSpeed) currentSpeed++; + }, timeout); +}; + +const stop = () => { + if (drawTimeout) clearTimeout(drawTimeout); + if (drawInterval) clearInterval(drawInterval); + + drawInterval = setInterval(() => { + if (currentSpeed <= 0) { + clearInterval(drawInterval); + draw("reset"); + } else { + draw("stop"); + bgScroll[0] += currentSpeed; + if (bgScroll[1]) bgScroll[1] += currentSpeed; + currentSpeed--; + } + }, timeout); +}; + +const wait = () => { + currentSonic = -1; + currentSpeed = 0; + if (drawTimeout) clearTimeout(drawTimeout); + if (drawInterval) clearInterval(drawInterval); + Bangle.setLCDPower(1); + + drawInterval = setInterval(() => draw("wait"), timeout); + + setTimeout(() => { + clearInterval(drawInterval); + currentSonic = -1; + draw("reset"); + }, 7500); +}; + +const queueDraw = () => { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function () { + drawTimeout = undefined; + draw("reset"); + }, 60000 - (Date.now() % 60000)); +}; + +const drawSonic = (action) => { + let target; + + if (action === "reset" || currentSonic === -1) { + target = defaultSonic; + } else if (action === "start") { + target = startingBuffers[currentSonic]; + } else if (action === "stop") { + if (currentSonic > 1) currentSonic = 0; + target = stoppingBuffers[currentSonic]; + } else { + target = waitingBuffers[currentSonic]; + } + + sonic.width = target.width; + sonic.height = target.height; + sonic.buffer = target.buffer; + sonic.offset = target.offset; + + g.drawImage( + sonic, + vw / 2 - 30 + (50 - sonic.width) + (sonic.offset || 0), + 86 + (65 - sonic.height) + ); + + if (action === "start") { + if (currentSonic === startingBuffers.length - 1) { + currentSonic = 6; + } else { + currentSonic++; + } + } else if (action === "stop") { + if (currentSpeed <= 2) { + currentSonic = -1; + } else if (currentSpeed <= 14) { + currentSonic = 1; + } else { + currentSonic = 0; + } + } else { + if (currentSonic === waitingBuffers.length - 1) { + currentSonic = 0; + } else { + currentSonic++; + } + } +}; + +const drawTime = () => { + const x = vw / 2; + const y = 24 + 25; + + const date = new Date(); + const timeStr = require("locale").time(date, 1); + const dateStr = require("locale").date(date).toUpperCase(); + + g.setColor("#000"); + g.setFontAlign(0, 0).setFont("6x8", 5); + g.drawString(timeStr, x + 3, y + 2); + + g.setFont("6x8", 1.5); + g.drawString(dateStr, x + 1, y + 29); + + g.setColor("#fff"); + g.setFontAlign(0, 0).setFont("6x8", 5); + g.drawString(timeStr, x, y); + + g.setFont("6x8", 1.5); + g.drawString(dateStr, x, y + 28); +}; + +const draw = (action) => { + if (bgWidth - bgScroll[0] < 0) { + bgScroll[0] = bgScroll[1]; + bgScroll[1] = null; + } + + g.drawImage(bg, -bgScroll[0], 24); + + if (bgWidth - bgScroll[0] < vw) { + bgScroll[1] = bgScroll[0] - bgWidth; + g.drawImage(bg, -bgScroll[1], 24); + } + + drawSonic(action); + drawTime(); + if (action === "reset") queueDraw(); +}; + +g.setTheme({ bg: "#0099ff", fg: "#fff", dark: true }).clear(); + +Bangle.on("lock", (locked) => { + if (locked) { + stop(); + } else { + start(); + } +}); + +Bangle.on("twist", () => wait()); + +Bangle.setOptions({ + lockTimeout: 10000, + backlightTimeout: 12000, +}); + +Bangle.setUI("clock"); + +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +draw("reset"); + +if (Bangle.isLocked()) { + stop(); +} else { + start(); +} diff --git a/apps/sonicclk/app.png b/apps/sonicclk/app.png new file mode 100644 index 0000000000000000000000000000000000000000..db359d1e58f497a51b621957bf476af89b6c846f GIT binary patch literal 372 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 Z;6HQd1dbxxA@~3Q002ovPDHLkV1fs|jBNk_ literal 0 HcmV?d00001 From cb85dc0c8e4f20b58175dd8db8f77b026c41b1c5 Mon Sep 17 00:00:00 2001 From: Jeroen Peters Date: Tue, 4 Jan 2022 15:32:48 +0100 Subject: [PATCH 146/489] Messages app: bring back icons in code, not on top --- apps/messages/widget.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/messages/widget.js b/apps/messages/widget.js index 05622b162..f2852f2ce 100644 --- a/apps/messages/widget.js +++ b/apps/messages/widget.js @@ -1,10 +1,10 @@ -WIDGETS["messages"]={area:"tl", width:0, ICONS:[atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+DAADDAADDAADDwAPD8A/DOBzDDn/DA//DAHvDAPvjAPvjAPvjAPvh///gf/vAAD+AAB8AAAAA=="),atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+D///D///A//8CP/xDj/HD48DD+B8D/D+D/3vD/vvj/vvj/vvj/vvh/v/gfnvAAD+AAB8AAAAA==")], //icons should be equal size or first larger +WIDGETS["messages"]={area:"tl", width:0, iconwidth:23, draw:function() { Bangle.removeListener('touch', this.touch); if (!this.width) return; var c = (Date.now()-this.t)/1000; - g.reset().clearRect(this.x, this.y, this.x+this.width, this.y+this.ICONS[0].charCodeAt(1)); - g.drawImage(this.ICONS[c&1], this.x, this.y); + g.reset().clearRect(this.x, this.y, this.x+this.width, this.y+this.iconwidth); + g.drawImage((c&1) ? atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+DAADDAADDAADDwAPD8A/DOBzDDn/DA//DAHvDAPvjAPvjAPvjAPvh///gf/vAAD+AAB8AAAAA==") : atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+D///D///A//8CP/xDj/HD48DD+B8D/D+D/3vD/vvj/vvj/vvj/vvh/v/gfnvAAD+AAB8AAAAA=="), this.x, this.y); //if (c<60) Bangle.setLCDPower(1); // keep LCD on for 1 minute let settings = require('Storage').readJSON("messages.settings.json", true) || {}; if (settings.repeat===undefined) settings.repeat = 4; @@ -18,7 +18,7 @@ draw:function() { WIDGETS["messages"].t=Date.now(); // first time WIDGETS["messages"].l=Date.now()-10000; // last buzz if (quiet) WIDGETS["messages"].t -= 500000; // if quiet, set last time in the past so there is no buzzing - WIDGETS["messages"].width=this.ICONS[0].charCodeAt(0); + WIDGETS["messages"].width=this.iconwidth; Bangle.drawWidgets(); Bangle.setLCDPower(1);// turns screen on },hide:function() { @@ -37,7 +37,7 @@ draw:function() { b(); },touch:function(b,c) { var w=WIDGETS["messages"]; - if (!w||!w.width||c.xw.x+w.width||c.yw.y+w.ICONS[0].charCodeAt(1)) return; + if (!w||!w.width||c.xw.x+w.width||c.yw.y+w.iconwidth) return; load("messages.app.js"); }}; /* We might have returned here if we were in the Messages app for a From 704ef337610a1ea142ec798bc9fef3713061df2f Mon Sep 17 00:00:00 2001 From: Joseph Moroney Date: Wed, 5 Jan 2022 01:01:49 +1000 Subject: [PATCH 147/489] patch - text alignment + twist acceleration --- apps.json | 2 +- apps/sonicclk/Changelog | 3 ++- apps/sonicclk/app.js | 8 +++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/apps.json b/apps.json index 5856486c0..3807b8663 100644 --- a/apps.json +++ b/apps.json @@ -5066,7 +5066,7 @@ { "id": "sonicclk", "name": "Sonic Clock", - "version": "1.00", + "version": "1.01", "description": "A classic sonic clock featuring run, stop and wait animations.", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}], diff --git a/apps/sonicclk/Changelog b/apps/sonicclk/Changelog index 396b6b3f4..7c83f6988 100644 --- a/apps/sonicclk/Changelog +++ b/apps/sonicclk/Changelog @@ -1 +1,2 @@ -1.00 Added sonic clock app \ No newline at end of file +1.00 Added sonic clock app +1.01 Fixed text alignment issue; Increased acceleration required to activate twist; \ No newline at end of file diff --git a/apps/sonicclk/app.js b/apps/sonicclk/app.js index 7cd8ef448..296677281 100644 --- a/apps/sonicclk/app.js +++ b/apps/sonicclk/app.js @@ -106,11 +106,12 @@ const timeout = 200; let currentSpeed = 0; let currentSonic = -1; -let drawTimeout, drawInterval; +let drawTimeout, drawInterval, waitTimeout; let bgScroll = [0, null]; const start = () => { if (drawTimeout) clearTimeout(drawTimeout); + if (waitTimeout) clearTimeout(waitTimeout); if (drawInterval) clearInterval(drawInterval); drawInterval = setInterval(() => { @@ -147,7 +148,7 @@ const wait = () => { drawInterval = setInterval(() => draw("wait"), timeout); - setTimeout(() => { + waitTimeout = setTimeout(() => { clearInterval(drawInterval); currentSonic = -1; draw("reset"); @@ -215,7 +216,7 @@ const drawTime = () => { const y = 24 + 25; const date = new Date(); - const timeStr = require("locale").time(date, 1); + const timeStr = require("locale").time(date, 1).trim(); const dateStr = require("locale").date(date).toUpperCase(); g.setColor("#000"); @@ -266,6 +267,7 @@ Bangle.on("twist", () => wait()); Bangle.setOptions({ lockTimeout: 10000, backlightTimeout: 12000, + twistThreshold: 1600, }); Bangle.setUI("clock"); From 2472a2bc7742321791ce4b8806af7504854a81f7 Mon Sep 17 00:00:00 2001 From: kyleplo <31634240+kyleplo@users.noreply.github.com> Date: Tue, 4 Jan 2022 10:39:51 -0500 Subject: [PATCH 148/489] Add files via upload --- apps/touchmenu/touchmenu.gif | Bin 0 -> 616646 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/touchmenu/touchmenu.gif diff --git a/apps/touchmenu/touchmenu.gif b/apps/touchmenu/touchmenu.gif new file mode 100644 index 0000000000000000000000000000000000000000..3df4b3462cf54e9db570567e5a83bd4c7e6b47a4 GIT binary patch literal 616646 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

>zrIgHZNgQ8j)Jb?ofjC;Wkf`VH!isY6 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�!%kWK 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"pgxuI+m&p)2(&i24nFU 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
dT(*nsu9!Bw=H#b=#cwl6qSaz>8ykQ|S zsq>vbJc`U&*Crct=f-FG zO9&2l@bih3?Vvs*;A_-lwMaa|YDf@+K7?_OK=!Z)F?)p8j)L`<*o^OfjQUG__VS&d ztY`YrM9~j{wX6jam4$dj-<$}>kNlnOi$CPrN_+B77+#ZbkNVuMuJyI|gLP5*`AJU;H8+=oyxS9x|TSkU|x@GfO&#a-1?HJrorx&;!VW98D~$ z81*T7l|16rW3XpXT?zC*oc56YoQT|UDdmVHKmp7o9v6{E9>T`dQW)Nl=KIvg7f^Tl0dZ554tEI0iCt`E)!r%O1BVU zt`f$b!?PSe(H{3mLB-Jj@pyqK|MI?cKAA*wea#Q(7_&zO@`ogzV>mwZS|3m`%%P9z z%c)Gv6402VWPR{ED*H_bf4H;H@@K*CI7!3RLp+0@tQE-sfD>qgw2*^2n1j!mOg^B) z6>*QxfsXsWC!{bhZp6JM}U+rF~mGPgz~r(91({A@XrHy#l}DYm(W82 zaLin^P-kVww8_j#NC;Kj&JS&o^5Ba@Am&p+rxI>?O#n*Yo{+#FfhL-V8yaa`a7 zAfY|jgVDfF2}%S$;6p#iR)@@mLy%W?K+umk;R6ui?VwN-$`%Dk zz_CHoNwkCw0)V|>k^#c+rVd!`S5)#K63QQ78P$HsFIz)#F#sod+%OOId zoD9Vx_Jd5^j@UdRAezu4M&J)E;seaX7Vh6yO$~A^qCVWiJ&;2H$^-$D%mW|ZKiC69tRMgoz!oY`^c)cEte`|$ z<9VUa41$t3b_f7SfY#ic+1(Dn%-kSyPhW6}I|Whq#Q%ez3?mb2*}?FG>=e-y5~H8o zPNB7g3zpD7bm2XK;VvD_0=W|mLK6fHj9L}iYk(qBFv~DP5i?$+im)R+q+>~#1s)C! zGuB{d{h>dE9l9{zJ3`St+@mJK7E4ygFk zMj}j_qCA)jOR6F(CK)0n2MP=lRfN?;fWtokm{zg~Q?!H=SO_=BfD8}%dpnTsL~l0d*f3J}LAom4vb+ylIUCWwPL+yD-o)R=UWT}GQ(Al6KIz#Jf% zFG++zQBs;cz&e0K4&*=|xk(C$z+F8AIMtFwDE|^3kiv;n=4F~gX4aBGEEp-|oeb{kj(`?p94QNDVeL!Q@2MsV&z~sOn5r;<93=PQUXy!mV z$rXyljyz1(aT!)w$;2oz(>kmJ4_Ib1RVNG>r#z_ULmZQh{R2fUiadzaTBgwqgl1kI z6L->sh@oY5PNhXf1d1(6JkS6O*jPNAfCtzCDx~Fa?&f&*<|y5PWP-zb{s>*ZXFTxc zfjQJKh1d)Xl1xnKgM}D!GAIo==sJkQA<3qMrT`#(sD(lohMG%+wr2`Z=rL84cGAFF zx=D=E z)MarP7(I*<8a%{b-hg1z19O>0b3T$;n7|Ae=I+c?d>Y+D5Em-chd|+H3QQ+wZq<3} z03~_EUr}eCLe@&nz#hnH$N3RG+yI%@shQ@4MZqa!!6;#DQa(BAED?t^IVo`j7Ze@G zfL$pIoRmlCKn}n`j}hjNSm!*EfRoC^W0gX8o+wV`=aj{q6Zm~ zfG<%+l?JN`fU8W5t3|127-cIBZ2zk`c&iC4=8tSCiJgJ=emaLmWHY&$t!Qk zL$3-fm-Z;MP{etd!5x5`xu9wyoI=sS&MvJLek6i(cmzdE#Xm@fl=y=i_`zggL>{yO zR#ejiSi%F`4j>!{U*tn_WCAce1aKAuJOsyH+-yErh2X^$9$W@L{A_VFTqD^@+B}4x z5l3LCh-Ux;5n4qjq@O%EtkM7{{WM%Khzl#(#8DK+-<^eXXber*gt%w~*!Dvo$blsg zgT`pY#YN4^DTmCUYH5JQMUbq?3Ijjb!(U*<^R#W0NlT18fE(n}%jQGi;)y=M0US8O zsnEk6tN~vz#sgfOidcnBJpT_PxhzJAEMuUY*CLiyP{d{YQRP0ZKj?+cPAys-1tVDm z21$m_wr(BRY|%EZ><(?O+y%!Wt{;Hg!>KGW$nFEsu0H_p$hs~t>@FU3!twS4>h=oN z0tdu`+p8Hb^17@?h%WBxF5_+lF?g=;%0%Td?C6jJ@*&5fpi3xFN9?ek&Cwvmpi3{b z2LVCJe%uJFh{~`K13bXPsO$&)fZ}=ZLxq@0Kd8c>kR7dH(EDD5FTJl0D%$hfgMd_t z1ly88z@NbQlBy`je&j>!?Jckfg*2`(`iV=jd~m1W1fLL3nTSiX)CK=a$%QP600U5& z5QpSF0F4CkLlBRCT>oKz2;Pr4u;rOc1kta;sEI5RvP2m2fY`{DB(jPuvOO4`djL!yv$6U@%ez1e zQiKjRM8o0W;>|gbz0iX^^aDA313COdiTV%y97*W>2*9|>6}pK)Ag~7Z%iJ8~J0z{| zP(`tn%uvYAkNoYscmx!C;zwSZeVNe9+JjzBVbci2k+e&@{OtlpVC9?%+$iBgbYb0G zi#tTbk$42lj{iwN+|Fc%&Y8T%J4@L!#$ot`jyqqAN1UQO{B3ulixTck+t|x9=R-8l zP{lCIH-qy)^P@TZ58dQX*iE26O>_fp4im))w)ecObv%$ii1v_#GU(z`;N6dL~WA`JX`g%jKIB} zM>_oj5O~0$a7jGKQ3V{zAQ*=Rn8iJuzzaB4T$kJwOYzKs=RHPP`0y z8vjxlu>w+TxLHVP*Ps}PS0-*fzz6`jAL)ZgwbuhkQfT_svz>tG)R8FZKp&vO^Gxd* z{gFs@*FUi7O%dTtVc1bXcpq$%A~BO=?JBy`fE+lFJV3Y*=M+h0d8J~C z)iT*q8HJ`y(A4t)ri2%#Epbz561t&7xT3QcTRwmskiw&HXem6;13>2{%@R;OfTfcH zrn5qvzrdW|d7wXpquXb^J`bXw`B01$PFOmBKST@s_i=PnGELaD$YW52LSUZ<>KKQJA*PSdI*~!xhg}3bB&@eL=0k{khv{in&^jrk z&5sX~hUw>Pj26xMKv*HUJG{ULsC#jcJ4B4qr!U|hG1kS`5&`WyD?~?F=>d|n!yb(} zT(SVc`l*DO{DGRo9+j1wiEf4J9n}$iP*^jW1EV&YJ7DR% zHaaR8J<`*BqGxE+ziVsCfsjePj_PJ^fmYU|K+*eyKy`i1qr#bBea7p2)XxB_x{1>F zysC#Pt;eC;i#RJLXK`GDS-=`5klmg?!f=}fF8o6_yaWO4f?32uHbj0IwEsdcoCvSs z#=&ixN5I--ctlEoEFGX0aIC=^SVYI^gjvvp;Xj<~69?;?#bmTTahyJGw0^C97?c%9 z?LWjqbVeOq0&uhe9oTH^0|lR<)}47AqwxV>NCfO>2x?6~sClvPC;mf}zFF{^pP6m) z2C?*Z+|efQ;g4O%Y1`}91aQom(y&_WgBn&WKX9DB_9q1Q6NdD+KR{Fp_TXQhJeY_* zctD3vrGyXg;BlyMp+JQOF;T2j=Rv}Mbn;{ZrZ7z!ix2GB$w-k-M};jN3A@;kB1U5W zKGM1L@IlCt4@#bV^Cpw9eEt|#qNp(D%##=u_S>lR<-vhKOg;KiWB?s!Sm^% z&6h17wtVn&X0QAh{gLC z3YEvnrAA8DM2c82oS{lRD0c7PW@0!0g%&0(-UGTzL&IGPSs~@6plMTFt&kL|V8tk+ zl1=gSzXzo-18WVsvvJ&!+xF|%TjBD`a_a_n`Jnf2g_|E-bxb?o1K|%tpKg6Td|RHO zufBdr*?aBkZ;`7f?%8$v^$Ks|F1%uv>nK3bep^pC{z!4FvH*`uP@x4s!wfpp9&$`V z^TIPuq1`4duD=A0yUs%kTf^|X#~y&EJQEcv1w`{a8nGC6T>pa+K>{DZ(75rSqme)M z9_WWVRgO94#0?i5&dDdCT%bY5arO1~DcK<2ooi70pGoEg);ijHMJ!Lmq zZOMHVPkQv^bKGS^Mb=bcPc`)2fFCGUp;c48c3F9UT`E&?u?@D-kE8u|Q(&J=_2gsS z+BG_JW1Y2De%vzIQGa~)^iXm^wo_bCjYc_HpjT!(-km3o6J2YGCfUAgYUSnq7mW==kKp1-?axHYDH?AMlO(U1J&#$VUCLVGSoLqyqOL z2NJQEMJ;ZTi(T~M7r_`tF^-XpWqeCK$Z@_0XhSyGctClU(v2&ck&bn=;~nvsM?LP5 zk9Yir`Tp3BcC>{Xl5rK82H8hNE|QUrbpPZdAsI=Ew5A<%q@+R)w-j3_#2RFhPrIl%M<$MG`4RfiI`RV;sMV-y0eV*1g1PE8P8MVlb!t(A5H}0PghPLoAvxhKdjaibbt=pr#{QIUd?aD-dWG+~*rixTjlf^q3c_XSY`%JZW+nSc?X zSwpGzv|SXfYaeMuKFap4(c&jXmqNJLqPCl?h0e}EYbhwOEtQ{K)m*eistKu{5 zZh5;+-#&@89o3?BJ=(?Pk`lZ7BAj1+8dB%xwzWsxF2Xi?-srxvFF0w(1io8Y`0@** z?v#xG;^9-@E_AGj1!sOQI{#hoVlEyk?QUBHyxN-*fu)2t)|(WFp8bz(AK6=t$q;JIQ1_p6I( z#jue-30i5klBfBM=XY5Q<|~WXgQf%UL+8vz6_Hq^#cGRgB z8O?dLGQuv(=Sb?-vI@nrQn#33C4bqtRVJ^LXWZygKKjv-R2YRzjoX~1+R%$+^^QNC zX;F_FbCRBPc_T_?O85B7uKqF z^{|PI>s}*!l*}IUv5g9DEf+YvW%Ty8!+CCQGgI9JQTJ`3%;G=e(XlBeW4o>0O?3qkKV{zrb1-Z!6Jw6OWH{dL9%c&X8Trz6>l`V(4C`nGlR*%-?1ea#c z_2qLX@w}8u|M@4KenzB=QJ#NQ>C~ST^-xp%>D$zLZm}N5*6jI=5#RaCyROZzvpJN@ ztgpGx9`m$EbN}s9;&AB(F2=e?nCo+YX3&SD+oX%J(gEI!wzar-D$CvP&IG({1aBzC z4?fO%k9*%6&u*EA__cdaZl5!ZcqC5#u8hyTFdskT&WBOM@+NXXTYp5-Go6&AKRqb* z2jFs}iK@4ysD2L*QA7TCr}k|)5o=CBF*Vgg*_@X@oBJf+i~jbbZ1G)39O0G!%mY^#{a6r{XQ&bxbML{gws%6v>aUI#Q9o_LA;V~ZNaUSWh z9_{fS@i8CuaUc1yAN}zk0Wu&3av%w^APw>$5i%haav>SAAszA|Au=K*av~|RA}#VF zF)|}Haw9piBR%pXK{6yoawJKzBu(-pQ8Fb}awS=^C0+6*VKOFVawciACT;R2aWW@$ zawmDRCw=lKfiftCawv(iD2?(ckuoWjaw(azDV_2up)x9^aw@5^Dy{M=u`(;Qax1yA zE4}h7!7?nxaxBTREY0#P(K0R7axK}iE!}di)a(%FZ=T@ri{f&OmJxIEa$oM!?*ER_ zu=cX;0&x(@sW71l-V%{8VN5aCO#0H!(wHprVriiMGN_8{vo15c0&~SGbNpN|_8Jc~ zjV%-T=*1k3G*=5XsY^9wuGnmF$KFpA7wV)sQ=@k8pHL96YV)Qt&InTx|K7^4;0!MA z%h~434a1NWacnomsI2}85MPfqnTa`*3gtjBtca+_#7_VP&xZO^NdNM zISuZo>MEcxEX5A`$qu_|jp8E1X-0!}O3O(O4+3*UC z;7i=H$v_X(kpwF+7j&kG^FezH%+PZ}$EQIpl$(I;#zfPoDzpp1ZL{i9FaJ*zw#XBf zimhf!E7n}A+*Hh_q-;g?sziYkw(!VC&&m;T&=F~nH_&5>LzFKw z^P8TOk6x3cBoo1sQwo#sxmYjHj;={_lSkufNtKH=n>5og!5 z>0V7uPp`fH;l1LkUp6gD-i{FQ3;6VKF9NPOMJ&9yFxbcq(n|3~vuvy!EH^uG%Baom zzUZUMkPS;`Pq*&M2=o&>EXhVN{^E=~v#dJe?Z*a{2wg1fV(d!S^yIcILkTL!=5tdM zrBi_|NwU><0f(ra;aAu#Hbmt}?^3%l{~K;&?Mlb=3=1 z(a-u5`N%I=jqE$8)l>ly#fGy~Q_-i!E~@5@LM64c@~}sxujT49Ma}g$bM?@;2*6Se z3GbrGOb|@NRI}ix7DXvYVe`^VN7kh9*rfAbv6a{=70>+e2T84$rcl93Z%bEgd>S@A zuM0-COJe<$VrvZ(Q?#vWYuZAwKmD_jRP#+k7Ks`ZU>WOfmW@Rjvz06`+Nw%r9d=PY zR!W<-N)`5qX0{6rFk`i74C&3C+Revi5AA^NI`{Bt-)#_2)l_xy&=3%QN)2i+Pv2^f zYLV75m3Bm%&g3i%Y{#f$9cgRDrwlJ~;mDAW1`Y$GtYq6(YX3t?ZY?qO%Fb;?cJa%@9qSZKb^38n>BWUw_Qy)ZaI(gzzDipH$^E| zbj7yYnl}M8cg$Ark!DmbZPs_yZhYTWeor?J>$g&g_UMRpfUgyO-B*0!H+cQme04B@ zt1Q9(1NKC-eU*1~nU{f4G51yx%ie3rqVTHLSNKLHVgCrq_}*f|@OE==tmw>7=;)Q* z(rWsM_ZP2ERDW||ktheFglWM~|3uWqX4U!9w_eYTsc5&1D$&5O5YoIA8gr0Nd+q)j za|406`9p4+`%dLWSsm*o-qRS}9&PIpO3M>+{o)4eUxl3r=Dv+A_%q?ecZ!s><5NrE z{8+E=qrv%h{bI6>`a{%fI_5pMV>%qY7lk=ue^9I9kt4;u_8n^`Y;VnIzlsM% zYDZ%4%Rak5-B2ZudUjXuLD)~hd(YBV&%BI`eb}$@_UD&}_dg4>>7%$jV&?Zsq+D6P zf&T*>Q~;n^9|Zsa#so-VyS~o@6{FYg$~E)M{T!ao}dGY-I`ZjoMzj;{bx7b_g zx1pVP#|wQLuS~zT|M%lcW?g~mc?O8Sh|u~o@^ zH8_F)>Cnc{XnqmETr-KGpBC$ezVEPJScs6Xbb8NY%y_#8OgT1E3A{EynND_U%NSIi zTowJA0FcvO8>f7&4_`lO=l>~iujX#`u^UTcSH$0jEJog*;+9MI2+%SxBlO%B`xs(< zx0s{$A22I(RT97i<_mlHEDwDH3DFeeEndfO;~E$39%6xezQQqRlNP>^+?~x{aO8qI z@0qfI{5u-UQ|VH^|E%e#fKk}6tq#~_q~G|E+DZx18ibJe$5QKppx4s9N zQYv~49Votz227TcLt{1mN8V*NdyKJ^xIh@0f( z2&W+H|HmnfE^Ok25%35gJ3^s_TW>m+dRlY84NNa(24BLnfdM7vTBBG}#>rm4l4dYD z(l-|u)s@%f-6-PXs#$+fz|HpBlx~Y{SUB0M^;UipptpAamdIJqVe2jBFKzP{05>0? z!^tksR*L)s?7FRiTNvzV&;~<@Tcv(t6K?zgM<8kaB^KBRKITom)tc}@yH^$T_qDAa zL!o&BlGe6$F;F?{fMhIj!JlFi(bxjc1xYpS#4*UB9t@ZHYg@|a(%o#rqh zf}+(8H@n9MVnb&al+U^5g*Zs>;6@as{q3}w0xm$IUrDLzaZPY&71A8^q-p*r7%Tt!V=6$Fy3sk< zeeG0Z9&IlSB>gcC2l&6=MFoKJf4+-MLyWqt_zWPynmIh~9 z_z%@|gkiaOTv1qcnRQk%%L6$LHuf00JTw>>@p{QTy#g=DWw|Ey+zWBz`adD1Li>Bn ze3>R_&OPlL%q~O5?#rq7wBz%~DC56pbV4Tf+OIi<{4{v#TkUZmj9@3@N*n#Zw%B;p z-Q?@W20V$rd{*EZ{!{r04 zk`b^^;j4C~B?kZ?^J^9d+mojo=2wGh?iU{KG^cPN>J9g_o6cdcZ;H<62){a~6FiXb zFrr+2uPu6Zd&k}e6zUm#mdL?`tjGC;%OU2fCXYyvOv7)jxoYQ)V&hyW|H@;NIS7kZ zE%mazv50!@JWT{l)>-n>s1P}!^4M^{`73VRH25pv<~QR%>%NZugK})e<`9;>6yJ0e zxX*2oE=x7j+VSmAAJ=Vlw-B|PPcZ3 z5D*ebfAGq2cXJ2*Ybz$aXn|Ca-KA>C*2NMe97cyYgQ_4}A`UzDmxB%q#I2@0TgfbA zIYkEej-?2Re`ewk~)~_S6O@b;RwpmP4&>+2~Xsjh10pZ8tEOlO& zD3aKw7&Tlf_3_f}($xf-eIx&2M45TeR2YXpYw<%gHZ?wCjZ*-7C(B@LBq>|qJUZB3 z+ouqinS>bFCgJX431^f)y>ag{-k70c&`E>w)uJChCQmVl>yJYS! z({N@xPe{6RSz*MN6ova;wb{Z_plYi=e1|HmCi=jBOWWr2?L>(+#a|o8_2w9hdso9eh1% z^W>miL@#(u)7Q>;nt;IpfL-~yu8R}2rp=^IjXv-ff^V6Q*H@z;Ep8NVeD-g#O~stbT@QpLj)rF04(Q3Cd4 zM87cD_4bBtM{l?3Ui+VK<5S%9T0n_ox9QA^RNl&qsF4nr`4fk62L3Iy^=@`qO zHhVtx(-J}N(0nuq53rl}Gt+e7y_oNB*Vq+#0{Q0A&3v2tW$*zaIRD8ev%!{g)mo*}R?0M$s#k#Fm(t@hDy2wCkBL`}ysokjiGt z=4l?bEW=8H2f7=i!ulw^_$KGB{C;o(0^aBS)Ts{~fe5K6`?UEDtXp=_T;^@%jTKd1 zs5qG(VJYsiF-eK98kFKhU2`(r(-9PWAI14iE}l9Elyq4q8WlC1f^sKr(o?mvk|4#< zjd;GVjTduU5;hobn#-!Bqz$R0>%S}&klxo07z>}|?4;g5N)fbKdb5+*4ZRk~KCidm z{2AJ^IXLwd5$Sa|*6b!|I``aDr}w+jTjn;>eqUNr%4vT}+^T#wD*9BF*G&Q+JS#1T zhW;}#j$1~*Jew|I@GfL>|B(5wWA!X+Zk|3&yN$S@KZ=+&`E7Ns@%q0{l>Ht@&j(Gb z+YDO2&U|PA#bBe&%prEQtX$I2R8j7He9Yp-b3sBgPo(Xm-4^pqc^~7_qgJ+&X2MnL z1-;r`XppVp4#wQ|%!$9yR8}VYwbp$Z}H5AY>UF>!`BGvT>^E zJyAt=%{|*bm}04LRPFXTPV?^`?Yhwt*irIwD5%GHt>iEL?qcC!yKM7;Su@`xW0+fK zo?+6Z&^++t!u^f(4jBcGFAQgM5{}Mv`00Gn_2mTs1gao9pQ1Dz z^bQvGNtga)JaM{ycJ=P}qM>8Z3F8-st%V7#>VNI4$7Ieb=^P47*z1w1%S6+5>?cLu zie6ga=fG0TtrVGWeCG=OV9|*X5Uff$TXm8j@zE{wIIo3JbCs;)Lqm+<2e%WZ`ii+5jnRYlJ8yJph=5uigbTl|X0TO!Qk}_mR z4)8kQb@yl2S)G6Z={FZ*#ebe3O!5D0)gfN9o&AdQ=}C|1*I}Q_C0-&vF-jEUF#JR`bTo>(^qd{+6O(~kTK;uV%o+x92zr!X-ck)fOQ9b?O$*PaWfp2o-rHlQ!MKj0p6mJyL#Kwv2_2?>T#^8X|bf}Qtq_;eCy)yKUOV??JM*aT5Ph;Y8I&VWF zC4ez6>EQd&lq$%5Fg-6Rv;j5l_^x~nW`XNbw0l)o(2hQ8mD0nQpa~{Y1*OjcT}dS2 zVkaO}D9Qei!KPf9_rft%S|IfuZzQ|SV{}I+3l#;Hwk^aKKFx;zp|U}!{)y|1B(C!@ zIGHpc<%DM`S2;u0Hs1_{wd0~{tou0*tfv8wXyWW;1;&%7VKI5WY(H%*u+KLDs-fP3 ztpOcEjZ_#Bc8oi)9%5@5S@8`bs8c~m>HgJ zGNQx8l;d$5TuFNvl#o7;ZAZ9+VgB9Itq@2F(Dg-~wr`)3uSyD`(w=Ra~X^YoJFkWB1A0&ic`&Z{F4$ zU-fq?%dvIkb5+heXMx@Q0vA2!t8%nV40q*D#kS0$b==C$q9iatw|M<4c|y;pe+B2xi;!rG;I}FF>aR@M#Z>v`ZG4W2Wym!OQl68JeOXFV z+~Sx>z75_f_dWQ{I;VP%FJJ?BXKE*t;|}8vaf_@5OXp|sIQPApghM%8kyEVd+pq=f z#iqulhMMZ3;{aww&K>cFmg*MSJ-l1}p-(!U+&Dr#sm7T!VPJx`*awWYj~P0N&}0{xl1mB-b1qa|`oo zCz&(kEsoZ2`vP8J>w}>gwYeq2ul!gvZN!e{8AM0DELboXJlL~TFPBhVt{oYCO zE_h^k^k4ezUA<X<59WB%3sFCbk@sI9mkvZ!2ROc{wbrE8w@)G zEr||HDvf_~cK(wKsM)O0a(80O(YocWbifZ=QqiHkwRK!4`*7HZ8QDJUF z{|(=MYONthe;9(GH-tOf3kAogD-omsUb@ae0KY)EBdcO}>eb(*580~GBh7fYwXnpW zaC!L1IQNw!4d?5AZL;0qoiio&TIr#KoT^QJ)$IXCAgq&UAY33aCJ@q9&%v%;}p3 zOmo?8<%zQS)NaDSR>K{v8PP+qqh7BC?Yr^t$ZIZ@?tyt*;0`ab*LcFO zCPHuZjjPz*^XDJLULGF7lGWZt(sKBIi4F;B8$_J?YFw3Y!B2abzM8E*U=HrZJb41z zfSlO-x~H>z|CGDVB%z@9J)S}tP?9n;l-8^BWAW6OPVX7n8``llSK$BE zIcTDG>$u&P_}gw~yViPM=R=}MFbNSgUSW^@P)g~@qe*O@um!UA1EAF8#4a&*9qlKS z0618bo_(Huez0+jn?aKGOw*c6qH?vo-4AgH)!^~c*1Ajc zq3q{AyLlU^pPL)}H>P4If^SwBDos`-48OvB4D@-EGm{)f);#q1tLCQY(@y`qII(t5 zJ7{w%@Y*`%t4=rq(ccIT_^Rg=I0s@YE&4uJ?$Eo_(%MLv-w?gtOl zEI5rS4*vR@_|kF`XB*qQW*sC+?R#a;zl7F0sD^5RRaDyNbH)NiVCMYFUy~+ry_tYV z0ip=Sm?OC>!77;D;D}9mB$JT8s_-_%Fl|C{G2h`Hw0YrEjRy1?_BvvTtiRhYaUWX@ z8AC|LxS96YTw`5pTmw~a*$ba-o96*Q$hUh9=R;l7B%g?HxhS?HWf8jNB`$XAvp4xZ zgF7qaT#U;~OzqqS!`i%(zhO?|jSdA^yIE|?bqJ5UumZB}rn5Q15P8ne)8xQu+sW(@ z=bl$6QBHHzpC!@?1mga2rxRlrCCZ+^urC@s_v_-N~ITHkr#u61d5!6SMU`%8oRB5H_R9(K!0Q9$dih=qJl6;x@Pkvvs>R_6B8OSeO| zTW|}JOnwOa-gbe?#}r2Z?)g7umqeUqlRNcGK&Pv+SXnQzU4!pR610=2pPe`-$lB>qY;=Gs?lcy zn6#0HFkR`VF()n&=nyH}C&Qm1-O&JP*uhwYNJPNbDyTAc*=uD|8{Mzf3K{aQb7Y{(&-Yp;=Nt>jT+jQ4R9xN{qp*TEM zEd_%K|@9$!-+Gqco1=kobD$X#mi!%Ayx*v;_5ZUvXCX9)T(sdx@r&_h!)(a zvQ$wG1uCMGM207D&=y>lmQ5PFztcRpgx@ABv;&^~GhJ#Kpc9Ah&`0v}v@aATK~v_O zI%WLW#X%(VT{F=+j5%ApU&^)kR^h^)B$={AZu_i6&HM&4(Il&y7m!!dkV)YHo4)6#-%EQMKYKN6lMLKQ}O=p_=3|`Z}8ZGRy+_Wv^nNSsPt@NG*&~a!D2)P`{Ms^SESl&WFlVP7IoGKiJ8QW}xd4sF1LTJT5zSY1lbjn@04dM5$9aq4!Sa!cOWr zt9)|Y!{UKhbbN2jUNd)7G9C?b&h&9w;10x4-6csJz!%=!2toWx3U6*WZjrZ|o~G4^ zOm}ZH75TDfC9Ona^IB*Xo5Y)|eFoMf2P6s56*^3Fiv2QD3Q-4tp-O}eql^F<0S%u| zEo&Pj+5T5De+*E-&P~^}nODMZ1JX1$^C&-N=9!XTOFC3Y9)8J~QE5cIMzPGV+rL9XZk|fm%LX7E9`gQQcG4A)siR zvY#@e%8Fw-}1g%gxl>gX8K?Vte?! zwjM7W{J{Qh=&ybgQ8I4Fh)~~e%yTHp{;2=M?sUTt?LlOc8)Uxu@jfw$oA*V+vH#s? z)CE8QcL2EmTVe1kd3IHmwx&Z9O#X9rk&P1JJF%qp4d*RlmL+cey6jVdg6jqHxT<9H z4JF^t#evke2Zeq!lUa^?hG_daQmW|i&`o|wQOiq>E3e+)fbW6Nq)B#h(YRN0tPxm7CF zi>0QC0+S`piHRJ1SakF&DJ8d%cOAmIH=CHyUAT}VcE4x~zy{jZ0h&sdYm9lb*c%Un z_>8JbaJyymv&NfU^L+sD_8(j-$bJBU1ubig;p80f4**M%?WR0|0Yi?)m3P#AfJodr z0DH8z#WMa>KJJvQ%C1Ago_o4$si3o@>y&HEuIH4uEPkgf0aP`N@CQewLM3ysRCK}` zilZ}9l>;(&ODzqL^en>ydcfg#?>sgtg^%RlGwppdVjOBXJDwG)D&Q9llF*kiQHb6_ zP_1M{hR@yHC_p^Ql$TrZPTQP!$zI3r=iZd{s2qY^?WLNbE0mc}Jf3j;#Zb@J0b6iM zydY%ma}8ummJ!0qdZa|72p#OL(Sti-YBb@Ib-r@68CU*6b^N(x1zQ@NI+`@Ua zYCa%Ap`92Gf|e7NtSi4{o|hzPsw`Wh?Q93HwCPZ3rE&s0`l2CI-*ae#(gG=ZqLOav zLZ>Jf-Ahk;n=p=*y>0#uw6qa)o&`a%L=fs+VBb8m(FbZEU=^(L+2$BrNVQi^A)*n z0CX)&%@J6o7gaEc?BKN8#StK(R=rj(TDP&O@IiodX-??Qh0#(Vum0m5 zNxEI-9c%NXpH>kLd2pOIl&^V~5P<%f7xUWpuoL<7D_YRbD7Xa8hPyVU;#!(`b zEM1`>549e;6QbHV`@r*t2^sy#U)FZxIAE>Fsy<~d6{yir8eVTu77>0NnuV{nGqV2cSlG28LTfl&W#~x`2=p_hy59G ziYBuob?!bL5+|qslJ7*NU}82;z&iA0TQWOB_dBKX6Sa(ciCqV8b2>a9XF7<3M!+mi zvtS)qUF0ikUcAG=KDD_;OCZ&U1yKy6J;1c_loA}cLaU(AyU5o}^oqFn-syKy{x$ax z<$WcFc*CORfZe~6#g%!La7^7)=^M?hcawOF7@?0)xRb)iNrQQe$VaH1Ar<4&h_9nc zDJ~%Cv=2@j9mKtIf$NuG#w%eDll-BArG#@<3o_)K7I4!uF1xGe-@aYZ*Qr?fdfQ+Y zh=@g1NZn{qG{dqN*kAZz89F$=zfe7$`~J2xxWj>}yo<6>@~b%ezVl!4RazYHCA!4j zS@6(R;@A@H%#(&er~?V=5?Ri!MeO4I9hb~!aEr&0>jlr_Te*mSdI-;2sM&K(Fk$q> zy_ z+aQ2y*1YXMw}1Y-FYw=48z}|K{*R3VR^#!KGK!4CCV(?9|994|^!&ufvKwW>8iTBB z9@}Rr?7_=Q!M$`5y*&kh)9m9xnu<4;Zl*K?me3qJ=t;b&04O8Wgpi-s3?<(lX6)2(8Fq17~xdsv>Up@f8o$y*i(Ic+@Vy=zC6#-DGE;o6=S@ybcC; zlK*J`_KtNB2^z}+rQLS|J0I}wk(5w+Aj2|OQ$3(riz%D zn8+G_!**Q+6*o7xYlU^uO$k{CbiX^U$g*QdAS`iV0{jOifCDfsGLYvH6*~aqq-9zz z@lYT@ItgqNieRz0b&;ujkL#U)+k5l592x_>Swzi&*$yy&S=6Yps8J}`lPFO!N96$G z`mHp2NOy@&(+bo?=7JVdacz%XCXc{lPBM1kDHN87^m8eNI1bS!UB>PQc;6!M;RH;U z8Q{AZ1Ri%Gb-Sbhp$O)Xcgi{P7b0NyyXGI^GC0f~^_7+i`fbY&3v%NirCWl=C?0tr zTOwa%zkj+BiC~wj<#F~QlWw+*V~|o6%c8=WqF!uehL~3IQuJdpZpi(0kgL)XNy#l% znR*KV!VwV#nvh3XSV1qv@8T6`ckruV&cfuXiUGWt7#A$%`Rkdr=8JC>=hWTRYk{Vn za`ZAYN6|pPle~HKy@K4(`{EdSoFM0J?mL8l?C->&q|@VImb+CJrmgGQr`A4eJf{-q zFHI=`hW=MZ+#uS))ys`$FQjZ1fp0zhu%p3$E7Qm+z-u2Me&@`^ze0{4Y;tgMA7Zmx z5S0-A2dAI0=%3U3@{TUD|I*Vv+GpEUQ;sK6JXV&?vF{{pvC}E=Oa9Vv~wF&HeBdf-GB`V*B88O+SK1e$N5Mt~7 zT!|}!%03GIF*C69-Klx-vVoR|$^cv*bL@9rWT6Zy=+Qsd99%SPL4d0`;zz8g#t}IA z8>$n0YKbYhmW*?GxEkf`SU2fNIT*Wn!O9@o5uxDju!j`bOP;co+o@0Syk)jZE^wb> zP=`UzV056K><{)wg-PVc+V?q9CK=UYBLUAfPP%Xht*zg@LkFCGW!4PF(JGU%F6f6V z64j5{bNd!bQ+emCB_Ffr3p9OqlrlSZ<)01uCD01G1c z(}+HdVkZFqW4T5}d^(}FIk#B4R_(6P(W+=_&~@g*T-$g6T;8eo*G>i_C!QpiYo#|ULCNS& zf?bf$<;5jjs&$W!XY-)O+TA=FSS8m1y=`YyG^zo^@aE8;O~ioW+{V5HyW=gz)B=TYoj$? zg4AMgVvr%8iWQ*m;okiSsezmirD+Xvgk<^ptt5Uzud>o?h$){HvZ9QVF%Xsf>)@Hd z3lVduGTm%*Qp^Rwz(Hemr=q6mq>mXDF%fpgc{<*<@YB#S*;fd}6MVnP43%AVnD+U)v+!}eB?4nu!t@2< zvojzC?`;T<=pI_Zl{ue!Xb4iZg%Hk(*hjcjfRbnecy*#rK+-@cT4?1VE>83~POU+8 z!MO_}HO%<9-tY_&K*!BZX?!3kpw_CCD~_okuakGtBBHCtZZ#(jT5K>yHX|hinVrgf z5Lc7UsLV0~vf^ieRrY5gv-tT-$%Ks)YO!QufQpDQH~aVje&h-JybQL3<_7}qzI<;U zob1U4fH3+m-(1DNmTW`R+2)gxt#^$*RV44L3!`lddHVewY#xP4d~in7r1neCZjc_R ze`^s-3|C9@XmE z)bR2OmQk~_$)b#0Y$NKRD*ZY>c`P^%B3E9*Z}-Yw90@f-6^V+wBwV&Is(vQr;wt@o zJBRufXRD^RHD}zo%2PBopZQAI?(Ff1}>IBYX0Ul;Eb$y=%7<{lC_=Lycm-{2KqrraWZ=XZnPzAWm=0`!^o@WeY!n zT7AdOdFxz*}5T95#u$w(#-NCtrvPT2^#O=Y^{$2I-ZPFZT%|v}J`Hp9`xf zk#5=49pFn4khVS*e$I#A<}$`-wp@Feq;JZvsx~EvZX{#Ar!Ayn9^IfSdjO{+ESMwcKgV6KZrDr36OWRycp{gjliiLjikf^ z{0^(wgK)?YccjfkvOuXBPsGK7$G9`?sx&_zF=5WIL5!v*uR|%vZDD?u5p*~nd73`} zTpCM^;U%hDS-06v{W1SCBIe^3lv65 Date: Tue, 4 Jan 2022 10:41:19 -0500 Subject: [PATCH 149/489] Update README.md --- apps/touchmenu/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/touchmenu/README.md b/apps/touchmenu/README.md index dfc65a754..0e81f3755 100644 --- a/apps/touchmenu/README.md +++ b/apps/touchmenu/README.md @@ -2,6 +2,8 @@ A redesign of the built-in `E.showMenu()` to take advantage of the full touch screen on the Bangle.js 2. +![screenshot](touchmenu.gif) + ## Features - All of the features of the built-in `E.showMenu()` From a489914a72dc2de876af25e818d9147d44c2581d Mon Sep 17 00:00:00 2001 From: kyleplo <31634240+kyleplo@users.noreply.github.com> Date: Tue, 4 Jan 2022 10:44:35 -0500 Subject: [PATCH 150/489] Update apps.json --- apps.json | 340 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 318 insertions(+), 22 deletions(-) diff --git a/apps.json b/apps.json index 3fc319361..e5000e49e 100644 --- a/apps.json +++ b/apps.json @@ -77,7 +77,7 @@ { "id": "messages", "name": "Messages", - "version": "0.14", + "version": "0.16", "description": "App to display notifications from iOS and Gadgetbridge", "icon": "app.png", "type": "app", @@ -167,7 +167,7 @@ { "id": "setting", "name": "Settings", - "version": "0.38", + "version": "0.39", "description": "A menu for setting up Bangle.js", "icon": "settings.png", "tags": "tool,system", @@ -768,7 +768,7 @@ "id": "recorder", "name": "Recorder (BETA)", "shortName": "Recorder", - "version": "0.04", + "version": "0.05", "description": "Record GPS position, heart rate and more in the background, then download to your PC.", "icon": "app.png", "tags": "tool,outdoors,gps,widget", @@ -971,7 +971,7 @@ { "id": "widbt", "name": "Bluetooth Widget", - "version": "0.07", + "version": "0.08", "description": "Show the current Bluetooth connection status in the top right of the clock", "icon": "widget.png", "type": "widget", @@ -1148,7 +1148,7 @@ { "id": "qrcode", "name": "Custom QR Code", - "version": "0.04", + "version": "0.05", "description": "Use this to upload a customised QR code to Bangle.js", "icon": "app.png", "tags": "qrcode", @@ -1501,7 +1501,7 @@ { "id": "gpsinfo", "name": "GPS Info", - "version": "0.05", + "version": "0.06", "description": "An application that displays information about altitude, lat/lon, satellites and time", "icon": "gps-info.png", "type": "app", @@ -2027,7 +2027,7 @@ "id": "chronowid", "name": "Chrono Widget", "shortName": "Chrono Widget", - "version": "0.04", + "version": "0.05", "description": "Chronometer (timer) which runs as widget.", "icon": "app.png", "tags": "tool,widget", @@ -2184,7 +2184,7 @@ "id": "calculator", "name": "Calculator", "shortName": "Calculator", - "version": "0.04", + "version": "0.05", "description": "Basic calculator reminiscent of MacOs's one. Handy for small calculus.", "icon": "calculator.png", "screenshots": [{"url":"screenshot_calculator.png"}], @@ -2429,7 +2429,7 @@ { "id": "calendar", "name": "Calendar", - "version": "0.04", + "version": "0.05", "description": "Simple calendar", "icon": "calendar.png", "screenshots": [{"url":"screenshot_calendar.png"}], @@ -4064,7 +4064,7 @@ { "id": "hcclock", "name": "Hi-Contrast Clock", - "version": "0.02", + "version": "0.03", "description": "Hi-Contrast Clock : A simple yet very bold clock that aims to be readable in high luninosity environments. Uses big 10x5 pixel digits. Use BTN 1 to switch background and foreground colors.", "icon": "hcclock-icon.png", "type": "clock", @@ -4487,7 +4487,7 @@ "name": "LCARS Clock", "shortName":"LCARS", "icon": "lcars.png", - "version":"0.07", + "version":"0.08", "readme": "README.md", "supports": ["BANGLEJS2"], "description": "Library Computer Access Retrieval System (LCARS) clock.", @@ -4652,7 +4652,7 @@ "id": "sensible", "name": "SensiBLE", "shortName": "SensiBLE", - "version": "0.04", + "version": "0.05", "description": "Collect, display and advertise real-time sensor data.", "icon": "sensible.png", "screenshots": [ @@ -4697,6 +4697,8 @@ "tags": "tool,timer", "readme":"README.md", "supports":["BANGLEJS2"], + "screenshots": [{"url":"screenshot1.png"},{"url":"screenshot2.png"},{"url":"screenshot3.png"}], + "allow_emulator": true, "storage": [ {"name":"a_speech_timer.app.js","url":"app.js"}, {"name":"a_speech_timer.img","url":"app-icon.js","evaluate":true} @@ -4778,7 +4780,7 @@ { "id": "weatherClock", "name": "Weather Clock", - "version": "0.04", + "version": "0.05", "description": "A clock which displays current weather conditions (requires Gadgetbridge and Weather apps).", "icon": "app.png", "screenshots": [{"url":"screens/screen1.png"}], @@ -4838,6 +4840,25 @@ {"name": "flow.img", "url": "app-icon.js","evaluate": true } ] }, + { "id": "tinydraw", + "name": "TinyDraw", + "shortName":"TinyDraw", + "version":"0.01", + "type": "app", + "description": "Draw stuff in your wrist", + "icon": "app.png", + "allow_emulator": true, + "tags": "tools, keyboard, text, scribble", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"tinydraw.app.js","url":"app.js"}, + {"name":"tinydraw.img","url":"app-icon.js","evaluate":true} + ], + "screenshots":[ + { "url":"screenshot.png" } + ] + }, { "id": "scribble", "name": "Scribble", "shortName":"Scribble", @@ -4861,7 +4882,7 @@ "id": "ptlaunch", "name": "Pattern Launcher", "shortName": "Pattern Launcher", - "version": "0.11", + "version": "0.13", "description": "Directly launch apps from the clock screen with custom patterns.", "icon": "app.png", "screenshots": [{"url":"manage_patterns_light.png"}], @@ -4875,6 +4896,20 @@ ], "data": [{"name":"ptlaunch.patterns.json"}] }, + { "id": "slimehunt", + "name": "Slime Hunt", + "shortName":"SlimeHunt", + "icon": "app.png", + "version":"0.02", + "description": "Fight against slimes in turn based combat, try to get the highscore!", + "tags": "rpg,slime", + "supports" : ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"slimehunt.app.js","url":"app.js"}, + {"name":"slimehunt.img","url":"app-icon.js","evaluate":true} + ] + }, { "id": "rebble", "name": "Rebble Clock", @@ -4931,10 +4966,12 @@ "id":"awairmonitor", "name":"Awair Monitor", "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], "allow_emulator": true, - "version":"0.01", + "version":"0.03", "description": "Displays the level of CO2, VOC, PM 2.5, Humidity and Temperature, from your Awair device.", - "tags": "tool,health", + "type": "clock", + "tags": "clock,tool,health", "readme":"README.md", "supports":["BANGLEJS2"], "storage": [ @@ -4963,8 +5000,8 @@ }, { "id": "coretemp", - "name": "Core Temp Display", - "version": "0.01", + "name": "CoreTemp", + "version": "0.02", "description": "Display CoreTemp device sensor data", "icon": "coretemp.png", "type": "app", @@ -4972,10 +5009,14 @@ "readme": "README.md", "supports": ["BANGLEJS","BANGLEJS2"], "storage": [ - {"name":"coretemp.boot.js","url":"boot.js"}, + {"name":"coretemp.wid.js","url":"widget.js"}, {"name":"coretemp.app.js","url":"coretemp.js"}, - {"name":"coretemp.img","url":"coretemp-icon.js","evaluate":true} - ] + {"name":"coretemp.settings.js","url":"settings.js"}, + {"name":"coretemp.img","url":"coretemp-icon.js","evaluate":true}, + {"name":"coretemp.boot.js","url":"boot.js"} + ], + "data": [{"name":"coretemp.json","url":"app-settings.json"}], + "screenshots": [{"url":"screenshot.png"}] }, { "id": "showimg", @@ -5029,9 +5070,10 @@ { "id": "circlesclock", "name": "Circles clock", "shortName":"Circles clock", - "version":"0.02", + "version":"0.03", "description": "A clock with circles for different data at the bottom in a probably familiar style", "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], "dependencies": {"widpedom":"app"}, "type": "clock", "tags": "clock", @@ -5047,6 +5089,22 @@ {"name":"circlesclock.json"} ] }, + { "id": "contourclock", + "name": "Contour Clock", + "shortName" : "Contour Clock", + "version":"0.01", + "icon": "app.png", + "description": "A Minimalist clockface with large Digits. Looks best with the dark theme", + "screenshots" : [{"url":"screenshot.png"}], + "tags": "clock", + "allow_emulator":true, + "supports" : ["BANGLEJS2"], + "type": "clock", + "storage": [ + {"name":"contourclock.app.js","url":"app.js"}, + {"name":"contourclock.img","url":"app-icon.js","evaluate":true} + ] + }, { "id": "ltherm", "name": "Localized Thermometer", @@ -5063,11 +5121,249 @@ {"name":"ltherm.img","url":"icon.js","evaluate":true} ] }, + { + "id": "slash", + "name": "Slash Watch", + "shortName":"Slash", + "icon": "slash.png", + "screenshots": [{"url":"screenshot.png"}], + "version":"0.01", + "description": "Slash Watch based on Pebble watch face by Nikki.", + "tags": "clock", + "type": "clock", + "supports":["BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"slash.app.js","url":"app.js"}, + {"name":"slash.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "promenu", + "name": "Pro Menu", + "version": "0.01", + "description": "Replace Bangle.js 1's built in menu function.", + "icon": "icon.png", + "type": "boot", + "tags": "system", + "supports": ["BANGLEJS"], + "screenshots": [{"url":"pro-menu-screenshot.png"}], + "storage": [ + {"name":"promenu.boot.js","url":"boot.js"}, + {"name":"promenu.img","url":"promenuIcon.js","evaluate":true} + ] + }, + { + "id": "touchtimer", + "name": "Touch Timer", + "shortName": "Touch Timer", + "version": "0.02", + "description": "Quickly and easily create a timer with touch-only input. The time can be easily set with a number pad.", + "icon": "app.png", + "tags": "tools", + "supports": ["BANGLEJS2"], + "readme": "README.md", + "screenshots": [{"url":"0_light_timer_edit.png"},{"url":"1_light_timer_ready.png"},{"url":"2_light_timer_running.png"},{"url":"3_light_timer_finished.png"}], + "storage": [ + { "name": "touchtimer.app.js", "url": "app.js" }, + { "name":"touchtimer.settings.js", "url":"settings.js"}, + { "name": "touchtimer.img", "url": "app-icon.js", "evaluate": true } + ], + "data": [{"name":"touchtimer.data.json"}] + }, + { + "id": "teatimer", + "name": "Tea Timer", + "version": "1.00", + "description": "A simple timer. You can easyly set up the time.", + "icon": "teatimer.png", + "type": "app", + "tags": "tool", + "supports": ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"teatimer.app.js","url":"app.js"}, + {"name":"teatimer.img","url":"app-icon.js","evaluate":true} + ], + "screenshots": [ + {"url":"TeatimerStart.jpg"}, + {"url":"TeatimerHelp.jpg"}, + {"url":"TeatimerRun.jpg"}, + {"url":"TeatimerUp.jpg"} + ] + }, + { + "id": "swp2clk", + "name": "Swipe back to the Clock", + "shortName": "Swipe to Clock", + "version": "0.01", + "description": "Let's you swipe from left to right on any app to return back to the clock face. Please configure in the settings app after installing to activate, since its disabled by default.", + "icon": "app.png", + "type": "boot", + "tags": "tools", + "supports": ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + { "name": "swp2clk.boot.js", "url": "boot.js" }, + {"name":"swp2clk.settings.js","url":"settings.js"} + ], + "data": [{"name":"swp2clk.data.json"}] + }, + { + "id":"colorwheel", + "name":"Color Wheel", + "tags":"app,tool", + "version":"0.01", + "description":"a tappable wheel of good-looking colors", + "readme":"README.md", + "supports":["BANGLEJS2"], + "allow_emulator":true, + "icon":"colorwheel.png", + "storage": [ + {"name":"colorwheel.app.js","url":"app.js"}, + {"name":"colorwheel.img","url":"app-icon.js","evaluate":true} + ] + }, + { "id": "minimal_clock", + "name": "Minimal Analog Clock", + "shortName":"Minimal Clock", + "version":"0.03", + "description": "a minimal analog clock - just with some hands and no clock face", + "icon": "app-icon.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"app-screenshot.png"}], + "readme": "README.md", + "storage": [ + {"name":"minimal_clock.app.js","url":"app.js"}, + {"name":"minimal_clock.img","url":"app-icon.js","evaluate":true} + ] + }, + { "id": "simple_clock", + "name": "Simple Analog Clock", + "shortName":"Simple Clock", + "version":"0.02", + "description": "a simple, yet stylish, analog clock", + "icon": "app-icon.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"app-screenshot.png"}], + "readme": "README.md", + "storage": [ + {"name":"simple_clock.app.js","url":"app.js"}, + {"name":"simple_clock.img","url":"app-icon.js","evaluate":true} + ] + }, + { "id": "colorful_clock", + "name": "Colorful Analog Clock", + "shortName":"Colorful Clock", + "version":"0.02", + "description": "a colorful analog clock", + "icon": "app-icon.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"app-screenshot.png"}], + "readme": "README.md", + "storage": [ + {"name":"colorful_clock.app.js","url":"app.js"}, + {"name":"colorful_clock.img","url":"app-icon.js","evaluate":true} + ] + }, + { "id": "themesetter", + "name": "Theme Setter", + "shortName":"Theme Setter", + "version":"0.04", + "description": "a comfortable way to configure theme colors", + "icon": "app-icon.png", + "type": "app", + "tags": "tool", + "supports" : ["BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"app-screenshot.png"}], + "readme": "README.md", + "storage": [ + {"name":"themesetter.app.js","url":"app.js"}, + {"name":"themesetter.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "widviztime", + "name": "Widget Autohide Widget", + "shortName": "Viz Time Widget", + "version": "0.01", + "description": "The widgets will be shown for four seconds after the device is unlocked.", + "icon": "eye.png", + "type": "widget", + "tags": "widget", + "readme":"README.md", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widviztime.wid.js","url":"widget.js"} + ] + }, + { + "id": "supf", + "name": "Simple Clock with Date", + "shortName": "supf Clock", + "version": "0.01", + "description": "Simple Clock with seconds and date in custom language. Install 'Languages' to get localized names.", + "icon": "icon.png", + "screenshots": [{"url":"screenshot_supf.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS2"], + "allow_emulator": true, + "readme": "README.md", + "storage": [ + {"name":"supf.app.js","url":"app.js"}, + {"name":"supf.img","url":"icon.js","evaluate":true} + ] + }, + { "id": "andark", + "name": "Analog Dark", + "shortName":"AnDark", + "version":"0.04", + "description": "analog clock face without disturbing widgets", + "icon": "andark_icon.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"andark.app.js","url":"app.js"}, + {"name":"andark.img","url":"app_icon.js","evaluate":true} + ] + }, + { + "id": "diract", + "name": "DirAct", + "shortName": "DirAct", + "version": "0.01", + "description": "Proximity interaction detection.", + "icon": "diract.png", + "type": "app", + "tags": "tool,sensors", + "supports" : [ "BANGLEJS2" ], + "allow_emulator": false, + "readme": "README.md", + "storage": [ + { "name": "diract.app.js", "url": "diract.js" }, + { "name": "diract.img", "url": "diract-icon.js", "evaluate": true } + ] + }, { "id": "touchmenu", "name": "TouchMenu", "version": "0.01", "description": "Redesigned menu that uses the full touchscreen on the Bangle.js 2", + "screenshots": [{"url":"touchmenu.gif"}], "icon": "touchmenu.png", "type": "bootloader", "tags": "tool", From 26854f8fba96c65c00d81acbf8769b2be9b87953 Mon Sep 17 00:00:00 2001 From: David Peer Date: Tue, 4 Jan 2022 18:37:18 +0100 Subject: [PATCH 151/489] Minor improvements. --- apps/lcars/lcars.app.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 74d0450c0..c3e3b2bfc 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -191,7 +191,7 @@ function drawState(){ return; } - g.clearRect(20, 93, 77, 170); + g.clearRect(20, 93, 80, 170); g.setColor(cWhite); var bat = E.getBattery(); var current = new Date(); @@ -206,16 +206,16 @@ function drawState(){ hours % 4 == 1 ? iconMars : hours % 4 == 2 ? iconMoon : iconEarth; - g.drawImage(iconImg, 29, 104); + g.drawImage(iconImg, 31, 104); } else { // Alarm within symbol g.setFontAntonioMedium(); g.setFontAlign(0, 0, 0); g.setColor(cOrange); - g.drawString("ALARM", 29+25, 107); + g.drawString("ALARM", 31+25, 107); g.setColor(cWhite); g.setFontAntonioLarge(); - g.drawString(getAlarmMinutes(), 29+25, 107+35); + g.drawString(getAlarmMinutes(), 31+25, 107+35); } g.setFontAlign(-1, -1, 0); From b4809c9cdd81b1f358697e10f9e8d805db10bfc9 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Tue, 4 Jan 2022 21:32:54 +0100 Subject: [PATCH 152/489] Add files via upload --- apps/mmind/mmind.png | Bin 1546 -> 712 bytes apps/mmind/screenshot_mmind.png | Bin 0 -> 2577 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/mmind/screenshot_mmind.png diff --git a/apps/mmind/mmind.png b/apps/mmind/mmind.png index 8afcc26974bc8eaa2239927b33b4d566e8df42ba..14a3ef7c647be749a768209a9dfaea0a09ab960f 100644 GIT binary patch delta 674 zcmeC;Il-#f8Q|y6%O%Cdz`(%k>ERLtq&I*t3p0?6o%u6&qN0MLM1W6->;M1%fkJTn zp8+iJ|9^zugt-&##Os+XJzX3_GVZ;dh9r6B4J?RMuJ;D?~a9lms4|@hr&o{8I0!Jl|U;hi%dQ8^(G6 z_$;&7>u-B@EPwyI`M`|lk3VY6OO0zw?3nst!ViPfqA91Rrhv%aCll(qPrKVk6&yd{ zFLtMR!&ABYk~fOl&$sPpTlkP?&@;u zUFtV}pd@_ctY-3|SNc0^pFOQV$hxe=^!U$((^Y0ITX*KQMW4~*?U}QDia$ww+fl;5 zXZO$%B z(=)p5(zmpO50o%u)+fz~teY_ZWBoy}E05?rl6`A?;LjXy&kYuA%pZ0gxLVd4z!i62 sJ9ho<(AUSms(Eak$?h27=k=E%;69JIf)@8nU>alaboFyt=akR{0Iy3qcK`qY delta 1534 zcmVVGd00o~(L_t(oN9~whXcJi!$4|4vSQ>^XVUQGBv)Tq9N-X_g zDN>45MXKzB4`N|g5h;BTKj=d!ODK^N(G6*#Y4;&Q9}2dLEKyQQLHtPZ#g8bpq7Vz4 zpx8>bwN2aDWMl81JNKrUiPU-Ze_?(zOwK)L?w!NE=bvP52_Xc2BuxDChv6rW$AcdW z3kw4S19$J<-L`F;-EL>GP2%ym&*z(*oWzjTYUSQMb8~b3{r%(P;}|M0FX!Gou~_Wt z)vJ+6WY3;G+qZA$UVv;id;k7@bh2hN8Z9X)kt7Ll$r6b~kKO(+04`n_e<0}hqjQr- zj~-bEt&pK%DJX@)As$eeo}RYZt^uSlEQ+JU!=pT)5DtZdQjh@2KxWW7h(j^|)2B~s zYimnOOVM6kT|IvMxXor885zMQO{lxA?LQ?Oc8&-FK8E%qYRqm=njDYNw7Z(>< z6sfOw0esyIi=zMI$B!(8f46yMFMUG(bXU1?KnzVyO}%~l*6DPjy|lD+>((t?0hSQ0 zp;~i?t#+!LO}%Mko}Lq9$slYByaMp^o zI0$zUa{Kn}nwlES45zcZyZi9r!)S}5NDU05%IrOM$ji(hELPc|)vAaLf|3*t6|3yp zHCrl0i*|HW933q@6$ypIQZPtknT&O?pfc=bHk+}ial#%ye}3H5)UKqWI_M58iyRaHJhPp_;|nafrG^(%cMJN?zrY5UaS+YW-vRMmP z8G_%yc*SMHe@fc9bLZIDSZizRsZ*!uV0Jvz#5F2Qt2Biq%^H=_-YOD_LSMYioYbgH zPH(BQmX;PQrhE79(S!mg1Lh$!9T(^jDjq(3IN8^?kz6NIe(~bPu3fu&dwZWfdlm=;aQV8rx{SXcdKd}mVI-u7 zk&qrne?oc~3F%=Zq=%7^9!5fX7zycNB&3ItkRFBivR8QEJ0;j;(7ZcS)|HJT zR1;2mdbt1lY`tV$Wig0dhwErKz|jF6N~$U%0ON|$0#LjgL-&Q?=1pqU)j@l^;?iSo k4*L4It;N`m`91*u1O9JFJ2Em3SpWb407*qoM6N<$f?a&%7XSbN diff --git a/apps/mmind/screenshot_mmind.png b/apps/mmind/screenshot_mmind.png new file mode 100644 index 0000000000000000000000000000000000000000..5c886e7e82c0a3a78ed1344837f32e33ecd639eb GIT binary patch literal 2577 zcmeHJ`#Td18=f`iPi93)YNl+N>Ez6E$T2ldFO$PqCE*pr*hVq0_hp+y)X2GnksJ!m zhs{2(P?Qg`G-ggEVHsW&msfwl_sjS5`@?hJ*Kc5!Ft)_Nzs zh6Qu>o%dc^tzxUmkj;{-P+aRHnceBu;ARBP66hcO3Gu@PKvSC>1c5gOhn$ub()Q%) zCGvBN&oP_=4mTUgfOxB`SS#Q(zg*EsIlg^@dGrI(ZDwemf-guO2xh_zz73Q;t45!n zajRzQE$wvOLR;5h?7LGy#qyRd5-Z8u8d;9P=&KZE4Wk#uHEqvJ9Y-1q8zRx`LZeUy z^+NjbL#?E($9ybNAWesu8!Xw{V($&eHi1M^FS=(Tj*BI7Ql)D*I2iQwc_8Ovuhz_j z|AUS;>wr>dAiDRR(Eq`UiUUu&Yq-TY)7v%h7e$tgJWc=oWT4ujgK!!j+M?cr?|RTy z?NMF{KPh>EaJZyNVTareswpoXyh~aRi}?26>o>P*`AQU4kr%AaYf6zC$3~*oG=fch z65EkS(M6obqSTQqkR~TF2zJ-Dhh5liSl2ageNz8UZd)#= z$mDK8SvO)^8_BAMo)6r|bRC_1lzwl{`b=?k{hnfbGk%U$x)$ ztRsI2l#v?sM{~+JdF{Lt+Bi$wSX;58@-qa;*?4gv^hPp zY^~2SoQWLT>@;({B&}7N&uj3M5!_zQsN=E5B2Ey6cau$3E8@174RQ0G=zWd3YkpVy z8Q+yRLgE?uBFO5qisa5X>9B}cpj@b#u;Ctb0Z)K?_O$B5$LZ=)eaq+eA`D#sJc8=V zxt^Kd)%u>hGZUCJFtI4omGwJF`?`|Im((@p5=plvbs-SstOtn@xb6{6sA|*pYc8*T zd0041D<8+zr`w3B1snb#(f#%fclM1PCZF^J1dp1~k63)uxni);x$rfDxc(U>I6LnOlcyh`Z~SRxYm`5viE)1x1B`F=~GD$S10%0+T3YaSfVA! zxg5v%+7;B!ZE>krVymgi^B(Y76PT_fA1gr3bc8TO+IxZTcb+xDKHbGM_YL#k&zoS%KL*uPFkYpn{xDdC5; z7Wr`k(mMWxJ}QyB{Ji@_0-`B8&sH_8-`Xa~{7VWs17qO*XM&oa$I0079)2RBlFhxZzLp<#1v=KhJ6N{6O9RU4|MAIZ;B zsUCQ@dQogjA6wa!wZq9SWvzP%!1TD8A|(h^sF;=47M^AHC-gKj1sF7=4I?^=un?r) zlGZWLh&k}T5%qTXs!k=!Fa!x-oQEK<8l|T3Rq9Pr^x-PB)|=OG0fFnR=$|KuL?~~Q zT}`iju{Y`y3IYq+(iO4g^8 T#S9|s{&)Zv2aJ8KT|m;`rbCOu literal 0 HcmV?d00001 From 786b13925cf1a3097706ec11a5c10565431e8fa9 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Tue, 4 Jan 2022 22:32:36 +0100 Subject: [PATCH 153/489] Add files via upload --- apps/mmind/README.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 apps/mmind/README.md diff --git a/apps/mmind/README.md b/apps/mmind/README.md new file mode 100644 index 000000000..508a158dd --- /dev/null +++ b/apps/mmind/README.md @@ -0,0 +1,34 @@ +# Mastermind + +Play the classic mind game mastermind on your Bangles 2. + +![](screenshot_mmind.png) + + +## Game +The game will start when run. +Four colors pins are randomly choosen and kept secret. +You need to find the secret by scoring your choise within 6 turns. +The game makes use of touch features. + + +## Play +Select one of the dots, the color menu will show, select a colour for the pin. +If all pins are choosen with a color the red button will turn green. +Hit the green button and your play will be scored and listed from the top. +The first digit shows the number of pins with the correct color and in the right place. +The second digit gives the number of pins with the correct color but in the wrong place. +There are six turns to get the correct secret. +The blue button will start a new game. + + +## Requests + +This is the first version, things to add: +Add menu to change game options number of colors, 5 pins per row. +Add feature to drag screen up and down to see more scores + + +## Creator + +This game is created by Peter Slendebroek. \ No newline at end of file From 1fdf05958dbd13af0e65ff30d0c044208a8c737f Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Tue, 4 Jan 2022 22:36:51 +0100 Subject: [PATCH 154/489] Update README.md --- apps/mmind/README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/mmind/README.md b/apps/mmind/README.md index 508a158dd..e09b5b966 100644 --- a/apps/mmind/README.md +++ b/apps/mmind/README.md @@ -13,6 +13,7 @@ The game makes use of touch features. ## Play +The screen needs to be unlocked. Select one of the dots, the color menu will show, select a colour for the pin. If all pins are choosen with a color the red button will turn green. Hit the green button and your play will be scored and listed from the top. @@ -25,10 +26,11 @@ The blue button will start a new game. ## Requests This is the first version, things to add: -Add menu to change game options number of colors, 5 pins per row. -Add feature to drag screen up and down to see more scores - +... +Add a menu to change game options like the number of colors, allow double colors, 5 pins per row. +Add feature to drag screen up and down to see more scores. +Times and high score ## Creator -This game is created by Peter Slendebroek. \ No newline at end of file +This game is created by Peter Slendebroek. From ed9b7f2e6b148f10a8a2b7f07bd4c12ea8622b02 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Tue, 4 Jan 2022 22:44:04 +0100 Subject: [PATCH 155/489] Update README.md --- apps/mmind/README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/mmind/README.md b/apps/mmind/README.md index e09b5b966..0623459f7 100644 --- a/apps/mmind/README.md +++ b/apps/mmind/README.md @@ -25,11 +25,10 @@ The blue button will start a new game. ## Requests -This is the first version, things to add: -... -Add a menu to change game options like the number of colors, allow double colors, 5 pins per row. -Add feature to drag screen up and down to see more scores. -Times and high score +This is the first version, things to add are:/ +Add a menu to change game options like the number of colors, allow double colors, 5 pins per row./ +Add feature to drag screen up and down to see more scores./ +Timer and high score./ ## Creator From 8931817a2b23ec5740346ab4c571de520153a189 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Tue, 4 Jan 2022 23:00:36 +0100 Subject: [PATCH 156/489] Add files via upload --- apps/mmind/mmind.info | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 apps/mmind/mmind.info diff --git a/apps/mmind/mmind.info b/apps/mmind/mmind.info new file mode 100644 index 000000000..a6dccde65 --- /dev/null +++ b/apps/mmind/mmind.info @@ -0,0 +1,5 @@ +require("Storage").write("mmind.info",{ + "id":"mmind", + "name":"Master Mindr", + "src":"mmind.app.js" +}); \ No newline at end of file From cd71d7937d636d2b3ba77b62b6edec5ecda3f0d7 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Tue, 4 Jan 2022 23:02:47 +0100 Subject: [PATCH 157/489] Update mmind.info --- apps/mmind/mmind.info | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/apps/mmind/mmind.info b/apps/mmind/mmind.info index a6dccde65..2e79822b1 100644 --- a/apps/mmind/mmind.info +++ b/apps/mmind/mmind.info @@ -1,5 +1,17 @@ -require("Storage").write("mmind.info",{ - "id":"mmind", - "name":"Master Mindr", - "src":"mmind.app.js" -}); \ No newline at end of file + { + "id": "mmind", + "name": "Classic Mind Game", + "shortName":"Master Mind", + "icon": "mmind.png", + "version":"0.01", + "description": "This is the classic game for masterminds", + "type": "game", + "tags": "mastermind, game, classic", + "readme":"README.md", + "supports": ["BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"mmind.app.js","url":"mmind.app.js"}, + {"name":"mmind.img","url":"mmind.icon.js","evaluate":true} + ] + } From 7974e4dd2b8d6dff7477315f9d43cf43b40c3867 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Tue, 4 Jan 2022 23:32:58 +0100 Subject: [PATCH 158/489] Prepare release of cprassist --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 64abacef2..4f966bbdd 100644 --- a/apps.json +++ b/apps.json @@ -2970,7 +2970,7 @@ { "id": "cprassist", "name": "CPR Assist", - "version": "0.02-rc1", + "version": "0.02", "description": "Provides assistance while performing a CPR", "icon": "cprassist-icon.png", "tags": "tool,firstaid", From 1ef8a0bfb0b52107cac461c7f009a7e74a6efa36 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Wed, 5 Jan 2022 01:00:03 +0100 Subject: [PATCH 159/489] Update core --- core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core b/core index 2a8e872ec..5a5957714 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 2a8e872ecb143a10e53273b4d3473164e104e1d3 +Subproject commit 5a5957714d4aa04413329f57c03e6de0cfb74caf From 6bdbd310bcc354b8b18da040138bc9122817ca66 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Tue, 4 Jan 2022 16:41:05 -0800 Subject: [PATCH 160/489] fix light mode not selected color from -10 to -20 --- apps/promenu/boot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/promenu/boot.js b/apps/promenu/boot.js index 002734113..bd813a812 100644 --- a/apps/promenu/boot.js +++ b/apps/promenu/boot.js @@ -70,7 +70,7 @@ E.showMenu = function(items) { if(g.theme.dark){ fillRectRnd(x+2,iy+1,x2,iy+options.fontHeight-3,7,hl ? g.theme.bgH : g.theme.bg+20); }else{ - fillRectRnd(x+2,iy+1,x2,iy+options.fontHeight-3,7,hl ? g.theme.bgH : g.theme.bg-10); + fillRectRnd(x+2,iy+1,x2,iy+options.fontHeight-3,7,hl ? g.theme.bgH : g.theme.bg-20); } g.setColor(hl ? g.theme.fgH : g.theme.fg); g.setFontAlign(-1,-1); From bbf4e76dce002a077612948df0a827e8125aae00 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 5 Jan 2022 09:10:40 +0000 Subject: [PATCH 161/489] fix build issues after PR merge --- apps.json | 2 +- core | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index f1afbe858..f116049dc 100644 --- a/apps.json +++ b/apps.json @@ -5387,7 +5387,7 @@ "tags": "tool", "supports": ["BANGLEJS2"], "storage": [ - {"name":"touchmenu.boot.js","url":"touchmenu.js"}, + {"name":"touchmenu.boot.js","url":"touchmenu.boot.js"} ] } ] diff --git a/core b/core index 2a8e872ec..5a5957714 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 2a8e872ecb143a10e53273b4d3473164e104e1d3 +Subproject commit 5a5957714d4aa04413329f57c03e6de0cfb74caf From ed6c1ddc839d278a50fded68c0d77368a126aae8 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 5 Jan 2022 09:13:08 +0000 Subject: [PATCH 162/489] now link to changes for new firmwares --- loader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader.js b/loader.js index 768f5f38f..a0c280634 100644 --- a/loader.js +++ b/loader.js @@ -40,7 +40,7 @@ function onFoundDeviceInfo(deviceId, deviceVersion) { if (deviceId != "BANGLEJS" && deviceId != "BANGLEJS2") { showToast(`You're using ${deviceId}, not a Bangle.js. Did you want espruino.com/apps instead?` ,"warning", 20000); } else if (versionLess(deviceVersion, RECOMMENDED_VERSION)) { - showToast(`You're using an old Bangle.js firmware (${deviceVersion}). You can update with the instructions here` ,"warning", 20000); + showToast(`You're using an old Bangle.js firmware (${deviceVersion}) and ${RECOMMENDED_VERSION} is available (see changes). You can update with the instructions here` ,"warning", 20000); } From f81032ac5b7bd084ee6c8695e9497362bd078960 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 5 Jan 2022 09:28:51 +0000 Subject: [PATCH 163/489] Ensure crypto module is only set as included for Bangle.js 2 (fix https://github.com/andrewgoz/Authentiwatch/issues/7) --- core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core b/core index 5a5957714..ae9586977 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 5a5957714d4aa04413329f57c03e6de0cfb74caf +Subproject commit ae9586977948279d267f2749bf3a48d3aa753c11 From 34b73682edc0785013cbd3f5dcb4085880da6a62 Mon Sep 17 00:00:00 2001 From: David Peer Date: Wed, 5 Jan 2022 10:30:10 +0100 Subject: [PATCH 164/489] Design improvements --- apps/lcars/lcars.app.js | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index c3e3b2bfc..cae66c1ec 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -147,14 +147,17 @@ function printData(key, y, c){ } g.setColor(c); + g.fillRect(79, y-2, 85 ,y+18); + + g.setFontAlign(0,-1,0); + g.drawString(value, 109, y); + + g.setColor(c); + g.setFontAlign(-1,-1,0); g.fillRect(133, y-2, 165 ,y+18); g.fillCircle(161, y+8, 10); g.setColor(cBlack); g.drawString(text, 135, y); - - g.setColor(c); - g.setFontAlign(1,-1,0); - g.drawString(value, 130, y); } function drawHorizontalBgLine(color, x1, x2, y, h){ @@ -191,7 +194,7 @@ function drawState(){ return; } - g.clearRect(20, 93, 80, 170); + g.clearRect(20, 93, 75, 170); g.setColor(cWhite); var bat = E.getBattery(); var current = new Date(); @@ -206,16 +209,18 @@ function drawState(){ hours % 4 == 1 ? iconMars : hours % 4 == 2 ? iconMoon : iconEarth; - g.drawImage(iconImg, 31, 104); + + // g.drawRect(25, 104, 25+50, 104+50); + g.drawImage(iconImg, 24, 104); } else { // Alarm within symbol g.setFontAntonioMedium(); g.setFontAlign(0, 0, 0); g.setColor(cOrange); - g.drawString("ALARM", 31+25, 107); + g.drawString("ALARM", 24+25, 108); g.setColor(cWhite); g.setFontAntonioLarge(); - g.drawString(getAlarmMinutes(), 31+25, 107+35); + g.drawString(getAlarmMinutes(), 24+25, 108+35); } g.setFontAlign(-1, -1, 0); @@ -401,7 +406,7 @@ function draw(){ * Step counter via widget */ function getSteps() { - var steps = 0 + var steps = 0; try { health = require("health"); } catch(ex) { From 47b93192b2986cc53e41baa9f9c1ef3a9bf14d61 Mon Sep 17 00:00:00 2001 From: David Peer Date: Wed, 5 Jan 2022 10:33:58 +0100 Subject: [PATCH 165/489] Open luncher on touch. --- apps/lcars/lcars.app.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index cae66c1ec..727ef6bae 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -558,6 +558,10 @@ Bangle.on("drag", e => { } }); +Bangle.on("touch", e => { + Bangle.showLauncher(); +}); + /* * Lets start widgets, listen for btn etc. From 154dc0a315cd173e69815893dcf4d1c2796caf6a Mon Sep 17 00:00:00 2001 From: David Peer Date: Wed, 5 Jan 2022 10:35:58 +0100 Subject: [PATCH 166/489] Created version 0.09 --- apps.json | 6 +++--- apps/lcars/ChangeLog | 3 ++- apps/lcars/README.md | 4 +++- apps/lcars/screenshot.png | Bin 5195 -> 5630 bytes 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/apps.json b/apps.json index 89c5f7b70..3b593e9d5 100644 --- a/apps.json +++ b/apps.json @@ -4487,7 +4487,7 @@ "name": "LCARS Clock", "shortName":"LCARS", "icon": "lcars.png", - "version":"0.08", + "version":"0.09", "readme": "README.md", "supports": ["BANGLEJS2"], "description": "Library Computer Access Retrieval System (LCARS) clock.", @@ -5099,7 +5099,7 @@ "tags": "clock", "allow_emulator":true, "supports" : ["BANGLEJS2"], - "type": "clock", + "type": "clock", "storage": [ {"name":"contourclock.app.js","url":"app.js"}, {"name":"contourclock.img","url":"app-icon.js","evaluate":true} @@ -5334,7 +5334,7 @@ "icon": "andark_icon.png", "type": "clock", "tags": "clock", - "supports" : ["BANGLEJS2"], + "supports" : ["BANGLEJS2"], "readme": "README.md", "storage": [ {"name":"andark.app.js","url":"app.js"}, diff --git a/apps/lcars/ChangeLog b/apps/lcars/ChangeLog index c171ec3d4..f5d8346da 100644 --- a/apps/lcars/ChangeLog +++ b/apps/lcars/ChangeLog @@ -5,4 +5,5 @@ 0.05: Additional icons for (1) charging and (2) bat < 30%. 0.06: Fix - Alarm disabled, if clock was closed. 0.07: Added settings to adjust data that is shown for each row. -0.08: Support for multiple screens. 24h graph for steps + HRM. Fullscreen Mode. \ No newline at end of file +0.08: Support for multiple screens. 24h graph for steps + HRM. Fullscreen Mode. +0.09: Tab anywhere to open the launcher. \ No newline at end of file diff --git a/apps/lcars/README.md b/apps/lcars/README.md index 97695a408..4bf5218f6 100644 --- a/apps/lcars/README.md +++ b/apps/lcars/README.md @@ -8,13 +8,15 @@ To contribute you can open a PR at this [GitHub Repo]( https://github.com/peerda * LCARS Style watch face. * Full screen mode - widgets are still loaded. * Supports multiple screens with different data. + * Tab anywhere to open the launcher. * [Screen 1] Date + Time + Lock status. * [Screen 1] Shows randomly images of real planets. * [Screen 1] Shows different states such as (charging, out of battery, GPS on etc.) * [Screen 1] Swipe up/down to activate an alarm. * [Screen 1] Shows 3 customizable datapoints on the first screen. * [Screen 1] The lower orange line indicates the battery level. - * [Screen 2] Display month graphs for steps + hrm on the second screen. + * [Screen 2] Display graphs for steps + hrm on the second screen. + * [Screen 2] Switch between day/month via swipe up/down. ## Multiple screens support diff --git a/apps/lcars/screenshot.png b/apps/lcars/screenshot.png index b3dfd42000766a5bff8e62a6e5d66103ac4f2a9b..bbc25abc30d9da3b1bf35a62698083c1d0eca781 100644 GIT binary patch literal 5630 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 Y2PMNWz8ZN*QUCw|07*qoM6N<$f+ZW)KmY&$ delta 5194 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 Ef-RE!%m4rY From 8b89d41e699551caa2dcca4adb2365d8568029b5 Mon Sep 17 00:00:00 2001 From: David Peer Date: Wed, 5 Jan 2022 11:51:16 +0100 Subject: [PATCH 167/489] Minor changes --- apps/lcars/lcars.app.js | 21 ++++++++++----------- apps/lcars/screenshot.png | Bin 5630 -> 5835 bytes 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 727ef6bae..1be2cfd43 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -195,12 +195,13 @@ function drawState(){ } g.clearRect(20, 93, 75, 170); - g.setColor(cWhite); - var bat = E.getBattery(); - var current = new Date(); - var hours = current.getHours(); + g.setFontAlign(0, 0, 0); + g.setFontAntonioMedium(); if(!isAlarmEnabled()){ + var bat = E.getBattery(); + var current = new Date(); + var hours = current.getHours(); var iconImg = Bangle.isCharging() ? iconCharging : bat < 30 ? iconNoBattery : @@ -209,18 +210,16 @@ function drawState(){ hours % 4 == 1 ? iconMars : hours % 4 == 2 ? iconMoon : iconEarth; - - // g.drawRect(25, 104, 25+50, 104+50); - g.drawImage(iconImg, 24, 104); + g.drawImage(iconImg, 23, 118); + g.setColor(cWhite); + g.drawString("STATUS", 23+25, 108); } else { // Alarm within symbol - g.setFontAntonioMedium(); - g.setFontAlign(0, 0, 0); g.setColor(cOrange); - g.drawString("ALARM", 24+25, 108); + g.drawString("ALARM", 23+25, 108); g.setColor(cWhite); g.setFontAntonioLarge(); - g.drawString(getAlarmMinutes(), 24+25, 108+35); + g.drawString(getAlarmMinutes(), 23+25, 108+35); } g.setFontAlign(-1, -1, 0); diff --git a/apps/lcars/screenshot.png b/apps/lcars/screenshot.png index bbc25abc30d9da3b1bf35a62698083c1d0eca781..8531913133233045e6ce34b5b99d4dc491432603 100644 GIT binary patch literal 5835 zcmV;+7BuOJP)Py0g-Jv~RCr$PUG27`APn5T|3lwBRnZXhF+nQW=Kk0{t$+}QVF-b~{{8#+_s{$L z`}_CrwWZAeSBpK#4ohXdzrW|Ti@;K8-7_2YC~(~}7ytl2l%xue)Bt{HV;;whw}AKE zwE%$M#=EON9p7^XaDw+)@&Ez@0N{uAdkx@EHv(b;Ppjqgw7_A31HfIu3yk>eg|t8i z3#7y{()ZFt`+L1|tx;? zM-j%{r#%HJJTX@!tzL6ku*&J4luCnN?cb{du*;yUW+%wbD^z^xVKfh9Z*DGX`8rb zC$*Lp$rnj$wHzr2Nz(-2fCd%;O!A{%iV{HPx$Znf4fR6Eqxrmr+QMk-!lJFLNWMtg zX#w1kf$4%y@=|zOn#&qbP9y^Z+I*R+I&3~z0}&YrNSZqsxHud%4J~PE$yMih9j5mK ze=7r9Ac_nGp7vt^4luCf2S)t22&j<-Be!ib@Qn-{W%Anq9MHhl&KzG$S(_HyD^EfUFfZDG~{ly7OOPo>Dfs=%hH;Iyu;gJLp>(QyIRaHMS*D`;u=^3zqde> zycKQHXbIq!KHu{opt>_nOJl5^G!Il-Akfu?o#iK{ZA=Dk>2a3FW7ydN?3us|)ba9v z@_7RIlh)nJema0}Fj4a>(hJdSIy_?n7`Ih4WqKi^7HdfV1OQtLxzc1W>I~VeSQc;F zKc1f$F?BL9Vx@~|W(TmhP}>2_g4X#$3)wD~ybl_v5wj-)BUZYYW_kb@1Q{Wb$k{k# zo0)>u^AjUxPX)?CdEjYV&7;8=gvh&En$z10kqpdw;qGJg5fDhAqQHxQ z&P(e(kJOu{)tJ=VDf5EXC4cfJx5cw?-Vu7)jW*e@6!q++o@H6!&_Jx^iJVOKK-oID zD*$)ii9;^}^wN24Ux*@a=0VJ4r-=aA16SO_8hp5yqwcZPg8_x0l9y{sq|U(uAQ5EP*uvywX4d7{m8a1}kX{KUe6u><-@KpdKTHTrnJaBr?zZIBh zyM{Axsi^j|RNih~$=~XQNC2ZynKRvR1|ALI=yXrJQDaB6Opjf?=W{~p-dg=U1EXNG zTyWZDe%>O^TV#6A?}f^oZyUzId{H(^LbL+dVn?J*k6pdzbHeHVS`B01PXibQ00K6P zeYvNEwhM9bN%=L~+z*fW-#8ruO90>tHELGtH;FZHXgXFZSL;H=vw#5DyW}JqWHdkI z`qpqd2EH4>ob3?MOL^#Gl(N4zD7-Y@^S&^6ZfQdq__<~~Uq(#j}?851+yVTEwCKw{9Etn?(&xa?qbF)1hfDF zFu86pcovSIsYB1kfpyGeX#v#&ZH)(+@7O3upSfxZiChm3Gc~m*b zOtKF9wA(1$oGv!$sfVwOtQqnmvq;)&Y)`2-^CYt%@Ljn#8F<_b4k-_!ELE_o7_(#6k4!Rrd10&aCjAY=LN6xe7PcrZ)LF6$; zGH`4o)U)T$F>p`tBF4=nNLt{k1xPSYZ2Gb^V}kc;w`6|Q0$Vs`f)_Pdrkl$GD}XyK z*phkY>fB$b&1*T1(J6uwSrvbiQLQz@lLvFpwNR@I54GQVCN3GcX7k z9EbF>Z10X?tzI6sdoVBsi`D6GnOB~B3|YCBm^?&4Ov|?hl{U@4^Go?kxt2W82B%h! z+ZfooX~w&S#sU~pt_5K4-4=+iFt7wd+DYDXUM~&~?=#viK4_#tBr(1<*m!!c-DQm? zf%rBCMs9)BF3dw1Qp$^bhtx~!>?;gRr&EcUyyqtXZ<Qy@T!gUT#X(omR7;~8SOc#lGc*RBiGic?s0Q#&UI>Kgeu;r4#eai^g!Gwl~ZBR8VYz`&Zzs}}=H3n#nhiKsP(kmdml9#_<`(+_( zhS0QU)cKBRSd^hPZQGN9JrGB|3ZB-tcJPKWum@s926zj-76$g}rLEX!Vqgx6UJQJP zA2bw^NBbyGb4D87TWM&)g zh44H8qX3LZiO~#fY0ghGF!f6G@Is)0KhrU=1z>HPR{|Hpww4z{ip%g8bfdixR?NaT zGO#p5P0hd-fH{bV0JzZ5pq)5tbK)Brc*zNL~aqlvDFSPz@-pqVI@>Kp2>V1F07p56q*)qJCg& z4MFQ|#sinQY^$SsJ@bNcdN0`c=1FOXilp3Ac?)Ife9=JPdddqcO2LN2%`Q2X7s z6W3{_Wa{qmA$$LSeZV_Nz9)rWZ( zGq*A@&!;Q|TSQc0K=-($n(GbM2j0evid?U8MI~X;!P&c5Nxcnm4pIOvk`6 z#(gb^Fb~G%3|u~+nfclzyXJ0T;KE!7AlH&~0IpIFAKgqzF#zYz1VrH++ zvof$WQ%$9T3yTLEwVe;bHhv#D8eL+^3@>rm09ldH{%EX8FVONi=IrUEm+Tt#Akf)B)5uaAJSihR=e8Qoz!ByxU_4|%t!*hobC;X_o=;SB6)WJDWB{lJu25r1&27h*aMym$$YmDYkHX%k}CtW|oxAUhP^0YXV5 z3*H3cn)MEH(%e@V7}cTrqaL&^Hwnq)Vn}5u(#R4-&0m_ z()()$_qq5A1EYRj&;Kg zxF-V_c4^V9_2R4E6>BLk85ls9=(jyB$j)8{Z{J+gzKA9s$-o76n%CgGSz8-f^9p>L zfvs(7K0|#S1MkeSog#d_my{i273!!pJ{TAPScn3mg+Ix_$O>H2D{mlPSYY2#lT7}%Uc|Be9YJP%hfdg$E1Ag7T*XpO z#9E66raJVP8``$AH2_}y-fGv?vZMJujeR=<%g2HU*y#Rl6*_6T#Jsp*EY@P*;oF1Y zZD6%9aI^zQq;J)z-nu06+ym}D_{aWQJqKk?iFG`0?M0v(c^MQH=n%OfLnEq#M*u9} zNoL%;f34p34tUXJGLs%L5<1gTml~BD^%=VDUa(z`%r&(qaL*Pngy9|L+N6JV5OYzz z?B(ZlWDK$+H-{izr85bMIj_?M?M&l^6To+%;L1A&0GKS)gqQ{>Mq*#!ZTs~`Ieaq% zi%M&YPP@_(nYYaX0|30P!?_!&`n*M*Rq?vJvtF+95j%SXp}ZF(hXVumN*pIPJO*9_ znB0`EJBn?c+n&p4m(z7#*TT<1`wakaI|G}b-*%xE&?3=l<__TLEWWQYc)Eg84s7|EGj(SycK>)P~PGPX|a(2Sl(t6rkAcct-_^_f7 zSF_*eumpv8($W+PH*17IPG4F5U(n;B#hjrh!A+cb_vF zcj5%C2!WSO+u}5>ZNL!FMj4pD$6T-hTH2gh1aR}s5hk|=XyCe$T70m5msy)8mOxyQ zil;?24J+sX$%fAza~38F9eqzK%56OLl`cz-|<3747{t_ z7YfqEa9Ru;S%8eX99qh1KJGf~Y<(nVcasMo_|VC^|np9>mzzMVLX)ympITtf&^ zXI1)BEX7sUrFFiGfj#+PXiib?c(abj*oH>dwuiqb7Q*AU)dDpm%QxxJdxA^2AqRU+ z3SP%~bz{$aF|ZdK0r^X{*aKq$=*bn&t6|16c=hpi@@((JE*;07O11&RU1^j|4((f) zL3M7$wQc}K5WK7K33?&WO$R>EjC|T4;?u3RIRR;4K5JcI;Oc$GHn%o-Sbc~4fqmFS z7@7YXQD?^Gm5nm62zsE79!NdS>KpmY0^0u4?cdw>nZyqqw(#mb*r(RQ5LG~Lw9tn1 zQ3h^!#gHsOOoF(1;~#f~k0*iNp$9PVkRHsJKEwhKW#ETcH>>$^3#>tjou&go&3(K< z`GViFz!p{8PrD?De+xjPTf2v}EW5QGnD`^!s?k=;_fKm98k4nNQ{Mr^r@*r9EgrZ( z{eG=pzw*6j|F!!`$lj!|rB|<30516b6o@@}(MyYes{T(e*R%iL|C2YAw&MigPlDKE zfMnpYGvHS+Fr77eGor@;z27%Ek$hCHNwUbZ|JN|EBz<~-D;fB+4C`rm&;Czj;Q!^n V6U{I?5Ptvw002ovPDHLkV1nnu{g40v literal 5630 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 Y2PMNWz8ZN*QUCw|07*qoM6N<$f+ZW)KmY&$ From 5e00b6d13658122ea7c645f25cff77704af7690e Mon Sep 17 00:00:00 2001 From: David Peer Date: Wed, 5 Jan 2022 11:54:56 +0100 Subject: [PATCH 168/489] Minor changes --- apps/lcars/lcars.app.js | 4 ++-- apps/lcars/screenshot.png | Bin 5835 -> 6073 bytes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 1be2cfd43..57e56d76c 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -251,7 +251,7 @@ function drawPosition0(){ var currentDate = new Date(); var timeStr = locale.time(currentDate,1); g.setFontAntonioLarge(); - g.drawString(timeStr, 28, 10); + g.drawString(timeStr, 29, 10); // Write date g.setColor(cWhite); @@ -259,7 +259,7 @@ function drawPosition0(){ var dayStr = locale.dow(currentDate, true).toUpperCase(); dayStr += " " + currentDate.getDate(); dayStr += " " + currentDate.getFullYear(); - g.drawString(dayStr, 29, 56); + g.drawString(dayStr, 32, 56); // Draw data g.setFontAlign(-1, -1, 0); diff --git a/apps/lcars/screenshot.png b/apps/lcars/screenshot.png index 8531913133233045e6ce34b5b99d4dc491432603..c749e14517cb8b47035dc15128c5b2ada0ac6061 100644 GIT binary patch literal 6073 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 V6U{I?5Ptvw002ovPDHLkV1nnu{g40v From cf41ff2bc683c1da8664a3db06d6350512920a38 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Wed, 5 Jan 2022 12:09:21 +0100 Subject: [PATCH 169/489] weather: fix widget icon --- apps.json | 2 +- apps/weather/ChangeLog | 1 + apps/weather/lib.js | 75 ++++++++++++++++++++++++++---------------- apps/weather/widget.js | 4 +-- 4 files changed, 50 insertions(+), 32 deletions(-) diff --git a/apps.json b/apps.json index f116049dc..ed5deec79 100644 --- a/apps.json +++ b/apps.json @@ -845,7 +845,7 @@ { "id": "weather", "name": "Weather", - "version": "0.14", + "version": "0.15", "description": "Show Gadgetbridge weather report", "icon": "icon.png", "screenshots": [{"url":"screenshot.png"}], diff --git a/apps/weather/ChangeLog b/apps/weather/ChangeLog index 910cd4658..101da48e1 100644 --- a/apps/weather/ChangeLog +++ b/apps/weather/ChangeLog @@ -11,3 +11,4 @@ 0.12: Allow hiding the widget 0.13: Tweak Bangle.js 2 light theme colors 0.14: Use weather condition code for icon selection +0.15: Fix widget icon diff --git a/apps/weather/lib.js b/apps/weather/lib.js index 8afdfe6df..1d48116e1 100644 --- a/apps/weather/lib.js +++ b/apps/weather/lib.js @@ -53,6 +53,16 @@ exports.get = function() { scheduleExpiry(storage.readJSON('weather.json')||{}); +/** + * + * @param cond Weather condition, as one of: + * {number} code: (Preferred form) https://openweathermap.org/weather-conditions#Weather-Condition-Codes-2 + * {string} weather description (in English: breaks for other languages!) + * {object} use cond.code if present, or fall back to cond.txt + * @param x Left + * @param y Top + * @param r Icon Size + */ exports.drawIcon = function(cond, x, y, r) { var palette; @@ -249,32 +259,35 @@ exports.drawIcon = function(cond, x, y, r) { g.setColor(g.theme.fg).setFontAlign(0, 0).setFont('Vector', r*2).drawString("?", x+r/10, y+r/6); } - function chooseIcon(condition) { - if (!condition) return () => {}; - condition = condition.toLowerCase(); - if (condition.includes("thunderstorm")) return drawThunderstorm; - if (condition.includes("freezing")||condition.includes("snow")|| - condition.includes("sleet")) { + /* + * Choose weather icon to display based on weather description + */ + function chooseIconByTxt(txt) { + if (!txt) return () => {}; + txt = txt.toLowerCase(); + if (txt.includes("thunderstorm")) return drawThunderstorm; + if (txt.includes("freezing")||txt.includes("snow")|| + txt.includes("sleet")) { return drawSnow; } - if (condition.includes("drizzle")|| - condition.includes("shower")) { + if (txt.includes("drizzle")|| + txt.includes("shower")) { return drawRain; } - if (condition.includes("rain")) return drawShowerRain; - if (condition.includes("clear")) return drawSun; - if (condition.includes("few clouds")) return drawFewClouds; - if (condition.includes("scattered clouds")) return drawCloud; - if (condition.includes("clouds")) return drawBrokenClouds; - if (condition.includes("mist") || - condition.includes("smoke") || - condition.includes("haze") || - condition.includes("sand") || - condition.includes("dust") || - condition.includes("fog") || - condition.includes("ash") || - condition.includes("squalls") || - condition.includes("tornado")) { + if (txt.includes("rain")) return drawShowerRain; + if (txt.includes("clear")) return drawSun; + if (txt.includes("few clouds")) return drawFewClouds; + if (txt.includes("scattered clouds")) return drawCloud; + if (txt.includes("clouds")) return drawBrokenClouds; + if (txt.includes("mist") || + txt.includes("smoke") || + txt.includes("haze") || + txt.includes("sand") || + txt.includes("dust") || + txt.includes("fog") || + txt.includes("ash") || + txt.includes("squalls") || + txt.includes("tornado")) { return drawMist; } return drawUnknown; @@ -298,7 +311,6 @@ exports.drawIcon = function(cond, x, y, r) { case 531: return drawShowerRain; default: return drawRain; } - break; case 6: return drawSnow; case 7: return drawMist; case 8: @@ -308,16 +320,21 @@ exports.drawIcon = function(cond, x, y, r) { case 802: return drawCloud; default: return drawBrokenClouds; } - break; default: return drawUnknown; } } - if (cond.code && cond.code > 0) { - chooseIconByCode(cond.code)(x, y, r); - } else { - chooseIcon(cond.txt)(x, y, r); + function chooseIcon(cond) { + if (typeof (cond)==="object") { + if ("code" in cond) return chooseIconByCode(cond.code); + if ("txt" in cond) return chooseIconByTxt(cond.txt); + } else if (typeof (cond)==="number") { + return chooseIconByCode(cond.code); + } else if (typeof (cond)==="string") { + return chooseIconByTxt(cond.txt); + } + return drawUnknown; } - + chooseIcon(cond)(x, y, r); }; diff --git a/apps/weather/widget.js b/apps/weather/widget.js index f2ddf0b5b..2905d776b 100644 --- a/apps/weather/widget.js +++ b/apps/weather/widget.js @@ -52,8 +52,8 @@ if (!w) return; g.reset(); g.clearRect(this.x, this.y, this.x+this.width-1, this.y+23); - if (w.txt) { - weather.drawIcon(w.txt, this.x+10, this.y+8, 7.5); + if (w.code||w.txt) { + weather.drawIcon(w, this.x+10, this.y+8, 7.5); } if (w.temp) { let t = require('locale').temp(w.temp-273.15); // applies conversion From 71504a7414dc35d136ae1cd45b991289fab1ec9a Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 12:16:14 +0100 Subject: [PATCH 170/489] Setting to toggle visibility of widgets Setting to set minimal heart rate --- apps/circlesclock/app.js | 45 +++++++++++++++++++++-------------- apps/circlesclock/settings.js | 18 ++++++++++++++ 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 026b47cc6..f123e0c2a 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -8,12 +8,13 @@ const powerIconGreen = heatshrink.decompress(atob("h0OwYQNkAEDpAEDiQEDkmSAgUJkmA const powerIconRed = heatshrink.decompress(atob("h0OwYQNoAEDyAEDkgEDpIFDiVJBweSAgUJkmAAoYZDgQpEBwYAJA")); let settings; - function loadSettings() { settings = require("Storage").readJSON("circlesclock.json", 1) || { + 'minHR': 40, 'maxHR': 200, 'stepGoal': 10000, - 'batteryWarn': 30 + 'batteryWarn': 30, + 'showWidgets': false }; // Load step goal from pedometer widget as fallback if (settings.stepGoal == undefined) { @@ -21,18 +22,21 @@ function loadSettings() { settings.stepGoal = d != undefined && d.settings != undefined ? d.settings.goal : 10000; } } +loadSettings(); +const showWidgets = settings.showWidgets || false; +let hrtValue; + +// layout values: const colorFg = g.theme.dark ? '#fff' : '#000'; const colorBg = g.theme.dark ? '#000' : '#fff'; const colorGrey = '#808080'; const colorRed = '#ff0000'; const colorGreen = '#00ff00'; - -let hrtValue; - -const h = g.getHeight(); +const widgetOffset = showWidgets ? 12 : 0; +const h = g.getHeight() - widgetOffset; const w = g.getWidth(); -const hOffset = 30; +const hOffset = 30 - widgetOffset; const h1 = Math.round(1 * h / 5 - hOffset); const h2 = Math.round(3 * h / 5 - hOffset); const h3 = Math.round(8 * h / 8 - hOffset); @@ -102,7 +106,7 @@ function drawHeartRate() { g.fillCircle(w2, h3, radiusOuter); if (hrtValue != undefined && hrtValue > 0) { - const minHR = 40; + const minHR = settings.minHR || 40; const percent = (hrtValue - minHR) / (settings.maxHR - minHR); drawGauge(w2, h3, percent, colorRed); } @@ -233,19 +237,24 @@ Bangle.on('charging', function(charging) { }); g.clear(); + + Bangle.loadWidgets(); -/* - * 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 (typeof WIDGETS === "object") { - for (let wd of WIDGETS) { - wd.draw = () => {}; - wd.area = ""; +if (!showWidgets) { + /* + * 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 = ""; + } } } -loadSettings(); + + setInterval(draw, 60000); draw(); Bangle.setUI("clock"); diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index ffda51538..15596ff18 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -8,6 +8,16 @@ } E.showMenu({ '': { 'title': 'circlesclock' }, + 'min heartrate': { + value: "minHR" in settings ? settings.minHR : 40, + min: 0, + max : 250, + step: 10, + format: x => { + return x; + }, + onchange: x => save('minHR', x), + }, 'max heartrate': { value: "maxHR" in settings ? settings.maxHR : 200, min: 20, @@ -38,6 +48,14 @@ }, onchange: x => save('batteryWarn', x), }, + 'show widgets': { + value: "showWidgets" in settings ? settings.showWidgets : false, + format: () => (settings.showWidgets ? 'Yes' : 'No'), + onchange: () => { + settings.showWidgets = !settings.showWidgets; + save('showWidgets', settings.showWidgets); + }, + }, '< Back': back, }); }); From c41bae14c9e6c5a0dc8d33163415a03787baa632 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 12:16:38 +0100 Subject: [PATCH 171/489] Update README --- apps/circlesclock/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/circlesclock/README.md b/apps/circlesclock/README.md index 66d9afe08..df47c369b 100644 --- a/apps/circlesclock/README.md +++ b/apps/circlesclock/README.md @@ -8,13 +8,11 @@ It shows besides time, date and day of week the following information: * Battery (including charging and battery low) ## Screenshot - ![Screenshot](screenshot.png) ## TODO * Show weather information * Configure which information to show in each circle -* Configure visibility of widgets ## Creator Marco ([myxor](https://github.com/myxor)) From e0130c451025ecbd6ef04dba4ddbcaa08f6d5004 Mon Sep 17 00:00:00 2001 From: David Peer Date: Wed, 5 Jan 2022 12:30:31 +0100 Subject: [PATCH 172/489] Minor changes. --- apps/lcars/lcars.app.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 57e56d76c..0b8c814cd 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -210,16 +210,16 @@ function drawState(){ hours % 4 == 1 ? iconMars : hours % 4 == 2 ? iconMoon : iconEarth; - g.drawImage(iconImg, 23, 118); + g.drawImage(iconImg, 24, 118); g.setColor(cWhite); - g.drawString("STATUS", 23+25, 108); + g.drawString("STATUS", 24+25, 108); } else { // Alarm within symbol g.setColor(cOrange); - g.drawString("ALARM", 23+25, 108); + g.drawString("ALARM", 24+25, 108); g.setColor(cWhite); g.setFontAntonioLarge(); - g.drawString(getAlarmMinutes(), 23+25, 108+35); + g.drawString(getAlarmMinutes(), 24+25, 108+35); } g.setFontAlign(-1, -1, 0); From fea7c2dcf817fbb9e6fe402fae1d79bf8089cab2 Mon Sep 17 00:00:00 2001 From: The Dod Date: Wed, 5 Jan 2022 13:49:02 +0200 Subject: [PATCH 173/489] typo fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 😖 --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 04cc12a37..b0ebce263 100644 --- a/apps.json +++ b/apps.json @@ -5139,6 +5139,7 @@ {"name":"fourTwenty","url":"fourTwenty.js"}, {"name":"fourTwentyTz","url":"fourTwentyTz.js"}, {"name":"ftclock.img","url":"app-icon.js","evaluate":true} + ] }, { "id": "slash", From 766d3cc1892874b5a8be3f611c3e4335da236c80 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 13:27:50 +0100 Subject: [PATCH 174/489] Make the types of the circles configurable --- apps/circlesclock/app.js | 163 ++++++++++++++++++++++++---------- apps/circlesclock/settings.js | 29 ++++++ 2 files changed, 144 insertions(+), 48 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index f123e0c2a..58055e96e 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -14,7 +14,10 @@ function loadSettings() { 'maxHR': 200, 'stepGoal': 10000, 'batteryWarn': 30, - 'showWidgets': false + 'showWidgets': false, + 'circle1': 'hr', + 'circle2': 'steps', + 'circle3': 'battery' }; // Load step goal from pedometer widget as fallback if (settings.stepGoal == undefined) { @@ -32,7 +35,9 @@ const colorFg = g.theme.dark ? '#fff' : '#000'; const colorBg = g.theme.dark ? '#000' : '#fff'; const colorGrey = '#808080'; const colorRed = '#ff0000'; -const colorGreen = '#00ff00'; +const colorGreen = '#008000'; +const colorBlue = '#0000ff'; +const colorYellow = '#ffff00'; const widgetOffset = showWidgets ? 12 : 0; const h = g.getHeight() - widgetOffset; const w = g.getWidth(); @@ -63,82 +68,137 @@ function draw() { g.drawString(locale.date(new Date()), w / 10, h2); g.drawString(locale.dow(new Date()), w / 10, h2 + 22); - // Steps circle - drawSteps(); - - // Heart circle - drawHeartRate(); - - // Battery circle - drawBattery(); + drawCircle(1, "steps"); + drawCircle(2, "hr"); + drawCircle(3, "battery"); } +function drawCircle(index, defaultType) { + const type = settings['circle' + index] || defaultType; + const w = index == 1 ? w1: index == 2 ? w2 : w3; -function drawSteps() { + switch (type) { + case "steps": + drawSteps(w); + break; + case "stepsDist": + drawStepsDistance(w); + break; + case "hr": + drawHeartRate(w); + break; + case "battery": + drawBattery(w); + break; + } +} +function getCirclePosition(type, defaultPos) { + for (let i = 1; i <= 3; i++) { + const setting = settings['circle' + i]; + if (setting == type) return i; + } + return defaultPos; +} + +function isCircleEnabled(type) { + return getCirclePosition(type) != undefined; +} + +function drawSteps(w) { + if (!w) w = getCirclePosition("steps", w1); const steps = getSteps(); - const blue = '#0000ff'; g.setColor(colorGrey); - g.fillCircle(w1, h3, radiusOuter); + g.fillCircle(w, h3, radiusOuter); const stepGoal = settings.stepGoal || 10000; if (stepGoal > 0) { let percent = steps / stepGoal; if (stepGoal < steps) percent = 1; - drawGauge(w1, h3, percent, blue); + drawGauge(w, h3, percent, colorBlue); } g.setColor(colorBg); - g.fillCircle(w1, h3, radiusInner); + g.fillCircle(w, h3, radiusInner); - g.fillPoly([w1, h3, w1 - 15, h3 + radiusOuter + 5, w1 + 15, h3 + radiusOuter + 5]); + g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); g.setFont("Vector:12"); g.setFontAlign(0, 0); g.setColor(colorFg); - g.drawString(shortValue(steps), w1 + 2, h3); + g.drawString(shortValue(steps), w + 2, h3); - g.drawImage(shoesIcon, w1 - 6, h3 + radiusOuter - 6); + g.drawImage(shoesIcon, w - 6, h3 + radiusOuter - 6); } -function drawHeartRate() { +function drawStepsDistance(w) { + if (!w) w = getCirclePosition("steps", w1); + const steps = getSteps(); + const stepDistance = 0.8; // TODO make configurable + const stepsDistance = steps * stepDistance; + g.setColor(colorGrey); - g.fillCircle(w2, h3, radiusOuter); + g.fillCircle(w, h3, radiusOuter); + + const stepDistanceGoal = settings.stepDistanceGoal || 5; + if (stepDistanceGoal > 0) { + let percent = stepsDistance / stepDistanceGoal; + if (stepDistanceGoal < stepsDistance) percent = 1; + drawGauge(w, h3, percent, colorGreen); + } + + g.setColor(colorBg); + g.fillCircle(w, h3, radiusInner); + + g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); + + g.setFont("Vector:12"); + g.setFontAlign(0, 0); + g.setColor(colorFg); + g.drawString(shortValue(stepsDistance), w + 2, h3); + + g.drawImage(shoesIcon, w - 6, h3 + radiusOuter - 6); +} + +function drawHeartRate(w) { + if (!w) w = getCirclePosition("hr", w2); + g.setColor(colorGrey); + g.fillCircle(w, h3, radiusOuter); if (hrtValue != undefined && hrtValue > 0) { const minHR = settings.minHR || 40; const percent = (hrtValue - minHR) / (settings.maxHR - minHR); - drawGauge(w2, h3, percent, colorRed); + drawGauge(w, h3, percent, colorRed); } g.setColor(colorBg); - g.fillCircle(w2, h3, radiusInner); + g.fillCircle(w, h3, radiusInner); - g.fillPoly([w2, h3, w2 - 15, h3 + radiusOuter + 5, w2 + 15, h3 + radiusOuter + 5]); + g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); g.setFont("Vector:12"); g.setFontAlign(0, 0); g.setColor(colorFg); - g.drawString(hrtValue != undefined ? hrtValue : "-", w2, h3); + g.drawString(hrtValue != undefined ? hrtValue : "-", w, h3); - g.drawImage(heartIcon, w2 - 6, h3 + radiusOuter - 6); + g.drawImage(heartIcon, w - 6, h3 + radiusOuter - 6); } -function drawBattery() { +function drawBattery(w) { + if (!w) w = getCirclePosition("battery", w3); const battery = E.getBattery(); - const yellow = '#ffff00'; g.setColor(colorGrey); - g.fillCircle(w3, h3, radiusOuter); + g.fillCircle(w, h3, radiusOuter); if (battery > 0) { const percent = battery / 100; - drawGauge(w3, h3, percent, yellow); + drawGauge(w, h3, percent, colorYellow); } g.setColor(colorBg); - g.fillCircle(w3, h3, radiusInner); + g.fillCircle(w, h3, radiusInner); - g.fillPoly([w3, h3, w3 - 15, h3 + radiusOuter + 5, w3 + 15, h3 + radiusOuter + 5]); + g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); g.setFont("Vector:12"); g.setFontAlign(0, 0); @@ -156,9 +216,9 @@ function drawBattery() { } } g.setColor(color); - g.drawString(battery + '%', w3, h3); + g.drawString(battery + '%', w, h3); - g.drawImage(icon, w3 - 6, h3 + radiusOuter - 6); + g.drawImage(icon, w - 6, h3 + radiusOuter - 6); } function radians(a) { @@ -210,30 +270,37 @@ function getSteps() { Bangle.on('lock', function(isLocked) { if (!isLocked) { - Bangle.setHRMPower(1, "watch"); - if (hrtValue == undefined) { - hrtValue = '...'; - drawHeartRate(); + if (isCircleEnabled("hr")) { + Bangle.setHRMPower(1, "watch"); + if (hrtValue == undefined) { + hrtValue = '...'; + drawHeartRate(); + } } } else { - Bangle.setHRMPower(0, "watch"); + if (isCircleEnabled("hr")) { + Bangle.setHRMPower(0, "watch"); + } } - drawHeartRate(); - drawSteps(); + if (isCircleEnabled("hr")) drawHeartRate(); + if (isCircleEnabled("steps")) drawSteps(); + if (isCircleEnabled("stepsDistance")) drawStepsDistance(); }); Bangle.on('HRM', function(hrm) { - //if(hrm.confidence > 90){ - hrtValue = hrm.bpm; - if (Bangle.isLCDOn()) - drawHeartRate(); - //} else { - // hrtValue = undefined; - //} + if (isCircleEnabled("hr")) { + //if(hrm.confidence > 90){ + hrtValue = hrm.bpm; + if (Bangle.isLCDOn()) + drawHeartRate(); + //} else { + // hrtValue = undefined; + //} + } }); Bangle.on('charging', function(charging) { - drawBattery(); + if (isCircleEnabled("battery")) drawBattery(); }); g.clear(); diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index 15596ff18..754fa0c69 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -6,6 +6,8 @@ settings[key] = value; storage.write(SETTINGS_FILE, settings); } + var valuesCircleTypes = ["steps", "stepsDist", "hr", "battery"]; + var namesCircleTypes = ["steps", "step distance", "heart", "battery"]; E.showMenu({ '': { 'title': 'circlesclock' }, 'min heartrate': { @@ -56,6 +58,33 @@ save('showWidgets', settings.showWidgets); }, }, + 'Left circle': { + value: Math.max(0,0 | valuesCircleTypes.indexOf(settings.circle1)), + min: 0, max: 3, + format: v => namesCircleTypes[v], + onchange: v => { + settings.circle1 = valuesCircleTypes[v]; + save('circle1', settings.circle1); + } + }, + 'Middle circle': { + value: Math.max(0,0 | valuesCircleTypes.indexOf(settings.circle2)), + min: 0, max: 3, + format: v => namesCircleTypes[v], + onchange: v => { + settings.circle2 = valuesCircleTypes[v]; + save('circle2', settings.circle2); + } + }, + 'Right circle': { + value: Math.max(0,0 | valuesCircleTypes.indexOf(settings.circle3)), + min: 0, max: 3, + format: v => namesCircleTypes[v], + onchange: v => { + settings.circle3 = valuesCircleTypes[v]; + save('circle3', settings.circle3); + } + }, '< Back': back, }); }); From ee252a3a97fc3880c7744ed79966e6f25bb6e8da Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 14:04:04 +0100 Subject: [PATCH 175/489] Fix position, default settings and add green step distance icon --- apps/circlesclock/app.js | 5 +++-- apps/circlesclock/settings.js | 14 +++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 58055e96e..686de735b 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -2,6 +2,7 @@ const locale = require("locale"); const heatshrink = require("heatshrink"); const shoesIcon = heatshrink.decompress(atob("h0OwYJGgmAAgUBkgECgVJB4cSoAUDyEBkARDpADBhMAyQRBgVAkgmDhIUDAAuQAgY1DAAYA=")); +const shoesIconGreen = heatshrink.decompress(atob("h0OwYJGhIEDgVIAgUEyQKDkmACgcggVACIeQAYMSgIRCgmApIbDiQUDAAkBkAFDGoYAD")); const heartIcon = heatshrink.decompress(atob("h0OwYOLkmQhMkgACByVJgESpIFBpEEBAIFBCgIFCCgsABwcAgQOCAAMSpAwDyBNM")); const powerIcon = heatshrink.decompress(atob("h0OwYQNsAED7AEDmwEDtu2AgUbtuABwXbBIUN23AAoYOCgEDFIgODABI")); const powerIconGreen = heatshrink.decompress(atob("h0OwYQNkAEDpAEDiQEDkmSAgUJkmABwVJBIUEyVAAoYOCgEBFIgODABI")); @@ -96,7 +97,7 @@ function drawCircle(index, defaultType) { function getCirclePosition(type, defaultPos) { for (let i = 1; i <= 3; i++) { const setting = settings['circle' + i]; - if (setting == type) return i; + if (setting == type) return i == 1 ? w1: i == 2 ? w2 : w3; } return defaultPos; } @@ -157,7 +158,7 @@ function drawStepsDistance(w) { g.setColor(colorFg); g.drawString(shortValue(stepsDistance), w + 2, h3); - g.drawImage(shoesIcon, w - 6, h3 + radiusOuter - 6); + g.drawImage(shoesIconGreen, w - 6, h3 + radiusOuter - 6); } function drawHeartRate(w) { diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index 754fa0c69..3ddacd29c 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -7,7 +7,7 @@ storage.write(SETTINGS_FILE, settings); } var valuesCircleTypes = ["steps", "stepsDist", "hr", "battery"]; - var namesCircleTypes = ["steps", "step distance", "heart", "battery"]; + var namesCircleTypes = ["steps", "distance", "heart", "battery"]; E.showMenu({ '': { 'title': 'circlesclock' }, 'min heartrate': { @@ -40,7 +40,7 @@ }, onchange: x => save('stepGoal', x), }, - 'battery warn lvl': { + 'battery warn': { value: "batteryWarn" in settings ? settings.batteryWarn : 30, min: 10, max : 100, @@ -58,7 +58,7 @@ save('showWidgets', settings.showWidgets); }, }, - 'Left circle': { + 'left': { value: Math.max(0,0 | valuesCircleTypes.indexOf(settings.circle1)), min: 0, max: 3, format: v => namesCircleTypes[v], @@ -67,8 +67,8 @@ save('circle1', settings.circle1); } }, - 'Middle circle': { - value: Math.max(0,0 | valuesCircleTypes.indexOf(settings.circle2)), + 'middle': { + value: Math.max(0,2 | valuesCircleTypes.indexOf(settings.circle2)), min: 0, max: 3, format: v => namesCircleTypes[v], onchange: v => { @@ -76,8 +76,8 @@ save('circle2', settings.circle2); } }, - 'Right circle': { - value: Math.max(0,0 | valuesCircleTypes.indexOf(settings.circle3)), + 'right': { + value: Math.max(0,3 | valuesCircleTypes.indexOf(settings.circle3)), min: 0, max: 3, format: v => namesCircleTypes[v], onchange: v => { From 3538c6024fe36715a82d0d2018862cab2992f944 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 14:14:47 +0100 Subject: [PATCH 176/489] Configuration of stepDistanceGoal and stepLength --- apps/circlesclock/app.js | 6 ++++-- apps/circlesclock/settings.js | 40 +++++++++++++++++++++-------------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 686de735b..3099b02ea 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -14,6 +14,8 @@ function loadSettings() { 'minHR': 40, 'maxHR': 200, 'stepGoal': 10000, + 'stepDistanceGoal': 8000, + 'stepLength': 0.8, 'batteryWarn': 30, 'showWidgets': false, 'circle1': 'hr', @@ -135,13 +137,13 @@ function drawSteps(w) { function drawStepsDistance(w) { if (!w) w = getCirclePosition("steps", w1); const steps = getSteps(); - const stepDistance = 0.8; // TODO make configurable + const stepDistance = settings.stepLength || 0.8; const stepsDistance = steps * stepDistance; g.setColor(colorGrey); g.fillCircle(w, h3, radiusOuter); - const stepDistanceGoal = settings.stepDistanceGoal || 5; + const stepDistanceGoal = settings.stepDistanceGoal || 8000; if (stepDistanceGoal > 0) { let percent = stepsDistance / stepDistanceGoal; if (stepDistanceGoal < stepsDistance) percent = 1; diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index 3ddacd29c..dc75f54af 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -40,6 +40,26 @@ }, onchange: x => save('stepGoal', x), }, + 'step length': { + value: "stepLength" in settings ? settings.stepLength : 0.8, + min: 0.1, + max : 1.5, + step: 0.01, + format: x => { + return x; + }, + onchange: x => save('stepLength', x), + }, + 'step dist goal': { + value: "stepDistanceGoal" in settings ? settings.stepDistanceGoal : 8000, + min: 2000, + max : 30000, + step: 1000, + format: x => { + return x; + }, + onchange: x => save('stepDistanceGoal', x), + }, 'battery warn': { value: "batteryWarn" in settings ? settings.batteryWarn : 30, min: 10, @@ -53,37 +73,25 @@ 'show widgets': { value: "showWidgets" in settings ? settings.showWidgets : false, format: () => (settings.showWidgets ? 'Yes' : 'No'), - onchange: () => { - settings.showWidgets = !settings.showWidgets; - save('showWidgets', settings.showWidgets); - }, + onchange: x => save('showWidgets', x), }, 'left': { value: Math.max(0,0 | valuesCircleTypes.indexOf(settings.circle1)), min: 0, max: 3, format: v => namesCircleTypes[v], - onchange: v => { - settings.circle1 = valuesCircleTypes[v]; - save('circle1', settings.circle1); - } + onchange: x => save('circle1', x), }, 'middle': { value: Math.max(0,2 | valuesCircleTypes.indexOf(settings.circle2)), min: 0, max: 3, format: v => namesCircleTypes[v], - onchange: v => { - settings.circle2 = valuesCircleTypes[v]; - save('circle2', settings.circle2); - } + onchange: x => save('circle2', x), }, 'right': { value: Math.max(0,3 | valuesCircleTypes.indexOf(settings.circle3)), min: 0, max: 3, format: v => namesCircleTypes[v], - onchange: v => { - settings.circle3 = valuesCircleTypes[v]; - save('circle3', settings.circle3); - } + onchange: x => save('circle3', x), }, '< Back': back, }); From f174cb56fbd586f7e6a357a73129f9d5d6ab244d Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 14:14:56 +0100 Subject: [PATCH 177/489] Update README --- apps/circlesclock/README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/circlesclock/README.md b/apps/circlesclock/README.md index df47c369b..86c388440 100644 --- a/apps/circlesclock/README.md +++ b/apps/circlesclock/README.md @@ -2,17 +2,19 @@ A clock with circles for different data at the bottom in a probably familiar style -It shows besides time, date and day of week the following information: +By default the time, date and day of week is shown. + +It can show the following information (this can be configured): * Steps (requires [pedometer widget](https://banglejs.com/apps/#pedometer)) - * Heart rate (when screen is on and unlocked) - * Battery (including charging and battery low) + * Steps distance (depending on steps) + * Heart rate (automatically updates when screen is on and unlocked) + * Battery (including charging status and battery low warning) ## Screenshot ![Screenshot](screenshot.png) ## TODO * Show weather information -* Configure which information to show in each circle ## Creator Marco ([myxor](https://github.com/myxor)) From ad371e9678cb380ea064ed01cbe6b7df385b4d56 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 14:21:01 +0100 Subject: [PATCH 178/489] Update changelog and bump version --- apps.json | 2 +- apps/circlesclock/ChangeLog | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index f116049dc..c6600ada0 100644 --- a/apps.json +++ b/apps.json @@ -5071,7 +5071,7 @@ { "id": "circlesclock", "name": "Circles clock", "shortName":"Circles clock", - "version":"0.03", + "version":"0.04", "description": "A clock with circles for different data at the bottom in a probably familiar style", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}], diff --git a/apps/circlesclock/ChangeLog b/apps/circlesclock/ChangeLog index c0aa4e2f8..f416929ac 100644 --- a/apps/circlesclock/ChangeLog +++ b/apps/circlesclock/ChangeLog @@ -1,3 +1,4 @@ 0.01: New clock 0.02: Fix icon & add battery warn functionality 0.03: Theming support & minor fixes +0.04: Make configurable what to show in each circle; add step distance circle; allow switching visibility of widgets From 3ba696ed0e29c6916726412d35895c48d74d8560 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 14:30:02 +0100 Subject: [PATCH 179/489] Fix settings --- apps/circlesclock/settings.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index dc75f54af..0c42319f5 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -79,19 +79,19 @@ value: Math.max(0,0 | valuesCircleTypes.indexOf(settings.circle1)), min: 0, max: 3, format: v => namesCircleTypes[v], - onchange: x => save('circle1', x), + onchange: x => save('circle1', valuesCircleTypes[x]), }, 'middle': { value: Math.max(0,2 | valuesCircleTypes.indexOf(settings.circle2)), min: 0, max: 3, format: v => namesCircleTypes[v], - onchange: x => save('circle2', x), + onchange: x => save('circle2', valuesCircleTypes[x]), }, 'right': { value: Math.max(0,3 | valuesCircleTypes.indexOf(settings.circle3)), min: 0, max: 3, format: v => namesCircleTypes[v], - onchange: x => save('circle3', x), + onchange: x => save('circle3', valuesCircleTypes[x]), }, '< Back': back, }); From 793e8c82468a5e9349f3d5d53ba0b92ed264e68d Mon Sep 17 00:00:00 2001 From: David Peer Date: Wed, 5 Jan 2022 14:30:43 +0100 Subject: [PATCH 180/489] Show battery grey --- apps/lcars/lcars.app.js | 3 ++- apps/lcars/screenshot.png | Bin 6073 -> 5918 bytes 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 0b8c814cd..49d32dbe9 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -24,6 +24,7 @@ let cOrange = "#FF9900"; let cPurple = "#FF00DC"; let cWhite = "#FFFFFF"; let cBlack = "#000000"; +let cGrey = "#9E9E9E"; /* * Global lcars variables @@ -240,7 +241,7 @@ function drawPosition0(){ var bat = E.getBattery() / 100.0; var batX2 = parseInt((172 - 35) * bat + 35); drawHorizontalBgLine(cOrange, 35, batX2, 171, 5); - drawHorizontalBgLine(cPurple, batX2+10, 172, 171, 5); + drawHorizontalBgLine(cGrey, batX2+10, 172, 171, 5); // Draw logo drawLock(); diff --git a/apps/lcars/screenshot.png b/apps/lcars/screenshot.png index c749e14517cb8b47035dc15128c5b2ada0ac6061..fea3ebb78a5d48859e2d27f622a0c10e34270cd0 100644 GIT binary patch literal 5918 zcmV+(7vboMP)Py0*hxe|RCr$PUE!Lfst%la|A*fFx@|PZBvk=y(P4kwbEgG_P!vTH_4nuJ=id+d z_wV1&&+n(?{O@A1JK5pgS@iGU{l+C=>5T54gSr*CzOony0N<3P3XkjoeAB_)jv2oK z-q+L;0Dc+oTm9*HpCf=Lc<&_-C@>HJzUjR00eto#C?-H!ZC;-i*etLCxGQ*x6+dTT zTA+gk764E1b};2^;tC7={`~v*uivSCGVc|W_?Peb`}3k->L5V)fv3j(%UHT(?2~~n zG5fq}FAGct?q$i@&LtL@4BXl5uOo%`@Ao%%M(EjA=V1=h+^`I+Coens+QJqXTH9pq zVa+tUZvdG8so#29CTDA%R8N*8@^JfEn7)sDQ* zw(}~7_N*ZpxHnsRfat|u8Nd}ldH3$w76aZlc0b^=z+!>d0=q7!LF~07LCS($j%z3e zK1=gm0bmKx%z{K^(RCKIvRuT#npr)j)!_3Oy8Ldnqx*q&hSwM_XJD3bTG;Yx052?e zJlt7hLgmo)DgYA=9Y^P|7b^TgGWxU&I#7ONLyvVf{Br$NrPlL0cr zz!7sw8B&5`h=D({d#Al80~@n80gR!{XyD1fjvXy;Lr<2u6M&g*1d_KN0C>}aCoWWU(fk}F;ty@A5C z*Q*S&%K^Y08CV|ZEH4Gp(kqD-B!ghapJCt$U?0|51};H24K@wV$Yu5zFT`04%p49Q z4a~4%hUu90dX>ra%VSIgPAh_@4`>ksTle++z)_g{u?(!`!(y<#G`SMMH9-t(46ol> z52G0djv{mV$(~*e9BJXlYT%Io%rGkpPPVNK3%B@zqZ|jxoYo>ikvEhe^j^GIN8-+q z5FXQJ7&rp}b_}IlCXr|KNSpi;N^;=oyY5>;;PndBtWwPeC zvcNoVfd-W)KbWv^qxhoj>Y!J4z|0pj6k_hN}iy={6=H3iAnKGy^w%6qN(r)Ilplq-LXiX28jm zVT^{n3}<>67?7vO@S(*h)sc}049F(~JF~-plPR<5JuWAi1r$@RSD7?`RX%W*Nv+3( ziadyNAY`zDd4%2?*JBwtJBhV92Mp+zZ4)nuUS+al_rktNqek_LJV3b;Q8{KDkJZ4; z;ANQ+0BixhwqKd?N7-oWj-+IU(MwR+#2s5g4ETn278K|(#e(-$?oR_acqXoff!F+m^6Zg%aiI4UbM)keHP6*Hzu!CO6Q9WN2A*MH#&{lpwIs=a4wXgMGyV4DLDrv}eWHT#da&b|49r?8C|7fU z%sf_vx`+M(Cj%=hpRr9c z2P9^)qcRNe5O_TuY~7b>iy0FG&ZS?+l*??eL$))s(U{p0WzN#TvKtYIvw-W_R=Duq zsG9k}9}6T=HH!~nfmUz8RfFiKf#LULt{URJ?~^SskEAP?*)cit}`mL0XSxT*5sE1xVVa}S3pI-MZRLs{e;|Dwe=R? z=00IP`${Y1;zQTj3Af5c3~Vu_F7N$qG42NN1$sX3b0hlwx45Uf{Hy8A6960mpIH>B z47%Prc?<)~xz**pzoo90Wh@r29mDUxw-9kcEXm)qFQt&o z_Hx{Nf1bO8_AU3goPo8BumH?3@@_&tvK}1_82}^MVaXr~I0k&E47%P2!2KB52CzEh zc8c6y&cGuASTg6|0kC}puhGDhfrSOEZCHZd+U{E=M2ptcyG52gt=-1jU6_T%GIMV) z#3B~n}IxkXJ+xMX~@OrZRocukHgmrN0 zaftid0FD`09`RZuaf`%Q{Ho9I5fDOPUE#~N_&19o_xel6fyJe$| zz`&Y?@5aCpJ2C)9?24|pfLAi`Zfh27j64X|bNefGuKQ>+r?2 ziTa1G*GzoxI+9U)Xj`^_Lqy^{07qJvaieJ?Aa8=zrUgpfF5_8faq*ogA6TG_T5f0t z{x*R1LSn#c)hUy0`LgA;^8eAoLDxqG*Ejk#3y{_d2_k!LI*zQ@t+;pF%IClhC;VV146!0x>eUd+4KQ_FX2huKMV1gd7o zx|>}_>hIyjCO!3V?W!839(bJ_B%sm7#_Y_>Mt`41L41H zpKG~yxjO{#2%VgLm=^FXFabQVacc`q0N;B0X6I=Dd!Ja!y#EiqrAdEiM1I9QbDzIb z583kt?;i6uvOPlp_Z~d*tMHZ-w6jPvj<+|5i z;X`d&rk(}*sNY{_VDBX#nU{m;S42g1t=BR|zZIjS*HED#0Rxs=rqkQ2Y^U7UTU^l38_m3HGck`zixx-qeU#w&l|Ts2}Xh^s>f2Y^k5U)&q$w&w$$kQv?=w zVTv=6S3g=b9;ge5EpVfqJb!18@<-hE`=x(JTXd z8rPCBh%qz$lAt-0fvx+n;q%GB2JlB?U{*dnoq^@}*0aht{lJL%JQkI|M~AGZGq86s zdi~y_c|C7|-nP*J3(1NSZ^&w98K=-Y$R!M{xA~pc3uJ&ScZLRz`eo_GRt;=v+z2$D z_d&YeA}z_the(!quER*v?&o&Nwu>}B3Zm#m{8bICnY0Fk(d+hW8JOvp3E)NzY)!7- zCM_44_7+48thFQqVhco!e>u|X68w=X54jdEW#HBDAC|Qk4}tJ30M~%H7Xz~(jl3A> zK!}0}-eU5$ZzLCLb^-+6%Qdhi6?%9L^uow`A((!h$-s=4A(9Vr+rO(9f(<)g%D}aU zIHsO=07Q&#)%%tgLTgGU!e+?_YkT$>+4H9&Ib$(+*0mP-f!TzzOEs_uM9IQ6fNN!7 zre9|Ahb^XT7!FXfyqW=ybe0}p?9^f`hl6Oud@zp)^_e? zx|Omhr4nu9P(nBi-jaY5Wq~mVIDN3RK&;0dMb@kxE31LSeBhFojf~yvI!emv4PYr5 zIWXx2(|r+UZ}x*Ag1=d zXV>fYqL2o+1Z%&q`hm|j{I}bWzEH$Yz_d0#;ReGNcS zof-!A>R3RLWy|%N`iRB!IIa6eWnS0xJ!;yB?Cp(VXa=rjTvQJMlf7QUz=gRsKrT$? z19&-Sd*yX|vhSsTJs8-!PsG%kp(Vs?HTLD%Xe=<8a$Y9mfhiPIGi|eFS{PU}YL>FuV&M^B<3IODkt+;9D^;0+j@{{+eFK<%aHa z76Z$6y%YTFcg?Wu--WGEd24)G4}xU+qdRT8L#qZJo`GH2u)4E7k#;RB5Gzk zyap=pBl{8}_CL#hc=t#BL=iaa`lA@QFe&%!+UDC_C+)+;Z_Qlco#@HHEt++I_}U+< zdTHQ{w*z@UBD*10J_2}vuN1Aj`L?SsPosQ^arJ$W5v|jDq-kY)=rr$n4ZPF-)|Ybj z-%l~p#H|b*x#T7T3+wK@4w5-PAV;9vJxp3rADz}cP3q}pi>0L3!MYy?i=UH#B6s^m z#z*2>e9CCf7@J<|2lm3j)y%68aIA*b!4gtVoS}h_fM1vu1H~@)Ee4i5ho!-1E`*v{ z_U$?A7F*?L1#r%UhAd76!gmKClHw>1}v3uh6iE zMNs6M^I0ZY-fV}I58FiBFlQMqVmY*c&bnU1kZ1J;NvE+GSS6vmTG-RNPU@uRB4e4` zo17X3K5L?Twi}JBHiDL|hk(1vzi)n}C^GU!tQ*6w=E7V8q0=Ggv@rF|__I=f$XCU=0qEX_owD0g_!k-H$E7 zaZ9sP0p2&0`k{}dp18idziuD3^Rlv4ru5smX5R0JfS~}KVc>mIx{)gR87mjjQwK*@ z17{i7D~~`N*7FuoN!l-n2l!{STjz*K)d?|^)!gk-^<{AQ0=Y@=A;j*hN-oW zi{KJJFp7Z5poYhw2L_g3_bXo}5eGbuiTB*=Kx;ZJL6$)I&UBh~4Q4pXy>L^3Y zi^b|Oa0=vx975XLVCvx*_;8>)yca^E1VU_AVCPyhveVF$9ml)fkbx;}Nr2U4a-yCI zQkH>_T6!o3cKx-6_uz2+-#w^#1bK#m>1C1Cz#h}F8rWpMECU-LOEGYurO#$yn*M7ir3m~~lwI{o%Rh{IVO8}Ge`dF|WEz_s8Nj8;I47+7o7ECcJs zVKV92eqhi4{qu8)1{Tv_{q(U1+(Xd9cz_dmLFh$MtATYrq=C0BEA|d}UXUGVvka`a z{~$;b`j3NyS|~4cgm1rCE@$8)m~{ZC-tT(^qLLe*NK<{#H|vEs?6JTf>y&0ToCkoULXW&RyR0FJ3G!A&pZR&$e$bfp%*<1qRz?0IzzLwnE!((8hKjr~a%MRo3 zsz}^%FYzrq{NF&6p31<1e4rTE@Lq(*3_xb?Jc)x{lOK4HTnHA3 zne4Q$GOwox*Du4LYQ`Ly!fGPBCyGi?Tb~%illBQ^^R_yY~SrO}qM* zESFj0JrAf4$Lm=y1ai)MF0P=SH|ZLrp$s8*mfHN|s>R12h=;>Y= zcSX<1nHH$Bz%DVi7l=JMg1~+D{d>ryUOUyd+hOHht*i3e^$Obencd|Zx1HpKo+M<% zURwOy;JCy65P7^+Py1b4f%&RCr$PUE7wWDh!Me2!MNx!+KmY#y`~Bzr z`~Cg*?`KUp|6eTjCOa&Z_5S_7uU!O|O6%U)s8@mOmcal3_@yLOd87sKOB?e#X1oQw zpRNS}{4w5L^+_z}2;d3ccgX_?3;=*%+V3rZuWkgy1fEu#&!+`;3+w<+1urn-XD>_( zBv_yTc!D>W&Zs8&@Z$Q0Q|sHk=H z7Mf*&$-r5bocTOrfyuy+n0*$SWr1NC__Ma8|9*b@7l@g8Nrvb7Bc0RJ9;uw3e31IR zCC#u5oC&(jyuJ~@3srmqV-$|4&#AYHCtdhv-BpnCq0iBLKIuH#8j^uCnIUc z>+e!Nd?xT_hEKI0XJEAR5ddfA<$;zyf0E@9yLfFu7`QSjWl{=Klz}NT^K!kvrFJ~7 zfippunU~k;cLMn8*~DTx4OCo4L>YJ`{YHCF24T)W!hrUf+Y|r;UI@z{OSLQNrKka9p6hP5Mr8143&hI+9Ax0S z>9)<7?0w0rAq^7G>+lLc@LvP)r@bhMkwqz*m&N=M29`7`;=e^ejVu^>J0=5z-VqCU z5eDuBa0Tim5+cCB*3KM1*<)>5ShB)%*)=oTh$k{4)3>K7d-ICC7X>g1Vw&%z06yUd zwqhLUX2)dU&Tz^I5WT^mJ=XxNferz%#GB9GLgft@q*juP=i#@?xA)RT<0ySdx$-sz}64DF};7W^Y zNTs!1TsJ4IGi@lSy>y7#Cj%o^N=SnM7?B4^nrL;A7=%a+1iAy~r9;{=85prrLYkog z%rq$iR!Pf7-bhfzugyi%%ea zV{OxdgE<;CJ2mh?07lprS?D48&@|dY%iAflLME*MAng>hcYsq~#0~h33}m`RJ1H|S ztxTkhEZ}A3(*T&A$T;hTm<-%`6#lF`3>_3aodjU&Wk3LqmVF6;*#a%<&yAj_K)fEP zJ*EamE#;)sK&-viz2Lecpgq9AmTL{!(Obp}P#)SXQv;)xN(68(cuVJBcOt_&i)Nih zo(#;uapjatr}iZ5ZrPwLJRE?Tx1jfWDCF`IiGf!IV}9m9oyq3iXt^-9Kzs(cwU$>h zuywBk1)1mHje0LMP$NAvqy|PRKGWn{;H*D3w>Efgc^cULo(x{8nQ~eHwZM>vI?>9{ zbkhP8z!L-i%GcgM7hKDc2=zHN6;JD>k;?GOMY?7J7_riqrzt?v;QMh7$cN#!Yona! z+XC?4?^a3~GIqI$*(ZPzD}8wyiwP;Sejv{OE->7E(_Wf7OfuNF%o-10Emhq@)WwAS zX8DS}tz8X|z3&w_kiNlyxW2qJ-t#kK%wk}PDS3MB?+>(gz!s?Q058zfc^_-h&u`h- zOZnGR83e2pAjpl6y+FL;JtR*rjraU)=OGMC`zFd>H3%A=nIuh zH-T#D4DDO{?r{d@;F180FtWwKX8=rR294vs1HiH)4e{S19tG|v&S2lAZ=Tk`BLbLz z&dSr8-vQt}4J-}x$-wL$1;mZ!x#lzpfh-g~Hs+ED&C^?Ode3{5aJB}n3q#3s@pT$l zV_@&2epdk412h5-4zP%Jr?$|f%XI+GV_>>-XZeA@!V7U0z|!=N`j$OFM%`+NR=4u> z!0A2r+M~`IMl3{+2DWzVw4J)%x(}s+x0R*fPUDP(03j+N&NA@30cmhNfC5DZKKNvB}$X+Slt1{yxSd%#CPuhpFoOe7XU ztKZcC?g7rhcB`hX0gh+2En24`G_VB%L^FEYSz>U>K$2_D1ATNh=<$%C0}1W)Z%Q{b z16$ybz-EP7B0%H=srMZ^V30xKrSYDB6Ck5)8HRzQ6(1?R2QW(tNrNV9Mj6RQSJh=0 z2EM9+GvDvFz+~X>?%%I(T`B`-?5upf#b*OkEwFg4H9uZYNq4zVdg?ac`92E}0Jl3a z`+?>7?-@}>-)HLCqAM&wZi7!doV?U?GVvANHS^>aXzqp3_PnE~lfNZBGL!I=24`lj zZ?W5*?KoU)lBtK^&KJlmGVS$jFRM56OlCpgyT`Ro=8dnFGML)ETIw$|3^&I z8csREiyCaE8_NO(z)3=XGVfTO`xk2SvmD1rio-xw#ouI9Yt8WH!JN4k>Rq^^_A6)N zCIfekD{JO@^I*=Jkuz}R*>N&(7j(-@SqxnB(K?Gi_ZYI~!_#?SsHX7VL+UFrDDs{J zdaK^IGO%{RN91Al#f0@ofwoxn|U3*)yLN@ahq{NbigWrqij!Oy2VY zfLBeUfy0}=X?_v|TQUX(b(IIv^!zN!GdDH^hl9tS3V9V=rRs+9^f%zh=Wg_20puK;VfvtLt%)oRZNf}(ztWhrnXMSnn zYH3<)rm?iYwz>8g19K_RvkGnX&ghDt<6 zJgtHM8Ust(d1wZ<0L(%Bml+rdoIwI07)Mh+zjmy@Y^_jnOuw;JO-CNu>&TnQBuU?uBvNUj}jhlhN zW(WklbVfj!5m|Vh$;aC{++v@vGU7Mqo8^TV%|<9QUI|`wuuTAuhMrlUkOd}yL*|-^ zN3*~L@Mt|U>l3oT1aQb)Gx2B^xGfeUyWtiTf6q; zVa*#_8-`=x7~>Z3?u^SBxc+@)=5v#5dAo;!D|79DEIH`_EK*2I&-0`0s`ZNwS&4zA zaxA9i3{4^4tFa%AM(Y90&cG{RK4AU#vjC^vhL)ph+TfiX%w^__c599XuFS+4HOj!= z`@Ecp{VnD{N`;cM#lW>}Zx-?DDA{Nj2F93I*SH(liLBU`ajVSuV0L}HX=Tr7*7GYF zSkss&gImn(wRuzqmS(D%k#XDb|K~5#lTWI12Av_A;Q302W*VGyUH}LLP|;@$gD7RJJ6eOT&cG4otzg_`KxOXrRKseKBd9%w z?_=UK4BT$Cv|b2_K~XP+r;!nD9Q6Zlr;?dBMe|qpdLf2m;KfU@ue25vNt+OrDa*=h zCtNNEj+$1|$j5O{?pk5q4Vxp*FfgJmEe7T_)AGw=V9BfD<<0GL)(bI|21b~-iE*Ib z1)_ny%?@5pbwfzyQ;m&GZ)X^|mr+0U@|cZkQjd{!31R!6X+0ByhYl2Scfjxa7y)4J%iD7IxfWFZR3 zhhDB^V5zk}So9q+&+pvKM&5%?!O>h~Z-)B)>1jgoHkiF%mnM z)Na;BepCl%GO!N#0)Za(@-`e&{8 zq-ZmsoGmt@4awXf@2pDCcp)r5a66sL%zB*ibx3MjR2|4loUc_cuH7wWjxz9z;(>`~ zT|vCCz_z0%nf$lWuRG>6*NTt_*_mrt3IebU1C-%Bc8%)9jPyMWnNhBkho`Y`XJGkQ zkg_|`gicy6F)uFI+lgy;^k@{D)iFH`d{swh<{M>5Z#~lU+ym}5OFsLxdJf83t(}S6 z>0JJO85G;e3*D*B1A0V0C*BA|e`f+`<`uWVV+?%QA!8?4BRh3_jD*g#)P=SW3i$*F zs)6I?o^NDZKnT^!F2bIKmnBMb5VNSl_TRchAnEq!e9M#iFsp#x-`8p*#SQ2Br0=xr z-zn<>0Job95vJu{iYW8SfkM)my1wYNzXO|bTKWKh7tUq(Hb|QrY_nl=*2`7iBe!-& zu3;W+T<|e|n0Ln({pRip{_0I}-yH`8$C?=Ja=OmzTKG9=zXt%^&%oSwD)~|u&?3=l z<__TDEWV637T(!*j^(`^8N5}~`8)%I@f7H7J3atl+IelutYbfDmv8PDa)5I;bp2X1 z3w#hWM*!Htz#Q}-)9_g6R-f~F?178>`9cu;DVNCKK2a)%8FLOc+Y%q7Vr#Kje8AFsE$3D5;58Q?{`b^lm*l7BC@YDOhpoz(# zK6OgDmw|a_dV|FTr8g)5P>HKp&U^p^hd@p=wh3+_9jWg?47}Hh$L214xXy@6T$V?U z2dBmk;#$hV@4G!f*_UcSVZj4wz6Tf>(v|>NMJ5N{JH^1qzIlv+t+Q#zyUzR@dAj_` zhnspp@545;w}(u_UI<7-60d;B+))Ph7FOH~!KZg&VJ9-E_MV{GQ3e(koU&YicY1`fHH1g}Q}`r4U>7s5<$=rB!Y>^nTf zg=R=DPp+7Q$!k}!&j1XpMUNft_odo+*Tic>R_{dhHt=ocBa^q9+m1N~z;p<#vxGV@ zjjKhnyEHgRMgOkhwGhiO{K}?W;F)>t1YB&6T_4cEZ6me#VEZn!K20ovxFHp2+9$d6 zGH}XfhBxhMS`}D0YW4FNSY%X9qjz{A#?!z=;~g%iI3Bd50OSl@pB*nlX_{TXGV891 zTW<%yL#7&EIm~*Z8dw|L#$Yn*^Hp95iGeqc+z*Sd8*Up>k{z}K z^BSHouAx`;tf@`l_b3BfF>a0nBh^6q@ z2O!=p$z2R=_+>ZO>AHh8*l| zznx@UUiB;n_F^L-f2px!W@>1mKTMDb@xsu;POv>BFNTgrv%##LB9^sml_G7Po7qA; zY~CQ_3#e!;1Wz9TA78y|gNRSJqcE_@^Z}P3>zc>?z&=zWjLhzLxCFG?LPi7SfwtK( zBw$wXKD%`Tz36uet+BoYgBEXFrOg)ON(DQ2;V#iJo|6`Kez#DI}QN862u+@Oa{)8alJF(S1>T0IkFkiV}R`P1}Bn~ zHAiGd@a+FJ3@pi?3~)^bzLsG Date: Wed, 5 Jan 2022 13:40:41 +0000 Subject: [PATCH 181/489] mclockplus 0.03: Allow widgets to detect this is a clock --- apps.json | 2 +- apps/mclockplus/ChangeLog | 1 + apps/mclockplus/mclockplus.app.js | 5 ++--- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps.json b/apps.json index f116049dc..90dc1d941 100644 --- a/apps.json +++ b/apps.json @@ -3533,7 +3533,7 @@ "id": "mclockplus", "name": "Morph Clock+", "shortName": "Morph Clock+", - "version": "0.02", + "version": "0.03", "description": "Morphing Clock with more readable seconds and date and additional stopwatch", "icon": "mclockplus.png", "type": "clock", diff --git a/apps/mclockplus/ChangeLog b/apps/mclockplus/ChangeLog index a1cecc698..097545ba8 100644 --- a/apps/mclockplus/ChangeLog +++ b/apps/mclockplus/ChangeLog @@ -1,2 +1,3 @@ 0.01: Created app 0.02: Use Bangle.setUI for button/launcher handling +0.03: Allow widgets to detect this is a clock diff --git a/apps/mclockplus/mclockplus.app.js b/apps/mclockplus/mclockplus.app.js index 4c74ce1be..970397478 100644 --- a/apps/mclockplus/mclockplus.app.js +++ b/apps/mclockplus/mclockplus.app.js @@ -304,15 +304,14 @@ Bangle.on('lcdPower',function(on) { }); g.clear(); +// Show launcher when button pressed +Bangle.setUI("clock"); Bangle.loadWidgets(); Bangle.drawWidgets(); // Update time once a second timeInterval = setInterval(showTime, 1000); showTime(); -// Show launcher when button pressed -Bangle.setUI("clock"); - // Start stopwatch when BTN3 is pressed setWatch(() => {swInterval=setInterval(stopWatch, 1000);stopWatch();}, BTN3, {repeat:false,edge:"falling"}); B3 = 1; // BTN3 is bound to start the stopwatch From 1b70c9eb9d70b042d2b235a3c45ba52bc2beb5c3 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 5 Jan 2022 13:40:46 +0000 Subject: [PATCH 182/489] Fix error message - ref https://github.com/espruino/BangleApps/issues/1198 --- core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core b/core index ae9586977..b05af96b2 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit ae9586977948279d267f2749bf3a48d3aa753c11 +Subproject commit b05af96b2522a7a7225a56d804faf9383f8a8f97 From 639bc1962eee45c31b4cf0d50f5edf782ac94e1c Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 15:28:18 +0100 Subject: [PATCH 183/489] Allow widgets to detect this is a clock --- apps/circlesclock/app.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 3099b02ea..2d6c132bb 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -308,7 +308,7 @@ Bangle.on('charging', function(charging) { g.clear(); - +Bangle.setUI("clock"); Bangle.loadWidgets(); if (!showWidgets) { /* @@ -324,7 +324,5 @@ if (!showWidgets) { } } - -setInterval(draw, 60000); draw(); -Bangle.setUI("clock"); +setInterval(draw, 60000); From f1c923d4b52187856bf2dce4fe6de640ae990246 Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Wed, 29 Dec 2021 07:30:47 +0100 Subject: [PATCH 184/489] Puzzle15: First playable version of the 15-puzzle --- apps/puzzle15/ChangeLog | 1 + apps/puzzle15/README.md | 18 ++ apps/puzzle15/puzzle15.app-icon.js | 1 + apps/puzzle15/puzzle15.app.js | 361 +++++++++++++++++++++++++++++ apps/puzzle15/puzzle15.app.png | Bin 0 -> 2313 bytes apps/puzzle15/screenshot.png | Bin 0 -> 1161 bytes 6 files changed, 381 insertions(+) create mode 100644 apps/puzzle15/ChangeLog create mode 100644 apps/puzzle15/README.md create mode 100644 apps/puzzle15/puzzle15.app-icon.js create mode 100644 apps/puzzle15/puzzle15.app.js create mode 100644 apps/puzzle15/puzzle15.app.png create mode 100644 apps/puzzle15/screenshot.png diff --git a/apps/puzzle15/ChangeLog b/apps/puzzle15/ChangeLog new file mode 100644 index 000000000..2f5d93cad --- /dev/null +++ b/apps/puzzle15/ChangeLog @@ -0,0 +1 @@ +0.01: Initial version, UI mechanics ready, no real game play so far diff --git a/apps/puzzle15/README.md b/apps/puzzle15/README.md new file mode 100644 index 000000000..540646f97 --- /dev/null +++ b/apps/puzzle15/README.md @@ -0,0 +1,18 @@ +# Puzzle15 - A 15-puzzle for the Bangle.js 2 + +Puzzle15 implements a 15-puzzle on the screen of the Bangle.js 2 smart watch. +A "15-puzzle" is a single-player game. 15 "stones" are numbered from 1 to 15 and placed randomly on a 4 by 4 playing field. +So, one place on the field is free. +The target of the game is to move the stones around (using the "gap" on the playing field) to bring them in natural order. + +_This is work in progress!_ + +## How to play + +After starting the game, the playing field is shown with the stones in the corrct order. +Push the stones around with drag gestures (left to right, right to left, top to bottom, bottom to top) to shuffle them. +Then, use the same gestures to restore the order. + +So far, there are no other capabililties or options. + +Have fun! diff --git a/apps/puzzle15/puzzle15.app-icon.js b/apps/puzzle15/puzzle15.app-icon.js new file mode 100644 index 000000000..04fb4a665 --- /dev/null +++ b/apps/puzzle15/puzzle15.app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgn/AC3+7oAD7e7AAW8BQndBQe79/9DomgHocH74KD/RJE34Xax4XDtvoC4fJ54XDluAC4f2z4XDzm/C4ett4XD34OBF4e/I4m+C4f8r4XChHuC5U98oXEF4cP7/AC5O9mYXC/2/F4cGtwvE/SsBC4Ws7gvD7YCBL4ULO4i/u1QAD7QED1e6AoetCAnf/YeE1wpD/lgBQcKIAgXG14LD/twC5kL3Z+BC4P+LgIXBg272wXD7wXEh7eCC4PWzIXChHtOoIXB/WX54XDh3KmAXC1oLBI4UD+AXC+/rdIIvD5wvD3O4C4cJ4AXC/dUI4kJhgMBC4Ov+AXDh9QC4X2/gvEhvvoAXC81dC4duR4f8wSncC6v8u4AD3ndAAXcy4KDtYKD7vf/oGE2wRDvPNBQfLFAnP/o2EVIIACg7yBAATZBAAe/C7P9g4XCx+wn/6C4Op//AC4MK+cI/+QC4X2/fPC4PM2HKh8H7vpewIXBhvThV5+AXC+/5C4UL2HHC4Pf/P/AIJHB6cAj2wC4X+3AXPhADBF4fX94XB1va1vOC4PXAIX6hfrxvb0CPD7p3C1e6hW2C4LOBAIIXB3eJ3YXEX78GM4IAC9QXG1QAD7QEDJYIFD14oE//7DwgME/twBQcPC70G6EG5dQ1/8VYPtC4ObgfM5IXHr/whvO4Gvy6LBtX9vfugnr3AXHkXggGOC4P97/43X9ukOgnv6BfIC4Oe2AXC6+nI4MOgfI9QXJhssF4f91AXCgnA9IXHr3u1HusGv3Ob//s/t693l3xHJX9v+3YAD7oAE5YKD34XFAC4=")) diff --git a/apps/puzzle15/puzzle15.app.js b/apps/puzzle15/puzzle15.app.js new file mode 100644 index 000000000..9a5864b9a --- /dev/null +++ b/apps/puzzle15/puzzle15.app.js @@ -0,0 +1,361 @@ +// A 15-puzzle game for the Bangle.js 2 clock +// (C) Dirk Hillbrecht 2022 +// Released unter the terms of the MIT license + +// *** Global settings +// Note: These could be changed by settings later... + +// Minimum number of pixels to interpret it as drag gesture +const dragThreshold = 10; + +// Number of steps in button move animation +const animationSteps = 5; + +// Milliseconds to wait between move animation steps +const animationWaitMillis = 70; + +// Size of the playing field +const buttonsPerLine = 4; + +// *** Global settings derived by device characteristics + +// Total width of the playing field (full screen width) +const fieldw = g.getWidth(); + +// Total height of the playing field (screen height minus widget zones) +const fieldh = g.getHeight() - 48; + +// Size of one button +const buttonsize = Math.floor(Math.min(fieldw / (buttonsPerLine + 1), fieldh / buttonsPerLine)) - 2; + +// Actual left start of the playing field (so that it is centered) +const leftstart = (fieldw - ((buttonsPerLine + 1) * buttonsize + 8)) / 2; + +// Actual top start of the playing field (so that it is centered) +const topstart = 24 + ((fieldh - (buttonsPerLine * buttonsize + 6)) / 2); + +// *** Low level helper classes + +// One node of a first-in-first-out storage +class FifoNode { + constructor(payload) { + this.payload = payload; + this.next = null; + } +} + +// Simple first-in-first-out (fifo) storage +// Needed to keep the stone movements in order +class Fifo { + // Initialize an empty Fifo + constructor() { + this.first = null; + this.last = null; + } + // Add an element to the end of the internal fifo queue + add(payload) { + if (this.last === null) { // queue is empty + this.first = new FifoNode(payload); + this.last = this.first; + } else { + let newlast = new FifoNode(payload); + this.last.next = newlast; + this.last = newlast; + } + } + // Returns the first element in the queue, null if it is empty + remove() { + if (this.first === null) + return null; + oldfirst = this.first; + this.first = this.first.next; + if (this.first === null) + this.last = null; + return oldfirst.payload; + } + // Returns if the fifo is empty, i.e. it does not hold any elements + isEmpty() { + return (this.first === null); + } +} + +// Helper class to keep track of tasks +// Executes tasks given by addTask. +// Tasks must call Worker.endTask() when they are finished, for this they get the worker passed as parameter. +// If a task is given with addTask() while another task is still running, +// it is queued and executed once the currently running task and all +// previously scheduled tasks have finished. +// Tasks must be functions with the Worker as first and only parameter. +class Worker { + // Create an empty worker + constructor() { + this.tasks = new Fifo(); + this.busy = false; + } + // Add a task to the worker + addTask(task) { + if (this.busy) // other task is running: Queue this task + this.tasks.add(task); + else { // No other task is running: Execute directly + this.busy = true; + task(this); + } + } + // Called by the task once it finished + endTask() { + if (this.tasks.isEmpty()) // No more tasks queued: Become idle + this.busy = false; + else // Call the next task immediately + this.tasks.remove()(this); + } +} + +// *** Mid-level game mechanics + +// Representation of a position where a stone is set. +// Stones can be moved from field to field. +// The playing field consists of a fixed set of fields forming a square. +// During an animation, a series of interim field instances is generated +// which represents the locations of a stone during the animation. +class Field { + // Generate a field with a left and a top coordinate. + // Note that these coordinates are "cooked", i.e. they contain all offsets + // needed place the elements globally correct on the screen + constructor(left, top) { + this.left = left; + this.top = top; + this.centerx = (left + buttonsize / 2) + 1; + this.centery = (top + buttonsize / 2) + 2; + } + // Generate a field for the given playing field index. + // Playing field indexes start at top left with "0" + // and go from left to right line by line from top to bottom. + static forIndex(index) { + return new Field(leftstart + (index % buttonsPerLine) * (buttonsize + 2), + topstart + (Math.floor(index / buttonsPerLine)) * (buttonsize + 2)); + } +} + +// Representation of a moveable stone of the game. +// Stones are moved from field to field to solve the puzzle +// Stones are numbered from 0 to the maximum number ot stones. +// Stone "0" represents the gap on the playing field. +// The main knowledge of a Stone instance is how to draw itself. +class Stone { + // Create stone with the given number + // The constructor creates the "draw()" function which is used to draw the stone + constructor(number, targetindex) { + this.number = number; + this.targetindex = targetindex; + // gap: Does not draw anything + if (number === 0) + this.draw = function(field) {}; + else if ((number + (buttonsPerLine % 2 == 0 ? (Math.floor((number - 1) / buttonsPerLine)) : 0)) % 2 == 0) { + // Black stone + this.draw = function(field) { + g.setFont("Vector", 20).setFontAlign(0, 0).setColor(0, 0, 0); + g.fillRect(field.left, field.top, field.left + buttonsize, field.top + buttonsize); + g.setColor(1, 1, 1).drawString(number, field.centerx, field.centery); + }; + } else { + // White stone + this.draw = function(field) { + g.setFont("Vector", 20).setFontAlign(0, 0).setColor(0, 0, 0); + g.drawRect(field.left, field.top, field.left + buttonsize, field.top + buttonsize); + g.drawString(number, field.centerx, field.centery); + }; + } + } + // Returns whether this stone is on its target index + isOnTarget(index) { + return index === this.targetindex; + } +} + +// Helper class which knows how to clear the rectangle opened up by the two given fields +class Clearer { + // Create a clearer for the area between the two given fields + constructor(startfield, endfield) { + this.minleft = Math.min(startfield.left, endfield.left); + this.mintop = Math.min(startfield.top, endfield.top); + this.maxleft = Math.max(startfield.left, endfield.left); + this.maxtop = Math.max(startfield.top, endfield.top); + } + // Clear the area defined by this clearer + clearArea() { + g.setColor(1, 1, 1); + g.fillRect(this.minleft, this.mintop, + this.maxleft + buttonsize, this.maxtop + buttonsize); + } +} + +// Helper class which moves a stone between two fields +class Mover extends Clearer { + // Create a mover which moves the given stone from startfield to endfield + // and animate the move in the given number of steps + constructor(stone, startfield, endfield, steps) { + super(startfield, endfield); + this.stone = stone; + this.startfield = startfield; + this.endfield = endfield; + this.steps = steps; + } + // Create the coordinate between start and end for the given step + // Computation uses sinus for a smooth movement + stepCoo(start, end, step) { + return start + ((end - start) * ((1 + Math.sin((step / this.steps) * Math.PI - (Math.PI / 2))) / 2)); + } + // Compute the interim field for the stone to place during the animation + stepField(step) { + return new Field( + (this.minleft === this.maxleft ? this.minleft : + this.stepCoo(this.startfield.left, this.endfield.left, step)), + (this.mintop === this.maxtop ? this.mintop : + this.stepCoo(this.startfield.top, this.endfield.top, step))); + } + // Perform one animation step + animateStep(step, worker) { + this.clearArea(); + this.stone.draw(this.stepField(step)); + if (step < this.steps) // still steps left: Issue next step + setTimeout(function(t) { + t.animateStep(step + 1, worker); + }, animationWaitMillis, this); + else // all steps done: Inform the worker + worker.endTask(); + } + // Start the animation, this method is called by the worker + animate(worker) { + this.animateStep(1, worker); + } +} + +// Representation of the playing field +// Knows to draw the field and to move a stone into a gap +// TODO: More game mechanics (shuffling, solving,...) +class Board { + // Generates the actual playing field with all fields and buttons + constructor() { + this.fields = []; + this.buttons = []; + for (i = 0; i < (buttonsPerLine * buttonsPerLine); i++) { + this.fields[i] = Field.forIndex(i); + this.buttons[i] = new Stone((i + 1) % (buttonsPerLine * buttonsPerLine),i); + } + } + // Draws the complete playing field + draw() { + new Clearer(this.fields[0], this.fields[this.fields.length - 1]).clearArea(); + for (i = 0; i < this.fields.length; i++) + this.buttons[i].draw(this.fields[i]); + } + // returns the index of the field left of the field with the given index, + // -1 if there is none (index indicates already a leftmost field on the board) + leftOf(index) { + return (index % buttonsPerLine === 0 ? -1 : index - 1); + } + rightOf(index) { + return (index % buttonsPerLine === (buttonsPerLine - 1) ? -1 : index + 1); + } + topOf(index) { + return (index >= buttonsPerLine ? index - buttonsPerLine : -1); + } + bottomOf(index) { + return (index < (buttonsPerLine - 1) * buttonsPerLine ? index + buttonsPerLine : -1); + } + // Return the index of the gap in the field, -1 if there is none (should never happel) + indexOf0() { + for (i = 0; i < this.buttons.length; i++) + if (this.buttons[i].number === 0) + return i; + return -1; + } + // Moves the stone at the field with the index found by the startfunc operation + // into the gap field. + moveTo0(startfunc, animator) { + let endidx = this.indexOf0(); // Target field (the gap) + if (endidx === -1) { + animator.endTask(); + return; + } + let startidx = startfunc(endidx); // Start field (relative to the gap) + if (startidx === -1) { + animator.endTask(); + return; + } + let moved = this.buttons[startidx]; + this.buttons[startidx] = this.buttons[endidx]; + this.buttons[endidx] = moved; + new Mover(moved, this.fields[startidx], this.fields[endidx], animationSteps).animate(animator); + } + // Move the stone right fro the gap into the gap + moveRight(animator) { + this.moveTo0(this.leftOf, animator); + } + moveLeft(animator) { + this.moveTo0(this.rightOf, animator); + } + moveUp(animator) { + this.moveTo0(this.bottomOf, animator); + } + moveDown(animator) { + this.moveTo0(this.topOf, animator); + } + // Check if the board is solved (all stones at the right position) + isSolved() { + for (i = 0; i < this.buttons.length; i++) + if (!this.buttons[i].isOnTarget(i)) + return false; + return true; + } +} + +// *** Main program + +// We need a worker... +var worker = new Worker(); +// ...and the board +var board = new Board(); + +// UI: Accumulation of current drag operation +var currentdrag = { + x: 0, + y: 0 +}; + +// Handle a drag event +function handledrag(e) { + if (e.b === 0) { // Drag event ended: Evaluate drag and start move operation + if (Math.abs(currentdrag.x) > Math.abs(currentdrag.y)) { // Horizontal drag + if (currentdrag.x > dragThreshold) + worker.addTask(e => board.moveRight(e)); + else if (currentdrag.x < -dragThreshold) + worker.addTask(e => board.moveLeft(e)); + } else { // Vertical drag + if (currentdrag.y > dragThreshold) + worker.addTask(e => board.moveDown(e)); + else if (currentdrag.y < -dragThreshold) + worker.addTask(e => board.moveUp(e)); + } + currentdrag.x = 0; // Clear the drag accumulator + currentdrag.y = 0; + } else { // Drag still running: Accumulate drag shifts + currentdrag.x += e.dx; + currentdrag.y += e.dy; + } +} + +// Clear the screen once, at startup +g.clear(); +// Drop mode as this is a game +Bangle.setUI(undefined); +// Load widgets +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +// Draw the board initially +board.draw(); +// Start the interaction +Bangle.on("drag", handledrag); + +// end of file \ No newline at end of file diff --git a/apps/puzzle15/puzzle15.app.png b/apps/puzzle15/puzzle15.app.png new file mode 100644 index 0000000000000000000000000000000000000000..f95366a4616cb5f6fde4f00694a5aaa1e1c7194c GIT binary patch literal 2313 zcmV+k3HJ7hP)-&vx#;&$;)U&*z-;j6(<^_z#O20QC3wL#b3! z4IqTz-Me?-a5${GHa0e}wY7zrnHj6DTCE0`%SC^GKh<-rT)7g~SHLp^sBqEWBdhXiVT0#gR+`q*Ye%6!q8o)3NE?l?(jYh*d!NG$E zAr_0#)6;|W^mJDJ#>PhE<>leQg9lU(=0uC6X*XJ^wJaO~JIaJgKnUGeep0mCrp z?(Rl%a!l;XCG#aF(rD1e*6!!M^aB*=l45RuWO{39hp^eKmY-e_M zHmt0y5EmE63a#(ozejU(Gq!EphMAceRznjL6T#tdkdcvL(B1SJP+3_COG``C*4AS6 z>eX1WVuis)1_uY>;NXDk*RO*Rf`EVkgSsv*E^v2uM@>x)PMkP_MT-_0H9#a10RY0n z!XTAO=?#dEj;3~@0|yS6+{|1mMz+uNxr zyrZLoDwS|_bOevb!}$0(tM2UVECd39L08dtlHT6l-%^R1ni^^fFDWS@0|NtuVHnn{ zxw)AnCMHtPee>o`qEe|?=T$0|q`keJ5JHF<0IJ>89vO!NYiny*TU)d0^7(v|T!YKy z!qU>xB$v}WdqqWs7Nez7DKauLj7~Nl$019 z)78}ldwY90J3G^(P*_-)Hm#kSnlie8L?S^+NeMhXJ#qj3eH=Y{)F_Pl`uc(p0(WaF05LH!U>Jr~|MlzFh>D6rNJt0<2M6h4)Y;h?DwPUBK|x4KNin*Jxw$#S zVlifBW{{VcM-@Zy@$u;F>|~9-z`#HxCnqB-D+?PpZlpIrBoblEmM!S(>w|}fhtWl* zr>BvWl!Tz5Af%?IQsw=^HYU~8)u^tnMs98{9zT9e9|IdUY{1*MZ{h0diqOzd zql*Lu1!2#gJ(!u9q2iK+gak}YO`)=~l2tc0HWsO=si>%^z@tZx4DJZ2t*teP&0H>5 z=UyZd5r$!?%EY#|HX;-Xsd=ERtc<#}ohyU6Gz|IIcO`6WY#W++zz{A6XYHqb!4LdtKbar-9ZQ2|Fa0nr!qoaeWeB^Sukjv$$s;Z)5SPu^m`1<<7 z(b17rSEW*6cz76h@7|@_$lbele?z9frLDp+%-_>i`PtO?XU6L_;Khp<;BYuNdGaKt zr>FG}Ja_IKlu9Ma%gX@(0RaIR8X5v21jWV0I(5M0$GJn!!S^(RLIH6(HW=LfXkOJV|I2Hn>KAiV`C!>aYb8On>OGwGc!?JTdQT- z?*sA8n>Pp!4%U9BR;w{EFo3I9uj-xK&(9AnEiKx(bar+|dU`qv3JQ>rkf0Npug6ZjLNF)--WHPk2 zwnCv$%&SM1ELnonr%xj_H5IY3vFPvbhmDO5ii?ZcbD>kGPNA=_4?>|(=jeZwmoHyx zKkwhaA4Nq)_~)O0aO>7By^X4bgan<~h>MFeNLo*xJkfrB`0ybd931GAIa^y>tXZ?h z=usynCFyPS>Juj?CpbAd%`3{km+#+CL`FuMmP)AAYJC3unU#&r%*;&6jnry2R4NtK z%M+ziX;O=QPM1RnAyTOn5{ZPm7uwU)L)GuGv$KOnqru3?2-O3Hhlhj5<54{apU=m_ zg$vo!=^rnVNJLaB6;*oB(a~X2Iz2KnLQIvPN+r~4HI?33}TSS;45o*Eh& zP+3`t9XodDecSRqnavgX`YN;B+*~a>tzEko&CShdYHC7LQxh&;y!h(|L`6lRu&_`E z_m3Po0v?YCUteDwK73e*E%Wp9ap%q*9n7Dep2qp}=kfgcbDc%1s;Uqk9u3UkIg#}7WOaDJH@MA90+S-booE*sIa=j%akH^!(-qNK@AruN> zWn~2`D=VYeZEkK3jYfmi)Ku{Kd`wPG{#s2u*G{}~;|9Kd{R){(hWh$?)Ya9Yxw#p$ zv$M#`%F>B}^73-+%ePmrUSZd+U2t@Cgt@u-ygp`eaWOV;-VBXK1G!v|#Kc4}3z jaPYVEz*Gb9AC`XspcQ$f%Ox5-00000NkvXXu0mjfxkpY+ literal 0 HcmV?d00001 diff --git a/apps/puzzle15/screenshot.png b/apps/puzzle15/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..3a79a3ae64687fcd1afdbc160b4e0a9f3a912169 GIT binary patch literal 1161 zcmV;41a|w0P)?f=M;sC?}hyxG@AP&exlP<$N%E0TG)@9*!JkQfr=dow!p-E4SrzozkYaiRU z?|;8;EfVSRT1HVoqOjtz?b~yo@Be8YS1**l|F>?DlQrteEPp^6w(eDhv6|Ni6;`58RP}1g!b3Jhp|@C8)k<%_XJ$TjgaPFf zQm-v@uRQ0Qy^`T3t>^HnN`5Vp_j#rep5xbf1!b ziaACW5lGGpo&yjEAPztrfH(kgK%!E1^>Y-QqxnA%w0(lxo`e1v^ylb?6>sPd62pEH zQlMG^!~uu{5C7~eJ{Bcnv`Z7K*q{39^Jx7ss@YFi0X@&*wX^8mAERftg~zh6 zzufJRk-~|^4@cA1rg4BYY_qjpYs{wk%k{|Aqa>u-w%@s_ii8x@JXq8Cl~^=vyA#$d z8@5F&oh58f-)b`AUWRoz)ynw@E6GKwc@z0mH$g5xjq6cEc#f+;tovqE?vLSZ|5VO# zPCPx_X_WpLRqfv;Rcq~DqxHw|Z1Ekkl%>sd%qK@stw8LA6c7g>4gkafhyz?p*=nUB z_MeV}{v2@IbI>1y{v6$~LVt|4?I$4x!~uu{5Cs;+jC@z`Ijc`aGWr?meG3o!!{23}?QvnAq6m|7TwUh*Pivw^UFo)M zfBt4CeDrhD3u|qE%b;wFFpymo8g_@TRnpgoHXhUX00000NkvXXu0mjfBDE|A literal 0 HcmV?d00001 From d5a4e7b93e6b5344e732f4a1de1f34a1dd853b99 Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Tue, 4 Jan 2022 23:12:45 +0100 Subject: [PATCH 185/489] Puzzle15: v0.01, initial integration into the app loader --- apps.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/apps.json b/apps.json index 5cc311413..7aeae8749 100644 --- a/apps.json +++ b/apps.json @@ -5389,5 +5389,22 @@ "storage": [ {"name":"touchmenu.boot.js","url":"touchmenu.boot.js"} ] + }, + { + "id": "puzzle15", + "name": "15 puzzle", + "version": "0.01", + "description": "A 15 puzzle game with drag gesture interface", + "readme":"README.md", + "icon": "puzzle15.app.png", + "screenshots": [{"url":"screenshot.png"}], + "type": "app", + "tags": "game", + "supports": ["BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"puzzle15.app.js","url":"puzzle15.app.js"}, + {"name":"puzzle15.img","url":"puzzle15.app-icon.js","evaluate":true} + ] } ] From 43e87247d7803efafd3216cb77eb9a9f2cf0062b Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Sat, 1 Jan 2022 19:03:35 +0100 Subject: [PATCH 186/489] Puzzle15: v0.02 with shuffled board init, menu-based control flow etc. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now it actually starts making sense… --- apps.json | 2 +- apps/puzzle15/ChangeLog | 1 + apps/puzzle15/puzzle15.app.js | 326 ++++++++++++++++++++++++++++------ 3 files changed, 274 insertions(+), 55 deletions(-) diff --git a/apps.json b/apps.json index 7aeae8749..4a3d8c7c8 100644 --- a/apps.json +++ b/apps.json @@ -5393,7 +5393,7 @@ { "id": "puzzle15", "name": "15 puzzle", - "version": "0.01", + "version": "0.02", "description": "A 15 puzzle game with drag gesture interface", "readme":"README.md", "icon": "puzzle15.app.png", diff --git a/apps/puzzle15/ChangeLog b/apps/puzzle15/ChangeLog index 2f5d93cad..bc5a4422b 100644 --- a/apps/puzzle15/ChangeLog +++ b/apps/puzzle15/ChangeLog @@ -1 +1,2 @@ 0.01: Initial version, UI mechanics ready, no real game play so far +0.02: Lots of enhancements, menu system not yet functional, but packaging should be now... diff --git a/apps/puzzle15/puzzle15.app.js b/apps/puzzle15/puzzle15.app.js index 9a5864b9a..801cdf759 100644 --- a/apps/puzzle15/puzzle15.app.js +++ b/apps/puzzle15/puzzle15.app.js @@ -8,14 +8,14 @@ // Minimum number of pixels to interpret it as drag gesture const dragThreshold = 10; +// Maximum number of pixels to interpret a click from a drag event series +const clickThreshold = 3; + // Number of steps in button move animation -const animationSteps = 5; +const animationSteps = 6; // Milliseconds to wait between move animation steps -const animationWaitMillis = 70; - -// Size of the playing field -const buttonsPerLine = 4; +const animationWaitMillis = 30; // *** Global settings derived by device characteristics @@ -25,14 +25,29 @@ const fieldw = g.getWidth(); // Total height of the playing field (screen height minus widget zones) const fieldh = g.getHeight() - 48; +// Size of the playing field +var buttonsPerLine; + // Size of one button -const buttonsize = Math.floor(Math.min(fieldw / (buttonsPerLine + 1), fieldh / buttonsPerLine)) - 2; +var buttonsize; // Actual left start of the playing field (so that it is centered) -const leftstart = (fieldw - ((buttonsPerLine + 1) * buttonsize + 8)) / 2; +var leftstart; // Actual top start of the playing field (so that it is centered) -const topstart = 24 + ((fieldh - (buttonsPerLine * buttonsize + 6)) / 2); +var topstart; + +// Number of buttons on the board (needed at several occasions) +var buttonsPerBoard; + +// Set the buttons per line globally and all derived values, too +function setButtonsPerLine(bPL) { + buttonsPerLine = bPL; + buttonsize = Math.floor(Math.min(fieldw / (buttonsPerLine + 1), fieldh / buttonsPerLine)) - 2; + leftstart = (fieldw - ((buttonsPerLine + 1) * buttonsize + 8)) / 2; + topstart = 24 + ((fieldh - (buttonsPerLine * buttonsize + 6)) / 2); + buttonsPerBoard = (buttonsPerLine * buttonsPerLine); +} // *** Low level helper classes @@ -67,7 +82,7 @@ class Fifo { remove() { if (this.first === null) return null; - oldfirst = this.first; + let oldfirst = this.first; this.first = this.first.next; if (this.first === null) this.last = null; @@ -110,6 +125,56 @@ class Worker { } } +// Evaluate "drag" events from the UI and call handlers for drags or clicks +// The UI sends a drag as a series of events indicating partial movements +// of the finger. +// This class combines such parts to a long drag from start to end +// If the drag is short, it is interpreted as click, +// otherwise as drag. +// The approprate method is called with the data of the drag. +class Dragger { + constructor(clickHandler, dragHandler, clickThreshold, dragThreshold) { + this.clickHandler = clickHandler; + this.dragHandler = dragHandler; + this.clickThreshold = (clickThreshold === undefined ? 3 : clickThreshold); + this.dragThreshold = (dragThreshold === undefined ? 10 : dragThreshold); + this.dx = 0; + this.dy = 0; + this.enabled = true; + } + // Enable or disable the Dragger + setEnabled(b) { + this.enabled = b; + } + // Handle a raw drag event from the UI + handleRawDrag(e) { + if (!this.enabled) + return; + this.dx += e.dx; // Always accumulate + this.dy += e.dy; + if (e.b === 0) { // Drag event ended: Evaluate full drag + if (Math.abs(this.dx) < this.clickThreshold && Math.abs(this.dy) < this.clickThreshold) + this.clickHandler({ + x: e.x - this.dx, + y: e.y - this.dy + }); // take x and y from the drag start + else if (Math.abs(this.dx) > this.dragThreshold || Math.abs(this.dy) > this.dragThreshold) + this.dragHandler({ + x: e.x - this.dx, + y: e.y - this.dy, + dx: this.dx, + dy: this.dy + }); + this.dx = 0; // Clear the drag accumulator + this.dy = 0; + } + } + // Attach the drag evaluator to the UI + attach() { + Bangle.on("drag", e => this.handleRawDrag(e)); + } +} + // *** Mid-level game mechanics // Representation of a position where a stone is set. @@ -127,6 +192,11 @@ class Field { this.centerx = (left + buttonsize / 2) + 1; this.centery = (top + buttonsize / 2) + 2; } + // Returns whether this field contains the given coordinate + contains(x, y) { + return (this.left < x && this.left + buttonsize > x && + this.top < y && this.top + buttonsize > y); + } // Generate a field for the given playing field index. // Playing field indexes start at top left with "0" // and go from left to right line by line from top to bottom. @@ -134,6 +204,16 @@ class Field { return new Field(leftstart + (index % buttonsPerLine) * (buttonsize + 2), topstart + (Math.floor(index / buttonsPerLine)) * (buttonsize + 2)); } + // Special field for the result "stone" + static forResult() { + return new Field(leftstart + (buttonsPerLine * (buttonsize + 2)), + topstart + ((buttonsPerLine - 1) * (buttonsize + 2))); + } + // Special field for the menu + static forMenu() { + return new Field(leftstart + (buttonsPerLine * (buttonsize + 2)), + topstart); + } } // Representation of a moveable stone of the game. @@ -217,11 +297,11 @@ class Mover extends Clearer { animateStep(step, worker) { this.clearArea(); this.stone.draw(this.stepField(step)); - if (step < this.steps) // still steps left: Issue next step + if (step < this.steps) // still steps left: Issue next step setTimeout(function(t) { t.animateStep(step + 1, worker); }, animationWaitMillis, this); - else // all steps done: Inform the worker + else // all steps done: Inform the worker worker.endTask(); } // Start the animation, this method is called by the worker @@ -232,22 +312,54 @@ class Mover extends Clearer { // Representation of the playing field // Knows to draw the field and to move a stone into a gap -// TODO: More game mechanics (shuffling, solving,...) +// TODO: More game mechanics (solving,...) class Board { // Generates the actual playing field with all fields and buttons constructor() { this.fields = []; - this.buttons = []; - for (i = 0; i < (buttonsPerLine * buttonsPerLine); i++) { + this.resultField = Field.forResult(); + this.menuField = Field.forMenu(); + for (i = 0; i < buttonsPerBoard; i++) this.fields[i] = Field.forIndex(i); - this.buttons[i] = new Stone((i + 1) % (buttonsPerLine * buttonsPerLine),i); + this.setShuffled(); + } + // Set the board into the "solved" position + setSolved() { + this.buttons = []; + for (i = 0; i < buttonsPerBoard; i++) + this.buttons[i] = new Stone((i + 1) % buttonsPerBoard, i); + this.moveCount = 0; + } + setShuffled() { + let nrs = []; + for (i = 0; i < buttonsPerBoard; i++) + nrs[i] = i; + this.buttons = []; + let count = buttonsPerBoard; + for (i = 0; i < buttonsPerBoard; i++) { + let curridx = Math.floor(Math.random() * count); + let currnr = nrs[curridx]; + this.buttons[i] = new Stone(currnr, (currnr + (buttonsPerBoard - 1)) % buttonsPerBoard); + for (j = curridx + 1; j < count; j++) + nrs[j - 1] = nrs[j]; + count -= 1; } + if (!this.isSolvable()) { + let a = (this.buttons[0].number === 0 ? 2 : 0); + let b = (this.buttons[1].number === 0 ? 2 : 1); + let bx = this.buttons[a]; + this.buttons[a] = this.buttons[b]; + this.buttons[b] = bx; + } + this.moveCount = 0; } // Draws the complete playing field draw() { new Clearer(this.fields[0], this.fields[this.fields.length - 1]).clearArea(); for (i = 0; i < this.fields.length; i++) this.buttons[i].draw(this.fields[i]); + this.drawResult(null); + this.drawMenu(); } // returns the index of the field left of the field with the given index, // -1 if there is none (index indicates already a leftmost field on the board) @@ -270,36 +382,44 @@ class Board { return i; return -1; } + // Returns the row in which the gap is, 0 is upmost + rowOf0() { + let idx = this.indexOf0(); + if (idx < 0) + return -1; + return Math.floor(idx / buttonsPerLine); + } // Moves the stone at the field with the index found by the startfunc operation // into the gap field. - moveTo0(startfunc, animator) { + moveTo0(startfunc, worker) { let endidx = this.indexOf0(); // Target field (the gap) if (endidx === -1) { - animator.endTask(); + worker.endTask(); return; } - let startidx = startfunc(endidx); // Start field (relative to the gap) + let startidx = startfunc(endidx); // Start field (relative to the gap) if (startidx === -1) { - animator.endTask(); + worker.endTask(); return; } let moved = this.buttons[startidx]; this.buttons[startidx] = this.buttons[endidx]; this.buttons[endidx] = moved; - new Mover(moved, this.fields[startidx], this.fields[endidx], animationSteps).animate(animator); + this.moveCount += 1; + new Mover(moved, this.fields[startidx], this.fields[endidx], animationSteps).animate(worker); } // Move the stone right fro the gap into the gap - moveRight(animator) { - this.moveTo0(this.leftOf, animator); + moveRight(worker) { + this.moveTo0(this.leftOf, worker); } - moveLeft(animator) { - this.moveTo0(this.rightOf, animator); + moveLeft(worker) { + this.moveTo0(this.rightOf, worker); } - moveUp(animator) { - this.moveTo0(this.bottomOf, animator); + moveUp(worker) { + this.moveTo0(this.bottomOf, worker); } - moveDown(animator) { - this.moveTo0(this.topOf, animator); + moveDown(worker) { + this.moveTo0(this.topOf, worker); } // Check if the board is solved (all stones at the right position) isSolved() { @@ -308,54 +428,152 @@ class Board { return false; return true; } + // counts the inversions on the board + // see https://www.geeksforgeeks.org/check-instance-15-puzzle-solvable/ + getInversionCount() { + let inversions = 0; + for (outer = 0; outer < buttonsPerBoard - 1; outer++) { + let outernr = this.buttons[outer].number; + if (outernr === 0) + continue; + for (inner = outer + 1; inner < buttonsPerBoard; inner++) { + let innernr = this.buttons[inner].number; + if (innernr > 0 && outernr > innernr) + inversions++; + } + } + return inversions; + } + // return whether the puzzle is solvable + // see https://www.geeksforgeeks.org/check-instance-15-puzzle-solvable/ + isSolvable() { + let invs = this.getInversionCount(); + if (buttonsPerLine % 2 !== 0) // odd number of rows/columns + return (invs % 2 === 0); + else { + return ((invs + this.rowOf0()) % 2 !== 0); + } + } + // draw the result field, pass null as argument if not called from worker + drawResult(worker) { + let field = this.resultField; + if (this.isSolved()) + g.setColor(0, 1, 0); + else + g.setColor(1, 0, 0); + g.fillRect(field.left, field.top, field.left + buttonsize, field.top + buttonsize); + g.setColor(0, 0, 0); + g.drawRect(field.left, field.top, field.left + buttonsize, field.top + buttonsize); + g.setFont("Vector", 14).setFontAlign(0, 0).drawString(this.moveCount, field.centerx, field.centery); + if (worker !== null) + worker.endTask(); + } + // draws the menu button + drawMenu() { + let field = this.menuField; + g.setColor(0.5, 0.5, 0.5); + g.fillRect(field.left, field.top, field.left + buttonsize, field.top + buttonsize); + g.setColor(0, 0, 0); + g.drawRect(field.left, field.top, field.left + buttonsize, field.top + buttonsize); + let l = field.left + 8; + let r = field.left + buttonsize - 8; + let t = field.top + 5; + for (i = 0; i < 3; i++) + g.fillRect(l, t + (i * 7), r, t + (i * 7) + 3); + } } +/* +// Main class, containing the complete game logic +class Puzzle15 { + constructor() { + this.worker=new Worker(); + this.board=new Board(); + } +} +*/ + // *** Main program // We need a worker... var worker = new Worker(); + +setButtonsPerLine(3); // ...and the board var board = new Board(); -// UI: Accumulation of current drag operation -var currentdrag = { - x: 0, - y: 0 -}; +var dragger; + +function initGame(bpl) { + setButtonsPerLine(bpl); + board = new Board(); + board.draw(); + dragger.setEnabled(true); +} + +function showMenu() { + var mainmenu = { + "": { + "title": "15 Puzzle" + }, + "< Back": () => { + E.showMenu(); + dragger.setEnabled(true); + board.draw(); + }, // remove the menu + "Start 3x3": function() { + E.showMenu(); + initGame(3); + }, + "Start 4x4": function() { + E.showMenu(); + initGame(4); + }, + "Start 5x5": function() { + E.showMenu(); + initGame(5); + } + }; + dragger.setEnabled(false); + + E.showMenu(mainmenu); +} + +function handleclick(e) { + if (board.menuField.contains(e.x, e.y)) { + console.log("GGG - handleclick, dragger: " + dragger); + g.reset(); + showMenu(); + console.log("showing menu ended"); + } +} // Handle a drag event function handledrag(e) { - if (e.b === 0) { // Drag event ended: Evaluate drag and start move operation - if (Math.abs(currentdrag.x) > Math.abs(currentdrag.y)) { // Horizontal drag - if (currentdrag.x > dragThreshold) - worker.addTask(e => board.moveRight(e)); - else if (currentdrag.x < -dragThreshold) - worker.addTask(e => board.moveLeft(e)); - } else { // Vertical drag - if (currentdrag.y > dragThreshold) - worker.addTask(e => board.moveDown(e)); - else if (currentdrag.y < -dragThreshold) - worker.addTask(e => board.moveUp(e)); - } - currentdrag.x = 0; // Clear the drag accumulator - currentdrag.y = 0; - } else { // Drag still running: Accumulate drag shifts - currentdrag.x += e.dx; - currentdrag.y += e.dy; - } + worker.addTask(Math.abs(e.dx) > Math.abs(e.dy) ? + (e.dx > 0 ? e => board.moveRight(e) : e => board.moveLeft(e)) : + (e.dy > 0 ? e => board.moveDown(e) : e => board.moveUp(e))); + worker.addTask(e => board.drawResult(e)); } // Clear the screen once, at startup g.clear(); -// Drop mode as this is a game -Bangle.setUI(undefined); + +// Clock mode allows short-press on button to exit +Bangle.setUI("clock"); // Load widgets Bangle.loadWidgets(); Bangle.drawWidgets(); // Draw the board initially board.draw(); + +dragger = new Dragger(handleclick, handledrag, clickThreshold, dragThreshold); + +showMenu(); // Start the interaction -Bangle.on("drag", handledrag); +dragger.attach(); + +console.log("GGG - main program, dragger: " + dragger); // end of file \ No newline at end of file From 46286e13b52127774ffe0f48ee7230e8b19bfdc7 Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Mon, 3 Jan 2022 18:12:04 +0100 Subject: [PATCH 187/489] Puzzle15: v0.03 with splash screen and working menu system --- apps.json | 2 +- apps/puzzle15/ChangeLog | 1 + apps/puzzle15/README.md | 27 ++++--- apps/puzzle15/introscreen.png | Bin 0 -> 3717 bytes apps/puzzle15/puzzle15.app.js | 147 ++++++++++++++++++++++------------ 5 files changed, 116 insertions(+), 61 deletions(-) create mode 100644 apps/puzzle15/introscreen.png diff --git a/apps.json b/apps.json index 4a3d8c7c8..f6ef51546 100644 --- a/apps.json +++ b/apps.json @@ -5393,7 +5393,7 @@ { "id": "puzzle15", "name": "15 puzzle", - "version": "0.02", + "version": "0.03", "description": "A 15 puzzle game with drag gesture interface", "readme":"README.md", "icon": "puzzle15.app.png", diff --git a/apps/puzzle15/ChangeLog b/apps/puzzle15/ChangeLog index bc5a4422b..d7458c968 100644 --- a/apps/puzzle15/ChangeLog +++ b/apps/puzzle15/ChangeLog @@ -1,2 +1,3 @@ 0.01: Initial version, UI mechanics ready, no real game play so far 0.02: Lots of enhancements, menu system not yet functional, but packaging should be now... +0.03: Menu logic now generally functioning, splash screen added. The first really playable version! diff --git a/apps/puzzle15/README.md b/apps/puzzle15/README.md index 540646f97..eddeb3b94 100644 --- a/apps/puzzle15/README.md +++ b/apps/puzzle15/README.md @@ -1,18 +1,27 @@ # Puzzle15 - A 15-puzzle for the Bangle.js 2 -Puzzle15 implements a 15-puzzle on the screen of the Bangle.js 2 smart watch. -A "15-puzzle" is a single-player game. 15 "stones" are numbered from 1 to 15 and placed randomly on a 4 by 4 playing field. -So, one place on the field is free. -The target of the game is to move the stones around (using the "gap" on the playing field) to bring them in natural order. +This is a Bangle.js 2 adoption of the famous 15 puzzle. -_This is work in progress!_ +## The game + +A board of n x n fields is filled with n²-1 numbered stones. +Bring them in the correct order so that the gap is finally at the bottom right of the playing field. +The less moves you need, the better you are. ## How to play -After starting the game, the playing field is shown with the stones in the corrct order. -Push the stones around with drag gestures (left to right, right to left, top to bottom, bottom to top) to shuffle them. -Then, use the same gestures to restore the order. +Select whether you want to play on a board with 3 x 3, 4 x 4, or 5 x 5 fields. +Move the stones with drag gestures on the screen. +If you want to move the stone below the gap upward, drag from the bottom of the screen upward. +The drag gestures can be performed anywhere on the screen, there is no need to start or end them on the stone to be moved. -So far, there are no other capabililties or options. +If you managed to order the stones correctly, a success message appears. +You can continue with another game, go to the game's main menu, or quit the game entirely. + +There is a menu button right of the board. It opens the game's main menu. + +## Implemenation notes + +The game engine always generates 15 puzzles which can be solved. Have fun! diff --git a/apps/puzzle15/introscreen.png b/apps/puzzle15/introscreen.png new file mode 100644 index 0000000000000000000000000000000000000000..766cd61fadbcf8afb58f5bbea090796c89df5eb1 GIT binary patch literal 3717 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 { + gameEnd(this.moveCount); + }, 500); } // draws the menu button drawMenu() { @@ -479,22 +500,39 @@ class Board { let r = field.left + buttonsize - 8; let t = field.top + 5; for (i = 0; i < 3; i++) - g.fillRect(l, t + (i * 7), r, t + (i * 7) + 3); + g.fillRect(l, t + (i * 6), r, t + (i * 6) + 2); } } -/* -// Main class, containing the complete game logic -class Puzzle15 { - constructor() { - this.worker=new Worker(); - this.board=new Board(); - } +function framedText(text, x, y, textcol, framecol) { + g.setColor(framecol); + for (i = -2; i < 3; i++) + for (j = -2; j < 3; j++) { + if (i === 0 && j === 0) + continue; + g.drawString(text, x + i, y + j); + } + g.setColor(textcol).drawString(text, x, y); +} + +function showSplash(afterSplash) { + g.reset(); + g.drawImage(introscreen, 0, 0); + setTimeout(() => { + g.setFont("Vector", 40).setFontAlign(0, 0); + framedText("15", g.getWidth() / 2, g.getHeight() / 2 - g.getFontHeight() * 0.66, "#f00", "#fff"); + setTimeout(() => { + g.setFont("Vector", 40).setFontAlign(0, 0); + framedText("Puzzle", g.getWidth() / 2, g.getHeight() / 2 + g.getFontHeight() * 0.66, "#f00", "#fff"); + setTimeout(afterSplash, 2000); + }, 1000); + }, 2000); } -*/ // *** Main program +g.reset(); + // We need a worker... var worker = new Worker(); @@ -504,48 +542,61 @@ var board = new Board(); var dragger; +// Initialize the game with an explicit number of stones per line function initGame(bpl) { setButtonsPerLine(bpl); + newGame(); +} + +// Start a new game with the same number of stones per line as before +function newGame() { board = new Board(); + continueGame(); +} + +// Continue the currently running game +function continueGame() { + E.showMenu(); board.draw(); dragger.setEnabled(true); } -function showMenu() { +// Show message on game end, allows to restart new game +function gameEnd(moveCount) { + dragger.setEnabled(false); + E.showPrompt("You solved the\n" + buttonsPerLine + "x" + buttonsPerLine + " puzzle in\n" + moveCount + " move" + (moveCount === 1 ? "" : "s") + ".", { + title: "Puzzle solved", + buttons: { + "Again": newGame, + "Menu": () => showMenu(false), + "Exit": load + } + }).then(v => { + E.showPrompt(); + setTimeout(v, 10); + }); +} + +function showMenu(withContinue) { var mainmenu = { "": { "title": "15 Puzzle" - }, - "< Back": () => { - E.showMenu(); - dragger.setEnabled(true); - board.draw(); - }, // remove the menu - "Start 3x3": function() { - E.showMenu(); - initGame(3); - }, - "Start 4x4": function() { - E.showMenu(); - initGame(4); - }, - "Start 5x5": function() { - E.showMenu(); - initGame(5); } }; + if (withContinue) + mainmenu.Continue = continueGame; + mainmenu["Start 3x3"] = () => initGame(3); + mainmenu["Start 4x4"] = () => initGame(4); + mainmenu["Start 5x5"] = () => initGame(5); + mainmenu.Exit = () => load(); dragger.setEnabled(false); - + g.clear(true); E.showMenu(mainmenu); } function handleclick(e) { - if (board.menuField.contains(e.x, e.y)) { - console.log("GGG - handleclick, dragger: " + dragger); - g.reset(); - showMenu(); - console.log("showing menu ended"); - } + if (board.menuField.contains(e.x, e.y)) + setTimeout(() => showMenu(true), 10); } // Handle a drag event @@ -556,24 +607,18 @@ function handledrag(e) { worker.addTask(e => board.drawResult(e)); } -// Clear the screen once, at startup -g.clear(); - -// Clock mode allows short-press on button to exit -Bangle.setUI("clock"); -// Load widgets -Bangle.loadWidgets(); -Bangle.drawWidgets(); - -// Draw the board initially -board.draw(); - dragger = new Dragger(handleclick, handledrag, clickThreshold, dragThreshold); -showMenu(); // Start the interaction dragger.attach(); -console.log("GGG - main program, dragger: " + dragger); +showSplash(() => { + // Clock mode allows short-press on button to exit + Bangle.setUI("clock"); + // Load widgets + Bangle.loadWidgets(); + Bangle.drawWidgets(); + showMenu(false); +}, 5000); // end of file \ No newline at end of file From 3633078a46a9526a15c023e58aeec3730692e8df Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Tue, 4 Jan 2022 17:35:52 +0100 Subject: [PATCH 188/489] Puzzle15: v0.04 with settings, formatting changes, about screen --- apps.json | 6 +- apps/puzzle15/ChangeLog | 1 + apps/puzzle15/README.md | 40 +++- apps/puzzle15/puzzle15.app.js | 357 ++++++++++++++++++++--------- apps/puzzle15/puzzle15.settings.js | 50 ++++ 5 files changed, 339 insertions(+), 115 deletions(-) create mode 100644 apps/puzzle15/puzzle15.settings.js diff --git a/apps.json b/apps.json index f6ef51546..3a390938d 100644 --- a/apps.json +++ b/apps.json @@ -5393,7 +5393,7 @@ { "id": "puzzle15", "name": "15 puzzle", - "version": "0.03", + "version": "0.04", "description": "A 15 puzzle game with drag gesture interface", "readme":"README.md", "icon": "puzzle15.app.png", @@ -5404,7 +5404,9 @@ "allow_emulator": true, "storage": [ {"name":"puzzle15.app.js","url":"puzzle15.app.js"}, + {"name":"puzzle15.settings.js","url":"puzzle15.settings.js"}, {"name":"puzzle15.img","url":"puzzle15.app-icon.js","evaluate":true} - ] + ], + "data": [{"name":"puzzle15.json"}] } ] diff --git a/apps/puzzle15/ChangeLog b/apps/puzzle15/ChangeLog index d7458c968..bd6af53d8 100644 --- a/apps/puzzle15/ChangeLog +++ b/apps/puzzle15/ChangeLog @@ -1,3 +1,4 @@ 0.01: Initial version, UI mechanics ready, no real game play so far 0.02: Lots of enhancements, menu system not yet functional, but packaging should be now... 0.03: Menu logic now generally functioning, splash screen added. The first really playable version! +0.04: Settings dialog, about screen diff --git a/apps/puzzle15/README.md b/apps/puzzle15/README.md index eddeb3b94..16c0c4593 100644 --- a/apps/puzzle15/README.md +++ b/apps/puzzle15/README.md @@ -4,13 +4,16 @@ This is a Bangle.js 2 adoption of the famous 15 puzzle. ## The game -A board of n x n fields is filled with n²-1 numbered stones. +A board of _n_ by _n_ fields is filled with _n^2-1_ numbered stones. So, one field, the "gap", is left free. + Bring them in the correct order so that the gap is finally at the bottom right of the playing field. The less moves you need, the better you are. +If _n_ is 4, the number of stones is _16-1=15_. Hence the name of the game. + ## How to play -Select whether you want to play on a board with 3 x 3, 4 x 4, or 5 x 5 fields. +If you start the game, it shows a splash screen and then generates a shuffled 4x4 board with a 15 puzzle. Move the stones with drag gestures on the screen. If you want to move the stone below the gap upward, drag from the bottom of the screen upward. The drag gestures can be performed anywhere on the screen, there is no need to start or end them on the stone to be moved. @@ -18,10 +21,37 @@ The drag gestures can be performed anywhere on the screen, there is no need to s If you managed to order the stones correctly, a success message appears. You can continue with another game, go to the game's main menu, or quit the game entirely. -There is a menu button right of the board. It opens the game's main menu. +There is a grey menu button right of the board containing the well-known three-bar menu symbol ("Hamburger menu"). +It opens the game's main menu directly from within the game. -## Implemenation notes +## The main menu -The game engine always generates 15 puzzles which can be solved. +Puzzle15 has a main menu which can be reached from the in-game menu button or the end-of-game message window. +It features the following options: + +* **Continue** - Continue the currently running game. _This option is only shown if the main menu is opened during an open game._ +* **Start 3x3**, **Start 4x4**, **Start 5x5** - Start a new game on a board with the respective dimension. Any currently open game is dropped. +* **About** Show a small "About" info box. +* **Exit** Exit Puzzle15 and return to the default watch face. + +## Game settings + +The game has some global settings which can be accessed on the usual way through the Bangle.js' app settings user interface. +Currently it has the following options: + +* **Splash** - Define whether the game should open with a splash screen. **long** shows the splash screen for five seconds, **short** shows it for two seconds. **off** starts the app _without_ a splash screen, it directly comes up with whatever the "Start with" option says. +* **Start with** - What should happen after the splash screen (or, if it is disabled, directly at app start): **3x3**, **4x4** and **5x5** start the game with a board of the respective dimension, **menu** shows the main menu which allows to select the board size. + +## Implementation notes + +The game engine always generates puzzles which can be solved. + +Solvability is detected by counting inversions, +i.e. pairs of stones where the stone at the earlier field (row-wise, left to right, top to bottom) has a number _greater than_ the stone on the later field, with all pairs of stones compared. +The algorithm is described at https://www.geeksforgeeks.org/check-instance-15-puzzle-solvable/ . + +## The splash screen + +The Splash screen shows a part of the illustration "The 14-15-puzzle in puzzleland" from Sam Loyd. Other than Puzzle15, it depicts a 15 puzzle with the stones "14" and "15" swapped. This puzzle is indeed *not* solvable. Have fun! diff --git a/apps/puzzle15/puzzle15.app.js b/apps/puzzle15/puzzle15.app.js index c5c60bb0f..e66f9b9bb 100644 --- a/apps/puzzle15/puzzle15.app.js +++ b/apps/puzzle15/puzzle15.app.js @@ -2,36 +2,37 @@ // (C) Dirk Hillbrecht 2022 // Released unter the terms of the MIT license -// *** Global settings -// Note: These could be changed by settings later... - +// The intro screen as large base-64-encoded binary data const introscreen = E.toArrayBuffer(atob("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")); +// *** Global constants from which several other settings are derived + // Minimum number of pixels to interpret it as drag gesture const dragThreshold = 10; // Maximum number of pixels to interpret a click from a drag event series const clickThreshold = 3; -// Number of steps in button move animation +// Number of steps in stone move animation const animationSteps = 6; // Milliseconds to wait between move animation steps const animationWaitMillis = 30; -// *** Global settings derived by device characteristics - // Total width of the playing field (full screen width) const fieldw = g.getWidth(); // Total height of the playing field (screen height minus widget zones) const fieldh = g.getHeight() - 48; -// Size of the playing field -var buttonsPerLine; -// Size of one button -var buttonsize; +// *** Global game characteristics + +// Size of the playing field +var stonesPerLine; + +// Size of one field +var stonesize; // Actual left start of the playing field (so that it is centered) var leftstart; @@ -39,18 +40,51 @@ var leftstart; // Actual top start of the playing field (so that it is centered) var topstart; -// Number of buttons on the board (needed at several occasions) -var buttonsPerBoard; +// Number of stones on the board (needed at several occasions) +var stonesPerBoard; -// Set the buttons per line globally and all derived values, too -function setButtonsPerLine(bPL) { - buttonsPerLine = bPL; - buttonsize = Math.floor(Math.min(fieldw / (buttonsPerLine + 1), fieldh / buttonsPerLine)) - 2; - leftstart = (fieldw - ((buttonsPerLine + 1) * buttonsize + 8)) / 2; - topstart = 24 + ((fieldh - (buttonsPerLine * buttonsize + 6)) / 2); - buttonsPerBoard = (buttonsPerLine * buttonsPerLine); +// Set the stones per line globally and all derived values, too +function setStonesPreLine(bPL) { + stonesPerLine = bPL; + stonesize = Math.floor(Math.min(fieldw / (stonesPerLine + 1), fieldh / stonesPerLine)) - 2; + leftstart = (fieldw - ((stonesPerLine + 1) * stonesize + 8)) / 2; + topstart = 24 + ((fieldh - (stonesPerLine * stonesize + 6)) / 2); + stonesPerBoard = (stonesPerLine * stonesPerLine); } + +// *** Global app settings + +var SETTINGSFILE = "puzzle15.json"; + +// variables defined from settings +var splashMode; +var startWith; + +/* For development purposes +require('Storage').writeJSON(SETTINGSFILE, { + splashMode: "off", + startWith: "5x5", +}); +/* */ + +/* OR (also for development purposes) +require('Storage').erase(SETTINGSFILE); +/* */ + +// Helper method for loading the settings +function def(value, def) { + return (value !== undefined ? value : def); +} + +// Load settings +function loadSettings() { + var settings = require('Storage').readJSON(SETTINGSFILE, true) || {}; + splashMode = def(settings.splashMode, "long"); + startWith = def(settings.startWith, "4x4"); +} + + // *** Low level helper classes // One node of a first-in-first-out storage @@ -64,11 +98,13 @@ class FifoNode { // Simple first-in-first-out (fifo) storage // Needed to keep the stone movements in order class Fifo { + // Initialize an empty Fifo constructor() { this.first = null; this.last = null; } + // Add an element to the end of the internal fifo queue add(payload) { if (this.last === null) { // queue is empty @@ -80,6 +116,7 @@ class Fifo { this.last = newlast; } } + // Returns the first element in the queue, null if it is empty remove() { if (this.first === null) @@ -90,10 +127,12 @@ class Fifo { this.last = null; return oldfirst.payload; } + // Returns if the fifo is empty, i.e. it does not hold any elements isEmpty() { return (this.first === null); } + } // Helper class to keep track of tasks @@ -104,11 +143,13 @@ class Fifo { // previously scheduled tasks have finished. // Tasks must be functions with the Worker as first and only parameter. class Worker { + // Create an empty worker constructor() { this.tasks = new Fifo(); this.busy = false; } + // Add a task to the worker addTask(task) { if (this.busy) // other task is running: Queue this task @@ -118,6 +159,7 @@ class Worker { task(this); } } + // Called by the task once it finished endTask() { if (this.tasks.isEmpty()) // No more tasks queued: Become idle @@ -125,6 +167,7 @@ class Worker { else // Call the next task immediately this.tasks.remove()(this); } + } // Evaluate "drag" events from the UI and call handlers for drags or clicks @@ -135,6 +178,7 @@ class Worker { // otherwise as drag. // The approprate method is called with the data of the drag. class Dragger { + constructor(clickHandler, dragHandler, clickThreshold, dragThreshold) { this.clickHandler = clickHandler; this.dragHandler = dragHandler; @@ -144,10 +188,12 @@ class Dragger { this.dy = 0; this.enabled = true; } + // Enable or disable the Dragger setEnabled(b) { this.enabled = b; } + // Handle a raw drag event from the UI handleRawDrag(e) { if (!this.enabled) @@ -171,6 +217,7 @@ class Dragger { this.dy = 0; } } + // Attach the drag evaluator to the UI attach() { Bangle.on("drag", e => this.handleRawDrag(e)); @@ -185,37 +232,43 @@ class Dragger { // During an animation, a series of interim field instances is generated // which represents the locations of a stone during the animation. class Field { + // Generate a field with a left and a top coordinate. // Note that these coordinates are "cooked", i.e. they contain all offsets // needed place the elements globally correct on the screen constructor(left, top) { this.left = left; this.top = top; - this.centerx = (left + buttonsize / 2) + 1; - this.centery = (top + buttonsize / 2) + 2; + this.centerx = (left + stonesize / 2) + 1; + this.centery = (top + stonesize / 2) + 2; } + // Returns whether this field contains the given coordinate contains(x, y) { - return (this.left < x && this.left + buttonsize > x && - this.top < y && this.top + buttonsize > y); + return (this.left < x && this.left + stonesize > x && + this.top < y && this.top + stonesize > y); } + // Generate a field for the given playing field index. // Playing field indexes start at top left with "0" // and go from left to right line by line from top to bottom. static forIndex(index) { - return new Field(leftstart + (index % buttonsPerLine) * (buttonsize + 2), - topstart + (Math.floor(index / buttonsPerLine)) * (buttonsize + 2)); + return new Field(leftstart + (index % stonesPerLine) * (stonesize + 2), + topstart + (Math.floor(index / stonesPerLine)) * (stonesize + 2)); + } // Special field for the result "stone" static forResult() { - return new Field(leftstart + (buttonsPerLine * (buttonsize + 2)), - topstart + ((buttonsPerLine - 1) * (buttonsize + 2))); + return new Field(leftstart + (stonesPerLine * (stonesize + 2)), + topstart + ((stonesPerLine - 1) * (stonesize + 2))); } + // Special field for the menu static forMenu() { - return new Field(leftstart + (buttonsPerLine * (buttonsize + 2)), + return new Field(leftstart + (stonesPerLine * (stonesize + 2)), topstart); } + } // Representation of a moveable stone of the game. @@ -224,6 +277,7 @@ class Field { // Stone "0" represents the gap on the playing field. // The main knowledge of a Stone instance is how to draw itself. class Stone { + // Create stone with the given number // The constructor creates the "draw()" function which is used to draw the stone constructor(number, targetindex) { @@ -232,22 +286,23 @@ class Stone { // gap: Does not draw anything if (number === 0) this.draw = function(field) {}; - else if ((number + (buttonsPerLine % 2 == 0 ? (Math.floor((number - 1) / buttonsPerLine)) : 0)) % 2 == 0) { + else if ((number + (stonesPerLine % 2 == 0 ? (Math.floor((number - 1) / stonesPerLine)) : 0)) % 2 == 0) { // Black stone this.draw = function(field) { - g.setFont("Vector", 20).setFontAlign(0, 0).setColor(0, 0, 0); - g.fillRect(field.left, field.top, field.left + buttonsize, field.top + buttonsize); + g.setFont("Vector", (stonesPerLine === 5 ? 16 : 20)).setFontAlign(0, 0).setColor(0, 0, 0); + g.fillRect(field.left, field.top, field.left + stonesize, field.top + stonesize); g.setColor(1, 1, 1).drawString(number, field.centerx, field.centery); }; } else { // White stone this.draw = function(field) { - g.setFont("Vector", 20).setFontAlign(0, 0).setColor(0, 0, 0); - g.drawRect(field.left, field.top, field.left + buttonsize, field.top + buttonsize); + g.setFont("Vector", (stonesPerLine === 5 ? 16 : 20)).setFontAlign(0, 0).setColor(0, 0, 0); + g.drawRect(field.left, field.top, field.left + stonesize, field.top + stonesize); g.drawString(number, field.centerx, field.centery); }; } } + // Returns whether this stone is on its target index isOnTarget(index) { return index === this.targetindex; @@ -256,6 +311,7 @@ class Stone { // Helper class which knows how to clear the rectangle opened up by the two given fields class Clearer { + // Create a clearer for the area between the two given fields constructor(startfield, endfield) { this.minleft = Math.min(startfield.left, endfield.left); @@ -263,16 +319,19 @@ class Clearer { this.maxleft = Math.max(startfield.left, endfield.left); this.maxtop = Math.max(startfield.top, endfield.top); } + // Clear the area defined by this clearer clearArea() { g.setColor(1, 1, 1); g.fillRect(this.minleft, this.mintop, - this.maxleft + buttonsize, this.maxtop + buttonsize); + this.maxleft + stonesize, this.maxtop + stonesize); } + } // Helper class which moves a stone between two fields class Mover extends Clearer { + // Create a mover which moves the given stone from startfield to endfield // and animate the move in the given number of steps constructor(stone, startfield, endfield, steps) { @@ -282,11 +341,13 @@ class Mover extends Clearer { this.endfield = endfield; this.steps = steps; } + // Create the coordinate between start and end for the given step // Computation uses sinus for a smooth movement stepCoo(start, end, step) { return start + ((end - start) * ((1 + Math.sin((step / this.steps) * Math.PI - (Math.PI / 2))) / 2)); } + // Compute the interim field for the stone to place during the animation stepField(step) { return new Field( @@ -295,6 +356,7 @@ class Mover extends Clearer { (this.mintop === this.maxtop ? this.mintop : this.stepCoo(this.startfield.top, this.endfield.top, step))); } + // Perform one animation step animateStep(step, worker) { this.clearArea(); @@ -306,53 +368,60 @@ class Mover extends Clearer { else // all steps done: Inform the worker worker.endTask(); } + // Start the animation, this method is called by the worker animate(worker) { this.animateStep(1, worker); } + } // Representation of the playing field // Knows to draw the field and to move a stone into a gap -// TODO: More game mechanics (solving,...) class Board { - // Generates the actual playing field with all fields and buttons + + // Generates the actual playing field with all fields and stones constructor() { this.fields = []; this.resultField = Field.forResult(); this.menuField = Field.forMenu(); - for (i = 0; i < buttonsPerBoard; i++) + for (i = 0; i < stonesPerBoard; i++) this.fields[i] = Field.forIndex(i); this.setShuffled(); //this.setAlmostSolved(); // to test the game end } + + /* // Set the board into the "solved" position. Useful for showcasing setSolved() { - this.buttons = []; - for (i = 0; i < buttonsPerBoard; i++) - this.buttons[i] = new Stone((i + 1) % buttonsPerBoard, i); + this.stones = []; + for (i = 0; i < stonesPerBoard; i++) + this.stones[i] = new Stone((i + 1) % stonesPerBoard, i); this.moveCount = 0; } + // Initialize an almost solved playing field. Useful for tests and development setAlmostSolved() { this.setSolved(); - b = this.buttons[this.buttons.length - 1]; - this.buttons[this.buttons.length - 1] = this.buttons[this.buttons.length - 2]; - this.buttons[this.buttons.length - 2] = b; + b = this.stones[this.stones.length - 1]; + this.stones[this.stones.length - 1] = this.stones[this.stones.length - 2]; + this.stones[this.stones.length - 2] = b; } + */ + // Initialize a shuffled field. The fields are always solvable. setShuffled() { let nrs = []; // numbers of the stones - for (i = 0; i < buttonsPerBoard; i++) + for (i = 0; i < stonesPerBoard; i++) nrs[i] = i; - this.buttons = []; - let count = buttonsPerBoard; - for (i = 0; i < buttonsPerBoard; i++) { + this.stones = []; + let count = stonesPerBoard; + for (i = 0; i < stonesPerBoard; i++) { // Take a random number of the (remaining) numbers let curridx = Math.floor(Math.random() * count); let currnr = nrs[curridx]; - // Initialize the next button with that random number - this.buttons[i] = new Stone(currnr, (currnr + (buttonsPerBoard - 1)) % buttonsPerBoard); + // Initialize the next stone with that random number + this.stones[i] = new Stone(currnr, (currnr + (stonesPerBoard - 1)) % stonesPerBoard); // Remove the number just taken from the list of numbers for (j = curridx + 1; j < count; j++) nrs[j - 1] = nrs[j]; @@ -361,52 +430,68 @@ class Board { // not solvable: Swap the first and second stone which are not the gap. // This will always result in a solvable board. if (!this.isSolvable()) { - let a = (this.buttons[0].number === 0 ? 2 : 0); - let b = (this.buttons[1].number === 0 ? 2 : 1); - let bx = this.buttons[a]; - this.buttons[a] = this.buttons[b]; - this.buttons[b] = bx; + let a = (this.stones[0].number === 0 ? 2 : 0); + let b = (this.stones[1].number === 0 ? 2 : 1); + let bx = this.stones[a]; + this.stones[a] = this.stones[b]; + this.stones[b] = bx; } this.moveCount = 0; } + // Draws the complete playing field draw() { new Clearer(this.fields[0], this.fields[this.fields.length - 1]).clearArea(); for (i = 0; i < this.fields.length; i++) - this.buttons[i].draw(this.fields[i]); + this.stones[i].draw(this.fields[i]); this.drawResult(null); this.drawMenu(); } + // returns the index of the field left of the field with the given index, // -1 if there is none (index indicates already a leftmost field on the board) leftOf(index) { - return (index % buttonsPerLine === 0 ? -1 : index - 1); + return (index % stonesPerLine === 0 ? -1 : index - 1); } + + // returns the index of the field right of the field with the given index, + // -1 if there is none (index indicates already a rightmost field on the board) rightOf(index) { - return (index % buttonsPerLine === (buttonsPerLine - 1) ? -1 : index + 1); + return (index % stonesPerLine === (stonesPerLine - 1) ? -1 : index + 1); } + + // returns the index of the field top of the field with the given index, + // -1 if there is none (index indicates already a topmost field on the board) topOf(index) { - return (index >= buttonsPerLine ? index - buttonsPerLine : -1); + return (index >= stonesPerLine ? index - stonesPerLine : -1); } + + // returns the index of the field bottom of the field with the given index, + // -1 if there is none (index indicates already a bottommost field on the board) bottomOf(index) { - return (index < (buttonsPerLine - 1) * buttonsPerLine ? index + buttonsPerLine : -1); + return (index < (stonesPerLine - 1) * stonesPerLine ? index + stonesPerLine : -1); } + // Return the index of the gap in the field, -1 if there is none (should never happel) indexOf0() { - for (i = 0; i < this.buttons.length; i++) - if (this.buttons[i].number === 0) + for (i = 0; i < this.stones.length; i++) + if (this.stones[i].number === 0) return i; return -1; } + // Returns the row in which the gap is, 0 is upmost rowOf0() { let idx = this.indexOf0(); if (idx < 0) return -1; - return Math.floor(idx / buttonsPerLine); + return Math.floor(idx / stonesPerLine); } - // Moves the stone at the field with the index found by the startfunc operation - // into the gap field. + + // Searches the gap on the field and then moves one of the adjacent stones into it. + // The stone is selected by the given startfunc which returns the index + // of the selected adjacent field. + // Startfunc is one of (left|right|top|bottom)Of. moveTo0(startfunc, worker) { let endidx = this.indexOf0(); // Target field (the gap) if (endidx === -1) { @@ -418,58 +503,71 @@ class Board { worker.endTask(); return; } - let moved = this.buttons[startidx]; - this.buttons[startidx] = this.buttons[endidx]; - this.buttons[endidx] = moved; + // Replace in the internal representation + let moved = this.stones[startidx]; + this.stones[startidx] = this.stones[endidx]; + this.stones[endidx] = moved; this.moveCount += 1; + // Move on screen using an animation effect. new Mover(moved, this.fields[startidx], this.fields[endidx], animationSteps).animate(worker); } - // Move the stone right fro the gap into the gap + + // Move the stone right from the gap into the gap moveRight(worker) { this.moveTo0(this.leftOf, worker); } + + // Move the stone left from the gap into the gap moveLeft(worker) { this.moveTo0(this.rightOf, worker); } + + // Move the stone above the gap into the gap moveUp(worker) { this.moveTo0(this.bottomOf, worker); } + + // Move the stone below the gap into the gap moveDown(worker) { this.moveTo0(this.topOf, worker); } + // Check if the board is solved (all stones at the right position) isSolved() { - for (i = 0; i < this.buttons.length; i++) - if (!this.buttons[i].isOnTarget(i)) + for (i = 0; i < this.stones.length; i++) + if (!this.stones[i].isOnTarget(i)) return false; return true; } + // counts the inversions on the board // see https://www.geeksforgeeks.org/check-instance-15-puzzle-solvable/ getInversionCount() { let inversions = 0; - for (outer = 0; outer < buttonsPerBoard - 1; outer++) { - let outernr = this.buttons[outer].number; + for (outer = 0; outer < stonesPerBoard - 1; outer++) { + let outernr = this.stones[outer].number; if (outernr === 0) continue; - for (inner = outer + 1; inner < buttonsPerBoard; inner++) { - let innernr = this.buttons[inner].number; + for (inner = outer + 1; inner < stonesPerBoard; inner++) { + let innernr = this.stones[inner].number; if (innernr > 0 && outernr > innernr) inversions++; } } return inversions; } + // return whether the puzzle is solvable // see https://www.geeksforgeeks.org/check-instance-15-puzzle-solvable/ isSolvable() { let invs = this.getInversionCount(); - if (buttonsPerLine % 2 !== 0) // odd number of rows/columns + if (stonesPerLine % 2 !== 0) // odd number of rows/columns return (invs % 2 === 0); else { return ((invs + this.rowOf0()) % 2 !== 0); } } + // draw the result field, pass null as argument if not called from worker drawResult(worker) { let field = this.resultField; @@ -478,9 +576,9 @@ class Board { g.setColor(0, 1, 0); else g.setColor(1, 0, 0); - g.fillRect(field.left, field.top, field.left + buttonsize, field.top + buttonsize); + g.fillRect(field.left, field.top, field.left + stonesize, field.top + stonesize); g.setColor(0, 0, 0); - g.drawRect(field.left, field.top, field.left + buttonsize, field.top + buttonsize); + g.drawRect(field.left, field.top, field.left + stonesize, field.top + stonesize); g.setFont("Vector", 14).setFontAlign(0, 0).drawString(this.moveCount, field.centerx, field.centery); if (worker !== null) worker.endTask(); @@ -489,21 +587,29 @@ class Board { gameEnd(this.moveCount); }, 500); } + // draws the menu button drawMenu() { let field = this.menuField; g.setColor(0.5, 0.5, 0.5); - g.fillRect(field.left, field.top, field.left + buttonsize, field.top + buttonsize); + g.fillRect(field.left, field.top, field.left + stonesize, field.top + stonesize); g.setColor(0, 0, 0); - g.drawRect(field.left, field.top, field.left + buttonsize, field.top + buttonsize); + g.drawRect(field.left, field.top, field.left + stonesize, field.top + stonesize); let l = field.left + 8; - let r = field.left + buttonsize - 8; + let r = field.left + stonesize - 8; let t = field.top + 5; for (i = 0; i < 3; i++) g.fillRect(l, t + (i * 6), r, t + (i * 6) + 2); } + } + +// *** Global helper methods + +// draw some text with some surrounding to increase contrast +// text is drawn at given (x,y) position with textcol. +// frame is drawn 2 pixels around (x,y) in each direction in framecol. function framedText(text, x, y, textcol, framecol) { g.setColor(framecol); for (i = -2; i < 3; i++) @@ -515,36 +621,32 @@ function framedText(text, x, y, textcol, framecol) { g.setColor(textcol).drawString(text, x, y); } +// Show the splash screen at program start, call afterSplash afterwards. +// If spash mode is "off", call afterSplash directly. function showSplash(afterSplash) { - g.reset(); - g.drawImage(introscreen, 0, 0); - setTimeout(() => { - g.setFont("Vector", 40).setFontAlign(0, 0); - framedText("15", g.getWidth() / 2, g.getHeight() / 2 - g.getFontHeight() * 0.66, "#f00", "#fff"); + if (splashMode === "off") + afterSplash(); + else { + g.reset(); + g.drawImage(introscreen, 0, 0); setTimeout(() => { g.setFont("Vector", 40).setFontAlign(0, 0); - framedText("Puzzle", g.getWidth() / 2, g.getHeight() / 2 + g.getFontHeight() * 0.66, "#f00", "#fff"); - setTimeout(afterSplash, 2000); - }, 1000); - }, 2000); + framedText("15", g.getWidth() / 2, g.getHeight() / 2 - g.getFontHeight() * 0.66, "#f00", "#fff"); + setTimeout(() => { + g.setFont("Vector", 40).setFontAlign(0, 0); + framedText("Puzzle", g.getWidth() / 2, g.getHeight() / 2 + g.getFontHeight() * 0.66, "#f00", "#fff"); + setTimeout(afterSplash, (splashMode === "long" ? 2000 : 1000)); + }, (splashMode === "long" ? 1000 : 1)); + }, (splashMode === "long" ? 2000 : 1000)); + } } -// *** Main program -g.reset(); - -// We need a worker... -var worker = new Worker(); - -setButtonsPerLine(3); -// ...and the board -var board = new Board(); - -var dragger; +// *** Global flow control // Initialize the game with an explicit number of stones per line function initGame(bpl) { - setButtonsPerLine(bpl); + setStonesPreLine(bpl); newGame(); } @@ -564,7 +666,7 @@ function continueGame() { // Show message on game end, allows to restart new game function gameEnd(moveCount) { dragger.setEnabled(false); - E.showPrompt("You solved the\n" + buttonsPerLine + "x" + buttonsPerLine + " puzzle in\n" + moveCount + " move" + (moveCount === 1 ? "" : "s") + ".", { + E.showPrompt("You solved the\n" + stonesPerLine + "x" + stonesPerLine + " puzzle in\n" + moveCount + " move" + (moveCount === 1 ? "" : "s") + ".", { title: "Puzzle solved", buttons: { "Again": newGame, @@ -577,6 +679,17 @@ function gameEnd(moveCount) { }); } +// A tiny about screen +function showAbout(doContinue) { + E.showAlert("Author: Dirk Hillbrecht\nLicense: MIT", "Puzzle15").then(() => { + if (doContinue) + continueGame(); + else + showMenu(false); + }); +} + +// Show the in-game menu allowing to start a new game function showMenu(withContinue) { var mainmenu = { "": { @@ -588,18 +701,20 @@ function showMenu(withContinue) { mainmenu["Start 3x3"] = () => initGame(3); mainmenu["Start 4x4"] = () => initGame(4); mainmenu["Start 5x5"] = () => initGame(5); + mainmenu.About = () => showAbout(withContinue); mainmenu.Exit = () => load(); dragger.setEnabled(false); g.clear(true); E.showMenu(mainmenu); } +// Handle a "click" event (only needed for menu button) function handleclick(e) { if (board.menuField.contains(e.x, e.y)) setTimeout(() => showMenu(true), 10); } -// Handle a drag event +// Handle a drag event (moving the stones around) function handledrag(e) { worker.addTask(Math.abs(e.dx) > Math.abs(e.dy) ? (e.dx > 0 ? e => board.moveRight(e) : e => board.moveLeft(e)) : @@ -607,18 +722,44 @@ function handledrag(e) { worker.addTask(e => board.drawResult(e)); } -dragger = new Dragger(handleclick, handledrag, clickThreshold, dragThreshold); -// Start the interaction +// *** Main program + +g.clear(true); + +// Load global app settings +loadSettings(); + +// We need a worker... +var worker = new Worker(); + +// Board will be initialized after the splash screen has been shown +var board; + +// Dragger is needed for interaction during the game +var dragger = new Dragger(handleclick, handledrag, clickThreshold, dragThreshold); + +// Disable dragger as board is not yet initialized +dragger.setEnabled(false); + +// Nevertheless attach it so that it is ready once the game starts dragger.attach(); +// Start the game by handling the splash screen sequence showSplash(() => { // Clock mode allows short-press on button to exit Bangle.setUI("clock"); // Load widgets Bangle.loadWidgets(); Bangle.drawWidgets(); - showMenu(false); -}, 5000); + if (startWith === "3x3") + initGame(3); + else if (startWith === "4x4") + initGame(4); + else if (startWith === "5x5") + initGame(5); + else + showMenu(false); +}); -// end of file \ No newline at end of file +// end of file diff --git a/apps/puzzle15/puzzle15.settings.js b/apps/puzzle15/puzzle15.settings.js new file mode 100644 index 000000000..352ec4315 --- /dev/null +++ b/apps/puzzle15/puzzle15.settings.js @@ -0,0 +1,50 @@ +// Settings menu for the Puzzle15 app + +(function(back) { + var FILE = "puzzle15.json"; + // Load settings + var settings = Object.assign({ + splashMode: "long", + startWith: "4x4" + }, require('Storage').readJSON(FILE, true) || {}); + + function writeSettings() { + require('Storage').writeJSON(FILE, settings); + } + + // Helper method which uses int-based menu item for set of string values + function stringItems(startvalue, writer, values) { + return { + value: (startvalue === undefined ? 0 : values.indexOf(startvalue)), + format: v => values[v], + min: 0, + max: values.length - 1, + wrap: true, + step: 1, + onchange: v => { + writer(values[v]); + writeSettings(); + } + }; + } + + // Helper method which breaks string set settings down to local settings object + function stringInSettings(name, values) { + return stringItems(settings[name], v => settings[name] = v, values); + } + + var mainmenu = { + "": { + "title": "15 Puzzle" + }, + "< Back": () => back(), + "Splash": stringInSettings("splashMode", ["long", "short", "off"]), + "Start with": stringInSettings("startWith", ["3x3", "4x4", "5x5", "menu"]) + }; + + // Actually display the menu + E.showMenu(mainmenu); + +}); + +// end of file \ No newline at end of file From cabb0c2d7d3529da1aa9810afbdb94678633aa84 Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Wed, 5 Jan 2022 09:52:06 +0100 Subject: [PATCH 189/489] Puzzle15: v0.05: Central game end function --- apps.json | 2 +- apps/puzzle15/ChangeLog | 1 + apps/puzzle15/puzzle15.app.js | 20 +++++++++++++------- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/apps.json b/apps.json index 3a390938d..c213fdaa6 100644 --- a/apps.json +++ b/apps.json @@ -5393,7 +5393,7 @@ { "id": "puzzle15", "name": "15 puzzle", - "version": "0.04", + "version": "0.05", "description": "A 15 puzzle game with drag gesture interface", "readme":"README.md", "icon": "puzzle15.app.png", diff --git a/apps/puzzle15/ChangeLog b/apps/puzzle15/ChangeLog index bd6af53d8..0950b7ae0 100644 --- a/apps/puzzle15/ChangeLog +++ b/apps/puzzle15/ChangeLog @@ -2,3 +2,4 @@ 0.02: Lots of enhancements, menu system not yet functional, but packaging should be now... 0.03: Menu logic now generally functioning, splash screen added. The first really playable version! 0.04: Settings dialog, about screen +0.05: Central game end function diff --git a/apps/puzzle15/puzzle15.app.js b/apps/puzzle15/puzzle15.app.js index e66f9b9bb..eec21933c 100644 --- a/apps/puzzle15/puzzle15.app.js +++ b/apps/puzzle15/puzzle15.app.js @@ -391,23 +391,23 @@ class Board { //this.setAlmostSolved(); // to test the game end } - /* - // Set the board into the "solved" position. Useful for showcasing + /* Set the board into the "solved" position. Useful for showcasing and development setSolved() { this.stones = []; for (i = 0; i < stonesPerBoard; i++) this.stones[i] = new Stone((i + 1) % stonesPerBoard, i); this.moveCount = 0; } + /* */ - // Initialize an almost solved playing field. Useful for tests and development + /* Initialize an almost solved playing field. Useful for tests and development setAlmostSolved() { this.setSolved(); b = this.stones[this.stones.length - 1]; this.stones[this.stones.length - 1] = this.stones[this.stones.length - 2]; this.stones[this.stones.length - 2] = b; } - */ + /* */ // Initialize a shuffled field. The fields are always solvable. setShuffled() { @@ -671,7 +671,7 @@ function gameEnd(moveCount) { buttons: { "Again": newGame, "Menu": () => showMenu(false), - "Exit": load + "Exit": exitGame } }).then(v => { E.showPrompt(); @@ -702,7 +702,7 @@ function showMenu(withContinue) { mainmenu["Start 4x4"] = () => initGame(4); mainmenu["Start 5x5"] = () => initGame(5); mainmenu.About = () => showAbout(withContinue); - mainmenu.Exit = () => load(); + mainmenu.Exit = exitGame; dragger.setEnabled(false); g.clear(true); E.showMenu(mainmenu); @@ -722,6 +722,12 @@ function handledrag(e) { worker.addTask(e => board.drawResult(e)); } +// exit the game, clear screen first to prevent ghost images +function exitGame() { + g.clear(true); + setTimeout(load, 300); +} + // *** Main program @@ -762,4 +768,4 @@ showSplash(() => { showMenu(false); }); -// end of file +// end of file \ No newline at end of file From 801237b2cfad1caf17a0d4bb496527bd4a217e8a Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 15:35:01 +0100 Subject: [PATCH 190/489] Let's only register HRM and battery events when respective circle is visible --- apps/circlesclock/app.js | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 2d6c132bb..e10d55f17 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -280,31 +280,32 @@ Bangle.on('lock', function(isLocked) { drawHeartRate(); } } + if (isCircleEnabled("steps")) drawSteps(); + if (isCircleEnabled("stepsDistance")) drawStepsDistance(); } else { if (isCircleEnabled("hr")) { Bangle.setHRMPower(0, "watch"); } } - if (isCircleEnabled("hr")) drawHeartRate(); - if (isCircleEnabled("steps")) drawSteps(); - if (isCircleEnabled("stepsDistance")) drawStepsDistance(); }); -Bangle.on('HRM', function(hrm) { - if (isCircleEnabled("hr")) { - //if(hrm.confidence > 90){ - hrtValue = hrm.bpm; - if (Bangle.isLCDOn()) - drawHeartRate(); - //} else { - // hrtValue = undefined; - //} - } -}); +if (isCircleEnabled("hr")) { + Bangle.on('HRM', function(hrm) { + //if(hrm.confidence > 90){ + hrtValue = hrm.bpm; + if (Bangle.isLCDOn()) + drawHeartRate(); + //} else { + // hrtValue = undefined; + //} + }); +} -Bangle.on('charging', function(charging) { - if (isCircleEnabled("battery")) drawBattery(); -}); +if (isCircleEnabled("battery")) { + Bangle.on('charging', function(charging) { + drawBattery(); + }); +} g.clear(); From 0b34ffefd58ee58f5d0437b5c4ff568a95eb778d Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Wed, 22 Dec 2021 21:18:55 +0100 Subject: [PATCH 191/489] Anton clock: Update with optional seconds and ISO-8601 date --- apps.json | 8 +- apps/antonclk/ChangeLog | 1 + apps/antonclk/app.js | 176 +++++++++++++++++++++++++++-------- apps/antonclk/app.png | Bin 759 -> 1989 bytes apps/antonclk/screenshot.png | Bin 696 -> 1617 bytes apps/antonclk/settings.js | 87 +++++++++++++++++ 6 files changed, 232 insertions(+), 40 deletions(-) create mode 100644 apps/antonclk/settings.js diff --git a/apps.json b/apps.json index 5cc311413..b0d74926b 100644 --- a/apps.json +++ b/apps.json @@ -4238,8 +4238,8 @@ { "id": "antonclk", "name": "Anton Clock", - "version": "0.03", - "description": "A simple clock using the bold Anton font.", + "version": "0.04", + "description": "A clock using the bold Anton font, optionally showing seconds and date in ISO-8601 format.", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}], "type": "clock", @@ -4248,8 +4248,10 @@ "allow_emulator": true, "storage": [ {"name":"antonclk.app.js","url":"app.js"}, + {"name":"antonclk.settings.js","url":"settings.js"}, {"name":"antonclk.img","url":"app-icon.js","evaluate":true} - ] + ], + "data": [{"name":"antonclk.json"}] }, { "id": "waveclk", diff --git a/apps/antonclk/ChangeLog b/apps/antonclk/ChangeLog index f88276a90..668047d7a 100644 --- a/apps/antonclk/ChangeLog +++ b/apps/antonclk/ChangeLog @@ -1,3 +1,4 @@ 0.01: New App! 0.02: Load widgets after setUI so widclk knows when to hide 0.03: Clock now shows day of week under date. +0.04: Clock can optionally show seconds, date optionally in ISO-8601 format, weekdays and uppercase configurable, too. diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index 7912dfc0f..3b9c14c46 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -1,10 +1,51 @@ +// Clock with large digits using the "Anton" bold font + +var SETTINGSFILE="antonclk.json"; + Graphics.prototype.setFontAnton = function(scale) { // Actual height 69 (68 - 0) g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAA/gAAAAAAAAAAP/gAAAAAAAAAH//gAAAAAAAAB///gAAAAAAAAf///gAAAAAAAP////gAAAAAAD/////gAAAAAA//////gAAAAAP//////gAAAAH///////gAAAB////////gAAAf////////gAAP/////////gAD//////////AA//////////gAA/////////4AAA////////+AAAA////////gAAAA///////wAAAAA//////8AAAAAA//////AAAAAAA/////gAAAAAAA////4AAAAAAAA///+AAAAAAAAA///gAAAAAAAAA//wAAAAAAAAAA/8AAAAAAAAAAA/AAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////AAAAAB///////8AAAAH////////AAAAf////////wAAA/////////4AAB/////////8AAD/////////+AAH//////////AAP//////////gAP//////////gAP//////////gAf//////////wAf//////////wAf//////////wAf//////////wA//8AAAAAB//4A//wAAAAAAf/4A//gAAAAAAP/4A//gAAAAAAP/4A//gAAAAAAP/4A//wAAAAAAf/4A///////////4Af//////////wAf//////////wAf//////////wAf//////////wAP//////////gAP//////////gAH//////////AAH//////////AAD/////////+AAB/////////8AAA/////////4AAAP////////gAAAD///////+AAAAAf//////4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gAAAAAAAAAAP/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/AAAAAAAAAAA//AAAAAAAAAAA/+AAAAAAAAAAB/8AAAAAAAAAAD//////////gAH//////////gAP//////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/4AAAAB/gAAD//4AAAAf/gAAP//4AAAB//gAA///4AAAH//gAB///4AAAf//gAD///4AAA///gAH///4AAD///gAP///4AAH///gAP///4AAP///gAf///4AAf///gAf///4AB////gAf///4AD////gA////4AH////gA////4Af////gA////4A/////gA//wAAB/////gA//gAAH/////gA//gAAP/////gA//gAA///8//gA//gAD///w//gA//wA////g//gA////////A//gA///////8A//gA///////4A//gAf//////wA//gAf//////gA//gAf/////+AA//gAP/////8AA//gAP/////4AA//gAH/////gAA//gAD/////AAA//gAB////8AAA//gAA////wAAA//gAAP///AAAA//gAAD//8AAAA//gAAAP+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/+AAAAAD/wAAB//8AAAAP/wAAB///AAAA//wAAB///wAAB//wAAB///4AAD//wAAB///8AAH//wAAB///+AAP//wAAB///+AAP//wAAB////AAf//wAAB////AAf//wAAB////gAf//wAAB////gA///wAAB////gA///wAAB////gA///w//AAf//wA//4A//AAA//wA//gA//AAAf/wA//gB//gAAf/wA//gB//gAAf/wA//gD//wAA//wA//wH//8AB//wA///////////gA///////////gA///////////gA///////////gAf//////////AAf//////////AAP//////////AAP/////////+AAH/////////8AAH///+/////4AAD///+f////wAAA///8P////gAAAf//4H///+AAAAH//gB///wAAAAAP4AAH/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/wAAAAAAAAAA//wAAAAAAAAAP//wAAAAAAAAB///wAAAAAAAAf///wAAAAAAAH////wAAAAAAA/////wAAAAAAP/////wAAAAAB//////wAAAAAf//////wAAAAH///////wAAAA////////wAAAP////////wAAA///////H/wAAA//////wH/wAAA/////8AH/wAAA/////AAH/wAAA////gAAH/wAAA///4AAAH/wAAA//+AAAAH/wAAA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gAAAAAAAAH/4AAAAAAAAAAH/wAAAAAAAAAAH/wAAAAAAAAAAH/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//8AAA/////+B///AAA/////+B///wAA/////+B///4AA/////+B///8AA/////+B///8AA/////+B///+AA/////+B////AA/////+B////AA/////+B////AA/////+B////gA/////+B////gA/////+B////gA/////+A////gA//gP/gAAB//wA//gf/AAAA//wA//gf/AAAAf/wA//g//AAAAf/wA//g//AAAA//wA//g//gAAA//wA//g//+AAP//wA//g////////gA//g////////gA//g////////gA//g////////gA//g////////AA//gf///////AA//gf//////+AA//gP//////+AA//gH//////8AA//gD//////4AA//gB//////wAA//gA//////AAAAAAAH////8AAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////gAAAAB///////+AAAAH////////gAAAf////////4AAB/////////8AAD/////////+AAH//////////AAH//////////gAP//////////gAP//////////gAf//////////wAf//////////wAf//////////wAf//////////wAf//////////4A//wAD/4AAf/4A//gAH/wAAP/4A//gAH/wAAP/4A//gAP/wAAP/4A//gAP/4AAf/4A//wAP/+AD//4A///wP//////4Af//4P//////wAf//4P//////wAf//4P//////wAf//4P//////wAP//4P//////gAP//4H//////gAH//4H//////AAH//4D/////+AAD//4D/////8AAB//4B/////4AAA//4A/////wAAAP/4AP////AAAAB/4AD///4AAAAAAAAAH/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//AAAAAAAAAAA//gAAAAAAAAAA//gAAAAAAAAAA//gAAAAAAADgA//gAAAAAAP/gA//gAAAAAH//gA//gAAAAB///gA//gAAAAP///gA//gAAAD////gA//gAAAf////gA//gAAB/////gA//gAAP/////gA//gAB//////gA//gAH//////gA//gA///////gA//gD///////gA//gf///////gA//h////////gA//n////////gA//////////gAA/////////AAAA////////wAAAA///////4AAAAA///////AAAAAA//////4AAAAAA//////AAAAAAA/////4AAAAAAA/////AAAAAAAA////8AAAAAAAA////gAAAAAAAA///+AAAAAAAAA///4AAAAAAAAA///AAAAAAAAAA//4AAAAAAAAAA/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//gB///wAAAAP//4H///+AAAA///8P////gAAB///+f////4AAD///+/////8AAH/////////+AAH//////////AAP//////////gAP//////////gAf//////////gAf//////////wAf//////////wAf//////////wA///////////wA//4D//wAB//4A//wB//gAA//4A//gA//gAAf/4A//gA//AAAf/4A//gA//gAAf/4A//wB//gAA//4A///P//8AH//4Af//////////wAf//////////wAf//////////wAf//////////wAf//////////gAP//////////gAP//////////AAH//////////AAD/////////+AAD///+/////8AAB///8f////wAAAf//4P////AAAAH//wD///8AAAAA/+AAf//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH//gAAAAAAAAB///+AA/+AAAAP////gA//wAAAf////wA//4AAB/////4A//8AAD/////8A//+AAD/////+A///AAH/////+A///AAP//////A///gAP//////A///gAf//////A///wAf//////A///wAf//////A///wAf//////A///wA///////AB//4A//4AD//AAP/4A//gAB//AAP/4A//gAA//AAP/4A//gAA/+AAP/4A//gAB/8AAP/4A//wAB/8AAf/4Af//////////wAf//////////wAf//////////wAf//////////wAf//////////wAP//////////gAP//////////gAH//////////AAH/////////+AAD/////////8AAB/////////4AAAf////////wAAAP////////AAAAB///////4AAAAAD/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/AAB/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("EiAnGicnJycnJycnEw=="), 78+(scale<<8)+(1<<16)); +}; + +// variables defined from settings +var secondsOnUnlock; +var secondsAlways; +var dateAsISO; +var longDate; +var weekDay; +var upperCase; + +// dynamic variables +var drawTimeout; +var queueMillis=1000; +var withSeconds=true; + +var isBangle1=(g.getWidth()==240); + +/* For development purposes +require('Storage').writeJSON(SETTINGSFILE, { + secondsOnUnlock: false, + secondsAlways: false, + dateAsISO: false, + longDate: true, + weekDay: true, + upperCase: true +}); +*/ + +function def(value,def) { + return (value!==undefined?value:def); } -// timeout used to update every minute -var drawTimeout; +function loadSettings() { + var settings = require('Storage').readJSON(SETTINGSFILE, true) || {}; + secondsOnUnlock = def(settings.secondsOnUnlock,true); + secondsAlways = def(settings.secondsAlways,false); + dateAsISO = def(settings.dateAsISO,true); + longDate = def(settings.longDate,true); + weekDay = def(settings.weekDay,true); + upperCase = def(settings.upperCase,false); +} // schedule a draw for the next minute function queueDraw() { @@ -12,50 +53,111 @@ function queueDraw() { drawTimeout = setTimeout(function() { drawTimeout = undefined; draw(); - }, 60000 - (Date.now() % 60000)); + }, queueMillis - (Date.now() % queueMillis)); } - -function draw() { - var x = g.getWidth()/2; - var y = g.getHeight()/2; - g.reset(); - var date = new Date(); - var timeStr = require("locale").time(date,1); - var dateStr = require("locale").date(date).toUpperCase(); - var dowStr = require("locale").dow(date).toUpperCase(); - // draw time - g.setFontAlign(0,0).setFont("Anton"); - g.clearRect(0,y-40,g.getWidth(),y+35); // clear the background - g.drawString(timeStr,x,y); - // draw date - y += 40; - g.setFontAlign(0,0).setFont("6x8",2); - g.clearRect(0,y-8,g.getWidth(),y+8); // clear the background - g.drawString(dateStr,x,y); - //draw day of week - y += 16; - g.clearRect(0,y-8,g.getWidth(),y+8); // clear the background - g.drawString(dowStr,x,y); - // queue draw in one minute - queueDraw(); -} - -// Clear the screen once, at startup -g.clear(); -// draw immediately at first, queue update -draw(); -// Stop updates when LCD is off, restart when on -Bangle.on('lcdPower',on=>{ - if (on) { +function updateState() { + if (Bangle.isLCDOn()) { + if ((secondsOnUnlock && !Bangle.isLocked()) || secondsAlways) { + withSeconds=true; + queueMillis=1000; + } else { + withSeconds=false; + queueMillis=60000; + } draw(); // draw immediately, queue redraw } else { // stop draw timer if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; } -}); +} + +function isoStr(date) { + return date.getFullYear()+"-"+("0" + (date.getMonth()+1)).substr(-2)+"-"+("0" + date.getDate()).substr(-2); +} + +function doColor() { + return !isBangle1 && !Bangle.isLocked(); +} + +function draw() { + var x = g.getWidth()/2; + var y = g.getHeight()/2; + if (secondsOnUnlock || secondsAlways) + y-= 25; + g.reset(); + g.clearRect(0,24,g.getWidth(),g.getHeight()); // clear whole background + var date = new Date(); + var timeStr = require("locale").time(date,1); + // draw time + g.setFontAlign(0,0).setFont("Anton"); + g.drawString(timeStr,x,y); + if (withSeconds) { + y+=77; + var secStr = ":"+("0" + date.getSeconds()).substr(-2); + g.setFontAlign(1,0).setFont("Anton"); + if (doColor()) + g.setColor(0,0,1); + g.drawString(secStr,g.getWidth()-(isBangle1?32:2),y); + y-=77; + y+=60; + x=g.getWidth()/4+(isBangle1?12:-4); + var dateStr2=(dateAsISO?isoStr(date):require("locale").date(date,1)); + var year; + var md; + var yearfirst; + if (dateStr2.match(/\d\d\d\d$/)) { + year=dateStr2.slice(-4); + md=dateStr2.slice(0,-4); + if (!md.endsWith(".")) + md=md.slice(0,-1); + yearfirst=false; + } + else { + if (!dateStr2.match(/^\d\d\d\d/)) + dateStr2=isoStr(date); + year=dateStr2.slice(0,4); + md=dateStr2.slice(5); + yearfirst=true; + } + g.setFontAlign(0,0).setFont("Vector",24); + if (doColor()) + g.setColor(1,0,0); + g.drawString(md,x,(yearfirst?y+28:y)); + g.drawString(year,x,(yearfirst?y:y+28)); + } + else { + y+=52; + var dateStr = (dateAsISO?isoStr(date):require("locale").date(date,(longDate?0:1))); + if (upperCase) + dateStr=dateStr.toUpperCase(); + g.setFontAlign(0,0).setFont("Vector",24); + g.drawString(dateStr,x,y); + if (weekDay) { + var dowStr = require("locale").dow(date); + if (upperCase) + dowStr=dowStr.toUpperCase(); + g.drawString(dowStr,x,y+28); + } + } + + // queue next draw + queueDraw(); +} + +// Init the settings of the app +loadSettings(); +// Clear the screen once, at startup +g.clear(); +// Set dynamic state and perform initial drawing +updateState(); +// Register hooks for LCD on/off event and screen lock on/off event +Bangle.on('lcdPower',on=>{ updateState(); }); +Bangle.on('lock',on=>{ updateState(); }); // Show launcher when middle button pressed Bangle.setUI("clock"); // Load widgets Bangle.loadWidgets(); Bangle.drawWidgets(); + +// end of file diff --git a/apps/antonclk/app.png b/apps/antonclk/app.png index d96f1775886e280f46652131b7e8c747fd28bf39..a38093c5f3b6f88dbc9b75017422dbe237d4407f 100644 GIT binary patch delta 1986 zcmV;z2R-=r1;r1L8Gix*007uvZqNV#2aHKXK~z}7?O0t*Q&$}S(aJ|1h>ls;g4h+@ zB+AGl)8UNHxGbA|xTyGG;sOsoEFnM;B+-{a7Q@E_V_6nMW&&<;@}SXB3>rlzVu;X< zRWXwk`@zScE!aY#?d`|e!>RXPZf_BAEI#a?lbioJ=XcKe-G6(||Kr>ULI_?bk>E9x z{|Wt1=v8G^xDKDsH!(3`G#X=LV-*U8TrOXDqLGmilgUK&#Kc6EN+kdc4-cEoX0}QQ z*}i?dOePafM8w2kFdRO7m=7x{DH$0V5e0j_-m_=V3Z|{9s&YD=eAwyJrv(^`#S%K3 z2qBxzmYSLx`hN`y3JT`t=0fr3&YhD;M7F-UxtYZ<46||L#$^(^di83!ed+D(C4@{& zOjs-yi^VcGH|KCTl9H16n23l7R(HGIbWWX4$8TSNkjR^LcXzY8Ua#-%?PaT@qoV@@ z0~H&dOV(ykrCQkT3X65OnG@Zi=UX7pnuAvM~@a65=02q*VnUpQc}{o zb?ew_S63H*UcpOeWMo7}M)E(H!{MOHjT<+pQd3j2Oe+(oFOl#G1p(}#J#>U2O z-@eU%9{^UX^}>Y<0168WUuvx{Ar!jtTeog?yWPRTtL6=FZEYMVBWjNgS_V&)sPS%G}B_$%Z5oY6qtTenW{1Nu^g`m} z<4>G8QB+jKf{jMwlP6E8URztc{8*NimDSVJLv{8QshCWryu3WB-@kuHJ4%z_z)>FVmDx>~KaTCMyOIXO8QA0HnT74;HACXwg7ckH-_vDjOOaLMP{&$oTm9qN2UoY*s3j zp$k-3SBvIDeSLkQ;GCQstJS(Np~a>jgpg;?o|ToA30{|B7!pRFK7CqOSGQ-+9vU&4 zo0~=15JIkBzg|&MQBhHG^5n^>si{yvL^#7CggBi}n!+lT%5dRAkoEfg{-~&^mwyJV zg`(%{c5_{|Li5heVRRH03*>SnCSvt!A;4yX)rzSpC=^gC5figulK+bG%P%A?jR3)- zRuhee>z$q^RaIOsK(=io_wFrts9#0e+U70BmOFQXfFFJk2WYhdLRKr$>4@J?2q6v! z`Qs1b^%6qJ>@4Z+CDg1@L7z6pDG^{(i2SkbpPdKwMlnD;pTVci*9=hFgSs zgt0MHSEIZfVy=i!h!F4{kf=Wi^-z~Cfu=;}wcszLg7?YD27=M7%NyqKl1-Cm`wryLQYX}5_n<$Y$t;Rd=@Cijlp`igT z7pA8X8;jgrI2<^029c4dtqtxYA+Xy~SqZxxem@;2l_EMiSR_mQl~P#=wHoig549R) zWtf>+0YAjI`L;Gf2&t&xTJ(C-(h}Cne*HDfRr)^@l?oqxz*T?xiGSU)*;zC{H zE;Kda=byp9j!jSF`|t7mIj3K~jM-Uw_S)K@(Lke_XY-4Z^XGBv7Lt>LRjn4!pHo7A z{t3Gs9uLjDk)4gKEL^_K4gLLhIGynM0N~CYeEB6*D%`pSU~mw5dC1L0ZZ0gAr4fpb z#+z^A-FJgkyB$6sHGlhEyD&AyUdQ2bp|us6nb7Oe-Hnew#wVYEy>UvVFc>g11H1h{ ziS|=dXl%rhBS=q&%Y_36AV}0d{S^-&q4nIc68v%6&MW2&W1#Sn>XQf;(x2J0BqTUEnC3*|HA1l zEy&D-(a5<(Lh$z69KdWwOblM!|B#xBHEXEZd%eW%CT=(JdO4k+urdq>AVk>96Q`5N z<>FSIpHBh-Vlss_`<9lKNk2L}#ngwjPIXiTSuzz@0DyR1QVY3BO*tgz-R4N2842(v2JWwjJb}a{Z?UMX|0QIbl USs20!PXGV_07*qoM6N<$g0gzc;Q#;t delta 746 zcmV#Upe&?7suvS{7$`q%$XUdCYatL*UM&qYkz00_3gdZkp%IXiY3DTK~M*l*UhrGbOTH@s=dXV zf09G{s><3KAL0N6xR{=cL_nHCF0Qe5xz8(%f`4q@m5r`n_Xa#UzVHyArFz-Gc zKm+!|0~`-toKmZ@`fYBHXFhRJxmIAUji{nSriljb1AkP<@icA%+OjwZJs^29h?!Ef z-TemQ2C)dzr(Mf2wV1+4Ie;xTq4hl^_`-nK0TfEH`ypDS7J#jPXdpM>j2NN40NJq# z{&FFNH{#+t0W5K}=m5aZI0(+a83M-^4*{K7!lef}MT5(z_;g8nFi@MU!y9& z0D~Ga2Y=`lS%av@1!#4Vgg00wzKaaIJ2L@bNR#tpBy|nIlrv8rGG@(^FsdRJ-QP{XzCF~qci@anb7w@o;375x%BD_RYP}fDMfEo&3+L6^SSGaoh~4+ z$TC{G#j66=9oYBrc}77;VUgTDWelk_cCxHK`(vE&O}8IO0(v{XR&*Uo8wB1qJ*#jG z=4;wIwv|`|g31@bP&0h$WpisvZdEEkr`;hEFPcka7#vXBt?hE5xty{J^%m!07*qoM6N<$f`mLmfdBvi diff --git a/apps/antonclk/screenshot.png b/apps/antonclk/screenshot.png index c66f8bdd85c6c2acef19f20ff86dab7b1d9c6a3f..e949b8a24a4eac5cbd8f8a01ffdd57b3660b939c 100644 GIT binary patch delta 1612 zcmV-S2DACN1AlTS_;6Lfh=O!<|dqR0_rLj7-Gw6Z=mpp~2Trq^-sN$JXdw$RVuL zh2YN@K!k`6Pvr(ctjI(h8vf-F??mA#V@N4cYlvqI5okD%_;DP$JZ&Vq6!#OKe-2k= zTnY^!SWV;*Zhz&*?VkZ+T^e4FIMl4veaLv{kHiaY8ZJ4eOESUYRxBF6&rgK#5Xh#u zh^d_lGqUH{I#wmxlgh#wCnl!sX>jup40b>oT>LaiC5grV6yh5Y9s#T=rCdP_t1Cx7#uck6xw7CA)cmrN5Z z87(9agn^YANE_|bKkF>#Mh8M)8{$o5Cc8FRku2BfXl|D&q@GEB?SUN zAVavl{C^WbAb>!j%1%GIf&mFAH!(qn65YGTfB^eSxzyv^$ znVJGY8u8OfjN&<1-1>p|YKvQ0+=BCwv6TPI8h=j}(Y+yF1hHNYWjJb$33G_!II4DC zYVYQgVzm5w4K066RQR$ zvwt8Zm9^v%t&H@Hld&C=2LdZkV~V_>mBE*gfqO6qLeCZ&EsxUX*dAgmD-(t+LdIBD z7TmHy4l#+9`?qdRmZG|C)Cpzfh8v!>R7ug!2o7TC+uL5DUQL!?a#=z*HhC~Vr)qVlOVN{y2 zklNJprC*XtHyUc&5!~YRr73`LqoJxb@eOZJ4FZHG4SH=h_X`lCj+~MJ0@MHk_kf20 zxI*nMw_H*_2e}ycP|(HMkbBF0z5e<%9(or`Sg5dpWvA=*b`#zXp8drkAN2RV*MCku z^?-Q(Z1XqWwZ5h7#X}uLbRL-FFuL~(NzMJ{(r4=OEpLZP?_ykel#uZ>096FuUR>L< z9||t3+g@&Qkg^lU5FH4;+Rvk^M14T$`Lb1ilwhc`^UHwg1x(z7M3`-OzIJGsn+dg$ z0S$xGhm%5v`^6g?a>x^Jt{i4z;qd9(eZbJ6z7d?iIaz8J!^HVTx zo9(q;$U}H#Q@rsIJ!F{GjVOA^kfNdF-(`s*Uc>^z>^110uXiK=kikpwc!)Y0WD%jD z2nvLwW4P@LN&@8&;lso_aeu7&T&yhCt);PFdrdySbO84-x`!%T%P5Hpwfi}H`fc7s zO1ffKWuQBZ&3>p&s?%ZLn2L9trF-BI>6BmP3pBu=Lt)VGrBgx%c0I{@_ z`211;5uG+;5CLLcC&7UsL7Dj3re&u9;mm}_0Zcuu0fZ+LF6V67o<%|j6U86bJI}4B z1!gJ* literal 696 zcmeAS@N?(olHy`uVBq!ia0vp^8$g(e8Ax8b$#WJ+v7|ftIx;Y9?C1WI$O_~uBzpw; zGB8xBF)%c=FfjZA3N^f7U???UV0e|lz+g3lfkC`r&aOZkpaf5VPl)UP|Nj{nfCxnV zoVS%9$Y4zJc6VXuV3qX%a@b2eeO=j~a*A_n%Kez1upTJA($mE;B;xSfYk_%(6?oVZ znx=@`mzU45aNRCkV(xU;^}@Uf{u^iKUb%22k=ZHgn#betkjQJ(wHVdc3iO{Um?DvM z`p1?79g#H?tfriI+96!Z*U!BsRg8cA`*^+i+8-jC+ouPvJND@90YimZJatyS5s?c& zt+tgDzj5GhL5XDLnY<58YfnAMc=^fV))bq*ZM!#=oOaa8IaTDs-PyLkAzNAs4m9XOIF3zyu2a|McptHjh`Yyi=a@ZK4iEEpI(UHx3vIVCg!011y7eE back(), + "Seconds...": () => E.showMenu(secmenu), + "ISO8601 date": { + value: (settings.dateAsISO !== undefined ? settings.dateAsISO : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.dateAsISO = v; + writeSettings(); + } + }, + "Long date": { + value: (settings.longDate !== undefined ? settings.longDate : true), + format: v => v ? "On" : "Off", + onchange: v => { + settings.longDate = v; + writeSettings(); + } + }, + "Show Weekday": { + value: (settings.weekDay !== undefined ? settings.weekDay : true), + format: v => v ? "On" : "Off", + onchange: v => { + settings.weekDay = v; + writeSettings(); + } + }, + "Uppercase": { + value: (settings.upperCase !== undefined ? settings.upperCase : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.upperCase = v; + writeSettings(); + } + }, + }; + + // Submenu + var secmenu = { + "": { + "title": "Show seconds..." + }, + "< Back": () => E.showMenu(mainmenu), + "If unlocked": { + value: (settings.secondsOnUnlock !== undefined ? settings.secondsOnUnlock : true), + format: v => v ? "On" : "Off", + onchange: v => { + settings.secondsOnUnlock = v; + if (v) + settings.secondsAlways = false; + writeSettings(); + } + }, + "Always": { + value: (settings.secondsAlways !== undefined ? settings.secondsAlways : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.secondsAlways = v; + if (v) + settings.secondsOnUnlock = false; + writeSettings(); + } + } + }; + + // Actually display the menu + E.showMenu(mainmenu); + +}); + +// end of file From a245fa748d3bb4e8b06c0c298af9122262342914 Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Sat, 25 Dec 2021 21:55:23 +0100 Subject: [PATCH 192/489] Anton clock: Coloured seconds, date format config, small enhancements Result of the feedback on the first version. --- apps/antonclk/app.js | 157 +++++++++++++++++++++----------------- apps/antonclk/settings.js | 38 +++++---- 2 files changed, 111 insertions(+), 84 deletions(-) diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index 3b9c14c46..31ba696b7 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -1,6 +1,6 @@ // Clock with large digits using the "Anton" bold font -var SETTINGSFILE="antonclk.json"; +var SETTINGSFILE = "antonclk.json"; Graphics.prototype.setFontAnton = function(scale) { // Actual height 69 (68 - 0) @@ -10,44 +10,56 @@ Graphics.prototype.setFontAnton = function(scale) { // variables defined from settings var secondsOnUnlock; var secondsAlways; +var secondsColoured; var dateAsISO; +var dateOnSecs; var longDate; var weekDay; var upperCase; // dynamic variables var drawTimeout; -var queueMillis=1000; -var withSeconds=true; +var queueMillis = 1000; +var secondsScreen = true; -var isBangle1=(g.getWidth()==240); +var isBangle1 = (g.getWidth() == 240); /* For development purposes require('Storage').writeJSON(SETTINGSFILE, { secondsOnUnlock: false, secondsAlways: false, + secondsColoured: true, dateAsISO: false, + dateOnSecs: true, longDate: true, weekDay: true, - upperCase: true + upperCase: false, }); -*/ +/* */ -function def(value,def) { - return (value!==undefined?value:def); +/* OR (also for development purposes) +require('Storage').erase(SETTINGSFILE); +/* */ + +// Helper method for loading the settings +function def(value, def) { + return (value !== undefined ? value : def); } +// Load settings function loadSettings() { var settings = require('Storage').readJSON(SETTINGSFILE, true) || {}; - secondsOnUnlock = def(settings.secondsOnUnlock,true); - secondsAlways = def(settings.secondsAlways,false); - dateAsISO = def(settings.dateAsISO,true); - longDate = def(settings.longDate,true); - weekDay = def(settings.weekDay,true); - upperCase = def(settings.upperCase,false); + secondsOnUnlock = def(settings.secondsOnUnlock, false); + secondsAlways = def(settings.secondsAlways, false); + secondsColoured = def(settings.secondsColoured, false); + dateAsISO = def(settings.dateAsISO, false); + dateOnSecs = def(settings.dateOnSecs, true); + longDate = def(settings.longDate, true); + weekDay = def(settings.weekDay, true); + upperCase = def(settings.upperCase, true); } -// schedule a draw for the next minute +// schedule a draw for the next second or minute function queueDraw() { if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = setTimeout(function() { @@ -59,11 +71,11 @@ function queueDraw() { function updateState() { if (Bangle.isLCDOn()) { if ((secondsOnUnlock && !Bangle.isLocked()) || secondsAlways) { - withSeconds=true; - queueMillis=1000; + secondsScreen = true; + queueMillis = 1000; } else { - withSeconds=false; - queueMillis=60000; + secondsScreen = false; + queueMillis = 60000; } draw(); // draw immediately, queue redraw } else { // stop draw timer @@ -73,71 +85,70 @@ function updateState() { } function isoStr(date) { - return date.getFullYear()+"-"+("0" + (date.getMonth()+1)).substr(-2)+"-"+("0" + date.getDate()).substr(-2); + return date.getFullYear() + "-" + ("0" + (date.getMonth() + 1)).substr(-2) + "-" + ("0" + date.getDate()).substr(-2); } function doColor() { - return !isBangle1 && !Bangle.isLocked(); + return !isBangle1 && !Bangle.isLocked() && secondsColoured; } function draw() { - var x = g.getWidth()/2; - var y = g.getHeight()/2; - if (secondsOnUnlock || secondsAlways) - y-= 25; + var x = g.getWidth() / 2; + var y = g.getHeight() / 2 - (secondsOnUnlock || secondsAlways ? 24 : 12); g.reset(); - g.clearRect(0,24,g.getWidth(),g.getHeight()); // clear whole background + g.clearRect(0, 24, g.getWidth(), g.getHeight()); // clear whole background var date = new Date(); - var timeStr = require("locale").time(date,1); + var timeStr = require("locale").time(date, 1); // draw time - g.setFontAlign(0,0).setFont("Anton"); - g.drawString(timeStr,x,y); - if (withSeconds) { - y+=77; - var secStr = ":"+("0" + date.getSeconds()).substr(-2); - g.setFontAlign(1,0).setFont("Anton"); + g.setFontAlign(0, 0).setFont("Anton"); + g.drawString(timeStr, x, y); + if (secondsScreen) { + y += 76; + var secStr = ":" + ("0" + date.getSeconds()).substr(-2); if (doColor()) - g.setColor(0,0,1); - g.drawString(secStr,g.getWidth()-(isBangle1?32:2),y); - y-=77; - y+=60; - x=g.getWidth()/4+(isBangle1?12:-4); - var dateStr2=(dateAsISO?isoStr(date):require("locale").date(date,1)); - var year; - var md; - var yearfirst; - if (dateStr2.match(/\d\d\d\d$/)) { - year=dateStr2.slice(-4); - md=dateStr2.slice(0,-4); - if (!md.endsWith(".")) - md=md.slice(0,-1); - yearfirst=false; + g.setColor(0, 0, 1); + g.setFont("Anton"); + if (dateOnSecs) { + g.setFontAlign(1, 0).drawString(secStr, g.getWidth() - (isBangle1 ? 32 : 2), y); + y -= 16; + x = g.getWidth() / 4 + (isBangle1 ? 12 : -4); + var dateStr2 = (dateAsISO ? isoStr(date) : require("locale").date(date, 1)); + var year; + var md; + var yearfirst; + if (dateStr2.match(/\d\d\d\d$/)) { + year = dateStr2.slice(-4); + md = dateStr2.slice(0, -4); + if (!md.endsWith(".")) + md = md.slice(0, -1); + yearfirst = false; + } else { + if (!dateStr2.match(/^\d\d\d\d/)) + dateStr2 = isoStr(date); + year = dateStr2.slice(0, 4); + md = dateStr2.slice(5); + yearfirst = true; + } + g.setFontAlign(0, 0).setFont("Vector", 24); + if (doColor()) + g.setColor(1, 0, 0); + g.drawString(md, x, (yearfirst ? y + 28 : y)); + g.drawString(year, x, (yearfirst ? y : y + 28)); + } else { + g.setFontAlign(0, 0).drawString(secStr, x, y); } - else { - if (!dateStr2.match(/^\d\d\d\d/)) - dateStr2=isoStr(date); - year=dateStr2.slice(0,4); - md=dateStr2.slice(5); - yearfirst=true; - } - g.setFontAlign(0,0).setFont("Vector",24); - if (doColor()) - g.setColor(1,0,0); - g.drawString(md,x,(yearfirst?y+28:y)); - g.drawString(year,x,(yearfirst?y:y+28)); - } - else { - y+=52; - var dateStr = (dateAsISO?isoStr(date):require("locale").date(date,(longDate?0:1))); + } else { // No seconds screen + y += 50; + var dateStr = (dateAsISO ? isoStr(date) : require("locale").date(date, (longDate ? 0 : 1))); if (upperCase) - dateStr=dateStr.toUpperCase(); - g.setFontAlign(0,0).setFont("Vector",24); - g.drawString(dateStr,x,y); + dateStr = dateStr.toUpperCase(); + g.setFontAlign(0, 0).setFont("Vector", 24); + g.drawString(dateStr, x, y); if (weekDay) { var dowStr = require("locale").dow(date); if (upperCase) - dowStr=dowStr.toUpperCase(); - g.drawString(dowStr,x,y+28); + dowStr = dowStr.toUpperCase(); + g.drawString(dowStr, x, y + 26); } } @@ -152,8 +163,12 @@ g.clear(); // Set dynamic state and perform initial drawing updateState(); // Register hooks for LCD on/off event and screen lock on/off event -Bangle.on('lcdPower',on=>{ updateState(); }); -Bangle.on('lock',on=>{ updateState(); }); +Bangle.on('lcdPower', on => { + updateState(); +}); +Bangle.on('lock', on => { + updateState(); +}); // Show launcher when middle button pressed Bangle.setUI("clock"); // Load widgets diff --git a/apps/antonclk/settings.js b/apps/antonclk/settings.js index 22cae41fb..2bcc1d7ce 100644 --- a/apps/antonclk/settings.js +++ b/apps/antonclk/settings.js @@ -4,7 +4,7 @@ var FILE = "antonclk.json"; // Load settings var settings = Object.assign({ - secondsOnUnlock: true, + secondsOnUnlock: false, }, require('Storage').readJSON(FILE, true) || {}); function writeSettings() { @@ -57,23 +57,35 @@ "title": "Show seconds..." }, "< Back": () => E.showMenu(mainmenu), - "If unlocked": { - value: (settings.secondsOnUnlock !== undefined ? settings.secondsOnUnlock : true), - format: v => v ? "On" : "Off", - onchange: v => { - settings.secondsOnUnlock = v; - if (v) - settings.secondsAlways = false; - writeSettings(); - } - }, "Always": { value: (settings.secondsAlways !== undefined ? settings.secondsAlways : false), format: v => v ? "On" : "Off", onchange: v => { settings.secondsAlways = v; - if (v) - settings.secondsOnUnlock = false; + writeSettings(); + } + }, + "If unlocked": { + value: (settings.secondsOnUnlock !== undefined ? settings.secondsOnUnlock : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.secondsOnUnlock = v; + writeSettings(); + } + }, + "Coloured": { + value: (settings.secondsColoured !== undefined ? settings.secondsColoured : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.secondsColoured = v; + writeSettings(); + } + }, + "With date": { + value: (settings.dateOnSecs !== undefined ? settings.dateOnSecs : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.dateOnSecs = v; writeSettings(); } } From 322a3a0b5aed5a697347b966ebd7d1e8ccb1370b Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Sat, 25 Dec 2021 21:55:30 +0100 Subject: [PATCH 193/489] Anton clock: README added --- apps.json | 1 + apps/antonclk/README.md | 66 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 apps/antonclk/README.md diff --git a/apps.json b/apps.json index b0d74926b..3411befc8 100644 --- a/apps.json +++ b/apps.json @@ -4240,6 +4240,7 @@ "name": "Anton Clock", "version": "0.04", "description": "A clock using the bold Anton font, optionally showing seconds and date in ISO-8601 format.", + "readme":"README.md", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}], "type": "clock", diff --git a/apps/antonclk/README.md b/apps/antonclk/README.md new file mode 100644 index 000000000..40aa9d457 --- /dev/null +++ b/apps/antonclk/README.md @@ -0,0 +1,66 @@ +# Anton Clock - Large font digital watch with seconds and date + +Anton clock uses the "Anton" bold font to show the time in a clear, easily readable manner. On the Bangle.js 2, the time can be read easily even if the screen is locked and unlit. + +## Features + +The basic time representation only shows hours and minutes of the current time. However, Anton clock can show additional information: + +* Seconds can be shown, either always or only if the screen is unlocked. +* To help easy recognition, the seconds can be coloured in blue on the Bangle.js 2. +* Date can be shown in three different formats: + * ISO-8601: 2021-12-19 + * short local format: 19/12/2021, 19.12.2021 + * long local format (not together with seconds): DEC 19 2021 +* Weekday can be shown (not together with seconds) + +## Usage + +Install Anton clock through the Bangle.js app loader. +Configure it through the default Bangle.js configuration mechanism +(Settings app, "Apps" menu, "Anton clock" submenu). +If you like it, make it your default watch face +(Settings app, "System" menu, "Clock" submenu, select "Anton clock"). + +## Configuration + +Anton clock is configured by the standard settings mechanism of Bangle.js's operating system: +Open the "Settings" app, then the "Apps" submenu and below it the "Anton clock" menu. +You configure Anton clock through several "on/off" switches in two menus. + +### The main menu + +The main menu contains several settings covering Anton clock in general. + +* **Seconds...** - Opens the submenu for configuring the presentation of the current time's seconds. +* **ISO8601 date** - Show the date in ISO-8601 format, irrespective of the current locale. +* **Long date** - Show the date in long format (usually with month in letters instead of number). +Exact format depends on the current locale. _Only evaluated if ISO8601 date is not set._ +* **Show Weekday** - Weekday is shown in the time presentation without seconds. +Weekday name depends on the current locale. +If seconds are shown, the weekday is never shown as there is not enough space on the watch face. +* **Uppercase** - Weekday name and month name in the long format are converted to upper case letters. +This can improve readability. + +### The "Seconds" submenu + +The "Seconds" submenu configures how (and if) seconds are shown on the "Anton" watch face. + +* **Always** - Seconds are _always_ shown, irrespective of the display's unlock state. +If this is enabled, weekdays will never been shown. +_Enabling this option increases power consumption as the watch face will update once per second instead of once per minute._ +* **If unlocked** - Seconds are shown if the display is unlocked. +On a locked display, only hour, minutes, date and weekday are shown. +"Always" overrides this option. +_This option is highly recommended on the Bangle.js 2!_ +* **Coloured** - If enabled, seconds are shown in blue instead of black. +This make the visual orientation much easier on the watch face. +* **With date** - If enabled, the date is shown together with the seconds. +Depending on the "ISO8601 date" settings, ISO8601 or short local format is used. +The date is coloured in red if the "Coloured" option is chosen. + +If neither "Always" nor "If unlocked" is selected, Anton clock does _never_ show seconds. + +## Compatibility + +Anton clock makes use of core Bangle.js 2 features (coloured display, display lock state). It also runs on the Bangle.js 1 but these features are not available there due to the hardware features. From 7829af0ef29837e829d4c13ef9c63f89cfdbb82e Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Sun, 26 Dec 2021 19:42:04 +0100 Subject: [PATCH 194/489] Anton clock: Switch between vector and 6x8 font for date and day of week --- apps/antonclk/README.md | 3 ++ apps/antonclk/app.js | 60 +++++++++++++++++++++++---------------- apps/antonclk/settings.js | 8 ++++++ 3 files changed, 46 insertions(+), 25 deletions(-) diff --git a/apps/antonclk/README.md b/apps/antonclk/README.md index 40aa9d457..cb37d566b 100644 --- a/apps/antonclk/README.md +++ b/apps/antonclk/README.md @@ -41,6 +41,9 @@ Weekday name depends on the current locale. If seconds are shown, the weekday is never shown as there is not enough space on the watch face. * **Uppercase** - Weekday name and month name in the long format are converted to upper case letters. This can improve readability. +* **Vector font** - Use the built-in vector font for dates and weekday. +This can improve readability. +Otherwise, a scaled version of the built-in 6x8 pixels font is used. ### The "Seconds" submenu diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index 31ba696b7..e772d679d 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -16,6 +16,7 @@ var dateOnSecs; var longDate; var weekDay; var upperCase; +var vectorFont; // dynamic variables var drawTimeout; @@ -34,6 +35,7 @@ require('Storage').writeJSON(SETTINGSFILE, { longDate: true, weekDay: true, upperCase: false, + vectorFont: false, }); /* */ @@ -57,6 +59,7 @@ function loadSettings() { longDate = def(settings.longDate, true); weekDay = def(settings.weekDay, true); upperCase = def(settings.upperCase, true); + vectorFont = def(settings.vectorFont, false); } // schedule a draw for the next second or minute @@ -92,63 +95,70 @@ function doColor() { return !isBangle1 && !Bangle.isLocked() && secondsColoured; } +// Actually draw the watch face function draw() { var x = g.getWidth() / 2; - var y = g.getHeight() / 2 - (secondsOnUnlock || secondsAlways ? 24 : 12); + var y = g.getHeight() / 2 - (secondsOnUnlock || secondsAlways ? 24 : (vectorFont ? 12 : 0)); g.reset(); g.clearRect(0, 24, g.getWidth(), g.getHeight()); // clear whole background - var date = new Date(); - var timeStr = require("locale").time(date, 1); - // draw time - g.setFontAlign(0, 0).setFont("Anton"); - g.drawString(timeStr, x, y); + var date = new Date(); // Actually the current date, this one is shown + var timeStr = require("locale").time(date, 1); // Hour and minute + g.setFontAlign(0, 0).setFont("Anton").drawString(timeStr, x, y); // draw time if (secondsScreen) { y += 76; var secStr = ":" + ("0" + date.getSeconds()).substr(-2); if (doColor()) g.setColor(0, 0, 1); g.setFont("Anton"); - if (dateOnSecs) { - g.setFontAlign(1, 0).drawString(secStr, g.getWidth() - (isBangle1 ? 32 : 2), y); - y -= 16; - x = g.getWidth() / 4 + (isBangle1 ? 12 : -4); + if (dateOnSecs) { // A bit of a complex drawing with seconds on the right and date on the left + g.setFontAlign(1, 0).drawString(secStr, g.getWidth() - (isBangle1 ? 32 : 2), y); // seconds + y -= (vectorFont ? 20 : 16); + x = g.getWidth() / 4 + (isBangle1 ? 12 : -6); var dateStr2 = (dateAsISO ? isoStr(date) : require("locale").date(date, 1)); var year; var md; var yearfirst; - if (dateStr2.match(/\d\d\d\d$/)) { + if (dateStr2.match(/\d\d\d\d$/)) { // formatted date ends with year year = dateStr2.slice(-4); md = dateStr2.slice(0, -4); - if (!md.endsWith(".")) + if (!md.endsWith(".")) // keep separator before the year only if it is a dot (31.12. but 31/12) md = md.slice(0, -1); yearfirst = false; - } else { - if (!dateStr2.match(/^\d\d\d\d/)) - dateStr2 = isoStr(date); + } else { // formatted date begins with year + if (!dateStr2.match(/^\d\d\d\d/)) // if year position cannot be detected... + dateStr2 = isoStr(date); // ...use ISO date format instead year = dateStr2.slice(0, 4); - md = dateStr2.slice(5); + md = dateStr2.slice(5); // never keep separator directly after year yearfirst = true; } - g.setFontAlign(0, 0).setFont("Vector", 24); + g.setFontAlign(0, 0); + if (vectorFont) + g.setFont("Vector", 24); + else + g.setFont("6x8", 2); if (doColor()) g.setColor(1, 0, 0); - g.drawString(md, x, (yearfirst ? y + 28 : y)); - g.drawString(year, x, (yearfirst ? y : y + 28)); + g.drawString(md, x, (yearfirst ? y + (vectorFont ? 26 : 16) : y)); + g.drawString(year, x, (yearfirst ? y : y + (vectorFont ? 26 : 16))); } else { - g.setFontAlign(0, 0).drawString(secStr, x, y); + g.setFontAlign(0, 0).drawString(secStr, x, y); // Just the seconds centered } - } else { // No seconds screen - y += 50; + } else { // No seconds screen: Show date and optionally day of week + y += (vectorFont ? 50 : (secondsOnUnlock || secondsAlways) ? 52 : 40); var dateStr = (dateAsISO ? isoStr(date) : require("locale").date(date, (longDate ? 0 : 1))); if (upperCase) dateStr = dateStr.toUpperCase(); - g.setFontAlign(0, 0).setFont("Vector", 24); + g.setFontAlign(0, 0); + if (vectorFont) + g.setFont("Vector", 24); + else + g.setFont("6x8", 2); g.drawString(dateStr, x, y); if (weekDay) { var dowStr = require("locale").dow(date); if (upperCase) dowStr = dowStr.toUpperCase(); - g.drawString(dowStr, x, y + 26); + g.drawString(dowStr, x, y + (vectorFont ? 26 : 16)); } } @@ -175,4 +185,4 @@ Bangle.setUI("clock"); Bangle.loadWidgets(); Bangle.drawWidgets(); -// end of file +// end of file \ No newline at end of file diff --git a/apps/antonclk/settings.js b/apps/antonclk/settings.js index 2bcc1d7ce..3af9df292 100644 --- a/apps/antonclk/settings.js +++ b/apps/antonclk/settings.js @@ -49,6 +49,14 @@ writeSettings(); } }, + "Vector font": { + value: (settings.vectorFont !== undefined ? settings.vectorFont : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.vectorFont = v; + writeSettings(); + } + }, }; // Submenu From 9bd1127ebc73e53353b4d5b112139b14cfcd455a Mon Sep 17 00:00:00 2001 From: David Peer Date: Wed, 5 Jan 2022 17:17:41 +0100 Subject: [PATCH 195/489] Design adaptions. --- apps/lcars/lcars.app.js | 6 +++--- apps/lcars/screenshot.png | Bin 5918 -> 5527 bytes 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 49d32dbe9..167adad2d 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -148,10 +148,10 @@ function printData(key, y, c){ } g.setColor(c); - g.fillRect(79, y-2, 85 ,y+18); + g.fillRect(79, y-2, 87 ,y+18); - g.setFontAlign(0,-1,0); - g.drawString(value, 109, y); + g.setFontAlign(1,-1,0); + g.drawString(value, 131, y); g.setColor(c); g.setFontAlign(-1,-1,0); diff --git a/apps/lcars/screenshot.png b/apps/lcars/screenshot.png index fea3ebb78a5d48859e2d27f622a0c10e34270cd0..fba55a9f71739c35e4497386a75c51ea4e1eee3d 100644 GIT binary patch literal 5527 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 Date: Wed, 5 Jan 2022 17:25:07 +0100 Subject: [PATCH 196/489] calendar: Use larger font for dates --- apps.json | 2 +- apps/calendar/ChangeLog | 1 + apps/calendar/calendar.js | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index f116049dc..7e33f6905 100644 --- a/apps.json +++ b/apps.json @@ -2430,7 +2430,7 @@ { "id": "calendar", "name": "Calendar", - "version": "0.05", + "version": "0.06", "description": "Simple calendar", "icon": "calendar.png", "screenshots": [{"url":"screenshot_calendar.png"}], diff --git a/apps/calendar/ChangeLog b/apps/calendar/ChangeLog index 3deec00e0..beba4ed95 100644 --- a/apps/calendar/ChangeLog +++ b/apps/calendar/ChangeLog @@ -3,3 +3,4 @@ 0.03: Add setting to start week on Sunday 0.04: Add setting to switch color schemes. On Bangle 2 non-dithering colors will be used by default. Use localized names for months and days of the week (Language app needed). 0.05: Update calendar weekend colors for start on Sunday +0.06: Use larger font for dates diff --git a/apps/calendar/calendar.js b/apps/calendar/calendar.js index 00e7d54cc..62702e349 100644 --- a/apps/calendar/calendar.js +++ b/apps/calendar/calendar.js @@ -206,6 +206,8 @@ function drawCalendar(date) { y2 - 1 ); } + require("Font8x12").add(Graphics); + g.setFont("8x12", fontSize); g.setColor(day < 50 ? fgOtherMonth : fgSameMonth); g.drawString( (day > 50 ? day - 50 : day).toString(), From 9a1543c1715e03ded04057956237adb839c43513 Mon Sep 17 00:00:00 2001 From: Alexander Minges Date: Wed, 5 Jan 2022 17:26:32 +0100 Subject: [PATCH 197/489] calendar: Update screenshot --- apps/calendar/screenshot_calendar.png | Bin 1174 -> 2584 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/calendar/screenshot_calendar.png b/apps/calendar/screenshot_calendar.png index 8285932c430aa2fee31b769b9d8b7ae071953fc4..7ef5986d4e63537cdaed0a9daa474c3e633a485b 100644 GIT binary patch literal 2584 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 Date: Wed, 5 Jan 2022 16:37:18 +0000 Subject: [PATCH 198/489] boot 0.40: Bootloader now rebuilds for new firmware versions --- apps.json | 2 +- apps/boot/ChangeLog | 1 + apps/boot/bootupdate.js | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/apps.json b/apps.json index 90dc1d941..c0088760f 100644 --- a/apps.json +++ b/apps.json @@ -16,7 +16,7 @@ { "id": "boot", "name": "Bootloader", - "version": "0.39", + "version": "0.40", "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/boot/ChangeLog b/apps/boot/ChangeLog index 5c929421b..d6619822b 100644 --- a/apps/boot/ChangeLog +++ b/apps/boot/ChangeLog @@ -43,3 +43,4 @@ 0.37: Remove Quiet Mode settings: now handled by Quiet Mode Schedule app 0.38: Option to log to file if settings.log==2 0.39: Fix passkey support (fix https://github.com/espruino/Espruino/issues/2035) +0.40: Bootloader now rebuilds for new firmware versions diff --git a/apps/boot/bootupdate.js b/apps/boot/bootupdate.js index e338d9020..664d64ee7 100644 --- a/apps/boot/bootupdate.js +++ b/apps/boot/bootupdate.js @@ -6,11 +6,11 @@ var s = require('Storage').readJSON('setting.json',1)||{}; var BANGLEJS2 = process.env.HWVERSION==2; // Is Bangle.js 2 var boot = ""; if (require('Storage').hash) { // new in 2v11 - helps ensure files haven't changed - var CRC = E.CRC32(require('Storage').read('setting.json'))+require('Storage').hash(/\.boot\.js/); - boot += `if (E.CRC32(require('Storage').read('setting.json'))+require('Storage').hash(/\\.boot\\.js/)!=${CRC})`; + var 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})`; } else { - var CRC = E.CRC32(require('Storage').read('setting.json'))+E.CRC32(require('Storage').list(/\.boot\.js/)); - boot += `if (E.CRC32(require('Storage').read('setting.json'))+E.CRC32(require('Storage').list(/\\.boot\\.js/))!=${CRC})`; + var 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 += ` { eval(require('Storage').read('bootupdate.js')); throw "Storage Updated!"}\n`; boot += `E.setFlags({pretokenise:1});\n`; From 896508e7a2645ed19e4c410da5c67df04776ed8c Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 5 Jan 2022 16:37:24 +0000 Subject: [PATCH 199/489] docs --- modules/Layout.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/Layout.js b/modules/Layout.js index 6dc4b6368..65e9a8dc8 100644 --- a/modules/Layout.js +++ b/modules/Layout.js @@ -42,8 +42,8 @@ layoutObject has: and `fillx`/`filly` to be set. Not compatible with text rotation. * A `col` field, eg `#f00` for red * A `bgCol` field for background color (will automatically fill on render) -* A `halign` field to set horizontal alignment. `-1`=left, `1`=right, `0`=center -* A `valign` field to set vertical alignment. `-1`=top, `1`=bottom, `0`=center +* A `halign` field to set horizontal alignment WITHIN a `v` container. `-1`=left, `1`=right, `0`=center +* A `valign` field to set vertical alignment WITHIN a `h` container. `-1`=top, `1`=bottom, `0`=center * A `pad` integer field to set pixels padding * A `fillx` int to choose if the object should fill available space in x. 0=no, 1=yes, 2=2x more space * A `filly` int to choose if the object should fill available space in y. 0=no, 1=yes, 2=2x more space From 37eac5585470dc831b80deac065aa532804d0663 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 5 Jan 2022 16:46:09 +0000 Subject: [PATCH 200/489] merge dozenal time into one app --- apps.json | 36 +-- apps/doztime/{app.js => app-bangle1.js} | 0 .../app.js => doztime/app-bangle2.js} | 0 apps/doztime2.app.js | 244 ------------------ apps/doztime2/app-icon.js | 1 - apps/doztime2/app.png | Bin 2500 -> 0 bytes 6 files changed, 3 insertions(+), 278 deletions(-) rename apps/doztime/{app.js => app-bangle1.js} (100%) rename apps/{doztime2/app.js => doztime/app-bangle2.js} (100%) delete mode 100644 apps/doztime2.app.js delete mode 100644 apps/doztime2/app-icon.js delete mode 100644 apps/doztime2/app.png diff --git a/apps.json b/apps.json index bd7877fad..65de7daf5 100644 --- a/apps.json +++ b/apps.json @@ -3987,11 +3987,12 @@ "icon": "app.png", "type": "clock", "tags": "clock", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS", "BANGLEJS2"], "readme": "README.md", "allow_emulator": true, "storage": [ - {"name":"doztime.app.js","url":"app.js"}, + {"name":"doztime.app.js","url":"app-bangle1.js","supports":["BANGLEJS"]}, + {"name":"doztime.app.js","url":"app-bangle2.js","supports":["BANGLEJS2"]}, {"name":"doztime.img","url":"app-icon.js","evaluate":true} ] }, @@ -4704,37 +4705,6 @@ {"name":"a_speech_timer.app.js","url":"app.js"}, {"name":"a_speech_timer.img","url":"app-icon.js","evaluate":true} ] -}, -{ "id":"doztime", - "name":"Dozenal Time", - "shortName":"Dozenal Time", - "icon":"app.png", - "version":"0.01", - "description":"A dozenal Holocene calendar and dozenal diurnal clock", - "tags":"clock", - "type":"clock", - "supports":["BANGLEJS"], - "allow_emulator":true, - "readme": "README.md", - "storage": [ - {"name":"doztime.app.js","url":"app.js"}, - {"name":"doztime.img","url":"app-icon.js","evaluate":true} - ] -}, -{ "id":"doztime2", - "name":"Dozenal Time 2", - "shortName":"Dozenal Time 2", - "icon":"app.png", - "version":"0.01", - "description":"A dozenal Holocene calendar and dozenal diurnal clock for Bangle.js 2", - "tags":"clock", - "type":"clock", - "supports":["BANGLEJS2"], - "allow_emulator":true, - "storage": [ - {"name":"doztime2.app.js","url":"app.js"}, - {"name":"doztime2.img","url":"app-icon.js","evaluate":true} - ] }, { "id": "mylocation", "name": "My Location", diff --git a/apps/doztime/app.js b/apps/doztime/app-bangle1.js similarity index 100% rename from apps/doztime/app.js rename to apps/doztime/app-bangle1.js diff --git a/apps/doztime2/app.js b/apps/doztime/app-bangle2.js similarity index 100% rename from apps/doztime2/app.js rename to apps/doztime/app-bangle2.js diff --git a/apps/doztime2.app.js b/apps/doztime2.app.js deleted file mode 100644 index b77e5201a..000000000 --- a/apps/doztime2.app.js +++ /dev/null @@ -1,244 +0,0 @@ -// Positioning values for graphics buffers -const g_height = 80; // total graphics height -const g_x_off = 0; // position from left was 16, then 8 here -const g_y_off = (184 - g_height)/2; // vertical center for graphics region was 240 -const g_width = 240 - 2 * g_x_off; // total graphics width -const g_height_d = 28; // height of date region was 32 -const g_y_off_d = 0; // y position of date region within graphics region -const spacing = 0; // space between date and time in graphics region -const g_y_off_t = g_y_off_d + g_height_d + spacing; // y position of time within graphics region -const g_height_t = 44; // height of time region was 48 - -// Other vars -const A1 = [30,30,30,30,31,31,31,31,31,31,30,30]; -const B1 = [30,30,30,30,30,31,31,31,31,31,30,30]; -const B2 = [30,30,30,30,31,31,31,31,31,30,30,30]; -const timeColour = "#ffffff"; -const dateColours = ["#ff0000","#ffa500","#ffff00","#00b800","#8383ff","#ff00ff","#ff0080"]; //blue was 0000ff -const calen10 = {"size":26,"pt0":[18-g_x_off,16],"step":[16,0],"dx":-4.5,"dy":-4.5}; // positioning for usual calendar line ft w 32, 32-g, step 20 -const calen7 = {"size":26,"pt0":[48-g_x_off,16],"step":[16,0],"dx":-4.5,"dy":-4.5}; // positioning for S-day calendar line ft w 32, 62-g, step 20 -const time5 = {"size":42,"pt0":[39-g_x_off,24],"step":[26,0],"dx":-6.5,"dy":-6.5}; // positioning for lull time line ft w 48, 64-g, step 30 -const time6 = {"size":42,"pt0":[26-g_x_off,24],"step":[26,0],"dx":-6.5,"dy":-6.5}; // positioning for twinkling time line ft w 48, 48-g, step 30 -const baseYear = 11584; -const baseDate = Date(2020,11,21); // month values run from 0 to 11 -let accum = new Date(baseDate.getTime()); -let sequence = []; -let timeActiveUntil; -let addTimeDigit = false; -let dateFormat = false; -let lastX = 999999999; -let res = {}; -//var last_time_log = 0; - -var drawtime_timeout; - -// Date and time graphics buffers -var dateColour = "#ffffff"; // override later -var timeColour2 = timeColour; -var g_d = Graphics.createArrayBuffer(g_width,g_height_d,1,{'msb':true}); -var g_t = Graphics.createArrayBuffer(g_width,g_height_t,1,{'msb':true}); -// Set screen mode and function to write graphics buffers -//Bangle.setLCDMode(); -g.clear(); // start with blank screen -g.flip = function() -{ - g.setBgColor(0,0,0); - g.setColor(dateColour); - g.drawImage( - { - width:g_width, - height:g_height_d, - buffer:g_d.buffer - }, g_x_off, g_y_off + g_y_off_d); - g.setColor(timeColour2); - g.drawImage( - { - width:g_width, - height:g_height_t, - buffer:g_t.buffer - }, g_x_off, g_y_off + g_y_off_t); -}; - -setWatch(function(){ modeTime(); }, BTN, {repeat:true} ); //was BTN1 -setWatch(function(){ Bangle.showLauncher(); }, BTN, { repeat: false, edge: "falling" }); //was BTN2 -//setWatch(function(){ modeWeather(); }, BTN3, {repeat:true}); -//setWatch(function(){ toggleTimeDigits(); }, BTN4, {repeat:true}); -//setWatch(function(){ toggleDateFormat(); }, BTN5, {repeat:true}); - -Bangle.on('touch', function(button, xy) { //from Gordon Williams - if (button==1) toggleTimeDigits(); - if (button==2) toggleDateFormat(); -}); - -function buildSequence(targ){ - for(let i=0;i n > dt)-1; - let year = baseYear+parseInt(index/12); - let month = index % 12; - let day = parseInt((dt-sequence[index])/86400000); - let colour = dateColours[day % 6]; - if(day==30){ colour=dateColours[6]; } - return({"year":year,"month":month,"day":day,"colour":colour}); -} -function toggleTimeDigits(){ - addTimeDigit = !addTimeDigit; - modeTime(); -} -function toggleDateFormat(){ - dateFormat = !dateFormat; - modeTime(); -} -function formatDate(res,dateFormat){ - let yyyy = res.year.toString(12); - calenDef = calen10; - if(!dateFormat){ //ordinal format - let mm = ("0"+(res.month+1).toString(12)).substr(-2); - let dd = ("0"+(res.day+1).toString(12)).substr(-2); - if(res.day==30){ - calenDef = calen7; - let m = ((res.month+1).toString(12)).substr(-2); - return(yyyy+"-"+"S"+m); // ordinal format - } - return(yyyy+"-"+mm+"-"+dd); - } - let m = res.month.toString(12); // cardinal format - let w = parseInt(res.day/6); - let d = res.day%6; - //return(yyyy+"-"+res.month+"-"+w+"-"+d); - return(yyyy+"-"+m+"-"+w+"-"+d); -} - -function writeDozTime(text,def){ - let pts = def.pts; - let x=def.pt0[0]; - let y=def.pt0[1]; - g_t.clear(); - g_t.setFont("Vector",def.size); - for(let i in text){ - if(text[i]=="a"){ g_t.setFontAlign(0,0,2); g_t.drawString("2",x+2+def.dx,y+1+def.dy); } //+1s are new - else if(text[i]=="b"){ g_t.setFontAlign(0,0,2); g_t.drawString("3",x+2+def.dx,y+1+def.dy); } //+1s are new - else{ g_t.setFontAlign(0,0,0); g_t.drawString(text[i],x,y); } - x = x+def.step[0]; - y = y+def.step[1]; - } -} -function writeDozDate(text,def,colour){ - - dateColour = colour; - let pts = def.pts; - let x=def.pt0[0]; - let y=def.pt0[1]; - g_d.clear(); - g_d.setFont("Vector",def.size); - for(let i in text){ - if(text[i]=="a"){ g_d.setFontAlign(0,0,2); g_d.drawString("2",x+2+def.dx,y+1+def.dy); } //+1s new - else if(text[i]=="b"){ g_d.setFontAlign(0,0,2); g_d.drawString("3",x+2+def.dx,y+1+def.dy); } //+1s new - else{ g_d.setFontAlign(0,0,0); g_d.drawString(text[i],x,y); } - x = x+def.step[0]; - y = y+def.step[1]; - } -} - -// Functions for time mode -function drawTime() -{ - let dt = new Date(); - let date = ""; - let timeDef; - let x = 0; - dt.setDate(dt.getDate()); - if(addTimeDigit){ - x = - 10368*dt.getHours()+172.8*dt.getMinutes()+2.88*dt.getSeconds()+0.00288*dt.getMilliseconds(); - let msg = "00000"+Math.floor(x).toString(12); - let time = msg.substr(-5,3)+"."+msg.substr(-2); - let wait = 347*(1-(x%1)); - timeDef = time6; - } else { - x = - 864*dt.getHours()+14.4*dt.getMinutes()+0.24*dt.getSeconds()+0.00024*dt.getMilliseconds(); - let msg = "0000"+Math.floor(x).toString(12); - let time = msg.substr(-4,3)+"."+msg.substr(-1); - let wait = 4167*(1-(x%1)); - timeDef = time5; - } - if(lastX > x){ res = getDate(dt); } // calculate date once at start-up and once when turning over to a new day - date = formatDate(res,dateFormat); - if(dt2200)) { - } else { - // We have a GPS time. Set time - setTime(g.time.getTime()/1000); - } - }); - Bangle.setGPSPower(1,"time"); - setTimeout(fixTime, 10*60*1000); // every 10 minutes -} -// Start time fixing with GPS on next 10 minute interval -setTimeout(fixTime, ((60-(new Date()).getMinutes()) % 10) * 60 * 1000); diff --git a/apps/doztime2/app-icon.js b/apps/doztime2/app-icon.js deleted file mode 100644 index 6154ac923..000000000 --- a/apps/doztime2/app-icon.js +++ /dev/null @@ -1 +0,0 @@ -require("heatshrink").decompress(atob("lEoxH+AHNYAAQjirwAEFbYkExIAGFTIkEJYoFDFQhMTDIODEQeI1gACxAJDwYpBKSAmDCoNe1nXABGsBwQoQHgRMBJQIhGFoxUBCoYoLGoImDJJBVIFAZRLJwQmJAA+CFwQoCKBSIDEyGsq+zKIijCEzfXq6tFFBR1CrDCGABOBwLMGXQInIOqmtZZGJE4p2CrDhIOpARI1hGCFAgnBA4J1XAAYfDOyzrFPBzQCYp2zOpLJDEASeFryeM1ldq9dB5ggCKATGF1gqJEwInKC4TIGE9R3PFIIQLO4zHSXQIoLY4xQBAwNeE5woMDoKYBE4gIBrAnPFBYfDE4rIDFCOzTwzGFPCwfCOxxQDwdYZJ5XJrGDJwx4DKCYAE2ZOCE44obExZ5EFComNE4KEBFBWsYQ50CC4IbBE5JQDFATMGE4+IJoTEIKJBhDrxJHFoYOCCQQmNFAo8CAoOIJwIABJQIJCwYmSPYgpBe4QABEQQACBYYlSKQgqEAAouDEyoqIKYokZFZIjgADI")) diff --git a/apps/doztime2/app.png b/apps/doztime2/app.png deleted file mode 100644 index 363537a58cf0ba55de061d555c4501f34d53279e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2500 zcmV;#2|MxUxKLUMAqh<|nF-|;LRvx^$2fKdl30=* zTf&MZTh`URdw2W65B!j0C#D_#-|pSB=l<^Qo;|w<_>POrrE`5lbD2r36_OB@93%w5 zHPSQyK_ZYuha%`FJDyo}=Kls*_vo&2L6yx^!X_@nLVyTWQw+P!CdpKxfB>_YrRQ=y zryD9D2q99t5WESDZQK3ay6*o8V0}Y#858_TB4IO?sVMRJRBy2tg@uKXBq?tn&N))4 zG?K|A;=Kve;ubg;FIfzYd!Jw1^Q{5aJ-+7w0552&s#H`|sD7UhTyP|lN%Z%ppl37C z^&E000|01>3{A7a;V6LHQv{F43yBcK;|X*|It{~MhJf|R?x$~kaZZ4@HNNeT4B7-D z)`!Dk5)1|iV+_$q4Dm!9mStfeV0;NyJ%6R>U260jdr2CI|g@w z4I5U@$MUKYcnfV~eKNWM04T7jWAFOXIu0H0#r6+QB9+M@5C|X?3SwYj5MQ(%H!O=C zA+oV*XXE<*Sp(kI__l*G`F%x}YinvRQzc14dwT~=J&U_;x&*72g(1_4>n@`kIQmr= z0HF4wzywGDFd4@?hdS}vdtXA;?5M1&1hXt0YiZ3HX6`>~CUZl+k<7cgC4)9mN^5Is zFH<=eXlZGIOBLAi%WH7kig{DuX7ksIETQh2`PlM{Yv52gT8 zA9kCHit=LIczFO{oJ!)v$u5+Ym%-z4(|EkMs`9#@b$5L9*Uu*m*7%3|hUPLN$P1xx zn7EuSoai_Kw?n~WcU}&=CZA)>hE-rwr@#TgKMx+o!Oz>^un(_ShbH6kyDx{=rK0_K zJDg4@f}xNEB5kQ_*i|wuAQSvaRa2BuFhC;F7;@PmJbBNRaM)&sn@(RRQ`ouh09Idr zHG-wz8+&ipWc+616)^NHB9R!vp&(RMQ2_cxUckCXca;+fn=2|RRK^&(yJNWPrb|%b zaa=H*5CU7b?}M+{jn&s*HKo1O>%g5qycpfxT`&v-72&W(K<=w=XfB%qD5$cT%2fD$ zK13tKTgmEW;R}WXfPEhw##fOu*tFqCkm;1=4ggratO9PQhFGi%e!mY?rosf4sa$Zx6LD-`O$97>CaBR5}eoleI(PT`fe_G2(J1dqEAH(z(fjD5!Y zFDouUHanauZJH(-IX(0Zpb##Z$`k-hX2EGwX3VXV_3F<3=uZy<0CG8V#;Kj^Uk0-* z0DvsZ6d*2Onp`XeoUmysve_*D-O_PR`^o+@Ivd+78Dkb827r+%CJ?c#u5$pe*=*?P8ya&mTU9Td zhd=!KJ^;XucR$8UuQvk#uBy58oRFjH>C3=AlB@Nc&WRwAF+fg8yOA?g&N&>80<@k^ z&KfMA>TkIg0A>X_s$-|m!tN-5WpNleQza7b7z0!U{e;0nI-Q2wQ-t>R9`vPk6whHV zJRiuul#bJ9QmCvfLpqfLAYdBOL11JJ?s#U^8A*~(^z|j-@pwTg#i6#|3x*rj`kSxC z4a=9{RbPb9xp=8F(rL)D zjPgJ^UfcgAdXhtPhMZ2_eHr}iy)O|61fePlIy)nV;Nr#cm--1CwZ+hA7|e*qx$x<2j6*iO=7%l z-Yiqsu=jOYq3f0|sZ}}WIQ~T&+)f2gY`PMq-uzd9+2-!Z_mScv+t;3q0`T1;p0RVp7_?BBRwOOX}(nX7^RF}(%&dwOR zy1L+TY1r_C1z28Hg5shXN*^g5pC0eUn;)DUj@Cc`;cyTG>5yK5^U{PtidB!xpk7>0pptP5W!;;<}^`DI0@p65YnaRHq6k>XL-L{DD^$4;Nc z=`$%%D#7RTBN!Tv)@US(Xe`DB$KTVMnAJ&YUBjOHK%_0IDytRY3f1rT zfeV3TGKo|wh3rrU*{lwe4WH)}nZj Date: Wed, 5 Jan 2022 17:49:05 +0100 Subject: [PATCH 201/489] Fixed 100% battery level. --- apps/lcars/lcars.app.js | 6 +++--- apps/lcars/screenshot.png | Bin 5527 -> 5259 bytes 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 167adad2d..8f06abc29 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -148,10 +148,10 @@ function printData(key, y, c){ } g.setColor(c); - g.fillRect(79, y-2, 87 ,y+18); + g.fillRect(79, y-2, 85 ,y+18); - g.setFontAlign(1,-1,0); - g.drawString(value, 131, y); + g.setFontAlign(0,-1,0); + g.drawString(value, 110, y); g.setColor(c); g.setFontAlign(-1,-1,0); diff --git a/apps/lcars/screenshot.png b/apps/lcars/screenshot.png index fba55a9f71739c35e4497386a75c51ea4e1eee3d..5d7603b45e6c7aadcc01aa0afdf13ff4d579eb93 100644 GIT binary patch literal 5259 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 Z{Rc&E;;+Q Date: Wed, 5 Jan 2022 08:49:36 -0800 Subject: [PATCH 202/489] Update apps.json --- apps.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 89c5f7b70..49397479a 100644 --- a/apps.json +++ b/apps.json @@ -5147,10 +5147,11 @@ "icon": "icon.png", "type": "boot", "tags": "system", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS","BANGLEJS2"] "screenshots": [{"url":"pro-menu-screenshot.png"}], "storage": [ - {"name":"promenu.boot.js","url":"boot.js"}, + {"name":"promenu.boot.js","url":"boot.js","supports": ["BANGLEJS"]}, + {"name":"promenu.bootb2.js","url":"boot.js","supports": ["BANGLEJS2"]}, {"name":"promenu.img","url":"promenuIcon.js","evaluate":true} ] }, From 1adeef592b84dff615a1937ae01216f8d492786f Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 08:51:42 -0800 Subject: [PATCH 203/489] Create bootb2.js --- apps/promenu/bootb2.js | 142 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 apps/promenu/bootb2.js diff --git a/apps/promenu/bootb2.js b/apps/promenu/bootb2.js new file mode 100644 index 000000000..096745f34 --- /dev/null +++ b/apps/promenu/bootb2.js @@ -0,0 +1,142 @@ +E.showMenu = function(items) { + function RectRnd(x1,y1,x2,y2,r) { + pp = []; + pp.push.apply(pp,g.quadraticBezier([x2-r,y1, x2,y1,x2,y1+r])); + pp.push.apply(pp,g.quadraticBezier([x2,y2-r,x2,y2,x2-r,y2])); + pp.push.apply(pp,g.quadraticBezier([x1+r,y2,x1,y2,x1,y2-r])); + pp.push.apply(pp,g.quadraticBezier([x1,y1+r,x1,y1,x1+r,y1])); + return pp; + } + function fillRectRnd(x1,y1,x2,y2,r,c) { + g.setColor(c); + g.fillPoly(RectRnd(x1,y1,x2,y2,r),1); + g.setColor(255,255,255); + } + function drawRectRnd(x1,y1,x2,y2,r,c) { + g.setColor(c); + g.drawPoly(RectRnd(x1,y1,x2,y2,r),1); + g.setColor(255,255,255); + } + g.reset().clearRect(Bangle.appRect); // clear if no menu supplied + Bangle.setLCDPower(1); // ensure screen is on + if (!items) { + Bangle.setUI(); + return; + } + var menuItems = Object.keys(items); + var options = items[""]; + if (options) menuItems.splice(menuItems.indexOf(""),1); + if (!(options instanceof Object)) options = {}; + options.fontHeight = options.fontHeight||25; + if (options.selected === undefined) + options.selected = 0; + var ar = Bangle.appRect; + var x = ar.x; + var x2 = ar.x2; + var y = ar.y; + var y2 = ar.y2 - 12; // padding at end for arrow + if (options.title) + y += 22; + var loc = require("locale"); + var l = { + lastIdx : 0, + draw : function(rowmin,rowmax) { + var rows = 0|Math.min((y2-y) / options.fontHeight,menuItems.length); + var idx = E.clip(options.selected-( rows>>1),0,menuItems.length-rows); + if (idx!=l.lastIdx) rowmin=undefined; // redraw all if we scrolled + l.lastIdx = idx; + var iy = y; + g.reset().setFontAlign(0,-1,0).setFont('12x20'); + if (options.predraw) options.predraw(g); + if (rowmin===undefined && options.title) + g.drawString(options.title,(x+x2)/2,y-21).drawLine(x,y-2,x2,y-2). + setColor(g.theme.fg).setBgColor(g.theme.bg); + iy += 4; + if (rowmin!==undefined) { + if (idxrowmax) { + rows = 1+rowmax-rowmin; + } + } + while (rows--) { + var name = menuItems[idx]; + var item = items[name]; + var hl = (idx==options.selected && !l.selectEdit); + if(g.theme.dark){ + fillRectRnd(x,iy,x2,iy+options.fontHeight-3,7,hl ? g.theme.bgH : g.theme.bg+40); + }else{ + fillRectRnd(x,iy,x2,iy+options.fontHeight-3,7,hl ? g.theme.bgH : g.theme.bg-20); + } + g.setColor(hl ? g.theme.fgH : g.theme.fg); + g.setFontAlign(-1,-1); + var v = item.value; + v = loc.translate(""+v); + if(loc.translate(name).length >= 19-v.length && "object" == typeof item){ + if (item.format) v=item.format(v); + g.drawString(loc.translate(name).substring(0, 12-v.length)+"...",x+3.7,iy+2.7); + }else{ + if(loc.translate(name).length >= 15){ + g.drawString(loc.translate(name).substring(0, 15)+"...",x+3.7,iy+2.7); + }else{ + g.drawString(loc.translate(name),x+3.7,iy+2.7); + } + } + if ("object" == typeof item) { + var xo = x2; + var v = item.value; + if (item.format) v=item.format(v); + v = loc.translate(""+v); + if (l.selectEdit && idx==options.selected) { + xo -= 24 + 1; + g.setColor(g.theme.fgH).drawImage("\x0c\x05\x81\x00 \x07\x00\xF9\xF0\x0E\x00@",xo,iy+(options.fontHeight-10)/2,{scale:2}); + } + g.setFontAlign(1,-1); + g.drawString(v,xo-2,iy+1); + } + g.setColor(g.theme.fg); + iy += options.fontHeight; + idx++; + } + g.setFontAlign(-1,-1); + g.setColor((idxitem.max) item.value = item.wrap ? item.min : item.max; + if (item.onchange) item.onchange(item.value); + l.draw(options.selected,options.selected); + } else { + var lastSelected=options.selected; + options.selected = (dir+options.selected+menuItems.length)%menuItems.length; + l.draw(Math.min(lastSelected,options.selected), Math.max(lastSelected,options.selected)); + } + } + }; + l.draw(); + Bangle.setUI("updown",dir => { + if (dir) l.move(dir); + else l.select(); + }); + return l; +}; From 3cfc5a83458bcd01bf913c2edcdad2a481afb0a5 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 08:53:08 -0800 Subject: [PATCH 204/489] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 01bdaf84f..a7a1c85a1 100644 --- a/apps.json +++ b/apps.json @@ -5163,7 +5163,7 @@ "id": "promenu", "name": "Pro Menu", "version": "0.01", - "description": "Replace Bangle.js 1's built in menu function.", + "description": "Replace the built in menu function. Supports Bangle.js 1 and Bangle.js 2.", "icon": "icon.png", "type": "boot", "tags": "system", From 485fb4a3c2bf9082be4dfb623d7f1a1042cef853 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 08:54:56 -0800 Subject: [PATCH 205/489] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index a7a1c85a1..16beb366a 100644 --- a/apps.json +++ b/apps.json @@ -5167,7 +5167,7 @@ "icon": "icon.png", "type": "boot", "tags": "system", - "supports": ["BANGLEJS","BANGLEJS2"] + "supports": ["BANGLEJS","BANGLEJS2"], "screenshots": [{"url":"pro-menu-screenshot.png"}], "storage": [ {"name":"promenu.boot.js","url":"boot.js","supports": ["BANGLEJS"]}, From bf5f5f68326004014433230f1a7f0e16ff9def65 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 5 Jan 2022 16:56:12 +0000 Subject: [PATCH 206/489] updated as per https://github.com/espruino/BangleApps/pull/1143#issuecomment-1005894992 --- apps/doztime/app-bangle2.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/doztime/app-bangle2.js b/apps/doztime/app-bangle2.js index 313ad9e48..b77e5201a 100644 --- a/apps/doztime/app-bangle2.js +++ b/apps/doztime/app-bangle2.js @@ -14,11 +14,11 @@ const A1 = [30,30,30,30,31,31,31,31,31,31,30,30]; const B1 = [30,30,30,30,30,31,31,31,31,31,30,30]; const B2 = [30,30,30,30,31,31,31,31,31,30,30,30]; const timeColour = "#ffffff"; -const dateColours = ["#ff0000","#ff8000","#ffff00","#00ff00","#0080ff","#ff00ff","#ffffff"]; +const dateColours = ["#ff0000","#ffa500","#ffff00","#00b800","#8383ff","#ff00ff","#ff0080"]; //blue was 0000ff const calen10 = {"size":26,"pt0":[18-g_x_off,16],"step":[16,0],"dx":-4.5,"dy":-4.5}; // positioning for usual calendar line ft w 32, 32-g, step 20 const calen7 = {"size":26,"pt0":[48-g_x_off,16],"step":[16,0],"dx":-4.5,"dy":-4.5}; // positioning for S-day calendar line ft w 32, 62-g, step 20 -const time5 = {"size":36,"pt0":[46-g_x_off,24],"step":[22,0],"dx":-6.5,"dy":-6.5}; // positioning for lull time line ft w 48, 64-g, step 30 -const time6 = {"size":36,"pt0":[36-g_x_off,24],"step":[22,0],"dx":-6.5,"dy":-6.5}; // positioning for twinkling time line ft w 48, 48-g, step 30 +const time5 = {"size":42,"pt0":[39-g_x_off,24],"step":[26,0],"dx":-6.5,"dy":-6.5}; // positioning for lull time line ft w 48, 64-g, step 30 +const time6 = {"size":42,"pt0":[26-g_x_off,24],"step":[26,0],"dx":-6.5,"dy":-6.5}; // positioning for twinkling time line ft w 48, 48-g, step 30 const baseYear = 11584; const baseDate = Date(2020,11,21); // month values run from 0 to 11 let accum = new Date(baseDate.getTime()); @@ -206,7 +206,7 @@ function modeTime() { timeActiveUntil = new Date(); timeActiveUntil.setDate(timeActiveUntil.getDate()); - timeActiveUntil.setSeconds(timeActiveUntil.getSeconds()+15); + timeActiveUntil.setSeconds(timeActiveUntil.getSeconds()+86400); if (typeof drawtime_timeout !== 'undefined') { clearTimeout(drawtime_timeout); From c87d1d16509ca3943db44bc1606c8757039fb3e5 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 19:28:32 +0100 Subject: [PATCH 207/489] Fix settings default values --- apps/circlesclock/settings.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index 0c42319f5..95ebc17db 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -10,6 +10,7 @@ var namesCircleTypes = ["steps", "distance", "heart", "battery"]; E.showMenu({ '': { 'title': 'circlesclock' }, + '< Back': back, 'min heartrate': { value: "minHR" in settings ? settings.minHR : 40, min: 0, @@ -76,23 +77,22 @@ onchange: x => save('showWidgets', x), }, 'left': { - value: Math.max(0,0 | valuesCircleTypes.indexOf(settings.circle1)), + value: settings.circle1 ? valuesCircleTypes.indexOf(settings.circle1) : 0, min: 0, max: 3, format: v => namesCircleTypes[v], onchange: x => save('circle1', valuesCircleTypes[x]), }, 'middle': { - value: Math.max(0,2 | valuesCircleTypes.indexOf(settings.circle2)), + value: settings.circle2 ? valuesCircleTypes.indexOf(settings.circle2) : 2, min: 0, max: 3, format: v => namesCircleTypes[v], onchange: x => save('circle2', valuesCircleTypes[x]), }, 'right': { - value: Math.max(0,3 | valuesCircleTypes.indexOf(settings.circle3)), + value: settings.circle3 ? valuesCircleTypes.indexOf(settings.circle3) : 3, min: 0, max: 3, format: v => namesCircleTypes[v], onchange: x => save('circle3', valuesCircleTypes[x]), - }, - '< Back': back, + } }); }); From 9a5937a3eb3535636e74f926d83dd41ebdd8c407 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 19:38:18 +0100 Subject: [PATCH 208/489] Improve widget visibility --- apps/circlesclock/app.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index e10d55f17..a256c93ce 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -41,7 +41,7 @@ const colorRed = '#ff0000'; const colorGreen = '#008000'; const colorBlue = '#0000ff'; const colorYellow = '#ffff00'; -const widgetOffset = showWidgets ? 12 : 0; +const widgetOffset = showWidgets ? 14 : 0; const h = g.getHeight() - widgetOffset; const w = g.getWidth(); const hOffset = 30 - widgetOffset; @@ -55,9 +55,9 @@ const radiusOuter = 22; const radiusInner = 16; function draw() { - g.reset(); + g.clear(true); g.setColor(colorBg); - g.fillRect(0, 0, w, h); + g.fillRect(0, widgetOffset, w, h); // time g.setFont("Vector:50"); @@ -265,7 +265,7 @@ function shortValue(v) { } function getSteps() { - if (WIDGETS.wpedom !== undefined) { + if (WIDGETS && WIDGETS.wpedom !== undefined) { return WIDGETS.wpedom.getSteps(); } return 0; @@ -307,8 +307,6 @@ if (isCircleEnabled("battery")) { }); } -g.clear(); - Bangle.setUI("clock"); Bangle.loadWidgets(); if (!showWidgets) { From c15b700ef6fde7bdad924150d25504e51660e358 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 19:50:07 +0100 Subject: [PATCH 209/489] Fix widget drawing --- apps/circlesclock/app.js | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index a256c93ce..fb4635424 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -56,6 +56,23 @@ const radiusInner = 16; function draw() { g.clear(true); + + if (!showWidgets) { + /* + * 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 = ""; + } + } + } else { + Bangle.drawWidgets(); + } + g.setColor(colorBg); g.fillRect(0, widgetOffset, w, h); @@ -280,8 +297,7 @@ Bangle.on('lock', function(isLocked) { drawHeartRate(); } } - if (isCircleEnabled("steps")) drawSteps(); - if (isCircleEnabled("stepsDistance")) drawStepsDistance(); + draw(); } else { if (isCircleEnabled("hr")) { Bangle.setHRMPower(0, "watch"); @@ -309,19 +325,6 @@ if (isCircleEnabled("battery")) { Bangle.setUI("clock"); Bangle.loadWidgets(); -if (!showWidgets) { - /* - * 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 = ""; - } - } -} draw(); setInterval(draw, 60000); From d36743032c878bd73fdda87cf0b22d5b8e002b10 Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Wed, 5 Jan 2022 22:21:55 +0100 Subject: [PATCH 210/489] Anton clock: Smaller seconds, weekday with seconds, seconds without colon, cleaner configuration --- apps/antonclk/README.md | 42 ++++++++++++-------- apps/antonclk/app.js | 81 +++++++++++++++++++++++---------------- apps/antonclk/settings.js | 64 ++++++++++++++----------------- 3 files changed, 101 insertions(+), 86 deletions(-) diff --git a/apps/antonclk/README.md b/apps/antonclk/README.md index cb37d566b..41d3e4559 100644 --- a/apps/antonclk/README.md +++ b/apps/antonclk/README.md @@ -11,8 +11,8 @@ The basic time representation only shows hours and minutes of the current time. * Date can be shown in three different formats: * ISO-8601: 2021-12-19 * short local format: 19/12/2021, 19.12.2021 - * long local format (not together with seconds): DEC 19 2021 -* Weekday can be shown (not together with seconds) + * long local format: DEC 19 2021 +* Weekday can be shown (on seconds screen only instead of year) ## Usage @@ -33,9 +33,10 @@ You configure Anton clock through several "on/off" switches in two menus. The main menu contains several settings covering Anton clock in general. * **Seconds...** - Opens the submenu for configuring the presentation of the current time's seconds. -* **ISO8601 date** - Show the date in ISO-8601 format, irrespective of the current locale. -* **Long date** - Show the date in long format (usually with month in letters instead of number). -Exact format depends on the current locale. _Only evaluated if ISO8601 date is not set._ +* **Date** - Format of the date representation. Possible values are + * **Long** - "Long" date format in the current locale. Usually with the month as name, not number. + * **Short** - "Short" date format in the current locale. Usually with the month as number. + * **ISO8601** - Show the date in ISO-8601 format (YYYY-MM-DD), irrespective of the current locale. * **Show Weekday** - Weekday is shown in the time presentation without seconds. Weekday name depends on the current locale. If seconds are shown, the weekday is never shown as there is not enough space on the watch face. @@ -49,21 +50,28 @@ Otherwise, a scaled version of the built-in 6x8 pixels font is used. The "Seconds" submenu configures how (and if) seconds are shown on the "Anton" watch face. -* **Always** - Seconds are _always_ shown, irrespective of the display's unlock state. -If this is enabled, weekdays will never been shown. -_Enabling this option increases power consumption as the watch face will update once per second instead of once per minute._ -* **If unlocked** - Seconds are shown if the display is unlocked. -On a locked display, only hour, minutes, date and weekday are shown. -"Always" overrides this option. +* **Show** - Configure when the seconds should be shown at all: + * **Never** - Seconds are never shown. +In this case, hour and minute are a bit more centered on the screen and the clock will always only update every minute. +This saves battery power. + * **Unlocked** - Seconds are shown if the display is unlocked. +On locked displays, only hour, minutes, date and optionally the weekday are shown. _This option is highly recommended on the Bangle.js 2!_ -* **Coloured** - If enabled, seconds are shown in blue instead of black. + * **Always** - Seconds are _always_ shown, irrespective of the display's unlock state. +_Enabling this option increases power consumption as the watch face will update once per second instead of once per minute._ +* **With ":"** - If enabled, a colon ":" is prepended to the seconds. +This resembles the usual time representation "hh:mm:ss", even though the seconds are printed on a separate line. +* **Color** - If enabled, seconds are shown in blue instead of black. +If the date is shown on the seconds screen, it is colored read instead of black. This make the visual orientation much easier on the watch face. -* **With date** - If enabled, the date is shown together with the seconds. -Depending on the "ISO8601 date" settings, ISO8601 or short local format is used. -The date is coloured in red if the "Coloured" option is chosen. +* **Date** - It is possible to show the date together with the seconds: + * **No** - Date is _not_ shown in the seconds screen. +In this case, the seconds are centered below hour and minute. + * **Year** - Date is shown with day, month, and year. If "Date" in the main settings is configured to _ISO8601_, this is used here, too. Otherwise, the short local format is used. + * **Weekday** - Date is shown with day, month, and weekday. -If neither "Always" nor "If unlocked" is selected, Anton clock does _never_ show seconds. +The date is coloured in red if the "Coloured" option is chosen. ## Compatibility -Anton clock makes use of core Bangle.js 2 features (coloured display, display lock state). It also runs on the Bangle.js 1 but these features are not available there due to the hardware features. +Anton clock makes use of core Bangle.js 2 features (coloured display, display lock state). It also runs on the Bangle.js 1 but these features are not available there due to hardware restrictions. diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index e772d679d..1f3e49792 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -3,17 +3,21 @@ var SETTINGSFILE = "antonclk.json"; Graphics.prototype.setFontAnton = function(scale) { -// Actual height 69 (68 - 0) - g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAA/gAAAAAAAAAAP/gAAAAAAAAAH//gAAAAAAAAB///gAAAAAAAAf///gAAAAAAAP////gAAAAAAD/////gAAAAAA//////gAAAAAP//////gAAAAH///////gAAAB////////gAAAf////////gAAP/////////gAD//////////AA//////////gAA/////////4AAA////////+AAAA////////gAAAA///////wAAAAA//////8AAAAAA//////AAAAAAA/////gAAAAAAA////4AAAAAAAA///+AAAAAAAAA///gAAAAAAAAA//wAAAAAAAAAA/8AAAAAAAAAAA/AAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////AAAAAB///////8AAAAH////////AAAAf////////wAAA/////////4AAB/////////8AAD/////////+AAH//////////AAP//////////gAP//////////gAP//////////gAf//////////wAf//////////wAf//////////wAf//////////wA//8AAAAAB//4A//wAAAAAAf/4A//gAAAAAAP/4A//gAAAAAAP/4A//gAAAAAAP/4A//wAAAAAAf/4A///////////4Af//////////wAf//////////wAf//////////wAf//////////wAP//////////gAP//////////gAH//////////AAH//////////AAD/////////+AAB/////////8AAA/////////4AAAP////////gAAAD///////+AAAAAf//////4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gAAAAAAAAAAP/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/AAAAAAAAAAA//AAAAAAAAAAA/+AAAAAAAAAAB/8AAAAAAAAAAD//////////gAH//////////gAP//////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/4AAAAB/gAAD//4AAAAf/gAAP//4AAAB//gAA///4AAAH//gAB///4AAAf//gAD///4AAA///gAH///4AAD///gAP///4AAH///gAP///4AAP///gAf///4AAf///gAf///4AB////gAf///4AD////gA////4AH////gA////4Af////gA////4A/////gA//wAAB/////gA//gAAH/////gA//gAAP/////gA//gAA///8//gA//gAD///w//gA//wA////g//gA////////A//gA///////8A//gA///////4A//gAf//////wA//gAf//////gA//gAf/////+AA//gAP/////8AA//gAP/////4AA//gAH/////gAA//gAD/////AAA//gAB////8AAA//gAA////wAAA//gAAP///AAAA//gAAD//8AAAA//gAAAP+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/+AAAAAD/wAAB//8AAAAP/wAAB///AAAA//wAAB///wAAB//wAAB///4AAD//wAAB///8AAH//wAAB///+AAP//wAAB///+AAP//wAAB////AAf//wAAB////AAf//wAAB////gAf//wAAB////gA///wAAB////gA///wAAB////gA///w//AAf//wA//4A//AAA//wA//gA//AAAf/wA//gB//gAAf/wA//gB//gAAf/wA//gD//wAA//wA//wH//8AB//wA///////////gA///////////gA///////////gA///////////gAf//////////AAf//////////AAP//////////AAP/////////+AAH/////////8AAH///+/////4AAD///+f////wAAA///8P////gAAAf//4H///+AAAAH//gB///wAAAAAP4AAH/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/wAAAAAAAAAA//wAAAAAAAAAP//wAAAAAAAAB///wAAAAAAAAf///wAAAAAAAH////wAAAAAAA/////wAAAAAAP/////wAAAAAB//////wAAAAAf//////wAAAAH///////wAAAA////////wAAAP////////wAAA///////H/wAAA//////wH/wAAA/////8AH/wAAA/////AAH/wAAA////gAAH/wAAA///4AAAH/wAAA//+AAAAH/wAAA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gAAAAAAAAH/4AAAAAAAAAAH/wAAAAAAAAAAH/wAAAAAAAAAAH/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//8AAA/////+B///AAA/////+B///wAA/////+B///4AA/////+B///8AA/////+B///8AA/////+B///+AA/////+B////AA/////+B////AA/////+B////AA/////+B////gA/////+B////gA/////+B////gA/////+A////gA//gP/gAAB//wA//gf/AAAA//wA//gf/AAAAf/wA//g//AAAAf/wA//g//AAAA//wA//g//gAAA//wA//g//+AAP//wA//g////////gA//g////////gA//g////////gA//g////////gA//g////////AA//gf///////AA//gf//////+AA//gP//////+AA//gH//////8AA//gD//////4AA//gB//////wAA//gA//////AAAAAAAH////8AAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////gAAAAB///////+AAAAH////////gAAAf////////4AAB/////////8AAD/////////+AAH//////////AAH//////////gAP//////////gAP//////////gAf//////////wAf//////////wAf//////////wAf//////////wAf//////////4A//wAD/4AAf/4A//gAH/wAAP/4A//gAH/wAAP/4A//gAP/wAAP/4A//gAP/4AAf/4A//wAP/+AD//4A///wP//////4Af//4P//////wAf//4P//////wAf//4P//////wAf//4P//////wAP//4P//////gAP//4H//////gAH//4H//////AAH//4D/////+AAD//4D/////8AAB//4B/////4AAA//4A/////wAAAP/4AP////AAAAB/4AD///4AAAAAAAAAH/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//AAAAAAAAAAA//gAAAAAAAAAA//gAAAAAAAAAA//gAAAAAAADgA//gAAAAAAP/gA//gAAAAAH//gA//gAAAAB///gA//gAAAAP///gA//gAAAD////gA//gAAAf////gA//gAAB/////gA//gAAP/////gA//gAB//////gA//gAH//////gA//gA///////gA//gD///////gA//gf///////gA//h////////gA//n////////gA//////////gAA/////////AAAA////////wAAAA///////4AAAAA///////AAAAAA//////4AAAAAA//////AAAAAAA/////4AAAAAAA/////AAAAAAAA////8AAAAAAAA////gAAAAAAAA///+AAAAAAAAA///4AAAAAAAAA///AAAAAAAAAA//4AAAAAAAAAA/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//gB///wAAAAP//4H///+AAAA///8P////gAAB///+f////4AAD///+/////8AAH/////////+AAH//////////AAP//////////gAP//////////gAf//////////gAf//////////wAf//////////wAf//////////wA///////////wA//4D//wAB//4A//wB//gAA//4A//gA//gAAf/4A//gA//AAAf/4A//gA//gAAf/4A//wB//gAA//4A///P//8AH//4Af//////////wAf//////////wAf//////////wAf//////////wAf//////////gAP//////////gAP//////////AAH//////////AAD/////////+AAD///+/////8AAB///8f////wAAAf//4P////AAAAH//wD///8AAAAA/+AAf//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH//gAAAAAAAAB///+AA/+AAAAP////gA//wAAAf////wA//4AAB/////4A//8AAD/////8A//+AAD/////+A///AAH/////+A///AAP//////A///gAP//////A///gAf//////A///wAf//////A///wAf//////A///wAf//////A///wA///////AB//4A//4AD//AAP/4A//gAB//AAP/4A//gAA//AAP/4A//gAA/+AAP/4A//gAB/8AAP/4A//wAB/8AAf/4Af//////////wAf//////////wAf//////////wAf//////////wAf//////////wAP//////////gAP//////////gAH//////////AAH/////////+AAD/////////8AAB/////////4AAAf////////wAAAP////////AAAAB///////4AAAAAD/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/AAB/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("EiAnGicnJycnJycnEw=="), 78+(scale<<8)+(1<<16)); + // Actual height 69 (68 - 0) + g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAA/gAAAAAAAAAAP/gAAAAAAAAAH//gAAAAAAAAB///gAAAAAAAAf///gAAAAAAAP////gAAAAAAD/////gAAAAAA//////gAAAAAP//////gAAAAH///////gAAAB////////gAAAf////////gAAP/////////gAD//////////AA//////////gAA/////////4AAA////////+AAAA////////gAAAA///////wAAAAA//////8AAAAAA//////AAAAAAA/////gAAAAAAA////4AAAAAAAA///+AAAAAAAAA///gAAAAAAAAA//wAAAAAAAAAA/8AAAAAAAAAAA/AAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////AAAAAB///////8AAAAH////////AAAAf////////wAAA/////////4AAB/////////8AAD/////////+AAH//////////AAP//////////gAP//////////gAP//////////gAf//////////wAf//////////wAf//////////wAf//////////wA//8AAAAAB//4A//wAAAAAAf/4A//gAAAAAAP/4A//gAAAAAAP/4A//gAAAAAAP/4A//wAAAAAAf/4A///////////4Af//////////wAf//////////wAf//////////wAf//////////wAP//////////gAP//////////gAH//////////AAH//////////AAD/////////+AAB/////////8AAA/////////4AAAP////////gAAAD///////+AAAAAf//////4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gAAAAAAAAAAP/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/AAAAAAAAAAA//AAAAAAAAAAA/+AAAAAAAAAAB/8AAAAAAAAAAD//////////gAH//////////gAP//////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/4AAAAB/gAAD//4AAAAf/gAAP//4AAAB//gAA///4AAAH//gAB///4AAAf//gAD///4AAA///gAH///4AAD///gAP///4AAH///gAP///4AAP///gAf///4AAf///gAf///4AB////gAf///4AD////gA////4AH////gA////4Af////gA////4A/////gA//wAAB/////gA//gAAH/////gA//gAAP/////gA//gAA///8//gA//gAD///w//gA//wA////g//gA////////A//gA///////8A//gA///////4A//gAf//////wA//gAf//////gA//gAf/////+AA//gAP/////8AA//gAP/////4AA//gAH/////gAA//gAD/////AAA//gAB////8AAA//gAA////wAAA//gAAP///AAAA//gAAD//8AAAA//gAAAP+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/+AAAAAD/wAAB//8AAAAP/wAAB///AAAA//wAAB///wAAB//wAAB///4AAD//wAAB///8AAH//wAAB///+AAP//wAAB///+AAP//wAAB////AAf//wAAB////AAf//wAAB////gAf//wAAB////gA///wAAB////gA///wAAB////gA///w//AAf//wA//4A//AAA//wA//gA//AAAf/wA//gB//gAAf/wA//gB//gAAf/wA//gD//wAA//wA//wH//8AB//wA///////////gA///////////gA///////////gA///////////gAf//////////AAf//////////AAP//////////AAP/////////+AAH/////////8AAH///+/////4AAD///+f////wAAA///8P////gAAAf//4H///+AAAAH//gB///wAAAAAP4AAH/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/wAAAAAAAAAA//wAAAAAAAAAP//wAAAAAAAAB///wAAAAAAAAf///wAAAAAAAH////wAAAAAAA/////wAAAAAAP/////wAAAAAB//////wAAAAAf//////wAAAAH///////wAAAA////////wAAAP////////wAAA///////H/wAAA//////wH/wAAA/////8AH/wAAA/////AAH/wAAA////gAAH/wAAA///4AAAH/wAAA//+AAAAH/wAAA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gAAAAAAAAH/4AAAAAAAAAAH/wAAAAAAAAAAH/wAAAAAAAAAAH/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//8AAA/////+B///AAA/////+B///wAA/////+B///4AA/////+B///8AA/////+B///8AA/////+B///+AA/////+B////AA/////+B////AA/////+B////AA/////+B////gA/////+B////gA/////+B////gA/////+A////gA//gP/gAAB//wA//gf/AAAA//wA//gf/AAAAf/wA//g//AAAAf/wA//g//AAAA//wA//g//gAAA//wA//g//+AAP//wA//g////////gA//g////////gA//g////////gA//g////////gA//g////////AA//gf///////AA//gf//////+AA//gP//////+AA//gH//////8AA//gD//////4AA//gB//////wAA//gA//////AAAAAAAH////8AAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////gAAAAB///////+AAAAH////////gAAAf////////4AAB/////////8AAD/////////+AAH//////////AAH//////////gAP//////////gAP//////////gAf//////////wAf//////////wAf//////////wAf//////////wAf//////////4A//wAD/4AAf/4A//gAH/wAAP/4A//gAH/wAAP/4A//gAP/wAAP/4A//gAP/4AAf/4A//wAP/+AD//4A///wP//////4Af//4P//////wAf//4P//////wAf//4P//////wAf//4P//////wAP//4P//////gAP//4H//////gAH//4H//////AAH//4D/////+AAD//4D/////8AAB//4B/////4AAA//4A/////wAAAP/4AP////AAAAB/4AD///4AAAAAAAAAH/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//AAAAAAAAAAA//gAAAAAAAAAA//gAAAAAAAAAA//gAAAAAAADgA//gAAAAAAP/gA//gAAAAAH//gA//gAAAAB///gA//gAAAAP///gA//gAAAD////gA//gAAAf////gA//gAAB/////gA//gAAP/////gA//gAB//////gA//gAH//////gA//gA///////gA//gD///////gA//gf///////gA//h////////gA//n////////gA//////////gAA/////////AAAA////////wAAAA///////4AAAAA///////AAAAAA//////4AAAAAA//////AAAAAAA/////4AAAAAAA/////AAAAAAAA////8AAAAAAAA////gAAAAAAAA///+AAAAAAAAA///4AAAAAAAAA///AAAAAAAAAA//4AAAAAAAAAA/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//gB///wAAAAP//4H///+AAAA///8P////gAAB///+f////4AAD///+/////8AAH/////////+AAH//////////AAP//////////gAP//////////gAf//////////gAf//////////wAf//////////wAf//////////wA///////////wA//4D//wAB//4A//wB//gAA//4A//gA//gAAf/4A//gA//AAAf/4A//gA//gAAf/4A//wB//gAA//4A///P//8AH//4Af//////////wAf//////////wAf//////////wAf//////////wAf//////////gAP//////////gAP//////////AAH//////////AAD/////////+AAD///+/////8AAB///8f////wAAAf//4P////AAAAH//wD///8AAAAA/+AAf//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH//gAAAAAAAAB///+AA/+AAAAP////gA//wAAAf////wA//4AAB/////4A//8AAD/////8A//+AAD/////+A///AAH/////+A///AAP//////A///gAP//////A///gAf//////A///wAf//////A///wAf//////A///wAf//////A///wA///////AB//4A//4AD//AAP/4A//gAB//AAP/4A//gAA//AAP/4A//gAA/+AAP/4A//gAB/8AAP/4A//wAB/8AAf/4Af//////////wAf//////////wAf//////////wAf//////////wAf//////////wAP//////////gAP//////////gAH//////////AAH/////////+AAD/////////8AAB/////////4AAAf////////wAAAP////////AAAAB///////4AAAAAD/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/AAB/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("EiAnGicnJycnJycnEw=="), 78 + (scale << 8) + (1 << 16)); +}; + +Graphics.prototype.setFontAntonSmall = function(scale) { + // Actual height 53 (52 - 0) + g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAAAAAAAAAAAAAMAAAAAAAAD8AAAAAAAA/8AAAAAAAf/8AAAAAAH//8AAAAAB///8AAAAA////8AAAAP////8AAAD/////8AAB//////8AAf//////8AH///////4A///////+AA///////AAA//////wAAA/////8AAAA////+AAAAA////gAAAAA///4AAAAAA//8AAAAAAA//AAAAAAAA/wAAAAAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/////wAAA//////8AAB//////+AAH///////gAH///////gAP///////wAf///////4Af///////4A////////8A////////8A////////8A//AAAAD/8A/8AAAAA/8A/8AAAAA/8A/8AAAAA/8A/+AAAAB/8A////////8A////////8A////////8Af///////4Af///////4AP///////wAP///////wAH///////gAD///////AAA//////8AAAP/////wAAAAAAAAAAAAAAAAAAAAAAAfwAAAAAAAA/4AAAAAAAA/4AAAAAAAB/wAAAAAAAB/wAAAAAAAD/wAAAAAAAD/gAAAAAAAH///////8AP///////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/4AAAP8AA//4AAA/8AB//4AAH/8AH//4AAP/8AP//4AA//8AP//4AB//8Af//4AD//8Af//4AP//8A///4Af//8A///4A///8A///4D///8A//AAH///8A/8AAP///8A/8AA//+/8A/8AD//8/8A/+Af//w/8A//////g/8A/////+A/8A/////8A/8Af////4A/8Af////wA/8AP////AA/8AP///+AA/8AH///8AA/8AD///wAA/8AA///AAA/8AAP/4AAA/8AAAAAAAAAAAAAAAAAAAAAAH4AAf/gAAA/4AAf/8AAD/4AAf//AAH/4AAf//gAP/4AAf//wAP/4AAf//wAf/4AAf//4Af/4AAf//4A//4AAf//8A//4AAf//8A//4AAP//8A//A/8AB/8A/8A/8AA/8A/8B/8AA/8A/8B/8AA/8A/+D//AB/8A////////8A////////8A////////8Af///////4Af///////4Af///////wAP///////gAH//9////gAD//4///+AAB//wf//4AAAP/AH//gAAAAAAAAAAAAAAAAAAAAAAAAAAAH/wAAAAAAB//wAAAAAAP//wAAAAAD///wAAAAA////wAAAAH////wAAAB/////wAAAf/////wAAD//////wAA///////wAA/////h/wAA////wB/wAA///8AB/wAA///AAB/wAA//gAAB/wAA////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8AAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAP/4AA////4P/+AA////4P//AA////4P//gA////4P//wA////4P//wA////4P//4A////4P//4A////4P//8A////4P//8A////4P//8A/8H/AAB/8A/8H+AAA/8A/8P+AAA/8A/8P+AAA/8A/8P/gAD/8A/8P/////8A/8P/////8A/8P/////8A/8P/////4A/8H/////4A/8H/////wA/8D/////wA/8B/////gA/8A////+AA/8AP///4AAAAAB///AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////wAAAf/////8AAB///////AAH///////gAP///////wAP///////wAf///////4Af///////4A////////8A////////8A////////8A/+AH/AB/8A/8AP+AA/8A/4Af+AA/8A/8Af+AA/8A/8Af/gH/8A//4f////8A//4f////8A//4f////8Af/4f////4Af/4f////4AP/4P////wAP/4P////gAH/4H////AAD/4D///+AAB/4B///4AAAP4AP//gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8AAAAAAAA/8AAAAAAAA/8AAAAAB8A/8AAAAB/8A/8AAAAf/8A/8AAAH//8A/8AAA///8A/8AAH///8A/8AA////8A/8AD////8A/8Af////8A/8B/////8A/8P/////8A/8//////8A////////AA///////AAA//////gAAA/////4AAAA/////AAAAA////4AAAAA////AAAAAA///8AAAAAA///gAAAAAA//+AAAAAAA//wAAAAAAA/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/gD//gAAA//4P//8AAD//8f///AAH//+////gAH///////wAP///////4AP///////8Af///////8Af///////+Af///////+A////////+A//B//AB/+A/+A/+AA/+A/8Af+AA/+A/+Af+AA/+A//A//AB/+A////////+Af///////+Af///////+Af///////8Af///////8AP///////4AH///////4AH//+////wAD//+////AAA//4P//+AAAP/gH//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH//gAfgAAA///8A/8AAB///+A//AAH////A//gAH////g//wAP////g//wAf////w//4Af////w//4A/////w//8A/////w//8A/////w//8A//gP/wA/8A/8AD/wA/8A/8AD/wAf8A/8AD/gA/8A/+AH/AB/8A////////8A////////8A////////8Af///////4Af///////4Af///////wAP///////wAH///////gAD//////+AAA//////4AAAP/////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("DhgeFB4eHh4eHh4eDw=="), 60 + (scale << 8) + (1 << 16)); }; // variables defined from settings -var secondsOnUnlock; -var secondsAlways; +var secondsMode; var secondsColoured; -var dateAsISO; +var secondsWithColon; +var dateOnMain; var dateOnSecs; -var longDate; var weekDay; var upperCase; var vectorFont; @@ -27,15 +31,14 @@ var isBangle1 = (g.getWidth() == 240); /* For development purposes require('Storage').writeJSON(SETTINGSFILE, { - secondsOnUnlock: false, - secondsAlways: false, + secondsMode: "Always", // "Never", "Unlocked", "Always" secondsColoured: true, - dateAsISO: false, - dateOnSecs: true, - longDate: true, + secondsWithColon: true, + dateOnMain: "Long", // "Short", "Long", "ISO8601" + dateOnSecs: "Year", // "No", "Year", "Weekday", LEGACY: true/false weekDay: true, - upperCase: false, - vectorFont: false, + upperCase: true, + vectorFont: true, }); /* */ @@ -51,15 +54,20 @@ function def(value, def) { // Load settings function loadSettings() { var settings = require('Storage').readJSON(SETTINGSFILE, true) || {}; - secondsOnUnlock = def(settings.secondsOnUnlock, false); - secondsAlways = def(settings.secondsAlways, false); - secondsColoured = def(settings.secondsColoured, false); - dateAsISO = def(settings.dateAsISO, false); - dateOnSecs = def(settings.dateOnSecs, true); - longDate = def(settings.longDate, true); + secondsMode = def(settings.secondsMode, "Never"); + secondsColoured = def(settings.secondsColoured, true); + secondsWithColon = def(settings.secondsWithColon, true); + dateOnMain = def(settings.dateOnMain, "Long"); + dateOnSecs = def(settings.dateOnSecs, "Year"); weekDay = def(settings.weekDay, true); upperCase = def(settings.upperCase, true); vectorFont = def(settings.vectorFont, false); + + // Legacy + if (dateOnSecs === true) + dateOnSecs = "Year"; + if (dateOnSecs === false) + dateOnSecs = "No"; } // schedule a draw for the next second or minute @@ -73,7 +81,7 @@ function queueDraw() { function updateState() { if (Bangle.isLCDOn()) { - if ((secondsOnUnlock && !Bangle.isLocked()) || secondsAlways) { + if ((secondsMode === "Unlocked" && !Bangle.isLocked()) || secondsMode === "Always") { secondsScreen = true; queueMillis = 1000; } else { @@ -98,28 +106,33 @@ function doColor() { // Actually draw the watch face function draw() { var x = g.getWidth() / 2; - var y = g.getHeight() / 2 - (secondsOnUnlock || secondsAlways ? 24 : (vectorFont ? 12 : 0)); + var y = g.getHeight() / 2 - (secondsMode !== "Never" ? 24 : (vectorFont ? 12 : 0)); g.reset(); - g.clearRect(0, 24, g.getWidth(), g.getHeight()); // clear whole background + /* This is to mark the widget areas during development. + g.setColor("#888") + .fillRect(0, 0, g.getWidth(), 23) + .fillRect(0, g.getHeight() - 23, g.getWidth(), g.getHeight()).reset(); + /* */ + g.clearRect(0, 24, g.getWidth(), g.getHeight() - 24); // clear whole background (w/o widgets) var date = new Date(); // Actually the current date, this one is shown var timeStr = require("locale").time(date, 1); // Hour and minute g.setFontAlign(0, 0).setFont("Anton").drawString(timeStr, x, y); // draw time if (secondsScreen) { - y += 76; - var secStr = ":" + ("0" + date.getSeconds()).substr(-2); + y += 65; + var secStr = (secondsWithColon ? ":" : "") + ("0" + date.getSeconds()).substr(-2); if (doColor()) g.setColor(0, 0, 1); - g.setFont("Anton"); - if (dateOnSecs) { // A bit of a complex drawing with seconds on the right and date on the left + g.setFont("AntonSmall"); + if (dateOnSecs !== "No") { // A bit of a complex drawing with seconds on the right and date on the left g.setFontAlign(1, 0).drawString(secStr, g.getWidth() - (isBangle1 ? 32 : 2), y); // seconds - y -= (vectorFont ? 20 : 16); - x = g.getWidth() / 4 + (isBangle1 ? 12 : -6); - var dateStr2 = (dateAsISO ? isoStr(date) : require("locale").date(date, 1)); + y -= (vectorFont ? 15 : 13); + x = g.getWidth() / 4 + (isBangle1 ? 12 : 4) + (secondsWithColon ? 0 : g.stringWidth(":") / 2); + var dateStr2 = (dateOnMain === "ISO8601" ? isoStr(date) : require("locale").date(date, 1)); var year; var md; var yearfirst; if (dateStr2.match(/\d\d\d\d$/)) { // formatted date ends with year - year = dateStr2.slice(-4); + year = (dateOnSecs === "Year" ? dateStr2.slice(-4) : require("locale").dow(date, 1)); md = dateStr2.slice(0, -4); if (!md.endsWith(".")) // keep separator before the year only if it is a dot (31.12. but 31/12) md = md.slice(0, -1); @@ -127,10 +140,12 @@ function draw() { } else { // formatted date begins with year if (!dateStr2.match(/^\d\d\d\d/)) // if year position cannot be detected... dateStr2 = isoStr(date); // ...use ISO date format instead - year = dateStr2.slice(0, 4); + year = (dateOnSecs === "Year" ? dateStr2.slice(0, 4) : require("locale").dow(date, 1)); md = dateStr2.slice(5); // never keep separator directly after year yearfirst = true; } + if (dateOnSecs === "Weekday" && upperCase) + year = year.toUpperCase(); g.setFontAlign(0, 0); if (vectorFont) g.setFont("Vector", 24); @@ -144,8 +159,8 @@ function draw() { g.setFontAlign(0, 0).drawString(secStr, x, y); // Just the seconds centered } } else { // No seconds screen: Show date and optionally day of week - y += (vectorFont ? 50 : (secondsOnUnlock || secondsAlways) ? 52 : 40); - var dateStr = (dateAsISO ? isoStr(date) : require("locale").date(date, (longDate ? 0 : 1))); + y += (vectorFont ? 50 : (secondsMode !== "Never") ? 52 : 40); + var dateStr = (dateOnMain === "ISO8601" ? isoStr(date) : require("locale").date(date, (dateOnMain === "Long" ? 0 : 1))); if (upperCase) dateStr = dateStr.toUpperCase(); g.setFontAlign(0, 0); diff --git a/apps/antonclk/settings.js b/apps/antonclk/settings.js index 3af9df292..08fde512e 100644 --- a/apps/antonclk/settings.js +++ b/apps/antonclk/settings.js @@ -11,28 +11,34 @@ require('Storage').writeJSON(FILE, settings); } + // Helper method which uses int-based menu item for set of string values + function stringItems(startvalue, writer, values) { + return { + value: (startvalue === undefined ? 0 : values.indexOf(startvalue)), + format: v => values[v], + min: 0, + max: values.length - 1, + wrap: true, + step: 1, + onchange: v => { + writer(values[v]); + writeSettings(); + } + }; + } + + // Helper method which breaks string set settings down to local settings object + function stringInSettings(name, values) { + return stringItems(settings[name], v => settings[name] = v, values); + } + var mainmenu = { "": { "title": "Anton clock" }, "< Back": () => back(), "Seconds...": () => E.showMenu(secmenu), - "ISO8601 date": { - value: (settings.dateAsISO !== undefined ? settings.dateAsISO : false), - format: v => v ? "On" : "Off", - onchange: v => { - settings.dateAsISO = v; - writeSettings(); - } - }, - "Long date": { - value: (settings.longDate !== undefined ? settings.longDate : true), - format: v => v ? "On" : "Off", - onchange: v => { - settings.longDate = v; - writeSettings(); - } - }, + "Date": stringInSettings("dateOnMain", ["Short", "Long", "ISO8601"]), "Show Weekday": { value: (settings.weekDay !== undefined ? settings.weekDay : true), format: v => v ? "On" : "Off", @@ -65,23 +71,16 @@ "title": "Show seconds..." }, "< Back": () => E.showMenu(mainmenu), - "Always": { - value: (settings.secondsAlways !== undefined ? settings.secondsAlways : false), + "Show": stringInSettings("secondsMode", ["Never", "Unlocked", "Always"]), + "With \":\"": { + value: (settings.secondsWithColon !== undefined ? settings.secondsWithColon : false), format: v => v ? "On" : "Off", onchange: v => { - settings.secondsAlways = v; + settings.secondsWithColon = v; writeSettings(); } }, - "If unlocked": { - value: (settings.secondsOnUnlock !== undefined ? settings.secondsOnUnlock : false), - format: v => v ? "On" : "Off", - onchange: v => { - settings.secondsOnUnlock = v; - writeSettings(); - } - }, - "Coloured": { + "Color": { value: (settings.secondsColoured !== undefined ? settings.secondsColoured : false), format: v => v ? "On" : "Off", onchange: v => { @@ -89,14 +88,7 @@ writeSettings(); } }, - "With date": { - value: (settings.dateOnSecs !== undefined ? settings.dateOnSecs : false), - format: v => v ? "On" : "Off", - onchange: v => { - settings.dateOnSecs = v; - writeSettings(); - } - } + "Date": stringInSettings("dateOnSecs", ["No", "Year", "Weekday"]) }; // Actually display the menu From ebc7005e372cbd03b6922fcec13d5f8010f0a802 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Wed, 5 Jan 2022 21:27:21 +0000 Subject: [PATCH 211/489] Flipper: switch between light and dark theme and vice versa --- apps.json | 15 ++++++++++++++ apps/flipper/flipper.app.js | 39 +++++++++++++++++++++++++++++++++++ apps/flipper/flipper.icon.js | 1 + apps/flipper/flipper.png | Bin 0 -> 644 bytes 4 files changed, 55 insertions(+) create mode 100644 apps/flipper/flipper.app.js create mode 100644 apps/flipper/flipper.icon.js create mode 100644 apps/flipper/flipper.png diff --git a/apps.json b/apps.json index ebafa9c97..a32522fa2 100644 --- a/apps.json +++ b/apps.json @@ -5427,5 +5427,20 @@ {"name":"puzzle15.img","url":"puzzle15.app-icon.js","evaluate":true} ], "data": [{"name":"puzzle15.json"}] + }, + { + "id": "flipper", + "name": "flipper", + "version": "0.01", + "description": "Switch between dark and light theme and vice versa, combine with pattern launcher and swipe to flip." + "icon": "flipper.png", + "type": "app", + "tags": "game", + "supports": ["BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"flipper.app.js","url":"flipper.app.js"}, + {"name":"flipper.img","url":"flipper.app-icon.js","evaluate":true} + ] } ] diff --git a/apps/flipper/flipper.app.js b/apps/flipper/flipper.app.js new file mode 100644 index 000000000..2e7d3551c --- /dev/null +++ b/apps/flipper/flipper.app.js @@ -0,0 +1,39 @@ +const storage = require('Storage'); +let settings = storage.readJSON('setting.json', 1); + +function cl(x) { return g.setColor(x).getColor(); } + +function upd(th) { + g.theme = th; + settings.theme = th; + storage.write('setting.json', settings); + delete g.reset; + g._reset = g.reset; + g.reset = function(n) { return g._reset().setColor(th.fg).setBgColor(th.bg); }; + g.clear = function(n) { if (n) g.reset(); return g.clearRect(0,0,g.getWidth(),g.getHeight()); }; + g.clear(1); +}; + +function flipTheme() { + if (!g.theme.dark) { + upd({ + fg:cl("#fff"), bg:cl("#000"), + fg2:cl("#0ff"), bg2:cl("#000"), + fgH:cl("#fff"), bgH:cl("#00f"), + dark:true + }); + } else { + upd({ + fg:cl("#000"), bg:cl("#fff"), + fg2:cl("#000"), bg2:cl("#cff"), + fgH:cl("#000"), bgH:cl("#0ff"), + dark:false + }); + } +} + +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +flipTheme(); +setTimeout(load, 20); diff --git a/apps/flipper/flipper.icon.js b/apps/flipper/flipper.icon.js new file mode 100644 index 000000000..16331c09e --- /dev/null +++ b/apps/flipper/flipper.icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4X/AAO/mMUzs975K+ggLKysUAYNVqoLFitUoAKBqtQBYkJBIQABqwLEgQLEqtABggJDqkVBaoNCBZQwEgILWgoJENYsVBIcVBYpDEgpSIBYMBKQg6CuogCBY1UgoLCXAQLDqAsDBYhSBqEJHAoLDoEBcQ4LBEwILIMooLdIg4LaVoyaGERLcFao4LIdRAACYYUQBY5RKAH4Ar")); diff --git a/apps/flipper/flipper.png b/apps/flipper/flipper.png new file mode 100644 index 0000000000000000000000000000000000000000..b91543070be72c6a53a11aabec8d779780d2bc11 GIT binary patch literal 644 zcmV-~0(-0O`Ea$39hd$rSFgp06=YM0Il{S zNt_9?Wo4B{?^|t~pJ#}Zrg02ZoGP${lF_V|5I_%73ZmJuT0&*lfPjaY0kbl|Sb3wL z2iZV)c;Qk98Bz=!?CoNy@mQ250PlrNr2`;lAs6C1E3GII=pLkuXTT=w$hHTa{YLQ` z0?xEdlzJYJ3F=Idm0(>vK^Pg(9sT9im&`Mr3Ts-00mn0N`_RDC^9pvhHpzW_4_+18 zL9D7-+xz_(>FX7?nT)LIEeMMfc@TeKdJw5k&EV#IQrPAaCrd~q@cQg1x6LKi2J!@! zbsCWl%(i2A&pkZvWCw5cpu zQ52!tv*A*c5t$$kc$hi6inbEUj%}3*5RIkQdBFF-Ff#srA^Yik31Y^IS-VB@>t~>A ez&Bk3zIg*Y=-nc5eyO+s0000 Date: Wed, 5 Jan 2022 22:04:50 +0000 Subject: [PATCH 212/489] Flipper: switch between light and dark theme and vice versa --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index a32522fa2..07d9c02ae 100644 --- a/apps.json +++ b/apps.json @@ -5432,7 +5432,7 @@ "id": "flipper", "name": "flipper", "version": "0.01", - "description": "Switch between dark and light theme and vice versa, combine with pattern launcher and swipe to flip." + "description": "Switch between dark and light theme and vice versa, combine with pattern launcher and swipe to flip.", "icon": "flipper.png", "type": "app", "tags": "game", From 71228efb4ba118f8c4c2145174008ca02f329b1c Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Wed, 5 Jan 2022 23:12:16 +0100 Subject: [PATCH 213/489] Update gps-info.js Resolve one FIFO_FULL case and exit App with button press --- apps/gpsinfo/gps-info.js | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/apps/gpsinfo/gps-info.js b/apps/gpsinfo/gps-info.js index a16d4a04e..467d12a95 100644 --- a/apps/gpsinfo/gps-info.js +++ b/apps/gpsinfo/gps-info.js @@ -19,6 +19,7 @@ var lastFix = { var SATinView = 0; var nofBD = 0; var nofGP = 0; +var listenerGPSraw = 1; function formatTime(now) { if (now == undefined) { @@ -93,6 +94,10 @@ function onGPS(fix) { } lastFix = fix; if (fix.fix) { + if (listenerGPSraw == 1) { + Bangle.removeListener('GPS-raw', onGPSraw); + listenerGPSraw = 0; + } var locale = require("locale"); var satellites = fix.satellites; var maidenhead = getMaidenHead(fix.lat,fix.lon); @@ -104,6 +109,10 @@ function onGPS(fix) { layout.sat.label = "Satellites: "+satellites; layout.maidenhead.label = "Maidenhead: "+maidenhead; } else { + if (listenerGPSraw == 0) { + Bangle.on('GPS-raw', onGPSraw); + listenerGPSraw = 1; + } layout.sat.label = fix.satellites; layout.progress.label = "in view: " + SATinView; } @@ -111,15 +120,26 @@ function onGPS(fix) { } function onGPSraw(nmea) { - if (nmea.slice(3,6) == "GSV") { - // console.log(nmea); - if (nmea.slice(0,7) == "$BDGSV,") nofBD = Number(nmea.slice(11,13)); - if (nmea.slice(0,7) == "$GPGSV,") nofGP = Number(nmea.slice(11,13)); - SATinView = nofBD + nofGP; - } + if (nmea.slice(0,7) == "$BDGSV,") nofBD = Number(nmea.slice(11,13)); + if (nmea.slice(0,7) == "$GPGSV,") nofGP = Number(nmea.slice(11,13)); + SATinView = nofBD + nofGP; } + Bangle.loadWidgets(); Bangle.drawWidgets(); Bangle.on('GPS', onGPS); Bangle.on('GPS-raw', onGPSraw); + +function exitApp() { + Bangle.setGPSPower(0, "app"); + Bangle.removeListener('GPS-raw', onGPSraw); + Bangle.removeListener('GPS', onGPS); + load(); +} + +setWatch(_=>exitApp(), BTN1); +if (global.BTN2) { + setWatch(_=>exitApp(), BTN2); + setWatch(_=>exitApp(), BTN3); +} From b2f844f32704d1863f18409f4da9898cef21f416 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Wed, 5 Jan 2022 23:15:27 +0100 Subject: [PATCH 214/489] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index ebafa9c97..7e3d29cdc 100644 --- a/apps.json +++ b/apps.json @@ -1501,7 +1501,7 @@ { "id": "gpsinfo", "name": "GPS Info", - "version": "0.06", + "version": "0.07", "description": "An application that displays information about altitude, lat/lon, satellites and time", "icon": "gps-info.png", "type": "app", From 97200f4ac566881ffa01b245c0da6cab61d08904 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Wed, 5 Jan 2022 23:16:33 +0100 Subject: [PATCH 215/489] Update ChangeLog --- apps/gpsinfo/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/gpsinfo/ChangeLog b/apps/gpsinfo/ChangeLog index 3ff284cb8..284ff7999 100644 --- a/apps/gpsinfo/ChangeLog +++ b/apps/gpsinfo/ChangeLog @@ -3,3 +3,4 @@ 0.04: Add Maidenhead readout of GPS location 0.05: Refactor to use 'layout' library for multi-device support 0.06: Added number of satellites in view and fixed crash with GPS time +0.07: Resolve one FIFO_FULL case and exit App with button press From f167ab829bf4f6fc1e78437cccbfadcfc984310a Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Wed, 5 Jan 2022 23:17:04 +0100 Subject: [PATCH 216/489] Update ChangeLog --- apps/gpsinfo/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/gpsinfo/ChangeLog b/apps/gpsinfo/ChangeLog index 284ff7999..a3a2fc89a 100644 --- a/apps/gpsinfo/ChangeLog +++ b/apps/gpsinfo/ChangeLog @@ -2,5 +2,5 @@ 0.03: Show number of satellites while waiting for fix 0.04: Add Maidenhead readout of GPS location 0.05: Refactor to use 'layout' library for multi-device support -0.06: Added number of satellites in view and fixed crash with GPS time +0.06: Add number of satellites in view and fix crash with GPS time 0.07: Resolve one FIFO_FULL case and exit App with button press From c5f77a06926cabc0fe7c7be4d503bd9c0b0e79e1 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Wed, 5 Jan 2022 22:31:21 +0000 Subject: [PATCH 217/489] Flipper: switch between light and dark theme and vice versa --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 07d9c02ae..e643d1c7d 100644 --- a/apps.json +++ b/apps.json @@ -5440,7 +5440,7 @@ "allow_emulator": true, "storage": [ {"name":"flipper.app.js","url":"flipper.app.js"}, - {"name":"flipper.img","url":"flipper.app-icon.js","evaluate":true} + {"name":"flipper.img","url":"flipper.icon.js","evaluate":true} ] } ] From 4f4cb8aba5eae7542b1f8b5ae7990758592ffc45 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Wed, 5 Jan 2022 22:36:45 +0000 Subject: [PATCH 218/489] Flipper: switch between light and dark theme and vice versa --- apps/flipper/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/flipper/ChangeLog diff --git a/apps/flipper/ChangeLog b/apps/flipper/ChangeLog new file mode 100644 index 000000000..9db0e26c5 --- /dev/null +++ b/apps/flipper/ChangeLog @@ -0,0 +1 @@ +0.01: first release From 1a97767aa32e3c08fe6ee1e7b57be7b639aac5a5 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 15:24:26 -0800 Subject: [PATCH 219/489] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index bd7f77cef..a52355909 100644 --- a/apps.json +++ b/apps.json @@ -5162,7 +5162,7 @@ { "id": "promenu", "name": "Pro Menu", - "version": "0.01", + "version": "0.02", "description": "Replace the built in menu function. Supports Bangle.js 1 and Bangle.js 2.", "icon": "icon.png", "type": "boot", From 3aada0243dbe45da9b43e38aa40f869a751863c3 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 15:25:39 -0800 Subject: [PATCH 220/489] Update ChangeLog --- apps/promenu/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/promenu/ChangeLog b/apps/promenu/ChangeLog index 5560f00bc..8d214723c 100644 --- a/apps/promenu/ChangeLog +++ b/apps/promenu/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Add Bangle.js 2 Support! From 73e3378d25026ed7a268308f031aa8a081d170ba Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 15:29:05 -0800 Subject: [PATCH 221/489] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index a52355909..051764016 100644 --- a/apps.json +++ b/apps.json @@ -5171,7 +5171,7 @@ "screenshots": [{"url":"pro-menu-screenshot.png"}], "storage": [ {"name":"promenu.boot.js","url":"boot.js","supports": ["BANGLEJS"]}, - {"name":"promenu.bootb2.js","url":"boot.js","supports": ["BANGLEJS2"]}, + {"name":"promenu.boot.js","url":"bootb2.js","supports": ["BANGLEJS2"]}, {"name":"promenu.img","url":"promenuIcon.js","evaluate":true} ] }, From d54692117792802f2433922d3df61aac1361b65d Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 15:35:57 -0800 Subject: [PATCH 222/489] fix text overlapping text issue --- apps/promenu/bootb2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/promenu/bootb2.js b/apps/promenu/bootb2.js index 096745f34..c84e0d894 100644 --- a/apps/promenu/bootb2.js +++ b/apps/promenu/bootb2.js @@ -74,7 +74,7 @@ E.showMenu = function(items) { g.setFontAlign(-1,-1); var v = item.value; v = loc.translate(""+v); - if(loc.translate(name).length >= 19-v.length && "object" == typeof item){ + if(loc.translate(name).length >= 17-v.length && "object" == typeof item){ if (item.format) v=item.format(v); g.drawString(loc.translate(name).substring(0, 12-v.length)+"...",x+3.7,iy+2.7); }else{ From d330d6dfd568162eb4ca3dce1978e0963420a04f Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 15:41:48 -0800 Subject: [PATCH 223/489] remove exclamation from change log --- apps/promenu/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/promenu/ChangeLog b/apps/promenu/ChangeLog index 8d214723c..b7287cc80 100644 --- a/apps/promenu/ChangeLog +++ b/apps/promenu/ChangeLog @@ -1,2 +1,2 @@ 0.01: New App! -0.02: Add Bangle.js 2 Support! +0.02: Add Bangle.js 2 Support From 84174a270b695e20f01fab6de5f37920f6422e24 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Wed, 5 Jan 2022 23:45:22 +0000 Subject: [PATCH 224/489] Flipper: added README --- apps.json | 2 ++ apps/flipper/README.md | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 apps/flipper/README.md diff --git a/apps.json b/apps.json index e643d1c7d..e9c4a9f6a 100644 --- a/apps.json +++ b/apps.json @@ -5433,6 +5433,8 @@ "name": "flipper", "version": "0.01", "description": "Switch between dark and light theme and vice versa, combine with pattern launcher and swipe to flip.", + "readme":"README.md", + "screenshots": [{"url":"flipper.png"}], "icon": "flipper.png", "type": "app", "tags": "game", diff --git a/apps/flipper/README.md b/apps/flipper/README.md new file mode 100644 index 000000000..88025b8b2 --- /dev/null +++ b/apps/flipper/README.md @@ -0,0 +1,20 @@ +# Flipper + +![](flipper.png) + + *A utility to switch from the dark to the light theme and vice versa* + +* If the current theme is dark it will switch to the light theme +* If the current theme is light it will switch to the dark theme +* Combine with the awesome pattern launcher and it saves loads of time + + +## Demo Video + +There's no screenshot but there is a [demo video.](https://espruino.microco.sm/api/v1/files/9caa1afef7e4cce1d9b518af2dd271f1a57c5ecc.mp4) + +## Future Enhancements + +* Nothing left to add + +Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) From d305de0bdc274c8c82a4a76556c506b9c6bfcff8 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 01:59:22 +0100 Subject: [PATCH 225/489] Update widget.js Increase screen update rate when charging, as requested by issue https://github.com/espruino/BangleApps/issues/1137 --- apps/widbatpc/widget.js | 59 ++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/apps/widbatpc/widget.js b/apps/widbatpc/widget.js index 5386ffe22..529923386 100644 --- a/apps/widbatpc/widget.js +++ b/apps/widbatpc/widget.js @@ -1,6 +1,9 @@ (function(){ + const intervalLow = 60000; // update time when not charging + const intervalHigh = 2000; // update time when charging + let COLORS = {}; - + if (process.env.HWVERSION == 1) { COLORS = { 'white': -1, // White @@ -17,13 +20,13 @@ 'high': "#0f0", // Green 'ok': "#ff0", // Orange 'low': "#f00", // Red - }; + }; } - const SETTINGS_FILE = 'widbatpc.json' + const SETTINGS_FILE = 'widbatpc.json'; - let settings + let settings; function loadSettings() { - settings = require('Storage').readJSON(SETTINGS_FILE, 1) || {} + settings = require('Storage').readJSON(SETTINGS_FILE, 1) || {}; const DEFAULTS = { 'color': 'By Level', 'percentage': true, @@ -32,17 +35,17 @@ 'alwaysoncharge': false, }; Object.keys(DEFAULTS).forEach(k=>{ - if (settings[k]===undefined) settings[k]=DEFAULTS[k] + if (settings[k]===undefined) settings[k]=DEFAULTS[k]; }); } function setting(key) { - if (!settings) { loadSettings() } + if (!settings) { loadSettings(); } return settings[key]; } const levelColor = (l) => { // "charging" is very bright -> percentage is hard to read, "high" is ok(ish) - const green = setting('percentage') ? COLORS.high : COLORS.charging + const green = setting('percentage') ? COLORS.high : COLORS.charging; switch (setting('color')) { case 'Monochrome': return COLORS.white; // no chance of reading the percentage here :-( case 'Green': return green; @@ -59,10 +62,11 @@ if (l >= 15) return COLORS.ok; return COLORS.low; } - } + }; const chargerColor = () => { - return (setting('color') === 'Monochrome') ? COLORS.white : COLORS.charging - } + return (setting('color') === 'Monochrome') ? COLORS.white : COLORS.charging; + }; + // sets width, returns true if it changed function setWidth() { var w = 40; @@ -77,6 +81,7 @@ WIDGETS["batpc"].width = w; return changed; } + function draw() { // if hidden, don't draw if (!WIDGETS["batpc"].width) return; @@ -106,11 +111,11 @@ if (!setting('percentage')) { return; } - let gfx = g + let gfx = g; if (setting('color') === 'Monochrome') { // draw text inverted on battery level gfx = Graphics.createCallback(g.getWidth(),g.getHeight(), 1, - (x,y) => {g.setPixel(x,y,x<=xl?0:-1)}) + (x,y) => {g.setPixel(x,y,x<=xl?0:-1);}); } gfx.setFontAlign(-1,-1); if (l >= 100) { @@ -122,19 +127,24 @@ gfx.drawString(l, x + 6, y + 4); } } + // reload widget, e.g. when settings have changed function reload() { - loadSettings() + loadSettings(); // need to redraw all widgets, because changing the "charger" setting // can affect the width and mess with the whole widget layout - setWidth() + setWidth(); g.clear(); Bangle.drawWidgets(); } + // update widget - redraw just widget, or all widgets if size changed function update() { if (setWidth()) Bangle.drawWidgets(); else WIDGETS["batpc"].draw(); + + if (Bangle.isCharging()) changeInterval(id, intervalHigh); + else changeInterval(id, intervalLow); } Bangle.on('charging',function(charging) { @@ -142,20 +152,13 @@ update(); g.flip(); }); - var batteryInterval; + Bangle.on('lcdPower', function(on) { - if (on) { - update(); - // refresh once a minute if LCD on - if (!batteryInterval) - batteryInterval = setInterval(update, 60000); - } else { - if (batteryInterval) { - clearInterval(batteryInterval); - batteryInterval = undefined; - } - } + if (on) update(); }); + + var id = setInterval(()=>WIDGETS["batpc"].draw(), intervalLow); + WIDGETS["batpc"]={area:"tr",width:40,draw:draw,reload:reload}; setWidth(); -})() +})(); From d343de172ea4a4a8e8a7b35c1d61af1435ac957e Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 02:01:54 +0100 Subject: [PATCH 226/489] Update ChangeLog --- apps/widbatpc/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/widbatpc/ChangeLog b/apps/widbatpc/ChangeLog index 273e611a4..e70093659 100644 --- a/apps/widbatpc/ChangeLog +++ b/apps/widbatpc/ChangeLog @@ -12,3 +12,4 @@ 0.13: Fillbar setting added, see README 0.14: Fix drawing the bar when charging 0.15: Added option to always display the icon when charging (useful if 'hide if charge greater than' is enabled) +0.16: Increase screen update rate when charging From 50ae67fcd7127d52ebc7d1eda834a02e91e44da2 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 02:03:30 +0100 Subject: [PATCH 227/489] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 7e3d29cdc..e37326674 100644 --- a/apps.json +++ b/apps.json @@ -936,7 +936,7 @@ "id": "widbatpc", "name": "Battery Level Widget (with percentage)", "shortName": "Battery Widget", - "version": "0.15", + "version": "0.16", "description": "Show the current battery level and charging status in the top right of the clock, with charge percentage", "icon": "widget.png", "type": "widget", From b9dcd0a8755dcbd463c45df3aa183f07dfc0c955 Mon Sep 17 00:00:00 2001 From: numerist Date: Wed, 5 Jan 2022 21:09:15 -0500 Subject: [PATCH 228/489] Update README.md This description now fits both Bangle watch versions, 1 and 2. --- apps/doztime/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/doztime/README.md b/apps/doztime/README.md index 075b2f66a..2f5b04780 100644 --- a/apps/doztime/README.md +++ b/apps/doztime/README.md @@ -11,4 +11,4 @@ The year itself begins on the December solstice. Because that always happens, th The epoch (year numbering) begins in the last year when the perihelion coincided with the June solstice, near the beginning of the Holocene era. That astronomical basis makes the calendar free from politics, religion, or geography. -While the year number remains cardinal, BTN5 toggles between cardinal and ordinal for the rest of the calendar segments. BTN4 adds or removes a quickly changing digit to or from the clock. +While the year number remains cardinal, tapping on the right side of the watch face toggles between cardinal and ordinal for the rest of the calendar segments. Tapping on the left adds or removes a quickly changing digit to or from the clock. From 670c232f28e0c746ae8f356c81a8f65e4fef340f Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:01 +0100 Subject: [PATCH 229/489] Create LICENSE --- apps/colorful_clock/LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 apps/colorful_clock/LICENSE diff --git a/apps/colorful_clock/LICENSE b/apps/colorful_clock/LICENSE new file mode 100644 index 000000000..7487dd5da --- /dev/null +++ b/apps/colorful_clock/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Andreas Rozek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 49bee5390bff6e8c03710fb094227b0f5b45f5e9 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:06 +0100 Subject: [PATCH 230/489] Create LICENSE --- apps/themesetter/LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 apps/themesetter/LICENSE diff --git a/apps/themesetter/LICENSE b/apps/themesetter/LICENSE new file mode 100644 index 000000000..7487dd5da --- /dev/null +++ b/apps/themesetter/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Andreas Rozek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 754e752a8bd292bdcccf73f3eb8a7ef172cd99cb Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:09 +0100 Subject: [PATCH 231/489] Create LICENSE --- apps/simple_clock/LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 apps/simple_clock/LICENSE diff --git a/apps/simple_clock/LICENSE b/apps/simple_clock/LICENSE new file mode 100644 index 000000000..7487dd5da --- /dev/null +++ b/apps/simple_clock/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Andreas Rozek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 117348cb16f74003180f4474c125efca0523e98e Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:17 +0100 Subject: [PATCH 232/489] Create app.js --- apps/configurable_clock/app.js | 1336 ++++++++++++++++++++++++++++++++ 1 file changed, 1336 insertions(+) create mode 100644 apps/configurable_clock/app.js diff --git a/apps/configurable_clock/app.js b/apps/configurable_clock/app.js new file mode 100644 index 000000000..19dc363e4 --- /dev/null +++ b/apps/configurable_clock/app.js @@ -0,0 +1,1336 @@ + let Layout = require('Layout'); + + let Caret = require("heatshrink").decompress(atob("hEUgMAsFgmEwjEYhkMg0GAYIHBBYIPBgAA==")); + + let ScreenWidth = g.getWidth(), CenterX; + let ScreenHeight = g.getHeight(), CenterY, outerRadius; + + Bangle.loadWidgets(); + +/**** updateClockFaceSize ****/ + + function updateClockFaceSize () { + CenterX = ScreenWidth/2; + CenterY = ScreenHeight/2; + + outerRadius = Math.min(CenterX,CenterY) * 0.9; + + if (global.WIDGETS == null) { return; } + + let WidgetLayouts = { + tl:{ x:0, y:0, Direction:0 }, + tr:{ x:ScreenWidth-1, y:0, Direction:1 }, + bl:{ x:0, y:ScreenHeight-24, Direction:0 }, + br:{ x:ScreenWidth-1, y:ScreenHeight-24, Direction:1 } + }; + + for (let Widget of WIDGETS) { + let WidgetLayout = WidgetLayouts[Widget.area]; // reference, not copy! + if (WidgetLayout == null) { continue; } + + Widget.x = WidgetLayout.x - WidgetLayout.Direction * Widget.width; + Widget.y = WidgetLayout.y; + + WidgetLayout.x += Widget.width * (1-2*WidgetLayout.Direction); + } + + let x,y, dx,dy; + let cx = CenterX, cy = CenterY, r = outerRadius, r2 = r*r; + + x = WidgetLayouts.tl.x; y = WidgetLayouts.tl.y+24; dx = x - cx; dy = y - cy; + if (dx*dx + dy*dy < r2) { + cy = CenterY + 12; dy = y - cy; r2 = dx*dx + dy*dy; r = Math.sqrt(r2); + } + + x = WidgetLayouts.tr.x; y = WidgetLayouts.tr.y+24; dx = x - cx; dy = y - cy; + if (dx*dx + dy*dy < r2) { + cy = CenterY + 12; dy = y - cy; r2 = dx*dx + dy*dy; r = Math.sqrt(r2); + } + + x = WidgetLayouts.bl.x; y = WidgetLayouts.bl.y; dx = x - cx; dy = y - cy; + if (dx*dx + dy*dy < r2) { + cy = CenterY - 12; dy = y - cy; r2 = dx*dx + dy*dy; r = Math.sqrt(r2); + } + + x = WidgetLayouts.br.x; y = WidgetLayouts.br.y; dx = x - cx; dy = y - cy; + if (dx*dx + dy*dy < r2) { + cy = CenterY - 12; dy = y - cy; r2 = dx*dx + dy*dy; r = Math.sqrt(r2); + } + + CenterX = cx; CenterY = cy; outerRadius = r * 0.9; + } + + updateClockFaceSize(); + +/**** custom version of Bangle.drawWidgets (does not clear the widget areas) ****/ + + Bangle.drawWidgets = function () { + var w = g.getWidth(), h = g.getHeight(); + + var pos = { + tl:{x:0, y:0, r:0, c:0}, // if r==1, we're right->left + tr:{x:w-1, y:0, r:1, c:0}, + bl:{x:0, y:h-24, r:0, c:0}, + br:{x:w-1, y:h-24, r:1, c:0} + }; + + if (global.WIDGETS) { + for (var wd of WIDGETS) { + var p = pos[wd.area]; + if (!p) continue; + + wd.x = p.x - p.r*wd.width; + wd.y = p.y; + + p.x += wd.width*(1-2*p.r); + p.c++; + } + + g.reset(); // also loads the current theme + + if (pos.tl.c || pos.tr.c) { + g.setClipRect(0,h-24,w-1,h-1); + g.reset(); // also (re)loads the current theme + } + + if (pos.bl.c || pos.br.c) { + g.setClipRect(0,h-24,w-1,h-1); + g.reset(); // also (re)loads the current theme + } + + try { + for (wd of WIDGETS) { + g.clearRect(wd.x,wd.y, wd.x+wd.width-1,23); + wd.draw(wd); + } + } catch (e) { print(e); } + } + }; + +/**** EventConsumerAtPoint ****/ + + let activeLayout; + + function EventConsumerAtPoint (HandlerName, x,y) { + let Layout = (activeLayout || {}).l; + if (Layout == null) { return; } + + function ConsumerIn (Control) { + if ( + (x < Control.x) || (x >= Control.x + Control.w) || + (y < Control.y) || (y >= Control.y + Control.h) + ) { return undefined; } + + if (typeof Control[HandlerName] === 'function') { return Control; } + + if (Control.c != null) { + let ControlList = Control.c; + for (let i = 0, l = ControlList.length; i < l; i++) { + let Consumer = ConsumerIn(ControlList[i]); + if (Consumer != null) { return Consumer; } + } + } + + return undefined; + } + + return ConsumerIn(Layout); + } + +/**** dispatchTouchEvent ****/ + + function dispatchTouchEvent (DefaultHandler) { + function handleTouchEvent (Button, xy) { + if (activeLayout == null) { + if (typeof DefaultHandler === 'function') { + DefaultHandler(); + } + } else { + let Control = EventConsumerAtPoint('onTouch', xy.x,xy.y); + if (Control != null) { + Control.onTouch(Control, Button, xy); + } + } + } + Bangle.on('touch',handleTouchEvent); + } + dispatchTouchEvent(); + +/**** dispatchStrokeEvent ****/ + + function dispatchStrokeEvent (DefaultHandler) { + function handleStrokeEvent (Coordinates) { + if (activeLayout == null) { + if (typeof DefaultHandler === 'function') { + DefaultHandler(); + } + } else { + let Control = EventConsumerAtPoint('onStroke', Coordinates.xy[0],Coordinates.xy[1]); + if (Control != null) { + Control.onStroke(Control, Coordinates); + } + } + } + Bangle.on('stroke',handleStrokeEvent); + } + dispatchStrokeEvent(); +/**** Label ****/ + + function Label (Text, Options) { + function renderLabel (Details) { + let x = Details.x, xAlignment = Details.halign || 0; + let y = Details.y, yAlignment = Details.valign || 0; + + let Width = Details.w, halfWidth = Width/2; + let Height = Details.h, halfHeight = Height/2; + + let Border = Details.border || 0, BorderColor = Details.BorderColor; + let Padding = Details.pad || 0; + let Hilite = Details.hilite || false; + let bold = Details.bold ? 1 : 0; + + if (Hilite || (Details.bgCol != null)) { + g.setBgColor(Hilite ? g.theme.bgH : Details.bgCol); + g.clearRect(x,y, x + Width-1,y + Height-1); + } + + if ((Border > 0) && (BorderColor !== null)) {// draw border of layout cell + g.setColor(BorderColor || Details.col || g.theme.fg); + + switch (Border) { + case 2: g.drawRect(x+1,y+1, x+Width-2,y+Height-2);// no break here! + case 1: g.drawRect(x,y, x+Width-1,y+Height-1); break; + default: g.fillPoly([ + x,y, x+Width,y, x+Width,y+Height, x,y+Height, x,y, + x+Border,y+Border, x+Border,y+Height-Border, + x+Width-Border,y+Height-Border, x+Width-Border,y+Border, + x+Border,y+Border + ]); + } + } + + g.setClipRect( + x+Border+Padding,y+Border+Padding, + x + Width-Border-Padding-1,y + Height-Border-Padding-1 + ); + + x += halfWidth + xAlignment*(halfWidth - Border - Padding); + y += halfHeight + yAlignment*(halfHeight - Border - Padding); + + g.setColor (Hilite ? g.theme.fgH : Details.col || g.theme.fg); + g.setBgColor(Hilite ? g.theme.bgH : Details.bgCol || g.theme.bg); + + if (Details.font != null) { g.setFont(Details.font); } + g.setFontAlign(xAlignment,yAlignment); + + g.drawString(Details.label, x,y); + if (bold !== 0) { + g.drawString(Details.label, x+1,y); + g.drawString(Details.label, x,y+1); + g.drawString(Details.label, x+1,y+1); + } + } + + let Result = Object.assign(( + Options == null ? {} : Object.assign({}, Options.common || {}, Options) + ), { + type:'custom', render:renderLabel, label:Text || '' + }); + let Border = Result.border || 0; + let Padding = Result.pad || 0; + + let TextMetrics; + if (! Result.width || ! Result.height) { + if (Result.font == null) { + Result.font = g.getFont(); + } else { + g.setFont(Result.font); + } + TextMetrics = g.stringMetrics(Result.label); + } + + if (Result.col == null) { Result.col = g.getColor(); } + if (Result.bgCol == null) { Result.bgCol = g.getBgColor(); } + + Result.width = Result.width || TextMetrics.width + 2*Border + 2*Padding; + Result.height = Result.height || TextMetrics.height + 2*Border + 2*Padding; + return Result; + } + +/**** Image ****/ + + function Image (Image, Options) { + function renderImage (Details) { + let x = Details.x, xAlignment = Details.halign || 0; + let y = Details.y, yAlignment = Details.valign || 0; + + let Width = Details.w, halfWidth = Width/2 - Details.ImageWidth/2; + let Height = Details.h, halfHeight = Height/2 - Details.ImageHeight/2; + + let Border = Details.border || 0, BorderColor = Details.BorderColor; + let Padding = Details.pad || 0; + let Hilite = Details.hilite || false; + + if (Hilite || (Details.bgCol != null)) { + g.setBgColor(Hilite ? g.theme.bgH : Details.bgCol); + g.clearRect(x,y, x + Width-1,y + Height-1); + } + + if ((Border > 0) && (BorderColor !== null)) {// draw border of layout cell + g.setColor(BorderColor || Details.col || g.theme.fg); + + switch (Border) { + case 2: g.drawRect(x+1,y+1, x+Width-2,y+Height-2);// no break here! + case 1: g.drawRect(x,y, x+Width-1,y+Height-1); break; + default: g.fillPoly([ + x,y, x+Width,y, x+Width,y+Height, x,y+Height, x,y, + x+Border,y+Border, x+Border,y+Height-Border, + x+Width-Border,y+Height-Border, x+Width-Border,y+Border, + x+Border,y+Border + ]); + } + } + + g.setClipRect( + x+Border+Padding,y+Border+Padding, + x + Width-Border-Padding-1,y + Height-Border-Padding-1 + ); + + x += halfWidth + xAlignment*(halfWidth - Border - Padding); + y += halfHeight + yAlignment*(halfHeight - Border - Padding); + + if ('rotate' in Details) { // "rotate" centers image at x,y! + x += Details.ImageWidth/2; + y += Details.ImageHeight/2; + } + + g.setColor (Hilite ? g.theme.fgH : Details.col || g.theme.fg); + g.setBgColor(Hilite ? g.theme.bgH : Details.bgCol || g.theme.bg); + + g.drawImage(Image, x,y, Details.ImageOptions); + } + + let Result = Object.assign(( + Options == null ? {} : Object.assign({}, Options.common || {}, Options) + ), { + type:'custom', render:renderImage, Image:Image + }); + let ImageMetrics = g.imageMetrics(Image); + let Scale = Result.scale || 1; + let Border = Result.border || 0; + let Padding = Result.pad || 0; + + Result.ImageWidth = Scale * ImageMetrics.width; + Result.ImageHeight = Scale * ImageMetrics.height; + + if (('rotate' in Result) || ('scale' in Result) || ('frame' in Result)) { + Result.ImageOptions = {}; + if ('rotate' in Result) { Result.ImageOptions.rotate = Result.rotate; } + if ('scale' in Result) { Result.ImageOptions.scale = Result.scale; } + if ('frame' in Result) { Result.ImageOptions.frame = Result.frame; } + } + + Result.width = Result.width || Result.ImageWidth + 2*Border + 2*Padding; + Result.height = Result.height || Result.ImageHeight + 2*Border + 2*Padding; + return Result; + } + +/**** Drawable ****/ + + function Drawable (Callback, Options) { + function renderDrawable (Details) { + let x = Details.x, xAlignment = Details.halign || 0; + let y = Details.y, yAlignment = Details.valign || 0; + + let Width = Details.w, DrawableWidth = Details.DrawableWidth || Width; + let Height = Details.h, DrawableHeight = Details.DrawableHeight || Height; + + let halfWidth = Width/2 - DrawableWidth/2; + let halfHeight = Height/2 - DrawableHeight/2; + + let Border = Details.border || 0, BorderColor = Details.BorderColor; + let Padding = Details.pad || 0; + let Hilite = Details.hilite || false; + + if (Hilite || (Details.bgCol != null)) { + g.setBgColor(Hilite ? g.theme.bgH : Details.bgCol); + g.clearRect(x,y, x + Width-1,y + Height-1); + } + + if ((Border > 0) && (BorderColor !== null)) {// draw border of layout cell + g.setColor(BorderColor || Details.col || g.theme.fg); + + switch (Border) { + case 2: g.drawRect(x+1,y+1, x+Width-2,y+Height-2);// no break here! + case 1: g.drawRect(x,y, x+Width-1,y+Height-1); break; + default: g.fillPoly([ + x,y, x+Width,y, x+Width,y+Height, x,y+Height, x,y, + x+Border,y+Border, x+Border,y+Height-Border, + x+Width-Border,y+Height-Border, x+Width-Border,y+Border, + x+Border,y+Border + ]); + } + } + + let DrawableX = x + halfWidth + xAlignment*(halfWidth - Border - Padding); + let DrawableY = y + halfHeight + yAlignment*(halfHeight - Border - Padding); + + g.setClipRect( + Math.max(x+Border+Padding,DrawableX), + Math.max(y+Border+Padding,DrawableY), + Math.min(x+Width -Border-Padding,DrawableX+DrawableWidth)-1, + Math.min(y+Height-Border-Padding,DrawableY+DrawableHeight)-1 + ); + + g.setColor (Hilite ? g.theme.fgH : Details.col || g.theme.fg); + g.setBgColor(Hilite ? g.theme.bgH : Details.bgCol || g.theme.bg); + + Callback(DrawableX,DrawableY, DrawableWidth,DrawableHeight, Details); + } + + let Result = Object.assign(( + Options == null ? {} : Object.assign({}, Options.common || {}, Options) + ), { + type:'custom', render:renderDrawable, cb:Callback + }); + let DrawableWidth = Result.DrawableWidth || 10; + let DrawableHeight = Result.DrawableHeight || 10; + + let Border = Result.border || 0; + let Padding = Result.pad || 0; + + Result.width = Result.width || DrawableWidth + 2*Border + 2*Padding; + Result.height = Result.height || DrawableHeight + 2*Border + 2*Padding; + return Result; + } + + if (g.drawRoundedRect == null) { + g.drawRoundedRect = function drawRoundedRect (x1,y1, x2,y2, r) { + let x,y; + if (x1 > x2) { x = x1; x1 = x2; x2 = x; } + if (y1 > y2) { y = y1; y1 = y2; y2 = y; } + + r = Math.min(r || 0, (x2-x1)/2, (y2-y1)/2); + + let cx1 = x1+r, cx2 = x2-r; + let cy1 = y1+r, cy2 = y2-r; + + this.drawLine(cx1,y1, cx2,y1); + this.drawLine(cx1,y2, cx2,y2); + this.drawLine(x1,cy1, x1,cy2); + this.drawLine(x2,cy1, x2,cy2); + + x = r; y = 0; + + let dx,dy, Error = 0; + while (y <= x) { + dy = 1 + 2*y; y++; Error -= dy; + if (Error < 0) { + dx = 1 - 2*x; x--; Error -= dx; + } + + this.setPixel(cx1 - x, cy1 - y); this.setPixel(cx1 - y, cy1 - x); + this.setPixel(cx2 + x, cy1 - y); this.setPixel(cx2 + y, cy1 - x); + this.setPixel(cx2 + x, cy2 + y); this.setPixel(cx2 + y, cy2 + x); + this.setPixel(cx1 - x, cy2 + y); this.setPixel(cx1 - y, cy2 + x); + } + }; + } + + if (g.fillRoundedRect == null) { + g.fillRoundedRect = function fillRoundedRect (x1,y1, x2,y2, r) { + let x,y; + if (x1 > x2) { x = x1; x1 = x2; x2 = x; } + if (y1 > y2) { y = y1; y1 = y2; y2 = y; } + + r = Math.min(r || 0, (x2-x1)/2, (y2-y1)/2); + + let cx1 = x1+r, cx2 = x2-r; + let cy1 = y1+r, cy2 = y2-r; + + this.fillRect(x1,cy1, x2,cy2); + + x = r; y = 0; + + let dx,dy, Error = 0; + while (y <= x) { + dy = 1 + 2*y; y++; Error -= dy; + if (Error < 0) { + dx = 1 - 2*x; x--; Error -= dx; + } + + this.drawLine(cx1 - x, cy1 - y, cx2 + x, cy1 - y); + this.drawLine(cx1 - y, cy1 - x, cx2 + y, cy1 - x); + this.drawLine(cx1 - x, cy2 + y, cx2 + x, cy2 + y); + this.drawLine(cx1 - y, cy2 + x, cx2 + y, cy2 + x); + } + }; + } + + +/**** Button ****/ + + function Button (Text, Options) { + function renderButton (Details) { + let x = Details.x, Width = Details.w, halfWidth = Width/2; + let y = Details.y, Height = Details.h, halfHeight = Height/2; + + let Padding = Details.pad || 0; + let Hilite = Details.hilite || false; + + if (Details.bgCol != null) { + g.setBgColor(Details.bgCol); + g.clearRect(x,y, x + Width-1,y + Height-1); + } + + if (Hilite) { + g.setColor(g.theme.bgH); // no typo! + g.fillRoundedRect(x+Padding,y+Padding, x+Width-Padding-1,y+Height-Padding-1,8); + } + + g.setColor (Hilite ? g.theme.fgH : Details.col || g.theme.fg); + g.setBgColor(Hilite ? g.theme.bgH : Details.bgCol || g.theme.bg); + + if (Details.font != null) { g.setFont(Details.font); } + g.setFontAlign(0,0); + + g.drawRoundedRect(x+Padding,y+Padding, x+Width-Padding-1,y+Height-Padding-1,8); + + g.setClipRect(x+Padding,y+Padding, x+Width-Padding-1,y+Height-Padding-1); + + g.drawString(Details.label, x+halfWidth,y+halfHeight); + g.drawString(Details.label, x+halfWidth+1,y+halfHeight); + g.drawString(Details.label, x+halfWidth,y+halfHeight+1); + g.drawString(Details.label, x+halfWidth+1,y+halfHeight+1); + } + + let Result = Object.assign(( + Options == null ? {} : Object.assign({}, Options.common || {}, Options) + ), { + type:'custom', render:renderButton, label:Text || 'Tap' + }); + let Padding = Result.pad || 0; + + let TextMetrics; + if (! Result.width || ! Result.height) { + if (Result.font == null) { + Result.font = g.getFont(); + } else { + g.setFont(Result.font); + } + TextMetrics = g.stringMetrics(Result.label); + } + + Result.width = Result.width || TextMetrics.width + 2*10 + 2*Padding; + Result.height = Result.height || TextMetrics.height + 2*5 + 2*Padding; + return Result; + } + + const Checkbox_checked = require("heatshrink").decompress(atob("ikUgMf/+GgEGoEAlEAgOAgEYsFhw8OjE54OB/EYh4OB+EYj+BwecjFw8OGg0YDocUgECsEAsP//A")); + const Checkbox_unchecked = require("heatshrink").decompress(atob("ikUgMf/+GgEGoEAlEAgOAgEYAjkUgECsEAsP//A=")); + +/**** Checkbox ****/ + + function Checkbox (Options) { + function renderCheckbox (Details) { + let x = Details.x, xAlignment = Details.halign || 0; + let y = Details.y, yAlignment = Details.valign || 0; + + let Width = Details.w, halfWidth = Width/2 - 10; + let Height = Details.h, halfHeight = Height/2 - 10; + + let Padding = Details.pad || 0; + + if (Details.bgCol != null) { + g.setBgColor(Details.bgCol); + g.clearRect(x,y, x + Width-1,y + Height-1); + } + + x += halfWidth + xAlignment*(halfWidth - Padding); + y += halfHeight + yAlignment*(halfHeight - Padding); + + g.setColor (Details.col || g.theme.fg); + g.setBgColor(Details.bgCol || g.theme.bg); + + g.drawImage( + Details.checked ? Checkbox_checked : Checkbox_unchecked, x,y + ); + } + + let Result = Object.assign(( + Options == null ? {} : Object.assign({}, Options.common || {}, Options) + ), { + type:'custom', render:renderCheckbox, onTouch:toggleCheckbox + }); + let Padding = Result.pad || 0; + + Result.width = Result.width || 20 + 2*Padding; + Result.height = Result.height || 20 + 2*Padding; + + if (Result.checked == null) { Result.checked = false; } + return Result; + } + + /* private */ function toggleCheckbox (Control) { + g.reset(); + + Control.checked = ! Control.checked; + Control.render(Control); + + if (typeof Control.onChange === 'function') { + Control.onChange(Control); + } + } + +/**** toggleInnerCheckbox ****/ + + /* export */ function toggleInnerCheckbox (Control) { + if (Control.c == null) { + if (('checked' in Control) && ! ('GroupName' in Control)) { + toggleCheckbox(Control); + return true; + } + } else { + let ControlList = Control.c; + for (let i = 0, l = ControlList.length; i < l; i++) { + let done = toggleInnerCheckbox(ControlList[i]); + if (done) { return true; } + } + } + } + + const Radiobutton_checked = require("heatshrink").decompress(atob("ikUgMB/EAsFgjEBwUAgkggFEgECoEAlEPgOB/EYj+BAgmA+EUCYciDodBwEYg0GgEfwA")); + const Radiobutton_unchecked = require("heatshrink").decompress(atob("ikUgMB/EAsFgjEBwUAgkggFEgECoEAlEAgOAgEYAhEUCYciDodBwEYg0GgEfwAA=")); + +/**** Radiobutton ****/ + + function Radiobutton (Options) { + function renderRadiobutton (Details) { + let x = Details.x, xAlignment = Details.halign || 0; + let y = Details.y, yAlignment = Details.valign || 0; + + let Width = Details.w, halfWidth = Width/2 - 10; + let Height = Details.h, halfHeight = Height/2 - 10; + + let Padding = Details.pad || 0; + + if (Details.bgCol != null) { + g.setBgColor(Details.bgCol); + g.clearRect(x,y, x + Width-1,y + Height-1); + } + + x += halfWidth + xAlignment*(halfWidth - Padding); + y += halfHeight + yAlignment*(halfHeight - Padding); + + g.setColor (Details.col || g.theme.fg); + g.setBgColor(Details.bgCol || g.theme.bg); + + g.drawImage( + Details.checked ? Radiobutton_checked : Radiobutton_unchecked, x,y + ); + } + + let Result = Object.assign(( + Options == null ? {} : Object.assign({}, Options.common || {}, Options) + ), { + type:'custom', render:renderRadiobutton, onTouch:checkRadiobutton + }); + let Padding = Result.pad || 0; + + Result.width = Result.width || 20 + 2*Padding; + Result.height = Result.height || 20 + 2*Padding; + + if (Result.checked == null) { Result.checked = false; } + return Result; + } + + /* private */ function checkRadiobutton (Control) { + if (! Control.checked) { + uncheckRadiobuttonsIn((activeLayout || {}).l,Control.GroupName); + toggleRadiobutton(Control); + + if (typeof Control.onChange === 'function') { + Control.onChange(Control); + } + } + } + + /* private */ function toggleRadiobutton (Control) { + g.reset(); + + Control.checked = ! Control.checked; + Control.render(Control); + } + + /* private */ function uncheckRadiobuttonsIn (Control,GroupName) { + if ((Control == null) || (GroupName == null)) { return; } + + if (Control.c == null) { + if (('checked' in Control) && (Control.GroupName === GroupName)) { + if (Control.checked) { toggleRadiobutton(Control); } + } + } else { + let ControlList = Control.c; + for (let i = 0, l = ControlList.length; i < l; i++) { + uncheckRadiobuttonsIn(ControlList[i],GroupName); + } + } + } + +/**** checkInnerRadiobutton ****/ + + /* export */ function checkInnerRadiobutton (Control) { + if (Control.c == null) { + if (('checked' in Control) && ('GroupName' in Control)) { + checkRadiobutton(Control); + return true; + } + } else { + let ControlList = Control.c; + for (let i = 0, l = ControlList.length; i < l; i++) { + let done = checkInnerRadiobutton(ControlList[i]); + if (done) { return true; } + } + } + } + + + let Theme = g.theme; + g.clear(true); + +/**** Settings ****/ + + let Settings; + + function readSettings () { + Settings = Object.assign({}, + { + Face:'1-12', colored:true, + Hands:'rounded', withSeconds:true, + Foreground:'Theme', Background:'Theme', Seconds:'#FF0000' + }, + require('Storage').readJSON('configurable_clock.json', true) || {} + ); + + prepareTransformedPolygon(); + } + + function saveSettings () { + require('Storage').writeJSON('configurable_clock.json', Settings); + prepareTransformedPolygon(); + } + + function prepareTransformedPolygon () { + switch (Settings.Hands) { + case 'simple': transformedPolygon = new Array(simpleHourHandPolygon.length); break; + case 'rounded': transformedPolygon = new Array(roundedHandPolygon.length); break; + case 'hollow': transformedPolygon = new Array(hollowHandPolygon.length); + } + } + +//readSettings(); // not yet + + +/**** Hands ****/ + + let HourHandLength = outerRadius * 0.5; + let HourHandWidth = 2*3, halfHourHandWidth = HourHandWidth/2; + + let MinuteHandLength = outerRadius * 0.8; + let MinuteHandWidth = 2*2, halfMinuteHandWidth = MinuteHandWidth/2; + + let SecondHandLength = outerRadius * 0.9; + let SecondHandOffset = 10; + + let twoPi = 2*Math.PI, deg2rad = Math.PI/180; + let Pi = Math.PI; + let halfPi = Math.PI/2; + + let sin = Math.sin, cos = Math.cos; + +/**** simple Hands ****/ + + let simpleHourHandPolygon = [ + -halfHourHandWidth,halfHourHandWidth, + -halfHourHandWidth,halfHourHandWidth-HourHandLength, + halfHourHandWidth,halfHourHandWidth-HourHandLength, + halfHourHandWidth,halfHourHandWidth, + ]; + + let simpleMinuteHandPolygon = [ + -halfMinuteHandWidth,halfMinuteHandWidth, + -halfMinuteHandWidth,halfMinuteHandWidth-MinuteHandLength, + halfMinuteHandWidth,halfMinuteHandWidth-MinuteHandLength, + halfMinuteHandWidth,halfMinuteHandWidth, + ]; + + +/**** rounded Hands ****/ + + let outerBoltRadius = halfHourHandWidth + 2; + let innerBoltRadius = outerBoltRadius - 4; + let roundedHandOffset = outerBoltRadius + 4; + + let sine = [0, sin(30*deg2rad), sin(60*deg2rad), 1]; + + let roundedHandPolygon = [ + -sine[3],-sine[0], -sine[2],-sine[1], -sine[1],-sine[2], -sine[0],-sine[3], + sine[0],-sine[3], sine[1],-sine[2], sine[2],-sine[1], sine[3],-sine[0], + sine[3], sine[0], sine[2], sine[1], sine[1], sine[2], sine[0], sine[3], + -sine[0], sine[3], -sine[1], sine[2], -sine[2], sine[1], -sine[3], sine[0], + ]; + + let roundedHourHandPolygon = new Array(roundedHandPolygon.length); + for (let i = 0, l = roundedHandPolygon.length; i < l; i+=2) { + roundedHourHandPolygon[i] = halfHourHandWidth*roundedHandPolygon[i]; + roundedHourHandPolygon[i+1] = halfHourHandWidth*roundedHandPolygon[i+1]; + if (i < l/2) { roundedHourHandPolygon[i+1] -= HourHandLength; } + if (i > l/2) { roundedHourHandPolygon[i+1] += roundedHandOffset; } + } + let roundedMinuteHandPolygon = new Array(roundedHandPolygon.length); + for (let i = 0, l = roundedHandPolygon.length; i < l; i+=2) { + roundedMinuteHandPolygon[i] = halfMinuteHandWidth*roundedHandPolygon[i]; + roundedMinuteHandPolygon[i+1] = halfMinuteHandWidth*roundedHandPolygon[i+1]; + if (i < l/2) { roundedMinuteHandPolygon[i+1] -= MinuteHandLength; } + if (i > l/2) { roundedMinuteHandPolygon[i+1] += roundedHandOffset; } + } + + +/**** hollow Hands ****/ + + let BoltRadius = 3; + let hollowHandOffset = BoltRadius + 15; + + let hollowHandPolygon = [ + -sine[3],-sine[0], -sine[2],-sine[1], -sine[1],-sine[2], -sine[0],-sine[3], + sine[0],-sine[3], sine[1],-sine[2], sine[2],-sine[1], sine[3],-sine[0], + sine[3], sine[0], sine[2], sine[1], sine[1], sine[2], sine[0], sine[3], + 0,0, + -sine[0], sine[3], -sine[1], sine[2], -sine[2], sine[1], -sine[3], sine[0] + ]; + + let hollowHourHandPolygon = new Array(hollowHandPolygon.length); + for (let i = 0, l = hollowHandPolygon.length; i < l; i+=2) { + hollowHourHandPolygon[i] = halfHourHandWidth*hollowHandPolygon[i]; + hollowHourHandPolygon[i+1] = halfHourHandWidth*hollowHandPolygon[i+1]; + if (i < l/2) { hollowHourHandPolygon[i+1] -= HourHandLength; } + if (i > l/2) { hollowHourHandPolygon[i+1] -= hollowHandOffset; } + } + hollowHourHandPolygon[25] = -BoltRadius; + + let hollowMinuteHandPolygon = new Array(hollowHandPolygon.length); + for (let i = 0, l = hollowHandPolygon.length; i < l; i+=2) { + hollowMinuteHandPolygon[i] = halfMinuteHandWidth*hollowHandPolygon[i]; + hollowMinuteHandPolygon[i+1] = halfMinuteHandWidth*hollowHandPolygon[i+1]; + if (i < l/2) { hollowMinuteHandPolygon[i+1] -= MinuteHandLength; } + if (i > l/2) { hollowMinuteHandPolygon[i+1] -= hollowHandOffset; } + } + hollowMinuteHandPolygon[25] = -BoltRadius; + + + +/**** transform polygon ****/ + + let transformedPolygon; + + function transformPolygon (originalPolygon, OriginX,OriginY, Phi) { + let sPhi = sin(Phi), cPhi = cos(Phi), x,y; + + for (let i = 0, l = originalPolygon.length; i < l; i+=2) { + x = originalPolygon[i]; + y = originalPolygon[i+1]; + + transformedPolygon[i] = OriginX + x*cPhi + y*sPhi; + transformedPolygon[i+1] = OriginY + x*sPhi - y*cPhi; + } + } + +/**** refreshClock ****/ + + let Timer; + function refreshClock () { + activeLayout = null; + + g.setTheme({ + fg:(Settings.Foreground === 'Theme' ? Theme.fg : Settings.Foreground || '#000000'), + bg:(Settings.Background === 'Theme' ? Theme.bg : Settings.Background || '#FFFFFF') + }); + g.clear(true); // also installs the current theme + + Bangle.drawWidgets(); + renderClock(); + + let Period = (Settings.withSeconds ? 1000 : 60000); + + let Pause = Period - (Date.now() % Period); + Timer = setTimeout(refreshClock,Pause); + } + +/**** renderClock ****/ + + function renderClock () { + g.setColor (Settings.Foreground === 'Theme' ? Theme.fg : Settings.Foreground || '#000000'); + g.setBgColor(Settings.Background === 'Theme' ? Theme.bg : Settings.Background || '#FFFFFF'); + + switch (Settings.Face) { + case 'none': + break; + case '3,6,9,12': + g.setFont('Vector', 22); + + g.setFontAlign(0,-1); + g.drawString('12', CenterX,CenterY-outerRadius); + + g.setFontAlign(1,0); + g.drawString('3', CenterX+outerRadius,CenterY); + + g.setFontAlign(0,1); + g.drawString('6', CenterX,CenterY+outerRadius); + + g.setFontAlign(-1,0); + g.drawString('9', CenterX-outerRadius,CenterY); + break; + case '1-12': + let innerRadius = outerRadius * 0.9 - 10; + + for (let i = 0; i < 60; i++) { + let Phi = i * twoPi/60; + + let x = CenterX + outerRadius * sin(Phi); + let y = CenterY - outerRadius * cos(Phi); + + if (Settings.colored) { + let Color = E.HSBtoRGB(i/60,1,1, true); + g.setColor(Color[0]/255,Color[1]/255,Color[2]/255); + } + + g.fillCircle(x,y, 1); + } + + g.setFont('Vector', 20); + g.setFontAlign(0,0); + + for (let i = 0; i < 12; i++) { + let Phi = i * twoPi/12; + + let Radius = innerRadius; + if (i >= 10) { Radius -= 4; } + + let x = CenterX + Radius * sin(Phi); + let y = CenterY - Radius * cos(Phi); + + if (Settings.colored) { + let Color = E.HSBtoRGB(i/12,1,1, true); + g.setColor(Color[0]/255,Color[1]/255,Color[2]/255); + } + + g.drawString(i == 0 ? '12' : '' + i, x,y); + } + } + + let now = new Date(); + + let Hours = now.getHours() % 12; + let Minutes = now.getMinutes(); + + let HoursAngle = (Hours+(Minutes/60))/12 * twoPi - Pi; + let MinutesAngle = (Minutes/60) * twoPi - Pi; + + g.setColor(Settings.Foreground === 'Theme' ? Theme.fg : Settings.Foreground || '#000000'); + + switch (Settings.Hands) { + case 'simple': + transformPolygon(simpleHourHandPolygon, CenterX,CenterY, HoursAngle); + g.fillPoly(transformedPolygon); + + transformPolygon(simpleMinuteHandPolygon, CenterX,CenterY, MinutesAngle); + g.fillPoly(transformedPolygon); + break; + case 'rounded': + transformPolygon(roundedHourHandPolygon, CenterX,CenterY, HoursAngle); + g.fillPoly(transformedPolygon); + + transformPolygon(roundedMinuteHandPolygon, CenterX,CenterY, MinutesAngle); + g.fillPoly(transformedPolygon); + +// g.setColor(Settings.Foreground === 'Theme' ? Theme.fg || '#000000'); + g.fillCircle(CenterX,CenterY, outerBoltRadius); + + g.setColor(Settings.Background === 'Theme' ? Theme.bg : Settings.Background || '#FFFFFF'); + g.drawCircle(CenterX,CenterY, outerBoltRadius); + g.fillCircle(CenterX,CenterY, innerBoltRadius); + break; + case 'hollow': + transformPolygon(hollowHourHandPolygon, CenterX,CenterY, HoursAngle); + g.drawPoly(transformedPolygon,true); + + transformPolygon(hollowMinuteHandPolygon, CenterX,CenterY, MinutesAngle); + g.drawPoly(transformedPolygon,true); + + g.drawCircle(CenterX,CenterY, BoltRadius); + } + + if (Settings.withSeconds) { + g.setColor(Settings.Seconds === 'Theme' ? Theme.fgH : Settings.Seconds || '#FF0000'); + + let Seconds = now.getSeconds(); + let SecondsAngle = (Seconds/60) * twoPi - Pi; + + let sPhi = Math.sin(SecondsAngle), cPhi = Math.cos(SecondsAngle); + + g.drawLine( + CenterX + SecondHandOffset*sPhi, + CenterY - SecondHandOffset*cPhi, + CenterX - SecondHandLength*sPhi, + CenterY + SecondHandLength*cPhi + ); + } + } + + +/**** MainScreen Logic ****/ + + let Changes = {}, KeysToChange; + + let fullScreen = { + x:0,y:0, w:ScreenWidth,h:ScreenHeight, x2:ScreenWidth-1,y2:ScreenHeight-1 + }; + let AppRect; + + function openMainScreen () { + if (Timer != null) { clearTimeout(Timer); Timer = undefined; } + if (AppRect == null) { AppRect = Bangle.appRect; Bangle.appRect = fullScreen; } + + KeysToChange = 'Face colored Hands withSeconds Foreground Background Seconds'; + + g.setTheme({ fg:'#000000', bg:'#FFFFFF' }); + g.clear(true); // also installs the current theme + + (activeLayout = MainScreen).render(); + } + + function applySettings () { saveSettings(); Bangle.appRect = AppRect; refreshClock(); } + function withdrawSettings () { readSettings(); Bangle.appRect = AppRect; refreshClock(); } + +/**** FacesScreen Logic ****/ + + function openFacesScreen () { + KeysToChange = 'Face colored'; + Bangle.appRect = fullScreen; + refreshFacesScreen(); + } + + function refreshFacesScreen () { + activeLayout = FacesScreen; + activeLayout['none'].checked = ((Changes.Face || Settings.Face) === 'none'); + activeLayout['3,6,9,12'].checked = ((Changes.Face || Settings.Face) === '3,6,9,12'); + activeLayout['1-12'].checked = ((Changes.Face || Settings.Face) === '1-12'); + activeLayout['colored'].checked = (Changes.colored == null ? Settings.colored : Changes.colored); + activeLayout.render(); + } + + function chooseFace (Control) { Changes.Face = Control.id; refreshFacesScreen(); } + function toggleColored () { Changes.colored = ! Changes.colored; refreshFacesScreen(); } + +/**** HandsScreen Logic ****/ + + function openHandsScreen () { + KeysToChange = 'Hands withSeconds'; + Bangle.appRect = fullScreen; + refreshHandsScreen(); + } + + function refreshHandsScreen () { + activeLayout = HandsScreen; + activeLayout['simple'].checked = ((Changes.Hands || Settings.Hands) === 'simple'); + activeLayout['rounded'].checked = ((Changes.Hands || Settings.Hands) === 'rounded'); + activeLayout['hollow'].checked = ((Changes.Hands || Settings.Hands) === 'hollow'); + activeLayout['withSeconds'].checked = (Changes.withSeconds == null ? Settings.withSeconds : Changes.withSeconds); + activeLayout.render(); + } + + function chooseHand (Control) { Changes.Hands = Control.id; refreshHandsScreen(); } + function toggleSeconds () { Changes.withSeconds = ! Changes.withSeconds; refreshHandsScreen(); } + +/**** ColorsScreen Logic ****/ + + function openColorsScreen () { + KeysToChange = 'Foreground Background Seconds'; + Bangle.appRect = fullScreen; + refreshColorsScreen(); + } + + function refreshColorsScreen () { + let Foreground = (Changes.Foreground == null ? Settings.Foreground : Changes.Foreground); + let Background = (Changes.Background == null ? Settings.Background : Changes.Background); + let Seconds = (Changes.Seconds == null ? Settings.Seconds : Changes.Seconds); + + activeLayout = ColorsScreen; + activeLayout['Foreground'].bgCol = (Foreground === 'Theme' ? Theme.fg : Foreground); + activeLayout['Background'].bgCol = (Background === 'Theme' ? Theme.bg : Background); + activeLayout['Seconds'].bgCol = (Seconds === 'Theme' ? Theme.fgH : Seconds); + activeLayout.render(); + } + + function selectForegroundColor () { ColorToChange = 'Foreground'; openColorChoiceScreen(); } + function selectBackgroundColor () { ColorToChange = 'Background'; openColorChoiceScreen(); } + function selectSecondsColor () { ColorToChange = 'Seconds'; openColorChoiceScreen(); } + +/**** ColorChoiceScreen Logic ****/ + + let ColorToChange, chosenColor; + + function openColorChoiceScreen () { + chosenColor = ( + Changes[ColorToChange] == null ? Settings[ColorToChange] : Changes[ColorToChange] + ); + Bangle.appRect = fullScreen; + refreshColorChoiceScreen(); + } + + function refreshColorChoiceScreen () { + activeLayout = ColorChoiceScreen; + activeLayout['#000000'].selected = (chosenColor === '#000000'); + activeLayout['#FF0000'].selected = (chosenColor === '#FF0000'); + activeLayout['#00FF00'].selected = (chosenColor === '#00FF00'); + activeLayout['#0000FF'].selected = (chosenColor === '#0000FF'); + activeLayout['#FFFF00'].selected = (chosenColor === '#FFFF00'); + activeLayout['#FF00FF'].selected = (chosenColor === '#FF00FF'); + activeLayout['#00FFFF'].selected = (chosenColor === '#00FFFF'); + activeLayout['#FFFFFF'].selected = (chosenColor === '#FFFFFF'); + activeLayout['Theme'].selected = (chosenColor === 'Theme'); + activeLayout.render(); + } + + function chooseColor (Control) { chosenColor = Control.id; refreshColorChoiceScreen(); } + function chooseThemeColor () { chosenColor = 'Theme'; refreshColorChoiceScreen(); } + + function applyColor () { + Changes[ColorToChange] = chosenColor; + openColorsScreen(); + } + + function withdrawColor () { + openColorsScreen(); + } + +/**** common logic for multiple screens ****/ + + function applyChanges () { + Settings = Object.assign(Settings,Changes); + Changes = {}; + openMainScreen(); + } + + function withdrawChanges () { + Changes = {}; + openMainScreen(); + } + + + g.setFont12x20(); // does not seem to be respected in layout! + + let OkCancelWidth = Math.max( + g.stringWidth('Ok'), g.stringWidth('Cancel') + ) + 2*10; + + let StdFont = { font:'12x20' }; + let legible = Object.assign({ col:'#000000', bgCol:'#FFFFFF' }, StdFont); + let leftAligned = Object.assign({ halign:-1, valign:0 }, legible); + let ColorView = Object.assign({ width:30, border:1, BorderColor:'#000000' }, StdFont); + let ColorChoice = Object.assign({ DrawableWidth:30, DrawableHeight:30, onTouch:chooseColor }, StdFont); + +/**** MainScreen ****/ + + let MainScreen = new Layout({ + type:'v', c:[ + Label('Settings', { common:legible, bold:true, filly:1 }), + { height:4 }, + { type:'h', c:[ + Label('Faces', { common:leftAligned, fillx:1 }), + Image(Caret, { common:leftAligned }), + ], filly:1, onTouch:openFacesScreen }, + { type:'h', c:[ + Label('Hands', { common:leftAligned, fillx:1 }), + Image(Caret, { common:leftAligned }), + ], filly:1, onTouch:openHandsScreen }, + { type:'h', c:[ + Label('Colors', { common:leftAligned, fillx:1 }), + Image(Caret, { common:leftAligned }), + ], filly:1, onTouch:openColorsScreen }, + { height:4 }, + { type:'h', c:[ + Button('Ok', { common:legible, width:OkCancelWidth, onTouch:applySettings }), + { width:4 }, + Button('Cancel', { common:legible, width:OkCancelWidth, onTouch:withdrawSettings }), + ], filly:1 }, + ], bgCol:'#FFFFFF' + }); + + +/**** FacesScreen ****/ + + let FacesScreen = new Layout({ + type:'v', c:[ + Label('Clock Faces', { common:legible, bold:true, filly:1 }), + { height:4 }, + { type:'h', c:[ + Radiobutton({ id:'none', GroupName:'Faces', common:legible, onChange:chooseFace }), + Label(' no Face', { common:leftAligned, pad:4, fillx:1 }), + ], filly:1, onTouch:checkInnerRadiobutton }, + { type:'h', c:[ + Radiobutton({ id:'3,6,9,12', GroupName:'Faces', common:legible, onChange:chooseFace }), + Label(' 3, 6, 9 and 12', { common:leftAligned, pad:4, fillx:1 }), + ], filly:1, onTouch:checkInnerRadiobutton }, + { type:'h', c:[ + Radiobutton({ id:'1-12', GroupName:'Faces', common:legible, onChange:chooseFace }), + Label(' numbers 1...12', { common:leftAligned, pad:4, fillx:1 }), + ], filly:1, onTouch:checkInnerRadiobutton }, + { type:'h', c:[ + { width:30 }, + Checkbox({ id:'colored', common:legible, onChange:toggleColored }), + Label(' colorful', { common:leftAligned, pad:4, fillx:1 }), + ], filly:1, onTouch:toggleInnerCheckbox }, + { height:4 }, + { type:'h', c:[ + Button('Ok', { common:legible, width:OkCancelWidth, onTouch:applyChanges }), + { width:4 }, + Button('Cancel', { common:legible, width:OkCancelWidth, onTouch:withdrawChanges }), + ], filly:1 }, + ], bgCol:'#FFFFFF' + }); + + +/**** HandsScreen ****/ + + let HandsScreen = new Layout({ + type:'v', c:[ + Label('Clock Hands', { common:legible, bold:true, filly:1 }), + { height:4 }, + { type:'h', c:[ + Radiobutton({ id:'simple', GroupName:'Faces', common:legible, onChange:chooseHand }), + Label(' simple', { common:leftAligned, pad:4, fillx:1 }), + ], filly:1, onTouch:checkInnerRadiobutton }, + { type:'h', c:[ + Radiobutton({ id:'rounded', GroupName:'Faces', common:legible, onChange:chooseHand }), + Label(' rounded + Bolt', { common:leftAligned, pad:4, fillx:1 }), + ], filly:1, onTouch:checkInnerRadiobutton }, + { type:'h', c:[ + Radiobutton({ id:'hollow', GroupName:'Faces', common:legible, onChange:chooseHand }), + Label(' hollow + Bolt', { common:leftAligned, pad:4, fillx:1 }), + ], filly:1, onTouch:checkInnerRadiobutton }, + { type:'h', c:[ + Checkbox({ id:'withSeconds', common:legible, onChange:toggleSeconds }), + Label(' show Seconds', { common:leftAligned, pad:4, fillx:1 }), + ], filly:1, onTouch:toggleInnerCheckbox }, + { height:4 }, + { type:'h', c:[ + Button('Ok', { common:legible, width:OkCancelWidth, onTouch:applyChanges }), + { width:4 }, + Button('Cancel', { common:legible, width:OkCancelWidth, onTouch:withdrawChanges }), + ], filly:1 }, + ], bgCol:'#FFFFFF' + }); + + +/**** ColorsScreen ****/ + + let ColorsScreen = new Layout({ + type:'v', c:[ + Label('Clock Colors', { common:legible, bold:true, filly:1 }), + { height:4 }, + { type:'h', c:[ + Label('Foreground', { common:leftAligned, pad:4, fillx:1 }), + Label('', { id:'Foreground', common:ColorView, bgCol:Theme.fg }), + ], filly:1, onTouch:selectForegroundColor }, + { type:'h', c:[ + Label('Background', { common:leftAligned, pad:4, fillx:1 }), + Label('', { id:'Background', common:ColorView, bgCol:Theme.bg }), + ], filly:1, onTouch:selectBackgroundColor }, + { type:'h', c:[ + Label('Seconds', { common:leftAligned, pad:4, fillx:1 }), + Label('', { id:'Seconds', common:ColorView, bgCol:Theme.fgH }), + ], filly:1, onTouch:selectSecondsColor }, + { height:4 }, + { type:'h', c:[ + Button('Ok', { common:legible, width:OkCancelWidth, onTouch:applyChanges }), + { width:4 }, + Button('Cancel', { common:legible, width:OkCancelWidth, onTouch:withdrawChanges }), + ], filly:1 }, + ], bgCol:'#FFFFFF' + }); + + +/**** ColorChoiceScreen ****/ + + function drawColorChoice (x,y, Width,Height, Details) { + let selected = Details.selected; + if (selected) { + g.setColor('#FF0000'); + g.fillPoly([ + x,y, x+Width-1,y, x+Width-1,y+Height-1, x,y+Height-1, x,y, + x+3,y+3, x+3,y+Height-4, x+Width-4,y+Height-4, x+Width-4,y+3, x+3,y+3 + ]); + } else { + g.setColor('#000000'); + g.drawRect(x+3,y+3, x+Width-4,y+Height-4); + } + + g.setColor(Details.col); + g.fillRect(x+4,y+4, x+Width-5,y+Height-5); + } + + let ColorChoiceScreen = new Layout({ + type:'v', c:[ + Label('Choose Color', { common:legible, bold:true, filly:1 }), + { height:4 }, + { type:'h', c:[ + Drawable(drawColorChoice, { id:'#000000', common:ColorChoice, col:'#000000' }), + { width:8 }, + Drawable(drawColorChoice, { id:'#FF0000', common:ColorChoice, col:'#FF0000' }), + { width:8 }, + Drawable(drawColorChoice, { id:'#00FF00', common:ColorChoice, col:'#00FF00' }), + { width:8 }, + Drawable(drawColorChoice, { id:'#0000FF', common:ColorChoice, col:'#0000FF' }), + ], filly:1 }, + { type:'h', c:[ + Drawable(drawColorChoice, { id:'#FFFFFF', common:ColorChoice, col:'#FFFFFF' }), + { width:8 }, + Drawable(drawColorChoice, { id:'#FFFF00', common:ColorChoice, col:'#FFFF00' }), + { width:8 }, + Drawable(drawColorChoice, { id:'#FF00FF', common:ColorChoice, col:'#FF00FF' }), + { width:8 }, + Drawable(drawColorChoice, { id:'#00FFFF', common:ColorChoice, col:'#00FFFF' }), + ], filly:1 }, + { type:'h', c:[ + Label('use Theme:', { id:'Theme', common:leftAligned, pad:4 }), + { width:10 }, + Drawable(drawColorChoice, { id:'Theme', common:ColorChoice, col:Theme.fg }), + ], filly:1, onTouch:chooseThemeColor }, + { height:4 }, + { type:'h', c:[ + Button('Ok', { common:legible, width:OkCancelWidth, onTouch:applyColor }), + { width:4 }, + Button('Cancel', { common:legible, width:OkCancelWidth, onTouch:withdrawColor }), + ], filly:1 }, + ], bgCol:'#FFFFFF' + }); + + + + readSettings(); + + Bangle.on('swipe', (Direction) => { + if (Direction === 0) { openMainScreen(); } + }); + + setTimeout(refreshClock, 500); // enqueue first draw request + + Bangle.on('lcdPower', (on) => { + if (on) { + if (Timer != null) { clearTimeout(Timer); Timer = undefined; } + refreshClock(); + } + }); + + Bangle.setUI('clock'); From 56a25fb3f6230e9559ef0065490c89da72045828 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:20 +0100 Subject: [PATCH 233/489] Create app-screenshot.png --- apps/configurable_clock/app-screenshot.png | Bin 0 -> 3218 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/app-screenshot.png diff --git a/apps/configurable_clock/app-screenshot.png b/apps/configurable_clock/app-screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..5287217593fe6c4482120906e42c36c0d8860ee9 GIT binary patch literal 3218 zcmb7{*H;th7RA2=LP)4$=vr=t-aRyJ)QHgQ>-kExsW1A005WCRYRNKPWnge zY`RC4QOb2SC^=SP7-ltl1}V2o z^Ez&A^*)6D@0#H_F|`b}4_&cw@YB#xqArNJ2duAU8cp2q1I?DFO_g*nYrrV?b;WLS zVk2P|6N%fA2-?jvm`icjl!f);;SYEOra)k{$m)QEyL?C`MF;=UA-tXCyYth0sDI%) zm69p5jkvad*V#DX%5k`2hbC-Vcd889XG>EIPdB;3^1WSakq;~Dq%&&*$TZSY;c@vj%L&LY<_C_F6z#g;GrNdA59HmB=n}|0F zB4O0MuX)Q{5RAi}BJ$&^=kt3g(U_mX2}wfrOa1AON(9-XhiDGyp$P}$)jkfEsDzvd z(E;1<#h?qnAl77eTf%f5Mp@B<@CesF3!bA_w>mg}rpPyY@6PaHFzTN3HNHFkkXbDcdo&=0{Pdh}zy*3Ir$pQZC+i&FKMV#;8 z2$I#eW2Y%I;%Z5JJ-~DiiV00Luk9$`)2@Q*p}m4s1G=A^A%8qKf3Hca3s^7K-j zk8ZIL5V~gnTa%#rE)*1YeuNG~gP5%25K} z?bwXu1X%=D!tOc$|Cr!gNS(X@=SLJi*4F8L_csG~3RqmaYvY~rQ#ss2eKPT004R>n ze4qf4+OL}S=tK1&xl;<4I~(U1O%@p_{Ur>L`{Cl~>X+%?m`ddU6Gwmesy6oAO|DYG+!SHFh-lsXrEczZ56!?j?%{qyUW@ zsA;OP>LRzMa<=uOe(4uGYg0 z%E2SG41CP$q4aX@hrc#Oog`OB=UR4Kjl7!s$4?k96_iCkM;gt*W}>boFQ?Z6_*FXc zRU#CA)$El|ShC~dA6BJLhxy8f)z*;P(XU&|p?ck-?Xm1nMS2r)S%jg5cZi@~hea+= z7X4s}r%RiTrl;*>D=U?ZgjdoQK=4KNze<;`r#>8ikY^QlFc(vU>}HD6wFI-i$dpak zEuOd%v*Z2;GQP6P!>FcuhM;93eDYkVW5PL^)q{&OkRFqjj7f9WVtbgv7dxb)(XG3# zvt(Sh-F2GvpIv{o&ipdvHT6G@Rtj5ke!;8SMYf>|6{E+hkph+jgHw<#lM0auYOlD~G z9GdZ}XTD>nTj$Dv_WnJ~5TUY+pbA1+afP2>1QLE(G^f{=-~Jzpx#O5Xd=#KGlI9+JccpsX$Y`xo( znU$eav)!^dmh<^2cVPEL{*G~X;KpH)lJ(8FvWE%3G}BE6HY<>U{A6MW8XSe(@=jxL zS7=chB9u_%Po7x-ygXy=aIc;AFjrwG@hv73m$e%Ez2gzBn%0)+vx|t#XQeV zrslnj+#g!y)BM`V3g!pi4#;Joae*hP`4{xslU{=GNCH!n;#MvRnsI5}Px4XICi-P7 zv>M2!m@lYi4bbKUF_9$({cr+=R12rxz&f9Obfu~z^8oKZc10>!w%QJ^D~{j@-?tCY ze>{++@~xC2LA7IYOg6{Pi^DLPW%zC0wxrmA+R;cwjZbcJDh2mrwtov`yzI6^~gNi)oL2Abz1G2hd>Q+k-*0Rj3n&PANUi6y| z#17#;cTPN7=y)|`wz@0AI+(W5cJ5|+(N+;kA6rkZqVFuSKCw#pTGP8kZsH;dQ}V~* z6Cw`JD3#;=xFGPu5QJSVubxO6S6(@%phHNV;Mh=kW{^zQ(&nL1%jDO8=s7YC*xP_u zncyt_ri++U@TZMc$n>{K`LhE;tDW_SjiHc!{;=ckef zYB$OvNd4LtFNEnVN3Ey_#Egi_so6MXM5&PiU5&vIv&(eEb{f(gUFJhdZ|QW=2C^n9i)f;h-+s5Wf~c(4QhU?X{kg zQ|9I%_*vI$t@^132I$<6<|b4@qOEANb_+-}s#zrS9RL~5nLgeyQg8X_Arw1Im;x<% zks0-nZK*hykf$Jg@=aia0%$iWvUipOE~*W=)f^y*@2hP#f?)sPyVN?AlFJ$~=?SIT iO1v6u1OIaE7d%+S$$YPr_s8#&0Zfc63~TkV_x=x}ck>Yd literal 0 HcmV?d00001 From 9eaf501ce7b91ba1b171360bb775097d0cba9c4c Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:24 +0100 Subject: [PATCH 234/489] Create app-icon.png --- apps/configurable_clock/app-icon.png | Bin 0 -> 4369 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/app-icon.png diff --git a/apps/configurable_clock/app-icon.png b/apps/configurable_clock/app-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..58f50365d4ed18b6b1f5e006a3e2a4398452cbbb GIT binary patch literal 4369 zcmY*dXIK+RyA4G;!Y6`M=|vF;z4x+-fOMn?7$POoLK38xfXY$@MY<4L0HsNhCZS1} zE>S|0Vjy5dS_BmMaCh(Cd*^v(-kCG!J!jteF+V23^41@$OuS400Du(?GO|98z~7yL z?tHvWeH4ElXub5!^#Op_Pndr}E}XB0pdf2=03b{P0El@A034q~F&h9t(0StKT>wBM z8vwWh&u_ERI^SS~gB+0n05iw$P6f!#=LP_%9AUN&C3lz~| z5)u;9LfrGzur@OJC;fb-E#i$r!8PRMf`fx)gB4{15MFZf>gwupKm|Dk1(|b(3^LRo z1qqSyM~eO}@;^F89!Mwx21mgH{Dpq&Lfiv_P}(9Qzm5KFf1eWt^ZZ{Yf8;-9ofjzg zdq+-Q7AW_x_Iaw-Z&bqq0rNO_{;jVguk{!6|6%|5XvzIH|38QMyVAeV^HOz~wB-K1 zHXSCj9!W<4fK3E!q;KneVJ6oH^?W90;A~xNU2H8%k}*r{5~oaYQ^nw=%gp#xgDjtG zhFbo(1CHJ}awYBlv%Rvv{v6k{Je zK~R1b1b0fVi<$q4iP~uRsI$HJb0N!1H|s2ll4m5QzPlu2tjjhgx?CDqpbj}gI{w+} zS8Y*^&Mw}xGVtK-duY{^UY~vFJs2TBE{l-WL{#BFiS{|PuG`dpy;29eCA}^^Vpl1} z?Og0Y;CIwN(jvad&DSh&DiNE`dd0N1J58{Ne=}KeZDDOw!qpApUD8zTiv!OtSubgz7~LSdZba2 zc{e3b$(fV4+H`2H$*mfAr^Z_QRe4Y*;(!TzPb*6PHt&*z`B~z=d@>Po^Vz2^&qV>9 z8`bk`jy19n(NWwlaI^)CrVn%=Wi~cpWNyz&DR@;mcsSrR#Fg0S8gOAtr_7gZTOM_j zEGbWlQ2O3+i}a+UpxTk66dyMw&$ecsMe;sKVzui7dK~ZiRQ=aTnf&}uOl<@ltP`eT*2Xmz_|He zawEpbwUvF-XkCNQwJ~MhY2D?p$fboU>EkU9+ex>Yj}@3-0@)|x?U*pYa(e8y*UM99r-e>Nog{!-;55+KH*W|3!3JbAjyLBN1t! z+CFelowlsi{PfMz`f+G*>IHSpHQW!-{TI=O1lDm(S$O1JD|GE z(8rKPk6m|%#FD)yC_P{;TX(*;P|BoCZu!W8xU%~?=V8}vC71Yafs$yuJ6@k)Y0HiI zVSC(Bbtg&PQ6;&rr^Y{mIrIv4BbM-V3PFv>yU`Hj!Lu^SC=nT)X`)xmEk-f-6`t6~ z+CoWz!>-Oe*R9cuQ0BAhAPu&47p$8%CpU*3U2FlV|1?v1znf(<{+a`~AOzcq}nez?M4f)vI1cdhOHxhwgRo zG^IFOa9CzWX~bBJ%dwtYNs(D7n(ivzz@_U!J@*fq(T|;X;fx{}2NU{^{Oj_<)2D&8 zLLT?Pa^$o(-+GijW&5m)`-Q6kJx5m}vc;+$gj4A7QG0v^oKwj>dS4}a*cv}_2LIGtes7D-HXMfHGM6c+y>w*kxExosvxni&K7UR28RQINOr09sc@+#eUS}M`nWo z-yjjtz99mmC#dh4EiE<5d!=43JB!Vmn7VpR7ZtG-7d#ZJy$3RxxjSC@OE7-yy?fi!mC-agplx=N@64;z4Wcj_D(q5~q>Q#TQlNJ$8lbWq zhp4B{^>H27{W6k@(d_56> z+hIs{OI(^UjlWo=Pn%w9iKd&;=C)+qT`*rv?Y3R63)n0K^@%AyQJBgrH3eBbOJ5JDXN=i@AqDnfGr!0#WU)3HN3exMqhFbbQX91YO7kw@cHljks3Wz zTm3E3mP_l3Pi4DZ@P#isFV`K}GoGDH75e%P24@>hM3I|f%-ZKWmJ^)S-w!2Pu;fav z^cQd-9mVBuTR$6bZ^?_!n(ryYxkWj?jP9fpx!auHn<-_Pe#j>upf#!;?lA{0M(co|a1Syul@wuu%`8t^)n8hI!hU!BqMKaBv-2Kb5Rm9!)J{!XsIW($zGyM zPX5lu7%L7+$CI?;#ESm?>B~14ChminzVdJiqKh;GZ2OPIHxrtr(D6iZ_LKI=VJ*E3 z3cmfWNPEO;3e|MBaW;=#Cd6Q5mcxnPW#Oi2KYB7Ti?s?D7Z{)W_DiYIm4F2u^Bi z)-qf_TjtHtkw|sRZpgN=QQ;nZck!Z&=KmYbUeKI4- z<=ck)6}f$%uKl#VI?jQn@UHfi>u#N!f?searE*Z6i**dgIYjD$OB-F@hJY7WE_@MT zxt_$J^n_cg=TYB>c(NTZ3afnORJL>hY#u8Zve!hNnCOO-OrmK|T%n zoVkN$+G{304LYl6ze7W{2NR0A)lu2I z0g>8!W@q_I&i;#rIDYA!@wMC{#vD&5XfZZ9>@(`pMW2@gG&H-C4NHYDdrL zGYAw2y@B)l^fk@IEmK~-@dN5qN?8z4&mn?R2vwhNT0JdOF8W^+boDF*Qb;By2EVpREf9hqDsv z1@{o`GyGd-4_=$-%uPOi7$?=AsTdos$yZzpVIE|YAEK&^gQdCPA0Etw)PTc-rN6Yw z{#o#xtb`pSncmiX5w1=yy9jwIihhA?XXf>{R4?QDWp=e zXl85_ytWoEUz4$NbLfqLFnZhP3y^IphD^qs=*;DSK?$;--Ak{eikZ_P0t-7bdteU!5rK29>tS9_VOhWFF)J zXPeJ9IN2$TZn8Y8)_=G_>~UfuitF5i8ek zTc(*Ufpd$9CZEFK;h6vMISUl5Ep<$iTE*YZ>IR1`$Dc0nbRq2Kv(^>HUy^YA9=?aO zffcNnSIdL3DHA<}9gMZvdR1%15dim9*PBFeu6rIC6+6ihQjcAbOsVN~{mGQHZzW-Q zho=X=d*}<*;b=4-5ahdKNSu$4!L&}pi6d}CSI;1&fa}L$|A+1Ge03*$*e@S$%E=P% z)Y1_Bzl%B>N-gY%;{;AWG%LTBZ})Hv@x9kg2;YXxK})4;_x)UeFg~Z#*v1b1V}bsT z4e-SWgw*&ui*VtrgoY#FFb~3&eswB=<5Y9#G3!*x6NK8#Vec4@prTxk*QA@O3e_Ww z2mTyrPWS`_13>1Yri&8#<>>utErk^7O%2O~HJ%8ayyO!onnNxzI{dl3_Vh=w%97^k|`udx>Pg*L}tdZ21rQotoTNHrm3cI(e)t zo;^5A2k!e`XaV1d7ABn{hdD2^!f`qssDy>e!WoTr8Y&mq92oZd;{j}Z%c#cSZtQ;n D06kr; literal 0 HcmV?d00001 From a499ad279a3c95a54fbde1736f46399594907ed4 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:27 +0100 Subject: [PATCH 235/489] Create app-icon.js --- apps/configurable_clock/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/configurable_clock/app-icon.js diff --git a/apps/configurable_clock/app-icon.js b/apps/configurable_clock/app-icon.js new file mode 100644 index 000000000..b0cf74241 --- /dev/null +++ b/apps/configurable_clock/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgZC/AB1RgkQsAQMyUKAYMIkAPJgNFiEBgACBg0YCRMogEJkGSAwMSEZNAAQMAEAMGgBKHgXAlECwMgzcAmkAhgRGilRssUgMEEYcBwARFiBHBgQKB7AjCawIQEgoCCigDBjEBwwEBEwIAGlmSEYYABI4PAEYhEBNYIjCAYVtwCSElG2xdoAwQjDhpZEEAMUqAHDCIaPBEYlAiwjItkAgYjFqJHDCIdhI4j1CAAhlEZoTUEAAcGEYZKEEYWgCIgjEWYkBoqwCCITLBgcMmPXhgjCgUB2iFDm3pw0YLAMygEgc4QjF49cmA3BbQQjDgGkI5OwNZZ9FEYoRLEYxmBCI5jBEYQACyQRHgmAEYsEEZEka4kAhEEEY8BCIMJCIYjKgGChAFDCwKzDNYyKEJgUDlgRBAoPDRQQjEZQZzEjScIhgjBEwQjEH4aXEgIjBjYCBjQCBMYYADmAjDFIjcGKocAjBKCgJRCAAwaCEARQBmARIhBrEgSMEAApEBmHAAQJrCABUCjFhwwQMI4oA7")) \ No newline at end of file From db5cb644fd36460d61d76ce9014bd5a6a542c118 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:32 +0100 Subject: [PATCH 236/489] Create LICENSE --- apps/configurable_clock/LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 apps/configurable_clock/LICENSE diff --git a/apps/configurable_clock/LICENSE b/apps/configurable_clock/LICENSE new file mode 100644 index 000000000..7487dd5da --- /dev/null +++ b/apps/configurable_clock/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Andreas Rozek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 54ee423106d32237a7c8738d319458c3888c9730 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:34 +0100 Subject: [PATCH 237/489] Create Screenshot-01.png --- apps/configurable_clock/Screenshot-01.png | Bin 0 -> 1621 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-01.png diff --git a/apps/configurable_clock/Screenshot-01.png b/apps/configurable_clock/Screenshot-01.png new file mode 100644 index 0000000000000000000000000000000000000000..b2367784c76e682019d944c899f572357ab0fded GIT binary patch literal 1621 zcmds2+f!3_5dNKn1PDh61|{ez7gLK=g^1M#L2e=enMn|^PJs|+6icN-0E4kf@B|Q| zLji?BsS1kIf^9+UfJu?dNzH(j78EO?f^Z1bl%`;Ua%ne1ATkR8*(EkAB1x1s_k5~g zY&VQPUa@#}20v{4DfSC_4fJ+Z_8I^89!R>LySlqAr(ea%z9e~q_q&7o3j+Yt zp~VS|n@osjIyu=LC>IxlLNK`99|-jNd=cuA$piR^MrQy!A9Vt(<@V4NbnLniLR0t+ z_lZA->j^;76Iy0}SvEof*;1*q3zPU?7F?-CFZGUQ2PyfKcDt_BjcS8G=^3GvjxV7; zrOHK`s5>;rcizbZH&0kL_q>V&OCM<0uIEZ=mmt`9%ba6vjDt#*-TkvUcpmCgzx$Di zbjc3R&8ki;>)navR85kZYE6`6 zD@NtJ80Ww~$#%8E4mJv@lk07Pa7h+MU1m$fHjIYb!luTPnV6SGH}rJzBy4!n9Wm~* z1LM!b+B7*dp$w3ly~!e7tM|N&j_1rfY9}k{cyVyi$|(j}gco{y%3tq`1D>#pF}+!v z0bI!TB4&~?5cMtE7vlPLrXN;)!>1mu?Lu&x%qP@!`|M`W0Ndz84H-{${L21|%q|CGoEFg@ep_^ z^-A$6)bcrK4n;(Mk+}(F$61Dj`b3fHj<8N_4Ka=VfCc46qwIGr3%iEoiqJ?g$;efO z9C$+$Xm*}<$~_rOe1(7@ zuhS7s)eSj2Qv@gC(JZl;V82Xev6_AV?egLqAWcWwsRcXdPv&Pg((?swwo^sdLLmu$ z1#2+bUdXvTh(*Cw@r(i6v~KsvI93nr`w)a=NN>K70V)Al&@2V}RK6%XV2EZH-e)i2)AmC*M zZ?+})e04!c0mb=r6(K&no}` literal 0 HcmV?d00001 From d89f1eef84e353336078f1a7243e90ec5ec38d2a Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:37 +0100 Subject: [PATCH 238/489] Create Screenshot-02.png --- apps/configurable_clock/Screenshot-02.png | Bin 0 -> 1959 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-02.png diff --git a/apps/configurable_clock/Screenshot-02.png b/apps/configurable_clock/Screenshot-02.png new file mode 100644 index 0000000000000000000000000000000000000000..909a2a04a3559d66b724b7c265ee61a68b4a17d2 GIT binary patch literal 1959 zcmb7FYc!kL8vcCq;iGXTg1A@2y{@H2qljxFh>mpH6iuVr6NYLSv&c~L9hWvmqpYS? zf_9G4o>Ro2bk)(%4AnC_X-S8=PTYz?C(1OYZYQ(W{5yYU_FC_L-}UV0+56qkpI2~< zPSMde(FOoOCyW{#t;&+$1J+RO%^h!NzIl3Kr=opIN*2|YgIg*K1;x8 zR4MZor#cx6Io&|uE(Slg`>1js%xnMDEv#ZhwUmbbSePa+L<1ZtWBw4^})>HZF{-jk3>ZS&v)HN7U5xr_|Q(5OKiB2EbF)S=;b?b%G|XaQ_2#u-ezpS7hR2Va{qJ*m{8rdeVc~R`vs1##2$rmopo93&t{Z4Wc)bQvlfPaqdzpMZTfktHDQGmT&rH|AhlZ7Sa(#Xw7@a zTsd2I$sg(8*L50)QyO{>lwd)tG`#s%vquR^oj5ar@d(uF3h&w(==RR9Sxv^+DRRSB zipTqYa3elIQyknEN4uZCR7oDA{}#foZn);A#GMZ!tdU@y)}^|knlV!kh0f&QT=kzvAo;?hOl{D6TlTgBCv*^{!cm${9bDd5e1C?K>>08RabG@=9Bf zKrKOUkSy2MZ9?UtrJjNg3qR_7rMs1+#U&%b>R!)x*v^ldS%D*qL6Ewwa*Y|CAZ9X;uEJ7gvWe8D9Xxz1}lULIAw zHnxuGo4lY`%3Ky>YH1>E^`?5$>RPDZjpt(o5h=|U;gARho3e{cyx;|=uM$cntR`fPr!ry_hhls+VRS7BO^5g zl+;?6i7Vtw)`vgD9u~ZvKwp$)o{`2lKAKh4d0=Wz2IQhB9LVr@1*RD3wIfhoX8D6G5OQ()WrQ- z8pp&(rWU68aH8zNamldgep^V^-rn?^)UUI?Z|5B0qu(Fcefmuoj>GdB*SSB5cW*-* zO{>Q5`5uz|YLs+X5Z>@frr#EgqzLl8U4EibZ}QYL2g5CXh%Pe@N>&=UR(YC%#o71c4 zud%mD7$jfD2;8m%U{t}2p%E>D;)|l-TT}qC`^82qa3%T=OOz{xGgF z{xDDZC}S4ix7)AVSv#8NA$_+$oi)C0+2_>GJ;W*lQnbdt-0prpER4{^zv{F} zTuuwnPEvVSx8WQRE8G`NHC1_5->emreS5M6g?b3+K&o6Zvo)P8q)L_ r5PmQp*46`Iv)s5M8IJrXp4?Vb#?4qzK6hiPCNB^cLJw{VWdGxT>q%q& literal 0 HcmV?d00001 From 350458f9e0e53bf105234238d24e0c2a29c276b1 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:39 +0100 Subject: [PATCH 239/489] Create Screenshot-03.png --- apps/configurable_clock/Screenshot-03.png | Bin 0 -> 2814 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-03.png diff --git a/apps/configurable_clock/Screenshot-03.png b/apps/configurable_clock/Screenshot-03.png new file mode 100644 index 0000000000000000000000000000000000000000..80407c84f0b4d317b0fca562ff3eaec1c396d188 GIT binary patch literal 2814 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 O1&${Owh!^-wEqH%A`7|z literal 0 HcmV?d00001 From ea0104878867a101755eedd82617e1be795ec44f Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:42 +0100 Subject: [PATCH 240/489] Create Screenshot-04.png --- apps/configurable_clock/Screenshot-04.png | Bin 0 -> 3302 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-04.png diff --git a/apps/configurable_clock/Screenshot-04.png b/apps/configurable_clock/Screenshot-04.png new file mode 100644 index 0000000000000000000000000000000000000000..175476c81ba153ec1b69e9537484a232d1706259 GIT binary patch literal 3302 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 Date: Thu, 6 Jan 2022 06:33:46 +0100 Subject: [PATCH 241/489] Create Screenshot-11.png --- apps/configurable_clock/Screenshot-11.png | Bin 0 -> 1570 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-11.png diff --git a/apps/configurable_clock/Screenshot-11.png b/apps/configurable_clock/Screenshot-11.png new file mode 100644 index 0000000000000000000000000000000000000000..bca534613173b18345c9c900cb584f6e2bdee4fe GIT binary patch literal 1570 zcmeHH?N3v882#Or-mc{WRhTWdg2nNovDk_tSVKioUUZ1)bQ+*c9gt|CP=(8&aA^Tc z6p7PWGtgo(qBCk0U#PQ`%e=EjEGWc*Qs5Sy1ff#p)dFQK+4d*w(>^@UNltRkNuHBD z6$$atZp_6@0DxO;OjP1L-u!DmgXg!d;Z4dsK=Q=sP2ff=Zx8^QB{nK@H=1JW>DeWjm0m7#5m?#=0`J40z@x#PB+`v&RE&f1KUb=ZmCnuEn&fK%E| z1HlS~yN8fk=L(V>4xUdc9LEOwvGMQ?IC3@^$OebxDCQlM49ND*0Xqmu_yyo~x;876 zR(lk}wn?=QsZTc!Qh>%7ah!g>x-!Lj3G=LrA(>0qGigsKa=QTNVY~*e?kKz+50qRy3|KVm>0zbyXfEC4IjIUF9!v#I#=f!jGyB9;b*Yf z;M3m$m7@aUvJ3KIy?Tc$r++O=yI4q!FVN0Q?=GMYH_3tp98xzl+V|qcQN(U;j7;(n z;ga`A|9&-OluKEik%(ROK&gihU|NeOVTwlVC&bFBE;W>?_f>QKW}h#_xDPj5I4knK z@ycc>6Zye_kf%si9uc>nDND~#i&eB$babhZpgvdnK&Wsfp|S=@VEd_B)`)uD;7%;B zycA8xFH}(tA>>3D;pyjo3ZOzun`!AquX;IxUugCb(9y)lts;;I7u@6ZSBSXLkcD&g zm^X2~?(H=y8gI(l6-sC(tD1^t@(a3GPkZhJr249~Z@a~>JUn0xE=pcC(#=H+Mtcnv zjgc^KJDmHIN0P?LO3af@mX_9 z#4Wbn1{<5vi(FE}n`T>RGvkYlMVBUI<}b+)`{>oqobG&rB!XOF#%NCPw9AL>)?!4oozl1=^P>|xwS^nauuX7LU6%qZs%^74a!e3 z+A~ll@v{EfdUDUaVMdTX%^$B4`Z9DQC4tT_bMEM#1voQ~`~0zt_-Sb0xJ|r#M;8YR ztfT!~$Q>RT%NLt~#Ty}Gn*%B#G%+UYA8NQar*GqSbyygMY?cY64quzNgCTim-3m5X z;|dGUv$AC_xXNlM2`sG^Qb@*v#*)A&9uKmohGmfqYrsi>rbqQ{97gn`*;pQIh;Vw= zXDtmVQ;1-)rZtzb0>~1+J}75`nvR#jku>1WJbWY`!sP3_{jUH#@|#NYav+OOf8g>t z2n)J)E1U*e2ajlKDS%$KHuN&U!!Ott?gnJ-%|~y&K-lHm$x0^RdHvp1LjeOv?`=zf mFx9V%t9OC_!~Q#fmxh?8^Mp2eDh?qi$?URsIQ;s<7Pv literal 0 HcmV?d00001 From 9cc680155ccea5bdf513c94e11e5174ac22586e3 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:48 +0100 Subject: [PATCH 242/489] Create Screenshot-12.png --- apps/configurable_clock/Screenshot-12.png | Bin 0 -> 1682 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-12.png diff --git a/apps/configurable_clock/Screenshot-12.png b/apps/configurable_clock/Screenshot-12.png new file mode 100644 index 0000000000000000000000000000000000000000..973b6da5e62b45e5d55918ed7878b65da00c10d4 GIT binary patch literal 1682 zcmd^A>r+#A5dGcUkOT-2u$4CngD+YMiP9+wrXkRYhy_F|s5EMQq!2O$`UF=ur!Uj?`LeRsCsShi!8auRV?)WaDsv&b3tt7C<)sZqYe43V;sJdN>nYsM z{?Ao1ym-FAAiOwV$PP!9cS6WUKS?d(O;80Nkb2XbVgG@YAg2FeWLUoF%bWED_lg3~ zJ`DBO2O!?8faQswBduKY6J8Jeu~fv{-hEv&b_MaKAK&nNApr{YNRDnWKezC)+Qtvv zaGvTF=PwQtk^fzH1a2p2uq}69_++zIe*=VyS?X>m&m1pR;K?5{DN(jA`V?B38$&(i z80Fxi@0CK+cEitdpzI5sGw+UVCYTe1loz37lct?kb=Czd$_$AoGSQ@?RwwM#AgSG2 zzaWKlC64MwM_9|CO5Hhg*PIad+;b}C_5E~M#S~e{+|ULDmV|nc#$?+ddxG5wMh%rt zG_z3(m1Hx@=101*wo6#@*UPdTR7;Yk8RTI4ADByX=0F|IxUAR;;Za5 zkdTy6J?Qx(GIM$Cvc168>daBHvsmN?Z2^A-8Hr_C&iDivZzPHrlu<|?2FZD*TQ5IANP6s z5d>nTmX{6<;tn9M*VHI|_-wKXpx;N*PV(N33EGjF?7b6a#qm?TzDYr)oIOc?-#@c> zvg%dcN~~ Date: Thu, 6 Jan 2022 06:33:50 +0100 Subject: [PATCH 243/489] Create Screenshot-13.png --- apps/configurable_clock/Screenshot-13.png | Bin 0 -> 1739 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-13.png diff --git a/apps/configurable_clock/Screenshot-13.png b/apps/configurable_clock/Screenshot-13.png new file mode 100644 index 0000000000000000000000000000000000000000..b87d977124e6ce8a9c16202362d61aba3cd02c4b GIT binary patch literal 1739 zcmd^=`#)597{|{XU(C_cn5kUTRC8f->$MfTu2aL9Xo#*W*X^?8GVVt$Ii?h=8)e#J zD8#lC)5V%iypC-ODWp}3I7C)0Gl(RYo!$Lu|AGBwe|VnH`}O(Zd4735uP4(-z|+++ z)`1{Mm+!&#Rjcf;B5SF8W%WRyT1aueyp2#ri|H@~X&vKpIor^{kym|*#txskg`f+^ z1qSQhQ>}xOEn6E0Uh|%Z$3-ZfRs8fr*vpCG_?fSgSIW$>FEE3V{F{}4>~*vhp`gQ4 z782Za*F^{uM-}!XkFfv9oF(wVLW?`DV_%CP47r=}qs=vjie@Y5OUP&0V$W|(@=Jjl z#4Obn^c#h7Kmtrdb^QVqlaozIcf-5#+q7xjWa^62eX}Wu7a_OO%mpkV$LcjxUta&v zP+vTJf`K959Zd>T@`K^Brg()rV5#(bN^9AehWX=ql83e%*%b07pc2t4pqIuLLhT%V zSi3&go*X`8h>38-6ja4!;~WC$rN8{rozNo~qiI!s=kVo4NH^(VnK|a*N|S3m6KsW( z(pfQVSyK$01ha(yhG@vEU$>2AwNj-e13ge=I~9(GJc)lScNwFHY@KX`*}+VeyRfO5 zd{^HbvrG33bSFqf46`)x?Q^&W9dU$g!YnXtS1Jkxw)?`1(-~uQynYav0S|(cCTd0; z$!Bm8q%EeQ6gs9&(z9l(=y-E1mF?Os*HjOz334aE36pBNdJ7OhVwomJqZ_Zzp+|LQ z;3h>*{-N0(@QYt`F$b(Ri)N4P9ohg!!IZV2pL?PHI@uH~&D6KwXkoXB;7Wkts8M$o z&hdF-m|0vB8w*C;;2hg-Ip6CpJFLJN#-n^MKZ*mxrBo%WXVAk}9f zux8F~;?9Lj4LykC>5=XIN`H!r^_%YVjUoZzn77b1oT%e+xI8Aet041+76r}j?dnj1 zIxEKbE)BBd0~>}afmP@D2+d`U|LjgdO{(8qYdBnIg%uVwmPCctnd$WIG#-(0^YI;+ z(yi`s12^??0UpDy$!V3`ar5qL=n}r!2PZX&_03WuW~1hQ?=dQ@d}t;h_yvt;q|C9> z_r0kmr|@H%btkDx?%c@4T8vH3kC}1K>!4OmP9iIADe{1%EyD=r*$nKj`vA7x^QWSQ zeXY9lb92X)L6Y^w7f&y!@9hfi9bK?xR*?Oyvu);3KhGs%4a~lLBw^L)81InhZ%*MJ zzjoH@Vl`)-f`ldb*^hE&GBx8>^-3XiTnFy`el~n+e%)DQ7K0bAerf;$ioAWeW^jH? z>cB+4z2r}kXO=H7w^Wt2Hh`#4FTA95RauJ~-@ee3GKBHYf%~L%VOQ(^(Dj&0m>T_B z6N9&7E+K!r)tMcGC-Wav-ze_i#R-NN=&Df;?>?_xokTylmCI5USuPbHc}O118X1|` zo&rXI*=)erFuYT8#HLFB0xkll0t5tU{<<=&9PMyc#dumXRj&T2_oi*r4v0&E8SX`p zP`;-+AUU{(DkqPMQU;0@OO@yKQWfpZNPe57%c=cc*IRDUOk? Date: Thu, 6 Jan 2022 06:33:53 +0100 Subject: [PATCH 244/489] Create Screenshot-21.png --- apps/configurable_clock/Screenshot-21.png | Bin 0 -> 2678 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-21.png diff --git a/apps/configurable_clock/Screenshot-21.png b/apps/configurable_clock/Screenshot-21.png new file mode 100644 index 0000000000000000000000000000000000000000..46d799e6d2aa1296d73600ee22a335ac60756964 GIT binary patch literal 2678 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 Nm>F9c(G73J{Tl;|?qmP} literal 0 HcmV?d00001 From b28719da164d9ccb2fce2e6ccb72f2b6caba1e40 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:55 +0100 Subject: [PATCH 245/489] Create Screenshot-22.png --- apps/configurable_clock/Screenshot-22.png | Bin 0 -> 3508 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-22.png diff --git a/apps/configurable_clock/Screenshot-22.png b/apps/configurable_clock/Screenshot-22.png new file mode 100644 index 0000000000000000000000000000000000000000..7ee02568ea7332cdcc302903eb0e8b2e54b84ed1 GIT binary patch literal 3508 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 i4R9g@awP?Z75D>?eJSBek!TA50000 Date: Thu, 6 Jan 2022 06:33:57 +0100 Subject: [PATCH 246/489] Create Screenshot-23.png --- apps/configurable_clock/Screenshot-23.png | Bin 0 -> 3506 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-23.png diff --git a/apps/configurable_clock/Screenshot-23.png b/apps/configurable_clock/Screenshot-23.png new file mode 100644 index 0000000000000000000000000000000000000000..f3248993bafcf568d1bcc3b4b62b227fe33a8a3a GIT binary patch literal 3506 zcmbVP`8U-6_kYb;(o|GZW-wabwn0%u1|=gQS!a}WvW|TXS!cAGl*&%lF&V}fOEZ=* z(;|gP_9dnyV=_o~;p_eV`~{!SJ?Gwg9{1dP&+~cigdy<=z6zg$DE?tk?HK37@;}TL0;@t)#@{it=bABWAcx?fjKv4$>LUa3pV%}B zHFoXQ{9G-zC#N4G$#E#@>XgEs3Gx-%J5THJn%Y+htz&@E_%yfhTFmRtaSTC)tx!i6 zH>Sj=U8|jDL+l8u^oeRKm zZ{EmUU{suT&JBtc(7pfCphiVtHA?wp%lmTUZk<}D{M9M6vRa$TV%0ye0sgifR*B6( zQPjv5Dk0m+{V%%D?d#Rq`9EInT|-!N;7^a_?kBz7KGz(q>%b@a<_4Pga;(&hK$!er zm-3Xx#gaGmoY!qa7BlK>`hP_pMz9nD(QKd=!QC?3Ni&;V`9a&6BSz?Jd?}c| zE*DVxB`@Xyn69%&9rb$7z*`Y27O%4wyn`>U5xQG92c3%T@Ad^J|8^+6G7!Rj zQ_q~kK4hCy&)K{_9swBb=~vM36v0j&?gpzJgbCG3;Yfc~<$rH@pamn%r{ED8uyUfj z;$s)zU-m+IAhm>yArMQ31Fv-xQfpcMEwTC$AelbfsA$4$>n-?H5I-+Y@lltQNxYdN8Rnt{)@%5SzO7^oXFn#z)+!7SNHPZ|JsM zbn%vQ0Co-tqPZ$}DfR?E!Ffm1bEDep4rpiToBH|aXChCw8A)(L!OP3}BRERz2~lMW zBU9!8dH+ITcyOwqN4z&8HZ~8M0kUS?SVZ`%^{~#sdgET!KfYhLa09N{!yGpS$(D>F zWWq0@*}I0(Eq<&ta2y#&4I6}_L9E_Vgy#nBkQ&>8{I-(UXL2LCBq9 zFD_$7cb>~JR*1M1@>%+_VQ+I(jK=w%06a8Jeh`HivM{ ztSjy>#(YpadIZV|G)faxW|Hp|I{Y4*OO*ZbYj+iB76^i9fE}Gg3m#&7odjA4!_f)$ zy==1w@m~tud($<9SEowuKs&aw-%1Qh)J1}nk1U0SbT!t4Ux71bFVq5&1A(Nk(@Lmh zIaG0i5?+bfks|FmB#~&subB+xJlE#cm@YxRRgZ~S_EyN>W!SmRlzzhi`JI(rK{kZ6 zDVC~T#B{g#hI)Pf)<9jiTO}o3rO^&=8e7EjJgq~%)wr&9VmW`Us|R;Lgl^CgW^YpM zpHIV|pIw>xtFPbSv1?eCUM}#w2=AhleY{2iO2)hJq{-#2xkY$T-hToh`2U12EUVnn zsS#VC5QmyGz~`q3$sp3vqPJgYosZ$HJ{E};B3RWLgG{P2bWWGS*&VFBZK)aGcl*2P z402@lNruO%n~20A1Ijbj2d&-;ZeL&7S7WpnuNb(%!l?UP%ZkZw7 zKbyVV(;W8bjFv@m9f=O)ZYio~P|z{jt=b!?g+t9z%}5NW(|@Mo>Q8-2tGqSAtGE3j zQLI}IHEePHRB|PsJb7~>>PO@K^aGg>%^pZoG$Xt4QJ`|$dTJ!`3DMtOy!A~E#!^B= z?lGGA@1FK)s)d@F8bqI95BQ`KJ7dN)!1Dn|v>VhUB~P3U63@7p)SMpah41<2rM!`h zMSY4SCmy0AP={fd=G-20xq-qnz>f9`MW%06j)e#pYawMRl_LFq2wJoPNXl6y8k*Fdp55z^YEvxEbMbLmHWY>^BBJb*3hc z2%a^O?>9c1QOE5I7HpH()w#cMo!}DDhnB4ihm~It6AB0}XfiH$>(~7))E@@h= zkvj*9*Ru#P&i_Lw=f6a404c?!D|I^1wn&BzB%1Sw>huij>ZA;hvjq{?neaQ6sC4atvN;y4A_y+9o&5o90?$cPY z`AG6*lQ-PKtX7kOQv)b?Q&Li)v5=>xB((KGRSD1-vi3wcGdkz2f=aYR@@3P2j_3Ev zD~Q6cT0Zfp`Uqs}CtfxNi^26@ZxI#3lwElxSAB%d?OXf$-81yjf+K876EGHX701tb zf|JsvX0)V2%+x((;0*N1H+F#IE1?tfQH*3k?OGRuxRU65*|CC=VF$=Zj9;>K;T#!` z-ZM>c&M=?Z`#x@SYNl(}$fv-0WN*;3EXTW60p^s1Qa%!halSnB!fwa~cJF54)I8PzWw@?24y*^H0N$*L>-{6>i z%&l=A4_N~yX~r*N=!XO+!Kc}RY%=6Fdu~X-8l0S94Yj*|@kiLw!S5|O+Cnd7{9N_~ z*_&kTn&hSr*R=J&=b;G_`$8h};K0h_x8G(DhCPovWuyfdA}@@BD~mwBInI7uCBcoi z_ZLXJ5b%yMkBwHG*ApKGO)t~yj=}dbJ`Fgb)+c-XIIyw|ayoP+PZ4kS3a6PE$mmLp zX;RBVHKCC=uP?Xo0;ULadAb6+^0(!j_62!0?Wh6kehRRB`gr;sSflf$cN#`2>$D$r z74cCp&SO{Sdu3yNA-D_Y+^J}@b8|v3)&Lc=E=T#*-+!m)k{|eK4FVevB z*FuX!IM28vWoob0nZwl;iuYXy)#q>}JcK}uvDM6

EGBAq8Mt^3+q)og)k|F}jMX IxQI>oKk(JLumAu6 literal 0 HcmV?d00001 From 59eb274eeb734c9178e3fea29b4aa606ed599be4 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:34:00 +0100 Subject: [PATCH 247/489] Create Screenshot-24.png --- apps/configurable_clock/Screenshot-24.png | Bin 0 -> 3040 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-24.png diff --git a/apps/configurable_clock/Screenshot-24.png b/apps/configurable_clock/Screenshot-24.png new file mode 100644 index 0000000000000000000000000000000000000000..8a7753bfc5dd89b2dbb0ee9b034900f5b3151889 GIT binary patch literal 3040 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 literal 0 HcmV?d00001 From 01d6e37f185ea9de7c22c50eb2250294c01daa04 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:34:02 +0100 Subject: [PATCH 248/489] Create Screenshot-25.png --- apps/configurable_clock/Screenshot-25.png | Bin 0 -> 2775 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-25.png diff --git a/apps/configurable_clock/Screenshot-25.png b/apps/configurable_clock/Screenshot-25.png new file mode 100644 index 0000000000000000000000000000000000000000..c2950d7b2ab4e1a58829bc51f2d0f739f4012f5a GIT binary patch literal 2775 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 Date: Thu, 6 Jan 2022 06:34:05 +0100 Subject: [PATCH 249/489] Create BangleApps__apps__variable_clock__README.md --- ...angleApps__apps__variable_clock__README.md | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 apps/configurable_clock/BangleApps__apps__variable_clock__README.md diff --git a/apps/configurable_clock/BangleApps__apps__variable_clock__README.md b/apps/configurable_clock/BangleApps__apps__variable_clock__README.md new file mode 100644 index 000000000..da5bed56d --- /dev/null +++ b/apps/configurable_clock/BangleApps__apps__variable_clock__README.md @@ -0,0 +1,27 @@ +# Variable Analog Clock # + +This app implements an analog clock with various faces, hands and colors to +choose from. + +You have the choice between: + +* 4 different clock faces ![](Screenshot_01.png) ![](Screenshot_02.png) ![](Screenshot_03.png) ![](Screenshot_04.png) and +* 3 different clock hands (optionally with or without second hands) ![](Screenshot_11.png) ![](Screenshot_12.png) ![](Screenshot_13.png) + +Additionally, you may use the currently configured global theme or configure +your own colors for clock fore- and background and second hands. + +Just swipe up or down to switch from clock display to configuration screen + +![](Screenshot_21.png) ![](Screenshot_22.png) ![](Screenshot_23.png) +![](Screenshot_24.png) ![](Screenshot_25.png) + +Chosen settings will be written to the Bangle.js's flash memory and restored +whenever the clock is started again. + +This clock also acts as an example for the building blocks found in the author's +[GitHub repository](https://github.com/rozek/banglejs-2-activities) + +## License ## + +[MIT License](LICENSE) From 4ffee250d7c9eb258fc8651e86704e456387869b Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:36:08 +0100 Subject: [PATCH 250/489] Create README.md --- apps/configurable_clock/README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 apps/configurable_clock/README.md diff --git a/apps/configurable_clock/README.md b/apps/configurable_clock/README.md new file mode 100644 index 000000000..fd7527d0b --- /dev/null +++ b/apps/configurable_clock/README.md @@ -0,0 +1,27 @@ +# Configurable Analog Clock # + +This app implements an analog clock with various faces, hands and colors to +choose from. + +You have the choice between: + +* 4 different clock faces ![](Screenshot_01.png) ![](Screenshot_02.png) ![](Screenshot_03.png) ![](Screenshot_04.png) and +* 3 different clock hands (optionally with or without second hands) ![](Screenshot_11.png) ![](Screenshot_12.png) ![](Screenshot_13.png) + +Additionally, you may use the currently configured global theme or configure +your own colors for clock fore- and background and second hands. + +Just swipe up or down to switch from clock display to configuration screen + +![](Screenshot_21.png) ![](Screenshot_22.png) ![](Screenshot_23.png) +![](Screenshot_24.png) ![](Screenshot_25.png) + +Chosen settings will be written to the Bangle.js's flash memory and restored +whenever the clock is started again. + +This clock also acts as an example for the building blocks found in the author's +[GitHub repository](https://github.com/rozek/banglejs-2-activities) + +## License ## + +[MIT License](LICENSE) From f495cddef5d30ad826f761ddf392ceb0e2c6c4a4 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:49:46 +0100 Subject: [PATCH 251/489] Update app.js --- apps/configurable_clock/app.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/apps/configurable_clock/app.js b/apps/configurable_clock/app.js index 19dc363e4..5ed52b33b 100644 --- a/apps/configurable_clock/app.js +++ b/apps/configurable_clock/app.js @@ -1147,16 +1147,22 @@ Label('Settings', { common:legible, bold:true, filly:1 }), { height:4 }, { type:'h', c:[ + { width:4 }, Label('Faces', { common:leftAligned, fillx:1 }), Image(Caret, { common:leftAligned }), + { width:4 }, ], filly:1, onTouch:openFacesScreen }, { type:'h', c:[ + { width:4 }, Label('Hands', { common:leftAligned, fillx:1 }), Image(Caret, { common:leftAligned }), + { width:4 }, ], filly:1, onTouch:openHandsScreen }, { type:'h', c:[ + { width:4 }, Label('Colors', { common:leftAligned, fillx:1 }), Image(Caret, { common:leftAligned }), + { width:4 }, ], filly:1, onTouch:openColorsScreen }, { height:4 }, { type:'h', c:[ @@ -1175,14 +1181,17 @@ Label('Clock Faces', { common:legible, bold:true, filly:1 }), { height:4 }, { type:'h', c:[ + { width:4 }, Radiobutton({ id:'none', GroupName:'Faces', common:legible, onChange:chooseFace }), Label(' no Face', { common:leftAligned, pad:4, fillx:1 }), ], filly:1, onTouch:checkInnerRadiobutton }, { type:'h', c:[ + { width:4 }, Radiobutton({ id:'3,6,9,12', GroupName:'Faces', common:legible, onChange:chooseFace }), Label(' 3, 6, 9 and 12', { common:leftAligned, pad:4, fillx:1 }), ], filly:1, onTouch:checkInnerRadiobutton }, { type:'h', c:[ + { width:4 }, Radiobutton({ id:'1-12', GroupName:'Faces', common:legible, onChange:chooseFace }), Label(' numbers 1...12', { common:leftAligned, pad:4, fillx:1 }), ], filly:1, onTouch:checkInnerRadiobutton }, @@ -1208,18 +1217,22 @@ Label('Clock Hands', { common:legible, bold:true, filly:1 }), { height:4 }, { type:'h', c:[ + { width:4 }, Radiobutton({ id:'simple', GroupName:'Faces', common:legible, onChange:chooseHand }), Label(' simple', { common:leftAligned, pad:4, fillx:1 }), ], filly:1, onTouch:checkInnerRadiobutton }, { type:'h', c:[ + { width:4 }, Radiobutton({ id:'rounded', GroupName:'Faces', common:legible, onChange:chooseHand }), Label(' rounded + Bolt', { common:leftAligned, pad:4, fillx:1 }), ], filly:1, onTouch:checkInnerRadiobutton }, { type:'h', c:[ + { width:4 }, Radiobutton({ id:'hollow', GroupName:'Faces', common:legible, onChange:chooseHand }), Label(' hollow + Bolt', { common:leftAligned, pad:4, fillx:1 }), ], filly:1, onTouch:checkInnerRadiobutton }, { type:'h', c:[ + { width:4 }, Checkbox({ id:'withSeconds', common:legible, onChange:toggleSeconds }), Label(' show Seconds', { common:leftAligned, pad:4, fillx:1 }), ], filly:1, onTouch:toggleInnerCheckbox }, @@ -1240,16 +1253,22 @@ Label('Clock Colors', { common:legible, bold:true, filly:1 }), { height:4 }, { type:'h', c:[ + { width:4 }, Label('Foreground', { common:leftAligned, pad:4, fillx:1 }), Label('', { id:'Foreground', common:ColorView, bgCol:Theme.fg }), + { width:4 }, ], filly:1, onTouch:selectForegroundColor }, { type:'h', c:[ + { width:4 }, Label('Background', { common:leftAligned, pad:4, fillx:1 }), Label('', { id:'Background', common:ColorView, bgCol:Theme.bg }), + { width:4 }, ], filly:1, onTouch:selectBackgroundColor }, { type:'h', c:[ + { width:4 }, Label('Seconds', { common:leftAligned, pad:4, fillx:1 }), Label('', { id:'Seconds', common:ColorView, bgCol:Theme.fgH }), + { width:4 }, ], filly:1, onTouch:selectSecondsColor }, { height:4 }, { type:'h', c:[ From 8338c671c2d3e1572fb6192e617588eaf04019a6 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:53:26 +0100 Subject: [PATCH 252/489] Update apps.json --- apps.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/apps.json b/apps.json index ebafa9c97..6021608e2 100644 --- a/apps.json +++ b/apps.json @@ -5427,5 +5427,22 @@ {"name":"puzzle15.img","url":"puzzle15.app-icon.js","evaluate":true} ], "data": [{"name":"puzzle15.json"}] + }, + { "id": "configurable_clock", + "name": "Configurable Analog Clock", + "shortName":"Configurable Clock", + "version":"0.01", + "description": "an analog clock with several kinds of faces, hands and colors to choose from", + "icon": "app-icon.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"app-screenshot.png"}], + "readme": "README.md", + "storage": [ + {"name":"configurable_clock.app.js","url":"app.js"}, + {"name":"configurable_clock.img","url":"app-icon.js","evaluate":true} + ] } ] From 4d4071e1514c29db60f6506f48335d4333f133b1 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 07:05:49 +0100 Subject: [PATCH 253/489] Update README.md --- apps/configurable_clock/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/configurable_clock/README.md b/apps/configurable_clock/README.md index fd7527d0b..e1c2bb574 100644 --- a/apps/configurable_clock/README.md +++ b/apps/configurable_clock/README.md @@ -5,16 +5,16 @@ choose from. You have the choice between: -* 4 different clock faces ![](Screenshot_01.png) ![](Screenshot_02.png) ![](Screenshot_03.png) ![](Screenshot_04.png) and -* 3 different clock hands (optionally with or without second hands) ![](Screenshot_11.png) ![](Screenshot_12.png) ![](Screenshot_13.png) +* 4 different clock faces ![](Screenshot-01.png) ![](Screenshot-02.png) ![](Screenshot-03.png) ![](Screenshot-04.png) and +* 3 different clock hands (optionally with or without second hands) ![](Screenshot-11.png) ![](Screenshot-12.png) ![](Screenshot-13.png) Additionally, you may use the currently configured global theme or configure your own colors for clock fore- and background and second hands. Just swipe up or down to switch from clock display to configuration screen -![](Screenshot_21.png) ![](Screenshot_22.png) ![](Screenshot_23.png) -![](Screenshot_24.png) ![](Screenshot_25.png) +![](Screenshot-21.png) ![](Screenshot-22.png) ![](Screenshot-23.png) +![](Screenshot-24.png) ![](Screenshot-25.png) Chosen settings will be written to the Bangle.js's flash memory and restored whenever the clock is started again. From 3571435499e824ff600b6a47f1cb22672a969bad Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 07:19:43 +0100 Subject: [PATCH 254/489] Update README.md --- apps/configurable_clock/README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/configurable_clock/README.md b/apps/configurable_clock/README.md index e1c2bb574..faddd092a 100644 --- a/apps/configurable_clock/README.md +++ b/apps/configurable_clock/README.md @@ -5,16 +5,18 @@ choose from. You have the choice between: -* 4 different clock faces ![](Screenshot-01.png) ![](Screenshot-02.png) ![](Screenshot-03.png) ![](Screenshot-04.png) and -* 3 different clock hands (optionally with or without second hands) ![](Screenshot-11.png) ![](Screenshot-12.png) ![](Screenshot-13.png) +* 4 different clock faces
![](Screenshot-01.png)   ![](Screenshot-02.png)   ![](Screenshot-03.png)   ![](Screenshot-04.png) and +* 3 different clock hands (optionally with or without second hands)
![](Screenshot-11.png)   ![](Screenshot-12.png)   ![](Screenshot-13.png) Additionally, you may use the currently configured global theme or configure your own colors for clock fore- and background and second hands. -Just swipe up or down to switch from clock display to configuration screen +Just swipe up or down to switch from clock display to the first configuration +screen and continue from there -![](Screenshot-21.png) ![](Screenshot-22.png) ![](Screenshot-23.png) -![](Screenshot-24.png) ![](Screenshot-25.png) +![](Screenshot-21.png)   ![](Screenshot-22.png)   +![](Screenshot-23.png)   ![](Screenshot-24.png)   +![](Screenshot-25.png) Chosen settings will be written to the Bangle.js's flash memory and restored whenever the clock is started again. From c2646e5b9f5fca7090c93cc0dbd3f17086b63231 Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Wed, 5 Jan 2022 22:28:52 -0800 Subject: [PATCH 255/489] Update resourcer.js Improve character shapes. --- apps/pooqround/resourcer.js | 60 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/apps/pooqround/resourcer.js b/apps/pooqround/resourcer.js index 44186e658..17c35a40d 100644 --- a/apps/pooqround/resourcer.js +++ b/apps/pooqround/resourcer.js @@ -1,6 +1,6 @@ // pooqRoman resource maker // -// Copyright (c) 2021 Stephen P Spackman +// Copyright (c) 2021, 2022 Stephen P Spackman // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -147,18 +147,18 @@ res += prepFont('y10', ` xxx xxx -2-------------------------------- - x xx + x xxx xx xxx xxxx xxx xxxxx xxx xxxxxxx xxx xxxx xxx xxx - xxxx xxxx xxx - xxxx xxxx xxx - xxxx xxxxxxxx xxxxxxx - xxxx xxxxxxxxxxxxxxxxxxx + xxxx xxxx xxxx + xxxx xxxxx xxxx + xxxx xxxxxxx xxxxxx + xxxx xxxxxxxxxxxxxxxxx xxxx xxxxxxxxxxxxxx -xxxx xxxxxxxxxx +xxxx xxxxxxxxx -3-------------------------------- xxx x xxx xxx xx xxx @@ -270,10 +270,10 @@ res += prepFont('y1', ` xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -1---------------------------------------------- xxx - xxx - xxx - xxx x - xxx x + xxx x + xxx xx + xxx xx + xxx xxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx @@ -282,18 +282,18 @@ res += prepFont('y1', ` xxx xxx -2---------------------------------------------- - x xx + x xxx xx xxx xxxx xxx - xxxxx xxx - xxxxxxx xxx - xxxx xxxx xxx - xxxx xxxxx xxx - xxxx xxxxxxx xxxx - xxxx xxxxxxxxxxxxx xxxxxxxxxxx - xxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - xxxx xxxxxxxxxxxxxxxxxxxxxxxxx -xxxx xxxxxxxxxxxxxx + xxxxxx xxx + xxxxxxxx xxx + xxxx xxxxx xxx + xxxx xxxxxx xxxx + xxxx xxxxxxxx xxxx + xxxx xxxxxxxxxxx xxxxxxxx + xxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxx xxxxxxxxxxxxxxxxxxxxxxxxx +xxxx xxxxxxxxxxxxxxxxx -3---------------------------------------------- xxx x xxx xxx xx xxx @@ -645,12 +645,12 @@ xxxx xxxx -1---------------------------------------------- -xxx x -xxx xx -xxx xxx -xxx xxx -xxx xxxx -xxx xxxx +xxx +xxx x +xxx xx +xxx xx +xxx xxx +xxx xxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx @@ -993,9 +993,9 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxx - xxxxxxxxxxxxxxxx - xxxxxxxxxxxxxxxx - xxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxx xxxx xxxx xxx From adc5ae007155c61a7bc1ba45c87df40f4ed5c03b Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 6 Jan 2022 09:03:35 +0000 Subject: [PATCH 256/489] fix issues with flipper pr --- apps/flipper/flipper.app.js | 2 +- apps/flipper/flipper.icon.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/flipper/flipper.app.js b/apps/flipper/flipper.app.js index 2e7d3551c..7171306b1 100644 --- a/apps/flipper/flipper.app.js +++ b/apps/flipper/flipper.app.js @@ -12,7 +12,7 @@ function upd(th) { g.reset = function(n) { return g._reset().setColor(th.fg).setBgColor(th.bg); }; g.clear = function(n) { if (n) g.reset(); return g.clearRect(0,0,g.getWidth(),g.getHeight()); }; g.clear(1); -}; +} function flipTheme() { if (!g.theme.dark) { diff --git a/apps/flipper/flipper.icon.js b/apps/flipper/flipper.icon.js index 16331c09e..494072c3c 100644 --- a/apps/flipper/flipper.icon.js +++ b/apps/flipper/flipper.icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEw4X/AAO/mMUzs975K+ggLKysUAYNVqoLFitUoAKBqtQBYkJBIQABqwLEgQLEqtABggJDqkVBaoNCBZQwEgILWgoJENYsVBIcVBYpDEgpSIBYMBKQg6CuogCBY1UgoLCXAQLDqAsDBYhSBqEJHAoLDoEBcQ4LBEwILIMooLdIg4LaVoyaGERLcFao4LIdRAACYYUQBY5RKAH4Ar")); +require("heatshrink").decompress(atob("mEw4X/AAO/mMUzs975K+ggLKysUAYNVqoLFitUoAKBqtQBYkJBIQABqwLEgQLEqtABggJDqkVBaoNCBZQwEgILWgoJENYsVBIcVBYpDEgpSIBYMBKQg6CuogCBY1UgoLCXAQLDqAsDBYhSBqEJHAoLDoEBcQ4LBEwILIMooLdIg4LaVoyaGERLcFao4LIdRAACYYUQBY5RKAH4Ar")) From f6e374838fe654ec27133c2451863acf00e35721 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 11:04:01 +0100 Subject: [PATCH 257/489] Update ChangeLog --- apps/gpsinfo/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/gpsinfo/ChangeLog b/apps/gpsinfo/ChangeLog index a3a2fc89a..8d428ce85 100644 --- a/apps/gpsinfo/ChangeLog +++ b/apps/gpsinfo/ChangeLog @@ -4,3 +4,4 @@ 0.05: Refactor to use 'layout' library for multi-device support 0.06: Add number of satellites in view and fix crash with GPS time 0.07: Resolve one FIFO_FULL case and exit App with button press +0.08: Leave GPS power switched on on exit (will switch off after 0.5 seconds anyway) From f59e97c5fc9eaf1e94a98edaffeec9bd0663782d Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 11:04:14 +0100 Subject: [PATCH 258/489] Update gps-info.js Leave GPS power switched on on exit (will switch off after 0.5 seconds anyway). --- apps/gpsinfo/gps-info.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/gpsinfo/gps-info.js b/apps/gpsinfo/gps-info.js index 467d12a95..fdac3d403 100644 --- a/apps/gpsinfo/gps-info.js +++ b/apps/gpsinfo/gps-info.js @@ -132,9 +132,6 @@ Bangle.on('GPS', onGPS); Bangle.on('GPS-raw', onGPSraw); function exitApp() { - Bangle.setGPSPower(0, "app"); - Bangle.removeListener('GPS-raw', onGPSraw); - Bangle.removeListener('GPS', onGPS); load(); } From 1df9b03a30aa8e8147ca1ec17b157202ea48ab7f Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 11:04:22 +0100 Subject: [PATCH 259/489] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index e37326674..71fcb3ff8 100644 --- a/apps.json +++ b/apps.json @@ -1501,7 +1501,7 @@ { "id": "gpsinfo", "name": "GPS Info", - "version": "0.07", + "version": "0.08", "description": "An application that displays information about altitude, lat/lon, satellites and time", "icon": "gps-info.png", "type": "app", From aba0d7126b26d1c24435cb89b2bfd24f4b07e581 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Thu, 6 Jan 2022 11:08:46 +0100 Subject: [PATCH 260/489] Fix widget height --- apps/circlesclock/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index fb4635424..319e99809 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -41,7 +41,7 @@ const colorRed = '#ff0000'; const colorGreen = '#008000'; const colorBlue = '#0000ff'; const colorYellow = '#ffff00'; -const widgetOffset = showWidgets ? 14 : 0; +const widgetOffset = showWidgets ? 24 : 0; const h = g.getHeight() - widgetOffset; const w = g.getWidth(); const hOffset = 30 - widgetOffset; From 66294b3c8a7a0e5ee92c7eeab3ea346e44f314d9 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Thu, 6 Jan 2022 11:17:27 +0100 Subject: [PATCH 261/489] Round step distance --- apps/circlesclock/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 319e99809..d9a8d8eae 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -175,7 +175,7 @@ function drawStepsDistance(w) { g.setFont("Vector:12"); g.setFontAlign(0, 0); g.setColor(colorFg); - g.drawString(shortValue(stepsDistance), w + 2, h3); + g.drawString(Math.round(shortValue(stepsDistance)), w + 2, h3); g.drawImage(shoesIconGreen, w - 6, h3 + radiusOuter - 6); } From 33deb83a675b744599090325596ee015ea98d6f9 Mon Sep 17 00:00:00 2001 From: Marco H Date: Thu, 6 Jan 2022 13:01:36 +0100 Subject: [PATCH 262/489] Fix rounding of step distance --- apps/circlesclock/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index d9a8d8eae..099217706 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -155,7 +155,7 @@ function drawStepsDistance(w) { if (!w) w = getCirclePosition("steps", w1); const steps = getSteps(); const stepDistance = settings.stepLength || 0.8; - const stepsDistance = steps * stepDistance; + const stepsDistance = Math.round(steps * stepDistance); g.setColor(colorGrey); g.fillCircle(w, h3, radiusOuter); @@ -175,7 +175,7 @@ function drawStepsDistance(w) { g.setFont("Vector:12"); g.setFontAlign(0, 0); g.setColor(colorFg); - g.drawString(Math.round(shortValue(stepsDistance)), w + 2, h3); + g.drawString(shortValue(stepsDistance), w + 2, h3); g.drawImage(shoesIconGreen, w - 6, h3 + radiusOuter - 6); } From a9ea028ede2e9fad7e48b4364609c6aaa43f3481 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 6 Jan 2022 12:13:21 +0000 Subject: [PATCH 263/489] fwupdate 0.03: Improve bootloader update safety. Now sets unsafeFlash:1 to allow flash with 2v11 and later Add CRC checks for common bootloaders that we know don't work --- apps.json | 2 +- apps/fwupdate/ChangeLog | 2 ++ apps/fwupdate/custom.html | 23 ++++++++++------------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/apps.json b/apps.json index 33836e05f..8fab1c96e 100644 --- a/apps.json +++ b/apps.json @@ -2,7 +2,7 @@ { "id": "fwupdate", "name": "Firmware Update", - "version": "0.02", + "version": "0.03", "description": "[BETA] Uploads new Espruino firmwares to Bangle.js 2. For now, please use the instructions under https://www.espruino.com/Bangle.js2#firmware-updates", "icon": "app.png", "type": "RAM", diff --git a/apps/fwupdate/ChangeLog b/apps/fwupdate/ChangeLog index 96e7e4e9b..458d695f0 100644 --- a/apps/fwupdate/ChangeLog +++ b/apps/fwupdate/ChangeLog @@ -2,3 +2,5 @@ 0.02: Add support for ZIPs Find and download ZIPs direct from the Espruino website Take 'beta' tag off +0.03: Improve bootloader update safety. Now sets unsafeFlash:1 to allow flash with 2v11 and later + Add CRC checks for common bootloaders that we know don't work diff --git a/apps/fwupdate/custom.html b/apps/fwupdate/custom.html index 8c2008e54..7a1e736e4 100644 --- a/apps/fwupdate/custom.html +++ b/apps/fwupdate/custom.html @@ -60,6 +60,7 @@ function onInit(device) { document.getElementById("fw-unknown").style = "display:none"; document.getElementById("fw-ok").style = ""; } + } function checkForFileOnServer() { @@ -264,6 +265,8 @@ function createJS_app(binary, startAddress, endAddress) { bin32[3] = VERSION; // VERSION! Use this to test ourselves console.log("CRC 0x"+bin32[2].toString(16)); hexJS = "";//`\x10if (E.CRC32(E.memoryArea(${startAddress},${endAddress-startAddress}))==${bin32[2]}) { print("FIRMWARE UP TO DATE!"); load();}\n`; + hexJS += `\x10if (E.CRC32(E.memoryArea(0xF7000,0x7000))==1339551013) { print("BOOTLOADER 2v10.219 needs update"); load();}\n`; + hexJS += `\x10if (E.CRC32(E.memoryArea(0xF7000,0x7000))==1207580954) { print("BOOTLOADER 2v10.236 needs update"); load();}\n`; hexJS += '\x10var s = require("Storage");\n'; hexJS += '\x10s.erase(".firmware");\n'; var CHUNKSIZE = 2048; @@ -291,20 +294,14 @@ function createJS_bootloader(binary, startAddress, endAddress) { var chunk = btoa(new Uint8Array(binary.buffer, binary.byteOffset+i, l)); hexJS += '\x10_fw.set(atob("'+chunk+'"), 0x'+(i).toString(16)+');\n'; } -// hexJS += `\x10(function() { -// if (E.CRC32(_fw)!=${crc}) throw "Invalid CRC!"; -// var f = require("Flash"); -// for (var i=${startAddress};i<${endAddress};i+=4096) f.erasePage(i); -// f.write(_fw,${startAddress}); -// E.reboot(); -// })();\n`; - hexJS += `\x10if (E.CRC32(_fw)!=${crc}) throw "Invalid CRC: 0x"+E.CRC32(_fw).toString(16);\n`; - hexJS += '\x10var f = require("Flash");\n'; + hexJS += `\x10(function() { if (E.CRC32(_fw)!=${crc}) throw "Invalid CRC: 0x"+E.CRC32(_fw).toString(16);\n`; + hexJS += 'E.showMessage("Flashing Bootloader...")\n'; + hexJS += 'E.setFlags({unsafeFlash:1})\n'; + hexJS += 'var f = require("Flash");\n'; for (var i=startAddress;i Date: Thu, 6 Jan 2022 15:15:58 +0100 Subject: [PATCH 264/489] Update ChangeLog --- apps/wid_a_battery_widget/ChangeLog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/wid_a_battery_widget/ChangeLog b/apps/wid_a_battery_widget/ChangeLog index b04824ae8..8a1538479 100644 --- a/apps/wid_a_battery_widget/ChangeLog +++ b/apps/wid_a_battery_widget/ChangeLog @@ -1,3 +1,4 @@ 1.00: Release for Bangle 2 (2021/11/18) 1.01: Internal id update to wid_* as per Gordon's request (2021/11/21) -1.02: Support dark themes \ No newline at end of file +1.02: Support dark themes +1.03: Increase screen update rate when charging From ae27f50a476a4af463c4333a203ac2f118da2373 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 15:17:43 +0100 Subject: [PATCH 265/489] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 958bf71e9..2393e47c3 100644 --- a/apps.json +++ b/apps.json @@ -4477,7 +4477,7 @@ "name": "A Battery Widget (with percentage)", "shortName":"A Battery Widget", "icon": "widget.png", - "version":"1.02", + "version":"1.03", "type": "widget", "supports": ["BANGLEJS", "BANGLEJS2"], "readme": "README.md", From 5e7afb28273bdf6f72ad8ffae1a484b8016f63fe Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Thu, 6 Jan 2022 15:18:45 +0100 Subject: [PATCH 266/489] Increase size of circles and fonts inside Updated screenshots --- apps.json | 2 +- apps/circlesclock/README.md | 5 +++-- apps/circlesclock/app.js | 19 ++++++++++--------- apps/circlesclock/screenshot-dark.png | Bin 0 -> 3857 bytes apps/circlesclock/screenshot-light.png | Bin 0 -> 3823 bytes apps/circlesclock/screenshot.png | Bin 3576 -> 0 bytes 6 files changed, 14 insertions(+), 12 deletions(-) create mode 100644 apps/circlesclock/screenshot-dark.png create mode 100644 apps/circlesclock/screenshot-light.png delete mode 100644 apps/circlesclock/screenshot.png diff --git a/apps.json b/apps.json index f1609bf4f..a2fd1ec9b 100644 --- a/apps.json +++ b/apps.json @@ -5078,7 +5078,7 @@ "version":"0.04", "description": "A clock with circles for different data at the bottom in a probably familiar style", "icon": "app.png", - "screenshots": [{"url":"screenshot.png"}], + "screenshots": [{"url":"screenshot-dark.png"}, {"url":"screenshot-light.png"}], "dependencies": {"widpedom":"app"}, "type": "clock", "tags": "clock", diff --git a/apps/circlesclock/README.md b/apps/circlesclock/README.md index 86c388440..9004161d6 100644 --- a/apps/circlesclock/README.md +++ b/apps/circlesclock/README.md @@ -10,8 +10,9 @@ It can show the following information (this can be configured): * Heart rate (automatically updates when screen is on and unlocked) * Battery (including charging status and battery low warning) -## Screenshot -![Screenshot](screenshot.png) +## Screenshots +![Screenshot dark theme](screenshot-dark.png) +![Screenshot light theme](screenshot-light.png) ## TODO * Show weather information diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 099217706..ac7ae1b3f 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -47,12 +47,13 @@ const w = g.getWidth(); const hOffset = 30 - widgetOffset; const h1 = Math.round(1 * h / 5 - hOffset); const h2 = Math.round(3 * h / 5 - hOffset); -const h3 = Math.round(8 * h / 8 - hOffset); +const h3 = Math.round(8 * h / 8 - hOffset - 3); const w1 = Math.round(w / 6); const w2 = Math.round(3 * w / 6); const w3 = Math.round(5 * w / 6); -const radiusOuter = 22; -const radiusInner = 16; +const radiusOuter = 25; +const radiusInner = 18; +const circleFont = "Vector:15"; function draw() { g.clear(true); @@ -83,7 +84,7 @@ function draw() { g.drawString(locale.time(new Date(), 1), w / 10, h1 + 8); // date & dow - g.setFont("Vector:20"); + g.setFont("Vector:21"); g.setFontAlign(-1, 0); g.drawString(locale.date(new Date()), w / 10, h2); g.drawString(locale.dow(new Date()), w / 10, h2 + 22); @@ -143,7 +144,7 @@ function drawSteps(w) { g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); - g.setFont("Vector:12"); + g.setFont(circleFont); g.setFontAlign(0, 0); g.setColor(colorFg); g.drawString(shortValue(steps), w + 2, h3); @@ -172,7 +173,7 @@ function drawStepsDistance(w) { g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); - g.setFont("Vector:12"); + g.setFont(circleFont); g.setFontAlign(0, 0); g.setColor(colorFg); g.drawString(shortValue(stepsDistance), w + 2, h3); @@ -196,7 +197,7 @@ function drawHeartRate(w) { g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); - g.setFont("Vector:12"); + g.setFont(circleFont); g.setFontAlign(0, 0); g.setColor(colorFg); g.drawString(hrtValue != undefined ? hrtValue : "-", w, h3); @@ -220,7 +221,7 @@ function drawBattery(w) { g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); - g.setFont("Vector:12"); + g.setFont(circleFont); g.setFontAlign(0, 0); let icon = powerIcon; @@ -259,7 +260,7 @@ function drawGauge(cx, cy, percent, color) { g.setColor(color); - const size = 4; + const size = radiusOuter - radiusInner - 2; // draw gauge for (i = startrot; i > endrot - size; i -= size) { x = cx + r * Math.sin(radians(i)); diff --git a/apps/circlesclock/screenshot-dark.png b/apps/circlesclock/screenshot-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..00c0e3399cf9a1f4fbd299e259d245e7a9519db7 GIT binary patch literal 3857 zcmai%`8U+xAIINgn6WQomt{(-F-Ec{RAk>G##qu6@jqRcsg@& z`fsqqj`lZ~8S@z}sMQ<+5#v%kql^;t4dj zLBrp_MIH*vHdm1IF)>CYm&Hobg>_>~_2c-l!^8dk{e}b4i!VVU=ROQ{>cAu(UPA)B zLUb$=n9_Q9^C2L~eTQ-hXuQAMwhL&AjXFjGA&aZAYY;yrDvbrQIy}ua3uWT*-fS#P z$~(~xIM@mfbFzX?ac2|x2+@%gVRiz8_lDR-Zsw!E3&~P{52f9IL^#ea81659c9rpt z&a{k|QkgegLeu==Vvq_rzuQBKrbmnPpO0?^E;cS*`Yv6@_Im8o2VuNzRvuVzPpNRu zCu~XoyFoaW4t>GM+S3ZMxFT5lj0>z#(uuq|uNP}Fu{Ao9olN`E%^NgDHsz%z9^7gzRIE==2%oH^? z9O&Onmu(_TvJpIQ1qQH3LJ2+vuVjds>AE(*-&OM!Dvwk z&=As`&h=-$6Z+ntAAkze3)&fLtrTRrAx44J6&wiA-&Oe%E+Z z-`uNSl>y^>6I)poTlOd{aH(p!S{x_K*^tuA!xR>^2b_^oYn zfP}o201?HXH3Z|s<^auWm(W@#idp@E{j1gk9G@H~PAU88pGPS{R-Hpu66UvW?7Y){ zzp$nSAjNTE7jTUUs!+d2*$3n<8Z;WVwt7zYmCK2?U+e z^klk^3ji9#kG)_4dZMVrU|x5E@;aSWBV7S!;keA`2Z^^>K_4}HXJ?2Xq6WZO!pkp9 z0&q~7=8zyP^4rq}_*ccVl>6w&<=DShcqyniSl+iSKFV2d2d-7mdTCvM9rJ@HNmSKY zF|>BO_M53zI2#z3K5#JSwUeU)Oj)14Mv!AyC7oFr}17*N$OBOAjW;dE05F4wje;ONB5)L?9qk#@3y}&lZ0b0Ef zSjwtHO5%85DIQX5sij)wlF5n_M8cds_cOei2$9~XksmQHUwPm6B*=YCSu7$}G8#z!cnd_4ConFT^kt~|GZJVNNQUZ<+=5k9*0 z9j~H=*a>hBslnYd{J@_d5=Fc=NI?2zp!w|oFTf4e3?J~M8LbC+>iB$4YzmN(QCPEv zGOwWfJ2})`-%P@ddKtHY{nE4RR~bR`AOF2^;x~UV8k0XS`?s4nwE_ zHJIHJH@KvT$+nT{`d}S?@#Dd?XM$yxA?|#vG{@cs@Mpu$! z3GD+o5F&R$E&Svo9hZDwY9Ox6he9kcQJ1{upkGmT&nlnP`wC(`*a@|C>n#K3nYk%Q z5-Rq!{c5&Ur(~0>?3nHi$$?yUkZgd$=vm0HD)+1R0M1+|9@Jfqaugh35j$y2iA~#H zp}}92s+V>qMgJ)B6a=6SbPxZziNn3WKNxYuaoW<}sgM<}<@o%^`{Tp$`&fxGTVuvA zv>RST-UsGB-(^<(LU~0+00$&;=6T2z55M4{&gInZhP~8VoSg~{iW!lEnn8Tniid(( zL9+SDu@id^XeqA)-1PuvN{?yIjw3k(xI=bJR55@E5?I3+-VX*gv%taT-@5sye}$^FkF`_cG$3`wzy?3}V2}n)7W&6f0oeYmp-io5 zhEQw3)W~o)7hdM%m*LZhB>Iw3YRX!_`j2Q;%J#f>nhd5P1+nNP+Pw}ikTjr9wPVef zQhr&)uq)0cNl(VD-{*k-ZYB*dlR1A&ro1BD5wds1nDcAJHlp}zcKAxw`Lt(78Buq_ z$dpVB$AbwojWZMk{`mnVRP2S$jCNQrP=|H+L}~>s($M z45F(hSOxc6RJKseh)k6b)|r!ZeF;YexzL+fl@~PvGR|i4d&gUdY_wp(H{aw|EZp!eH7K3J zz%xD4fK}_cQ?w&8={Cw8q{2&pw!wDRkZB|^YT6~{@$~406dH52L9?;o(Q>Z2s3Ui; zxh0!Wj@+d@PxLQ2Lfa}eyv4*f*(hg!GLNBrAkMP7=U2B`TIL}LOW*Igk&i#2Mi#E6 znPBkh@GPFfp*)+1dahj&n_CnO889`=>*n3rr;h z$%V+wJv@|$dNPE~*wu6UIk;NvFDo0~yQJ6AKCwFWU0m#i8JCV$^H8Ozi+h97yjF)> z`ZYnkZZ6+g#jn?&kY=rIF8TAAh116-v%j9X8u|$4_+@hCf;fU94`%y0M&?K)!9@M( zQ|`jPYiKP>i$n+p>|4f+rMlw-tFj?Wkd>dc7uyxUys6)My(~u(UD-uKp=7egTi90} zr}xn-tiJvZkI9#Q%o#ET=!F(u>gf{e+_6EPoNuzc~!MCB#f6?QGyjnyt?M$Bu1v z($CTT7AsS@k)ofdh-GDxR=rf#j)BIS$xnvaJ$>EBJDtk5Gm(bOrq27Rpz`4WaCT-^ z#r?MtLVz%`M&ytWn9pW7u(_ZFAB~3piSszQ!}&9wyO9?(V%8=IcY$a~uL73A{ZK6R zu(*X&^$}&*a$F)T>S=fbPMk^fB}bcVu^t%pop)IrAuC^|b%XKw|KysjjqFZjM1Fc` z3$5K`dz|kiuGLdss;FY}hX=OeX@C)Xf6D;4i^2Z%u}48OtKSH{8_b*OyHu?-n3Z`r zWol#WT*jSPV8;nVAd4-!9KzjaAj7+lcVlaBdcU(pi{RU>YAp_Fe6Qa8;~WR%x+jl6 z)t7Qb-pxd6gO~|2w}MY*=jed1vr%+6kv|k>c+1*5eFf%u!EJIU*1lOZ0)3vOpQ{cn z0?Z(8%nZ8STbN;EcsQz#)vw&P8#=+MT1|0;^p57P@Y8U|xiV0hlgfTxuWHweMlD^N2}wxz;f@G%*fON+RF#whY4NZ zDg9HQMa`TzYGIZ&Xh&!%hecFN`{UZ9+J=^;WDGVvoaFdZB}N;p@Fg>8EZO6uugk~< z5m6uclx#|6ug;U~#$OgIw@KpZF)0fS`ew4d-02?IRY10xhU{N{b-NfVb^ZiYHlo^R z{Q~~vFJtF8h;#Ru>^A8y?rxDw0CDPew^_`)IBfnHgI`V4OwHfN+O)x{GE%)#5s-Bl ztmdhhp)d0uM`2L^i;3rUpDX>e>;eFgO=NiC1?np(Uh+p8j=iX zH;4?kZ$X(2HF%nC(XSEBu^^AzzCO&`-SH0m-m~Lut3M`Bo_{jZj2but7B$ggGrQV~ zj{kb%Er378mCWg#oWB0JTDm>0rP}J7$UmraoVU8HP$&|x#N+=aJ%B1sXllw(c_TDL zY~co{_?_BmoJu*dO>JJ&#oVj%Q@`7KhTA;Ck{8v=>(n8`F`p4`=+oy2^Pvg9$I?UZ z@r;_^Aw9Exlv?)$sJTh2Cs6|t0yCceN~MQ}A?e+1!~U^=JCe>-CTYuSUZTcX zMP}UFH&Ce(27`$)H?SYBaKgkQN7ZxrG`v12TP}>7@-rHB{>(hZ!7{e&qec-^_EL(E z+@#l{S#VKxB9)S{HP@HFUSwz;PI&Xre^bZA3lQE4wl@A}JfbuSvb#oet*$1|#cVzB zHGn!ti}85$ydMw?y{cxpy@k5m8^UF{(Qn)nEwLE9oD==g|HC0Wh&^ii{v-_1|8WWZ zq&3z_qHldm$gRt?ghGC%?n*|=Dm8aUb$-p#Z4wEFB$_MQrR|9!B;Mz4Obh|vy=V8D z@gke@O#hPzjaX&C)9T9 zJ=U5`Isno+q F{TF;GBE$dy literal 0 HcmV?d00001 diff --git a/apps/circlesclock/screenshot-light.png b/apps/circlesclock/screenshot-light.png new file mode 100644 index 0000000000000000000000000000000000000000..af47b30a40681d7515efcf0658d43784a3e87b8d GIT binary patch literal 3823 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 From c7fef8134c24ea748d3c60e77e61b331db73bcd6 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 15:20:09 +0100 Subject: [PATCH 267/489] Update widget.js Increase screen update rate when charging. --- apps/wid_a_battery_widget/widget.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/wid_a_battery_widget/widget.js b/apps/wid_a_battery_widget/widget.js index 8ab644ab3..74c76784d 100644 --- a/apps/wid_a_battery_widget/widget.js +++ b/apps/wid_a_battery_widget/widget.js @@ -1,4 +1,7 @@ (function(){ + const intervalLow = 60000; // update time when not charging + const intervalHigh = 2000; // update time when charging + let COLORS = { 'white': g.theme.dark ? "#000" : "#fff", 'black': g.theme.dark ? "#fff" : "#000", @@ -36,10 +39,14 @@ g.setFontAlign(0,0); g.setFont('6x8'); g.drawString(l, x + 14, y + 10); + + if (Bangle.isCharging()) changeInterval(id, intervalHigh); + else changeInterval(id, intervalLow); } + Bangle.on('charging',function(charging) { draw(); }); - setInterval(()=>WIDGETS["wid_a_battery_widget"].draw(), 60000); + var id = setInterval(()=>WIDGETS["wid_a_battery_widget"].draw(), intervalLow); WIDGETS["wid_a_battery_widget"]={area:"tr",width:30,draw:draw}; })(); From ba20a7b51eecc1452c7e5fb62b4964b5d7d875ad Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Thu, 6 Jan 2022 15:37:33 +0100 Subject: [PATCH 268/489] Center clock text & better placement for date texts --- apps/circlesclock/app.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index ac7ae1b3f..b5ee61c75 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -79,15 +79,15 @@ function draw() { // time g.setFont("Vector:50"); - g.setFontAlign(-1, -1); + g.setFontAlign(0, -1); g.setColor(colorFg); - g.drawString(locale.time(new Date(), 1), w / 10, h1 + 8); + g.drawString(locale.time(new Date(), 1), w / 2, h1 + 8); // date & dow g.setFont("Vector:21"); g.setFontAlign(-1, 0); - g.drawString(locale.date(new Date()), w / 10, h2); - g.drawString(locale.dow(new Date()), w / 10, h2 + 22); + g.drawString(locale.date(new Date()), w > 180 ? 2 * w / 10 : w / 10, h2); + g.drawString(locale.dow(new Date()), w > 180 ? 2 * w / 10 : w / 10, h2 + 22); drawCircle(1, "steps"); drawCircle(2, "hr"); From fec507c926cef377dbbe95ac701e989328e23b41 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:24:31 +0100 Subject: [PATCH 269/489] Only show plotting of speed if Latitude is available --- apps/recorder/app.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/recorder/app.js b/apps/recorder/app.js index fcd8d6031..5b1c63aef 100644 --- a/apps/recorder/app.js +++ b/apps/recorder/app.js @@ -199,9 +199,10 @@ function viewTrack(filename, info) { menu['Plot Alt.'] = function() { plotGraph(info, "Altitude"); }; - menu['Plot Speed'] = function() { - plotGraph(info, "Speed"); - }; + if (info.fields.includes("Latitude")) + menu['Plot Speed'] = function() { + plotGraph(info, "Speed"); + }; // TODO: steps, heart rate? menu['Erase'] = function() { E.showPrompt("Delete Track?").then(function(v) { From f13aa4f94a40fc20346193c61b08aaada2ec34bf Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:26:57 +0100 Subject: [PATCH 270/489] Adds battery stats --- apps/recorder/widget.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index 4d8cdddb1..b9d372ef8 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -82,7 +82,20 @@ draw : (x,y) => g.setColor(hasBPM?"#f00":"#888").drawImage(atob("DAyBAAAAAD/H/n/n/j/D/B+AYAAAAA=="),x,y) }; }, - + bat:function() { + return { + name : "BAT", + fields : ["Battery Percentage", "Battery Voltage", "Charging"], + getValues : () => { + return [E.getBattery(), NRF.getBattery(), Bangle.isCharging()]; + }, + start : () => { + }, + stop : () => { + }, + draw : (x,y) => g.setColor(Bangle.isCharging() ? "#0f0" : "#ff0").drawImage(atob("DAwBAABgH4G4EYG4H4H4H4GIH4AA"),x,y) + }; + }, temp:function() { var core = 0, skin = 0; var hasCore = false; From e60b27a5b01328a22c4cde0670d234f44516b9b4 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:27:24 +0100 Subject: [PATCH 271/489] Actually interpret the file content instead of the name --- apps/recorder/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index b9d372ef8..14e47a60e 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -151,7 +151,7 @@ } }) */ - require("Storage").list(/^.*\.recorder\.js$/).forEach(fn=>eval(fn)(recorders)); + require("Storage").list(/^.*\.recorder\.js$/).forEach(fn=>eval(require("Storage").read(fn))(recorders)); return recorders; } From d1d478015ec74d36bc520890e4cc199d7b37a950 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 6 Jan 2022 17:04:24 +0000 Subject: [PATCH 272/489] widpedom 0.21: Memory usage improvements, fix widget initial width (fix #1170) --- apps.json | 2 +- apps/widpedom/ChangeLog | 1 + apps/widpedom/widget.js | 53 +++++++++++++++++++---------------------- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/apps.json b/apps.json index 8fab1c96e..c60bdbefc 100644 --- a/apps.json +++ b/apps.json @@ -1590,7 +1590,7 @@ { "id": "widpedom", "name": "Pedometer widget", - "version": "0.20", + "version": "0.21", "description": "Daily pedometer widget", "icon": "widget.png", "type": "widget", diff --git a/apps/widpedom/ChangeLog b/apps/widpedom/ChangeLog index c033ea505..3483c3390 100644 --- a/apps/widpedom/ChangeLog +++ b/apps/widpedom/ChangeLog @@ -20,3 +20,4 @@ Fix issue with widget overwrite in large font mode Memory usage enhancements 0.20: Fix issue where step count would randomly reset +0.21: Memory usage improvements, fix widget initial width (fix #1170) diff --git a/apps/widpedom/widget.js b/apps/widpedom/widget.js index 0ec0780c9..3a079c066 100644 --- a/apps/widpedom/widget.js +++ b/apps/widpedom/widget.js @@ -1,5 +1,4 @@ (() => { - const PEDOMFILE = "wpedom.json" // Last time Bangle.on('step' was called let lastUpdate = new Date(); // Last step count when Bangle.on('step' was called @@ -8,19 +7,14 @@ let settings; function loadSettings() { - const d = require('Storage').readJSON(PEDOMFILE, 1) || {}; - settings = d.settings || {}; - } - - function setting(key) { - if (!settings) { loadSettings() } - const DEFAULTS = { + const d = require('Storage').readJSON("wpedom.json", 1) || {}; + settings = Object.assign({ 'goal': 10000, 'progress': false, 'large': false, 'hide': false - } - return (key in settings) ? settings[key] : DEFAULTS[key]; + }, d.settings || {}); + return d; } Bangle.on('step', stepCount => { @@ -31,10 +25,10 @@ if (lastUpdate.getDate() == date.getDate()){ stp_today += steps; } else { - // TODO: could save this to PEDOMFILE for lastUpdate's day? + // TODO: could save this to "wpedom.json" for lastUpdate's day? stp_today = steps; } - if (stp_today === setting('goal') + if (stp_today === settings.goal && !(require('Storage').readJSON('setting.json',1)||{}).quiet) { let b = 3, buzz = () => { if (b--) Bangle.buzz().then(() => setTimeout(buzz, 100)) @@ -51,29 +45,31 @@ }); // When unloading, save state E.on('kill', () => { - if (!settings) { loadSettings() } - let d = { + require("Storage").writeJSON("wpedom.json",{ lastUpdate : lastUpdate.valueOf(), stepsToday : stp_today, settings : settings, - }; - require("Storage").write(PEDOMFILE,d); + }); }); // add your widget - WIDGETS["wpedom"]={area:"tl",width:26, - redraw:function() { // work out the width, and queue a full redraw if needed - let stps = stp_today.toString(); + WIDGETS["wpedom"]={area:"tl",width:0, + getWidth:function() { let newWidth = 24; - if (setting('hide')) + if (settings.hide) newWidth = 0; else { - if (setting('large')) { + if (settings.large) { newWidth = 12 * stps.length + 3; - if (setting('progress')) + if (settings.progress) newWidth += 24; } } + return newWidth; + }, + redraw:function() { // work out the width, and queue a full redraw if needed + let stps = stp_today.toString(); + let newWidth = this.getWidth(); if (newWidth!=this.width) { // width has changed, re-layout all widgets this.width = newWidth; @@ -84,14 +80,14 @@ } }, draw:function() { - if (setting('hide')) return; + if (settings.hide) return; if (stp_today > 99999) stp_today = stp_today % 100000; // cap to five digits + comma = 6 characters let stps = stp_today.toString(); g.reset().clearRect(this.x, this.y, this.x + this.width, this.y + 23); // erase background - if (setting('progress')) { + if (settings.progress) { const width = 23, half = 11; - const goal = setting('goal'), left = Math.max(goal-stps,0); + const goal = settings.goal, left = Math.max(goal-stps,0); // blue or dark green g.setColor(left ? "#08f" : "#080").fillCircle(this.x + half, this.y + half, half); if (left) { @@ -113,10 +109,10 @@ } g.reset(); } - if (setting('large')) { + if (settings.large) { g.setFont("6x8",2); g.setFontAlign(-1, 0); - g.drawString(stps, this.x + (setting('progress')?28:4), this.y + 12); + g.drawString(stps, this.x + (settings.progress?28:4), this.y + 12); } else { let w = 24; if (stps.length > 3){ @@ -137,11 +133,12 @@ getSteps:()=>stp_today }; // Load data at startup - let pedomData = require("Storage").readJSON(PEDOMFILE,1); + let pedomData = loadSettings(); if (pedomData) { if (pedomData.lastUpdate) lastUpdate = new Date(pedomData.lastUpdate); stp_today = pedomData.stepsToday|0; delete pedomData; } + WIDGETS["wpedom"].width = WIDGETS["wpedom"].getWidth(); })() From c8126f5ce4302c85ddbda9bb4f5993dda72e0d3d Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 19:04:41 +0100 Subject: [PATCH 273/489] Changed icons and colors for better visibility --- apps/recorder/widget.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index 14e47a60e..34a6ca488 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -48,7 +48,7 @@ Bangle.removeListener('GPS', onGPS); Bangle.setGPSPower(0,"recorder"); }, - draw : (x,y) => g.setColor(hasFix?"#0ff":"#888").drawImage(atob("DAyBAAACADgDuBOAeA4AzAHADgAAAA=="),x,y) + draw : (x,y) => g.setColor(hasFix?"#0f0":"#f88").drawImage(atob("DAwBEAKARAKQE4DwHkPqPRGKAEAA"),x,y) }; }, hrm:function() { @@ -79,7 +79,7 @@ Bangle.removeListener('HRM', onHRM); Bangle.setHRMPower(0,"recorder"); }, - draw : (x,y) => g.setColor(hasBPM?"#f00":"#888").drawImage(atob("DAyBAAAAAD/H/n/n/j/D/B+AYAAAAA=="),x,y) + draw : (x,y) => g.setColor(hasBPM?"#f00":"#f88").drawImage(atob("DAwBAAAAMMeef+f+f+P8H4DwBgAA"),x,y) }; }, bat:function() { @@ -119,7 +119,7 @@ hasCore = false; Bangle.removeListener('CoreTemp', onCore); }, - draw : (x,y) => g.setColor(hasCore?"#0f0":"#888").drawImage(atob("DAyBAAHh0js3EuDMA8A8AWBnDj9A8A=="),x,y) + draw : (x,y) => g.setColor(hasCore?"#0f0":"#8f8").drawImage(atob("DAwBAAAOAKPOfgZgZgZgZgfgPAAA"),x,y) }; }, steps:function() { @@ -134,7 +134,7 @@ }, start : () => { lastSteps = Bangle.getStepCount(); }, stop : () => {}, - draw : (x,y) => g.reset().drawImage(atob("DAyBAAADDHnnnnnnnnnnjDmDnDnAAA=="),x,y) + draw : (x,y) => g.reset().drawImage(atob("DAwBAAMMeeeeeeeecOMMAAMMMMAA"),x,y) }; } // TODO: recAltitude from pressure sensor From 2c2141c9ec6beef3590c4082399e5dafe5421d53 Mon Sep 17 00:00:00 2001 From: Marc Englund Date: Thu, 6 Jan 2022 21:20:14 +0200 Subject: [PATCH 274/489] Initial version of Ruuvi Watch Added Ruuvi Watch, an app to watch the status of RuuviTags in range. --- apps.json | 13 +++ apps/ruuviwatch/ChangeLog | 1 + apps/ruuviwatch/README.md | 25 +++++ apps/ruuviwatch/ruuviwatch.app-icon.js | 1 + apps/ruuviwatch/ruuviwatch.app.js | 150 +++++++++++++++++++++++++ apps/ruuviwatch/ruuviwatch.png | Bin 0 -> 692 bytes 6 files changed, 190 insertions(+) create mode 100644 apps/ruuviwatch/ChangeLog create mode 100644 apps/ruuviwatch/README.md create mode 100644 apps/ruuviwatch/ruuviwatch.app-icon.js create mode 100644 apps/ruuviwatch/ruuviwatch.app.js create mode 100644 apps/ruuviwatch/ruuviwatch.png diff --git a/apps.json b/apps.json index 833c3505e..15654f26a 100644 --- a/apps.json +++ b/apps.json @@ -5448,5 +5448,18 @@ {"name":"flipper.app.js","url":"flipper.app.js"}, {"name":"flipper.img","url":"flipper.icon.js","evaluate":true} ] + }, + { "id": "ruuviwatch", + "name": "Ruuvi Watch", + "shortName":"Ruuvi Watch", + "icon": "ruuviwatch.png", + "version":"1.00", + "description": "Keep an eye on RuuviTag devices (https://ruuvi.com). Only shows RuuviTags using the v5 format.", + "readme":"README.md", + "tags": "bluetooth", + "storage": [ + {"name":"ruuviwatch.app.js","url":"ruuviwatch.app.js"}, + {"name":"ruuviwatch.img","url":"ruuviwatch.app-icon.js","evaluate":true} + ] } ] diff --git a/apps/ruuviwatch/ChangeLog b/apps/ruuviwatch/ChangeLog new file mode 100644 index 000000000..8a8ec68d5 --- /dev/null +++ b/apps/ruuviwatch/ChangeLog @@ -0,0 +1 @@ +1.00: Hello Ruuvi Watch! \ No newline at end of file diff --git a/apps/ruuviwatch/README.md b/apps/ruuviwatch/README.md new file mode 100644 index 000000000..bf4358267 --- /dev/null +++ b/apps/ruuviwatch/README.md @@ -0,0 +1,25 @@ +# Ruuvi Watch + +Watch the status of [RuuviTags](https://ruuvi.com) in range. + + - Id + - Temperature (°C) + - Humidity (%) + - Pressure (hPa) + - Battery voltage + + Also shows how "fresh" the data is (age of reading). + + ## Usage + + - Scans for devices when launched and every N seconds. + - Page trough devices with BTN1/BTN3. + - Trigger scan with BTN2. + +## Todo / ideas + + - Allow to "name" known devices + - Prevent flicker when updating + - Include more data + - Support older Ruuvi protocols + diff --git a/apps/ruuviwatch/ruuviwatch.app-icon.js b/apps/ruuviwatch/ruuviwatch.app-icon.js new file mode 100644 index 000000000..7ed27ef6c --- /dev/null +++ b/apps/ruuviwatch/ruuviwatch.app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwhC/AH4A/ABMP/4ACCyIVDAAXwCyoYPIggAFCx4oEDBw/JJJguCBhAwLBZYjKBQQeGCIYNHB45bIBw4gIRgw+NC4wwJJ5YRLC5DzFCJBGMEYoSEFxoMEBQIXEF4gVFF5QcEC553JC5QRITgy/NVxIXGf5QlFIwy4IGBQuFC5JhGCwpGGERZOEBQ4MEDAwJJGAzdJCxLVJFxoYLCxoYICx6/GCqAA/AH4A/ACA")) \ No newline at end of file diff --git a/apps/ruuviwatch/ruuviwatch.app.js b/apps/ruuviwatch/ruuviwatch.app.js new file mode 100644 index 000000000..9f5e03b4c --- /dev/null +++ b/apps/ruuviwatch/ruuviwatch.app.js @@ -0,0 +1,150 @@ +require("Storage").write("ruuviwatch.info",{ + "id":"ruuviwatch", + "name":"Ruuvi Watch", + "src":"ruuviwatch.app.js", + "icon":"ruuviwatch.img" + }); + + const lookup = {}; + const ruuvis = []; + let current = 0; + + function int2Hex (str) { + return ('0' + str.toString(16).toUpperCase()).slice(-2); + } + + function p(data) { + const OFFSET = 7; // 0-4 header, 5-6 Ruuvi id + const robject = {}; + robject.version = data[OFFSET]; + + let temperature = (data[OFFSET+1] << 8) | (data[OFFSET+2] & 0xff); + if (temperature > 32767) { + temperature -= 65534; + } + robject.temperature = temperature / 200.0; + + robject.humidity = (((data[OFFSET+3] & 0xff) << 8) | (data[OFFSET+4] & 0xff)) / 400.0; + robject.pressure = ((((data[OFFSET+5] & 0xff) << 8) | (data[OFFSET+6] & 0xff)) + 50000) / 100.0; + + let accelerationX = (data[OFFSET+7] << 8) | (data[OFFSET+8] & 0xff); + if (accelerationX > 32767) accelerationX -= 65536; // two's complement + robject.accelerationX = accelerationX / 1000.0; + + let accelerationY = (data[OFFSET+9] << 8) | (data[OFFSET+10] & 0xff); + if (accelerationY > 32767) accelerationY -= 65536; // two's complement + robject.accelerationY = accelerationY / 1000.0; + + let accelerationZ = (data[OFFSET+11] << 8) | (data[OFFSET+12] & 0xff); + if (accelerationZ > 32767) accelerationZ -= 65536; // two's complement + robject.accelerationZ = accelerationZ / 1000.0; + + const powerInfo = ((data[OFFSET+13] & 0xff) << 8) | (data[OFFSET+14] & 0xff); + robject.battery = ((powerInfo >>> 5) + 1600) / 1000.0; + robject.txPower = (powerInfo & 0b11111) * 2 - 40; + robject.movementCounter = data[OFFSET+15] & 0xff; + robject.measurementSequenceNumber = ((data[OFFSET+16] & 0xff) << 8) | (data[OFFSET+17] & 0xff); + + robject.mac = [ + int2Hex(data[OFFSET+18]), + int2Hex(data[OFFSET+19]), + int2Hex(data[OFFSET+20]), + int2Hex(data[OFFSET+21]), + int2Hex(data[OFFSET+22]), + int2Hex(data[OFFSET+23]) + ].join(':'); + + robject.name = "Ruuvi " + int2Hex(data[OFFSET+22]) + int2Hex(data[OFFSET+23]); + return robject; + } + + function getAge(created) { + const now = new Date().getTime(); + const ago = ((now - created) / 1000).toFixed(0); + return ago > 0 ? ago + "s ago" : "now"; + } + + function redraw() { + if (ruuvis.length > 0 && ruuvis[current]) { + const ruuvi = ruuvis[current]; + g.clear(); + g.setFontAlign(0,0); + g.setFont("Vector",12); + g.drawString(" (" + (current+1) + "/" + ruuvis.length + ")", g.getWidth()/2, 10); + g.setFont("Vector",20); + g.drawString(ruuvi.name, g.getWidth()/2, 30); + g.setFont("Vector",12); + const age = getAge(ruuvi.time); + if(age > (5*60)) { + g.setColor("#ff0000"); + } else if (age > 60) { + g.setColor("#f39c12"); + } else { + g.setColor("#2ecc71"); + } + g.drawString(age, g.getWidth()/2, 50); + g.setColor("#ffffff"); + g.setFont("Vector",60); + g.drawString(ruuvi.temperature.toFixed(2) + "°c", g.getWidth()/2, g.getHeight()/2); + g.setFontAlign(0,1); + g.setFont("Vector",20); + g.drawString(ruuvi.humidity + "% " + ruuvi.pressure + "hPa ", g.getWidth()/2, g.getHeight()-30); + g.setFont("Vector",12); + g.drawString(ruuvi.battery + "v", g.getWidth()/2, g.getHeight()-10); + } else { + g.clear(); + g.drawImage(require("Storage").read("ruuviwatch.img"), g.getWidth()/2-24, g.getHeight()/2-24); + g.setFontAlign(0,0); + g.setFont("Vector",16); + g.drawString("Looking for Ruuvi...", g.getWidth()/2, g.getHeight()/2 + 50); + } + } + + function scan() { + NRF.findDevices(function(devices) { + let foundNew = false; + devices.forEach(device => { + const data = p(device.data); + data.time = new Date().getTime(); + const idx = lookup[data.name]; + if (idx !== undefined) { + ruuvis[idx] = data; + } else { + lookup[data.name] = ruuvis.push(data)-1; + foundNew = true; + } + }); + redraw(); + if (foundNew) { + Bangle.buzz(); + g.flip(); + } + + }, {timeout : 2000, filters : [{ manufacturerData:{0x0499:{}} }] }); + } + + g.drawImage(require("Storage").read("ruuviwatch.img"), g.getWidth()/2-24, g.getHeight()/2-24); + + var drawInterval = setInterval(redraw, 1000); + var scanInterval = setInterval(scan, 10000); + setWatch(() => { + current--; + if (current < 0) { + current = ruuvis.length-1; + } + redraw(); + }, BTN1, {repeat:true}); + + setWatch(() => { + scan(); + }, BTN2, {repeat:true}); + + setWatch(() => { + current++; + if (current >= ruuvis.length) { + current = 0; + } + redraw(); + }, BTN3, {repeat:true}); + + scan(); \ No newline at end of file diff --git a/apps/ruuviwatch/ruuviwatch.png b/apps/ruuviwatch/ruuviwatch.png new file mode 100644 index 0000000000000000000000000000000000000000..3a5d0954952c77bbe18348240ff7313dcc1e8915 GIT binary patch literal 692 zcmV;l0!#ggP)!VNEuuo9P$>Ll4zvRRj_#*&Ry+IU%mlmf9PGcdKZnENFMS7G;?`N`?20^m``($M zufPX(Heet6Pwj{cc2*`f1=EhsnLZNCRUab>49*^$RhZYr(%**v$3&+M?M(=NjU;X} z^?WfNBb}&eFGAHg#@xgiZ4(maIMG%h&-adY#Obv{ob~HMNZwDQ-wI#5sH`8Y9+CO& zb-_>5{E=`@jgWk$^f!>XfLY|huL3`%8qyMiFDo%2b9X?TG13VxzOH!S7nQp5cREL; zxkUUc@I^eP0&`ni_LhcuK5MWMjhboylpD0A6+qq^mvjjoZg)CKjYoBF<3W4qnG|}1 z%7+oRqy+Pvw}@X8SQOe;<%9RbK9B-zM4|t*a2chBCq_Sc5<)-UImU$cnek~Tqqm+q z5v0R<`iO3w)Bfh<=km00ik<^t=4b{+(3H*rLn#F3E8_Q!S+)4+#xJ z9|`1j!BujC{-kc{vq1b=B$okS{KWW(b#J5Mu9U+ruhX88jOumT*+2I}{X&I8p-?FN abY20-1jwJ!GdeE-0000 Date: Thu, 6 Jan 2022 21:27:40 +0200 Subject: [PATCH 275/489] Add "supports" for Ruuvi Watch Add the "supports" section to apps.json for Ruuvi Watch. --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 15654f26a..f86d3bcf8 100644 --- a/apps.json +++ b/apps.json @@ -5457,6 +5457,7 @@ "description": "Keep an eye on RuuviTag devices (https://ruuvi.com). Only shows RuuviTags using the v5 format.", "readme":"README.md", "tags": "bluetooth", + "supports": ["BANGLEJS"], "storage": [ {"name":"ruuviwatch.app.js","url":"ruuviwatch.app.js"}, {"name":"ruuviwatch.img","url":"ruuviwatch.app-icon.js","evaluate":true} From 3558049233e1ecc75b477ccc7cfef588fc9b50f8 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Thu, 6 Jan 2022 20:35:28 +0100 Subject: [PATCH 276/489] Update README.md --- apps/mmind/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/mmind/README.md b/apps/mmind/README.md index 0623459f7..ea584b7e7 100644 --- a/apps/mmind/README.md +++ b/apps/mmind/README.md @@ -1,6 +1,6 @@ # Mastermind -Play the classic mind game mastermind on your Bangles 2. +Play the classic mind game mastermind on your Bangle 2. ![](screenshot_mmind.png) From 28bb2f73e0d9293c717f080889d7f8f946c2ebae Mon Sep 17 00:00:00 2001 From: Marc Englund Date: Thu, 6 Jan 2022 21:42:43 +0200 Subject: [PATCH 277/489] Visual fixes Make apploader logo black. Clear gfx before drawing logo on startup. --- apps.json | 2 +- apps/ruuviwatch/ChangeLog | 3 ++- apps/ruuviwatch/ruuviwatch.app.js | 1 + apps/ruuviwatch/ruuviwatch.png | Bin 692 -> 665 bytes 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index f86d3bcf8..6761dd47e 100644 --- a/apps.json +++ b/apps.json @@ -5453,7 +5453,7 @@ "name": "Ruuvi Watch", "shortName":"Ruuvi Watch", "icon": "ruuviwatch.png", - "version":"1.00", + "version":"1.01", "description": "Keep an eye on RuuviTag devices (https://ruuvi.com). Only shows RuuviTags using the v5 format.", "readme":"README.md", "tags": "bluetooth", diff --git a/apps/ruuviwatch/ChangeLog b/apps/ruuviwatch/ChangeLog index 8a8ec68d5..ebde871fa 100644 --- a/apps/ruuviwatch/ChangeLog +++ b/apps/ruuviwatch/ChangeLog @@ -1 +1,2 @@ -1.00: Hello Ruuvi Watch! \ No newline at end of file +1.00: Hello Ruuvi Watch! +1.01: Clear gfx on startup. \ No newline at end of file diff --git a/apps/ruuviwatch/ruuviwatch.app.js b/apps/ruuviwatch/ruuviwatch.app.js index 9f5e03b4c..46218a323 100644 --- a/apps/ruuviwatch/ruuviwatch.app.js +++ b/apps/ruuviwatch/ruuviwatch.app.js @@ -123,6 +123,7 @@ require("Storage").write("ruuviwatch.info",{ }, {timeout : 2000, filters : [{ manufacturerData:{0x0499:{}} }] }); } + g.clear(); g.drawImage(require("Storage").read("ruuviwatch.img"), g.getWidth()/2-24, g.getHeight()/2-24); var drawInterval = setInterval(redraw, 1000); diff --git a/apps/ruuviwatch/ruuviwatch.png b/apps/ruuviwatch/ruuviwatch.png index 3a5d0954952c77bbe18348240ff7313dcc1e8915..3737a7e8cb955bc7747861ed1eba36682f99885e 100644 GIT binary patch delta 590 zcmV-U0TLBDAveCk^&%HVS#^jDn$zM7sUQo?^paMm!hfAnRwqvYoz)hXvrrKB zy8qqh!{AQU(BL!K^}olUtd8IpvBr#SnTcE`HKw6(37GP~!wgi6^8@Ck#vRTD6};O< z8-cCHb!J_)8u<732J|*fszeDo_?6IJfj_8w(1#qoe`-sWh(O^s6Di%n*D_s2iir8e z$y2z^KuqQb3V($A{@!E10-eMnH1Uy`D5a%sAiKP@$H$r&-y(9-8fj4bIHjA_h&a^a z8?r?j4P?O&+ag3KwTUV3n4%x=`%K^zLQ8GTXix_kUlSFg#cc;8*%8hwgfU1D{uJv9ct&i1iuJLB@Up2FPY$LOrU0hs5~|bmrs)46)}C_ znz7k4^VFDu9phYls61%!TW^+sWCLyw8t|=9Ar1}xS>}xCe^p5o{Fj!?VJRR910 delta 617 zcmV-v0+#)m1+)c_R)0xJL_t(|0qvOWZR0QuhM5gAf;Kphpb@-*Z-Zuoc!PKYcZ1#r zz72dgfxAJv!CMJd(7+`n%6311>H&!Si1?DCJ}sg`p-?FNWDc|g0FLgba#lP0<;(=T z@f_^Gvp4rj?S4r63kT} zBMA)79-LK}*TmA_hX2Pzrw#2*2!4$uZZq|KF&-nGsA(@k)i}o7#2IZ966QG3Rv^#! zj&{W9wL+Zr>q1E0Pov)oU%RNRAFUpd`R#SVPt*L7a88Yoe5Ld^khy?aXmWFvgYp@ZGnrZ)( z8?>brK;9acbO{}9cRERpM|E%GL3`+#6ncZohY`1=1oND?h+h*}6xvqhgZINekOFK( zq5rgS8Ks6NMn8EHLO9aumStOSMU;M=Q zh;?tH;;xj#F0a#`kc{ee+Sxz%Lj6L8LZMJ7{B&Lc$OOor(K9+P00000NkvXXu0mjf Dtw1bu From 32fb5dc58e272b88810dc58236e003b9eada25d4 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Thu, 6 Jan 2022 21:39:23 +0000 Subject: [PATCH 278/489] Limelight: configurable analogue clock --- apps.json | 15 ++ apps/limelight/ChangeLog | 1 + apps/limelight/README.md | 11 ++ apps/limelight/limelight.app.js | 187 ++++++++++++++++++++++++ apps/limelight/limelight.icon.js | 1 + apps/limelight/limelight.png | Bin 0 -> 929 bytes apps/limelight/limelight.settings.js | 67 +++++++++ apps/limelight/screenshot_limelight.png | Bin 0 -> 2180 bytes 8 files changed, 282 insertions(+) create mode 100644 apps/limelight/ChangeLog create mode 100644 apps/limelight/README.md create mode 100644 apps/limelight/limelight.app.js create mode 100644 apps/limelight/limelight.icon.js create mode 100644 apps/limelight/limelight.png create mode 100644 apps/limelight/limelight.settings.js create mode 100644 apps/limelight/screenshot_limelight.png diff --git a/apps.json b/apps.json index 833c3505e..c4d7624be 100644 --- a/apps.json +++ b/apps.json @@ -5448,5 +5448,20 @@ {"name":"flipper.app.js","url":"flipper.app.js"}, {"name":"flipper.img","url":"flipper.icon.js","evaluate":true} ] + }, + { + "id": "limelight", + "name": "Limelight Clock", + "version": "0.01", + "description": " Simple configurable analogue clock based on the work of @Andreas_Rozek (Simple_Clock)", + "icon": "limelight.png", + "screenshots": [{"url":"screenshot_limelight.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"limelight.app.js","url":"app.js"}, + {"name":"limelight.img","url":"icon.js","evaluate":true} + ] } ] diff --git a/apps/limelight/ChangeLog b/apps/limelight/ChangeLog new file mode 100644 index 000000000..9db0e26c5 --- /dev/null +++ b/apps/limelight/ChangeLog @@ -0,0 +1 @@ +0.01: first release diff --git a/apps/limelight/README.md b/apps/limelight/README.md new file mode 100644 index 000000000..7d80ed985 --- /dev/null +++ b/apps/limelight/README.md @@ -0,0 +1,11 @@ +# Limelight + * Simple configurable analogie clock based on the work of @Andreas_Rozek [Simple_Clock](https://github.com/espruino/BangleApps/tree/master/apps/simple_clock)* + +![](screenshot_limelight.jpg) + +* Selection of different fonts +* 100 less lines of code, demonstrating that there is no need for a custom widget draw method + +Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS +Forum](http://forum.espruino.com/microcosms/1424/) + diff --git a/apps/limelight/limelight.app.js b/apps/limelight/limelight.app.js new file mode 100644 index 000000000..a1af79466 --- /dev/null +++ b/apps/limelight/limelight.app.js @@ -0,0 +1,187 @@ +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +// fonts.google.com +Graphics.prototype.setFontLimelight = function(scale) { + // Actual height 28 (28 - 1) + g.setFontCustom(atob("AAAAAAAAAAAAAAAAAeAAAAAD8AAAAAf4AAAAB/gAAAAH+AAAAAf4AAAAB/gAAAAD8AAAAAHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAPwAAAAH8AAAAD+AAAAD+AAAAB/AAAAA/gAAAAfwAAAAD4AAAAAMAAAAAAAAAAAAAAAAAAAAA/gAAAA//wAAAP//wAAB///wAAP///gAA///+AAH///8AAf///4AD////gAP///+AA////4AD////gAMAAAGAAwAAAYADAAABgAMAAAGAAwAAAwABgAADAAHAAAYAAOAADgAAeAA8AAAfh/AAAAf/wAAAAHgAAAAAAAAAAGAAAAAAYAAAAABAAAAAAMAAAAAAwAAAAAD///+AAf///4AB////gAH///+AAf///4AD////gAP///+AA////4AH////gAf///+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgABAAAeAAOAAH4AAwAA/gAGAAP+AAYAB/4ADAAf/gAMAD/+AAwAf/4ADAH//gAMA//+AAwH//4ADB//9gAOP//GAA///wYAD//+BgAH//gGAAf/8AYAA//ABgAB/4AGAAD+AAYAADAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAHAAAwAAGAAHAAAMAAYAAAwADAEABgAMAwAGAAwDAAYADAMABgAMAwAGAAwDAAYAD////gAP///+AA////4AD////gAP///8AAf///wAB/7//AAD/H/4AAP4f/AAAPA/4AAAAA+AAAAAAAAAAAAAAAAAAAGAAAAAB8AAAAAPwAAAADzAAAAAcMAAAAHgwAAAA8DAAAAHAMAAAB4AwAAAOADAAADwAMAAAcAAwAAD///+AA////4AD////gAP///+AA////4AD////gAP///+AA////4AD////gAP///+AAAAAMAAAAAAwAAAAADAAAAAAcAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAHAAAH4AOAAP/gAcAA+GAAwADAwABgAMDAAGAAwMAAYADAwABgAMDAAGAAwMAAYADA///gAMD//+AAwP//4ADA///AAMB//8AAwH//wADAP/+AAIAf/wAAAA/+AAAAB/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAD/8AAAA//8AAAH//4AAB///wAAH///gAA////AAH///8AAf///4AD////gAP///+AAwAAAYADAYABgAMBgAGAAwGAAYADAYABgAMBgAGAAwGAAwABgYADAAHAwAYAAMDgHAAAAHh4AAAAP/AAAAAHgAAAAAAAAAAAAAAAA+AAAAAD4AAAAAMAAAAAAwAAAAADAAAAAAMAA/+AAwB//4ADB///gAM///+AA////4AD////gAP///+AA////4AD////gAP///+AA////4AD//+AAAP/wAAAA/wAAAAD4AAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwAAA/g/wAAH/GDgAA/+wGAAD//AMAAf/4AwAB//gBgAP//AGAAx/+AYADD/4BgAMH/wGAAwP/AYACA/+BgAMB/8GAAwD/wYADAP/jgAMBf/+AAYH//wABgz//AADHH/4AAH4f/gAAOA/8AAAAB/AAAAAAwAAAAAAAAAAAAAAAAAeAAAAAH/AAAAB8eAAAAGAcBgAAwAwHAAGABgMAAYAGAYADAAIBgAMAAwGAAwADAYADAAYBgAMAAgGAAwAAAYAD////gAP///+AA////wAB////AAH///4AAP///AAA///8AAA///AAAB//4AAAB/+AAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfAeAAAD8D8AAAf4f4AAB/h/gAAH+H+AAAf4f4AAB/h/gAAD8D8AAAHgHgAAAAAAAAAAAAAAA="), 46, atob("DQ0aExgZHRkbGBsbDQ=="), 40+(scale<<8)+(1<<16)); +} + +// fonts.google.com +Graphics.prototype.setFontGochiHand = function(scale) { + // Actual height 29 (31 - 3) + g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAB4AAAAAD4AAAAAB4AAAAAB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAH/gAAAD//gAAD///gAD///+AAH///AAAH//gAAAH/wAAAAHwAAAAAAAAwAAAAAP+AAAAA//gAAAB//wAAAD//4AAAD8P4AAAHwD8AAAHgB8AAAPgA8AAAPAA8AAAPAA8AAAPAA8AAAPgA8AAAPgA8AAAPgB8AAAHwB4AAAH4D4AAAD+PwAAAD//gAAAB//gAAAA/+AAAAAP8AAAAAAAAAAAAAAAAAAAcAAAAAA8AAAAAB8AAAAAD4AAAAAD4AAAAAHwAAAAAHgAAAAAPgAAAAAPgAAAAAf/AAAAAf//wAAAP//wAAAH//wAAAAf/wAAAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAA8AAAeAB8AAA+AD8AAB+AH8AAB4AP8AAD4AP8AADwAf8AADwB+8AAD4D88AAD4H48AAD//w+AAB//g+AAB//A+AAA/8A+AAAPwA+AAAAAA+AAAAAAcAAAAAAIAAAAAAAAAA8AAAAAB8AAAAAB8AAAAAB4AHgAAD4AHwAAD4AH4AADwPH8AADwfB8AADwfA8AAD4fA+AAD4fA+AAB//A+AAB//A+AAA//A8AAA//x8AAAPP/8AAAAH/4AAAAD/wAAAAB/gAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAB4AAAAAH8AAAAAP+AAAAA/+AAAAB/+AAAAD8+AAAAP4+AAAB/weAAAD/weAAAD/8eAAAB///AAAA///AAAAH//8AAAAf//AAAAD//AAAAAf/AAAAAf+AAAAAfAAAAAAMAAAAAAAAAAAAAAAAAAPA/gAAAfh/wAAA/x/4AAA/x/4AAB/4/8AAB74B8AAB58A8AAB58A+AAB5+A+AAB4+A+AAB4+A+AAB4fA+AAB4fg+AAB4Pg8AAB4P58AAB4H/4AAB4D/4AAB4D/wAAAQA/gAAAAAAAAAAAAAAAAAAAAAAAAAf8AAAAB/+AAAAD//gAAAH//gAAAPwfwAAAPgf4AAAfAf4AAAeA/8AAAeA98AAAeA88AAAfB48AAAfB48AAAPB48AAAOB48AAAAB98AAAAB/8AAAAA/4AAAAA/wAAAAAfgAAA8AAAAAA8BAAAAA8HgAAAA8HgAAAA8HgAAAA8HgAAAA8HgAAAA+HgAAAA+HgAAAA+HgAAAAfHgAAAAf//+AAAf//+AAAP//+AAAH//8AAAAPwAAAAAHgAAAAAHwAAAAAHwAAAAAHwAAAAADwAAAAADgAAAAAAAAAAAAAAAAAAAB/AAAAP3/wAAAf//wAAA///4AAA//D8AAB9+B8AAB4+A8AAB4+A+AAB4+A+AAB4+A+AAB8+A+AAB8+A+AAA/+A8AAA//A8AAAf/x8AAAP//4AAAH//wAAAAD/gAAAAB/AAAAAAAAAAAAAAAAAAD/AAAAAD/gAAAAH/gAAAAP/wAAAAPHwAAAAPDwAAAAeDwAAAAeDwAAAAeDwAAAAeHwAAAAeHgAAAAePgAAAAefAAAAAf/AAAAAf///gAAf///wAAP///wAAP///gAAH8AAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8BwAAAA8B4AAAA+D4AAAA8B4AAAAcB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="), 46, atob("DQoYERUWFBYVFhcVDQ=="), 42+(scale<<8)+(1<<16)); +} + +// free for commercial use +// https://www.1001fonts.com/search.html?search=Grenadier+NF +Graphics.prototype.setFontGrenadierNF = function(scale) { + // Actual height 39 (39 - 1) + g.setFontCustom(atob("AAAAAAAAAAAAB4AAAAAAPAAAAAAB4AAAAAAAAAAAAAAAAAAAAAAEAAAAAAPgAAAAA/8AAAAB//gAAAD//4AAAP//wAAAf//AAAB//+AAAD//8AAAB//wAAAAP/gAAAAB+AAAAAAMAAAAAAAAAAAAAAAAB4AAAAAD/8AAAAB//4AAAA///wAAAP8D/AAAD8AD8AAA/AAPwAAPgAAfAAD4AAB8AAeAAAHgAHwAAA+AA8AAADwAHgAAAeAB4AAAB4APAAAAPAB4AAAB4APAAAAPAB4AAAB4APAAAAPAB4AAAB4APAAAAPAB4AAAB4APgAAAfAA8AAADwAHwAAA+AAeAAAHgAD4AAB8AAPgAAfAAA+AAHwAAD8AD8AAAP8D/AAAA///wAAAD//8AAAAH/+AAAAAD8AAAAAAAAAAAAAAAAAAABAAAAAAAcAAAAAAHwAAAAAB8AAAAAAfgAAAAAH/////AB/////4AP/////AB/////4AAAAAAAAAAAAAAAAAAAAADAAAAAAA4APAAAAPAB4AAAD4APAAAA/AB4AAAP4APAAAD/AB8AAA/4AHgAAPvAA8AAD54ADwAB+PAAfAAfh4AB8AH4PAAPwD+B4AA///gPAAD//wB4AAH/4APAAAP8AAAAAAAAAAAAAAAAAAAPAAAAHAB4AAAB4APAAAAPAB4PAAB4APB4AAPAB+/gAB4AH/8AAfAAf/wADwAB/fAA+AABD8APgAAAPwH4AAAA//+AAAAD//gAAAAH/4AAAAAP8AAAAAAAAAAAAAAAAAAAAAAYAAAAAAPAAAAAAH4AAAAAD/AAAAAB/4AAAAA//AAAAAf94AAAAH+PAAAAD/B4AAAB/gPAAAA/wB4AAAf8APAAAP////4AH/////AD/////4AAAAAPAAAAAAA4AAAAAAAAAAAAAAAAAAAIAAPAAAPAAB4AAf4AAPAA//gAB4AP/8AAPAB/3gAB4APg8AAfAB4DwADwAPAfAA+AB4B8APgAPAP4H4AB4A//+AAPAB//gAB4AH/4AAAAAP8AAAAAAAAAAAAAB4AAAAAD/4AAAAA//wAAAAf//AAAAP+H8AAAH+AHwAAB/gAfAAA/4AB4AAf+AAPAAP/wAA8AH+eAAHgB/ngAA8APw8AAHgB4HgAA8AMA8AAHgAADwAA8AAAeAAPgAAD4AB4AAAPgAfAAAA+AHwAAAH4D8AAAAf//AAAAB//wAAAAD/8AAAAAH8AAAAAAAAAAAAAAAAAAAAAAAYAAAAAAfAB4AAAP4APAAAH/AB4AAH/gAPAAD/wAB4AD/wAAPAB/4AAB4A/8AAAPA/8AAAB4f+AAAAPP+AAAAB//AAAAAP/gAAAAB/gAAAAAPwAAAAAB4AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAD/gAAAAB//AAAAAf/+AAAAH//4AAAB+AfgAA+fAB8AAP/wAHwAD/+AAeAA//gAB4APj8AAPAB4PAAB4APB4AAPAB4PAAB4APB4AAPAB8fgAB4AH/8AAPAAf/wADwAB/eAA+AADj4APgAAAPwD8AAAA///AAAAD//wAAAAP/4AAAAAf8AAAAAAAAAAAB4AAAAAB/4AAAAA//wAAAAP//AAAAD+H8AAAA/AHwAAAHgAfAAAB8AB4AAAPAAHgAADwAA8AAAeAAHgBADwAAeA4AeAADwfADwAAeP4AeAAD3+ADwAA9/gAfAAH/wAB4AB/4AAPgAf8AAA+AH+AAAD8B/gAAAP//wAAAA//4AAAAD/8AAAAAD+AAAAAAAAAAAAAAAAAAAAAAAeB4AAAADwPAAAAAeB4AAAAAAAAAAAAAAAA=="), 46, atob("Bg4kChURExEaFBoaBg=="), 45+(scale<<8)+(1<<16)); +} + +// fonts.google.com +Graphics.prototype.setFontMonoton = function(scale) { + // Actual height 38 (37 - 0) + g.setFontCustom(atob("AAAAAAAAAAEkAAAAAbYAAAABtgAAAAG2AAAAAbYAAAABtgAAAAG2AAAAASQAAAAAAAAAAAAAAAAAAAB4AAAAB/gAAAB/gAAAB/h4AAB/h/AAB/h/CAB/h/D4B/h/D/B/j/D/APj/D/AAD/D/AAB/D/AAAPD/AAAAD/AAAAB/AAAAAPAAAAAAAAAAAAAAAAAAAAAD/wAAAB//4AAAfAD4AAHj/x4AA5//5wAHfAB5gAzj/5zAHc//5mAbvDBzcDdz/zmwNu+HzZhs3ADu2G2YAHbYbbAANthtsAA2yG2wABtsbbAAG2xtsAA2yG2wADbYbZgAdthm3ADs2DZv/92wM3P/O7AbvAD3YB3P/87gDvP/HMAHPgD7gAOP/+cAAfH+HgAAfgH4AAAf/+AAAAD+AAAAAAAAAAAAAAAAbYAAAABtgAAAAG2AAAAAbYAAAABt////wG3////AbYAAAABt////wG3////AbYAAAABt////wG3////AbYAAAABt////wEn///+AAAAAAAAAAAAAADQAAAUgdoAAF7BtsAA3sG2wAOewbbAB17BtsAc3sG2wDnewbbAdx7BtsHO3sG2w7newbbPd57Btv3OXsGzc73ewZuPc57A2f3nHsDMc5wewG8POB7Ac/zgHsA4Y8AewB+fABSAB/wAAAAAAAAAAAAAAAAA0AAAAsHbAAAbYbbAANthtsAA22G2wADbYbbJJNthts22W2G2zbZpIbbNtm2xts22bbG2zbZJIbbNttthtv2322Gzfbu7YNuO3HZg3f7P5sDuf2OMwGeHPHmAO/2f8wAccOOOAA/PfvwAA/4f8AAAAAAAAAAAAAAAAABkgAAAA/bAAAAPtsAAAD52wAAA8fbAAAfH9sAAHz42wAB8+fbAAePn9sADjx82wAJ8ePbAAfPj9sADz482wAI+fDbAAfHwNsADx8A2wAM+D/b+APgP9v4D4AA2wAMAD/b+AAAP9v4AAAA2wAAAADSAAAAAAAAAAAAAAAAAAAAMAaf/8AwBt//wJgG2AAA3Abf/8JsBt//w2wG2AABtgbf/822BtgADbYG2NvNtgbY28SSBtjbxtsG2NvG2gbY28SSBtjbzbYG2Nv9tgbY23m2BtjNg2YG2Gz+bAbYZnzcBtgzg5gG2Dn/MASQHHzgAAAPg8AAAAP/gAAAAHwAAAAAAAAAAAAAAAAA//4AAAf//8AAHgAB4AA4//44AGf//5wAzgAB7AGY//52AbP//7MDZwABmwNu//zZhs3//m2G25LTbYbbN7Nthts3sSSG2zexpIbbN7G2xts3sSaG2zezbYbbN7Nthts3v22GbDbezYNsG+HbA3Qbf7sBsB3edgGQDPHuAMAGf9wAQAOOOAAAAfvwAAAAf8AAAAAAAAAAAAAABtgAAAAG2AAAAAbYAAAABtgAAAAG2AAAAAbYAAAMBtgAAPwG2AAP8AbYAf4cBtgf4fwG0f4f4Aaf4f4cAf4f4fwH4f4f4AYf4f4cA/4/w/wHw/w/wAQ/w/wAA/w/wAAHw/wAAAQ/wAAAA/wAAAAHwAAAAAAAAAAAAAAAAAAAA+AfAAAf/P/gADwPwHgA5/OfnAHP+f/OAZwO4HYDM+d/MwNn+3/bBuwZsM2G2e2+bYbb7b9thtskk2yG2zbZtobbNtm2xts22bbG2zbZtsbbNtm2xts22bbG2zbZNsbbNttshtv2322GzfZu7YNuO3HZg3f7v5sBud3OcwHfPvHmAOf3P8wAcAeAOAAf///wAA/4f8AAAAAAAAAAAAAAAAfwAAAAH/wAAAA4DwAIAGfzgAwAz/3AJgGYDsA2AzP2YDsDZz9g2wNszbDNhs3ns22G2zezbYbbN5NthtsTkSSG2xORtMbbE5G2xts3sySG2zezbYbbN7Nths2ABm2Cbf/+3YNmf/nbAzeAB7MBuf/+dgHcP/DuAO///9wAc///OAA8AADwAA///8AAA///AAAAAAAAAAAAAAAAAAAAAAA2xtgAADbG2AAANsbYAAA2xtgAADbG2AAANsbYAAAkhJAAAAAAAAAAAAAAAA"), 46, atob("ChIiERcYGRwfGSAfCw=="), 40+(scale<<8)+(1<<16)); +} + +function loadSettings() { + settings = require("Storage").readJSON(SETTINGS_FILE,1)||{}; + settings.secondhand = settings.secondhand||false; + settings.font = settings.font||"Limelight"; + settings.vector = settings.vector||false; + settings.vector_size = settings.vector_size||42; + UPDATE_PERIOD = (settings.secondhand ? 1000 : 60000); +} + +var UPDATE_PERIOD; +var drawTimeout; + +const CenterX = g.getWidth()/2; +const CenterY = (g.getHeight()/2) + (Bangle.appRect.y/2); +const outerRadius = (g.getHeight() - Bangle.appRect.y)/2; + +function debug(o) { + //console.log(o); +} + +debug("limelight.app.js"); +debug("CenterX=" + CenterX); +debug("CenterY=" + CenterY); +debug("outerRadius=" + outerRadius); +debug("y12=" + (CenterY - outerRadius)); +debug("y6=" + (CenterY + outerRadius)); + +const HourHandLength = outerRadius * 0.5; +const HourHandWidth = 2*3, halfHourHandWidth = HourHandWidth/2; +const MinuteHandLength = outerRadius * 0.7; +const MinuteHandWidth = 2*2, halfMinuteHandWidth = MinuteHandWidth/2; +const SecondHandLength = outerRadius * 0.9; +const SecondHandOffset = 6; + +const twoPi = 2*Math.PI; +const Pi = Math.PI; +const halfPi = Math.PI/2; + +let HourHandPolygon = [ + -halfHourHandWidth,halfHourHandWidth, + -halfHourHandWidth,halfHourHandWidth-HourHandLength, + halfHourHandWidth,halfHourHandWidth-HourHandLength, + halfHourHandWidth,halfHourHandWidth, +]; + +let MinuteHandPolygon = [ + -halfMinuteHandWidth,halfMinuteHandWidth, + -halfMinuteHandWidth,halfMinuteHandWidth-MinuteHandLength, + halfMinuteHandWidth,halfMinuteHandWidth-MinuteHandLength, + halfMinuteHandWidth,halfMinuteHandWidth, +]; + +let transformedPolygon = new Array(HourHandPolygon.length); + +function transformPolygon (originalPolygon, OriginX,OriginY, Phi) { + let sPhi = Math.sin(Phi), cPhi = Math.cos(Phi), x,y; + + for (let i = 0, l = originalPolygon.length; i < l; i+=2) { + x = originalPolygon[i]; + y = originalPolygon[i+1]; + + transformedPolygon[i] = OriginX + x*cPhi + y*sPhi; + transformedPolygon[i+1] = OriginY + x*sPhi - y*cPhi; + } +} + +function setHandsFont() { + if (settings.vector) { + g.setFont('Vector', settings.vector_size); + return; + } + + if (settings.font == "GochiHand") + g.setFontGochiHand(); + else if (settings.font == "Grenadier") + g.setFontCabinSketch(); + else if (settings.font == "Monoton") + g.setFontMonoton(); + else + g.setFontLimelight(); +} + +function drawNumbers() { + g.setColor(g.theme.fg); + setNumbersFont(); + + g.setFontAlign(0,-1); + g.drawString('12', CenterX, CenterY - outerRadius); + + g.setFontAlign(1,0); + g.drawString('3', CenterX + outerRadius, CenterY); + + g.setFontAlign(0,1); + g.drawString('6', CenterX, CenterY + outerRadius); + + g.setFontAlign(-1,0); + g.drawString('9', CenterX - outerRadius,CenterY); +} + +function drawHands () { + let now = new Date(); + let Hours = now.getHours() % 12; + let Minutes = now.getMinutes(); + let Seconds = now.getSeconds(); + + let HoursAngle = (Hours+(Minutes/60))/12 * twoPi - Pi; + let MinutesAngle = (Minutes/60) * twoPi - Pi; + let SecondsAngle = (Seconds/60) * twoPi - Pi; + + g.setColor(g.theme.fg); + transformPolygon(HourHandPolygon, CenterX,CenterY, HoursAngle); + g.fillPoly(transformedPolygon); + transformPolygon(MinuteHandPolygon, CenterX,CenterY, MinutesAngle); + g.fillPoly(transformedPolygon); + + if (settings.secondhand) { + let sPhi = Math.sin(SecondsAngle), cPhi = Math.cos(SecondsAngle); + g.setColor('#FF0000'); + g.drawLine( + CenterX + SecondHandOffset*sPhi, + CenterY - SecondHandOffset*cPhi, + CenterX - SecondHandLength*sPhi, + CenterY + SecondHandLength*cPhi + ); + } +} + +function draw() { + g.setColor(g.theme.bg); + g.fillRect(Bangle.appRect); + + drawHands(); + drawNumbers(); + queueDraw(); +} + +// schedule a draw for the next minute +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, UPDATE_PERIOD - (Date.now() % UPDATE_PERIOD)); +} + +// Stop updates when LCD is off, restart when on +Bangle.on('lcdPower',on=>{ + if (on) { + draw(); // draw immediately, queue redraw + } else { // stop draw timer + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } +}); + +loadSettings(); +Bangle.setUI('clock'); +draw(); diff --git a/apps/limelight/limelight.icon.js b/apps/limelight/limelight.icon.js new file mode 100644 index 000000000..06f93e2ef --- /dev/null +++ b/apps/limelight/limelight.icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwIdah/wAof//4ECgYFB4AFBg4FB8AFBj/wh/4AoM/wEB/gFBvwCEBAU/AQP4gfAj8AgPwAoMPwED8AFBg/AAYIBDA4ngg4TB4EBApkPKgJSBJQIFTMgIFCJIIFDKoIFEvgFBGoMAnw7DP4IFEh+BAoItBg+DNIQwBMIaeCKoKxCPoIzCEgKVHUIqtFXIrFFaIrdFdIwAV")) diff --git a/apps/limelight/limelight.png b/apps/limelight/limelight.png new file mode 100644 index 0000000000000000000000000000000000000000..cf057046be6eca51564a213bc3e7307271464009 GIT binary patch literal 929 zcmV;S177@zP)hL^4Q9~j~`7LX9JB(!Q` zf!g{&{RcFW&Q~mny+EQd5wRkG(GU|*v#i00#krWf=gz{s+-Te{nPTqF`ObG{=bo84 z7wV|v|Hht3JPkk}FaUG|9Y7m!Ao=|p@Bx?yW`SwoCGazne{UQEt^-TJmSbB2t^w^e zR}HiRcY*JgVs~m~;0|!8R^p4mY6RiBtpaENr0^Uv>(vCT0r!Cspcg0r`;t~jo{azx zfb|`CCKF##(F8oL;_xjnl#FrV8%ADg6Xz30z8#UnEWQMc5jI;nU_9Z{{Eq{QD8L7t!&STXpy9ZFm@kj^1Fem7{l-O!eBYr8>b)d^b3W}9W~#A6U*g95Oi>^=c4 z)~Zv`8K;EXvhfK3pp)!7am&FTkR7(HNX8sFd;lS+^%_N}!U1DH{Ly|K9>B#6_hueBM`PvzgXPMrIx>vGBiU)6Z4 zEpn3sb9fkCLB-z-YcKpmwJ#|r9RWl zC5~dFfRx^~zcZo4lLpcS%$dU%U1Vo|3%C)3JcraOHF*iC9^?bK^S~v{rNu|U-T>|j zG$FN0?PUAC7)9=|wrEE3yiS#A@zILA+sGlcN|VDaIFIb+1>`8+h@2|>kwB-& z?yx%JM4NdN29eBAO@MFvNQ4*G7A;7*Pj7ZUZ3CJ0gS8T$MjKKwTeK9b&o&dl(GUSK zKeKitb( font_options[v], + onchange: v => { + s.font = font_options[v]; + save(); + }, + }, + 'Vector Font': { + value: s.vector, + format: () => (s.vector ? 'Yes' : 'No'), + onchange: () => { + s.vector = !s.vector; + save(); + }, + }, + 'Vector Size': { + value: settings.vector_size, + min: 24, + max: 56, + step: 6, + onchange: v => { + settings.vector_size = v; + save(); + } + }, + 'Second Hand': { + value: s.secondhand, + format: () => (s.secondhand ? 'Yes' : 'No'), + onchange: () => { + s.secondhand = !s.secondhand; + save(); + }, + } + }); +}) diff --git a/apps/limelight/screenshot_limelight.png b/apps/limelight/screenshot_limelight.png new file mode 100644 index 0000000000000000000000000000000000000000..9affc3d1cbb9be291270cb57cd1474e03b685ea3 GIT binary patch literal 2180 zcmeHJ`!m~#7LSNFq7QG4TD79mCYD=m?;?bf2t`|^K}kwI(xOFMA!V(vUOPogqtPx) zwBp$kY0?!DtKZ#A>(yv(SCxupNUsVNgnHLaXZH8|2i$vR&iR}<^O^a~oSE~PlXvO_ zX(z%Q0f9hv`uY$~YmoOf;oCH|S*W0DK?8cLOw|IFED~c|;Q4-U9~) zer&36Ls`wW^pT=>0|PeRk*>q{zySHX*^Cw=)L&!OKwFX}`itSpWNT98-xPg%uxZ<5 zs4MIF3-B+3s;8nnb6!6g&&Cpa+netS1h0@1+9x^o^0CFRvPq};>_>>_ZU z^1+0+VpY!T_nuaB-G<4tc0hj`xNIi=Nb0$X6B|dI`!*XiiH{KIX!W3AIF)I_YHC0? zbzFaCdNd5rTTD0tqjs>*4Q6j_N5VJGd`Wap>^nK$QqHQy7kg+re6g|DC0~!VyRF}$ zs~d`J@2uK8Z5(?}GCJSdq&tTthCA$jc@WOi#vUksati`=@H!c#qXi?MvWZ4&!Kgp6 z|3E!L|0sk!f72+0wg`jAzle+B=E23oV;>ea@8C&%B^1r0nM8 zj{NDAH%t<8(mwMdaQM{Y0)|fDd%PJ!m6*RfW70f=EWgz*_4EDvM7(22ZUfb9eyW$U z2A9r5)rc5$JIRf7+o#yyL0S+xWI+-2!RS5HBLL3q0QT~c1e>I5oBgs!cZ)U+tc$FNDaHL27xA$IjEyF>+Y?g%2qrelFW z)-KN!oDW9fX!kErM5lo?mQdZY$Crc0_b!XFyvOaOZC7HUMSr{mgLPl&o*d*@qtD*h zp|&SeM6aQwR~T{j`9lKXSbx={^{M`XH>fh9-&5}BK>!ts>t6RQ(hr-b#gvLZH$LNz z^1%@1@?ITwspu=E7(^|23ma#+j#sJZ_R$xT8^kK&-M~u%3G#-?Xy%yPt0R-FC6w=o6mQcEU8hw(~o#iq-) zJkx57KP%jg`l*f|i5M$sOGL3tkeoy^VTuV2W8b>0M{SpgGTak# zL6mh`f#X`vq!PUZKg5%iBebwuu$J-KpUWW7$9cuH{n;RS)Hq1v-A4l#8e#fx^M5%X zuQ4p!#XN#^;Ro4;+U8O|1uO zZL`7nDn*!vVe);~pBkGBV7dNZ?0;vCD`qy|{M+>()y}q>w*ulzJVD@kM&|qnB+=s~ literal 0 HcmV?d00001 From e5dad4094be9e05a723850bafdad2c19548b1623 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Thu, 6 Jan 2022 21:58:44 +0000 Subject: [PATCH 279/489] fixed apps.json for limelight --- apps.json | 4 ++-- apps/limelight/README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index c4d7624be..98ce3e5d5 100644 --- a/apps.json +++ b/apps.json @@ -5460,8 +5460,8 @@ "tags": "clock", "supports": ["BANGLEJS","BANGLEJS2"], "storage": [ - {"name":"limelight.app.js","url":"app.js"}, - {"name":"limelight.img","url":"icon.js","evaluate":true} + {"name":"limelight.app.js","url":"limelight.app.js"}, + {"name":"limelight.img","url":"limelight.icon.js","evaluate":true} ] } ] diff --git a/apps/limelight/README.md b/apps/limelight/README.md index 7d80ed985..aa0c359b9 100644 --- a/apps/limelight/README.md +++ b/apps/limelight/README.md @@ -1,5 +1,5 @@ # Limelight - * Simple configurable analogie clock based on the work of @Andreas_Rozek [Simple_Clock](https://github.com/espruino/BangleApps/tree/master/apps/simple_clock)* + * Simple configurable analogue clock based on the work of @Andreas_Rozek [Simple_Clock](https://github.com/espruino/BangleApps/tree/master/apps/simple_clock)* ![](screenshot_limelight.jpg) From 59c7cb49d6d33cb87a95d85440105faf64532698 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Thu, 6 Jan 2022 22:10:56 +0000 Subject: [PATCH 280/489] limelight fixed apps.json, added settings file --- apps.json | 1 + apps/limelight/limelight.app.js | 2 ++ 2 files changed, 3 insertions(+) diff --git a/apps.json b/apps.json index 98ce3e5d5..64b5c358e 100644 --- a/apps.json +++ b/apps.json @@ -5461,6 +5461,7 @@ "supports": ["BANGLEJS","BANGLEJS2"], "storage": [ {"name":"limelight.app.js","url":"limelight.app.js"}, + {"name":"limelight.settings.js","url":"limelight.settings.js"}, {"name":"limelight.img","url":"limelight.icon.js","evaluate":true} ] } diff --git a/apps/limelight/limelight.app.js b/apps/limelight/limelight.app.js index a1af79466..f17114f2d 100644 --- a/apps/limelight/limelight.app.js +++ b/apps/limelight/limelight.app.js @@ -27,6 +27,8 @@ Graphics.prototype.setFontMonoton = function(scale) { g.setFontCustom(atob("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"), 46, atob("ChIiERcYGRwfGSAfCw=="), 40+(scale<<8)+(1<<16)); } +const SETTINGS_FILE = "limelight.json"; + function loadSettings() { settings = require("Storage").readJSON(SETTINGS_FILE,1)||{}; settings.secondhand = settings.secondhand||false; From 33a10e53932fa730c0493a93d6e7c7f08511ed99 Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Thu, 6 Jan 2022 22:58:12 +0100 Subject: [PATCH 281/489] ptlaunch: Improve documentation --- apps/ptlaunch/README.md | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/apps/ptlaunch/README.md b/apps/ptlaunch/README.md index cf75315a9..12c205980 100644 --- a/apps/ptlaunch/README.md +++ b/apps/ptlaunch/README.md @@ -2,11 +2,19 @@ Directly launch apps from the clock screen with custom patterns. -## Usage +## Installation and Usage + +Install Pattern Launcher alongside your main laucher app. +_Do not delete that launcher!_ +Pattern Launcher is designed as an additional app launching utility, not as a replacement for the main launcher. + +In the main launcher, start Pattern Launcher in the app menu to assign the pattern configuration (see below). +Note that this actually among the applications, _not_ in the application settings! Create patterns and link them to apps in the Pattern Launcher app. Then launch the linked apps directly from the clock screen by simply drawing the desired pattern. +Note that this does only work in the clock screen, not if other applications run. ## Add Pattern Screenshots @@ -28,7 +36,8 @@ Then launch the linked apps directly from the clock screen by simply drawing the ## Detailed Steps -From the main menu you can: +The main menu of Pattern Launcher is accessible from the _application_ starter of the main launcher. +From there you can: - Add a new pattern and link it to an app (first entry) - To create a new pattern first select "Add Pattern" @@ -60,6 +69,16 @@ Make sure the watch is unlocked before you start drawing. If this bothers you, y Please note that drawing on the clock screen will not visually show the pattern you drew. It will start the app as soon as the pattern was recognized - this might take 1 or 2 seconds! If still nothing happens, that might be a bug, sorry! +4. Where can I configure the patterns? + +You have to start the "Pattern Launcher" app from the main app launcher's app selection. + +5. Do I have to delete my former app launcher so that Pattern Launcher is the only installed launcher? + +No! Pattern Launcher works alongside another "main" launcher. +If you have deleted that one, you do not have a general purpose app launcher any more and cannot access Pattern Launcher's configuration. +If you already have deleted your main launcher accidentially, just reinstall it from the app loader. + ## Authors Initial creation: [crazysaem](https://github.com/crazysaem) @@ -67,3 +86,5 @@ Initial creation: [crazysaem](https://github.com/crazysaem) Improve pattern detection code readability: [PaddeK](http://forum.espruino.com/profiles/117930/) Improve pattern rendering: [HughB](http://forum.espruino.com/profiles/167235/) + +Doc additions: [dirkhillbrecht](http://forum.espruino.com/profiles/182498/) From cc7cbd24e1a7de0115fb87bb9250cc449865109c Mon Sep 17 00:00:00 2001 From: hughbarney Date: Thu, 6 Jan 2022 22:18:46 +0000 Subject: [PATCH 282/489] limelight fixes --- apps/limelight/limelight.app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/limelight/limelight.app.js b/apps/limelight/limelight.app.js index f17114f2d..c4a599c96 100644 --- a/apps/limelight/limelight.app.js +++ b/apps/limelight/limelight.app.js @@ -95,7 +95,7 @@ function transformPolygon (originalPolygon, OriginX,OriginY, Phi) { } } -function setHandsFont() { +function setNumbersFont() { if (settings.vector) { g.setFont('Vector', settings.vector_size); return; From bce36e9afc5e8e68ac508c11436bfe7c160020dd Mon Sep 17 00:00:00 2001 From: hughbarney Date: Thu, 6 Jan 2022 23:29:38 +0000 Subject: [PATCH 283/489] limelight fixes --- apps.json | 2 +- apps/limelight/limelight.app.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 64b5c358e..3e63507c7 100644 --- a/apps.json +++ b/apps.json @@ -5453,7 +5453,7 @@ "id": "limelight", "name": "Limelight Clock", "version": "0.01", - "description": " Simple configurable analogue clock based on the work of @Andreas_Rozek (Simple_Clock)", + "description": "Simple configurable analogue clock based on the work of @Andreas_Rozek (Simple_Clock)", "icon": "limelight.png", "screenshots": [{"url":"screenshot_limelight.png"}], "type": "clock", diff --git a/apps/limelight/limelight.app.js b/apps/limelight/limelight.app.js index c4a599c96..af4a99a38 100644 --- a/apps/limelight/limelight.app.js +++ b/apps/limelight/limelight.app.js @@ -46,7 +46,7 @@ const CenterY = (g.getHeight()/2) + (Bangle.appRect.y/2); const outerRadius = (g.getHeight() - Bangle.appRect.y)/2; function debug(o) { - //console.log(o); + console.log(o); } debug("limelight.app.js"); @@ -55,6 +55,7 @@ debug("CenterY=" + CenterY); debug("outerRadius=" + outerRadius); debug("y12=" + (CenterY - outerRadius)); debug("y6=" + (CenterY + outerRadius)); +debug("appRect=" + Bangle.appRect); const HourHandLength = outerRadius * 0.5; const HourHandWidth = 2*3, halfHourHandWidth = HourHandWidth/2; From a31b22d3fbad98d3b325fc7f46e4a1c8bfd5f292 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 7 Jan 2022 00:38:15 +0000 Subject: [PATCH 284/489] limelight sorted icon and png --- apps/limelight/limelight.app.js | 42 +++++++++++++++++---------- apps/limelight/limelight.icon.js | 2 +- apps/limelight/limelight.png | Bin 929 -> 318 bytes apps/limelight/limelight.settings.js | 6 ++-- 4 files changed, 31 insertions(+), 19 deletions(-) diff --git a/apps/limelight/limelight.app.js b/apps/limelight/limelight.app.js index af4a99a38..f41b050d1 100644 --- a/apps/limelight/limelight.app.js +++ b/apps/limelight/limelight.app.js @@ -41,6 +41,16 @@ function loadSettings() { var UPDATE_PERIOD; var drawTimeout; + +/* + * This calculation assumes that there will never be widgets on the + * bottom but it could just as easily be adjusted. If only 1 widget + * is loaded at the top Bangle.appRect changes to report as if + * widgets were loaded at the bottom as well. The other option would + * be for Bangle.appRect to adjust for different combinations EG: no + * widgets, wigets on top, widgets on bottom and widgets on top and + * bottom areas. + */ const CenterX = g.getWidth()/2; const CenterY = (g.getHeight()/2) + (Bangle.appRect.y/2); const outerRadius = (g.getHeight() - Bangle.appRect.y)/2; @@ -96,22 +106,6 @@ function transformPolygon (originalPolygon, OriginX,OriginY, Phi) { } } -function setNumbersFont() { - if (settings.vector) { - g.setFont('Vector', settings.vector_size); - return; - } - - if (settings.font == "GochiHand") - g.setFontGochiHand(); - else if (settings.font == "Grenadier") - g.setFontCabinSketch(); - else if (settings.font == "Monoton") - g.setFontMonoton(); - else - g.setFontLimelight(); -} - function drawNumbers() { g.setColor(g.theme.fg); setNumbersFont(); @@ -157,6 +151,22 @@ function drawHands () { } } +function setNumbersFont() { + if (settings.vector) { + g.setFont('Vector', settings.vector_size); + return; + } + + if (settings.font == "GochiHand") + g.setFontGochiHand(); + else if (settings.font == "Grenadier") + g.setFontGrenadierNF(); + else if (settings.font == "Monoton") + g.setFontMonoton(); + else + g.setFontLimelight(); +} + function draw() { g.setColor(g.theme.bg); g.fillRect(Bangle.appRect); diff --git a/apps/limelight/limelight.icon.js b/apps/limelight/limelight.icon.js index 06f93e2ef..9e886bbf8 100644 --- a/apps/limelight/limelight.icon.js +++ b/apps/limelight/limelight.icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwwIdah/wAof//4ECgYFB4AFBg4FB8AFBj/wh/4AoM/wEB/gFBvwCEBAU/AQP4gfAj8AgPwAoMPwED8AFBg/AAYIBDA4ngg4TB4EBApkPKgJSBJQIFTMgIFCJIIFDKoIFEvgFBGoMAnw7DP4IFEh+BAoItBg+DNIQwBMIaeCKoKxCPoIzCEgKVHUIqtFXIrFFaIrdFdIwAV")) +require("heatshrink").decompress(atob("lksgIqngf/wAFC//+AgUch/4AgMBwAQEh/8Dgf/4AKOEAQKCAYUB//gAoU/DQkPBQYVBGx5SDBQIbDBR0GEAlgFYcHGwh4B+CDHRwL04")); diff --git a/apps/limelight/limelight.png b/apps/limelight/limelight.png index cf057046be6eca51564a213bc3e7307271464009..b1744b28eab888dc537519f74401e020471b0b7e 100644 GIT binary patch literal 318 zcmV-E0m1%>P)Px#_(?=TR9Hvtn9&M=APhz4|9`Y$B#4yV%`Fpd&#{ij>(r8nWZCFR1P-1p8V(jL zG`x-Bobm3MQkhuWGaU&HXpd+Cp8{@SpFWNZNCWNyJo@0TfRPj;z@-jqdCD+>0RuGL zOF}Y?=J(8c^zrfySOe=0{06st<7ffCfOR)~x5!5W(Z*ppa2=oqeEFi&LKE21hc%Xe zV;DUE5txza445KOHv^=9qB|f`%e--H3yiF6#4u{tY`DhChL^4Q9~j~`7LX9JB(!Q` zf!g{&{RcFW&Q~mny+EQd5wRkG(GU|*v#i00#krWf=gz{s+-Te{nPTqF`ObG{=bo84 z7wV|v|Hht3JPkk}FaUG|9Y7m!Ao=|p@Bx?yW`SwoCGazne{UQEt^-TJmSbB2t^w^e zR}HiRcY*JgVs~m~;0|!8R^p4mY6RiBtpaENr0^Uv>(vCT0r!Cspcg0r`;t~jo{azx zfb|`CCKF##(F8oL;_xjnl#FrV8%ADg6Xz30z8#UnEWQMc5jI;nU_9Z{{Eq{QD8L7t!&STXpy9ZFm@kj^1Fem7{l-O!eBYr8>b)d^b3W}9W~#A6U*g95Oi>^=c4 z)~Zv`8K;EXvhfK3pp)!7am&FTkR7(HNX8sFd;lS+^%_N}!U1DH{Ly|K9>B#6_hueBM`PvzgXPMrIx>vGBiU)6Z4 zEpn3sb9fkCLB-z-YcKpmwJ#|r9RWl zC5~dFfRx^~zcZo4lLpcS%$dU%U1Vo|3%C)3JcraOHF*iC9^?bK^S~v{rNu|U-T>|j zG$FN0?PUAC7)9=|wrEE3yiS#A@zILA+sGlcN|VDaIFIb+1>`8+h@2|>kwB-& z?yx%JM4NdN29eBAO@MFvNQ4*G7A;7*Pj7ZUZ3CJ0gS8T$MjKKwTeK9b&o&dl(GUSK zKeKitb( { - settings.vector_size = v; + s.vector_size = v; save(); } }, From 32a1d048770859131aadb4b34fb58ed37ff61b89 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 7 Jan 2022 01:00:22 +0000 Subject: [PATCH 285/489] Limelight - screenshots --- apps/limelight/README.md | 11 +++++++++-- apps/limelight/screenshot_gochihand.png | Bin 0 -> 2332 bytes apps/limelight/screenshot_grenadier.png | Bin 0 -> 2376 bytes apps/limelight/screenshot_limelight.png | Bin 2180 -> 2425 bytes apps/limelight/screenshot_monoton.png | Bin 0 -> 3032 bytes 5 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 apps/limelight/screenshot_gochihand.png create mode 100644 apps/limelight/screenshot_grenadier.png create mode 100644 apps/limelight/screenshot_monoton.png diff --git a/apps/limelight/README.md b/apps/limelight/README.md index aa0c359b9..f1cc52092 100644 --- a/apps/limelight/README.md +++ b/apps/limelight/README.md @@ -1,11 +1,18 @@ # Limelight * Simple configurable analogue clock based on the work of @Andreas_Rozek [Simple_Clock](https://github.com/espruino/BangleApps/tree/master/apps/simple_clock)* -![](screenshot_limelight.jpg) +![](screenshot_limelight.png) * Selection of different fonts +* Settings menu where you can select font, or switch to Vector font and try a range of sizes * 100 less lines of code, demonstrating that there is no need for a custom widget draw method -Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS +![](screenshot_gochihand.png) +![](screenshot_monoton.png) +![](screenshot_grenadier.png) + +Many thanks for @Andreas_Rozek for his pioneering work on building a toolkit for the Bangle 2. + +Limelight Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) diff --git a/apps/limelight/screenshot_gochihand.png b/apps/limelight/screenshot_gochihand.png new file mode 100644 index 0000000000000000000000000000000000000000..af405c0f8406505893cedcbac16da25ea1e27804 GIT binary patch literal 2332 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 BY>NN@ literal 2180 zcmeHJ`!m~#7LSNFq7QG4TD79mCYD=m?;?bf2t`|^K}kwI(xOFMA!V(vUOPogqtPx) zwBp$kY0?!DtKZ#A>(yv(SCxupNUsVNgnHLaXZH8|2i$vR&iR}<^O^a~oSE~PlXvO_ zX(z%Q0f9hv`uY$~YmoOf;oCH|S*W0DK?8cLOw|IFED~c|;Q4-U9~) zer&36Ls`wW^pT=>0|PeRk*>q{zySHX*^Cw=)L&!OKwFX}`itSpWNT98-xPg%uxZ<5 zs4MIF3-B+3s;8nnb6!6g&&Cpa+netS1h0@1+9x^o^0CFRvPq};>_>>_ZU z^1+0+VpY!T_nuaB-G<4tc0hj`xNIi=Nb0$X6B|dI`!*XiiH{KIX!W3AIF)I_YHC0? zbzFaCdNd5rTTD0tqjs>*4Q6j_N5VJGd`Wap>^nK$QqHQy7kg+re6g|DC0~!VyRF}$ zs~d`J@2uK8Z5(?}GCJSdq&tTthCA$jc@WOi#vUksati`=@H!c#qXi?MvWZ4&!Kgp6 z|3E!L|0sk!f72+0wg`jAzle+B=E23oV;>ea@8C&%B^1r0nM8 zj{NDAH%t<8(mwMdaQM{Y0)|fDd%PJ!m6*RfW70f=EWgz*_4EDvM7(22ZUfb9eyW$U z2A9r5)rc5$JIRf7+o#yyL0S+xWI+-2!RS5HBLL3q0QT~c1e>I5oBgs!cZ)U+tc$FNDaHL27xA$IjEyF>+Y?g%2qrelFW z)-KN!oDW9fX!kErM5lo?mQdZY$Crc0_b!XFyvOaOZC7HUMSr{mgLPl&o*d*@qtD*h zp|&SeM6aQwR~T{j`9lKXSbx={^{M`XH>fh9-&5}BK>!ts>t6RQ(hr-b#gvLZH$LNz z^1%@1@?ITwspu=E7(^|23ma#+j#sJZ_R$xT8^kK&-M~u%3G#-?Xy%yPt0R-FC6w=o6mQcEU8hw(~o#iq-) zJkx57KP%jg`l*f|i5M$sOGL3tkeoy^VTuV2W8b>0M{SpgGTak# zL6mh`f#X`vq!PUZKg5%iBebwuu$J-KpUWW7$9cuH{n;RS)Hq1v-A4l#8e#fx^M5%X zuQ4p!#XN#^;Ro4;+U8O|1uO zZL`7nDn*!vVe);~pBkGBV7dNZ?0;vCD`qy|{M+>()y}q>w*ulzJVD@kM&|qnB+=s~ diff --git a/apps/limelight/screenshot_monoton.png b/apps/limelight/screenshot_monoton.png new file mode 100644 index 0000000000000000000000000000000000000000..d17d9bd26e9795c28c427f37ca8407db63b3f5b8 GIT binary patch literal 3032 zcmcJR`8U*y8^=GNkHMHxjJ+Dfbdhzs8d2E>Nw$!6G>v3WQ3@0Jj4n|cuRMxQ# z#pt8UO^d9PU4s-MDT9mZ>weGq{t4e7p67kev%JoE&Uwyxp2U-OmOC)JF#rJUusUw; zxUH;z4K1|os~bO1w*|cHXh{aD-s0x~0DITU-1Jlgbun-B>Vlf6dGoJd#g{V-mCVrO z5-fX%ixD!H(at?Avk`Gd}BrEcAa6w8o%K#c##rUfSuvJrQbUf;+GC&xS!^Njf= z&Kp?i-36)$C{~()O|DuT#+|5I=$i9PQx!xyf1Gs8BplSVW!glTm&zwTiZTDAE_-Rk z^4tPl5FH|*47Msf?@ZDKwdc!ja|>jk%3Q~eAV$z)#ZS^^!VvymH30sch~LkXEEA>BF zJHx=kS5|(m8YXbHOYZj)braZW=0RP#^j^eO6gd(D;h4!%XNY^H+F#eSu@4*tW(|8O&{k7TRF_+shqJ@><)?w=3eJv8$kWKHRe{{InfFup;N~Gz6 zUm9ep_R7d_SM75tPr<>Y_o#^6y^swI3g!oqVaAxhb0394dREa&zl3I0r8cQ<)>(XP zN-$#&qFMQPs3Pc~G_Thd`{mc?mrBUfV{-tZ((Fm9!|F|j&xL?(Kz$J6PN#7P*K|87 zT20QbJJ)3$R}Z6!B^fQ5MAWq8`l((YZq&{YBGPN(*1hHnKNYk0A}|#l;lUk<`jhJV zT|hHjKTu#5vRaHuRdV|nZfa>=p6jRA5rffEHMGFGn*9|lC^ zvczd7#ySWm)Q~p323d*QpoxWfvNVKb8;jXanTR2sbvuy(W0j~ZPPGgur1lN)T>1n# ziQ1y8HN`-o*>Aubj41jZjSPc0L!b^4c&_p<(_D_Xw%Ky1yI@{wFOujH6a9YItBO{i z$b}n`xXgsW_s%;)RNDW@lnw2lG-On&fBjAJl7x|6_DcYKdrI#6CG^ND4=}Id!gwyLc7TOfN%tDVDqfxZX7V z!te}*jAq&Da7VBqOOuMvD_(U)(@rbjvrs{Nd}B2~!O}y2KMc&cuA3c6E1N#vmNHr?_5-qu^}-6d_%5I;NU)-x8OL474{g z4f{Xs|$#rh%Ry`6Son2A8ZV<$RKYi-X%Mc(szg%YKo) z?^U7mjK=YRyXrNT!mt z65s1#a725nx9CO{4T}nIKakV!7&jXGXZmyiV64=1M3MrvC`1g353Rt}5w+u}u^hyO- zjeTP>W>f8p!-qzUaz&$KIN8^-i!B1|8gAr$6DcTNH>v9Q`R z(uWJ$!Cbv8-Qy8YUv;-om#57YS#O3{N_5)_a{Ttgxskfnm$yj@(R~3W7kHKwEqAEj zo(VbfgE!qifcc$vP8g)OIW+jet+xxn~Z*$>c+53Np$zg$BGyI|}<4wo0 z4h1!Yulc#=;DynfxTro~Qf)!R=|KIoQuu1WSC~Uabi6Itgu(|Xxm_Wh&;P#Wk4?>< zKLwLgN~Fx~3EftUMjFfY;@P}XKH~pM`C9ZWzW!P~|1s9gnfO4F6O!F)CzD0uAgrOcg?M=#RRGavKgJjP`Qk@i3fowI0a zeQa%X2>SglGJNOoiLdW?%Ccd>T*C~;^NXI}`aYtDvL<>*J8&US1iYj?52zwSh7J*_ zCvtw|IGD*6eqL#c><+Ns{(UpD;?|Fg-5Ak8 zKTz&TLK=I#YAarmxMFz^Ms}C))A0Gstnw_YFgGpdh@@IYE%ZrpQ9|@M@#1S9 z2~hM!OVdEYK4WHyw(%dp5y!F7fRvFNRO2zbm)-pacfT5L2OHAZuT$g`*p>>x9D~fp zE+T}tAwi0@l5Om^Of Date: Fri, 7 Jan 2022 01:02:43 +0000 Subject: [PATCH 286/489] Limelight - screenshots --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 3e63507c7..00a2b9860 100644 --- a/apps.json +++ b/apps.json @@ -5455,6 +5455,7 @@ "version": "0.01", "description": "Simple configurable analogue clock based on the work of @Andreas_Rozek (Simple_Clock)", "icon": "limelight.png", + "readme":"README.md", "screenshots": [{"url":"screenshot_limelight.png"}], "type": "clock", "tags": "clock", From 0dec5b608a9bb374a5be61b503e7032599cafbf2 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 7 Jan 2022 01:07:20 +0000 Subject: [PATCH 287/489] Limelight - apps.json update --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 00a2b9860..91ef1450a 100644 --- a/apps.json +++ b/apps.json @@ -5451,9 +5451,9 @@ }, { "id": "limelight", - "name": "Limelight Clock", + "name": "Limelight", "version": "0.01", - "description": "Simple configurable analogue clock based on the work of @Andreas_Rozek (Simple_Clock)", + "description": "Simple analogue clock (with configurable fonts) based on the work of @Andreas_Rozek (Simple_Clock)", "icon": "limelight.png", "readme":"README.md", "screenshots": [{"url":"screenshot_limelight.png"}], From 673865b31460864fc4c7d35a603e58a033e02786 Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Thu, 6 Jan 2022 17:23:48 -0800 Subject: [PATCH 288/489] Update app.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove unnecessary keywords. Remove autolight, since the system once again provides this service. Add optional autorotate while charging. Distinguish ‘slow’ second hand from regular second hand, visually. Tweak fonts. --- apps/pooqround/app.js | 195 ++++++++++++++++++++++++------------------ 1 file changed, 111 insertions(+), 84 deletions(-) diff --git a/apps/pooqround/app.js b/apps/pooqround/app.js index 22cf5ff79..b0c7592f2 100644 --- a/apps/pooqround/app.js +++ b/apps/pooqround/app.js @@ -25,8 +25,8 @@ // // This only works for Bangle 2. -const isString = x => typeof x === 'string'; -const imageWidth = i => isString(i) ? i.charCodeAt(0) : i.width; +const isString = x => typeof x === 'string', + imageWidth = i => isString(i) ? i.charCodeAt(0) : i.width; ////////////////////////////////////////////////////////////////////////////// /* System integration */ @@ -115,9 +115,9 @@ class RoundOptions extends Options { onchange: x => this.calendric = x, format: x => ['none', 'day', 'date', 'both', 'month', 'full'][x], }, - 'Auto-Illum.': { - init: _ => this.autolight, - onchange: x => this.autolight = x + 'Autorotate': { + init: _ => this.autorotate, + onchange: x => this.autorotate = x }, Defaults: _ => {this.reset(); this.interact();} }); @@ -133,7 +133,7 @@ RoundOptions.defaults = { calendric: 5, dayFg: '#fff', nightFg: '#000', - autolight: true, + autorotate: true, }; ////////////////////////////////////////////////////////////////////////////// @@ -144,29 +144,29 @@ const dec = x => E.toString(heatshrink.decompress(atob(x))); const y10F = [ dec( 'g///EAh////AA4IIBgPwgE+gAOBg/AngXB+EPAYM8gfggEfgF8D4OAj4dB8EDAYI' + - 'fBBAISBAAMOAYUB4AECnEAkAuBgEQBAPgIYX8IYX/wYDCEwIiMMgUYgECCIZlBAY' + - 'N4CoRUBIoMP8AZBge8CgMB8+BCAPw+F/gf8jxDB/0D4BGBEQMPAYIeBoAfBnEwge' + - 'Ah0cB4MDx4PBgHn4EB8E7LQM8h/eJ4MDBgIpB+H+g/wnE/WwMMO4P8LwM/XAJLBT' + - 'gY7BAAN/wC9CQwV+jwDB/4pBgP/EQKYBBIIxBPQP+SATfCIYIiCO4I9BBwM//hlB' + - 'PQJlCwYGBTAPgIgM4CYM8hwKBMoODegPA8F+gZlBewP4hz/BE4QrBGgM/LAV//4+' + - 'BAYJyBPwM/KQMeGQMPFwM8H4UHBIPwGQNwn4yBnhxBGQJxBGQK5BGQKWDOwUACAM' + - 'D/BDCNYPg///8E5HwR2BIwMDSgK0FSocMAYTLBAAYpBQAPnDwJGBEwK+B/hlB+F8' + - 'TARABTAJABTAPBMoR+BMoKXBDoX5DwIuBMoUPS4THCGwJbBhAaBvh5B+EHwPAOwP' + - 'guA1BvCcB4E8nxlBn1/VoIyBwDKBO4SGCgA=' + 'fBBAISBAAMOAYUB4AECnEAkAuBgEQBAPgIYX8IYX/wYDCEwIiMMgUcgECCIZlBAY' + + 'N4CoRUBIoMP8AZBge8MoMB8+B8B4B+E/gf4jw/B/kD4ADBEQMPSYXgoAfBnEwgeA' + + 'hw7BvEDx4PBgHn4EB8E7LQM8h/eJ4MDBgIpB+H+g/wnE/WwMMG4ReBn4zBJYKcDH' + + '4IABv+AXoSGCv0eAYP/FIMB/4iBTAIJBGIJ6B/yQCb4RDBEQTlBHoIOBn51BwC+B' + + 'MoWDAwKYBRgKYBCYM8hwKBMoODegPA8F+gZlBewP4hz/BE4QrBGgM/LAV//4+BAY' + + 'JyBPwM/KQMeGQMPFwM8H4UHBIPwGQNwZgPwnhxBGQJxBGQK5BGQKWDOwUACALlBI' + + 'YRrB8H///gnI+COwJGBgaUBWgqVDhgDCZYIADFIKAB84eBIwImBXwP8MoPwviYCI' + + 'AKYBIAKYB4JlCPwJlBS4IdC/IeBFwJlCh6XCY4Q2BLYMIDQN8PIPwg+B4B2B8FwG' + + 'oN4TgPAnk+MoM+v6tBGQOAZQJ3CQwUAA' ), 48, dec('hgAI'), 34 ];const y1F = [ dec( - 'g//AAPggE/AoX8gF/AoX+gF8CoU+gHwAoUPgAZBEIQFGCIodFFIo1FIIoADnAFEj' + - 'gFEh0AhA1EiAFCgeAFIf/4A1DFQIED/5MDGB6OEjAECHIIYDhkAuAFCjwFEj6DEn' + - '+AAod74AFD/PgvAtC+Hwv/wgZSBvEfLwc8RISOBGAJsBVAXgggEBE4PgIgJLC8E8' + - 'I4fgXQS/B8IhBGwOA8YFCgfA9+eAoMB4H/j/ACIPA/kPCQJCB/DMDMoMBboYVBKo' + - 'IDBSYeAAoYlCAATpEg/4Xwc/QIcPFoJcBQIP8GILXCDYLXBbId//BeCL4QwDgIwD' + - 'AAIXBDAQfCEYSPBAoaPCPQKPCAoZgBAoYvBAoIXBBAIFB/ALDEoJHBAoaPDaQSPB' + - 'AoKcBJgY9DTQX/EoKmCC4SyCYYJJB+CHBj+Aj8ASYJNBBINwIIOAM4ILDAYN/wAB' + - 'BB4JBBI45vCRYgADApEHL4pHB8AECFIPhAYLCCAggFBAgaNCYwgFEbAkAwAFEc4S' + - 'PCj/+LIKPBv6PEAoRnBFIMDFYLXCKoTLDa4YRDBYIdDh4FDMoQ1DK4ZBBMQIDBJY' + - 'bWBFIMEIIQpBgxxBgZRBh8AAYN8AoQVBjgbBAoTZBvwRCvEBF4IdB+E/OIp9CJgZ' + - 'BCQQUAA=' + 'g//AAPggE/AoX8gF/AoX+gF8CoU+gHwAoUPgAZBEIQFGCIodFFIo1FIIoADnEAgQ' + + 'FCjkAgwFCh0Ahg1EBoIABgeAFIf/4A1DFQIED/5MDGAYADEQYwDRwgMDhAYEH4Nw' + + 'AoUeAok/QYl/wAFD/fAHgUD+PgvAFBj/g+E/4EBLAN4j5SCgE8h4EB/AwCAoOAVA' + + 'PgggeBFoPgQgRLB8E8I4fgXQS/B8KwBMgOA8YFCgfA9+eAoMB4H/j/ACIPA/kPCQ' + + 'JIB/DMDMoJSBboQVBKoIDBSYZOBAAQlCAATpEg/4Xwc/QIZyBwBcBgf//gxBa4Qb' + + 'Ba4LZDv/4LwRfCGAcBGAYABC4IYCD4QjCR4IFDR4R6BR4QFDMAIFDF4IFBC4IIBA' + + 'oLEBBYQlBI4IFDR4ZrBR4QFBTgJMDHoaaCdQSmCC4SyCYYJJB+CHBj+Aj8ASYJNB' + + 'BINwIIOAM4ILDAYN/wABBB4JBBI45vCRYgADApEHL4pHB8AECFIPhAYLCCAggFBA' + + 'gaNCYwgFEbAkAwAFEc4SPCj/+LIKPBv6PEAoRnBFIMDFYLXCKoTLDa4YRDBYIdDh' + + '4FDMoQ1DK4ZBBMQIDBJYbWBFIMEIIQpBgxxBgZRBh8AAYN8AoQVBjgbBAoTZBvwR' + + 'CvEBF4IdB+E/OIp9CJgZBCQQUAA=' ), 48, dec('hgAI'), 48 ];const y10sF = [ dec( @@ -194,20 +194,20 @@ const y10F = [ ];const d1F = [ dec( 'AB1/+AECj///4FCAgP/8EAgf/4F//EAg4CBgf8gEPwAUBn0AhwaCAYMeAoUPgEcA' + - 'oUHAowRFDoopFGopBFJopZGBgIKCABlAIIcA4AFDgIFEgZBCAoMHAohVBAoY6CHg' + - 'U/Aol/AogADGoQFUABEMAQM/AQN8bIRZBRgJ5BLILhBgP3LIcD84rDg/HWYcPw4F' + - 'Dj4PBAoU+Aol8Aon4PocB+CJDgfgAoXgh/ATYX4v+AU4X//w/DbYQFCCwJ3PvDIE' + - 'NYQCCdoJ6CgfAiCGCI4NwgEeFwISCLoMeJwJdCnkfHYd4v4FD+f5AoUB9/BAoUD/' + - '4jCh8HG4IpCh5DBAIMeE4Q/BvjMCfoP8Z4Uf//wCgInB/5lCABs+AoicBAAUDAok' + - 'P9wFDv+OCAjUCHQP4AoY5BAoUHEIIFCv5JBAoLQBLQYqEApQpDArIAJv5IBnBTCV' + - '4McJAQFBcYLvBB4IkBd4N4cYQBBeoLdBCYIFDngFECoIFDOwIdCc4QpCFwIZCjwu' + - 'BEoU8FwIxCvAIBEIPB+AUBJIP/8AmBLYWAd4RnBdx4XCcYf/Dgn//AuEP4LjBXoJ' + - 'AC//vQYT0BBIKDC+CZBOIM/wAFDVYIFCgIrBAoUDPoIdCO4QnBaQYnBGoQVBIIZI' + - 'CJoTNCLIY4CAYIaDAAKRCAASRDAAIaEYAQtDYAI5DRgZFCAAYuCQoQuBAgIFBvEH' + - 'AgIFB+CgBAAMB86lE76EBFwX/GocPNoYmBIwk/HQl8LpIAQRId/SoYDB4ZJCUoPn' + - 'VoUHwP3Y4YYBY4k+Y4h5BdILhBd4YFFCIodFFIo1FIIpNFLIplGAArMFn6oBHYMA' + - 'DYQFBgP5E4IFBgfgUgIFCwBZBEAL1BPYZbDA4Z7DLYRtCBYYlDBoIxCEYMBHoIvC' + - 'HAI7Dh5PBI4X/LIX//7+Dn52Eh4QCA==' + 'oUHAowRFDoopFGopBFJopZGBgIKCAB5BBgA1CAoMBAokDCIgTCAYRTDAoI6CHgU/' + + 'Aol/Aog1GAqgAIhgCBn4CBvjZCLIKMBPIJZBcIMB+4lBMoMD84rDg/HL4cPw4FDj' + + '5rEnwFEvgFE/AFBaYMB+CJCwED8AFC8EP4CbC/F/wCnC//+H4bbCAoQWBO594EAI' + + 'TBgBrCAQTtBPQUD4EQQwRHBuEAjwuBCQRdBjxOBLoU8j47DvF/Aofz/IFCgPv4IF' + + 'Cgf/EYUPg43BFIUPIYIBBjwnCH4N8ZgT9B/jPCj//+AUBE4P/MoQANnwFETgIACg' + + 'YFEh/uAod/xwQEagQ6B/AFDHIIFCg4hBAoV/JIIFBaAJaDFQgFKFIYFZABN/JAM4' + + 'KYSvBjhICAoLjBd4IPBEgLvBvDjCAIL1BboITBAoc8AogVBAoZ2BDoTnCFIQuBDI' + + 'UeFwIlCnguBGIV4BAIhB4PwCgJJB//gEwJbCwDvCM4LuPC4TjD/4cE//4Fwh/BcY' + + 'K9BIAX/96DCegIJBQYXwTIJxBn+AAoarBAoUBFYIFCgZ9BDoR3CE4LSDE4I1CCoJ' + + 'BDJARNCZoRZDHAQDBDQYABSIQACSIYABDQjACFobABHIaMDIoQADFwSFCFwIEBAo' + + 'N4g4EBAoPwUAIABgPnUonfQgIuC/41Dh5tDEwJGEn46EvhdJACCJDv6VDAYPDJIS' + + 'lB86tCg+B+7HDDALHEnzHEPILpBcILvDAooRFDoopFGopBFJopZFMowAFZgs/VAI' + + '7BgAbCAoMB/InBAoMD8CkBAoWALIIgBeoJ7DLYYHDPYZbCNoQLDEoYNBGIQjBgI9' + + 'BF4Q4BHYcPJ4JHC/5ZC///fwc/OwkPCAQA==' ), 48, dec('ikPigAGA'), 48 ];const dowF = [ dec( @@ -220,10 +220,10 @@ const y10F = [ 'kDMIgeBFIQEBBYRTBCAZ3FAggAMg4zEj7LEn7LEv++AodzxwFD+ePAofjw4FVDoo' + 'pFv+eIImcJomYLImAAoZeEAtTyBAAQFEVYIFDSQIvhAojaCFwgABh4YEngFEuAqJ' + 'gPAAocDApYuEgP/fgl/+B9HAAv+Aon8HQMOIAkeAokcAohaDAoM4Aol4AohmDAoJ' + - 'BDAoJsDAo7vhABbJDAo9/AojEFMYbKMArCBDFI41FWIYABggFEgbuCDYMPLIQbBj' + - '//wBdCn0H4DZCvEBb4YZBdYZBBAofgCIQFDDoIFFDoPggYFBF4IFBGoI7B+AFCE4' + - 'NwCIIlCuAdBIYU4gPwn5VBjC7B/y0Dv/4YwcPCwMAjJlCAAM584FDufDCAUA8eBA' + - 'p/zC4n5EYj1BAoc//4RDU4IFDA==' + 'BDAoJsDAo7vhABZuBQYoFDv4FEYgpjDZRgFYGYYpHGoqxDAAMEAokDdwQbBh//DY' + + 'cf/+ALoU+g/AbIV4gLfDDILrDIIIFD8ARCAoYdBAoodB8EDAoIvBAoI1BHYPwAoQ' + + 'nBuARBEoVwDoJDCnEB+E/KoMYXYP+Wgd//DGDh4WBgEZMoQABnPnAodz4YQCgHjw' + + 'IFP+YXE/IjEeoIFDn//CIanBAoY=' ), 48, dec('kElkMljsljw='), 48 ];const mF = [ dec( @@ -322,21 +322,20 @@ class Round { this.r = this.xc - this.minR; } - reset(clear) {this.state = {}; clear && this.g.clear(true);} + reset(clear) {this.state = {}; clear == null || this.g.clear(true).setRotation(clear);} doIcons(which) { this.state[which] = null; - this.render(new Date()); // Not quite right, I think. } enhanceUntil(t) {this.enhance = t;} pie(f, a0, a1, invert) { if (!invert) return this.pie(f, a1, a0 + 1, true); - let t0 = Math.tan(a0 * 2 * Math.PI), t1 = Math.tan(a1 * 2 * Math.PI); + const t0 = Math.tan(a0 * 2 * Math.PI), t1 = Math.tan(a1 * 2 * Math.PI); let i0 = Math.floor(a0 * 4 + 0.5), i1 = Math.floor(a1 * 4 + 0.5); - let x = f.getWidth() / 2, y = f.getHeight() / 2; - let poly = [ + const x = f.getWidth() / 2, y = f.getHeight() / 2; + const poly = [ x + (i1 & 2 ? -x : x) * (i1 & 1 ? 1 : t1), y + (i1 & 2 ? y : -y) / (i1 & 1 ? t1 : 1), x, @@ -348,16 +347,17 @@ class Round { for (i0++; i0 <= i1; i0++) poly.push( 3 * i0 & 2 ? f.getWidth() : 0, i0 & 2 ? f.getHeight() : 0 ); - f.setColor(0).fillPoly(poly); + return f.setColor(0).fillPoly(poly); } hand(t, d, c0, r0, c1, r1) { + const g = this.g; t *= Math.PI / 30; - const r = this.r; - const z = 2 * r0 + 1; - const x = this.xc + r * Math.sin(t), y = this.yc - r * Math.cos(t); - const x0 = x - r0, y0 = y - r0; - d = d ? d[0] : Graphics.createArrayBuffer(z, z, 16, {msb: true}); + const r = this.r, + z = 2 * r0 + 1, + x = this.xc + r * Math.sin(t), y = this.yc - r * Math.cos(t), + x0 = x - r0, y0 = y - r0; + d = d ? d[0] : Graphics.createArrayBuffer(z, z, 4, {msb: true}); for (let i = 0; i < z; i++) for (let j = 0; j < z; j++) { d.setPixel(i, j, g.getPixel(x0 + i, y0 + j)); } @@ -366,24 +366,20 @@ class Round { return [d, x0, y0]; } - render(d) { - const g = this.g; - const b = this.b, bI = this.bI; - const c = this.c, cI = this.cI; - const e = d < this.enhance; - const state = this.state; - const options = this.options; - const cal = options.calendric; - const res = options.resolution; - const dow = (e || cal == 1 || cal > 2) && d.getDay(); - const ts = res < 2 && d.getSeconds(); - const tm = (e || res < 3) && d.getMinutes() + ts / 60; - const th = d.getHours() + d.getMinutes() / 60; - const dd = (e || cal > 1) && d.getDate(); - const dm = (e || cal > 3) && d.getMonth(); - const dy = (e || cal > 4) && d.getFullYear(); - const xc = this.xc, yc = this.yc, r = this.r; - const dlr = xc * 3/4, dlw = 8, dlhw = 4; + render(d, rate) { + const g = this.g, b = this.b, bI = this.bI, c = this.c, cI = this.cI, + e = d < this.enhance, + state = this.state, options = this.options, + cal = options.calendric, res = options.resolution, + dow = (e || cal === 1 || cal > 2) && d.getDay(), + ts = res < 2 && d.getSeconds(), + tm = (e || res < 3) && d.getMinutes() + ts / 60, + th = d.getHours() + d.getMinutes() / 60, + dd = (e || cal > 1) && d.getDate(), + dm = (e || cal > 3) && d.getMonth(), + dy = (e || cal > 4) && d.getFullYear(); + const xc = this.xc, yc = this.yc, r = this.r, + dlr = xc * 3/4, dlw = 8, dlhw = 4; // Restore saveunders for fast-moving, overdrawing indicators. if (state.sd) g.drawImage.apply(g, state.sd); @@ -397,10 +393,10 @@ class Round { state.dow = dow; } - const locked = Bangle.isLocked(); - const charging = Bangle.isCharging(); - const battery = E.getBattery(); - const HRMOn = Bangle.isHRMOn(); + const locked = Bangle.isLocked(), + charging = Bangle.isCharging(), + battery = E.getBattery(), + HRMOn = Bangle.isHRMOn(); if (dy !== state.dy || locked !== state.locked || charging !== state.charging || @@ -463,6 +459,7 @@ class Round { this.hand(tm, state.md, g.theme.bg, this.minR, g.theme.fg, this.minR - 1) : null; state.sd = ts === +ts ? + rate > 1000 ? this.hand(ts, state.sd, g.theme.fg2, this.secR, g.theme.bg, 2) : this.hand(ts, state.sd, g.theme.fg2, this.secR) : null; } @@ -482,7 +479,18 @@ class Clock { this.listeners = { lcdPower: on => on ? this.active() : this.inactive(), - charging: () => {face.doIcons('charging'); this.active();}, + charging: on => { + face.doIcons('charging'); + if (on) { + this.listeners.accel = + a => this.orientation(a) === this.attitude || this.active(); + Bangle.on('accel', this.listeners.accel); + } else { + Bangle.removeListener('accel', this.listeners.accel); + delete this.listeners.accel; + } + this.active(); + }, lock: () => {face.doIcons('locked'); this.active();}, faceUp: up => { this.conservative = !up; @@ -498,20 +506,23 @@ class Clock { if (e.y - this.e0.y < -50) { this.options.resolution > 0 && this.options.resolution--; this.rates.clock = this.timescales[this.options.resolution]; + this.ack(); this.active(); } else if (e.y - this.e0.y > 50) { this.options.resolution < this.timescales.length - 1 && this.options.resolution++; this.rates.clock = this.timescales[this.options.resolution]; + this.ack(); this.active(); } else if (this.yX - this.yN < 20) { const now = new Date(); if (now - this.t0 < 250) { + this.ack(); face.enhanceUntil(now + 30000); - face.render(now); + this.active(); } else if (now - this.t0 > 500) { this.stop(); - this.options.interact(); + this.ack().then(_ => this.options.interact()); } } this.t0 = null; @@ -524,9 +535,25 @@ class Clock { }; } + ack() { + return Bangle.buzz(33); + } + + orientation(a) { + return Math.abs(a.z) < 0.85 ? + Math.abs(a.y) > Math.abs(a.x) ? a.y < 0 ? 0 : 2 : a.x > 0 ? 1 : 3 : + 0; + } + + rotation() { + return this.options.autorotate && Bangle.isCharging() ? + this.orientation(Bangle.getAccel()) : + 0; + } + redraw(rate) { const now = this.updated = new Date(); - if (this.refresh) this.face.reset(true); + if (this.refresh) this.face.reset(this.attitude = this.rotation()); this.refresh = false; rate = this.face.render(now, rate); if (rate !== this.rates.face) { @@ -541,13 +568,13 @@ class Clock { this.exception && clearTimeout(this.exception); this.interval && clearInterval(this.interval); this.timeout = this.exception = this.interval = this.rate = null; - this.face.reset(false); // Cancel any ongoing background rendering + this.face.reset(); // Cancel any ongoing background rendering return this; } active() { - const prev = this.rate; - const now = Date.now(); + const prev = this.rate, + now = Date.now(); let rate = Infinity; for (const k in this.rates) { let r = this.rates[k]; From b878ae1f24b7e384851b3ea5a63785748cd87456 Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Thu, 6 Jan 2022 17:25:01 -0800 Subject: [PATCH 289/489] Update ChangeLog --- apps/pooqround/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/pooqround/ChangeLog b/apps/pooqround/ChangeLog index 8eb91cf97..17004449d 100644 --- a/apps/pooqround/ChangeLog +++ b/apps/pooqround/ChangeLog @@ -1,2 +1,3 @@ 0.00: Initial check-in. 0.01: Add tap-to-decorate feature. Bugfixes. +0.02: Add autorotate while charging. Remove autolight. Tweak fonts. From 3068a647d63f0425751305f0da08f03e039d582e Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Thu, 6 Jan 2022 17:28:32 -0800 Subject: [PATCH 290/489] Update README.md --- apps/pooqround/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/pooqround/README.md b/apps/pooqround/README.md index d413fd88e..6f6bafa69 100644 --- a/apps/pooqround/README.md +++ b/apps/pooqround/README.md @@ -20,8 +20,7 @@ you can quickly alter the number of ‘hands’ on the display. When the watch i or down to remove the distraction. There's also a setting that displays the second hand, but only if the watch is perfectly face-to-the-sky, in case you want the ability to check the _exact_ time, hands free, without the impact on battery life this usually entails. -In some versions of the Bangle.js firmware, the backlight doesn't come on automatically when you twist your wrist. There's currently a workaround -for this integrated into the watchface; you can disable it in the menu, if you prefer. +While charging the main display automatically rotates so that noon is up. This can be disabled. ## Limitations From 9811ada68d1c62e55cd8b18d87beea1d7e00639e Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Thu, 6 Jan 2022 17:29:39 -0800 Subject: [PATCH 291/489] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 8b4e86d52..40e92d201 100644 --- a/apps.json +++ b/apps.json @@ -4943,7 +4943,7 @@ { "id": "pooqround", "name": "pooq Round watch face", "shortName":"pooq Round", - "version":"0.01", + "version":"0.02", "description": "A 24 hour analogue watchface with high legibility and a novel style.", "icon": "app.png", "type": "clock", From 99c7dba8f2100d247afabaec694e874a448bb06b Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Thu, 6 Jan 2022 17:43:05 -0800 Subject: [PATCH 292/489] Update ChangeLog --- apps/pooqround/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/pooqround/ChangeLog b/apps/pooqround/ChangeLog index 17004449d..bc35b69df 100644 --- a/apps/pooqround/ChangeLog +++ b/apps/pooqround/ChangeLog @@ -1,3 +1,3 @@ 0.00: Initial check-in. 0.01: Add tap-to-decorate feature. Bugfixes. -0.02: Add autorotate while charging. Remove autolight. Tweak fonts. +0.02: Add autorotate while charging. Remove autolight. Tweak fonts. Add some haptic feedback on touchscreen operations. From fe66e54b4fdfc7b9f34bb8874c57bf537287cf45 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 7 Jan 2022 01:48:39 +0000 Subject: [PATCH 293/489] Limelight fix icon --- apps/limelight/limelight.icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/limelight/limelight.icon.js b/apps/limelight/limelight.icon.js index 9e886bbf8..f7e74db90 100644 --- a/apps/limelight/limelight.icon.js +++ b/apps/limelight/limelight.icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("lksgIqngf/wAFC//+AgUch/4AgMBwAQEh/8Dgf/4AKOEAQKCAYUB//gAoU/DQkPBQYVBGx5SDBQIbDBR0GEAlgFYcHGwh4B+CDHRwL04")); +require("heatshrink").decompress(atob("lksgIqngf/wAFC//+AgUch/4AgMBwAQEh/8Dgf/4AKOEAQKCAYUB//gAoU/DQkPBQYVBGx5SDBQIbDBR0GEAlgFYcHGwh4B+CDHRwL04")) \ No newline at end of file From 328f2d0e09163b93ba238ddbd8751500b14dc88a Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Thu, 6 Jan 2022 22:40:34 -0800 Subject: [PATCH 294/489] Update app.js Remove internal autolight logic. --- apps/pooqround/app.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/pooqround/app.js b/apps/pooqround/app.js index b0c7592f2..06e208e61 100644 --- a/apps/pooqround/app.js +++ b/apps/pooqround/app.js @@ -496,7 +496,6 @@ class Clock { this.conservative = !up; this.active(); }, - twist: _ => this.options.autolight && Bangle.setLCDPower(true), drag: e => { if (this.t0) { if (e.b) { From 341080e09b3ad310cd2eb9e0f74f117bf121fd01 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 7 Jan 2022 08:53:32 +0000 Subject: [PATCH 295/489] widpedom 0.22: Fix 'stps' regression for 0.21 (fix #1233) --- apps.json | 2 +- apps/widpedom/ChangeLog | 1 + apps/widpedom/widget.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 7fc5145aa..6b81f6a41 100644 --- a/apps.json +++ b/apps.json @@ -1590,7 +1590,7 @@ { "id": "widpedom", "name": "Pedometer widget", - "version": "0.21", + "version": "0.22", "description": "Daily pedometer widget", "icon": "widget.png", "type": "widget", diff --git a/apps/widpedom/ChangeLog b/apps/widpedom/ChangeLog index 3483c3390..54f6b203b 100644 --- a/apps/widpedom/ChangeLog +++ b/apps/widpedom/ChangeLog @@ -21,3 +21,4 @@ Memory usage enhancements 0.20: Fix issue where step count would randomly reset 0.21: Memory usage improvements, fix widget initial width (fix #1170) +0.22: Fix 'stps' regression for 0.21 (fix #1233) diff --git a/apps/widpedom/widget.js b/apps/widpedom/widget.js index 3a079c066..cc7fdb579 100644 --- a/apps/widpedom/widget.js +++ b/apps/widpedom/widget.js @@ -55,6 +55,7 @@ // add your widget WIDGETS["wpedom"]={area:"tl",width:0, getWidth:function() { + let stps = stp_today.toString(); let newWidth = 24; if (settings.hide) newWidth = 0; @@ -68,7 +69,6 @@ return newWidth; }, redraw:function() { // work out the width, and queue a full redraw if needed - let stps = stp_today.toString(); let newWidth = this.getWidth(); if (newWidth!=this.width) { // width has changed, re-layout all widgets From aa47b7fa99cceb520f7684a8e05bd995fd828de1 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Fri, 7 Jan 2022 09:53:40 +0100 Subject: [PATCH 296/489] Hopefully fix bug where no HRM data is received --- apps/circlesclock/app.js | 67 +++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index b5ee61c75..392fa4287 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -9,6 +9,7 @@ const powerIconGreen = heatshrink.decompress(atob("h0OwYQNkAEDpAEDiQEDkmSAgUJkmA const powerIconRed = heatshrink.decompress(atob("h0OwYQNoAEDyAEDkgEDpIFDiVJBweSAgUJkmAAoYZDgQpEBwYAJA")); let settings; + function loadSettings() { settings = require("Storage").readJSON("circlesclock.json", 1) || { 'minHR': 40, @@ -60,10 +61,10 @@ function draw() { if (!showWidgets) { /* - * 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. - */ + * 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 = () => {}; @@ -97,7 +98,7 @@ function draw() { function drawCircle(index, defaultType) { const type = settings['circle' + index] || defaultType; - const w = index == 1 ? w1: index == 2 ? w2 : w3; + const w = index == 1 ? w1 : index == 2 ? w2 : w3; switch (type) { case "steps": @@ -114,12 +115,13 @@ function drawCircle(index, defaultType) { break; } } + function getCirclePosition(type, defaultPos) { for (let i = 1; i <= 3; i++) { const setting = settings['circle' + i]; - if (setting == type) return i == 1 ? w1: i == 2 ? w2 : w3; + if (setting == type) return i == 1 ? w1 : i == 2 ? w2 : w3; } - return defaultPos; + return defaultPos || undefined; } function isCircleEnabled(type) { @@ -229,8 +231,7 @@ function drawBattery(w) { if (Bangle.isCharging()) { color = colorGreen; icon = powerIconGreen; - } - else { + } else { if (settings.batteryWarn != undefined && battery <= settings.batteryWarn) { color = colorRed; icon = powerIconRed; @@ -289,39 +290,41 @@ function getSteps() { return 0; } +function enableHRMSensor() { + Bangle.setHRMPower(1, "circleclock"); + if (hrtValue == undefined) { + hrtValue = '...'; + drawHeartRate(); + } +} + Bangle.on('lock', function(isLocked) { if (!isLocked) { if (isCircleEnabled("hr")) { - Bangle.setHRMPower(1, "watch"); - if (hrtValue == undefined) { - hrtValue = '...'; - drawHeartRate(); - } + enableHRMSensor(); } draw(); } else { - if (isCircleEnabled("hr")) { - Bangle.setHRMPower(0, "watch"); - } + Bangle.setHRMPower(0, "circleclock"); } }); -if (isCircleEnabled("hr")) { - Bangle.on('HRM', function(hrm) { - //if(hrm.confidence > 90){ - hrtValue = hrm.bpm; - if (Bangle.isLCDOn()) - drawHeartRate(); - //} else { - // hrtValue = undefined; - //} - }); -} -if (isCircleEnabled("battery")) { - Bangle.on('charging', function(charging) { - drawBattery(); - }); +Bangle.on('HRM', function(hrm) { + if (isCircleEnabled("hr")) { + hrtValue = hrm.bpm; + if (Bangle.isLCDOn()) + drawHeartRate(); + } +}); + + +Bangle.on('charging', function(charging) { + if (isCircleEnabled("battery")) drawBattery(); +}); + +if (isCircleEnabled("hr")) { + enableHRMSensor(); } Bangle.setUI("clock"); From 2f16365e6cf6b4ad9717770e4103b6d52a4f6fe2 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Fri, 7 Jan 2022 10:26:45 +0100 Subject: [PATCH 297/489] Redraw background rectangle before drawing circles (fixes graphical glitch) --- apps/circlesclock/app.js | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 392fa4287..4f2fea4ab 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -131,6 +131,11 @@ function isCircleEnabled(type) { function drawSteps(w) { if (!w) w = getCirclePosition("steps", w1); const steps = getSteps(); + + // Draw rectangle background: + g.setColor(colorBg); + g.fillRect(w - radiusOuter - 3, h3 - radiusOuter - 3, w + radiusOuter + 3, h3 + radiusOuter + 3); + g.setColor(colorGrey); g.fillCircle(w, h3, radiusOuter); @@ -160,6 +165,10 @@ function drawStepsDistance(w) { const stepDistance = settings.stepLength || 0.8; const stepsDistance = Math.round(steps * stepDistance); + // Draw rectangle background: + g.setColor(colorBg); + g.fillRect(w - radiusOuter - 3, h3 - radiusOuter - 3, w + radiusOuter + 3, h3 + radiusOuter + 3); + g.setColor(colorGrey); g.fillCircle(w, h3, radiusOuter); @@ -185,6 +194,11 @@ function drawStepsDistance(w) { function drawHeartRate(w) { if (!w) w = getCirclePosition("hr", w2); + + // Draw rectangle background: + g.setColor(colorBg); + g.fillRect(w - radiusOuter - 3, h3 - radiusOuter - 3, w + radiusOuter + 3, h3 + radiusOuter + 3); + g.setColor(colorGrey); g.fillCircle(w, h3, radiusOuter); @@ -210,6 +224,11 @@ function drawHeartRate(w) { function drawBattery(w) { if (!w) w = getCirclePosition("battery", w3); const battery = E.getBattery(); + + // Draw rectangle background: + g.setColor(colorBg); + g.fillRect(w - radiusOuter - 3, h3 - radiusOuter - 3, w + radiusOuter + 3, h3 + radiusOuter + 3); + g.setColor(colorGrey); g.fillCircle(w, h3, radiusOuter); @@ -319,6 +338,12 @@ Bangle.on('HRM', function(hrm) { }); +Bangle.setUI("clock"); +Bangle.loadWidgets(); + +draw(); +setInterval(draw, 60000); + Bangle.on('charging', function(charging) { if (isCircleEnabled("battery")) drawBattery(); }); @@ -326,9 +351,3 @@ Bangle.on('charging', function(charging) { if (isCircleEnabled("hr")) { enableHRMSensor(); } - -Bangle.setUI("clock"); -Bangle.loadWidgets(); - -draw(); -setInterval(draw, 60000); From 96802b0bd48e50ba721b157590d23e3fad8963dd Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Fri, 7 Jan 2022 10:32:39 +0100 Subject: [PATCH 298/489] Make min- & maxHR settings more granular --- apps/circlesclock/settings.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index 95ebc17db..a16bb99a8 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -15,7 +15,7 @@ value: "minHR" in settings ? settings.minHR : 40, min: 0, max : 250, - step: 10, + step: 5, format: x => { return x; }, @@ -25,7 +25,7 @@ value: "maxHR" in settings ? settings.maxHR : 200, min: 20, max : 250, - step: 10, + step: 5, format: x => { return x; }, From c47cabe156e3e03756492be8ed34b8bc31854d98 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Fri, 7 Jan 2022 10:43:06 +0100 Subject: [PATCH 299/489] Update ChangeLog --- apps/circlesclock/ChangeLog | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/circlesclock/ChangeLog b/apps/circlesclock/ChangeLog index f416929ac..4230c1468 100644 --- a/apps/circlesclock/ChangeLog +++ b/apps/circlesclock/ChangeLog @@ -1,4 +1,7 @@ 0.01: New clock 0.02: Fix icon & add battery warn functionality 0.03: Theming support & minor fixes -0.04: Make configurable what to show in each circle; add step distance circle; allow switching visibility of widgets +0.04: Make configurable what to show in each circle + Add step distance circle + Allow switching visibility of widgets + Make circles and text slightly bigger From 95c3b70af4c8d0873b5ec61636136738ca508477 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 19:06:07 +0100 Subject: [PATCH 300/489] Log confidence alongside heartrate instead of discarding confidence 0 samples --- apps/recorder/widget.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index 34a6ca488..8f82f1f37 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -53,33 +53,29 @@ }, hrm:function() { var bpm = 0, bpmConfidence = 0; - var hasBPM = false; function onHRM(h) { if (h.confidence >= bpmConfidence) { bpmConfidence = h.confidence; bpm = h.bpm; - if (bpmConfidence) hasBPM = true; } } return { name : "HR", - fields : ["Heartrate"], + fields : ["Heartrate", "Confidence"], getValues : () => { - var r = [bpmConfidence?bpm:""]; + var r = [bpm,bpmConfidence]; bpm = 0; bpmConfidence = 0; return r; }, start : () => { - hasBPM = false; Bangle.on('HRM', onHRM); Bangle.setHRMPower(1,"recorder"); }, stop : () => { - hasBPM = false; Bangle.removeListener('HRM', onHRM); Bangle.setHRMPower(0,"recorder"); }, - draw : (x,y) => g.setColor(hasBPM?"#f00":"#f88").drawImage(atob("DAwBAAAAMMeef+f+f+P8H4DwBgAA"),x,y) + draw : (x,y) => g.setColor(Bangle.isHRMOn()?"#f00":"#f88").drawImage(atob("DAwBAAAAMMeef+f+f+P8H4DwBgAA"),x,y) }; }, bat:function() { From 089f0cd4386c24a9d05fd9bd258ed436fd375253 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:39:39 +0100 Subject: [PATCH 301/489] Emit additional BTHRM event and allow overwriting HRM optionally --- apps.json | 3 +- apps/bthrm/boot.js | 65 ++++++++++++++++++++++++++++++++---------- apps/bthrm/settings.js | 33 +++++++++++++++++++++ 3 files changed, 85 insertions(+), 16 deletions(-) create mode 100644 apps/bthrm/settings.js diff --git a/apps.json b/apps.json index 95c7b4bbc..6aa109142 100644 --- a/apps.json +++ b/apps.json @@ -1049,7 +1049,8 @@ "readme": "README.md", "storage": [ {"name":"bthrm.boot.js","url":"boot.js"}, - {"name":"bthrm.img","url":"app-icon.js","evaluate":true} + {"name":"bthrm.img","url":"app-icon.js","evaluate":true}, + {"name":"bthrm.settings.js","url":"settings.js"} ] }, { diff --git a/apps/bthrm/boot.js b/apps/bthrm/boot.js index 88e574480..0aa8d5c96 100644 --- a/apps/bthrm/boot.js +++ b/apps/bthrm/boot.js @@ -2,24 +2,43 @@ var log = function() {};//print var gatt; var status; - - Bangle.isHRMOn = function() { + + var origIsHRMOn = Bangle.isHRMOn; + + Bangle.isBTHRMOn = function(){ return (status=="searching" || status=="connecting") || (gatt!==undefined); } - Bangle.setHRMPower = function(isOn, app) { + + Bangle.isHRMOn = function() { + var settings = require('Storage').readJSON("bthrm.json", true) || {}; + + print(settings); + if (settings.enabled && !settings.replace){ + return origIsHRMOn(); + } else if (settings.enabled && settings.replace){ + return Bangle.isBTHRMOn(); + } + return origIsHRMOn() || Bangle.isBTHRMOn(); + } + + Bangle.setBTHRMPower = function(isOn, app) { + + + var settings = require('Storage').readJSON("bthrm.json", true) || {}; + // Do app power handling if (!app) app="?"; - log("setHRMPower ->", isOn, app); + log("setBTHRMPower ->", isOn, app); if (Bangle._PWR===undefined) Bangle._PWR={}; - if (Bangle._PWR.HRM===undefined) Bangle._PWR.HRM=[]; - if (isOn && !Bangle._PWR.HRM.includes(app)) Bangle._PWR.HRM.push(app); - if (!isOn && Bangle._PWR.HRM.includes(app)) Bangle._PWR.HRM = Bangle._PWR.HRM.filter(a=>a!=app); - isOn = Bangle._PWR.HRM.length; + if (Bangle._PWR.BTHRM===undefined) Bangle._PWR.BTHRM=[]; + if (isOn && !Bangle._PWR.BTHRM.includes(app)) Bangle._PWR.BTHRM.push(app); + if (!isOn && Bangle._PWR.BTHRM.includes(app)) Bangle._PWR.BTHRM = Bangle._PWR.BTHRM.filter(a=>a!=app); + isOn = Bangle._PWR.BTHRM.length; // so now we know if we're really on if (isOn) { - log("setHRMPower on", app); - if (!Bangle.isHRMOn()) { - log("HRM not already on"); + log("setBTHRMPower on", app); + if (!Bangle.isBTHRMOn()) { + log("BTHRM not already on"); status = "searching"; NRF.requestDevice({ filters: [{ services: ['180D'] }] }).then(function(device) { log("Found device "+device.id); @@ -49,7 +68,11 @@ if (flags&16) { var interval = dv.getUint16(idx,1); // in milliseconds }*/ - Bangle.emit('HRM',{ + + + var eventName = settings.replace ? "HRM" : "BTHRM"; + + Bangle.emit(eventName, { bpm:bpm, confidence:100 }); @@ -65,15 +88,27 @@ }); } } else { // not on - log("setHRMPower off", app); + log("setBTHRMPower off", app); if (gatt) { - log("HRM connected - disconnecting"); + log("BTHRM connected - disconnecting"); status = undefined; try {gatt.disconnect();}catch(e) { - log("HRM disconnect error", e); + log("BTHRM disconnect error", e); } gatt = undefined; } } }; + + var origSetHRMPower = Bangle.setHRMPower; + + Bangle.setHRMPower = function(isOn, app) { + var settings = require('Storage').readJSON("bthrm.json", true) || {}; + if (settings.enabled || !isOn){ + Bangle.setBTHRMPower(isOn, app); + } + if (settings.enabled && !settings.replace || !isOn){ + origSetHRMPower(isOn, app); + } + } })(); diff --git a/apps/bthrm/settings.js b/apps/bthrm/settings.js new file mode 100644 index 000000000..8cb00614e --- /dev/null +++ b/apps/bthrm/settings.js @@ -0,0 +1,33 @@ +(function(back) { + var FILE = "bthrm.json"; + + var settings = Object.assign({ + enabled: true, + replace: true, + }, require('Storage').readJSON(FILE, true) || {}); + + function writeSettings() { + require('Storage').writeJSON(FILE, settings); + } + + E.showMenu({ + '': { 'title': 'Bluetooth HRM' }, + '< Back': back, + 'Use BT HRM': { + value: !!settings.enabled, + format: v => settings.enabled ? "On" : "Off", + onchange: v => { + settings.enabled = v; + writeSettings(); + } + }, + 'Use HRM event': { + value: !!settings.replace, + format: v => settings.replace ? "On" : "Off", + onchange: v => { + settings.replace = v; + writeSettings(); + } + } + }); +}) From 55c7ed5dd8b7273baae42606e66b926126592ebd Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:41:26 +0100 Subject: [PATCH 302/489] Adds app to check status of BT/HRM --- apps.json | 3 ++- apps/bthrm/bthrm.js | 61 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 apps/bthrm/bthrm.js diff --git a/apps.json b/apps.json index 6aa109142..c3001a31d 100644 --- a/apps.json +++ b/apps.json @@ -1043,11 +1043,12 @@ "version": "0.01", "description": "Overrides Bangle.js's build in heart rate monitor with an external Bluetooth one.", "icon": "app.png", - "type": "boot", + "type": "app", "tags": "health,bluetooth", "supports": ["BANGLEJS","BANGLEJS2"], "readme": "README.md", "storage": [ + {"name":"bthrm.app.js","url":"bthrm.js"}, {"name":"bthrm.boot.js","url":"boot.js"}, {"name":"bthrm.img","url":"app-icon.js","evaluate":true}, {"name":"bthrm.settings.js","url":"settings.js"} diff --git a/apps/bthrm/bthrm.js b/apps/bthrm/bthrm.js new file mode 100644 index 000000000..7c80c735f --- /dev/null +++ b/apps/bthrm/bthrm.js @@ -0,0 +1,61 @@ +var btm = g.getHeight()-1; +var eventInt = null; +var eventBt = null; +var counterInt = 0; +var counterBt = 0; + + +function draw(y, event, type, counter) { + var px = g.getWidth()/2; + g.reset(); + g.setFontAlign(0,0); + g.clearRect(0,y,g.getWidth(),y+80); + if (type == null || event == null || counter == 0) return; + var str = event.bpm + ""; + g.setFontVector(40).drawString(str,px,y+20); + str = "Confidence: " + event.confidence; + g.setFontVector(12).drawString(str,px,y+50); + str = "Event: " + type; + g.setFontVector(12).drawString(str,px,y+60); +} + +function onBtHrm(e) { + print("Event for BT " + JSON.stringify(e)); + counterBt += 5; + eventBt = e; +} + +function onHrm(e) { + print("Event for Int " + JSON.stringify(e)); + counterInt += 5; + eventInt = e; +} + +Bangle.on('BTHRM', onBtHrm); +Bangle.on('HRM', onHrm); + +Bangle.setHRMPower(1,'bthrm') +Bangle.setBTHRMPower(1,'bthrm') + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +g.reset().setFont("6x8",2).setFontAlign(0,0); +g.drawString("Please wait...",g.getWidth()/2,g.getHeight()/2 - 16); + +function drawInt(){ + counterInt--; + if (counterInt < 0) counterInt = 0; + if (counterInt > 5) counterInt = 5; + draw(24, eventInt, "HRM", counterInt); +} +function drawBt(){ + counterBt--; + if (counterBt < 0) counterBt = 0; + if (counterBt > 5) counterBt = 5; + draw(100, eventBt, "BTHRM", counterBt); +} + +var interval = setInterval(drawInt, 1000); +var interval = setInterval(drawBt, 1000); From 3baf11613b242807dcdd9060eab60b1e9ddf4645 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:42:29 +0100 Subject: [PATCH 303/489] Adds recorder app plugin to record the BTHRM event --- apps.json | 1 + apps/bthrm/recorder.js | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 apps/bthrm/recorder.js diff --git a/apps.json b/apps.json index c3001a31d..7c9cbffdd 100644 --- a/apps.json +++ b/apps.json @@ -1049,6 +1049,7 @@ "readme": "README.md", "storage": [ {"name":"bthrm.app.js","url":"bthrm.js"}, + {"name":"bthrm.recorder.js","url":"recorder.js"}, {"name":"bthrm.boot.js","url":"boot.js"}, {"name":"bthrm.img","url":"app-icon.js","evaluate":true}, {"name":"bthrm.settings.js","url":"settings.js"} diff --git a/apps/bthrm/recorder.js b/apps/bthrm/recorder.js new file mode 100644 index 000000000..40f64a676 --- /dev/null +++ b/apps/bthrm/recorder.js @@ -0,0 +1,27 @@ +(function(recorders) { + recorders.bthrm = function() { + var bpm = 0; + function onHRM(h) { + bpm = h.bpm; + } + return { + name : "BTHR", + fields : ["BT Heartrate"], + getValues : () => { + result = [bpm]; + bpm = 0; + return result; + }, + start : () => { + Bangle.on('BTHRM', onHRM); + Bangle.setBTHRMPower(1,"recorder"); + }, + stop : () => { + Bangle.removeListener('BTHRM', onHRM); + Bangle.setBTHRMPower(0,"recorder"); + }, + draw : (x,y) => g.setColor(Bangle.isBTHRMOn()?"#00f":"#88f").drawImage(atob("DAwBAAAAMMeef+f+f+P8H4DwBgAA"),x,y) + }; + } +}) + From 47cc9434a30c299eb49820ee95a76e258a021592 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:32:25 +0100 Subject: [PATCH 304/489] Bump version and changelog --- apps.json | 2 +- apps/recorder/ChangeLog | 4 ++++ apps/recorder/README.md | 5 +++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 958bf71e9..95c7b4bbc 100644 --- a/apps.json +++ b/apps.json @@ -768,7 +768,7 @@ "id": "recorder", "name": "Recorder (BETA)", "shortName": "Recorder", - "version": "0.05", + "version": "0.06", "description": "Record GPS position, heart rate and more in the background, then download to your PC.", "icon": "app.png", "tags": "tool,outdoors,gps,widget", diff --git a/apps/recorder/ChangeLog b/apps/recorder/ChangeLog index bedc63141..dbf086f7d 100644 --- a/apps/recorder/ChangeLog +++ b/apps/recorder/ChangeLog @@ -4,3 +4,7 @@ 0.03: Fix theme and maps/graphing if no GPS 0.04: Multiple bugfixes 0.05: Add recording for coresensor +0.06: Add recording for battery stats + Fix execution of other recorders (*.recorder.js) + Modified icons and colors for better visibility + Only show plotting speed if Latitude is available diff --git a/apps/recorder/README.md b/apps/recorder/README.md index 4a4561f1c..87be34424 100644 --- a/apps/recorder/README.md +++ b/apps/recorder/README.md @@ -16,7 +16,8 @@ You can record * **Time** The current time * **GPS** GPS Latitude, Longitude and Altitude * **Steps** Steps counted by the step counter -* **HR** Heart rate +* **HR** Heart rate and confidence +* **BAT** Battery percentage and voltage * **Core** CoreTemp body temperature **Note:** It is possible for other apps to record information using this app @@ -25,4 +26,4 @@ function in `widget.js` for more information. ## Tips -When recording GPS, it usually takes several minutes for the watch to get a [GPS fix](https://en.wikipedia.org/wiki/Time_to_first_fix). There is a grey satellite symbol, which you will see turn red when you get an actual GPS Fix. You can [upload assistant files](https://banglejs.com/apps/#assisted%20gps%20update) to speed up the time spent on getting a GPS fix. +When recording GPS, it usually takes several minutes for the watch to get a [GPS fix](https://en.wikipedia.org/wiki/Time_to_first_fix). There is a red satellite symbol, which you will see turn green when you get an actual GPS Fix. You can [upload assistant files](https://banglejs.com/apps/#assisted%20gps%20update) to speed up the time spent on getting a GPS fix. From 01d236b761c61819aa16d5fa75dd55877dd9289a Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:44:44 +0100 Subject: [PATCH 305/489] Bump version and changelog --- apps.json | 2 +- apps/bthrm/ChangeLog | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 7c9cbffdd..3601aeca4 100644 --- a/apps.json +++ b/apps.json @@ -1040,7 +1040,7 @@ "id": "bthrm", "name": "Bluetooth Heart Rate Monitor", "shortName": "BT HRM", - "version": "0.01", + "version": "0.02", "description": "Overrides Bangle.js's build in heart rate monitor with an external Bluetooth one.", "icon": "app.png", "type": "app", diff --git a/apps/bthrm/ChangeLog b/apps/bthrm/ChangeLog index 5560f00bc..27a58dd78 100644 --- a/apps/bthrm/ChangeLog +++ b/apps/bthrm/ChangeLog @@ -1 +1,4 @@ 0.01: New App! +0.02: Make overriding the HRM event optional + Emit BTHRM event for external sensor + Add recorder app plugin From b0238957b6be2c3ec4b41bcd214c1b25919ff39c Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Fri, 7 Jan 2022 12:56:53 +0100 Subject: [PATCH 306/489] fix update mmind.icon,js from 176px to 48px --- apps/mmind/mmind.icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/mmind/mmind.icon.js b/apps/mmind/mmind.icon.js index 976243b48..17c28ba0f 100644 --- a/apps/mmind/mmind.icon.js +++ b/apps/mmind/mmind.icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("2GwxH+64A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A6gAAFEf5I/VtpEcEcZI/Dw4PbCQu0AApnZDIUeAAqLaDQUFAApIc3IAFEabHPa6StJWLKtJWLStJWLKtJWKieFChIPPCYquKWAZmUVxSwDV6quKWAYjUVxSwDVqQUIB56uTWCiuOWCquOWCiuOWByaFV5oPLVyiwSVyCwTVyCwSVyCwNTIqvMB5iv/V/6vQUpQPTVyqwQVySwRVySwQVySwNT6Kv/V/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V/6vvWCZBSV0CwUJCSuhV/6v/V/4PPWCBBRWCIjSWCJIUV0CvfWB6KTWB4jUWB5IWVz6viWBYdPEZCuMV6ywLJDCuMV+SxLRKyxMEbKxKJDitXCAQALB6AoTRS4jkJHyvoFRCJZEcxI8V9DyZEdpI/ZaQpTB4W0AApnZDIUFAAqLaDQXSAApIckYAFEaTLPbaatJWLKtJWLStJWLKtJWKaeKDAgPPEgyuKWAZmUVxSwDV6quKWAYjUVxSwDV7AZDB56uSWCiuOWCquOWCiuOWByWJBAoPPVyiwSVyCwTVyCwSVyCwNSpIKLB5qv/V/6vuVySwQVySwRVySwQVySwMV/6v/V/6uRV/6v/V8wNDV/6v/V9SuJV/6v/V8atEV/6v/V9KtLV/6v/V8SuNWCiKPWCYjQWCZISVzavSVopGLV/6v/V8RDPVz6wSEaSwRJCiuaV6KuSWCCKTWB4jUWB5IWVzKvKVAyuTCgauMMyqwLEaokDVxhIWVxgjNT46uKIiytcWJojZWJRIcVqygGAA4OOFhYUUJbIjYJH4bOV7AaIRLIjmJH4bMV7QA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+goAHEbUeAA5s/ADO0ADitRWLStIWP6v/VxywWVxiw/V/quOWCiuOWH6v7VyCwSVyCw/V/6v/AH6vpVySwQVySw/V/6v/ABMAAAaXeEa6v/V+SKEWDwjYV/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V+SMFVzgjZV/6vzAHaviWCZHQV36v/V/6v/V/awRJCSu/V/6vLWB5JUV36v/V5awNJSyu/V/6vLWJRMaVv6v/V5YA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4AkA=")) +require("heatshrink").decompress(atob("mEwxH+64A/AEOBq2sBAusqwJHCaQFDAYlP2m0yGBCIkSj0eiWHBIkDgsFgYTE01v3O5t4mC1krgAEBq0ACYQuCAANsHIcxFwIwCEocsFwIwCBIYuCAANQF4QwBOgQABAgNIF4ZgELwQvCHIcCF4cEKwYvEt45DF4QwCL5YvFL5ITDF6OstheCvTjEjAuBjDJFX4UEq4TEyguBygTEF4dWBIeskkkqwQDDgUGgwaEBIUBgITHkslCYeBd4MrqwDBAgIuBcwRVGNIVs0oJEv3S6V+CYmIisjkcVZAYpBgDyBAAJFBFwTlGZIolDqouBGAQJDFwQABmRfCFAICCGwXXhgvDMAheCfI1UF4eoKwYvEiovHSoJfLF4pfJCYYvN1gwBAYMSLwVcbQmQFwOQZIq/C1GACYkcFwMcCYQoCLYNWF4KPBDgNWmIkEBIVPp5TDBIdWqoTHmUyCYlWRQTwCD4wA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AHmy2QJH6PRBI/Q6AkOCAIAFBINDjwABGInR3+53O/GIu72gABGJnQCAQAE69oFwQABCYfFFwIwCBIfCDIe7FIus1gvXLwQACLw4aCAAkAgAvcL4gvLq1WF5uyFwdoCYfLF4fLDpHCX6owBtFoxoUF6PF4ruFDwPC4XJFxbSCAAwVNAH4ARA")) From 2fe1ea524d2d6c0882edcd04ed96c39772aa30df Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Fri, 7 Jan 2022 13:15:54 +0100 Subject: [PATCH 307/489] correct some typo's --- apps/mmind/README.md | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/apps/mmind/README.md b/apps/mmind/README.md index ea584b7e7..8060b95f6 100644 --- a/apps/mmind/README.md +++ b/apps/mmind/README.md @@ -7,15 +7,14 @@ Play the classic mind game mastermind on your Bangle 2. ## Game The game will start when run. -Four colors pins are randomly choosen and kept secret. -You need to find the secret by scoring your choise within 6 turns. +Four colors pins are randomly chosen and kept secret. +You need to find the secret by scoring your choice within 6 turns. The game makes use of touch features. ## Play -The screen needs to be unlocked. Select one of the dots, the color menu will show, select a colour for the pin. -If all pins are choosen with a color the red button will turn green. +If all pins are chosen with a color the red button will turn green. Hit the green button and your play will be scored and listed from the top. The first digit shows the number of pins with the correct color and in the right place. The second digit gives the number of pins with the correct color but in the wrong place. @@ -24,12 +23,9 @@ The blue button will start a new game. ## Requests - -This is the first version, things to add are:/ -Add a menu to change game options like the number of colors, allow double colors, 5 pins per row./ -Add feature to drag screen up and down to see more scores./ -Timer and high score./ +This is the first version, things to add are: +Add a menu to change game options like the number of colors, allow double colors, 5 pins per row. Add feature to drag screen up and down to see more scores. Timer and high score. +Any other fearures or remarks, let me know @psbest. ## Creator - This game is created by Peter Slendebroek. From 2397f5957acc41e9eb91c4da6e65d50901debcca Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Fri, 7 Jan 2022 13:30:09 +0100 Subject: [PATCH 308/489] Add weather functionality Improve circle position finding --- apps/circlesclock/ChangeLog | 2 +- apps/circlesclock/README.md | 4 +- apps/circlesclock/app.js | 138 +++++++++++++++++++++++++++++----- apps/circlesclock/settings.js | 10 +-- 4 files changed, 126 insertions(+), 28 deletions(-) diff --git a/apps/circlesclock/ChangeLog b/apps/circlesclock/ChangeLog index 4230c1468..ca1da6e21 100644 --- a/apps/circlesclock/ChangeLog +++ b/apps/circlesclock/ChangeLog @@ -2,6 +2,6 @@ 0.02: Fix icon & add battery warn functionality 0.03: Theming support & minor fixes 0.04: Make configurable what to show in each circle - Add step distance circle + Add step distance and weather Allow switching visibility of widgets Make circles and text slightly bigger diff --git a/apps/circlesclock/README.md b/apps/circlesclock/README.md index 9004161d6..a071efcf5 100644 --- a/apps/circlesclock/README.md +++ b/apps/circlesclock/README.md @@ -9,14 +9,12 @@ It can show the following information (this can be configured): * Steps distance (depending on steps) * Heart rate (automatically updates when screen is on and unlocked) * Battery (including charging status and battery low warning) + * Weather (requires [weather app](https://banglejs.com/apps/#weather)) ## Screenshots ![Screenshot dark theme](screenshot-dark.png) ![Screenshot light theme](screenshot-light.png) -## TODO -* Show weather information - ## Creator Marco ([myxor](https://github.com/myxor)) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 4f2fea4ab..23be307b9 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -1,5 +1,6 @@ const locale = require("locale"); const heatshrink = require("heatshrink"); +const storage = require("Storage"); const shoesIcon = heatshrink.decompress(atob("h0OwYJGgmAAgUBkgECgVJB4cSoAUDyEBkARDpADBhMAyQRBgVAkgmDhIUDAAuQAgY1DAAYA=")); const shoesIconGreen = heatshrink.decompress(atob("h0OwYJGhIEDgVIAgUEyQKDkmACgcggVACIeQAYMSgIRCgmApIbDiQUDAAkBkAFDGoYAD")); @@ -8,10 +9,19 @@ const powerIcon = heatshrink.decompress(atob("h0OwYQNsAED7AEDmwEDtu2AgUbtuABwXbB const powerIconGreen = heatshrink.decompress(atob("h0OwYQNkAEDpAEDiQEDkmSAgUJkmABwVJBIUEyVAAoYOCgEBFIgODABI")); const powerIconRed = heatshrink.decompress(atob("h0OwYQNoAEDyAEDkgEDpIFDiVJBweSAgUJkmAAoYZDgQpEBwYAJA")); +const weatherCloudy = heatshrink.decompress(atob("h0OwYPMgfwAgU//4FCv///+Ag4DB//gh4EC//jAgYAK+IED8EBAgXAHpQA==")); +const weatherSunny = heatshrink.decompress(atob("h0OwYKHhuAAYM2AQkA7AOD2wFCgdt20AgOA7dtwHAC4PbsAUGgFt2ApIAAgIIA==")); +const weatherPartlyCloudy = heatshrink.decompress(atob("h0OwYOLg4FEn/8AgV+g/gAgMcgE48EB48f/wJBgP/gfwgEDBAIRBC4UH/kB4AmC8F+C4X4gf/AAIaBAAgA==")); +const weatherRainy = heatshrink.decompress(atob("h0OwYKHh/AAgX8AoUB/EAuEAj/wgEDwEHCIX/wIXD8ARB/kAnED+P/8f+BgNwnARCjkOAgUH/+AAoU/IQ4A=")); +const weatherPartlyRainy = heatshrink.decompress(atob("h0OwYJGjkAnAFCj+AAgU//4FCuEA8EAg8ch/4gEB4////AAoIIBCIMD/wgCg4bBg/8BwMD+AgBh4ZBDQf/FIIABh4IBgAA==")); +const weatherSnowy = heatshrink.decompress(atob("h0OwYKHh/AAgUD+AKD/gIDn4LC/4ABBYX8DQYODgYPCAoIOCEAgpGDQRCHA=")); +const weatherFoggy = heatshrink.decompress(atob("h0OwYPMj/+AgU4gFwgED+ACBwEH8AMB/kB4AEBBAYAHg////H/+ABQl+n4LB/A9K")); +const weatherStormy = heatshrink.decompress(atob("h0OwYKHh/AAgX8AoUB/EAuEAj/wgEDwEHCIX/wIRBBwPgAQMcgE4gfwn8D/wpGCgQAQA")); + let settings; function loadSettings() { - settings = require("Storage").readJSON("circlesclock.json", 1) || { + settings = storage.readJSON("circlesclock.json", 1) || { 'minHR': 40, 'maxHR': 200, 'stepGoal': 10000, @@ -48,13 +58,12 @@ const w = g.getWidth(); const hOffset = 30 - widgetOffset; const h1 = Math.round(1 * h / 5 - hOffset); const h2 = Math.round(3 * h / 5 - hOffset); -const h3 = Math.round(8 * h / 8 - hOffset - 3); -const w1 = Math.round(w / 6); -const w2 = Math.round(3 * w / 6); -const w3 = Math.round(5 * w / 6); +const h3 = Math.round(8 * h / 8 - hOffset - 3); // circle y position +const circlePosX = [Math.round(w / 6), Math.round(3 * w / 6), Math.round(5 * w / 6)]; // cirle x positions const radiusOuter = 25; const radiusInner = 18; const circleFont = "Vector:15"; +const circleFontSmall = "Vector:13"; function draw() { g.clear(true); @@ -90,16 +99,17 @@ function draw() { g.drawString(locale.date(new Date()), w > 180 ? 2 * w / 10 : w / 10, h2); g.drawString(locale.dow(new Date()), w > 180 ? 2 * w / 10 : w / 10, h2 + 22); - drawCircle(1, "steps"); - drawCircle(2, "hr"); - drawCircle(3, "battery"); + drawCircle(1); + drawCircle(2); + drawCircle(3); } +const defaultCircleTypes = ["steps", "hr", "battery"]; -function drawCircle(index, defaultType) { - const type = settings['circle' + index] || defaultType; - const w = index == 1 ? w1 : index == 2 ? w2 : w3; - +function drawCircle(index) { + let type = settings['circle' + index]; + if (!type) type = defaultCircleTypes[index - 1]; + const w = getCirclePosition(type); switch (type) { case "steps": drawSteps(w); @@ -113,15 +123,21 @@ function drawCircle(index, defaultType) { case "battery": drawBattery(w); break; + case "weather": + drawWeather(w); + break; } } -function getCirclePosition(type, defaultPos) { +function getCirclePosition(type) { for (let i = 1; i <= 3; i++) { const setting = settings['circle' + i]; - if (setting == type) return i == 1 ? w1 : i == 2 ? w2 : w3; + if (setting == type) return circlePosX[i - 1]; } - return defaultPos || undefined; + for (let i = 0; i < defaultCircleTypes.length; i++) { + if (type == defaultCircleTypes[i]) return circlePosX[i]; + } + return undefined; } function isCircleEnabled(type) { @@ -129,7 +145,7 @@ function isCircleEnabled(type) { } function drawSteps(w) { - if (!w) w = getCirclePosition("steps", w1); + if (!w) w = getCirclePosition("steps"); const steps = getSteps(); // Draw rectangle background: @@ -160,7 +176,7 @@ function drawSteps(w) { } function drawStepsDistance(w) { - if (!w) w = getCirclePosition("steps", w1); + if (!w) w = getCirclePosition("steps"); const steps = getSteps(); const stepDistance = settings.stepLength || 0.8; const stepsDistance = Math.round(steps * stepDistance); @@ -193,7 +209,7 @@ function drawStepsDistance(w) { } function drawHeartRate(w) { - if (!w) w = getCirclePosition("hr", w2); + if (!w) w = getCirclePosition("hr"); // Draw rectangle background: g.setColor(colorBg); @@ -222,7 +238,7 @@ function drawHeartRate(w) { } function drawBattery(w) { - if (!w) w = getCirclePosition("battery", w3); + if (!w) w = getCirclePosition("battery"); const battery = E.getBattery(); // Draw rectangle background: @@ -262,6 +278,85 @@ function drawBattery(w) { g.drawImage(icon, w - 6, h3 + radiusOuter - 6); } +function drawWeather(w) { + if (!w) w = getCirclePosition("weather"); + const weather = getWeather(); + const tempString = weather ? locale.temp(weather.temp - 273.15) : undefined; + const code = weather ? weather.code : -1; + + // Draw rectangle background: + g.setColor(colorBg); + g.fillRect(w - radiusOuter - 3, h3 - radiusOuter - 3, w + radiusOuter + 3, h3 + radiusOuter + 3); + + g.setColor(colorGrey); + g.fillCircle(w, h3, radiusOuter); + + g.setColor(colorBg); + g.fillCircle(w, h3, radiusInner); + + g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); + + const content = tempString ? tempString : "?"; + g.setFont(content.length < 4 ? circleFont : circleFontSmall); + g.setFontAlign(0, 0); + g.setColor(colorFg); + g.drawString(content, w, h3); + + if (code > 0) { + const icon = getWeatherIconByCode(code); + if (icon) g.drawImage(icon, w - 6, h3 + radiusOuter - 6); + } +} + +/* + * Choose weather icon to display based on weather conditition code + * https://openweathermap.org/weather-conditions#Weather-Condition-Codes-2 + */ +function getWeatherIconByCode(code) { + const codeGroup = Math.round(code / 100); + switch (codeGroup) { + case 2: + return weatherStormy; + case 3: + return weatherCloudy; + case 5: + switch (code) { + case 511: + return weatherSnowy; + case 520: + return weatherPartlyRainy; + case 521: + return weatherPartlyRainy; + case 522: + return weatherPartlyRainy; + case 531: + return weatherPartlyRainy; + default: + return weatherRainy; + } + break; + case 6: + return weatherSnowy; + case 7: + return weatherFoggy; + case 8: + switch (code) { + case 800: + return weatherSunny; + case 801: + return weatherPartlyCloudy; + case 802: + return weatherPartlyCloudy; + default: + return weatherCloudy; + } + break; + default: + return undefined; + } + return undefined; +} + function radians(a) { return a * Math.PI / 180; } @@ -309,6 +404,11 @@ function getSteps() { return 0; } +function getWeather() { + const jsonWeather = storage.readJSON('weather.json'); + return jsonWeather && jsonWeather.weather ? jsonWeather.weather : undefined; +} + function enableHRMSensor() { Bangle.setHRMPower(1, "circleclock"); if (hrtValue == undefined) { diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index a16bb99a8..ac4215a8a 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -6,8 +6,8 @@ settings[key] = value; storage.write(SETTINGS_FILE, settings); } - var valuesCircleTypes = ["steps", "stepsDist", "hr", "battery"]; - var namesCircleTypes = ["steps", "distance", "heart", "battery"]; + var valuesCircleTypes = ["steps", "stepsDist", "hr", "battery", "weather"]; + var namesCircleTypes = ["steps", "distance", "heart", "battery", "weather"]; E.showMenu({ '': { 'title': 'circlesclock' }, '< Back': back, @@ -78,19 +78,19 @@ }, 'left': { value: settings.circle1 ? valuesCircleTypes.indexOf(settings.circle1) : 0, - min: 0, max: 3, + min: 0, max: 4, format: v => namesCircleTypes[v], onchange: x => save('circle1', valuesCircleTypes[x]), }, 'middle': { value: settings.circle2 ? valuesCircleTypes.indexOf(settings.circle2) : 2, - min: 0, max: 3, + min: 0, max: 4, format: v => namesCircleTypes[v], onchange: x => save('circle2', valuesCircleTypes[x]), }, 'right': { value: settings.circle3 ? valuesCircleTypes.indexOf(settings.circle3) : 3, - min: 0, max: 3, + min: 0, max: 4, format: v => namesCircleTypes[v], onchange: x => save('circle3', valuesCircleTypes[x]), } From 209d05e6d68c5748f80b98298aaba1cacc68292a Mon Sep 17 00:00:00 2001 From: Qucchia <45072410+qucchia@users.noreply.github.com> Date: Fri, 7 Jan 2022 16:24:36 +0100 Subject: [PATCH 309/489] Fix alarm not activating --- apps/qalarm/qalarm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/qalarm/qalarm.js b/apps/qalarm/qalarm.js index 6b31ba645..8e82be186 100644 --- a/apps/qalarm/qalarm.js +++ b/apps/qalarm/qalarm.js @@ -143,7 +143,7 @@ let alarms = require("Storage").readJSON("qalarm.json", 1) || []; let active = alarms.filter( (alarm) => alarm.on && - alarm.t < t && + alarm.t <= t && alarm.last != time.getDate() && (alarm.timer || alarm.daysOfWeek[time.getDay()]) ); From 426ba76ad4012f14072d1694d36510977346665d Mon Sep 17 00:00:00 2001 From: Qucchia <45072410+qucchia@users.noreply.github.com> Date: Fri, 7 Jan 2022 16:25:15 +0100 Subject: [PATCH 310/489] Update ChangeLog --- apps/qalarm/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/qalarm/ChangeLog b/apps/qalarm/ChangeLog index fb6c751bb..b9be6039d 100644 --- a/apps/qalarm/ChangeLog +++ b/apps/qalarm/ChangeLog @@ -3,3 +3,4 @@ 0.03: Fix unfreed memory, and clearInterval that disabled all clocks at midnight Fix app icon Change menu order so 'back' is at the top +0.04: Fix alarm not activating sometimes. From ab00b477fd39f0304c12cdf407fcbd2d9fa42c16 Mon Sep 17 00:00:00 2001 From: Qucchia <45072410+qucchia@users.noreply.github.com> Date: Fri, 7 Jan 2022 16:25:55 +0100 Subject: [PATCH 311/489] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 3fc0616da..e0c85c2f3 100644 --- a/apps.json +++ b/apps.json @@ -4422,7 +4422,7 @@ "name": "Q Alarm and Timer", "shortName": "Q Alarm", "icon": "app.png", - "version": "0.03", + "version": "0.04", "description": "Alarm and timer app with days of week and 'hard' option.", "tags": "tool,alarm,widget", "supports": ["BANGLEJS", "BANGLEJS2"], From ea71f6a0ead902813e91d065363bcf6b288b7b70 Mon Sep 17 00:00:00 2001 From: Didgeridoohan Date: Fri, 7 Jan 2022 16:39:45 +0100 Subject: [PATCH 312/489] Swedish localisation with English text (en_SE) --- apps/locale/locales.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/apps/locale/locales.js b/apps/locale/locales.js index cf511c54f..fea217efe 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -283,6 +283,24 @@ var locales = { day: "söndag,måndag,tisdag,onsdag,torsdag,fredag,lördag", trans: { yes: "ja", Yes: "Ja", no: "nej", No: "Nej", ok: "ok", on: "on", off: "off" } }, + "en_SE": { // Swedish localisation with English text + lang: "en_SE", + decimal_point: ",", + thousands_sep: ".", + currency_symbol: "kr", + int_curr_symbol: "SKR", + speed: 'kmh', + distance: { "0": "m", "1": "km" }, + temperature: '°C', + ampm: { 0: "", 1: "" }, + timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, + datePattern: { 0: "%A %B %d %Y", "1": "%Y-%m-%d" }, // Sunday 1 March 2020 // 2020-03-01 + abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", + month: "January,February,March,April,May,June,July,August,September,October,November,December", + abday: "Sun,Mon,Tue,Wed,Thu,Fri,Sat", + day: "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday", + // No translation for english... + }, "en_NZ": { lang: "en_NZ", decimal_point: ".", From efc8845c13434357cb7b1afd0d3d1058e572ebce Mon Sep 17 00:00:00 2001 From: Didgeridoohan Date: Fri, 7 Jan 2022 16:42:29 +0100 Subject: [PATCH 313/489] Update ChangeLog --- apps/locale/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/locale/ChangeLog b/apps/locale/ChangeLog index 448f8119a..1b6f82671 100644 --- a/apps/locale/ChangeLog +++ b/apps/locale/ChangeLog @@ -14,3 +14,4 @@ 0.12: Fixed nl_NL formatting, because the full months won't fit on the Bangle.js2's screen 0.13: Now use shorter de_DE date format to more closely match other languages for size 0.14: Added some first translations for Messages in nl_NL +0.15: Added Swedish localisation with English text From 0a4f2dd5b928528d97194bdcee601c380b881b87 Mon Sep 17 00:00:00 2001 From: Didgeridoohan Date: Fri, 7 Jan 2022 16:43:12 +0100 Subject: [PATCH 314/489] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 3fc0616da..f5a17c37d 100644 --- a/apps.json +++ b/apps.json @@ -218,7 +218,7 @@ { "id": "locale", "name": "Languages", - "version": "0.14", + "version": "0.15", "description": "Translations for different countries", "icon": "locale.png", "type": "locale", From 9e0bef98ae313ccabc7117545f56d302953f7ec9 Mon Sep 17 00:00:00 2001 From: 7kasper <7kasper@users.noreply.github.com> Date: Fri, 7 Jan 2022 16:44:54 +0100 Subject: [PATCH 315/489] Add combination HID to bootupdate. --- apps/boot/bootupdate.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/boot/bootupdate.js b/apps/boot/bootupdate.js index 664d64ee7..1b826de5a 100644 --- a/apps/boot/bootupdate.js +++ b/apps/boot/bootupdate.js @@ -18,6 +18,7 @@ boot += `var bleServices = {}, bleServiceOptions = { uart : true};\n`; if (s.ble!==false) { if (s.HID) { // Human interface device if (s.HID=="joy") boot += `Bangle.HID = E.toUint8Array(atob("BQEJBKEBCQGhAAUJGQEpBRUAJQGVBXUBgQKVA3UBgQMFAQkwCTEVgSV/dQiVAoECwMA="));`; + else if (s.HID=="com") boot += `Bangle.HID = E.toUint8Array(atob("BQEJAqEBhQEJAaEABQkZASkFFQAlAZUFdQGBApUBdQOBAwUBCTAJMQk4FYElf3UIlQOBBgUMCjgCFYElf3UIlQGBBsDABQEJBqEBhQIFBxngKecVACUBdQGVCIECdQiVAYEBGQApcxUAJXOVBXUIgQDA"));` else if (s.HID=="kb") boot += `Bangle.HID = E.toUint8Array(atob("BQEJBqEBBQcZ4CnnFQAlAXUBlQiBApUBdQiBAZUFdQEFCBkBKQWRApUBdQORAZUGdQgVACVzBQcZAClzgQAJBRUAJv8AdQiVArECwA=="));` else /*kbmedia*/boot += `Bangle.HID = E.toUint8Array(atob("BQEJBqEBhQIFBxngKecVACUBdQGVCIEClQF1CIEBlQV1AQUIGQEpBZEClQF1A5EBlQZ1CBUAJXMFBxkAKXOBAAkFFQAm/wB1CJUCsQLABQwJAaEBhQEVACUBdQGVAQm1gQIJtoECCbeBAgm4gQIJzYECCeKBAgnpgQIJ6oECwA=="));`; boot += `bleServiceOptions.hid=Bangle.HID;\n`; From 47da82a547e82e29228c3d0a86c2992e71fafb90 Mon Sep 17 00:00:00 2001 From: 7kasper <7kasper@users.noreply.github.com> Date: Fri, 7 Jan 2022 16:48:15 +0100 Subject: [PATCH 316/489] Add HID option to settings. --- apps/setting/settings.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/setting/settings.js b/apps/setting/settings.js index 4bdf7f304..27ce24e50 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -154,8 +154,8 @@ function showAlertsMenu() { function showBLEMenu() { - var hidV = [false, "kbmedia", "kb", "joy"]; - var hidN = ["Off", "Kbrd & Media", "Kbrd","Joystick"]; + var hidV = [false, "kbmedia", "kb", "com", "joy"]; + var hidN = ["Off", "Kbrd & Media", "Kbrd", "Kbrd & Mouse" ,"Joystick"]; E.showMenu({ '': { 'title': 'Bluetooth' }, '< Back': ()=>showMainMenu(), From 677cd16f8b081c8954bd8242d1a9328e5b3d5778 Mon Sep 17 00:00:00 2001 From: David Peer Date: Fri, 7 Jan 2022 17:26:34 +0100 Subject: [PATCH 317/489] Fixed bug that clock is unresponsive --- apps.json | 2 +- apps/lcars/ChangeLog | 3 ++- apps/lcars/lcars.app.js | 26 ++++++++++---------------- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/apps.json b/apps.json index 0f200d53a..20ac0afce 100644 --- a/apps.json +++ b/apps.json @@ -4488,7 +4488,7 @@ "name": "LCARS Clock", "shortName":"LCARS", "icon": "lcars.png", - "version":"0.09", + "version":"0.10", "readme": "README.md", "supports": ["BANGLEJS2"], "description": "Library Computer Access Retrieval System (LCARS) clock.", diff --git a/apps/lcars/ChangeLog b/apps/lcars/ChangeLog index f5d8346da..26aa605e6 100644 --- a/apps/lcars/ChangeLog +++ b/apps/lcars/ChangeLog @@ -6,4 +6,5 @@ 0.06: Fix - Alarm disabled, if clock was closed. 0.07: Added settings to adjust data that is shown for each row. 0.08: Support for multiple screens. 24h graph for steps + HRM. Fullscreen Mode. -0.09: Tab anywhere to open the launcher. \ No newline at end of file +0.09: Tab anywhere to open the launcher. +0.10: Fix - Clock is unresponsive, if gadgetbridge connects. \ No newline at end of file diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 8f06abc29..3535f57d5 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -32,8 +32,8 @@ let cGrey = "#9E9E9E"; let lcarsViewPos = 0; let drag; let hrmValue = 0; -var connected = NRF.getSecurityStatus().connected; var plotWeek = false; +var disableInfoUpdate = true; // When gadgetbridge connects, step infos cannot be loaded /* * Requirements and globals @@ -170,7 +170,7 @@ function drawHorizontalBgLine(color, x1, x2, y, h){ } -function drawLock(){ +function drawInfo(){ if(lcarsViewPos != 0){ return; } @@ -179,7 +179,8 @@ function drawLock(){ g.setColor(cOrange); g.clearRect(120, 10, g.getWidth(), 75); g.drawString("LCARS", 128, 13); - if(connected){ + + if(NRF.getSecurityStatus().connected){ g.drawString("CONN", 128, 33); } else { g.drawString("NOCON", 128, 33); @@ -243,8 +244,8 @@ function drawPosition0(){ drawHorizontalBgLine(cOrange, 35, batX2, 171, 5); drawHorizontalBgLine(cGrey, batX2+10, 172, 171, 5); - // Draw logo - drawLock(); + // Draw Infos + drawInfo(); // Write time g.setFontAlign(-1, -1, 0); @@ -467,24 +468,17 @@ function handleAlarm(){ Bangle.on('lcdPower',on=>{ if (on) { // Whenever we connect to Gadgetbridge, reading data from - // health failed. Therefore, we update and read data from - // health iff the connection state did not change. - if(connected == NRF.getSecurityStatus().connected) { - draw(); - } else { - connected = NRF.getSecurityStatus().connected - drawLock(); - } + // health failed. Therefore, we update only partially... + drawInfo(); + drawState(); } else { // stop draw timer if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; } - - connected = NRF.getSecurityStatus().connected }); Bangle.on('lock', function(isLocked) { - drawLock(); + drawInfo(); }); Bangle.on('charging',function(charging) { From 83debe93ee54ef1d01f78e572dc2c1a2d7dee66e Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Fri, 7 Jan 2022 18:21:36 +0100 Subject: [PATCH 318/489] Bigger weather icons & a bit thinner circles --- apps/circlesclock/app.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 23be307b9..f93a283f2 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -9,14 +9,14 @@ const powerIcon = heatshrink.decompress(atob("h0OwYQNsAED7AEDmwEDtu2AgUbtuABwXbB const powerIconGreen = heatshrink.decompress(atob("h0OwYQNkAEDpAEDiQEDkmSAgUJkmABwVJBIUEyVAAoYOCgEBFIgODABI")); const powerIconRed = heatshrink.decompress(atob("h0OwYQNoAEDyAEDkgEDpIFDiVJBweSAgUJkmAAoYZDgQpEBwYAJA")); -const weatherCloudy = heatshrink.decompress(atob("h0OwYPMgfwAgU//4FCv///+Ag4DB//gh4EC//jAgYAK+IED8EBAgXAHpQA==")); -const weatherSunny = heatshrink.decompress(atob("h0OwYKHhuAAYM2AQkA7AOD2wFCgdt20AgOA7dtwHAC4PbsAUGgFt2ApIAAgIIA==")); -const weatherPartlyCloudy = heatshrink.decompress(atob("h0OwYOLg4FEn/8AgV+g/gAgMcgE48EB48f/wJBgP/gfwgEDBAIRBC4UH/kB4AmC8F+C4X4gf/AAIaBAAgA==")); -const weatherRainy = heatshrink.decompress(atob("h0OwYKHh/AAgX8AoUB/EAuEAj/wgEDwEHCIX/wIXD8ARB/kAnED+P/8f+BgNwnARCjkOAgUH/+AAoU/IQ4A=")); +const weatherCloudy = heatshrink.decompress(atob("iEQwYWTgP//+AAoMPAoPwAoN/AocfAgP//0AAgQAB/AFEABgdDAAMDDohMRA")); +const weatherSunny = heatshrink.decompress(atob("iEQwYLIg3AAgVgAQMMAo8Am3YAgUB23bAoUNAoIUBjYFCsOwBYoFDDpFgHYI1JI4gFGAAYA=")); +const weatherPartlyCloudy = heatshrink.decompress(atob("iEQwYQNv0AjgGDn4EDh///gFChwREC4MfxwIBv0//+AC4X4j4FCv/AgfwgED/wIBuAaBBwgFDgP4gf/AAXABwIEBDQQAEA==")); +const weatherRainy = heatshrink.decompress(atob("iEQwYLIg/gAgUB///wAFBh/AgfwgED/wIBuEAj4OCv0AjgaCh/4AocAnAFBFIU4EAM//gRBEAIOBhw1C/AmDAosAC4JNIAAg")); const weatherPartlyRainy = heatshrink.decompress(atob("h0OwYJGjkAnAFCj+AAgU//4FCuEA8EAg8ch/4gEB4////AAoIIBCIMD/wgCg4bBg/8BwMD+AgBh4ZBDQf/FIIABh4IBgAA==")); -const weatherSnowy = heatshrink.decompress(atob("h0OwYKHh/AAgUD+AKD/gIDn4LC/4ABBYX8DQYODgYPCAoIOCEAgpGDQRCHA=")); -const weatherFoggy = heatshrink.decompress(atob("h0OwYPMj/+AgU4gFwgED+ACBwEH8AMB/kB4AEBBAYAHg////H/+ABQl+n4LB/A9K")); -const weatherStormy = heatshrink.decompress(atob("h0OwYKHh/AAgX8AoUB/EAuEAj/wgEDwEHCIX/wIRBBwPgAQMcgE4gfwn8D/wpGCgQAQA")); +const weatherSnowy = heatshrink.decompress(atob("iEQwYROn/8AocH8AECuAFBh0Agf+CIN/4EDx/4j/x4EAgIIBwAXBAogRFDoopFGoxBGABIA=")); +const weatherFoggy = heatshrink.decompress(atob("iEQwYROn/8AgUB/EfwAFBh/AgfwgED/wIBuEABwd/4EcDQgFDgE4Fosf///8f//A/Lj/xCQIRNA=")); +const weatherStormy = heatshrink.decompress(atob("iEQwYLIg/gAgUB///wAFBh/AgfwgED/wIBuEAj4OCv0AjgaCh/4AoX8gE4AoQpBnAdBF4IRBDQMH/kOHgY7DAo4AOA==")); let settings; @@ -61,7 +61,7 @@ const h2 = Math.round(3 * h / 5 - hOffset); const h3 = Math.round(8 * h / 8 - hOffset - 3); // circle y position const circlePosX = [Math.round(w / 6), Math.round(3 * w / 6), Math.round(5 * w / 6)]; // cirle x positions const radiusOuter = 25; -const radiusInner = 18; +const radiusInner = 20; const circleFont = "Vector:15"; const circleFontSmall = "Vector:13"; @@ -292,9 +292,9 @@ function drawWeather(w) { g.fillCircle(w, h3, radiusOuter); g.setColor(colorBg); - g.fillCircle(w, h3, radiusInner); + g.fillCircle(w, h3, radiusInner + 1); // the weather circle is thinner - g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); + g.fillPoly([w, h3, w - 25, h3 + radiusOuter + 5, w + 25, h3 + radiusOuter + 5]); const content = tempString ? tempString : "?"; g.setFont(content.length < 4 ? circleFont : circleFontSmall); @@ -304,7 +304,7 @@ function drawWeather(w) { if (code > 0) { const icon = getWeatherIconByCode(code); - if (icon) g.drawImage(icon, w - 6, h3 + radiusOuter - 6); + if (icon) g.drawImage(icon, w - 6, h3 + radiusOuter - 10); } } @@ -375,7 +375,7 @@ function drawGauge(cx, cy, percent, color) { g.setColor(color); - const size = radiusOuter - radiusInner - 2; + const size = radiusOuter - radiusInner - 3; // draw gauge for (i = startrot; i > endrot - size; i -= size) { x = cx + r * Math.sin(radians(i)); From 8bbe2a43b40a2a2f6bc48b17f934ac2c413a3a86 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Fri, 7 Jan 2022 18:33:09 +0100 Subject: [PATCH 319/489] Same size for every circle --- apps/circlesclock/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index f93a283f2..6d408fd59 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -292,7 +292,7 @@ function drawWeather(w) { g.fillCircle(w, h3, radiusOuter); g.setColor(colorBg); - g.fillCircle(w, h3, radiusInner + 1); // the weather circle is thinner + g.fillCircle(w, h3, radiusInner); g.fillPoly([w, h3, w - 25, h3 + radiusOuter + 5, w + 25, h3 + radiusOuter + 5]); From 6a72aafc1919f4440051a20424c13dd12953e635 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 7 Jan 2022 20:18:17 +0100 Subject: [PATCH 320/489] layout: use 'col' for btn label/image --- modules/Layout.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/Layout.js b/modules/Layout.js index 65e9a8dc8..cb64183ea 100644 --- a/modules/Layout.js +++ b/modules/Layout.js @@ -34,7 +34,7 @@ layoutObject has: optional `scale` specifies if image should be scaled up or not * `"custom"` - a custom block where `render(layoutObj)` is called to render * `"h"` - Horizontal layout, `c` is an array of more `layoutObject` - * `"v"` - Veritical layout, `c` is an array of more `layoutObject` + * `"v"` - Vertical layout, `c` is an array of more `layoutObject` * A `id` field. If specified the object is added with this name to the returned `layout` object, so can be referenced as `layout.foo` * A `font` field, eg `6x8` or `30%` to use a percentage of screen height @@ -261,6 +261,7 @@ Layout.prototype.render = function (l) { x,y+4 ], bg = l.selected?g.theme.bgH:g.theme.bg2; g.setColor(bg).fillPoly(poly).setColor(l.selected ? g.theme.fgH : g.theme.fg2).drawPoly(poly); + if (l.col) g.setColor(l.col); if (l.src) g.setBgColor(bg).drawImage("function"==typeof l.src?l.src():l.src, l.x + 10 + (0|l.pad), l.y + 8 + (0|l.pad)); else g.setFont("6x8",2).setFontAlign(0,0,l.r).drawString(l.label,l.x+l.w/2,l.y+l.h/2); }, "img":function(l){ From 436aecbca3f6fc772c83205daa4ae9ce1baea7c0 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Fri, 7 Jan 2022 20:28:00 +0100 Subject: [PATCH 321/489] ISO8601 added in changelog and readme --- apps/ffcniftya/ChangeLog | 2 +- apps/ffcniftya/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/ChangeLog b/apps/ffcniftya/ChangeLog index bf70a213b..420c553f5 100644 --- a/apps/ffcniftya/ChangeLog +++ b/apps/ffcniftya/ChangeLog @@ -1,2 +1,2 @@ 0.01: New Clock Nifty A -0.02: Shows the current week number, can be disabled via settings "" +0.02: Shows the current week number (ISO8601), can be disabled via settings "" diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index 769cbcb74..66acd1421 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -8,7 +8,7 @@ Colors are black/white - photos have non correct camera color "blue" ![](photo_nifty.png) (*photo*) -## The week number can be turned of in settings +## The week number (ISO8601) can be turned of in settings (default is **"On"**) ![](screenshot_settings_nifty.png) (*emulated*) From a3d1494318039c39d464204cc654e76cf321dc53 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Fri, 7 Jan 2022 20:34:23 +0100 Subject: [PATCH 322/489] update tags mmind , remove spaces. --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 663cb1ae3..5dd4331f9 100644 --- a/apps.json +++ b/apps.json @@ -5134,7 +5134,7 @@ "version":"0.01", "description": "This is the classic game for masterminds", "type": "game", - "tags": "mastermind, game, classic", + "tags": "game,app", "readme":"README.md", "supports": ["BANGLEJS2"], "allow_emulator": true, From 0ee13c2fffc9902cb9d9351004491fe7da7ee768 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Fri, 7 Jan 2022 21:05:46 +0100 Subject: [PATCH 323/489] added screenshot to mmind app --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 5dd4331f9..3321f822f 100644 --- a/apps.json +++ b/apps.json @@ -5133,6 +5133,7 @@ "icon": "mmind.png", "version":"0.01", "description": "This is the classic game for masterminds", + "screenshots": [{"url":"screenshot_mmind.png"}], "type": "game", "tags": "game,app", "readme":"README.md", From c8ea4c55b3e743ceee9350a091fcd80d63023826 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 7 Jan 2022 22:43:49 +0000 Subject: [PATCH 324/489] Limelight, switched to bolted hands, redid screenshots --- apps/limelight/README.md | 1 + apps/limelight/limelight.app.js | 98 +++++++++++++++++------- apps/limelight/screenshot_gochihand.png | Bin 2332 -> 2452 bytes apps/limelight/screenshot_grenadier.png | Bin 2376 -> 2646 bytes apps/limelight/screenshot_limelight.png | Bin 2425 -> 2573 bytes apps/limelight/screenshot_monoton.png | Bin 3032 -> 2993 bytes 6 files changed, 71 insertions(+), 28 deletions(-) diff --git a/apps/limelight/README.md b/apps/limelight/README.md index f1cc52092..e84714403 100644 --- a/apps/limelight/README.md +++ b/apps/limelight/README.md @@ -6,6 +6,7 @@ * Selection of different fonts * Settings menu where you can select font, or switch to Vector font and try a range of sizes * 100 less lines of code, demonstrating that there is no need for a custom widget draw method +* Full screen options (widgets loaded but not displayed) ![](screenshot_gochihand.png) ![](screenshot_monoton.png) diff --git a/apps/limelight/limelight.app.js b/apps/limelight/limelight.app.js index 2d4ce5a43..20d79deeb 100644 --- a/apps/limelight/limelight.app.js +++ b/apps/limelight/limelight.app.js @@ -1,3 +1,14 @@ +/* + * Limelight analoguce clock with bolted hands + * Based on the work of @Andreas_Rozek + * [Simple_Clock](https://github.com/espruino/BangleApps/tree/master/apps/simple_clock) + * + * . Demonstrates simpler approach to establishing the available size of the appRect in relation + * to widgets, avoids having to take on the responsibility for managing the widget draw. + * . Demonstrates a settings menu and various configuration options + * . Demonstrates fullscreen verses, widgets and app area. + * + */ g.clear(); @@ -78,7 +89,7 @@ if (settings.fullscreen) { } function debug(o) { - console.log(o); + //console.log(o); } debug("limelight.app.js"); @@ -88,35 +99,54 @@ debug("outerRadius=" + outerRadius); debug("y12=" + (CenterY - outerRadius)); debug("y6=" + (CenterY + outerRadius)); -const HourHandLength = outerRadius * 0.5; -const HourHandWidth = 2*3, halfHourHandWidth = HourHandWidth/2; -const MinuteHandLength = outerRadius * 0.7; -const MinuteHandWidth = 2*2, halfMinuteHandWidth = MinuteHandWidth/2; -const SecondHandLength = outerRadius * 0.9; -const SecondHandOffset = 6; +let HourHandLength = outerRadius * 0.5; +let HourHandWidth = 2*5, halfHourHandWidth = HourHandWidth/2; -const twoPi = 2*Math.PI; -const Pi = Math.PI; -const halfPi = Math.PI/2; +let MinuteHandLength = outerRadius * 0.7; +let MinuteHandWidth = 2*3, halfMinuteHandWidth = MinuteHandWidth/2; -let HourHandPolygon = [ - -halfHourHandWidth,halfHourHandWidth, - -halfHourHandWidth,halfHourHandWidth-HourHandLength, - halfHourHandWidth,halfHourHandWidth-HourHandLength, - halfHourHandWidth,halfHourHandWidth, +let SecondHandLength = outerRadius * 0.9; +let SecondHandOffset = halfHourHandWidth + 10; + +let outerBoltRadius = halfHourHandWidth + 2, innerBoltRadius = outerBoltRadius - 4; +let HandOffset = outerBoltRadius + 4; + +let twoPi = 2*Math.PI, deg2rad = Math.PI/180; +let Pi = Math.PI; +let halfPi = Math.PI/2; + +let sin = Math.sin, cos = Math.cos; + +let sine = [0, sin(30*deg2rad), sin(60*deg2rad), 1]; + +let HandPolygon = [ + -sine[3],-sine[0], -sine[2],-sine[1], -sine[1],-sine[2], -sine[0],-sine[3], + sine[0],-sine[3], sine[1],-sine[2], sine[2],-sine[1], sine[3],-sine[0], + sine[3], sine[0], sine[2], sine[1], sine[1], sine[2], sine[0], sine[3], + -sine[0], sine[3], -sine[1], sine[2], -sine[2], sine[1], -sine[3], sine[0], ]; -let MinuteHandPolygon = [ - -halfMinuteHandWidth,halfMinuteHandWidth, - -halfMinuteHandWidth,halfMinuteHandWidth-MinuteHandLength, - halfMinuteHandWidth,halfMinuteHandWidth-MinuteHandLength, - halfMinuteHandWidth,halfMinuteHandWidth, -]; +let HourHandPolygon = new Array(HandPolygon.length); +for (let i = 0, l = HandPolygon.length; i < l; i+=2) { + HourHandPolygon[i] = halfHourHandWidth*HandPolygon[i]; + HourHandPolygon[i+1] = halfHourHandWidth*HandPolygon[i+1]; + if (i < l/2) { HourHandPolygon[i+1] -= HourHandLength; } + if (i > l/2) { HourHandPolygon[i+1] += HandOffset; } +} +let MinuteHandPolygon = new Array(HandPolygon.length); +for (let i = 0, l = HandPolygon.length; i < l; i+=2) { + MinuteHandPolygon[i] = halfMinuteHandWidth*HandPolygon[i]; + MinuteHandPolygon[i+1] = halfMinuteHandWidth*HandPolygon[i+1]; + if (i < l/2) { MinuteHandPolygon[i+1] -= MinuteHandLength; } + if (i > l/2) { MinuteHandPolygon[i+1] += HandOffset; } +} -let transformedPolygon = new Array(HourHandPolygon.length); +/**** transforme polygon ****/ + +let transformedPolygon = new Array(HandPolygon.length); function transformPolygon (originalPolygon, OriginX,OriginY, Phi) { - let sPhi = Math.sin(Phi), cPhi = Math.cos(Phi), x,y; + let sPhi = sin(Phi), cPhi = cos(Phi), x,y; for (let i = 0, l = originalPolygon.length; i < l; i+=2) { x = originalPolygon[i]; @@ -127,8 +157,11 @@ function transformPolygon (originalPolygon, OriginX,OriginY, Phi) { } } -function drawHands () { +/**** draw clock hands ****/ + +function drawClockHands () { let now = new Date(); + let Hours = now.getHours() % 12; let Minutes = now.getMinutes(); let Seconds = now.getSeconds(); @@ -138,14 +171,17 @@ function drawHands () { let SecondsAngle = (Seconds/60) * twoPi - Pi; g.setColor(g.theme.fg); + transformPolygon(HourHandPolygon, CenterX,CenterY, HoursAngle); g.fillPoly(transformedPolygon); + transformPolygon(MinuteHandPolygon, CenterX,CenterY, MinutesAngle); g.fillPoly(transformedPolygon); + let sPhi = Math.sin(SecondsAngle), cPhi = Math.cos(SecondsAngle); + if (settings.secondhand) { - let sPhi = Math.sin(SecondsAngle), cPhi = Math.cos(SecondsAngle); - g.setColor('#FF0000'); + g.setColor(g.theme.fg2); g.drawLine( CenterX + SecondHandOffset*sPhi, CenterY - SecondHandOffset*cPhi, @@ -153,6 +189,13 @@ function drawHands () { CenterY + SecondHandLength*cPhi ); } + + g.setColor(g.theme.fg); + g.fillCircle(CenterX,CenterY, outerBoltRadius); + + g.setColor(g.theme.bg); + g.drawCircle(CenterX,CenterY, outerBoltRadius); + g.fillCircle(CenterX,CenterY, innerBoltRadius); } function setNumbersFont() { @@ -192,7 +235,7 @@ function draw() { g.setColor(g.theme.bg); g.fillRect(Bangle.appRect); - drawHands(); + drawClockHands(); drawNumbers(); queueDraw(); } @@ -216,6 +259,5 @@ Bangle.on('lcdPower',on=>{ } }); -loadSettings(); Bangle.setUI('clock'); draw(); diff --git a/apps/limelight/screenshot_gochihand.png b/apps/limelight/screenshot_gochihand.png index af405c0f8406505893cedcbac16da25ea1e27804..244b008dc2f56804bcb252a7f89dd49339c6e0f7 100644 GIT binary patch literal 2452 zcmai$dpOkDAIHyk#tdc{lnK#QDKkdol1pO|hLsV9M3~s*+UQ5iPcC2ki>5>utyL)3 z+!_ql$GPLsv$!~pz8^_h9I z>z3pIk(M#^OkwYux6@Ax`c;1q(Z-1cYhn~6%ofG!_hn|v>buO*6ddHuNaABm|k+I;ryvGF9)Jww~I}JZ) zVnF;AIV8AM+8-4|xmfDL4#q6FzM1MuU_7ld^!iZoVWjrE@foymUAMOm6}(yaDTgyd ze+d>Ut~$T?JjN@lb(WJEtuvS8zse2;m6+mteO*vGDYx#u9kqO=(OO3{edH5aXFGE! z+Xy^l{h4-}y`v!A@NqbEPQ59T9!yOfxX8GX<{f`ji@5&yV^>;J3CbQH;3%C(^g=PB zy~ZW0K9Pi%;EEy%TFjA4!ROP5pS50G>gHS>eM!If8i{ z2)lf(n^g<|x|@dsLf+b)dCOxUP(5Oa3U<#HBpyQ>k~oCXU_}raQG?(SvyG!RP}m9U zxwf*A?KJJiV#F*9a+l`Jh}15i)b78!*7hJDxPy(wR<|STw;fxex2fEtqA!0ZEhzy zLSSvKvv|L_LkjA)?L`1=M))xlFrb00P%!NR;MhjpQZ@>l?U3RLH34EasqAV60c~H2 zzzs#fe01?9DGvZ8-Cy)$aDd}@%!cR$;ACZson{y?TBMqP<1l9z@}LSLeo4|-#D!pV zqd9y9`H`e3Rk+1J~ zf2b@J!urZ-uXcvW>d23vc@GBH0J@rZ|L3jQtk@Y%0*K$7emYpasgUVfqp}w*EXi?~ zHBRc+(J0dH&wNqlx|V4s%Unz<&8(R0BBso5zO)%DbJ2v$Lh^1HQ`wI;3^e-cJwMMT zPZEt#OSnBPQ{TPz4R58NT~igNe(m49YZmJt#KevUhd43c`mLKZ>I-ho> z*>CY6*qsp7MeEU0&y)XMpEdlj=2LcwMFT3BG&}FwjsJ4vk;#~l+dpQ|8?c-~5WXB* z*YefqxQ`7=Y1O0iNZ}$Es5M+YQu)B*r>qmN3jAUoCqynxJV|oP*OF}m_5G`#r>m^ zWPyzxo*~Hr&);;8xrsvbLA;yj-cTLW?2Bc;vlFFyr(eK6eUh~9INn%LVr>~zfASo4 zvqj^D^;?QzPqO>XkZe`j&3iSOs^`WwjnifymLPVm+|n@C{Gh|F;#|9lOAdaCMt)Ub z;YlfVHs(sy8-bn81?9{J%4-I1Dz)dyniQgO2Kl|K9<1+$HvDhQ0h>72lN{+}(SmklJm!Um>H%J`E^zST6vna~B#D20d?>jj~W+ zv(CPxb)`)g4a65_QJrKbrNM1qtf zhQ4iSHHfZg>`|n|{r3qBcW(7`g#V^Fd0G!8CPm@yTrZa#oWKEMwz!F`oDcq>35XLzY2km50D_wt^M&{Y94CSIsg~JS{!_A)q0hUQ2`({O; zPb`b#-zB^6*?``24H!&?v1e$TUtRG>fU5PLt7wjsJ-#5nq=J}{Y)s-P45c!&@eOVf zOGTLDLX-}8hvO(YYuZIm+uL`=&)m8Fb-9rnn}Ipvy5Unbo3Oe?5MA%l?K>HD%b>We zD9;izyuDnE*YXiP^}D!`Q`Ijp;U{j-Ixx|^^sU6 zFwEJcq)*F?9yhN4je6H9fl_*gRC?aKltZJCI6if+Z7FXm_Lw$n@Qt63w)~nSNk`nH zEi39fE~|lwKEQ19?^AGNdw$ssNB-c9=Bt8XZ3yuwG?L_!3)ONLuj_q#x2)E**2Z8S z%t+TEcTBy+BX7GoVS%Yba2B-GAFD$gy?K5TGUY0Ov%k@fx*P@w?v7MR82}@zNxh0< zl3O0IoF@U~a?3uwL=-5Ozka(>91&iu?vuFykgfI?REjfUMD-u7&%j&3j~*P8JPq+T O3)orHttu^npGOI2g!9Am-1q0Yug`V;bYIVt?CeOCmQs>}!C=xP zJ8M^Qt^Rf3lH$9H^U+6KBqCjjCt;O5m01`J&L>%)ICI5kzHsz1>)=jU{?^vaS9NI} zGHj0Od1!E0%_CKE$obvz`1trD%eWI1XFvwrUmuyhp^?B%lC>B7U9l#;vFLtjV+#pc zjS@}3Zs-A`0#J1z&n0_L2LPUr(b0Akz5DT46p&B;4X07arO7od8~7ZB$bXZo*>l+< zQPW+517sDC)*9D!e>Tt^l+JmQsI3DjZ8%%(Fq9A144(zba-+?;hC`lZDgFM4>;;cw z<;j}iBsjQQPuUz1yJ}7DZ(1%PT~)VRx({XWaqUOfj&%-3tG9NjeX~dmX7F2k2lMcA ziD-hrxd2OdfI*&ev^Hk|u5u?UfQ?WKr+=u}YY&60E@oDkNq`p|3RX^vQEkV}Cz=Ud zc5}xZD-afIv z!+VN04}ymEjo8Y7{^mY)`NGhfU*A~?kdCe~m;isE=jO)M<>&1Rc*)X?y-=vg#@ZN? z(Pmy~<*jxVGujUxs!ho>)Jj)puK`j4Ot}0JOjZPo#(J@*qxb}0`OYv@>zm3jNnq~Y*%SiB;vC4w zm7_1Nv_$@N96J&LRu;34>kPW}ha?jy%A8l)B~|;hfYG;!HYSXDZPW6=zB#P;kvoYQVZ;9 ze8lTmK8rEmNf0QcmFb`Im9Ol%F^FspUDX$Yy?92fceWLxwQV;sr^$^qMV;`~oL3cA zzOH)%kR^s-r&*I^o<~Vl{b8aCW?f#hdikd5Gje2_$vxpQ27TrEfohxT{;Bl8YU_XY z)G|N$Ww`lSigp2E_c(apI_{nat89)G)nl}o={+ob?$IE#&UQ|oe;t$S_i$_o@ch`M z+a0UHyxK~)pS+MxH@>SM^(0C0q(D#SoS9KwFV4Z2z5IAP^Hkmbz8-93InrJ4xALjA z&qfz*&*jG=U34|Amag`UO#w_P=cz`tFcX)TS0*(kvNqN7F4Ox$UHZ}_6nO+-%s%@r zx$BHRii}3ay-DJ0O$H^^^XHY6zMp!(v~V6@6o^2LXgFIhGNY>eiUWDoj62jbFG~Yw zR$!3R(c;i9y}qf%AM&{?NQm6L6~B<-ZV(>i8{KfNB1TKMGr-dRz|y)_s!?_S=gH!t zTW|X{hylwOvn(zXfve??@>2qRtZfBV<(fI%Jo?o=&{-2zySUG@v1Z>Zyu9STF90b4 zKECI!I{DLCrWKy5<@+2nPAfoqm)67cYg(R`SBG%2;bYQ_wnQPehFTn)mUHPgLjS=> zJT-KrIm-P$d1m6)<=wB;&cyl0x~9-P6S>k#arIpqCg}AdiS{COqjWvbW#<;BV3*TE zGirYKJJQ#Ct#qMmBj=eAVbWvDv{z9#lEXu-_i3!GP#xw{@S=AvqTtkrs4}dsUX%{J zpxUBtTrgxkc1keM$$qrqr#L&0#w;r^{uOVeEN_t}1&aVJbb z9i_WbGbsFZKbA_}h5!R714QSLf*V0Ucc?(hJ$s+141UkW0z}0jo&NDsV;~xB6!F%a zoXXA6jOvXVHrNhCXIFL)MCW(Iy*i6|M}$~0hsoxPqTjlzg&W++{8-3P!i1w=2Q!VA zOl<{upRhd^Q{pBdbI6c(C>hn*V2oJmum6)ExOx4FZqTiuR4zM&)XbYfW5Qi)&N0nI zOaSuC%Zy{A#P(XbWl=FKl9(f{NNLMx*bP6H;M``f^1Il>$XwFn@VZ#~g!LD1Dqk$r z)~9fOBNdJLMgRh}%|^vSICo=;v`2|CAfxTX%*5HHa&tliTUa-sg`C2DTHv{ro+J?6 zCg0{l23ap#^k1m{ohFgaHCAcgd_dAM0CM3kjuXYn-owJKkIx%FSB7mA0?;;h+pVql z37HqN0H}~{>!U@W;Q@1rhVQg^9=dcFkwS|_jUZkrrg0q;;9tR+okWTj;W0N;OP=R? zL5%Vmd=b4ehYG^CPr~&RE=48T4h*;+Q#C~W*i?a5dN;*U^nXeF?GsLJMXKgc+dEPC zgsGe^w^3kLnnFk(EFlQ~%MU(41^!APiu2bI#1UbHDSYy1UwmVD@4F03r_d zCp`I;@h^fXer{-)59SwGyr-QNpbsg01^^@GaKh4?6#VtxRMJD7u#MX8?r@2X%hJ2t zywzUrbifr|e%#!aPNQ07aB+za@u_#s z7WY%*x?a)d?o(cO_``WM#sIHNs~^yWMJ0kk>HVXWw^$b9NW@^{sMFA{Hh$r)G}+DQ z30x4`u(~V{O$K|UsxBfO;#Pu_Qyw^Nk8teS*I&l_JVO#|UYTvtb3~!H6di-nFfhT! z8{N;{!BZdqZ1*`g-4_s$yKXwXRq`_3n&wD;>NZQj3PaIQ*p8B>uq7T%2YxrAo>@E; zaq6redyz8dw6&fb0E<3WJ3KlM1waO;7j5VSL5+Q&STbc{u>g&m><`zuaUpk})*0+8 zzgx0NyY*wy(sr%(FPt7|Ko8$L)+ONQ=={aJaw{z#?t%OV@7VlP2a>;8wk3z*S*2#> z^t8IbK$lC3^pHCs8+ae+y?_C{3nPs&S#VHVzF$Ae3y`CW$}$Zk0rx>p-<;i`ko#1e zf+fnv+!@U!7mxIBjC?RvLHF#IU?5kK&S+j!G2-+&@y&+Hv~GvB{1uOb=;IC8S3gs@ zknJG-!5C1ttfz)JZ;iizvD`V4n@raz``ET}K+|p$XxK=w9Cgz23XGEl@^5r3SN{Hm z4z(6{wT7`CO``(VY|?e10L(}sTYvBrw)gu<69qEjV3S3)zpcC|IelD!DB^!lpTK20 zou7rReGG>)is`*Lk(grM9TE_Rq^orL!pV)=Ra7(tB16J8$&`)VPY*H$xwKekCz6H| zKrk}ZVrc@UvfQ+){71yKTN{ z(H4ZHn=bdwLdU0%Hy&7GmRI6hqfa`33C{^xHA?lK`s6}18RqxmMzXUcQKaMPX#6h= z(MXi{9X&Xaz0r7!(5hs=Wk>q8)&yB@C7m;t;|eFp88H%x|A( zboQ7PliQ@-_mxVM2K{^6T=)ISi@FYH1S)`Hqa**`^vLsqvD8_yq=rnuB|qw|0g;lC zJu#g0cXh&0N_|$YK=9oG5II_xW(cMZpon*aKUKh3hxEbJcTGi+j-+H5i|+qH7&JQx zK}mye&H_dd0W?SW96^vSJ%KaaTE6>(m7)X!w8q(*73Tfo zPM@v@C1x>h|P{A)AH^r|T2U(;OpM!9Euk9V5n|Hhb4yfTMC+F{ zGvOEkj$(UlomYnGjno5+E!}ncS=mwbDOuoWS`cZ$Ud8tKGsNso*icfa3FILbu-@3< zdYDzQ@3H~pa?5$gtTTSckZi`Q7yK)n*F1?4)iN`PgO%>#9Q9dPU}Ev#N=Y_kt$nUA z9DLdtL_}FJ7kfIdr}57s(vCqleXGYQ2KR6&1>C_)y~$p%z(Qx6f%E%RO_B(=@)vO1 zJK{2rKTx!Yb=f5zY)rQ5SD)T8+um0lzK&0+b>#Z}XMM__>7M$KC-rB*X z85OowsiH-EZbI3dLz?m8u<3F#`*A_p1-J1n=TA`mV6()4eLKM~BJF}Q`^pCCNJ!B3 z>p25I`-{ZSS&N%n@}(QC%Ka^FYvp}YhBXTzvJgkLr5fklpPAZr((G{nlB=y0h1kr? zH0AsrBxN7>#UxyHS}S=2FTkbMeGQA!miqdp{QeVPx3UsE8_w7WU(ZhLQ+ORxS<0cg z9qPD0*Z->Gbd6Z&`izN;ddi`$!Sssbo!3p<-_HQM-zEYLFXk62-HKpuecl`P^LAo+ zF}(Ee#8|c4lT8Q72d|-m>qmC;lKAQ2;SWQt-S5Caqg&?UN318J%hZ$p$r2d zlhLk%w)47N+D<BAW%gUh)OoC zrzU8zd-A-JA^pjv!GR}ASUg>VDTX8+PGO(eywZ zaMh6mYC@V<5!@4847x78$pS~v!xhH6^F7@q23w*}UWmC?oC%ycYYhwc~v zoP+%-SzwHr*h{C#pk2k<#o^>D?cp;>?t^#uSLzas^>?%3MkzBL1TF+Se0ViA7?u4$ z8SWE=wx5s{)GdCv3HNy3O-({|SSU2;V^_v_U(k_sj_sU_Q8ky{^J&jTE8p7*~Xgs^D z4&)sJVF5PIFN&4SCCPaQ2T(f4%3_ZdC}W{siL>xqa{aA&?}gFCQyK>4{kdn@y%Aab z>3_&^!wNnqd_HW1BrAT(@0Pi@X1~?s1z7%suiMx@UfI#1@5Lo3h~jy!V{AwWPl5A{ z3Csvv3YWR;QludFeo#t*9RK6MBoPTn46gRAIsg{G zI53~{jRf(zzm6{q42>6^zaj;=&odeW>3m;Nr#6hz0?-xYxwb&$Kgh$e!C}`iayERU O2pnu&PtdK18UF>*lD-=N delta 2353 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 Ce0p>M literal 2425 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 BY>NN@ diff --git a/apps/limelight/screenshot_monoton.png b/apps/limelight/screenshot_monoton.png index d17d9bd26e9795c28c427f37ca8407db63b3f5b8..e75b11f5daaceca3fc7ee629ee942e822dca01bb 100644 GIT binary patch delta 2974 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 Date: Fri, 7 Jan 2022 23:46:24 +0100 Subject: [PATCH 325/489] menuwheel: override Bangle.setUI to clear up touch handler Because apps/libraries expect setUI to clean up touch handlers. --- apps.json | 2 +- apps/menuwheel/ChangeLog | 1 + apps/menuwheel/boot.js | 10 ++++++---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/apps.json b/apps.json index 3fc0616da..56691d2d4 100644 --- a/apps.json +++ b/apps.json @@ -4805,7 +4805,7 @@ { "id": "menuwheel", "name": "Wheel Menus", - "version": "0.01", + "version": "0.02", "description": "Replace Bangle.js 2's menus with a version that contains variable-size text and a back button", "readme": "README.md", "icon": "icon.png", diff --git a/apps/menuwheel/ChangeLog b/apps/menuwheel/ChangeLog index defdb5049..050cf2049 100644 --- a/apps/menuwheel/ChangeLog +++ b/apps/menuwheel/ChangeLog @@ -1 +1,2 @@ 0.01: New menu! +0.02: Clean up touch handler in setUI diff --git a/apps/menuwheel/boot.js b/apps/menuwheel/boot.js index 3e708e9a8..deb15264d 100644 --- a/apps/menuwheel/boot.js +++ b/apps/menuwheel/boot.js @@ -1,8 +1,5 @@ E.showMenu = function(items) { g.clearRect(Bangle.appRect); // clear screen if no menu supplied - // clean up back button listener - if (Bangle.backHandler) Bangle.removeListener('touch', Bangle.backHandler) - delete Bangle.backHandler; if (!items) { Bangle.setUI(); return; @@ -206,8 +203,13 @@ E.showMenu = function(items) { if (b===1) back(); } } - // note: backHandler is cleaned up at the top of this file Bangle.on('touch', Bangle.backHandler); } return l; }; +// setUI now also needs to clear up our back button touch handler +Bangle.setUI = (old => function() { + if (Bangle.backHandler) Bangle.removeListener("touch", Bangle.backHandler); + delete Bangle.backHandler; + return old.apply(this, arguments); +})(Bangle.setUI); \ No newline at end of file From ebfedfd18b1220b00cc6cf7ec64663e56d440377 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 7 Jan 2022 22:55:43 +0000 Subject: [PATCH 326/489] fixed apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 1ddacceca..7d0789953 100644 --- a/apps.json +++ b/apps.json @@ -5483,4 +5483,4 @@ {"name":"limelight.img","url":"limelight.icon.js","evaluate":true} ] } -} +] From 2a2c26393fafe60c5509f15157fed98d575023e5 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 7 Jan 2022 23:11:14 +0000 Subject: [PATCH 327/489] limelight README tweak --- apps/limelight/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/limelight/README.md b/apps/limelight/README.md index e84714403..e7c13a139 100644 --- a/apps/limelight/README.md +++ b/apps/limelight/README.md @@ -5,14 +5,14 @@ * Selection of different fonts * Settings menu where you can select font, or switch to Vector font and try a range of sizes -* 100 less lines of code, demonstrating that there is no need for a custom widget draw method -* Full screen options (widgets loaded but not displayed) +* Reduction by 100 lines of code, demonstrating that there is no need for a custom widget draw method +* Full screen option (widgets are loaded but not displayed) ![](screenshot_gochihand.png) ![](screenshot_monoton.png) ![](screenshot_grenadier.png) -Many thanks for @Andreas_Rozek for his pioneering work on building a toolkit for the Bangle 2. +Many thanks for @Andreas_Rozek for his pioneering work on building an analogue clock toolkit for the Bangle 2. Limelight Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) From 597efeab00c8f9a9caf106e6c366e2c66dfefbf4 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 7 Jan 2022 23:14:15 +0000 Subject: [PATCH 328/489] limelight README tweak --- apps/limelight/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/limelight/README.md b/apps/limelight/README.md index e7c13a139..49b858127 100644 --- a/apps/limelight/README.md +++ b/apps/limelight/README.md @@ -1,5 +1,5 @@ # Limelight - * Simple configurable analogue clock based on the work of @Andreas_Rozek [Simple_Clock](https://github.com/espruino/BangleApps/tree/master/apps/simple_clock)* + *Simple configurable analogue clock based on the work of @Andreas_Rozek [Simple_Clock](https://github.com/espruino/BangleApps/tree/master/apps/simple_clock)* ![](screenshot_limelight.png) From 049555a08dd3083b956c8df0e44575f9148e5add Mon Sep 17 00:00:00 2001 From: hughbarney Date: Sat, 8 Jan 2022 00:25:43 +0000 Subject: [PATCH 329/489] Simplest, switched to queueDraw() method, update once per minute --- apps.json | 2 +- apps/simplest/ChangeLog | 1 + apps/simplest/app.js | 66 ++++++++++++++++++++++++++++++----------- 3 files changed, 51 insertions(+), 18 deletions(-) diff --git a/apps.json b/apps.json index 7d0789953..1f4e983e6 100644 --- a/apps.json +++ b/apps.json @@ -3794,7 +3794,7 @@ { "id": "simplest", "name": "Simplest Clock", - "version": "0.03", + "version": "0.04", "description": "The simplest working clock, acts as a tutorial piece", "icon": "simplest.png", "screenshots": [{"url":"screenshot_simplest.png"}], diff --git a/apps/simplest/ChangeLog b/apps/simplest/ChangeLog index f37015d6a..c5ceb7a44 100644 --- a/apps/simplest/ChangeLog +++ b/apps/simplest/ChangeLog @@ -1,3 +1,4 @@ 0.01: Modified for use with new bootloader and firmware 0.02: Use Bangle.setUI for button/launcher handling 0.03: Fix display for Bangle 2 +0.04: Use queueDraw(), update every minute, respect theme, use Lato font diff --git a/apps/simplest/app.js b/apps/simplest/app.js index 68564ff33..85ccc1509 100644 --- a/apps/simplest/app.js +++ b/apps/simplest/app.js @@ -1,28 +1,60 @@ - const h = g.getHeight(); const w = g.getWidth(); -function draw() { - var d = new Date(); - var da = d.toString().split(" "); - var time = da[4].substr(0,5); - - g.reset(); - g.clearRect(0, 30, w, 99); - g.setFontAlign(0, -1); - g.setFont("Vector", w/3); - g.drawString(time, w/2, 40); +// from fonts.google.com +Graphics.prototype.setFontLato = function(scale) { + // Actual height 50 (53 - 4) + this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAP4AAAAAAAAD/gAAAAAAAAf8AAAAAAAAD/gAAAAAAAAP4AAAAAAAAB/AAAAAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAfAAAAAAAAAf4AAAAAAAAP/AAAAAAAAP/wAAAAAAAH/4AAAAAAAH/8AAAAAAAH/8AAAAAAAD/+AAAAAAAD/+AAAAAAAB//AAAAAAAB//AAAAAAAA//gAAAAAAA//gAAAAAAAf/gAAAAAAAf/wAAAAAAAP/wAAAAAAAP/4AAAAAAAH/4AAAAAAAB/8AAAAAAAAf8AAAAAAAAD+AAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf//gAAAAAAf///gAAAAAf////gAAAAH/////AAAAD/////8AAAA//////wAAAP/4AB//AAAD/wAAA/8AAA/wAAAA/wAAH8AAAAD+AAB/AAAAAP4AAPwAAAAA/AAB8AAAAAD4AAPgAAAAAfAAD8AAAAAD8AAfgAAAAAfgAD8AAAAAD8AAfgAAAAAfgAD8AAAAAD8AAPgAAAAAfAAB+AAAAAH4AAPwAAAAA/AAA/AAAAAPwAAH+AAAAH+AAAf8AAAB/gAAD/4AAB/8AAAP//gf//AAAA//////wAAAB/////4AAAAH////+AAAAAP////AAAAAAP///AAAAAAAD/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAADgAAAAAAAAA+AAAAAAAAAPwAAAD4AAAD+AAAAfAAAA/gAAAD4AAAP4AAAAfAAAD+AAAAD4AAA/wAAAAfAAAH8AAAAD4AAB/AAAAAfAAAfwAAAAD4AAH8AAAAAfAAB///////4AAP///////AAB///////4AAP///////AAB///////4AAP///////AAAAAAAAAD4AAAAAAAAAfAAAAAAAAAD4AAAAAAAAAfAAAAAAAAAD4AAAAAAAAAfAAAAAAAAAD4AAAAAAAAAfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAHAAAAD4AAAH4AAAA/AAAB/AAAAP4AAA/4AAAD/AAAP/AAAA/4AAD/4AAAP/AAAf4AAAD/4AAH8AAAA//AAA/AAAAP74AAPwAAAD+fAAB+AAAA/n4AAPgAAAP4/AAD8AAAD+H4AAfgAAA/g/AAD8AAAP4H4AAfgAAD+A/AAD8AAA/gH4AAfgAAP4A/AAB8AAH+AH4AAPwAB/gA/AAB/AA/4AH4AAH8Af+AA/AAA////gAH4AAD///wAA/AAAP//8AAH4AAA///AAA/AAAD//gAAH4AAAH/wAAA/AAAAHwAAAD4AAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAA8AAAAAPAAAP4AAAAP4AAB/gAAAD/AAAP/AAAA/4AAB/4AAAP/AAAD/gAAD/wAAAH+AAA/wAAAAfwAAH8AAAAB/AAB/AAAAAH4AAPwAAAAAfAAB8AAAAAD8AAPgADwAAfgAD8AAeAAD8AAfgADwAAfgAD8AAfAAD8AAfgAH4AAfgAD8AA/AAD8AAPgAH4AAfAAB+AB/gAH4AAPwAP8AA/AAB/AD/wAPwAAH+B+/AH+AAA///3+D/gAAD//8f//8AAAP//D///AAAA//wP//wAAAB/8A//8AAAAD8AB/+AAAAAAAAD+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAH4AAAAAAAAD/AAAAAAAAA/4AAAAAAAAP/AAAAAAAAH/4AAAAAAAB//AAAAAAAAf74AAAAAAAP+fAAAAAAAD/D4AAAAAAA/wfAAAAAAAf8D4AAAAAAH+AfAAAAAAD/gD4AAAAAA/4AfAAAAAAP8AD4AAAAAH/AAfAAAAAB/gAD4AAAAAf4AAfAAAAAP+AAD4AAAAD/AAAfAAAAA/wAAD4AAAAP///////AAB///////4AAP///////AAB///////4AAP///////AAB///////4AAAAAAAfAAAAAAAAAD4AAAAAAAAAfAAAAAAAAAD4AAAAAAAAAfAAAAAAAAAD4AAAAAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAA4AAAAAAAAAPgAAAAB/AAD8AAAAH/4AAfwAAA///AAB+AAB///4AAP4AAP///AAA/AAB///4AAH4AAP/gfAAAfAAB+AHwAAD8AAPwA+AAAfgAB+AHwAAD8AAPwA+AAAfgAB+AHwAAD8AAPwA+AAAfgAB+AH4AAD4AAPwA/AAAfAAB+AH4AAH4AAPwAfgAB/AAB+AD8AAfwAAPwAf4AH+AAB+AB/gD/gAAPwAP///4AAB+AA///+AAAPgAD///gAAB8AAP//4AAAPAAAf/8AAAAAAAA/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/gAAAAAAAB//gAAAAAAA///AAAAAAAf//8AAAAAAH///4AAAAAD////AAAAAA//gf8AAAAAP/wAfwAAAAH/8AB+AAAAB//AAH4AAAA//wAA/AAAAP+8AAD4AAAD/ngAAfgAAB/58AAD8AAAf8PgAAfgAAH/B8AAD8AAD/wPgAAfgAA/8B8AAD8AAP+APgAAfAAB/gB8AAD4AAP4APwAA/AAB8AB+AAH4AAPAAH4AB+AABwAA/wA/wAAIAAD/gf8AAAAAAf///AAAAAAB///wAAAAAAH//8AAAAAAAf//AAAAAAAA//gAAAAAAAB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8AAAAAAAAAPgAAAAAAAAB+AAAAAAAAAPwAAAAAAAAB+AAAAAAAAAPwAAAAADAAB+AAAAAB4AAPwAAAAA/AAB+AAAAAf4AAPwAAAAP/AAB+AAAAH/4AAPwAAAD/+AAB+AAAB//AAAPwAAA//gAAB+AAAf/wAAAPwAAP/4AAAB+AAH/8AAAAPwAD/+AAAAB+AB//AAAAAPwA//gAAAAB+Af/gAAAAAPwP/wAAAAAB+H/4AAAAAAPz/8AAAAAAB//+AAAAAAAP//AAAAAAAB//gAAAAAAAP/wAAAAAAAB/4AAAAAAAAP8AAAAAAAAB+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf8AAAAAHgAP/4AAAAH/gD//gAAAD//A///AAAA//8P//4AAAP//z///gAAD//+fwP+AAA/4f/4AfwAAH4A/+AB/AAB+AB/gAH4AAPgAH8AAfAAB8AA/AAD4AAfgAH4AAfgAD4AAfAAB8AAfAAD4AAPgAD4AAfAAB8AAfAAD4AAPgAD4AAfAAD8AAPgAH4AAfAAB8AA/gAD4AAPwAP8AA/AAA/AD/wAH4AAH8B//AB+AAAf//78A/wAAD//+f//8AAAP//h///gAAA//4P//4AAAB/+A//+AAAAD/AD//gAAAAAAAH/wAAAAAAAAHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAf/gAAAAAAAP/+AAAAAAAD//8AAAAAAA///wAAAAAAP///AAAAAAD///4AADAAA/wB/gAA4AAH8AD8AAPAAB/AAPwAH4AAPwAB+AB/AAB8AAHwAf4AAPgAA+AP/AAD8AAHwD/wAAfgAA+A/8AAD8AAHwf+AAAfgAA+H/gAAD8AAHx/wAAAPgAA8/8AAAB8AAPv/AAAAPwAB//gAAAB/AAf/4AAAAH8AH/8AAAAA/wD//AAAAAD////gAAAAAP///4AAAAAA///8AAAAAAD//+AAAAAAAH//AAAAAAAAP/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgAAHwAAAAB+AAB/AAAAAf4AAP4AAAAD/AAD/gAAAAf4AAf8AAAAD/AAB/AAAAAPwAAP4AAAAA8AAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="), 46, atob("DRclJSUlJSUlJSUlEA=="), 63+(scale<<8)+(1<<16)); + return this; } -// handle switch display on by pressing BTN1 -Bangle.on('lcdPower', function(on) { - if (on) draw(); +function draw() { + var date = new Date(); + var timeStr = require("locale").time(date,1); + var dateStr = require("locale").date(date).toUpperCase(); + + g.reset(); + g.setColor(g.theme.bg); + g.fillRect(Bangle.appRect); + + g.setFontLato(); + g.setFontAlign(0, -1); + g.setColor(g.theme.fg); + g.drawString(timeStr, w/2, h/3); + + g.setFont("6x8",2); + g.setFontAlign(0,0) + g.drawString(dateStr, w/2, h - 24 - 24); + + queueDraw(); +} + +// timeout used to update every minute +var drawTimeout; + +// schedule a draw for the next minute +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +} + +// Stop updates when LCD is off, restart when on +Bangle.on('lcdPower',on=>{ + if (on) { + draw(); // draw immediately, queue redraw + } else { // stop draw timer + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } }); g.clear(); +// Show launcher when middle button pressed +Bangle.setUI("clock"); +// Load widgets Bangle.loadWidgets(); Bangle.drawWidgets(); -setInterval(draw, 15000); // refresh every 15s draw(); -// Show launcher when button pressed -Bangle.setUI("clock"); From 968e7b5840fdf95f1b3b5300a964b77ab788ab8a Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Sat, 8 Jan 2022 10:25:24 +0100 Subject: [PATCH 330/489] Make text size in heart rate circle slightly bigger as it does not have any units --- apps/circlesclock/app.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 6d408fd59..3843d5dda 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -63,6 +63,7 @@ const circlePosX = [Math.round(w / 6), Math.round(3 * w / 6), Math.round(5 * w / const radiusOuter = 25; const radiusInner = 20; const circleFont = "Vector:15"; +const circleFontBig = "Vector:16"; const circleFontSmall = "Vector:13"; function draw() { @@ -229,7 +230,7 @@ function drawHeartRate(w) { g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); - g.setFont(circleFont); + g.setFont(circleFontBig); g.setFontAlign(0, 0); g.setColor(colorFg); g.drawString(hrtValue != undefined ? hrtValue : "-", w, h3); From 04129c82818dbd956ed4f7b13d103b7754a02a1e Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Sat, 8 Jan 2022 13:58:47 +0100 Subject: [PATCH 331/489] changed type to app of mmind app --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 3321f822f..5153e3deb 100644 --- a/apps.json +++ b/apps.json @@ -5134,8 +5134,8 @@ "version":"0.01", "description": "This is the classic game for masterminds", "screenshots": [{"url":"screenshot_mmind.png"}], - "type": "game", - "tags": "game,app", + "type": "app", + "tags": "game", "readme":"README.md", "supports": ["BANGLEJS2"], "allow_emulator": true, From a1ebca296cf3f09ab8974610c23307ffb5cf76f9 Mon Sep 17 00:00:00 2001 From: Marcus Olsson Date: Sat, 8 Jan 2022 21:15:32 +0100 Subject: [PATCH 332/489] Fixed sv_SE formatting Long date does not work well for Bangle.js2 This aligns with default locale en_GB. --- apps.json | 2 +- apps/locale/ChangeLog | 1 + apps/locale/locales.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 3fc0616da..f5a17c37d 100644 --- a/apps.json +++ b/apps.json @@ -218,7 +218,7 @@ { "id": "locale", "name": "Languages", - "version": "0.14", + "version": "0.15", "description": "Translations for different countries", "icon": "locale.png", "type": "locale", diff --git a/apps/locale/ChangeLog b/apps/locale/ChangeLog index 448f8119a..198322fb2 100644 --- a/apps/locale/ChangeLog +++ b/apps/locale/ChangeLog @@ -14,3 +14,4 @@ 0.12: Fixed nl_NL formatting, because the full months won't fit on the Bangle.js2's screen 0.13: Now use shorter de_DE date format to more closely match other languages for size 0.14: Added some first translations for Messages in nl_NL +0.15: Fixed sv_SE formatting, long date does not work well for Bangle.js2 diff --git a/apps/locale/locales.js b/apps/locale/locales.js index cf511c54f..1626b744f 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -276,7 +276,7 @@ var locales = { temperature: "°C", ampm: { 0: "fm", 1: "em" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, - datePattern: { 0: "%A %B %d %Y", "1": "%Y-%m-%d" }, // söndag 1 mars 2020 // 2020-03-01 + datePattern: { 0: "%b %d %Y", "1": "%Y-%m-%d" }, // feb 1 2020 // 2020-03-01 abmonth: "jan,feb,mars,apr,maj,juni,juli,aug,sep,okt,nov,dec", month: "januari,februari,mars,april,maj,juni,juli,augusti,september,oktober,november,december", abday: "sön,mån,tis,ons,tors,fre,lör", From 4341efb46a358612bce0c11ca259abd0109f374d Mon Sep 17 00:00:00 2001 From: hughbarney Date: Sat, 8 Jan 2022 20:43:06 +0000 Subject: [PATCH 333/489] Updated simplest to make it simpler, tweak to Pastel to make it cycle better --- apps.json | 4 ++-- apps/pastel/ChangeLog | 1 + apps/pastel/pastel.app.js | 2 +- apps/simplest/ChangeLog | 2 ++ apps/simplest/app.js | 27 +++++++++++---------------- 5 files changed, 17 insertions(+), 19 deletions(-) diff --git a/apps.json b/apps.json index 1f4e983e6..2d87b2f73 100644 --- a/apps.json +++ b/apps.json @@ -3794,7 +3794,7 @@ { "id": "simplest", "name": "Simplest Clock", - "version": "0.04", + "version": "0.05", "description": "The simplest working clock, acts as a tutorial piece", "icon": "simplest.png", "screenshots": [{"url":"screenshot_simplest.png"}], @@ -4215,7 +4215,7 @@ "id": "pastel", "name": "Pastel Clock", "shortName": "Pastel", - "version": "0.10", + "version": "0.11", "description": "A Configurable clock with custom fonts, background and weather display. Has a cyclic information line that includes, day, date, battery, sunrise and sunset times", "icon": "pastel.png", "dependencies": {"mylocation":"app", "widpedom":"app","weather":"app"}, diff --git a/apps/pastel/ChangeLog b/apps/pastel/ChangeLog index 627531f03..00090fcd1 100644 --- a/apps/pastel/ChangeLog +++ b/apps/pastel/ChangeLog @@ -8,3 +8,4 @@ 0.08: Added dependancy on MyLocation 0.09: Added dependancy on Pedometer Widget 0.10: Added Weather line, fixed issues on a Bangle 1, update every minute +0.11: Changed cycle on minute to prevInfo to avoid the 2nd one being the blank line diff --git a/apps/pastel/pastel.app.js b/apps/pastel/pastel.app.js index db60a2738..3e64cdd9c 100644 --- a/apps/pastel/pastel.app.js +++ b/apps/pastel/pastel.app.js @@ -255,7 +255,7 @@ function queueDraw() { if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = setTimeout(function() { drawTimeout = undefined; - nextInfo(); + prevInfo(); draw(); }, 60000 - (Date.now() % 60000)); } diff --git a/apps/simplest/ChangeLog b/apps/simplest/ChangeLog index c5ceb7a44..e7ab5f2c3 100644 --- a/apps/simplest/ChangeLog +++ b/apps/simplest/ChangeLog @@ -2,3 +2,5 @@ 0.02: Use Bangle.setUI for button/launcher handling 0.03: Fix display for Bangle 2 0.04: Use queueDraw(), update every minute, respect theme, use Lato font +0.05: Decided against custom font as it inceases the code size + minimalism is useful when narrowing down issues diff --git a/apps/simplest/app.js b/apps/simplest/app.js index 85ccc1509..582c4c2d5 100644 --- a/apps/simplest/app.js +++ b/apps/simplest/app.js @@ -1,31 +1,19 @@ const h = g.getHeight(); const w = g.getWidth(); -// from fonts.google.com -Graphics.prototype.setFontLato = function(scale) { - // Actual height 50 (53 - 4) - this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAP4AAAAAAAAD/gAAAAAAAAf8AAAAAAAAD/gAAAAAAAAP4AAAAAAAAB/AAAAAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAfAAAAAAAAAf4AAAAAAAAP/AAAAAAAAP/wAAAAAAAH/4AAAAAAAH/8AAAAAAAH/8AAAAAAAD/+AAAAAAAD/+AAAAAAAB//AAAAAAAB//AAAAAAAA//gAAAAAAA//gAAAAAAAf/gAAAAAAAf/wAAAAAAAP/wAAAAAAAP/4AAAAAAAH/4AAAAAAAB/8AAAAAAAAf8AAAAAAAAD+AAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf//gAAAAAAf///gAAAAAf////gAAAAH/////AAAAD/////8AAAA//////wAAAP/4AB//AAAD/wAAA/8AAA/wAAAA/wAAH8AAAAD+AAB/AAAAAP4AAPwAAAAA/AAB8AAAAAD4AAPgAAAAAfAAD8AAAAAD8AAfgAAAAAfgAD8AAAAAD8AAfgAAAAAfgAD8AAAAAD8AAPgAAAAAfAAB+AAAAAH4AAPwAAAAA/AAA/AAAAAPwAAH+AAAAH+AAAf8AAAB/gAAD/4AAB/8AAAP//gf//AAAA//////wAAAB/////4AAAAH////+AAAAAP////AAAAAAP///AAAAAAAD/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAADgAAAAAAAAA+AAAAAAAAAPwAAAD4AAAD+AAAAfAAAA/gAAAD4AAAP4AAAAfAAAD+AAAAD4AAA/wAAAAfAAAH8AAAAD4AAB/AAAAAfAAAfwAAAAD4AAH8AAAAAfAAB///////4AAP///////AAB///////4AAP///////AAB///////4AAP///////AAAAAAAAAD4AAAAAAAAAfAAAAAAAAAD4AAAAAAAAAfAAAAAAAAAD4AAAAAAAAAfAAAAAAAAAD4AAAAAAAAAfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAHAAAAD4AAAH4AAAA/AAAB/AAAAP4AAA/4AAAD/AAAP/AAAA/4AAD/4AAAP/AAAf4AAAD/4AAH8AAAA//AAA/AAAAP74AAPwAAAD+fAAB+AAAA/n4AAPgAAAP4/AAD8AAAD+H4AAfgAAA/g/AAD8AAAP4H4AAfgAAD+A/AAD8AAA/gH4AAfgAAP4A/AAB8AAH+AH4AAPwAB/gA/AAB/AA/4AH4AAH8Af+AA/AAA////gAH4AAD///wAA/AAAP//8AAH4AAA///AAA/AAAD//gAAH4AAAH/wAAA/AAAAHwAAAD4AAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAA8AAAAAPAAAP4AAAAP4AAB/gAAAD/AAAP/AAAA/4AAB/4AAAP/AAAD/gAAD/wAAAH+AAA/wAAAAfwAAH8AAAAB/AAB/AAAAAH4AAPwAAAAAfAAB8AAAAAD8AAPgADwAAfgAD8AAeAAD8AAfgADwAAfgAD8AAfAAD8AAfgAH4AAfgAD8AA/AAD8AAPgAH4AAfAAB+AB/gAH4AAPwAP8AA/AAB/AD/wAPwAAH+B+/AH+AAA///3+D/gAAD//8f//8AAAP//D///AAAA//wP//wAAAB/8A//8AAAAD8AB/+AAAAAAAAD+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAH4AAAAAAAAD/AAAAAAAAA/4AAAAAAAAP/AAAAAAAAH/4AAAAAAAB//AAAAAAAAf74AAAAAAAP+fAAAAAAAD/D4AAAAAAA/wfAAAAAAAf8D4AAAAAAH+AfAAAAAAD/gD4AAAAAA/4AfAAAAAAP8AD4AAAAAH/AAfAAAAAB/gAD4AAAAAf4AAfAAAAAP+AAD4AAAAD/AAAfAAAAA/wAAD4AAAAP///////AAB///////4AAP///////AAB///////4AAP///////AAB///////4AAAAAAAfAAAAAAAAAD4AAAAAAAAAfAAAAAAAAAD4AAAAAAAAAfAAAAAAAAAD4AAAAAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAA4AAAAAAAAAPgAAAAB/AAD8AAAAH/4AAfwAAA///AAB+AAB///4AAP4AAP///AAA/AAB///4AAH4AAP/gfAAAfAAB+AHwAAD8AAPwA+AAAfgAB+AHwAAD8AAPwA+AAAfgAB+AHwAAD8AAPwA+AAAfgAB+AH4AAD4AAPwA/AAAfAAB+AH4AAH4AAPwAfgAB/AAB+AD8AAfwAAPwAf4AH+AAB+AB/gD/gAAPwAP///4AAB+AA///+AAAPgAD///gAAB8AAP//4AAAPAAAf/8AAAAAAAA/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/gAAAAAAAB//gAAAAAAA///AAAAAAAf//8AAAAAAH///4AAAAAD////AAAAAA//gf8AAAAAP/wAfwAAAAH/8AB+AAAAB//AAH4AAAA//wAA/AAAAP+8AAD4AAAD/ngAAfgAAB/58AAD8AAAf8PgAAfgAAH/B8AAD8AAD/wPgAAfgAA/8B8AAD8AAP+APgAAfAAB/gB8AAD4AAP4APwAA/AAB8AB+AAH4AAPAAH4AB+AABwAA/wA/wAAIAAD/gf8AAAAAAf///AAAAAAB///wAAAAAAH//8AAAAAAAf//AAAAAAAA//gAAAAAAAB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8AAAAAAAAAPgAAAAAAAAB+AAAAAAAAAPwAAAAAAAAB+AAAAAAAAAPwAAAAADAAB+AAAAAB4AAPwAAAAA/AAB+AAAAAf4AAPwAAAAP/AAB+AAAAH/4AAPwAAAD/+AAB+AAAB//AAAPwAAA//gAAB+AAAf/wAAAPwAAP/4AAAB+AAH/8AAAAPwAD/+AAAAB+AB//AAAAAPwA//gAAAAB+Af/gAAAAAPwP/wAAAAAB+H/4AAAAAAPz/8AAAAAAB//+AAAAAAAP//AAAAAAAB//gAAAAAAAP/wAAAAAAAB/4AAAAAAAAP8AAAAAAAAB+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf8AAAAAHgAP/4AAAAH/gD//gAAAD//A///AAAA//8P//4AAAP//z///gAAD//+fwP+AAA/4f/4AfwAAH4A/+AB/AAB+AB/gAH4AAPgAH8AAfAAB8AA/AAD4AAfgAH4AAfgAD4AAfAAB8AAfAAD4AAPgAD4AAfAAB8AAfAAD4AAPgAD4AAfAAD8AAPgAH4AAfAAB8AA/gAD4AAPwAP8AA/AAA/AD/wAH4AAH8B//AB+AAAf//78A/wAAD//+f//8AAAP//h///gAAA//4P//4AAAB/+A//+AAAAD/AD//gAAAAAAAH/wAAAAAAAAHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAf/gAAAAAAAP/+AAAAAAAD//8AAAAAAA///wAAAAAAP///AAAAAAD///4AADAAA/wB/gAA4AAH8AD8AAPAAB/AAPwAH4AAPwAB+AB/AAB8AAHwAf4AAPgAA+AP/AAD8AAHwD/wAAfgAA+A/8AAD8AAHwf+AAAfgAA+H/gAAD8AAHx/wAAAPgAA8/8AAAB8AAPv/AAAAPwAB//gAAAB/AAf/4AAAAH8AH/8AAAAA/wD//AAAAAD////gAAAAAP///4AAAAAA///8AAAAAAD//+AAAAAAAH//AAAAAAAAP/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgAAHwAAAAB+AAB/AAAAAf4AAP4AAAAD/AAD/gAAAAf4AAf8AAAAD/AAB/AAAAAPwAAP4AAAAA8AAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="), 46, atob("DRclJSUlJSUlJSUlEA=="), 63+(scale<<8)+(1<<16)); - return this; -} - function draw() { var date = new Date(); var timeStr = require("locale").time(date,1); - var dateStr = require("locale").date(date).toUpperCase(); g.reset(); g.setColor(g.theme.bg); g.fillRect(Bangle.appRect); - g.setFontLato(); - g.setFontAlign(0, -1); + g.setFont('Vector', w/3); + g.setFontAlign(0, 0); g.setColor(g.theme.fg); - g.drawString(timeStr, w/2, h/3); + g.drawString(timeStr, w/2, h/2); - g.setFont("6x8",2); - g.setFontAlign(0,0) - g.drawString(dateStr, w/2, h - 24 - 24); - queueDraw(); } @@ -52,8 +40,15 @@ Bangle.on('lcdPower',on=>{ }); g.clear(); + // Show launcher when middle button pressed -Bangle.setUI("clock"); +//Bangle.setUI("clock"); +// use clockupdown as it tests for issue #1249 +Bangle.setUI("clockupdown", btn=> { + draw(); +}); + + // Load widgets Bangle.loadWidgets(); Bangle.drawWidgets(); From 72eb12827255b12926d82cd825871349cdcea5b7 Mon Sep 17 00:00:00 2001 From: Didgeridoohan Date: Sun, 9 Jan 2022 07:32:57 +0100 Subject: [PATCH 334/489] Tweak long date --- apps/locale/locales.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/locale/locales.js b/apps/locale/locales.js index fea217efe..fce2b8c2a 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -294,7 +294,7 @@ var locales = { temperature: '°C', ampm: { 0: "", 1: "" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, - datePattern: { 0: "%A %B %d %Y", "1": "%Y-%m-%d" }, // Sunday 1 March 2020 // 2020-03-01 + datePattern: { 0: "%B %d %Y", "1": "%Y-%m-%d" }, // March 1 2020 // 2020-03-01 abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", month: "January,February,March,April,May,June,July,August,September,October,November,December", abday: "Sun,Mon,Tue,Wed,Thu,Fri,Sat", From 6896b282b2ac83fdf6c4149ff463493a5b8c07a6 Mon Sep 17 00:00:00 2001 From: The Dod Date: Sun, 9 Jan 2022 14:17:14 +0200 Subject: [PATCH 335/489] Rewrite mkFourTwentyTz in JS (instead of Python) --- apps/ftclock/.gitignore | 4 + apps/ftclock/README.md | 18 +- apps/ftclock/fourTwentyTz.js | 997 +++++++++++++++------------------ apps/ftclock/mkFourTwentyTz.js | 74 +++ apps/ftclock/mkFourTwentyTz.py | 46 -- apps/ftclock/package.json | 15 + 6 files changed, 568 insertions(+), 586 deletions(-) create mode 100644 apps/ftclock/.gitignore create mode 100644 apps/ftclock/mkFourTwentyTz.js delete mode 100644 apps/ftclock/mkFourTwentyTz.py create mode 100644 apps/ftclock/package.json diff --git a/apps/ftclock/.gitignore b/apps/ftclock/.gitignore new file mode 100644 index 000000000..b384cf1f2 --- /dev/null +++ b/apps/ftclock/.gitignore @@ -0,0 +1,4 @@ +timezonedb.csv.zip +country.csv +zone.csv +timezone.csv diff --git a/apps/ftclock/README.md b/apps/ftclock/README.md index 665a7693d..f30151552 100644 --- a/apps/ftclock/README.md +++ b/apps/ftclock/README.md @@ -4,12 +4,20 @@ A clock that tells when and where it's going to be [4:20](https://en.wikipedia.o ![screensot](screenshot.png) ![screenshot at 4:20](screenshot1.png) -## Note +## Generating `fourTwentyTz.js` -Once in a while, there'd be updates to the [timezone database](https://timezonedb.com/download) which -would require updating `fourTwentyTz.js`. I'll do my best to release a new version every time this happens, -but if you ever need to do this yourself, just run `python mkFourTwentyTz.py` (after downloading the timezone CSV files. -See comment at the top of the script). +Once in a while we need to regenerate it for 2 reasons: + +* One or more places got in or out of daylight saving time (DST) mode. +* The database saying _when_ places enter/exit DST mode got updated. + +I'll do my best to release a new version every time this happens, +but if you ever need to do this yourself, here's how: + +* `cd` to the `ftclock` folder +* If you haven't done so yet, run `npm install` there (this would create the `node_modules` folder). +* Get and unzip the latest `timezone.csv.zip` from https://timezonedb.com/download +* Run `npm run make` ## Creator diff --git a/apps/ftclock/fourTwentyTz.js b/apps/ftclock/fourTwentyTz.js index e41f3fdd0..cebab42cb 100644 --- a/apps/ftclock/fourTwentyTz.js +++ b/apps/ftclock/fourTwentyTz.js @@ -1,536 +1,463 @@ -// Generated by mk420tz.py - see https://github.com/thedod/BangleApps/420clock -// (version: Sat Dec 18 10:17:32 2021) +// Generated by mkFourTwentyTz.js // Data source: https://timezonedb.com/files/timezonedb.csv.zip -// (version: Sat Oct 16 01:48:14 2021) -exports.timezones = [ - [ - 1380, - [ - "Azores, Portugal", - "Cape Verde, Cabo Verde", - "Scoresbysund, Greenland" - ] - ], - [ - 1320, - [ - "Noronha, Brazil", - "South Georgia, South Georgia and the South Sandwich Islands" - ] - ], - [ - 1260, - [ - "Araguaina, Brazil", - "Asuncion, Paraguay", - "Bahia, Brazil", - "Belem, Brazil", - "Buenos Aires, Argentina", - "Catamarca, Argentina", - "Cayenne, French Guiana", - "Cordoba, Argentina", - "Fortaleza, Brazil", - "Jujuy, Argentina", - "La Rioja, Argentina", - "Maceio, Brazil", - "Mendoza, Argentina", - "Miquelon, Saint Pierre and Miquelon", - "Montevideo, Uruguay", - "Nuuk, Greenland", - "Palmer, Antarctica", - "Paramaribo, Suriname", - "Punta Arenas, Chile", - "Recife, Brazil", - "Rio Gallegos, Argentina", - "Rothera, Antarctica", - "Salta, Argentina", - "San Juan, Argentina", - "San Luis, Argentina", - "Santarem, Brazil", - "Santiago, Chile", - "Sao Paulo, Brazil", - "Stanley, Falkland Islands (Malvinas)", - "Tucuman, Argentina", - "Ushuaia, Argentina" - ] - ], - [ - 1200, - [ - "Anguilla, AI", - "Antigua, Antigua and Barbuda", - "Aruba, AW", - "Barbados, BB", - "Bermuda, BM", - "Blanc-Sablon, Canada", - "Boa Vista, Brazil", - "Campo Grande, Brazil", - "Caracas, Venezuela (Bolivarian Republic of)", - "Cuiaba, Brazil", - "Curacao, Cura\u00e7ao", - "Dominica, DM", - "Glace Bay, Canada", - "Goose Bay, Canada", - "Grenada, GD", - "Guadeloupe, GP", - "Guyana, GY", - "Halifax, Canada", - "Kralendijk, Bonaire, Sint Eustatius and Saba", - "La Paz, Bolivia (Plurinational State of)", - "Lower Princes, Sint Maarten (Dutch part)", - "Manaus, Brazil", - "Marigot, Saint Martin (French part)", - "Martinique, MQ", - "Moncton, Canada", - "Montserrat, MS", - "Port of Spain, Trinidad and Tobago", - "Porto Velho, Brazil", - "Puerto Rico, PR", - "Santo Domingo, Dominican Republic", - "St Barthelemy, Saint Barth\u00e9lemy", - "St Kitts, Saint Kitts and Nevis", - "St Lucia, Saint Lucia", - "St Thomas, Virgin Islands (U.S.)", - "St Vincent, Saint Vincent and the Grenadines", - "Thule, Greenland", - "Tortola, Virgin Islands (British)" - ] - ], - [ - 1140, - [ - "Atikokan, Canada", - "Bogota, Colombia", - "Cancun, Mexico", - "Cayman, Cayman Islands", - "Detroit, United States of America", - "Easter, Chile", - "Eirunepe, Brazil", - "Grand Turk, Turks and Caicos Islands", - "Guayaquil, Ecuador", - "Havana, Cuba", - "Indianapolis, Indiana", - "Iqaluit, Canada", - "Jamaica, JM", - "Lima, Peru", - "Louisville, Kentucky", - "Marengo, Indiana", - "Monticello, Kentucky", - "Nassau, Bahamas", - "New York, United States of America", - "Nipigon, Canada", - "Panama, PA", - "Pangnirtung, Canada", - "Petersburg, Indiana", - "Port-au-Prince, Haiti", - "Rio Branco, Brazil", - "Thunder Bay, Canada", - "Toronto, Canada", - "Vevay, Indiana", - "Vincennes, Indiana", - "Winamac, Indiana" - ] - ], - [ - 1080, - [ - "Bahia Banderas, Mexico", - "Belize, BZ", - "Beulah, North Dakota", - "Center, North Dakota", - "Chicago, United States of America", - "Costa Rica, CR", - "El Salvador, SV", - "Galapagos, Ecuador", - "Guatemala, GT", - "Knox, Indiana", - "Managua, Nicaragua", - "Matamoros, Mexico", - "Menominee, United States of America", - "Merida, Mexico", - "Mexico City, Mexico", - "Monterrey, Mexico", - "New Salem, North Dakota", - "Rainy River, Canada", - "Rankin Inlet, Canada", - "Regina, Canada", - "Resolute, Canada", - "Swift Current, Canada", - "Tegucigalpa, Honduras", - "Tell City, Indiana", - "Winnipeg, Canada" - ] - ], - [ - 1020, - [ - "Boise, United States of America", - "Cambridge Bay, Canada", - "Chihuahua, Mexico", - "Creston, Canada", - "Dawson Creek, Canada", - "Dawson, Canada", - "Denver, United States of America", - "Edmonton, Canada", - "Fort Nelson, Canada", - "Hermosillo, Mexico", - "Inuvik, Canada", - "Mazatlan, Mexico", - "Ojinaga, Mexico", - "Phoenix, United States of America", - "Whitehorse, Canada", - "Yellowknife, Canada" - ] - ], - [ - 960, - [ - "Los Angeles, United States of America", - "Pitcairn, PN", - "Tijuana, Mexico", - "Vancouver, Canada" - ] - ], - [ - 900, - [ - "Anchorage, United States of America", - "Gambier, French Polynesia", - "Juneau, United States of America", - "Metlakatla, United States of America", - "Nome, United States of America", - "Sitka, United States of America", - "Yakutat, United States of America" - ] - ], - [ - 840, - [ - "Adak, United States of America", - "Honolulu, United States of America", - "Kiritimati, Kiribati", - "Rarotonga, Cook Islands", - "Tahiti, French Polynesia" - ] - ], - [ - 780, - [ - "Apia, Samoa", - "Auckland, New Zealand", - "Fakaofo, Tokelau", - "Kanton, Kiribati", - "McMurdo, Antarctica", - "Midway, United States Minor Outlying Islands", - "Niue, NU", - "Pago Pago, American Samoa", - "Tongatapu, Tonga" - ] - ], - [ - 720, - [ - "Anadyr, Russian Federation", - "Fiji, FJ", - "Funafuti, Tuvalu", - "Kamchatka, Russian Federation", - "Kwajalein, Marshall Islands", - "Majuro, Marshall Islands", - "Nauru, NR", - "Norfolk, Norfolk Island", - "Tarawa, Kiribati", - "Wake, United States Minor Outlying Islands", - "Wallis, Wallis and Futuna" - ] - ], - [ - 660, - [ - "Bougainville, Papua New Guinea", - "Casey, Antarctica", - "Efate, Vanuatu", - "Guadalcanal, Solomon Islands", - "Hobart, Australia", - "Kosrae, Micronesia (Federated States of)", - "Lord Howe, Australia", - "Macquarie, Australia", - "Magadan, Russian Federation", - "Melbourne, Australia", - "Noumea, New Caledonia", - "Pohnpei, Micronesia (Federated States of)", - "Sakhalin, Russian Federation", - "Srednekolymsk, Russian Federation", - "Sydney, Australia" - ] - ], - [ - 600, - [ - "Brisbane, Australia", - "Chuuk, Micronesia (Federated States of)", - "DumontDUrville, Antarctica", - "Guam, GU", - "Lindeman, Australia", - "Port Moresby, Papua New Guinea", - "Saipan, Northern Mariana Islands", - "Ust-Nera, Russian Federation", - "Vladivostok, Russian Federation" - ] - ], - [ - 540, - [ - "Chita, Russian Federation", - "Dili, Timor-Leste", - "Jayapura, Indonesia", - "Khandyga, Russian Federation", - "Palau, PW", - "Pyongyang, Korea (Democratic People's Republic of)", - "Seoul, Korea, Republic of", - "Tokyo, Japan", - "Yakutsk, Russian Federation" - ] - ], - [ - 480, - [ - "Brunei, Brunei Darussalam", - "Choibalsan, Mongolia", - "Hong Kong, HK", - "Irkutsk, Russian Federation", - "Kuala Lumpur, Malaysia", - "Kuching, Malaysia", - "Macau, Macao", - "Makassar, Indonesia", - "Manila, Philippines", - "Perth, Australia", - "Shanghai, China", - "Singapore, SG", - "Taipei, Taiwan, Province of China", - "Ulaanbaatar, Mongolia" - ] - ], - [ - 420, - [ - "Bangkok, Thailand", - "Barnaul, Russian Federation", - "Christmas, Christmas Island", - "Davis, Antarctica", - "Ho Chi Minh, Viet Nam", - "Hovd, Mongolia", - "Jakarta, Indonesia", - "Krasnoyarsk, Russian Federation", - "Novokuznetsk, Russian Federation", - "Novosibirsk, Russian Federation", - "Phnom Penh, Cambodia", - "Pontianak, Indonesia", - "Tomsk, Russian Federation", - "Vientiane, Lao People's Democratic Republic" - ] - ], - [ - 360, - [ - "Almaty, Kazakhstan", - "Bishkek, Kyrgyzstan", - "Chagos, British Indian Ocean Territory", - "Dhaka, Bangladesh", - "Omsk, Russian Federation", - "Qostanay, Kazakhstan", - "Thimphu, Bhutan", - "Urumqi, China", - "Vostok, Antarctica" - ] - ], - [ - 300, - [ - "Aqtau, Kazakhstan", - "Aqtobe, Kazakhstan", - "Ashgabat, Turkmenistan", - "Atyrau, Kazakhstan", - "Dushanbe, Tajikistan", - "Karachi, Pakistan", - "Kerguelen, French Southern Territories", - "Maldives, MV", - "Mawson, Antarctica", - "Oral, Kazakhstan", - "Qyzylorda, Kazakhstan", - "Samarkand, Uzbekistan", - "Tashkent, Uzbekistan", - "Yekaterinburg, Russian Federation" - ] - ], - [ - 240, - [ - "Astrakhan, Russian Federation", - "Baku, Azerbaijan", - "Dubai, United Arab Emirates", - "Mahe, Seychelles", - "Mauritius, MU", - "Muscat, Oman", - "Reunion, R\u00e9union", - "Samara, Russian Federation", - "Saratov, Russian Federation", - "Tbilisi, Georgia", - "Ulyanovsk, Russian Federation", - "Yerevan, Armenia" - ] - ], - [ - 180, - [ - "Addis Ababa, Ethiopia", - "Aden, Yemen", - "Antananarivo, Madagascar", - "Asmara, Eritrea", - "Baghdad, Iraq", - "Bahrain, BH", - "Comoro, Comoros", - "Dar es Salaam, Tanzania, United Republic of", - "Djibouti, DJ", - "Istanbul, Turkey", - "Kampala, Uganda", - "Kirov, Russian Federation", - "Kuwait, KW", - "Mayotte, YT", - "Minsk, Belarus", - "Mogadishu, Somalia", - "Moscow, Russian Federation", - "Nairobi, Kenya", - "Qatar, QA", - "Riyadh, Saudi Arabia", - "Simferopol, Ukraine", - "Syowa, Antarctica", - "Volgograd, Russian Federation" - ] - ], - [ - 120, - [ - "Amman, Jordan", - "Athens, Greece", - "Beirut, Lebanon", - "Blantyre, Malawi", - "Bucharest, Romania", - "Bujumbura, Burundi", - "Cairo, Egypt", - "Chisinau, Moldova, Republic of", - "Damascus, Syrian Arab Republic", - "Famagusta, Cyprus", - "Gaborone, Botswana", - "Gaza, Palestine, State of", - "Harare, Zimbabwe", - "Hebron, Palestine, State of", - "Helsinki, Finland", - "Jerusalem, Israel", - "Johannesburg, South Africa", - "Juba, South Sudan", - "Kaliningrad, Russian Federation", - "Khartoum, Sudan", - "Kiev, Ukraine", - "Kigali, Rwanda", - "Lubumbashi, Congo, Democratic Republic of the", - "Lusaka, Zambia", - "Maputo, Mozambique", - "Mariehamn, \u00c5land Islands", - "Maseru, Lesotho", - "Mbabane, Eswatini", - "Nicosia, Cyprus", - "Riga, Latvia", - "Sofia, Bulgaria", - "Tallinn, Estonia", - "Tripoli, Libya", - "Uzhgorod, Ukraine", - "Vilnius, Lithuania", - "Windhoek, Namibia", - "Zaporozhye, Ukraine" - ] - ], - [ - 60, - [ - "Algiers, Algeria", - "Amsterdam, Netherlands", - "Andorra, AD", - "Bangui, Central African Republic", - "Belgrade, Serbia", - "Berlin, Germany", - "Bratislava, Slovakia", - "Brazzaville, Congo", - "Brussels, Belgium", - "Budapest, Hungary", - "Busingen, Germany", - "Casablanca, Morocco", - "Ceuta, Spain", - "Copenhagen, Denmark", - "Douala, Cameroon", - "El Aaiun, Western Sahara", - "Gibraltar, GI", - "Kinshasa, Congo, Democratic Republic of the", - "Lagos, Nigeria", - "Libreville, Gabon", - "Ljubljana, Slovenia", - "Longyearbyen, Svalbard and Jan Mayen", - "Luanda, Angola", - "Luxembourg, LU", - "Madrid, Spain", - "Malabo, Equatorial Guinea", - "Malta, MT", - "Monaco, MC", - "Ndjamena, Chad", - "Niamey, Niger", - "Oslo, Norway", - "Paris, France", - "Podgorica, Montenegro", - "Porto-Novo, Benin", - "Prague, Czechia", - "Rome, Italy", - "San Marino, SM", - "Sarajevo, Bosnia and Herzegovina", - "Skopje, North Macedonia", - "Stockholm, Sweden", - "Tirane, Albania", - "Tunis, Tunisia", - "Vaduz, Liechtenstein", - "Vatican, Holy See", - "Vienna, Austria", - "Warsaw, Poland", - "Zagreb, Croatia", - "Zurich, Switzerland" - ] - ], - [ - 0, - [ - "Abidjan, C\u00f4te d'Ivoire", - "Accra, Ghana", - "Bamako, Mali", - "Banjul, Gambia", - "Bissau, Guinea-Bissau", - "Canary, Spain", - "Conakry, Guinea", - "Dakar, Senegal", - "Danmarkshavn, Greenland", - "Dublin, Ireland", - "Faroe, Faroe Islands", - "Freetown, Sierra Leone", - "Guernsey, GG", - "Isle of Man, IM", - "Jersey, JE", - "Lisbon, Portugal", - "Lome, Togo", - "London, United Kingdom of Great Britain and Northern Ireland", - "Madeira, Portugal", - "Monrovia, Liberia", - "Nouakchott, Mauritania", - "Ouagadougou, Burkina Faso", - "Reykjavik, Iceland", - "Sao Tome, Sao Tome and Principe", - "St Helena, Saint Helena, Ascension and Tristan da Cunha", - "Troll, Antarctica" - ] - ] -]; +// Sun Jan 09 2022 13:21:47 GMT+0200 (Israel Standard Time) +exports.timezones = { + "0": [ + "Troll, Antarctica", + "Ouagadougou, Burkina Faso", + "Abidjan, Côte d'Ivoire", + "Canary, Spain", + "Faroe, Faroe Islands", + "London, United Kingdom of Great Britain and Northern Ireland", + "Guernsey, Guernsey", + "Accra, Ghana", + "Danmarkshavn, Greenland", + "Banjul, Gambia", + "Conakry, Guinea", + "Bissau, Guinea-Bissau", + "Dublin, Ireland", + "Isle of_Man, Isle of Man", + "Reykjavik, Iceland", + "Jersey, Jersey", + "Monrovia, Liberia", + "Bamako, Mali", + "Nouakchott, Mauritania", + "Lisbon, Portugal", + "Madeira, Portugal", + "St Helena, Saint Helena, Ascension and Tristan da Cunha", + "Freetown, Sierra Leone", + "Dakar, Senegal", + "Sao Tome, Sao Tome and Principe", + "Lome, Togo" + ], + "60": [ + "Andorra, Andorra", + "Tirane, Albania", + "Luanda, Angola", + "Vienna, Austria", + "Sarajevo, Bosnia and Herzegovina", + "Brussels, Belgium", + "Porto-Novo, Benin", + "Kinshasa, Congo, Democratic Republic of the", + "Bangui, Central African Republic", + "Brazzaville, Congo", + "Zurich, Switzerland", + "Douala, Cameroon", + "Prague, Czechia", + "Berlin, Germany", + "Busingen, Germany", + "Copenhagen, Denmark", + "Algiers, Algeria", + "El Aaiun, Western Sahara", + "Madrid, Spain", + "Ceuta, Spain", + "Paris, France", + "Libreville, Gabon", + "Gibraltar, Gibraltar", + "Malabo, Equatorial Guinea", + "Zagreb, Croatia", + "Budapest, Hungary", + "Rome, Italy", + "Vaduz, Liechtenstein", + "Luxembourg, Luxembourg", + "Casablanca, Morocco", + "Monaco, Monaco", + "Podgorica, Montenegro", + "Skopje, North Macedonia", + "Malta, Malta", + "Niamey, Niger", + "Lagos, Nigeria", + "Amsterdam, Netherlands", + "Oslo, Norway", + "Warsaw, Poland", + "Belgrade, Serbia", + "Stockholm, Sweden", + "Ljubljana, Slovenia", + "Longyearbyen, Svalbard and Jan Mayen", + "Bratislava, Slovakia", + "San Marino, San Marino", + "Ndjamena, Chad", + "Tunis, Tunisia", + "Vatican, Holy See" + ], + "120": [ + "Mariehamn, Åland Islands", + "Sofia, Bulgaria", + "Bujumbura, Burundi", + "Gaborone, Botswana", + "Lubumbashi, Congo, Democratic Republic of the", + "Nicosia, Cyprus", + "Famagusta, Cyprus", + "Tallinn, Estonia", + "Cairo, Egypt", + "Helsinki, Finland", + "Athens, Greece", + "Jerusalem, Israel", + "Amman, Jordan", + "Beirut, Lebanon", + "Maseru, Lesotho", + "Vilnius, Lithuania", + "Riga, Latvia", + "Tripoli, Libya", + "Chisinau, Moldova, Republic of", + "Blantyre, Malawi", + "Maputo, Mozambique", + "Windhoek, Namibia", + "Gaza, Palestine, State of", + "Hebron, Palestine, State of", + "Bucharest, Romania", + "Kaliningrad, Russian Federation", + "Kigali, Rwanda", + "Khartoum, Sudan", + "Juba, South Sudan", + "Damascus, Syrian Arab Republic", + "Mbabane, Eswatini", + "Kiev, Ukraine", + "Uzhgorod, Ukraine", + "Zaporozhye, Ukraine", + "Johannesburg, South Africa", + "Lusaka, Zambia", + "Harare, Zimbabwe" + ], + "180": [ + "Syowa, Antarctica", + "Bahrain, Bahrain", + "Minsk, Belarus", + "Djibouti, Djibouti", + "Asmara, Eritrea", + "Addis Ababa, Ethiopia", + "Baghdad, Iraq", + "Nairobi, Kenya", + "Comoro, Comoros", + "Kuwait, Kuwait", + "Antananarivo, Madagascar", + "Qatar, Qatar", + "Moscow, Russian Federation", + "Simferopol, Ukraine", + "Kirov, Russian Federation", + "Volgograd, Russian Federation", + "Riyadh, Saudi Arabia", + "Mogadishu, Somalia", + "Istanbul, Turkey", + "Dar es_Salaam, Tanzania, United Republic of", + "Kampala, Uganda", + "Aden, Yemen", + "Mayotte, Mayotte" + ], + "240": [ + "Dubai, United Arab Emirates", + "Yerevan, Armenia", + "Baku, Azerbaijan", + "Tbilisi, Georgia", + "Mauritius, Mauritius", + "Muscat, Oman", + "Reunion, Réunion", + "Astrakhan, Russian Federation", + "Saratov, Russian Federation", + "Ulyanovsk, Russian Federation", + "Samara, Russian Federation", + "Mahe, Seychelles" + ], + "300": [ + "Mawson, Antarctica", + "Qyzylorda, Kazakhstan", + "Aqtobe, Kazakhstan", + "Aqtau, Kazakhstan", + "Atyrau, Kazakhstan", + "Oral, Kazakhstan", + "Maldives, Maldives", + "Karachi, Pakistan", + "Yekaterinburg, Russian Federation", + "Kerguelen, French Southern Territories", + "Dushanbe, Tajikistan", + "Ashgabat, Turkmenistan", + "Samarkand, Uzbekistan", + "Tashkent, Uzbekistan" + ], + "360": [ + "Vostok, Antarctica", + "Dhaka, Bangladesh", + "Thimphu, Bhutan", + "Urumqi, China", + "Chagos, British Indian Ocean Territory", + "Bishkek, Kyrgyzstan", + "Almaty, Kazakhstan", + "Qostanay, Kazakhstan", + "Omsk, Russian Federation" + ], + "420": [ + "Davis, Antarctica", + "Christmas, Christmas Island", + "Jakarta, Indonesia", + "Pontianak, Indonesia", + "Phnom Penh, Cambodia", + "Vientiane, Lao People's Democratic Republic", + "Hovd, Mongolia", + "Novosibirsk, Russian Federation", + "Barnaul, Russian Federation", + "Tomsk, Russian Federation", + "Novokuznetsk, Russian Federation", + "Krasnoyarsk, Russian Federation", + "Bangkok, Thailand", + "Ho Chi_Minh, Viet Nam" + ], + "480": [ + "Perth, Australia", + "Brunei, Brunei Darussalam", + "Shanghai, China", + "Hong Kong, Hong Kong", + "Makassar, Indonesia", + "Ulaanbaatar, Mongolia", + "Choibalsan, Mongolia", + "Macau, Macao", + "Kuala Lumpur, Malaysia", + "Kuching, Malaysia", + "Manila, Philippines", + "Irkutsk, Russian Federation", + "Singapore, Singapore", + "Taipei, Taiwan, Province of China" + ], + "540": [ + "Jayapura, Indonesia", + "Tokyo, Japan", + "Pyongyang, Korea (Democratic People's Republic of)", + "Seoul, Korea, Republic of", + "Palau, Palau", + "Chita, Russian Federation", + "Yakutsk, Russian Federation", + "Khandyga, Russian Federation", + "Dili, Timor-Leste" + ], + "600": [ + "DumontDUrville, Antarctica", + "Brisbane, Australia", + "Lindeman, Australia", + "Chuuk, Micronesia (Federated States of)", + "Guam, Guam", + "Saipan, Northern Mariana Islands", + "Port Moresby, Papua New Guinea", + "Vladivostok, Russian Federation", + "Ust-Nera, Russian Federation" + ], + "660": [ + "Casey, Antarctica", + "Lord Howe, Australia", + "Macquarie, Australia", + "Hobart, Australia", + "Melbourne, Australia", + "Sydney, Australia", + "Pohnpei, Micronesia (Federated States of)", + "Kosrae, Micronesia (Federated States of)", + "Noumea, New Caledonia", + "Bougainville, Papua New Guinea", + "Magadan, Russian Federation", + "Sakhalin, Russian Federation", + "Srednekolymsk, Russian Federation", + "Guadalcanal, Solomon Islands", + "Efate, Vanuatu" + ], + "720": [ + "Tarawa, Kiribati", + "Majuro, Marshall Islands", + "Kwajalein, Marshall Islands", + "Norfolk, Norfolk Island", + "Nauru, Nauru", + "Kamchatka, Russian Federation", + "Anadyr, Russian Federation", + "Funafuti, Tuvalu", + "Wake, United States Minor Outlying Islands", + "Wallis, Wallis and Futuna" + ], + "780": [ + "McMurdo, Antarctica", + "Pago Pago, American Samoa", + "Fiji, Fiji", + "Kanton, Kiribati", + "Niue, Niue", + "Auckland, New Zealand", + "Fakaofo, Tokelau", + "Tongatapu, Tonga", + "Midway, United States Minor Outlying Islands", + "Apia, Samoa" + ], + "840": [ + "Rarotonga, Cook Islands", + "Kiritimati, Kiribati", + "Tahiti, French Polynesia", + "Adak, United States of America", + "Honolulu, United States of America" + ], + "900": [ + "Gambier, French Polynesia", + "Anchorage, United States of America", + "Juneau, United States of America", + "Sitka, United States of America", + "Metlakatla, United States of America", + "Yakutat, United States of America", + "Nome, United States of America" + ], + "960": [ + "Vancouver, Canada", + "Tijuana, Mexico", + "Pitcairn, Pitcairn", + "Los Angeles, United States of America" + ], + "1020": [ + "Edmonton, Canada", + "Cambridge Bay, Canada", + "Yellowknife, Canada", + "Inuvik, Canada", + "Creston, Canada", + "Dawson Creek, Canada", + "Fort Nelson, Canada", + "Whitehorse, Canada", + "Dawson, Canada", + "Mazatlan, Mexico", + "Chihuahua, Mexico", + "Ojinaga, Mexico", + "Hermosillo, Mexico", + "Denver, United States of America", + "Boise, United States of America", + "Phoenix, United States of America" + ], + "1080": [ + "Belize, Belize", + "Winnipeg, Canada", + "Rainy River, Canada", + "Resolute, Canada", + "Rankin Inlet, Canada", + "Regina, Canada", + "Swift Current, Canada", + "Costa Rica, Costa Rica", + "Galapagos, Ecuador", + "Guatemala, Guatemala", + "Tegucigalpa, Honduras", + "Mexico City, Mexico", + "Merida, Mexico", + "Monterrey, Mexico", + "Matamoros, Mexico", + "Bahia Banderas, Mexico", + "Managua, Nicaragua", + "El Salvador, El Salvador", + "Chicago, United States of America", + "Tell City, Indiana", + "Knox, Indiana", + "Menominee, United States of America", + "Center, North Dakota", + "New_Salem, North Dakota", + "Beulah, North Dakota" + ], + "1140": [ + "Eirunepe, Brazil", + "Rio Branco, Brazil", + "Nassau, Bahamas", + "Toronto, Canada", + "Nipigon, Canada", + "Thunder Bay, Canada", + "Iqaluit, Canada", + "Pangnirtung, Canada", + "Atikokan, Canada", + "Easter, Chile", + "Bogota, Colombia", + "Havana, Cuba", + "Guayaquil, Ecuador", + "Port-au-Prince, Haiti", + "Jamaica, Jamaica", + "Cayman, Cayman Islands", + "Cancun, Mexico", + "Panama, Panama", + "Lima, Peru", + "Grand Turk, Turks and Caicos Islands", + "New York, United States of America", + "Detroit, United States of America", + "Louisville, Kentucky", + "Monticello, Kentucky", + "Indianapolis, Indiana", + "Vincennes, Indiana", + "Winamac, Indiana", + "Marengo, Indiana", + "Petersburg, Indiana", + "Vevay, Indiana" + ], + "1200": [ + "Antigua, Antigua and Barbuda", + "Anguilla, Anguilla", + "Aruba, Aruba", + "Barbados, Barbados", + "St Barthelemy, Saint Barthélemy", + "Bermuda, Bermuda", + "La Paz, Bolivia (Plurinational State of)", + "Kralendijk, Bonaire, Sint Eustatius and Saba", + "Campo Grande, Brazil", + "Cuiaba, Brazil", + "Porto Velho, Brazil", + "Boa Vista, Brazil", + "Manaus, Brazil", + "Halifax, Canada", + "Glace Bay, Canada", + "Moncton, Canada", + "Goose Bay, Canada", + "Blanc-Sablon, Canada", + "Curacao, Curaçao", + "Dominica, Dominica", + "Santo Domingo, Dominican Republic", + "Grenada, Grenada", + "Thule, Greenland", + "Guadeloupe, Guadeloupe", + "Guyana, Guyana", + "St Kitts, Saint Kitts and Nevis", + "St Lucia, Saint Lucia", + "Marigot, Saint Martin (French part)", + "Martinique, Martinique", + "Montserrat, Montserrat", + "Puerto Rico, Puerto Rico", + "Lower Princes, Sint Maarten (Dutch part)", + "Port of_Spain, Trinidad and Tobago", + "St Vincent, Saint Vincent and the Grenadines", + "Caracas, Venezuela (Bolivarian Republic of)", + "Tortola, Virgin Islands (British)", + "St Thomas, Virgin Islands (U.S.)" + ], + "1260": [ + "Palmer, Antarctica", + "Rothera, Antarctica", + "Buenos Aires, Argentina", + "Cordoba, Argentina", + "Salta, Argentina", + "Jujuy, Argentina", + "Tucuman, Argentina", + "Catamarca, Argentina", + "La Rioja, Argentina", + "San Juan, Argentina", + "Mendoza, Argentina", + "San Luis, Argentina", + "Rio Gallegos, Argentina", + "Ushuaia, Argentina", + "Belem, Brazil", + "Fortaleza, Brazil", + "Recife, Brazil", + "Araguaina, Brazil", + "Maceio, Brazil", + "Bahia, Brazil", + "Sao Paulo, Brazil", + "Santarem, Brazil", + "Santiago, Chile", + "Punta Arenas, Chile", + "Stanley, Falkland Islands (Malvinas)", + "Cayenne, French Guiana", + "Nuuk, Greenland", + "Miquelon, Saint Pierre and Miquelon", + "Asuncion, Paraguay", + "Paramaribo, Suriname", + "Montevideo, Uruguay" + ], + "1320": [ + "Noronha, Brazil", + "South Georgia, South Georgia and the South Sandwich Islands" + ], + "1380": [ + "Cape Verde, Cabo Verde", + "Scoresbysund, Greenland", + "Azores, Portugal" + ] +} \ No newline at end of file diff --git a/apps/ftclock/mkFourTwentyTz.js b/apps/ftclock/mkFourTwentyTz.js new file mode 100644 index 000000000..dd199523a --- /dev/null +++ b/apps/ftclock/mkFourTwentyTz.js @@ -0,0 +1,74 @@ +let fs = require('fs'); +let csv = require('csv'); + +let countries = {}, + zones = {}, + offsdict = {}, + now = Date.now(); // we need this to find zone's current DST state + +function handleWrite(err,bytes) { + if (err) { + console.log(`Error writing to file ${err}`); + } +} + +console.log("Generating fourTwentyTz.js..."); +fs.createReadStream(__dirname+'/country.csv') + .pipe(csv.parse()) + .on('data', (r) => { + countries[r[0]] = r[1]; + }) + .on('end', () => { + fs.createReadStream(__dirname+'/zone.csv') + .pipe(csv.parse()) + .on('data', (r) => { + let parts = r[2].replace('_',' ').split('/'); + let city = parts[parts.length-1]; + let country =''; + if (parts.length>2) { // e.g. America/North_Dakota/New_Salem + country = parts[1]; // e.g. North Dakota + } else { + country = countries[r[1]]; // e.g. United States + } + zones[parseInt(r[0])] = {"name": `${city}, ${country}`}; + }) + .on('end', () => { + fs.createReadStream(__dirname+'/timezone.csv') + .pipe(csv.parse()) + .on('data', (r) => { + code = parseInt(r[0]); + if (!(code in zones)) return; + starttime = parseInt(r[2] || "0"); // Bugger. They're feeding us blanks for UTC now + offs = parseInt(r[3]); + if (offs<0) { + offs += 60*60*24; + } + zone = zones[code]; + if (starttime { + for (z in zones) { + zone = zones[z]; + if (zone.offs%60) continue; // One a dem funky timezones. Ignore. + zonelist = offsdict[zone.offs] || []; + zonelist.push(zone.name); + offsdict[zone.offs] = zonelist; + } + fs.open("fourTwentyTz.js","w", (err, fd) => { + if (err) { + console.log("Can't open output file"); + return; + } + fs.write(fd, "// Generated by mkFourTwentyTz.js\n", handleWrite); + fs.write(fd, `// ${Date()}\n`, handleWrite); + fs.write(fd, "// Data source: https://timezonedb.com/files/timezonedb.csv.zip\n", handleWrite); + fs.write(fd, "exports.timezones = ", handleWrite); + fs.write(fd, JSON.stringify(offsdict, null, 4), handleWrite); + console.log('Done.'); + }); + }) + }) + }); diff --git a/apps/ftclock/mkFourTwentyTz.py b/apps/ftclock/mkFourTwentyTz.py deleted file mode 100644 index 713b68059..000000000 --- a/apps/ftclock/mkFourTwentyTz.py +++ /dev/null @@ -1,46 +0,0 @@ -# Generates fourTwentyTz.js from time zone csv files -# get latest files from https://timezonedb.com/download -import csv,json,time,os,math -countries = {} -for r in csv.reader(open("country.csv")): - countries[r[0]] = r[1] -zones = {} -for r in csv.reader(open("zone.csv")): - parts = r[2].replace('_',' ').split('/') - city = parts[-1] - if len(parts)>2: # e.g. America/North_Dakota/New_Salem - country = parts[1] # e.g. North Dakota - else: # e.g. America/Denver - country = countries[r[1]] # e.g. United States - if country==city: # Avoid awkward searches like "Anguilla, Anguilla" - country = r[1] # Use code instead - zones[int(r[0])] = {"name":', '.join((city,country))} -now = int(time.time()) -for r in csv.reader(open("timezone.csv")): - code = int(r[0]) - if code not in zones: - continue - starttime = int(r[2] or "0") # Bugger. They're feeding us blanks for UTC now - offs = int(r[3]) - if offs < 0: - offs += 60*60*24 - d = zones[code] - if starttime Date: Sun, 9 Jan 2022 13:42:01 +0100 Subject: [PATCH 336/489] Fix drawing of full circle --- apps/circlesclock/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 3843d5dda..1f6cc75ab 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -372,7 +372,7 @@ function drawGauge(cx, cy, percent, color) { if (percent > 1) percent = 1; var startrot = -offset; - var endrot = startrot - ((end - offset) * percent) - 15; + var endrot = startrot - ((end - offset) * percent) - 35; g.setColor(color); From 05f0d3003a32df7e1e95bfd72d679d9edc333097 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Sun, 9 Jan 2022 13:45:50 +0100 Subject: [PATCH 337/489] Fix minor glitch in circle drawing --- apps/circlesclock/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 1f6cc75ab..91d4937c4 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -376,7 +376,7 @@ function drawGauge(cx, cy, percent, color) { g.setColor(color); - const size = radiusOuter - radiusInner - 3; + const size = radiusOuter - radiusInner - 2; // draw gauge for (i = startrot; i > endrot - size; i -= size) { x = cx + r * Math.sin(radians(i)); From 6f1b1093621a20aba705cbe483222013c416f1b4 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Sun, 9 Jan 2022 13:46:12 +0100 Subject: [PATCH 338/489] Add TODOs to README --- apps/circlesclock/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/circlesclock/README.md b/apps/circlesclock/README.md index a071efcf5..9aaa4bc8e 100644 --- a/apps/circlesclock/README.md +++ b/apps/circlesclock/README.md @@ -15,6 +15,10 @@ It can show the following information (this can be configured): ![Screenshot dark theme](screenshot-dark.png) ![Screenshot light theme](screenshot-light.png) +# TODO +* Add sunrise and sunset +* Display moon instead of sun during night on weather circle + ## Creator Marco ([myxor](https://github.com/myxor)) From 992b1e6564777d5d4e3bb012594ee5c030953393 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 9 Jan 2022 18:55:33 +0100 Subject: [PATCH 339/489] Bumped wohrm version number --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index ebe193f3a..c155f9262 100644 --- a/apps.json +++ b/apps.json @@ -1717,7 +1717,7 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.09-rc10", + "version": "0.09", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app", From 707118ffbbc92dc8869b5643fce60847521ef530 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 9 Jan 2022 19:04:00 +0100 Subject: [PATCH 340/489] Bumped Hand Wash Timer version number --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 6fbc82e8b..b73cfe0e6 100644 --- a/apps.json +++ b/apps.json @@ -1893,7 +1893,7 @@ { "id": "widhwt", "name": "Hand Wash Timer", - "version": "0.02-rc10", + "version": "0.02", "description": "On Bangle.js 1 swipe your wrist over the watch face to start your personal Bangle.js 1 hand wash timer. On Bangle.js2 the Pattern Launcher is recommended to start the timer. Start washing after the short buzz and stop after the long buzz 35sec. later.", "icon": "widget.png", "type": "widget", From 20406ca29cadef7492c6cdc3e6a06ca134252259 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Mon, 10 Jan 2022 00:11:24 +0100 Subject: [PATCH 341/489] Clock can optionally show ISO-8601 calendar weeknumber --- apps.json | 2 +- apps/antonclk/ChangeLog | 3 +++ apps/antonclk/README.md | 3 +-- apps/antonclk/app.js | 38 +++++++++++++++++++++++++++++--------- apps/antonclk/settings.js | 8 ++++++++ 5 files changed, 42 insertions(+), 12 deletions(-) diff --git a/apps.json b/apps.json index 3fc0616da..c2180b91d 100644 --- a/apps.json +++ b/apps.json @@ -4242,7 +4242,7 @@ { "id": "antonclk", "name": "Anton Clock", - "version": "0.04", + "version": "0.05", "description": "A clock using the bold Anton font, optionally showing seconds and date in ISO-8601 format.", "readme":"README.md", "icon": "app.png", diff --git a/apps/antonclk/ChangeLog b/apps/antonclk/ChangeLog index 668047d7a..fdf20c175 100644 --- a/apps/antonclk/ChangeLog +++ b/apps/antonclk/ChangeLog @@ -2,3 +2,6 @@ 0.02: Load widgets after setUI so widclk knows when to hide 0.03: Clock now shows day of week under date. 0.04: Clock can optionally show seconds, date optionally in ISO-8601 format, weekdays and uppercase configurable, too. +0.05: Clock can optionally show ISO-8601 calendar weeknumber (default: Off) + when weekday name "Off": week #: + when weekday name "On": weekday name is cut at 6th position and .# is added \ No newline at end of file diff --git a/apps/antonclk/README.md b/apps/antonclk/README.md index 41d3e4559..fa4cc4919 100644 --- a/apps/antonclk/README.md +++ b/apps/antonclk/README.md @@ -40,8 +40,7 @@ The main menu contains several settings covering Anton clock in general. * **Show Weekday** - Weekday is shown in the time presentation without seconds. Weekday name depends on the current locale. If seconds are shown, the weekday is never shown as there is not enough space on the watch face. -* **Uppercase** - Weekday name and month name in the long format are converted to upper case letters. -This can improve readability. +**Show Weeknumber** - Weeknumber (ISO-8601) is shown. * **Vector font** - Use the built-in vector font for dates and weekday. This can improve readability. Otherwise, a scaled version of the built-in 6x8 pixels font is used. diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index 1f3e49792..be6c23789 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -19,6 +19,7 @@ var secondsWithColon; var dateOnMain; var dateOnSecs; var weekDay; +var calWeek; var upperCase; var vectorFont; @@ -29,22 +30,25 @@ var secondsScreen = true; var isBangle1 = (g.getWidth() == 240); -/* For development purposes +//For development purposes +/* require('Storage').writeJSON(SETTINGSFILE, { - secondsMode: "Always", // "Never", "Unlocked", "Always" + secondsMode: "Unlocked", // "Never", "Unlocked", "Always" secondsColoured: true, secondsWithColon: true, dateOnMain: "Long", // "Short", "Long", "ISO8601" dateOnSecs: "Year", // "No", "Year", "Weekday", LEGACY: true/false weekDay: true, + calWeek: true, upperCase: true, vectorFont: true, }); -/* */ +*/ -/* OR (also for development purposes) +// OR (also for development purposes) +/* require('Storage').erase(SETTINGSFILE); -/* */ +*/ // Helper method for loading the settings function def(value, def) { @@ -60,6 +64,7 @@ function loadSettings() { dateOnMain = def(settings.dateOnMain, "Long"); dateOnSecs = def(settings.dateOnSecs, "Year"); weekDay = def(settings.weekDay, true); + calWeek = def(settings.calWeek, false); upperCase = def(settings.upperCase, true); vectorFont = def(settings.vectorFont, false); @@ -99,6 +104,18 @@ function isoStr(date) { return date.getFullYear() + "-" + ("0" + (date.getMonth() + 1)).substr(-2) + "-" + ("0" + date.getDate()).substr(-2); } +function ISO8601calWeek(date) { //copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480 + var tdt = new Date(date.valueOf()); + var dayn = (date.getDay() + 6) % 7; + tdt.setDate(tdt.getDate() - dayn + 3); + var firstThursday = tdt.valueOf(); + tdt.setMonth(0, 1); + if (tdt.getDay() !== 4) { + tdt.setMonth(0, 1 + ((4 - tdt.getDay()) + 7) % 7); + } + return 1 + Math.ceil((firstThursday - tdt) / 604800000); +} + function doColor() { return !isBangle1 && !Bangle.isLocked() && secondsColoured; } @@ -169,11 +186,14 @@ function draw() { else g.setFont("6x8", 2); g.drawString(dateStr, x, y); - if (weekDay) { - var dowStr = require("locale").dow(date); + if (weekDay || calWeek) { + var dowwumStr = require("locale").dow(date); + dowwumStr = "thursday"; + if (calWeek) + dowwumStr = (weekDay ? dowwumStr.substr(0,Math.min(dowwumStr.length,6)) + (dowwumStr.length>=6 ? "." : "") : "week ") + "#" + ISO8601calWeek(date); if (upperCase) - dowStr = dowStr.toUpperCase(); - g.drawString(dowStr, x, y + (vectorFont ? 26 : 16)); + dowwumStr = dowwumStr.toUpperCase(); + g.drawString(dowwumStr, x, y + (vectorFont ? 26 : 16)); } } diff --git a/apps/antonclk/settings.js b/apps/antonclk/settings.js index 08fde512e..293aa0438 100644 --- a/apps/antonclk/settings.js +++ b/apps/antonclk/settings.js @@ -47,6 +47,14 @@ writeSettings(); } }, + "Show Weeknumber": { + value: (settings.weekNum !== undefined ? settings.weekNum : true), + format: v => v ? "On" : "Off", + onchange: v => { + settings.weekNum = v; + writeSettings(); + } + }, "Uppercase": { value: (settings.upperCase !== undefined ? settings.upperCase : false), format: v => v ? "On" : "Off", From d06283137995b78bb126e1861a6a2a81f0d80c1a Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 10 Jan 2022 08:47:52 +0000 Subject: [PATCH 342/489] Changelog for #1240 0.41: Add Keyboard and Mouse Bluetooth HID option --- apps.json | 2 +- apps/boot/ChangeLog | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 2493ac6cb..2a51fc0ae 100644 --- a/apps.json +++ b/apps.json @@ -16,7 +16,7 @@ { "id": "boot", "name": "Bootloader", - "version": "0.40", + "version": "0.41", "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/boot/ChangeLog b/apps/boot/ChangeLog index d6619822b..702a8091e 100644 --- a/apps/boot/ChangeLog +++ b/apps/boot/ChangeLog @@ -44,3 +44,4 @@ 0.38: Option to log to file if settings.log==2 0.39: Fix passkey support (fix https://github.com/espruino/Espruino/issues/2035) 0.40: Bootloader now rebuilds for new firmware versions +0.41: Add Keyboard and Mouse Bluetooth HID option From eaaddae9465af1c1bcc3c409b874f4806343c498 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 10 Jan 2022 14:06:50 +0000 Subject: [PATCH 343/489] fix broken instagram icon --- apps/messages/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/messages/app.js b/apps/messages/app.js index e36bb699e..6e51c2b33 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -83,7 +83,7 @@ function getMessageImage(msg) { if (s=="calendar") return atob("GBiBAAAAAAAAAAAAAA//8B//+BgAGBgAGBgAGB//+B//+B//+B9m2B//+B//+Btm2B//+B//+Btm+B//+B//+A//8AAAAAAAAAAAAA=="); if (s=="facebook") return getFBIcon(); if (s=="hangouts") return atob("FBaBAAH4AH/gD/8B//g//8P//H5n58Y+fGPnxj5+d+fmfj//4//8H//B//gH/4A/8AA+AAHAABgAAAA="); - if (s=="instagram") return atob("GBiBAf////////////////wAP/n/n/P/z/f/b/eB7/c87/d+7/d+7/d+7/d+7/c87/eB7/f/7/P/z/n/n/wAP////////////////w=="); + if (s=="instagram") return atob("GBiBAAAAAAAAAAAAAAAAAAP/wAYAYAwAMAgAkAh+EAjDEAiBEAiBEAiBEAiBEAjDEAh+EAgAEAwAMAYAYAP/wAAAAAAAAAAAAAAAAA=="); if (s=="gmail") return getNotificationImage(); if (s=="google home") return atob("GBiCAAAAAAAAAAAAAAAAAAAAAoAAAAAACqAAAAAAKqwAAAAAqroAAAACquqAAAAKq+qgAAAqr/qoAACqv/6qAAKq//+qgA6r///qsAqr///6sAqv///6sAqv///6sAqv///6sA6v///6sA6v///qsA6qqqqqsA6qqqqqsA6qqqqqsAP7///vwAAAAAAAAAAAAAAAAA=="); if (s=="mail") return getNotificationImage(); From b711b50f888ecfb96f5a5cf4e2340507a6087c87 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Mon, 10 Jan 2022 16:10:42 +0100 Subject: [PATCH 344/489] Initial version of BanglExercise --- apps.json | 19 ++- apps/banglexercise/ChangeLog | 1 + apps/banglexercise/README.md | 35 ++++ apps/banglexercise/app-icon.js | 1 + apps/banglexercise/app.js | 259 ++++++++++++++++++++++++++++++ apps/banglexercise/app.png | Bin 0 -> 690 bytes apps/banglexercise/screenshot.png | Bin 0 -> 2043 bytes 7 files changed, 314 insertions(+), 1 deletion(-) create mode 100644 apps/banglexercise/ChangeLog create mode 100644 apps/banglexercise/README.md create mode 100644 apps/banglexercise/app-icon.js create mode 100644 apps/banglexercise/app.js create mode 100644 apps/banglexercise/app.png create mode 100644 apps/banglexercise/screenshot.png diff --git a/apps.json b/apps.json index 389603249..0adb4abc5 100644 --- a/apps.json +++ b/apps.json @@ -5149,7 +5149,7 @@ {"name":"mmind.app.js","url":"mmind.app.js"}, {"name":"mmind.img","url":"mmind.icon.js","evaluate":true} ] - }, + }, { "id": "presentor", "name": "Presentor", @@ -5503,5 +5503,22 @@ {"name":"limelight.settings.js","url":"limelight.settings.js"}, {"name":"limelight.img","url":"limelight.icon.js","evaluate":true} ] + }, + { "id": "banglexercise", + "name": "BanglExercise", + "shortName":"BanglExercise", + "version":"0.01", + "description": "Can automatically track exercises while wearing the Bangle.js watch.", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], + "type": "app", + "tags": "sport", + "supports" : ["BANGLEJS2"], + "allow_emulator":true, + "readme": "README.md", + "storage": [ + {"name":"banglexercise.app.js","url":"app.js"}, + {"name":"banglexercise.img","url":"app-icon.js","evaluate":true} + ] } ] diff --git a/apps/banglexercise/ChangeLog b/apps/banglexercise/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/banglexercise/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/banglexercise/README.md b/apps/banglexercise/README.md new file mode 100644 index 000000000..e7ac9573d --- /dev/null +++ b/apps/banglexercise/README.md @@ -0,0 +1,35 @@ +# Banglexercise + +Can automatically track exercises while wearing the Bangle.js watch. + +Currently only push ups are supported. + + +## Usage + +Select the exercise type you want to practive and go for it! +Press stop to end your exercise. + + +## Screenshots +![](screenshot.png) + +## TODO +* Add other exercise types: + * Rope jumps + * Curls + * Sit ups + * ... +* Save exercises to file system +* Add settings (vibration, beep, ...) +* Find a nicer icon + + +## Contribute +Feel free to send in improvements and remarks. + +## Creator +Marco ([myxor](https://github.com/myxor)) + +## Icons +Icons taken from [materialdesignicons](https://materialdesignicons.com) under Apache License 2.0 diff --git a/apps/banglexercise/app-icon.js b/apps/banglexercise/app-icon.js new file mode 100644 index 000000000..e1923bf54 --- /dev/null +++ b/apps/banglexercise/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwIbYh/8AYM/+EP/wFBv4FB/4FB/4FHAwIEBAv4FPAgIGCAosHAofggYFD4EABgXgOgIFLDAQWBAo0BAoOAVIV/UYQABj/4AocDCwQFTg46CEY4vFAopBBApIAVA==")) diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js new file mode 100644 index 000000000..feb3a1127 --- /dev/null +++ b/apps/banglexercise/app.js @@ -0,0 +1,259 @@ +const Layout = require("Layout"); + +let historyY = []; +let historyZ = []; +const avgSize = 10; + +const thresholdY = 2500; +const thresholdPushUpTime = 1400; // mininmal time between two push ups +let tStart; + +let avgY; +let avgZ; +let historyAvgY = []; +let historyAvgZ = []; +let historySlopeY = []; +let historySlopeZ = []; + +let lastZeroPassType; +let lastZeroPassTime = 0; +let lastPushUpCmpltTime = 0; + +let exerciseType = ""; +let pushUpCounter = 0; + +let layout; + +let recordActive = false; + + +function showMenu() { + let menu; + if (pushUpCounter == 0) { + menu = { + "": { + title: "Banglexercise" + }, + "Start push ups": function() { + exerciseType = "push ups"; + E.showMenu(); + startRecording(); + } + }; + } else { + menu = { + "": { + title: "Banglexercise" + }, + "Last:": { + value: pushUpCounter + " push ups" + }, + "Start push ups": function() { + exerciseType = "push ups"; + E.showMenu(); + startRecording(); + } + }; + } + E.showMenu(menu); +} + +function accelHandler(accel) { + const t = Math.round(new Date().getTime()); // time in ms + const y = accel.y * 8192; + const z = accel.z * 8192; + //console.log(t, y, z); + + while (historyY.length > avgSize) + historyY.shift(); + historyY.push(y); + + if (historyY.length > avgSize / 2) + avgY = E.sum(historyY) / historyY.length; + + while (historyZ.length > avgSize) + historyZ.shift(); + historyZ.push(z); + + if (historyZ.length > avgSize / 2) + avgZ = E.sum(historyZ) / historyZ.length; + + if (avgY) { + //console.log(avgY, avgZ); + historyAvgY.push([t, avgY]); + historyAvgZ.push([t, avgZ]); + } + + let mY; + let mZ; + // slope for Y + let l = historyAvgY.length; + if (l > 1) { + const p1 = historyAvgY[l - 2]; + const p2 = historyAvgY[l - 1]; + mY = (p2[1] - p1[1]) / (p2[0] / 1000 - p1[0] / 1000); + if (Math.abs(mY) >= thresholdY) { + historyAvgY.shift(); + historySlopeY.push([t, mY]); + //console.log(t, Math.abs(mY)); + + const lMY = historySlopeY.length; + if (lMY > 1) { + const pMY1 = historySlopeY[lMY - 2][1]; + const pMY2 = historySlopeY[lMY - 1][1]; + isValidPushUp(pMY1, pMY2, t); + } + } + } + + // slope for Z + l = historyAvgZ.length; + if (l > 1) { + const p1 = historyAvgZ[l - 2]; + const p2 = historyAvgZ[l - 1]; + mZ = (p2[1] - p1[1]) / (p2[0] - p1[0]); + historyAvgZ.shift(); + historySlopeZ.push([p2[0] - p1[0], mZ]); + } +} + +function isValidPushUp(p1, p2, t) { + if (p1 > 0 && p2 < 0) { + + if (lastZeroPassType == "-+") { + console.log(t, "Push up half complete..."); + + layout.progress.label = "..."; + layout.render(layout.progress); + } + + lastZeroPassType = "+-"; + lastZeroPassTime = t; + } + if (p2 > 0 && p1 < 0) { + + if (lastZeroPassType == "+-") { + // potential complete push up. Let's check the time difference... + const tDiffLastPushUp = t - lastPushUpCmpltTime; + const tDiffStart = t - tStart; + console.log(t, "Push up maybe complete?", Math.round(tDiffLastPushUp), Math.round(tDiffStart)); + + if ((lastPushUpCmpltTime <= 0 && tDiffStart >= thresholdPushUpTime) || tDiffLastPushUp >= thresholdPushUpTime) { + console.log(t, "Push up complete!!!"); + + lastPushUpCmpltTime = t; + pushUpCounter++; + + layout.count.label = pushUpCounter; + layout.render(layout.count); + layout.progress.label = ""; + layout.render(layout.progress); + + Bangle.buzz(100, 0.3); // TODO make configurable + } else { + console.log(t, "Push up to quick for threshold!"); + } + } + + lastZeroPassType = "-+"; + lastZeroPassTime = t; + } +} + +/* + +function calcPushUps() { + const l = historySlopeY.length; + for (let i = 1; i < l; i++) { + const p1 = historySlopeY[i - 1][1]; + const p2 = historySlopeY[i][1]; + const t = historySlopeY[i][0]; + isValidPushUp(p1, p2, t); + } +} +*/ + +function reset() { + historyY = []; + historyZ = []; + historyAvgY = []; + historyAvgZ = []; + historySlopeY = []; + historySlopeZ = []; + + lastZeroPassType = ""; + lastZeroPassTime = 0; + lastPushUpCmpltTime = 0; + pushUpCounter = 0; +} + + +function startRecording() { + if (recordActive) return; + g.clear(1); + reset(); + layout = new Layout({ + type: "v", + c: [{ + type: "txt", + id: "type", + font: "6x8:2", + label: exerciseType, + pad: 5 + }, + { + type: "txt", + id: "count", + font: "6x8:9", + label: pushUpCounter, + pad: 5, + bgCol: g.theme.bg + }, + { + type: "txt", + id: "progress", + font: "6x8:2", + label: "", + pad: 5 + }, + { + type: "txt", + id: "recording", + font: "6x8:2", + label: "RECORDING", + bgCol: "#f00", + pad: 5, + fillx: 1 + }, + ] + }, { + btns: [ + { + label: "STOP", + cb: () => { + stopRecording(); + } + } + ] + }); + layout.render(); + + Bangle.setPollInterval(80); // 12.5 Hz + Bangle.on('accel', accelHandler); + Bangle.buzz(200, 1); + tStart = new Date().getTime(); + recordActive = true; +} + +function stopRecording() { + if (!recordActive) return; + g.clear(1); + Bangle.removeListener('accel', accelHandler); + showMenu(); + console.log("Found " + pushUpCounter + " push ups!"); + recordActive = false; +} + +g.clear(1); +Bangle.drawWidgets(); +showMenu(); diff --git a/apps/banglexercise/app.png b/apps/banglexercise/app.png new file mode 100644 index 0000000000000000000000000000000000000000..ee733206310029c15e866e4fc6bef39305d70668 GIT binary patch literal 690 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTCmUKs7M+SzC{oH>NS%G|oWRD45dJguM!v-tY$DUh!@P+6=(yLU`z6LcLCBs@Y8vBJ&@uo z@Q5r1(g|SvA=~LZ0|Vn0PZ!6KjC*fqZuC0rAk)5ISX|cS=uz>4qEPnOCH@cIG_P3P zFGDWi zNGnrbNL|R7G5egyoLkxdBkfxbtgvmLFk!~jikVyTJQzLaunJ`CzH(+>eiw_(tM5ID zCxaKT>-gQeKjZ#PZ`Muf7F<@rVfw%ShRjWzrNDVa4Hc#BdJrKWAyK=c`uohKOXBRS z7i6&M&E|RIp%;De^8uL)tYJyZ&wgNABYF7x`R1LH8)UCF6mu=pVXB?2D!xxh=y%`w zvwFGbP5q~azSwr`;=Yw1ZzZe9Wl8+~?RF@-QMWVkzz65fv&UH090_!2JnVKjno+s% zjis=&wZJj^z|x7+T(&#?Q18sW|I6{rTaII}*{P}%1L#X5Imj9~9Jam|MPl%6IS=VU&;E=?<Hxi+V}Sty2#I1U-4_X;bU=*PM1S-^ErIH(Bc9_KZH+1;!FW?Xq@{?d#wat2 zqSPaenYJE9vqHzCE!82k>QzeX6>8#H&He5_^T(`p*S-JUv(`C#?X~wgd+)PNP;eAqEM1m z_SP0|asJCCgE3v@PMo1! z*f|v3#LSzFzS{I!!rV21lYAG;c$8rSY` zrtv;c`F-*otRXP}(DjxKjPZJTgeC>x=>7yoFGVWJH|o)xX+XB^NKHex&wPl`a~=~X za(P8aF({q6xR8)IKj56l)xcxv656}p+2QGn?xOha*4FfUv5E=1o8>8@ke5^X-Alra z{?c-FSdtCn#41uNW-umNx0VFrlWLa)#(@Ij$rUqQ#GSv%Zi@XPBg}gPCyKWp&p8}M z6HV+)2y3H)YaQ^Mom$c5vW71elfNdWFPDfG{GjOe_VwTz(o~)T+9W+c*{D*%tK9*e zoJ~|W+Yzo%+X)vnc0{$qEqCJk=RJ4*O9-72(B~Uzi@Es|RQEyjmgu4b^j7ydTi6Z= zTKjLeV4AP--+63`7du)}g~nr62CXHl@SB==)Cgk4oJWBwo1uoLt@$Jzoe zC8XG-fYql4>_h}+N$)&!8#8LB2x!D1B(J^4SIpD$WT!%~SBvItV#w}Bu^X$Pk*we;?6cI0@-D(Q=rGO_|R9q%_clHFEW>WP@3PJ2lX6b9WH_gJ#2oO{P>u;wA8BEkN?TPq z%^@Y+O-FLEsH-w~$0{or?;P%C_!V_W>sRIRoIl=dlz?e=`(Rq?PWbD0J3{ciJg-L; zxvZ9qEgR}wlM84&H3=%LDFm|q3jH11uV|iGtX+s^Gmi0ynq5i*$3#_ zg+J!w${3g@L`bGr#cC#`$MNK5&VPC>2@A?DFMX?x#pRoMyH9t@B^7G+?s{Oh_8X0G zdxIWdXd?sP7~p>UV*XhE!$E*z;+B&8<4Q^M4d>$>b`fhPoA)+AQJd17ewQEr$U-(Z zi?LMG(ytl$U}&R@dAxoWMG>q1h-<}t6VKQVm+sCMa7sP7#%G{990ok zZaza$U~;u;dV?Im+ikXvp0`kdvfQSWgVmHyrEgp=ZF(@0w^`k28dzQ*VFU;ceDdf(o`Cg>Bmg3o{v-Hn zd2^(E?-x3$-1VX;Tbvj|TjlUy#vZ*@U9b6V39?(t1J}IJ@v@K-((+>Q%!fY+P7m~> z)!xYJRn$*Dw4B`OQ+_C%Wykju9`})?N8H^aB$=bl;ZJN}EjlY>dhI#z)la1C1rXhwz1fgbiQh50C;I)_p2 z20-=scl5QzK*vM-t?q$nFKrt?G64N@O6e*^3d{M literal 0 HcmV?d00001 From bfe2725483e55f657f0592e519e60c077abe1897 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Mon, 10 Jan 2022 19:02:39 +0100 Subject: [PATCH 345/489] Show heart rate during training Alot of code cleanup and improvements --- apps/banglexercise/README.md | 2 +- apps/banglexercise/app.js | 269 +++++++++++++++++++---------------- 2 files changed, 151 insertions(+), 120 deletions(-) diff --git a/apps/banglexercise/README.md b/apps/banglexercise/README.md index e7ac9573d..efc87424d 100644 --- a/apps/banglexercise/README.md +++ b/apps/banglexercise/README.md @@ -1,4 +1,4 @@ -# Banglexercise +# BanglExercise Can automatically track exercises while wearing the Bangle.js watch. diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js index feb3a1127..e18faf554 100644 --- a/apps/banglexercise/app.js +++ b/apps/banglexercise/app.js @@ -1,15 +1,9 @@ const Layout = require("Layout"); +const heatshrink = require('heatshrink'); +let tStart; let historyY = []; let historyZ = []; -const avgSize = 10; - -const thresholdY = 2500; -const thresholdPushUpTime = 1400; // mininmal time between two push ups -let tStart; - -let avgY; -let avgZ; let historyAvgY = []; let historyAvgZ = []; let historySlopeY = []; @@ -17,103 +11,122 @@ let historySlopeZ = []; let lastZeroPassType; let lastZeroPassTime = 0; -let lastPushUpCmpltTime = 0; -let exerciseType = ""; -let pushUpCounter = 0; +let lastExerciseCmpltTime = 0; + +let exerciseType = { + "name": "" +}; +const exerciseTypes = [{ + "id": "pushup", + "name": "Push ups", + "useYaxe": true, + "useZaxe": false + } // add other exercises here +]; +let exerciseCounter = 0; let layout; - let recordActive = false; +/** + * Thresholds + */ +const avgSize = 6; +const pushUpThresholdY = 2500; +const pushUpThresholdTime = 1400; // mininmal time between two push ups -function showMenu() { +let hrtValue; + +function showMainMenu() { let menu; - if (pushUpCounter == 0) { - menu = { - "": { - title: "Banglexercise" - }, - "Start push ups": function() { - exerciseType = "push ups"; - E.showMenu(); - startRecording(); - } + menu = { + "": { + title: "BanglExercise" + } + }; + + exerciseTypes.forEach(function(et) { + menu["Do " + et.name] = function() { + exerciseType = et; + E.showMenu(); + startRecording(); }; - } else { - menu = { - "": { - title: "Banglexercise" - }, - "Last:": { - value: pushUpCounter + " push ups" - }, - "Start push ups": function() { - exerciseType = "push ups"; - E.showMenu(); - startRecording(); - } + }); + + if (exerciseCounter > 0) { + menu["----"] = {}; + menu["Last:"] = { + value: exerciseCounter + " " + exerciseType.name }; } + E.showMenu(menu); } function accelHandler(accel) { + if (!exerciseType) return; const t = Math.round(new Date().getTime()); // time in ms - const y = accel.y * 8192; - const z = accel.z * 8192; + const y = exerciseType.useYaxe ? accel.y * 8192 : 0; + const z = exerciseType.useZaxe ? accel.z * 8192 : 0; //console.log(t, y, z); - while (historyY.length > avgSize) - historyY.shift(); - historyY.push(y); + if (exerciseType.useYaxe) { + while (historyY.length > avgSize) + historyY.shift(); - if (historyY.length > avgSize / 2) - avgY = E.sum(historyY) / historyY.length; + historyY.push(y); - while (historyZ.length > avgSize) - historyZ.shift(); - historyZ.push(z); - - if (historyZ.length > avgSize / 2) - avgZ = E.sum(historyZ) / historyZ.length; - - if (avgY) { - //console.log(avgY, avgZ); - historyAvgY.push([t, avgY]); - historyAvgZ.push([t, avgZ]); + if (historyY.length > avgSize / 2) { + const avgY = E.sum(historyY) / historyY.length; + historyAvgY.push([t, avgY]); + } } - let mY; - let mZ; - // slope for Y - let l = historyAvgY.length; - if (l > 1) { - const p1 = historyAvgY[l - 2]; - const p2 = historyAvgY[l - 1]; - mY = (p2[1] - p1[1]) / (p2[0] / 1000 - p1[0] / 1000); - if (Math.abs(mY) >= thresholdY) { - historyAvgY.shift(); - historySlopeY.push([t, mY]); - //console.log(t, Math.abs(mY)); + if (exerciseType.useYaxe) { + while (historyZ.length > avgSize) + historyZ.shift(); - const lMY = historySlopeY.length; - if (lMY > 1) { - const pMY1 = historySlopeY[lMY - 2][1]; - const pMY2 = historySlopeY[lMY - 1][1]; - isValidPushUp(pMY1, pMY2, t); + historyZ.push(z); + + if (historyZ.length > avgSize / 2) { + const avgZ = E.sum(historyZ) / historyZ.length; + historyAvgZ.push([t, avgZ]); + } + } + + // slope for Y + if (exerciseType.useYaxe) { + let l = historyAvgY.length; + if (l > 1) { + const p1 = historyAvgY[l - 2]; + const p2 = historyAvgY[l - 1]; + const mY = (p2[1] - p1[1]) / (p2[0] / 1000 - p1[0] / 1000); + if (Math.abs(mY) >= pushUpThresholdY) { + historyAvgY.shift(); + historySlopeY.push([t, mY]); + //console.log(t, Math.abs(mY)); + + const lMY = historySlopeY.length; + if (lMY > 1) { + const pMY1 = historySlopeY[lMY - 2][1]; + const pMY2 = historySlopeY[lMY - 1][1]; + isValidPushUp(pMY1, pMY2, t); + } } } } // slope for Z - l = historyAvgZ.length; - if (l > 1) { - const p1 = historyAvgZ[l - 2]; - const p2 = historyAvgZ[l - 1]; - mZ = (p2[1] - p1[1]) / (p2[0] - p1[0]); - historyAvgZ.shift(); - historySlopeZ.push([p2[0] - p1[0], mZ]); + if (exerciseType.useZaxe) { + l = historyAvgZ.length; + if (l > 1) { + const p1 = historyAvgZ[l - 2]; + const p2 = historyAvgZ[l - 1]; + const mZ = (p2[1] - p1[1]) / (p2[0] - p1[0]); + historyAvgZ.shift(); + historySlopeZ.push([p2[0] - p1[0], mZ]); + } } } @@ -123,8 +136,8 @@ function isValidPushUp(p1, p2, t) { if (lastZeroPassType == "-+") { console.log(t, "Push up half complete..."); - layout.progress.label = "..."; - layout.render(layout.progress); + layout.progress.label = "*"; + layout.render(); } lastZeroPassType = "+-"; @@ -134,20 +147,19 @@ function isValidPushUp(p1, p2, t) { if (lastZeroPassType == "+-") { // potential complete push up. Let's check the time difference... - const tDiffLastPushUp = t - lastPushUpCmpltTime; + const tDiffLastPushUp = t - lastExerciseCmpltTime; const tDiffStart = t - tStart; console.log(t, "Push up maybe complete?", Math.round(tDiffLastPushUp), Math.round(tDiffStart)); - if ((lastPushUpCmpltTime <= 0 && tDiffStart >= thresholdPushUpTime) || tDiffLastPushUp >= thresholdPushUpTime) { + if ((lastExerciseCmpltTime <= 0 && tDiffStart >= pushUpThresholdTime) || tDiffLastPushUp >= pushUpThresholdTime) { console.log(t, "Push up complete!!!"); - lastPushUpCmpltTime = t; - pushUpCounter++; + lastExerciseCmpltTime = t; + exerciseCounter++; - layout.count.label = pushUpCounter; - layout.render(layout.count); + layout.count.label = exerciseCounter; layout.progress.label = ""; - layout.render(layout.progress); + layout.render(); Bangle.buzz(100, 0.3); // TODO make configurable } else { @@ -160,19 +172,6 @@ function isValidPushUp(p1, p2, t) { } } -/* - -function calcPushUps() { - const l = historySlopeY.length; - for (let i = 1; i < l; i++) { - const p1 = historySlopeY[i - 1][1]; - const p2 = historySlopeY[i][1]; - const t = historySlopeY[i][0]; - isValidPushUp(p1, p2, t); - } -} -*/ - function reset() { historyY = []; historyZ = []; @@ -183,8 +182,9 @@ function reset() { lastZeroPassType = ""; lastZeroPassTime = 0; - lastPushUpCmpltTime = 0; - pushUpCounter = 0; + lastExerciseCmpltTime = 0; + exerciseCounter = 0; + tStart = 0; } @@ -192,29 +192,54 @@ function startRecording() { if (recordActive) return; g.clear(1); reset(); + Bangle.setHRMPower(1, "banglexercise"); + if (!hrtValue) hrtValue = "..."; + layout = new Layout({ type: "v", c: [{ type: "txt", id: "type", font: "6x8:2", - label: exerciseType, + label: exerciseType.name, pad: 5 }, { - type: "txt", - id: "count", - font: "6x8:9", - label: pushUpCounter, - pad: 5, - bgCol: g.theme.bg + type: "h", + c: [{ + type: "txt", + id: "count", + font: "6x8:10", + label: exerciseCounter, + pad: 5, + bgCol: g.theme.bg + }, + { + type: "txt", + id: "progress", + font: "6x8:2", + label: "", + pad: 5 + }, + ] }, { - type: "txt", - id: "progress", - font: "6x8:2", - label: "", - pad: 5 + type: "h", + c: [{ + type: "img", + pad: 4, + src: function() { + return heatshrink.decompress(atob("h0OwYOLkmQhMkgACByVJgESpIFBpEEBAIFBCgIFCCgsABwcAgQOCAAMSpAwDyBNM")); + } + }, + { + type: "txt", + id: "hrtRate", + font: "6x8:2", + label: hrtValue, + pad: 5 + }, + ] }, { type: "txt", @@ -234,7 +259,8 @@ function startRecording() { stopRecording(); } } - ] + ], + lazy: true }); layout.render(); @@ -248,12 +274,17 @@ function startRecording() { function stopRecording() { if (!recordActive) return; g.clear(1); + + Bangle.setHRMPower(0, "banglexercise"); + Bangle.removeListener('accel', accelHandler); - showMenu(); - console.log("Found " + pushUpCounter + " push ups!"); + showMainMenu(); recordActive = false; } +Bangle.on('HRM', function(hrm) { + hrtValue = hrm.bpm; +}); + g.clear(1); -Bangle.drawWidgets(); -showMenu(); +showMainMenu(); From 0f2a58dddefe92c6377ebb35d433800036eb54e5 Mon Sep 17 00:00:00 2001 From: Jon Warrington Date: Mon, 10 Jan 2022 11:31:37 -0700 Subject: [PATCH 346/489] Adding current weather to lcars --- apps/lcars/lcars.app.js | 9 +++++++++ apps/lcars/lcars.settings.js | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 167adad2d..4e1073723 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -1,5 +1,6 @@ const SETTINGS_FILE = "lcars.setting.json"; const Storage = require("Storage"); +const weather = require('weather'); // ...and overwrite them with any saved values @@ -145,6 +146,14 @@ function printData(key, y, c){ text = "VREF"; value = E.getAnalogVRef().toFixed(2) + "V"; + } else if (key == "Weather"){ + text = "TEMP"; + const w = weather.get(); + if (!w) { + value = "ERR"; + } else { + value = require('locale').temp(w.temp-273.15); // applies conversion + } } g.setColor(c); diff --git a/apps/lcars/lcars.settings.js b/apps/lcars/lcars.settings.js index 0d004b002..b1fceb518 100644 --- a/apps/lcars/lcars.settings.js +++ b/apps/lcars/lcars.settings.js @@ -18,7 +18,7 @@ storage.write(SETTINGS_FILE, settings) } - var data_options = ["Battery", "Steps", "Temp.", "HRM", "VREF"]; + var data_options = ["Battery", "Steps", "Temp.", "HRM", "VREF", "Weather"]; E.showMenu({ '': { 'title': 'LCARS Clock' }, From 05215fab73314fca30696445cfe986b06b3c0d43 Mon Sep 17 00:00:00 2001 From: Jon Warrington Date: Mon, 10 Jan 2022 11:38:26 -0700 Subject: [PATCH 347/489] Updating version info for lcars --- apps.json | 2 +- apps/lcars/ChangeLog | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 389603249..8f1783f10 100644 --- a/apps.json +++ b/apps.json @@ -4498,7 +4498,7 @@ "name": "LCARS Clock", "shortName":"LCARS", "icon": "lcars.png", - "version":"0.09", + "version":"0.10", "readme": "README.md", "supports": ["BANGLEJS2"], "description": "Library Computer Access Retrieval System (LCARS) clock.", diff --git a/apps/lcars/ChangeLog b/apps/lcars/ChangeLog index f5d8346da..8a8970124 100644 --- a/apps/lcars/ChangeLog +++ b/apps/lcars/ChangeLog @@ -6,4 +6,5 @@ 0.06: Fix - Alarm disabled, if clock was closed. 0.07: Added settings to adjust data that is shown for each row. 0.08: Support for multiple screens. 24h graph for steps + HRM. Fullscreen Mode. -0.09: Tab anywhere to open the launcher. \ No newline at end of file +0.09: Tab anywhere to open the launcher. +0.10: Added getting the gadgetbridge weather \ No newline at end of file From 78dc343afafa8abfaf5fcc391353473028d015c8 Mon Sep 17 00:00:00 2001 From: Jon Warrington Date: Mon, 10 Jan 2022 11:48:57 -0700 Subject: [PATCH 348/489] Fixing a problem with the lcars settings --- apps/lcars/lcars.settings.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/lcars/lcars.settings.js b/apps/lcars/lcars.settings.js index b1fceb518..a0e54f9b4 100644 --- a/apps/lcars/lcars.settings.js +++ b/apps/lcars/lcars.settings.js @@ -25,7 +25,7 @@ '< Back': back, 'Row 1': { value: 0 | data_options.indexOf(settings.dataRow1), - min: 0, max: 4, + min: 0, max: 5, format: v => data_options[v], onchange: v => { settings.dataRow1 = data_options[v]; @@ -34,7 +34,7 @@ }, 'Row 2': { value: 0 | data_options.indexOf(settings.dataRow2), - min: 0, max: 4, + min: 0, max: 5, format: v => data_options[v], onchange: v => { settings.dataRow2 = data_options[v]; @@ -43,7 +43,7 @@ }, 'Row 3': { value: 0 | data_options.indexOf(settings.dataRow3), - min: 0, max: 4, + min: 0, max: 5, format: v => data_options[v], onchange: v => { settings.dataRow3 = data_options[v]; From 791f88b0613b1776793ee478f11f6aad22a03b70 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Mon, 10 Jan 2022 20:27:40 +0100 Subject: [PATCH 349/489] New widget: Heart rate alarm --- apps.json | 16 +++++++++++ apps/hralarm/ChangeLog | 1 + apps/hralarm/README.md | 15 +++++++++++ apps/hralarm/settings.js | 57 +++++++++++++++++++++++++++++++++++++++ apps/hralarm/widget.js | 27 +++++++++++++++++++ apps/hralarm/widget.png | Bin 0 -> 12944 bytes 6 files changed, 116 insertions(+) create mode 100644 apps/hralarm/ChangeLog create mode 100644 apps/hralarm/README.md create mode 100644 apps/hralarm/settings.js create mode 100644 apps/hralarm/widget.js create mode 100644 apps/hralarm/widget.png diff --git a/apps.json b/apps.json index 389603249..08d6113d4 100644 --- a/apps.json +++ b/apps.json @@ -1351,6 +1351,22 @@ {"name":"pparrot.img","url":"party-parrot-icon.js","evaluate":true} ] }, + { + "id": "hralarm", + "name": "Heart rate alarm", + "shortName":"HR Alarm", + "version":"0.01", + "description": "This invisible widget vibrates whenever the heart rate gets close to the upper limit or goes over or under the configured limits", + "icon": "widget.png", + "type": "widget", + "tags": "widget", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"hralarm.wid.js","url":"widget.js"}, + {"name":"hralarm.settings.js","url":"settings.js"} + ] + }, { "id": "hrings", "name": "Hypno Rings", diff --git a/apps/hralarm/ChangeLog b/apps/hralarm/ChangeLog new file mode 100644 index 000000000..4c21f3ace --- /dev/null +++ b/apps/hralarm/ChangeLog @@ -0,0 +1 @@ +0.01: New Widget! diff --git a/apps/hralarm/README.md b/apps/hralarm/README.md new file mode 100644 index 000000000..37b14ad9d --- /dev/null +++ b/apps/hralarm/README.md @@ -0,0 +1,15 @@ +# Heart rate alarm + +This invisible widget vibrates whenever the heart rate gets close to the upper limit or goes over or under the configured limits. + +## Usage + +Configure the heart rate limits in the apps settings. This widget uses both 'HRM' and 'BTHRM' events. + +## Features + +Long vibration every 10 seconds on reaching upper limit, short vibrations between upper limit and warning threshold and an single vibration when reaching the lower limit again. + +## Requests/Creator + +https://github.com/halemmerich diff --git a/apps/hralarm/settings.js b/apps/hralarm/settings.js new file mode 100644 index 000000000..3158ab8b7 --- /dev/null +++ b/apps/hralarm/settings.js @@ -0,0 +1,57 @@ +(function(back) { + var FILE = "hralarm.json"; + + var settings = Object.assign({ + enabled: false, + upper: 180, + warning: 170, + lower: 150, + }, require('Storage').readJSON(FILE, true) || {}); + + function writeSettings() { + require('Storage').writeJSON(FILE, settings); + } + + E.showMenu({ + '': { 'title': 'HR Alarm' }, + '< Back': back, + 'Enabled': { + value: !!settings.enabled, + format: v => settings.enabled ? "On" : "Off", + onchange: v => { + settings.enabled = v; + writeSettings(); + } + }, + 'Upper limit': { + value: settings.upper, + min: 0, + step:5, + max: 300, + onchange: v => { + settings.upper = v; + writeSettings(); + } + }, + 'Lower limit': { + value: settings.lower, + min: 0, + step:5, + max: 300, + onchange: v => { + settings.lower = v; + writeSettings(); + } + }, + 'Warning at': { + value: settings.warning, + min: 0, + step:5, + max: 300, + onchange: v => { + settings.warning = v; + writeSettings(); + } + } + }); +}) diff --git a/apps/hralarm/widget.js b/apps/hralarm/widget.js new file mode 100644 index 000000000..30a94fdf2 --- /dev/null +++ b/apps/hralarm/widget.js @@ -0,0 +1,27 @@ +(() => { + var settings = require('Storage').readJSON("hralarm.json", true) || {}; + if (!settings.enabled){ Bangle.setHRMPower(0, 'hralarm'); return; } + Bangle.setHRMPower(1, 'hralarm'); + var hitLimit = 0; + var checkHr = function(hr){ + if (hr.bpm > settings.warning && hr.bpm <= settings.upper){ + Bangle.buzz(100, 1); + } + if (hitLimit < getTime() && hr.bpm > settings.upper){ + hitLimit = getTime() + 10; + Bangle.buzz(2000, 1); + } + if (hitLimit > 0 && hr.bpm < settings.lower){ + hitLimit = 0; + Bangle.buzz(500, 1); + } + }; + Bangle.on("HRM", checkHr); + Bangle.on("BTHRM", checkHr); + + WIDGETS["hralarm"]={ + area:"tl", + width: 0, + draw: function(){} + }; +})() diff --git a/apps/hralarm/widget.png b/apps/hralarm/widget.png new file mode 100644 index 0000000000000000000000000000000000000000..726cf3f9bb528f4a8aecd0fba7e4862f4cc4ec2d GIT binary patch literal 12944 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 Date: Mon, 10 Jan 2022 13:47:50 -0700 Subject: [PATCH 350/489] Incrementing the version number --- apps.json | 2 +- apps/lcars/ChangeLog | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 8f1783f10..658adaaa8 100644 --- a/apps.json +++ b/apps.json @@ -4498,7 +4498,7 @@ "name": "LCARS Clock", "shortName":"LCARS", "icon": "lcars.png", - "version":"0.10", + "version":"0.11", "readme": "README.md", "supports": ["BANGLEJS2"], "description": "Library Computer Access Retrieval System (LCARS) clock.", diff --git a/apps/lcars/ChangeLog b/apps/lcars/ChangeLog index 8a8970124..ad5330b26 100644 --- a/apps/lcars/ChangeLog +++ b/apps/lcars/ChangeLog @@ -7,4 +7,4 @@ 0.07: Added settings to adjust data that is shown for each row. 0.08: Support for multiple screens. 24h graph for steps + HRM. Fullscreen Mode. 0.09: Tab anywhere to open the launcher. -0.10: Added getting the gadgetbridge weather \ No newline at end of file +0.11: Added getting the gadgetbridge weather \ No newline at end of file From 53f787fff740d10efb6c10efed3b828fbf7130e8 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Mon, 10 Jan 2022 22:02:29 +0100 Subject: [PATCH 351/489] Lap Counter - Use themeable icon --- apps.json | 2 +- apps/lapcounter/ChangeLog | 1 + apps/lapcounter/app-icon.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 389603249..af3bb44d8 100644 --- a/apps.json +++ b/apps.json @@ -5046,7 +5046,7 @@ { "id": "lapcounter", "name": "Lap Counter", - "version": "0.01", + "version": "0.02", "description": "Click button to count laps. Shows count and total time snapshot (like a stopwatch, but laid back).", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}], diff --git a/apps/lapcounter/ChangeLog b/apps/lapcounter/ChangeLog index 9db0e26c5..146ff1b05 100644 --- a/apps/lapcounter/ChangeLog +++ b/apps/lapcounter/ChangeLog @@ -1 +1,2 @@ 0.01: first release +0.02: Themeable app icon diff --git a/apps/lapcounter/app-icon.js b/apps/lapcounter/app-icon.js index a443b3a41..354c07124 100644 --- a/apps/lapcounter/app-icon.js +++ b/apps/lapcounter/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwwkBiIA/AH4A/AAkQgEBAREAC6oABdZQXkI6wuKC5iPUFxoXIOpoX/C6QFCC6IsCC6ZEDC/4XcPooXOFgoXQIgwX/C7IUFC5wsIC5ouCC6hcJC5h1DF9YwBChCPOAH4A/AH4Ap")) +require("heatshrink").decompress(atob("mEwwI0xg+evPsAon+ApX8Aon4AonwAod78AFDv4FWvoFE/IFDz4FXvIFD3wFE/wFW7wFDh5xBAoUfAok/Aol/BZUXAogA6A=")) From 52647e7a8a9650e7e22389aedc3cfae80a92ecc0 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Tue, 11 Jan 2022 00:08:06 +0100 Subject: [PATCH 352/489] fixed typo in readme.md --- apps/antonclk/README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/antonclk/README.md b/apps/antonclk/README.md index fa4cc4919..c2c8b917e 100644 --- a/apps/antonclk/README.md +++ b/apps/antonclk/README.md @@ -40,7 +40,10 @@ The main menu contains several settings covering Anton clock in general. * **Show Weekday** - Weekday is shown in the time presentation without seconds. Weekday name depends on the current locale. If seconds are shown, the weekday is never shown as there is not enough space on the watch face. -**Show Weeknumber** - Weeknumber (ISO-8601) is shown. +* **Show Weeknumber** - Week-number (ISO-8601) is shown. (default: Off) +when weekday name "Off" it displays week #: +when weekday name "On": weekday name is cut at 6th position and .# is added +If seconds are shown, the week number is never shown as there is not enough space on the watch face. * **Vector font** - Use the built-in vector font for dates and weekday. This can improve readability. Otherwise, a scaled version of the built-in 6x8 pixels font is used. From 1a21358f2be7fe4f5dcdddb324c14e1f698aa610 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Tue, 11 Jan 2022 00:12:04 +0100 Subject: [PATCH 353/489] Updated readme.md typo / format --- apps/antonclk/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/antonclk/README.md b/apps/antonclk/README.md index c2c8b917e..38a42aa22 100644 --- a/apps/antonclk/README.md +++ b/apps/antonclk/README.md @@ -41,8 +41,8 @@ The main menu contains several settings covering Anton clock in general. Weekday name depends on the current locale. If seconds are shown, the weekday is never shown as there is not enough space on the watch face. * **Show Weeknumber** - Week-number (ISO-8601) is shown. (default: Off) -when weekday name "Off" it displays week #: -when weekday name "On": weekday name is cut at 6th position and .# is added +If "Show Weekday" is "Off" the week-number is displayed as week #:. +If "Show Weekday" is "On" the weekday name is cut at 6th position and .# is added. If seconds are shown, the week number is never shown as there is not enough space on the watch face. * **Vector font** - Use the built-in vector font for dates and weekday. This can improve readability. From 3e458115046ec7182edb00871ca3077f1253728d Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Tue, 11 Jan 2022 00:13:34 +0100 Subject: [PATCH 354/489] Updated readme.md type / format --- apps/antonclk/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/antonclk/README.md b/apps/antonclk/README.md index 38a42aa22..85c03788d 100644 --- a/apps/antonclk/README.md +++ b/apps/antonclk/README.md @@ -41,8 +41,8 @@ The main menu contains several settings covering Anton clock in general. Weekday name depends on the current locale. If seconds are shown, the weekday is never shown as there is not enough space on the watch face. * **Show Weeknumber** - Week-number (ISO-8601) is shown. (default: Off) -If "Show Weekday" is "Off" the week-number is displayed as week #:. -If "Show Weekday" is "On" the weekday name is cut at 6th position and .# is added. +If "Show Weekday" is "Off" the week-number is displayed as "week #:". +If "Show Weekday" is "On" the weekday name is cut at 6th position and suffixed with ".#". If seconds are shown, the week number is never shown as there is not enough space on the watch face. * **Vector font** - Use the built-in vector font for dates and weekday. This can improve readability. From dcc4dc8e66c43eaf7bc0d54128e790572d904ee8 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Tue, 11 Jan 2022 00:16:40 +0100 Subject: [PATCH 355/489] app.js - bugfix: removed codefragement testdata "thursday" added todo for locale "week" --- apps/antonclk/app.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index be6c23789..05758cbfd 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -188,9 +188,8 @@ function draw() { g.drawString(dateStr, x, y); if (weekDay || calWeek) { var dowwumStr = require("locale").dow(date); - dowwumStr = "thursday"; if (calWeek) - dowwumStr = (weekDay ? dowwumStr.substr(0,Math.min(dowwumStr.length,6)) + (dowwumStr.length>=6 ? "." : "") : "week ") + "#" + ISO8601calWeek(date); + dowwumStr = (weekDay ? dowwumStr.substr(0,Math.min(dowwumStr.length,6)) + (dowwumStr.length>=6 ? "." : "") : "week ") + "#" + ISO8601calWeek(date); //TODO: locale for "week" if (upperCase) dowwumStr = dowwumStr.toUpperCase(); g.drawString(dowwumStr, x, y + (vectorFont ? 26 : 16)); From 7905d3cffc5a268635e13baa0b05cbdd97b9ddc1 Mon Sep 17 00:00:00 2001 From: BartS23 <10829389+BartS23@users.noreply.github.com> Date: Mon, 10 Jan 2022 16:11:09 +0100 Subject: [PATCH 356/489] Reduce FIFO_FULL messages 1. the lazy layout rendering takes too much time. 2. enable the gps at the end of the file. 3. save SATinView to detect changes. --- apps/gpsinfo/gps-info.js | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/apps/gpsinfo/gps-info.js b/apps/gpsinfo/gps-info.js index fdac3d403..79acc05fe 100644 --- a/apps/gpsinfo/gps-info.js +++ b/apps/gpsinfo/gps-info.js @@ -4,7 +4,7 @@ function satelliteImage() { var Layout = require("Layout"); var layout; -Bangle.setGPSPower(1, "app"); +//Bangle.setGPSPower(1, "app"); E.showMessage("Loading..."); // avoid showing rubbish on screen var lastFix = { @@ -19,7 +19,7 @@ var lastFix = { var SATinView = 0; var nofBD = 0; var nofGP = 0; -var listenerGPSraw = 1; +var listenerGPSraw = 0; function formatTime(now) { if (now == undefined) { @@ -87,12 +87,12 @@ function onGPS(fix) { {type:"txt", font:"6x8", pad:3, label:"Satellites used" } ]}, {type:"txt", font:"6x8", label:"", fillx:true, id:"progress" } - ]},{lazy:true}); + ]},{lazy:false}); } g.clearRect(0,24,g.getWidth(),g.getHeight()); layout.render(); } - lastFix = fix; + //lastFix = fix; if (fix.fix) { if (listenerGPSraw == 1) { Bangle.removeListener('GPS-raw', onGPSraw); @@ -108,6 +108,7 @@ function onGPS(fix) { layout.time.label = "Time: "+formatTime(fix.time); layout.sat.label = "Satellites: "+satellites; layout.maidenhead.label = "Maidenhead: "+maidenhead; + layout.render(); } else { if (listenerGPSraw == 0) { Bangle.on('GPS-raw', onGPSraw); @@ -116,7 +117,15 @@ function onGPS(fix) { layout.sat.label = fix.satellites; layout.progress.label = "in view: " + SATinView; } - layout.render(); + //layout.render(); + + if (listenerGPSraw == 0 && !fix.fix) { + setTimeout(() => Bangle.on('GPS-raw', onGPSraw), 10); + listenerGPSraw = 1; + } + + lastFix = fix; + lastFix.SATinView = SATinView; } function onGPSraw(nmea) { @@ -129,7 +138,8 @@ function onGPSraw(nmea) { Bangle.loadWidgets(); Bangle.drawWidgets(); Bangle.on('GPS', onGPS); -Bangle.on('GPS-raw', onGPSraw); +//Bangle.on('GPS-raw', onGPSraw); +Bangle.setGPSPower(1, "app"); function exitApp() { load(); From 8053de33079cc96be65ed2bb1f82557dc1dc0006 Mon Sep 17 00:00:00 2001 From: BartS23 <10829389+BartS23@users.noreply.github.com> Date: Mon, 10 Jan 2022 20:37:22 +0100 Subject: [PATCH 357/489] Fix layout and double enabling of event GPS-raw --- apps/gpsinfo/gps-info.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/gpsinfo/gps-info.js b/apps/gpsinfo/gps-info.js index 79acc05fe..f4521f265 100644 --- a/apps/gpsinfo/gps-info.js +++ b/apps/gpsinfo/gps-info.js @@ -110,12 +110,16 @@ function onGPS(fix) { layout.maidenhead.label = "Maidenhead: "+maidenhead; layout.render(); } else { - if (listenerGPSraw == 0) { - Bangle.on('GPS-raw', onGPSraw); - listenerGPSraw = 1; + if (fix.satelites != lastFix.satelites) { + layout.clear(layout.sat); + layout.sat.label = fix.satellites; + layout.render(layout.sat); + } + if (SATinView != lastFix.SATinView) { + layout.clear(layout.progress); + layout.progress.label = "in view: " + SATinView; + layout.render(layout.progress); } - layout.sat.label = fix.satellites; - layout.progress.label = "in view: " + SATinView; } //layout.render(); From 0c0d7e9dd17ee2565aebe20682a82af66944bc94 Mon Sep 17 00:00:00 2001 From: Romek Date: Tue, 11 Jan 2022 11:10:54 +0100 Subject: [PATCH 358/489] Update changelog and version --- apps.json | 2 +- apps/gpsinfo/ChangeLog | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 02076497e..57934dff3 100644 --- a/apps.json +++ b/apps.json @@ -1520,7 +1520,7 @@ { "id": "gpsinfo", "name": "GPS Info", - "version": "0.08", + "version": "0.09", "description": "An application that displays information about altitude, lat/lon, satellites and time", "icon": "gps-info.png", "type": "app", diff --git a/apps/gpsinfo/ChangeLog b/apps/gpsinfo/ChangeLog index 8d428ce85..414b9d9fb 100644 --- a/apps/gpsinfo/ChangeLog +++ b/apps/gpsinfo/ChangeLog @@ -5,3 +5,4 @@ 0.06: Add number of satellites in view and fix crash with GPS time 0.07: Resolve one FIFO_FULL case and exit App with button press 0.08: Leave GPS power switched on on exit (will switch off after 0.5 seconds anyway) +0.09: Fix FIFO_FULL error From c9fa1b8f65db32d3dae0063630228332f0679c3f Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Tue, 11 Jan 2022 11:44:07 +0100 Subject: [PATCH 359/489] Update screenshot --- apps/banglexercise/screenshot.png | Bin 2043 -> 2181 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/banglexercise/screenshot.png b/apps/banglexercise/screenshot.png index 9a325d87378dd297bab31da0521462e06d5c1ab9..417be685b08802657be55b02498c4c292128b70d 100644 GIT binary patch literal 2181 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 From d59db5ba381941c14abc0676c2fb174063a2e2d9 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Tue, 11 Jan 2022 11:48:10 +0100 Subject: [PATCH 360/489] Show correct percentage values in circles --- apps.json | 2 +- apps/circlesclock/ChangeLog | 1 + apps/circlesclock/app.js | 13 ++++++------- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps.json b/apps.json index 02076497e..8d1e481a1 100644 --- a/apps.json +++ b/apps.json @@ -5097,7 +5097,7 @@ { "id": "circlesclock", "name": "Circles clock", "shortName":"Circles clock", - "version":"0.04", + "version":"0.05", "description": "A clock with circles for different data at the bottom in a probably familiar style", "icon": "app.png", "screenshots": [{"url":"screenshot-dark.png"}, {"url":"screenshot-light.png"}], diff --git a/apps/circlesclock/ChangeLog b/apps/circlesclock/ChangeLog index ca1da6e21..86b77bb6f 100644 --- a/apps/circlesclock/ChangeLog +++ b/apps/circlesclock/ChangeLog @@ -5,3 +5,4 @@ Add step distance and weather Allow switching visibility of widgets Make circles and text slightly bigger +0.05: Show correct percentage values in circles diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 91d4937c4..de7bc73f9 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -363,22 +363,21 @@ function radians(a) { } function drawGauge(cx, cy, percent, color) { - let offset = 30; - let end = 300; - var i = 0; - var r = radiusInner + 3; + const offset = 15; + const end = 345; + const r = radiusInner + 3; if (percent <= 0) return; if (percent > 1) percent = 1; - var startrot = -offset; - var endrot = startrot - ((end - offset) * percent) - 35; + const startrot = -offset; + const endrot = startrot - ((end - offset) * percent); g.setColor(color); const size = radiusOuter - radiusInner - 2; // draw gauge - for (i = startrot; i > endrot - size; i -= size) { + for (let i = startrot; i > endrot - size; i -= size) { x = cx + r * Math.sin(radians(i)); y = cy + r * Math.cos(radians(i)); g.fillCircle(x, y, size); From 83aa32ee840a6aec7fcaf0995de8f3a1278e4a89 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Tue, 11 Jan 2022 12:38:19 +0100 Subject: [PATCH 361/489] Moved exercise threshold values to the exercise type configuration & initial support for curls --- apps/banglexercise/README.md | 9 ++- apps/banglexercise/app.js | 148 +++++++++++++++++++++-------------- 2 files changed, 98 insertions(+), 59 deletions(-) diff --git a/apps/banglexercise/README.md b/apps/banglexercise/README.md index efc87424d..9d8ee7be4 100644 --- a/apps/banglexercise/README.md +++ b/apps/banglexercise/README.md @@ -2,7 +2,13 @@ Can automatically track exercises while wearing the Bangle.js watch. -Currently only push ups are supported. +Currently only push ups and curls are supported. + +## Disclaimer + +This app is very experimental. +It could be and is likely that the threshold values for detecting exercises do not work for everyone. +Therefore it would be great if we could improve this app together :-) ## Usage @@ -17,7 +23,6 @@ Press stop to end your exercise. ## TODO * Add other exercise types: * Rope jumps - * Curls * Sit ups * ... * Save exercises to file system diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js index e18faf554..3f710cf1e 100644 --- a/apps/banglexercise/app.js +++ b/apps/banglexercise/app.js @@ -15,26 +15,35 @@ let lastZeroPassTime = 0; let lastExerciseCmpltTime = 0; let exerciseType = { + "id": "", "name": "" }; + +// add new exercises here: const exerciseTypes = [{ "id": "pushup", "name": "Push ups", "useYaxe": true, - "useZaxe": false - } // add other exercises here + "useZaxe": false, + "thresholdY": 2500, + "thresholdTime": 1400 // mininmal time between two push ups + }, + { + "id": "curl", + "name": "Curls", + "useYaxe": true, + "useZaxe": false, + "thresholdY": 2500, + "thresholdTime": 1000 // mininmal time between two curls + } ]; let exerciseCounter = 0; let layout; let recordActive = false; -/** - * Thresholds - */ +// Size of average window for data analysis const avgSize = 6; -const pushUpThresholdY = 2500; -const pushUpThresholdTime = 1400; // mininmal time between two push ups let hrtValue; @@ -55,7 +64,9 @@ function showMainMenu() { }); if (exerciseCounter > 0) { - menu["----"] = {}; + menu["----"] = { + value: "" + }; menu["Last:"] = { value: exerciseCounter + " " + exerciseType.name }; @@ -101,19 +112,18 @@ function accelHandler(accel) { if (l > 1) { const p1 = historyAvgY[l - 2]; const p2 = historyAvgY[l - 1]; - const mY = (p2[1] - p1[1]) / (p2[0] / 1000 - p1[0] / 1000); - if (Math.abs(mY) >= pushUpThresholdY) { - historyAvgY.shift(); - historySlopeY.push([t, mY]); - //console.log(t, Math.abs(mY)); + const slopeY = (p2[1] - p1[1]) / (p2[0] / 1000 - p1[0] / 1000); - const lMY = historySlopeY.length; - if (lMY > 1) { - const pMY1 = historySlopeY[lMY - 2][1]; - const pMY2 = historySlopeY[lMY - 1][1]; - isValidPushUp(pMY1, pMY2, t); - } + // we use this data for exercises which can be detected by using Y axis data + switch (exerciseType.id) { + case "pushup": + isValidYAxisExercise(slopeY, t); + break; + case "curl": + isValidYAxisExercise(slopeY, t); + break; } + } } @@ -123,55 +133,81 @@ function accelHandler(accel) { if (l > 1) { const p1 = historyAvgZ[l - 2]; const p2 = historyAvgZ[l - 1]; - const mZ = (p2[1] - p1[1]) / (p2[0] - p1[0]); + const slopeZ = (p2[1] - p1[1]) / (p2[0] - p1[0]); historyAvgZ.shift(); - historySlopeZ.push([p2[0] - p1[0], mZ]); + historySlopeZ.push([p2[0] - p1[0], slopeZ]); + + // TODO: we can use this data for some exercises which can be detected by using Z axis data } } } -function isValidPushUp(p1, p2, t) { - if (p1 > 0 && p2 < 0) { +/* + * Check if slope value of Y-axis data looks like an exercise + * + * In detail we look for slop values which are bigger than the configured Y threshold for the current exercise + * Then we look for two consecutive slope values of which one is above 0 and the other is below zero. + * If we find one pair of these values this could be part of one exercise. + * Then we look for a pair of values which cross the zero from the otherwise direction + */ +function isValidYAxisExercise(slopeY, t) { + if (!exerciseType) return; - if (lastZeroPassType == "-+") { - console.log(t, "Push up half complete..."); + const thresholdY = exerciseType.thresholdY; + const thresholdTime = exerciseType.thresholdTime; + const exerciseName = exerciseType.name; - layout.progress.label = "*"; - layout.render(); - } + if (Math.abs(slopeY) >= thresholdY) { + historyAvgY.shift(); + historySlopeY.push([t, slopeY]); + //console.log(t, Math.abs(slopeY)); - lastZeroPassType = "+-"; - lastZeroPassTime = t; - } - if (p2 > 0 && p1 < 0) { + const lSlopeY = historySlopeY.length; + if (lSlopeY > 1) { + const p1 = historySlopeY[lSlopeY - 2][1]; + const p2 = historySlopeY[lSlopeY - 1][1]; + if (p1 > 0 && p2 < 0) { + if (lastZeroPassType == "-+") { + console.log(t, exerciseName + " half complete..."); - if (lastZeroPassType == "+-") { - // potential complete push up. Let's check the time difference... - const tDiffLastPushUp = t - lastExerciseCmpltTime; - const tDiffStart = t - tStart; - console.log(t, "Push up maybe complete?", Math.round(tDiffLastPushUp), Math.round(tDiffStart)); + layout.progress.label = "*"; + layout.render(); + } - if ((lastExerciseCmpltTime <= 0 && tDiffStart >= pushUpThresholdTime) || tDiffLastPushUp >= pushUpThresholdTime) { - console.log(t, "Push up complete!!!"); + lastZeroPassType = "+-"; + lastZeroPassTime = t; + } + if (p2 > 0 && p1 < 0) { + if (lastZeroPassType == "+-") { + // potential complete exercise. Let's check the time difference... + const tDiffLastPushUp = t - lastExerciseCmpltTime; + const tDiffStart = t - tStart; + console.log(t, exerciseName + " maybe complete?", Math.round(tDiffLastPushUp), Math.round(tDiffStart)); - lastExerciseCmpltTime = t; - exerciseCounter++; + if ((lastExerciseCmpltTime <= 0 && tDiffStart >= thresholdTime) || tDiffLastPushUp >= thresholdTime) { + console.log(t, exerciseName + " complete!!!"); - layout.count.label = exerciseCounter; - layout.progress.label = ""; - layout.render(); + lastExerciseCmpltTime = t; + exerciseCounter++; - Bangle.buzz(100, 0.3); // TODO make configurable - } else { - console.log(t, "Push up to quick for threshold!"); + layout.count.label = exerciseCounter; + layout.progress.label = ""; + layout.render(); + + Bangle.buzz(100, 0.4); // TODO make configurable + } else { + console.log(t, exerciseName + " to quick for time threshold!"); + } + } + + lastZeroPassType = "-+"; + lastZeroPassTime = t; } } - - lastZeroPassType = "-+"; - lastZeroPassTime = t; } } + function reset() { historyY = []; historyZ = []; @@ -252,14 +288,12 @@ function startRecording() { }, ] }, { - btns: [ - { - label: "STOP", - cb: () => { - stopRecording(); - } + btns: [{ + label: "STOP", + cb: () => { + stopRecording(); } - ], + }], lazy: true }); layout.render(); From d12a415740bd5236d9d475551a9fac69e2bee62a Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Tue, 11 Jan 2022 13:52:19 +0100 Subject: [PATCH 362/489] Show humidity as weather circle data --- apps/circlesclock/README.md | 3 +++ apps/circlesclock/app.js | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/apps/circlesclock/README.md b/apps/circlesclock/README.md index 9aaa4bc8e..c3704e3d7 100644 --- a/apps/circlesclock/README.md +++ b/apps/circlesclock/README.md @@ -10,6 +10,9 @@ It can show the following information (this can be configured): * Heart rate (automatically updates when screen is on and unlocked) * Battery (including charging status and battery low warning) * Weather (requires [weather app](https://banglejs.com/apps/#weather)) + * Humidity as circle progress + * Temperature inside circle + * Condition as icon below circle ## Screenshots ![Screenshot dark theme](screenshot-dark.png) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index de7bc73f9..822802afa 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -283,6 +283,7 @@ function drawWeather(w) { if (!w) w = getCirclePosition("weather"); const weather = getWeather(); const tempString = weather ? locale.temp(weather.temp - 273.15) : undefined; + const humidity = weather ? weather.hum : undefined; const code = weather ? weather.code : -1; // Draw rectangle background: @@ -292,6 +293,10 @@ function drawWeather(w) { g.setColor(colorGrey); g.fillCircle(w, h3, radiusOuter); + if (humidity >= 0) { + drawGauge(w, h3, humidity / 100, colorYellow); + } + g.setColor(colorBg); g.fillCircle(w, h3, radiusInner); From a29dbeedd3cf3b0084999fca59244d739bb0ee4b Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Tue, 11 Jan 2022 14:08:48 +0100 Subject: [PATCH 363/489] Update changelog --- apps/circlesclock/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/circlesclock/ChangeLog b/apps/circlesclock/ChangeLog index 86b77bb6f..5464a8103 100644 --- a/apps/circlesclock/ChangeLog +++ b/apps/circlesclock/ChangeLog @@ -6,3 +6,4 @@ Allow switching visibility of widgets Make circles and text slightly bigger 0.05: Show correct percentage values in circles + Show humidity as weather circle data From a3ada12a928931646e078a083bc394012f3c646e Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Tue, 11 Jan 2022 16:04:54 +0100 Subject: [PATCH 364/489] Add settings for buzz; more timeouts to better detect activities; reduce memory usage --- apps.json | 6 ++- apps/banglexercise/app.js | 99 ++++++++++++++++++++++------------ apps/banglexercise/settings.js | 21 ++++++++ 3 files changed, 92 insertions(+), 34 deletions(-) create mode 100644 apps/banglexercise/settings.js diff --git a/apps.json b/apps.json index 0adb4abc5..230a37b67 100644 --- a/apps.json +++ b/apps.json @@ -5518,7 +5518,11 @@ "readme": "README.md", "storage": [ {"name":"banglexercise.app.js","url":"app.js"}, - {"name":"banglexercise.img","url":"app-icon.js","evaluate":true} + {"name":"banglexercise.img","url":"app-icon.js","evaluate":true}, + {"name":"banglexercise.settings.js","url":"settings.js"} + ], + "data": [ + {"name":"banglexercise.json"} ] } ] diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js index 3f710cf1e..ac4153239 100644 --- a/apps/banglexercise/app.js +++ b/apps/banglexercise/app.js @@ -9,10 +9,11 @@ let historyAvgZ = []; let historySlopeY = []; let historySlopeZ = []; -let lastZeroPassType; +let lastZeroPassCameFromPositive; let lastZeroPassTime = 0; -let lastExerciseCmpltTime = 0; +let lastExerciseCompletionTime = 0; +let lastExerciseHalfCompletionTime = 0; let exerciseType = { "id": "", @@ -22,19 +23,23 @@ let exerciseType = { // add new exercises here: const exerciseTypes = [{ "id": "pushup", - "name": "Push ups", + "name": "push ups", "useYaxe": true, "useZaxe": false, "thresholdY": 2500, - "thresholdTime": 1400 // mininmal time between two push ups + "thresholdMinTime": 1400, // mininmal time between two push ups in ms + "thresholdMaxTime": 5000, // maximal time between two push ups in ms + "thresholdMinDurationTime": 700, // mininmal duration of half a push ups in ms }, { "id": "curl", - "name": "Curls", + "name": "curls", "useYaxe": true, "useZaxe": false, "thresholdY": 2500, - "thresholdTime": 1000 // mininmal time between two curls + "thresholdMinTime": 1000, // mininmal time between two curls in ms + "thresholdMaxTime": 5000, // maximal time between two curls in ms + "thresholdMinDurationTime": 500, // mininmal duration of half a push ups in ms } ]; let exerciseCounter = 0; @@ -47,6 +52,10 @@ const avgSize = 6; let hrtValue; +let settings = storage.readJSON("banglexercise.json", 1) || { + 'buzz': true +}; + function showMainMenu() { let menu; menu = { @@ -64,7 +73,7 @@ function showMainMenu() { }); if (exerciseCounter > 0) { - menu["----"] = { + menu["--------"] = { value: "" }; menu["Last:"] = { @@ -91,6 +100,8 @@ function accelHandler(accel) { if (historyY.length > avgSize / 2) { const avgY = E.sum(historyY) / historyY.length; historyAvgY.push([t, avgY]); + while (historyAvgY.length > avgSize) + historyAvgY.shift(); } } @@ -103,6 +114,8 @@ function accelHandler(accel) { if (historyZ.length > avgSize / 2) { const avgZ = E.sum(historyZ) / historyZ.length; historyAvgZ.push([t, avgZ]); + while (historyAvgZ.length > avgSize) + historyAvgZ.shift(); } } @@ -113,7 +126,6 @@ function accelHandler(accel) { const p1 = historyAvgY[l - 2]; const p2 = historyAvgY[l - 1]; const slopeY = (p2[1] - p1[1]) / (p2[0] / 1000 - p1[0] / 1000); - // we use this data for exercises which can be detected by using Y axis data switch (exerciseType.id) { case "pushup": @@ -154,7 +166,9 @@ function isValidYAxisExercise(slopeY, t) { if (!exerciseType) return; const thresholdY = exerciseType.thresholdY; - const thresholdTime = exerciseType.thresholdTime; + const thresholdMinTime = exerciseType.thresholdMinTime; + const thresholdMaxTime = exerciseType.thresholdMaxTime; + const thresholdMinDurationTime = exerciseType.thresholdMinDurationTime; const exerciseName = exerciseType.name; if (Math.abs(slopeY) >= thresholdY) { @@ -164,43 +178,61 @@ function isValidYAxisExercise(slopeY, t) { const lSlopeY = historySlopeY.length; if (lSlopeY > 1) { - const p1 = historySlopeY[lSlopeY - 2][1]; - const p2 = historySlopeY[lSlopeY - 1][1]; + const p1 = historySlopeY[lSlopeY - 1][1]; + const p2 = historySlopeY[lSlopeY - 2][1]; if (p1 > 0 && p2 < 0) { - if (lastZeroPassType == "-+") { + if (lastZeroPassCameFromPositive == false) { + lastExerciseHalfCompletionTime = t; console.log(t, exerciseName + " half complete..."); - layout.progress.label = "*"; + layout.progress.label = "½"; layout.render(); } - lastZeroPassType = "+-"; + lastZeroPassCameFromPositive = true; lastZeroPassTime = t; } if (p2 > 0 && p1 < 0) { - if (lastZeroPassType == "+-") { - // potential complete exercise. Let's check the time difference... - const tDiffLastPushUp = t - lastExerciseCmpltTime; + if (lastZeroPassCameFromPositive == true) { + const tDiffLastExercise = t - lastExerciseCompletionTime; const tDiffStart = t - tStart; - console.log(t, exerciseName + " maybe complete?", Math.round(tDiffLastPushUp), Math.round(tDiffStart)); + console.log(t, exerciseName + " maybe complete?", Math.round(tDiffLastExercise), Math.round(tDiffStart)); - if ((lastExerciseCmpltTime <= 0 && tDiffStart >= thresholdTime) || tDiffLastPushUp >= thresholdTime) { - console.log(t, exerciseName + " complete!!!"); + // check minimal time between exercises: + if ((lastExerciseCompletionTime <= 0 && tDiffStart >= thresholdMinTime) || tDiffLastExercise >= thresholdMinTime) { - lastExerciseCmpltTime = t; - exerciseCounter++; + // check maximal time between exercises: + if (lastExerciseCompletionTime <= 0 || tDiffLastExercise <= thresholdMaxTime) { - layout.count.label = exerciseCounter; - layout.progress.label = ""; - layout.render(); + // check minimal duration of exercise: + const tDiffExerciseHalfCompletion = t - lastExerciseHalfCompletionTime; + if (tDiffExerciseHalfCompletion > thresholdMinDurationTime) { + console.log(t, exerciseName + " complete!!!"); - Bangle.buzz(100, 0.4); // TODO make configurable + lastExerciseCompletionTime = t; + exerciseCounter++; + + layout.count.label = exerciseCounter; + layout.progress.label = ""; + layout.render(); + + if (settings.buzz) + Bangle.buzz(100, 0.4); + } else { + console.log(t, exerciseName + " to quick for duration time threshold!"); + lastExerciseCompletionTime = t; + } + } else { + console.log(t, exerciseName + " to slow for time threshold!"); + lastExerciseCompletionTime = t; + } } else { console.log(t, exerciseName + " to quick for time threshold!"); + lastExerciseCompletionTime = t; } } - lastZeroPassType = "-+"; + lastZeroPassCameFromPositive = false; lastZeroPassTime = t; } } @@ -216,9 +248,10 @@ function reset() { historySlopeY = []; historySlopeZ = []; - lastZeroPassType = ""; + lastZeroPassCameFromPositive = undefined; lastZeroPassTime = 0; - lastExerciseCmpltTime = 0; + lastExerciseHalfCompletionTime = 0; + lastExerciseCompletionTime = 0; exerciseCounter = 0; tStart = 0; } @@ -300,18 +333,18 @@ function startRecording() { Bangle.setPollInterval(80); // 12.5 Hz Bangle.on('accel', accelHandler); - Bangle.buzz(200, 1); tStart = new Date().getTime(); recordActive = true; + if (settings.buzz) + Bangle.buzz(200, 1); } function stopRecording() { if (!recordActive) return; + g.clear(1); - - Bangle.setHRMPower(0, "banglexercise"); - Bangle.removeListener('accel', accelHandler); + Bangle.setHRMPower(0, "banglexercise"); showMainMenu(); recordActive = false; } diff --git a/apps/banglexercise/settings.js b/apps/banglexercise/settings.js new file mode 100644 index 000000000..3208c6eca --- /dev/null +++ b/apps/banglexercise/settings.js @@ -0,0 +1,21 @@ +(function(back) { + const SETTINGS_FILE = "banglexercise.json"; + const storage = require('Storage'); + let settings = storage.readJSON(SETTINGS_FILE, 1) || {}; + function save(key, value) { + settings[key] = value; + storage.write(SETTINGS_FILE, settings); + } + E.showMenu({ + '': { 'title': 'BanglExercise' }, + '< Back': back, + 'Buzz': { + value: "buzz" in settings ? settings.buzz : false, + format: () => (settings.buzz ? 'Yes' : 'No'), + onchange: () => { + settings.buzz = !settings.buzz; + save('buzz', settings.buzz); + } + } + }); +}); From cc5a1f5d5a3756bc99d9b8cb66783a7cc34f0890 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Tue, 11 Jan 2022 16:09:02 +0100 Subject: [PATCH 365/489] Fix missing module requirement --- apps/banglexercise/app.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js index ac4153239..3e53cff61 100644 --- a/apps/banglexercise/app.js +++ b/apps/banglexercise/app.js @@ -1,5 +1,6 @@ const Layout = require("Layout"); const heatshrink = require('heatshrink'); +const storage = require('storage'); let tStart; let historyY = []; From 800624f2d405270deb9f7ed5cab41946d494b41e Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Tue, 11 Jan 2022 16:18:10 +0100 Subject: [PATCH 366/489] Fix missing module requirement --- apps/banglexercise/app.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js index ac4153239..f5a532408 100644 --- a/apps/banglexercise/app.js +++ b/apps/banglexercise/app.js @@ -1,5 +1,6 @@ const Layout = require("Layout"); const heatshrink = require('heatshrink'); +const storage = require('Storage'); let tStart; let historyY = []; From e669138023cfb661bd599308c4b8b21e427c3cc1 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Tue, 11 Jan 2022 16:28:48 +0100 Subject: [PATCH 367/489] Update apps.json --- apps.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/apps.json b/apps.json index c93efd152..a62bb19cf 100644 --- a/apps.json +++ b/apps.json @@ -5538,5 +5538,22 @@ {"name":"limelight.settings.js","url":"limelight.settings.js"}, {"name":"limelight.img","url":"limelight.icon.js","evaluate":true} ] + }, + { "id": "configurable_clock", + "name": "Configurable Analog Clock", + "shortName":"Configurable Clock", + "version":"0.02", + "description": "an analog clock with several kinds of faces, hands and colors to choose from", + "icon": "app-icon.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"app-screenshot.png"}], + "readme": "README.md", + "storage": [ + {"name":"configurable_clock.app.js","url":"app.js"}, + {"name":"configurable_clock.img","url":"app-icon.js","evaluate":true} + ] } ] From 216610780f734f111704c99964f567fb2b8b24a0 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Tue, 11 Jan 2022 16:29:19 +0100 Subject: [PATCH 368/489] Create app.js --- apps/ac_ac/app.js | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 apps/ac_ac/app.js diff --git a/apps/ac_ac/app.js b/apps/ac_ac/app.js new file mode 100644 index 000000000..1d9b2e3c6 --- /dev/null +++ b/apps/ac_ac/app.js @@ -0,0 +1,2 @@ +let Clockwork = require('https://raw.githubusercontent.com/rozek/banglejs-2-simple-clockwork/main/Clockwork.js'); +Clockwork.windUp(); \ No newline at end of file From 0666181c8d8b83161364b54264de82d8fc774e5a Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Tue, 11 Jan 2022 16:29:24 +0100 Subject: [PATCH 369/489] Create README.md --- apps/ac_ac/README.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 apps/ac_ac/README.md diff --git a/apps/ac_ac/README.md b/apps/ac_ac/README.md new file mode 100644 index 000000000..0e0084b64 --- /dev/null +++ b/apps/ac_ac/README.md @@ -0,0 +1,34 @@ +# AC-AC - A Configurable Analog Clock # + +This app implements an analog clock with various faces, hands and complications +to choose from before uploading to a Bangle.js 2. + +It is based on the [Analog Clock Construction Kit (ACCK)](https://github.com/rozek/banglejs-2-analog-clock-construction-kit) +and makes most of the currently implemented parts available with a few mouse +clicks - just click on "Upload" and you will be directed to a web form where +you compose your very own, personal analog clock. + +You currently have the choice between + +* 2 different clock sizes, +* 4 different clock faces, +* 3 different clock hands and +* 4 different complications + +Alternatively, you may specify the GitHub URL of ACCK compatible modules for +external clock sizes, faces, hands or complications. + +Additionally, you may use the currently configured global theme or configure +your own colors for clock fore- and background and second hands. + +Consequently, even without external modules you already have the choice between +87552 combinations! + + + +## License ## + +[MIT License](LICENSE) From 16b50228bdaee15584a5c2b5e7a9b5d38ff1cdbe Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Tue, 11 Jan 2022 16:30:27 +0100 Subject: [PATCH 370/489] Update apps.json --- apps.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/apps.json b/apps.json index a62bb19cf..aa626a609 100644 --- a/apps.json +++ b/apps.json @@ -5555,5 +5555,23 @@ {"name":"configurable_clock.app.js","url":"app.js"}, {"name":"configurable_clock.img","url":"app-icon.js","evaluate":true} ] + }, + { "id": "ac_ac", + "name": "A Configurable Analog Clock", + "shortName":"Configurable Clock", + "version":"0.02", + "description": "a highly customizable analog clock", + "icon": "app-icon.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"app-screenshot.png"}], + "readme": "README.md", + "custom": "Customizer.html", + "storage": [ + {"name":"ac_ac.app.js","url":"app.js"}, + {"name":"ac_ac.img","url":"app-icon.js","evaluate":true} + ] } ] From 3715ae433a796088c1ac0444b507c42162329b7f Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Tue, 11 Jan 2022 16:30:48 +0100 Subject: [PATCH 371/489] Create Customizer.html --- apps/ac_ac/Customizer.html | 91 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 apps/ac_ac/Customizer.html diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html new file mode 100644 index 000000000..6637b5df4 --- /dev/null +++ b/apps/ac_ac/Customizer.html @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + +

A Configurable Analog Clock

+ + Please customize your analog clock for the Bangle.js 2 according to your needs. + When finished, click on "Upload". + +

Clock Size Calculation

+ +
+
+ +  
+ +

Clock Face

+ +
+
+  
+
+  
+
+  
+ +

Clock Hands

+ +
+
+
+   Hand Fill Color
+ +

Complications

+ +

Settings

+ + Foreground Color:
+ + Background Color:
+ + Second Hand Color:
+ + + + + From 7b1c19f67ff50d962de810380bd365bc3dc0ec02 Mon Sep 17 00:00:00 2001 From: David Peer Date: Tue, 11 Jan 2022 17:22:17 +0100 Subject: [PATCH 372/489] Removed swipe gestures to be compatible with the ecosystem --- apps/lcars/lcars.app.js | 91 ++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 43 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 3535f57d5..34a3a2e12 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -241,8 +241,8 @@ function drawPosition0(){ // The last line is a battery indicator too var bat = E.getBattery() / 100.0; var batX2 = parseInt((172 - 35) * bat + 35); - drawHorizontalBgLine(cOrange, 35, batX2, 171, 5); - drawHorizontalBgLine(cGrey, batX2+10, 172, 171, 5); + drawHorizontalBgLine(cOrange, 35, batX2-5, 171, 5); + drawHorizontalBgLine(cGrey, batX2+5, 172, 171, 5); // Draw Infos drawInfo(); @@ -253,15 +253,15 @@ function drawPosition0(){ var currentDate = new Date(); var timeStr = locale.time(currentDate,1); g.setFontAntonioLarge(); - g.drawString(timeStr, 29, 10); + g.drawString(timeStr, 27, 10); // Write date g.setColor(cWhite); g.setFontAntonioMedium(); var dayStr = locale.dow(currentDate, true).toUpperCase(); dayStr += " " + currentDate.getDate(); - dayStr += " " + currentDate.getFullYear(); - g.drawString(dayStr, 32, 56); + dayStr += " " + locale.month(currentDate, 1).toUpperCase(); + g.drawString(dayStr, 30, 56); // Draw data g.setFontAlign(-1, -1, 0); @@ -408,6 +408,7 @@ function draw(){ */ function getSteps() { var steps = 0; + let health; try { health = require("health"); } catch(ex) { @@ -511,49 +512,53 @@ function decreaseAlarm(){ Storage.writeJSON(SETTINGS_FILE, settings); } +function feedback(){ + Bangle.buzz(40, 0.3); +} -// Thanks to the app "gbmusic" for this code to detect swipes in all 4 directions. -Bangle.on("drag", e => { - if (!drag) { // start dragging - drag = {x: e.x, y: e.y}; - } else if (!e.b) { // released - const dx = e.x-drag.x, dy = e.y-drag.y; - drag = null; +// Touch gestures to control clock. We don't use swipe to be compatible with the bangle ecosystem +Bangle.on('touch', function(btn, e){ + var left = parseInt(g.getWidth() * 0.2); + var right = g.getWidth() - left; + var upper = parseInt(g.getHeight() * 0.2); + var lower = g.getHeight() - upper; - // Horizontal swipe - if (Math.abs(dx)>Math.abs(dy)+10) { - if(dx > 0){ - lcarsViewPos = 0; - } else { - lcarsViewPos = 1; - } - - // Vertical swipe - } else if (Math.abs(dy)>Math.abs(dx)+10) { - if(lcarsViewPos == 0){ - if(dy > 0){ - decreaseAlarm(); - } else { - increaseAlarm(); - } - - // Only update the state and return to - // avoid a full draw as this is much faster. - drawState(); - return; - } - - if(lcarsViewPos == 1){ - plotWeek = dy < 0 ? true : false; - } - } + var is_left = e.x < left; + var is_right = e.x > right; + var is_upper = e.y < upper; + var is_lower = e.y > lower; + if(is_left && lcarsViewPos == 1){ + feedback(); + lcarsViewPos = 0; draw(); - } -}); + return; -Bangle.on("touch", e => { - Bangle.showLauncher(); + } else if(is_right && lcarsViewPos == 0){ + feedback(); + lcarsViewPos = 1; + draw(); + return; + } + + if(lcarsViewPos == 0){ + if(is_upper){ + feedback(); + increaseAlarm(); + drawState(); + return; + } if(is_lower){ + feedback(); + decreaseAlarm(); + drawState(); + return; + } + } else if (lcarsViewPos == 1 && (is_upper || is_lower) && plotWeek != is_lower){ + feedback(); + plotWeek = is_lower; + draw(); + return; + } }); From 1cdcedc997db4286270eaa5c3b7782b57310f073 Mon Sep 17 00:00:00 2001 From: David Peer Date: Tue, 11 Jan 2022 17:41:02 +0100 Subject: [PATCH 373/489] Bugfix: If the weather module does not exist, an exception was thrown. Now its hidden in a function. --- apps/lcars/lcars.app.js | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 09998ccf5..39d01a687 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -1,10 +1,5 @@ const SETTINGS_FILE = "lcars.setting.json"; -const Storage = require("Storage"); -const weather = require('weather'); - - -// ...and overwrite them with any saved values -// This way saved values are preserved if a new version adds more settings +const locale = require('locale'); const storage = require('Storage') let settings = { alarm: -1, @@ -39,7 +34,7 @@ var disableInfoUpdate = true; // When gadgetbridge connects, step infos cannot b /* * Requirements and globals */ -const locale = require('locale'); + var bgLeft = { width : 27, height : 176, bpp : 3, @@ -124,7 +119,7 @@ function queueDraw() { function printData(key, y, c){ g.setFontAlign(-1,-1,0); var text = "ERR"; - var value = "NOT FOUND"; + var value = "ERR"; if(key == "Battery"){ text = "BAT"; @@ -136,7 +131,7 @@ function printData(key, y, c){ } else if(key == "Temp."){ text = "TEMP"; - value = Math.floor(E.getTemperature()) + "C"; + value = locale.temp(parseInt(E.getTemperature())); } else if(key == "HRM"){ text = "HRM"; @@ -148,12 +143,8 @@ function printData(key, y, c){ } else if (key == "Weather"){ text = "TEMP"; - const w = weather.get(); - if (!w) { - value = "ERR"; - } else { - value = require('locale').temp(w.temp-273.15); // applies conversion - } + var weather = getWeather(); + value = locale.temp(parseInt(weather.temp-273.15)); } g.setColor(c); @@ -429,6 +420,21 @@ function getSteps() { } +function getWeather(){ + let weather; + + try { + weather = require('weather'); + } catch(ex) { + return { + temp: 0.0 + }; + } + + return weather.get(); +} + + /* * Handle alarm */ From 5de8ca8184909f17b65900e1883204810b82c3e5 Mon Sep 17 00:00:00 2001 From: David Peer Date: Tue, 11 Jan 2022 18:10:05 +0100 Subject: [PATCH 374/489] Updated changelog, readme, screenshots etc. More consistent naming of datapoints. --- apps/lcars/ChangeLog | 4 ++-- apps/lcars/README.md | 36 +++++++++++++++------------- apps/lcars/lcars.app.js | 45 ++++++++++++++++------------------- apps/lcars/lcars.settings.js | 2 +- apps/lcars/screenshot.png | Bin 5259 -> 5547 bytes 5 files changed, 44 insertions(+), 43 deletions(-) diff --git a/apps/lcars/ChangeLog b/apps/lcars/ChangeLog index 45d7a8dd7..bcaddeb56 100644 --- a/apps/lcars/ChangeLog +++ b/apps/lcars/ChangeLog @@ -7,5 +7,5 @@ 0.07: Added settings to adjust data that is shown for each row. 0.08: Support for multiple screens. 24h graph for steps + HRM. Fullscreen Mode. 0.09: Tab anywhere to open the launcher. -0.10: Fix - Clock is unresponsive, if gadgetbridge connects. -0.11: Added getting the gadgetbridge weather \ No newline at end of file +0.10: Removed swipes to be compatible with the Pattern Launcher. Stability improvements. +0.11: Show the gadgetbridge weather temperature (settings). \ No newline at end of file diff --git a/apps/lcars/README.md b/apps/lcars/README.md index 4bf5218f6..510e5637c 100644 --- a/apps/lcars/README.md +++ b/apps/lcars/README.md @@ -4,20 +4,27 @@ A simple LCARS inspired clock. Note: To display the steps, the health app is required. If this app is not installed, the data will not be shown. To contribute you can open a PR at this [GitHub Repo]( https://github.com/peerdavid/BangleApps) +## Control + * Tap left / right to change between screens. + * Tap top / bottom to control the current screen. + ## Features * LCARS Style watch face. - * Full screen mode - widgets are still loaded. - * Supports multiple screens with different data. - * Tab anywhere to open the launcher. - * [Screen 1] Date + Time + Lock status. - * [Screen 1] Shows randomly images of real planets. - * [Screen 1] Shows different states such as (charging, out of battery, GPS on etc.) - * [Screen 1] Swipe up/down to activate an alarm. - * [Screen 1] Shows 3 customizable datapoints on the first screen. - * [Screen 1] The lower orange line indicates the battery level. - * [Screen 2] Display graphs for steps + hrm on the second screen. - * [Screen 2] Switch between day/month via swipe up/down. + * Full screen mode - widgets are still loaded but not shown. + * Tab on left/right to switch between different screens. + * Cusomizable data that is shown on screen 1 (steps, weather etc.) + * Shows random images of real planets. + * Tap on top/bottom of screen 1 to activate an alarm. + * The lower orange line indicates the battery level. + * Display graphs for steps + hrm on the second screen. +## Data that can be configured + * Steps - Steps loaded via the health module + * Battery - Current battery level in % + * VREF - Voltage of battery + * HRM - Last measured HRM + * Temp - Weather temperature loaded via the weather module + gadgetbridge + * CoreT - Temperature of device ## Multiple screens support Access different screens via swipe left/ right @@ -26,10 +33,7 @@ Access different screens via swipe left/ right ![](screenshot_2.png) -## Icons - - - ## Contributors -- Creator: [David Peer](https://github.com/peerdavid). +- Initial creation and improvements: [David Peer](https://github.com/peerdavid). - Improvements: [Adam Schmalhofer](https://github.com/adamschmalhofer). +- Improvements: [Jon Warrington](https://github.com/BartokW). diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 39d01a687..521f661e7 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -28,7 +28,7 @@ let cGrey = "#9E9E9E"; let lcarsViewPos = 0; let drag; let hrmValue = 0; -var plotWeek = false; +var plotMonth = false; var disableInfoUpdate = true; // When gadgetbridge connects, step infos cannot be loaded /* @@ -118,33 +118,30 @@ function queueDraw() { function printData(key, y, c){ g.setFontAlign(-1,-1,0); - var text = "ERR"; + key = key.toUpperCase() + var text = key; var value = "ERR"; - if(key == "Battery"){ - text = "BAT"; - value = E.getBattery() + "%"; - - } else if(key == "Steps"){ + if(key == "STEPS"){ text = "STEP"; value = getSteps(); - } else if(key == "Temp."){ - text = "TEMP"; - value = locale.temp(parseInt(E.getTemperature())); - - } else if(key == "HRM"){ - text = "HRM"; - value = hrmValue; + } else if(key == "BATTERY"){ + text = "BAT"; + value = E.getBattery() + "%"; } else if (key == "VREF"){ - text = "VREF"; value = E.getAnalogVRef().toFixed(2) + "V"; - } else if (key == "Weather"){ - text = "TEMP"; + } else if(key == "HRM"){ + value = hrmValue; + + } else if (key == "TEMP"){ var weather = getWeather(); value = locale.temp(parseInt(weather.temp-273.15)); + + } else if(key == "CORET"){ + value = locale.temp(parseInt(E.getTemperature())); } g.setColor(c); @@ -300,7 +297,7 @@ function drawPosition1(){ } // Plot HRM graph - if(plotWeek){ + if(plotMonth){ var data = new Uint16Array(32); var cnt = new Uint8Array(32); health.readDailySummaries(new Date(), h=>{ @@ -337,8 +334,8 @@ function drawPosition1(){ g.setFontAlign(1, 1, 0); g.setFontAntonioMedium(); g.setColor(cWhite); - g.drawString("WEEK HRM", 154, 27); - g.drawString("WEEK STEPS [K]", 154, 115); + g.drawString("M-HRM", 154, 27); + g.drawString("M-STEPS [K]", 154, 115); // Plot day } else { @@ -378,8 +375,8 @@ function drawPosition1(){ g.setFontAlign(1, 1, 0); g.setFontAntonioMedium(); g.setColor(cWhite); - g.drawString("DAY HRM", 154, 27); - g.drawString("DAY STEPS", 154, 115); + g.drawString("D-HRM", 154, 27); + g.drawString("D-STEPS", 154, 115); } } @@ -568,9 +565,9 @@ Bangle.on('touch', function(btn, e){ drawState(); return; } - } else if (lcarsViewPos == 1 && (is_upper || is_lower) && plotWeek != is_lower){ + } else if (lcarsViewPos == 1 && (is_upper || is_lower) && plotMonth != is_lower){ feedback(); - plotWeek = is_lower; + plotMonth = is_lower; draw(); return; } diff --git a/apps/lcars/lcars.settings.js b/apps/lcars/lcars.settings.js index a0e54f9b4..1dd6e8d73 100644 --- a/apps/lcars/lcars.settings.js +++ b/apps/lcars/lcars.settings.js @@ -18,7 +18,7 @@ storage.write(SETTINGS_FILE, settings) } - var data_options = ["Battery", "Steps", "Temp.", "HRM", "VREF", "Weather"]; + var data_options = ["Steps", "Battery", "VREF", "HRM", "Temp", "CoreT"]; E.showMenu({ '': { 'title': 'LCARS Clock' }, diff --git a/apps/lcars/screenshot.png b/apps/lcars/screenshot.png index 5d7603b45e6c7aadcc01aa0afdf13ff4d579eb93..5381492b242865bae924e11daf9a5cd40313188f 100644 GIT binary patch literal 5547 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 literal 5259 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 Date: Tue, 11 Jan 2022 18:11:49 +0100 Subject: [PATCH 375/489] Updated screenshot. --- apps/lcars/screenshot.png | Bin 5547 -> 5721 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/lcars/screenshot.png b/apps/lcars/screenshot.png index 5381492b242865bae924e11daf9a5cd40313188f..319062dcce36640c38e24378d97b7724ab3a9f74 100644 GIT binary patch literal 5721 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 From 755f44cf3f3896a3a646f96bea49ce48aa94b90d Mon Sep 17 00:00:00 2001 From: David Peer Date: Tue, 11 Jan 2022 18:20:53 +0100 Subject: [PATCH 376/489] Bugfix: Alarm not working. --- apps/lcars/ChangeLog | 3 ++- apps/lcars/lcars.app.js | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/lcars/ChangeLog b/apps/lcars/ChangeLog index bcaddeb56..bb5270b70 100644 --- a/apps/lcars/ChangeLog +++ b/apps/lcars/ChangeLog @@ -8,4 +8,5 @@ 0.08: Support for multiple screens. 24h graph for steps + HRM. Fullscreen Mode. 0.09: Tab anywhere to open the launcher. 0.10: Removed swipes to be compatible with the Pattern Launcher. Stability improvements. -0.11: Show the gadgetbridge weather temperature (settings). \ No newline at end of file +0.11: Show the gadgetbridge weather temperature (settings). +0.12: Refactoring and stability improvements. \ No newline at end of file diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 521f661e7..c4e675873 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -470,7 +470,7 @@ function handleAlarm(){ .then(() => { // Update alarm state to disabled settings.alarm = -1; - Storage.writeJSON(SETTINGS_FILE, settings); + storage.writeJSON(SETTINGS_FILE, settings); }); } @@ -510,7 +510,7 @@ function increaseAlarm(){ settings.alarm = getCurrentTimeInMinutes() + 5; } - Storage.writeJSON(SETTINGS_FILE, settings); + storage.writeJSON(SETTINGS_FILE, settings); } @@ -521,7 +521,7 @@ function decreaseAlarm(){ settings.alarm = -1; } - Storage.writeJSON(SETTINGS_FILE, settings); + storage.writeJSON(SETTINGS_FILE, settings); } function feedback(){ From 8467a8810af3a651ae85af6d6866f97222f2abeb Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Tue, 11 Jan 2022 19:16:05 +0100 Subject: [PATCH 377/489] messages: app-specific icon colors --- apps.json | 2 +- apps/messages/ChangeLog | 1 + apps/messages/app.js | 31 +++++++++++++++++++++++++++++-- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index b5929a56c..71a60ec88 100644 --- a/apps.json +++ b/apps.json @@ -77,7 +77,7 @@ { "id": "messages", "name": "Messages", - "version": "0.17", + "version": "0.18", "description": "App to display notifications from iOS and Gadgetbridge", "icon": "app.png", "type": "app", diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index 4f0498e92..84dc67288 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -24,3 +24,4 @@ 0.15: Don't buzz when Quiet Mode is active 0.16: Fix text wrapping so it fits the screen even if title is big (fix #1147) 0.17: Fix: Get dynamic dimensions of notify icon, fixed notification font +0.18: Use app-specific icon colors diff --git a/apps/messages/app.js b/apps/messages/app.js index 6e51c2b33..f670c39a2 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -101,6 +101,31 @@ function getMessageImage(msg) { if (msg.id=="back") return getBackImage(); return getNotificationImage(); } +function getMessageImageCol(msg,def) { + return { + // generic colors, using B2-safe colors + "calendar": "#f00", + "mail": "#ff0", + "music": "#f0f", + "phone": "#0f0", + "sms message": "#0ff", + // brands, according to https://www.schemecolor.com/?s (picking one for multicolored logos) + // all dithered on B2, but we only use the color for the icons. (Could maybe pick the closest 3-bit color for B2?) + "facebook": "#4267b2", + "gmail": "#ea4335", + "google home": "#fbbc05", + "hangouts": "#1ba261", + "instagram": "#dd2a7b", + "messenger": "#0078ff", + "outlook mail": "#0072c6", + "skype": "#00aff0", + "slack": "#e51670", + "telegram": "#0088cc", + "twitter": "#1da1f2", + "whatsapp": "#4fce5d", + "wordfeud": "#dcc8bd", + }[(msg.src||"").toLowerCase()]||(def !== undefined?def:g.theme.fg); +} function showMapMessage(msg) { var m; @@ -248,7 +273,7 @@ function showMessage(msgid) { var body = (lines.length>4) ? lines.slice(0,4).join("\n")+"..." : lines.join("\n"); layout = new Layout({ type:"v", c: [ {type:"h", fillx:1, bgCol:colBg, c: [ - { type:"btn", src:getMessageImage(msg), pad: 3, cb:()=>{ + { type:"btn", src:getMessageImage(msg), col:getMessageImageCol(msg), pad: 3, cb:()=>{ cancelReloadTimeout(); // don't auto-reload to clock now showMessageSettings(msg); }}, @@ -310,7 +335,9 @@ function checkMessages(options) { body = msg.track; } if (img) { - g.drawImage(img, x+24, r.y+24, {rotate:0}); // force centering + var fg = g.getColor(); + g.setColor(getMessageImageCol(msg,fg)).drawImage(img, x+24, r.y+24, {rotate:0}) // force centering + .setColor(fg); // only color the icon x += 50; } var m = msg.title+"\n"+msg.body; From d32674f825a0906ca9d1149505371dc4e0f101e2 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Tue, 11 Jan 2022 19:17:16 +0100 Subject: [PATCH 378/489] messages: Spread message action buttons out --- apps/messages/ChangeLog | 1 + apps/messages/app.js | 2 ++ 2 files changed, 3 insertions(+) diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index 84dc67288..4a28f7cd9 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -25,3 +25,4 @@ 0.16: Fix text wrapping so it fits the screen even if title is big (fix #1147) 0.17: Fix: Get dynamic dimensions of notify icon, fixed notification font 0.18: Use app-specific icon colors + Spread message action buttons out diff --git a/apps/messages/app.js b/apps/messages/app.js index f670c39a2..5161ce665 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -253,6 +253,7 @@ function showMessage(msgid) { }} // back ]; if (msg.positive) { + buttons.push({fillx:1}); buttons.push({type:"btn", src:getPosImage(), cb:()=>{ msg.new = false; saveMessages(); cancelReloadTimeout(); // don't auto-reload to clock now @@ -261,6 +262,7 @@ function showMessage(msgid) { }}); } if (msg.negative) { + buttons.push({fillx:1}); buttons.push({type:"btn", src:getNegImage(), cb:()=>{ msg.new = false; saveMessages(); cancelReloadTimeout(); // don't auto-reload to clock now From a945a32f51a7d2a1a42a5a70bed38309aab2d555 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Tue, 11 Jan 2022 19:18:19 +0100 Subject: [PATCH 379/489] messages: Back button now goes back to list of messages --- apps/messages/ChangeLog | 1 + apps/messages/app.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index 4a28f7cd9..0c02a76e1 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -26,3 +26,4 @@ 0.17: Fix: Get dynamic dimensions of notify icon, fixed notification font 0.18: Use app-specific icon colors Spread message action buttons out + Back button now goes back to list of messages diff --git a/apps/messages/app.js b/apps/messages/app.js index 5161ce665..4704c422f 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -249,7 +249,7 @@ function showMessage(msgid) { {type:"btn", src:getBackImage(), cb:()=>{ msg.new = false; saveMessages(); // read mail cancelReloadTimeout(); // don't auto-reload to clock now - checkMessages({clockIfNoMsg:1,clockIfAllRead:0,showMsgIfUnread:1}); + checkMessages({clockIfNoMsg:1,clockIfAllRead:0,showMsgIfUnread:0}); }} // back ]; if (msg.positive) { From 1f06e6cfc578473c86214f76c5c43d9715b905a4 Mon Sep 17 00:00:00 2001 From: David Peer Date: Tue, 11 Jan 2022 21:24:23 +0100 Subject: [PATCH 380/489] Added humidity --- apps/lcars/README.md | 1 + apps/lcars/lcars.app.js | 28 +++++++++++++++++++--------- apps/lcars/lcars.settings.js | 10 +++++----- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/apps/lcars/README.md b/apps/lcars/README.md index 510e5637c..46e134f78 100644 --- a/apps/lcars/README.md +++ b/apps/lcars/README.md @@ -24,6 +24,7 @@ To contribute you can open a PR at this [GitHub Repo]( https://github.com/peerda * VREF - Voltage of battery * HRM - Last measured HRM * Temp - Weather temperature loaded via the weather module + gadgetbridge + * Humidity - Humidity loaded via the weather module + gadgetbridge * CoreT - Temperature of device ## Multiple screens support diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index c4e675873..0005e9016 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -3,9 +3,9 @@ const locale = require('locale'); const storage = require('Storage') let settings = { alarm: -1, - dataRow1: "Battery", - dataRow2: "Steps", - dataRow3: "Temp." + dataRow1: "Steps", + dataRow2: "Temp", + dataRow3: "Battery" }; let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; for (const key in saved_settings) { @@ -140,6 +140,11 @@ function printData(key, y, c){ var weather = getWeather(); value = locale.temp(parseInt(weather.temp-273.15)); + } else if (key == "HUMIDITY"){ + text = "HUM"; + var weather = getWeather(); + value = parseInt(weather.hum) + "%"; + } else if(key == "CORET"){ value = locale.temp(parseInt(E.getTemperature())); } @@ -418,17 +423,22 @@ function getSteps() { function getWeather(){ - let weather; + var weather = { + temp: 0, + hum: 0, + txt: "", + wind: 0, + wdir: 0, + wrose: "" + }; try { - weather = require('weather'); + weather = require('weather').get(); } catch(ex) { - return { - temp: 0.0 - }; + // Return default } - return weather.get(); + return weather; } diff --git a/apps/lcars/lcars.settings.js b/apps/lcars/lcars.settings.js index 1dd6e8d73..ba630799a 100644 --- a/apps/lcars/lcars.settings.js +++ b/apps/lcars/lcars.settings.js @@ -7,7 +7,7 @@ alarm: -1, dataRow1: "Battery", dataRow2: "Steps", - dataRow3: "Temp." + dataRow3: "Temp" }; let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; for (const key in saved_settings) { @@ -18,14 +18,14 @@ storage.write(SETTINGS_FILE, settings) } - var data_options = ["Steps", "Battery", "VREF", "HRM", "Temp", "CoreT"]; + var data_options = ["Steps", "Battery", "VREF", "HRM", "Temp", "Humidity", "CoreT"]; E.showMenu({ '': { 'title': 'LCARS Clock' }, '< Back': back, 'Row 1': { value: 0 | data_options.indexOf(settings.dataRow1), - min: 0, max: 5, + min: 0, max: 6, format: v => data_options[v], onchange: v => { settings.dataRow1 = data_options[v]; @@ -34,7 +34,7 @@ }, 'Row 2': { value: 0 | data_options.indexOf(settings.dataRow2), - min: 0, max: 5, + min: 0, max: 6, format: v => data_options[v], onchange: v => { settings.dataRow2 = data_options[v]; @@ -43,7 +43,7 @@ }, 'Row 3': { value: 0 | data_options.indexOf(settings.dataRow3), - min: 0, max: 5, + min: 0, max: 6, format: v => data_options[v], onchange: v => { settings.dataRow3 = data_options[v]; From 009df38104965fc2b3119ebdd5fcb8e95d3223f5 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Wed, 12 Jan 2022 00:16:01 +0100 Subject: [PATCH 381/489] fixed and aligned for bangle2 *bugfix* stopwatch broken with v0.03 setUI realigned quick n dirty screen positions help adjusted to fit bangle1 & bangle2 screen-size with widgets fixed bangle2 colors for chrono and last lap highlight added screen for bangle2 and a small README --- apps.json | 5 +- apps/devstopwatch/ChangeLog | 5 ++ apps/devstopwatch/README.md | 16 ++++++ apps/devstopwatch/app.js | 46 +++++++++++------- .../bangle1-dev-stopwatch-screenshot.png | Bin 3825 -> 2469 bytes .../bangle2-dev-stopwatch-screenshot.png | Bin 0 -> 2382 bytes 6 files changed, 52 insertions(+), 20 deletions(-) create mode 100644 apps/devstopwatch/README.md create mode 100644 apps/devstopwatch/bangle2-dev-stopwatch-screenshot.png diff --git a/apps.json b/apps.json index b5929a56c..f1872f337 100644 --- a/apps.json +++ b/apps.json @@ -2095,12 +2095,13 @@ "id": "devstopwatch", "name": "Dev Stopwatch", "shortName": "Dev Stopwatch", - "version": "0.03", + "version": "0.04", "description": "Stopwatch with 5 laps supported (cyclically replaced)", "icon": "app.png", "tags": "stopwatch,chrono,timer,chronometer", "supports": ["BANGLEJS","BANGLEJS2"], - "screenshots": [{"url":"bangle1-dev-stopwatch-screenshot.png"}], + "screenshots": [{"url":"bangle1-dev-stopwatch-screenshot.png"},{"url":"bangle2-dev-stopwatch-screenshot.png"}], + "readme": "README.md", "allow_emulator": true, "storage": [ {"name":"devstopwatch.app.js","url":"app.js"}, diff --git a/apps/devstopwatch/ChangeLog b/apps/devstopwatch/ChangeLog index e2b392fe9..7e90e061e 100644 --- a/apps/devstopwatch/ChangeLog +++ b/apps/devstopwatch/ChangeLog @@ -1,3 +1,8 @@ 0.01: App created 0.02: Persist state to storage to enable stopwatch to continue in the background 0.03: Modified to use setUI, theme and different screens +0.04: *bugfix* stopwatch broken with v0.03 setUI + realigned quick n dirty screen positions + help adjusted to fit bangle1 & bangle2 screen-size with widgets + fixed bangle2 colors for chrono and last lap highlight + added screen for bangle2 and a small README \ No newline at end of file diff --git a/apps/devstopwatch/README.md b/apps/devstopwatch/README.md new file mode 100644 index 000000000..c068aadfe --- /dev/null +++ b/apps/devstopwatch/README.md @@ -0,0 +1,16 @@ +# dev stop watch + +stores state at kill + +Look and control: + +![](bangle1-dev-stopwatch-screenshot.png) +BTN1: start/lap +BTN2: launcher +BTN3: reset + +![](bangle2-dev-stopwatch-screenshot.png) +TAP top right: start/lap +TAP bottom right: reset +Use BTN to get to launcher + diff --git a/apps/devstopwatch/app.js b/apps/devstopwatch/app.js index 83bb693a9..d2a4b1117 100644 --- a/apps/devstopwatch/app.js +++ b/apps/devstopwatch/app.js @@ -3,11 +3,11 @@ const EMPTY_H = '00:00:000'; const MAX_LAPS = 6; const XY_CENTER = g.getWidth() / 2; const big = g.getWidth()>200; -const Y_CHRONO = 40; -const Y_HEADER = big?80:60; -const Y_LAPS = big?125:90; +const Y_CHRONO = big?40:30; +const Y_HEADER = big?95:65; +const Y_LAPS = big?125:80; const H_LAPS = big?15:8; -const Y_BTN3 = big?225:165; +const Y_HELP = big?225:135; const FONT = '6x8'; const CHRONO = '/* C H R O N O */'; @@ -27,18 +27,17 @@ var state = require("Storage").readJSON("devstopwatch.state.json",1) || { // Show launcher when button pressed Bangle.setUI("clockupdown", btn=>{ - if (btn==0) { - reset = false; - - if (state.started) { - changeLap(); - } else { - if (!reset) { - chronoInterval = setInterval(chronometer, 10); - } + switch (btn) { + case -1: + if (state.started) { + changeLap(); + } else { + chronoInterval = setInterval(chronometer, 10); + } + break; + case 1: resetChrono(); break; + default: Bangle.showLauncher(); break; //launcher handeled by ROM } -} - if (btn==1) resetChrono(); }); function resetChrono() { @@ -105,6 +104,7 @@ function printChrono() { var print = ''; + g.setColor(g.theme.fg); g.setFont(FONT, big?2:1); print = CHRONO; g.drawString(print, XY_CENTER, Y_CHRONO, true); @@ -124,7 +124,8 @@ function printChrono() { let suffix = ' '; if (state.currentLapIndex === i) { let suffix = '*'; - g.setColor("#f70"); + if (process.env.HWVERSION==2) g.setColor("#0ee"); + else g.setColor("#f70"); } const lapLine = `L${i - 1} ${state.laps[i]} ${suffix}\n`; @@ -133,8 +134,17 @@ function printChrono() { g.setColor(g.theme.fg); g.setFont(FONT, 1); - print = 'Press 3 to reset'; - g.drawString(print, XY_CENTER, Y_BTN3, true); + //help for model 2 or 1 + if (process.env.HWVERSION==2) { + print = /*LANG*/'TAP right top/bottom'; + g.drawString(print, XY_CENTER, Y_HELP, true); + print = /*LANG*/'start&lap/reset, BTN1: EXIT'; + g.drawString(print, XY_CENTER, Y_HELP+10, true); + } + else { + print = /*LANG*/'BTNs 1:startlap 2:exit 3:reset'; + g.drawString(print, XY_CENTER, Y_HELP, true); + } g.flip(); } diff --git a/apps/devstopwatch/bangle1-dev-stopwatch-screenshot.png b/apps/devstopwatch/bangle1-dev-stopwatch-screenshot.png index b668794b1f94f728fff6fbce8cfcfdc3c28e7787..8a9c9b46e33b4aa403bc90a43e0e4eca14b908ac 100644 GIT binary patch literal 2469 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 Z7IZMz?QhEcvOf^uGQ`cL@{-@9-vN`~z(@c9 literal 0 HcmV?d00001 From 30f8546319c83f79221fa73dcc9708aa6f131b31 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Wed, 12 Jan 2022 00:17:23 +0100 Subject: [PATCH 382/489] Update README.md --- apps/devstopwatch/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/devstopwatch/README.md b/apps/devstopwatch/README.md index c068aadfe..efead677b 100644 --- a/apps/devstopwatch/README.md +++ b/apps/devstopwatch/README.md @@ -5,11 +5,13 @@ stores state at kill Look and control: ![](bangle1-dev-stopwatch-screenshot.png) + BTN1: start/lap BTN2: launcher BTN3: reset ![](bangle2-dev-stopwatch-screenshot.png) + TAP top right: start/lap TAP bottom right: reset Use BTN to get to launcher From 382dce1176f8794fd117f587825fac2bb3453e9d Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Wed, 12 Jan 2022 00:18:52 +0100 Subject: [PATCH 383/489] Update README.md --- apps/devstopwatch/README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/devstopwatch/README.md b/apps/devstopwatch/README.md index efead677b..02a13151f 100644 --- a/apps/devstopwatch/README.md +++ b/apps/devstopwatch/README.md @@ -2,17 +2,17 @@ stores state at kill -Look and control: - +## Bangle 1 ![](bangle1-dev-stopwatch-screenshot.png) -BTN1: start/lap -BTN2: launcher -BTN3: reset +* BTN1: start/lap +* BTN2: launcher +* BTN3: reset +## Bangle 2 ![](bangle2-dev-stopwatch-screenshot.png) -TAP top right: start/lap -TAP bottom right: reset -Use BTN to get to launcher +* TAP top right: start/lap +* TAP bottom right: reset +* Use BTN to get to launcher From dfd04df0f3d6237559e8319957eca9c0c5021f39 Mon Sep 17 00:00:00 2001 From: David Peer Date: Wed, 12 Jan 2022 07:20:08 +0100 Subject: [PATCH 384/489] Fixed weather --- apps/lcars/lcars.app.js | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 0005e9016..2674d323f 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -138,7 +138,7 @@ function printData(key, y, c){ } else if (key == "TEMP"){ var weather = getWeather(); - value = locale.temp(parseInt(weather.temp-273.15)); + value = weather.temp; } else if (key == "HUMIDITY"){ text = "HUM"; @@ -423,14 +423,7 @@ function getSteps() { function getWeather(){ - var weather = { - temp: 0, - hum: 0, - txt: "", - wind: 0, - wdir: 0, - wrose: "" - }; + var weather; try { weather = require('weather').get(); @@ -438,6 +431,19 @@ function getWeather(){ // Return default } + if (weather === undefined){ + weather = { + temp: "-", + hum: "-", + txt: "-", + wind: "-", + wdir: "-", + wrose: "-" + }; + } else { + weather.temp = locale.temp(parseInt(weather.temp-273.15)) + } + return weather; } From 2e564e06913e10ff6f06b67477dc9d3104e92440 Mon Sep 17 00:00:00 2001 From: David Peer Date: Wed, 12 Jan 2022 07:20:52 +0100 Subject: [PATCH 385/489] Created V0.12 --- apps.json | 6 +++--- apps/lcars/ChangeLog | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps.json b/apps.json index b5929a56c..0a4a80a72 100644 --- a/apps.json +++ b/apps.json @@ -1357,7 +1357,7 @@ "shortName":"HR Alarm", "version":"0.01", "description": "This invisible widget vibrates whenever the heart rate gets close to the upper limit or goes over or under the configured limits", - "icon": "widget.png", + "icon": "widget.png", "type": "widget", "tags": "widget", "supports" : ["BANGLEJS2"], @@ -4514,7 +4514,7 @@ "name": "LCARS Clock", "shortName":"LCARS", "icon": "lcars.png", - "version":"0.11", + "version":"0.12", "readme": "README.md", "supports": ["BANGLEJS2"], "description": "Library Computer Access Retrieval System (LCARS) clock.", @@ -5184,7 +5184,7 @@ {"name":"mmind.app.js","url":"mmind.app.js"}, {"name":"mmind.img","url":"mmind.icon.js","evaluate":true} ] - }, + }, { "id": "presentor", "name": "Presentor", diff --git a/apps/lcars/ChangeLog b/apps/lcars/ChangeLog index bb5270b70..702ef58b9 100644 --- a/apps/lcars/ChangeLog +++ b/apps/lcars/ChangeLog @@ -9,4 +9,4 @@ 0.09: Tab anywhere to open the launcher. 0.10: Removed swipes to be compatible with the Pattern Launcher. Stability improvements. 0.11: Show the gadgetbridge weather temperature (settings). -0.12: Refactoring and stability improvements. \ No newline at end of file +0.12: Added humidity to data. \ No newline at end of file From fcfa78cb989f9b0823c69cc70367fe78932b5fb0 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 08:50:21 +0100 Subject: [PATCH 386/489] Create none.png --- apps/ac_ac/none.png | Bin 0 -> 1430 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/none.png diff --git a/apps/ac_ac/none.png b/apps/ac_ac/none.png new file mode 100644 index 0000000000000000000000000000000000000000..6f8d8ae14912ac974d77928fd613c80692486969 GIT binary patch literal 1430 zcmeAS@N?(olHy`uVBq!ia0vp^8$g(Y4M?uv{v-}aF%}28J29*~C-ahlfi=L>#WAEJ z?(NKreX|WjT&Dm3pRp>oQ_HEdmiOBx=03iL^sPW(`mO0Skq@3{2jSlPg$`F}`FIh>(&$tZcyNVcu}y z(hmu_#zKc(j4acR9sj`5!+eQXVS|ZXn|p%Hggl1Er5_D#m>xHb8i_Y7qdE5E-mahY zd!O^yrH$9~_Wi%LR=%?FF5}q>>ACR*+KqS1rb~X3`(7|LA}S$V!}w^e`i9GaPGJds ze2-^Y@B1LeR9v#+^c%H}OAfr*SDJWUTkuC!`Q>#b%?4{{9O}IjSNBtP#$)G$w=N4U z=XLOVa8dRNPxhBz*W3%9-u`p>eEo8BrvCk3F0Yf&{jc+8xnq@e<$JsN>)ywfpV|EC zr){IQ{zH=r?mU&f%-NE>b-R`tF^9&%=>#} z)(YbfmznO>*11mT>e=f*^;Ge{Q&KE;wHK4w|7mAkd*+a!*r>fbo7LL7VChoVY`4?v z=gf@Gt~xLM^Sh*bhon%rRb)&4uiU3)4?gGbwp}0^vDftK{i5pq%<+OdK1G+UZ{BRW zch6IddEPN9Jb1$7w*4jBLfs92?1X^@ OErX}4pUXO@geCxFHD;9n literal 0 HcmV?d00001 From 4b4a4e117b4f436d22528cf0f8b2c5164e0beb66 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 08:50:25 +0100 Subject: [PATCH 387/489] Create custom.png --- apps/ac_ac/custom.png | Bin 0 -> 1668 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/custom.png diff --git a/apps/ac_ac/custom.png b/apps/ac_ac/custom.png new file mode 100644 index 0000000000000000000000000000000000000000..14d797ba32005a45ae28d36b2f6775989a01836a GIT binary patch literal 1668 zcmeAS@N?(olHy`uVBq!ia0vp^8$g(Y4M?uv{v-}aF%}28J29*~C-ahlfz8g-#WAEJ z?(NNsMYr7qTrPh2Z$C@ZdYaeKh8K}e3TaO!hw~q}cU!!>wP^SK_uuRPv>ymyGH2q? z^?P%lg~O-iA`6GjF1v@EXBtOYGz$ZL(H~{IYt0Jw-`{$1#)0eW>W;p-bUl@+ob}R; zg{K#n-YJOUxbrmA?(l@ZrSg&K+rP#r6_|6lbNOEXw`FTtb@9H~2YC#W8r=W?UC#NZ z+kLrdtkwsAJFA+G`zzlp=6`(s_3kyV*E0Rj-JQSvZr1^J&XUS3e!b+EpXTp+rZ@Xy zs`ZEa1vNiTS{F>;y4Ux?V*fX`UoG2o zDF5Zwtp+un2ecPV;yC{vnP9V_&ZonV+U5By15-!?uFy9Z#dZS8V0qu%ac&r(RXb%fH#n z{`lrBjz0>|y(ad{b40Jd9g_9*`?oZ$Np)vJ&TqQ9bMfo7G4V4!g_iSO()%y_|K2x_ zK*0ijho`?n8~6W<(<;vnU&|F^`TU)%ecaA{n=)-aseR~c6lFXwQnC8N)P4)5`s4p* zy-#HScX-7v>vdi+wF273SIygGExPyH1Zuu`?W_GcUHn(h#HpV*%2q^9oUXSch5g>I zh6vmErJt`~tgp9mT4G-rTDEs@sr=dMFOBw9Z0qWT_oTeM7x?+#vG{ckb=$b#>+aDy zf6DgTzb{`Z=C^#fx%ZOuN1gm%yNg@hcO8GFHd&%(`;Phf7EJ%!7X`iO3Yf}Xxaq*l z-oj}c{#OUbs}?-vyl>@R7whnK<@z_v*4G>ft*?Lmbx+Zp9}&f-kFCodT;2XM(rN!& zo;|+;H*bA#>c7Pe=C2ihvpC)B?dPtZU&|gMH|12+r8B42&3aclZNv0;2iDhU?BQ;? zzf$;x();}R_bOX{^u_MzyZJY(QE;LHh^WG0rpn7)je z42{Oh!o8dVI|?lqr82Rc>+vxGDmeDEV;ZM`g|X4a84Qim)0Lw}H4Tw~_@IArAD4~) T%p(VY)e3{BtDnm{r-UW|FwpmH literal 0 HcmV?d00001 From 4039f71dd60df8137121de6631403d54544b9f66 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 08:50:37 +0100 Subject: [PATCH 388/489] Create fourfoldClockFace.png --- apps/ac_ac/fourfoldClockFace.png | Bin 0 -> 2121 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/fourfoldClockFace.png diff --git a/apps/ac_ac/fourfoldClockFace.png b/apps/ac_ac/fourfoldClockFace.png new file mode 100644 index 0000000000000000000000000000000000000000..391303b31d4d1ce4b1bacdb4bd67501a22ab53a2 GIT binary patch literal 2121 zcmeHJ`#;oq7ytVD4qr|9&S+6)t*=WWCE>%CpR~m?kDEVN4gwrDvYkbNTK051t>+=Y2lsbzbMZU+28e>zuNn zKws4@JGKA-pz81E6(YyBe+sN5e_OjGG&v|74e|8=T81bu0RUF?_i_)*p)FjA&bn@i z5FTx6E$lVyEw=L8u)X?QYQscB*dpBPfAhtg4+T;JcA9(<5pvQ;|I)MbNM2E9-Gb?o zD-pYp#M5M6G9~4t*2VK>)}`Ak@KZNjs@ja1RGMLg89o#QY05gXMizK?UNekON_F~> zNCA_TOtK8%-=aLLOykDFW(S`{b(Sxd;r9vl+9kNp@!)Ci=h}tkzwh^?&yan-*J8!; z)+hGKKOuRN{L5=OPO}=%MgAqr)~T+l*cmG0v(=ffLoLI7K{KXKx-i2lft0i2mwfz( zQvBC&H@c(!z;(&&s3TZ8jDy(IM3~WU{8{%q!$pke^YK$7+J;<{ z94j$;HHSUm{B2!#{!{j!_GO60z=S2F8RAJtZ%xbTLKV12&_Ey3t-ZRox&72E|gOvqZ1$0_Ai2leKmb)&sr7QRp@bGmLzd)zBBJ?({wG4ouiR z2?nDFA7h?^T#vKkp6XcNTvRb43|Ra|w>7lnS{Q`3ff4z;z|w!InqX<~7NUpP{``7n zxg}es2eCU|mCFf~gpf|+TOt|gefoCr$?M%WzZEG zMo>Fa&RXRcp4(0CBasTbh2P zT)QkAl9D1Ducp2w5L`NV@axfF*R@077lUgHEnKDj%4132)~AuMVNoVY*m5;>mH_dq zcnq|_;Z;I?q`0Y!izg7TjgPp@G=MSTG>5jYy(b=OY$-ULOA_9^mOM5n>ABm@Kp8v! zOt|7F<_f6FocUYzxn!)B$!WrV|FX7(o$$Jvzz-dNP7xaXkh!Qu;5YF+8R(Eq^lF9( zK8>10Q>FvoEgosd4FvgXYP_!RWAaHig2cg+o;&z$@7h9XI*SPD`cFouqIoh4*Mdv^ zf~1~z3q#xmtD3Oss+3wY>C{jbcdSKeGD1AwdNE43_p2jzf#jTi^S&&T)IHK+pO{@~ z2kZh7?cBm}T@P_9m9oonn!h5Bg*IQY_5J9QjY*=KvGl9EX+^kzTWDa@fIpuSqL$N~ zCA?I#yIDtv;3L{xek=tWvuEhJp_OYN`L!t!*s4BYQ!#NK9L>zEXQ^Z3fbT{pb@+^T z!8XufsWA73E+0}7%@$bwq(g*CHu&8WG~T%7afqEk3GRBF`H5Q2ZcB9OorlYL*16Te z(dsX>2z5#4#uOWp*U38_EJ93|TLh{YYbBEQV`(b5#F_h}^+_cf zZ%o-I*3cS}jF=Da=V#KEXM4_f6)TCp^IHd0XcGVCp4b~87 zrV9jV)BYZ{dm4xkPWe>!oK-p%3cm?2cOhZat!`qohj6X;dvh(U!_t7M83kFOR2CV` z5R)Hn8`Lktqv8h5(IVXFqDhrEfOQC}qCEhNY8h&H8UPbmMqMWXu$q3;Pg4OJ(x;}V zC_omy`&ee6JSKaR48jLbT+)w%5c|_+zZgMCH)P}eGpr|1lTMX`O8luflAOWM5;o%Y z|Ahauq=C58m!rGieJI!&rk5^n24>MbF!if`y53y)Hc&Y&d60YFZCXzVQ;6ximkxw+ zG}@cH5;MdA-){%-SR2EAnDdD+<=?6=xHQndqFPjdV7LOq$c}k*yO&x~Pnnw-xcOhF z8fVLV2_RsgWHhUehcflojCE}6rs}TtEOGbH#Q+CUIQ>+kb7iB5s%;Bmifq2oxAP`n zyS;p7fY|#f4EjUdJ9@$t*>V_P#LMd~flP_mEKz Date: Wed, 12 Jan 2022 08:50:40 +0100 Subject: [PATCH 389/489] Create twelvefoldClockFace.png --- apps/ac_ac/twelvefoldClockFace.png | Bin 0 -> 2493 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/twelvefoldClockFace.png diff --git a/apps/ac_ac/twelvefoldClockFace.png b/apps/ac_ac/twelvefoldClockFace.png new file mode 100644 index 0000000000000000000000000000000000000000..fc04d865e38f930ea094d7e03dd4729eaae70a66 GIT binary patch literal 2493 zcmV;u2}1UXP)Px;cS%G+RCr$Poo$z^Dhx(%|NoEfUCy)}k5x!QKoa)(cGiRto@^s8Y9G(%^Z6hD zP#~xR4*(9DIl}%?0Du7@v;qL^kiN&`@$n*=k?rlbhLSc8VWxBez>R6uz<9Jhb`8k- zWB{;Uv){SbuIlbxlpq9Pqu7OJ0BqFsIBj_U{|eyJG($TDF@~J782}s8x8vu4n zsTN@1^${L`eRTY6tJS6ufa@gq%S}jtwev=;y+vY41)d4s5t>+Z)V2u+uoeQXy;i`t zy%ykFrMAW)X*Ws}Ni3~4VF1>id}-~Qg{R!x_g6z%yoLP)qjXzd3M<+iReY7(Xb zYsJ^v-$vEIjx%Z!2H=5trmH{-0C1pW5$d-B01OqO6#(GS=_7amhJnxu0C4E^5j+6H zKxhR3ICT059)MvWv;qJeI(-BWz%US60RRr2K7t2e7znKZ0EbRroZyd7!bxAot&PwH zVC`p8?4jS=C>Xq{*fVCgn+hjkh&|ZUypVoCo;FWVTz(=WTZ@8BJ?lqWo z(trO*x13oQV4nE~;QLt!6@g~aem1by_FskbX}ydNo~Xc~I5Y)oS-4-Vb*`q9+Q6v5 zTE!N$FKvZM>YsPj{pX^f0xw9UV#qVYyA6X1tVrf+rma(kAHZHee&aP|U=F+*g@*CA zR^4}(z2Uv30w1r$5rZ`3aM>na@E)sgNl?i=`l`Ko3Q;@bes_3w*l`t1%RrVT&S~JD z;GR|B6abg5O5k-O(cq>ByoNALP0SV8)EkYaQy?u*yq`iw z2RYl`u4a9aej6=wHD0yqF1HUXg?JMtN;L-FUyRdN;Ll`#_i9V+7Bw@(fctOumH}7` z@{AAz?|1204&a~LPQYpmyyy4LB>|39jRChj;aeKu*{d<|)>bPEE#hiYNT(H}=Ef`U z?bdR&+%}q25Glkxx7(dGM5^XFZqY7;#-S*}U`B4$_y91K_i(CKDHf+cPf@DCwZw_4 zPB2)n!mVksZ+EK84qm{$IFtb3{#T0>~Y}+ck!A2Y`XM4)12s4DgkcWA`NFJ0YLD7x2nxtyr1n zz;B<`Io`#&zDwkRoou=t=f7O+wuCkTeAZ>jp)JIOtqxmfz+29-bB~^X^SS44%7=XQ$RQUm5m0TQLc*y1H1Asl$r22ZOXz~HTCfRn4 zfVWk_ruG2bB;U`I*X%sBYS_>ofE&aE-WKtE+5&Kkj#S?k^<3HlaEpup+@hXKTL8Ao z2)tJ1T-yP#RZal5D(Bh`fGu(YuSK;kZ2;IJD*#(m>(T~*wXy=QR!pvGSwn3-Oq6W zZ&!GaQ_j}AbGIpk=T+8S(R~L1++A)@HktuWwTJ`W?(j}mf!`zUbyPS+(Z50Pp}wJl zw|C}Jf!o8FzysBHf+Xle0AQ-Go|=hT0PydmjH$y!P-;Q}U;x(eGMy~|1MqZEY61da zrVkokrn3cL0G-SQB8X zZ<^}@fYYRM&4GjjxcOC;MJsT#ZWCT3>jAtdyuSyI4-tZ`Z%K$caWVp6Cm|!a0pI{x zD!#6=aP{3+;7Ap=hFr)BTpCpACDYX(n=EQmBW2RRrvjMjTiG*x&4G^}*xOn~t;#6@ zK265r(+BAyE*i*d01Ui8rCG9w1K^wHN=zT>!b?5_7Hv9_rUJ8gs{<@q`~q;Bj;7XB zUz2SAH1hmfPJ1+R4=F0}tkw58=e&Dm? zX@_*GT!aUB##`U4084fv?z*^C)b5Pa06dHE5mx#szGL@-I6T1CE4Np>jK{UTwDRx^ zz#b~@Z)pjSYn>%>bqBz%a^^hka+b)|9RRz^3Bb;BR^0(`RU(~1ghiZgL~~mMuycMg z9u_!DyA%N6yOgJ27X|(YT-Iz_?m;3>00000NkvXX Hu0mjfm>s5V literal 0 HcmV?d00001 From d20f6ddd1e06370dadcf0afe7debc8bf0f563334 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 08:50:43 +0100 Subject: [PATCH 390/489] Create RainbowClockFace.png --- apps/ac_ac/RainbowClockFace.png | Bin 0 -> 3493 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/RainbowClockFace.png diff --git a/apps/ac_ac/RainbowClockFace.png b/apps/ac_ac/RainbowClockFace.png new file mode 100644 index 0000000000000000000000000000000000000000..2defa759bc33a9c441c844e9f9950c6e0801ab5f GIT binary patch literal 3493 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 Date: Wed, 12 Jan 2022 08:50:48 +0100 Subject: [PATCH 391/489] Create simpleClockSize.png --- apps/ac_ac/simpleClockSize.png | Bin 0 -> 3203 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/simpleClockSize.png diff --git a/apps/ac_ac/simpleClockSize.png b/apps/ac_ac/simpleClockSize.png new file mode 100644 index 0000000000000000000000000000000000000000..49650586e01cdda1e25b2ac3aa464cb58f80d042 GIT binary patch literal 3203 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 Date: Wed, 12 Jan 2022 08:50:51 +0100 Subject: [PATCH 392/489] Create smartClockSize.png --- apps/ac_ac/smartClockSize.png | Bin 0 -> 3291 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/smartClockSize.png diff --git a/apps/ac_ac/smartClockSize.png b/apps/ac_ac/smartClockSize.png new file mode 100644 index 0000000000000000000000000000000000000000..6891acc89e7b1a3bbdd28e1d6e0944673e67aace GIT binary patch literal 3291 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 Z{{b@j@|O7s$qE1f002ovPDHLkV1h@MC+z?L literal 0 HcmV?d00001 From 4fcad7444e3d6bcf2334ecf48c520704a71f8632 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 08:50:53 +0100 Subject: [PATCH 393/489] Create simpleClockHands.png --- apps/ac_ac/simpleClockHands.png | Bin 0 -> 1446 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/simpleClockHands.png diff --git a/apps/ac_ac/simpleClockHands.png b/apps/ac_ac/simpleClockHands.png new file mode 100644 index 0000000000000000000000000000000000000000..820606f27cc11a8cbce78c9d8ef2da401f61dc12 GIT binary patch literal 1446 zcmeAS@N?(olHy`uVBq!ia0vp^8$g(Y4M?uv{v-}aF%}28J29*~C-ahlfi=O?#WAEJ z?(N;zWs4$2S}%V3D}PHa?a8%HH> zcK*G_a6n;+G=qh$-9yGSg}V#~UVh}{H(-9r#^BfQU(q1xVa`xcRda~>jKeO*hRctI zpQFVAN_lJhh{_eLbUNg

zG{7^zIy>?kTHy4;|a4cR+f^ zi5MlYrYOq{nf0@GOs(bl{q3RhVa5DMe(#yB^FK&49bWX8V_Wmu>K)2Q*dO%U|4>wX zpYd9b>x2KEc9%Vy*H%j$*#1F|>to-?cmLGh$vyC9+->Xk=F5qK9kX|6c9gSMK9Bxx z;NG!b`u+FwnmaysDD3a$-&D%a{zLFYy=|rSe_OdeRI47I-~DiJ zl@!a5XkBNevXmd6U)mlBe>Ib-aV!@zV58R?Opr_w>HYJ$>w@;vwr5yUHpEJUq3bbzC7w*yynKyTE+?{|OoA_dD!zXfM9c^kC=Nzd!b6cjy=B$J^H{ z=YM;=t##A8m$?ja6|?5cCzrCmi=W<9bx(m|-u2sW-&gGqoc*o(LVdi Date: Wed, 12 Jan 2022 08:50:56 +0100 Subject: [PATCH 394/489] Create roundedClockHands.png --- apps/ac_ac/roundedClockHands.png | Bin 0 -> 1390 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/roundedClockHands.png diff --git a/apps/ac_ac/roundedClockHands.png b/apps/ac_ac/roundedClockHands.png new file mode 100644 index 0000000000000000000000000000000000000000..cbd48e856985e2cb0c840b2336394bcb719f788a GIT binary patch literal 1390 zcmeAS@N?(olHy`uVBq!ia0vp^8$g(Y4M?uv{v-}aF%}28J29*~C-ahlfmOrP#WAEJ z?(LnoeYYY6SS~#MD?dy0qLARU{%%9zU9X;`A8T8;PWd(46ib=@VF3?1;uUF*euUzCW1E zxZbW;abB;5)CaAk{|9DwTgVw4DK1>+6UTUCXGQCwGuf*cfGXy8KTlZ4yr&B&#`ehT zfWY|!JB?Cx6P`a3mAhZ>Yy05p@{PqG%ahoC?2ilEx3gI9pWP9L_!6d%-x+Jo1P_>- zZDG1O@sZ@(`9CcWlz-#-c%Gr=dn`lUhJ&I<&K-R(RP(;BVg4KbN8cN2f8{lZo9|(| zxwE2hrga?K2kz4?KU!1&URcVof5!`uYJI)0y{8%PZP+7vWP6|R^4~JXW;%Z^+HdJM z+f}*vyTbgis`uh+9QIV+HP8RTa&O1^@Q?HEKkK<&oc#FF`aI@}$8z$viSzfW>^X0? ziZH)zlAlFulsjz^0!~_ zx7SVD_<6_Uc)ka7wPRX$7Tx`t(I@v`pZkF<<9vIi>TlU`+aK&TPqWTyC}*juTIt^L zzSeHfXO7VLX$*U|&*MIFUH|W!lQorp=lQ?9{Cb()O2&T-58U;CzTlpazW7b26|2dC z^H*vfJpXRzeD71(+ZBxW7NxaU+xl~36M3W_ Date: Wed, 12 Jan 2022 08:50:59 +0100 Subject: [PATCH 395/489] Create hollowClockHands.png --- apps/ac_ac/hollowClockHands.png | Bin 0 -> 1669 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/hollowClockHands.png diff --git a/apps/ac_ac/hollowClockHands.png b/apps/ac_ac/hollowClockHands.png new file mode 100644 index 0000000000000000000000000000000000000000..2dce42ef598eece0c07beaf0fe57fb6b38555834 GIT binary patch literal 1669 zcmeHI`#02i82)@`%#g@V%E=5iO|eMGu`^OExisVwyRk8Ju*z)=a=%Rx$EnS#M2Fp3 zotW%oMvVI~-?hogEv6z3^W}(!#tf~?4#w)Vf5QH_KfKTLoacGZdEfK?@)r7dxoN87 z)d2vSlrzr0J6!jv)UZ3qZJr6}mg@z}G4K0r`BUqRB6e?SIK8-^pThVMX!I1LdOK0)lvn&z0o>K6uv)AR|)0ld#7B z>eCGn9>b!vZ*(Qyd_u3AYfLwVNxU^KVRA#@7+m0!)GYymt|+|!yVl^feT+D(vS$ki zOgUv(d53Lvyi0YT4O3m7HNu%lGql&5Hi6tKnXG}iEsB?F3x<^upEbr(5h)%Hlsq^# zBSg`%MzHaoPg$y>^s0aiR6xVPTy45KZ0@hVHhp1?1$}Tow>yG2E&=Vn&XF$zNJo&@ zX4f;8TFO`$Q9>2n0-GvQ=@h@$zF!|4Md1D@^hWMcLq&GA_`h1qH0ux5Ew|p2RSNt!}D{;xV&t6s1|tLT3vEq+GKHV7u8QlvyP7b*&g8hssb*G%xuk^P)3zMDh~_F z0x%obXp#CXW4kf_BU?x6=DnuINV#ka+vT;@9f9q_x4x7M?=;IjXm&5Jyf%j>YZ`KJ z;#Fn#=o_|pW^1F#p{t_`1L7#Mi7)}PWuo+`K~&PCI@Gnt}> zvzHjVq5L=clY8g*4_~eq9rjJ3lq{z7GD+l{!KXu z<0^`6(5TK*{f^MgHv7Fp!O>vwO!7s(ho7w?A<#^DlN`7TT8`9KHC_if2_Xh)$I<-# z^mF`6_xk~Q)9mW&=s$|RQ4n@L7FAo8A(+&V>%hjX_RhouIBR%#u_GHw8W((Q$0W|O ze1LMFJY2X&JzHC5?eMdvCCoIEFURBh0n1hSdqj2ISG+3kk`|}D>9_GX*mKIYIzgDP zb%Sbn;ZAO|%@gVo~yCyYv-V3~{%XtddMD zKx@#S_SQuMY-&J7aTf@7?_DvRo|D@EbSAmW90N8@PYF|Q)NqP02M`WYuZ3Q>Jtri+ z9ph|38gdT2I;n^B1&f6E()88 zETtPHa!52bGNRMq>bOHCR?R0!h?TYfccG|%CxXv8pof+<%`*YKWt|fG--U8j>OiIW U{v?a^oxcJoE?&+Yr;FGA0bv~;9{>OV literal 0 HcmV?d00001 From 657cf26dc54e0b94bac8baa9cd865493202e2a37 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 09:43:39 +0100 Subject: [PATCH 396/489] Update Customizer.html --- apps/ac_ac/Customizer.html | 531 ++++++++++++++++++++++++++++++++++--- 1 file changed, 491 insertions(+), 40 deletions(-) diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index 6637b5df4..203235e3d 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -19,73 +19,524 @@ } + + + + + + + + + + - - - + + + -

A Configurable Analog Clock

- +

Please customize your analog clock for the Bangle.js 2 according to your needs. - When finished, click on "Upload". + When finished, click on "Upload" at the bottom of this form. +

-

Clock Size Calculation

+

Clock Size Calculation

-
-
- -  
+

+ Click on the desired clock size calculator (if you installed some widgets + on your Bangle.js 2, the smart one may produce larger clock faces than the + simple one): +

+ + + -

Clock Face

+ -
-
-  
-
-  
-
-  
+ + +
+
+ simple +
+
+ smart +
+
+ (custom) +
+

+ If you prefer a "custom" clock size calculator, please enter the URL + of its JavaScript module below: +

+ custom URL: +

-

Clock Hands

+

Clock Face

-
-
-
-   Hand Fill Color
+

+ Click on the desired clock face: +

+ + + -

Complications

+ -

Settings

+ - Foreground Color:
+ - Background Color:
+ + +
+
+ none +
+
+ four-fold +
+
+ twelve-fold +
+
+ "rainbow"
colored +
+
+ (custom) +
+

+ Clock faces are drawn in the configured foreground and background colors + (you may select them at the end of this form) +

+ The "twelve-fold" and "rainbow"-colored faces may be drawn with or without + dots marking the position of every minute. Which variant do you prefer? +

+ without dots
+ with dots +

+ If you prefer a "custom" clock face, please enter the URL + of its JavaScript module below: +

+ custom URL: +

- Second Hand Color:
+

Clock Hands

+

+ Click on the desired clock hands: +

+ + + + + + + + + + +
+
+ simple +
+
+ rounded +
+
+ hollow +
+
+ (custom) +
+

+ Clock hands are drawn in the configured foreground and background colors + (you may select them at the end of this form) +

+ Additionally, all clock hands may be drawn with or without second hands. + If you want them to be drawn, please click on their desired color below + (or choose "themed" to use your Bangle's configured theme) - if not, just + select "none": +

+ Second Hand Color:
+ + + + + + + + + + +

+ If you prefer "custom" clock hands, please enter the URL + of their JavaScript module below: +

+ custom URL: +

+ +

Complications

+ +

+ Complications are small displays for additional information. If you want + one or multiple complications to be added to your clock, you'll have to + specify which one to be loaded and where it should be placed. +

+ Up to 6 possible positions exist (top-left, top-right, left, right, + bottom-left and bottom-right). Alternatively, the positions "top-left" and + "top-right" may be traded for a slightly larger complication at position + "top" or "bottom-left" and "bottom-right" for one at the "bottom". +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
top-left:
  Complication: + +
custom URL:
top:
  Complication: + +
custom URL:
top-right:
  Complication: + +
custom URL:
left:
  Complication: + +
custom URL:
right:
  Complication: + +
custom URL:
bottom-left:
  Complication: + +
custom URL:
bottom:
  Complication: + +
custom URL:
bottom-right:
  Complication: + +
custom URL:
+

+ +

Settings

+ +

+ Color faces, hands and complications are often drawn using configurable + foreground and background colors. +

+ Here you may specify these colors. Click on a color to select it - or on + "themed" if you want the clock to use the currently configured theme on + your Bangle.js 2: +

+ Foreground Color:
+ +

+ +
+ + + + + + + + +

+ Background Color:
+ + + + + + + + + +

+ When you are satisfied with your configuration, just click on "Upload" in + order to generate the specified clock and upload it to your Bangle.js 2: +

+

From 10896c63ddb881ececcf1749c142989c07062dc0 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 10:07:15 +0100 Subject: [PATCH 397/489] Create app-icon.png --- apps/ac_ac/app-icon.png | Bin 0 -> 4120 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/app-icon.png diff --git a/apps/ac_ac/app-icon.png b/apps/ac_ac/app-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b83541133fb2fcdcc215cf294baa7f5565215f58 GIT binary patch literal 4120 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 WA~L?Y2T6SZ0000 Date: Wed, 12 Jan 2022 10:07:18 +0100 Subject: [PATCH 398/489] Create app-icon.js --- apps/ac_ac/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/ac_ac/app-icon.js diff --git a/apps/ac_ac/app-icon.js b/apps/ac_ac/app-icon.js new file mode 100644 index 000000000..20caf2c8e --- /dev/null +++ b/apps/ac_ac/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgn/ABH+AQPvBpIAI/n8/3f5/PCp/v9oHF7w1CABffGxAYMH4f9z/514YDCxW/O4gFBxwHD/ZEL7/9GgX8GwQLCBQQXH/uP/Hf/2N44IBAgIXJ7oaD/3v/3uAYIIB9wQGAA2+/iRG5oSIM4f+1nrPYgAB3aHIAC77QYYRoCAAP676ICABXYFIntDoPf3+PC5f+BoPOX4vPNBn7IogEB/eu3QXC9wNEAAeKBIP+dgbSCDYMwgEApQVEygPCeRH8iAWBAAMHPwXDgoRGAonACwYABgN5uMAC4q8GC4U0DQsAggRF9gXFgggB/2hC4kdVAQCBVAX7xwXCVAnGCwUadAeeDYfr7IhEAAf93e+A4gpB9yRB/mqcgndRgQAHzqRE1gEC/KoCjLZEsgCB9evO4gOC/RyEgqdC2KnFO4S/KgFYsC/Ga5EBs1AX5bXHgx1C2YXEnp7GCARgB4AfE64WCnawFCgf9VAK/G/3M7zWDz4PF/maXJIAD7D8EVAP85QXN3OP/42DfoQXN/wvE/ySGABa8FAC37AgepVwQ9E1SfBAAJIEAAnrBQ39xgwJ7pRHFQX+3QECCAbyG9bPDzwXC9QMBdgQXIAAf41wEC5pLCJJBcF9fZQ5IAGYYn81q7RJQwWC/wXM9/tA4veCxooDIAPv55PEABwpB97rDAAw")) \ No newline at end of file From 54ad33318a382b741a41e9d5fce4ad9b869449ae Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 10:08:42 +0100 Subject: [PATCH 399/489] Update README.md --- apps/ac_ac/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ac_ac/README.md b/apps/ac_ac/README.md index 0e0084b64..05e5f4798 100644 --- a/apps/ac_ac/README.md +++ b/apps/ac_ac/README.md @@ -22,10 +22,10 @@ Additionally, you may use the currently configured global theme or configure your own colors for clock fore- and background and second hands. Consequently, even without external modules you already have the choice between -87552 combinations! +102144 combinations! From 5e353b6755d97021a349a980db632aef75486bff Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 12 Jan 2022 09:14:33 +0000 Subject: [PATCH 400/489] messages : If showMessage called with no message (eg all messages deleted) now return to the clock (fix #1267) --- apps/messages/ChangeLog | 1 + apps/messages/app.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index 0c02a76e1..522534af0 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -27,3 +27,4 @@ 0.18: Use app-specific icon colors Spread message action buttons out Back button now goes back to list of messages + If showMessage called with no message (eg all messages deleted) now return to the clock (fix #1267) diff --git a/apps/messages/app.js b/apps/messages/app.js index 4704c422f..80e4a3244 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -225,7 +225,7 @@ function showMessageSettings(msg) { function showMessage(msgid) { var msg = MESSAGES.find(m=>m.id==msgid); - if (!msg) return checkMessages({clockIfNoMsg:0,clockIfAllRead:0,showMsgIfUnread:0}); // go home if no message found + if (!msg) return checkMessages({clockIfNoMsg:1,clockIfAllRead:0,showMsgIfUnread:0}); // go home if no message found if (msg.src=="Maps") { cancelReloadTimeout(); // don't auto-reload to clock now return showMapMessage(msg); From 3e6cfc95a9c4aaa6991dbe30c9b82fca681c87a8 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 12 Jan 2022 10:27:39 +0100 Subject: [PATCH 401/489] Improve layout and add exit menu item --- apps/banglexercise/README.md | 6 +++--- apps/banglexercise/app.js | 14 +++++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/apps/banglexercise/README.md b/apps/banglexercise/README.md index 9d8ee7be4..729fb60e3 100644 --- a/apps/banglexercise/README.md +++ b/apps/banglexercise/README.md @@ -6,7 +6,7 @@ Currently only push ups and curls are supported. ## Disclaimer -This app is very experimental. +This app is experimental but it seems to work quiet reliable for me. It could be and is likely that the threshold values for detecting exercises do not work for everyone. Therefore it would be great if we could improve this app together :-) @@ -25,8 +25,8 @@ Press stop to end your exercise. * Rope jumps * Sit ups * ... -* Save exercises to file system -* Add settings (vibration, beep, ...) +* Save exercise summaries to file system +* Configure daily goal for exercises * Find a nicer icon diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js index f5a532408..778207d26 100644 --- a/apps/banglexercise/app.js +++ b/apps/banglexercise/app.js @@ -81,6 +81,9 @@ function showMainMenu() { value: exerciseCounter + " " + exerciseType.name }; } + menu.Exit = function() { + load(); + }; E.showMenu(menu); } @@ -187,6 +190,7 @@ function isValidYAxisExercise(slopeY, t) { console.log(t, exerciseName + " half complete..."); layout.progress.label = "½"; + g.clear(); layout.render(); } @@ -215,6 +219,7 @@ function isValidYAxisExercise(slopeY, t) { layout.count.label = exerciseCounter; layout.progress.label = ""; + g.clear(); layout.render(); if (settings.buzz) @@ -279,10 +284,9 @@ function startRecording() { c: [{ type: "txt", id: "count", - font: "6x8:10", - label: exerciseCounter, - pad: 5, - bgCol: g.theme.bg + font: exerciseCounter < 100 ? "6x8:9" : "6x8:8", + label: 10, + pad: 5 }, { type: "txt", @@ -328,7 +332,7 @@ function startRecording() { stopRecording(); } }], - lazy: true + lazy: false }); layout.render(); From 4b8490645d11ca3c69ff99a4b78c6fbd8b4dc60f Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 12 Jan 2022 10:31:05 +0100 Subject: [PATCH 402/489] Fix typo and disable debug logging --- apps/banglexercise/README.md | 2 +- apps/banglexercise/app.js | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/banglexercise/README.md b/apps/banglexercise/README.md index 729fb60e3..28b276a59 100644 --- a/apps/banglexercise/README.md +++ b/apps/banglexercise/README.md @@ -13,7 +13,7 @@ Therefore it would be great if we could improve this app together :-) ## Usage -Select the exercise type you want to practive and go for it! +Select the exercise type you want to practice and go for it! Press stop to end your exercise. diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js index 778207d26..99ebd121e 100644 --- a/apps/banglexercise/app.js +++ b/apps/banglexercise/app.js @@ -187,7 +187,7 @@ function isValidYAxisExercise(slopeY, t) { if (p1 > 0 && p2 < 0) { if (lastZeroPassCameFromPositive == false) { lastExerciseHalfCompletionTime = t; - console.log(t, exerciseName + " half complete..."); + //console.log(t, exerciseName + " half complete..."); layout.progress.label = "½"; g.clear(); @@ -201,7 +201,7 @@ function isValidYAxisExercise(slopeY, t) { if (lastZeroPassCameFromPositive == true) { const tDiffLastExercise = t - lastExerciseCompletionTime; const tDiffStart = t - tStart; - console.log(t, exerciseName + " maybe complete?", Math.round(tDiffLastExercise), Math.round(tDiffStart)); + //console.log(t, exerciseName + " maybe complete?", Math.round(tDiffLastExercise), Math.round(tDiffStart)); // check minimal time between exercises: if ((lastExerciseCompletionTime <= 0 && tDiffStart >= thresholdMinTime) || tDiffLastExercise >= thresholdMinTime) { @@ -212,7 +212,7 @@ function isValidYAxisExercise(slopeY, t) { // check minimal duration of exercise: const tDiffExerciseHalfCompletion = t - lastExerciseHalfCompletionTime; if (tDiffExerciseHalfCompletion > thresholdMinDurationTime) { - console.log(t, exerciseName + " complete!!!"); + //console.log(t, exerciseName + " complete!!!"); lastExerciseCompletionTime = t; exerciseCounter++; @@ -225,15 +225,15 @@ function isValidYAxisExercise(slopeY, t) { if (settings.buzz) Bangle.buzz(100, 0.4); } else { - console.log(t, exerciseName + " to quick for duration time threshold!"); + //console.log(t, exerciseName + " to quick for duration time threshold!"); lastExerciseCompletionTime = t; } } else { - console.log(t, exerciseName + " to slow for time threshold!"); + //console.log(t, exerciseName + " to slow for time threshold!"); lastExerciseCompletionTime = t; } } else { - console.log(t, exerciseName + " to quick for time threshold!"); + //console.log(t, exerciseName + " to quick for time threshold!"); lastExerciseCompletionTime = t; } } From 797d5fbd8185f6459187c494b5433b12a5732f84 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 10:57:10 +0100 Subject: [PATCH 403/489] Update Customizer.html --- apps/ac_ac/Customizer.html | 186 +++++++++++++++++++++---------------- 1 file changed, 106 insertions(+), 80 deletions(-) diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index 203235e3d..59c08f2cd 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -26,11 +26,12 @@ default-src 'self' 'unsafe-inline' 'unsafe-eval' file: https:; "> - + + - + @@ -279,23 +302,24 @@ (or choose "themed" to use your Bangle's configured theme) - if not, just select "none":

- Second Hand Color:
- - - - - - - - - - + Second Hand Color: +

+ + + + + + + + + +

If you prefer "custom" clock hands, please enter the URL of their JavaScript module below: @@ -504,33 +528,35 @@ "themed" if you want the clock to use the currently configured theme on your Bangle.js 2:

- Foreground Color:
- -

- -
- - - - - - - - + Foreground Color:

- Background Color:
- - - - - - - - - + + + + + + + + + +

+ Background Color: +

+ + + + + + + + +

When you are satisfied with your configuration, just click on "Upload" in order to generate the specified clock and upload it to your Bangle.js 2: From f878a336529815a2ea358361d9a748fb5599cda1 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 10:58:21 +0100 Subject: [PATCH 404/489] Create app-screenshot.png --- apps/ac_ac/app-screenshot.png | Bin 0 -> 4042 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/app-screenshot.png diff --git a/apps/ac_ac/app-screenshot.png b/apps/ac_ac/app-screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..e0e3bb0b95de844ed0656d16023e71708c117f96 GIT binary patch literal 4042 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 literal 0 HcmV?d00001 From ffcdcbce6bf15fc19bc605130235dbd608f3d913 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 12 Jan 2022 11:24:04 +0100 Subject: [PATCH 405/489] Rename "recording" to "training" (because there is no recording for now) --- apps/banglexercise/app.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js index 99ebd121e..0d5c814bf 100644 --- a/apps/banglexercise/app.js +++ b/apps/banglexercise/app.js @@ -69,7 +69,7 @@ function showMainMenu() { menu["Do " + et.name] = function() { exerciseType = et; E.showMenu(); - startRecording(); + startTraining(); }; }); @@ -263,7 +263,7 @@ function reset() { } -function startRecording() { +function startTraining() { if (recordActive) return; g.clear(1); reset(); @@ -319,7 +319,7 @@ function startRecording() { type: "txt", id: "recording", font: "6x8:2", - label: "RECORDING", + label: "TRAINING", bgCol: "#f00", pad: 5, fillx: 1 @@ -329,7 +329,7 @@ function startRecording() { btns: [{ label: "STOP", cb: () => { - stopRecording(); + stopTraining(); } }], lazy: false @@ -344,7 +344,7 @@ function startRecording() { Bangle.buzz(200, 1); } -function stopRecording() { +function stopTraining() { if (!recordActive) return; g.clear(1); From ea44abb791634b60c454dbfb746c493ffac20614 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 12 Jan 2022 10:58:47 +0000 Subject: [PATCH 406/489] android 0.06: Option to keep messages after a disconnect (default false) (fix #1186) --- apps.json | 8 ++++--- apps/android/ChangeLog | 1 + apps/android/README.md | 48 ++++++++++++++++++++++++++++++++++++++++ apps/android/boot.js | 6 ++++- apps/android/settings.js | 20 +++++++++++++---- 5 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 apps/android/README.md diff --git a/apps.json b/apps.json index 882816204..bb55dcc17 100644 --- a/apps.json +++ b/apps.json @@ -99,18 +99,20 @@ "id": "android", "name": "Android Integration", "shortName": "Android", - "version": "0.05", + "version": "0.06", "description": "Display notifications/music/etc sent from the Gadgetbridge app on Android. This replaces the old 'Gadgetbridge' Bangle.js widget.", "icon": "app.png", "tags": "tool,system,messages,notifications", "dependencies": {"messages":"app"}, "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", "storage": [ {"name":"android.app.js","url":"app.js"}, {"name":"android.settings.js","url":"settings.js"}, {"name":"android.img","url":"app-icon.js","evaluate":true}, {"name":"android.boot.js","url":"boot.js"} ], + "data": [{"name":"android.settings.json"}], "sortorder": -8 }, { @@ -1357,7 +1359,7 @@ "shortName":"HR Alarm", "version":"0.01", "description": "This invisible widget vibrates whenever the heart rate gets close to the upper limit or goes over or under the configured limits", - "icon": "widget.png", + "icon": "widget.png", "type": "widget", "tags": "widget", "supports" : ["BANGLEJS2"], @@ -5185,7 +5187,7 @@ {"name":"mmind.app.js","url":"mmind.app.js"}, {"name":"mmind.img","url":"mmind.icon.js","evaluate":true} ] - }, + }, { "id": "presentor", "name": "Presentor", diff --git a/apps/android/ChangeLog b/apps/android/ChangeLog index c2c4ea6be..0d837fe43 100644 --- a/apps/android/ChangeLog +++ b/apps/android/ChangeLog @@ -4,3 +4,4 @@ 0.03: Handling of message actions (ok/clear) 0.04: Android icon now goes to settings page with 'find phone' 0.05: Fix handling of message actions +0.06: Option to keep messages after a disconnect (default false) (fix #1186) diff --git a/apps/android/README.md b/apps/android/README.md new file mode 100644 index 000000000..c10718aac --- /dev/null +++ b/apps/android/README.md @@ -0,0 +1,48 @@ +# Android Integration + +This app allows your Bangle.js to receive notifications [from the Gadgetbridge app on Android](http://www.espruino.com/Gadgetbridge) + +See [this link](http://www.espruino.com/Gadgetbridge) for notes on how to install +the Android app (and how it works). + +It requires the `Messages` app on Bangle.js (which should be automatically installed) to +display any notifications that are received. + +## Settings + +You can access the settings menu either from the `Android` icon in the launcher, +or from `App Settings` in the `Settings` menu. + +It contains: + +* `Connected` - shows whether there is an active Bluetooth connection or not +* `Find Phone` - opens a submenu where you can activate the `Find Phone` functionality +of Gadgetbridge - making your phone make noise so you can find it. +* `Keep Msgs` - default is `Off`. When Gadgetbridge disconnects, should Bangle.js +keep any messages it has received, or should it delete them? +* `Messages` - launches the messages app, showing a list of messages + +## How it works + +Gadgetbridge on Android connects to Bangle.js, and sends commands over the +BLE UART connection. These take the form of `GB({ ... JSON ... })\n` - so they +call a global function called `GB` which then interprets the JSON. + +Responses are sent back to Gadgetbridge simply as one line of JSON. + +More info on message formats on http://www.espruino.com/Gadgetbridge + +## Testing + +Bangle.js can only hold one connection open at a time, so it's hard to see +if there are any errors when handling Gadgetbridge messages. + +However you can: + +* Use the `Gadgetbridge Debug` app on Bangle.js to display/log the messages received from Gadgetbridge +* Connect with the Web IDE and manually enter the Gadgetbridge messages on the left-hand side to +execute them as if they came from Gadgetbridge, for instance: + +``` +GB({"t":"notify","id":1575479849,"src":"Hangouts","title":"A Name","body":"message contents"}) +``` diff --git a/apps/android/boot.js b/apps/android/boot.js index 59ffe006d..fff9ad444 100644 --- a/apps/android/boot.js +++ b/apps/android/boot.js @@ -4,6 +4,7 @@ Bluetooth.println(JSON.stringify(message)); } + var settings = require("Storage").readJSON("android.settings.json",1)||{}; var _GB = global.GB; global.GB = (event) => { // feed a copy to other handlers if there were any @@ -51,7 +52,8 @@ // Battery monitor function sendBattery() { gbSend({ t: "status", bat: E.getBattery() }); } NRF.on("connect", () => setTimeout(sendBattery, 2000)); - NRF.on("disconnect", () => require("messages").clearAll()); // remove all messages on disconnect + if (!settings.keep) + NRF.on("disconnect", () => require("messages").clearAll()); // remove all messages on disconnect setInterval(sendBattery, 10*60*1000); // Health tracking Bangle.on('health', health=>{ @@ -68,4 +70,6 @@ if (isFinite(msg.id)) return gbSend({ t: "notify", n:response?"OPEN":"DISMISS", id: msg.id }); // error/warn here? }; + // remove settings object so it's not taking up RAM + delete settings; })(); diff --git a/apps/android/settings.js b/apps/android/settings.js index d241397a4..7c46a1fc0 100644 --- a/apps/android/settings.js +++ b/apps/android/settings.js @@ -2,17 +2,29 @@ function gb(j) { Bluetooth.println(JSON.stringify(j)); } + var settings = require("Storage").readJSON("android.settings.json",1)||{}; + function updateSettings() { + require("Storage").writeJSON("android.settings.json", settings); + } var mainmenu = { "" : { "title" : "Android" }, "< Back" : back, - "Connected" : { value : NRF.getSecurityStatus().connected?"Yes":"No" }, + /*LANG*/"Connected" : { value : NRF.getSecurityStatus().connected?"Yes":"No" }, "Find Phone" : () => E.showMenu({ "" : { "title" : "Find Phone" }, "< Back" : ()=>E.showMenu(mainmenu), - "On" : _=>gb({t:"findPhone",n:true}), - "Off" : _=>gb({t:"findPhone",n:false}), + /*LANG*/"On" : _=>gb({t:"findPhone",n:true}), + /*LANG*/"Off" : _=>gb({t:"findPhone",n:false}), }), - "Messages" : ()=>load("messages.app.js") + /*LANG*/"Keep Msgs" : { + value : !!settings.keep, + format : v=>v?/*LANG*/"Yes":/*LANG*/"No", + onchange: v => { + settings.keep = v; + updateSettings(); + } + }, + /*LANG*/"Messages" : ()=>load("messages.app.js") }; E.showMenu(mainmenu); }) From 569c5f9e2b5ef2d59770e244db4adffed8a1d586 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 12 Jan 2022 10:59:02 +0000 Subject: [PATCH 407/489] Add LANG tags to settings for translations --- apps/setting/settings.js | 122 +++++++++++++++++++-------------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/apps/setting/settings.js b/apps/setting/settings.js index 27ce24e50..514adf1dd 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -63,7 +63,7 @@ const boolFormat = v => v ? /*LANG*/"On" : /*LANG*/"Off"; function showMainMenu() { const mainmenu = { - '': { 'title': 'Settings' }, + '': { 'title': /*LANG*/'Settings' }, '< Back': ()=>load(), /*LANG*/'Apps': ()=>showAppSettingsMenu(), /*LANG*/'System': ()=>showSystemMenu(), @@ -78,7 +78,7 @@ function showMainMenu() { function showSystemMenu() { const mainmenu = { - '': { 'title': 'System' }, + '': { 'title': /*LANG*/'System' }, '< Back': ()=>showMainMenu(), /*LANG*/'Theme': ()=>showThemeMenu(), /*LANG*/'LCD': ()=>showLCDMenu(), @@ -122,7 +122,7 @@ function showAlertsMenu() { } const mainmenu = { - '': { 'title': 'Alerts' }, + '': { 'title': /*LANG*/'Alerts' }, '< Back': ()=>showMainMenu(), /*LANG*/'Beep': beepMenuItem, /*LANG*/'Vibration': { @@ -159,8 +159,8 @@ function showBLEMenu() { E.showMenu({ '': { 'title': 'Bluetooth' }, '< Back': ()=>showMainMenu(), - 'Make Connectable': ()=>makeConnectable(), - 'BLE': { + /*LANG*/'Make Connectable': ()=>makeConnectable(), + /*LANG*/'BLE': { value: settings.ble, format: boolFormat, onchange: () => { @@ -168,7 +168,7 @@ function showBLEMenu() { updateSettings(); } }, - 'Programmable': { + /*LANG*/'Programmable': { value: settings.blerepl, format: boolFormat, onchange: () => { @@ -176,7 +176,7 @@ function showBLEMenu() { updateSettings(); } }, - 'HID': { + /*LANG*/'HID': { value: Math.max(0,0 | hidV.indexOf(settings.HID)), min: 0, max: 3, format: v => hidN[v], @@ -185,11 +185,11 @@ function showBLEMenu() { updateSettings(); } }, - 'Passkey BETA': { + /*LANG*/'Passkey BETA': { value: settings.passkey?settings.passkey:"none", onchange: () => setTimeout(showPasskeyMenu) // graphical_menu redraws after the call }, - 'Whitelist': { + /*LANG*/'Whitelist': { value: settings.whitelist?(settings.whitelist.length+" devs"):"off", onchange: () => setTimeout(showWhitelistMenu) // graphical_menu redraws after the call } @@ -213,7 +213,7 @@ function showThemeMenu() { var m = E.showMenu({ '':{title:'Theme'}, '< Back': ()=>showSystemMenu(), - 'Dark BW': ()=>{ + /*LANG*/'Dark BW': ()=>{ upd({ fg:cl("#fff"), bg:cl("#000"), fg2:cl("#0ff"), bg2:cl("#000"), @@ -221,7 +221,7 @@ function showThemeMenu() { dark:true }); }, - 'Light BW': ()=>{ + /*LANG*/'Light BW': ()=>{ upd({ fg:cl("#000"), bg:cl("#fff"), fg2:cl("#000"), bg2:cl("#cff"), @@ -229,7 +229,7 @@ function showThemeMenu() { dark:false }); }, - 'Customize': ()=>showCustomThemeMenu(), + /*LANG*/'Customize': ()=>showCustomThemeMenu(), }); function showCustomThemeMenu() { @@ -261,9 +261,9 @@ function showThemeMenu() { "< Back": () => showThemeMenu() }; const labels = { - fg: 'Foreground', bg: 'Background', - fg2: 'Foreground 2', bg2: 'Background 2', - fgH: 'Highlight FG', bgH: 'Highlight BG', + fg: /*LANG*/'Foreground', bg: /*LANG*/'Background', + fg2: /*LANG*/'Foreground 2', bg2: /*LANG*/'Background 2', + fgH: /*LANG*/'Highlight FG', bgH: /*LANG*/'Highlight BG', }; ["fg", "bg", "fg2", "bg2", "fgH", "bgH"].forEach(t => { menu[labels[t]] = { @@ -292,7 +292,7 @@ function showThemeMenu() { function showPasskeyMenu() { var menu = { "< Back" : ()=>showBLEMenu(), - "Disable" : () => { + /*LANG*/"Disable" : () => { settings.passkey = undefined; updateSettings(); showBLEMenu(); @@ -320,7 +320,7 @@ function showPasskeyMenu() { function showWhitelistMenu() { var menu = { "< Back" : ()=>showBLEMenu(), - "Disable" : () => { + /*LANG*/"Disable" : () => { settings.whitelist = undefined; updateSettings(); showBLEMenu(); @@ -328,7 +328,7 @@ function showWhitelistMenu() { }; if (settings.whitelist) settings.whitelist.forEach(function(d){ menu[d.substr(0,17)] = function() { - E.showPrompt('Remove\n'+d).then((v) => { + E.showPrompt(/*LANG*/'Remove\n'+d).then((v) => { if (v) { settings.whitelist.splice(settings.whitelist.indexOf(d),1); updateSettings(); @@ -337,8 +337,8 @@ function showWhitelistMenu() { }); } }); - menu['Add Device']=function() { - E.showAlert("Connect device\nto add to\nwhitelist","Whitelist").then(function() { + menu[/*LANG*/'Add Device']=function() { + E.showAlert(/*LANG*/"Connect device\nto add to\nwhitelist",/*LANG*/"Whitelist").then(function() { NRF.removeAllListeners('connect'); showWhitelistMenu(); }); @@ -358,7 +358,7 @@ function showLCDMenu() { const lcdMenu = { '': { 'title': 'LCD' }, '< Back': ()=>showSystemMenu(), - 'LCD Brightness': { + /*LANG*/'LCD Brightness': { value: settings.brightness, min: 0.1, max: 1, @@ -369,7 +369,7 @@ function showLCDMenu() { Bangle.setLCDBrightness(settings.brightness); } }, - 'LCD Timeout': { + /*LANG*/'LCD Timeout': { value: settings.timeout, min: 0, max: 60, @@ -380,7 +380,7 @@ function showLCDMenu() { Bangle.setLCDTimeout(settings.timeout); } }, - 'Wake on BTN1': { + /*LANG*/'Wake on BTN1': { value: settings.options.wakeOnBTN1, format: boolFormat, onchange: () => { @@ -391,7 +391,7 @@ function showLCDMenu() { }; if (!BANGLEJS2) Object.assign(lcdMenu, { - 'Wake on BTN2': { + /*LANG*/'Wake on BTN2': { value: settings.options.wakeOnBTN2, format: boolFormat, onchange: () => { @@ -399,7 +399,7 @@ function showLCDMenu() { updateOptions(); } }, - 'Wake on BTN3': { + /*LANG*/'Wake on BTN3': { value: settings.options.wakeOnBTN3, format: boolFormat, onchange: () => { @@ -408,7 +408,7 @@ function showLCDMenu() { } }}); Object.assign(lcdMenu, { - 'Wake on FaceUp': { + /*LANG*/'Wake on FaceUp': { value: settings.options.wakeOnFaceUp, format: boolFormat, onchange: () => { @@ -416,7 +416,7 @@ function showLCDMenu() { updateOptions(); } }, - 'Wake on Touch': { + /*LANG*/'Wake on Touch': { value: settings.options.wakeOnTouch, format: boolFormat, onchange: () => { @@ -424,7 +424,7 @@ function showLCDMenu() { updateOptions(); } }, - 'Wake on Twist': { + /*LANG*/'Wake on Twist': { value: settings.options.wakeOnTwist, format: boolFormat, onchange: () => { @@ -432,7 +432,7 @@ function showLCDMenu() { updateOptions(); } }, - 'Twist Threshold': { + /*LANG*/'Twist Threshold': { value: internalToG(settings.options.twistThreshold), min: -0.5, max: 0.5, @@ -442,7 +442,7 @@ function showLCDMenu() { updateOptions(); } }, - 'Twist Max Y': { + /*LANG*/'Twist Max Y': { value: settings.options.twistMaxY, min: -1500, max: 1500, @@ -452,7 +452,7 @@ function showLCDMenu() { updateOptions(); } }, - 'Twist Timeout': { + /*LANG*/'Twist Timeout': { value: settings.options.twistTimeout, min: 0, max: 2000, @@ -468,9 +468,9 @@ function showLCDMenu() { function showLocaleMenu() { const localemenu = { - '': { 'title': 'Locale' }, + '': { 'title': /*LANG*/'Locale' }, '< Back': ()=>showSystemMenu(), - 'Time Zone': { + /*LANG*/'Time Zone': { value: settings.timezone, min: -11, max: 13, @@ -480,7 +480,7 @@ function showLocaleMenu() { updateSettings(); } }, - 'Clock Style': { + /*LANG*/'Clock Style': { value: !!settings["12hour"], format: v => v ? "12hr" : "24hr", onchange: v => { @@ -494,29 +494,29 @@ function showLocaleMenu() { function showUtilMenu() { var menu = { - '': { 'title': 'Utilities' }, + '': { 'title': /*LANG*/'Utilities' }, '< Back': ()=>showMainMenu(), - 'Debug Info': { + /*LANG*/'Debug Info': { value: E.clip(0|settings.log,0,2), min: 0, max: 2, - format: v => ["Hide","Show","Log"][E.clip(0|v,0,2)], + format: v => [/*LANG*/"Hide",/*LANG*/"Show",/*LANG*/"Log"][E.clip(0|v,0,2)], onchange: v => { settings.log = v; updateSettings(); } }, - 'Compact Storage': () => { - E.showMessage("Compacting...\nTakes approx\n1 minute",{title:"Storage"}); + /*LANG*/'Compact Storage': () => { + E.showMessage(/*LANG*/"Compacting...\nTakes approx\n1 minute",{title:/*LANG*/"Storage"}); require("Storage").compact(); showUtilMenu(); }, - 'Rewrite Settings': () => { + /*LANG*/'Rewrite Settings': () => { require("Storage").write(".boot0","eval(require('Storage').read('bootupdate.js'));"); load("setting.app.js"); }, - 'Flatten Battery': () => { - E.showMessage('Flattening battery - this can take hours.\nLong-press button to cancel.'); + /*LANG*/'Flatten Battery': () => { + E.showMessage(/*LANG*/'Flattening battery - this can take hours.\nLong-press button to cancel.'); Bangle.setLCDTimeout(0); Bangle.setLCDPower(1); if (Bangle.setGPSPower) Bangle.setGPSPower(1,"flat"); @@ -528,8 +528,8 @@ function showUtilMenu() { var i=1000;while (i--); }, 1); }, - 'Reset Settings': () => { - E.showPrompt('Reset to Defaults?',{title:"Settings"}).then((v) => { + /*LANG*/'Reset Settings': () => { + E.showPrompt(/*LANG*/'Reset to Defaults?',{title:/*LANG*/"Settings"}).then((v) => { if (v) { E.showMessage('Resetting'); resetSettings(); @@ -540,8 +540,8 @@ function showUtilMenu() { /*LANG*/'Turn Off': ()=>{ if (Bangle.softOff) Bangle.softOff(); else Bangle.off() } }; if (Bangle.factoryReset) { - menu['Factory Reset'] = ()=>{ - E.showPrompt('This will remove everything!',{title:"Factory Reset"}).then((v) => { + menu[/*LANG*/'Factory Reset'] = ()=>{ + E.showPrompt(/*LANG*/'This will remove everything!',{title:/*LANG*/"Factory Reset"}).then((v) => { if (v) { E.showMessage(); Terminal.setConsole(); @@ -558,7 +558,7 @@ function makeConnectable() { try { NRF.wake(); } catch (e) { } Bluetooth.setConsole(1); var name = "Bangle.js " + NRF.getAddress().substr(-5).replace(":", ""); - E.showPrompt(name + "\nStay Connectable?", { title: "Connectable" }).then(r => { + E.showPrompt(name + /*LANG*/"\nStay Connectable?", { title: /*LANG*/"Connectable" }).then(r => { if (settings.ble != r) { settings.ble = r; updateSettings(); @@ -574,7 +574,7 @@ function showClockMenu() { .sort((a, b) => a.sortorder - b.sortorder); const clockMenu = { '': { - 'title': 'Select Clock', + 'title': /*LANG*/'Select Clock', }, '< Back': ()=>showSystemMenu(), }; @@ -592,7 +592,7 @@ function showClockMenu() { }; }); if (clockApps.length === 0) { - clockMenu["No Clocks Found"] = () => { }; + clockMenu[/*LANG*/"No Clocks Found"] = () => { }; } return E.showMenu(clockMenu); } @@ -600,47 +600,47 @@ function showClockMenu() { function showSetTimeMenu() { d = new Date(); const timemenu = { - '': { 'title': 'Set Time' }, + '': { 'title': /*LANG*/'Set Time' }, '< Back': function () { setTime(d.getTime() / 1000); showSystemMenu(); }, - 'Hour': { + /*LANG*/'Hour': { value: d.getHours(), onchange: function (v) { this.value = (v+24)%24; d.setHours(this.value); } }, - 'Minute': { + /*LANG*/'Minute': { value: d.getMinutes(), onchange: function (v) { this.value = (v+60)%60; d.setMinutes(this.value); } }, - 'Second': { + /*LANG*/'Second': { value: d.getSeconds(), onchange: function (v) { this.value = (v+60)%60; d.setSeconds(this.value); } }, - 'Date': { + /*LANG*/'Date': { value: d.getDate(), onchange: function (v) { this.value = ((v+30)%31)+1; d.setDate(this.value); } }, - 'Month': { + /*LANG*/'Month': { value: d.getMonth() + 1, onchange: function (v) { this.value = ((v+11)%12)+1; d.setMonth(this.value - 1); } }, - 'Year': { + /*LANG*/'Year': { value: d.getFullYear(), min: 2019, max: 2100, @@ -654,7 +654,7 @@ function showSetTimeMenu() { function showAppSettingsMenu() { let appmenu = { - '': { 'title': 'App Settings' }, + '': { 'title': /*LANG*/'App Settings' }, '< Back': ()=>showMainMenu(), } const apps = storage.list(/\.settings\.js$/) @@ -671,7 +671,7 @@ function showAppSettingsMenu() { return 0; }) if (apps.length === 0) { - appmenu['No app has settings'] = () => { }; + appmenu[/*LANG*/'No app has settings'] = () => { }; } apps.forEach(function (app) { appmenu[app.name] = () => { showAppSettings(app) }; @@ -688,17 +688,17 @@ function showAppSettings(app) { appSettings = eval(appSettings); } catch (e) { console.log(`${app.name} settings error:`, e) - return showError('Error in settings'); + return showError(/*LANG*/'Error in settings'); } if (typeof appSettings !== "function") { - return showError('Invalid settings'); + return showError(/*LANG*/'Invalid settings'); } try { // pass showAppSettingsMenu as "back" argument appSettings(()=>showAppSettingsMenu()); } catch (e) { console.log(`${app.name} settings error:`, e) - return showError('Error in settings'); + return showError(/*LANG*/'Error in settings'); } } From fc8e089fbe43621862b00df5b2a014d61f0bfca9 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 12 Jan 2022 11:05:27 +0000 Subject: [PATCH 408/489] improve sanity checking - no false warnings for apps files with `supports` field --- bin/sanitycheck.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index e50256fb6..98fd1275f 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -58,6 +58,7 @@ const APP_KEYS = [ ]; const STORAGE_KEYS = ['name', 'url', 'content', 'evaluate', 'noOverwite', 'supports']; const DATA_KEYS = ['name', 'wildcard', 'storageFile', 'url', 'content', 'evaluate']; +const SUPPORTS_DEVICES = ["BANGLEJS","BANGLEJS2"]; // device IDs allowed for 'supports' const FORBIDDEN_FILE_NAME_CHARS = /[,;]/; // used as separators in appid.info const VALID_DUPLICATES = [ '.tfmodel', '.tfnames' ]; const GRANDFATHERED_ICONS = ["s7clk", "snek", "astral", "alpinenav", "slomoclock", "arrow", "pebble", "rebble"]; @@ -90,7 +91,7 @@ apps.forEach((app,appIdx) => { if (!Array.isArray(app.supports)) ERROR(`App ${app.id} has no 'supports' field or it's not an array`); else { app.supports.forEach(dev => { - if (!["BANGLEJS","BANGLEJS2"].includes(dev)) + if (!SUPPORTS_DEVICES.includes(dev)) ERROR(`App ${app.id} has unknown device in 'supports' field - ${dev}`); }); } @@ -140,6 +141,13 @@ apps.forEach((app,appIdx) => { if (char) ERROR(`App ${app.id} storage file ${file.name} contains invalid character "${char[0]}"`) if (fileNames.includes(file.name) && !file.supports) // assume that there aren't duplicates if 'supports' is set ERROR(`App ${app.id} file ${file.name} is a duplicate`); + if (file.supports && !Array.isArray(file.supports)) + ERROR(`App ${app.id} file ${file.name} supports field must be an array`); + if (file.supports) + file.supports.forEach(dev => { + if (!SUPPORTS_DEVICES.includes(dev)) + ERROR(`App ${app.id} file ${file.name} has unknown device in 'supports' field - ${dev}`); + }); fileNames.push(file.name); allFiles.push({app: app.id, file: file.name}); if (file.url) if (!fs.existsSync(appDir+file.url)) ERROR(`App ${app.id} file ${file.url} doesn't exist`); @@ -271,7 +279,8 @@ while(fileA=allFiles.pop()) { if (globA.test(nameB)||globB.test(nameA)) { if (isGlob(nameA)||isGlob(nameB)) ERROR(`App ${fileB.app} ${typeB} file ${nameB} matches app ${fileA.app} ${typeB} file ${nameA}`) - else WARN(`App ${fileB.app} ${typeB} file ${nameB} is also listed as ${typeA} file for app ${fileA.app}`) + else if (fileA.app != fileB.app) + WARN(`App ${fileB.app} ${typeB} file ${nameB} is also listed as ${typeA} file for app ${fileA.app}`) } }) } From bda5512db423bf6e2c9f7ceb0b622e874f0bf85e Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 13:02:52 +0100 Subject: [PATCH 409/489] Update Customizer.html --- apps/ac_ac/Customizer.html | 335 ++++++++++++++++++++++++++++++------- 1 file changed, 279 insertions(+), 56 deletions(-) diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index 59c08f2cd..5c60c0aa4 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -26,13 +26,10 @@ default-src 'self' 'unsafe-inline' 'unsafe-eval' file: https:; "> - - + - - - - + + @@ -235,17 +212,17 @@ switch (ClockSize) { case 'simple': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-simple-clock-size/main/ClockSize.js')" case 'smart': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-smart-clock-size/main/ClockSize.js')" - case 'custom': return 'require(' + ClockSizeURL + ')' + case 'custom': return "require('" + ClockSizeURL + "')" } } function chosenClockFace () { switch (ClockFace) { - case 'none': return undefined + case 'none': return "undefined" case 'four-fold': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-four-fold-clock-face/main/ClockFace.js')" case 'twelve-fold': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-twelve-fold-clock-face/main/ClockFace.js')" case 'rainbow': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-rainbow-clock-face/main/ClockFace.js')" - case 'custom': return 'require(' + ClockFaceURL + ')' + case 'custom': return "require('" + ClockFaceURL + "')" } } @@ -254,18 +231,18 @@ case 'simple': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-simpled-clock-hands/main/ClockHands.js')" case 'rounded': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-rounded-clock-hands/main/ClockHands.js')" case 'hollow': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-hollow-clock-hands/main/ClockHands.js')" - case 'custom': return 'require(' + ClockHandsURL + ')' + case 'custom': return "require('" + ClockHandsURL + "')" } } function chosenComplication (Complication, customURL) { switch (Complication) { - case 'none': return undefined + case 'none': return "undefined" case 'date': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-date-complication/main/Complication.js')" case 'weekday': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-weekday-complication/main/Complication.js')" case 'calendar-week': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-calendar-week-complication/main/Complication.js')" case 'moon-phase': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-moon-phase-complication/main/Complication.js')" - case 'custom': return 'require(' + customURL + ')' + case 'custom': return "require('" + customURL + "')" } } function chosenComplicationAt (Position) { @@ -282,7 +259,7 @@ } function chosenColor (ColorChoice) { - return (ColorChoice === 'none' ? undefined : ColorChoice) + return (ColorChoice === 'none' ? 'undefined' : "'" + ColorChoice + '"') } function chosenForeground () { return chosenColor(Foreground) } @@ -290,7 +267,7 @@ function chosenSecondHand () { return chosenColor(SecondHand) } function chosenFillColor () { return chosenColor(FillColor) } - function chosenDots () { return (ClockFaceDots === 'with-dots') } + function chosenDots () { return (ClockFaceDots === 'with-dots' ? 'true' : 'false') } let AppSource = ` let Clockwork = require('https://raw.githubusercontent.com/rozek/banglejs-2-simple-clockwork/main/Clockwork.js'); From 8bd074131da4d9c09aa9521297d603018345e4f7 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 15:55:00 +0100 Subject: [PATCH 421/489] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 1ef111b1d..fd0920156 100644 --- a/apps.json +++ b/apps.json @@ -32,7 +32,7 @@ { "id": "ac_ac", "name": "A Configurable Analog Clock", "shortName":"Configurable Clock", - "version":"0.01", + "version":"0.02", "description": "AC-AC, a highly customizable analog clock", "icon": "app-icon.png", "type": "clock", From 3636b32084fbfec92ff1db5ecfcbdacb71883adf Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 15:58:20 +0100 Subject: [PATCH 422/489] Update Customizer.html --- apps/ac_ac/Customizer.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index 113f4279b..2bfab8d51 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -295,6 +295,9 @@ Clockwork.windUp({ FillColor: ${chosenFillColor()} }); ` +console.log('the configured AC-AC app looks as follows:') +console.log(AppSource) + sendCustomizedApp({ storage:[ {name:'ac-ac.app.js', url:'app.js', content:AppSource}, From 4429288362574ad7b23f3bb7b495dba4aa45207c Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 16:02:28 +0100 Subject: [PATCH 423/489] Update Customizer.html --- apps/ac_ac/Customizer.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index 2bfab8d51..f2387f9dd 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -259,7 +259,7 @@ } function chosenColor (ColorChoice) { - return (ColorChoice === 'none' ? 'undefined' : "'" + ColorChoice + '"') + return (ColorChoice === 'none' ? 'undefined' : "'" + ColorChoice + "'") } function chosenForeground () { return chosenColor(Foreground) } From 40c8d69b1e64ee691eb69f66d579bcd4c260123f Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 16:02:30 +0100 Subject: [PATCH 424/489] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index fd0920156..1ef111b1d 100644 --- a/apps.json +++ b/apps.json @@ -32,7 +32,7 @@ { "id": "ac_ac", "name": "A Configurable Analog Clock", "shortName":"Configurable Clock", - "version":"0.02", + "version":"0.01", "description": "AC-AC, a highly customizable analog clock", "icon": "app-icon.png", "type": "clock", From 116dec3cb98aa074e72cfa8a7cd1ab6e8be7c51e Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 16:36:28 +0100 Subject: [PATCH 425/489] Update Customizer.html --- apps/ac_ac/Customizer.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index f2387f9dd..f50def79b 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -300,7 +300,7 @@ console.log(AppSource) sendCustomizedApp({ storage:[ - {name:'ac-ac.app.js', url:'app.js', content:AppSource}, + {name:'ac_ac.app.js', url:'app.js', content:AppSource}, ] }) } From f6b064d20f45be365b4463a981f6613638469701 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 16:36:31 +0100 Subject: [PATCH 426/489] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 1ef111b1d..fd0920156 100644 --- a/apps.json +++ b/apps.json @@ -32,7 +32,7 @@ { "id": "ac_ac", "name": "A Configurable Analog Clock", "shortName":"Configurable Clock", - "version":"0.01", + "version":"0.02", "description": "AC-AC, a highly customizable analog clock", "icon": "app-icon.png", "type": "clock", From 276fdd647e757b60de647b9ae6b56ecda5172fc4 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 16:45:28 +0100 Subject: [PATCH 427/489] Update Customizer.html --- apps/ac_ac/Customizer.html | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index f50def79b..a2798b6bd 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -208,6 +208,14 @@ /**** createAndUploadApp ****/ function createAndUploadApp () { + function WidgetsOnBackground () { + return ( + ClockSize === 'smart' + ? "require('https://raw.githubusercontent.com/rozek/banglejs-2-widgets-on-background/main/drawWidgets.js');" + : '' + ) + } + function chosenClockSize () { switch (ClockSize) { case 'simple': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-simple-clock-size/main/ClockSize.js')" @@ -270,6 +278,8 @@ function chosenDots () { return (ClockFaceDots === 'with-dots' ? 'true' : 'false') } let AppSource = ` +${WidgetsOnBackground()} + let Clockwork = require('https://raw.githubusercontent.com/rozek/banglejs-2-simple-clockwork/main/Clockwork.js'); Clockwork.windUp({ From 3fdbfd6b850c2f4c4bb616d550a66ac3c2dea3a7 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 16:45:32 +0100 Subject: [PATCH 428/489] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index fd0920156..1ef111b1d 100644 --- a/apps.json +++ b/apps.json @@ -32,7 +32,7 @@ { "id": "ac_ac", "name": "A Configurable Analog Clock", "shortName":"Configurable Clock", - "version":"0.02", + "version":"0.01", "description": "AC-AC, a highly customizable analog clock", "icon": "app-icon.png", "type": "clock", From 12254e06f3cfde37db3c5992d04c2586d2d0ecd5 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 12 Jan 2022 15:46:38 +0000 Subject: [PATCH 429/489] Add 'run' app --- apps.json | 13 ++++ apps/run/ChangeLog | 1 + apps/run/README.md | 33 +++++++++ apps/run/app-icon.js | 1 + apps/run/app.js | 159 +++++++++++++++++++++++++++++++++++++++++++ apps/run/app.png | Bin 0 -> 1479 bytes 6 files changed, 207 insertions(+) create mode 100644 apps/run/ChangeLog create mode 100644 apps/run/README.md create mode 100644 apps/run/app-icon.js create mode 100644 apps/run/app.js create mode 100644 apps/run/app.png diff --git a/apps.json b/apps.json index 93b1cf44e..adc98ff2b 100644 --- a/apps.json +++ b/apps.json @@ -2277,6 +2277,19 @@ {"name":"buffgym.img","url":"buffgym-icon.js","evaluate":true} ] }, + { "id": "run", + "name": "Run", + "version":"0.01", + "description": "Displays distance, time, steps, cadence, pace and more for runners.", + "icon": "app.png", + "tags": "run,running,fitness,outdoors,gps", + "supports" : ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"run.app.js","url":"app.js"}, + {"name":"run.img","url":"app-icon.js","evaluate":true} + ] + }, { "id": "banglerun", "name": "BangleRun", diff --git a/apps/run/ChangeLog b/apps/run/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/run/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/run/README.md b/apps/run/README.md new file mode 100644 index 000000000..34ad6511b --- /dev/null +++ b/apps/run/README.md @@ -0,0 +1,33 @@ +# Run App + +This app allows you to display the status of your run. + +To use it, start the app and press the middle button so that +the red `STOP` in the bottom right turns to a green `RUN`. + +## Display + +* `DIST` - the distance travelled based on the GPS (if you have a GPS lock). + * NOTE: this is based on the GPS coordinates which are not 100% accurate, especially initially. As + the GPS updates your position as it gets more satellites your position changes and the distance + shown will increase, even if you are standing still. +* `TIME` - the elapsed time for your run +* `PACE` - the number of minutes it takes you to run a kilometer **based on your run so far** +* `HEART` - Your heart rate +* `STEPS` - Steps since you started exercising +* `CADENCE` - Steps per second based on your step rate *over the last minute* +* `GPS` - this is green if you have a GPS lock. GPS is turned on automatically +so if you have no GPS lock you just need to wait. +* The current time is displayed right at the bottom of the screen +* `RUN/STOP` - whether the distance for your run is being displayed or not + +## Recording Tracks + +`Run` doesn't directly allow you to record your tracks at the moment. +However you can just install the `Recorder` app, turn recording on in +that, and then start the `Run` app. + +## TODO + +* Allow this app to trigger the `Recorder` app on and off directly. +* Keep a log of each run's stats (distance/steps/etc) diff --git a/apps/run/app-icon.js b/apps/run/app-icon.js new file mode 100644 index 000000000..a97d1b8ce --- /dev/null +++ b/apps/run/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4UA///pH9vEFt9TIW0FqALJitUBZNVqoLqgo4BHZAUBtBTHgILB1XAEREV1WsEQ9AgWq1ALHgEO1WtBYxCBhWq0pdInWq2tABY8q1WVBZGq1XFBZS/IKQRvCDIsP9WsBZP60CTCBYs//+wLxALBTQ4AB///+AKHgYLB/gLK/4LHh//AIIwFitVr/8DIIwFLANXBAILIqogBn7DBEYrXBeQRgIBYKmHDgYLLZRBACBZYKJZIILKKRZeWgJGKAFQA==")) diff --git a/apps/run/app.js b/apps/run/app.js new file mode 100644 index 000000000..a10d3841f --- /dev/null +++ b/apps/run/app.js @@ -0,0 +1,159 @@ +var B2 = process.env.HWVERSION==2; +var Layout = require("Layout"); +var locale = require("locale") +var fontHeading = "6x8:2"; +var fontValue = B2 ? "6x15:2" : "6x8:3"; +var headingCol = "#888"; +var running = false; +var startTime; +var startSteps; +// This & previous GPS readings +var lastGPS, thisGPS; +var distance = 0; ///< distance in meters +var startSteps = Bangle.getStepCount(); ///< number of steps when we started +var lastStepCount = startSteps; // last time 'step' was called +var stepHistory = new Uint8Array(60); // steps each second for the last minute (0 = current minute) + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +// --------------------------- + +function formatTime(ms) { + var s = Math.round(ms/1000); + var min = Math.floor(s/60).toString(); + s = (s%60).toString(); + return min.padStart(2,0)+":"+s.padStart(2,0); +} + +// Format speed in meters/second +function formatPace(speed) { + if (speed < 0.1667) { + return `__'__"`; + } + const pace = Math.round(1000 / speed); // seconds for 1km + const min = Math.floor(pace / 60); // minutes for 1km + const sec = pace % 60; + return ('0' + min).substr(-2) + `'` + ('0' + sec).substr(-2) + `"`; +} + +// --------------------------- + +function clearState() { + distance = 0; + startSteps = Bangle.getStepCount(); + stepHistory.fill(0); + layout.dist.label=locale.distance(distance); + layout.time.label="00:00"; + layout.pace.label=formatPace(0); + layout.hrm.label="--"; + layout.steps.label=0; + layout.cadence.label= "0"; + layout.status.bgCol = "#f00"; + layout.gps.bgCol = "#f00"; +} + +function onStartStop() { + running = !running; + layout.button.label = running ? "STOP" : "START"; + layout.status.label = running ? "RUN" : "STOP"; + layout.status.bgCol = running ? "#0f0" : "#f00"; + if (running) { + clearState(); + startTime = Date.now(); + } + // if stopping running, don't clear state + // so we can at least refer to what we've done + layout.render(); +} + +var layout = new Layout( { + type:"v", c: [ + { type:"h", filly:1, c:[ + {type:"txt", font:fontHeading, label:"DIST", fillx:1, col:headingCol }, + {type:"txt", font:fontHeading, label:"TIME", fillx:1, col:headingCol } + ]}, { type:"h", filly:1, c:[ + {type:"txt", font:fontValue, label:"0.00", id:"dist", fillx:1 }, + {type:"txt", font:fontValue, label:"00:00", id:"time", fillx:1 } + ]}, { type:"h", filly:1, c:[ + {type:"txt", font:fontHeading, label:"PACE", fillx:1, col:headingCol }, + {type:"txt", font:fontHeading, label:"HEART", fillx:1, col:headingCol } + ]}, { type:"h", filly:1, c:[ + {type:"txt", font:fontValue, label:`__'__"`, id:"pace", fillx:1 }, + {type:"txt", font:fontValue, label:"--", id:"hrm", fillx:1 } + ]}, { type:"h", filly:1, c:[ + {type:"txt", font:fontHeading, label:"STEPS", fillx:1, col:headingCol }, + {type:"txt", font:fontHeading, label:"CADENCE", fillx:1, col:headingCol } + ]}, { type:"h", filly:1, c:[ + {type:"txt", font:fontValue, label:"0", id:"steps", fillx:1 }, + {type:"txt", font:fontValue, label:"0", id:"cadence", fillx:1 } + ]}, { type:"h", filly:1, c:[ + {type:"txt", font:fontHeading, label:"GPS", id:"gps", fillx:1 }, + {type:"txt", font:fontHeading, label:"00:00", id:"clock", fillx:1, bgCol:g.theme.fg, col:g.theme.bg }, + {type:"txt", font:fontHeading, label:"STOP", id:"status", fillx:1 } + ]}, + + ] +},{lazy:true, btns:[{ label:"START", cb: onStartStop, id:"button"}]}); +clearState(); +layout.render(); + + + +function onTimer() { + layout.clock.label = locale.time(new Date(),1); + if (!running) { + layout.render(); + return; + } + // called once a second + var duration = Date.now() - startTime; // in ms + // set cadence based on steps over last minute + var stepsInMinute = E.sum(stepHistory); + var cadence = 60000 * stepsInMinute / Math.min(duration,60000); + // update layout + layout.time.label = formatTime(duration); + layout.steps.label = Bangle.getStepCount()-startSteps; + layout.cadence.label = Math.round(cadence); + layout.render(); + // move step history onwards + stepHistory.set(stepHistory,1); + stepHistory[0]=0; +} + +Bangle.on("GPS", function(fix) { + layout.gps.bgCol = fix.fix ? "#0f0" : "#f00"; + lastGPS = thisGPS; + thisGPS = fix; + if (running && fix.fix && lastGPS.fix) { + // work out distance - moving from a to b + var a = Bangle.project(lastGPS); + var b = Bangle.project(thisGPS); + var dx = a.x-b.x, dy = a.y-b.y; + var d = Math.sqrt(dx*dx+dy*dy); // this should be the distance in meters + distance += d; + layout.dist.label=locale.distance(distance); + var duration = Date.now() - startTime; // in ms + var speed = distance * 1000 / duration; // meters/sec + layout.pace.label = formatPace(speed); + } +}); +Bangle.on("HRM", function(h) { + layout.hrm.label = h.bpm; +}); +Bangle.on("step", function(steps) { + if (running) { + layout.steps.label = steps-Bangle.getStepCount(); + stepHistory[0] += steps-lastStepCount; + } + lastStepCount = steps; +}); + +// We always call ourselves once a second, if only to update the time +setInterval(onTimer, 1000); + +/* Turn GPS and HRM on right at the start to ensure +we get the highest chance of a lock. */ +Bangle.setHRMPower(true,"app"); +Bangle.setGPSPower(true,"app"); diff --git a/apps/run/app.png b/apps/run/app.png new file mode 100644 index 0000000000000000000000000000000000000000..7059b8b015e20039a96de8b65c8a6b68a5e51e18 GIT binary patch literal 1479 zcmV;&1vvVNP)b0~r9hI1hzN2C_Hz2bec46d zz32!1f7|Dr^Zft+eV+5aXV1bTJi@~b@gPX$zNip1Yz1>vN2mz2DMEkvlG@MN zqD@lE?a)(59(>u0=Kppec*EA5(*zQ(EG3+(+KI->CEFJ!ACP%5!I+F&=p{{UFEnH!o7WN}(7DfEF{6T=^qRTOGUUmDCINa`%K?dqCzyBw&^& zdx;n90#h)O*AZj`^*@L)UE%?ZC>&z+*w0Pj=Mr*u5X*l)p2LibbmVEnr6riETg&$lZ8)JSSrFFIvt>|1LfBuoykZR)&GJv4Nif!en;z zv+6Z;L-k`+==0YD>-(E?LK%{G3lE#^`JOB$P&RcWluLnM)#~Vk(_duC*`K_4L>V>S z)_4dF#+CBq(XN1$@$$f&f%ft_-N11%bdLd>txt@&{Fx`lWV(+H188fpdoMWEz{=c= zcS=M^psn$7;>Mk!^KP#d`utPCk6iBMM%oOs0tuJ37nQ16rohH)E z9ia`tY}y~?;W9hY+Ci=jL57GcSZ9mZX%$dBo+%nx{F~SG>u0QvN67NBtqYU0IzJ12 z!D%4xE@^d0`F6j&s+C&7&h>F)stg0CXcP_pe^xQKQS72jOY-(wh zZbX~G&?_#4KvUbwYbW!Gs64aVQ65`xr~;X3@&0)ixmMMvar5@_BseI*>bwB=Hsh4X zYQh$!?Cq~z?1DoTIA3l2sj5-q2GG>pLe-60r0n}JscF?|Pu=!AaWEs^-w{4*u-m|v z)cN}2e|5diF%6APc(zvE@zj|5xTt9M^e(*}a5ghB(al~?Yp}~eT3VX+_&;u68O^;r zFm#Zy>3N^}(KCW>&hyn7OqS~|H4F%<8>aciPOVnaXAj8ih*=;qfnl~5NeLTDd^m8~ zvnv)fz-)*f*%Y>B(}4>B-+uJwvah5;)T5WD&l4qTwmGbG5^Ni*$W&M4^}G>c@+r0 zm&L6n!K$N!Oe1_uD^fG^zOXju@RlWhrFCBC&eabb;-_mPZum831lFJkDuuov#6kU5 z4CF+`AmwiE&BPU?TrL(A+P>=nva%L?1T`4WzcBdbD0fZgQOG$4`W)s&T>c@z;lw?$ z*r#$R-lF#xBG~4P-1p~Z&LlR|e(BYTGQ71roRQk)24wckiNM_6L75_6I@Icn{4O=n ze($4X(0i|)Kwp^SEDqOJAUkp)FsXM?t`S20EwnAT>>nDL9jAl(3m`*#gmZ Date: Wed, 12 Jan 2022 16:50:37 +0100 Subject: [PATCH 430/489] Update Customizer.html --- apps/ac_ac/Customizer.html | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index a2798b6bd..8552eaf70 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -777,7 +777,13 @@ console.log(AppSource)

-

 

+

+ This application is based on the author's + [Analog Clock Construction Kit (ACCK)](https://github.com/rozek/banglejs-2-analog-clock-construction-kit). + If you need a different "clockwork", clock size calculation or clock face, + or specific clock hands or complications, just follow the link to learn how to + implement your own clock parts. +

From 1d8febed9f0559e1a4716ed9afb1b7d12e197d7c Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 12 Jan 2022 16:57:42 +0100 Subject: [PATCH 431/489] Do not overwrite circle on event (e.g. charging) if there is a circle configured for that place --- apps/circlesclock/app.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 822802afa..88a04d4b9 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -136,8 +136,10 @@ function getCirclePosition(type) { if (setting == type) return circlePosX[i - 1]; } for (let i = 0; i < defaultCircleTypes.length; i++) { - if (type == defaultCircleTypes[i]) return circlePosX[i]; - } + if (type == defaultCircleTypes[i] && (!settings || settings['circle' + (i + 1)] == undefined)) { + return circlePosX[i]; + } + } return undefined; } From 910c3c0b5bfec2d04cd206c64c0329ae6a8ea87d Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 12 Jan 2022 15:59:30 +0000 Subject: [PATCH 432/489] add screenshot, minor tweaks --- apps.json | 3 ++- apps/run/app.js | 9 ++++----- apps/run/screenshot.png | Bin 0 -> 3716 bytes 3 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 apps/run/screenshot.png diff --git a/apps.json b/apps.json index adc98ff2b..4c6f3bdcf 100644 --- a/apps.json +++ b/apps.json @@ -2284,12 +2284,13 @@ "icon": "app.png", "tags": "run,running,fitness,outdoors,gps", "supports" : ["BANGLEJS","BANGLEJS2"], + "screenshots": [{"url":"screenshot.png"}], "readme": "README.md", "storage": [ {"name":"run.app.js","url":"app.js"}, {"name":"run.img","url":"app-icon.js","evaluate":true} ] - }, + }, { "id": "banglerun", "name": "BangleRun", diff --git a/apps/run/app.js b/apps/run/app.js index a10d3841f..44c42711c 100644 --- a/apps/run/app.js +++ b/apps/run/app.js @@ -51,18 +51,17 @@ function clearState() { layout.steps.label=0; layout.cadence.label= "0"; layout.status.bgCol = "#f00"; - layout.gps.bgCol = "#f00"; } function onStartStop() { running = !running; - layout.button.label = running ? "STOP" : "START"; - layout.status.label = running ? "RUN" : "STOP"; - layout.status.bgCol = running ? "#0f0" : "#f00"; if (running) { clearState(); startTime = Date.now(); } + layout.button.label = running ? "STOP" : "START"; + layout.status.label = running ? "RUN" : "STOP"; + layout.status.bgCol = running ? "#0f0" : "#f00"; // if stopping running, don't clear state // so we can at least refer to what we've done layout.render(); @@ -89,7 +88,7 @@ var layout = new Layout( { {type:"txt", font:fontValue, label:"0", id:"steps", fillx:1 }, {type:"txt", font:fontValue, label:"0", id:"cadence", fillx:1 } ]}, { type:"h", filly:1, c:[ - {type:"txt", font:fontHeading, label:"GPS", id:"gps", fillx:1 }, + {type:"txt", font:fontHeading, label:"GPS", id:"gps", fillx:1, bgCol:"#f00" }, {type:"txt", font:fontHeading, label:"00:00", id:"clock", fillx:1, bgCol:g.theme.fg, col:g.theme.bg }, {type:"txt", font:fontHeading, label:"STOP", id:"status", fillx:1 } ]}, diff --git a/apps/run/screenshot.png b/apps/run/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..1a813f19dfe304e3d8bf711692fd2abf1013c391 GIT binary patch literal 3716 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 Date: Wed, 12 Jan 2022 17:18:29 +0100 Subject: [PATCH 433/489] Update Customizer.html --- apps/ac_ac/Customizer.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index 8552eaf70..2846352d6 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -779,7 +779,7 @@ console.log(AppSource)

This application is based on the author's - [Analog Clock Construction Kit (ACCK)](https://github.com/rozek/banglejs-2-analog-clock-construction-kit). + Analog Clock Construction Kit (ACCK). If you need a different "clockwork", clock size calculation or clock face, or specific clock hands or complications, just follow the link to learn how to implement your own clock parts. From 9691d0bb0466535af2858f6876b39f1ddef80dc1 Mon Sep 17 00:00:00 2001 From: The Dod Date: Wed, 12 Jan 2022 19:19:16 +0200 Subject: [PATCH 434/489] RAM efficient version of `fourTwentyTz.js` As suggested by @gfwilliams here: https://github.com/espruino/BangleApps/pull/1152#issuecomment-1009739110 Also make `apps.json` entry more accurate, and play nice with dark theme. --- apps.json | 5 +- apps/ftclock/ChangeLog | 1 + apps/ftclock/app.js | 3 +- apps/ftclock/fourTwenty.js | 12 +- apps/ftclock/fourTwentyTz.js | 492 +++------------------------------ apps/ftclock/mkFourTwentyTz.js | 17 +- 6 files changed, 57 insertions(+), 473 deletions(-) diff --git a/apps.json b/apps.json index 4c6f3bdcf..761e9d363 100644 --- a/apps.json +++ b/apps.json @@ -5169,14 +5169,13 @@ { "id": "ftclock", "name": "Four Twenty Clock", - "version": "0.01", + "version": "0.02", "description": "A clock that tells when and where it's going to be 4:20 next", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}, {"url":"screenshot1.png"}], "type": "clock", "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, + "supports": ["BANGLEJS2"], "readme": "README.md", "storage": [ {"name":"ftclock.app.js","url":"app.js"}, diff --git a/apps/ftclock/ChangeLog b/apps/ftclock/ChangeLog index 9db0e26c5..c944dd9ac 100644 --- a/apps/ftclock/ChangeLog +++ b/apps/ftclock/ChangeLog @@ -1 +1,2 @@ 0.01: first release +0.02: RAM efficient version of `fourTwentyTz.js` (as suggested by @gfwilliams). diff --git a/apps/ftclock/app.js b/apps/ftclock/app.js index 1aed8da54..b12db10f1 100644 --- a/apps/ftclock/app.js +++ b/apps/ftclock/app.js @@ -17,14 +17,13 @@ function queueDraw() { function draw() { g.reset(); - g.setBgColor("#ffffff"); let date = new Date(); let timeStr = require("locale").time(date,1); let next420 = getNextFourTwenty(); g.clearRect(0,26,g.getWidth(),g.getHeight()); g.setColor("#00ff00").setFontAlign(0,-1).setFont("Teletext10x18Ascii",2); g.drawString(next420.minutes? timeStr: `\0${leaf_img}${timeStr}\0${leaf_img}`, g.getWidth()/2, 28); - g.setColor("#000000"); + g.setColor(g.theme.fg); g.setFontAlign(-1,-1).setFont("Teletext10x18Ascii"); g.drawString(g.wrapString(next420.text, g.getWidth()-8).join("\n"),4,60); diff --git a/apps/ftclock/fourTwenty.js b/apps/ftclock/fourTwenty.js index ac15f40e6..b2a2aa8fb 100644 --- a/apps/ftclock/fourTwenty.js +++ b/apps/ftclock/fourTwenty.js @@ -1,4 +1,6 @@ -let timezones = require("fourTwentyTz").timezones; +let ftz = require("fourTwentyTz"), + offsets = ftz.offsets, + timezones = ftz.timezones; function get420offset() { let current_time = Math.floor((Date.now()%(24*3600*1000))/60000); @@ -24,10 +26,10 @@ function makeFourTwentyText(minutes, places) { function getNextFourTwenty() { let offs = get420offset(); - for (let i=0; i { if (err) { console.log("Can't open output file"); @@ -65,8 +69,17 @@ fs.createReadStream(__dirname+'/country.csv') fs.write(fd, "// Generated by mkFourTwentyTz.js\n", handleWrite); fs.write(fd, `// ${Date()}\n`, handleWrite); fs.write(fd, "// Data source: https://timezonedb.com/files/timezonedb.csv.zip\n", handleWrite); - fs.write(fd, "exports.timezones = ", handleWrite); - fs.write(fd, JSON.stringify(offsdict, null, 4), handleWrite); + fs.write(fd, "exports.offsets = ", handleWrite); + fs.write(fd, JSON.stringify(offsets), handleWrite); + fs.write(fd, ";\n", handleWrite); + fs.write(fd, "exports.timezones = function(offs) {\n", handleWrite); + fs.write(fd, " switch (offs) {\n", handleWrite); + for (o in offsdict) { + fs.write(fd, ` case ${o}: return ${JSON.stringify(offsdict[o])};\n`, handleWrite); + } + fs.write(fd, " default: return [\"Houston, we have a bug.\"];\n", handleWrite); + fs.write(fd, " };\n", handleWrite); + fs.write(fd, "};\n", handleWrite); console.log('Done.'); }); }) From 1c8083ba6e9bc423b7592390d624ed41d830fef2 Mon Sep 17 00:00:00 2001 From: The Dod Date: Wed, 12 Jan 2022 19:36:27 +0200 Subject: [PATCH 435/489] Remove a `;` that was disturbing Travis Also make `fourTwentyTz.js` sorted (to minimize diffs in the future). --- apps/ftclock/fourTwentyTz.js | 48 +++++++++++++++++----------------- apps/ftclock/mkFourTwentyTz.js | 5 ++-- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/apps/ftclock/fourTwentyTz.js b/apps/ftclock/fourTwentyTz.js index d02402e2f..5fa6cdab7 100644 --- a/apps/ftclock/fourTwentyTz.js +++ b/apps/ftclock/fourTwentyTz.js @@ -1,33 +1,33 @@ // Generated by mkFourTwentyTz.js -// Wed Jan 12 2022 17:49:39 GMT+0200 (Israel Standard Time) +// Wed Jan 12 2022 19:35:36 GMT+0200 (Israel Standard Time) // Data source: https://timezonedb.com/files/timezonedb.csv.zip exports.offsets = [1380,1320,1260,1200,1140,1080,1020,960,900,840,780,720,660,600,540,480,420,360,300,240,180,120,60,0]; exports.timezones = function(offs) { switch (offs) { - case 0: return ["Troll, Antarctica","Ouagadougou, Burkina Faso","Abidjan, Côte d'Ivoire","Canary, Spain","Faroe, Faroe Islands","London, United Kingdom of Great Britain and Northern Ireland","Guernsey, Guernsey","Accra, Ghana","Danmarkshavn, Greenland","Banjul, Gambia","Conakry, Guinea","Bissau, Guinea-Bissau","Dublin, Ireland","Isle of_Man, Isle of Man","Reykjavik, Iceland","Jersey, Jersey","Monrovia, Liberia","Bamako, Mali","Nouakchott, Mauritania","Lisbon, Portugal","Madeira, Portugal","St Helena, Saint Helena, Ascension and Tristan da Cunha","Freetown, Sierra Leone","Dakar, Senegal","Sao Tome, Sao Tome and Principe","Lome, Togo"]; - case 60: return ["Andorra, Andorra","Tirane, Albania","Luanda, Angola","Vienna, Austria","Sarajevo, Bosnia and Herzegovina","Brussels, Belgium","Porto-Novo, Benin","Kinshasa, Congo, Democratic Republic of the","Bangui, Central African Republic","Brazzaville, Congo","Zurich, Switzerland","Douala, Cameroon","Prague, Czechia","Berlin, Germany","Busingen, Germany","Copenhagen, Denmark","Algiers, Algeria","El Aaiun, Western Sahara","Madrid, Spain","Ceuta, Spain","Paris, France","Libreville, Gabon","Gibraltar, Gibraltar","Malabo, Equatorial Guinea","Zagreb, Croatia","Budapest, Hungary","Rome, Italy","Vaduz, Liechtenstein","Luxembourg, Luxembourg","Casablanca, Morocco","Monaco, Monaco","Podgorica, Montenegro","Skopje, North Macedonia","Malta, Malta","Niamey, Niger","Lagos, Nigeria","Amsterdam, Netherlands","Oslo, Norway","Warsaw, Poland","Belgrade, Serbia","Stockholm, Sweden","Ljubljana, Slovenia","Longyearbyen, Svalbard and Jan Mayen","Bratislava, Slovakia","San Marino, San Marino","Ndjamena, Chad","Tunis, Tunisia","Vatican, Holy See"]; - case 120: return ["Mariehamn, Åland Islands","Sofia, Bulgaria","Bujumbura, Burundi","Gaborone, Botswana","Lubumbashi, Congo, Democratic Republic of the","Nicosia, Cyprus","Famagusta, Cyprus","Tallinn, Estonia","Cairo, Egypt","Helsinki, Finland","Athens, Greece","Jerusalem, Israel","Amman, Jordan","Beirut, Lebanon","Maseru, Lesotho","Vilnius, Lithuania","Riga, Latvia","Tripoli, Libya","Chisinau, Moldova, Republic of","Blantyre, Malawi","Maputo, Mozambique","Windhoek, Namibia","Gaza, Palestine, State of","Hebron, Palestine, State of","Bucharest, Romania","Kaliningrad, Russian Federation","Kigali, Rwanda","Khartoum, Sudan","Juba, South Sudan","Damascus, Syrian Arab Republic","Mbabane, Eswatini","Kiev, Ukraine","Uzhgorod, Ukraine","Zaporozhye, Ukraine","Johannesburg, South Africa","Lusaka, Zambia","Harare, Zimbabwe"]; - case 180: return ["Syowa, Antarctica","Bahrain, Bahrain","Minsk, Belarus","Djibouti, Djibouti","Asmara, Eritrea","Addis Ababa, Ethiopia","Baghdad, Iraq","Nairobi, Kenya","Comoro, Comoros","Kuwait, Kuwait","Antananarivo, Madagascar","Qatar, Qatar","Moscow, Russian Federation","Simferopol, Ukraine","Kirov, Russian Federation","Volgograd, Russian Federation","Riyadh, Saudi Arabia","Mogadishu, Somalia","Istanbul, Turkey","Dar es_Salaam, Tanzania, United Republic of","Kampala, Uganda","Aden, Yemen","Mayotte, Mayotte"]; - case 240: return ["Dubai, United Arab Emirates","Yerevan, Armenia","Baku, Azerbaijan","Tbilisi, Georgia","Mauritius, Mauritius","Muscat, Oman","Reunion, Réunion","Astrakhan, Russian Federation","Saratov, Russian Federation","Ulyanovsk, Russian Federation","Samara, Russian Federation","Mahe, Seychelles"]; + case 1380: return ["Cape Verde, Cabo Verde","Scoresbysund, Greenland","Azores, Portugal"]; + case 1320: return ["Noronha, Brazil","South Georgia, South Georgia and the South Sandwich Islands"]; + case 1260: return ["Palmer, Antarctica","Rothera, Antarctica","Buenos Aires, Argentina","Cordoba, Argentina","Salta, Argentina","Jujuy, Argentina","Tucuman, Argentina","Catamarca, Argentina","La Rioja, Argentina","San Juan, Argentina","Mendoza, Argentina","San Luis, Argentina","Rio Gallegos, Argentina","Ushuaia, Argentina","Belem, Brazil","Fortaleza, Brazil","Recife, Brazil","Araguaina, Brazil","Maceio, Brazil","Bahia, Brazil","Sao Paulo, Brazil","Santarem, Brazil","Santiago, Chile","Punta Arenas, Chile","Stanley, Falkland Islands (Malvinas)","Cayenne, French Guiana","Nuuk, Greenland","Miquelon, Saint Pierre and Miquelon","Asuncion, Paraguay","Paramaribo, Suriname","Montevideo, Uruguay"]; + case 1200: return ["Antigua, Antigua and Barbuda","Anguilla, Anguilla","Aruba, Aruba","Barbados, Barbados","St Barthelemy, Saint Barthélemy","Bermuda, Bermuda","La Paz, Bolivia (Plurinational State of)","Kralendijk, Bonaire, Sint Eustatius and Saba","Campo Grande, Brazil","Cuiaba, Brazil","Porto Velho, Brazil","Boa Vista, Brazil","Manaus, Brazil","Halifax, Canada","Glace Bay, Canada","Moncton, Canada","Goose Bay, Canada","Blanc-Sablon, Canada","Curacao, Curaçao","Dominica, Dominica","Santo Domingo, Dominican Republic","Grenada, Grenada","Thule, Greenland","Guadeloupe, Guadeloupe","Guyana, Guyana","St Kitts, Saint Kitts and Nevis","St Lucia, Saint Lucia","Marigot, Saint Martin (French part)","Martinique, Martinique","Montserrat, Montserrat","Puerto Rico, Puerto Rico","Lower Princes, Sint Maarten (Dutch part)","Port of_Spain, Trinidad and Tobago","St Vincent, Saint Vincent and the Grenadines","Caracas, Venezuela (Bolivarian Republic of)","Tortola, Virgin Islands (British)","St Thomas, Virgin Islands (U.S.)"]; + case 1140: return ["Eirunepe, Brazil","Rio Branco, Brazil","Nassau, Bahamas","Toronto, Canada","Nipigon, Canada","Thunder Bay, Canada","Iqaluit, Canada","Pangnirtung, Canada","Atikokan, Canada","Easter, Chile","Bogota, Colombia","Havana, Cuba","Guayaquil, Ecuador","Port-au-Prince, Haiti","Jamaica, Jamaica","Cayman, Cayman Islands","Cancun, Mexico","Panama, Panama","Lima, Peru","Grand Turk, Turks and Caicos Islands","New York, United States of America","Detroit, United States of America","Louisville, Kentucky","Monticello, Kentucky","Indianapolis, Indiana","Vincennes, Indiana","Winamac, Indiana","Marengo, Indiana","Petersburg, Indiana","Vevay, Indiana"]; + case 1080: return ["Belize, Belize","Winnipeg, Canada","Rainy River, Canada","Resolute, Canada","Rankin Inlet, Canada","Regina, Canada","Swift Current, Canada","Costa Rica, Costa Rica","Galapagos, Ecuador","Guatemala, Guatemala","Tegucigalpa, Honduras","Mexico City, Mexico","Merida, Mexico","Monterrey, Mexico","Matamoros, Mexico","Bahia Banderas, Mexico","Managua, Nicaragua","El Salvador, El Salvador","Chicago, United States of America","Tell City, Indiana","Knox, Indiana","Menominee, United States of America","Center, North Dakota","New_Salem, North Dakota","Beulah, North Dakota"]; + case 1020: return ["Edmonton, Canada","Cambridge Bay, Canada","Yellowknife, Canada","Inuvik, Canada","Creston, Canada","Dawson Creek, Canada","Fort Nelson, Canada","Whitehorse, Canada","Dawson, Canada","Mazatlan, Mexico","Chihuahua, Mexico","Ojinaga, Mexico","Hermosillo, Mexico","Denver, United States of America","Boise, United States of America","Phoenix, United States of America"]; + case 960: return ["Vancouver, Canada","Tijuana, Mexico","Pitcairn, Pitcairn","Los Angeles, United States of America"]; + case 900: return ["Gambier, French Polynesia","Anchorage, United States of America","Juneau, United States of America","Sitka, United States of America","Metlakatla, United States of America","Yakutat, United States of America","Nome, United States of America"]; + case 840: return ["Rarotonga, Cook Islands","Kiritimati, Kiribati","Tahiti, French Polynesia","Adak, United States of America","Honolulu, United States of America"]; + case 780: return ["McMurdo, Antarctica","Pago Pago, American Samoa","Fiji, Fiji","Kanton, Kiribati","Niue, Niue","Auckland, New Zealand","Fakaofo, Tokelau","Tongatapu, Tonga","Midway, United States Minor Outlying Islands","Apia, Samoa"]; + case 720: return ["Tarawa, Kiribati","Majuro, Marshall Islands","Kwajalein, Marshall Islands","Norfolk, Norfolk Island","Nauru, Nauru","Kamchatka, Russian Federation","Anadyr, Russian Federation","Funafuti, Tuvalu","Wake, United States Minor Outlying Islands","Wallis, Wallis and Futuna"]; + case 660: return ["Casey, Antarctica","Lord Howe, Australia","Macquarie, Australia","Hobart, Australia","Melbourne, Australia","Sydney, Australia","Pohnpei, Micronesia (Federated States of)","Kosrae, Micronesia (Federated States of)","Noumea, New Caledonia","Bougainville, Papua New Guinea","Magadan, Russian Federation","Sakhalin, Russian Federation","Srednekolymsk, Russian Federation","Guadalcanal, Solomon Islands","Efate, Vanuatu"]; + case 600: return ["DumontDUrville, Antarctica","Brisbane, Australia","Lindeman, Australia","Chuuk, Micronesia (Federated States of)","Guam, Guam","Saipan, Northern Mariana Islands","Port Moresby, Papua New Guinea","Vladivostok, Russian Federation","Ust-Nera, Russian Federation"]; + case 540: return ["Jayapura, Indonesia","Tokyo, Japan","Pyongyang, Korea (Democratic People's Republic of)","Seoul, Korea, Republic of","Palau, Palau","Chita, Russian Federation","Yakutsk, Russian Federation","Khandyga, Russian Federation","Dili, Timor-Leste"]; + case 480: return ["Perth, Australia","Brunei, Brunei Darussalam","Shanghai, China","Hong Kong, Hong Kong","Makassar, Indonesia","Ulaanbaatar, Mongolia","Choibalsan, Mongolia","Macau, Macao","Kuala Lumpur, Malaysia","Kuching, Malaysia","Manila, Philippines","Irkutsk, Russian Federation","Singapore, Singapore","Taipei, Taiwan, Province of China"]; + case 420: return ["Davis, Antarctica","Christmas, Christmas Island","Jakarta, Indonesia","Pontianak, Indonesia","Phnom Penh, Cambodia","Vientiane, Lao People's Democratic Republic","Hovd, Mongolia","Novosibirsk, Russian Federation","Barnaul, Russian Federation","Tomsk, Russian Federation","Novokuznetsk, Russian Federation","Krasnoyarsk, Russian Federation","Bangkok, Thailand","Ho Chi_Minh, Viet Nam"]; case 360: return ["Vostok, Antarctica","Dhaka, Bangladesh","Thimphu, Bhutan","Urumqi, China","Chagos, British Indian Ocean Territory","Bishkek, Kyrgyzstan","Almaty, Kazakhstan","Qostanay, Kazakhstan","Omsk, Russian Federation"]; case 300: return ["Mawson, Antarctica","Qyzylorda, Kazakhstan","Aqtobe, Kazakhstan","Aqtau, Kazakhstan","Atyrau, Kazakhstan","Oral, Kazakhstan","Maldives, Maldives","Karachi, Pakistan","Yekaterinburg, Russian Federation","Kerguelen, French Southern Territories","Dushanbe, Tajikistan","Ashgabat, Turkmenistan","Samarkand, Uzbekistan","Tashkent, Uzbekistan"]; - case 420: return ["Davis, Antarctica","Christmas, Christmas Island","Jakarta, Indonesia","Pontianak, Indonesia","Phnom Penh, Cambodia","Vientiane, Lao People's Democratic Republic","Hovd, Mongolia","Novosibirsk, Russian Federation","Barnaul, Russian Federation","Tomsk, Russian Federation","Novokuznetsk, Russian Federation","Krasnoyarsk, Russian Federation","Bangkok, Thailand","Ho Chi_Minh, Viet Nam"]; - case 480: return ["Perth, Australia","Brunei, Brunei Darussalam","Shanghai, China","Hong Kong, Hong Kong","Makassar, Indonesia","Ulaanbaatar, Mongolia","Choibalsan, Mongolia","Macau, Macao","Kuala Lumpur, Malaysia","Kuching, Malaysia","Manila, Philippines","Irkutsk, Russian Federation","Singapore, Singapore","Taipei, Taiwan, Province of China"]; - case 540: return ["Jayapura, Indonesia","Tokyo, Japan","Pyongyang, Korea (Democratic People's Republic of)","Seoul, Korea, Republic of","Palau, Palau","Chita, Russian Federation","Yakutsk, Russian Federation","Khandyga, Russian Federation","Dili, Timor-Leste"]; - case 600: return ["DumontDUrville, Antarctica","Brisbane, Australia","Lindeman, Australia","Chuuk, Micronesia (Federated States of)","Guam, Guam","Saipan, Northern Mariana Islands","Port Moresby, Papua New Guinea","Vladivostok, Russian Federation","Ust-Nera, Russian Federation"]; - case 660: return ["Casey, Antarctica","Lord Howe, Australia","Macquarie, Australia","Hobart, Australia","Melbourne, Australia","Sydney, Australia","Pohnpei, Micronesia (Federated States of)","Kosrae, Micronesia (Federated States of)","Noumea, New Caledonia","Bougainville, Papua New Guinea","Magadan, Russian Federation","Sakhalin, Russian Federation","Srednekolymsk, Russian Federation","Guadalcanal, Solomon Islands","Efate, Vanuatu"]; - case 720: return ["Tarawa, Kiribati","Majuro, Marshall Islands","Kwajalein, Marshall Islands","Norfolk, Norfolk Island","Nauru, Nauru","Kamchatka, Russian Federation","Anadyr, Russian Federation","Funafuti, Tuvalu","Wake, United States Minor Outlying Islands","Wallis, Wallis and Futuna"]; - case 780: return ["McMurdo, Antarctica","Pago Pago, American Samoa","Fiji, Fiji","Kanton, Kiribati","Niue, Niue","Auckland, New Zealand","Fakaofo, Tokelau","Tongatapu, Tonga","Midway, United States Minor Outlying Islands","Apia, Samoa"]; - case 840: return ["Rarotonga, Cook Islands","Kiritimati, Kiribati","Tahiti, French Polynesia","Adak, United States of America","Honolulu, United States of America"]; - case 900: return ["Gambier, French Polynesia","Anchorage, United States of America","Juneau, United States of America","Sitka, United States of America","Metlakatla, United States of America","Yakutat, United States of America","Nome, United States of America"]; - case 960: return ["Vancouver, Canada","Tijuana, Mexico","Pitcairn, Pitcairn","Los Angeles, United States of America"]; - case 1020: return ["Edmonton, Canada","Cambridge Bay, Canada","Yellowknife, Canada","Inuvik, Canada","Creston, Canada","Dawson Creek, Canada","Fort Nelson, Canada","Whitehorse, Canada","Dawson, Canada","Mazatlan, Mexico","Chihuahua, Mexico","Ojinaga, Mexico","Hermosillo, Mexico","Denver, United States of America","Boise, United States of America","Phoenix, United States of America"]; - case 1080: return ["Belize, Belize","Winnipeg, Canada","Rainy River, Canada","Resolute, Canada","Rankin Inlet, Canada","Regina, Canada","Swift Current, Canada","Costa Rica, Costa Rica","Galapagos, Ecuador","Guatemala, Guatemala","Tegucigalpa, Honduras","Mexico City, Mexico","Merida, Mexico","Monterrey, Mexico","Matamoros, Mexico","Bahia Banderas, Mexico","Managua, Nicaragua","El Salvador, El Salvador","Chicago, United States of America","Tell City, Indiana","Knox, Indiana","Menominee, United States of America","Center, North Dakota","New_Salem, North Dakota","Beulah, North Dakota"]; - case 1140: return ["Eirunepe, Brazil","Rio Branco, Brazil","Nassau, Bahamas","Toronto, Canada","Nipigon, Canada","Thunder Bay, Canada","Iqaluit, Canada","Pangnirtung, Canada","Atikokan, Canada","Easter, Chile","Bogota, Colombia","Havana, Cuba","Guayaquil, Ecuador","Port-au-Prince, Haiti","Jamaica, Jamaica","Cayman, Cayman Islands","Cancun, Mexico","Panama, Panama","Lima, Peru","Grand Turk, Turks and Caicos Islands","New York, United States of America","Detroit, United States of America","Louisville, Kentucky","Monticello, Kentucky","Indianapolis, Indiana","Vincennes, Indiana","Winamac, Indiana","Marengo, Indiana","Petersburg, Indiana","Vevay, Indiana"]; - case 1200: return ["Antigua, Antigua and Barbuda","Anguilla, Anguilla","Aruba, Aruba","Barbados, Barbados","St Barthelemy, Saint Barthélemy","Bermuda, Bermuda","La Paz, Bolivia (Plurinational State of)","Kralendijk, Bonaire, Sint Eustatius and Saba","Campo Grande, Brazil","Cuiaba, Brazil","Porto Velho, Brazil","Boa Vista, Brazil","Manaus, Brazil","Halifax, Canada","Glace Bay, Canada","Moncton, Canada","Goose Bay, Canada","Blanc-Sablon, Canada","Curacao, Curaçao","Dominica, Dominica","Santo Domingo, Dominican Republic","Grenada, Grenada","Thule, Greenland","Guadeloupe, Guadeloupe","Guyana, Guyana","St Kitts, Saint Kitts and Nevis","St Lucia, Saint Lucia","Marigot, Saint Martin (French part)","Martinique, Martinique","Montserrat, Montserrat","Puerto Rico, Puerto Rico","Lower Princes, Sint Maarten (Dutch part)","Port of_Spain, Trinidad and Tobago","St Vincent, Saint Vincent and the Grenadines","Caracas, Venezuela (Bolivarian Republic of)","Tortola, Virgin Islands (British)","St Thomas, Virgin Islands (U.S.)"]; - case 1260: return ["Palmer, Antarctica","Rothera, Antarctica","Buenos Aires, Argentina","Cordoba, Argentina","Salta, Argentina","Jujuy, Argentina","Tucuman, Argentina","Catamarca, Argentina","La Rioja, Argentina","San Juan, Argentina","Mendoza, Argentina","San Luis, Argentina","Rio Gallegos, Argentina","Ushuaia, Argentina","Belem, Brazil","Fortaleza, Brazil","Recife, Brazil","Araguaina, Brazil","Maceio, Brazil","Bahia, Brazil","Sao Paulo, Brazil","Santarem, Brazil","Santiago, Chile","Punta Arenas, Chile","Stanley, Falkland Islands (Malvinas)","Cayenne, French Guiana","Nuuk, Greenland","Miquelon, Saint Pierre and Miquelon","Asuncion, Paraguay","Paramaribo, Suriname","Montevideo, Uruguay"]; - case 1320: return ["Noronha, Brazil","South Georgia, South Georgia and the South Sandwich Islands"]; - case 1380: return ["Cape Verde, Cabo Verde","Scoresbysund, Greenland","Azores, Portugal"]; + case 240: return ["Dubai, United Arab Emirates","Yerevan, Armenia","Baku, Azerbaijan","Tbilisi, Georgia","Mauritius, Mauritius","Muscat, Oman","Reunion, Réunion","Astrakhan, Russian Federation","Saratov, Russian Federation","Ulyanovsk, Russian Federation","Samara, Russian Federation","Mahe, Seychelles"]; + case 180: return ["Syowa, Antarctica","Bahrain, Bahrain","Minsk, Belarus","Djibouti, Djibouti","Asmara, Eritrea","Addis Ababa, Ethiopia","Baghdad, Iraq","Nairobi, Kenya","Comoro, Comoros","Kuwait, Kuwait","Antananarivo, Madagascar","Qatar, Qatar","Moscow, Russian Federation","Simferopol, Ukraine","Kirov, Russian Federation","Volgograd, Russian Federation","Riyadh, Saudi Arabia","Mogadishu, Somalia","Istanbul, Turkey","Dar es_Salaam, Tanzania, United Republic of","Kampala, Uganda","Aden, Yemen","Mayotte, Mayotte"]; + case 120: return ["Mariehamn, Åland Islands","Sofia, Bulgaria","Bujumbura, Burundi","Gaborone, Botswana","Lubumbashi, Congo, Democratic Republic of the","Nicosia, Cyprus","Famagusta, Cyprus","Tallinn, Estonia","Cairo, Egypt","Helsinki, Finland","Athens, Greece","Jerusalem, Israel","Amman, Jordan","Beirut, Lebanon","Maseru, Lesotho","Vilnius, Lithuania","Riga, Latvia","Tripoli, Libya","Chisinau, Moldova, Republic of","Blantyre, Malawi","Maputo, Mozambique","Windhoek, Namibia","Gaza, Palestine, State of","Hebron, Palestine, State of","Bucharest, Romania","Kaliningrad, Russian Federation","Kigali, Rwanda","Khartoum, Sudan","Juba, South Sudan","Damascus, Syrian Arab Republic","Mbabane, Eswatini","Kiev, Ukraine","Uzhgorod, Ukraine","Zaporozhye, Ukraine","Johannesburg, South Africa","Lusaka, Zambia","Harare, Zimbabwe"]; + case 60: return ["Andorra, Andorra","Tirane, Albania","Luanda, Angola","Vienna, Austria","Sarajevo, Bosnia and Herzegovina","Brussels, Belgium","Porto-Novo, Benin","Kinshasa, Congo, Democratic Republic of the","Bangui, Central African Republic","Brazzaville, Congo","Zurich, Switzerland","Douala, Cameroon","Prague, Czechia","Berlin, Germany","Busingen, Germany","Copenhagen, Denmark","Algiers, Algeria","El Aaiun, Western Sahara","Madrid, Spain","Ceuta, Spain","Paris, France","Libreville, Gabon","Gibraltar, Gibraltar","Malabo, Equatorial Guinea","Zagreb, Croatia","Budapest, Hungary","Rome, Italy","Vaduz, Liechtenstein","Luxembourg, Luxembourg","Casablanca, Morocco","Monaco, Monaco","Podgorica, Montenegro","Skopje, North Macedonia","Malta, Malta","Niamey, Niger","Lagos, Nigeria","Amsterdam, Netherlands","Oslo, Norway","Warsaw, Poland","Belgrade, Serbia","Stockholm, Sweden","Ljubljana, Slovenia","Longyearbyen, Svalbard and Jan Mayen","Bratislava, Slovakia","San Marino, San Marino","Ndjamena, Chad","Tunis, Tunisia","Vatican, Holy See"]; + case 0: return ["Troll, Antarctica","Ouagadougou, Burkina Faso","Abidjan, Côte d'Ivoire","Canary, Spain","Faroe, Faroe Islands","London, United Kingdom of Great Britain and Northern Ireland","Guernsey, Guernsey","Accra, Ghana","Danmarkshavn, Greenland","Banjul, Gambia","Conakry, Guinea","Bissau, Guinea-Bissau","Dublin, Ireland","Isle of_Man, Isle of Man","Reykjavik, Iceland","Jersey, Jersey","Monrovia, Liberia","Bamako, Mali","Nouakchott, Mauritania","Lisbon, Portugal","Madeira, Portugal","St Helena, Saint Helena, Ascension and Tristan da Cunha","Freetown, Sierra Leone","Dakar, Senegal","Sao Tome, Sao Tome and Principe","Lome, Togo"]; default: return ["Houston, we have a bug."]; - }; + } }; diff --git a/apps/ftclock/mkFourTwentyTz.js b/apps/ftclock/mkFourTwentyTz.js index 2be18f88a..4571c15f7 100644 --- a/apps/ftclock/mkFourTwentyTz.js +++ b/apps/ftclock/mkFourTwentyTz.js @@ -74,11 +74,12 @@ fs.createReadStream(__dirname+'/country.csv') fs.write(fd, ";\n", handleWrite); fs.write(fd, "exports.timezones = function(offs) {\n", handleWrite); fs.write(fd, " switch (offs) {\n", handleWrite); - for (o in offsdict) { + for (i=0; i Date: Wed, 12 Jan 2022 18:36:07 +0100 Subject: [PATCH 436/489] Select which GNSS system to use fewer GNSS systems could decrease time to fix. This patch adds a checkbox for each choice. --- apps.json | 2 +- apps/assistedgps/ChangeLog | 1 + apps/assistedgps/custom.html | 34 ++++++++++++++++++++++++++++++++-- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 4c6f3bdcf..88db38bbb 100644 --- a/apps.json +++ b/apps.json @@ -1536,7 +1536,7 @@ { "id": "assistedgps", "name": "Assisted GPS Update (AGPS)", - "version": "0.02", + "version": "0.03", "description": "Downloads assisted GPS (AGPS) data to Bangle.js 1 or 2 for faster GPS startup and more accurate fixes. **No app will be installed**, this just uploads new data to the GPS chip.", "icon": "app.png", "type": "RAM", diff --git a/apps/assistedgps/ChangeLog b/apps/assistedgps/ChangeLog index 4ec2c8f71..739ccf915 100644 --- a/apps/assistedgps/ChangeLog +++ b/apps/assistedgps/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! 0.02: Update to work with Bangle.js 2 +0.03: Select GNSS systems to use for Bangle.js 2 diff --git a/apps/assistedgps/custom.html b/apps/assistedgps/custom.html index fa11b696c..80d68a71f 100644 --- a/apps/assistedgps/custom.html +++ b/apps/assistedgps/custom.html @@ -27,6 +27,31 @@

@@ -116,8 +141,13 @@ } if (isB2) { // CASIC - // Disable BDS, use just GPS (supposedly improve lock time) - js += `\x10Serial1.println("${CASIC_CHECKSUM("$PCAS04,1")}")\n`; // set GPS-only mode + // Select what GNSS System to use for decreased fix time. + var radios = document.getElementsByName('gnss_select'); + var gnss_select="1"; + for (var i=0; i Date: Wed, 12 Jan 2022 19:33:22 +0100 Subject: [PATCH 437/489] Update app-screenshot.png --- apps/ac_ac/app-screenshot.png | Bin 4042 -> 3459 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/ac_ac/app-screenshot.png b/apps/ac_ac/app-screenshot.png index e0e3bb0b95de844ed0656d16023e71708c117f96..0aef3fa3815fe19d368bcf37f6afd3aa1f9e335c 100644 GIT binary patch delta 3444 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

P0Nr8KQ7MDGw1#ySt+-U>WBeK-J~ zIf*MltOajcveRsr0B$sy2QZ_POPON%?=hH}>b#UQ@y`9#V*bGe6YD2OK@bM^g>YE)66hwe?X+jO|hJRCbJ+w#lLb1a(0p3A@w*ffL z)_&%^C5FIm6JW(Fba+#{De!Oy@=oXg^ZbQdm(qk4(+7OC(=8SS*m#bNRU)jF(Tq>j z7M#Q(7xoG{atUH<@P-r@ya;Nse-#{Dfv4XD4RpX2*gz1x3!n7Bq6%Dz)e7mwXw()~ zSj<)X0e`&mLl7)l($5#paj_xq2e2#fJLayy*mbbj=Q}~ZF`N{t_ETWWsCRm(u+vy5 zu}f^e3ve9yVs+0~j9r1z?|v0r7mFWaN!2X%#b8*!slZquC^@nQSd=zCuCQ3B9N?UX zNMI4(Fvi-!KEEFG{&jNobO)nR@VNsla9TJ-135lQ8`A!Lp56^@JHXvt m>?i2y0SCCJcfIZI9{3NXIof%KH)?hO0000 From 73062edf8321892b65d4372f6f0c2f304d2c25a3 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Wed, 12 Jan 2022 19:08:19 +0100 Subject: [PATCH 438/489] qmsched: switch theme fixes #1266 --- apps.json | 4 +-- apps/qmsched/ChangeLog | 3 ++- apps/qmsched/README.md | 5 ++++ apps/qmsched/app.js | 60 +++++++++++++++++++++++++++++++----------- apps/qmsched/boot.js | 4 ++- apps/qmsched/lib.js | 36 ++++++++++++++++++++++++- apps/qmsched/widget.js | 2 +- 7 files changed, 93 insertions(+), 21 deletions(-) diff --git a/apps.json b/apps.json index b5929a56c..870c7b49f 100644 --- a/apps.json +++ b/apps.json @@ -3919,8 +3919,8 @@ "id": "qmsched", "name": "Quiet Mode Schedule and Widget", "shortName": "Quiet Mode", - "version": "0.06", - "description": "Automatically turn Quiet Mode on or off at set times, and change LCD options while Quiet Mode is active.", + "version": "0.07", + "description": "Automatically turn Quiet Mode on or off at set times, change theme and LCD options while Quiet Mode is active.", "icon": "app.png", "screenshots": [{"url":"screenshot_b1_main.png"},{"url":"screenshot_b1_edit.png"},{"url":"screenshot_b1_lcd.png"}, {"url":"screenshot_b2_main.png"},{"url":"screenshot_b2_edit.png"},{"url":"screenshot_b2_lcd.png"}], diff --git a/apps/qmsched/ChangeLog b/apps/qmsched/ChangeLog index 35832a300..cc0050cdd 100644 --- a/apps/qmsched/ChangeLog +++ b/apps/qmsched/ChangeLog @@ -3,4 +3,5 @@ 0.03: Bangle.js 2 support 0.04: Move Quiet Mode LCD options from global settings to this app 0.05: Avoid immediately redrawing widgets on load -0.06: Fix: don't try to redraw widget when widgets not loaded \ No newline at end of file +0.06: Fix: don't try to redraw widget when widgets not loaded +0.07: Option to switch theme diff --git a/apps/qmsched/README.md b/apps/qmsched/README.md index 535ae56e4..660bda787 100644 --- a/apps/qmsched/README.md +++ b/apps/qmsched/README.md @@ -9,6 +9,11 @@ Automatically turn Quiet Mode on or off at set times, and display a widget when | ![Edit Schedule menu](screenshot_b1_edit.png) | ![Edit Schedule menu](screenshot_b2_edit.png) | | ![LCD Options menu](screenshot_b1_lcd.png) | ![LCD Options menu](screenshot_b2_lcd.png) | +### Switch Theme: + +Switch to dark theme during Quiet Mode. + * **NOTE**: This switches between the default "Dark BW" and "Light BW" themes, so custom theme settings will be lost. + ### LCD Settings: If set, these override the default LCD settings while Quiet Mode is active. \ No newline at end of file diff --git a/apps/qmsched/app.js b/apps/qmsched/app.js index 7be3339fb..433dab409 100644 --- a/apps/qmsched/app.js +++ b/apps/qmsched/app.js @@ -3,7 +3,7 @@ Bangle.drawWidgets(); const modeNames = ["Off", "Alarms", "Silent"]; -// load global brightness setting +// load global settings let bSettings = require('Storage').readJSON('setting.json',true)||{}; let current = 0|bSettings.quiet; delete bSettings; // we don't need any other global settings @@ -18,6 +18,7 @@ delete bSettings; // we don't need any other global settings */ function save() { require('Storage').writeJSON('qmsched.json', settings); + eval(require('Storage').read('qmsched.boot.js')); // apply new schedules right away } function get(key, def) { return (key in settings) ? settings[key] : def; @@ -77,37 +78,66 @@ function formatTime(t) { const mins = Math.round((t-hrs)*60); return (" "+hrs).substr(-2)+":"+("0"+mins).substr(-2); } +/** + * Apply theme + */ +function applyTheme() { + const theme = (require("Storage").readJSON("setting.json", 1) || {}).theme; + if (theme && theme.dark===g.theme.dark) return; // already correct + g.theme = theme; + delete g.reset; + g._reset = g.reset; + g.reset = function(n) { return g._reset().setColor(g.theme.fg).setBgColor(g.theme.bg); }; + g.clear = function(n) { if (n) g.reset(); return g.clearRect(0,0,g.getWidth(),g.getHeight()); }; + g.clear(1); + Bangle.drawWidgets(); + delete m.lastIdx; // force redraw + m.draw(); +} +/** + * Library uses this to make the app update itself + * @param {int} mode New Quite Mode + */ +function setAppMode(mode) { + if (mode === current) return; + current = mode; + delete m.lastIdx; // force redraw + applyTheme(); + if (m.lastIdx===undefined) m.draw(); // applyTheme didn't redraw menu, but we need to show updated mode +} + +let m; function showMainMenu() { - let _m, menu = { + let menu = { "": {"title": "Quiet Mode"}, "< Exit": () => load() }; // "Current Mode""Silent" won't fit on Bangle.js 2 menu["Current"+((process.env.HWVERSION===2) ? "" : " Mode")] = { value: current, - format: v => modeNames[v], - onchange: function(v) { - if (v<0) {v = 2;} - if (v>2) {v = 0;} - require("qmsched").setMode(v); - current = v; - this.value = v; - }, + min:0, max:2, wrap: true, + format: () => modeNames[current], + onchange: require("qmsched").setMode, // library calls setAppMode(), which updates `current` }; scheds.sort((a, b) => (a.hr-b.hr)); scheds.forEach((sched, idx) => { menu[formatTime(sched.hr)] = { format: () => modeNames[sched.mode], // abuse format to right-align text - onchange: function() { - _m.draw = ()=> {}; // prevent redraw of main menu over edit menu + onchange: () => { + m.draw = ()=> {}; // prevent redraw of main menu over edit menu (needed because we abuse format/onchange) showEditMenu(idx); } }; }); menu["Add Schedule"] = () => showEditMenu(-1); + menu["Switch Theme"] = { + value: !!get("switchTheme"), + format: v => v ? /*LANG*/"Yes" : /*LANG*/"No", + onchange: v => v ? set("switchTheme", v) : unset("switchTheme"), + }; menu["LCD Settings"] = () => showOptionsMenu(); - _m = E.showMenu(menu); + m = E.showMenu(menu); } function showEditMenu(index) { @@ -174,7 +204,7 @@ function showEditMenu(index) { showMainMenu(); }; } - return E.showMenu(menu); + m = E.showMenu(menu); } function showOptionsMenu() { @@ -244,7 +274,7 @@ function showOptionsMenu() { onchange: () => {toggle("wakeOnTwist");}, }, }; - return E.showMenu(oMenu); + m = E.showMenu(oMenu); } loadSettings(); diff --git a/apps/qmsched/boot.js b/apps/qmsched/boot.js index c3bc49b58..c4610ce3e 100644 --- a/apps/qmsched/boot.js +++ b/apps/qmsched/boot.js @@ -1,5 +1,7 @@ // apply Quiet Mode schedules (function qm() { + if (Bangle.qmTimeout) clearTimeout(Bangle.qmTimeout); // so the app can eval() this file to apply changes right away + delete Bangle.qmTimeout; let bSettings = require('Storage').readJSON('setting.json',true)||{}; const curr = 0|bSettings.quiet; delete bSettings; @@ -18,7 +20,7 @@ let t = 3600000*(next.hr-hr); // timeout in milliseconds if (t<0) {t += 86400000;} // scheduled for tomorrow: add a day /* update quiet mode at the correct time. */ - setTimeout(() => { + Bangle.qmTimeout=setTimeout(() => { require("qmsched").setMode(mode); qm(); // schedule next update }, t); diff --git a/apps/qmsched/lib.js b/apps/qmsched/lib.js index e9ed3ec90..e048d15bf 100644 --- a/apps/qmsched/lib.js +++ b/apps/qmsched/lib.js @@ -1,5 +1,37 @@ /** - * Apply LCD options for given mode + * Apply appropriate theme for given mode + * @param {int} mode Quiet Mode + */ +function switchTheme(mode) { + if (!!mode === g.theme.dark) return; // nothing to do + let s = require("Storage").readJSON("setting.json", 1) || {}; + // default themes, copied from settings.js:showThemeMenu() + function cl(x) { return g.setColor(x).getColor(); } + s.theme = mode ? { + // 'Dark BW' + fg: cl("#fff"), bg: cl("#000"), + fg2: cl("#0ff"), bg2: cl("#000"), + fgH: cl("#fff"), bgH: cl("#00f"), + dark: true + } : { + // 'Light BW' + fg: cl("#000"), bg: cl("#fff"), + fg2: cl("#000"), bg2: cl("#cff"), + fgH: cl("#000"), bgH: cl("#0ff"), + dark: false + }; + require("Storage").writeJSON("setting.json", s); + if (typeof __FILE__ === 'string') { // undefined means it loaded the default clock + const info = require("Storage").readJSON(__FILE__.split(".")[0]+".info", 1); + if (info && info.type!=="clock") { // info can have no type (but then it isn't a clock) + return; // not a clock: wait for user to switch apps + } + } + // current app is a clock: reload it with new theme + load(global.__FILE__); +} +/** + * Apply LCD options and theme for given mode * @param {int} mode Quiet Mode */ exports.applyOptions = function(mode) { @@ -8,6 +40,7 @@ exports.applyOptions = function(mode) { Bangle.setOptions(get("options", {})); Bangle.setLCDBrightness(get("brightness", 1)); Bangle.setLCDTimeout(get("timeout", 10)); + if ((require("Storage").readJSON("qmsched.json", 1) || {}).switchTheme) switchTheme(mode); }; /** * Set new Quiet Mode and apply Bangle options @@ -20,4 +53,5 @@ exports.setMode = function(mode) { )); exports.applyOptions(mode); if (typeof WIDGETS === "object" && "qmsched" in WIDGETS) WIDGETS["qmsched"].draw(); + if (global.__FILE__ === "qmsched.app.js") setAppMode(mode); }; diff --git a/apps/qmsched/widget.js b/apps/qmsched/widget.js index b25192b06..daa11ac71 100644 --- a/apps/qmsched/widget.js +++ b/apps/qmsched/widget.js @@ -18,7 +18,7 @@ return; // drawWidgets will call draw again } let x = this.x, y = this.y; - g.clearRect(x, y, x+23, y+23); + g.reset().clearRect(x, y, x+23, y+23); // quiet mode: draw red one-way-street sign (dim red on Bangle.js 1) x = this.x+11;y = this.y+11; // center of widget g.setColor(process.env.HWVERSION===2 ? 1 : 0.8, 0, 0).fillCircle(x, y, 8); From 0b455f921c5b4d2514db5061b5ade73f817050a5 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Wed, 12 Jan 2022 19:09:00 +0100 Subject: [PATCH 439/489] qmsched: set minutes in 5-min steps --- apps/qmsched/ChangeLog | 1 + apps/qmsched/app.js | 24 ++++++------------------ 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/apps/qmsched/ChangeLog b/apps/qmsched/ChangeLog index cc0050cdd..c868b6668 100644 --- a/apps/qmsched/ChangeLog +++ b/apps/qmsched/ChangeLog @@ -5,3 +5,4 @@ 0.05: Avoid immediately redrawing widgets on load 0.06: Fix: don't try to redraw widget when widgets not loaded 0.07: Option to switch theme + Changed time selection to 5-minute intervals \ No newline at end of file diff --git a/apps/qmsched/app.js b/apps/qmsched/app.js index 433dab409..b65761d5c 100644 --- a/apps/qmsched/app.js +++ b/apps/qmsched/app.js @@ -155,31 +155,19 @@ function showEditMenu(index) { "< Cancel": () => showMainMenu(), "Hours": { value: hrs, - onchange: function(v) { - if (v<0) {v = 23;} - if (v>23) {v = 0;} - hrs = v; - this.value = v; - }, // no arrow fn -> preserve 'this' + min:0, max:23, wrap:true, + onchange: v => {hrs = v;}, }, "Minutes": { value: mins, - onchange: function(v) { - if (v<0) {v = 59;} - if (v>59) {v = 0;} - mins = v; - this.value = v; - }, // no arrow fn -> preserve 'this' + min:0, max:55, step:5, wrap:true, + onchange: v => {mins = v;}, }, "Switch to": { value: mode, + min:0, max:2, wrap:true, format: v => modeNames[v], - onchange: function(v) { - if (v<0) {v = 2;} - if (v>2) {v = 0;} - mode = v; - this.value = v; - }, // no arrow fn -> preserve 'this' + onchange: v => {mode = v;}, }, }; function getSched() { From 8edda16ca2b9bfe47d358b50655d707657e71871 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 19:48:24 +0100 Subject: [PATCH 440/489] Log pressure if sensor is available --- apps/recorder/widget.js | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index 8f82f1f37..bffa15283 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -133,8 +133,38 @@ draw : (x,y) => g.reset().drawImage(atob("DAwBAAMMeeeeeeeecOMMAAMMMMAA"),x,y) }; } - // TODO: recAltitude from pressure sensor }; + if (Bangle.getPressure){ + recorders['baro'] = function() { + var temp="",press="",alt=""; + function onPress(c) { + temp=c.temperature; + press=c.pressure; + alt=c.altitude; + } + return { + name : "Baro", + fields : ["Barometer Temperature", "Barometer Pressure", "Barometer Altitude"], + getValues : () => { + var r = [temp,press,alt]; + temp=""; + press=""; + alt=""; + return r; + }, + start : () => { + Bangle.setBarometerPower(1,"recorder"); + Bangle.on('pressure', onPress); + }, + stop : () => { + Bangle.setBarometerPower(0,"recorder"); + Bangle.removeListener('pressure', onPress); + }, + draw : (x,y) => g.setColor("#0f0").drawImage(atob("DAwBAAH4EIHIEIHIEIHIEIEIH4AA"),x,y) + }; + } + } + /* eg. foobar.recorder.js (function(recorders) { recorders.foobar = { From 58e9a4705192156ce7e58158cee79b07997145ab Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 20:35:52 +0100 Subject: [PATCH 441/489] Record empty string if no value instead of 0 --- apps/recorder/widget.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index bffa15283..9d66e0a02 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -52,7 +52,7 @@ }; }, hrm:function() { - var bpm = 0, bpmConfidence = 0; + var bpm = "", bpmConfidence = ""; function onHRM(h) { if (h.confidence >= bpmConfidence) { bpmConfidence = h.confidence; @@ -64,7 +64,7 @@ fields : ["Heartrate", "Confidence"], getValues : () => { var r = [bpm,bpmConfidence]; - bpm = 0; bpmConfidence = 0; + bpm = ""; bpmConfidence = ""; return r; }, start : () => { From c9efc0958199f5ed1f515e4ec09369a0d18d33cb Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 20:45:32 +0100 Subject: [PATCH 442/489] Always log bpm and confidence --- apps/recorder/widget.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index 9d66e0a02..359af721f 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -54,10 +54,8 @@ hrm:function() { var bpm = "", bpmConfidence = ""; function onHRM(h) { - if (h.confidence >= bpmConfidence) { - bpmConfidence = h.confidence; - bpm = h.bpm; - } + bpmConfidence = h.confidence; + bpm = h.bpm; } return { name : "HR", From 412b5dd20c08787bb334af2f287423cd8ede4f3e Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 19:56:03 +0100 Subject: [PATCH 443/489] Move recorder code to plugin in coretemp app --- apps.json | 3 ++- apps/coretemp/ChangeLog | 1 + apps/coretemp/recorder.js | 31 +++++++++++++++++++++++++++++++ apps/recorder/widget.js | 26 -------------------------- 4 files changed, 34 insertions(+), 27 deletions(-) create mode 100644 apps/coretemp/recorder.js diff --git a/apps.json b/apps.json index 4c6f3bdcf..e3964fd2a 100644 --- a/apps.json +++ b/apps.json @@ -5046,7 +5046,7 @@ { "id": "coretemp", "name": "CoreTemp", - "version": "0.02", + "version": "0.03", "description": "Display CoreTemp device sensor data", "icon": "coretemp.png", "type": "app", @@ -5056,6 +5056,7 @@ "storage": [ {"name":"coretemp.wid.js","url":"widget.js"}, {"name":"coretemp.app.js","url":"coretemp.js"}, + {"name":"coretemp.recorder.js","url":"recorder.js"}, {"name":"coretemp.settings.js","url":"settings.js"}, {"name":"coretemp.img","url":"coretemp-icon.js","evaluate":true}, {"name":"coretemp.boot.js","url":"boot.js"} diff --git a/apps/coretemp/ChangeLog b/apps/coretemp/ChangeLog index ea6911f1a..ad6f0742d 100644 --- a/apps/coretemp/ChangeLog +++ b/apps/coretemp/ChangeLog @@ -1,2 +1,3 @@ 0.01: New app 0.02: Cleanup interface and add settings, widget, add skin temp reporting. +0.03: Move code for recording to this app diff --git a/apps/coretemp/recorder.js b/apps/coretemp/recorder.js new file mode 100644 index 000000000..1499605f3 --- /dev/null +++ b/apps/coretemp/recorder.js @@ -0,0 +1,31 @@ +(function(recorders) { + recorders.coretemp = function() { + var core = "", skin = ""; + var hasCore = false; + function onCore(c) { + core=c.core; + skin=c.skin; + hasCore = true; + } + return { + name : "Core", + fields : ["Core","Skin"], + getValues : () => { + var r = [core,skin]; + core = ""; + skin = ""; + return r; + }, + start : () => { + hasCore = false; + Bangle.on('CoreTemp', onCore); + }, + stop : () => { + hasCore = false; + Bangle.removeListener('CoreTemp', onCore); + }, + draw : (x,y) => g.setColor(hasCore?"#0f0":"#8f8").drawImage(atob("DAyBAAHh0js3EuDMA8A8AWBnDj9A8A=="),x,y) + }; + } +}) + diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index 359af721f..de465b7c1 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -90,32 +90,6 @@ draw : (x,y) => g.setColor(Bangle.isCharging() ? "#0f0" : "#ff0").drawImage(atob("DAwBAABgH4G4EYG4H4H4H4GIH4AA"),x,y) }; }, - temp:function() { - var core = 0, skin = 0; - var hasCore = false; - function onCore(c) { - core=c.core; - skin=c.skin; - hasCore = true; - } - return { - name : "Core", - fields : ["Core","Skin"], - getValues : () => { - var r = [core,skin]; - return r; - }, - start : () => { - hasCore = false; - Bangle.on('CoreTemp', onCore); - }, - stop : () => { - hasCore = false; - Bangle.removeListener('CoreTemp', onCore); - }, - draw : (x,y) => g.setColor(hasCore?"#0f0":"#8f8").drawImage(atob("DAwBAAAOAKPOfgZgZgZgZgfgPAAA"),x,y) - }; - }, steps:function() { var lastSteps = 0; return { From 6b22bd84866a13e1d21f29fca670109f4cb10059 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 22:52:03 +0100 Subject: [PATCH 444/489] Bump version and changelog for recorder --- apps.json | 2 +- apps/recorder/ChangeLog | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index e3964fd2a..d121ddccc 100644 --- a/apps.json +++ b/apps.json @@ -770,7 +770,7 @@ "id": "recorder", "name": "Recorder (BETA)", "shortName": "Recorder", - "version": "0.06", + "version": "0.07", "description": "Record GPS position, heart rate and more in the background, then download to your PC.", "icon": "app.png", "tags": "tool,outdoors,gps,widget", diff --git a/apps/recorder/ChangeLog b/apps/recorder/ChangeLog index dbf086f7d..e2ae0111b 100644 --- a/apps/recorder/ChangeLog +++ b/apps/recorder/ChangeLog @@ -8,3 +8,6 @@ Fix execution of other recorders (*.recorder.js) Modified icons and colors for better visibility Only show plotting speed if Latitude is available +0.07: Add recording for Barometer + Record all HRM events + Move recording for CoreTemp to its own app From 225c5566cda17464b5a5d6be0af2a06188b4b9ac Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 20:26:07 +0100 Subject: [PATCH 445/489] Move previously registered HRM listener over if needed --- apps/bthrm/boot.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/apps/bthrm/boot.js b/apps/bthrm/boot.js index 0aa8d5c96..85333feb1 100644 --- a/apps/bthrm/boot.js +++ b/apps/bthrm/boot.js @@ -12,7 +12,6 @@ Bangle.isHRMOn = function() { var settings = require('Storage').readJSON("bthrm.json", true) || {}; - print(settings); if (settings.enabled && !settings.replace){ return origIsHRMOn(); } else if (settings.enabled && settings.replace){ @@ -107,8 +106,20 @@ if (settings.enabled || !isOn){ Bangle.setBTHRMPower(isOn, app); } - if (settings.enabled && !settings.replace || !isOn){ + if ((settings.enabled && !settings.replace) || !settings.enabled || !isOn){ origSetHRMPower(isOn, app); } } + + var settings = require('Storage').readJSON("bthrm.json", true) || {}; + if (settings.enabled && settings.replace){ + if (!(Bangle._PWR===undefined) && !(Bangle._PWR.HRM===undefined)){ + for (var i = 0; i < Bangle._PWR.HRM.length; i++){ + var app = Bangle._PWR.HRM[i]; + origSetHRMPower(0, app); + Bangle.setBTHRMPower(1, app); + if (Bangle._PWR.HRM===undefined) break; + } + } +} })(); From 92139253bebb1846d910e1392d83689e6b31886a Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 19:44:18 +0100 Subject: [PATCH 446/489] Set src property if emitting an event --- apps/bthrm/boot.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/apps/bthrm/boot.js b/apps/bthrm/boot.js index 85333feb1..fbc872630 100644 --- a/apps/bthrm/boot.js +++ b/apps/bthrm/boot.js @@ -68,13 +68,11 @@ var interval = dv.getUint16(idx,1); // in milliseconds }*/ - - var eventName = settings.replace ? "HRM" : "BTHRM"; - - Bangle.emit(eventName, { + Bangle.emit(settings.replace?"HRM":"BTHRM", { bpm:bpm, - confidence:100 - }); + confidence:100, + src:settings.replace?"bthrm":undefined + }); }); return characteristic.startNotifications(); }).then(function() { From b02befe3dd0b9ba65b46339acee17358bd9c85d8 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 19:46:15 +0100 Subject: [PATCH 447/489] Record empty string if no value instead of 0 --- apps/bthrm/recorder.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/bthrm/recorder.js b/apps/bthrm/recorder.js index 40f64a676..b1c27660d 100644 --- a/apps/bthrm/recorder.js +++ b/apps/bthrm/recorder.js @@ -1,15 +1,15 @@ (function(recorders) { recorders.bthrm = function() { - var bpm = 0; + var bpm = ""; function onHRM(h) { - bpm = h.bpm; + bpm = h.bpm; } return { name : "BTHR", fields : ["BT Heartrate"], getValues : () => { result = [bpm]; - bpm = 0; + bpm = ""; return result; }, start : () => { From e0a4cea3b8d3666686d11fb8387b135915c4b88c Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 23:24:38 +0100 Subject: [PATCH 448/489] Explicit call to setBTHRMPower is not needed --- apps/bthrm/bthrm.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/bthrm/bthrm.js b/apps/bthrm/bthrm.js index 7c80c735f..81d5d5997 100644 --- a/apps/bthrm/bthrm.js +++ b/apps/bthrm/bthrm.js @@ -35,7 +35,6 @@ Bangle.on('BTHRM', onBtHrm); Bangle.on('HRM', onHrm); Bangle.setHRMPower(1,'bthrm') -Bangle.setBTHRMPower(1,'bthrm') g.clear(); Bangle.loadWidgets(); From 9aba113acb72fbd6b277844cfc5abfe7a3a02ca2 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 23:31:44 +0100 Subject: [PATCH 449/489] Show actual source for HRM event --- apps/bthrm/bthrm.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/bthrm/bthrm.js b/apps/bthrm/bthrm.js index 81d5d5997..712344b11 100644 --- a/apps/bthrm/bthrm.js +++ b/apps/bthrm/bthrm.js @@ -9,13 +9,14 @@ function draw(y, event, type, counter) { var px = g.getWidth()/2; g.reset(); g.setFontAlign(0,0); - g.clearRect(0,y,g.getWidth(),y+80); + g.clearRect(0,y,g.getWidth(),y+75); if (type == null || event == null || counter == 0) return; var str = event.bpm + ""; g.setFontVector(40).drawString(str,px,y+20); str = "Confidence: " + event.confidence; g.setFontVector(12).drawString(str,px,y+50); str = "Event: " + type; + if (type == "HRM") str += " Source: " + (event.src ? event.src : "internal"); g.setFontVector(12).drawString(str,px,y+60); } From 56e33ed98ba854f52a807cd066ca139cfbf28062 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 23:10:36 +0100 Subject: [PATCH 450/489] Bump version and changelog --- apps.json | 2 +- apps/bthrm/ChangeLog | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 4c6f3bdcf..dc887d255 100644 --- a/apps.json +++ b/apps.json @@ -1042,7 +1042,7 @@ "id": "bthrm", "name": "Bluetooth Heart Rate Monitor", "shortName": "BT HRM", - "version": "0.02", + "version": "0.03", "description": "Overrides Bangle.js's build in heart rate monitor with an external Bluetooth one.", "icon": "app.png", "type": "app", diff --git a/apps/bthrm/ChangeLog b/apps/bthrm/ChangeLog index 27a58dd78..481d855c8 100644 --- a/apps/bthrm/ChangeLog +++ b/apps/bthrm/ChangeLog @@ -2,3 +2,6 @@ 0.02: Make overriding the HRM event optional Emit BTHRM event for external sensor Add recorder app plugin +0.03: Prevent readings from internal sensor mixing into BT values + Mark events with src property + Show actual source of event in app From a98a6015b1c381476901aae9abb89370034c243b Mon Sep 17 00:00:00 2001 From: hughbarney Date: Wed, 12 Jan 2022 22:45:42 +0000 Subject: [PATCH 451/489] Simple Pedometer and Lato Pedometer widgets --- apps.json | 32 ++++++++++++++++++++++++++++++++ apps/widpa/README.md | 16 ++++++++++++++++ apps/widpa/screenshot_widpa.png | Bin 0 -> 246 bytes apps/widpa/widpa.wid.js | 17 +++++++++++++++++ apps/widpb/README.md | 17 +++++++++++++++++ apps/widpb/screenshot_widpb.png | Bin 0 -> 338 bytes apps/widpb/widpb.wid.js | 20 ++++++++++++++++++++ 7 files changed, 102 insertions(+) create mode 100644 apps/widpa/README.md create mode 100644 apps/widpa/screenshot_widpa.png create mode 100644 apps/widpa/widpa.wid.js create mode 100644 apps/widpb/README.md create mode 100644 apps/widpb/screenshot_widpb.png create mode 100644 apps/widpb/widpb.wid.js diff --git a/apps.json b/apps.json index 4c6f3bdcf..56ddbed2d 100644 --- a/apps.json +++ b/apps.json @@ -5577,5 +5577,37 @@ "data": [ {"name":"banglexercise.json"} ] + }, + { + "id": "widpa", + "name": "Simple Pedometer", + "shortName":"Simple Pedometer", + "icon": "screenshot_widpa.png", + "screenshots": [{"url":"screenshot_widpa.png"}], + "version":"0.01", + "type": "widget", + "supports": ["BANGLEJS", "BANGLEJS2"], + "readme": "README.md", + "description": "Displays the current step count from `Bangle.getHealthStatus(\"day\").steps` in 12x16 font, requires firmware v2.11.21 or later", + "tags": "widget,battery", + "storage": [ + {"name":"widpa.wid.js","url":"widpa.wid.js"} + ] + }, + { + "id": "widpb", + "name": "Lato Pedometer", + "shortName":"Lato Pedometer", + "icon": "screenshot_widpb.png", + "screenshots": [{"url":"screenshot_widpb.png"}], + "version":"0.01", + "type": "widget", + "supports": ["BANGLEJS", "BANGLEJS2"], + "readme": "README.md", + "description": "Displays the current step count from `Bangle.getHealthStatus(\"day\").steps` in the Lato font, requires firmware v2.11.21 or later", + "tags": "widget,battery", + "storage": [ + {"name":"widpb.wid.js","url":"widpb.wid.js"} + ] } ] diff --git a/apps/widpa/README.md b/apps/widpa/README.md new file mode 100644 index 000000000..92fbb8c11 --- /dev/null +++ b/apps/widpa/README.md @@ -0,0 +1,16 @@ +# Simple Pedometer Widget + +*Displays the current step count from `Bangle.getHealthStatus("day").steps` in (6x8,2) font, Requires firmware v2.11.21 or later* + +* Designed to be small, minimal, does one thing well, no settings +* Supports Bangle 1 and Bangle 2 + +## Notes + +* Requires firmware v2.11.21 or later +* `Bangle.getHealthStatus("day").steps` is reset to zero if you reboot your watch with a long BTN Press +* The step count displayed may be a few steps more than that reported by widpedpm as widpedom may not always be loaded. + +![](screenshot_widpa.png) + +Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) diff --git a/apps/widpa/screenshot_widpa.png b/apps/widpa/screenshot_widpa.png new file mode 100644 index 0000000000000000000000000000000000000000..e33550f50d6376cdec0f5faeaaec87a548e979f3 GIT binary patch literal 246 zcmVPx#ut`KgR9HvtR?!ZCAPAKI|7hFVXv)Gv%MBU5LKnv!1l3w=IsBm{;Y7hy!if+i zt`bDlHCbC=GLK*SD_<(j-;?;SN*ql>V`}XP=SdudYmIA4cS;~Itw=-?;acNE5}LPn zd3@HcJOjg-2t@*I71R-{-B#^qQX)w-?ftr)kiF%s-rLE#9ainMijU5kr=Io{-~9)k w#YeOA%wRYYNItLexL2&#j%#(L5?&O$01ECQ%Y=MG this.width) {this.width = w; setTimeout(() => Bangle.drawWidgets(),10); return;} + g.reset(); + g.setColor(g.theme.bg); + g.fillRect(this.x, this.y, this.x + this.width, this.y + 23); + g.setColor(g.theme.fg); + g.setFont('6x8',2); + g.setFontAlign(-1, 0); + g.drawString(steps, this.x, this.y + 12); +}}; diff --git a/apps/widpb/README.md b/apps/widpb/README.md new file mode 100644 index 000000000..bec127b6b --- /dev/null +++ b/apps/widpb/README.md @@ -0,0 +1,17 @@ +# Lato Pedometer Widget + +*Displays the current step count from `Bangle.getHealthStatus("day").steps` in the Lato font, Requires firmware v2.11.21 or later* + +* Designed to be minimal, does one thing well, no settings +* Supports Bangle 1 and Bangle 2 + +## Notes + +* Requires firmware v2.11.21 or later +* Uses the Lato custom font, so memory footprint is 500 bytes larger than 'Simple Pedometer Widget' +* `Bangle.getHealthStatus("day").steps` is reset to zero if you reboot your watch with a long BTN Press +* The step count displayed may be a few steps more than that reported by widpedpm as widpedom may not always be loaded. + +![](screenshot_widpb.png) + +Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) diff --git a/apps/widpb/screenshot_widpb.png b/apps/widpb/screenshot_widpb.png new file mode 100644 index 0000000000000000000000000000000000000000..af1222e7e8663af2945d6f4c2978cad7a4cac5b8 GIT binary patch literal 338 zcmV-Y0j>UtP)Px$3`s;mR9HvtSkVrIAPhVH|D!RO!{FR#y9Yyvz8N=Y*KTlEYOVFR!BajWi>bK3 zBBhk8=207sF{40i+cA6eb$e`xCF&8hNkpP=jL6vhSvZDZ(xStFt2!bhkuB zk)~GG^WKS!M)1QD!3{x;yRIn6%d>;et2%04rqT+g+g&SrF0c*j5uRBqO$7OQ this.width) {this.width = w; setTimeout(() => Bangle.drawWidgets(),10); return;} + g.reset(); + g.setColor(g.theme.bg); + g.fillRect(this.x, this.y, this.x + this.width, this.y + 23); // erase background + g.setColor(g.theme.fg); + // Lato from fonts.google.com, Actual height 17 (17 - 1), Numeric only + const scale = 1; + g.setFontCustom(atob("AAAAABwAAOAAAgAAHAADwAD4AB8AB8AA+AAeAADAAAAOAAP+AH/8B4DwMAGBgAwMAGBgAwOAOA//gD/4AD4AAAAAAAABgAAcAwDAGAwAwP/+B//wAAGAAAwAAGAAAAAAAAIAwHgOA4DwMA+BgOwMDmBg4wOeGA/gwDwGAAAAAAAAAGAHA8A4DwMAGBhAwMMGBjgwOcOA+/gDj4AAAAABgAAcAAHgADsAA5gAOMAHBgBwMAP/+B//wABgAAMAAAAAAAgD4OB/AwOYGBjAwMYGBjBwMe8Bh/AIHwAAAAAAAAAfAAP8AHxwB8GAdgwPMGBxgwMOOAB/gAH4AAAAAAABgAAMAABgAwMAeBgPgMHwBj4AN8AB+AAPAABAAAAAAAMfAH38B/xwMcGBhgwMMGBjgwP+OA+/gDj4AAAAAAAAOAAH4AA/gQMMGBgzwME8BhvAOPgA/4AD8AAEAAAAAAGAwA4OAHBwAAA="), 46, atob("BAgMDAwMDAwMDAwMBQ=="), 21+(scale<<8)+(1<<16)); + g.setFontAlign(-1, 0); + g.drawString(steps, this.x, this.y + 12); +}}; From 60bb06a655595a6bab3f539c4f266eea1f934f63 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Wed, 12 Jan 2022 22:46:16 +0000 Subject: [PATCH 452/489] Simple Pedometer and Lato Pedometer widgets --- apps/widpa/ChangeLog | 1 + apps/widpb/ChangeLog | 1 + 2 files changed, 2 insertions(+) create mode 100644 apps/widpa/ChangeLog create mode 100644 apps/widpb/ChangeLog diff --git a/apps/widpa/ChangeLog b/apps/widpa/ChangeLog new file mode 100644 index 000000000..7b83706bf --- /dev/null +++ b/apps/widpa/ChangeLog @@ -0,0 +1 @@ +0.01: First release diff --git a/apps/widpb/ChangeLog b/apps/widpb/ChangeLog new file mode 100644 index 000000000..7b83706bf --- /dev/null +++ b/apps/widpb/ChangeLog @@ -0,0 +1 @@ +0.01: First release From 223f6b6b8120f34e5063e7fa4ccde04deeb22f83 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Wed, 12 Jan 2022 23:57:44 +0100 Subject: [PATCH 453/489] fixes #1271 & some code rework + moved settings-helper method def to load settings method + settingsfile as const + isBangle1 via HWVERSION==1 --- apps.json | 2 +- apps/antonclk/ChangeLog | 5 ++++- apps/antonclk/README.md | 6 +++--- apps/antonclk/app.js | 36 +++++++++++++++++++++++------------- apps/antonclk/settings.js | 4 ++-- 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/apps.json b/apps.json index 4c6f3bdcf..dd2ddbcb3 100644 --- a/apps.json +++ b/apps.json @@ -4279,7 +4279,7 @@ { "id": "antonclk", "name": "Anton Clock", - "version": "0.05", + "version": "0.06", "description": "A clock using the bold Anton font, optionally showing seconds and date in ISO-8601 format.", "readme":"README.md", "icon": "app.png", diff --git a/apps/antonclk/ChangeLog b/apps/antonclk/ChangeLog index fdf20c175..4dca8053e 100644 --- a/apps/antonclk/ChangeLog +++ b/apps/antonclk/ChangeLog @@ -4,4 +4,7 @@ 0.04: Clock can optionally show seconds, date optionally in ISO-8601 format, weekdays and uppercase configurable, too. 0.05: Clock can optionally show ISO-8601 calendar weeknumber (default: Off) when weekday name "Off": week #: - when weekday name "On": weekday name is cut at 6th position and .# is added \ No newline at end of file + when weekday name "On": weekday name is cut at 6th position and .# is added +0.06: fixes #1271 - wrong settings name + when weekday name and calendar weeknumber are on then display is # + week is buffered until date or timezone changes \ No newline at end of file diff --git a/apps/antonclk/README.md b/apps/antonclk/README.md index 85c03788d..28a38f5fd 100644 --- a/apps/antonclk/README.md +++ b/apps/antonclk/README.md @@ -40,9 +40,9 @@ The main menu contains several settings covering Anton clock in general. * **Show Weekday** - Weekday is shown in the time presentation without seconds. Weekday name depends on the current locale. If seconds are shown, the weekday is never shown as there is not enough space on the watch face. -* **Show Weeknumber** - Week-number (ISO-8601) is shown. (default: Off) -If "Show Weekday" is "Off" the week-number is displayed as "week #:". -If "Show Weekday" is "On" the weekday name is cut at 6th position and suffixed with ".#". +* **Show CalWeek** - Week-number (ISO-8601) is shown. (default: Off) +If "Show Weekday" is "Off" displays the week-number as "week #". +If "Show Weekday" is "On" displays "weekday name short" with " #" . If seconds are shown, the week number is never shown as there is not enough space on the watch face. * **Vector font** - Use the built-in vector font for dates and weekday. This can improve readability. diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index 05758cbfd..7d8c8ce89 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -1,6 +1,6 @@ // Clock with large digits using the "Anton" bold font -var SETTINGSFILE = "antonclk.json"; +const SETTINGSFILE = "antonclk.json"; Graphics.prototype.setFontAnton = function(scale) { // Actual height 69 (68 - 0) @@ -28,7 +28,7 @@ var drawTimeout; var queueMillis = 1000; var secondsScreen = true; -var isBangle1 = (g.getWidth() == 240); +var isBangle1 = (process.env.HWVERSION == 1); //For development purposes /* @@ -50,13 +50,11 @@ require('Storage').writeJSON(SETTINGSFILE, { require('Storage').erase(SETTINGSFILE); */ -// Helper method for loading the settings -function def(value, def) { - return (value !== undefined ? value : def); -} - // Load settings function loadSettings() { + // Helper function default setting + function def (value, def) {return value !== undefined ? value : def;} + var settings = require('Storage').readJSON(SETTINGSFILE, true) || {}; secondsMode = def(settings.secondsMode, "Never"); secondsColoured = def(settings.secondsColoured, true); @@ -104,7 +102,14 @@ function isoStr(date) { return date.getFullYear() + "-" + ("0" + (date.getMonth() + 1)).substr(-2) + "-" + ("0" + date.getDate()).substr(-2); } +var calWeekBuffer = [false,false,false]; //buffer tz, date, week no (once calculated until other tz or date is requested) function ISO8601calWeek(date) { //copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480 + console.log(date); + dateNoTime = date; dateNoTime.setHours(0,0,0,0); + console.log(dateNoTime); + if (calWeekBuffer[0] === date.getTimezoneOffset() && calWeekBuffer[1] === dateNoTime) return calWeekBuffer[2]; + calWeekBuffer[0] = date.getTimezoneOffset(); + calWeekBuffer[1] = dateNoTime; var tdt = new Date(date.valueOf()); var dayn = (date.getDay() + 6) % 7; tdt.setDate(tdt.getDate() - dayn + 3); @@ -113,7 +118,8 @@ function ISO8601calWeek(date) { //copied from: https://gist.github.com/IamSilviu if (tdt.getDay() !== 4) { tdt.setMonth(0, 1 + ((4 - tdt.getDay()) + 7) % 7); } - return 1 + Math.ceil((firstThursday - tdt) / 604800000); + calWeekBuffer[2] = 1 + Math.ceil((firstThursday - tdt) / 604800000); + return calWeekBuffer[2]; } function doColor() { @@ -186,13 +192,17 @@ function draw() { else g.setFont("6x8", 2); g.drawString(dateStr, x, y); - if (weekDay || calWeek) { - var dowwumStr = require("locale").dow(date); + if (calWeek || weekDay) { + var dowcwStr = ""; if (calWeek) - dowwumStr = (weekDay ? dowwumStr.substr(0,Math.min(dowwumStr.length,6)) + (dowwumStr.length>=6 ? "." : "") : "week ") + "#" + ISO8601calWeek(date); //TODO: locale for "week" + dowcwStr = " #" + ("0" + ISO8601calWeek(date)).substring(-2); + if (weekDay) + dowcwStr = require("locale").dow(date, calWeek ? 1 : 0) + dowcwStr; //weekDay e.g. Monday or weekDayShort # e.g. Mon #01 + else //week #01 + dowcwStr = /*LANG*/"week" + dowcwStr; if (upperCase) - dowwumStr = dowwumStr.toUpperCase(); - g.drawString(dowwumStr, x, y + (vectorFont ? 26 : 16)); + dowcwStr = dowcwStr.toUpperCase(); + g.drawString(dowcwStr, x, y + (vectorFont ? 26 : 16)); } } diff --git a/apps/antonclk/settings.js b/apps/antonclk/settings.js index 293aa0438..45c89f0a4 100644 --- a/apps/antonclk/settings.js +++ b/apps/antonclk/settings.js @@ -48,10 +48,10 @@ } }, "Show Weeknumber": { - value: (settings.weekNum !== undefined ? settings.weekNum : true), + value: (settings.calWeek !== undefined ? settings.calWeek : false), format: v => v ? "On" : "Off", onchange: v => { - settings.weekNum = v; + settings.calWeek = v; writeSettings(); } }, From b9031b1844be8ad0f3951c8baa9ea301d1c70085 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 13 Jan 2022 00:06:49 +0100 Subject: [PATCH 454/489] settings txt weeknumber was to long --- apps/antonclk/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/antonclk/settings.js b/apps/antonclk/settings.js index 45c89f0a4..e452b02c7 100644 --- a/apps/antonclk/settings.js +++ b/apps/antonclk/settings.js @@ -47,7 +47,7 @@ writeSettings(); } }, - "Show Weeknumber": { + "Show CalWeek": { value: (settings.calWeek !== undefined ? settings.calWeek : false), format: v => v ? "On" : "Off", onchange: v => { From 6098af08b8d36a6b8cdf33a8f440802de876ac69 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 13 Jan 2022 01:02:02 +0100 Subject: [PATCH 455/489] removed two log statements --- apps/antonclk/app.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index 7d8c8ce89..7b40d8eb5 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -104,9 +104,7 @@ function isoStr(date) { var calWeekBuffer = [false,false,false]; //buffer tz, date, week no (once calculated until other tz or date is requested) function ISO8601calWeek(date) { //copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480 - console.log(date); dateNoTime = date; dateNoTime.setHours(0,0,0,0); - console.log(dateNoTime); if (calWeekBuffer[0] === date.getTimezoneOffset() && calWeekBuffer[1] === dateNoTime) return calWeekBuffer[2]; calWeekBuffer[0] = date.getTimezoneOffset(); calWeekBuffer[1] = dateNoTime; From 5e4cd77313f3f25193d50365b4bde8c4bbc539d7 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 13 Jan 2022 06:41:37 +0100 Subject: [PATCH 456/489] Update apps.json --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index b90deb045..bef974af8 100644 --- a/apps.json +++ b/apps.json @@ -32,13 +32,13 @@ { "id": "ac_ac", "name": "A Configurable Analog Clock", "shortName":"Configurable Clock", - "version":"0.01", + "version":"0.02", "description": "AC-AC, a highly customizable analog clock", "icon": "app-icon.png", "type": "clock", "tags": "clock", "supports" : ["BANGLEJS2"], - "allow_emulator": true, + "allow_emulator": false, "screenshots": [{"url":"app-screenshot.png"}], "readme": "README.md", "custom": "Customizer.html", From ee02b17196fe4b62e8049ab619be3e55102ae21e Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 13 Jan 2022 06:42:13 +0100 Subject: [PATCH 457/489] Update Customizer.html --- apps/ac_ac/Customizer.html | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index 2846352d6..8cddbb4da 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -101,7 +101,7 @@