From ac652282ca54552f74ffcc0dd060041e3460c7c3 Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Wed, 9 Mar 2022 10:22:23 +0100 Subject: [PATCH 01/26] cscsensor: Test enable on Bangle2 --- apps/cscsensor/ChangeLog | 1 + apps/cscsensor/metadata.json | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/cscsensor/ChangeLog b/apps/cscsensor/ChangeLog index 8f23fa9f3..a98be5c0f 100644 --- a/apps/cscsensor/ChangeLog +++ b/apps/cscsensor/ChangeLog @@ -5,3 +5,4 @@ 0.05: Add cadence sensor support 0.06: Now read wheel rev as well as cadence sensor Improve connection code +0.07: Make Bangle.js 2 compatible diff --git a/apps/cscsensor/metadata.json b/apps/cscsensor/metadata.json index af338c59e..4006789ef 100644 --- a/apps/cscsensor/metadata.json +++ b/apps/cscsensor/metadata.json @@ -2,11 +2,11 @@ "id": "cscsensor", "name": "Cycling speed sensor", "shortName": "CSCSensor", - "version": "0.06", + "version": "0.07", "description": "Read BLE enabled cycling speed and cadence sensor and display readings on watch", "icon": "icons8-cycling-48.png", "tags": "outdoors,exercise,ble,bluetooth", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS", "BANGLEJS2"], "readme": "README.md", "storage": [ {"name":"cscsensor.app.js","url":"cscsensor.app.js"}, From 10892718cdf3192d3deb7abd5b755f072ec23ae4 Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Wed, 9 Mar 2022 22:53:31 +0100 Subject: [PATCH 02/26] cscsensor Fix button mapping --- apps/cscsensor/README.md | 6 +++--- apps/cscsensor/cscsensor.app.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/cscsensor/README.md b/apps/cscsensor/README.md index 9740fd9cf..3828e8e3e 100644 --- a/apps/cscsensor/README.md +++ b/apps/cscsensor/README.md @@ -11,9 +11,9 @@ Currently the app displays the following data: - total distance traveled - an icon with the battery status of the remote sensor -Button 1 resets all measurements except total distance traveled. The latter gets preserved by being written to storage every 0.1 miles and upon exiting the app. -If the watch app has not received an update from the sensor for at least 10 seconds, pushing button 3 will attempt to reconnect to the sensor. -Button 2 switches between the display for cycling speed and cadence. +Button 1 (swipe up on Bangle.js 2) resets all measurements except total distance traveled. The latter gets preserved by being written to storage every 0.1 miles and upon exiting the app. +If the watch app has not received an update from the sensor for at least 10 seconds, pushing button 3 (swipe down on Bangle.js 2) will attempt to reconnect to the sensor. +Button 2 (tap on Bangle.js 2) switches between the display for cycling speed and cadence. Values displayed are imperial or metric (depending on locale), cadence is in RPM, the wheel circumference can be adjusted in the global settings app. diff --git a/apps/cscsensor/cscsensor.app.js b/apps/cscsensor/cscsensor.app.js index e2af0db16..14403dd8d 100644 --- a/apps/cscsensor/cscsensor.app.js +++ b/apps/cscsensor/cscsensor.app.js @@ -254,8 +254,8 @@ E.on('kill',()=>{ NRF.on('disconnect', connection_setup); // restart if disconnected Bangle.setUI("updown", d=>{ if (d<0) { mySensor.reset(); g.clearRect(0, 48, W, H); mySensor.updateScreen(); } - if (d==0) { if (Date.now()-mySensor.lastBangleTime>10000) connection_setup(); } - if (d>0) { mySensor.toggleDisplayCadence(); g.clearRect(0, 48, W, H); mySensor.updateScreen(); } + else if (d>0) { if (Date.now()-mySensor.lastBangleTime>10000) connection_setup(); } + else { mySensor.toggleDisplayCadence(); g.clearRect(0, 48, W, H); mySensor.updateScreen(); } }); Bangle.loadWidgets(); From 2f2f6f0b0d7bcd8d0eb64c1d4edccb6e188cc560 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 11 Mar 2022 11:39:29 +0000 Subject: [PATCH 03/26] 0.43: Fix Gadgetbridge handling with Programmable:off --- apps/boot/ChangeLog | 1 + apps/boot/bootupdate.js | 2 +- apps/boot/metadata.json | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/boot/ChangeLog b/apps/boot/ChangeLog index 4c3d3b930..e75c9cc7b 100644 --- a/apps/boot/ChangeLog +++ b/apps/boot/ChangeLog @@ -46,3 +46,4 @@ 0.40: Bootloader now rebuilds for new firmware versions 0.41: Add Keyboard and Mouse Bluetooth HID option 0.42: Sort *.boot.js files lexically and by optional numeric priority, e.g. appname..boot.js +0.43: Fix Gadgetbridge handling with Programmable:off diff --git a/apps/boot/bootupdate.js b/apps/boot/bootupdate.js index 63424bfbf..e5a8cff51 100644 --- a/apps/boot/bootupdate.js +++ b/apps/boot/bootupdate.js @@ -38,7 +38,7 @@ LoopbackA.setConsole(true);\n`; boot += ` Bluetooth.line=""; Bluetooth.on('data',function(d) { - var l = (Bluetooth.line + d).split("\n"); + var l = (Bluetooth.line + d).split(/[\\n\\r]/); Bluetooth.line = l.pop(); l.forEach(n=>Bluetooth.emit("line",n)); }); diff --git a/apps/boot/metadata.json b/apps/boot/metadata.json index 4cbfd9c59..edddc6b41 100644 --- a/apps/boot/metadata.json +++ b/apps/boot/metadata.json @@ -1,7 +1,7 @@ { "id": "boot", "name": "Bootloader", - "version": "0.42", + "version": "0.43", "description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings", "icon": "bootloader.png", "type": "bootloader", From 7335289abfc7a333dcc6b6e960812915a94055a9 Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Sat, 12 Mar 2022 07:10:48 +0100 Subject: [PATCH 04/26] cscsensor Scale layout on BangleJS2 --- apps/cscsensor/cscsensor.app.js | 155 +++++++++++++++++--------------- 1 file changed, 81 insertions(+), 74 deletions(-) diff --git a/apps/cscsensor/cscsensor.app.js b/apps/cscsensor/cscsensor.app.js index 14403dd8d..4ebe7d57e 100644 --- a/apps/cscsensor/cscsensor.app.js +++ b/apps/cscsensor/cscsensor.app.js @@ -7,6 +7,11 @@ const SETTINGS_FILE = 'cscsensor.json'; const storage = require('Storage'); const W = g.getWidth(); const H = g.getHeight(); +const yStart = 48; +const rowHeight = (H-yStart)/6; +const yCol1 = W/2.7586; +const fontSizeLabel = W/12.632; +const fontSizeValue = W/9.2308; class CSCSensor { constructor() { @@ -22,7 +27,6 @@ class CSCSensor { this.speed = 0; this.maxSpeed = 0; this.lastSpeed = 0; - this.qUpdateScreen = true; this.lastRevsStart = -1; this.qMetric = !require("locale").speed(1).toString().endsWith("mph"); this.speedUnit = this.qMetric ? "km/h" : "mph"; @@ -49,6 +53,7 @@ class CSCSensor { toggleDisplayCadence() { this.showCadence = !this.showCadence; this.screenInit = true; + g.setBgColor(0, 0, 0); } setBatteryLevel(level) { @@ -63,14 +68,16 @@ class CSCSensor { } drawBatteryIcon() { - g.setColor(1, 1, 1).drawRect(10, 55, 20, 75).fillRect(14, 53, 16, 55).setColor(0).fillRect(11, 56, 19, 74); + g.setColor(1, 1, 1).drawRect(10*W/240, yStart+0.029167*H, 20*W/240, yStart+0.1125*H) + .fillRect(14*W/240, yStart+0.020833*H, 16*W/240, yStart+0.029167*H) + .setColor(0).fillRect(11*W/240, yStart+0.033333*H, 19*W/240, yStart+0.10833*H); if (this.batteryLevel!=-1) { if (this.batteryLevel<25) g.setColor(1, 0, 0); else if (this.batteryLevel<50) g.setColor(1, 0.5, 0); else g.setColor(0, 1, 0); - g.fillRect(11, 74-18*this.batteryLevel/100, 19, 74); + g.fillRect(11*W/240, (yStart+0.10833*H)-18*this.batteryLevel/100, 19*W/240, yStart+0.10833*H); } - else g.setFontVector(14).setFontAlign(0, 0, 0).setColor(0xffff).drawString("?", 16, 66); + else g.setFontVector(W/17.143).setFontAlign(0, 0, 0).setColor(0xffff).drawString("?", 16*W/240, yStart+0.075*H); } updateScreenRevs() { @@ -88,36 +95,36 @@ class CSCSensor { for (var i=0; i<6; ++i) { if ((i&1)==0) g.setColor(0, 0, 0); else g.setColor(0x30cd); - g.fillRect(0, 48+i*32, 86, 48+(i+1)*32); + g.fillRect(0, yStart+i*rowHeight, yCol1-1, yStart+(i+1)*rowHeight); if ((i&1)==1) g.setColor(0); else g.setColor(0x30cd); - g.fillRect(87, 48+i*32, 239, 48+(i+1)*32); - g.setColor(0.5, 0.5, 0.5).drawRect(87, 48+i*32, 239, 48+(i+1)*32).drawLine(0, 239, 239, 239);//.drawRect(0, 48, 87, 239); - g.moveTo(0, 80).lineTo(30, 80).lineTo(30, 48).lineTo(87, 48).lineTo(87, 239).lineTo(0, 239).lineTo(0, 80); + g.fillRect(yCol1, yStart+i*rowHeight, H-1, yStart+(i+1)*rowHeight); + g.setColor(0.5, 0.5, 0.5).drawRect(yCol1, yStart+i*rowHeight, H-1, yStart+(i+1)*rowHeight).drawLine(0, H-1, W-1, H-1); + g.moveTo(0, yStart+0.13333*H).lineTo(30*W/240, yStart+0.13333*H).lineTo(30*W/240, yStart).lineTo(yCol1, yStart).lineTo(yCol1, H-1).lineTo(0, H-1).lineTo(0, yStart+0.13333*H); } - g.setFontAlign(1, 0, 0).setFontVector(19).setColor(1, 1, 0); - g.drawString("Time:", 87, 66); - g.drawString("Speed:", 87, 98); - g.drawString("Ave spd:", 87, 130); - g.drawString("Max spd:", 87, 162); - g.drawString("Trip:", 87, 194); - g.drawString("Total:", 87, 226); + g.setFontAlign(1, 0, 0).setFontVector(fontSizeLabel).setColor(1, 1, 0); + g.drawString("Time:", yCol1, yStart+rowHeight/2+0*rowHeight); + g.drawString("Speed:", yCol1, yStart+rowHeight/2+1*rowHeight); + g.drawString("Avg spd:", yCol1, yStart+rowHeight/2+2*rowHeight); + g.drawString("Max spd:", yCol1, yStart+rowHeight/2+3*rowHeight); + g.drawString("Trip:", yCol1, yStart+rowHeight/2+4*rowHeight); + g.drawString("Total:", yCol1, yStart+rowHeight/2+5*rowHeight); this.drawBatteryIcon(); this.screenInit = false; } - g.setFontAlign(-1, 0, 0).setFontVector(26); - g.setColor(0x30cd).fillRect(88, 49, 238, 79); - g.setColor(0xffff).drawString(dmins+":"+dsecs, 92, 66); - g.setColor(0).fillRect(88, 81, 238, 111); - g.setColor(0xffff).drawString(dspeed+" "+this.speedUnit, 92, 98); - g.setColor(0x30cd).fillRect(88, 113, 238, 143); - g.setColor(0xffff).drawString(avespeed + " " + this.speedUnit, 92, 130); - g.setColor(0).fillRect(88, 145, 238, 175); - g.setColor(0xffff).drawString(maxspeed + " " + this.speedUnit, 92, 162); - g.setColor(0x30cd).fillRect(88, 177, 238, 207); - g.setColor(0xffff).drawString(ddist + " " + this.distUnit, 92, 194); - g.setColor(0).fillRect(88, 209, 238, 238); - g.setColor(0xffff).drawString(tdist + " " + this.distUnit, 92, 226); + g.setFontAlign(-1, 0, 0).setFontVector(fontSizeValue); + g.setColor(0x30cd).fillRect(yCol1+1, 49+rowHeight*0, 238, 47+1*rowHeight); + g.setColor(0xffff).drawString(dmins+":"+dsecs, yCol1+5, 50+rowHeight/2+0*rowHeight); + g.setColor(0).fillRect(yCol1+1, 49+rowHeight*1, 238, 47+2*rowHeight); + g.setColor(0xffff).drawString(dspeed+" "+this.speedUnit, yCol1+5, 50+rowHeight/2+1*rowHeight); + g.setColor(0x30cd).fillRect(yCol1+1, 49+rowHeight*2, 238, 47+3*rowHeight); + g.setColor(0xffff).drawString(avespeed + " " + this.speedUnit, yCol1+5, 50+rowHeight/2+2*rowHeight); + g.setColor(0).fillRect(yCol1+1, 49+rowHeight*3, 238, 47+4*rowHeight); + g.setColor(0xffff).drawString(maxspeed + " " + this.speedUnit, yCol1+5, 50+rowHeight/2+3*rowHeight); + g.setColor(0x30cd).fillRect(yCol1+1, 49+rowHeight*4, 238, 47+5*rowHeight); + g.setColor(0xffff).drawString(ddist + " " + this.distUnit, yCol1+5, 50+rowHeight/2+4*rowHeight); + g.setColor(0).fillRect(yCol1+1, 49+rowHeight*5, 238, 47+6*rowHeight); + g.setColor(0xffff).drawString(tdist + " " + this.distUnit, yCol1+5, 50+rowHeight/2+5*rowHeight); } updateScreenCadence() { @@ -125,21 +132,21 @@ class CSCSensor { for (var i=0; i<2; ++i) { if ((i&1)==0) g.setColor(0, 0, 0); else g.setColor(0x30cd); - g.fillRect(0, 48+i*32, 86, 48+(i+1)*32); + g.fillRect(0, yStart+i*rowHeight, yCol1-1, yStart+(i+1)*rowHeight); if ((i&1)==1) g.setColor(0); else g.setColor(0x30cd); - g.fillRect(87, 48+i*32, 239, 48+(i+1)*32); - g.setColor(0.5, 0.5, 0.5).drawRect(87, 48+i*32, 239, 48+(i+1)*32).drawLine(0, 239, 239, 239);//.drawRect(0, 48, 87, 239); - g.moveTo(0, 80).lineTo(30, 80).lineTo(30, 48).lineTo(87, 48).lineTo(87, 239).lineTo(0, 239).lineTo(0, 80); + g.fillRect(yCol1, yStart+i*rowHeight, H-1, yStart+(i+1)*rowHeight); + g.setColor(0.5, 0.5, 0.5).drawRect(yCol1, yStart+i*rowHeight, H-1, yStart+(i+1)*rowHeight).drawLine(0, H-1, W-1, H-1); + g.moveTo(0, yStart+0.13333*H).lineTo(30*W/240, yStart+0.13333*H).lineTo(30*W/240, yStart).lineTo(yCol1, yStart).lineTo(yCol1, H-1).lineTo(0, H-1).lineTo(0, yStart+0.13333*H); } - g.setFontAlign(1, 0, 0).setFontVector(19).setColor(1, 1, 0); - g.drawString("Cadence:", 87, 98); + g.setFontAlign(1, 0, 0).setFontVector(fontSizeLabel).setColor(1, 1, 0); + g.drawString("Cadence:", yCol1, yStart+rowHeight/2+1*rowHeight); this.drawBatteryIcon(); this.screenInit = false; } - g.setFontAlign(-1, 0, 0).setFontVector(26); - g.setColor(0).fillRect(88, 81, 238, 111); - g.setColor(0xffff).drawString(Math.round(this.cadence), 92, 98); + g.setFontAlign(-1, 0, 0).setFontVector(fontSizeValue); + g.setColor(0).fillRect(yCol1+1, 49+rowHeight*1, 238, 47+2*rowHeight); + g.setColor(0xffff).drawString(Math.round(this.cadence), yCol1+5, 50+rowHeight/2+1*rowHeight); } updateScreen() { @@ -163,45 +170,45 @@ class CSCSensor { } this.lastCrankRevs = crankRevs; this.lastCrankTime = crankTime; - } - // wheel revolution - var wheelRevs = event.target.value.getUint32(1, true); - var dRevs = (this.lastRevs>0 ? wheelRevs-this.lastRevs : 0); - if (dRevs>0) { - qChanged = true; - this.totaldist += dRevs*this.wheelCirc/63360.0; - if ((this.totaldist-this.settings.totaldist)>0.1) { - this.settings.totaldist = this.totaldist; - storage.writeJSON(SETTINGS_FILE, this.settings); + } else { + // wheel revolution + var wheelRevs = event.target.value.getUint32(1, true); + var dRevs = (this.lastRevs>0 ? wheelRevs-this.lastRevs : 0); + if (dRevs>0) { + qChanged = true; + this.totaldist += dRevs*this.wheelCirc/63360.0; + if ((this.totaldist-this.settings.totaldist)>0.1) { + this.settings.totaldist = this.totaldist; + storage.writeJSON(SETTINGS_FILE, this.settings); + } } - } - this.lastRevs = wheelRevs; - if (this.lastRevsStart<0) this.lastRevsStart = wheelRevs; - var wheelTime = event.target.value.getUint16(5, true); - var dT = (wheelTime-this.lastTime)/1024; - var dBT = (Date.now()-this.lastBangleTime)/1000; - this.lastBangleTime = Date.now(); - if (dT<0) dT+=64; - if (Math.abs(dT-dBT)>3) dT = dBT; - this.lastTime = wheelTime; - this.speed = this.lastSpeed; - if (dRevs>0 && dT>0) { - this.speed = (dRevs*this.wheelCirc/63360.0)*3600/dT; - this.speedFailed = 0; - this.movingTime += dT; - } - else { - this.speedFailed++; - qChanged = false; - if (this.speedFailed>3) { - this.speed = 0; - qChanged = (this.lastSpeed>0); + this.lastRevs = wheelRevs; + if (this.lastRevsStart<0) this.lastRevsStart = wheelRevs; + var wheelTime = event.target.value.getUint16(5, true); + var dT = (wheelTime-this.lastTime)/1024; + var dBT = (Date.now()-this.lastBangleTime)/1000; + this.lastBangleTime = Date.now(); + if (dT<0) dT+=64; + if (Math.abs(dT-dBT)>3) dT = dBT; + this.lastTime = wheelTime; + this.speed = this.lastSpeed; + if (dRevs>0 && dT>0) { + this.speed = (dRevs*this.wheelCirc/63360.0)*3600/dT; + this.speedFailed = 0; + this.movingTime += dT; + } else if (!this.showCadence) { + this.speedFailed++; + qChanged = false; + if (this.speedFailed>3) { + this.speed = 0; + qChanged = (this.lastSpeed>0); + } } + this.lastSpeed = this.speed; + if (this.speed>this.maxSpeed && (this.movingTime>3 || this.speed<20) && this.speed<50) this.maxSpeed = this.speed; } - this.lastSpeed = this.speed; - if (this.speed>this.maxSpeed && (this.movingTime>3 || this.speed<20) && this.speed<50) this.maxSpeed = this.speed; } - if (qChanged && this.qUpdateScreen) this.updateScreen(); + if (qChanged) this.updateScreen(); } } @@ -253,9 +260,9 @@ E.on('kill',()=>{ }); NRF.on('disconnect', connection_setup); // restart if disconnected Bangle.setUI("updown", d=>{ - if (d<0) { mySensor.reset(); g.clearRect(0, 48, W, H); mySensor.updateScreen(); } + if (d<0) { mySensor.reset(); g.clearRect(0, yStart, W, H); mySensor.updateScreen(); } else if (d>0) { if (Date.now()-mySensor.lastBangleTime>10000) connection_setup(); } - else { mySensor.toggleDisplayCadence(); g.clearRect(0, 48, W, H); mySensor.updateScreen(); } + else { mySensor.toggleDisplayCadence(); g.clearRect(0, yStart, W, H); mySensor.updateScreen(); } }); Bangle.loadWidgets(); From 5a546780c276e02698c9882e001155e18fe13933 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Sat, 12 Mar 2022 12:06:30 +0100 Subject: [PATCH 05/26] Update ChangeLog --- apps/speedalt/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/speedalt/ChangeLog b/apps/speedalt/ChangeLog index 0550f9b86..78c14594b 100644 --- a/apps/speedalt/ChangeLog +++ b/apps/speedalt/ChangeLog @@ -9,3 +9,4 @@ 0.09: Add third screen mode with large clock and waypoint selection display to ease visibility in bright daylight. 0.10: Add Kalman filter to smooth the speed and altitude values. Can be disabled in settings. 0.11: Now also runs on Bangle.js 2 with basic functionality +0.12: Full functionality on Bangle.js 2: Bangle.js 1 buttons mapped to touch areas. From defc6206fff1226081c4234c48e94e0d56b54ce9 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Sat, 12 Mar 2022 12:06:58 +0100 Subject: [PATCH 06/26] Update metadata.json --- apps/speedalt/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/speedalt/metadata.json b/apps/speedalt/metadata.json index 617ac4b8e..e03d23c8b 100644 --- a/apps/speedalt/metadata.json +++ b/apps/speedalt/metadata.json @@ -2,7 +2,7 @@ "id": "speedalt", "name": "GPS Adventure Sports", "shortName": "GPS Adv Sport", - "version": "0.11", + "version": "0.12", "description": "GPS speed, altitude and distance to waypoint display. Designed for easy viewing and use during outdoor activities such as para-gliding, hang-gliding, sailing, cycling etc.", "icon": "app.png", "type": "app", From 35cf7630b33b522ef72195df42a63b86c58f350f Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Sat, 12 Mar 2022 12:12:51 +0100 Subject: [PATCH 07/26] Update app.js --- apps/speedalt/app.js | 117 ++++++++++++++++++------------------------- 1 file changed, 50 insertions(+), 67 deletions(-) diff --git a/apps/speedalt/app.js b/apps/speedalt/app.js index f979762f1..79db932db 100644 --- a/apps/speedalt/app.js +++ b/apps/speedalt/app.js @@ -349,7 +349,7 @@ function drawSecondary(n,u) { s = 30; // Font size if (BANGLEJS2) s *= fontFactorB2; buf.setFontVector(s); - buf.drawString(u,xu - (BANGLEJS2*20),screenH_TwoThirds-25); + buf.drawString(u,xu - (BANGLEJS2*xu/5),screenH_TwoThirds-25); } function drawTime() { @@ -391,7 +391,7 @@ function drawWP() { // from waypoints.json - see README.md buf.setFontAlign(-1,1); //left, bottom if (BANGLEJS2) s *= fontFactorB2; buf.setFontVector(s); - buf.drawString(nm.substring(0,6),72,screenH_TwoThirds-(BANGLEJS2 * 20)); + buf.drawString(nm.substring(0,6),72,screenH_TwoThirds-(BANGLEJS2 * 15)); } if ( cfg.modeA == 2 ) { // clock/large mode @@ -421,7 +421,7 @@ function drawSats(sats) { buf.drawString('A',screenW,140-(BANGLEJS2 * 40)); if ( showMax ) { buf.setFontAlign(0,1); //centre, bottom - buf.drawString('MAX',120,164); + buf.drawString('MAX',screenW_Half,screenH_TwoThirds + 4); } } if ( cfg.modeA == 0 ) buf.drawString('D',screenW,140-(BANGLEJS2 * 40)); @@ -536,22 +536,18 @@ function onGPS(fix) { } -function setButtons(){ -if (!BANGLEJS2) { // Buttons for Bangle.js - // Spd+Dist : Select next waypoint - setWatch(function(e) { - var dur = e.time - e.lastTime; - if ( cfg.modeA == 1 ) { - // Spd+Alt mode - Switch between fix and MAX - if ( dur < 2 ) showMax = !showMax; // Short press toggle fix/max display - else { max.spd = 0; max.alt = 0; } // Long press resets max values. - } - else nxtWp(1); // Spd+Dist or Clock mode - Select next waypoint - onGPS(lf); - }, BTN1, { edge:"falling",repeat:true}); - // Power saving on/off - setWatch(function(e){ +function btn1press(longpress) { + if(emulator) console.log("Btn1, long="+longpress); + if ( cfg.modeA == 1 ) { // Spd+Alt mode - Switch between fix and MAX + if ( !longpress ) showMax = !showMax; // Short press toggle fix/max display + else { max.spd = 0; max.alt = 0; } // Long press resets max values. + } + else nxtWp(1); // Spd+Dist or Clock mode - Select next waypoint + onGPS(lf); + } +function btn2press(){ + if(emulator) console.log("Btn2"); pwrSav=!pwrSav; if ( pwrSav ) { LED1.reset(); @@ -564,52 +560,51 @@ if (!BANGLEJS2) { // Buttons for Bangle.js Bangle.setLCDPower(1); LED1.set(); } - }, BTN2, {repeat:true,edge:"falling"}); - - // Toggle between alt or dist - setWatch(function(e){ - cfg.modeA = cfg.modeA+1; - if ( cfg.modeA > 2 ) cfg.modeA = 0; - savSettings(); - onGPS(lf); - }, BTN3, {repeat:true,edge:"falling"}); - - // Touch left screen to toggle display - setWatch(function(e){ - cfg.primSpd = !cfg.primSpd; - savSettings(); - onGPS(lf); // Update display - }, BTN4, {repeat:true,edge:"falling"}); - -} else { // Buttons for Bangle.js 2 - setWatch(function(e){ // Bangle.js BTN3 + } +function btn3press(){ + if(emulator) console.log("Btn3"); cfg.modeA = cfg.modeA+1; if ( cfg.modeA > 2 ) cfg.modeA = 0; if(emulator)console.log("cfg.modeA="+cfg.modeA); savSettings(); onGPS(lf); - }, BTN1, {repeat:true,edge:"falling"}); - -/* Bangle.on('tap', function(data) { // data - {dir, double, x, y, z} + } +function btn4press(){ + if(emulator) console.log("Btn4"); cfg.primSpd = !cfg.primSpd; - if(emulator)console.log("!cfg.primSpd"); - }); */ + savSettings(); + onGPS(lf); // Update display + } -/* Bangle.on('swipe', function(dir) { - if (dir < 0) { // left: Bangle.js BTN3 - cfg.modeA = cfg.modeA+1; - if ( cfg.modeA > 2 ) cfg.modeA = 0; - if(emulator)console.log("cfg.modeA="+cfg.modeA); - } + +function setButtons(){ +if (!BANGLEJS2) { // Buttons for Bangle.js 1 + setWatch(function(e) { + btn1press(( e.time - e.lastTime) > 2); // > 2 sec. is long press + }, BTN1, { edge:"falling",repeat:true}); + + // Power saving on/off (red dot visible if off) + setWatch(btn2press, BTN2, {repeat:true,edge:"falling"}); + + // Toggle between alt or dist + setWatch(btn3press, BTN3, {repeat:true,edge:"falling"}); + + // Touch left screen to toggle display + setWatch(btn4press, BTN4, {repeat:true,edge:"falling"}); + +} else { // Buttons for Bangle.js 2 + setWatch(function(e) { + btn1press(( e.time - e.lastTime) > 0.4); // > 0.4 sec. is long press + }, BTN1, { edge:"falling",repeat:true}); + + Bangle.on('touch', function(btn_l_r, e) { + if(e.x < screenW_Half) btn4press(); else - { // right: Bangle.js BTN4 - cfg.primSpd = !cfg.primSpd; - if(emulator)console.log("!cfg.primSpd"); - } + if (e.y < screenH_Half) + btn2press(); + else + btn3press(); }); -*/ - savSettings(); - onGPS(lf); } } @@ -700,18 +695,6 @@ Bangle.on('lcdPower',function(on) { else stopDraw(); }); -/* -function onGPSraw(nmea) { - var nofGP = 0, nofBD = 0, nofGL = 0; - if (nmea.slice(3,6) == "GSV") { - // console.log(nmea.slice(1,3) + " " + nmea.slice(11,13)); - if (nmea.slice(0,7) == "$GPGSV,") nofGP = Number(nmea.slice(11,13)); - if (nmea.slice(0,7) == "$BDGSV,") nofBD = Number(nmea.slice(11,13)); - if (nmea.slice(0,7) == "$GLGSV,") nofGL = Number(nmea.slice(11,13)); - SATinView = nofGP + nofBD + nofGL; - } } -if(BANGLEJS2) Bangle.on('GPS-raw', onGPSraw); -*/ var gpssetup; try { From a5c024b4b49f6873e4012b2ae0071a9a17dd38da Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Sat, 12 Mar 2022 12:33:07 +0100 Subject: [PATCH 08/26] Update README.md --- apps/speedalt/README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/apps/speedalt/README.md b/apps/speedalt/README.md index c21828aff..6f0d4efe5 100644 --- a/apps/speedalt/README.md +++ b/apps/speedalt/README.md @@ -2,23 +2,21 @@ You can switch between three display modes. One showing speed and altitude (A), one showing speed and distance to waypoint (D) and a large dispay of time and selected waypoint. -*Note for **Bangle.js 2:** Currently only the BTN3 functionality is working with the Bangle.js 2 button.* - Within the [A]ltitude and [D]istance displays modes one figure is displayed on the watch face using the largest possible characters depending on the number of digits. The other is in a smaller characters below that. Both are always visible. You can display the current or maximum observed speed/altitude values. Current time is always displayed. The waypoints list is the same as that used with the [GPS Navigation](https://banglejs.com/apps/#gps%20navigation) app so the same set of waypoints can be used across both apps. Refer to that app for waypoint file information. ## Buttons and Controls -BTN3 : Cycles the modes between Speed+[A]ltitude, Speed+[D]istance and large Time/Waypoint +*(Mapping for **Bangle.js 2**: BTN2 = Touch upper right side; BTN3 = Touch lower right side; BTN4 = Touch left side)* -***Bangle.js 2:** Currently only this button function is working* +BTN3 : Cycles the modes between Speed+[A]ltitude, Speed+[D]istance and large Time/Waypoint ### [A]ltitude mode BTN1 : Short press < 2 secs toggles the displays between showing the current speed/alt values or the maximum speed/alt values recorded. -BTN1 : Long press > 2 secs resets the recorded maximum values. +BTN1 : Long press > 2 secs resets the recorded maximum values. *(Bangle.js 2: Long press > 0.4 secs)* ### [D]istance mode @@ -32,7 +30,7 @@ BTN1 : Select next waypoint. BTN2 : Disables/Restores power saving timeout. Locks the screen on and GPS in SuperE mode to enable reading for longer periods but uses maximum battery drain. Red LED (dot) at top of screen when screen is locked on. Press again to restore power saving timeouts. -BTN3 : Long press exit and return to watch. +BTN3 : Long press exit and return to watch. *(Bangle.js 2: Long press BTN > 2 secs)* BTN4 : Left Display Tap : Swaps which figure is in the large display. You can have either speed or [A]ltitude/[D]istance on the large primary display. From 5d1d155ad8e16a8391647f967d835b9c3a8e5ea7 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Sat, 12 Mar 2022 12:56:39 +0100 Subject: [PATCH 09/26] Update ChangeLog --- apps/vectorclock/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/vectorclock/ChangeLog b/apps/vectorclock/ChangeLog index abbfcbb99..02831edde 100644 --- a/apps/vectorclock/ChangeLog +++ b/apps/vectorclock/ChangeLog @@ -5,3 +5,4 @@ 0.05: "Chime the time" (buzz or beep) with up/down swipe added 0.06: Redraw widgets when time is updated 0.07: Fix problem with "Bangle.CLOCK": github.com/espruino/BangleApps/issues/1437 +0.08: Redraw widgets only once per minute From 6eb7e3f8af506ce137dec33aa13981b2aa5716a1 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Sat, 12 Mar 2022 12:57:17 +0100 Subject: [PATCH 10/26] Update metadata.json --- apps/vectorclock/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/vectorclock/metadata.json b/apps/vectorclock/metadata.json index 0f558e3ee..541766fa2 100644 --- a/apps/vectorclock/metadata.json +++ b/apps/vectorclock/metadata.json @@ -1,7 +1,7 @@ { "id": "vectorclock", "name": "Vector Clock", - "version": "0.07", + "version": "0.08", "description": "A digital clock that uses the built-in vector font.", "icon": "app.png", "type": "clock", From 16863635ec703b2f0856c424a678ac7e857035aa Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Sat, 12 Mar 2022 12:58:37 +0100 Subject: [PATCH 11/26] Update app.js --- apps/vectorclock/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/vectorclock/app.js b/apps/vectorclock/app.js index 8d2961c4a..18b4378b2 100644 --- a/apps/vectorclock/app.js +++ b/apps/vectorclock/app.js @@ -81,7 +81,7 @@ function draw() { executeCommands(); - Bangle.drawWidgets(); + if (!showSeconds) Bangle.drawWidgets(); } var timeout; From fc37036bff63a81104675e4338f96d7009812140 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Sat, 12 Mar 2022 13:14:23 +0100 Subject: [PATCH 12/26] Update app.js --- apps/vectorclock/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/vectorclock/app.js b/apps/vectorclock/app.js index 18b4378b2..663a4c84f 100644 --- a/apps/vectorclock/app.js +++ b/apps/vectorclock/app.js @@ -81,7 +81,7 @@ function draw() { executeCommands(); - if (!showSeconds) Bangle.drawWidgets(); + if (process.env.HWVERSION==2) Bangle.drawWidgets(); } var timeout; From 1349e75cb39688dee480f80016c3d73446184e8a Mon Sep 17 00:00:00 2001 From: Rarder44 Date: Sat, 12 Mar 2022 18:44:34 +0100 Subject: [PATCH 13/26] added charging icon --- apps/rebble/ChangeLog | 1 + apps/rebble/metadata.json | 2 +- apps/rebble/rebble.app.js | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/apps/rebble/ChangeLog b/apps/rebble/ChangeLog index b9c26b4e3..b80dfef94 100644 --- a/apps/rebble/ChangeLog +++ b/apps/rebble/ChangeLog @@ -2,3 +2,4 @@ 0.02: Fix typo to Purple 0.03: Added dependancy on Pedometer Widget 0.04: Fixed icon and png to 48x48 pixels +0.05: added charging icon \ No newline at end of file diff --git a/apps/rebble/metadata.json b/apps/rebble/metadata.json index 212a7b5b3..b26fb6a27 100644 --- a/apps/rebble/metadata.json +++ b/apps/rebble/metadata.json @@ -2,7 +2,7 @@ "id": "rebble", "name": "Rebble Clock", "shortName": "Rebble", - "version": "0.04", + "version": "0.05", "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/rebble.app.js b/apps/rebble/rebble.app.js index d186ea8ec..7c7d57939 100644 --- a/apps/rebble/rebble.app.js +++ b/apps/rebble/rebble.app.js @@ -204,6 +204,14 @@ function drawBattery(x,y,wi,hi) { g.setColor(g.theme.fg); g.fillRect(x+wi-3,y+2+(((hi - 1)/2)-1),x+wi-2,y+2+(((hi - 1)/2)-1)+4); // contact g.fillRect(x+3, y+5, x +4 + E.getBattery()*(wi-12)/100, y+hi-1); // the level + + if( Bangle.isCharging() ) + { + g.setBgColor(settings.bg); + image = ()=> { return require("heatshrink").decompress(atob("j8OwMB/4AD94DC44DCwP//n/gH//EOgE/+AdBh/gAYMH4EAvkDAYP/+/AFAX+FgfzGAnAA=="));} + g.drawImage(image(),x+3,y+4); + } + } function getSteps() { @@ -270,3 +278,14 @@ for (let wd of WIDGETS) {wd.draw=()=>{};wd.area="";} loadSettings(); loadLocation(); draw(); // queues the next draw for a minutes time +Bangle.on('charging', function(charging) { + //redraw the sidebar ( with the battery ) + switch(sideBar) { + case 0: + drawSideBar1(); + break; + case 1: + drawSideBar2(); + break; + } +}); \ No newline at end of file From a438fe0a65962f688a3c1af104a2eff8e098c86b Mon Sep 17 00:00:00 2001 From: Francois Lancelot <16709438+francoislanc@users.noreply.github.com> Date: Sun, 13 Mar 2022 16:52:39 +0100 Subject: [PATCH 14/26] Create Todo List app --- apps/todolist/ChangeLog | 1 + apps/todolist/README.md | 40 +++++++++++ apps/todolist/app-icon.js | 1 + apps/todolist/app.js | 129 ++++++++++++++++++++++++++++++++++ apps/todolist/app.png | Bin 0 -> 1833 bytes apps/todolist/metadata.json | 23 ++++++ apps/todolist/screenshot1.png | Bin 0 -> 1671 bytes apps/todolist/screenshot2.png | Bin 0 -> 2510 bytes apps/todolist/screenshot3.png | Bin 0 -> 2286 bytes 9 files changed, 194 insertions(+) create mode 100644 apps/todolist/ChangeLog create mode 100644 apps/todolist/README.md create mode 100644 apps/todolist/app-icon.js create mode 100644 apps/todolist/app.js create mode 100644 apps/todolist/app.png create mode 100644 apps/todolist/metadata.json create mode 100644 apps/todolist/screenshot1.png create mode 100644 apps/todolist/screenshot2.png create mode 100644 apps/todolist/screenshot3.png diff --git a/apps/todolist/ChangeLog b/apps/todolist/ChangeLog new file mode 100644 index 000000000..2e979ec12 --- /dev/null +++ b/apps/todolist/ChangeLog @@ -0,0 +1 @@ +0.01: Initial release \ No newline at end of file diff --git a/apps/todolist/README.md b/apps/todolist/README.md new file mode 100644 index 000000000..27c7cfb63 --- /dev/null +++ b/apps/todolist/README.md @@ -0,0 +1,40 @@ +Todo List +======== + +This is a simple Todo List application. + +![](screenshot2.png) + +The content is loaded from a JSON file. +You can mark a task as completed. + +JSON file content example: +```javascript +[ + { + name: "Pro", + children: [ + { + name: "Read doc", + done: true, + children: [], + } + ], + }, + { + name: "Pers", + children: [ + { + name: "Grocery", + children: [ + { name: "Milk", done: false, children: [] }, + { name: "Eggs", done: false, children: [] }, + { name: "Cheese", done: false, children: [] }, + ], + }, + { name: "Workout", done: false, children: [] }, + { name: "Learn Rust", done: false, children: [] }, + ], + }, +] +``` \ No newline at end of file diff --git a/apps/todolist/app-icon.js b/apps/todolist/app-icon.js new file mode 100644 index 000000000..9d9019c70 --- /dev/null +++ b/apps/todolist/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("AEURiMQCycBC6gVDDKAPBAAYXDA4gWMiUhAgUiDBYmBiUiCAMjmQQBiczBQkRFw0T/4ABC4MzkUSmYXBl4KB+QXHBYQXDAAYLFJAsRn4LDIYIXIkIXGBQQLBRYojEmIXKmIWFiQLEC5X/IwkzFwYXNABQX/C6kxXIYXR+cRj4XTkUyaIPzbYcSVIQXJFoLRC+LZEGwQvKFQIPBDgQACF5gTBkLpEX/6/Z/6/VmfyX4UiAAa/kC4UT/4yBAAZmCX5bPDX/4MEmRIJX8sv+czAAa/PAoK/rmQPDI4h3OB4bX/aJIAFkIXGOQQALTgIXGiQwNmMRCwkAgK3EABQuFGAQAOCwwAU") \ No newline at end of file diff --git a/apps/todolist/app.js b/apps/todolist/app.js new file mode 100644 index 000000000..58cd3783c --- /dev/null +++ b/apps/todolist/app.js @@ -0,0 +1,129 @@ +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +// Const +let TODOLIST_FILE = "todolist.json"; +let MAX_DESCRIPTION_LEN = 14; + +// Clear todolist file +// require("Storage").erase(TODOLIST_FILE); + +let DEFAULT_TODOLIST = [ + { + name: "Pro", + children: [ + { + name: "Read doc", + done: true, + children: [], + }, + ], + }, + { + name: "Pers", + children: [ + { + name: "Grocery", + children: [ + { name: "Milk", done: false, children: [] }, + { name: "Eggs", done: false, children: [] }, + { name: "Cheese", done: false, children: [] }, + ], + }, + { name: "Workout", done: false, children: [] }, + { name: "Learn Rust", done: false, children: [] }, + ], + }, +]; + +// Load todolist +let todolist = + require("Storage").readJSON(TODOLIST_FILE, true) || DEFAULT_TODOLIST; +let menus = {}; + +function writeData() { + require("Storage").writeJSON(TODOLIST_FILE, todolist); +} + +function getChild(todolist, indexes) { + let childData = todolist; + for (let i = 0; i < indexes.length; i++) { + childData = childData[indexes[i]]; + childData = childData.children; + } + + return childData; +} + +function getName(item) { + let title = item.name.substr(0, MAX_DESCRIPTION_LEN); + return title; +} +function getParentTitle(todolist, indexes) { + let parentIndexes = indexes.slice(0, indexes.length - 1); + let lastIndex = indexes[indexes.length - 1]; + let item = getItem(todolist, parentIndexes, lastIndex); + return getName(item); +} + +function getItem(todolist, parentIndexes, index) { + let childData = getChild(todolist, parentIndexes, index); + return childData[index]; +} + +function toggleableStatus(todolist, indexes, index) { + const reminder = getItem(todolist, indexes, index); + return { + value: !!reminder.done, // !! converts undefined to false + format: (val) => (val ? "[X]" : "[-]"), + onchange: (val) => { + reminder.done = val; + writeData(); + }, + }; +} + +function showSubMenu(key) { + const sub_menu = menus[key]; + return E.showMenu(sub_menu); +} + +function createListItem(todolist, indexes, index) { + let reminder = getItem(todolist, indexes, index); + if (reminder.children.length > 0) { + let childIndexes = []; + for (let i = 0; i < indexes.length; i++) { + childIndexes.push(indexes[i]); + } + childIndexes.push(index); + createMenus(todolist, childIndexes); + return () => showSubMenu(childIndexes); + } else { + return toggleableStatus(todolist, indexes, index); + } +} + +function showMainMenu() { + const mainmenu = menus[""]; + return E.showMenu(mainmenu); +} + +function createMenus(todolist, indexes) { + const menuItem = {}; + if (indexes.length == 0) { + menuItem[""] = { title: "todolist" }; + } else { + menuItem[""] = { title: getParentTitle(todolist, indexes) }; + menuItem["< Back"] = () => + showSubMenu(indexes.slice(0, indexes.length - 1)); + } + for (let i = 0; i < getChild(todolist, indexes).length; i++) { + const item = getItem(todolist, indexes, i); + const name = getName(item); + menuItem[name] = createListItem(todolist, indexes, i); + } + menus[indexes] = menuItem; +} + +createMenus(todolist, []); +showMainMenu(); diff --git a/apps/todolist/app.png b/apps/todolist/app.png new file mode 100644 index 0000000000000000000000000000000000000000..a93fc14ad2bcf0a5d8f9686ba0203e985089c20e GIT binary patch literal 1833 zcmV+^2iEwBP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H12DV8= zK~!jg?V4*)l-C``e`oKk5)oMiq+ApeEg~(*O{ljf6LWEfQ6{Y^p{D7Sc818LmvjQn z*p5l3Hj`*=E_PxxF_Oemjb=>JO2!)PAlQ+{L~1}}xk;p4gar|I***P0K*44A<=vO~ zCC{gK&-?uU=Xv&A_nZ|>9Yknsdb)r)ZlV9A$6nDiC6!D?(pgcNbA?{M2PA)4d-t8V{bLuBOw+0;$}uf#A7mvn&Q(frQmSBnb0ZhBN_D-eNsEd2hG9 z>S$O@Mk(;H7m5=^tCvUzLevS5EbC~lI)IOE=hJ{KHgk=X@-1MdFCM`Bh4G}X$^ziS zvLjsS?80gda?Y7!b2K)#gh?q$&Prq9l0~?jE)JLe4dJ(smV$iZT<0C3{NW3;zjCN(vQrAw2>RkWEd^ zEsiHNpp)W7z#JMH!nSRjiI0!-$~%1cC=N&en6d>4cd_Yrzv9fls_5_OBWhkW$yrM= zna#JvCoWk;Uf#M}%B7T)mcGj?uj~a$s;w`$pacG_$UtaxY66e~P*n8TgyMa{7H(rr z?t_z#8-Wmlyu5W(SD&M*sv0RoK3)vyyanrZ`o#b`osP`R6rUBD%|-zFdL4?z4LMz0 z8yFalAJ-+vBRf0w%O|-QFJsng3rI;YfW=~F+BB=r3KA0+VYjzXQGSw&@{@kWk4Msy zMLyq$g^kY477`MS`fW|bN#>I~@hI-YpqCv5nB4tw7`KyB?sN=i0iG>lERVtEEDmS?CErW66K#NiRM zdGg7hX{ALKzFr4L(9qCKVc~BmSFxoI1e$E-Tth=_{_XQLTpT`pyXT(oXpvSCR2w+{ z@hOZ3Bg>Yh@cN#=j*8!~A!n4+*w{)%#lP`*d>_W?^*XY$(uj_ZoU{&A23lG!QBu4W zfO&DzG__m;;Qsqok(IS{l=sXt+c|%}UQy2DA6N31oqw3L7F7mpwlI>u^-a!x@?RS4 z&A{+azfDCy9>ZI?av2UsKhn=>s7@zXxkBA^tIB}IV&>(Seotj(HG6jN=R&=ml9I;> z4xToKmzTHB>ye3;2xt&zWF(W3k&N5zL9f3(GqNVN-Y)T=;X2UW-NTL@yE#`=t5r%x z(8Pe0k}X^Q#Qy#7vGe7k?@Gw969n4r%(R}fbZUY<6fix>Q!n# zzvy=z(CGvV7smTNMDqq!2HOAE$q)03@JJ7Pi1c(_e*&WMQFYNV)Z zff+M`dHb!GC_C^z@4S78-rhb63m+vSa?TiDaq;666+Nb?3#sWo5WpA+vRcT0WIYe% zKEUPnPGV!d-ZH5crW66sLY5%QgyO#ncr_q|bOX5EZlu4B%oM}pc8@$tYHXhI@4dHx zq#fY;bti3Y?NcUB3F;e0FZes*_$}u%UJbZJPzB%w*thTCl!^0)-rhbAA38exLGVv+ z9IrR^gFTIdK{KOl0@Ca18tCf0!uMqdeG1ClzPSGf X`~f40OX#!|00000NkvXXu0mjf51oTh literal 0 HcmV?d00001 diff --git a/apps/todolist/metadata.json b/apps/todolist/metadata.json new file mode 100644 index 000000000..0833a86bd --- /dev/null +++ b/apps/todolist/metadata.json @@ -0,0 +1,23 @@ +{ + "id": "todolist", + "name": "TodoList", + "shortName": "TodoList", + "version": "0.01", + "type": "app", + "description": "Simple Todo List", + "icon": "app.png", + "allow_emulator": true, + "tags": "tool,todo", + "supports": ["BANGLEJS", "BANGLEJS2"], + "readme": "README.md", + "storage": [ + { "name": "todolist.app.js", "url": "app.js" }, + { "name": "todolist.img", "url": "app-icon.js", "evaluate": true } + ], + "data": [{ "name": "todolist.json" }], + "screenshots": [ + { "url": "screenshot1.png" }, + { "url": "screenshot2.png" }, + { "url": "screenshot3.png" } + ] +} diff --git a/apps/todolist/screenshot1.png b/apps/todolist/screenshot1.png new file mode 100644 index 0000000000000000000000000000000000000000..523d60307e3e9805676205a6a9d34688ce7a3e4b GIT binary patch literal 1671 zcmeAS@N?(olHy`uVBq!ia0vp^8$g(Y4M?uv{v-}aF%}28J29*~C-ahlfz8p=#WAEJ z?(N*SMYA0QSQdY;&seJC9y)`ex;p7P&*h(z2k&0EY$yNg)8n5tcK<){Gc96~#{EUmvyJD=WHdUd`y%e;(d!G?Y3{+GOY`gD%v zHI`-5f(0s=J}*yF_`vdIE|A@ny7Yi>VVVC=ljk!dR~?%qUa@z5OmozGvE{c9XXlj%$?6`yvF1SF%*{b*$6OzLp6m9Y-be69 z%}y&fmjuSf>A&wxls+|a>OSXneU<_dE)SF?HSecSuQcH4}bjPH_tTfAHP<;`|_71x7Y9@Ka)JC z&8Dp<>auzNIw&|Rh*(4w_J>{c`0(Q6nbv|e>WyD6XPnk`-oo0!(ku6UP0Q+Y0vzEF zz9vY%T$H@{xUu-5jq_LpZfyR3JI0jh{xYxg+>Qz7@8uU?<*1phWvjm=x+HV2_Y_6zlP`0uTNkFur2(+=xZshf%0NN*e>y`GCiBP763ZI340R zL6WK8-iFuUaBs1m6GNkZ5R2h6jvDSiKYm5)v;Uv>M|Otgo;jhu50)Q@UbOG2+oM-{ z67@|EIv>7k3*L8D{>YN#w^F6yz|<1S-E$7?IZ*xk*;B2(aXS|m-{_t$Ubmg|8Oy!f zL2o#JtCnuz{rTnNZqvhGc?3IH?IsmvcRl_1TJ&oMzbvOsiKWaFH--NuQ7X6Q9k|Gw zV6raSIOe@TV+Cs*zi{U^)dCg$^Cdh}k2?Mro*{0r$a2&ByT2dakgk5hu6XL`7tETFVdQ&MBb@0G(G0>Hq)$ literal 0 HcmV?d00001 diff --git a/apps/todolist/screenshot2.png b/apps/todolist/screenshot2.png new file mode 100644 index 0000000000000000000000000000000000000000..0337f9000378268ccf6e771ce0c46a7c5b1875f4 GIT binary patch literal 2510 zcmeHJS5%V=5)QwC1QbXVrC%U`s31taQY3&C3amhaVCX0vqM}HZ7A`F)Vhe-- zDU=9A_acY^L?H-Las@+|q7)-#vk&{WPy4)c&dhgaUcPhYoNvCl?}V}y7n2hMfk5K+ zb{AX(*zoU!iU=yDdB#@&LeVa^R-pQRg?SK2G{gRa<>ffv<;uSkrcWIbZeH1c-|p8o za-{^YeQl9jIGXDHj|a8^*^1piw|4~bPb74_hy?+rXi+u0)*!qR%-p=qB%)yboEL0c zE#lJ9`7pK3A{l%-%kSBXeQdDWW}yuJz%4{WRg0|+)a*n==tL6n$;Gu{qq?r|5HUa! zI$oCV{o1?+P2C=j>-a%w6b3YOzUWmK>xYDklljTw6TB6{DE#rs!TvQWYXNZDFzx(7 z8B_%z1lX*L=3oe*8Q=O*H|31V>O+=TeBgxl<}2%pYQAYM>o%}LbQ@+@>FkDH$FrbG zp@nc6Jbar2E&yr|*1JhZYN;#`bPq^ElL#$$H$0TEPo@#t$fJk|qO7+J+`|9y)dvnl z5HMTXm=4ExyTi9p70#A+>b7aJXS=gF7%=QpopMc~Y8uPfmu4gYjIc_jf)KcWt(qPmJiXAdBsUvEypAlf zaOGyhNaW0cPfrvB*gb{jyu;7MDvB-X?rXA4T0pjJ{D*EIpcDKX+!E*dCNY#ZDM>D3 zPA1CpTgkoQ+Aay7?YZ|@kJE{Ck@}5~3(Q!jA_!~Fd|3+!$T_loY}?@xb~3%^Wtly_ zy~%OfZZt{*uY;!?OW+*Z`4p)hbPyF|Gbviq$T{+-$${p{($C&Up=Zp}Hbji_So z6oUyA{5wzj<~~Q*oyT_44nXKU^c5v^Y{5RINL$$(n-u1THAD0t*C85q%~vJx!&;qU z$9KPJH0&0(lmfM$?m2X&-&OmMuNGld^lqMRku+n@P==>I5^dg%n}*T97PgEOL-TY6B&qF2!(!pAl-&E3AiD&hD5dcznFK&l-@#~aE z=K*R4a>7?_)scIC(uKpB(ve{EV1HV2DJ%z-@p;K}6OVeJjcvzqOe~ika1avvlBm&ZVS-_{4)|=X(eB-w@W%WFXR5&^m?2+$meG+hPQmaqO~s zN$N4HD;68ypeH;r;}C6~bXZm&0_`mYp5ZTo=sI%juG-ge;JJ|A8+ z7aq8DVlG#=`fEh5dKuM~Ip=Mi>UV2MBNvkj_0cf}{7e<}DDThN$c>2zBwI#`Pf?|Q zFOZF!X>V`GHQ91|w%c9Nyvi=k%sq!>lD>!R0Ars>x5aYjoNH1fl@4QT*fg?e9qObQ3X=r(jdltOkush(T)eEU;?<>8Y_$y4UzNiXCu&KFF|E%D za!3M>p(@nethRjXbPWP?+w!0WEq++ZK)mr1^f&sgH7zzAKw|0etqy4d;Z$9bEoz%!PUHRETVo_!8nmZ5; zJ$NS)(cbFWnFIZaTXEFyI={->kx(BPI?XMK0b+KSSMD!^b5pWEdxvhCM}6Bs2JDjV z7m-yiBYG-f)C z6{C!i;*4uao1<|vX^NhkCwQpHF0Jy#82s?Hl&>$`UpcRNg_Rnv9sN16xB4M@`xE>_O*7w7a`wZQ$szbK~x2so_Lu;}5b-#k09d>L2&6*P4VTgD2x<|H9? z&JcUUgYLGrWF9zH+gOV4mZ*8aA}#hvn5f00F%8)D<_Py$P`&S)_d0yDHF-<|}Zbx?To@iZ3atBSGU w1vskmg(J{^o0-}(fz2T<{GaT9SR)td07g`e?B&e~9yE}>HR?jWmH(}O0Ylf7a{vGU literal 0 HcmV?d00001 diff --git a/apps/todolist/screenshot3.png b/apps/todolist/screenshot3.png new file mode 100644 index 0000000000000000000000000000000000000000..e5a4a85acd3d4298f930359725df1de07f21175a GIT binary patch literal 2286 zcmeHJ`BT$*68+@Ma2O696jm{Eh&qHIDu>(<7$phO2mv7k0&zSz0)leHEQBEn!w6!; zXjnkdaI@wDIcC8?R2CUAtbl||E-#22i6DoA$}&H1ZPoq(`$PAu_o}<9tLs%)U-czm zbm2yD0DvwIdxW@w;y*)6VW;D0syUQ+!4=!OJQ@xlg(w8I!CLN z>n|jCi)-_rz-~qc=*zzp{g`n^xp#Nt@={vc_|L0Zkf*^VSiJ8PcC8F;nI0|*>I<~C zVMLu!Q|ZO&(v(WZe#-s2Z2*76XO0$Ja-R&k-%VZYw}QnhqTP1V z)<@)Tl;JQJsPN@fgmPg#Is8Cl(oZo@am+_li!Yu8k1T>8k?X9l_z?-6iu zM(5<4x|2XvC!exFq$jNY7GnS&@|T?8niB|j>kxHtfX2N380MJ8?h1rSyU2IT;z9TS z-eLyvKbs~hQ>ZO}r>AP-Ia77kKUk+~i4C*;?liI=7>(O^54k#x1+lE9hNk7Dn$fay zmkw1Y$34{`5{k+6%+4Qn^JzYpeYHfdV@#C;RRaa$MFuw$-8d%NF+w#x5P6VZ)s_RO{XPB}@j>UcOWioWnFt!9zm z6J{IFu(`u@m>()c@B0N3+KS)b{@h|!7(4>;>~=mCU$GLvLt8b35&iP@u5$Ke(%mg| zSJ&F?;}6@QCZ!kl!H3{<0e#J<{9YSY1lyDmrB$*eQ#PxF|I&bA+!=ux+uTB^}ahm7H*ZGf6X zZYNX$a3W&Urr`fVrJ575MYzQwmh<^fpGPIcxxj(MXE$CT)yX5}g-^c-vi#5Pwyz3L zZ@Tw=yEzFnUJ54s5gBf)(^vM+T<`$%o}nej$)*BnR#J9*5u8-gIKKA9Rte`GUsli>F0!Pc|B|C&m&`B*Jeyyh_jy9>oJo|`$CtWXI4}i*HOu&7?v5l6*oUQSOZ={g z8E1niFn^(!h?8i{<7RcmjnX8mf1Rx97#G`$lQ8D_4YUArSd7HTR!#IsW_PkubFl7P zL5G39A4)aouAqdmV$1sJ?03ftDv!6s z&6e&db}dEcTk{>8ue8`%Dx$Pc88 zdTxis5vhMouSiN@C|-0#zd653bKb>uf zm{m9GdzT5vj)i0e!d}hPHz1}*DUi6o@XklK^op~uh2FA!I90~YN<0UPCzuLO;_f&u zMT~oM^j+Zbaf>Zh0ST9bGtIsksqZ21%LpE7cy)&M?p(~8llsH2&_qI7e7zqG2)|o2 zY@gPg^xhCJ7O}b-qLqXTIYT3M^skMjFLB!SKr$#mfSQsej)FIZQCbY$8y&KwxXI}q$bep4wDpKIwTzmg$ zgYc^1p-h`4xJqzF5_p7Az2WIdI8tG-3R6u>&ZXq{ri3s3xV0ddHP+H&Wl#HK72-2d zrXa+Mw3@ zOTwDhn+EMXX3i+`NfHR~2R;P7?cq$f-$0O&@hIuLLSpk8NB_a>ka4cWMicwV553Uo z{7kh^7?ve3&iBP%Z5YNl5G7kHPf}6rk}a6E1~@)7gvFgIOySAv>b{H|2ycqDJBDUe zZ`gXdx;t+L0|OcvFW?|Pat&*oe#*2S0*GPvo0`<^S^@yF8rg4Q+cmsUK+2mlXMkT= g|1bT|4XkfIp&ff88rdGY@xTDwQNj_S7xnVL0pPJ6_5c6? literal 0 HcmV?d00001 From ab9013956cddc314fa2b4c68890c574bb42d0ebd Mon Sep 17 00:00:00 2001 From: Francois Lancelot <16709438+francoislanc@users.noreply.github.com> Date: Sun, 13 Mar 2022 17:09:02 +0100 Subject: [PATCH 15/26] Update todolist app icon --- apps/todolist/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/todolist/app-icon.js b/apps/todolist/app-icon.js index 9d9019c70..229852134 100644 --- a/apps/todolist/app-icon.js +++ b/apps/todolist/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("AEURiMQCycBC6gVDDKAPBAAYXDA4gWMiUhAgUiDBYmBiUiCAMjmQQBiczBQkRFw0T/4ABC4MzkUSmYXBl4KB+QXHBYQXDAAYLFJAsRn4LDIYIXIkIXGBQQLBRYojEmIXKmIWFiQLEC5X/IwkzFwYXNABQX/C6kxXIYXR+cRj4XTkUyaIPzbYcSVIQXJFoLRC+LZEGwQvKFQIPBDgQACF5gTBkLpEX/6/Z/6/VmfyX4UiAAa/kC4UT/4yBAAZmCX5bPDX/4MEmRIJX8sv+czAAa/PAoK/rmQPDI4h3OB4bX/aJIAFkIXGOQQALTgIXGiQwNmMRCwkAgK3EABQuFGAQAOCwwAU") \ No newline at end of file +require("heatshrink").decompress(atob("mEwwgmjiMRiAWTgIXUCoYZQB4IADC4YHECxkSkIECkQYLEwMSkQQBkcyCAMTmYKEiIuGif/AAIXBmciiUzC4MvBQPyC44LCC4YADBYpIFiM/BYZDBC5EhC4wKCBYKLFEYkxC5UxCwsSBYgXK/5GEmYuDC5oAKC/4XUmK5DC6PziMfC6cimTRB+bbDiSpCC5ItBaIXxbIg2CF5QqBB4IcCAAQvMCYMhdIi//X7P/X6sz+S/CkQADX8gXCif/GQIADMwS/LZ4a//BgkyJBK/ll/zmYADX54FBX9cyB4ZHEO5wPDa/7RJAAshC4xyCABacBC40SGBsxiIWEgEBW4gAKFwowCABwWGACgA==")) \ No newline at end of file From 9f8ec28c20390c9de726d2ae25b9ec85d37061fe Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Sun, 13 Mar 2022 20:30:10 +0100 Subject: [PATCH 16/26] Update README.md --- apps/info/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/info/README.md b/apps/info/README.md index 007a9794e..32920cb75 100644 --- a/apps/info/README.md +++ b/apps/info/README.md @@ -7,7 +7,7 @@ screen. Very useful if combined with pattern launcher ;) ![](screenshot_1.png) ![](screenshot_2.png) -![](screenshot_2.png) +![](screenshot_3.png) ## Contributors From 45cbb6a006d70c0bfdfb3ff4bb3b6aac2fae429a Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Sun, 13 Mar 2022 22:20:32 +0100 Subject: [PATCH 17/26] boot: fix alphabetic sorting of *.boot.js files No version bump: assuming that where it really matters we already set a priority, which worked fine. --- apps/boot/bootupdate.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/boot/bootupdate.js b/apps/boot/bootupdate.js index 63424bfbf..7a69bbaeb 100644 --- a/apps/boot/bootupdate.js +++ b/apps/boot/bootupdate.js @@ -196,7 +196,7 @@ if (!Bangle.appRect) { // added in 2v11 - polyfill for older firmwares // Append *.boot.js files // These could change bleServices/bleServiceOptions if needed var getPriority = /.*\.(\d+)\.boot\.js$/; -require('Storage').list(/\.boot\.js/).sort((a,b)=>{ +require('Storage').list(/\.boot\.js$/).sort((a,b)=>{ var aPriority = a.match(getPriority); var bPriority = b.match(getPriority); if (aPriority && bPriority){ @@ -206,7 +206,7 @@ require('Storage').list(/\.boot\.js/).sort((a,b)=>{ } else if (!aPriority && bPriority){ return 1; } - return a > b; + return a==b ? 0 : (a>b ? 1 : -1); }).forEach(bootFile=>{ // we add a semicolon so if the file is wrapped in (function(){ ... }() // with no semicolon we don't end up with (function(){ ... }()(function(){ ... }() From 82c80fb39c40b445222a358ac85d77dd57ca9269 Mon Sep 17 00:00:00 2001 From: Micha <97034053+foostuff@users.noreply.github.com> Date: Mon, 14 Mar 2022 08:35:26 +0100 Subject: [PATCH 18/26] Add files via upload --- apps/clockcal/screenshot3.png | Bin 0 -> 5870 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/clockcal/screenshot3.png diff --git a/apps/clockcal/screenshot3.png b/apps/clockcal/screenshot3.png new file mode 100644 index 0000000000000000000000000000000000000000..ab34f43068b7eff781948a549d173fd72e73e122 GIT binary patch literal 5870 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 t&S zybYetV~-wy$Z<;TdSrL63f$e!+fE!BM6{jM&5`6_b#~SdPbMv&A$HNsifUz6MoF0W z1Msd!wS>48;PxBZRiVEvc-W~EZI8CoWPs;y z3yf@6xf6zhX=NYl4UD$E>Ti(FEY167SFw@VpqKzVogq7~7kG5H41pfew!{1-0A2@~ zXm4p%7T`PKJxPcW8fDs?5f~YPu2+giIyP<32p|!d03%VFZ5|te3GidPW;%vMU;>Op zX|{Q61SY_b?V9Nr5`hUY5~bPZu@RU6KelV8V@L%413pc(4_0-?OaK4?07*qoM6N<$ Ef=_ZI`v3p{ literal 0 HcmV?d00001 From 89351bd6957b61cdd65d53609c380861059e1aac Mon Sep 17 00:00:00 2001 From: Micha <97034053+foostuff@users.noreply.github.com> Date: Mon, 14 Mar 2022 08:41:01 +0100 Subject: [PATCH 19/26] Update README.md --- apps/clockcal/README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/clockcal/README.md b/apps/clockcal/README.md index c19ee54a6..8fe0485f8 100644 --- a/apps/clockcal/README.md +++ b/apps/clockcal/README.md @@ -7,7 +7,9 @@ I know that it seems redundant because there already **is** a *time&cal*-app, bu - ![locked screen](https://foostuff.github.io/BangleApps/apps/clockcal/screenshot.png) - unlocked screen (twist?) with seconds - ![unlocked screen](https://foostuff.github.io/BangleApps/apps/clockcal/screenshot2.png) - +- swipe up for big calendar (up down to scroll, left/right to exit) +- ![unlocked screen](https://foostuff.github.io/BangleApps/apps/clockcal/screenshot3.png) +- ## Configurable Features - Number of calendar rows (weeks) - Buzz on connect/disconnect (I know, this should be an extra widget, but for now, it is included) @@ -15,6 +17,14 @@ I know that it seems redundant because there already **is** a *time&cal*-app, bu - First day of the week - Red Saturday - Red Sunday +- Swipes (to disable all gestures) +- Swipes: music (swipe down) +- Spipes: messages (swipe right) + +## Auto detects your message/music apps: +- swiping down will search your files for an app with the string "music" in its filename and launch it +- swiping right will search your files for an app with the string "message" in its filename and launch it. +- Configurable apps coming soon. ## Feedback The clock works for me in a 24h/MondayFirst/WeekendFree environment but is not well-tested with other settings. From 0992edfbb428cebbbe21f0a3decdc3eb2f3dbd25 Mon Sep 17 00:00:00 2001 From: Micha <97034053+foostuff@users.noreply.github.com> Date: Mon, 14 Mar 2022 08:41:57 +0100 Subject: [PATCH 20/26] Update README.md --- apps/clockcal/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/clockcal/README.md b/apps/clockcal/README.md index 8fe0485f8..eeb23c35e 100644 --- a/apps/clockcal/README.md +++ b/apps/clockcal/README.md @@ -8,7 +8,7 @@ I know that it seems redundant because there already **is** a *time&cal*-app, bu - unlocked screen (twist?) with seconds - ![unlocked screen](https://foostuff.github.io/BangleApps/apps/clockcal/screenshot2.png) - swipe up for big calendar (up down to scroll, left/right to exit) -- ![unlocked screen](https://foostuff.github.io/BangleApps/apps/clockcal/screenshot3.png) +- ![big calendar](https://foostuff.github.io/BangleApps/apps/clockcal/screenshot3.png) - ## Configurable Features - Number of calendar rows (weeks) From 511ddd56bd46d0fbf5eaff7b853f3f3e1cfbe155 Mon Sep 17 00:00:00 2001 From: Micha <97034053+foostuff@users.noreply.github.com> Date: Mon, 14 Mar 2022 08:58:53 +0100 Subject: [PATCH 21/26] Update README.md --- apps/clockcal/README.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/apps/clockcal/README.md b/apps/clockcal/README.md index eeb23c35e..da6887177 100644 --- a/apps/clockcal/README.md +++ b/apps/clockcal/README.md @@ -3,13 +3,15 @@ This is my "Hello World". I first made this watchface almost 10 years ago for my original Pebble and Pebble Time and I missed this so much, that I had to write it for the BangleJS2. I know that it seems redundant because there already **is** a *time&cal*-app, but it didn't fit my style. -- locked screen with only one minimal update/minute -- ![locked screen](https://foostuff.github.io/BangleApps/apps/clockcal/screenshot.png) -- unlocked screen (twist?) with seconds -- ![unlocked screen](https://foostuff.github.io/BangleApps/apps/clockcal/screenshot2.png) -- swipe up for big calendar (up down to scroll, left/right to exit) -- ![big calendar](https://foostuff.github.io/BangleApps/apps/clockcal/screenshot3.png) -- +|Screenshot|description| +|:--:|:-| +|![locked screen](screenshot.png)|locked: triggers only one minimal update/min| +|![unlocked screen](screenshot2.png)|unlocked: smaller clock, but with seconds| +|![big calendar](screenshot3.png)|swipe up for big calendar, (up down to scroll, left/right to exit)| + + + + ## Configurable Features - Number of calendar rows (weeks) - Buzz on connect/disconnect (I know, this should be an extra widget, but for now, it is included) From 98968d9a92ff522fa2f473b79684d744b082cbb4 Mon Sep 17 00:00:00 2001 From: Micha <97034053+foostuff@users.noreply.github.com> Date: Mon, 14 Mar 2022 09:01:42 +0100 Subject: [PATCH 22/26] Update app.js --- apps/clockcal/app.js | 185 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 179 insertions(+), 6 deletions(-) diff --git a/apps/clockcal/app.js b/apps/clockcal/app.js index fc299912f..86fa0815a 100644 --- a/apps/clockcal/app.js +++ b/apps/clockcal/app.js @@ -7,15 +7,116 @@ var s = Object.assign({ FIRSTDAYOFFSET: 6, //First day of the week: 0-6: Sun, Sat, Fri, Thu, Wed, Tue, Mon REDSUN: true, // Use red color for sunday? REDSAT: true, // Use red color for saturday? + DRAGENABLED: true, + DRAGMUSIC: true, + DRAGMESSAGES: true }, require('Storage').readJSON("clockcal.json", true) || {}); const h = g.getHeight(); const w = g.getWidth(); const CELL_W = w / 7; +const CELL2_W = w / 8;//full calendar const CELL_H = 15; const CAL_Y = h - s.CAL_ROWS * CELL_H; const DEBUG = false; +var state = "watch"; +var monthOffset = 0; +/* + * Calendar features + */ +function drawFullCalendar(monthOffset) { + addMonths = function (_d, _am) { + var ay = 0, m = _d.getMonth(), y = _d.getFullYear(); + while ((m + _am) > 11) { ay++; _am -= 12; } + while ((m + _am) < 0) { ay--; _am += 12; } + n = new Date(_d.getTime()); + n.setMonth(m + _am); + n.setFullYear(y + ay); + return n; + }; + monthOffset = (typeof monthOffset == "undefined") ? 0 : monthOffset; + state = "calendar"; + var start = Date().getTime(); + const months = ['Jan.', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec.']; + const monthclr = ['#0f0', '#f0f', '#00f', '#ff0', '#0ff', '#fff']; + if (typeof dayInterval !== "undefined") clearTimeout(dayInterval); + if (typeof secondInterval !== "undefined") clearTimeout(secondInterval); + if (typeof minuteInterval !== "undefined") clearTimeout(minuteInterval); + d = addMonths(Date(), monthOffset); + tdy = Date().getDate() + "." + Date().getMonth(); + newmonth=false; + c_y = 0; + g.reset(); + g.setBgColor(0); + g.clear(); + var prevmonth = addMonths(d, -1) + const today = prevmonth.getDate(); + var rD = new Date(prevmonth.getTime()); + rD.setDate(rD.getDate() - (today - 1)); + const dow = (s.FIRSTDAYOFFSET + rD.getDay()) % 7; + rD.setDate(rD.getDate() - dow); + var rDate = rD.getDate(); + bottomrightY = c_y - 3; + clrsun=s.REDSUN?'#f00':'#fff'; + clrsat=s.REDSUN?'#f00':'#fff'; + var fg=[clrsun,'#fff','#fff','#fff','#fff','#fff',clrsat]; + for (var y = 1; y <= 11; y++) { + bottomrightY += CELL_H; + bottomrightX = -2; + for (var x = 1; x <= 7; x++) { + bottomrightX += CELL2_W; + rMonth = rD.getMonth(); + rDate = rD.getDate(); + if (tdy == rDate + "." + rMonth) { + caldrawToday(rDate); + } else if (rDate == 1) { + caldrawFirst(rDate); + } else { + caldrawNormal(rDate,fg[rD.getDay()]); + } + if (newmonth && x == 7) { + caldrawMonth(rDate,monthclr[rMonth % 6],months[rMonth],rD); + } + rD.setDate(rDate + 1); + } + } + delete addMonths; + if (DEBUG) console.log("Calendar performance (ms):" + (Date().getTime() - start)); +} +function caldrawMonth(rDate,c,m,rD) { + g.setColor(c); + g.setFont("Vector", 18); + g.setFontAlign(-1, 1, 1); + drawyear = ((rMonth % 11) == 0) ? String(rD.getFullYear()).substr(-2) : ""; + g.drawString(m + drawyear, bottomrightX, bottomrightY - CELL_H, 1); + newmonth = false; +} +function caldrawToday(rDate) { + g.setFont("Vector", 16); + g.setFontAlign(1, 1); + g.setColor('#0f0'); + g.fillRect(bottomrightX - CELL2_W + 1, bottomrightY - CELL_H - 1, bottomrightX, bottomrightY - 2); + g.setColor('#000'); + g.drawString(rDate, bottomrightX, bottomrightY); +} +function caldrawFirst(rDate) { + g.flip(); + g.setFont("Vector", 16); + g.setFontAlign(1, 1); + bottomrightY += 3; + newmonth = true; + g.setColor('#0ff'); + g.fillRect(bottomrightX - CELL2_W + 1, bottomrightY - CELL_H - 1, bottomrightX, bottomrightY - 2); + g.setColor('#000'); + g.drawString(rDate, bottomrightX, bottomrightY); +} +function caldrawNormal(rDate,c) { + g.setFont("Vector", 16); + g.setFontAlign(1, 1); + g.setColor(c); + g.drawString(rDate, bottomrightX, bottomrightY);//100 +} function drawMinutes() { if (DEBUG) console.log("|-->minutes"); var d = new Date(); @@ -52,8 +153,10 @@ function drawSeconds() { if (!dimSeconds) secondInterval = setTimeout(drawSeconds, 1000); } -function drawCalendar() { +function drawWatch() { if (DEBUG) console.log("CALENDAR"); + monthOffset = 0; + state = "watch"; var d = new Date(); g.reset(); g.setBgColor(0); @@ -91,7 +194,7 @@ function drawCalendar() { var nextday = (3600 * 24) - (d.getHours() * 3600 + d.getMinutes() * 60 + d.getSeconds() + 1); if (DEBUG) console.log("Next Day:" + (nextday / 3600)); if (typeof dayInterval !== "undefined") clearTimeout(dayInterval); - dayInterval = setTimeout(drawCalendar, nextday * 1000); + dayInterval = setTimeout(drawWatch, nextday * 1000); } function BTevent() { @@ -103,17 +206,87 @@ function BTevent() { } } +function input(dir) { + if (s.DRAGENABLED) { + Bangle.buzz(100,1); + console.log("swipe:"+dir); + switch (dir) { + case "r": + if (state == "calendar") { + drawWatch(); + } else { + if (s.DRAGMUSIC) { + l=require("Storage").list(RegExp("music.*app")); + if (l.length > 0) { + load(l[0]); + } else Bangle.buzz(3000,1);//not found + } + } + break; + case "l": + if (state == "calendar") { + drawWatch(); + } + break; + case "d": + if (state == "calendar") { + monthOffset--; + drawFullCalendar(monthOffset); + } else { + if (s.DRAGMESSAGES) { + l=require("Storage").list(RegExp("message.*app")); + if (l.length > 0) { + load(l[0]); + } else Bangle.buzz(3000,1);//not found + } + } + break; + case "u": + if (state == "watch") { + state = "calendar"; + drawFullCalendar(0); + } else if (state == "calendar") { + monthOffset++; + drawFullCalendar(monthOffset); + } + break; + default: + if (state == "calendar") { + drawWatch(); + } + break; + } + } +} + +let drag; +Bangle.on("drag", e => { + if (s.DRAGENABLED) { + if (!drag) { + drag = { x: e.x, y: e.y }; + } else if (!e.b) { + const dx = e.x - drag.x, dy = e.y - drag.y; + var dir = "t"; + if (Math.abs(dx) > Math.abs(dy) + 10) { + dir = (dx > 0) ? "r" : "l"; + } else if (Math.abs(dy) > Math.abs(dx) + 10) { + dir = (dy > 0) ? "d" : "u"; + } + drag = null; + input(dir); + } + } +}); + //register events Bangle.on('lock', locked => { if (typeof secondInterval !== "undefined") clearTimeout(secondInterval); dimSeconds = locked; //dim seconds if lock=on - drawCalendar(); + drawWatch(); }); NRF.on('connect', BTevent); NRF.on('disconnect', BTevent); - dimSeconds = Bangle.isLocked(); -drawCalendar(); - +drawWatch(); Bangle.setUI("clock"); From 0146efb99f4147cb72132a1b1c17ce81c2ae858b Mon Sep 17 00:00:00 2001 From: Micha <97034053+foostuff@users.noreply.github.com> Date: Mon, 14 Mar 2022 09:03:37 +0100 Subject: [PATCH 23/26] Added Drag-to-launch-stuff options --- apps/clockcal/settings.js | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/apps/clockcal/settings.js b/apps/clockcal/settings.js index cc2a78181..c4ec764c9 100644 --- a/apps/clockcal/settings.js +++ b/apps/clockcal/settings.js @@ -8,6 +8,9 @@ FIRSTDAY: 6, //First day of the week: mo, tu, we, th, fr, sa, su REDSUN: true, // Use red color for sunday? REDSAT: true, // Use red color for saturday? + DRAGENABLED: true, //Enable drag gestures (bigger calendar etc) + DRAGMUSIC: true, //Enable drag down for music (looks for "music*app") + DRAGMESSAGES: true //Enable drag right for messages (looks for "message*app") }, require('Storage').readJSON(FILE, true) || {}); @@ -67,6 +70,30 @@ writeSettings(); } }, + 'Swipes (big cal.)?': { + value: settings.DRAGENABLED, + format: v => v ? "On" : "Off", + onchange: v => { + settings.DRAGENABLED = v; + writeSettings(); + } + }, + 'Swipes (music)?': { + value: settings.DRAGMUSIC, + format: v => v ? "On" : "Off", + onchange: v => { + settings.DRAGMUSIC = v; + writeSettings(); + } + }, + 'Swipes (messg)?': { + value: settings.DRAGMESSAGES, + format: v => v ? "On" : "Off", + onchange: v => { + settings.DRAGMESSAGES = v; + writeSettings(); + } + }, 'Load deafauls?': { value: 0, min: 0, max: 1, @@ -80,13 +107,16 @@ FIRSTDAY: 6, //First day of the week: mo, tu, we, th, fr, sa, su REDSUN: true, // Use red color for sunday? REDSAT: true, // Use red color for saturday? + DRAGENABLED: true, + DRAGMUSIC: true, + DRAGMESSAGES: true }; writeSettings(); - load() + load(); } } }, - } + }; // Show the menu E.showMenu(menu); -}) +}); From f573985bdc2646a9be45a49ee0a83b1b592a9b8d Mon Sep 17 00:00:00 2001 From: Micha <97034053+foostuff@users.noreply.github.com> Date: Mon, 14 Mar 2022 09:05:50 +0100 Subject: [PATCH 24/26] Update metadata.json --- apps/clockcal/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/clockcal/metadata.json b/apps/clockcal/metadata.json index ccc84a980..a42e1ad2e 100644 --- a/apps/clockcal/metadata.json +++ b/apps/clockcal/metadata.json @@ -1,7 +1,7 @@ { "id": "clockcal", "name": "Clock & Calendar", - "version": "0.01", + "version": "0.2", "description": "Clock with Calendar", "readme":"README.md", "icon": "app.png", From cde9f59ba3d77b897e96408a9ca7abfbbc55ead5 Mon Sep 17 00:00:00 2001 From: Micha <97034053+foostuff@users.noreply.github.com> Date: Mon, 14 Mar 2022 09:06:48 +0100 Subject: [PATCH 25/26] Update ChangeLog --- apps/clockcal/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/clockcal/ChangeLog b/apps/clockcal/ChangeLog index e874c8c67..299b1ec69 100644 --- a/apps/clockcal/ChangeLog +++ b/apps/clockcal/ChangeLog @@ -1 +1,2 @@ 0.01: Initial upload +0.2: Added scrollable calendar and swipe gestures From fe0e19148e9b27e7016d9f85505e758ff5d26a81 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 14 Mar 2022 09:29:35 +0000 Subject: [PATCH 26/26] 0.09: Fix broken start/stop if recording not enabled (fix #1561) --- apps/run/ChangeLog | 3 ++- apps/run/app.js | 3 +++ apps/run/metadata.json | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/run/ChangeLog b/apps/run/ChangeLog index 0a697ecb9..032ebdc1a 100644 --- a/apps/run/ChangeLog +++ b/apps/run/ChangeLog @@ -6,4 +6,5 @@ 0.05: exstats updated so update 'distance' label is updated, option for 'speed' 0.06: Add option to record a run using the recorder app automatically 0.07: Fix crash if an odd number of active boxes are configured (fix #1473) -0.08: Added support for notifications from exstats. Support all stats from exstats \ No newline at end of file +0.08: Added support for notifications from exstats. Support all stats from exstats +0.09: Fix broken start/stop if recording not enabled (fix #1561) diff --git a/apps/run/app.js b/apps/run/app.js index 45daf878e..d066c8b1f 100644 --- a/apps/run/app.js +++ b/apps/run/app.js @@ -66,6 +66,9 @@ function onStartStop() { } } + if (!prepPromises.length) // fix for Promise.all bug in 2v12 + prepPromises.push(Promise.resolve()); + Promise.all(prepPromises) .then(() => { if (running) { diff --git a/apps/run/metadata.json b/apps/run/metadata.json index 8f139c2d5..01a85ed05 100644 --- a/apps/run/metadata.json +++ b/apps/run/metadata.json @@ -1,6 +1,6 @@ { "id": "run", "name": "Run", - "version":"0.08", + "version":"0.09", "description": "Displays distance, time, steps, cadence, pace and more for runners.", "icon": "app.png", "tags": "run,running,fitness,outdoors,gps",