diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml index 28021246f..c32feaf85 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml @@ -1,20 +1,19 @@ -name: Bangle bug report -description: "Bangle: Create a issue to help us improve!" -title: "Short description and provide the affected app/widget" +name: Bangle.js bug report +description: "Create a issue to help us improve!" +title: "[app/widget name] Short description of bug" labels: ["bug"] assignees: [] body: - type: markdown attributes: value: | - # Attention: If you have a question then ask it at the [bangle forum](http://forum.espruino.com/microcosms/1424/), please! + **:fire: Attention: If you have a question then please ask on the [Bangle.js forum](http://forum.espruino.com/microcosms/1424/) :fire:** - type: dropdown id: hwversion attributes: label: Affected hardware version description: | - Which Bangle hardware version(s) is/are affected? - _Hint: You can select multiple entries._ + Which Bangle hardware version(s) is/are affected? _You can select multiple entries._ options: - Bangle 1 - Bangle 2 @@ -26,13 +25,15 @@ body: attributes: label: Your firmware version description: | - ## Please make sure you installed the latest (released) firmware! - If it occurs only in "Cutting Edge build" please mention this. - Update instructions: - **Bangle 2: [firmware update instructions](https://www.espruino.com/Bangle.js2#firmware-updates)** - **Bangle 1: [firmware update instructions](https://www.espruino.com/Bangle.js#firmware-updates)** - _Hint: The links will open inplace hold e.g. ctrl/cmd-key and click to open in a new tab instead._ - placeholder: e.g. 2v11 + **Please make sure you have installed the latest (released) firmware!** + To find your firmware version, check the `About` Bangle.js app or connect with [the App Loader](https://banglejs.com/apps/), click `More...` and look for a `Device Info` heading. + If the issue occurs only in "Cutting Edge" builds, please mention this. + + **FW Update instructions:** + * **Bangle 2:** [firmware update instructions](https://www.espruino.com/Bangle.js2#firmware-updates) + * **Bangle 1:** [firmware update instructions](https://www.espruino.com/Bangle.js#firmware-updates) + _Hint: The links will open in-place (hold ctrl/cmd-key and click to open in a new tab instead)_ + placeholder: e.g. 2v12 validations: required: true - type: textarea @@ -40,19 +41,19 @@ body: attributes: label: The bug description: | - ## Please also mention the expected behaviour and steps to reproduce + **Please also mention the expected behaviour and steps to reproduce** placeholder: | - ###Describe the bug + ### Describe the bug A clear and concise description of what the bug is. - ###Expected behavior + ### Expected behavior A clear and concise description of what you expected to happen. - ###Steps to reproduce - 1. Start app xy - 2. choose abc - 3. bug occurs + ### Steps to reproduce + 1. Do you have other apps/widgets installed that are relevant? + 2. Start app xy + 3. Perform some action + 4. bug occurs - It could be helpfull for us to provide the devopment folder in 'bangle apps' folder validations: - required: true \ No newline at end of file + required: true diff --git a/README.md b/README.md index 0a92aae30..9cf30065a 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,7 @@ Apps are listed in the Bangle.js menu, accessible from a clock app via the middl * `app.png` - app icon - 48x48px * `app-icon.js` - JS version of the icon (made with http://www.espruino.com/Image+Converter) for use in Bangle.js's menu * `app.js` - app code +* `ChangeLog` - A file containing a list of changes to your app so users can see what's changed #### `app-icon.js` @@ -189,9 +190,23 @@ When the widget is to be drawn, `x` and `y` values are set up in `WIDGETS["mywid and `draw` can then use `this.x` and `this.y` to figure out where it needs to draw to. +### ChangeLog + +This is a file containing a list of changes to your app so users can see what's changed, for example: + +``` +0.01: New App! +0.02: Changed the colors +0.03: Made the app run quicker +``` + +Entries should be newest last, with the version number of the last entry matching the version in `metadata.json` + +Please keep the same format at the example as the file needs to be parsed by the BangleApps tools. + ### `app.info` format -This is the file that's **auto-generated** and loaded onto Bangle.js by the App Loader, +This is the file that's **auto-generated** from `metadata.json` and loaded onto Bangle.js by the App Loader, and which gives information about the app for the Launcher. ``` diff --git a/apps/ac_ac/ChangeLog.txt b/apps/ac_ac/ChangeLog.txt new file mode 100644 index 000000000..307e4165d --- /dev/null +++ b/apps/ac_ac/ChangeLog.txt @@ -0,0 +1,2 @@ +0.01: initial release +1.00: first official release (also fixes bug in Customizer) \ No newline at end of file diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index f2aa79920..ae40be939 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -321,7 +321,7 @@ function chosenClockHands () { switch (ClockHands) { - case 'simple': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-simpled-clock-hands/main/ClockHands.js')" + case 'simple': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-simple-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 + "')" diff --git a/apps/ac_ac/metadata.json b/apps/ac_ac/metadata.json index a4f3de0ac..4dbe93834 100644 --- a/apps/ac_ac/metadata.json +++ b/apps/ac_ac/metadata.json @@ -1,7 +1,7 @@ { "id": "ac_ac", "name": "A Configurable Analog Clock", "shortName":"Configurable Clock", - "version":"0.03", + "version":"1.00", "description": "AC-AC, a highly customizable analog clock with several clock faces, hands and complications to choose from", "icon": "app-icon.png", "type": "clock", diff --git a/apps/alarm/boot.js b/apps/alarm/boot.js index dffb3a37f..47dae5361 100644 --- a/apps/alarm/boot.js +++ b/apps/alarm/boot.js @@ -7,7 +7,7 @@ active = active.sort((a,b)=>(a.hr-b.hr)+(a.last-b.last)*24); var hr = time.getHours()+(time.getMinutes()/60)+(time.getSeconds()/3600); if (!require('Storage').read("alarm.js")) { - console.log(/*LANG*/"No alarm app!"); + console.log("No alarm app!"); require('Storage').write('alarm.json',"[]"); } else { var t = 3600000*(active[0].hr-hr); diff --git a/apps/android/ChangeLog b/apps/android/ChangeLog index 0d837fe43..59cb23a46 100644 --- a/apps/android/ChangeLog +++ b/apps/android/ChangeLog @@ -5,3 +5,4 @@ 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) +0.07: Include charging state in battery updates to phone diff --git a/apps/android/boot.js b/apps/android/boot.js index fff9ad444..eb3d26c6e 100644 --- a/apps/android/boot.js +++ b/apps/android/boot.js @@ -50,8 +50,9 @@ }; // Battery monitor - function sendBattery() { gbSend({ t: "status", bat: E.getBattery() }); } + function sendBattery() { gbSend({ t: "status", bat: E.getBattery(), chg: Bangle.isCharging()?1:0 }); } NRF.on("connect", () => setTimeout(sendBattery, 2000)); + Bangle.on("charging", sendBattery); if (!settings.keep) NRF.on("disconnect", () => require("messages").clearAll()); // remove all messages on disconnect setInterval(sendBattery, 10*60*1000); diff --git a/apps/android/metadata.json b/apps/android/metadata.json index 6b780ff55..d126b869a 100644 --- a/apps/android/metadata.json +++ b/apps/android/metadata.json @@ -2,7 +2,7 @@ "id": "android", "name": "Android Integration", "shortName": "Android", - "version": "0.06", + "version": "0.07", "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,gadgetbridge", diff --git a/apps/authentiwatch/ChangeLog b/apps/authentiwatch/ChangeLog index 7a902a731..7d6f96026 100644 --- a/apps/authentiwatch/ChangeLog +++ b/apps/authentiwatch/ChangeLog @@ -2,3 +2,4 @@ 0.02: Fix JSON save format 0.03: Add "Calculating" placeholder, update JSON save format 0.04: Fix tapping at very bottom of list, exit on inactivity +0.05: Add support for bulk importing and exporting tokens diff --git a/apps/authentiwatch/README.md b/apps/authentiwatch/README.md index 8d0e74a0c..cc25e9604 100644 --- a/apps/authentiwatch/README.md +++ b/apps/authentiwatch/README.md @@ -3,6 +3,15 @@ * GitHub: https://github.com/andrewgoz/Authentiwatch <-- Report bugs here * Bleeding edge AppLoader: https://andrewgoz.github.io/Authentiwatch/ +## Important! + +Tokens are stored *ONLY* on the watch. Make sure you do one or more of the following: + +* Make a backup copy of the "authentiwatch.json" file. +* Export all your tokens to another device or print the QR code. + +Keep those copies safe and secure. + ## Supports * Google Authenticator compatible 2-factor authentication @@ -14,8 +23,8 @@ * Between 6 and 10 digits * Phone/PC configuration web page: * Add/edit/delete/arrange tokens - * Scan QR codes - * Produce scannable QR codes + * Scan token and migration(import) QR codes + * Produce scannable token and migration(export) QR codes ## Usage @@ -24,6 +33,8 @@ * Swipe right to exit to the app launcher. * Swipe left on selected counter token to advance the counter to the next value. +![Screenshot](screenshot.png) + ## Creator Andrew Gregory (andrew.gregory at gmail) diff --git a/apps/authentiwatch/app.js b/apps/authentiwatch/app.js index c0cb608c0..640183230 100644 --- a/apps/authentiwatch/app.js +++ b/apps/authentiwatch/app.js @@ -1,4 +1,5 @@ -const tokenentryheight = 46; +const tokenextraheight = 16; +var tokendigitsheight = 30; // Hash functions const crypto = require("crypto"); const algos = { @@ -44,9 +45,6 @@ function b32decode(seedstr) { } } } - if (bitcount > 0) { - retstr += String.fromCharCode(buf << (8 - bitcount)); - } var retbuf = new Uint8Array(retstr.length); for (i in retstr) { retbuf[i] = retstr.charCodeAt(i); @@ -117,27 +115,31 @@ function drawToken(id, r) { var y1 = r.y; var x2 = r.x + r.w - 1; var y2 = r.y + r.h - 1; - var adj, sz; + var adj, lbl, sz; g.setClipRect(Math.max(x1, Bangle.appRect.x ), Math.max(y1, Bangle.appRect.y ), Math.min(x2, Bangle.appRect.x2), Math.min(y2, Bangle.appRect.y2)); + lbl = tokens[id].label.substr(0, 10); if (id == state.curtoken) { // current token g.setColor(g.theme.fgH); g.setBgColor(g.theme.bgH); - g.setFont("Vector", 16); + g.setFont("Vector", tokenextraheight); // center just below top line g.setFontAlign(0, -1, 0); adj = y1; } else { g.setColor(g.theme.fg); g.setBgColor(g.theme.bg); - g.setFont("Vector", 30); + sz = tokendigitsheight; + do { + g.setFont("Vector", sz--); + } while (g.stringWidth(lbl) > r.w); // center in box g.setFontAlign(0, 0, 0); adj = (y1 + y2) / 2; } g.clearRect(x1, y1, x2, y2); - g.drawString(tokens[id].label.substr(0, 10), (x1 + x2) / 2, adj, false); + g.drawString(lbl, (x1 + x2) / 2, adj, false); if (id == state.curtoken) { if (tokens[id].period > 0) { // timed - draw progress bar @@ -148,14 +150,14 @@ function drawToken(id, r) { // counter - draw triangle as swipe hint let yc = (y1 + y2) / 2; g.fillPoly([0, yc, 10, yc - 10, 10, yc + 10, 0, yc]); - adj = 10; + adj = 12; } // digits just below label - sz = 30; + sz = tokendigitsheight; do { g.setFont("Vector", sz--); } while (g.stringWidth(state.otp) > (r.w - adj)); - g.drawString(state.otp, (x1 + adj + x2) / 2, y1 + 16, false); + g.drawString(state.otp, (x1 + adj + x2) / 2, y1 + tokenextraheight, false); } // shaded lines top and bottom g.setColor(0.5, 0.5, 0.5); @@ -196,15 +198,15 @@ function draw() { } if (tokens.length > 0) { var drewcur = false; - var id = Math.floor(state.listy / tokenentryheight); - var y = id * tokenentryheight + Bangle.appRect.y - state.listy; + var id = Math.floor(state.listy / (tokendigitsheight + tokenextraheight)); + var y = id * (tokendigitsheight + tokenextraheight) + Bangle.appRect.y - state.listy; while (id < tokens.length && y < Bangle.appRect.y2) { - drawToken(id, {x:Bangle.appRect.x, y:y, w:Bangle.appRect.w, h:tokenentryheight}); + drawToken(id, {x:Bangle.appRect.x, y:y, w:Bangle.appRect.w, h:(tokendigitsheight + tokenextraheight)}); if (id == state.curtoken && (tokens[id].period <= 0 || state.nextTime != 0)) { drewcur = true; } id += 1; - y += tokenentryheight; + y += (tokendigitsheight + tokenextraheight); } if (drewcur) { // the current token has been drawn - schedule a redraw @@ -226,7 +228,7 @@ function draw() { state.nexttime = 0; } } else { - g.setFont("Vector", 30); + g.setFont("Vector", tokendigitsheight); g.setFontAlign(0, 0, 0); g.drawString(notokens, Bangle.appRect.x + Bangle.appRect.w / 2, Bangle.appRect.y + Bangle.appRect.h / 2, false); } @@ -238,18 +240,18 @@ function draw() { function onTouch(zone, e) { if (e) { - var id = Math.floor((state.listy + (e.y - Bangle.appRect.y)) / tokenentryheight); + var id = Math.floor((state.listy + (e.y - Bangle.appRect.y)) / (tokendigitsheight + tokenextraheight)); if (id == state.curtoken || tokens.length == 0 || id >= tokens.length) { id = -1; } if (state.curtoken != id) { if (id != -1) { - var y = id * tokenentryheight - state.listy; + var y = id * (tokendigitsheight + tokenextraheight) - state.listy; if (y < 0) { state.listy += y; y = 0; } - y += tokenentryheight; + y += (tokendigitsheight + tokenextraheight); if (y > Bangle.appRect.h) { state.listy += (y - Bangle.appRect.h); } @@ -266,12 +268,15 @@ function onTouch(zone, e) { function onDrag(e) { if (e.x > g.getWidth() || e.y > g.getHeight()) return; if (e.dx == 0 && e.dy == 0) return; - var newy = Math.min(state.listy - e.dy, tokens.length * tokenentryheight - Bangle.appRect.h); + var newy = Math.min(state.listy - e.dy, tokens.length * (tokendigitsheight + tokenextraheight) - Bangle.appRect.h); state.listy = Math.max(0, newy); draw(); } function onSwipe(e) { + if (e == 1) { + exitApp(); + } if (e == -1 && state.curtoken != -1 && tokens[state.curtoken].period <= 0) { tokens[state.curtoken].period--; let newsettings={tokens:tokens,misc:settings.misc}; @@ -296,7 +301,7 @@ function bangle1Btn(e) { state.curtoken = Math.max(state.curtoken, 0); state.curtoken = Math.min(state.curtoken, tokens.length - 1); var fakee = {}; - fakee.y = state.curtoken * tokenentryheight - state.listy + Bangle.appRect.y; + fakee.y = state.curtoken * (tokendigitsheight + tokenextraheight) - state.listy + Bangle.appRect.y; state.curtoken = -1; state.nextTime = 0; onTouch(0, fakee); diff --git a/apps/authentiwatch/interface.html b/apps/authentiwatch/interface.html index 26533b17b..d2213b819 100644 --- a/apps/authentiwatch/interface.html +++ b/apps/authentiwatch/interface.html @@ -7,7 +7,10 @@