Merge branch 'master' of github.com:ff2005/BangleApps into feature/nifty-clock-a
commit
dad29a9fd7
42
apps.json
42
apps.json
|
|
@ -13,6 +13,21 @@
|
||||||
],
|
],
|
||||||
"sortorder" : -10
|
"sortorder" : -10
|
||||||
},
|
},
|
||||||
|
{ "id": "health",
|
||||||
|
"name": "Health Tracking",
|
||||||
|
"tags": "tool,system,b2",
|
||||||
|
"icon": "app.png",
|
||||||
|
"version":"0.01",
|
||||||
|
"description": "Logs health data and provides an app to view it (BETA - requires firmware 2v11)",
|
||||||
|
"readme": "README.md",
|
||||||
|
"storage": [
|
||||||
|
{"name":"health.app.js","url":"app.js"},
|
||||||
|
{"name":"health.img","url":"app-icon.js","evaluate":true},
|
||||||
|
{"name":"health.boot.js","url":"boot.js"},
|
||||||
|
{"name":"health","url":"lib.js"}
|
||||||
|
],
|
||||||
|
"sortorder" : -10
|
||||||
|
},
|
||||||
{ "id": "moonphase",
|
{ "id": "moonphase",
|
||||||
"name": "Moonphase",
|
"name": "Moonphase",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
|
|
@ -55,7 +70,7 @@
|
||||||
"name": "Launcher (Bangle.js 2)",
|
"name": "Launcher (Bangle.js 2)",
|
||||||
"shortName":"Launcher",
|
"shortName":"Launcher",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"version":"0.02",
|
"version":"0.03",
|
||||||
"description": "This is needed by Bangle.js 2.0 to display a menu allowing you to choose your own applications. It will not work on Bangle.js 1.0.",
|
"description": "This is needed by Bangle.js 2.0 to display a menu allowing you to choose your own applications. It will not work on Bangle.js 1.0.",
|
||||||
"tags": "tool,system,launcher,b2,bno1",
|
"tags": "tool,system,launcher,b2,bno1",
|
||||||
"type":"launch",
|
"type":"launch",
|
||||||
|
|
@ -67,7 +82,7 @@
|
||||||
{ "id": "about",
|
{ "id": "about",
|
||||||
"name": "About",
|
"name": "About",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"version":"0.08",
|
"version":"0.09",
|
||||||
"description": "Bangle.js About page - showing software version, stats, and a collaborative mural from the Bangle.js KickStarter backers",
|
"description": "Bangle.js About page - showing software version, stats, and a collaborative mural from the Bangle.js KickStarter backers",
|
||||||
"tags": "tool,system,b2",
|
"tags": "tool,system,b2",
|
||||||
"allow_emulator":true,
|
"allow_emulator":true,
|
||||||
|
|
@ -500,9 +515,9 @@
|
||||||
{ "id": "speedo",
|
{ "id": "speedo",
|
||||||
"name": "Speedo",
|
"name": "Speedo",
|
||||||
"icon": "speedo.png",
|
"icon": "speedo.png",
|
||||||
"version":"0.04",
|
"version":"0.05",
|
||||||
"description": "Show the current speed according to the GPS",
|
"description": "Show the current speed according to the GPS",
|
||||||
"tags": "tool,outdoors,gps",
|
"tags": "tool,outdoors,gps,b2",
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"speedo.app.js","url":"speedo.js"},
|
{"name":"speedo.app.js","url":"speedo.js"},
|
||||||
{"name":"speedo.img","url":"speedo-icon.js","evaluate":true}
|
{"name":"speedo.img","url":"speedo-icon.js","evaluate":true}
|
||||||
|
|
@ -653,7 +668,7 @@
|
||||||
"name": "Battery Level Widget (with percentage)",
|
"name": "Battery Level Widget (with percentage)",
|
||||||
"shortName": "Battery Widget",
|
"shortName": "Battery Widget",
|
||||||
"icon": "widget.png",
|
"icon": "widget.png",
|
||||||
"version":"0.12",
|
"version":"0.13",
|
||||||
"description": "Show the current battery level and charging status in the top right of the clock, with charge percentage",
|
"description": "Show the current battery level and charging status in the top right of the clock, with charge percentage",
|
||||||
"tags": "widget,battery,b2",
|
"tags": "widget,battery,b2",
|
||||||
"type":"widget",
|
"type":"widget",
|
||||||
|
|
@ -1421,7 +1436,7 @@
|
||||||
"icon": "chrono.png",
|
"icon": "chrono.png",
|
||||||
"version":"0.01",
|
"version":"0.01",
|
||||||
"description": "Single click BTN1 to add 5 minutes. Single click BTN2 to add 30 seconds. Single click BTN3 to add 5 seconds. Tap to pause or play to timer. Double click BTN1 to reset. When timer finishes the watch vibrates.",
|
"description": "Single click BTN1 to add 5 minutes. Single click BTN2 to add 30 seconds. Single click BTN3 to add 5 seconds. Tap to pause or play to timer. Double click BTN1 to reset. When timer finishes the watch vibrates.",
|
||||||
"tags": "Tools",
|
"tags": "tool",
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"chrono.app.js","url":"chrono.js"},
|
{"name":"chrono.app.js","url":"chrono.js"},
|
||||||
{"name":"chrono.img","url":"chrono-icon.js","evaluate":true}
|
{"name":"chrono.img","url":"chrono-icon.js","evaluate":true}
|
||||||
|
|
@ -1562,7 +1577,7 @@
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"version":"0.03",
|
"version":"0.03",
|
||||||
"description": "Chronometer (timer) which runs as widget.",
|
"description": "Chronometer (timer) which runs as widget.",
|
||||||
"tags": "tools,widget",
|
"tags": "tool,widget,b2",
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"chronowid.wid.js","url":"widget.js"},
|
{"name":"chronowid.wid.js","url":"widget.js"},
|
||||||
|
|
@ -3502,7 +3517,7 @@
|
||||||
"name": "Pastel Clock",
|
"name": "Pastel Clock",
|
||||||
"shortName": "Pastel",
|
"shortName": "Pastel",
|
||||||
"icon": "pastel.png",
|
"icon": "pastel.png",
|
||||||
"version":"0.03",
|
"version":"0.04",
|
||||||
"description": "A Configurable clock with custom fonts and background",
|
"description": "A Configurable clock with custom fonts and background",
|
||||||
"tags": "clock,b2",
|
"tags": "clock,b2",
|
||||||
"type":"clock",
|
"type":"clock",
|
||||||
|
|
@ -3573,6 +3588,17 @@
|
||||||
{"name":"score.json"}
|
{"name":"score.json"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{ "id": "menusmall",
|
||||||
|
"name": "Small Menus",
|
||||||
|
"icon": "app.png",
|
||||||
|
"version":"0.01",
|
||||||
|
"description": "Replace Bangle.js 2's menus with a version that contains smaller text",
|
||||||
|
"tags": "b2,bno1,system",
|
||||||
|
"type": "boot",
|
||||||
|
"storage": [
|
||||||
|
{"name":"menusmall.boot.js","url":"boot.js"}
|
||||||
|
]
|
||||||
|
},
|
||||||
{ "id": "ffcniftya",
|
{ "id": "ffcniftya",
|
||||||
"name": "Nifty-A Clock",
|
"name": "Nifty-A Clock",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
|
|
|
||||||
|
|
@ -6,3 +6,4 @@
|
||||||
0.06: Actual pixels as of 12 Jun 2020
|
0.06: Actual pixels as of 12 Jun 2020
|
||||||
0.07: Pressing a button now exits immediately (fix #618)
|
0.07: Pressing a button now exits immediately (fix #618)
|
||||||
0.08: Make about (mostly) work on non-240px screens
|
0.08: Make about (mostly) work on non-240px screens
|
||||||
|
0.09: Actual Bangle.js 1 pixels as of 13 Oct 2021
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -5,11 +5,15 @@ The advantage is, that you can still see your normal watchface and other widgets
|
||||||
The widget is always active, but only shown when the timer is on.
|
The widget is always active, but only shown when the timer is on.
|
||||||
Hours, minutes, seconds and timer status can be set with an app.
|
Hours, minutes, seconds and timer status can be set with an app.
|
||||||
|
|
||||||
Depending on when you start the timer, it may alert up to 0,999 seconds early. This is because it checks only for full seconds. When there is less than one seconds left, it buzzes. This cannot be avoided without checking more than every second, which I would like to avoid.
|
When there is less than one seconds left on the timer it buzzes.
|
||||||
|
|
||||||
|
The widget has been tested on Bangle 1 and Bangle 2
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
|
|
||||||
TBD
|

|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
0.01: New App!
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
# Health Tracking
|
||||||
|
|
||||||
|
Logs health data to a file every 10 minutes, and provides an app to view it
|
||||||
|
|
||||||
|
**BETA - requires firmware 2v11**
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Once installed, health data is logged automatically.
|
||||||
|
|
||||||
|
To view data, run the `Health` app from your watch.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
Stores:
|
||||||
|
|
||||||
|
* Heart rate (TODO)
|
||||||
|
* Step count
|
||||||
|
* Movement
|
||||||
|
|
||||||
|
## Technical Info
|
||||||
|
|
||||||
|
Once installed, the `health.boot.js` hooks onto the `Bangle.health` event and
|
||||||
|
writes data to a binary file (one per month).
|
||||||
|
|
||||||
|
A library (that can be used with `require("health").readXYZ` can then be used
|
||||||
|
to grab historical health info.
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
* **Extend file format to include combined data for each day (to make graphs faster)**
|
||||||
|
* `interface` page for desktop to allow data to be viewed and exported in common formats
|
||||||
|
* More features in app:
|
||||||
|
* Step counting goal (ensure pedometers use this)
|
||||||
|
* Calendar view showing steps per day
|
||||||
|
* Yearly view
|
||||||
|
* Heart rate 'zone' graph
|
||||||
|
* .. other
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEw4UA///8H5AYM7/5L/ACsBqtQAgMFqtABYcVqtVAgIDBqgLDAwITBDYNVrQiEAANQEQNVtWAFIYfCE4Xq0AuEAAdX1W0BZFe1XUHQgADvWrJogAE9WtBYl66ouD2oLEtQGBFwQQBBYgeBFwYjFA4QuCBYgfCFwYLCL4IICFwacCPwetEwYLCR4QJBFwbFCU4QhBFwbMDNAYuCHQQwFFwowFFwowFFwwwEFwzNGFwjxFFwowEFw7aFBQwwDFwwwEFwwwEFw4wDBRAwBFxAwCFxAwCFxIA/AB4A="))
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
function menuMain() {
|
||||||
|
E.showMenu({
|
||||||
|
"":{title:"Health Tracking"},
|
||||||
|
"< Back":()=>load(),
|
||||||
|
"Step Counting":()=>menuStepCount(),
|
||||||
|
"Movement":()=>menuMovement()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function menuStepCount() {
|
||||||
|
E.showMenu({
|
||||||
|
"":{title:"Step Counting"},
|
||||||
|
"per hour":()=>stepsPerHour()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function menuMovement() {
|
||||||
|
E.showMenu({
|
||||||
|
"":{title:"Movement"},
|
||||||
|
"per hour":()=>movementPerHour()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function stepsPerHour() {
|
||||||
|
E.showMessage("Loading...");
|
||||||
|
var data = new Uint16Array(24);
|
||||||
|
require("health").readDay(new Date(), h=>data[h.hr]+=h.steps);
|
||||||
|
g.clear(1);
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
g.reset();
|
||||||
|
require("graph").drawBar(g, data, {
|
||||||
|
y:24,
|
||||||
|
miny: 0,
|
||||||
|
axes : true,
|
||||||
|
gridx : 6,
|
||||||
|
gridy : 500
|
||||||
|
});
|
||||||
|
Bangle.setUI("updown", ()=>menuStepCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
function movementPerHour() {
|
||||||
|
E.showMessage("Loading...");
|
||||||
|
var data = new Uint16Array(24);
|
||||||
|
require("health").readDay(new Date(), h=>data[h.hr]+=h.movement);
|
||||||
|
g.clear(1);
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
g.reset();
|
||||||
|
require("graph").drawLine(g, data, {
|
||||||
|
y:24,
|
||||||
|
miny: 0,
|
||||||
|
axes : true,
|
||||||
|
gridx : 6,
|
||||||
|
ylabel : null
|
||||||
|
});
|
||||||
|
Bangle.setUI("updown", ()=>menuStepCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
Bangle.loadWidgets();
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
menuMain();
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -0,0 +1,38 @@
|
||||||
|
Bangle.on("health", health => {
|
||||||
|
// ensure we write health info for *last* block
|
||||||
|
var d = new Date(Date.now() - 590000);
|
||||||
|
|
||||||
|
const DB_RECORD_LEN = 4;
|
||||||
|
const DB_RECORDS_PER_HR = 6;
|
||||||
|
const DB_RECORDS_PER_DAY = DB_RECORDS_PER_HR*24;
|
||||||
|
const DB_RECORDS_PER_MONTH = DB_RECORDS_PER_DAY*31;
|
||||||
|
const DB_HEADER_LEN = 8;
|
||||||
|
const DB_FILE_LEN = DB_HEADER_LEN + DB_RECORDS_PER_MONTH*DB_RECORD_LEN;
|
||||||
|
|
||||||
|
function getRecordFN(d) {
|
||||||
|
return "health-"+d.getFullYear()+"-"+d.getMonth()+".raw";
|
||||||
|
}
|
||||||
|
function getRecordIdx(d) {
|
||||||
|
return (DB_RECORDS_PER_DAY*(d.getDate()-1)) +
|
||||||
|
(DB_RECORDS_PER_HR*d.getHours()) +
|
||||||
|
(0|(d.getMinutes()*DB_RECORDS_PER_HR/60));
|
||||||
|
}
|
||||||
|
|
||||||
|
var rec = getRecordIdx(d);
|
||||||
|
var fn = getRecordFN(d);
|
||||||
|
var f = require("Storage").read(fn);
|
||||||
|
if (f) {
|
||||||
|
var dt = f.substr(DB_HEADER_LEN+(rec*DB_RECORD_LEN), DB_RECORD_LEN);
|
||||||
|
if (dt!="\xFF\xFF\xFF\xFF") {
|
||||||
|
print("HEALTH ERR: Already written!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
require("Storage").write(fn, "HEALTH1\0", 0, DB_FILE_LEN); // header
|
||||||
|
}
|
||||||
|
var recordData = String.fromCharCode(
|
||||||
|
health.steps>>8,health.steps&255, // 16 bit steps
|
||||||
|
health.bpm, // 8 bit bpm
|
||||||
|
Math.min(health.movement / 8, 255)); // movement
|
||||||
|
require("Storage").write(fn, recordData, DB_HEADER_LEN+(rec*DB_RECORD_LEN), DB_FILE_LEN);
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
const DB_RECORD_LEN = 4;
|
||||||
|
const DB_RECORDS_PER_HR = 6;
|
||||||
|
const DB_RECORDS_PER_DAY = DB_RECORDS_PER_HR*24;
|
||||||
|
const DB_RECORDS_PER_MONTH = DB_RECORDS_PER_DAY*31;
|
||||||
|
const DB_HEADER_LEN = 8;
|
||||||
|
const DB_FILE_LEN = DB_HEADER_LEN + DB_RECORDS_PER_MONTH*DB_RECORD_LEN;
|
||||||
|
|
||||||
|
function getRecordFN(d) {
|
||||||
|
return "health-"+d.getFullYear()+"-"+d.getMonth()+".raw";
|
||||||
|
}
|
||||||
|
function getRecordIdx(d) {
|
||||||
|
return (DB_RECORDS_PER_DAY*(d.getDate()-1)) +
|
||||||
|
(DB_RECORDS_PER_HR*d.getHours()) +
|
||||||
|
(0|(d.getMinutes()*DB_RECORDS_PER_HR/60));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read all records from the given month
|
||||||
|
exports.readAllRecords = function(d, cb) {
|
||||||
|
var rec = getRecordIdx(d);
|
||||||
|
var fn = getRecordFN(d);
|
||||||
|
var f = require("Storage").read(fn);
|
||||||
|
var idx = DB_HEADER_LEN;
|
||||||
|
for (var day=0;day<31;day++) {
|
||||||
|
for (var hr=0;hr<24;hr++) {
|
||||||
|
for (var m=0;m<DB_RECORDS_PER_HR;m++) {
|
||||||
|
var h = f.substr(idx, DB_RECORD_LEN);
|
||||||
|
if (h!="\xFF\xFF\xFF\xFF") {
|
||||||
|
cb({
|
||||||
|
day:day+1, hr : hr, min:m*10,
|
||||||
|
steps : (h.charCodeAt(0)<<8) | h.charCodeAt(1),
|
||||||
|
bpm : h.charCodeAt(2),
|
||||||
|
movement : h.charCodeAt(3)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
idx += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read all records from the given month
|
||||||
|
exports.readDay = function(d, cb) {
|
||||||
|
var rec = getRecordIdx(d);
|
||||||
|
var fn = getRecordFN(d);
|
||||||
|
var f = require("Storage").read(fn);
|
||||||
|
var idx = DB_HEADER_LEN + (DB_RECORD_LEN*DB_RECORDS_PER_DAY*(d.getDate()-1));
|
||||||
|
for (var hr=0;hr<24;hr++) {
|
||||||
|
for (var m=0;m<DB_RECORDS_PER_HR;m++) {
|
||||||
|
var h = f.substr(idx, DB_RECORD_LEN);
|
||||||
|
if (h!="\xFF\xFF\xFF\xFF") {
|
||||||
|
cb({
|
||||||
|
hr : hr, min:m*10,
|
||||||
|
steps : (h.charCodeAt(0)<<8) | h.charCodeAt(1),
|
||||||
|
bpm : h.charCodeAt(2),
|
||||||
|
movement : h.charCodeAt(3)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
idx += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
0.01: New App!
|
0.01: New App!
|
||||||
0.02: Fix occasional missed image when scrolling up
|
0.02: Fix occasional missed image when scrolling up
|
||||||
|
0.03: Text wrapping, better font
|
||||||
|
|
|
||||||
|
|
@ -14,17 +14,23 @@ var w = g.getWidth();
|
||||||
var h = g.getHeight();
|
var h = g.getHeight();
|
||||||
var n = Math.ceil((h-24)/APPH);
|
var n = Math.ceil((h-24)/APPH);
|
||||||
var menuScrollMax = APPH*apps.length - (h-24);
|
var menuScrollMax = APPH*apps.length - (h-24);
|
||||||
|
// FIXME: not needed after 2v11
|
||||||
|
var font = g.getFonts().includes("12x20") ? "12x20" : "6x8:2";
|
||||||
|
|
||||||
apps.forEach(app=>{
|
apps.forEach(app=>{
|
||||||
if (app.icon)
|
if (app.icon)
|
||||||
app.icon = s.read(app.icon); // should just be a link to a memory area
|
app.icon = s.read(app.icon); // should just be a link to a memory area
|
||||||
});
|
});
|
||||||
|
if (g.wrapString) { // FIXME: check not needed after 2v11
|
||||||
|
g.setFont(font);
|
||||||
|
apps.forEach(app=>app.name = g.wrapString(app.name, g.getWidth()-64).join("\n"));
|
||||||
|
}
|
||||||
|
|
||||||
function drawApp(i) {
|
function drawApp(i) {
|
||||||
var y = 24+i*APPH-menuScroll;
|
var y = 24+i*APPH-menuScroll;
|
||||||
var app = apps[i];
|
var app = apps[i];
|
||||||
if (!app || y<-APPH || y>=g.getHeight()) return;
|
if (!app || y<-APPH || y>=g.getHeight()) return;
|
||||||
g.setFont("6x8",2).setFontAlign(-1,0).drawString(app.name,64,y+32);
|
g.setFont(font).setFontAlign(-1,0).drawString(app.name,64,y+32);
|
||||||
if (app.icon) try {g.drawImage(app.icon,8,y+8);} catch(e){}
|
if (app.icon) try {g.drawImage(app.icon,8,y+8);} catch(e){}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
0.01: New App!
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 619 B |
|
|
@ -0,0 +1,121 @@
|
||||||
|
"";//not entirely sure why we need this - related to how bootupdate adds these to .boot0
|
||||||
|
E.showMenu = function(items) {
|
||||||
|
g.clear(1).flip(); // clear screen if no menu supplied
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
if (!items) {
|
||||||
|
Bangle.setUI();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var w = g.getWidth();
|
||||||
|
var h = g.getHeight();
|
||||||
|
var menuItems = Object.keys(items);
|
||||||
|
var options = items[""];
|
||||||
|
if (options) menuItems.splice(menuItems.indexOf(""),1);
|
||||||
|
if (!(options instanceof Object)) options = {};
|
||||||
|
options.fontHeight=14;
|
||||||
|
options.x=0;
|
||||||
|
options.x2=w-1;
|
||||||
|
options.y=24;
|
||||||
|
options.y2=h-12;
|
||||||
|
if (options.selected === undefined)
|
||||||
|
options.selected = 0;
|
||||||
|
var x = 0|options.x;
|
||||||
|
var x2 = options.x2||(g.getWidth()-1);
|
||||||
|
var y = 0|options.y;
|
||||||
|
var y2 = options.y2||(g.getHeight()-1);
|
||||||
|
if (options.title)
|
||||||
|
y += 15;
|
||||||
|
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);
|
||||||
|
g.setFontCustom(atob("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"), 32, atob("AwIGCAgICAMFBQYIAwYDBwcFBgYHBgYGBgYDAwYHBgcHBgYGBgYGBgYEBgYGBgYGBgYGBgYGBggGBgYEBwQGBwQGBgYGBgYHBgYGBgYGBgYGBgYGBgYGBgYGBgQCBAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAHCAYGBgAGBgYGAAYGBQYABgMGBgQABgYHBgAGBgYGBgYGBgYGBgYGBgYEBAYGBgYGBgYGAAYGBgYGBgYHBgYGBgYGBgYGBgYGBgYGBwcGBgYGBgYABgYGBgYGBg=="), 15);
|
||||||
|
|
||||||
|
if (rowmin===undefined && options.title)
|
||||||
|
g.drawString(options.title,(x+x2)/2,y-14).drawLine(x,y-2,x2,y-2).
|
||||||
|
setColor(g.theme.fg).setBgColor(g.theme.bg);
|
||||||
|
iy += 12;
|
||||||
|
g.setColor((idx>0)?g.theme.fg:g.theme.bg).fillPoly([72,iy,104,iy,88,iy-12]);
|
||||||
|
if (rowmin!==undefined) {
|
||||||
|
if (idx<rowmin) {
|
||||||
|
iy += options.fontHeight*(rowmin-idx);
|
||||||
|
idx=rowmin;
|
||||||
|
}
|
||||||
|
if (idx+rows>rowmax) {
|
||||||
|
rows = 1+rowmax-rowmin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var less = idx>0;
|
||||||
|
while (rows--) {
|
||||||
|
var name = menuItems[idx];
|
||||||
|
var item = items[name];
|
||||||
|
var hl = (idx==options.selected && !l.selectEdit);
|
||||||
|
g.setColor(hl ? g.theme.bgH : g.theme.bg);
|
||||||
|
g.fillRect(x,iy,x2,iy+options.fontHeight-1);
|
||||||
|
g.setColor(hl ? g.theme.fgH : g.theme.fg);
|
||||||
|
g.setFontAlign(-1,-1);
|
||||||
|
g.drawString(loc.translate(name),x+1,iy+1);
|
||||||
|
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.bgH).fillRect(xo-(g.stringWidth(v)+4),iy,x2,iy+options.fontHeight-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((idx<menuItems.length)?g.theme.fg:g.theme.bg).fillPoly([72,166,104,166,88,174]);
|
||||||
|
g.flip();
|
||||||
|
},
|
||||||
|
select : function(dir) {
|
||||||
|
var item = items[menuItems[options.selected]];
|
||||||
|
if ("function" == typeof item) item(l);
|
||||||
|
else if ("object" == typeof item) {
|
||||||
|
// if a number, go into 'edit mode'
|
||||||
|
if ("number" == typeof item.value)
|
||||||
|
l.selectEdit = l.selectEdit?undefined:item;
|
||||||
|
else { // else just toggle bools
|
||||||
|
if ("boolean" == typeof item.value) item.value=!item.value;
|
||||||
|
if (item.onchange) item.onchange(item.value);
|
||||||
|
}
|
||||||
|
l.draw();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
move : function(dir) {
|
||||||
|
if (l.selectEdit) {
|
||||||
|
var item = l.selectEdit;
|
||||||
|
item.value -= (dir||1)*(item.step||1);
|
||||||
|
if (item.min!==undefined && item.value<item.min) item.value = item.min;
|
||||||
|
if (item.max!==undefined && item.value>item.max) item.value = item.max;
|
||||||
|
if (item.onchange) item.onchange(item.value);
|
||||||
|
l.draw(options.selected,options.selected);
|
||||||
|
} else {
|
||||||
|
var a=options.selected;
|
||||||
|
options.selected = (dir+options.selected)%menuItems.length;
|
||||||
|
if (options.selected<0) options.selected += menuItems.length;
|
||||||
|
l.draw(Math.min(a,options.selected), Math.max(a,options.selected));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
l.draw();
|
||||||
|
Bangle.setUI("updown",dir => {
|
||||||
|
if (dir) l.move(dir);
|
||||||
|
else l.select();
|
||||||
|
});
|
||||||
|
return l;
|
||||||
|
};
|
||||||
|
|
@ -8,6 +8,7 @@ function redraw() {
|
||||||
m.draw();
|
m.draw();
|
||||||
drawMarker();
|
drawMarker();
|
||||||
if (WIDGETS["gpsrec"] && WIDGETS["gpsrec"].plotTrack) {
|
if (WIDGETS["gpsrec"] && WIDGETS["gpsrec"].plotTrack) {
|
||||||
|
g.flip(); // force immediate draw on double-buffered screens - track will update later
|
||||||
g.setColor(0.75,0.2,0);
|
g.setColor(0.75,0.2,0);
|
||||||
WIDGETS["gpsrec"].plotTrack(m);
|
WIDGETS["gpsrec"].plotTrack(m);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
0.01: First release
|
0.01: First release
|
||||||
0.02: Display 12 hour clock as 12:xx not 00:xx when just into PM
|
0.02: Display 12 hour clock as 12:xx not 00:xx when just into PM
|
||||||
0.03: Make it work with Gadgetbridge, Notifications fullscreen on a Bangle 2
|
0.03: Make it work with Gadgetbridge, Notifications fullscreen on a Bangle 2
|
||||||
|
0.04: Leave space at the bottom for Chrono widget, set back option at first option
|
||||||
|
|
|
||||||
|
|
@ -87,19 +87,19 @@ function draw() {
|
||||||
// avoid flicker on a bangle 1 by comparing with previous minute
|
// avoid flicker on a bangle 1 by comparing with previous minute
|
||||||
if (mm_prev != mm) {
|
if (mm_prev != mm) {
|
||||||
mm_prev = mm;
|
mm_prev = mm;
|
||||||
g.clearRect(0, 30, w, h);
|
g.clearRect(0, 30, w, h - 24);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// on a b2 safe to just clear anyway as there is no flicker
|
// on a b2 safe to just clear anyway as there is no flicker
|
||||||
g.clearRect(0, 30, w, h);
|
g.clearRect(0, 30, w, h - 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw a grid like graph paper
|
// draw a grid like graph paper
|
||||||
if (settings.grid && process.env.HWVERSION !=1) {
|
if (settings.grid && process.env.HWVERSION !=1) {
|
||||||
g.setColor("#0f0");
|
g.setColor("#0f0");
|
||||||
for (var gx=20; gx <= w; gx += 20)
|
for (var gx=20; gx <= w; gx += 20)
|
||||||
g.drawLine(gx, 30, gx, h);
|
g.drawLine(gx, 30, gx, h - 24);
|
||||||
for (var gy=30; gy <= h; gy += 20)
|
for (var gy=30; gy <= h - 24; gy += 20)
|
||||||
g.drawLine(0, gy, w, gy);
|
g.drawLine(0, gy, w, gy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
E.showMenu({
|
E.showMenu({
|
||||||
'': { 'title': 'Pastel Clock' },
|
'': { 'title': 'Pastel Clock' },
|
||||||
|
'< Back': back,
|
||||||
'Font': {
|
'Font': {
|
||||||
value: 0 | font_options.indexOf(s.font),
|
value: 0 | font_options.indexOf(s.font),
|
||||||
min: 0, max: 4,
|
min: 0, max: 4,
|
||||||
|
|
@ -50,7 +51,6 @@
|
||||||
s.date = !s.date
|
s.date = !s.date
|
||||||
save()
|
save()
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
'< Back': back,
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -3,3 +3,4 @@
|
||||||
0.03: Use offscreen buffer (not doublebuffer)
|
0.03: Use offscreen buffer (not doublebuffer)
|
||||||
Use 'locale' to get internationalised speed
|
Use 'locale' to get internationalised speed
|
||||||
0.04: Start GPS after loading app, just in case widgets affect it (#449)
|
0.04: Start GPS after loading app, just in case widgets affect it (#449)
|
||||||
|
0.05: Use Layout lib for Bangle.js 2 compatibility
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,61 @@
|
||||||
var buf = Graphics.createArrayBuffer(240,120,1,{msb:true});
|
var Layout = require("Layout");
|
||||||
var lastFix = {fix:0,satellites:0};
|
var layout;
|
||||||
|
|
||||||
|
var lastFix = {fix:-1,satellites:0};
|
||||||
|
|
||||||
|
function speedoImage() {
|
||||||
|
return require("heatshrink").decompress(atob("kkdxH+ABteAAwWOECImZDQ2CAQglUD4us2fX68ymQDB1omFESWtDgIACEYYACrolPBwddmWIEZWsmVWJYgiLwXX2YcB1gdDq+BAodWGIWsEhQiDRAWBmQdEAAhGBroFC1ojMC4etERIlDAggkHNIgAWSYYjFVwNWGwgAP5KkBEYoFC1ihBagwAL5W72vKJAxpExCiDABnQ4W12vD6AHBEYxnT4YhB3ghCSIhqDe4SIP3giBM4LfFEYpiMDoQhC3fDCA7+DfBwiCAARmFAAmtEYlYagMywISHEQhEId4UyEYleqwABEZBHERQwABroZBq5rR6BGLNZKzMAAPKRZKzJr2tfaAAKxD7CfgRsD1g1GAAwME2YGDwQjFNgOzwMyCwuCwIAEBg0yHoKODEYmCcYNWCwutAAuzBgg4BCwJGEEgj7JV5r7BIwgjEWrDVCEQYkCWgYAWNYIjF/z8awQfD"));
|
||||||
|
}
|
||||||
|
|
||||||
function onGPS(fix) {
|
function onGPS(fix) {
|
||||||
|
if (lastFix.fix != fix.fix) {
|
||||||
|
// if fix is different, change the layout
|
||||||
|
if (fix.fix) {
|
||||||
|
layout = new Layout( {
|
||||||
|
type:"v", c: [
|
||||||
|
{type:"txt", font:"6x8:2", label:"Speed" },
|
||||||
|
{type:"h", c: [
|
||||||
|
{type:"img", src:speedoImage, pad:4 },
|
||||||
|
{type:"txt", font:"35%", label:"--", fillx:true, id:"speed" },
|
||||||
|
]},
|
||||||
|
{type:"txt", font:"6x8", label:"--", id:"units" },
|
||||||
|
{type:"h", c: [
|
||||||
|
{type:"txt", font:"10%", label:fix.satellites, pad:2, id:"sat" },
|
||||||
|
{type:"txt", font:"6x8", pad:3, label:"Satellites" }
|
||||||
|
]},
|
||||||
|
]},[],{lazy:true});
|
||||||
|
} else {
|
||||||
|
layout = new Layout( {
|
||||||
|
type:"v", c: [
|
||||||
|
{type:"txt", font:"6x8:2", label:"Speed" },
|
||||||
|
{type:"img", src:speedoImage, pad:4 },
|
||||||
|
{type:"txt", font:"6x8", label:"Waiting for GPS" },
|
||||||
|
{type:"h", c: [
|
||||||
|
{type:"txt", font:"10%", label:fix.satellites, pad:2, id:"sat" },
|
||||||
|
{type:"txt", font:"6x8", pad:3, label:"Satellites" }
|
||||||
|
]},
|
||||||
|
]},[],{lazy:true});
|
||||||
|
}
|
||||||
|
g.clearRect(0,24,g.getWidth(),g.getHeight());
|
||||||
|
layout.render();
|
||||||
|
}
|
||||||
lastFix = fix;
|
lastFix = fix;
|
||||||
buf.clear();
|
|
||||||
buf.setFontAlign(0,0);
|
if (fix.fix && isFinite(fix.speed)) {
|
||||||
buf.setFont("6x8");
|
|
||||||
buf.drawString(fix.satellites+" satellites",120,6);
|
|
||||||
if (fix.fix) {
|
|
||||||
var speed = require("locale").speed(fix.speed);
|
var speed = require("locale").speed(fix.speed);
|
||||||
var m = speed.match(/([0-9,\.]+)(.*)/); // regex splits numbers from units
|
var m = speed.match(/([0-9,\.]+)(.*)/); // regex splits numbers from units
|
||||||
var txt = (fix.speed<20) ? fix.speed.toFixed(1) : Math.round(fix.speed);
|
var txt = (fix.speed<20) ? fix.speed.toFixed(1) : Math.round(fix.speed);
|
||||||
var value = m[1], units = m[2];
|
layout.speed.label = m[1];
|
||||||
var s = 80;
|
layout.units.label = m[2];
|
||||||
buf.setFontVector(s);
|
|
||||||
buf.drawString(value,120,10+s/2);
|
|
||||||
buf.setFont("6x8",2);
|
|
||||||
buf.drawString(units,120,s+26);
|
|
||||||
} else {
|
|
||||||
buf.setFont("6x8",2);
|
|
||||||
buf.drawString("Waiting for GPS",120,56);
|
|
||||||
}
|
}
|
||||||
g.reset();
|
layout.sat.label = fix.satellites;
|
||||||
g.drawImage({width:buf.getWidth(),height:buf.getHeight(),bpp:1,buffer:buf.buffer},0,70);
|
layout.render();
|
||||||
g.flip();
|
|
||||||
}
|
}
|
||||||
g.clear();
|
g.clear();
|
||||||
onGPS(lastFix);
|
onGPS({fix:0,satellites:0});
|
||||||
|
// onGPS({fix:1,satellites:3,speed:200}); // testing
|
||||||
Bangle.loadWidgets();
|
Bangle.loadWidgets();
|
||||||
Bangle.drawWidgets();
|
Bangle.drawWidgets();
|
||||||
|
|
||||||
Bangle.on('GPS', onGPS);
|
Bangle.on('GPS', onGPS);
|
||||||
Bangle.setGPSPower(1);
|
Bangle.setGPSPower(1, "app");
|
||||||
|
|
|
||||||
|
|
@ -9,3 +9,4 @@
|
||||||
0.10: Add 'hide if charge greater than'
|
0.10: Add 'hide if charge greater than'
|
||||||
0.11: Don't overwrite existing settings on app update
|
0.11: Don't overwrite existing settings on app update
|
||||||
0.12: Fixed for Bangle 2
|
0.12: Fixed for Bangle 2
|
||||||
|
0.13: Fillbar setting added, see README
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,13 @@ Show the current battery level and charging status in the top right of the clock
|
||||||
|
|
||||||
Works with Bangle 1 and Bangle 2
|
Works with Bangle 1 and Bangle 2
|
||||||
|
|
||||||

|
When the fillbar setting is on the level colour will fill the entire
|
||||||
|
bar. This makes for an easier to read dsiplay when the charge is
|
||||||
|
below 50%.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
When the fillbar setting is off the level colour will follow the battry percentage
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB |
|
|
@ -10,6 +10,7 @@
|
||||||
let s = {
|
let s = {
|
||||||
'color': COLORS[0],
|
'color': COLORS[0],
|
||||||
'percentage': true,
|
'percentage': true,
|
||||||
|
'fillbar': false,
|
||||||
'charger': true,
|
'charger': true,
|
||||||
'hideifmorethan': 100,
|
'hideifmorethan': 100,
|
||||||
}
|
}
|
||||||
|
|
@ -54,6 +55,11 @@
|
||||||
save('color')(s.color)
|
save('color')(s.color)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'Fill Bar': {
|
||||||
|
value: s.fillbar,
|
||||||
|
format: onOffFormat,
|
||||||
|
onchange: save('fillbar'),
|
||||||
|
},
|
||||||
'Hide if >': {
|
'Hide if >': {
|
||||||
value: s.hideifmorethan||100,
|
value: s.hideifmorethan||100,
|
||||||
min: 10,
|
min: 10,
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 3.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
|
|
@ -80,7 +80,12 @@
|
||||||
var s = 39;
|
var s = 39;
|
||||||
var x = this.x, y = this.y;
|
var x = this.x, y = this.y;
|
||||||
const l = E.getBattery();
|
const l = E.getBattery();
|
||||||
const xl = x+4+l*(s-12)/100
|
let xl = x+4+l*(s-12)/100;
|
||||||
|
|
||||||
|
// show bar full in the level color, as you cant see the color if the bar is too small
|
||||||
|
if (setting('fillbar'))
|
||||||
|
xl = x+4+100*(s-12)/100;
|
||||||
|
|
||||||
c = levelColor(l);
|
c = levelColor(l);
|
||||||
|
|
||||||
if (Bangle.isCharging() && setting('charger')) {
|
if (Bangle.isCharging() && setting('charger')) {
|
||||||
|
|
|
||||||
|
|
@ -40,10 +40,6 @@
|
||||||
<p id="requireHTTPS" class="hidden">
|
<p id="requireHTTPS" class="hidden">
|
||||||
<b>STOP!</b> This page <b>must</b> be served over HTTPS. Please <a>reload this page via HTTPS</a>.
|
<b>STOP!</b> This page <b>must</b> be served over HTTPS. Please <a>reload this page via HTTPS</a>.
|
||||||
</p>
|
</p>
|
||||||
<div class="toast toast-success flex-centered" id="bangle2ks">
|
|
||||||
<img src="data:image/png;base64,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" />
|
|
||||||
Bangle.js 2 is now on KickStarter! <a href="https://www.kickstarter.com/projects/gfw/banglejs-2-the-open-smart-watch" target="_blank">Check it out here</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue