Merge branch 'espruino:master' into master
|
@ -14,5 +14,6 @@
|
||||||
{"name":"90sclk.app.js","url":"app.js"},
|
{"name":"90sclk.app.js","url":"app.js"},
|
||||||
{"name":"90sclk.img","url":"app-icon.js","evaluate":true},
|
{"name":"90sclk.img","url":"app-icon.js","evaluate":true},
|
||||||
{"name":"90sclk.settings.js","url":"settings.js"}
|
{"name":"90sclk.settings.js","url":"settings.js"}
|
||||||
]
|
],
|
||||||
|
"data": [{"name":"90sclk.setting.json"}]
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,5 +14,6 @@
|
||||||
{"name":"activepedom.settings.js","url":"settings.js"},
|
{"name":"activepedom.settings.js","url":"settings.js"},
|
||||||
{"name":"activepedom.img","url":"app-icon.js","evaluate":true},
|
{"name":"activepedom.img","url":"app-icon.js","evaluate":true},
|
||||||
{"name":"activepedom.app.js","url":"app.js"}
|
{"name":"activepedom.app.js","url":"app.js"}
|
||||||
]
|
],
|
||||||
|
"data":[{"name":"activepedom.settings.json"}]
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,3 +13,4 @@
|
||||||
Added dynamic, short and range fields to clkinfo
|
Added dynamic, short and range fields to clkinfo
|
||||||
0.12: Added color field and updating clkinfo periodically (running events)
|
0.12: Added color field and updating clkinfo periodically (running events)
|
||||||
0.13: Show day of the week in date
|
0.13: Show day of the week in date
|
||||||
|
0.14: Fixed "Today" and "Yesterday" wrongly displayed for allDay events on some time zones
|
||||||
|
|
|
@ -38,13 +38,12 @@ function formatDay(date) {
|
||||||
if (!settings.useToday) {
|
if (!settings.useToday) {
|
||||||
return formattedDate;
|
return formattedDate;
|
||||||
}
|
}
|
||||||
const dateformatted = date.toISOString().split('T')[0]; // yyyy-mm-dd
|
const today = new Date(Date.now());
|
||||||
const today = new Date(Date.now()).toISOString().split('T')[0]; // yyyy-mm-dd
|
if (date.getDay() == today.getDay() && date.getMonth() == today.getMonth())
|
||||||
if (dateformatted == today) {
|
|
||||||
return /*LANG*/"Today ";
|
return /*LANG*/"Today ";
|
||||||
} else {
|
else {
|
||||||
const tomorrow = new Date(Date.now() + 86400 * 1000).toISOString().split('T')[0]; // yyyy-mm-dd
|
const tomorrow = new Date(Date.now() + 86400 * 1000);
|
||||||
if (dateformatted == tomorrow) {
|
if (date.getDay() == tomorrow.getDay() && date.getMonth() == tomorrow.getMonth()) {
|
||||||
return /*LANG*/"Tomorrow ";
|
return /*LANG*/"Tomorrow ";
|
||||||
}
|
}
|
||||||
return formattedDate;
|
return formattedDate;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "agenda",
|
"id": "agenda",
|
||||||
"name": "Agenda",
|
"name": "Agenda",
|
||||||
"version": "0.13",
|
"version": "0.14",
|
||||||
"description": "Simple agenda",
|
"description": "Simple agenda",
|
||||||
"icon": "agenda.png",
|
"icon": "agenda.png",
|
||||||
"screenshots": [{"url":"screenshot_agenda_overview.png"}, {"url":"screenshot_agenda_event1.png"}, {"url":"screenshot_agenda_event2.png"}],
|
"screenshots": [{"url":"screenshot_agenda_overview.png"}, {"url":"screenshot_agenda_event1.png"}, {"url":"screenshot_agenda_event2.png"}],
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
0.01: first release
|
|
@ -0,0 +1,4 @@
|
||||||
|
# Half-Life Alyx Style clock
|
||||||
|
|
||||||
|

|
||||||
|
|
|
@ -0,0 +1,174 @@
|
||||||
|
const icoH = [
|
||||||
|
[0,1,1,0,0,1,1,0],
|
||||||
|
[1,1,1,1,1,1,1,1],
|
||||||
|
[1,1,1,1,1,1,1,1],
|
||||||
|
[1,1,1,1,1,1,1,1],
|
||||||
|
[0,1,1,1,1,1,1,0],
|
||||||
|
[0,0,1,1,1,1,0,0],
|
||||||
|
[0,0,0,1,1,0,0,0],
|
||||||
|
[0,0,0,0,0,0,0,0],
|
||||||
|
]
|
||||||
|
|
||||||
|
const icoR = [
|
||||||
|
[0,0,0,0,1,1,1,1,0,0,0,0],
|
||||||
|
[0,0,1,1,0,0,0,0,1,1,0,0],
|
||||||
|
[0,1,1,1,1,0,0,1,1,0,1,0],
|
||||||
|
[0,1,1,0,0,0,0,0,0,0,1,0],
|
||||||
|
[1,1,1,1,1,1,1,1,0,0,0,1],
|
||||||
|
[1,1,0,0,1,0,0,0,0,0,0,1],
|
||||||
|
[1,1,1,1,1,1,1,0,1,1,0,1],
|
||||||
|
[1,1,1,1,1,1,0,0,0,0,1,1],
|
||||||
|
[0,1,1,1,1,1,1,1,1,1,1,0],
|
||||||
|
[0,1,1,1,1,1,1,1,1,1,1,0],
|
||||||
|
[0,0,1,1,1,1,1,1,1,1,0,0],
|
||||||
|
[0,0,0,0,1,1,1,1,0,0,0,0],
|
||||||
|
]
|
||||||
|
|
||||||
|
let idTimeout = null;
|
||||||
|
|
||||||
|
function icon (icon, x, y, size, gap) {
|
||||||
|
const color = g.getColor();
|
||||||
|
for (let r=0; r<icon.length; r++) {
|
||||||
|
for (let c=0; c<icon[r].length; c++) {
|
||||||
|
if (icon[r][c]===1){
|
||||||
|
g.setColor(color);
|
||||||
|
g.fillRect(c * size + x, r * size + y, (c+1) * size - gap + x, (r+1)*size - gap + y);
|
||||||
|
g.setColor('#fff');
|
||||||
|
g.drawLine(c * size + x + size/2 - 1, r * size + y + size/2 - 1, c * size + x + size/2 - 1, r * size + y + size/2 - 1, )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.setColor(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ohmA(x, y) {
|
||||||
|
g.setColor('#666');
|
||||||
|
g.fillRect(x, y, x+8, y+15);
|
||||||
|
g.setColor('#00f');
|
||||||
|
g.drawLine(x, y + 4, x + 8, y + 4);
|
||||||
|
g.setColor('#f00');
|
||||||
|
g.drawLine(x, y + 6, x + 8, y + 6);
|
||||||
|
g.setColor('#0f0');
|
||||||
|
g.drawLine(x, y + 8, x + 8, y + 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ohmB(x, y) {
|
||||||
|
g.setColor('#666');
|
||||||
|
g.fillRect(x, y, x+15, y+8);
|
||||||
|
g.setColor('#00f');
|
||||||
|
g.drawLine(x + 4, y + 8, x + 4, y);
|
||||||
|
g.setColor('#f00');
|
||||||
|
g.drawLine(x + 6, y + 8, x + 6, y);
|
||||||
|
g.setColor('#0f0');
|
||||||
|
g.drawLine(x + 8, y + 8, x + 8, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
function heart (x, y) {
|
||||||
|
g.setColor('#000');
|
||||||
|
g.fillRect(x-2, y-2, x + 32, y + 32)
|
||||||
|
g.setColor('#666');
|
||||||
|
g.drawRect(x-2, y-2, x + 32, y + 32)
|
||||||
|
g.setColor('#f00');
|
||||||
|
icon(icoH, x, y, 4, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resin() {
|
||||||
|
let d = Date();
|
||||||
|
let h = d.getHours();
|
||||||
|
let m = d.getMinutes();
|
||||||
|
|
||||||
|
const resinPosX = 25;
|
||||||
|
const resinPosY = 130;
|
||||||
|
g.setColor('#000');
|
||||||
|
g.fillRect(resinPosX - 3, resinPosY - 3, Bangle.appRect.w - resinPosX + 2, resinPosY + 40);
|
||||||
|
g.setColor('#666');
|
||||||
|
g.drawRect(resinPosX - 3, resinPosY - 3, Bangle.appRect.w - resinPosX + 2, resinPosY + 40);
|
||||||
|
g.setColor('#6ff');
|
||||||
|
icon(icoR, resinPosX, resinPosY, 3, 1);
|
||||||
|
g.setFont('6x8', 5);
|
||||||
|
g.setFontAlign(-1, -1);
|
||||||
|
g.drawString('_' + (m<10?'0':'')+m, resinPosX + 40, resinPosY - 5);
|
||||||
|
|
||||||
|
g.setFontAlign(1, -1);
|
||||||
|
g.setFont('6x8', 2);
|
||||||
|
g.drawString(h, resinPosX + 66, resinPosY);
|
||||||
|
}
|
||||||
|
|
||||||
|
function screw(x, y) {
|
||||||
|
g.setColor('#666').fillCircle(x, y, 4).setColor('#000').drawLine(x - 4, y, x + 4, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
function led(x,y) {
|
||||||
|
g.setColor('#0f0').fillCircle(x, y, 8).setColor('#fff').fillCircle(x-3, y-3, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function drawTime() {
|
||||||
|
const R = Bangle.appRect;
|
||||||
|
g.setBgColor('#000');
|
||||||
|
g.clear();
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
g.reset();
|
||||||
|
|
||||||
|
// pcb
|
||||||
|
g.setColor('#030').fillRect(R.x, R.y, R.x2, R.y2);
|
||||||
|
screw(R.x + 8, R.y + 8)
|
||||||
|
screw(R.x2 - 8, R.y + 8)
|
||||||
|
screw(R.x + 8, R.y2 - 8)
|
||||||
|
screw(R.x2 - 8, R.y2 - 8)
|
||||||
|
for(let i=0; i<6; i++) {
|
||||||
|
g.setColor('#fff');
|
||||||
|
g.drawLine(24 + i * 9, 70, 24 + i * 9, 110);
|
||||||
|
g.drawLine(24 + i * 9, 110, 54 + i * 9, 140);
|
||||||
|
}
|
||||||
|
ohmA(29, 90);
|
||||||
|
ohmA(56, 90);
|
||||||
|
ohmB(80, 90);
|
||||||
|
screw(90, 110)
|
||||||
|
// led
|
||||||
|
led(50, R.y+10);
|
||||||
|
led(70, R.y+10);
|
||||||
|
ohmB(20, R.y + 10);
|
||||||
|
ohmB(90, R.y + 2);
|
||||||
|
ohmB(90, R.y + 14);
|
||||||
|
|
||||||
|
heart(10, 52);
|
||||||
|
heart(50, 52);
|
||||||
|
heart(90, 52);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
g.setColor('#666');
|
||||||
|
for (let i=0; i<6; i++) {
|
||||||
|
g.fillCircle(110 + i*10, 80+10, 3);
|
||||||
|
g.fillCircle(110 + i*10, 110+10, 3);
|
||||||
|
}
|
||||||
|
g.setColor('#000');
|
||||||
|
g.fillRect(110, 80+10, 170, 110+10);
|
||||||
|
g.setColor('#666');
|
||||||
|
g.drawRect(110, 80+10, 170, 110+10);
|
||||||
|
g.setFont('6x8').setColor('#666').drawString('AH-118080\n0WT 18-001', 112, 85+10);
|
||||||
|
|
||||||
|
|
||||||
|
resin();
|
||||||
|
|
||||||
|
let d = Date();
|
||||||
|
let t = d.getSeconds()*1000 + d.getMilliseconds();
|
||||||
|
idTimeout = setTimeout(drawTime, 60000 - t); // time till next minute
|
||||||
|
}
|
||||||
|
|
||||||
|
// special function to handle display switch on
|
||||||
|
Bangle.on('lcdPower', function(on){
|
||||||
|
if (on) {
|
||||||
|
drawTime();
|
||||||
|
} else {
|
||||||
|
if(idTimeout) {
|
||||||
|
clearTimeout(idTimeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Show launcher when button pressed
|
||||||
|
Bangle.setUI("clock");
|
||||||
|
Bangle.loadWidgets();
|
||||||
|
drawTime();
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwwkAqoA/AHlUmYADC69FC601C600C60yC6x4SAANTPCgyFkowTSCgACkZ4TAAVDPCwvCPCaqEPCSnDPCZeDmc0Uyh4TqQXFPCBGEPCQWFPCClEPCSlDmjZDdiUlMYZ4NIwg0EPBpGEDoh4NIIYpCPCDqGMoUydh4oDPB5GGPCBGGG4h4CGQ6HDN4gIEqkjSY4+DBYreDSZINDHYpoDKYw9FTww5DC5BGJPAg8MQQw6DBpBGJWIsyCwtUkQABZhA7CkjYKfJIsGAB9UCqgA/ACQ"))
|
After Width: | Height: | Size: 854 B |
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"id": "alyxclock",
|
||||||
|
"name": "Alyx Clock",
|
||||||
|
"version": "0.01",
|
||||||
|
"description": "A clock in the style of half-life alyx gravity gloves",
|
||||||
|
"icon": "alyxclock.png",
|
||||||
|
"screenshots": [{"url":"screenshot_alyxclock.png"}],
|
||||||
|
"type": "clock",
|
||||||
|
"tags": "clock",
|
||||||
|
"supports": ["BANGLEJS2"],
|
||||||
|
"readme": "README.md",
|
||||||
|
"allow_emulator": true,
|
||||||
|
"storage": [
|
||||||
|
{"name":"alyxclock.app.js","url":"alyxclock.app.js"},
|
||||||
|
{"name":"alyxclock.img","url":"alyxclock.icon.js","evaluate":true}
|
||||||
|
]
|
||||||
|
}
|
After Width: | Height: | Size: 3.5 KiB |
|
@ -26,3 +26,5 @@
|
||||||
0.25: Added option to 'ignore' an app from the message
|
0.25: Added option to 'ignore' an app from the message
|
||||||
0.26: Change handling of GPS status to depend on GPS events instead of connection events
|
0.26: Change handling of GPS status to depend on GPS events instead of connection events
|
||||||
0.27: Issue newline before GB commands (solves issue with console.log and ignored commands)
|
0.27: Issue newline before GB commands (solves issue with console.log and ignored commands)
|
||||||
|
0.28: Navigation messages no longer launch the Maps view unless they're new
|
||||||
|
0.29: Support for http request xpath return format
|
|
@ -203,6 +203,8 @@
|
||||||
event.t="add";
|
event.t="add";
|
||||||
event.src="maps"; // for the icon
|
event.src="maps"; // for the icon
|
||||||
event.title="Navigation";
|
event.title="Navigation";
|
||||||
|
if (require("messages").getMessages().find(m=>m.id=="nav"))
|
||||||
|
event.t = "modify";
|
||||||
} else {
|
} else {
|
||||||
event.t="remove";
|
event.t="remove";
|
||||||
}
|
}
|
||||||
|
@ -229,6 +231,7 @@
|
||||||
//send the request
|
//send the request
|
||||||
var req = {t: "http", url:url, id:options.id};
|
var req = {t: "http", url:url, id:options.id};
|
||||||
if (options.xpath) req.xpath = options.xpath;
|
if (options.xpath) req.xpath = options.xpath;
|
||||||
|
if (options.return) req.return = options.return; // for xpath
|
||||||
if (options.method) req.method = options.method;
|
if (options.method) req.method = options.method;
|
||||||
if (options.body) req.body = options.body;
|
if (options.body) req.body = options.body;
|
||||||
if (options.headers) req.headers = options.headers;
|
if (options.headers) req.headers = options.headers;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "android",
|
"id": "android",
|
||||||
"name": "Android Integration",
|
"name": "Android Integration",
|
||||||
"shortName": "Android",
|
"shortName": "Android",
|
||||||
"version": "0.27",
|
"version": "0.29",
|
||||||
"description": "Display notifications/music/etc sent from the Gadgetbridge app on Android. This replaces the old 'Gadgetbridge' Bangle.js widget.",
|
"description": "Display notifications/music/etc sent from the Gadgetbridge app on Android. This replaces the old 'Gadgetbridge' Bangle.js widget.",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"tags": "tool,system,messages,notifications,gadgetbridge",
|
"tags": "tool,system,messages,notifications,gadgetbridge",
|
||||||
|
|
|
@ -1,2 +1,5 @@
|
||||||
0.01: New App!
|
0.01: New App!
|
||||||
0.02: New config options such as step, meridian, short/long formats, custom prefix/suffix
|
0.02: New config options such as step, meridian, short/long formats, custom prefix/suffix
|
||||||
|
0.03: Allows showing the month in short or long format by setting `"shortMonth"` to true or false
|
||||||
|
0.04: Improves touchscreen drag handling for background apps such as Pattern Launcher
|
||||||
|
0.05: Fixes step count not resetting after a new day starts
|
||||||
|
|
|
@ -18,7 +18,7 @@ Each box can be customized extensively via a simple JSON configuration. You can
|
||||||
|
|
||||||
## Config File Structure
|
## Config File Structure
|
||||||
|
|
||||||
Here's what an example configuration might look like:
|
Here's an example of what a configuration might contain:
|
||||||
|
|
||||||
```
|
```
|
||||||
{
|
{
|
||||||
|
@ -37,8 +37,9 @@ Here's what an example configuration might look like:
|
||||||
"boxPos": { "x": 0.5, "y": 0.5 },
|
"boxPos": { "x": 0.5, "y": 0.5 },
|
||||||
"prefix": "", // Adds a string to the beginning of the main string
|
"prefix": "", // Adds a string to the beginning of the main string
|
||||||
"suffix": "", // Adds a string to the end of the main string
|
"suffix": "", // Adds a string to the end of the main string
|
||||||
"disableSuffix": true, // Only used to remove the DayOfMonth suffix
|
"disableSuffix": true, // Use to remove DayOfMonth suffix only
|
||||||
"short": false // Gets long format value of time, meridian, date, or DoW
|
"short": false, // Use long format of time, meridian, date, or DoW
|
||||||
|
"shortMonth": false // Use long format of month within date
|
||||||
|
|
||||||
},
|
},
|
||||||
"bg": { // Can also be removed for no background
|
"bg": { // Can also be removed for no background
|
||||||
|
@ -51,9 +52,9 @@ __Breakdown of Parameters:__
|
||||||
|
|
||||||
* **Box Name:** The name of your text box. Box Clock includes functional support for "time", "date", "meridian" (AM/PM), "dow" (Day of Week), "batt" (Battery), and "step" (Step count). You can add additional custom boxes with unique titles.
|
* **Box Name:** The name of your text box. Box Clock includes functional support for "time", "date", "meridian" (AM/PM), "dow" (Day of Week), "batt" (Battery), and "step" (Step count). You can add additional custom boxes with unique titles.
|
||||||
|
|
||||||
* **string:** The text string to be displayed inside the box.
|
* **string:** The text string to be displayed inside the box. This is only required for custom Box Names.
|
||||||
|
|
||||||
* **font:** The font name given to g.setFont()
|
* **font:** The font name given to g.setFont().
|
||||||
|
|
||||||
* **fontSize:** The size of the font.
|
* **fontSize:** The size of the font.
|
||||||
|
|
||||||
|
@ -75,17 +76,34 @@ __Breakdown of Parameters:__
|
||||||
|
|
||||||
* **suffix:** Adds a string to the end of the main string. For example, you can set "suffix": "%" to display "80%" for the battery percentage.
|
* **suffix:** Adds a string to the end of the main string. For example, you can set "suffix": "%" to display "80%" for the battery percentage.
|
||||||
|
|
||||||
* **disableSuffix:** Applies only to the "date" box. Set to true to disable the DayOfMonth suffix. This is used to remove the "st","nd","rd", or "th" from the DayOfMonth number
|
* **disableSuffix:** Applies only to the "date" box. Set to true to disable the DayOfMonth suffix. This is used to remove the "st","nd","rd", or "th" from the DayOfMonth number.
|
||||||
|
|
||||||
* **short:** Set to false to get the long format value of time, meridian, date, or DayOfWeek. Short formats are used by default,
|
* **short:** Set to false to get the long format value of time, meridian, date, or DayOfWeek. Short formats are used by default if not specified.
|
||||||
|
|
||||||
|
* **shortMonth:** Applies only to the "date" box. Set to false to get the long format value of the month. Short format is used by default if not specified.
|
||||||
|
|
||||||
* **bg:** This specifies a custom background image, with the img property defining the name of the image file on the Bangle.js storage.
|
* **bg:** This specifies a custom background image, with the img property defining the name of the image file on the Bangle.js storage.
|
||||||
|
|
||||||
## Multiple Configurations
|
## Multiple Configurations
|
||||||
|
|
||||||
The app includes a settings menu that allows you to switch between different configurations. The selected configuration is stored in the default JSON file alongside the other configuration data using the selectedConfig property.
|
__Settings Menu:__
|
||||||
|
|
||||||
If the selectedConfig property is not present or is set to 0, the app will use the default configuration. To create additional configurations, create separate JSON files with the naming convention boxclk-N.json, where N is the configuration number. The settings menu will list all available configurations.
|
The app includes a settings menu that allows you to switch between different configurations. The selected configuration is stored as a number in the default `boxclk.json` file using the selectedConfig property.
|
||||||
|
|
||||||
|
If the selectedConfig property is not present or is set to 0, the app will use the default configuration. To create additional configurations, create separate JSON files with the naming convention `boxclk-N.json`, where `N` is the configuration number. The settings menu will list all available configurations.
|
||||||
|
|
||||||
|
## Example Configs:
|
||||||
|
|
||||||
|
To easily try out other configs, download and place the JSON configs and/or background images from below onto your Bangle.js storage. Then go to the Box Clock settings menu to select the new config number. You can also modify them to suit your personal preferences.
|
||||||
|
|
||||||
|
__Space Theme:__
|
||||||
|
|
||||||
|
- **Config:** [boxclk-1.json](https://github.com/espruino/BangleApps/tree/master/apps/boxclk/boxclk-1.json)
|
||||||
|
- **Background:** [boxclk.space.img](https://github.com/espruino/BangleApps/tree/master/apps/boxclk/boxclk.space.img) ([Original Source](https://www.pixilart.com/art/fallin-from-outer-space-sr2e0c1a705749a))
|
||||||
|
|
||||||
|
__System Color Theme:__
|
||||||
|
|
||||||
|
- **Config:** [boxclk-2.json](https://github.com/espruino/BangleApps/tree/master/apps/boxclk/boxclk-2.json)
|
||||||
|
|
||||||
## Compatibility
|
## Compatibility
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* 1. Module dependencies and initial configurations
|
* 1. Module dependencies and initial configurations
|
||||||
* ---------------------------------------------------------------
|
* ---------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let storage = require("Storage");
|
let storage = require("Storage");
|
||||||
let locale = require("locale");
|
let locale = require("locale");
|
||||||
let widgets = require("widget_utils");
|
let widgets = require("widget_utils");
|
||||||
|
@ -30,6 +31,7 @@
|
||||||
* 2. Graphical and visual configurations
|
* 2. Graphical and visual configurations
|
||||||
* ---------------------------------------------------------------
|
* ---------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let w = g.getWidth();
|
let w = g.getWidth();
|
||||||
let h = g.getHeight();
|
let h = g.getHeight();
|
||||||
let totalWidth, totalHeight;
|
let totalWidth, totalHeight;
|
||||||
|
@ -40,6 +42,7 @@
|
||||||
* 3. Touchscreen Handlers
|
* 3. Touchscreen Handlers
|
||||||
* ---------------------------------------------------------------
|
* ---------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let touchHandler;
|
let touchHandler;
|
||||||
let dragHandler;
|
let dragHandler;
|
||||||
let movementDistance = 0;
|
let movementDistance = 0;
|
||||||
|
@ -49,6 +52,7 @@
|
||||||
* 4. Font loading function
|
* 4. Font loading function
|
||||||
* ---------------------------------------------------------------
|
* ---------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let loadCustomFont = function() {
|
let loadCustomFont = function() {
|
||||||
Graphics.prototype.setFontBrunoAce = function() {
|
Graphics.prototype.setFontBrunoAce = function() {
|
||||||
// Actual height 23 (24 - 2)
|
// Actual height 23 (24 - 2)
|
||||||
|
@ -66,6 +70,7 @@
|
||||||
* 5. Initial settings of boxes and their positions
|
* 5. Initial settings of boxes and their positions
|
||||||
* ---------------------------------------------------------------
|
* ---------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (let key in boxesConfig) {
|
for (let key in boxesConfig) {
|
||||||
if (key === 'bg' && boxesConfig[key].img) {
|
if (key === 'bg' && boxesConfig[key].img) {
|
||||||
bgImage = storage.read(boxesConfig[key].img);
|
bgImage = storage.read(boxesConfig[key].img);
|
||||||
|
@ -167,14 +172,15 @@
|
||||||
* 7. String forming helper functions
|
* 7. String forming helper functions
|
||||||
* ---------------------------------------------------------------
|
* ---------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let isBool = function(val, defaultVal) {
|
let isBool = function(val, defaultVal) {
|
||||||
return typeof val !== 'undefined' ? Boolean(val) : defaultVal;
|
return typeof val !== 'undefined' ? Boolean(val) : defaultVal;
|
||||||
};
|
};
|
||||||
|
|
||||||
let getDate = function(short, disableSuffix) {
|
let getDate = function(short, shortMonth, disableSuffix) {
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
const dayOfMonth = date.getDate();
|
const dayOfMonth = date.getDate();
|
||||||
const month = short ? locale.month(date, 0) : locale.month(date, 1);
|
const month = shortMonth ? locale.month(date, 1) : locale.month(date, 0);
|
||||||
const year = date.getFullYear();
|
const year = date.getFullYear();
|
||||||
let suffix;
|
let suffix;
|
||||||
if ([1, 21, 31].includes(dayOfMonth)) {
|
if ([1, 21, 31].includes(dayOfMonth)) {
|
||||||
|
@ -211,6 +217,7 @@
|
||||||
* 8. Main draw function
|
* 8. Main draw function
|
||||||
* ---------------------------------------------------------------
|
* ---------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let draw = (function() {
|
let draw = (function() {
|
||||||
let updatePerMinute = true; // variable to track the state of time display
|
let updatePerMinute = true; // variable to track the state of time display
|
||||||
|
|
||||||
|
@ -228,7 +235,12 @@
|
||||||
boxes.meridian.string = modString(boxes.meridian, locale.meridian(date, isBool(boxes.meridian.short, true)));
|
boxes.meridian.string = modString(boxes.meridian, locale.meridian(date, isBool(boxes.meridian.short, true)));
|
||||||
}
|
}
|
||||||
if (boxes.date) {
|
if (boxes.date) {
|
||||||
boxes.date.string = modString(boxes.date, getDate(isBool(boxes.date.short, true), isBool(boxes.date.disableSuffix, false)));
|
boxes.date.string = (
|
||||||
|
modString(boxes.date,
|
||||||
|
getDate(isBool(boxes.date.short, true),
|
||||||
|
isBool(boxes.date.shortMonth, true),
|
||||||
|
isBool(boxes.date.disableSuffix, false)
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
if (boxes.dow) {
|
if (boxes.dow) {
|
||||||
boxes.dow.string = modString(boxes.dow, getDayOfWeek(date, isBool(boxes.dow.short, true)));
|
boxes.dow.string = modString(boxes.dow, getDayOfWeek(date, isBool(boxes.dow.short, true)));
|
||||||
|
@ -237,7 +249,7 @@
|
||||||
boxes.batt.string = modString(boxes.batt, E.getBattery());
|
boxes.batt.string = modString(boxes.batt, E.getBattery());
|
||||||
}
|
}
|
||||||
if (boxes.step) {
|
if (boxes.step) {
|
||||||
boxes.step.string = modString(boxes.step, Bangle.getStepCount());
|
boxes.step.string = modString(boxes.step, Bangle.getHealthStatus("day").steps);
|
||||||
}
|
}
|
||||||
boxKeys.forEach((boxKey) => {
|
boxKeys.forEach((boxKey) => {
|
||||||
let boxItem = boxes[boxKey];
|
let boxItem = boxes[boxKey];
|
||||||
|
@ -267,6 +279,7 @@
|
||||||
* 9. Helper function for touch event
|
* 9. Helper function for touch event
|
||||||
* ---------------------------------------------------------------
|
* ---------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let touchInText = function(e, boxItem, boxKey) {
|
let touchInText = function(e, boxItem, boxKey) {
|
||||||
calcBoxSize(boxItem);
|
calcBoxSize(boxItem);
|
||||||
const pos = calcBoxPos(boxKey);
|
const pos = calcBoxPos(boxKey);
|
||||||
|
@ -291,6 +304,7 @@
|
||||||
* 10. Setup function to configure event handlers
|
* 10. Setup function to configure event handlers
|
||||||
* ---------------------------------------------------------------
|
* ---------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let setup = function() {
|
let setup = function() {
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
// Define the touchHandler function
|
// Define the touchHandler function
|
||||||
|
@ -338,6 +352,8 @@
|
||||||
// Define the dragHandler function
|
// Define the dragHandler function
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
dragHandler = function(e) {
|
dragHandler = function(e) {
|
||||||
|
// Check if any box is being dragged
|
||||||
|
if (!Object.values(isDragging).some(Boolean)) return;
|
||||||
// Calculate the movement distance
|
// Calculate the movement distance
|
||||||
movementDistance += Math.abs(e.dx) + Math.abs(e.dy);
|
movementDistance += Math.abs(e.dx) + Math.abs(e.dy);
|
||||||
// Check if the movement distance exceeds a threshold
|
// Check if the movement distance exceeds a threshold
|
||||||
|
@ -391,8 +407,9 @@
|
||||||
* 11. Main execution part
|
* 11. Main execution part
|
||||||
* ---------------------------------------------------------------
|
* ---------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Bangle.loadWidgets();
|
Bangle.loadWidgets();
|
||||||
widgets.swipeOn();
|
widgets.swipeOn();
|
||||||
modSetColor();
|
modSetColor();
|
||||||
setup();
|
setup();
|
||||||
}
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
{
|
||||||
|
"time": {
|
||||||
|
"font": "6x8",
|
||||||
|
"fontSize": 3,
|
||||||
|
"outline": 2,
|
||||||
|
"color": "#0ff",
|
||||||
|
"outlineColor": "#00f",
|
||||||
|
"border": "#0f0",
|
||||||
|
"xPadding": -1,
|
||||||
|
"yPadding": -2.5,
|
||||||
|
"xOffset": 2,
|
||||||
|
"yOffset": 0,
|
||||||
|
"boxPos": {
|
||||||
|
"x": "0.33",
|
||||||
|
"y": "0.29"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"meridian": {
|
||||||
|
"font": "6x8",
|
||||||
|
"fontSize": 2,
|
||||||
|
"outline": 1,
|
||||||
|
"color": "#FF9900",
|
||||||
|
"outlineColor": "fg",
|
||||||
|
"border": "#0ff",
|
||||||
|
"xPadding": -0.5,
|
||||||
|
"yPadding": -1.5,
|
||||||
|
"xOffset": 2,
|
||||||
|
"yOffset": 1,
|
||||||
|
"boxPos": {
|
||||||
|
"x": "0.34",
|
||||||
|
"y": "0.46"
|
||||||
|
},
|
||||||
|
"short": false
|
||||||
|
},
|
||||||
|
"dow": {
|
||||||
|
"font": "6x8",
|
||||||
|
"fontSize": 2,
|
||||||
|
"outline": 1,
|
||||||
|
"color": "#000",
|
||||||
|
"outlineColor": "#fff",
|
||||||
|
"border": "#0f0",
|
||||||
|
"xPadding": -0.5,
|
||||||
|
"yPadding": -0.5,
|
||||||
|
"xOffset": 1,
|
||||||
|
"yOffset": 1,
|
||||||
|
"boxPos": {
|
||||||
|
"x": "0.5",
|
||||||
|
"y": "0.82"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"font": "6x8",
|
||||||
|
"fontSize": 2,
|
||||||
|
"outline": 1,
|
||||||
|
"color": "#000",
|
||||||
|
"outlineColor": "#fff",
|
||||||
|
"border": "#0f0",
|
||||||
|
"xPadding": -0.5,
|
||||||
|
"yPadding": 0.5,
|
||||||
|
"xOffset": 1,
|
||||||
|
"yOffset": 1,
|
||||||
|
"boxPos": {
|
||||||
|
"x": "0.5",
|
||||||
|
"y": "0.71"
|
||||||
|
},
|
||||||
|
"prefix": "Steps: "
|
||||||
|
},
|
||||||
|
"batt": {
|
||||||
|
"font": "4x6",
|
||||||
|
"fontSize": 2,
|
||||||
|
"outline": 1,
|
||||||
|
"color": "#0ff",
|
||||||
|
"outlineColor": "#00f",
|
||||||
|
"border": "#0f0",
|
||||||
|
"xPadding": -0.5,
|
||||||
|
"yPadding": -0.5,
|
||||||
|
"xOffset": 1,
|
||||||
|
"yOffset": 1,
|
||||||
|
"boxPos": {
|
||||||
|
"x": "0.87",
|
||||||
|
"y": "0.87"
|
||||||
|
},
|
||||||
|
"suffix": "%"
|
||||||
|
},
|
||||||
|
"bg": {
|
||||||
|
"img": "boxclk.space.img"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
{
|
||||||
|
"time": {
|
||||||
|
"font": "6x8",
|
||||||
|
"fontSize": 5,
|
||||||
|
"outline": 3,
|
||||||
|
"color": "bgH",
|
||||||
|
"outlineColor": "fg",
|
||||||
|
"border": "#f0f",
|
||||||
|
"xPadding": -2,
|
||||||
|
"yPadding": -4.5,
|
||||||
|
"xOffset": 3,
|
||||||
|
"yOffset": 0,
|
||||||
|
"boxPos": {
|
||||||
|
"x": "0.5",
|
||||||
|
"y": "0.33"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dow": {
|
||||||
|
"font": "6x8",
|
||||||
|
"fontSize": 3,
|
||||||
|
"outline": 1,
|
||||||
|
"color": "#5ccd73",
|
||||||
|
"outlineColor": "fg",
|
||||||
|
"border": "#f0f",
|
||||||
|
"xPadding": -1,
|
||||||
|
"yPadding": 0.5,
|
||||||
|
"xOffset": 2,
|
||||||
|
"yOffset": 0,
|
||||||
|
"boxPos": {
|
||||||
|
"x": "0.5",
|
||||||
|
"y": "0.57"
|
||||||
|
},
|
||||||
|
"short": false
|
||||||
|
},
|
||||||
|
"date": {
|
||||||
|
"font": "6x8",
|
||||||
|
"fontSize": 2,
|
||||||
|
"outline": 1,
|
||||||
|
"color": "#5ccd73",
|
||||||
|
"outlineColor": "fg",
|
||||||
|
"border": "#f0f",
|
||||||
|
"xPadding": -0.5,
|
||||||
|
"yPadding": 0.5,
|
||||||
|
"xOffset": 1,
|
||||||
|
"yOffset": 0,
|
||||||
|
"boxPos": {
|
||||||
|
"x": "0.5",
|
||||||
|
"y": "0.75"
|
||||||
|
},
|
||||||
|
"shortMonth": false,
|
||||||
|
"disableSuffix": true
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"font": "4x6",
|
||||||
|
"fontSize": 3,
|
||||||
|
"outline": 2,
|
||||||
|
"color": "bgH",
|
||||||
|
"outlineColor": "fg",
|
||||||
|
"border": "#f0f",
|
||||||
|
"xPadding": -1,
|
||||||
|
"yPadding": 0.5,
|
||||||
|
"xOffset": 2,
|
||||||
|
"yOffset": 1,
|
||||||
|
"boxPos": {
|
||||||
|
"x": "0.5",
|
||||||
|
"y": "0.92"
|
||||||
|
},
|
||||||
|
"prefix": "Steps: "
|
||||||
|
},
|
||||||
|
"batt": {
|
||||||
|
"font": "4x6",
|
||||||
|
"fontSize": 3,
|
||||||
|
"outline": 2,
|
||||||
|
"color": "bgH",
|
||||||
|
"outlineColor": "fg",
|
||||||
|
"border": "#f0f",
|
||||||
|
"xPadding": -1,
|
||||||
|
"yPadding": -1,
|
||||||
|
"xOffset": 2,
|
||||||
|
"yOffset": 2,
|
||||||
|
"boxPos": {
|
||||||
|
"x": "0.85",
|
||||||
|
"y": "0.08"
|
||||||
|
},
|
||||||
|
"suffix": "%"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,13 @@
|
||||||
{
|
{
|
||||||
"id": "boxclk",
|
"id": "boxclk",
|
||||||
"name": "Box Clock",
|
"name": "Box Clock",
|
||||||
"version": "0.02",
|
"version": "0.05",
|
||||||
"description": "A customizable clock with configurable text boxes that can be positioned to show your favorite background",
|
"description": "A customizable clock with configurable text boxes that can be positioned to show your favorite background",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"screenshots": [
|
"screenshots": [
|
||||||
{"url":"screenshot.png"},
|
{"url":"screenshot.png"},
|
||||||
{"url":"screenshot-1.png"}
|
{"url":"screenshot-1.png"},
|
||||||
|
{"url":"screenshot-2.png"}
|
||||||
],
|
],
|
||||||
"type": "clock",
|
"type": "clock",
|
||||||
"tags": "clock",
|
"tags": "clock",
|
||||||
|
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 3.4 KiB |
|
@ -1,411 +1,413 @@
|
||||||
var __assign = Object.assign;
|
|
||||||
var Layout = require("Layout");
|
|
||||||
Bangle.loadWidgets();
|
|
||||||
Bangle.drawWidgets();
|
|
||||||
var HRM_MIN_CONFIDENCE = 75;
|
|
||||||
var services = ["0x180d", "0x181a", "0x1819"];
|
|
||||||
var acc;
|
|
||||||
var bar;
|
|
||||||
var gps;
|
|
||||||
var hrm;
|
|
||||||
var hrmAny;
|
|
||||||
var mag;
|
|
||||||
var btnsShown = false;
|
|
||||||
var prevBtnsShown = undefined;
|
|
||||||
var hrmAnyClear;
|
|
||||||
var settings = {
|
|
||||||
bar: false,
|
|
||||||
gps: false,
|
|
||||||
hrm: false,
|
|
||||||
mag: false,
|
|
||||||
};
|
|
||||||
var idToName = {
|
|
||||||
acc: "Acceleration",
|
|
||||||
bar: "Barometer",
|
|
||||||
gps: "GPS",
|
|
||||||
hrm: "HRM",
|
|
||||||
mag: "Magnetometer",
|
|
||||||
};
|
|
||||||
var infoFont = "6x8:2";
|
|
||||||
var colour = {
|
|
||||||
on: "#0f0",
|
|
||||||
off: "#fff",
|
|
||||||
};
|
|
||||||
var makeToggle = function (id) { return function () {
|
|
||||||
settings[id] = !settings[id];
|
|
||||||
var entry = btnLayout[id];
|
|
||||||
var col = settings[id] ? colour.on : colour.off;
|
|
||||||
entry.btnBorder = entry.col = col;
|
|
||||||
btnLayout.update();
|
|
||||||
btnLayout.render();
|
|
||||||
enableSensors();
|
|
||||||
}; };
|
|
||||||
var btnStyle = {
|
|
||||||
font: "Vector:14",
|
|
||||||
fillx: 1,
|
|
||||||
filly: 1,
|
|
||||||
col: g.theme.fg,
|
|
||||||
bgCol: g.theme.bg,
|
|
||||||
btnBorder: "#fff",
|
|
||||||
};
|
|
||||||
var btnLayout = new Layout({
|
|
||||||
type: "v",
|
|
||||||
c: [
|
|
||||||
{
|
|
||||||
type: "h",
|
|
||||||
c: [
|
|
||||||
__assign({ type: "btn", label: idToName.bar, id: "bar", cb: makeToggle('bar') }, btnStyle),
|
|
||||||
__assign({ type: "btn", label: idToName.gps, id: "gps", cb: makeToggle('gps') }, btnStyle),
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "h",
|
|
||||||
c: [
|
|
||||||
__assign({ type: "btn", label: idToName.hrm, id: "hrm", cb: makeToggle('hrm') }, btnStyle),
|
|
||||||
__assign({ type: "btn", label: idToName.mag, id: "mag", cb: makeToggle('mag') }, btnStyle),
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "h",
|
|
||||||
c: [
|
|
||||||
__assign(__assign({ type: "btn", label: idToName.acc, id: "acc", cb: function () { } }, btnStyle), { col: colour.on, btnBorder: colour.on }),
|
|
||||||
__assign({ type: "btn", label: "Back", cb: function () {
|
|
||||||
setBtnsShown(false);
|
|
||||||
} }, btnStyle),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}, {
|
|
||||||
lazy: true,
|
|
||||||
back: function () {
|
|
||||||
setBtnsShown(false);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
var setBtnsShown = function (b) {
|
|
||||||
btnsShown = b;
|
|
||||||
hook(!btnsShown);
|
|
||||||
setIntervals();
|
|
||||||
redraw();
|
|
||||||
};
|
|
||||||
var drawInfo = function (force) {
|
|
||||||
var _a = Bangle.appRect, y = _a.y, x = _a.x, w = _a.w;
|
|
||||||
var mid = x + w / 2;
|
|
||||||
var drawn = false;
|
|
||||||
if (!force && !bar && !gps && !hrm && !mag)
|
|
||||||
return;
|
|
||||||
g.reset()
|
|
||||||
.clearRect(Bangle.appRect)
|
|
||||||
.setFont(infoFont)
|
|
||||||
.setFontAlign(0, -1);
|
|
||||||
if (bar) {
|
|
||||||
g.drawString("".concat(bar.altitude.toFixed(1), "m"), mid, y);
|
|
||||||
y += g.getFontHeight();
|
|
||||||
g.drawString("".concat(bar.pressure.toFixed(1), " hPa"), mid, y);
|
|
||||||
y += g.getFontHeight();
|
|
||||||
g.drawString("".concat(bar.temperature.toFixed(1), "C"), mid, y);
|
|
||||||
y += g.getFontHeight();
|
|
||||||
drawn = true;
|
|
||||||
}
|
|
||||||
if (gps) {
|
|
||||||
g.drawString("".concat(gps.lat.toFixed(4), " lat, ").concat(gps.lon.toFixed(4), " lon"), mid, y);
|
|
||||||
y += g.getFontHeight();
|
|
||||||
g.drawString("".concat(gps.alt, "m (").concat(gps.satellites, " sat)"), mid, y);
|
|
||||||
y += g.getFontHeight();
|
|
||||||
drawn = true;
|
|
||||||
}
|
|
||||||
if (hrm) {
|
|
||||||
g.drawString("".concat(hrm.bpm, " BPM (").concat(hrm.confidence, "%)"), mid, y);
|
|
||||||
y += g.getFontHeight();
|
|
||||||
drawn = true;
|
|
||||||
}
|
|
||||||
else if (hrmAny) {
|
|
||||||
g.drawString("~".concat(hrmAny.bpm, " BPM (").concat(hrmAny.confidence, "%)"), mid, y);
|
|
||||||
y += g.getFontHeight();
|
|
||||||
drawn = true;
|
|
||||||
if (!settings.hrm && !hrmAnyClear) {
|
|
||||||
hrmAnyClear = setTimeout(function () {
|
|
||||||
hrmAny = undefined;
|
|
||||||
hrmAnyClear = undefined;
|
|
||||||
}, 10000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mag) {
|
|
||||||
g.drawString("".concat(mag.x, " ").concat(mag.y, " ").concat(mag.z), mid, y);
|
|
||||||
y += g.getFontHeight();
|
|
||||||
g.drawString("heading: ".concat(mag.heading.toFixed(1)), mid, y);
|
|
||||||
y += g.getFontHeight();
|
|
||||||
drawn = true;
|
|
||||||
}
|
|
||||||
if (!drawn) {
|
|
||||||
if (!force || Object.values(settings).every(function (x) { return !x; })) {
|
|
||||||
g.drawString("swipe to enable", mid, y);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
g.drawString("events pending", mid, y);
|
|
||||||
}
|
|
||||||
y += g.getFontHeight();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var onTap = function () {
|
|
||||||
setBtnsShown(true);
|
|
||||||
};
|
|
||||||
var redraw = function () {
|
|
||||||
if (btnsShown) {
|
|
||||||
if (!prevBtnsShown) {
|
|
||||||
prevBtnsShown = btnsShown;
|
|
||||||
Bangle.removeListener("swipe", onTap);
|
|
||||||
btnLayout.setUI();
|
|
||||||
btnLayout.forgetLazyState();
|
|
||||||
g.clearRect(Bangle.appRect);
|
|
||||||
}
|
|
||||||
btnLayout.render();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (prevBtnsShown) {
|
|
||||||
prevBtnsShown = btnsShown;
|
|
||||||
Bangle.setUI();
|
|
||||||
Bangle.on("swipe", onTap);
|
|
||||||
drawInfo(true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
drawInfo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var encodeHrm = function (hrm) {
|
|
||||||
return [0, hrm.bpm];
|
|
||||||
};
|
|
||||||
encodeHrm.maxLen = 2;
|
|
||||||
var encodePressure = function (data) {
|
|
||||||
return toByteArray(Math.round(data.pressure * 10), 4, false);
|
|
||||||
};
|
|
||||||
encodePressure.maxLen = 4;
|
|
||||||
var encodeElevation = function (data) {
|
|
||||||
return toByteArray(Math.round(data.altitude * 100), 3, true);
|
|
||||||
};
|
|
||||||
encodeElevation.maxLen = 3;
|
|
||||||
var encodeTemp = function (data) {
|
|
||||||
return toByteArray(Math.round(data.temperature * 10), 2, true);
|
|
||||||
};
|
|
||||||
encodeTemp.maxLen = 2;
|
|
||||||
var encodeGps = function (data) {
|
|
||||||
var speed = toByteArray(Math.round(1000 * data.speed / 36), 2, false);
|
|
||||||
var lat = toByteArray(Math.round(data.lat * 10000000), 4, true);
|
|
||||||
var lon = toByteArray(Math.round(data.lon * 10000000), 4, true);
|
|
||||||
var elevation = toByteArray(Math.round(data.alt * 100), 3, true);
|
|
||||||
var heading = toByteArray(Math.round(data.course * 100), 2, false);
|
|
||||||
return [
|
|
||||||
157,
|
|
||||||
2,
|
|
||||||
speed[0], speed[1],
|
|
||||||
lat[0], lat[1], lat[2], lat[3],
|
|
||||||
lon[0], lon[1], lon[2], lon[3],
|
|
||||||
elevation[0], elevation[1], elevation[2],
|
|
||||||
heading[0], heading[1]
|
|
||||||
];
|
|
||||||
};
|
|
||||||
encodeGps.maxLen = 17;
|
|
||||||
var encodeGpsHeadingOnly = function (data) {
|
|
||||||
var heading = toByteArray(Math.round(data.heading * 100), 2, false);
|
|
||||||
return [
|
|
||||||
16,
|
|
||||||
16,
|
|
||||||
heading[0], heading[1]
|
|
||||||
];
|
|
||||||
};
|
|
||||||
encodeGpsHeadingOnly.maxLen = 17;
|
|
||||||
var encodeMag = function (data) {
|
|
||||||
var x = toByteArray(data.x, 2, true);
|
|
||||||
var y = toByteArray(data.y, 2, true);
|
|
||||||
var z = toByteArray(data.z, 2, true);
|
|
||||||
return [x[0], x[1], y[0], y[1], z[0], z[1]];
|
|
||||||
};
|
|
||||||
encodeMag.maxLen = 6;
|
|
||||||
var toByteArray = function (value, numberOfBytes, isSigned) {
|
|
||||||
var byteArray = new Array(numberOfBytes);
|
|
||||||
if (isSigned && (value < 0)) {
|
|
||||||
value += 1 << (numberOfBytes * 8);
|
|
||||||
}
|
|
||||||
for (var index = 0; index < numberOfBytes; index++) {
|
|
||||||
byteArray[index] = (value >> (index * 8)) & 0xff;
|
|
||||||
}
|
|
||||||
return byteArray;
|
|
||||||
};
|
|
||||||
var enableSensors = function () {
|
|
||||||
Bangle.setBarometerPower(settings.bar, "btadv");
|
|
||||||
if (!settings.bar)
|
|
||||||
bar = undefined;
|
|
||||||
Bangle.setGPSPower(settings.gps, "btadv");
|
|
||||||
if (!settings.gps)
|
|
||||||
gps = undefined;
|
|
||||||
Bangle.setHRMPower(settings.hrm, "btadv");
|
|
||||||
if (!settings.hrm)
|
|
||||||
hrm = hrmAny = undefined;
|
|
||||||
Bangle.setCompassPower(settings.mag, "btadv");
|
|
||||||
if (!settings.mag)
|
|
||||||
mag = undefined;
|
|
||||||
};
|
|
||||||
var haveServiceData = function (serv) {
|
|
||||||
switch (serv) {
|
|
||||||
case "0x180d": return !!hrm;
|
|
||||||
case "0x181a": return !!(bar || mag);
|
|
||||||
case "0x1819": return !!(gps && gps.lat && gps.lon || mag);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var serviceToAdvert = function (serv, initial) {
|
|
||||||
var _a, _b, _c;
|
|
||||||
if (initial === void 0) { initial = false; }
|
|
||||||
switch (serv) {
|
|
||||||
case "0x180d":
|
|
||||||
if (hrm || initial) {
|
|
||||||
var o = {
|
|
||||||
maxLen: encodeHrm.maxLen,
|
|
||||||
readable: true,
|
|
||||||
notify: true,
|
|
||||||
};
|
|
||||||
if (hrm) {
|
|
||||||
o.value = encodeHrm(hrm);
|
|
||||||
hrm = undefined;
|
|
||||||
}
|
|
||||||
return _a = {}, _a["0x2a37"] = o, _a;
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
case "0x1819":
|
|
||||||
if (gps || initial) {
|
|
||||||
var o = {
|
|
||||||
maxLen: encodeGps.maxLen,
|
|
||||||
readable: true,
|
|
||||||
notify: true,
|
|
||||||
};
|
|
||||||
if (gps) {
|
|
||||||
o.value = encodeGps(gps);
|
|
||||||
gps = undefined;
|
|
||||||
}
|
|
||||||
return _b = {}, _b["0x2a67"] = o, _b;
|
|
||||||
}
|
|
||||||
else if (mag) {
|
|
||||||
var o = {
|
|
||||||
maxLen: encodeGpsHeadingOnly.maxLen,
|
|
||||||
readable: true,
|
|
||||||
notify: true,
|
|
||||||
value: encodeGpsHeadingOnly(mag),
|
|
||||||
};
|
|
||||||
return _c = {}, _c["0x2a67"] = o, _c;
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
case "0x181a": {
|
|
||||||
var o = {};
|
|
||||||
if (bar || initial) {
|
|
||||||
o["0x2a6c"] = {
|
|
||||||
maxLen: encodeElevation.maxLen,
|
|
||||||
readable: true,
|
|
||||||
notify: true,
|
|
||||||
};
|
|
||||||
o["0x2A1F"] = {
|
|
||||||
maxLen: encodeTemp.maxLen,
|
|
||||||
readable: true,
|
|
||||||
notify: true,
|
|
||||||
};
|
|
||||||
o["0x2a6d"] = {
|
|
||||||
maxLen: encodePressure.maxLen,
|
|
||||||
readable: true,
|
|
||||||
notify: true,
|
|
||||||
};
|
|
||||||
if (bar) {
|
|
||||||
o["0x2a6c"].value = encodeElevation(bar);
|
|
||||||
o["0x2A1F"].value = encodeTemp(bar);
|
|
||||||
o["0x2a6d"].value = encodePressure(bar);
|
|
||||||
bar = undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mag || initial) {
|
|
||||||
o["0x2aa1"] = {
|
|
||||||
maxLen: encodeMag.maxLen,
|
|
||||||
readable: true,
|
|
||||||
notify: true,
|
|
||||||
};
|
|
||||||
if (mag) {
|
|
||||||
o["0x2aa1"].value = encodeMag(mag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var getBleAdvert = function (map, all) {
|
|
||||||
if (all === void 0) { all = false; }
|
|
||||||
var advert = {};
|
|
||||||
for (var _i = 0, services_1 = services; _i < services_1.length; _i++) {
|
|
||||||
var serv = services_1[_i];
|
|
||||||
if (all || haveServiceData(serv)) {
|
|
||||||
advert[serv] = map(serv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mag = undefined;
|
|
||||||
return advert;
|
|
||||||
};
|
|
||||||
var updateServices = function () {
|
|
||||||
var newAdvert = getBleAdvert(serviceToAdvert);
|
|
||||||
NRF.updateServices(newAdvert);
|
|
||||||
};
|
|
||||||
var onAccel = function (newAcc) { return acc = newAcc; };
|
|
||||||
var onPressure = function (newBar) { return bar = newBar; };
|
|
||||||
var onGPS = function (newGps) { return gps = newGps; };
|
|
||||||
var onHRM = function (newHrm) {
|
|
||||||
if (newHrm.confidence >= HRM_MIN_CONFIDENCE)
|
|
||||||
hrm = newHrm;
|
|
||||||
hrmAny = newHrm;
|
|
||||||
};
|
|
||||||
var onMag = function (newMag) { return mag = newMag; };
|
|
||||||
var hook = function (enable) {
|
|
||||||
if (enable) {
|
|
||||||
Bangle.on("accel", onAccel);
|
|
||||||
Bangle.on("pressure", onPressure);
|
|
||||||
Bangle.on("GPS", onGPS);
|
|
||||||
Bangle.on("HRM", onHRM);
|
|
||||||
Bangle.on("mag", onMag);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Bangle.removeListener("accel", onAccel);
|
|
||||||
Bangle.removeListener("pressure", onPressure);
|
|
||||||
Bangle.removeListener("GPS", onGPS);
|
|
||||||
Bangle.removeListener("HRM", onHRM);
|
|
||||||
Bangle.removeListener("mag", onMag);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var setIntervals = function (locked, connected) {
|
|
||||||
if (locked === void 0) { locked = Bangle.isLocked(); }
|
|
||||||
if (connected === void 0) { connected = NRF.getSecurityStatus().connected; }
|
|
||||||
changeInterval(redrawInterval, locked ? 15000 : 5000);
|
|
||||||
if (connected) {
|
|
||||||
var interval = btnsShown ? 5000 : 1000;
|
|
||||||
if (bleInterval) {
|
|
||||||
changeInterval(bleInterval, interval);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bleInterval = setInterval(updateServices, interval);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (bleInterval) {
|
|
||||||
clearInterval(bleInterval);
|
|
||||||
bleInterval = undefined;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var redrawInterval = setInterval(redraw, 1000);
|
|
||||||
Bangle.on("lock", function (locked) { return setIntervals(locked); });
|
|
||||||
var bleInterval;
|
|
||||||
NRF.on("connect", function () { return setIntervals(undefined, true); });
|
|
||||||
NRF.on("disconnect", function () { return setIntervals(undefined, false); });
|
|
||||||
setIntervals();
|
|
||||||
setBtnsShown(true);
|
|
||||||
enableSensors();
|
|
||||||
{
|
{
|
||||||
var ad = getBleAdvert(function (serv) { return serviceToAdvert(serv, true); }, true);
|
var __assign = Object.assign;
|
||||||
var adServices = Object
|
var Layout_1 = require("Layout");
|
||||||
.keys(ad)
|
Bangle.loadWidgets();
|
||||||
.map(function (k) { return k.replace("0x", ""); });
|
Bangle.drawWidgets();
|
||||||
NRF.setServices(ad, {
|
var HRM_MIN_CONFIDENCE_1 = 75;
|
||||||
advertise: adServices,
|
var services_1 = ["0x180d", "0x181a", "0x1819"];
|
||||||
uart: false,
|
var acc_1;
|
||||||
|
var bar_1;
|
||||||
|
var gps_1;
|
||||||
|
var hrm_1;
|
||||||
|
var hrmAny_1;
|
||||||
|
var mag_1;
|
||||||
|
var btnsShown_1 = false;
|
||||||
|
var prevBtnsShown_1 = undefined;
|
||||||
|
var hrmAnyClear_1;
|
||||||
|
var settings_1 = {
|
||||||
|
bar: false,
|
||||||
|
gps: false,
|
||||||
|
hrm: false,
|
||||||
|
mag: false,
|
||||||
|
};
|
||||||
|
var idToName = {
|
||||||
|
acc: "Acceleration",
|
||||||
|
bar: "Barometer",
|
||||||
|
gps: "GPS",
|
||||||
|
hrm: "HRM",
|
||||||
|
mag: "Magnetometer",
|
||||||
|
};
|
||||||
|
var infoFont_1 = "6x8:2";
|
||||||
|
var colour_1 = {
|
||||||
|
on: "#0f0",
|
||||||
|
off: "#fff",
|
||||||
|
};
|
||||||
|
var makeToggle = function (id) { return function () {
|
||||||
|
settings_1[id] = !settings_1[id];
|
||||||
|
var entry = btnLayout_1[id];
|
||||||
|
var col = settings_1[id] ? colour_1.on : colour_1.off;
|
||||||
|
entry.btnBorder = entry.col = col;
|
||||||
|
btnLayout_1.update();
|
||||||
|
btnLayout_1.render();
|
||||||
|
enableSensors_1();
|
||||||
|
}; };
|
||||||
|
var btnStyle = {
|
||||||
|
font: "Vector:14",
|
||||||
|
fillx: 1,
|
||||||
|
filly: 1,
|
||||||
|
col: g.theme.fg,
|
||||||
|
bgCol: g.theme.bg,
|
||||||
|
btnBorder: "#fff",
|
||||||
|
};
|
||||||
|
var btnLayout_1 = new Layout_1({
|
||||||
|
type: "v",
|
||||||
|
c: [
|
||||||
|
{
|
||||||
|
type: "h",
|
||||||
|
c: [
|
||||||
|
__assign({ type: "btn", label: idToName.bar, id: "bar", cb: makeToggle('bar') }, btnStyle),
|
||||||
|
__assign({ type: "btn", label: idToName.gps, id: "gps", cb: makeToggle('gps') }, btnStyle),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "h",
|
||||||
|
c: [
|
||||||
|
__assign({ type: "btn", label: idToName.hrm, id: "hrm", cb: makeToggle('hrm') }, btnStyle),
|
||||||
|
__assign({ type: "btn", label: idToName.mag, id: "mag", cb: makeToggle('mag') }, btnStyle),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "h",
|
||||||
|
c: [
|
||||||
|
__assign(__assign({ type: "btn", label: idToName.acc, id: "acc", cb: function () { } }, btnStyle), { col: colour_1.on, btnBorder: colour_1.on }),
|
||||||
|
__assign({ type: "btn", label: "Back", cb: function () {
|
||||||
|
setBtnsShown_1(false);
|
||||||
|
} }, btnStyle),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
lazy: true,
|
||||||
|
back: function () {
|
||||||
|
setBtnsShown_1(false);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
var setBtnsShown_1 = function (b) {
|
||||||
|
btnsShown_1 = b;
|
||||||
|
hook_1(!btnsShown_1);
|
||||||
|
setIntervals_1();
|
||||||
|
redraw_1();
|
||||||
|
};
|
||||||
|
var drawInfo_1 = function (force) {
|
||||||
|
var _a = Bangle.appRect, y = _a.y, x = _a.x, w = _a.w;
|
||||||
|
var mid = x + w / 2;
|
||||||
|
var drawn = false;
|
||||||
|
if (!force && !bar_1 && !gps_1 && !hrm_1 && !mag_1)
|
||||||
|
return;
|
||||||
|
g.reset()
|
||||||
|
.clearRect(Bangle.appRect)
|
||||||
|
.setFont(infoFont_1)
|
||||||
|
.setFontAlign(0, -1);
|
||||||
|
if (bar_1) {
|
||||||
|
g.drawString("".concat(bar_1.altitude.toFixed(1), "m"), mid, y);
|
||||||
|
y += g.getFontHeight();
|
||||||
|
g.drawString("".concat(bar_1.pressure.toFixed(1), " hPa"), mid, y);
|
||||||
|
y += g.getFontHeight();
|
||||||
|
g.drawString("".concat(bar_1.temperature.toFixed(1), "C"), mid, y);
|
||||||
|
y += g.getFontHeight();
|
||||||
|
drawn = true;
|
||||||
|
}
|
||||||
|
if (gps_1) {
|
||||||
|
g.drawString("".concat(gps_1.lat.toFixed(4), " lat, ").concat(gps_1.lon.toFixed(4), " lon"), mid, y);
|
||||||
|
y += g.getFontHeight();
|
||||||
|
g.drawString("".concat(gps_1.alt, "m (").concat(gps_1.satellites, " sat)"), mid, y);
|
||||||
|
y += g.getFontHeight();
|
||||||
|
drawn = true;
|
||||||
|
}
|
||||||
|
if (hrm_1) {
|
||||||
|
g.drawString("".concat(hrm_1.bpm, " BPM (").concat(hrm_1.confidence, "%)"), mid, y);
|
||||||
|
y += g.getFontHeight();
|
||||||
|
drawn = true;
|
||||||
|
}
|
||||||
|
else if (hrmAny_1) {
|
||||||
|
g.drawString("~".concat(hrmAny_1.bpm, " BPM (").concat(hrmAny_1.confidence, "%)"), mid, y);
|
||||||
|
y += g.getFontHeight();
|
||||||
|
drawn = true;
|
||||||
|
if (!settings_1.hrm && !hrmAnyClear_1) {
|
||||||
|
hrmAnyClear_1 = setTimeout(function () {
|
||||||
|
hrmAny_1 = undefined;
|
||||||
|
hrmAnyClear_1 = undefined;
|
||||||
|
}, 10000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mag_1) {
|
||||||
|
g.drawString("".concat(mag_1.x, " ").concat(mag_1.y, " ").concat(mag_1.z), mid, y);
|
||||||
|
y += g.getFontHeight();
|
||||||
|
g.drawString("heading: ".concat(mag_1.heading.toFixed(1)), mid, y);
|
||||||
|
y += g.getFontHeight();
|
||||||
|
drawn = true;
|
||||||
|
}
|
||||||
|
if (!drawn) {
|
||||||
|
if (!force || Object.values(settings_1).every(function (x) { return !x; })) {
|
||||||
|
g.drawString("swipe to enable", mid, y);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g.drawString("events pending", mid, y);
|
||||||
|
}
|
||||||
|
y += g.getFontHeight();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var onTap_1 = function () {
|
||||||
|
setBtnsShown_1(true);
|
||||||
|
};
|
||||||
|
var redraw_1 = function () {
|
||||||
|
if (btnsShown_1) {
|
||||||
|
if (!prevBtnsShown_1) {
|
||||||
|
prevBtnsShown_1 = btnsShown_1;
|
||||||
|
Bangle.removeListener("swipe", onTap_1);
|
||||||
|
btnLayout_1.setUI();
|
||||||
|
btnLayout_1.forgetLazyState();
|
||||||
|
g.clearRect(Bangle.appRect);
|
||||||
|
}
|
||||||
|
btnLayout_1.render();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (prevBtnsShown_1) {
|
||||||
|
prevBtnsShown_1 = btnsShown_1;
|
||||||
|
Bangle.setUI();
|
||||||
|
Bangle.on("swipe", onTap_1);
|
||||||
|
drawInfo_1(true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
drawInfo_1();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var encodeHrm_1 = function (hrm) {
|
||||||
|
return [0, hrm.bpm];
|
||||||
|
};
|
||||||
|
encodeHrm_1.maxLen = 2;
|
||||||
|
var encodePressure_1 = function (data) {
|
||||||
|
return toByteArray_1(Math.round(data.pressure * 10), 4, false);
|
||||||
|
};
|
||||||
|
encodePressure_1.maxLen = 4;
|
||||||
|
var encodeElevation_1 = function (data) {
|
||||||
|
return toByteArray_1(Math.round(data.altitude * 100), 3, true);
|
||||||
|
};
|
||||||
|
encodeElevation_1.maxLen = 3;
|
||||||
|
var encodeTemp_1 = function (data) {
|
||||||
|
return toByteArray_1(Math.round(data.temperature * 10), 2, true);
|
||||||
|
};
|
||||||
|
encodeTemp_1.maxLen = 2;
|
||||||
|
var encodeGps_1 = function (data) {
|
||||||
|
var speed = toByteArray_1(Math.round(1000 * data.speed / 36), 2, false);
|
||||||
|
var lat = toByteArray_1(Math.round(data.lat * 10000000), 4, true);
|
||||||
|
var lon = toByteArray_1(Math.round(data.lon * 10000000), 4, true);
|
||||||
|
var elevation = toByteArray_1(Math.round(data.alt * 100), 3, true);
|
||||||
|
var heading = toByteArray_1(Math.round(data.course * 100), 2, false);
|
||||||
|
return [
|
||||||
|
157,
|
||||||
|
2,
|
||||||
|
speed[0], speed[1],
|
||||||
|
lat[0], lat[1], lat[2], lat[3],
|
||||||
|
lon[0], lon[1], lon[2], lon[3],
|
||||||
|
elevation[0], elevation[1], elevation[2],
|
||||||
|
heading[0], heading[1]
|
||||||
|
];
|
||||||
|
};
|
||||||
|
encodeGps_1.maxLen = 17;
|
||||||
|
var encodeGpsHeadingOnly_1 = function (data) {
|
||||||
|
var heading = toByteArray_1(Math.round(data.heading * 100), 2, false);
|
||||||
|
return [
|
||||||
|
16,
|
||||||
|
16,
|
||||||
|
heading[0], heading[1]
|
||||||
|
];
|
||||||
|
};
|
||||||
|
encodeGpsHeadingOnly_1.maxLen = 17;
|
||||||
|
var encodeMag_1 = function (data) {
|
||||||
|
var x = toByteArray_1(data.x, 2, true);
|
||||||
|
var y = toByteArray_1(data.y, 2, true);
|
||||||
|
var z = toByteArray_1(data.z, 2, true);
|
||||||
|
return [x[0], x[1], y[0], y[1], z[0], z[1]];
|
||||||
|
};
|
||||||
|
encodeMag_1.maxLen = 6;
|
||||||
|
var toByteArray_1 = function (value, numberOfBytes, isSigned) {
|
||||||
|
var byteArray = new Array(numberOfBytes);
|
||||||
|
if (isSigned && (value < 0)) {
|
||||||
|
value += 1 << (numberOfBytes * 8);
|
||||||
|
}
|
||||||
|
for (var index = 0; index < numberOfBytes; index++) {
|
||||||
|
byteArray[index] = (value >> (index * 8)) & 0xff;
|
||||||
|
}
|
||||||
|
return byteArray;
|
||||||
|
};
|
||||||
|
var enableSensors_1 = function () {
|
||||||
|
Bangle.setBarometerPower(settings_1.bar, "btadv");
|
||||||
|
if (!settings_1.bar)
|
||||||
|
bar_1 = undefined;
|
||||||
|
Bangle.setGPSPower(settings_1.gps, "btadv");
|
||||||
|
if (!settings_1.gps)
|
||||||
|
gps_1 = undefined;
|
||||||
|
Bangle.setHRMPower(settings_1.hrm, "btadv");
|
||||||
|
if (!settings_1.hrm)
|
||||||
|
hrm_1 = hrmAny_1 = undefined;
|
||||||
|
Bangle.setCompassPower(settings_1.mag, "btadv");
|
||||||
|
if (!settings_1.mag)
|
||||||
|
mag_1 = undefined;
|
||||||
|
};
|
||||||
|
var haveServiceData_1 = function (serv) {
|
||||||
|
switch (serv) {
|
||||||
|
case "0x180d": return !!hrm_1;
|
||||||
|
case "0x181a": return !!(bar_1 || mag_1);
|
||||||
|
case "0x1819": return !!(gps_1 && gps_1.lat && gps_1.lon || mag_1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var serviceToAdvert_1 = function (serv, initial) {
|
||||||
|
var _a, _b, _c;
|
||||||
|
if (initial === void 0) { initial = false; }
|
||||||
|
switch (serv) {
|
||||||
|
case "0x180d":
|
||||||
|
if (hrm_1 || initial) {
|
||||||
|
var o = {
|
||||||
|
maxLen: encodeHrm_1.maxLen,
|
||||||
|
readable: true,
|
||||||
|
notify: true,
|
||||||
|
};
|
||||||
|
if (hrm_1) {
|
||||||
|
o.value = encodeHrm_1(hrm_1);
|
||||||
|
hrm_1 = undefined;
|
||||||
|
}
|
||||||
|
return _a = {}, _a["0x2a37"] = o, _a;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
case "0x1819":
|
||||||
|
if (gps_1 || initial) {
|
||||||
|
var o = {
|
||||||
|
maxLen: encodeGps_1.maxLen,
|
||||||
|
readable: true,
|
||||||
|
notify: true,
|
||||||
|
};
|
||||||
|
if (gps_1) {
|
||||||
|
o.value = encodeGps_1(gps_1);
|
||||||
|
gps_1 = undefined;
|
||||||
|
}
|
||||||
|
return _b = {}, _b["0x2a67"] = o, _b;
|
||||||
|
}
|
||||||
|
else if (mag_1) {
|
||||||
|
var o = {
|
||||||
|
maxLen: encodeGpsHeadingOnly_1.maxLen,
|
||||||
|
readable: true,
|
||||||
|
notify: true,
|
||||||
|
value: encodeGpsHeadingOnly_1(mag_1),
|
||||||
|
};
|
||||||
|
return _c = {}, _c["0x2a67"] = o, _c;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
case "0x181a": {
|
||||||
|
var o = {};
|
||||||
|
if (bar_1 || initial) {
|
||||||
|
o["0x2a6c"] = {
|
||||||
|
maxLen: encodeElevation_1.maxLen,
|
||||||
|
readable: true,
|
||||||
|
notify: true,
|
||||||
|
};
|
||||||
|
o["0x2A1F"] = {
|
||||||
|
maxLen: encodeTemp_1.maxLen,
|
||||||
|
readable: true,
|
||||||
|
notify: true,
|
||||||
|
};
|
||||||
|
o["0x2a6d"] = {
|
||||||
|
maxLen: encodePressure_1.maxLen,
|
||||||
|
readable: true,
|
||||||
|
notify: true,
|
||||||
|
};
|
||||||
|
if (bar_1) {
|
||||||
|
o["0x2a6c"].value = encodeElevation_1(bar_1);
|
||||||
|
o["0x2A1F"].value = encodeTemp_1(bar_1);
|
||||||
|
o["0x2a6d"].value = encodePressure_1(bar_1);
|
||||||
|
bar_1 = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mag_1 || initial) {
|
||||||
|
o["0x2aa1"] = {
|
||||||
|
maxLen: encodeMag_1.maxLen,
|
||||||
|
readable: true,
|
||||||
|
notify: true,
|
||||||
|
};
|
||||||
|
if (mag_1) {
|
||||||
|
o["0x2aa1"].value = encodeMag_1(mag_1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var getBleAdvert_1 = function (map, all) {
|
||||||
|
if (all === void 0) { all = false; }
|
||||||
|
var advert = {};
|
||||||
|
for (var _i = 0, services_2 = services_1; _i < services_2.length; _i++) {
|
||||||
|
var serv = services_2[_i];
|
||||||
|
if (all || haveServiceData_1(serv)) {
|
||||||
|
advert[serv] = map(serv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mag_1 = undefined;
|
||||||
|
return advert;
|
||||||
|
};
|
||||||
|
var updateServices_1 = function () {
|
||||||
|
var newAdvert = getBleAdvert_1(serviceToAdvert_1);
|
||||||
|
NRF.updateServices(newAdvert);
|
||||||
|
};
|
||||||
|
var onAccel_1 = function (newAcc) { return acc_1 = newAcc; };
|
||||||
|
var onPressure_1 = function (newBar) { return bar_1 = newBar; };
|
||||||
|
var onGPS_1 = function (newGps) { return gps_1 = newGps; };
|
||||||
|
var onHRM_1 = function (newHrm) {
|
||||||
|
if (newHrm.confidence >= HRM_MIN_CONFIDENCE_1)
|
||||||
|
hrm_1 = newHrm;
|
||||||
|
hrmAny_1 = newHrm;
|
||||||
|
};
|
||||||
|
var onMag_1 = function (newMag) { return mag_1 = newMag; };
|
||||||
|
var hook_1 = function (enable) {
|
||||||
|
if (enable) {
|
||||||
|
Bangle.on("accel", onAccel_1);
|
||||||
|
Bangle.on("pressure", onPressure_1);
|
||||||
|
Bangle.on("GPS", onGPS_1);
|
||||||
|
Bangle.on("HRM", onHRM_1);
|
||||||
|
Bangle.on("mag", onMag_1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Bangle.removeListener("accel", onAccel_1);
|
||||||
|
Bangle.removeListener("pressure", onPressure_1);
|
||||||
|
Bangle.removeListener("GPS", onGPS_1);
|
||||||
|
Bangle.removeListener("HRM", onHRM_1);
|
||||||
|
Bangle.removeListener("mag", onMag_1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var setIntervals_1 = function (locked, connected) {
|
||||||
|
if (locked === void 0) { locked = Bangle.isLocked(); }
|
||||||
|
if (connected === void 0) { connected = NRF.getSecurityStatus().connected; }
|
||||||
|
changeInterval(redrawInterval_1, locked ? 15000 : 5000);
|
||||||
|
if (connected) {
|
||||||
|
var interval = btnsShown_1 ? 5000 : 1000;
|
||||||
|
if (bleInterval_1) {
|
||||||
|
changeInterval(bleInterval_1, interval);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bleInterval_1 = setInterval(updateServices_1, interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (bleInterval_1) {
|
||||||
|
clearInterval(bleInterval_1);
|
||||||
|
bleInterval_1 = undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var redrawInterval_1 = setInterval(redraw_1, 1000);
|
||||||
|
Bangle.on("lock", function (locked) { return setIntervals_1(locked); });
|
||||||
|
var bleInterval_1;
|
||||||
|
NRF.on("connect", function () { return setIntervals_1(undefined, true); });
|
||||||
|
NRF.on("disconnect", function () { return setIntervals_1(undefined, false); });
|
||||||
|
setIntervals_1();
|
||||||
|
setBtnsShown_1(true);
|
||||||
|
enableSensors_1();
|
||||||
|
{
|
||||||
|
var ad = getBleAdvert_1(function (serv) { return serviceToAdvert_1(serv, true); }, true);
|
||||||
|
var adServices = Object
|
||||||
|
.keys(ad)
|
||||||
|
.map(function (k) { return k.replace("0x", ""); });
|
||||||
|
NRF.setServices(ad, {
|
||||||
|
advertise: adServices,
|
||||||
|
uart: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// ts helpers:
|
{
|
||||||
|
// @ts-ignore helper
|
||||||
const __assign = Object.assign;
|
const __assign = Object.assign;
|
||||||
|
|
||||||
const Layout = require("Layout");
|
const Layout = require("Layout");
|
||||||
|
@ -713,3 +714,4 @@ enableSensors();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -18,5 +18,6 @@
|
||||||
{"name":"bthrm.settings.js","url":"settings.js"},
|
{"name":"bthrm.settings.js","url":"settings.js"},
|
||||||
{"name":"bthrm","url":"lib.js"},
|
{"name":"bthrm","url":"lib.js"},
|
||||||
{"name":"bthrm.default.json","url":"default.json"}
|
{"name":"bthrm.default.json","url":"default.json"}
|
||||||
]
|
],
|
||||||
|
"data": [{"name":"bthrm.json"}]
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,5 +15,6 @@
|
||||||
{"name":"bwclk.app.js","url":"app.js"},
|
{"name":"bwclk.app.js","url":"app.js"},
|
||||||
{"name":"bwclk.img","url":"app-icon.js","evaluate":true},
|
{"name":"bwclk.img","url":"app-icon.js","evaluate":true},
|
||||||
{"name":"bwclk.settings.js","url":"settings.js"}
|
{"name":"bwclk.settings.js","url":"settings.js"}
|
||||||
]
|
],
|
||||||
|
"data":[{"name":"bwclk.setting.json"}]
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,5 +39,10 @@
|
||||||
"name": "bwclklite.settings.js",
|
"name": "bwclklite.settings.js",
|
||||||
"url": "settings.js"
|
"url": "settings.js"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"name": "bwclklite.setting.json"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,10 @@
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"storage": [
|
"storage": [
|
||||||
{ "name": "cassioWatch.app.js", "url": "app.js" },
|
{ "name": "cassioWatch.app.js", "url": "app.js" },
|
||||||
{"name":"cassioWatch.settings.js","url":"settings.js"},
|
{ "name": "cassioWatch.settings.js","url": "settings.js" },
|
||||||
{ "name": "cassioWatch.img", "url": "icon.js", "evaluate": true }
|
{ "name": "cassioWatch.img", "url": "icon.js", "evaluate": true }
|
||||||
|
],
|
||||||
|
"data": [
|
||||||
|
{ "name": "cassioWatch.settings.json" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,3 +2,4 @@
|
||||||
0.02: Support BangleJS2
|
0.02: Support BangleJS2
|
||||||
0.03: Added threshold
|
0.03: Added threshold
|
||||||
0.04: Added notification
|
0.04: Added notification
|
||||||
|
0.05: Fixed boot
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
const pin = process.env.HWVERSION === 2 ? D3 : D30;
|
const pin = process.env.HWVERSION === 2 ? D3 : D30;
|
||||||
|
|
||||||
var id;
|
var id;
|
||||||
Bangle.on('charging', (charging) => {
|
function gent(charging) {
|
||||||
if (charging) {
|
if (charging) {
|
||||||
if (!id) {
|
if (!id) {
|
||||||
var max = 0;
|
var max = 0;
|
||||||
|
@ -37,5 +37,8 @@
|
||||||
require('notify').hide({id: 'chargent'});
|
require('notify').hide({id: 'chargent'});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
Bangle.on('charging', gent);
|
||||||
|
if (Bangle.isCharging()) gent(true);
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{ "id": "chargent",
|
{ "id": "chargent",
|
||||||
"name": "Charge Gently",
|
"name": "Charge Gently",
|
||||||
"version": "0.04",
|
"version": "0.05",
|
||||||
"description": "When charging, reminds you to disconnect the watch to prolong battery life.",
|
"description": "When charging, reminds you to disconnect the watch to prolong battery life.",
|
||||||
"icon": "icon.png",
|
"icon": "icon.png",
|
||||||
"type": "bootloader",
|
"type": "bootloader",
|
||||||
|
|
|
@ -11,5 +11,6 @@
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"chargerot.boot.js","url":"boot.js"},
|
{"name":"chargerot.boot.js","url":"boot.js"},
|
||||||
{"name":"chargerot.settings.js","url":"settings.js"}
|
{"name":"chargerot.settings.js","url":"settings.js"}
|
||||||
]
|
],
|
||||||
|
"data":[{"name":"chargerot.settings.json"}]
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AEnPAEAv/wAAcF6XWAAYdFBQgLLF/4v/F/4vTFKoLGF/4v/F/4v/F4QpWBQov/F7UslgKBAYIABEgIDDF/4v/F4es1gvTdKoLBFYYAHF/4vTmQvuvQwJFxAvbAAOIxIAFFxIvzFKYLG6CMNF8GsF92BdpwvfqwvtRwgvQAC+IxIAJF5QAYF93OwEyRwqSPACwsJGEov/AH4A/AH4AwA="))
|
|
@ -0,0 +1,283 @@
|
||||||
|
// Using p4wn chess engine: https://p4wn.sourceforge.net/ | https://github.com/douglasbagnall/p4wn
|
||||||
|
const engine = require("chessengine");
|
||||||
|
|
||||||
|
Bangle.loadWidgets(); // load before first appRect call
|
||||||
|
|
||||||
|
const FIELD_WIDTH = Bangle.appRect.w/8;
|
||||||
|
const FIELD_HEIGHT = Bangle.appRect.h/8;
|
||||||
|
const SETTINGS_FILE = "chess.json";
|
||||||
|
const DEFAULT_TIMEOUT = Bangle.getOptions().lockTimeout;
|
||||||
|
const ICON_SIZE=45;
|
||||||
|
const ICON_BISHOP = require("heatshrink").decompress(atob("lstwMB/4Ac/wFE4IED/kPAofgn4FDGon8j4QEBQgQE4EHBQcACwfAgF/BQYWD8EAHAX+NgI4C+AQEwAQDDYIhDDYMDCAQKBGQQsHHogKDCAJODCAI3CHoQKCHoIQDHoIQCFgoQBFgfgIQYmBEIQECKgIrCBYQKDC4OBg/8iCvEAC+AA="));
|
||||||
|
const ICON_PAWN = require("heatshrink").decompress(atob("lstwMB/4At/AFEGon4h4FDwE/AgX8CAngCAkAv4bDgYbECAf4gAhD4AhD/kAg4mDCAkACAYbBEIYQBG4gbDEII9DFhXAgEfBQYWDEwJUC/wKBGQXwCAgEBE4RCBCAYmBCAQmCCAQmBCAbdCCAIbCQ4gAYwA="));
|
||||||
|
const ICON_KING = require("heatshrink").decompress(atob("lstwMB/4Ac/wFE+4KEh4FD+F/AofvCwgKE+IKEg4bEj4FDwADC/k8g+HAoJhCC4PwAoQXBNod//AECgYfBAoUP/gQE8AQEBQcfCAaLBCAZmBEIZuBBQgyDJAIWCPgXAEAQWDBQRUCPgQnBHgJqBLwYhDOwRvDGQc/EIaSDCwLedwAA=="));
|
||||||
|
const ICON_QUEEN = require("heatshrink").decompress(atob("lstwMB/4Ac/l/AgXn4PzAgP+j0Ph4FB8FwuE///PgeDwPn/k8n0+j0f4Hz+Px8F+g/Px+fgf4vgACn/jAAf/x8Pj0en/8vAsB+P/+PBwcHj//w0MjEwJgMwsHBw5CBwMEhBDBPoR6B/gFCDYPgAoRZBAgUH//4AoQbB4AbDCAYbBCAZ1CAgJ7CwAKDGQQmBCAYmBEIQmC+AQEDYQQBDYQQCFgo3CXQIsFBYIEDACmAA="));
|
||||||
|
const ICON_ROOK = require("heatshrink").decompress(atob("lstwMB/4Ax/0HgPAAoPwnEOg4FBwBFBn///gEBI4XgAoMPAoJWCv4QDDYXwBQf/4AKD/wmDCARuDGQImCEIQbCGQMDCAQKBj4EB/AFBBQQsgDYQQCNQQhCOog3CCAQ3BEIRvCAoSRCE4IxCKgQmCKgYAZwA="));
|
||||||
|
const ICON_KNIGHT = require("heatshrink").decompress(atob("lstwMB/4Ann1/AgX48IKD4UPAgX+gEHAoXwgALDJQMfDYQFBEQWAgBSCBQQcC4AFBn///hnCBQPgAgMDGIQnDGIIQDAgQQBEwQQCGIIQCEwMECAQxBsAQBEwMPCAQmBAIJDB4EPDoM/CAIoBKgP4BQQQB/AzCKgJlIPgQ+COwJlCHoJlDJwJlDS4aBDDYQsCADOA"));
|
||||||
|
|
||||||
|
const settings = Object.assign({
|
||||||
|
state: engine.P4_INITIAL_BOARD,
|
||||||
|
computer_level: 0, // default to "stupid" which is the fastest
|
||||||
|
}, require("Storage").readJSON(SETTINGS_FILE,1) || {});
|
||||||
|
|
||||||
|
var ovr = Graphics.createArrayBuffer(Bangle.appRect.w,Bangle.appRect.h,2,{msb:true});
|
||||||
|
const curfield = [4*FIELD_WIDTH, 6*FIELD_HEIGHT]; // e2
|
||||||
|
const startfield = Array(2);
|
||||||
|
let piece_sel = 0;
|
||||||
|
let showmenu = false;
|
||||||
|
|
||||||
|
const writeSettings = () => {
|
||||||
|
settings.state = engine.p4_state2fen(state);
|
||||||
|
require('Storage').writeJSON(SETTINGS_FILE, settings);
|
||||||
|
};
|
||||||
|
|
||||||
|
const generateBgImage = () => {
|
||||||
|
var buf = Graphics.createArrayBuffer(Bangle.appRect.w,Bangle.appRect.h,1,{msb:true});
|
||||||
|
for(let idxrow=0; idxrow<8; idxrow++) {
|
||||||
|
for(let idxcol=0; idxcol<8; idxcol++) {
|
||||||
|
const bgCol = idxrow % 2 != idxcol % 2 ? 0 : 1;
|
||||||
|
const x = idxcol*FIELD_WIDTH;
|
||||||
|
const y = idxrow*FIELD_HEIGHT;
|
||||||
|
buf.setColor(bgCol).fillRect({x:x, y:y, w:FIELD_WIDTH, h:FIELD_HEIGHT});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {width:buf.getWidth(), height:buf.getHeight(),
|
||||||
|
buffer:buf.buffer
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const idx2Pos = (idxcol, idxrow) => {
|
||||||
|
"ram"
|
||||||
|
return 2*(1+8+1) + (7-idxrow)*(1+8+1) + idxcol + 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
const drawPiece = (buf, x, y, piece) => {
|
||||||
|
let icon;
|
||||||
|
|
||||||
|
switch(piece & ~0x1) {
|
||||||
|
case engine.P4_PAWN:
|
||||||
|
icon = ICON_PAWN;
|
||||||
|
break;
|
||||||
|
case engine.P4_BISHOP:
|
||||||
|
icon = ICON_BISHOP;
|
||||||
|
break;
|
||||||
|
case engine.P4_KING:
|
||||||
|
icon = ICON_KING;
|
||||||
|
break;
|
||||||
|
case engine.P4_QUEEN:
|
||||||
|
icon = ICON_QUEEN;
|
||||||
|
break;
|
||||||
|
case engine.P4_ROOK:
|
||||||
|
icon = ICON_ROOK;
|
||||||
|
break;
|
||||||
|
case engine.P4_KNIGHT:
|
||||||
|
icon = ICON_KNIGHT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (icon) {
|
||||||
|
const scale = FIELD_HEIGHT/ICON_SIZE;
|
||||||
|
buf.drawImage(icon, x+(FIELD_WIDTH-(ICON_SIZE*scale))/2, y, {scale: scale});
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
const drawBoard = () => {
|
||||||
|
//console.log("Free: " + process.memory().free);
|
||||||
|
|
||||||
|
g.setBgColor("#555").setColor("#aaa").drawImage(bgImage, Bangle.appRect.x, Bangle.appRect.y);
|
||||||
|
for(let idxrow=0; idxrow<8; idxrow++) {
|
||||||
|
for(let idxcol=0; idxcol<8; idxcol++) {
|
||||||
|
const x = idxcol*FIELD_WIDTH+Bangle.appRect.x;
|
||||||
|
const y = idxrow*FIELD_HEIGHT+Bangle.appRect.y;
|
||||||
|
|
||||||
|
const pos = idx2Pos(idxcol, idxrow);
|
||||||
|
const field = state.board[pos];
|
||||||
|
|
||||||
|
if (field) {
|
||||||
|
const fgCol = field & 0x1 ? "#000" : "#fff";
|
||||||
|
drawPiece(g.setBgColor(fgCol), x, y, field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const roundX = (x) => {
|
||||||
|
return Math.round(x/FIELD_WIDTH)*FIELD_WIDTH;
|
||||||
|
};
|
||||||
|
|
||||||
|
const roundY = (y) => {
|
||||||
|
return Math.round(y/FIELD_HEIGHT)*FIELD_HEIGHT;
|
||||||
|
};
|
||||||
|
|
||||||
|
const drawSelectedField = () => {
|
||||||
|
ovr.clear();
|
||||||
|
if (!showmenu) {
|
||||||
|
if (startfield[0] !== undefined && startfield[1] !== undefined) {
|
||||||
|
// remove piece from startfield
|
||||||
|
const x = startfield[0];
|
||||||
|
const y = startfield[1];
|
||||||
|
ovr.setColor(2).fillRect({x:x, y:y, w:FIELD_WIDTH, h:FIELD_HEIGHT});
|
||||||
|
}
|
||||||
|
|
||||||
|
const x = roundX(curfield[0]);
|
||||||
|
const y = roundY(curfield[1]);
|
||||||
|
ovr.setColor(piece_sel ? 1 : 2)
|
||||||
|
.drawRect({x:x+1, y:y, w:FIELD_WIDTH-2, h:FIELD_HEIGHT})
|
||||||
|
.drawRect({x:x+2, y:y+1, w:FIELD_WIDTH-4, h:FIELD_HEIGHT-2})
|
||||||
|
.drawRect({x:x+3, y:y+2, w:FIELD_WIDTH-6, h:FIELD_HEIGHT-4});
|
||||||
|
if (piece_sel) {
|
||||||
|
drawPiece(ovr.setBgColor(1), x, y, piece_sel);
|
||||||
|
ovr.setBgColor(0); // back to transparent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Bangle.setLCDOverlay({width:ovr.getWidth(), height:ovr.getHeight(),
|
||||||
|
bpp:2, transparent:0,
|
||||||
|
palette:new Uint16Array([0, g.toColor("#F00"), g.toColor("#0F0"), 0]),
|
||||||
|
buffer:ovr.buffer
|
||||||
|
},Bangle.appRect.x,Bangle.appRect.y);
|
||||||
|
};
|
||||||
|
|
||||||
|
const isInside = (rect, e) => {
|
||||||
|
return e.x>=rect.x && e.x<rect.x+rect.w
|
||||||
|
&& e.y>=rect.y && e.y<=rect.y+rect.h;
|
||||||
|
};
|
||||||
|
|
||||||
|
const showAlert = (msg) => {
|
||||||
|
showmenu = true;
|
||||||
|
drawSelectedField();
|
||||||
|
E.showAlert(msg).then(function() {
|
||||||
|
showmenu = false;
|
||||||
|
drawBoard();
|
||||||
|
drawSelectedField();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const move = (from,to) => {
|
||||||
|
const res = state.move(from, to);
|
||||||
|
//console.log(res);
|
||||||
|
if (!res.ok) {
|
||||||
|
showAlert("Illegal move");
|
||||||
|
} else {
|
||||||
|
if (res.flags & engine.P4_MOVE_FLAG_MATE) {
|
||||||
|
showAlert("Checkmate or stalemate");
|
||||||
|
} else if (res.flags & engine.P4_MOVE_FLAG_CHECK) {
|
||||||
|
showAlert("A king is in check");
|
||||||
|
} else if (res.flags & engine.P4_MOVE_FLAG_DRAW) {
|
||||||
|
showAlert("A draw is available");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
const showMessage = (msg) => {
|
||||||
|
g.setColor("#f00").setFont("4x6:2").setFontAlign(-1,1).drawString(msg, 10, Bangle.appRect.y2-10);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Run
|
||||||
|
|
||||||
|
g.reset();
|
||||||
|
const bgImage = generateBgImage();
|
||||||
|
let state = engine.p4_fen2state(settings.state);
|
||||||
|
drawBoard();
|
||||||
|
drawSelectedField();
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
|
||||||
|
// drag selected field
|
||||||
|
Bangle.on('drag', (ev) => {
|
||||||
|
const newx = curfield[0]+ev.dx;
|
||||||
|
const newy = curfield[1]+ev.dy;
|
||||||
|
if (newx >= 0 && newx <= 7*FIELD_WIDTH) {
|
||||||
|
curfield[0] = newx;
|
||||||
|
}
|
||||||
|
if (newy >= 0 && newy <= 7*FIELD_HEIGHT) {
|
||||||
|
curfield[1] = newy;
|
||||||
|
}
|
||||||
|
drawSelectedField();
|
||||||
|
});
|
||||||
|
|
||||||
|
// touch to start/stop moving a piece
|
||||||
|
Bangle.on('touch', (button, xy) => {
|
||||||
|
if (isInside(Bangle.appRect, xy) && !showmenu) {
|
||||||
|
if (piece_sel === 0) {
|
||||||
|
startfield[0] = roundX(curfield[0]);
|
||||||
|
startfield[1] = roundY(curfield[1]);
|
||||||
|
const startpos = idx2Pos(startfield[0]/FIELD_WIDTH, startfield[1]/FIELD_HEIGHT);
|
||||||
|
piece_sel = state.board[startpos];
|
||||||
|
if (piece_sel === 0) {
|
||||||
|
startfield[0] = startfield[1] = undefined;
|
||||||
|
// nothing here, do nothing
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else { // piece_sel === 0
|
||||||
|
const colTo = roundX(curfield[0]);
|
||||||
|
const rowTo = roundY(curfield[1]);
|
||||||
|
if (startfield[0] !== colTo || startfield[1] !== rowTo) {
|
||||||
|
showMessage(/*LANG*/"Moving..");
|
||||||
|
const posFrom = idx2Pos(startfield[0]/FIELD_WIDTH, startfield[1]/FIELD_HEIGHT);
|
||||||
|
const posTo = idx2Pos(colTo/FIELD_WIDTH, rowTo/FIELD_HEIGHT);
|
||||||
|
setTimeout(() => {
|
||||||
|
if (move(posFrom, posTo).ok) {
|
||||||
|
// human move ok, update
|
||||||
|
drawBoard();
|
||||||
|
drawSelectedField();
|
||||||
|
// do computer move
|
||||||
|
Bangle.setLCDTimeout(0.1); // this can take some time, turn off to save power
|
||||||
|
showMessage(/*LANG*/"Calculating..");
|
||||||
|
setTimeout(() => {
|
||||||
|
const compMove = state.findmove(settings.computer_level+1);
|
||||||
|
const result = move(compMove[0], compMove[1]);
|
||||||
|
writeSettings();
|
||||||
|
Bangle.setLCDPower(true);
|
||||||
|
Bangle.setLocked(false);
|
||||||
|
Bangle.setLCDTimeout(DEFAULT_TIMEOUT/1000); // restore
|
||||||
|
if (!showmenu) {
|
||||||
|
showAlert(result.string);
|
||||||
|
}
|
||||||
|
}, 200); // execute after display update
|
||||||
|
}
|
||||||
|
}, 100); // execute after display update
|
||||||
|
} // piece_sel === 0
|
||||||
|
startfield[0] = startfield[1] = undefined;
|
||||||
|
piece_sel = 0;
|
||||||
|
}
|
||||||
|
drawSelectedField();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// show menu on button
|
||||||
|
setWatch(() => {
|
||||||
|
showmenu = true;
|
||||||
|
drawSelectedField();
|
||||||
|
|
||||||
|
const closeMenu = () => {
|
||||||
|
showmenu = false;
|
||||||
|
E.showMenu();
|
||||||
|
drawBoard();
|
||||||
|
drawSelectedField();
|
||||||
|
};
|
||||||
|
|
||||||
|
E.showMenu({
|
||||||
|
"" : { title : /*LANG*/"Chess settings" },
|
||||||
|
"< Back" : () => closeMenu(),
|
||||||
|
/*LANG*/"New Game" : () => {
|
||||||
|
state = engine.p4_fen2state(engine.P4_INITIAL_BOARD);
|
||||||
|
writeSettings();
|
||||||
|
closeMenu();
|
||||||
|
},
|
||||||
|
/*LANG*/"Undo Move" : () => {
|
||||||
|
state.jump_to_moveno(-2);
|
||||||
|
closeMenu();
|
||||||
|
},
|
||||||
|
/*LANG*/'Level': {
|
||||||
|
value: settings.computer_level,
|
||||||
|
min: 0, max: 4,
|
||||||
|
format: v => [/*LANG*/'stupid', /*LANG*/'middling', /*LANG*/'default', /*LANG*/'slow', /*LANG*/'slowest'][v],
|
||||||
|
onchange: v => {
|
||||||
|
settings.computer_level = v;
|
||||||
|
writeSettings();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/*LANG*/"Exit" : () => load(),
|
||||||
|
});
|
||||||
|
}, BTN, { repeat: true, edge: "falling" });
|
After Width: | Height: | Size: 445 B |
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"id": "chess",
|
||||||
|
"name": "Chess",
|
||||||
|
"shortName": "Chess",
|
||||||
|
"version": "0.01",
|
||||||
|
"description": "Chess game based on the [p4wn engine](https://p4wn.sourceforge.net/). Drag on the touchscreen to move the green cursor onto a piece, select it with a single touch and drag the now red cursor around. Release the piece with another touch to finish the move. The button opens a menu.",
|
||||||
|
"icon": "app.png",
|
||||||
|
"tags": "game",
|
||||||
|
"supports": ["BANGLEJS2"],
|
||||||
|
"storage": [
|
||||||
|
{"name":"chess.app.js","url":"app.js"},
|
||||||
|
{"name":"chessengine","url":"engine.js"},
|
||||||
|
{"name":"chess.img","url":"app-icon.js","evaluate":true}
|
||||||
|
],
|
||||||
|
"data": [{"name":"chess.json"}],
|
||||||
|
"screenshots": [ {"url":"screenshot.png"} ]
|
||||||
|
}
|
After Width: | Height: | Size: 3.5 KiB |
|
@ -1,3 +1,4 @@
|
||||||
0.01: Initial Creation
|
0.01: Initial Creation
|
||||||
0.02: Fixed some sleep bugs. Added a sleep mode toggle
|
0.02: Fixed some sleep bugs. Added a sleep mode toggle
|
||||||
0.03: Reduce busy-loop and code
|
0.03: Reduce busy-loop and code
|
||||||
|
0.04: Separate buzz-time and sleep-time
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "chimer",
|
"id": "chimer",
|
||||||
"name": "Chimer",
|
"name": "Chimer",
|
||||||
"version": "0.03",
|
"version": "0.04",
|
||||||
"description": "A fork of Hour Chime that adds extra features such as: \n - Buzz or beep on every 60, 30 or 15 minutes. \n - Repeat Chime up to 3 times \n - Set hours to disable chime",
|
"description": "A fork of Hour Chime that adds extra features such as: \n - Buzz or beep on every 60, 30 or 15 minutes. \n - Repeat Chime up to 3 times \n - Set hours to disable chime",
|
||||||
"icon": "widget.png",
|
"icon": "widget.png",
|
||||||
"type": "widget",
|
"type": "widget",
|
||||||
|
|
|
@ -20,15 +20,16 @@
|
||||||
let count = settings.repeat;
|
let count = settings.repeat;
|
||||||
|
|
||||||
const chime1 = () => {
|
const chime1 = () => {
|
||||||
|
let p;
|
||||||
if (settings.type === 1) {
|
if (settings.type === 1) {
|
||||||
Bangle.buzz(100);
|
p = Bangle.buzz(100);
|
||||||
} else if (settings.type === 2) {
|
} else if (settings.type === 2) {
|
||||||
Bangle.beep();
|
p = Bangle.beep();
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (--count > 0)
|
if (--count > 0)
|
||||||
setTimeout(chime1, 150);
|
p.then(() => setTimeout(chime1, 150));
|
||||||
};
|
};
|
||||||
|
|
||||||
chime1();
|
chime1();
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
const enum StopWatchFormat {
|
|
||||||
HMS,
|
|
||||||
Colon,
|
|
||||||
}
|
|
||||||
type StopWatchSettings = {
|
|
||||||
format: StopWatchFormat,
|
|
||||||
};
|
|
||||||
|
|
||||||
(back => {
|
|
||||||
const SETTINGS_FILE = "clkinfostopw.setting.json";
|
|
||||||
|
|
||||||
const storage = require("Storage");
|
|
||||||
const settings: StopWatchSettings = Object.assign(
|
|
||||||
{ format: StopWatchFormat.HMS },
|
|
||||||
storage.readJSON(SETTINGS_FILE, true),
|
|
||||||
);
|
|
||||||
|
|
||||||
const save = () => {
|
|
||||||
storage.writeJSON(SETTINGS_FILE, settings)
|
|
||||||
};
|
|
||||||
|
|
||||||
E.showMenu({
|
|
||||||
"": { "title": "stopwatch" },
|
|
||||||
"< Back": back,
|
|
||||||
"Format": {
|
|
||||||
value: settings.format,
|
|
||||||
min: StopWatchFormat.HMS,
|
|
||||||
max: StopWatchFormat.Colon,
|
|
||||||
format: v => v === StopWatchFormat.HMS ? "12m34s" : "12:34",
|
|
||||||
onchange: v => {
|
|
||||||
settings.format = v;
|
|
||||||
save();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}) satisfies SettingsFunc
|
|
|
@ -5,6 +5,7 @@
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "clkinfo",
|
"type": "clkinfo",
|
||||||
"tags": "clkinfo,sunrise",
|
"tags": "clkinfo,sunrise",
|
||||||
|
"dependencies": {"mylocation":"app"},
|
||||||
"supports" : ["BANGLEJS2"],
|
"supports" : ["BANGLEJS2"],
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"sunrise.clkinfo.js","url":"clkinfo.js"}
|
{"name":"sunrise.clkinfo.js","url":"clkinfo.js"}
|
||||||
|
|
|
@ -3,4 +3,5 @@
|
||||||
0.03: Reported image for battery now reflects charge level
|
0.03: Reported image for battery now reflects charge level
|
||||||
0.04: On 2v18+ firmware, we can now stop swipe events from being handled by other apps
|
0.04: On 2v18+ firmware, we can now stop swipe events from being handled by other apps
|
||||||
eg. when a clockinfo is selected, swipes won't affect swipe-down widgets
|
eg. when a clockinfo is selected, swipes won't affect swipe-down widgets
|
||||||
0.05: Reported image for battery is now transparent (2v18+)
|
0.05: Reported image for battery is now transparent (2v18+)
|
||||||
|
0.06: When >1 clockinfo, swiping one back tries to ensure they don't display the same thing
|
|
@ -10,7 +10,12 @@ if (stepGoal == undefined) {
|
||||||
stepGoal = d != undefined && d.settings != undefined ? d.settings.goal : 10000;
|
stepGoal = d != undefined && d.settings != undefined ? d.settings.goal : 10000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the settings, with defaults
|
/// How many times has addInteractive been called?
|
||||||
|
exports.loadCount = 0;
|
||||||
|
/// A list of all the instances returned by addInteractive
|
||||||
|
exports.clockInfos = [];
|
||||||
|
|
||||||
|
/// Load the settings, with defaults
|
||||||
exports.loadSettings = function() {
|
exports.loadSettings = function() {
|
||||||
return Object.assign({
|
return Object.assign({
|
||||||
hrmOn : 0, // 0(Always), 1(Tap)
|
hrmOn : 0, // 0(Always), 1(Tap)
|
||||||
|
@ -22,6 +27,7 @@ exports.loadSettings = function() {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Load a list of ClockInfos - this does not cache and reloads each time
|
||||||
exports.load = function() {
|
exports.load = function() {
|
||||||
var settings = exports.loadSettings();
|
var settings = exports.loadSettings();
|
||||||
delete settings.apps; // keep just the basic settings in memory
|
delete settings.apps; // keep just the basic settings in memory
|
||||||
|
@ -63,7 +69,7 @@ exports.load = function() {
|
||||||
} else img=atob("GBiBAAABgAADwAAHwAAPgACfAAHOAAPkBgHwDwP4Hwf8Pg/+fB//OD//kD//wD//4D//8D//4B//QB/+AD/8AH/4APnwAHAAACAAAA==");
|
} else img=atob("GBiBAAABgAADwAAHwAAPgACfAAHOAAPkBgHwDwP4Hwf8Pg/+fB//OD//kD//wD//4D//8D//4B//QB/+AD/8AH/4APnwAHAAACAAAA==");
|
||||||
return {
|
return {
|
||||||
text : v + "%", v : v, min:0, max:100, img : img
|
text : v + "%", v : v, min:0, max:100, img : img
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
show : function() { this.interval = setInterval(()=>this.emit('redraw'), 60000); Bangle.on("charging", batteryUpdateHandler); batteryUpdateHandler(); },
|
show : function() { this.interval = setInterval(()=>this.emit('redraw'), 60000); Bangle.on("charging", batteryUpdateHandler); batteryUpdateHandler(); },
|
||||||
hide : function() { clearInterval(this.interval); delete this.interval; Bangle.removeListener("charging", batteryUpdateHandler); },
|
hide : function() { clearInterval(this.interval); delete this.interval; Bangle.removeListener("charging", batteryUpdateHandler); },
|
||||||
|
@ -73,7 +79,7 @@ exports.load = function() {
|
||||||
get : () => { let v = Bangle.getHealthStatus("day").steps; return {
|
get : () => { let v = Bangle.getHealthStatus("day").steps; return {
|
||||||
text : v, v : v, min : 0, max : stepGoal,
|
text : v, v : v, min : 0, max : stepGoal,
|
||||||
img : atob("GBiBAAcAAA+AAA/AAA/AAB/AAB/gAA/g4A/h8A/j8A/D8A/D+AfH+AAH8AHn8APj8APj8AHj4AHg4AADAAAHwAAHwAAHgAAHgAADAA==")
|
img : atob("GBiBAAcAAA+AAA/AAA/AAB/AAB/gAA/g4A/h8A/j8A/D8A/D+AfH+AAH8AHn8APj8APj8AHj4AHg4AADAAAHwAAHwAAHgAAHgAADAA==")
|
||||||
}},
|
};},
|
||||||
show : function() { Bangle.on("step", stepUpdateHandler); stepUpdateHandler(); },
|
show : function() { Bangle.on("step", stepUpdateHandler); stepUpdateHandler(); },
|
||||||
hide : function() { Bangle.removeListener("step", stepUpdateHandler); },
|
hide : function() { Bangle.removeListener("step", stepUpdateHandler); },
|
||||||
},
|
},
|
||||||
|
@ -82,7 +88,7 @@ exports.load = function() {
|
||||||
get : () => { return {
|
get : () => { return {
|
||||||
text : (hrm||"--") + " bpm", v : hrm, min : 40, max : 200,
|
text : (hrm||"--") + " bpm", v : hrm, min : 40, max : 200,
|
||||||
img : atob("GBiBAAAAAAAAAAAAAAAAAAAAAADAAADAAAHAAAHjAAHjgAPngH9n/n82/gA+AAA8AAA8AAAcAAAYAAAYAAAAAAAAAAAAAAAAAAAAAA==")
|
img : atob("GBiBAAAAAAAAAAAAAAAAAAAAAADAAADAAAHAAAHjAAHjgAPngH9n/n82/gA+AAA8AAA8AAAcAAAYAAAYAAAAAAAAAAAAAAAAAAAAAA==")
|
||||||
}},
|
};},
|
||||||
run : function() {
|
run : function() {
|
||||||
Bangle.setHRMPower(1,"clkinfo");
|
Bangle.setHRMPower(1,"clkinfo");
|
||||||
if (settings.hrmOn==1/*Tap*/) {
|
if (settings.hrmOn==1/*Tap*/) {
|
||||||
|
@ -131,11 +137,11 @@ exports.load = function() {
|
||||||
require("Storage").list(/clkinfo.js$/).forEach(fn => {
|
require("Storage").list(/clkinfo.js$/).forEach(fn => {
|
||||||
try{
|
try{
|
||||||
var a = eval(require("Storage").read(fn))();
|
var a = eval(require("Storage").read(fn))();
|
||||||
var b = menu.find(x => x.name === a.name)
|
var b = menu.find(x => x.name === a.name);
|
||||||
if(b) b.items = b.items.concat(a.items);
|
if(b) b.items = b.items.concat(a.items);
|
||||||
else menu = menu.concat(a);
|
else menu = menu.concat(a);
|
||||||
} catch(e){
|
} catch(e){
|
||||||
console.log("Could not load clock info "+E.toJS(fn))
|
console.log("Could not load clock info "+E.toJS(fn));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -204,11 +210,12 @@ exports.addInteractive = function(menu, options) {
|
||||||
if ("function" == typeof options) options = {draw:options}; // backwards compatibility
|
if ("function" == typeof options) options = {draw:options}; // backwards compatibility
|
||||||
options.index = 0|exports.loadCount;
|
options.index = 0|exports.loadCount;
|
||||||
exports.loadCount = options.index+1;
|
exports.loadCount = options.index+1;
|
||||||
|
exports.clockInfos[options.index] = options;
|
||||||
options.focus = options.index==0 && options.x===undefined; // focus if we're the first one loaded and no position has been defined
|
options.focus = options.index==0 && options.x===undefined; // focus if we're the first one loaded and no position has been defined
|
||||||
const appName = (options.app||"default")+":"+options.index;
|
const appName = (options.app||"default")+":"+options.index;
|
||||||
|
|
||||||
// load the currently showing clock_infos
|
// load the currently showing clock_infos
|
||||||
let settings = exports.loadSettings()
|
let settings = exports.loadSettings();
|
||||||
if (settings.apps[appName]) {
|
if (settings.apps[appName]) {
|
||||||
let a = settings.apps[appName].a|0;
|
let a = settings.apps[appName].a|0;
|
||||||
let b = settings.apps[appName].b|0;
|
let b = settings.apps[appName].b|0;
|
||||||
|
@ -259,6 +266,10 @@ exports.addInteractive = function(menu, options) {
|
||||||
//can happen for dynamic ones (alarms, events)
|
//can happen for dynamic ones (alarms, events)
|
||||||
//in the worst case we come back to 0
|
//in the worst case we come back to 0
|
||||||
} while(menu[options.menuA].items.length==0);
|
} while(menu[options.menuA].items.length==0);
|
||||||
|
// When we change, ensure we don't display the same thing as another clockinfo if we can avoid it
|
||||||
|
while ((options.menuB < menu[options.menuA].items.length) &&
|
||||||
|
exports.clockInfos.some(m => (m!=options) && m.menuA==options.menuA && m.menuB==options.menuB))
|
||||||
|
options.menuB++;
|
||||||
}
|
}
|
||||||
if (oldMenuItem) {
|
if (oldMenuItem) {
|
||||||
menuHideItem(oldMenuItem);
|
menuHideItem(oldMenuItem);
|
||||||
|
@ -319,6 +330,7 @@ exports.addInteractive = function(menu, options) {
|
||||||
delete Bangle.CLKINFO_FOCUS;
|
delete Bangle.CLKINFO_FOCUS;
|
||||||
menuHideItem(menu[options.menuA].items[options.menuB]);
|
menuHideItem(menu[options.menuA].items[options.menuB]);
|
||||||
exports.loadCount--;
|
exports.loadCount--;
|
||||||
|
delete exports.clockInfos[options.index];
|
||||||
};
|
};
|
||||||
options.redraw = function() {
|
options.redraw = function() {
|
||||||
drawItem(menu[options.menuA].items[options.menuB]);
|
drawItem(menu[options.menuA].items[options.menuB]);
|
||||||
|
@ -339,8 +351,7 @@ exports.addInteractive = function(menu, options) {
|
||||||
menuShowItem(menu[options.menuA].items[options.menuB]);
|
menuShowItem(menu[options.menuA].items[options.menuB]);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
};
|
||||||
|
|
||||||
delete settings; // don't keep settings in RAM - save space
|
delete settings; // don't keep settings in RAM - save space
|
||||||
return options;
|
return options;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{ "id": "clock_info",
|
{ "id": "clock_info",
|
||||||
"name": "Clock Info Module",
|
"name": "Clock Info Module",
|
||||||
"shortName": "Clock Info",
|
"shortName": "Clock Info",
|
||||||
"version":"0.05",
|
"version":"0.06",
|
||||||
"description": "A library used by clocks to provide extra information on the clock face (Altitude, BPM, etc)",
|
"description": "A library used by clocks to provide extra information on the clock face (Altitude, BPM, etc)",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
|
@ -6,3 +6,4 @@
|
||||||
0.06: Add button for force compass calibration
|
0.06: Add button for force compass calibration
|
||||||
0.07: Use 360-heading to output the correct heading value (fix #1866)
|
0.07: Use 360-heading to output the correct heading value (fix #1866)
|
||||||
0.08: Added adjustment for Bangle.js magnetometer heading fix
|
0.08: Added adjustment for Bangle.js magnetometer heading fix
|
||||||
|
0.09: use falling edge of button to reset compass (allows exit without compass reset)
|
|
@ -68,7 +68,7 @@ g.clear(1);
|
||||||
g.setFont("6x8").setFontAlign(0,0,3).drawString(/*LANG*/"RESET", g.getWidth()-5, g.getHeight()/2);
|
g.setFont("6x8").setFontAlign(0,0,3).drawString(/*LANG*/"RESET", g.getWidth()-5, g.getHeight()/2);
|
||||||
setWatch(function() {
|
setWatch(function() {
|
||||||
Bangle.resetCompass();
|
Bangle.resetCompass();
|
||||||
}, (process.env.HWVERSION==2) ? BTN1 : BTN2, {repeat:true});
|
}, (process.env.HWVERSION==2) ? BTN1 : BTN2, {repeat:true, edge:"falling"});
|
||||||
|
|
||||||
Bangle.loadWidgets();
|
Bangle.loadWidgets();
|
||||||
Bangle.drawWidgets();
|
Bangle.drawWidgets();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "compass",
|
"id": "compass",
|
||||||
"name": "Compass",
|
"name": "Compass",
|
||||||
"version": "0.08",
|
"version": "0.09",
|
||||||
"description": "Simple compass that points North",
|
"description": "Simple compass that points North",
|
||||||
"icon": "compass.png",
|
"icon": "compass.png",
|
||||||
"screenshots": [{"url":"screenshot_compass.png"}],
|
"screenshots": [{"url":"screenshot_compass.png"}],
|
||||||
|
|
|
@ -15,5 +15,6 @@
|
||||||
{"name":"contourclock.settings.js","url":"contourclock.settings.js"},
|
{"name":"contourclock.settings.js","url":"contourclock.settings.js"},
|
||||||
{"name":"contourclock","url":"lib.js"},
|
{"name":"contourclock","url":"lib.js"},
|
||||||
{"name":"contourclock.img","url":"app-icon.js","evaluate":true}
|
{"name":"contourclock.img","url":"app-icon.js","evaluate":true}
|
||||||
]
|
],
|
||||||
|
"data": [{"name":"contourclock.json"}]
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,5 +13,6 @@
|
||||||
{"name":"cprassist.app.js","url":"cprassist.js"},
|
{"name":"cprassist.app.js","url":"cprassist.js"},
|
||||||
{"name":"cprassist.img","url":"cprassist-icon.js","evaluate":true},
|
{"name":"cprassist.img","url":"cprassist-icon.js","evaluate":true},
|
||||||
{"name":"cprassist.settings.js","url":"settings.js"}
|
{"name":"cprassist.settings.js","url":"settings.js"}
|
||||||
]
|
],
|
||||||
|
"data":[{"name":"cprassist.settings.json"}]
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,5 +12,8 @@
|
||||||
{"name":"cscsensor.app.js","url":"cscsensor.app.js"},
|
{"name":"cscsensor.app.js","url":"cscsensor.app.js"},
|
||||||
{"name":"cscsensor.settings.js","url":"settings.js"},
|
{"name":"cscsensor.settings.js","url":"settings.js"},
|
||||||
{"name":"cscsensor.img","url":"cscsensor-icon.js","evaluate":true}
|
{"name":"cscsensor.img","url":"cscsensor-icon.js","evaluate":true}
|
||||||
|
],
|
||||||
|
"data": [
|
||||||
|
{"name":"cscsensor.json"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,5 +13,8 @@
|
||||||
{"name":"cycling.settings.js","url":"settings.js"},
|
{"name":"cycling.settings.js","url":"settings.js"},
|
||||||
{"name":"blecsc","url":"blecsc.js"},
|
{"name":"blecsc","url":"blecsc.js"},
|
||||||
{"name":"cycling.img","url":"cycling.icon.js","evaluate": true}
|
{"name":"cycling.img","url":"cycling.icon.js","evaluate": true}
|
||||||
|
],
|
||||||
|
"data": [
|
||||||
|
{"name":"cycling.json"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,13 @@
|
||||||
"type":"textinput",
|
"type":"textinput",
|
||||||
"tags": "keyboard",
|
"tags": "keyboard",
|
||||||
"supports" : ["BANGLEJS2"],
|
"supports" : ["BANGLEJS2"],
|
||||||
"screenshots": [{"url":"screenshot.png"}],
|
"screenshots": [{"url":"screenshot.png"}],
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"textinput","url":"lib.js"},
|
{"name":"textinput","url":"lib.js"},
|
||||||
{"name":"dragboard.settings.js","url":"settings.js"}
|
{"name":"dragboard.settings.js","url":"settings.js"}
|
||||||
|
],
|
||||||
|
"data": [
|
||||||
|
{"name":"dragboard.json"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,13 @@
|
||||||
"type":"textinput",
|
"type":"textinput",
|
||||||
"tags": "keyboard",
|
"tags": "keyboard",
|
||||||
"supports" : ["BANGLEJS2"],
|
"supports" : ["BANGLEJS2"],
|
||||||
"screenshots": [{"url":"screenshot.png"}],
|
"screenshots": [{"url":"screenshot.png"}],
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"textinput","url":"lib.js"},
|
{"name":"textinput","url":"lib.js"},
|
||||||
{"name":"draguboard.settings.js","url":"settings.js"}
|
{"name":"draguboard.settings.js","url":"settings.js"}
|
||||||
|
],
|
||||||
|
"data": [
|
||||||
|
{"name":"draguboard.json"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,5 +12,6 @@
|
||||||
{"name":"f9lander.app.js","url":"app.js"},
|
{"name":"f9lander.app.js","url":"app.js"},
|
||||||
{"name":"f9lander.img","url":"app-icon.js","evaluate":true},
|
{"name":"f9lander.img","url":"app-icon.js","evaluate":true},
|
||||||
{"name":"f9lander.settings.js", "url":"settings.js"}
|
{"name":"f9lander.settings.js", "url":"settings.js"}
|
||||||
]
|
],
|
||||||
|
"data":[{"name":"f9settings.json"}]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
0.01: New App!
|
0.01: New App!
|
||||||
0.02: Allow redirection of loads to the launcher
|
0.02: Allow redirection of loads to the launcher
|
||||||
0.03: Allow hiding the fastloading info screen
|
0.03: Allow hiding the fastloading info screen
|
||||||
|
0.04: (WIP) Allow use of app history when going back (`load()` or `Bangle.load()` calls without specified app).
|
||||||
|
|
|
@ -8,9 +8,16 @@ This allows fast loading of all apps with two conditions:
|
||||||
|
|
||||||
## Settings
|
## Settings
|
||||||
|
|
||||||
|
* Activate app history and navigate back through recent apps instead of immediately loading the clock face
|
||||||
|
* If Quick Launch is installed it can be excluded from app history
|
||||||
* Allows to redirect all loads usually loading the clock to the launcher instead
|
* Allows to redirect all loads usually loading the clock to the launcher instead
|
||||||
* The "Fastloading..." screen can be switched off
|
* The "Fastloading..." screen can be switched off
|
||||||
|
|
||||||
|
## App history
|
||||||
|
|
||||||
|
* Long press of hardware button clears the app history and loads the clock face
|
||||||
|
* Installing the 'Fast Reset' app allows doing fastloads directly to the clock face by pressing the hardware button for one second. Useful if there are many apps in the history and the user want to access the clock quickly.
|
||||||
|
|
||||||
## Technical infos
|
## Technical infos
|
||||||
|
|
||||||
This is still experimental but it uses the same mechanism as `.bootcde` does.
|
This is still experimental but it uses the same mechanism as `.bootcde` does.
|
||||||
|
@ -19,3 +26,6 @@ It checks the app to be loaded for widget use and stores the result of that and
|
||||||
# Creator
|
# Creator
|
||||||
|
|
||||||
[halemmerich](https://github.com/halemmerich)
|
[halemmerich](https://github.com/halemmerich)
|
||||||
|
|
||||||
|
# Contributors
|
||||||
|
[thyttan](https://github.com/thyttan)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
const SETTINGS = require("Storage").readJSON("fastload.json") || {};
|
const s = require("Storage");
|
||||||
|
const SETTINGS = s.readJSON("fastload.json") || {};
|
||||||
|
|
||||||
let loadingScreen = function(){
|
let loadingScreen = function(){
|
||||||
g.reset();
|
g.reset();
|
||||||
|
@ -16,26 +17,26 @@ let loadingScreen = function(){
|
||||||
g.flip(true);
|
g.flip(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
let cache = require("Storage").readJSON("fastload.cache") || {};
|
let cache = s.readJSON("fastload.cache") || {};
|
||||||
|
|
||||||
let checkApp = function(n){
|
let checkApp = function(n){
|
||||||
// no widgets, no problem
|
// no widgets, no problem
|
||||||
if (!global.WIDGETS) return true;
|
if (!global.WIDGETS) return true;
|
||||||
let app = require("Storage").read(n);
|
let app = s.read(n);
|
||||||
if (cache[n] && E.CRC32(app) == cache[n].crc)
|
if (cache[n] && E.CRC32(app) == cache[n].crc)
|
||||||
return cache[n].fast
|
return cache[n].fast;
|
||||||
cache[n] = {};
|
cache[n] = {};
|
||||||
cache[n].fast = app.includes("Bangle.loadWidgets");
|
cache[n].fast = app.includes("Bangle.loadWidgets");
|
||||||
cache[n].crc = E.CRC32(app);
|
cache[n].crc = E.CRC32(app);
|
||||||
require("Storage").writeJSON("fastload.cache", cache);
|
s.writeJSON("fastload.cache", cache);
|
||||||
return cache[n].fast;
|
return cache[n].fast;
|
||||||
}
|
};
|
||||||
|
|
||||||
global._load = load;
|
global._load = load;
|
||||||
|
|
||||||
let slowload = function(n){
|
let slowload = function(n){
|
||||||
global._load(n);
|
global._load(n);
|
||||||
}
|
};
|
||||||
|
|
||||||
let fastload = function(n){
|
let fastload = function(n){
|
||||||
if (!n || checkApp(n)){
|
if (!n || checkApp(n)){
|
||||||
|
@ -50,17 +51,40 @@ let fastload = function(n){
|
||||||
};
|
};
|
||||||
global.load = fastload;
|
global.load = fastload;
|
||||||
|
|
||||||
|
let appHistory, resetHistory, recordHistory;
|
||||||
|
if (SETTINGS.useAppHistory){
|
||||||
|
appHistory = s.readJSON("fastload.history.json",true)||[];
|
||||||
|
resetHistory = ()=>{appHistory=[];s.writeJSON("fastload.history.json",appHistory);};
|
||||||
|
recordHistory = ()=>{s.writeJSON("fastload.history.json",appHistory);};
|
||||||
|
}
|
||||||
|
|
||||||
Bangle.load = (o => (name) => {
|
Bangle.load = (o => (name) => {
|
||||||
if (Bangle.uiRemove && !SETTINGS.hideLoading) loadingScreen();
|
if (Bangle.uiRemove && !SETTINGS.hideLoading) loadingScreen();
|
||||||
|
if (SETTINGS.useAppHistory){
|
||||||
|
if (name && name!=".bootcde" && !(name=="quicklaunch.app.js" && SETTINGS.disregardQuicklaunch)) {
|
||||||
|
// store the name of the app to launch
|
||||||
|
appHistory.push(name);
|
||||||
|
} else if (name==".bootcde") { // when Bangle.showClock is called
|
||||||
|
resetHistory();
|
||||||
|
} else if (name=="quicklaunch.app.js" && SETTINGS.disregardQuicklaunch) {
|
||||||
|
// do nothing with history
|
||||||
|
} else {
|
||||||
|
// go back in history
|
||||||
|
appHistory.pop();
|
||||||
|
name = appHistory[appHistory.length-1];
|
||||||
|
}
|
||||||
|
}
|
||||||
if (SETTINGS.autoloadLauncher && !name){
|
if (SETTINGS.autoloadLauncher && !name){
|
||||||
let orig = Bangle.load;
|
let orig = Bangle.load;
|
||||||
Bangle.load = (n)=>{
|
Bangle.load = (n)=>{
|
||||||
Bangle.load = orig;
|
Bangle.load = orig;
|
||||||
fastload(n);
|
fastload(n);
|
||||||
}
|
};
|
||||||
Bangle.showLauncher();
|
Bangle.showLauncher();
|
||||||
Bangle.load = orig;
|
Bangle.load = orig;
|
||||||
} else
|
} else
|
||||||
o(name);
|
o(name);
|
||||||
})(Bangle.load);
|
})(Bangle.load);
|
||||||
|
|
||||||
|
if (SETTINGS.useAppHistory) E.on('kill', ()=>{if (!BTN.read()) recordHistory(); else resetHistory();}); // Usually record history, but reset it if long press of HW button was used.
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{ "id": "fastload",
|
{ "id": "fastload",
|
||||||
"name": "Fastload Utils",
|
"name": "Fastload Utils",
|
||||||
"shortName" : "Fastload Utils",
|
"shortName" : "Fastload Utils",
|
||||||
"version": "0.03",
|
"version": "0.04",
|
||||||
"icon": "icon.png",
|
"icon": "icon.png",
|
||||||
"description": "Enable experimental fastloading for more apps",
|
"description": "Enable experimental fastloading for more apps",
|
||||||
"type":"bootloader",
|
"type":"bootloader",
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
(function(back) {
|
(function(back) {
|
||||||
var FILE="fastload.json";
|
var FILE="fastload.json";
|
||||||
var settings;
|
var settings;
|
||||||
|
var isQuicklaunchPresent = !!require('Storage').read("quicklaunch.app.js", 0, 1);
|
||||||
|
|
||||||
function writeSettings(key, value) {
|
function writeSettings(key, value) {
|
||||||
var s = require('Storage').readJSON(FILE, true) || {};
|
var s = require('Storage').readJSON(FILE, true) || {};
|
||||||
s[key] = value;
|
s[key] = value;
|
||||||
|
@ -12,25 +13,52 @@
|
||||||
function readSettings(){
|
function readSettings(){
|
||||||
settings = require('Storage').readJSON(FILE, true) || {};
|
settings = require('Storage').readJSON(FILE, true) || {};
|
||||||
}
|
}
|
||||||
|
|
||||||
readSettings();
|
readSettings();
|
||||||
|
|
||||||
function buildMainMenu(){
|
function buildMainMenu(){
|
||||||
var mainmenu = {
|
var mainmenu = {};
|
||||||
'': { 'title': 'Fastload', back: back },
|
|
||||||
'Force load to launcher': {
|
mainmenu[''] = { 'title': 'Fastload', back: back };
|
||||||
|
|
||||||
|
mainmenu['Activate app history'] = {
|
||||||
|
value: !!settings.useAppHistory,
|
||||||
|
onchange: v => {
|
||||||
|
writeSettings("useAppHistory",v);
|
||||||
|
if (v && settings.autoloadLauncher) {
|
||||||
|
writeSettings("autoloadLauncher",!v); // Don't use app history and load to launcher together.
|
||||||
|
setTimeout(()=>E.showMenu(buildMainMenu()), 0); // Update the menu so it can be seen if a value was automatically set to false (app history vs load launcher).
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isQuicklaunchPresent) {
|
||||||
|
mainmenu['Exclude Quick Launch from history'] = {
|
||||||
|
value: !!settings.disregardQuicklaunch,
|
||||||
|
onchange: v => {
|
||||||
|
writeSettings("disregardQuicklaunch",v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
mainmenu['Force load to launcher'] = {
|
||||||
value: !!settings.autoloadLauncher,
|
value: !!settings.autoloadLauncher,
|
||||||
onchange: v => {
|
onchange: v => {
|
||||||
writeSettings("autoloadLauncher",v);
|
writeSettings("autoloadLauncher",v);
|
||||||
|
if (v && settings.useAppHistory) {
|
||||||
|
writeSettings("useAppHistory",!v);
|
||||||
|
setTimeout(()=>E.showMenu(buildMainMenu()), 0); // Update the menu so it can be seen if a value was automatically set to false (app history vs load launcher).
|
||||||
|
} // Don't use app history and load to launcher together.
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
'Hide "Fastloading..."': {
|
|
||||||
|
mainmenu['Hide "Fastloading..."'] = {
|
||||||
value: !!settings.hideLoading,
|
value: !!settings.hideLoading,
|
||||||
onchange: v => {
|
onchange: v => {
|
||||||
writeSettings("hideLoading",v);
|
writeSettings("hideLoading",v);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
return mainmenu;
|
return mainmenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
0.01: New App!
|
|
@ -0,0 +1,32 @@
|
||||||
|
# Fast Reset
|
||||||
|
|
||||||
|
Reset the watch by holding the hardware button for half a second. If 'Fastload Utils' is installed this will typically be done with fastloading. A buzz acts as indicator.
|
||||||
|
|
||||||
|
Fast Reset was developed with the app history feature of 'Fastload Utils' in mind. If many apps are in the history stack, the user may want a fast way to exit directly to the clock face without using the firmwares reset function.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Just install and it will run as boot code.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
If 'Fastload Utils' is installed fastloading will be used when possible. Otherwise a standard `load(.bootcde)` is used.
|
||||||
|
|
||||||
|
If the hardware button is held for longer the standard reset functionality of the firmware is executed as well (total 1.5 seconds). And eventually the watchdog will be kicked.
|
||||||
|
|
||||||
|
## Controls
|
||||||
|
|
||||||
|
Hold the hardware button for half a second to feel the buzz, loading the clock face.
|
||||||
|
|
||||||
|
## Requests
|
||||||
|
|
||||||
|
Mention @[thyttan](https://github.com/thyttan) in an issue to the official [BangleApps repository](https://github.com/espruino/BangleApps/issues) for feature requests and bug reports.
|
||||||
|
|
||||||
|
## Acknowledgements
|
||||||
|
|
||||||
|
<a target="_blank" href="https://icons8.com/icon/15165/rewind">Rewind</a> icon by <a target="_blank" href="https://icons8.com">Icons8</a>
|
||||||
|
|
||||||
|
## Creator
|
||||||
|
|
||||||
|
[thyttan](https://github.com/thyttan)
|
||||||
|
|
After Width: | Height: | Size: 343 B |
|
@ -0,0 +1,5 @@
|
||||||
|
{let buzzTimeout;
|
||||||
|
setWatch((e)=>{
|
||||||
|
if (e.state) buzzTimeout = setTimeout(()=>{Bangle.buzz(80,0.40);Bangle.showClock();}, 500);
|
||||||
|
if (!e.state && buzzTimeout) clearTimeout(buzzTimeout);},
|
||||||
|
BTN,{repeat:true, edge:'both' });}
|
|
@ -0,0 +1,14 @@
|
||||||
|
{ "id": "fastreset",
|
||||||
|
"name": "Fast Reset",
|
||||||
|
"shortName":"Fast Reset",
|
||||||
|
"version":"0.01",
|
||||||
|
"description": "Reset the watch by holding the hardware button for half a second. If 'Fastload Utils' is installed this will typically be done with fastloading. A buzz acts as indicator.",
|
||||||
|
"icon": "app.png",
|
||||||
|
"type": "bootloader",
|
||||||
|
"tags": "system",
|
||||||
|
"supports" : ["BANGLEJS2"],
|
||||||
|
"readme": "README.md",
|
||||||
|
"storage": [
|
||||||
|
{"name":"fastreset.boot.js","url":"boot.js"}
|
||||||
|
]
|
||||||
|
}
|
|
@ -14,5 +14,6 @@
|
||||||
{"name":"game1024.app.js","url":"app.js"},
|
{"name":"game1024.app.js","url":"app.js"},
|
||||||
{"name":"game1024.settings.js","url":"settings.js"},
|
{"name":"game1024.settings.js","url":"settings.js"},
|
||||||
{"name":"game1024.img","url":"app-icon.js","evaluate":true}
|
{"name":"game1024.img","url":"app-icon.js","evaluate":true}
|
||||||
]
|
],
|
||||||
|
"data":[{"name":"game1024.settings.json"}]
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
0.01: New App!
|
|
@ -0,0 +1,11 @@
|
||||||
|
Bluetooth.println("");
|
||||||
|
Bluetooth.println(JSON.stringify({
|
||||||
|
t:"intent",
|
||||||
|
target:"activity",
|
||||||
|
action:"android.intent.action.VOICE_COMMAND",
|
||||||
|
flags:["FLAG_ACTIVITY_NEW_TASK"]
|
||||||
|
}));
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
Bangle.showClock();
|
||||||
|
}, 0);
|
After Width: | Height: | Size: 799 B |
|
@ -0,0 +1,21 @@
|
||||||
|
// load settings
|
||||||
|
var settings = Object.assign({
|
||||||
|
enableTap: true
|
||||||
|
}, require("Storage").readJSON("gassist.json", true) || {});
|
||||||
|
|
||||||
|
if (settings.enableTap) {
|
||||||
|
Bangle.on("tap", function(e) {
|
||||||
|
if (e.dir=="front" && e.double) {
|
||||||
|
Bluetooth.println("");
|
||||||
|
Bluetooth.println(JSON.stringify({
|
||||||
|
t:"intent",
|
||||||
|
target:"activity",
|
||||||
|
action:"android.intent.action.VOICE_COMMAND",
|
||||||
|
flags:["FLAG_ACTIVITY_NEW_TASK"]
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear variable
|
||||||
|
settings = undefined;
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwxH+AH4A/AH4ALiAAFFtoxmFpQxjFxwwfFyAwdFyQwcF9wuUGDQvuFywwYF/4vUnAABF9YuCGBAv/F/6/PGC4bE3QACG5YvdFoYxSLzAvuFw4wjLxbCidhAvVGB4UFF7QxMCZAuaGJIRKF7oATFtoA/AEPMAAQttGNQuHGE4vuFxIwlF/4v/d/4vwGBAumGIwtpAH4A/AEIA=="))
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"id": "gassist",
|
||||||
|
"name": "Google Assist",
|
||||||
|
"version": "0.01",
|
||||||
|
"description": "A simple way to initiate Google Assistant on Android. Intents must be enabled in Gadgetbridge.",
|
||||||
|
"icon": "app.png",
|
||||||
|
"type": "app",
|
||||||
|
"tags": "tool, voice, tasker",
|
||||||
|
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||||
|
"allow_emulator": false,
|
||||||
|
"storage": [
|
||||||
|
{"name":"gassist.boot.js","url":"boot.js"},
|
||||||
|
{"name":"gassist.app.js","url":"app.js"},
|
||||||
|
{"name":"gassist.settings.js","url":"settings.js"},
|
||||||
|
{"name":"gassist.img","url":"icon.js","evaluate":true}
|
||||||
|
],
|
||||||
|
"data": [{"name":"gassist.json"}]
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
(function (back) {
|
||||||
|
let storage = require('Storage');
|
||||||
|
let file = "gassist.json";
|
||||||
|
|
||||||
|
// Load and set default settings
|
||||||
|
let appSettings = Object.assign({
|
||||||
|
enableTap : true
|
||||||
|
}, storage.readJSON(file, true) || {});
|
||||||
|
|
||||||
|
// Save settings to storage
|
||||||
|
function writeSettings() {
|
||||||
|
storage.writeJSON(file, appSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showMenu() {
|
||||||
|
E.showMenu({
|
||||||
|
"": {
|
||||||
|
"title": "Google Assist"
|
||||||
|
},
|
||||||
|
"< Back": () => back(),
|
||||||
|
'Front Tap:': {
|
||||||
|
value: (appSettings.enableTap === true),
|
||||||
|
format: v => v ? "On" : "Off",
|
||||||
|
onchange: v => {
|
||||||
|
appSettings.enableTap = v;
|
||||||
|
writeSettings();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Initially show the menu
|
||||||
|
showMenu();
|
||||||
|
});
|
|
@ -2,3 +2,4 @@
|
||||||
0.02: BTN2->launcher, use smaller text to allow "20:00" to fit on screen
|
0.02: BTN2->launcher, use smaller text to allow "20:00" to fit on screen
|
||||||
0.03: Changed setWatch to Bangle.setUI
|
0.03: Changed setWatch to Bangle.setUI
|
||||||
0.04: Tell clock widgets to hide.
|
0.04: Tell clock widgets to hide.
|
||||||
|
0.05: Making geissclock work on Bangle.js 2 (but only animate when unlocked!)
|
|
@ -1,4 +1,7 @@
|
||||||
var W = 79, H = 64;
|
var W = 79, H = 64;
|
||||||
|
// if screen is always on, only animate when unlocked
|
||||||
|
var isScreenAlwaysOn = process.env.BOARD=="BANGLEJS2";
|
||||||
|
|
||||||
/*var compiled = E.compiledC(`
|
/*var compiled = E.compiledC(`
|
||||||
// void transl(int, int, int )
|
// void transl(int, int, int )
|
||||||
int transl(unsigned char *map, unsigned char *imgfrom, unsigned char *imgto) {
|
int transl(unsigned char *map, unsigned char *imgfrom, unsigned char *imgto) {
|
||||||
|
@ -46,6 +49,7 @@ var map = new Uint8Array(W*H);
|
||||||
var pal = new Uint16Array(256);
|
var pal = new Uint16Array(256);
|
||||||
var PALETTES = 3;
|
var PALETTES = 3;
|
||||||
var MAPS = 6;
|
var MAPS = 6;
|
||||||
|
var animInterval;
|
||||||
|
|
||||||
// If we're missing any maps, compute them!
|
// If we're missing any maps, compute them!
|
||||||
(function() {
|
(function() {
|
||||||
|
@ -65,6 +69,8 @@ function randomPalette() {
|
||||||
var n = (0|Math.random()*200000) % PALETTES;
|
var n = (0|Math.random()*200000) % PALETTES;
|
||||||
var p = new Uint8Array(pal.buffer);
|
var p = new Uint8Array(pal.buffer);
|
||||||
p.set(require("Storage").readArrayBuffer("geissclk."+n+".pal"));
|
p.set(require("Storage").readArrayBuffer("geissclk."+n+".pal"));
|
||||||
|
if (!g.theme.dark) // if not dark, invert colors
|
||||||
|
E.mapInPlace(pal,pal,x=>x^0xFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
function randomMap() {
|
function randomMap() {
|
||||||
|
@ -93,7 +99,7 @@ var im = {
|
||||||
};
|
};
|
||||||
var lastSeconds = -1;
|
var lastSeconds = -1;
|
||||||
|
|
||||||
function iterate() { "ram"
|
function iterate(clearBuf) { "ram"
|
||||||
var d = new Date();
|
var d = new Date();
|
||||||
var time = require("locale").time(d,1);
|
var time = require("locale").time(d,1);
|
||||||
var seconds = d.getSeconds().toString().padStart(2,0);
|
var seconds = d.getSeconds().toString().padStart(2,0);
|
||||||
|
@ -108,27 +114,59 @@ function iterate() { "ram"
|
||||||
gfx.buffer = dataa.buffer;
|
gfx.buffer = dataa.buffer;
|
||||||
}
|
}
|
||||||
var x,y,n,t = getTime()/10;
|
var x,y,n,t = getTime()/10;
|
||||||
var amt = 100*Bangle.getAccel().diff;
|
if (clearBuf) {
|
||||||
for (var i=0;i<amt;i++) {
|
gfx.clear();
|
||||||
//x = Math.round((W/2) + 20*Math.sin(t));
|
} else { // do geiss animation
|
||||||
//y = Math.round((H/2) + 20*Math.cos(t));
|
var amt = 100*Bangle.getAccel().diff;
|
||||||
//t += 0.628;
|
for (var i=0;i<amt;i++) {
|
||||||
x = 1+(Math.random()*(W-2))|0;
|
//x = Math.round((W/2) + 20*Math.sin(t));
|
||||||
y = 1+(Math.random()*(H-2))|0;
|
//y = Math.round((H/2) + 20*Math.cos(t));
|
||||||
dataa[x + y*W] = 240;
|
//t += 0.628;
|
||||||
|
x = 1+(Math.random()*(W-2))|0;
|
||||||
|
y = 1+(Math.random()*(H-2))|0;
|
||||||
|
dataa[x + y*W] = 240;
|
||||||
|
}
|
||||||
|
compiled.transl(addrmap, addra, addrb);
|
||||||
}
|
}
|
||||||
compiled.transl(addrmap, addra, addrb);
|
|
||||||
|
|
||||||
|
|
||||||
x = 8;
|
x = 8;
|
||||||
|
|
||||||
gfx.setFont("5x9Numeric7Seg",2);
|
gfx.setFont("5x9Numeric7Seg",2);
|
||||||
gfx.drawString(time, x, 20);
|
gfx.drawString(time, x, 20);
|
||||||
gfx.setFont("5x9Numeric7Seg");
|
if (!clearBuf) { // don't draw seconds if not animating
|
||||||
gfx.drawString(seconds, x+55, 30);
|
gfx.setFont("5x9Numeric7Seg");
|
||||||
|
gfx.drawString(seconds, x+55, 30);
|
||||||
|
}
|
||||||
// firmwares pre-2v09 wouldn't accelerate a 3x blit if it went right to the RHS - hence we're 79px not 80
|
// firmwares pre-2v09 wouldn't accelerate a 3x blit if it went right to the RHS - hence we're 79px not 80
|
||||||
g.drawImage(im,1,24,{scale:3});
|
if (g.getWidth()==176) // Bangle.js 2
|
||||||
|
g.drawImage(im,8,24,{scale:2});
|
||||||
|
else
|
||||||
|
g.drawImage(im,3,24,{scale:3});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isScreenAlwaysOn) {
|
||||||
|
Bangle.on('lock',function(on) {
|
||||||
|
if (animInterval) {
|
||||||
|
clearInterval(animInterval);
|
||||||
|
animInterval = undefined;
|
||||||
|
}
|
||||||
|
if (!on) { // not locked - animate!
|
||||||
|
randomMap();
|
||||||
|
randomPalette();
|
||||||
|
iterate();
|
||||||
|
animInterval = setInterval(iterate, 50);
|
||||||
|
} else {
|
||||||
|
iterate(true); // just clear
|
||||||
|
animInterval = setTimeout(function() {
|
||||||
|
iterate(true);
|
||||||
|
animInterval = setInterval(function() {
|
||||||
|
iterate(true);
|
||||||
|
}, 60000);
|
||||||
|
}, 60000 - (Date.now() % 60000));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Bangle.on('lcdPower',function(on) {
|
Bangle.on('lcdPower',function(on) {
|
||||||
if (animInterval) {
|
if (animInterval) {
|
||||||
|
@ -144,11 +182,15 @@ Bangle.on('lcdPower',function(on) {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Show launcher when button pressed
|
// Show launcher when button pressed
|
||||||
Bangle.setUI("clock");g.clear();
|
Bangle.setUI("clock");
|
||||||
|
g.clear(1);
|
||||||
|
|
||||||
Bangle.loadWidgets();
|
Bangle.loadWidgets();
|
||||||
Bangle.drawWidgets();
|
Bangle.drawWidgets();
|
||||||
iterate();
|
iterate(true);
|
||||||
animInterval = setInterval(iterate, 50);
|
if (Bangle.isLCDOn() && (!isScreenAlwaysOn || !Bangle.isLocked())) {
|
||||||
|
console.log("Starting");
|
||||||
|
animInterval = setInterval(iterate, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"id": "geissclk",
|
"id": "geissclk",
|
||||||
"name": "Geiss Clock",
|
"name": "Geiss Clock",
|
||||||
"version": "0.04",
|
"version": "0.05",
|
||||||
"description": "7 segment clock with animated background in the style of Ryan Geiss' music visualisation. NOTE: The first run will take ~1 minute to do some precalculation",
|
"description": "7 segment clock with animated background in the style of Ryan Geiss' music visualisation. NOTE: The first run will take ~1 minute to do some precalculation",
|
||||||
"icon": "clock.png",
|
"icon": "clock.png",
|
||||||
"type": "clock",
|
"type": "clock",
|
||||||
"tags": "clock",
|
"tags": "clock",
|
||||||
"supports": ["BANGLEJS"],
|
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"geissclk.app.js","url":"clock.js"},
|
{"name":"geissclk.app.js","url":"clock.js"},
|
||||||
{"name":"geissclk.precompute.js","url":"precompute.js"},
|
{"name":"geissclk.precompute.js","url":"precompute.js"},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// PALETTES ---------------------------
|
// PALETTES ---------------------------
|
||||||
E.showMessage("Precomputing\npalettes\n\nPlease wait...\n0 / 3");
|
E.showMessage("Precomputing\npalettes\n\nPlease wait...\n0 / 3");
|
||||||
(function() { // fire
|
(function() { "jit" // fire
|
||||||
for (var i=0;i<256;i++) {
|
for (var i=0;i<256;i++) {
|
||||||
var r = Math.min(i*6,240);
|
var r = Math.min(i*6,240);
|
||||||
var g = Math.min(i*3,240);
|
var g = Math.min(i*3,240);
|
||||||
|
@ -10,7 +10,7 @@ E.showMessage("Precomputing\npalettes\n\nPlease wait...\n0 / 3");
|
||||||
})()
|
})()
|
||||||
require("Storage").write("geissclk.0.pal",pal.buffer);
|
require("Storage").write("geissclk.0.pal",pal.buffer);
|
||||||
E.showMessage("Precomputing\npalettes\n\nPlease wait...\n1 / 3");
|
E.showMessage("Precomputing\npalettes\n\nPlease wait...\n1 / 3");
|
||||||
(function() { // gunge
|
(function() { "jit" // gunge
|
||||||
for (var i=0;i<256;i++) {
|
for (var i=0;i<256;i++) {
|
||||||
var r = 0;
|
var r = 0;
|
||||||
var g = Math.min(i*3,255);
|
var g = Math.min(i*3,255);
|
||||||
|
@ -20,7 +20,7 @@ E.showMessage("Precomputing\npalettes\n\nPlease wait...\n1 / 3");
|
||||||
})()
|
})()
|
||||||
require("Storage").write("geissclk.1.pal",pal.buffer);
|
require("Storage").write("geissclk.1.pal",pal.buffer);
|
||||||
E.showMessage("Precomputing\npalettes\n\nPlease wait...\n2 / 3");
|
E.showMessage("Precomputing\npalettes\n\nPlease wait...\n2 / 3");
|
||||||
(function() { // rainbow
|
(function() { "jit" // rainbow
|
||||||
for (var i=0;i<256;i++) {
|
for (var i=0;i<256;i++) {
|
||||||
var cl = E.HSBtoRGB((48+i)/128,1,Math.min(i/16,0.9),true);
|
var cl = E.HSBtoRGB((48+i)/128,1,Math.min(i/16,0.9),true);
|
||||||
var r = cl[0];
|
var r = cl[0];
|
||||||
|
@ -35,7 +35,7 @@ require("Storage").write("geissclk.2.pal",pal.buffer);
|
||||||
// MAPS ----------------------------------------------
|
// MAPS ----------------------------------------------
|
||||||
E.showMessage("Precomputing\nmaps\n\nPlease wait...\n0 / 5");
|
E.showMessage("Precomputing\nmaps\n\nPlease wait...\n0 / 5");
|
||||||
// straight out
|
// straight out
|
||||||
(function() { "ram"; var n = 0; for (var y=0;y<H;y++) {
|
(function() { "jit"; var n = 0; for (var y=0;y<H;y++) {
|
||||||
for (var x=0;x<W;x++) {
|
for (var x=0;x<W;x++) {
|
||||||
var dx = x-(W/2);
|
var dx = x-(W/2);
|
||||||
var dy = y-(H/2);
|
var dy = y-(H/2);
|
||||||
|
@ -49,7 +49,7 @@ E.showMessage("Precomputing\nmaps\n\nPlease wait...\n0 / 5");
|
||||||
require("Storage").write("geissclk.0.map",map);
|
require("Storage").write("geissclk.0.map",map);
|
||||||
E.showMessage("Precomputing\nmaps\n\nPlease wait...\n1 / 5");
|
E.showMessage("Precomputing\nmaps\n\nPlease wait...\n1 / 5");
|
||||||
// ripple out
|
// ripple out
|
||||||
(function() { "ram"; var n = 0; for (var y=0;y<H;y++) {
|
(function() { "jit"; var n = 0; for (var y=0;y<H;y++) {
|
||||||
for (var x=0;x<W;x++) {
|
for (var x=0;x<W;x++) {
|
||||||
var dx = x-(W/2);
|
var dx = x-(W/2);
|
||||||
var dy = y-(H/2);
|
var dy = y-(H/2);
|
||||||
|
@ -63,7 +63,7 @@ E.showMessage("Precomputing\nmaps\n\nPlease wait...\n1 / 5");
|
||||||
require("Storage").write("geissclk.1.map",map);
|
require("Storage").write("geissclk.1.map",map);
|
||||||
E.showMessage("Precomputing\nmaps\n\nPlease wait...\n2 / 5");
|
E.showMessage("Precomputing\nmaps\n\nPlease wait...\n2 / 5");
|
||||||
// twisty outwards
|
// twisty outwards
|
||||||
(function() { "ram"; var n = 0; for (var y=0;y<H;y++) {
|
(function() { "jit"; var n = 0; for (var y=0;y<H;y++) {
|
||||||
for (var x=0;x<W;x++) {
|
for (var x=0;x<W;x++) {
|
||||||
var dx = x-(W/2);
|
var dx = x-(W/2);
|
||||||
var dy = y-(H/2);
|
var dy = y-(H/2);
|
||||||
|
@ -76,7 +76,7 @@ E.showMessage("Precomputing\nmaps\n\nPlease wait...\n2 / 5");
|
||||||
require("Storage").write("geissclk.2.map",map);
|
require("Storage").write("geissclk.2.map",map);
|
||||||
E.showMessage("Precomputing\nmaps\n\nPlease wait...\n3 / 5");
|
E.showMessage("Precomputing\nmaps\n\nPlease wait...\n3 / 5");
|
||||||
// spiral
|
// spiral
|
||||||
(function() { "ram"; var n = 0; for (var y=0;y<H;y++) {
|
(function() { "jit"; var n = 0; for (var y=0;y<H;y++) {
|
||||||
for (var x=0;x<W;x++) {
|
for (var x=0;x<W;x++) {
|
||||||
var dx = x-(W/2);
|
var dx = x-(W/2);
|
||||||
var dy = y-(H/2);
|
var dy = y-(H/2);
|
||||||
|
@ -89,7 +89,7 @@ E.showMessage("Precomputing\nmaps\n\nPlease wait...\n3 / 5");
|
||||||
require("Storage").write("geissclk.3.map",map);
|
require("Storage").write("geissclk.3.map",map);
|
||||||
E.showMessage("Precomputing\nmaps\n\nPlease wait...\n4 / 5");
|
E.showMessage("Precomputing\nmaps\n\nPlease wait...\n4 / 5");
|
||||||
// blur down
|
// blur down
|
||||||
(function() { "ram"; var n=0; for (var y=0;y<H;y++) {
|
(function() { "jit"; var n=0; for (var y=0;y<H;y++) {
|
||||||
for (var x=0;x<W;x++) {
|
for (var x=0;x<W;x++) {
|
||||||
map[n++] = 136 - 6*16 + (y&1)*8-4;
|
map[n++] = 136 - 6*16 + (y&1)*8-4;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ E.showMessage("Precomputing\nmaps\n\nPlease wait...\n4 / 5");
|
||||||
require("Storage").write("geissclk.4.map",map);
|
require("Storage").write("geissclk.4.map",map);
|
||||||
E.showMessage("Precomputing\nmaps\n\nPlease wait...\n5 / 5");
|
E.showMessage("Precomputing\nmaps\n\nPlease wait...\n5 / 5");
|
||||||
// twisty
|
// twisty
|
||||||
(function() { "ram"; var n=0; for (var y=0;y<H;y++) {
|
(function() { "jit"; var n=0; for (var y=0;y<H;y++) {
|
||||||
for (var x=0;x<W;x++) {
|
for (var x=0;x<W;x++) {
|
||||||
dx = Math.sin(y*0.2);
|
dx = Math.sin(y*0.2);
|
||||||
dy = Math.cos(x*0.2);
|
dy = Math.cos(x*0.2);
|
||||||
|
|
|
@ -14,5 +14,6 @@
|
||||||
{"name":"getup.app.js","url":"app.js"},
|
{"name":"getup.app.js","url":"app.js"},
|
||||||
{"name":"getup.settings.js","url":"settings.js"},
|
{"name":"getup.settings.js","url":"settings.js"},
|
||||||
{"name":"getup.img","url":"app-icon.js","evaluate":true}
|
{"name":"getup.img","url":"app-icon.js","evaluate":true}
|
||||||
]
|
],
|
||||||
|
"data":[{"name":"getup.settings.json"}]
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,5 +20,6 @@
|
||||||
{"name":"happyclk.app.js","url":"happyclk.app.js"},
|
{"name":"happyclk.app.js","url":"happyclk.app.js"},
|
||||||
{"name":"happyclk.img","url":"happyclk.icon.js","evaluate":true},
|
{"name":"happyclk.img","url":"happyclk.icon.js","evaluate":true},
|
||||||
{"name":"happyclk.settings.js","url":"happyclk.settings.js"}
|
{"name":"happyclk.settings.js","url":"happyclk.settings.js"}
|
||||||
]
|
],
|
||||||
|
"data":[{"name":"happyclk.setting.json"}]
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"shortName":"HR Alarm",
|
"shortName":"HR Alarm",
|
||||||
"version":"0.02",
|
"version":"0.02",
|
||||||
"description": "This invisible widget vibrates whenever the heart rate gets close to the upper limit or goes over or under the configured limits",
|
"description": "This invisible widget vibrates whenever the heart rate gets close to the upper limit or goes over or under the configured limits",
|
||||||
"icon": "widget.png",
|
"icon": "widget.png",
|
||||||
"type": "widget",
|
"type": "widget",
|
||||||
"tags": "widget",
|
"tags": "widget",
|
||||||
"supports" : ["BANGLEJS2"],
|
"supports" : ["BANGLEJS2"],
|
||||||
|
@ -12,5 +12,8 @@
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"hralarm.wid.js","url":"widget.js"},
|
{"name":"hralarm.wid.js","url":"widget.js"},
|
||||||
{"name":"hralarm.settings.js","url":"settings.js"}
|
{"name":"hralarm.settings.js","url":"settings.js"}
|
||||||
|
],
|
||||||
|
"data": [
|
||||||
|
{"name":"hralarm.json"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,5 +15,8 @@
|
||||||
{"name":"imageclock.app.js","url":"app.js"},
|
{"name":"imageclock.app.js","url":"app.js"},
|
||||||
{"name":"imageclock.settings.js","url":"settings.js"},
|
{"name":"imageclock.settings.js","url":"settings.js"},
|
||||||
{"name":"imageclock.img","url":"app-icon.js","evaluate":true}
|
{"name":"imageclock.img","url":"app-icon.js","evaluate":true}
|
||||||
|
],
|
||||||
|
"data": [
|
||||||
|
{"name":"imageclock.json"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,5 +12,6 @@
|
||||||
{"name":"textinput","url":"lib.js"},
|
{"name":"textinput","url":"lib.js"},
|
||||||
{"name":"kbtouch.settings.js","url":"settings.js"}
|
{"name":"kbtouch.settings.js","url":"settings.js"}
|
||||||
],
|
],
|
||||||
"sortorder":-1
|
"sortorder":-1,
|
||||||
|
"data":[{"name":"kbtouch.settings.json"}]
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,4 +24,6 @@
|
||||||
0.24: Add ability to disable alarm functionality.
|
0.24: Add ability to disable alarm functionality.
|
||||||
0.25: Add more colors to the settings and add the ability to disable the data charts+Markup.
|
0.25: Add more colors to the settings and add the ability to disable the data charts+Markup.
|
||||||
0.26: Use widget_utils.
|
0.26: Use widget_utils.
|
||||||
0.27: Report latest HRM rather than HRM 10 minutes ago (fix #2395)
|
0.27: Report latest HRM rather than HRM 10 minutes ago (fix #2395)
|
||||||
|
0.28: Battery Vref implemented correctly.
|
||||||
|
0.29: Support fastload.
|
|
@ -25,7 +25,8 @@ the "sched" app must be installed on your device.
|
||||||
## Data that can be configured
|
## Data that can be configured
|
||||||
* Steps - Steps loaded via the wpedom app.
|
* Steps - Steps loaded via the wpedom app.
|
||||||
* Battery - Current battery level in %
|
* Battery - Current battery level in %
|
||||||
* VREF - Voltage of battery
|
* BattVolt - Voltage of battery
|
||||||
|
* VREF - Internal Voltage Reference
|
||||||
* HRM - Last measured HRM
|
* HRM - Last measured HRM
|
||||||
* Temp - Weather temperature loaded via the weather module + gadgetbridge
|
* Temp - Weather temperature loaded via the weather module + gadgetbridge
|
||||||
* Humidity - Humidity loaded via the weather module + gadgetbridge
|
* Humidity - Humidity loaded via the weather module + gadgetbridge
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
{
|
||||||
const TIMER_IDX = "lcars";
|
const TIMER_IDX = "lcars";
|
||||||
const SETTINGS_FILE = "lcars.setting.json";
|
const SETTINGS_FILE = "lcars.setting.json";
|
||||||
const locale = require('locale');
|
const locale = require('locale');
|
||||||
const storage = require('Storage')
|
const storage = require('Storage');
|
||||||
const widget_utils = require('widget_utils');
|
const widget_utils = require('widget_utils');
|
||||||
let settings = {
|
let settings = {
|
||||||
alarm: -1,
|
alarm: -1,
|
||||||
|
@ -18,7 +19,7 @@ let settings = {
|
||||||
};
|
};
|
||||||
let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings;
|
let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings;
|
||||||
for (const key in saved_settings) {
|
for (const key in saved_settings) {
|
||||||
settings[key] = saved_settings[key]
|
settings[key] = saved_settings[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -36,10 +37,10 @@ let cGrey = "#424242";
|
||||||
*/
|
*/
|
||||||
let lcarsViewPos = 0;
|
let lcarsViewPos = 0;
|
||||||
// let hrmValue = 0;
|
// let hrmValue = 0;
|
||||||
var plotMonth = false;
|
let plotMonth = false;
|
||||||
|
|
||||||
|
|
||||||
function convert24to16(input)
|
let convert24to16 = function(input)
|
||||||
{
|
{
|
||||||
let RGB888 = parseInt(input.replace(/^#/, ''), 16);
|
let RGB888 = parseInt(input.replace(/^#/, ''), 16);
|
||||||
let r = (RGB888 & 0xFF0000) >> 16;
|
let r = (RGB888 & 0xFF0000) >> 16;
|
||||||
|
@ -55,17 +56,17 @@ function convert24to16(input)
|
||||||
RGB565 = RGB565 | b;
|
RGB565 = RGB565 | b;
|
||||||
|
|
||||||
return "0x"+RGB565.toString(16);
|
return "0x"+RGB565.toString(16);
|
||||||
}
|
};
|
||||||
|
|
||||||
var color1C = convert24to16(color1);//Converting colors to the correct format.
|
let color1C = convert24to16(color1);//Converting colors to the correct format.
|
||||||
var color2C = convert24to16(color2);
|
let color2C = convert24to16(color2);
|
||||||
var color3C = convert24to16(color3);
|
let color3C = convert24to16(color3);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Requirements and globals
|
* Requirements and globals
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var colorPalette = new Uint16Array([//Used to change the color of the image if the user selects a color that is diffrent than the default.
|
let colorPalette = new Uint16Array([//Used to change the color of the image if the user selects a color that is diffrent than the default.
|
||||||
0x0000, // not used
|
0x0000, // not used
|
||||||
color2C, // second
|
color2C, // second
|
||||||
color3C, // third
|
color3C, // third
|
||||||
|
@ -84,73 +85,73 @@ var colorPalette = new Uint16Array([//Used to change the color of the image if t
|
||||||
0x0000 // not used
|
0x0000 // not used
|
||||||
],0,1);
|
],0,1);
|
||||||
|
|
||||||
var bgLeftFullscreen = {
|
let bgLeftFullscreen = {
|
||||||
width : 27, height : 176, bpp : 3,
|
width : 27, height : 176, bpp : 3,
|
||||||
transparent : 0,
|
transparent : 0,
|
||||||
buffer : require("heatshrink").decompress((atob("/4AB+VJkmSAQV///+BAtJn//5IIFkmf/4IGyVP/gIGpMnF41PHIImGF4ImHJoQmGJoIdK8hNHNY47C/JNGBIJZGyYJBQA5GCKH5Q/KAQAoUP7y/KH5QGDoQAy0hGF34JB6RGFr4JB9JkFl4JB+gdFy4JB/QdFpYJB/odFkqrCS4xGCWoyDCKH5Q1GShlJChQLCCg5TCHw5TMAD35FAoIIkgJB8hGGv/8Mg8/+QIFp4cB5IRGBIIvI/4IFybyCF4wTCDp5NBHZZiGz4JBLJKAGk4JBO4xQ/KGQA8UP7y/KH5QnAHih/eX5Q/GQ4JCGRJlKCgxTDBAwgCCg5TCHwxTCNA4"))),
|
buffer : require("heatshrink").decompress((atob("/4AB+VJkmSAQV///+BAtJn//5IIFkmf/4IGyVP/gIGpMnF41PHIImGF4ImHJoQmGJoIdK8hNHNY47C/JNGBIJZGyYJBQA5GCKH5Q/KAQAoUP7y/KH5QGDoQAy0hGF34JB6RGFr4JB9JkFl4JB+gdFy4JB/QdFpYJB/odFkqrCS4xGCWoyDCKH5Q1GShlJChQLCCg5TCHw5TMAD35FAoIIkgJB8hGGv/8Mg8/+QIFp4cB5IRGBIIvI/4IFybyCF4wTCDp5NBHZZiGz4JBLJKAGk4JBO4xQ/KGQA8UP7y/KH5QnAHih/eX5Q/GQ4JCGRJlKCgxTDBAwgCCg5TCHwxTCNA4"))),
|
||||||
palette: colorPalette
|
palette: colorPalette
|
||||||
};
|
};
|
||||||
|
|
||||||
var bgLeftNotFullscreen = {
|
let bgLeftNotFullscreen = {
|
||||||
width : 27, height : 152, bpp : 3,
|
width : 27, height : 152, bpp : 3,
|
||||||
transparent : 0,
|
transparent : 0,
|
||||||
buffer : require("heatshrink").decompress((atob("/4AB+VJkmSAQV///+BAtJn//5IIFkmf/4IGyVP/gIGpMnF41PHIImGF4ImHJoQmGJoIdK8hNHNY47C/JNGBIJZGyYJBQA5GCKH5Q/KAQAy0hGF34JB6RGFr4JB9JkFl4JB+gdFy4JB/QdFpYJB/odFkqrCS4xGCWoyhCKH5Q1GShlJChQLCCg5TCHw5TMAD35FAoIIkgJB8hGGv/8Mg8/+QIFp4cB5IRGBIIvI/4IFybyCF4wTCDp5NBHZZiGz4JBLJKAGk4JBO4xQ/KGQA8UP7y/KH5QnAHih/eX5Q/GQ4JCGRJlKCgxTDBAwgCCg5TCHwxTCNA4A=="))),
|
buffer : require("heatshrink").decompress((atob("/4AB+VJkmSAQV///+BAtJn//5IIFkmf/4IGyVP/gIGpMnF41PHIImGF4ImHJoQmGJoIdK8hNHNY47C/JNGBIJZGyYJBQA5GCKH5Q/KAQAy0hGF34JB6RGFr4JB9JkFl4JB+gdFy4JB/QdFpYJB/odFkqrCS4xGCWoyhCKH5Q1GShlJChQLCCg5TCHw5TMAD35FAoIIkgJB8hGGv/8Mg8/+QIFp4cB5IRGBIIvI/4IFybyCF4wTCDp5NBHZZiGz4JBLJKAGk4JBO4xQ/KGQA8UP7y/KH5QnAHih/eX5Q/GQ4JCGRJlKCgxTDBAwgCCg5TCHwxTCNA4A=="))),
|
||||||
palette: colorPalette
|
palette: colorPalette
|
||||||
};
|
};
|
||||||
|
|
||||||
var bgRightFullscreen = {
|
let bgRightFullscreen = {
|
||||||
width : 27, height : 176, bpp : 3,
|
width : 27, height : 176, bpp : 3,
|
||||||
transparent : 0,
|
transparent : 0,
|
||||||
buffer : require("heatshrink").decompress((atob("yVJkgCCyf/AAPJBAYCBk4JB8gUFyVP//yBAoCB//5BAwUCAAIUHAAIgGChopGv5TIn5TIz4yLKYxxC/iGI/xxGKH5Q/agwAnUP7y/KH4yGeVYAJ0hGF34JB6RGFr4JB9JkFl4JB+gdFy4JB/QdFpYJB/odFkp4CS4xGCWoyhCKH5QuDoxQCDpI7GDoJZGHYIRGLIQvGO4QvGMQRNJADv+GIqTC/5PGz4JBJ41JBIPJCg2TD4QLGn4JB/gUaHwRTGHwRTHBIRTGNAQyJ8gyI+QdFp4JB/IdFk5lLKH5QvAHih/eX5Q/KE4A8UP7y/KH5QGDpg7HJoxZCCIx3CJowmCF4yACJoyJC/4A=="))),
|
buffer : require("heatshrink").decompress((atob("yVJkgCCyf/AAPJBAYCBk4JB8gUFyVP//yBAoCB//5BAwUCAAIUHAAIgGChopGv5TIn5TIz4yLKYxxC/iGI/xxGKH5Q/agwAnUP7y/KH4yGeVYAJ0hGF34JB6RGFr4JB9JkFl4JB+gdFy4JB/QdFpYJB/odFkp4CS4xGCWoyhCKH5QuDoxQCDpI7GDoJZGHYIRGLIQvGO4QvGMQRNJADv+GIqTC/5PGz4JBJ41JBIPJCg2TD4QLGn4JB/gUaHwRTGHwRTHBIRTGNAQyJ8gyI+QdFp4JB/IdFk5lLKH5QvAHih/eX5Q/KE4A8UP7y/KH5QGDpg7HJoxZCCIx3CJowmCF4yACJoyJC/4A=="))),
|
||||||
palette: colorPalette
|
palette: colorPalette
|
||||||
};
|
};
|
||||||
|
|
||||||
var bgRightNotFullscreen = {
|
let bgRightNotFullscreen = {
|
||||||
width : 27, height : 152, bpp : 3,
|
width : 27, height : 152, bpp : 3,
|
||||||
transparent : 0,
|
transparent : 0,
|
||||||
buffer : require("heatshrink").decompress((atob("yVJkgCCyf/AAPJBAYCBk4JB8gUFyVP//yBAoCB//5BAwUCAAIUHAAIgGChopGv5TIn5TIz4yLKYxxC/iGI/xxGKH5Q/agwAx0hGF34JB6RGFr4JB9JkFl4JB+gdFy4JB/QdFpYJB/odFkqrCS4xGCWoyhCKH5QuDoxQCDpI7GDoJZGHYIRGLIQvGO4QvGMQRNJADv+GIqTC/5PGz4JBJ41JBIPJCg2TD4QLGn4JB/gUaHwRTGHwRTHBIRTGNAQyJ8gyI+QdFp4JB/IdFk5lLKH5QvAHih/eX5Q/KE4A8UP7y/KH5QGDpg7HJoxZCCIx3CJowmCF4yACJoyJC/4A="))),
|
buffer : require("heatshrink").decompress((atob("yVJkgCCyf/AAPJBAYCBk4JB8gUFyVP//yBAoCB//5BAwUCAAIUHAAIgGChopGv5TIn5TIz4yLKYxxC/iGI/xxGKH5Q/agwAx0hGF34JB6RGFr4JB9JkFl4JB+gdFy4JB/QdFpYJB/odFkqrCS4xGCWoyhCKH5QuDoxQCDpI7GDoJZGHYIRGLIQvGO4QvGMQRNJADv+GIqTC/5PGz4JBJ41JBIPJCg2TD4QLGn4JB/gUaHwRTGHwRTHBIRTGNAQyJ8gyI+QdFp4JB/IdFk5lLKH5QvAHih/eX5Q/KE4A8UP7y/KH5QGDpg7HJoxZCCIx3CJowmCF4yACJoyJC/4A="))),
|
||||||
palette: colorPalette
|
palette: colorPalette
|
||||||
};
|
};
|
||||||
|
|
||||||
var bgLeft = settings.fullscreen ? bgLeftFullscreen : bgLeftNotFullscreen;
|
let bgLeft = settings.fullscreen ? bgLeftFullscreen : bgLeftNotFullscreen;
|
||||||
var bgRight= settings.fullscreen ? bgRightFullscreen : bgRightNotFullscreen;
|
let bgRight= settings.fullscreen ? bgRightFullscreen : bgRightNotFullscreen;
|
||||||
|
|
||||||
var iconEarth = {
|
let iconEarth = {
|
||||||
width : 50, height : 50, bpp : 3,
|
width : 50, height : 50, bpp : 3,
|
||||||
buffer : require("heatshrink").decompress(atob("AFtx48ECBsDwU5k/yhARLjgjBjlzAQMQEZcIkOP/fn31IEZgCBnlz58cEpM4geugEgwU/8+WNZJHDuHHvgmBCQ8goEOnVgJoMnyV58mACItHI4X8uAFBuVHnnz4BuGxk4////Egz3IkmWvPgNw8f/prB//BghTC+AjE7848eMjNnzySBwUJkmf/BuGuPDAQIjBiPHhhTCSQnjMo0ITANJn44Dg8MuFBggCCiFBcAJ0Bv5xEh+ITo2OhHkyf/OIQdBWwVHhgjBNwUE+fP/5EEgePMoYLBhMgyVJk/+BQQdC688I4XxOIc8v//NAvr+QEBj/5NwKVBy1/QYUciPBhk1EAJrC+KeC489QYaMBgU/8BNB9+ChEjz1Jkn/QYMBDQIgCcYTCCiP/nlzJQmenMAgV4//uy/9wRaB/1J8iVCcAfHjt9TYYICnhKCgRKBw159/v//r927OIeeoASBDQccvv3791KYVDBYPLJQeCnPnz//AAP6ocEjEkXgMgJQtz79fLAP8KYkccAcJ8Gf/f/xu/cAMQ4eP5MlyQRCMolx40YsOGBAPfnnzU4KVDpKMBvz8Dh0/8me7IICgkxJQXPIgZTD58sEgcJk+eNoONnFBhk4/5uB/pcDg5KD+4mEv4CBXISVDhEn31/8/+mH7x//JQK5CAAMB4JBCnnxJQf/+fJEgkAa4L+CAQOOjMn/1bXIRxDJQXx58f//Hhlz/88EgsChMgz/Zs/+nfkyV/8huDOI6SD498NwoACi1Z8+S/Plz17/+QCI7jC+ZxBmfPnojIAAMDcYWSp//2wRJEwq2GABECjMgNYwAmA="))
|
buffer : require("heatshrink").decompress(atob("AFtx48ECBsDwU5k/yhARLjgjBjlzAQMQEZcIkOP/fn31IEZgCBnlz58cEpM4geugEgwU/8+WNZJHDuHHvgmBCQ8goEOnVgJoMnyV58mACItHI4X8uAFBuVHnnz4BuGxk4////Egz3IkmWvPgNw8f/prB//BghTC+AjE7848eMjNnzySBwUJkmf/BuGuPDAQIjBiPHhhTCSQnjMo0ITANJn44Dg8MuFBggCCiFBcAJ0Bv5xEh+ITo2OhHkyf/OIQdBWwVHhgjBNwUE+fP/5EEgePMoYLBhMgyVJk/+BQQdC688I4XxOIc8v//NAvr+QEBj/5NwKVBy1/QYUciPBhk1EAJrC+KeC489QYaMBgU/8BNB9+ChEjz1Jkn/QYMBDQIgCcYTCCiP/nlzJQmenMAgV4//uy/9wRaB/1J8iVCcAfHjt9TYYICnhKCgRKBw159/v//r927OIeeoASBDQccvv3791KYVDBYPLJQeCnPnz//AAP6ocEjEkXgMgJQtz79fLAP8KYkccAcJ8Gf/f/xu/cAMQ4eP5MlyQRCMolx40YsOGBAPfnnzU4KVDpKMBvz8Dh0/8me7IICgkxJQXPIgZTD58sEgcJk+eNoONnFBhk4/5uB/pcDg5KD+4mEv4CBXISVDhEn31/8/+mH7x//JQK5CAAMB4JBCnnxJQf/+fJEgkAa4L+CAQOOjMn/1bXIRxDJQXx58f//Hhlz/88EgsChMgz/Zs/+nfkyV/8huDOI6SD498NwoACi1Z8+S/Plz17/+QCI7jC+ZxBmfPnojIAAMDcYWSp//2wRJEwq2GABECjMgNYwAmA="))
|
||||||
};
|
};
|
||||||
|
|
||||||
var iconSaturn = {
|
let iconSaturn = {
|
||||||
width : 50, height : 50, bpp : 3,
|
width : 50, height : 50, bpp : 3,
|
||||||
transparent : 1,
|
transparent : 1,
|
||||||
buffer : require("heatshrink").decompress(atob("AH4A/AEkQuPHCJ0ChEAwARNjAjBjgjOhs06Q2OEYVx4ARMhEggUMkANIDoIgBoEEgEBNxJEC6ZrBAAMwNxAjDNYcHNxIjB7dtEwIHBwRoKj158+cuPEjlwCRAjC23bpu0wRNDAAsHEYWeEwaSJ6YjCAQUNSRQjEzxQBWZMNEYlsmg2JWAIjCz95SoJuJggjDtuw6dMG5JKCz998wFBJRVNEYW0yaVBJRNhJQN9+4pCzhKJmBKC4YpB/fINxIgCzFxSoQ3J4ENm3CAQPb98wbpEcAQMYWwKYBNxMDXgc2/fv3g2IEAOAgAjBjy5CEhEMfYICBgfPnjdLjj+CgMHiC3JknDhhoINw4jCAB0IJQIANR4QjPAH4A/AFA"))
|
buffer : require("heatshrink").decompress(atob("AH4A/AEkQuPHCJ0ChEAwARNjAjBjgjOhs06Q2OEYVx4ARMhEggUMkANIDoIgBoEEgEBNxJEC6ZrBAAMwNxAjDNYcHNxIjB7dtEwIHBwRoKj158+cuPEjlwCRAjC23bpu0wRNDAAsHEYWeEwaSJ6YjCAQUNSRQjEzxQBWZMNEYlsmg2JWAIjCz95SoJuJggjDtuw6dMG5JKCz998wFBJRVNEYW0yaVBJRNhJQN9+4pCzhKJmBKC4YpB/fINxIgCzFxSoQ3J4ENm3CAQPb98wbpEcAQMYWwKYBNxMDXgc2/fv3g2IEAOAgAjBjy5CEhEMfYICBgfPnjdLjj+CgMHiC3JknDhhoINw4jCAB0IJQIANR4QjPAH4A/AFA"))
|
||||||
};
|
};
|
||||||
|
|
||||||
var iconMoon = {
|
let iconMoon = {
|
||||||
width : 50, height : 50, bpp : 3,
|
width : 50, height : 50, bpp : 3,
|
||||||
transparent : 1,
|
transparent : 1,
|
||||||
buffer : require("heatshrink").decompress(atob("AH4AQjlx44CCCZsg8eOkHDwAQKEYgmPhEgEQM48AOIgMHEYoCB4ATI8UAmH/x04JoRuJsImHuBKLn37EwZuIgEQOI8cEpXj/yYBhE8+YNGgkYoJxITBUPnAaC///nC+FjBuIOJZEB8YeCh/8AoYACoMEEAnEjhQDPQJKJ/DCDAoi5DoLdHAoMQgLjFWYPOnngh02IwXzwDjEgPGEYS8BI4MBYoSVG4fP/nghkAgZrDkngJQqSG4gvBg4sBQgkImHihEAWwP8ZBMBEYl5/+cSoVAGQIUFh04weJn///0gj/OEw5KEz45BzhuCTYQAEgePB4IACAoJuBnAQEa4XHjxKB//xFgWHJQsCRgMDEonipwjENwUBDQNx8+evvn/hTDLw3igE+EgZxB8UOXIvEJQUfEYOfv53DEQkgga5BJQvzx84cAj+CDoNh8/eEYJKDuCSEcocnEon+/7xEgFBIIcfB4Mf/IICXI2DgDdBAAn758gCIq5Dv4zBvJuIOIfjEgvP/ARHgwdCB4P3AoTdFAAk4EYk8SQgAFTALaDSQwAGh08//vnDmBABYmEEZYAzA=="))
|
buffer : require("heatshrink").decompress(atob("AH4AQjlx44CCCZsg8eOkHDwAQKEYgmPhEgEQM48AOIgMHEYoCB4ATI8UAmH/x04JoRuJsImHuBKLn37EwZuIgEQOI8cEpXj/yYBhE8+YNGgkYoJxITBUPnAaC///nC+FjBuIOJZEB8YeCh/8AoYACoMEEAnEjhQDPQJKJ/DCDAoi5DoLdHAoMQgLjFWYPOnngh02IwXzwDjEgPGEYS8BI4MBYoSVG4fP/nghkAgZrDkngJQqSG4gvBg4sBQgkImHihEAWwP8ZBMBEYl5/+cSoVAGQIUFh04weJn///0gj/OEw5KEz45BzhuCTYQAEgePB4IACAoJuBnAQEa4XHjxKB//xFgWHJQsCRgMDEonipwjENwUBDQNx8+evvn/hTDLw3igE+EgZxB8UOXIvEJQUfEYOfv53DEQkgga5BJQvzx84cAj+CDoNh8/eEYJKDuCSEcocnEon+/7xEgFBIIcfB4Mf/IICXI2DgDdBAAn758gCIq5Dv4zBvJuIOIfjEgvP/ARHgwdCB4P3AoTdFAAk4EYk8SQgAFTALaDSQwAGh08//vnDmBABYmEEZYAzA=="))
|
||||||
};
|
};
|
||||||
|
|
||||||
var iconMars = {
|
let iconMars = {
|
||||||
width : 50, height : 50, bpp : 3,
|
width : 50, height : 50, bpp : 3,
|
||||||
transparent : 1,
|
transparent : 1,
|
||||||
buffer : require("heatshrink").decompress(atob("AH4ATjlwCJ+Dh0wwAQMg0cuPHjFhCZkDps0yVJkmQCBMEjFx42atOmzQmLhMkEYQCCCREQoOGEYmmzB0IEY4CBkARGoJKBEYQCEzgSGkGSpAjDyYCCphuGiFhJQgCD8ASFgRHGAQKbB6BuHJRGeOIsINxEk6dNmARDgMEjQjHAQPnVQojIyZKB6YSDNwK5FAQt54BuDXJIjBEwK5EgxKKXgq5BJRdgXIojJAQJKMcAM0EwM2JUApDoCVFExa7FkGCgAmIkAREEwUEjAmHCIgABhEggQmFpACBCIojBEwRQCzVhwkQU4YADgQmBwQCCI4IFBCAojFAQojGJQQjDAQgRGEZICBEo4gFyUIkilFJQUYEAZrBAQMYNw5KDSQSbCNwwABgOGEwgCBsPACQ5xGwdNnARJcAVh48evvnCJK8Chs+/fv33gCRcB48cuPHCBYA/ADAA=="))
|
buffer : require("heatshrink").decompress(atob("AH4ATjlwCJ+Dh0wwAQMg0cuPHjFhCZkDps0yVJkmQCBMEjFx42atOmzQmLhMkEYQCCCREQoOGEYmmzB0IEY4CBkARGoJKBEYQCEzgSGkGSpAjDyYCCphuGiFhJQgCD8ASFgRHGAQKbB6BuHJRGeOIsINxEk6dNmARDgMEjQjHAQPnVQojIyZKB6YSDNwK5FAQt54BuDXJIjBEwK5EgxKKXgq5BJRdgXIojJAQJKMcAM0EwM2JUApDoCVFExa7FkGCgAmIkAREEwUEjAmHCIgABhEggQmFpACBCIojBEwRQCzVhwkQU4YADgQmBwQCCI4IFBCAojFAQojGJQQjDAQgRGEZICBEo4gFyUIkilFJQUYEAZrBAQMYNw5KDSQSbCNwwABgOGEwgCBsPACQ5xGwdNnARJcAVh48evvnCJK8Chs+/fv33gCRcB48cuPHCBYA/ADAA=="))
|
||||||
};
|
};
|
||||||
|
|
||||||
var iconSatellite = {
|
let iconSatellite = {
|
||||||
width : 50, height : 50, bpp : 3,
|
width : 50, height : 50, bpp : 3,
|
||||||
transparent : 2,
|
transparent : 2,
|
||||||
buffer : require("heatshrink").decompress(atob("pMkyQC/ATGXhIRPyNl0gmPjlwCJ9ly1aCJ1c+fHJR1Hy1ZJR1I+fPnlx6QRLpe+/JKBr5KMuYjBJQMdCJce/fvJQW0CJUlEYQCBSpvvJQbXJjl0NwnzNxGQwEOnHhgF78+WqQyIrFx48cAQXz4ShJgAABh0+8cP//9LJEhg4jDuP3//0LhGQgYlBgeAn///5cIy8MuAmDCIP/9I4HkmCEYMOgHfCQWkCI0cuBuDgF/CIP+CI1Ny1IkeAgHANwIAB/QRFrj7BhkxEwQRC/4RFpbXDgSVBg4RCSorXDI4MJAQMfCIP8cwImDn37fwN58+kwHgLgSVFub7CI4NyBAJKDLgkuEYX78+evKtCLg0jEYRKC58JMoRcFkwjDJQTFDl65EkojEAQMdcwn/+gFC3YjEJQLXEpYRDWwQmEdI6SHAQO0CJUkx4jDF4gCIJQgRMXIjCEARIjCCJ2XEYPKCJqJBJQIROcAUpCJ0kybaDARtdCKAC2kAA="))
|
buffer : require("heatshrink").decompress(atob("pMkyQC/ATGXhIRPyNl0gmPjlwCJ9ly1aCJ1c+fHJR1Hy1ZJR1I+fPnlx6QRLpe+/JKBr5KMuYjBJQMdCJce/fvJQW0CJUlEYQCBSpvvJQbXJjl0NwnzNxGQwEOnHhgF78+WqQyIrFx48cAQXz4ShJgAABh0+8cP//9LJEhg4jDuP3//0LhGQgYlBgeAn///5cIy8MuAmDCIP/9I4HkmCEYMOgHfCQWkCI0cuBuDgF/CIP+CI1Ny1IkeAgHANwIAB/QRFrj7BhkxEwQRC/4RFpbXDgSVBg4RCSorXDI4MJAQMfCIP8cwImDn37fwN58+kwHgLgSVFub7CI4NyBAJKDLgkuEYX78+evKtCLg0jEYRKC58JMoRcFkwjDJQTFDl65EkojEAQMdcwn/+gFC3YjEJQLXEpYRDWwQmEdI6SHAQO0CJUkx4jDF4gCIJQgRMXIjCEARIjCCJ2XEYPKCJqJBJQIROcAUpCJ0kybaDARtdCKAC2kAA="))
|
||||||
};
|
};
|
||||||
|
|
||||||
var iconCharging = {
|
let iconCharging = {
|
||||||
width : 50, height : 50, bpp : 3,
|
width : 50, height : 50, bpp : 3,
|
||||||
transparent : 5,
|
transparent : 5,
|
||||||
buffer : require("heatshrink").decompress(atob("23btugAwUBtoICARG0h048eODQYCJ6P/AAUCCJfbo4SDxYRLtEcuPHjlwgoRJ7RnIloUHoYjDAQfAExEAwUIkACEkSAIEYwCBhZKH6EIJI0CJRFHEY0BJRWBSgf//0AJRYSE4BKLj4SE8BKLv4RD/hK/JS2AXY0gXwRKG4cMmACCJQMAg8csEFJQsBAwfasEAm379u0gFbcBfHzgFBz1xMQZKBjY/D0E2+BOChu26yVEEYdww+cgAFCg+cgIfB6RKF4HbgEIkGChEAthfCJQ0eEAIjBBAMxk6GCJQtgtyVBwRKBAQMbHAJKGXIIFCgACBhl54qVG2E+EAJKBJoWAm0WJQ6SCXgdxFgMLJQvYjeAEAUwFIUitEtJQ14NwUHgEwKYZKGwOwNYX7XgWCg3CJQ5rB4MevPnAoPDJRJrCgEG/ECAoNsJRUwoEesIIBiJKI3CVDti/CJRKVDiJHBSo0YsOGjED8AjBcAcIgdhcAXAPIUAcAYIBcA4dBAQUG8BrBgBuCgOwcBEeXIK2BBAIFBgRqBGoYAChq8CcYUE4FbUYOACQsHzgjDgwFBCIImBAQsDtwYD7cAloRI22B86YBw5QBgoRJ7dAgYEDCJaeBJoMcsARMAQNoJIIRE6A"))
|
buffer : require("heatshrink").decompress(atob("23btugAwUBtoICARG0h048eODQYCJ6P/AAUCCJfbo4SDxYRLtEcuPHjlwgoRJ7RnIloUHoYjDAQfAExEAwUIkACEkSAIEYwCBhZKH6EIJI0CJRFHEY0BJRWBSgf//0AJRYSE4BKLj4SE8BKLv4RD/hK/JS2AXY0gXwRKG4cMmACCJQMAg8csEFJQsBAwfasEAm379u0gFbcBfHzgFBz1xMQZKBjY/D0E2+BOChu26yVEEYdww+cgAFCg+cgIfB6RKF4HbgEIkGChEAthfCJQ0eEAIjBBAMxk6GCJQtgtyVBwRKBAQMbHAJKGXIIFCgACBhl54qVG2E+EAJKBJoWAm0WJQ6SCXgdxFgMLJQvYjeAEAUwFIUitEtJQ14NwUHgEwKYZKGwOwNYX7XgWCg3CJQ5rB4MevPnAoPDJRJrCgEG/ECAoNsJRUwoEesIIBiJKI3CVDti/CJRKVDiJHBSo0YsOGjED8AjBcAcIgdhcAXAPIUAcAYIBcA4dBAQUG8BrBgBuCgOwcBEeXIK2BBAIFBgRqBGoYAChq8CcYUE4FbUYOACQsHzgjDgwFBCIImBAQsDtwYD7cAloRI22B86YBw5QBgoRJ7dAgYEDCJaeBJoMcsARMAQNoJIIRE6A"))
|
||||||
};
|
};
|
||||||
|
|
||||||
var iconWarning = {
|
let iconWarning = {
|
||||||
width : 50, height : 50, bpp : 3,
|
width : 50, height : 50, bpp : 3,
|
||||||
transparent : 1,
|
transparent : 1,
|
||||||
buffer : require("heatshrink").decompress(atob("kmSpIC/AWMyoQIFsmECJFJhMmA4QXByVICIwODAQ4RRFIQGD5JVLkIGDzJqMyAGDph8MiRKGyApEAoZKFyYIDQwMkSQNkQZABBhIIOOJRuEL5gRIAUKACVQMhmUSNYNDQYJTBBwYFByGTkOE5FJWYNMknCAQKYCiaSCpmGochDoSYBhMwTAZrChILBhmEzKPBF4ImBTAREBDoMmEwJVDoYjBycJFgWEJQRuLJQ1kmQCCjJlCBYbjCagaDBwyDBmBuBF4TjJAUQKINBChCDQxZBcZIIQF4NIgEAgKSDiQmEVQKMBoARBAAMCSQLLBVoxqKL4gaCChVCNwoRKOIo4CJIgABBoSMHpIRFgDdJOIJUBCAUJRgJuEAQb+DIIgRIAX4C/ASOQA"))
|
buffer : require("heatshrink").decompress(atob("kmSpIC/AWMyoQIFsmECJFJhMmA4QXByVICIwODAQ4RRFIQGD5JVLkIGDzJqMyAGDph8MiRKGyApEAoZKFyYIDQwMkSQNkQZABBhIIOOJRuEL5gRIAUKACVQMhmUSNYNDQYJTBBwYFByGTkOE5FJWYNMknCAQKYCiaSCpmGochDoSYBhMwTAZrChILBhmEzKPBF4ImBTAREBDoMmEwJVDoYjBycJFgWEJQRuLJQ1kmQCCjJlCBYbjCagaDBwyDBmBuBF4TjJAUQKINBChCDQxZBcZIIQF4NIgEAgKSDiQmEVQKMBoARBAAMCSQLLBVoxqKL4gaCChVCNwoRKOIo4CJIgABBoSMHpIRFgDdJOIJUBCAUJRgJuEAQb+DIIgRIAX4C/ASOQA"))
|
||||||
|
@ -172,26 +173,26 @@ Graphics.prototype.setFontAntonioLarge = function(scale) {
|
||||||
/*
|
/*
|
||||||
* Draw watch face
|
* Draw watch face
|
||||||
*/
|
*/
|
||||||
var drawTimeout;
|
let drawTimeout;
|
||||||
function queueDraw() {
|
let queueDraw = function() {
|
||||||
|
|
||||||
// Faster updates during alarm to ensure that it is
|
// Faster updates during alarm to ensure that it is
|
||||||
// shown correctly...
|
// shown correctly...
|
||||||
var timeout = isAlarmEnabled() ? 10000 : 60000;
|
let timeout = isAlarmEnabled() ? 10000 : 60000;
|
||||||
|
|
||||||
if (drawTimeout) clearTimeout(drawTimeout);
|
if (drawTimeout) clearTimeout(drawTimeout);
|
||||||
drawTimeout = setTimeout(function() {
|
drawTimeout = setTimeout(function() {
|
||||||
drawTimeout = undefined;
|
drawTimeout = undefined;
|
||||||
draw();
|
draw();
|
||||||
}, timeout - (Date.now() % timeout));
|
}, timeout - (Date.now() % timeout));
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function plots a data row in LCARS style.
|
* This function plots a data row in LCARS style.
|
||||||
* Note: It can be called async and therefore, the text alignment and
|
* Note: It can be called async and therefore, the text alignment and
|
||||||
* font is set each time the function is called.
|
* font is set each time the function is called.
|
||||||
*/
|
*/
|
||||||
function printRow(text, value, y, c){
|
let printRow = function(text, value, y, c){
|
||||||
g.setFontAntonioMedium();
|
g.setFontAntonioMedium();
|
||||||
g.setFontAlign(-1,-1,0);
|
g.setFontAlign(-1,-1,0);
|
||||||
|
|
||||||
|
@ -210,23 +211,23 @@ function printRow(text, value, y, c){
|
||||||
g.setColor(c);
|
g.setColor(c);
|
||||||
g.setFontAlign(1,-1,0);
|
g.setFontAlign(1,-1,0);
|
||||||
g.drawString(value, 126, y);
|
g.drawString(value, 126, y);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
function drawData(key, y, c){
|
let drawData = function(key, y, c){
|
||||||
try{
|
try{
|
||||||
_drawData(key, y, c);
|
_drawData(key, y, c);
|
||||||
} catch(ex){
|
} catch(ex){
|
||||||
// Show last error - next try hopefully works.
|
// Show last error - next try hopefully works.
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
function _drawData(key, y, c){
|
let _drawData = function(key, y, c){
|
||||||
key = key.toUpperCase()
|
key = key.toUpperCase()
|
||||||
var text = key;
|
let text = key;
|
||||||
var value = "ERR";
|
let value = "ERR";
|
||||||
var should_print= true;
|
let should_print= true;
|
||||||
|
|
||||||
if(key == "STEPS"){
|
if(key == "STEPS"){
|
||||||
text = "STEP";
|
text = "STEP";
|
||||||
|
@ -239,21 +240,24 @@ function _drawData(key, y, c){
|
||||||
} else if (key == "VREF"){
|
} else if (key == "VREF"){
|
||||||
value = E.getAnalogVRef().toFixed(2) + "V";
|
value = E.getAnalogVRef().toFixed(2) + "V";
|
||||||
|
|
||||||
|
} else if (key =="BATTVOLT" ) {
|
||||||
|
text = "BATV";
|
||||||
|
value = (E.getAnalogVRef()*analogRead(3)*4).toFixed(2) + "V";
|
||||||
} else if(key == "HRM"){
|
} else if(key == "HRM"){
|
||||||
value = Math.round(Bangle.getHealthStatus().bpm||Bangle.getHealthStatus("last").bpm);
|
value = Math.round(Bangle.getHealthStatus().bpm||Bangle.getHealthStatus("last").bpm);
|
||||||
|
|
||||||
} else if (key == "TEMP"){
|
} else if (key == "TEMP"){
|
||||||
var weather = getWeather();
|
let weather = getWeather();
|
||||||
value = weather.temp;
|
value = weather.temp;
|
||||||
|
|
||||||
} else if (key == "HUMIDITY"){
|
} else if (key == "HUMIDITY"){
|
||||||
text = "HUM";
|
text = "HUM";
|
||||||
var weather = getWeather();
|
let weather = getWeather();
|
||||||
value = weather.hum;
|
value = weather.hum;
|
||||||
|
|
||||||
} else if (key == "WIND"){
|
} else if (key == "WIND"){
|
||||||
text = "WND";
|
text = "WND";
|
||||||
var weather = getWeather();
|
let weather = getWeather();
|
||||||
value = weather.wind;
|
value = weather.wind;
|
||||||
|
|
||||||
} else if (key == "ALTITUDE"){
|
} else if (key == "ALTITUDE"){
|
||||||
|
@ -277,18 +281,18 @@ function _drawData(key, y, c){
|
||||||
if(should_print){
|
if(should_print){
|
||||||
printRow(text, value, y, c);
|
printRow(text, value, y, c);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
function drawHorizontalBgLine(color, x1, x2, y, h){
|
let drawHorizontalBgLine = function(color, x1, x2, y, h){
|
||||||
g.setColor(color);
|
g.setColor(color);
|
||||||
|
|
||||||
for(var i=0; i<h; i++){
|
for(let i=0; i<h; i++){
|
||||||
g.drawLine(x1, y+i, x2,y+i);
|
g.drawLine(x1, y+i, x2,y+i);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
function drawInfo(){
|
let drawInfo = function(){
|
||||||
if(lcarsViewPos != 0 || !settings.fullscreen){
|
if(lcarsViewPos != 0 || !settings.fullscreen){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -310,9 +314,9 @@ function drawInfo(){
|
||||||
g.setColor(color3);
|
g.setColor(color3);
|
||||||
g.drawString("LOCK", 128, 53);
|
g.drawString("LOCK", 128, 53);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
function drawState(){
|
let drawState = function(){
|
||||||
if(lcarsViewPos != 0){
|
if(lcarsViewPos != 0){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -322,11 +326,11 @@ function drawState(){
|
||||||
g.setFontAntonioMedium();
|
g.setFontAntonioMedium();
|
||||||
|
|
||||||
if(!isAlarmEnabled()){
|
if(!isAlarmEnabled()){
|
||||||
var bat = E.getBattery();
|
let bat = E.getBattery();
|
||||||
var flash = storage.getFree() / process.env.STORAGE;
|
let flash = storage.getFree() / process.env.STORAGE;
|
||||||
var current = new Date();
|
let current = new Date();
|
||||||
var hours = current.getHours();
|
let hours = current.getHours();
|
||||||
var iconMsg =
|
let iconMsg =
|
||||||
Bangle.isCharging() ? { icon: iconCharging, text: "STATUS" } :
|
Bangle.isCharging() ? { icon: iconCharging, text: "STATUS" } :
|
||||||
bat < 30 ? { icon: iconWarning, text: "BAT" } :
|
bat < 30 ? { icon: iconWarning, text: "BAT" } :
|
||||||
flash < 0.1 ? { icon: iconWarning, text: "DISK" } :
|
flash < 0.1 ? { icon: iconWarning, text: "DISK" } :
|
||||||
|
@ -348,12 +352,12 @@ function drawState(){
|
||||||
}
|
}
|
||||||
|
|
||||||
g.setFontAlign(-1, -1, 0);
|
g.setFontAlign(-1, -1, 0);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
function drawPosition0(){
|
let drawPosition0 = function(){
|
||||||
// Draw background image
|
// Draw background image
|
||||||
var offset = settings.fullscreen ? 0 : 24;
|
let offset = settings.fullscreen ? 0 : 24;
|
||||||
g.drawImage(bgLeft, 0, offset);
|
g.drawImage(bgLeft, 0, offset);
|
||||||
drawHorizontalBgLine(color1, 25, 120, offset, 4);
|
drawHorizontalBgLine(color1, 25, 120, offset, 4);
|
||||||
drawHorizontalBgLine(color1, 130, 176, offset, 4);
|
drawHorizontalBgLine(color1, 130, 176, offset, 4);
|
||||||
|
@ -363,13 +367,13 @@ function drawPosition0(){
|
||||||
drawHorizontalBgLine(color2, 120, 176, 87, 4);
|
drawHorizontalBgLine(color2, 120, 176, 87, 4);
|
||||||
|
|
||||||
// The last line is a battery indicator too
|
// The last line is a battery indicator too
|
||||||
var bat = E.getBattery() / 100.0;
|
let bat = E.getBattery() / 100.0;
|
||||||
var batStart = 19;
|
let batStart = 19;
|
||||||
var batWidth = 172 - batStart;
|
let batWidth = 172 - batStart;
|
||||||
var batX2 = parseInt(batWidth * bat + batStart);
|
let batX2 = parseInt(batWidth * bat + batStart);
|
||||||
drawHorizontalBgLine(color2, batStart, batX2, 171, 5);
|
drawHorizontalBgLine(color2, batStart, batX2, 171, 5);
|
||||||
drawHorizontalBgLine(cGrey, batX2, 172, 171, 5);
|
drawHorizontalBgLine(cGrey, batX2, 172, 171, 5);
|
||||||
for(var i=0; i+batStart<=172; i+=parseInt(batWidth/4)){
|
for(let i=0; i+batStart<=172; i+=parseInt(batWidth/4)){
|
||||||
drawHorizontalBgLine(cBlack, batStart+i, batStart+i+3, 168, 8)
|
drawHorizontalBgLine(cBlack, batStart+i, batStart+i+3, 168, 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,8 +383,8 @@ function drawPosition0(){
|
||||||
// Write time
|
// Write time
|
||||||
g.setFontAlign(-1, -1, 0);
|
g.setFontAlign(-1, -1, 0);
|
||||||
g.setColor(cWhite);
|
g.setColor(cWhite);
|
||||||
var currentDate = new Date();
|
let currentDate = new Date();
|
||||||
var timeStr = locale.time(currentDate,1);
|
let timeStr = locale.time(currentDate,1);
|
||||||
g.setFontAntonioLarge();
|
g.setFontAntonioLarge();
|
||||||
if(settings.fullscreen){
|
if(settings.fullscreen){
|
||||||
g.drawString(timeStr, 27, 10);
|
g.drawString(timeStr, 27, 10);
|
||||||
|
@ -392,13 +396,13 @@ function drawPosition0(){
|
||||||
g.setColor(cWhite);
|
g.setColor(cWhite);
|
||||||
g.setFontAntonioMedium();
|
g.setFontAntonioMedium();
|
||||||
if(settings.fullscreen){
|
if(settings.fullscreen){
|
||||||
var dayStr = locale.dow(currentDate, true).toUpperCase();
|
let dayStr = locale.dow(currentDate, true).toUpperCase();
|
||||||
dayStr += " " + currentDate.getDate();
|
dayStr += " " + currentDate.getDate();
|
||||||
dayStr += " " + locale.month(currentDate, 1).toUpperCase();
|
dayStr += " " + locale.month(currentDate, 1).toUpperCase();
|
||||||
g.drawString(dayStr, 30, 56);
|
g.drawString(dayStr, 30, 56);
|
||||||
} else {
|
} else {
|
||||||
var dayStr = locale.dow(currentDate, true).toUpperCase();
|
let dayStr = locale.dow(currentDate, true).toUpperCase();
|
||||||
var date = currentDate.getDate();
|
let date = currentDate.getDate();
|
||||||
g.drawString(dayStr, 128, 35);
|
g.drawString(dayStr, 128, 35);
|
||||||
g.drawString(date, 128, 55);
|
g.drawString(date, 128, 55);
|
||||||
}
|
}
|
||||||
|
@ -412,11 +416,11 @@ function drawPosition0(){
|
||||||
|
|
||||||
// Draw state
|
// Draw state
|
||||||
drawState();
|
drawState();
|
||||||
}
|
};
|
||||||
|
|
||||||
function drawPosition1(){
|
let drawPosition1 = function(){
|
||||||
// Draw background image
|
// Draw background image
|
||||||
var offset = settings.fullscreen ? 0 : 24;
|
let offset = settings.fullscreen ? 0 : 24;
|
||||||
g.drawImage(bgRight, 149, offset);
|
g.drawImage(bgRight, 149, offset);
|
||||||
if(settings.fullscreen){
|
if(settings.fullscreen){
|
||||||
drawHorizontalBgLine(color1, 0, 140, offset, 4);
|
drawHorizontalBgLine(color1, 0, 140, offset, 4);
|
||||||
|
@ -444,8 +448,8 @@ function drawPosition1(){
|
||||||
|
|
||||||
// Plot HRM graph
|
// Plot HRM graph
|
||||||
if(plotMonth){
|
if(plotMonth){
|
||||||
var data = new Uint16Array(32);
|
let data = new Uint16Array(32);
|
||||||
var cnt = new Uint8Array(32);
|
let cnt = new Uint8Array(32);
|
||||||
health.readDailySummaries(new Date(), h=>{
|
health.readDailySummaries(new Date(), h=>{
|
||||||
data[h.day]+=h.bpm;
|
data[h.day]+=h.bpm;
|
||||||
if (h.bpm) cnt[h.day]++;
|
if (h.bpm) cnt[h.day]++;
|
||||||
|
@ -462,9 +466,9 @@ function drawPosition1(){
|
||||||
});
|
});
|
||||||
|
|
||||||
// Plot step graph
|
// Plot step graph
|
||||||
var data = new Uint16Array(32);
|
data = new Uint16Array(32);
|
||||||
health.readDailySummaries(new Date(), h=>data[h.day]+=h.steps/1000);
|
health.readDailySummaries(new Date(), h=>data[h.day]+=h.steps/1000);
|
||||||
var gridY = parseInt(Math.max.apply(Math, data)/2);
|
let gridY = parseInt(Math.max.apply(Math, data)/2);
|
||||||
gridY = gridY <= 0 ? 1 : gridY;
|
gridY = gridY <= 0 ? 1 : gridY;
|
||||||
require("graph").drawBar(g, data, {
|
require("graph").drawBar(g, data, {
|
||||||
axes : true,
|
axes : true,
|
||||||
|
@ -490,8 +494,8 @@ function drawPosition1(){
|
||||||
|
|
||||||
// Plot day
|
// Plot day
|
||||||
} else {
|
} else {
|
||||||
var data = new Uint16Array(24);
|
let data = new Uint16Array(24);
|
||||||
var cnt = new Uint8Array(24);
|
let cnt = new Uint8Array(24);
|
||||||
health.readDay(new Date(), h=>{
|
health.readDay(new Date(), h=>{
|
||||||
data[h.hr]+=h.bpm;
|
data[h.hr]+=h.bpm;
|
||||||
if (h.bpm) cnt[h.hr]++;
|
if (h.bpm) cnt[h.hr]++;
|
||||||
|
@ -508,9 +512,9 @@ function drawPosition1(){
|
||||||
});
|
});
|
||||||
|
|
||||||
// Plot step graph
|
// Plot step graph
|
||||||
var data = new Uint16Array(24);
|
data = new Uint16Array(24);
|
||||||
health.readDay(new Date(), h=>data[h.hr]+=h.steps);
|
health.readDay(new Date(), h=>data[h.hr]+=h.steps);
|
||||||
var gridY = parseInt(Math.max.apply(Math, data)/1000)*1000;
|
let gridY = parseInt(Math.max.apply(Math, data)/1000)*1000;
|
||||||
gridY = gridY <= 0 ? 1000 : gridY;
|
gridY = gridY <= 0 ? 1000 : gridY;
|
||||||
require("graph").drawBar(g, data, {
|
require("graph").drawBar(g, data, {
|
||||||
axes : true,
|
axes : true,
|
||||||
|
@ -534,9 +538,9 @@ function drawPosition1(){
|
||||||
g.drawString("DAY", 154, 115);
|
g.drawString("DAY", 154, 115);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
function draw(){
|
let draw = function(){
|
||||||
// Queue draw first to ensure that its called in one minute again.
|
// Queue draw first to ensure that its called in one minute again.
|
||||||
queueDraw();
|
queueDraw();
|
||||||
|
|
||||||
|
@ -557,14 +561,14 @@ function draw(){
|
||||||
} else {
|
} else {
|
||||||
Bangle.drawWidgets();
|
Bangle.drawWidgets();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Step counter via widget
|
* Step counter via widget
|
||||||
*/
|
*/
|
||||||
function getSteps() {
|
let getSteps = function() {
|
||||||
var steps = 0;
|
let steps = 0;
|
||||||
try{
|
try{
|
||||||
if (WIDGETS.wpedom !== undefined) {
|
if (WIDGETS.wpedom !== undefined) {
|
||||||
steps = WIDGETS.wpedom.getSteps();
|
steps = WIDGETS.wpedom.getSteps();
|
||||||
|
@ -578,15 +582,15 @@ function getSteps() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return steps;
|
return steps;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
function getWeather(){
|
let getWeather = function(){
|
||||||
var weatherJson;
|
let weatherJson;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
weatherJson = storage.readJSON('weather.json');
|
weatherJson = storage.readJSON('weather.json');
|
||||||
var weather = weatherJson.weather;
|
let weather = weatherJson.weather;
|
||||||
|
|
||||||
// Temperature
|
// Temperature
|
||||||
weather.temp = locale.temp(weather.temp-273.15);
|
weather.temp = locale.temp(weather.temp-273.15);
|
||||||
|
@ -596,7 +600,7 @@ function getWeather(){
|
||||||
|
|
||||||
// Wind
|
// Wind
|
||||||
const wind = locale.speed(weather.wind).match(/^(\D*\d*)(.*)$/);
|
const wind = locale.speed(weather.wind).match(/^(\D*\d*)(.*)$/);
|
||||||
var speedFactor = settings.speed == "kph" ? 1.0 : 1.0 / 1.60934;
|
let speedFactor = settings.speed == "kph" ? 1.0 : 1.0 / 1.60934;
|
||||||
weather.wind = Math.round(wind[1] * speedFactor);
|
weather.wind = Math.round(wind[1] * speedFactor);
|
||||||
|
|
||||||
return weather
|
return weather
|
||||||
|
@ -613,15 +617,15 @@ function getWeather(){
|
||||||
wdir: " ? ",
|
wdir: " ? ",
|
||||||
wrose: " ? "
|
wrose: " ? "
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle alarm
|
* Handle alarm
|
||||||
*/
|
*/
|
||||||
function isAlarmEnabled(){
|
let isAlarmEnabled = function(){
|
||||||
try{
|
try{
|
||||||
var alarm = require('sched');
|
let alarm = require('sched');
|
||||||
var alarmObj = alarm.getAlarm(TIMER_IDX);
|
let alarmObj = alarm.getAlarm(TIMER_IDX);
|
||||||
if(alarmObj===undefined || !alarmObj.on){
|
if(alarmObj===undefined || !alarmObj.on){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -630,35 +634,35 @@ function isAlarmEnabled(){
|
||||||
|
|
||||||
} catch(ex){ }
|
} catch(ex){ }
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
function getAlarmMinutes(){
|
let getAlarmMinutes = function(){
|
||||||
if(!isAlarmEnabled()){
|
if(!isAlarmEnabled()){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var alarm = require('sched');
|
let alarm = require('sched');
|
||||||
var alarmObj = alarm.getAlarm(TIMER_IDX);
|
let alarmObj = alarm.getAlarm(TIMER_IDX);
|
||||||
return Math.round(alarm.getTimeToAlarm(alarmObj)/(60*1000));
|
return Math.round(alarm.getTimeToAlarm(alarmObj)/(60*1000));
|
||||||
}
|
};
|
||||||
|
|
||||||
function increaseAlarm(){
|
let increaseAlarm = function(){
|
||||||
try{
|
try{
|
||||||
var minutes = isAlarmEnabled() ? getAlarmMinutes() : 0;
|
let minutes = isAlarmEnabled() ? getAlarmMinutes() : 0;
|
||||||
var alarm = require('sched')
|
let alarm = require('sched')
|
||||||
alarm.setAlarm(TIMER_IDX, {
|
alarm.setAlarm(TIMER_IDX, {
|
||||||
timer : (minutes+5)*60*1000,
|
timer : (minutes+5)*60*1000,
|
||||||
});
|
});
|
||||||
alarm.reload();
|
alarm.reload();
|
||||||
} catch(ex){ }
|
} catch(ex){ }
|
||||||
}
|
};
|
||||||
|
|
||||||
function decreaseAlarm(){
|
let decreaseAlarm = function(){
|
||||||
try{
|
try{
|
||||||
var minutes = getAlarmMinutes();
|
let minutes = getAlarmMinutes();
|
||||||
minutes -= 5;
|
minutes -= 5;
|
||||||
|
|
||||||
var alarm = require('sched')
|
let alarm = require('sched')
|
||||||
alarm.setAlarm(TIMER_IDX, undefined);
|
alarm.setAlarm(TIMER_IDX, undefined);
|
||||||
|
|
||||||
if(minutes > 0){
|
if(minutes > 0){
|
||||||
|
@ -669,13 +673,13 @@ function decreaseAlarm(){
|
||||||
|
|
||||||
alarm.reload();
|
alarm.reload();
|
||||||
} catch(ex){ }
|
} catch(ex){ }
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Listeners
|
* Listeners
|
||||||
*/
|
*/
|
||||||
Bangle.on('lcdPower',on=>{
|
let onLcdPower = on=>{
|
||||||
if (on) {
|
if (on) {
|
||||||
// Whenever we connect to Gadgetbridge, reading data from
|
// Whenever we connect to Gadgetbridge, reading data from
|
||||||
// health failed. Therefore, we update only partially...
|
// health failed. Therefore, we update only partially...
|
||||||
|
@ -685,31 +689,34 @@ Bangle.on('lcdPower',on=>{
|
||||||
if (drawTimeout) clearTimeout(drawTimeout);
|
if (drawTimeout) clearTimeout(drawTimeout);
|
||||||
drawTimeout = undefined;
|
drawTimeout = undefined;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
Bangle.on('lcdPower', onLcdPower);
|
||||||
|
|
||||||
Bangle.on('lock', function(isLocked) {
|
let onLock = function(isLocked) {
|
||||||
drawInfo();
|
drawInfo();
|
||||||
});
|
};
|
||||||
|
Bangle.on('lock', onLock);
|
||||||
|
|
||||||
Bangle.on('charging',function(charging) {
|
|
||||||
|
let onCharge = function(charging) {
|
||||||
drawState();
|
drawState();
|
||||||
});
|
};
|
||||||
|
Bangle.on('charging', onCharge);
|
||||||
|
|
||||||
function feedback(){
|
let feedback = function(){
|
||||||
Bangle.buzz(40, 0.3);
|
Bangle.buzz(40, 0.3);
|
||||||
}
|
};
|
||||||
|
|
||||||
// Touch gestures to control clock. We don't use swipe to be compatible with the bangle ecosystem
|
let onTouch = function(btn, e){
|
||||||
Bangle.on('touch', function(btn, e){
|
let left = parseInt(g.getWidth() * 0.2);
|
||||||
var left = parseInt(g.getWidth() * 0.2);
|
let right = g.getWidth() - left;
|
||||||
var right = g.getWidth() - left;
|
let upper = parseInt(g.getHeight() * 0.2);
|
||||||
var upper = parseInt(g.getHeight() * 0.2);
|
let lower = g.getHeight() - upper;
|
||||||
var lower = g.getHeight() - upper;
|
|
||||||
|
|
||||||
var is_left = e.x < left;
|
let is_left = e.x < left;
|
||||||
var is_right = e.x > right;
|
let is_right = e.x > right;
|
||||||
var is_upper = e.y < upper;
|
let is_upper = e.y < upper;
|
||||||
var is_lower = e.y > lower;
|
let is_lower = e.y > lower;
|
||||||
|
|
||||||
if(!settings.disableData){
|
if(!settings.disableData){
|
||||||
if(is_left && lcarsViewPos == 1){
|
if(is_left && lcarsViewPos == 1){
|
||||||
|
@ -744,16 +751,30 @@ Bangle.on('touch', function(btn, e){
|
||||||
draw();
|
draw();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
// Touch gestures to control clock. We don't use swipe to be compatible with the bangle ecosystem
|
||||||
|
Bangle.on('touch', onTouch);
|
||||||
|
|
||||||
|
let themeBefore = g.theme;
|
||||||
/*
|
/*
|
||||||
* Lets start widgets, listen for btn etc.
|
* Lets start widgets, listen for btn etc.
|
||||||
*/
|
*/
|
||||||
// Show launcher when middle button pressed
|
// Show launcher when middle button pressed
|
||||||
Bangle.setUI("clock");
|
Bangle.setUI({mode:"clock",remove:function() {
|
||||||
|
if (drawTimeout) clearTimeout(drawTimeout);
|
||||||
|
delete Graphics.prototype.setFontAntonioMedium;
|
||||||
|
delete Graphics.prototype.setFontAntonioLarge;
|
||||||
|
Bangle.removeListener("lcdPower",onLcdPower);
|
||||||
|
Bangle.removeListener("lock",onLock);
|
||||||
|
Bangle.removeListener("charging",onCharge);
|
||||||
|
Bangle.removeListener("touch",onTouch);
|
||||||
|
require('sched').setAlarm(TIMER_IDX, undefined);
|
||||||
|
g.setTheme(themeBefore);
|
||||||
|
widget_utils.cleanup();
|
||||||
|
}});
|
||||||
Bangle.loadWidgets();
|
Bangle.loadWidgets();
|
||||||
|
|
||||||
// Clear the screen once, at startup and draw clock
|
// Clear the screen once, at startup and draw clock
|
||||||
g.setTheme({bg:"#000",fg:"#fff",dark:true}).clear();
|
g.setTheme({bg:"#000",fg:"#fff",dark:true}).clear();
|
||||||
draw();
|
draw();
|
||||||
|
}
|
|
@ -26,7 +26,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var dataOptions = ["Steps", "Battery", "VREF", "HRM", "Temp", "Humidity", "Wind", "Altitude", "CoreT"];
|
var dataOptions = ["Steps", "Battery", "BattVolt", "VREF", "HRM", "Temp", "Humidity", "Wind", "Altitude", "CoreT"];
|
||||||
var speedOptions = ["kph", "mph"];
|
var speedOptions = ["kph", "mph"];
|
||||||
var color_options = ['Green','Orange','Cyan','Purple','Red','Blue','Yellow','White','Purple','Pink','Light Green','Dark Green'];
|
var color_options = ['Green','Orange','Cyan','Purple','Red','Blue','Yellow','White','Purple','Pink','Light Green','Dark Green'];
|
||||||
var bg_code = ['#00ff00','#FF9900','#0094FF','#FF00DC','#ff0000','#0000ff','#ffef00','#FFFFFF','#FF00FF','#6C00FF','#99FF00','#556B2F'];
|
var bg_code = ['#00ff00','#FF9900','#0094FF','#FF00DC','#ff0000','#0000ff','#ffef00','#FFFFFF','#FF00FF','#6C00FF','#99FF00','#556B2F'];
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"name": "LCARS Clock",
|
"name": "LCARS Clock",
|
||||||
"shortName":"LCARS",
|
"shortName":"LCARS",
|
||||||
"icon": "lcars.png",
|
"icon": "lcars.png",
|
||||||
"version":"0.27",
|
"version":"0.29",
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"supports": ["BANGLEJS2"],
|
"supports": ["BANGLEJS2"],
|
||||||
"description": "Library Computer Access Retrieval System (LCARS) clock.",
|
"description": "Library Computer Access Retrieval System (LCARS) clock.",
|
||||||
|
@ -16,5 +16,6 @@
|
||||||
{"name":"lcars.app.js","url":"lcars.app.js"},
|
{"name":"lcars.app.js","url":"lcars.app.js"},
|
||||||
{"name":"lcars.img","url":"lcars.icon.js","evaluate":true},
|
{"name":"lcars.img","url":"lcars.icon.js","evaluate":true},
|
||||||
{"name":"lcars.settings.js","url":"lcars.settings.js"}
|
{"name":"lcars.settings.js","url":"lcars.settings.js"}
|
||||||
]
|
],
|
||||||
|
"data":[{"name":"lcars.setting.json"}]
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,5 +13,8 @@
|
||||||
{"name":"limelight.app.js","url":"limelight.app.js"},
|
{"name":"limelight.app.js","url":"limelight.app.js"},
|
||||||
{"name":"limelight.settings.js","url":"limelight.settings.js"},
|
{"name":"limelight.settings.js","url":"limelight.settings.js"},
|
||||||
{"name":"limelight.img","url":"limelight.icon.js","evaluate":true}
|
{"name":"limelight.img","url":"limelight.icon.js","evaluate":true}
|
||||||
|
],
|
||||||
|
"data": [
|
||||||
|
{"name":"limelight.json"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,5 +14,6 @@
|
||||||
{"name":"linuxclock.app.js","url":"app.js"},
|
{"name":"linuxclock.app.js","url":"app.js"},
|
||||||
{"name":"linuxclock.img","url":"app-icon.js","evaluate":true},
|
{"name":"linuxclock.img","url":"app-icon.js","evaluate":true},
|
||||||
{"name":"linuxclock.settings.js","url":"settings.js"}
|
{"name":"linuxclock.settings.js","url":"settings.js"}
|
||||||
]
|
],
|
||||||
|
"data":[{"name":"linuxclock.setting.json"}]
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,5 +10,6 @@
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"loadingscreen.settings.js","url":"settings.js"}
|
{"name":"loadingscreen.settings.js","url":"settings.js"}
|
||||||
]
|
],
|
||||||
|
"data":[{"name":".loading"}]
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,4 +96,7 @@
|
||||||
Nav messages with '/' now get split on newlines
|
Nav messages with '/' now get split on newlines
|
||||||
0.70: Handle nav messages from newer Gadgetbridge builds that output distance as a String
|
0.70: Handle nav messages from newer Gadgetbridge builds that output distance as a String
|
||||||
If we receive a 'music' message and we're in the messages app (but not showing a message) show music (#2814)
|
If we receive a 'music' message and we're in the messages app (but not showing a message) show music (#2814)
|
||||||
0.71: Cancel buzzing when watch unlocked, or when different messages viewed
|
0.71: Cancel buzzing when watch unlocked, or when different messages viewed
|
||||||
|
On 2v18.64+ firmware, 'No Messages' now has a 'back' button
|
||||||
|
0.72: Nav message updastes don't automatically launch navigation menu unless they're new
|
||||||
|
0.73: Add sharp left+right nav icons
|
|
@ -70,6 +70,8 @@ var onMessagesModified = function(type,msg) {
|
||||||
if (msg.state && msg.state!="play") openMusic = false; // no longer playing music to go back to
|
if (msg.state && msg.state!="play") openMusic = false; // no longer playing music to go back to
|
||||||
if ((active!=undefined) && (active!="list") && (active!="music")) return; // don't open music over other screens (but do if we're in the main menu)
|
if ((active!=undefined) && (active!="list") && (active!="music")) return; // don't open music over other screens (but do if we're in the main menu)
|
||||||
}
|
}
|
||||||
|
if (msg && msg.id=="nav" && msg.t=="modify" && active!="map")
|
||||||
|
return; // don't show an updated nav message if we're just in the menu
|
||||||
showMessage(msg&&msg.id);
|
showMessage(msg&&msg.id);
|
||||||
};
|
};
|
||||||
Bangle.on("message", onMessagesModified);
|
Bangle.on("message", onMessagesModified);
|
||||||
|
@ -102,6 +104,8 @@ function showMapMessage(msg) {
|
||||||
case "right": img = "GhcBAABgAAA8AAAPgAAB8AAAPgAAB8D///j///9///+/AAPPAAHjgAD44AB8OAA+DgAPA4ABAOAAADgAAA4AAAOAAADgAAA4AAAOAAAA";break;
|
case "right": img = "GhcBAABgAAA8AAAPgAAB8AAAPgAAB8D///j///9///+/AAPPAAHjgAD44AB8OAA+DgAPA4ABAOAAADgAAA4AAAOAAADgAAA4AAAOAAAA";break;
|
||||||
case "left_slight": img = "ERgB//B/+D/8H4AP4Af4A74Bz4Dj4HD4OD4cD4AD4ADwADwADgAHgAPAAOAAcAA4ABwADgAH";break;
|
case "left_slight": img = "ERgB//B/+D/8H4AP4Af4A74Bz4Dj4HD4OD4cD4AD4ADwADwADgAHgAPAAOAAcAA4ABwADgAH";break;
|
||||||
case "right_slight": img = "ERgBB/+D/8H/4APwA/gD/APuA+cD44Phw+Dj4HPgAeAB4ADgAPAAeAA4ABwADgAHAAOAAcAA";break;
|
case "right_slight": img = "ERgBB/+D/8H/4APwA/gD/APuA+cD44Phw+Dj4HPgAeAB4ADgAPAAeAA4ABwADgAHAAOAAcAA";break;
|
||||||
|
case "left_sharp": img = "GBaBAAAA+AAB/AAH/gAPjgAeBwA8BwB4B+DwB+HgB+PAB+eAB+8AB+4AB/wAB/gAB//gB//gB//gBwAABwAABwAABwAABw=="; break;
|
||||||
|
case "right_sharp": img = "GBaBAB8AAD+AAH/gAHHwAOB4AOA8AOAeAOAPB+AHh+ADx+AB5+AA9+AAd+AAP+AAH+AH/+AH/+AH/+AAAOAAAOAAAOAAAA==";break;
|
||||||
case "keep_left": img = "ERmBAACAAOAB+AD+AP+B/+H3+PO+8c8w4wBwADgAHgAPAAfAAfAAfAAfAAeAAeAAcAA8AA4ABwADgA==";break;
|
case "keep_left": img = "ERmBAACAAOAB+AD+AP+B/+H3+PO+8c8w4wBwADgAHgAPAAfAAfAAfAAfAAeAAeAAcAA8AA4ABwADgA==";break;
|
||||||
case "keep_right": img = "ERmBAACAAOAA/AD+AP+A//D/fPueeceY4YBwADgAPAAeAB8AHwAfAB8ADwAPAAcAB4ADgAHAAOAAAA==";break;
|
case "keep_right": img = "ERmBAACAAOAA/AD+AP+A//D/fPueeceY4YBwADgAPAAeAB8AHwAfAB8ADwAPAAcAB4ADgAHAAOAAAA==";break;
|
||||||
case "uturn_left": img = "GRiBAAAH4AAP/AAP/wAPj8APAfAPAHgHgB4DgA8BwAOA4AHAcADsOMB/HPA7zvgd9/gOf/gHH/gDh/gBwfgA4DgAcBgAOAAAHAAADgAABw==";break;
|
case "uturn_left": img = "GRiBAAAH4AAP/AAP/wAPj8APAfAPAHgHgB4DgA8BwAOA4AHAcADsOMB/HPA7zvgd9/gOf/gHH/gDh/gBwfgA4DgAcBgAOAAAHAAADgAABw==";break;
|
||||||
|
@ -414,8 +418,9 @@ function checkMessages(options) {
|
||||||
if (!options.clockIfNoMsg) return E.showPrompt(/*LANG*/"No Messages",{
|
if (!options.clockIfNoMsg) return E.showPrompt(/*LANG*/"No Messages",{
|
||||||
title:/*LANG*/"Messages",
|
title:/*LANG*/"Messages",
|
||||||
img:require("heatshrink").decompress(atob("kkk4UBrkc/4AC/tEqtACQkBqtUDg0VqAIGgoZFDYQIIM1sD1QAD4AIBhnqA4WrmAIBhc6BAWs8AIBhXOBAWz0AIC2YIC5wID1gkB1c6BAYFBEQPqBAYXBEQOqBAnDAIQaEnkAngaEEAPDFgo+IKA5iIOhCGIAFb7RqAIGgtUBA0VqobFgNVA")),
|
img:require("heatshrink").decompress(atob("kkk4UBrkc/4AC/tEqtACQkBqtUDg0VqAIGgoZFDYQIIM1sD1QAD4AIBhnqA4WrmAIBhc6BAWs8AIBhXOBAWz0AIC2YIC5wID1gkB1c6BAYFBEQPqBAYXBEQOqBAnDAIQaEnkAngaEEAPDFgo+IKA5iIOhCGIAFb7RqAIGgtUBA0VqobFgNVA")),
|
||||||
buttons : {/*LANG*/"Ok":1}
|
buttons : {/*LANG*/"Ok":1},
|
||||||
}).then(() => { load() });
|
back: () => load()
|
||||||
|
}).then(() => load());
|
||||||
return load();
|
return load();
|
||||||
}
|
}
|
||||||
// we have >0 messages
|
// we have >0 messages
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "messagegui",
|
"id": "messagegui",
|
||||||
"name": "Message UI",
|
"name": "Message UI",
|
||||||
"shortName": "Messages",
|
"shortName": "Messages",
|
||||||
"version": "0.71",
|
"version": "0.73",
|
||||||
"description": "Default app to display notifications from iOS and Gadgetbridge/Android",
|
"description": "Default app to display notifications from iOS and Gadgetbridge/Android",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "app",
|
"type": "app",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Messages library
|
# Messages library
|
||||||
|
|
||||||
This library handles the passing of messages. It can storess a list of messages
|
This library handles the passing of messages. It can stores a list of messages
|
||||||
and allows them to be retrieved by other apps.
|
and allows them to be retrieved by other apps.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
@ -37,18 +37,10 @@ myMessageListener = Bangle.on("message", (type, message)=>{
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
Apps can launch the full GUI by calling `require("messages").openGUI()`, if you
|
Apps can launch the currently installed Message GUI by calling `require("messages").openGUI()`.
|
||||||
want to write your own GUI, it should include boot code that listens for
|
If you want to write your own GUI, it should include a library called `messagegui`
|
||||||
`"messageGUI"` events:
|
with a method called `open` that will cause it to be opened, with the
|
||||||
|
optionally supplied message. See `apps/messagegui/lib.js` for an example.
|
||||||
```js
|
|
||||||
Bangle.on("messageGUI", message=>{
|
|
||||||
if (message.handled) return; // another app already opened it's GUI
|
|
||||||
message.handled = true; // prevent other apps form launching
|
|
||||||
Bangle.load("my_message_gui.app.js");
|
|
||||||
})
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Requests
|
## Requests
|
||||||
|
|
|
@ -107,7 +107,7 @@ exports.dismiss = function(msg) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emit a "type=openGUI" event, to open GUI app
|
* Open the Messages GUI app
|
||||||
*
|
*
|
||||||
* @param {object} [msg={}] Message the app should show
|
* @param {object} [msg={}] Message the app should show
|
||||||
*/
|
*/
|
||||||
|
@ -215,7 +215,7 @@ exports.buzz = function(msgSrc) {
|
||||||
|
|
||||||
let repeat = msgSettings.repeat;
|
let repeat = msgSettings.repeat;
|
||||||
if (repeat===undefined) repeat = 4; // repeat may be zero
|
if (repeat===undefined) repeat = 4; // repeat may be zero
|
||||||
if (repeat)
|
if (repeat)
|
||||||
{
|
{
|
||||||
exports.buzzInterval = setInterval(() => require("buzz").pattern(pattern), repeat*1000);
|
exports.buzzInterval = setInterval(() => require("buzz").pattern(pattern), repeat*1000);
|
||||||
let vibrateTimeout = msgSettings.vibrateTimeout;
|
let vibrateTimeout = msgSettings.vibrateTimeout;
|
||||||
|
|
|
@ -13,5 +13,6 @@
|
||||||
{"name":"metronome.app.js","url":"metronome.js"},
|
{"name":"metronome.app.js","url":"metronome.js"},
|
||||||
{"name":"metronome.img","url":"metronome-icon.js","evaluate":true},
|
{"name":"metronome.img","url":"metronome-icon.js","evaluate":true},
|
||||||
{"name":"metronome.settings.js","url":"settings.js"}
|
{"name":"metronome.settings.js","url":"settings.js"}
|
||||||
]
|
],
|
||||||
|
"data":[{"name":"metronome.settings.json"}]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
0.01: Initial version
|
0.01: Initial version
|
||||||
0.02: Update for time_utils module
|
0.02: Update for time_utils module
|
||||||
0.03: Use default Bangle formatter for booleans
|
0.03: Use default Bangle formatter for booleans
|
||||||
|
0.04: Remove copied sched alarm.js & import newer features (oneshot alarms)
|
||||||
|
|