Merge branch 'espruino:master' into master
96
apps.json
|
@ -77,7 +77,7 @@
|
||||||
{
|
{
|
||||||
"id": "messages",
|
"id": "messages",
|
||||||
"name": "Messages",
|
"name": "Messages",
|
||||||
"version": "0.13",
|
"version": "0.14",
|
||||||
"description": "App to display notifications from iOS and Gadgetbridge",
|
"description": "App to display notifications from iOS and Gadgetbridge",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "app",
|
"type": "app",
|
||||||
|
@ -132,7 +132,7 @@
|
||||||
{
|
{
|
||||||
"id": "health",
|
"id": "health",
|
||||||
"name": "Health Tracking",
|
"name": "Health Tracking",
|
||||||
"version": "0.08",
|
"version": "0.09",
|
||||||
"description": "Logs health data and provides an app to view it (requires firmware 2v10.100 or later)",
|
"description": "Logs health data and provides an app to view it (requires firmware 2v10.100 or later)",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"tags": "tool,system,health",
|
"tags": "tool,system,health",
|
||||||
|
@ -167,7 +167,7 @@
|
||||||
{
|
{
|
||||||
"id": "setting",
|
"id": "setting",
|
||||||
"name": "Settings",
|
"name": "Settings",
|
||||||
"version": "0.37",
|
"version": "0.38",
|
||||||
"description": "A menu for setting up Bangle.js",
|
"description": "A menu for setting up Bangle.js",
|
||||||
"icon": "settings.png",
|
"icon": "settings.png",
|
||||||
"tags": "tool,system",
|
"tags": "tool,system",
|
||||||
|
@ -554,7 +554,7 @@
|
||||||
{
|
{
|
||||||
"id": "impwclock",
|
"id": "impwclock",
|
||||||
"name": "Imprecise Word Clock",
|
"name": "Imprecise Word Clock",
|
||||||
"version": "0.03",
|
"version": "0.04",
|
||||||
"description": "Imprecise word clock for vacations, weekends, and those who never need accurate time.",
|
"description": "Imprecise word clock for vacations, weekends, and those who never need accurate time.",
|
||||||
"icon": "clock-impword.png",
|
"icon": "clock-impword.png",
|
||||||
"type": "clock",
|
"type": "clock",
|
||||||
|
@ -1590,7 +1590,7 @@
|
||||||
{
|
{
|
||||||
"id": "widpedom",
|
"id": "widpedom",
|
||||||
"name": "Pedometer widget",
|
"name": "Pedometer widget",
|
||||||
"version": "0.19",
|
"version": "0.20",
|
||||||
"description": "Daily pedometer widget",
|
"description": "Daily pedometer widget",
|
||||||
"icon": "widget.png",
|
"icon": "widget.png",
|
||||||
"type": "widget",
|
"type": "widget",
|
||||||
|
@ -3478,8 +3478,8 @@
|
||||||
{
|
{
|
||||||
"id": "speedalt2",
|
"id": "speedalt2",
|
||||||
"name": "GPS Adventure Sports II",
|
"name": "GPS Adventure Sports II",
|
||||||
"shortName": "GPS Adv Sport II",
|
"shortName":"GPS Adv Sport II",
|
||||||
"version": "0.07",
|
"version":"1.10",
|
||||||
"description": "GPS speed, altitude and distance to waypoint display. Designed for easy viewing and use during outdoor activities such as para-gliding, hang-gliding, sailing, cycling etc.",
|
"description": "GPS speed, altitude and distance to waypoint display. Designed for easy viewing and use during outdoor activities such as para-gliding, hang-gliding, sailing, cycling etc.",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "app",
|
"type": "app",
|
||||||
|
@ -4014,11 +4014,12 @@
|
||||||
{
|
{
|
||||||
"id": "thermom",
|
"id": "thermom",
|
||||||
"name": "Thermometer",
|
"name": "Thermometer",
|
||||||
"version": "0.04",
|
"version": "0.05",
|
||||||
"description": "Displays the current temperature in degree Celsius, updated every 20 seconds",
|
"description": "Displays the current temperature in degree Celsius/Fahrenheit (depending on locale), updates every 10 seconds with average of last 5 readings.",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"tags": "tool",
|
"tags": "tool",
|
||||||
"supports": ["BANGLEJS", "BANGLEJS2"],
|
"supports": ["BANGLEJS", "BANGLEJS2"],
|
||||||
|
"screenshots": [{"url":"screenshot.png"}],
|
||||||
"allow_emulator": true,
|
"allow_emulator": true,
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"thermom.app.js","url":"app.js"},
|
{"name":"thermom.app.js","url":"app.js"},
|
||||||
|
@ -4080,7 +4081,7 @@
|
||||||
"id": "thermomF",
|
"id": "thermomF",
|
||||||
"name": "Fahrenheit Temp",
|
"name": "Fahrenheit Temp",
|
||||||
"version": "0.01",
|
"version": "0.01",
|
||||||
"description": "A modification of the Thermometer App to display temprature in Fahrenheit",
|
"description": "[NOT RECOMMENDED] A modification of the Thermometer App to display temprature in Fahrenheit. Please use the 'Thermometer App' and install 'Languages' to get the temperature in the correct format for your locale.",
|
||||||
"icon": "thermf.png",
|
"icon": "thermf.png",
|
||||||
"tags": "tool",
|
"tags": "tool",
|
||||||
"supports": ["BANGLEJS"],
|
"supports": ["BANGLEJS"],
|
||||||
|
@ -4209,7 +4210,7 @@
|
||||||
"id": "pastel",
|
"id": "pastel",
|
||||||
"name": "Pastel Clock",
|
"name": "Pastel Clock",
|
||||||
"shortName": "Pastel",
|
"shortName": "Pastel",
|
||||||
"version": "0.08",
|
"version": "0.09",
|
||||||
"description": "A Configurable clock with custom fonts and background. Has a cyclic information line that includes, day, date, battery, sunrise and sunset times",
|
"description": "A Configurable clock with custom fonts and background. Has a cyclic information line that includes, day, date, battery, sunrise and sunset times",
|
||||||
"icon": "pastel.png",
|
"icon": "pastel.png",
|
||||||
"dependencies": {"mylocation":"app", "widpedom":"app"},
|
"dependencies": {"mylocation":"app", "widpedom":"app"},
|
||||||
|
@ -4724,8 +4725,9 @@
|
||||||
"id": "pebble",
|
"id": "pebble",
|
||||||
"name": "Pebble Clock",
|
"name": "Pebble Clock",
|
||||||
"shortName": "Pebble",
|
"shortName": "Pebble",
|
||||||
"version": "0.04",
|
"version": "0.06",
|
||||||
"description": "A pebble style clock to keep the rebellion going",
|
"description": "A pebble style clock to keep the rebellion going",
|
||||||
|
"dependencies": {"widpedom":"app"},
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"icon": "pebble.png",
|
"icon": "pebble.png",
|
||||||
"screenshots": [{"url":"pebble_screenshot.png"}],
|
"screenshots": [{"url":"pebble_screenshot.png"}],
|
||||||
|
@ -4859,10 +4861,10 @@
|
||||||
"id": "ptlaunch",
|
"id": "ptlaunch",
|
||||||
"name": "Pattern Launcher",
|
"name": "Pattern Launcher",
|
||||||
"shortName": "Pattern Launcher",
|
"shortName": "Pattern Launcher",
|
||||||
"version": "0.10",
|
"version": "0.11",
|
||||||
"description": "Directly launch apps from the clock screen with custom patterns.",
|
"description": "Directly launch apps from the clock screen with custom patterns.",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"screenshots": [{"url":"main_menu_add.png"}, {"url":"add_pattern.png"}, {"url":"select_app.png"}, {"url":"main_menu_manage.png"}, {"url":"manage_patterns.png"}],
|
"screenshots": [{"url":"manage_patterns_light.png"}],
|
||||||
"tags": "tools",
|
"tags": "tools",
|
||||||
"supports": ["BANGLEJS2"],
|
"supports": ["BANGLEJS2"],
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
|
@ -4877,11 +4879,11 @@
|
||||||
"id": "rebble",
|
"id": "rebble",
|
||||||
"name": "Rebble Clock",
|
"name": "Rebble Clock",
|
||||||
"shortName": "Rebble",
|
"shortName": "Rebble",
|
||||||
"version": "0.02",
|
"version": "0.03",
|
||||||
"description": "A Pebble style clock, with configurable background, three sidebars including steps, day, date, sunrise, sunset, long live the rebellion",
|
"description": "A Pebble style clock, with configurable background, three sidebars including steps, day, date, sunrise, sunset, long live the rebellion",
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"icon": "rebble.png",
|
"icon": "rebble.png",
|
||||||
"dependencies": {"mylocation":"app"},
|
"dependencies": {"mylocation":"app", "widpedom":"app"},
|
||||||
"screenshots": [{"url":"screenshot_rebble.png"}],
|
"screenshots": [{"url":"screenshot_rebble.png"}],
|
||||||
"type": "clock",
|
"type": "clock",
|
||||||
"tags": "clock",
|
"tags": "clock",
|
||||||
|
@ -4919,6 +4921,7 @@
|
||||||
"supports" : ["BANGLEJS", "BANGLEJS2"],
|
"supports" : ["BANGLEJS", "BANGLEJS2"],
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"storage": [
|
"storage": [
|
||||||
|
{"name":"clicompleteclk.app.js","url":"app.js"},
|
||||||
{"name":"clicompleteclk.img","url":"app-icon.js","evaluate":true},
|
{"name":"clicompleteclk.img","url":"app-icon.js","evaluate":true},
|
||||||
{"name":"clicompleteclk.settings.js","url":"settings.js"}
|
{"name":"clicompleteclk.settings.js","url":"settings.js"}
|
||||||
],
|
],
|
||||||
|
@ -4942,7 +4945,7 @@
|
||||||
{ "id": "pooqround",
|
{ "id": "pooqround",
|
||||||
"name": "pooq Round watch face",
|
"name": "pooq Round watch face",
|
||||||
"shortName":"pooq Round",
|
"shortName":"pooq Round",
|
||||||
"version":"0.00",
|
"version":"0.01",
|
||||||
"description": "A 24 hour analogue watchface with high legibility and a novel style.",
|
"description": "A 24 hour analogue watchface with high legibility and a novel style.",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "clock",
|
"type": "clock",
|
||||||
|
@ -4978,8 +4981,8 @@
|
||||||
"id": "showimg",
|
"id": "showimg",
|
||||||
"name": "simple image viewer",
|
"name": "simple image viewer",
|
||||||
"shortName":"showImage",
|
"shortName":"showImage",
|
||||||
"version":"0.1",
|
"version":"0.2",
|
||||||
"description": "Displays the image file in showimage.user.img. Returns to watch face after 60s or button push. I use it to display my vaccination certificate.",
|
"description": "Displays the image in \"showimg.user.img\". The file has to be uploaded via the espruino IDE. Returns to watch face after 60s or button push. I use it to display my vaccination certificate.",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"tags": "tool",
|
"tags": "tool",
|
||||||
"supports" : ["BANGLEJS2"],
|
"supports" : ["BANGLEJS2"],
|
||||||
|
@ -5004,5 +5007,60 @@
|
||||||
{"name":"lapcounter.app.js","url":"app.js"},
|
{"name":"lapcounter.app.js","url":"app.js"},
|
||||||
{"name":"lapcounter.img","url":"app-icon.js","evaluate":true}
|
{"name":"lapcounter.img","url":"app-icon.js","evaluate":true}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pebbled",
|
||||||
|
"name": "Pebble Clock with distance",
|
||||||
|
"shortName": "Pebble + distance",
|
||||||
|
"version": "0.1",
|
||||||
|
"description": "Fork of Pebble Clock with distance in KM. Both step count and the distance are on the main screen. Default step length = 0.75m (can be changed in settings).",
|
||||||
|
"readme": "README.md",
|
||||||
|
"icon": "pebbled.png",
|
||||||
|
"screenshots": [{"url":"pebble_screenshot.png"}],
|
||||||
|
"type": "clock",
|
||||||
|
"tags": "clock,distance",
|
||||||
|
"supports": ["BANGLEJS2"],
|
||||||
|
"storage": [
|
||||||
|
{"name":"pebbled.app.js","url":"pebbled.app.js"},
|
||||||
|
{"name":"pebbled.settings.js","url":"pebbled.settings.js"},
|
||||||
|
{"name":"pebbled.img","url":"pebbled.icon.js","evaluate":true}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ "id": "circlesclock",
|
||||||
|
"name": "Circles clock",
|
||||||
|
"shortName":"Circles clock",
|
||||||
|
"version":"0.02",
|
||||||
|
"description": "A clock with circles for different data at the bottom in a probably familiar style",
|
||||||
|
"icon": "app.png",
|
||||||
|
"dependencies": {"widpedom":"app"},
|
||||||
|
"type": "clock",
|
||||||
|
"tags": "clock",
|
||||||
|
"supports" : ["BANGLEJS2"],
|
||||||
|
"allow_emulator":true,
|
||||||
|
"readme": "README.md",
|
||||||
|
"storage": [
|
||||||
|
{"name":"circlesclock.app.js","url":"app.js"},
|
||||||
|
{"name":"circlesclock.img","url":"app-icon.js","evaluate":true},
|
||||||
|
{"name":"circlesclock.settings.js","url":"settings.js"}
|
||||||
|
],
|
||||||
|
"data": [
|
||||||
|
{"name":"circlesclock.json"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ltherm",
|
||||||
|
"name": "Localized Thermometer",
|
||||||
|
"shortName": "Thermometer",
|
||||||
|
"version": "0.01",
|
||||||
|
"description": "Displays the current temperature in localized units.",
|
||||||
|
"icon": "thermf.png",
|
||||||
|
"tags": "tool",
|
||||||
|
"supports": ["BANGLEJS2"],
|
||||||
|
"allow_emulator": true,
|
||||||
|
"readme": "README.md",
|
||||||
|
"storage": [
|
||||||
|
{"name":"ltherm.app.js","url":"app.js"},
|
||||||
|
{"name":"ltherm.img","url":"icon.js","evaluate":true}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
0.04: Fix tapping at very bottom of list, exit on inactivity
|
|
||||||
0.03: Add "Calculating" placeholder, update JSON save format
|
|
||||||
0.02: Fix JSON save format
|
|
||||||
0.01: First release
|
0.01: First release
|
||||||
|
0.02: Fix JSON save format
|
||||||
|
0.03: Add "Calculating" placeholder, update JSON save format
|
||||||
|
0.04: Fix tapping at very bottom of list, exit on inactivity
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
require("heatshrink").decompress(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH8AAAAAAMGAAAAAAYDAAAAAAwBgAAAABgAwAAAABAAQAAAABAAQAAAABAAQAAAABAAQAAAABAAQAAAABgAwAAAAAwBgAAAAAYDAAAAAAMGAAAAAAH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH8AAAAAAP+AAAAAAf/AAAAAA//gAAAAB//wAAAAB//wAAAAB//wAAAAB//wAAAAB//wAAAAB//wAAAAB//wAAAAA//gAAAAAf/AAAAAAP+AAAAAAH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"))
|
require("heatshrink").decompress(atob("mEwgIurg/wAocMjAFDjEMIAkGAodggYFDoBLEAq4jFF4o7FI4pTFOLsP/AFDj/8Aoc//wFDv//As4vFHYpHFOLoAPA=="))
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
0.01: New clock
|
||||||
|
0.02: Fix icon & add battery warn functionality
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Circles clock
|
||||||
|
|
||||||
|
A clock with circles for different data at the bottom in a probably familiar style
|
||||||
|
|
||||||
|
It shows besides time, date and day of week the following information:
|
||||||
|
* Steps (requires [pedometer widget](https://banglejs.com/apps/#pedometer))
|
||||||
|
* Heart rate (when screen is on and unlocked)
|
||||||
|
* Battery (including charging and battery low)
|
||||||
|
|
||||||
|
## Screenshot
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## TODO
|
||||||
|
* Show weather information
|
||||||
|
|
||||||
|
## Creator
|
||||||
|
Marco ([myxor](https://github.com/myxor))
|
||||||
|
|
||||||
|
## Icons
|
||||||
|
Icons taken from [materialdesignicons](https://materialdesignicons.com) under Apache License 2.0
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwwcCIf4ALv///gFCv0Agf+CJP/wAODAwPAEpAjCCIX8h4RMj/+g/8gP4CA4LBDoP/GpkH8EP4/8LIIRMAQIOCCJU/CgQOBEwMPI5ARCR4YRJgP/gB3CI5Z0CCIiABfHRfEj+BAoN+n4FBLIkP/8chwRBx5cC//8v4REhytDgYRCv//8fxEYwRFgfxA4I1FRgI1D+JHE/7FINZzCBAAc4CRU4/kB44FCjgRKLQRlBPQ4RHgYCB/jpBABB6BPoKzBCJYAGuD/vAB1JkgLJm3bAgUCpMnwDdCPwIFChu27dgAoMSCIP+FAQRB+AFBtoRBtgFByQCBRIIoBAocDtonBAQWQdgXAgVIAocDEAUNwEEyEHBYUSoE//gRCsI7BxvACIILDCIcBCIYFCCJ3/wIRCIIYRBI4h6CAoJrDLJYRDDwJ9LAoKhBoMDUIcEgFwUIQREgUBaAcIkhPCAAQzBAAUBdIhhDAAMGCIkAkAFEdAQAFA=="))
|
|
@ -0,0 +1,235 @@
|
||||||
|
const locale = require("locale");
|
||||||
|
const heatshrink = require("heatshrink");
|
||||||
|
|
||||||
|
const shoesIcon = heatshrink.decompress(atob("h0OwYJGgmAAgUBkgECgVJB4cSoAUDyEBkARDpADBhMAyQRBgVAkgmDhIUDAAuQAgY1DAAYA="));
|
||||||
|
const heartIcon = heatshrink.decompress(atob("h0OwYOLkmQhMkgACByVJgESpIFBpEEBAIFBCgIFCCgsABwcAgQOCAAMSpAwDyBNM"));
|
||||||
|
const powerIcon = heatshrink.decompress(atob("h0OwYQNsAED7AEDmwEDtu2AgUbtuABwXbBIUN23AAoYOCgEDFIgODABI"));
|
||||||
|
const powerIconGreen = heatshrink.decompress(atob("h0OwYQNkAEDpAEDiQEDkmSAgUJkmABwVJBIUEyVAAoYOCgEBFIgODABI"));
|
||||||
|
const powerIconRed = heatshrink.decompress(atob("h0OwYQNoAEDyAEDkgEDpIFDiVJBweSAgUJkmAAoYZDgQpEBwYAJA"));
|
||||||
|
|
||||||
|
const SETTINGS_FILE = "circlesclock.json";
|
||||||
|
let settings;
|
||||||
|
|
||||||
|
function loadSettings() {
|
||||||
|
settings = require("Storage").readJSON(SETTINGS_FILE, 1) || {
|
||||||
|
'maxHR': 200,
|
||||||
|
'stepGoal': 10000,
|
||||||
|
'batteryWarn': 30
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const colorFg = '#fff';
|
||||||
|
const colorBg = '#000';
|
||||||
|
const colorGrey = '#808080';
|
||||||
|
const colorRed = '#ff0000';
|
||||||
|
const colorGreen = '#00ff00';
|
||||||
|
|
||||||
|
let hrtValue;
|
||||||
|
|
||||||
|
const h = g.getHeight();
|
||||||
|
const w = g.getWidth();
|
||||||
|
const hOffset = 30;
|
||||||
|
const h1 = Math.round(1 * h / 5 - hOffset);
|
||||||
|
const h2 = Math.round(3 * h / 5 - hOffset);
|
||||||
|
const h3 = Math.round(8 * h / 8 - hOffset);
|
||||||
|
const w1 = Math.round(w / 6);
|
||||||
|
const w2 = Math.round(3 * w / 6);
|
||||||
|
const w3 = Math.round(5 * w / 6);
|
||||||
|
const radiusOuter = 22;
|
||||||
|
const radiusInner = 16;
|
||||||
|
|
||||||
|
function draw() {
|
||||||
|
g.reset();
|
||||||
|
g.setColor(colorBg);
|
||||||
|
g.fillRect(0, 0, w, h);
|
||||||
|
|
||||||
|
// time
|
||||||
|
g.setFont("Vector:50");
|
||||||
|
g.setFontAlign(-1, -1);
|
||||||
|
g.setColor(colorFg);
|
||||||
|
g.drawString(locale.time(new Date(), 1), w / 10, h1 + 8);
|
||||||
|
|
||||||
|
// date & dow
|
||||||
|
g.setFont("Vector:20");
|
||||||
|
g.setFontAlign(-1, 0);
|
||||||
|
g.drawString(locale.date(new Date()), w / 10, h2);
|
||||||
|
g.drawString(locale.dow(new Date()), w / 10, h2 + 22);
|
||||||
|
|
||||||
|
// Steps circle
|
||||||
|
drawSteps();
|
||||||
|
|
||||||
|
// Heart circle
|
||||||
|
drawHeartRate();
|
||||||
|
|
||||||
|
// Battery circle
|
||||||
|
drawBattery();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function drawSteps() {
|
||||||
|
const steps = getSteps();
|
||||||
|
const blue = '#0000ff';
|
||||||
|
g.setColor(colorGrey);
|
||||||
|
g.fillCircle(w1, h3, radiusOuter);
|
||||||
|
|
||||||
|
const stepGoal = settings.stepGoal;
|
||||||
|
if (stepGoal > 0) {
|
||||||
|
let percent = steps / stepGoal;
|
||||||
|
if (stepGoal < steps) percent = 1;
|
||||||
|
drawGauge(w1, h3, percent, blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
g.setColor(colorBg);
|
||||||
|
g.fillCircle(w1, h3, radiusInner);
|
||||||
|
|
||||||
|
g.fillPoly([w1, h3, w1 - 15, h3 + radiusOuter + 5, w1 + 15, h3 + radiusOuter + 5]);
|
||||||
|
|
||||||
|
g.setFont("Vector:12");
|
||||||
|
g.setFontAlign(0, 0);
|
||||||
|
g.setColor(colorFg);
|
||||||
|
g.drawString(shortValue(steps), w1 + 2, h3);
|
||||||
|
|
||||||
|
g.drawImage(shoesIcon, w1 - 6, h3 + radiusOuter - 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawHeartRate() {
|
||||||
|
g.setColor(colorGrey);
|
||||||
|
g.fillCircle(w2, h3, radiusOuter);
|
||||||
|
|
||||||
|
if (hrtValue != undefined) {
|
||||||
|
const percent = hrtValue / settings.maxHR;
|
||||||
|
drawGauge(w2, h3, percent, colorRed);
|
||||||
|
}
|
||||||
|
|
||||||
|
g.setColor(colorBg);
|
||||||
|
g.fillCircle(w2, h3, radiusInner);
|
||||||
|
|
||||||
|
g.fillPoly([w2, h3, w2 - 15, h3 + radiusOuter + 5, w2 + 15, h3 + radiusOuter + 5]);
|
||||||
|
|
||||||
|
g.setFont("Vector:12");
|
||||||
|
g.setFontAlign(0, 0);
|
||||||
|
g.setColor(colorFg);
|
||||||
|
g.drawString(hrtValue != undefined ? hrtValue : "-", w2, h3);
|
||||||
|
|
||||||
|
g.drawImage(heartIcon, w2 - 6, h3 + radiusOuter - 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawBattery() {
|
||||||
|
const battery = E.getBattery();
|
||||||
|
const yellow = '#ffff00';
|
||||||
|
g.setColor(colorGrey);
|
||||||
|
g.fillCircle(w3, h3, radiusOuter);
|
||||||
|
|
||||||
|
if (battery > 0) {
|
||||||
|
const percent = battery / 100;
|
||||||
|
drawGauge(w3, h3, percent, yellow);
|
||||||
|
}
|
||||||
|
|
||||||
|
g.setColor(colorBg);
|
||||||
|
g.fillCircle(w3, h3, radiusInner);
|
||||||
|
|
||||||
|
g.fillPoly([w3, h3, w3 - 15, h3 + radiusOuter + 5, w3 + 15, h3 + radiusOuter + 5]);
|
||||||
|
|
||||||
|
g.setFont("Vector:12");
|
||||||
|
g.setFontAlign(0, 0);
|
||||||
|
|
||||||
|
let icon = powerIcon;
|
||||||
|
let color = colorFg;
|
||||||
|
if (Bangle.isCharging()) {
|
||||||
|
color = colorGreen;
|
||||||
|
icon = powerIconGreen;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (settings.batteryWarn != undefined && battery <= settings.batteryWarn) {
|
||||||
|
color = colorRed;
|
||||||
|
icon = powerIconRed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.setColor(color);
|
||||||
|
g.drawString(battery + '%', w3, h3);
|
||||||
|
|
||||||
|
g.drawImage(icon, w3 - 6, h3 + radiusOuter - 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
function radians(a) {
|
||||||
|
return a * Math.PI / 180;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function drawGauge(cx, cy, percent, color) {
|
||||||
|
let offset = 30;
|
||||||
|
let end = 300;
|
||||||
|
var i = 0;
|
||||||
|
var r = radiusInner + 3;
|
||||||
|
|
||||||
|
if (percent > 1) percent = 1;
|
||||||
|
|
||||||
|
var startrot = -offset;
|
||||||
|
var endrot = startrot - ((end - offset) * percent);
|
||||||
|
|
||||||
|
g.setColor(color);
|
||||||
|
|
||||||
|
// draw gauge
|
||||||
|
for (i = startrot; i > endrot; i -= 4) {
|
||||||
|
x = cx + r * Math.sin(radians(i));
|
||||||
|
y = cy + r * Math.cos(radians(i));
|
||||||
|
g.fillCircle(x, y, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function shortValue(v) {
|
||||||
|
if (isNaN(v)) return '-';
|
||||||
|
if (v <= 999) return v;
|
||||||
|
if (v >= 1000 && v < 10000) {
|
||||||
|
v = Math.floor(v / 100) * 100;
|
||||||
|
return (v / 1000).toFixed(1).replace(/\.0$/, '') + 'k';
|
||||||
|
}
|
||||||
|
if (v >= 10000) {
|
||||||
|
v = Math.floor(v / 1000) * 1000;
|
||||||
|
return (v / 1000).toFixed(1).replace(/\.0$/, '') + 'k';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSteps() {
|
||||||
|
if (WIDGETS.wpedom !== undefined) {
|
||||||
|
return WIDGETS.wpedom.getSteps();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bangle.on('lock', function(isLocked) {
|
||||||
|
if (!isLocked) {
|
||||||
|
Bangle.setHRMPower(1, "watch");
|
||||||
|
} else {
|
||||||
|
Bangle.setHRMPower(0, "watch");
|
||||||
|
}
|
||||||
|
drawHeartRate();
|
||||||
|
drawSteps();
|
||||||
|
});
|
||||||
|
|
||||||
|
Bangle.on('HRM', function(hrm) {
|
||||||
|
//if(hrm.confidence > 90){
|
||||||
|
hrtValue = hrm.bpm;
|
||||||
|
if (Bangle.isLCDOn())
|
||||||
|
drawHeartRate();
|
||||||
|
//} else {
|
||||||
|
// hrtValue = undefined;
|
||||||
|
//}
|
||||||
|
});
|
||||||
|
|
||||||
|
g.clear();
|
||||||
|
Bangle.loadWidgets();
|
||||||
|
/*
|
||||||
|
* we are not drawing the widgets as we are taking over the whole screen
|
||||||
|
* so we will blank out the draw() functions of each widget and change the
|
||||||
|
* area to the top bar doesn't get cleared.
|
||||||
|
*/
|
||||||
|
for (let wd of WIDGETS) {
|
||||||
|
wd.draw = () => {};
|
||||||
|
wd.area = "";
|
||||||
|
}
|
||||||
|
loadSettings();
|
||||||
|
setInterval(draw, 60000);
|
||||||
|
draw();
|
||||||
|
Bangle.setUI("clock");
|
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 3.5 KiB |
|
@ -0,0 +1,43 @@
|
||||||
|
(function(back) {
|
||||||
|
const SETTINGS_FILE = "circlesclock.json";
|
||||||
|
const storage = require('Storage');
|
||||||
|
let settings = storage.readJSON(SETTINGS_FILE, 1) || {};
|
||||||
|
function save(key, value) {
|
||||||
|
settings[key] = value;
|
||||||
|
storage.write(SETTINGS_FILE, settings);
|
||||||
|
}
|
||||||
|
E.showMenu({
|
||||||
|
'': { 'title': 'circlesclock' },
|
||||||
|
'max heartrate': {
|
||||||
|
value: "maxHR" in settings ? settings.maxHR : 200,
|
||||||
|
min: 20,
|
||||||
|
max : 250,
|
||||||
|
step: 10,
|
||||||
|
format: x => {
|
||||||
|
return x;
|
||||||
|
},
|
||||||
|
onchange: x => save('maxHR', x),
|
||||||
|
},
|
||||||
|
'step goal': {
|
||||||
|
value: "stepGoal" in settings ? settings.stepGoal : 10000,
|
||||||
|
min: 2000,
|
||||||
|
max : 50000,
|
||||||
|
step: 2000,
|
||||||
|
format: x => {
|
||||||
|
return x;
|
||||||
|
},
|
||||||
|
onchange: x => save('stepGoal', x),
|
||||||
|
},
|
||||||
|
'battery warn lvl': {
|
||||||
|
value: "batteryWarn" in settings ? settings.batteryWarn : 30,
|
||||||
|
min: 10,
|
||||||
|
max : 100,
|
||||||
|
step: 10,
|
||||||
|
format: x => {
|
||||||
|
return x + '%';
|
||||||
|
},
|
||||||
|
onchange: x => save('batteryWarn', x),
|
||||||
|
},
|
||||||
|
'< Back': back,
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,2 +1,3 @@
|
||||||
0.01: New clock!
|
0.01: New clock!
|
||||||
0.02: Load steps from Health Tracking app (if installed)
|
0.02: Load steps from Health Tracking app (if installed)
|
||||||
|
0.03: ...
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
0.1: New app
|
0.01: New app
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
require("heatshrink").decompress(atob("/wA/AH4A/AH4A/ACmsAEQuMlcAAD0rGBQKBFr4ADGBOsqwvjqwvJRsCRFF/8Gg4ADEZYQEgwvWg8+AAgwKCJgvQDgoABF5IRMF5xEBJpBhGCJwvNDQM4AYMNAAQaBnCAFCJ4vNIwQeBAAkxQAwGCmIRFFwIRDF64dDgwGBgwRNF/4v/F/4v/F/4v/F/4dJmIdECIkxF7MHFwUHhoACg4eCAYIACCJ4vNDQIgCAAgICKwoROF5yAEAAgtFCKAvQJpAAICJgvQgEGg4ADFxIwCAAcGBYovRADov6qwvjqwvJ1gvjEoIvHGASRgRoIuJGAYAhFxQA/AH4A/AH4A/ABQ"))
|
require("heatshrink").decompress(atob("mEw4UA///A4N551ulxL/ACkK1QAG0ALBlNVAA1oBYOlBY9aBYO1BY9eBYOVBY9WBbf/+oIBr//BYlX//9BYN///VC599qtX6oBBqt9BYYRBr/1AIIdBBf4L/BY6bLZcb7MBau1BY9eBYOlBY9aBYMpBY9oBYMK1QAG0ALBAH4ASA"))
|
||||||
|
|
|
@ -4,4 +4,4 @@
|
||||||
0.04: reset to clock after 2 mins of inactivity
|
0.04: reset to clock after 2 mins of inactivity
|
||||||
0.05: add Bangle 2 version
|
0.05: add Bangle 2 version
|
||||||
0.06: Adds settings page (hide clocks or launchers)
|
0.06: Adds settings page (hide clocks or launchers)
|
||||||
0.06: Adds setting for directly launching app on touch for Bangle 2
|
0.07: Adds setting for directly launching app on touch for Bangle 2
|
||||||
|
|
|
@ -7,3 +7,4 @@
|
||||||
0.06: Fix daily health summary for movement (a line got deleted!)
|
0.06: Fix daily health summary for movement (a line got deleted!)
|
||||||
0.07: Added coloured bar charts
|
0.07: Added coloured bar charts
|
||||||
0.08: Suppress bleed through of E.showMenu's when displaying bar charts
|
0.08: Suppress bleed through of E.showMenu's when displaying bar charts
|
||||||
|
0.09: Fix file naming so months are 1-based (not 0) (fix #1119)
|
||||||
|
|
|
@ -27,7 +27,7 @@ Bangle.on("health", health => {
|
||||||
const DB_FILE_LEN = DB_HEADER_LEN + DB_RECORDS_PER_MONTH*DB_RECORD_LEN;
|
const DB_FILE_LEN = DB_HEADER_LEN + DB_RECORDS_PER_MONTH*DB_RECORD_LEN;
|
||||||
|
|
||||||
function getRecordFN(d) {
|
function getRecordFN(d) {
|
||||||
return "health-"+d.getFullYear()+"-"+d.getMonth()+".raw";
|
return "health-"+d.getFullYear()+"-"+(d.getMonth()+1)+".raw";
|
||||||
}
|
}
|
||||||
function getRecordIdx(d) {
|
function getRecordIdx(d) {
|
||||||
return (DB_RECORDS_PER_DAY*(d.getDate()-1)) +
|
return (DB_RECORDS_PER_DAY*(d.getDate()-1)) +
|
||||||
|
|
|
@ -6,7 +6,7 @@ const DB_HEADER_LEN = 8;
|
||||||
const DB_FILE_LEN = DB_HEADER_LEN + DB_RECORDS_PER_MONTH*DB_RECORD_LEN;
|
const DB_FILE_LEN = DB_HEADER_LEN + DB_RECORDS_PER_MONTH*DB_RECORD_LEN;
|
||||||
|
|
||||||
function getRecordFN(d) {
|
function getRecordFN(d) {
|
||||||
return "health-"+d.getFullYear()+"-"+d.getMonth()+".raw";
|
return "health-"+d.getFullYear()+"-"+(d.getMonth()+1)+".raw";
|
||||||
}
|
}
|
||||||
function getRecordIdx(d) {
|
function getRecordIdx(d) {
|
||||||
return (DB_RECORDS_PER_DAY*(d.getDate()-1)) +
|
return (DB_RECORDS_PER_DAY*(d.getDate()-1)) +
|
||||||
|
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 3.3 KiB |
|
@ -154,7 +154,8 @@ var locales = {
|
||||||
month: "Januar,Februar,März,April,Mai,Juni,Juli,August,September,Oktober,November,Dezember",
|
month: "Januar,Februar,März,April,Mai,Juni,Juli,August,September,Oktober,November,Dezember",
|
||||||
abday: "So,Mo,Di,Mi,Do,Fr,Sa",
|
abday: "So,Mo,Di,Mi,Do,Fr,Sa",
|
||||||
day: "Sonntag,Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag",
|
day: "Sonntag,Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag",
|
||||||
trans: { yes: "ja", Yes: "Ja", no: "nein", No: "Nein", ok: "ok", on: "an", off: "aus", "< Back": "< Zurück" }
|
trans: { yes: "ja", Yes: "Ja", no: "nein", No: "Nein", ok: "ok", on: "an", off: "aus",
|
||||||
|
"< Back": "< Zurück", "Delete": "Löschen", "Mark Unread": "Als ungelesen markieren" }
|
||||||
},
|
},
|
||||||
"en_US": {
|
"en_US": {
|
||||||
lang: "en_US",
|
lang: "en_US",
|
||||||
|
@ -327,13 +328,15 @@ var locales = {
|
||||||
speed: "kmh",
|
speed: "kmh",
|
||||||
distance: { 0: "m", 1: "km" },
|
distance: { 0: "m", 1: "km" },
|
||||||
temperature: "°C",
|
temperature: "°C",
|
||||||
|
ampm: { 0: "", 1: "" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%A, %d. %B %Y", "1": "%d.%m.%y" }, // Sonntag, 1. März 2020 // 01.03.20
|
datePattern: { 0: "%A, %d. %B %Y", "1": "%d.%m.%y" }, // Sonntag, 1. März 2020 // 01.03.20
|
||||||
abmonth: "Jän,Feb,März,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez",
|
abmonth: "Jän,Feb,März,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez",
|
||||||
month: "Jänner,Februar,März,April,Mai,Juni,Juli,August,September,Oktober,November,Dezember",
|
month: "Jänner,Februar,März,April,Mai,Juni,Juli,August,September,Oktober,November,Dezember",
|
||||||
abday: "So,Mo,Di,Mi,Do,Fr,Sa",
|
abday: "So,Mo,Di,Mi,Do,Fr,Sa",
|
||||||
day: "Sonntag,Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag",
|
day: "Sonntag,Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag",
|
||||||
trans: { yes: "ja", Yes: "Ja", no: "nein", No: "Nein", ok: "ok", on: "an", off: "aus" }
|
trans: { yes: "ja", Yes: "Ja", no: "nein", No: "Nein", ok: "ok", on: "an", off: "aus",
|
||||||
|
"< Back": "< Zurück", "Delete": "Löschen", "Mark Unread": "Als ungelesen markieren" }
|
||||||
},
|
},
|
||||||
"en_IL": {
|
"en_IL": {
|
||||||
lang: "en_IL",
|
lang: "en_IL",
|
||||||
|
@ -369,7 +372,8 @@ var locales = {
|
||||||
month: "enero,febrero,marzo,abril,mayo,junio,julio,agosto,septiembre,octubre,noviembre,diciembre",
|
month: "enero,febrero,marzo,abril,mayo,junio,julio,agosto,septiembre,octubre,noviembre,diciembre",
|
||||||
abday: "dom,lun,mar,mié,jue,vie,sáb",
|
abday: "dom,lun,mar,mié,jue,vie,sáb",
|
||||||
day: "domingo,lunes,martes,miércoles,jueves,viernes,sábado",
|
day: "domingo,lunes,martes,miércoles,jueves,viernes,sábado",
|
||||||
trans: { yes: "sí", Yes: "Sí", no: "no", No: "No", ok: "ok", on: "on", off: "off" }
|
trans: { yes: "sí", Yes: "Sí", no: "no", No: "No", ok: "ok", on: "on", off: "off",
|
||||||
|
"< Back": "< Atrás", "Delete": "Borrar ", "Mark Unread": "Marcar como no leído" }
|
||||||
},
|
},
|
||||||
"fr_BE": {
|
"fr_BE": {
|
||||||
lang: "fr_BE",
|
lang: "fr_BE",
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Thermometer
|
||||||
|
|
||||||
|
Localized Bangle.js 2 thermometer app. It also starts maintaining an average of the temperature to help lower the margin of error after 10 consecutive readings; due to the low quality die-thermometer.
|
|
@ -0,0 +1,25 @@
|
||||||
|
function drawTemperature() {
|
||||||
|
g.reset(1).clearRect(0,24,g.getWidth(),g.getHeight());
|
||||||
|
g.setFont("6x8",2).setFontAlign(0,0);
|
||||||
|
var x = g.getWidth()/2;
|
||||||
|
var y = g.getHeight()/2 + 10;
|
||||||
|
g.drawString("Temp", x, y - 45);
|
||||||
|
g.setFontVector(70).setFontAlign(0,0);
|
||||||
|
var h = E.getTemperature();
|
||||||
|
if (avg.length < 10) {
|
||||||
|
avg[avg.length] = h;
|
||||||
|
} else {
|
||||||
|
avg.shift();
|
||||||
|
avg[avg.length] = h;
|
||||||
|
h = ((avg[0] + avg[1] + avg[2] + avg[3] + avg[4] + avg[5] + avg[6] + avg[7] + avg[8] + avg[9]) / 10);
|
||||||
|
}
|
||||||
|
var t = require('locale').temp(h);
|
||||||
|
g.drawString(t, x, y);
|
||||||
|
}
|
||||||
|
const avg = [];
|
||||||
|
setInterval(function() {
|
||||||
|
drawTemperature();
|
||||||
|
}, 2000);
|
||||||
|
E.showMessage("Loading...");
|
||||||
|
Bangle.loadWidgets();
|
||||||
|
Bangle.drawWidgets();
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwwhC/AH4AChGIxGAC6eIAQgARFgUIC9ReCAYJgSC7BHDF6gUBC6ovWI/5Hga/6P/ABsCkABDC/4XxkQXDkQuSAQwXPDQkAC6BBCkQDDC6MCmczFoIXQCQQXBDgQXP2EA2YXBncAhYXR3YXB3YXRCQWznYcCC6ICBAYYXPhYrBApAwPFyQqCIoYuRLwZgDAH4A/"))
|
After Width: | Height: | Size: 1.2 KiB |
|
@ -20,3 +20,4 @@
|
||||||
0.13: Add /*LANG*/ comments for internationalisation
|
0.13: Add /*LANG*/ comments for internationalisation
|
||||||
Add 'Delete All' option to message options
|
Add 'Delete All' option to message options
|
||||||
Now update correctly when 'require("messages").clearAll()' is called
|
Now update correctly when 'require("messages").clearAll()' is called
|
||||||
|
0.14: Hide widget when all unread notifications are dismissed from phone
|
||||||
|
|
|
@ -30,6 +30,10 @@ exports.pushMessage = function(event) {
|
||||||
require("Storage").writeJSON("messages.json",messages);
|
require("Storage").writeJSON("messages.json",messages);
|
||||||
// if in app, process immediately
|
// if in app, process immediately
|
||||||
if (inApp) return onMessagesModified(mIdx<0 ? {id:event.id} : messages[mIdx]);
|
if (inApp) return onMessagesModified(mIdx<0 ? {id:event.id} : messages[mIdx]);
|
||||||
|
// if we've removed the last new message, hide the widget
|
||||||
|
if (event.t=="remove" && !messages.some(m=>m.new)) {
|
||||||
|
if (global.WIDGETS && WIDGETS.messages) WIDGETS.messages.hide();
|
||||||
|
}
|
||||||
// ok, saved now - we only care if it's new
|
// ok, saved now - we only care if it's new
|
||||||
if (event.t!="add") {
|
if (event.t!="add") {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
require("heatshrink").decompress(atob("MDABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"))
|
require("heatshrink").decompress(atob("mEwwIHEgPAAocP+AFDv4FDgf/Aoc/AocB/4FDh4FEv4FEAgIFIDgQFR+FwAoeAAof8gAFDLoIFC/wyBAoQ4CAoXgAoh0CAtybCAoJPBAoahDAoMHAoicBAoM54EfAoJqCAoQUBAoYUBAoYCBAoXgZAIFC4AFCCgOAYYI1CZIRHB/AFDcwmAAoj9Dj6mCdoQaBAAYWDgA"))
|
||||||
|
|
|
@ -6,3 +6,4 @@
|
||||||
0.06: Converted fonts to font modules
|
0.06: Converted fonts to font modules
|
||||||
0.07: Added info line that cycles on BTN1/BTN3 (or vitual buttons on a bangle 2)
|
0.07: Added info line that cycles on BTN1/BTN3 (or vitual buttons on a bangle 2)
|
||||||
0.08: Added dependancy on MyLocation
|
0.08: Added dependancy on MyLocation
|
||||||
|
0.09: Added dependancy on Pedometer Widget
|
||||||
|
|
|
@ -3,3 +3,4 @@
|
||||||
0.03: Changed time+calendar font to LECO1976Regular, changed to slanting boot
|
0.03: Changed time+calendar font to LECO1976Regular, changed to slanting boot
|
||||||
0.04: Fix widget hiding code (fix #1046)
|
0.04: Fix widget hiding code (fix #1046)
|
||||||
0.05: Fix typo in settings - Purple
|
0.05: Fix typo in settings - Purple
|
||||||
|
0.06: Added dependancy on Pedometer Widget
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
0.1: first release
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Pebble with distance and steps
|
||||||
|
|
||||||
|
- Forked from [Pebble](https://github.com/espruino/BangleApps/tree/master/apps/pebble)
|
||||||
|
- Added distance in km (kilometers) based on step length (can be changed in settings and is equal 0.75m by default)
|
||||||
|
- Battery warning changed to 15% instead of 30%
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
Initially written by: [Hugh Barney](https://github.com/hughbarney)
|
||||||
|
|
||||||
|
Forked and changed by [RomanistHere](https://github.com/RomanistHere)
|
||||||
|
|
||||||
|
For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/)
|
||||||
|
|
||||||
|
## How to measure step length
|
||||||
|
|
||||||
|
It's much easier than you think. When you're walking, just note number of current steps at two points and then see the distance in any map service. For example, your route from bus station to home. Write number of steps at bus station (let's say 3451) and when you entered your home (3921). You passed 3921 - 3451 = 470 steps. Then see the actual distance in Google maps. Let's say it shows 300 meters. So your step length (in settings) used in app should be 300 / 470 = 0.64. After you have set it, the displayed distance at the main screen should be more accurate.
|
||||||
|
|
||||||
|
## Plans
|
||||||
|
|
||||||
|
Make step length depend on height/sex/age for lazy ones who don't want to measure it.
|
After Width: | Height: | Size: 25 KiB |
|
@ -0,0 +1,129 @@
|
||||||
|
Graphics.prototype.setFontLECO1976Regular42 = function(scale) {
|
||||||
|
// Actual height 42 (41 - 0)
|
||||||
|
g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAA/AAAAAAAAH/AAAAAAAA//AAAAAAAP//AAAAAAB///AAAAAAP///AAAAAB////AAAAAf////AAAAD////4AAAAf////AAAAH////4AAAA////+AAAAA////wAAAAA///+AAAAAA///gAAAAAA//8AAAAAAA//gAAAAAAA/4AAAAAAAA/AAAAAAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//h////AAA//h////AAA//h////AAA//h////AAA//h////AAA//h////AAA//h////AAA//h////AAA//h////AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA////gD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4B/gH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////wAAAAA////wAAAAA////wAAAAA////wAAAAA////wAAAAA////wAAAAA////wAAAAA////wAAAAA////wAAAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////x//AAA////x//AAA////x//AAA////x//AAA////x//AAA////x//AAA////x//AAA////x//AAA////x//AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B////AAA/4B////AAA/4B////AAA/4B////AAA/4B////AAA/4B////AAA/4B////AAA/4B////AAA/wB////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B////AAA/4B////AAA/4B////AAA/4B////AAA/4B////AAA/4B////AAA/4B////AAA/4B////AAA/wB////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//gAAAAAAA//gAAAAAAA//gAAAAAAA//gAAAAAAA//gAAAAAAA//gAAAAAAA//gAAAAAAA//gAAAAAAA//gAAAAAAA/4AAAAAAAA/4AAAAAAAA/4AAAAAAAA/4AAAAAAAA/4AAAAAAAA/4AAAAAAAA/4AAAAAAAA/4AAAAAAAA/4AAAAAAAA/4AAAAAAAA/4AAAAAAAA/4AAAAAAAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+AAH/AAAAP+AAH/AAAAP+AAH/AAAAP+AAH/AAAAP+AAH/AAAAP+AAH/AAAAP+AAH/AAAAP+AAH/AAAAH+AAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), 46, atob("ERkmHyYmJiYmJCYmEQ=="), 60+(scale<<8)+(1<<16));
|
||||||
|
};
|
||||||
|
|
||||||
|
Graphics.prototype.setFontLECO1976Regular22 = function(scale) {
|
||||||
|
// Actual height 22 (21 - 0)
|
||||||
|
g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/nA/+cD/5wP/nAAAAAAAAPwAA/gAD+AAPwAAAAAD+AAP4AA/gAAAAAAAAAAAAAcOAP//A//8D//wP//AHDgAcOAP//A//8D//wP//AHDgAAAAAAAAH/jgf+OB/44H/jj8OP/w4//Dj/8OPxw/4HD/gcP+Bw/4AAAAAAAP+AA/8AD/wQOHHA4c8D//wP/8A//gAD4AAfAAH/8A//wP//A84cDjhwIP/AA/8AB/wAAAAAAAD//wP//A//8D//wOHHA4ccDhxwOHHA4f8Dh/wOH/A4f8ABwAAAAAAAAD8AAP4AA/gAD8AAAAAAAAAAAEAAD+AB//A///v/D//gB/wABwAAAAAADgAA/wAf/4P8///wf/4AP8AAOAAAAAAAAAyAAHcAAPwAD/gAP/AA/8AA/AAH8AAMwAAAAAAAAAAAAADgAAOAAA4AAf8AD/wAP/AA/8AAOAAA4AADgAAAAAAAAAAD8AAfwAB/AAD8AAAAAAAADgAAOAAA4AADgAAOAAA4AADgAAAAAAAAAADgAAOAAA4AADgAAAAAAAAABwAB/AA/8A//gP/gA/wADwAAIAAAAAAD//wP//A//8D//wOAHA4AcDgBwOAHA//8D//wP//A//8AAAAAAAA4AcDgBwOAHA//8D//wP//A//8AABwAAHAAAcAAAAAAAA+f8D5/wPn/A+f8DhxwOHHA4ccDhxwP/HA/8cD/xwP/HAAAAAAAAOAHA4AcDhxwOHHA4ccDhxwOHHA4ccD//wP//A//8D//wAAAAAAAD/wAP/AA/8AD/wAAHAAAcAABwAAHAA//8D//wP//A//8AAAAAAAA/98D/3wP/fA/98DhxwOHHA4ccDhxwOH/A4f8Dh/wOH/AAAAAAAAP//A//8D//wP//A4ccDhxwOHHA4ccDh/wOH/A4f8Dh/wAAAAAAAD4AAPgAA+AADgAAOAAA4AADgAAP//A//8D//wP//AAAAAAAAP//A//8D//wP//A4ccDhxwOHHA4ccD//wP//A//8D//wAAAAAAAD/xwP/HA/8cD/xwOHHA4ccDhxwOHHA//8D//wP//A//8AAAAAAAAOA4A4DgDgOAOA4AAAAAAAAOA/A4H8DgfwOA/AAAAAAAAB4AAPwAA/AAD8AAf4ABzgAPPAA8cAHh4AAAAAAAAAAAAHHAAccABxwAHHAAccABxwAHHAAccABxwAHHAAAAAAAAAOHAA4cADzwAPPAAf4AB/gAD8AAPwAAeAAB4AAAAAAAAA+AAD4AAPgAA+ecDh9wOH3A4fcDhwAP/AA/8AD/wAP/AAAAAAAAAP//4///j//+P//44ADjn/OOf845/zjnHOP8c4//zj//OP/84AAAAAAAP//A//8D//wP//A4cADhwAOHAA4cAD//wP//A//8D//wAAAAAAAD//wP//A//8D//wOHHA4ccDhxwOHHA//8D//wP9/A/j8AAAAAAAA//8D//wP//A//8DgBwOAHA4AcDgBwOAHA4AcDgBwOAHAAAAAAAAP//A//8D//wP//A4AcDgBwOAHA8A8D//wH/+AP/wAf+AAAAAAAAD//wP//A//8D//wOHHA4ccDhxwOHHA4ccDhxwOAHA4AcAAAAAAAA//8D//wP//A//8DhwAOHAA4cADhwAOHAA4cADgAAOAAAAAAD//wP//A//8D//wOAHA4ccDhxwOHHA4f8Dh/wOH/A4f8AAAAAAAA//8D//wP//A//8ABwAAHAAAcAABwAP//A//8D//wP//AAAAAAAAP//A//8D//wP//AAAAAAAAOAHA4AcDgBwOAHA4AcDgBwOAHA//8D//wP//A//8AAAAAAAA//8D//wP//A//8AHwAA/AAP8AB/wAPn/A8f8DB/wIH/AAAAAAAAP//A//8D//wP//AAAcAABwAAHAAAcAABwAAHAAAAAAAAP//A//8D//wP//Af8AAP+AAH/AAD8AAHwAD/AB/wAf8AP+AA//8D//wP//AAAAAAAAP//A//8D//wP//AfwAAfwAAfwAAfwAAfwP//A//8D//wAAAAAAAAAAAP//A//8D//wP//A4AcDgBwOAHA4AcD//wP//A//8D//wAAAAAAAD//wP//A//8D//wOHAA4cADhwAOHAA/8AD/wAP/AA/8AAAAAP//A//8D//wP//A4AcDgBwOAHA4AcD//+P//4///j//+AAA4AADgAAAP//A//8D//wP//A4eADh+AOH8A4f4D/3wP/HA/8MD/wQAAAAAAAD/xwP/HA/8cD/xwOHHA4ccDhxwOHHA4f8Dh/wOH/A4f8AAAAAAAA4AADgAAOAAA//8D//wP//A//8DgAAOAAA4AADgAAAAAA//8D//wP//A//8AABwAAHAAAcAABwP//A//8D//wP//AAAADAAAPgAA/wAD/4AB/8AA/8AAfwAB/AA/8Af+AP/AA/wAD4AAMAAA4AAD+AAP/gA//8AH/wAB/AAf8Af/wP/4A/4AD/gAP/4AH/8AB/wAB/AB/8D//wP/gA/gADgAAIABA4AcDwDwPw/Afn4Af+AA/wAD/AA//AH5+A/D8DwDwOAHAgAEAAAAP/AA/8AD/wAP/AAAf8AB/wAH/AAf8D/wAP/AA/8AD/wAAAAAAAADh/wOH/A4f8Dh/wOHHA4ccDhxwOHHA/8cD/xwP/HA/8cAAAAAAAAf//9///3///f//9wAA3AADcAAMAAAOAAA/gAD/wAH/8AB/8AA/wAAPAAAEAAAAHAADcAANwAB3///f//9///wAA"), 32, atob("BwYLDg4UDwYJCQwMBgkGCQ4MDg4ODg4NDg4GBgwMDA4PDg4ODg4NDg4GDQ4MEg8ODQ8ODgwODhQODg4ICQg="), 22+(scale<<8)+(1<<16));
|
||||||
|
};
|
||||||
|
|
||||||
|
const SETTINGS_FILE = "pebbleDistance.json";
|
||||||
|
let settings;
|
||||||
|
|
||||||
|
function loadSettings() {
|
||||||
|
settings = require("Storage").readJSON(SETTINGS_FILE,1)|| {'bg': '#0f0', 'color': 'Green', 'avStep': 0.75};
|
||||||
|
}
|
||||||
|
|
||||||
|
var img = require("heatshrink").decompress(atob("oFAwkEogA/AH4A/AH4A/AH4A/AE8AAAoeXoAfeDQUBmcyD7A+Dh///8QD649CiAfaHwUvD4sEHy0DDYIfEICg+Cn4fHICY+DD4nxcgojOHwgfEIAYfRCIQaDD4ZAFD5r7DH4//kAfRCIZ/GAAnwD5p9DX44fTHgYSBf4ofVDAQEBl4fFUAgfOXoQzBgIfFBAIfPP4RAEAoYAB+cRiK/SG4h/WIBAfXIA7CBAAswD55AHn6fUIBMCD65AHl4gCmcziAfQQJqfQQJpiDgk0IDXxQLRAEECaBM+QgRYRYgUIA0CD4ggSQJiDCiAKBICszAAswD55AHABKBVD7BAFABIqBD5pAFABPxD55AOD6BADiIAJQAyxLABwf/gaAPAH4A/AH4ARA=="));
|
||||||
|
|
||||||
|
const h = g.getHeight();
|
||||||
|
const w = g.getWidth();
|
||||||
|
const ha = 2*h/5 - 11;
|
||||||
|
const h2 = 3*h/5 - 19;
|
||||||
|
const h3 = 7*h/8 - 10;
|
||||||
|
|
||||||
|
let batteryWarning = false;
|
||||||
|
|
||||||
|
function draw() {
|
||||||
|
let date = new Date();
|
||||||
|
let da = date.toString().split(" ");
|
||||||
|
let timeStr = da[4].substr(0,5);
|
||||||
|
const t = 6;
|
||||||
|
const stps = getSteps();
|
||||||
|
|
||||||
|
// turn the warning on once we have dipped below 15%
|
||||||
|
if (E.getBattery() < 15)
|
||||||
|
batteryWarning = true;
|
||||||
|
|
||||||
|
// turn the warning off once we have dipped above 20%
|
||||||
|
if (E.getBattery() > 20)
|
||||||
|
batteryWarning = false;
|
||||||
|
|
||||||
|
g.reset();
|
||||||
|
g.setColor(settings.bg);
|
||||||
|
g.fillRect(0, 0, w, h2 - t);
|
||||||
|
|
||||||
|
// contrast bar
|
||||||
|
g.setColor(g.theme.fg);
|
||||||
|
g.fillRect(0, h2 - t, w, h2);
|
||||||
|
|
||||||
|
// day and steps
|
||||||
|
if (settings.color == 'Blue' || settings.color == 'Red')
|
||||||
|
g.setColor('#fff'); // white on blue or red best contrast
|
||||||
|
else
|
||||||
|
g.setColor('#000'); // otherwise black regardless of theme
|
||||||
|
|
||||||
|
g.setFontLECO1976Regular22();
|
||||||
|
g.setFontAlign(0, -1);
|
||||||
|
g.drawString(da[0].toUpperCase(), w/4, ha); // day of week
|
||||||
|
g.drawString(stps, 3*w/4, ha);
|
||||||
|
|
||||||
|
// time
|
||||||
|
// white on red for battery warning
|
||||||
|
g.setColor(!batteryWarning ? g.theme.bg : '#f00');
|
||||||
|
g.fillRect(0, h2, w, h3);
|
||||||
|
|
||||||
|
g.setFontLECO1976Regular42();
|
||||||
|
g.setFontAlign(0, -1);
|
||||||
|
g.setColor(!batteryWarning ? g.theme.fg : '#fff');
|
||||||
|
g.drawString(timeStr, w/2, h2 + 8);
|
||||||
|
|
||||||
|
// contrast bar
|
||||||
|
g.setColor(g.theme.fg);
|
||||||
|
g.fillRect(0, h3, w, h3 + t);
|
||||||
|
|
||||||
|
// the bottom
|
||||||
|
g.setColor(settings.bg);
|
||||||
|
g.fillRect(0, h3 + t, w, h);
|
||||||
|
|
||||||
|
g.setColor(settings.bg);
|
||||||
|
g.drawImage(img, w/2 + ((w/2) - 64)/2, -2, { scale: 1 });
|
||||||
|
drawCalendar(((w/2) - 42)/2, 11, 42, 4, da[2]);
|
||||||
|
|
||||||
|
// distance
|
||||||
|
if (settings.color == 'Blue' || settings.color == 'Red')
|
||||||
|
g.setColor('#fff'); // white on blue or red best contrast
|
||||||
|
else
|
||||||
|
g.setColor('#000'); // otherwise black regardless of theme
|
||||||
|
g.drawString((stps / 1000 * settings.avStep).toFixed(2) + ' KM', w/2, ha + 107);
|
||||||
|
}
|
||||||
|
|
||||||
|
// at x,y width:wi thicknes:th
|
||||||
|
function drawCalendar(x,y,wi,th,str) {
|
||||||
|
g.setColor(g.theme.fg);
|
||||||
|
g.fillRect(x, y, x + wi, y + wi);
|
||||||
|
g.setColor(g.theme.bg);
|
||||||
|
g.fillRect(x + th, y + th, x + wi - th, y + wi - th);
|
||||||
|
g.setColor(g.theme.fg);
|
||||||
|
|
||||||
|
let hook_t = 6;
|
||||||
|
// first calendar hook, one third in
|
||||||
|
g.fillRect(x + (wi/3) - (th/2), y - hook_t, x + wi/3 + th - (th/2), y + hook_t);
|
||||||
|
// second calendar hook, two thirds in
|
||||||
|
g.fillRect(x + (2*wi/3) -(th/2), y - hook_t, x + 2*wi/3 + th - (th/2), y + hook_t);
|
||||||
|
|
||||||
|
g.setFontLECO1976Regular22();
|
||||||
|
g.setFontAlign(0, 0);
|
||||||
|
g.drawString(str, x + wi/2, y + wi/2 + th);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSteps() {
|
||||||
|
if (WIDGETS.wpedom !== undefined) {
|
||||||
|
return WIDGETS.wpedom.getSteps();
|
||||||
|
}
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
g.clear();
|
||||||
|
Bangle.loadWidgets();
|
||||||
|
/*
|
||||||
|
* we are not drawing the widgets as we are taking over the whole screen
|
||||||
|
* so we will blank out the draw() functions of each widget and change the
|
||||||
|
* area to the top bar doesn't get cleared.
|
||||||
|
*/
|
||||||
|
for (let wd of WIDGETS) {wd.draw=()=>{};wd.area="";}
|
||||||
|
loadSettings();
|
||||||
|
setInterval(draw, 15000); // refresh every 15s
|
||||||
|
draw();
|
||||||
|
Bangle.setUI("clock");
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEw4kB78A/4ACj/fn8Rz/Or987+M38hv8Rn++z9Cn8y/9rj9Tr+diIAHiAxDgIOICpYADCywyNCxQYMSxouVGBIWODBDgRC7hGQJAwWRGAguSC7JICCyYXYJAQXWLyhICC94LKu8Gqk1gGD+AjQ//C6Ei2HS0AXQ/U2gEquFVC6Pyk8AlssmwXK3oGF+fi2Et0v2C4ONoAPFhsiwBfFhU0lvS2wXBsVUC4vSkwHF90Etlso0L6CSBkowEFwNgM5sImQwEFw4AJGAguQGAsQ6UvxAAQ2UloMYkQAU0MZmUjmYAQmUi+MRSowAM4UmiMRSowALhiKBC4MQGCIuBgAXCGCAuCgIXBiLGCFyQXCGAJINsToBC4cQgGMI50AIwYwCACAWEGAQAOFwowRCwwwPFw4wPCxAYNCxRJLCxYxKCxwyGORI"))
|
After Width: | Height: | Size: 1.2 KiB |
|
@ -0,0 +1,48 @@
|
||||||
|
(function(back) {
|
||||||
|
const SETTINGS_FILE = "pebbleDistance.json";
|
||||||
|
|
||||||
|
// initialize with default settings...
|
||||||
|
let s = {'bg': '#0f0', 'color': 'Green', 'avStep': 0.75};
|
||||||
|
|
||||||
|
// ...and overwrite them with any saved values
|
||||||
|
// This way saved values are preserved if a new version adds more settings
|
||||||
|
const storage = require('Storage');
|
||||||
|
let settings = storage.readJSON(SETTINGS_FILE, 1) || s;
|
||||||
|
const saved = settings || {};
|
||||||
|
for (const key in saved) {
|
||||||
|
s[key] = saved[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
settings = s;
|
||||||
|
storage.write(SETTINGS_FILE, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
var color_options = ['Green','Orange','Cyan','Purple','Red','Blue'];
|
||||||
|
var bg_code = ['#0f0','#ff0','#0ff','#f0f','#f00','#00f'];
|
||||||
|
|
||||||
|
E.showMenu({
|
||||||
|
'': { 'title': 'Pebble Clock' },
|
||||||
|
'< Back': back,
|
||||||
|
'Color': {
|
||||||
|
value: 0 | color_options.indexOf(s.color),
|
||||||
|
min: 0, max: 5,
|
||||||
|
format: v => color_options[v],
|
||||||
|
onchange: v => {
|
||||||
|
s.color = color_options[v];
|
||||||
|
s.bg = bg_code[v];
|
||||||
|
save();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'Step length': {
|
||||||
|
value: 0.75 || s.avStep,
|
||||||
|
min: 0.2,
|
||||||
|
max: 1.5,
|
||||||
|
step: 0.01,
|
||||||
|
onchange : v => {
|
||||||
|
s.avStep = v;
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
After Width: | Height: | Size: 161 KiB |
|
@ -16,8 +16,8 @@ the ability to check the _exact_ time, hands free, without the impact on battery
|
||||||
Although we generally obey the system-wide theming, you can long press on the display for a menu of additional options specific to the face.
|
Although we generally obey the system-wide theming, you can long press on the display for a menu of additional options specific to the face.
|
||||||
You can also override the system 12/24 hour setting just for this face here, since it's, well, a rather different experience than with numeric displays.
|
You can also override the system 12/24 hour setting just for this face here, since it's, well, a rather different experience than with numeric displays.
|
||||||
|
|
||||||
By default, there is a backlight that comes on when you twist your wrist. This, of course, somewhat increases power draw and could be
|
In some previous versions of the Bangle.js firmware, the backlight doesn't come on automatically when you twist your wrist. There's currently a
|
||||||
annoying in an intentionally dark environment, so there is an option to disable it.
|
workaround for this integrated into the watchface; you can disable it in the menu, if you prefer.
|
||||||
|
|
||||||
One other thing: there's some integration with system timers and alarms; they will show as small pips at the appropriate places
|
One other thing: there's some integration with system timers and alarms; they will show as small pips at the appropriate places
|
||||||
in the day around the display. When they come within an hour, the pips turn to crosses relating to the minute hand, and the minute
|
in the day around the display. When they come within an hour, the pips turn to crosses relating to the minute hand, and the minute
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
0.00: Initial check-in.
|
0.00: Initial check-in.
|
||||||
|
0.01: Add tap-to-decorate feature. Bugfixes.
|
||||||
|
|
|
@ -10,16 +10,18 @@ Either you'll like that, or you won't.
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
|
||||||
Because sometimes I don't want to burn what I'm cooking and others I'm lazy and just want to know if it's afternoon yet,
|
|
||||||
you can alter the number of ‘hands’ on the display. When the watch is unlocked, slide up to add dots representing the minute and second,
|
|
||||||
or down to remove the distraction. There's also a setting that displays the second hand, but only if the watch is perfectly face-to-the-sky,
|
|
||||||
in case you want the ability to check the _exact_ time, hands free, without the impact on battery life this usually entails.
|
|
||||||
|
|
||||||
Although we generally obey the system-wide theming, you can long press on the display for a menu of additional options specific to the face.
|
Although we generally obey the system-wide theming, you can long press on the display for a menu of additional options specific to the face.
|
||||||
We don't observe the system 12/24 setting, since it the design of the face is equally good in either interpretation.
|
We don't observe the system 12/24 setting, since it the design of the face is equally good in either interpretation.
|
||||||
|
|
||||||
By default, there is a backlight that comes on when you twist your wrist. This, of course, somewhat increases power draw and could be
|
If you like an uncluttered display style, you can still bring up the day, date and minute hand transiently with a tap on the watchface (when unlocked).
|
||||||
annoying in an intentionally dark environment, so there is an option to disable it.
|
|
||||||
|
Similarly, because sometimes I don't want to burn what I'm cooking and others I'm lazy and just want to know if it's afternoon yet,
|
||||||
|
you can quickly alter the number of ‘hands’ on the display. When the watch is unlocked, slide up to add dots representing the minute and second,
|
||||||
|
or down to remove the distraction. There's also a setting that displays the second hand, but only if the watch is perfectly face-to-the-sky,
|
||||||
|
in case you want the ability to check the _exact_ time, hands free, without the impact on battery life this usually entails.
|
||||||
|
|
||||||
|
In some versions of the Bangle.js firmware, the backlight doesn't come on automatically when you twist your wrist. There's currently a workaround
|
||||||
|
for this integrated into the watchface; you can disable it in the menu, if you prefer.
|
||||||
|
|
||||||
## Limitations
|
## Limitations
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,6 @@ class Options {
|
||||||
Bangle.removeListener('drag', this.reactivator);
|
Bangle.removeListener('drag', this.reactivator);
|
||||||
this.emit('done');
|
this.emit('done');
|
||||||
}
|
}
|
||||||
g.clear(true);
|
|
||||||
E.showMenu(m);
|
E.showMenu(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,7 +308,7 @@ class Round {
|
||||||
buffer: this.c.buffer, transparent: 0
|
buffer: this.c.buffer, transparent: 0
|
||||||
};
|
};
|
||||||
this.options = new RoundOptions();
|
this.options = new RoundOptions();
|
||||||
this.timescales = [1000, 0, 60000, 900000];
|
this.timescales = [1000, [1000, 60000], 60000, 900000];
|
||||||
this.state = {};
|
this.state = {};
|
||||||
// Precomputed polygons for the border areas.
|
// Precomputed polygons for the border areas.
|
||||||
this.tl = [0, 0, 58, 0, 0, 58];
|
this.tl = [0, 0, 58, 0, 0, 58];
|
||||||
|
@ -323,13 +322,15 @@ class Round {
|
||||||
this.r = this.xc - this.minR;
|
this.r = this.xc - this.minR;
|
||||||
}
|
}
|
||||||
|
|
||||||
reset() {this.state = {}; this.g.clear(true);}
|
reset(clear) {this.state = {}; clear && this.g.clear(true);}
|
||||||
|
|
||||||
doIcons(which) {
|
doIcons(which) {
|
||||||
this.state[which] = null;
|
this.state[which] = null;
|
||||||
this.render(new Date()); // Not quite right, I think.
|
this.render(new Date()); // Not quite right, I think.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enhanceUntil(t) {this.enhance = t;}
|
||||||
|
|
||||||
pie(f, a0, a1, invert) {
|
pie(f, a0, a1, invert) {
|
||||||
if (!invert) return this.pie(f, a1, a0 + 1, true);
|
if (!invert) return this.pie(f, a1, a0 + 1, true);
|
||||||
let t0 = Math.tan(a0 * 2 * Math.PI), t1 = Math.tan(a1 * 2 * Math.PI);
|
let t0 = Math.tan(a0 * 2 * Math.PI), t1 = Math.tan(a1 * 2 * Math.PI);
|
||||||
|
@ -369,17 +370,18 @@ class Round {
|
||||||
const g = this.g;
|
const g = this.g;
|
||||||
const b = this.b, bI = this.bI;
|
const b = this.b, bI = this.bI;
|
||||||
const c = this.c, cI = this.cI;
|
const c = this.c, cI = this.cI;
|
||||||
|
const e = d < this.enhance;
|
||||||
const state = this.state;
|
const state = this.state;
|
||||||
const options = this.options;
|
const options = this.options;
|
||||||
const cal = options.calendric;
|
const cal = options.calendric;
|
||||||
const res = options.resolution;
|
const res = options.resolution;
|
||||||
const dow = (cal == 1 || cal > 2) && d.getDay();
|
const dow = (e || cal == 1 || cal > 2) && d.getDay();
|
||||||
const ts = res < 2 && d.getSeconds();
|
const ts = res < 2 && d.getSeconds();
|
||||||
const tm = res < 3 && d.getMinutes() + ts / 60;
|
const tm = (e || res < 3) && d.getMinutes() + ts / 60;
|
||||||
const th = d.getHours() + d.getMinutes() / 60;
|
const th = d.getHours() + d.getMinutes() / 60;
|
||||||
const dd = cal > 1 && d.getDate();
|
const dd = (e || cal > 1) && d.getDate();
|
||||||
const dm = cal > 3 && d.getMonth();
|
const dm = (e || cal > 3) && d.getMonth();
|
||||||
const dy = cal > 4 && d.getFullYear();
|
const dy = (e || cal > 4) && d.getFullYear();
|
||||||
const xc = this.xc, yc = this.yc, r = this.r;
|
const xc = this.xc, yc = this.yc, r = this.r;
|
||||||
const dlr = xc * 3/4, dlw = 8, dlhw = 4;
|
const dlr = xc * 3/4, dlw = 8, dlhw = 4;
|
||||||
|
|
||||||
|
@ -475,7 +477,6 @@ class Clock {
|
||||||
this.timescales = face.timescales;
|
this.timescales = face.timescales;
|
||||||
this.options = face.options;
|
this.options = face.options;
|
||||||
this.rates = {};
|
this.rates = {};
|
||||||
this.faceUp = null;
|
|
||||||
|
|
||||||
this.options.on('done', () => this.start());
|
this.options.on('done', () => this.start());
|
||||||
|
|
||||||
|
@ -485,7 +486,6 @@ class Clock {
|
||||||
lock: () => {face.doIcons('locked'); this.active();},
|
lock: () => {face.doIcons('locked'); this.active();},
|
||||||
faceUp: up => {
|
faceUp: up => {
|
||||||
this.conservative = !up;
|
this.conservative = !up;
|
||||||
this.faceUp = up;
|
|
||||||
this.active();
|
this.active();
|
||||||
},
|
},
|
||||||
twist: _ => this.options.autolight && Bangle.setLCDPower(true),
|
twist: _ => this.options.autolight && Bangle.setLCDPower(true),
|
||||||
|
@ -504,9 +504,15 @@ class Clock {
|
||||||
this.options.resolution++;
|
this.options.resolution++;
|
||||||
this.rates.clock = this.timescales[this.options.resolution];
|
this.rates.clock = this.timescales[this.options.resolution];
|
||||||
this.active();
|
this.active();
|
||||||
} else if (this.yX - this.yN < 20 && Date.now() - this.t0 > 500) {
|
} else if (this.yX - this.yN < 20) {
|
||||||
this.stop();
|
const now = new Date();
|
||||||
this.options.interact();
|
if (now - this.t0 < 250) {
|
||||||
|
face.enhanceUntil(now + 30000);
|
||||||
|
face.render(now);
|
||||||
|
} else if (now - this.t0 > 500) {
|
||||||
|
this.stop();
|
||||||
|
this.options.interact();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.t0 = null;
|
this.t0 = null;
|
||||||
}
|
}
|
||||||
|
@ -520,7 +526,7 @@ class Clock {
|
||||||
|
|
||||||
redraw(rate) {
|
redraw(rate) {
|
||||||
const now = this.updated = new Date();
|
const now = this.updated = new Date();
|
||||||
if (this.refresh) this.face.reset();
|
if (this.refresh) this.face.reset(true);
|
||||||
this.refresh = false;
|
this.refresh = false;
|
||||||
rate = this.face.render(now, rate);
|
rate = this.face.render(now, rate);
|
||||||
if (rate !== this.rates.face) {
|
if (rate !== this.rates.face) {
|
||||||
|
@ -535,7 +541,7 @@ class Clock {
|
||||||
this.exception && clearTimeout(this.exception);
|
this.exception && clearTimeout(this.exception);
|
||||||
this.interval && clearInterval(this.interval);
|
this.interval && clearInterval(this.interval);
|
||||||
this.timeout = this.exception = this.interval = this.rate = null;
|
this.timeout = this.exception = this.interval = this.rate = null;
|
||||||
this.face.reset(); // Cancel any ongoing background rendering
|
this.face.reset(false); // Cancel any ongoing background rendering
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
0.01: Initial creation of the pattern launch app
|
0.01: Initial creation of the pattern launch app
|
||||||
0.02: Turn on lcd when launching an app if the lock screen was disabled in the settings
|
0.02: Turn on lcd when launching an app if the lock screen was disabled in the settings
|
||||||
0.03: Make tap to confirm new pattern more reliable. Also allow for easier creation of single circle patterns.
|
0.03: Make tap to confirm new pattern more reliable. Also allow for easier creation of single circle patterns.
|
||||||
0.10: Improve the management of existing patterns: Draw the linked pattern on the left hand side of the app name within a scroller, similar to the default launcher. Slighlty clean up the code to make it less horrible.
|
0.10: Improve the management of existing patterns: Draw the linked pattern on the left hand side of the app name within a scroller, similar to the default launcher. Slighlty clean up the code to make it less horrible.
|
||||||
|
0.11: Respect theme colors. Fix: Do not pollute global space with internal variables ans functions in boot.js
|
|
@ -10,14 +10,21 @@ Then launch the linked apps directly from the clock screen by simply drawing the
|
||||||
|
|
||||||
## Add Pattern Screenshots
|
## Add Pattern Screenshots
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
## Manage Pattern Screenshots
|
## Manage Pattern Screenshots
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
## Detailed Steps
|
## Detailed Steps
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.1 KiB |
|
@ -119,8 +119,7 @@ var recognizeAndDrawPattern = () => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
E.showMenu();
|
E.showMenu();
|
||||||
g.clear();
|
g.clear();
|
||||||
g.setColor(0, 0, 0);
|
drawCirclesWithPattern([]);
|
||||||
CIRCLES.forEach((circle) => drawCircle(circle));
|
|
||||||
|
|
||||||
var pattern = [];
|
var pattern = [];
|
||||||
|
|
||||||
|
@ -369,7 +368,6 @@ var drawAppWithPattern = (i, r, storedPatterns) => {
|
||||||
offset: { x: 1, y: 3 + r.y },
|
offset: { x: 1, y: 3 + r.y },
|
||||||
});
|
});
|
||||||
|
|
||||||
g.setColor(0, 0, 0);
|
|
||||||
if (!storedPattern.wrappedAppName) {
|
if (!storedPattern.wrappedAppName) {
|
||||||
storedPattern.wrappedAppName = g
|
storedPattern.wrappedAppName = g
|
||||||
.wrapString(app.name, g.getWidth() - 64)
|
.wrapString(app.name, g.getWidth() - 64)
|
||||||
|
@ -490,7 +488,7 @@ var drawCircle = (circle, drawBuffer, scale) => {
|
||||||
log("drawing circle");
|
log("drawing circle");
|
||||||
log({ x: x, y: y, r: r });
|
log({ x: x, y: y, r: r });
|
||||||
|
|
||||||
drawBuffer.fillCircle(x, y, r);
|
drawBuffer.drawCircle(x, y, r);
|
||||||
};
|
};
|
||||||
|
|
||||||
var cachedCirclesDrawings = {};
|
var cachedCirclesDrawings = {};
|
||||||
|
@ -535,17 +533,15 @@ var drawCirclesWithPattern = (pattern, options) => {
|
||||||
{ msb: true }
|
{ msb: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
drawBuffer.setColor(1);
|
|
||||||
CIRCLES.forEach((circle) => drawCircle(circle, drawBuffer, scale));
|
CIRCLES.forEach((circle) => drawCircle(circle, drawBuffer, scale));
|
||||||
|
|
||||||
drawBuffer.setColor(0);
|
|
||||||
drawBuffer.setFontAlign(0, 0);
|
drawBuffer.setFontAlign(0, 0);
|
||||||
drawBuffer.setFont("6x8", 4 * scale);
|
drawBuffer.setFont("Vector", 40 * scale);
|
||||||
pattern.forEach((circleIndex, patternIndex) => {
|
pattern.forEach((circleIndex, patternIndex) => {
|
||||||
var circle = CIRCLES[circleIndex];
|
var circle = CIRCLES[circleIndex];
|
||||||
drawBuffer.drawString(
|
drawBuffer.drawString(
|
||||||
patternIndex + 1,
|
patternIndex + 1,
|
||||||
circle.x * scale,
|
(circle.x + (scale === 1 ? 1 : 5)) * scale,
|
||||||
circle.y * scale
|
circle.y * scale
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,167 +1,167 @@
|
||||||
var DEBUG = true;
|
|
||||||
var log = (message) => {
|
|
||||||
if (DEBUG) {
|
|
||||||
console.log(JSON.stringify(message));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var storedPatterns;
|
|
||||||
var positions = [];
|
|
||||||
var dragHandler = (position) => {
|
|
||||||
positions.push(position);
|
|
||||||
|
|
||||||
debounce().then(() => {
|
|
||||||
log(positions.length);
|
|
||||||
|
|
||||||
var CIRCLE_RADIUS = 25;
|
|
||||||
var CIRCLE_RADIUS_2 = CIRCLE_RADIUS * CIRCLE_RADIUS;
|
|
||||||
|
|
||||||
var circles = [
|
|
||||||
{ x: 25, y: 25, i: 0 },
|
|
||||||
{ x: 87, y: 25, i: 1 },
|
|
||||||
{ x: 150, y: 25, i: 2 },
|
|
||||||
{ x: 25, y: 87, i: 3 },
|
|
||||||
{ x: 87, y: 87, i: 4 },
|
|
||||||
{ x: 150, y: 87, i: 5 },
|
|
||||||
{ x: 25, y: 150, i: 6 },
|
|
||||||
{ x: 87, y: 150, i: 7 },
|
|
||||||
{ x: 150, y: 150, i: 8 },
|
|
||||||
];
|
|
||||||
var pattern = [];
|
|
||||||
|
|
||||||
var step = Math.floor(positions.length / 100) + 1;
|
|
||||||
|
|
||||||
var p, a, b, circle;
|
|
||||||
|
|
||||||
for (var i = 0; i < positions.length; i += step) {
|
|
||||||
p = positions[i];
|
|
||||||
|
|
||||||
circle = circles[0];
|
|
||||||
if (circle) {
|
|
||||||
a = p.x - circle.x;
|
|
||||||
b = p.y - circle.y;
|
|
||||||
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
|
|
||||||
pattern.push(circle.i);
|
|
||||||
circles.splice(0, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
circle = circles[1];
|
|
||||||
if (circle) {
|
|
||||||
a = p.x - circle.x;
|
|
||||||
b = p.y - circle.y;
|
|
||||||
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
|
|
||||||
pattern.push(circle.i);
|
|
||||||
circles.splice(1, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
circle = circles[2];
|
|
||||||
if (circle) {
|
|
||||||
a = p.x - circle.x;
|
|
||||||
b = p.y - circle.y;
|
|
||||||
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
|
|
||||||
pattern.push(circle.i);
|
|
||||||
circles.splice(2, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
circle = circles[3];
|
|
||||||
if (circle) {
|
|
||||||
a = p.x - circle.x;
|
|
||||||
b = p.y - circle.y;
|
|
||||||
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
|
|
||||||
pattern.push(circle.i);
|
|
||||||
circles.splice(3, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
circle = circles[4];
|
|
||||||
if (circle) {
|
|
||||||
a = p.x - circle.x;
|
|
||||||
b = p.y - circle.y;
|
|
||||||
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
|
|
||||||
pattern.push(circle.i);
|
|
||||||
circles.splice(4, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
circle = circles[5];
|
|
||||||
if (circle) {
|
|
||||||
a = p.x - circle.x;
|
|
||||||
b = p.y - circle.y;
|
|
||||||
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
|
|
||||||
pattern.push(circle.i);
|
|
||||||
circles.splice(5, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
circle = circles[6];
|
|
||||||
if (circle) {
|
|
||||||
a = p.x - circle.x;
|
|
||||||
b = p.y - circle.y;
|
|
||||||
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
|
|
||||||
pattern.push(circle.i);
|
|
||||||
circles.splice(6, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
circle = circles[7];
|
|
||||||
if (circle) {
|
|
||||||
a = p.x - circle.x;
|
|
||||||
b = p.y - circle.y;
|
|
||||||
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
|
|
||||||
pattern.push(circle.i);
|
|
||||||
circles.splice(7, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
circle = circles[8];
|
|
||||||
if (circle) {
|
|
||||||
a = p.x - circle.x;
|
|
||||||
b = p.y - circle.y;
|
|
||||||
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
|
|
||||||
pattern.push(circle.i);
|
|
||||||
circles.splice(8, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
positions = [];
|
|
||||||
|
|
||||||
pattern = pattern.join("");
|
|
||||||
|
|
||||||
if (pattern) {
|
|
||||||
if (storedPatterns[pattern]) {
|
|
||||||
var app = storedPatterns[pattern].app;
|
|
||||||
if (!!app && !!app.src) {
|
|
||||||
if (storedPatterns.settings) {
|
|
||||||
if (storedPatterns.settings.lockDisabled) {
|
|
||||||
Bangle.setLCDPower(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bangle.removeListener("drag", dragHandler);
|
|
||||||
load(app.src);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var debounceTimeoutId;
|
|
||||||
var debounce = (delay) => {
|
|
||||||
if (debounceTimeoutId) {
|
|
||||||
clearTimeout(debounceTimeoutId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
debounceTimeoutId = setTimeout(() => {
|
|
||||||
debounceTimeoutId = undefined;
|
|
||||||
resolve();
|
|
||||||
}, delay || 500);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
|
var DEBUG = false;
|
||||||
|
var log = (message) => {
|
||||||
|
if (DEBUG) {
|
||||||
|
console.log(JSON.stringify(message));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var storedPatterns;
|
||||||
|
var positions = [];
|
||||||
|
var dragHandler = (position) => {
|
||||||
|
positions.push(position);
|
||||||
|
|
||||||
|
debounce().then(() => {
|
||||||
|
log(positions.length);
|
||||||
|
|
||||||
|
var CIRCLE_RADIUS = 25;
|
||||||
|
var CIRCLE_RADIUS_2 = CIRCLE_RADIUS * CIRCLE_RADIUS;
|
||||||
|
|
||||||
|
var circles = [
|
||||||
|
{ x: 25, y: 25, i: 0 },
|
||||||
|
{ x: 87, y: 25, i: 1 },
|
||||||
|
{ x: 150, y: 25, i: 2 },
|
||||||
|
{ x: 25, y: 87, i: 3 },
|
||||||
|
{ x: 87, y: 87, i: 4 },
|
||||||
|
{ x: 150, y: 87, i: 5 },
|
||||||
|
{ x: 25, y: 150, i: 6 },
|
||||||
|
{ x: 87, y: 150, i: 7 },
|
||||||
|
{ x: 150, y: 150, i: 8 },
|
||||||
|
];
|
||||||
|
var pattern = [];
|
||||||
|
|
||||||
|
var step = Math.floor(positions.length / 100) + 1;
|
||||||
|
|
||||||
|
var p, a, b, circle;
|
||||||
|
|
||||||
|
for (var i = 0; i < positions.length; i += step) {
|
||||||
|
p = positions[i];
|
||||||
|
|
||||||
|
circle = circles[0];
|
||||||
|
if (circle) {
|
||||||
|
a = p.x - circle.x;
|
||||||
|
b = p.y - circle.y;
|
||||||
|
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
|
||||||
|
pattern.push(circle.i);
|
||||||
|
circles.splice(0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
circle = circles[1];
|
||||||
|
if (circle) {
|
||||||
|
a = p.x - circle.x;
|
||||||
|
b = p.y - circle.y;
|
||||||
|
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
|
||||||
|
pattern.push(circle.i);
|
||||||
|
circles.splice(1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
circle = circles[2];
|
||||||
|
if (circle) {
|
||||||
|
a = p.x - circle.x;
|
||||||
|
b = p.y - circle.y;
|
||||||
|
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
|
||||||
|
pattern.push(circle.i);
|
||||||
|
circles.splice(2, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
circle = circles[3];
|
||||||
|
if (circle) {
|
||||||
|
a = p.x - circle.x;
|
||||||
|
b = p.y - circle.y;
|
||||||
|
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
|
||||||
|
pattern.push(circle.i);
|
||||||
|
circles.splice(3, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
circle = circles[4];
|
||||||
|
if (circle) {
|
||||||
|
a = p.x - circle.x;
|
||||||
|
b = p.y - circle.y;
|
||||||
|
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
|
||||||
|
pattern.push(circle.i);
|
||||||
|
circles.splice(4, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
circle = circles[5];
|
||||||
|
if (circle) {
|
||||||
|
a = p.x - circle.x;
|
||||||
|
b = p.y - circle.y;
|
||||||
|
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
|
||||||
|
pattern.push(circle.i);
|
||||||
|
circles.splice(5, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
circle = circles[6];
|
||||||
|
if (circle) {
|
||||||
|
a = p.x - circle.x;
|
||||||
|
b = p.y - circle.y;
|
||||||
|
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
|
||||||
|
pattern.push(circle.i);
|
||||||
|
circles.splice(6, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
circle = circles[7];
|
||||||
|
if (circle) {
|
||||||
|
a = p.x - circle.x;
|
||||||
|
b = p.y - circle.y;
|
||||||
|
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
|
||||||
|
pattern.push(circle.i);
|
||||||
|
circles.splice(7, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
circle = circles[8];
|
||||||
|
if (circle) {
|
||||||
|
a = p.x - circle.x;
|
||||||
|
b = p.y - circle.y;
|
||||||
|
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
|
||||||
|
pattern.push(circle.i);
|
||||||
|
circles.splice(8, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
positions = [];
|
||||||
|
|
||||||
|
pattern = pattern.join("");
|
||||||
|
|
||||||
|
if (pattern) {
|
||||||
|
if (storedPatterns[pattern]) {
|
||||||
|
var app = storedPatterns[pattern].app;
|
||||||
|
if (!!app && !!app.src) {
|
||||||
|
if (storedPatterns.settings) {
|
||||||
|
if (storedPatterns.settings.lockDisabled) {
|
||||||
|
Bangle.setLCDPower(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bangle.removeListener("drag", dragHandler);
|
||||||
|
load(app.src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var debounceTimeoutId;
|
||||||
|
var debounce = (delay) => {
|
||||||
|
if (debounceTimeoutId) {
|
||||||
|
clearTimeout(debounceTimeoutId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
debounceTimeoutId = setTimeout(() => {
|
||||||
|
debounceTimeoutId = undefined;
|
||||||
|
resolve();
|
||||||
|
}, delay || 500);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
var sui = Bangle.setUI;
|
var sui = Bangle.setUI;
|
||||||
Bangle.setUI = function (mode, cb) {
|
Bangle.setUI = function (mode, cb) {
|
||||||
sui(mode, cb);
|
sui(mode, cb);
|
||||||
|
|
After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
@ -1,2 +1,3 @@
|
||||||
0.01: First release
|
0.01: First release
|
||||||
0.02: Fix dependancies, fix type to Purple
|
0.02: Fix typo to Purple
|
||||||
|
0.03: Added dependancy on Pedometer Widget
|
||||||
|
|
|
@ -40,3 +40,4 @@
|
||||||
0.35: Change App/Widget settings to 'App Settings' so it fits on Bangle screen
|
0.35: Change App/Widget settings to 'App Settings' so it fits on Bangle screen
|
||||||
0.36: Added 'Utils' menu with helpful utilities for restoring Bangle.js
|
0.36: Added 'Utils' menu with helpful utilities for restoring Bangle.js
|
||||||
0.37: Going into passkey menu now saves settings with passkey
|
0.37: Going into passkey menu now saves settings with passkey
|
||||||
|
0.38: Restructed menus as per forum discussion
|
||||||
|
|
|
@ -61,6 +61,37 @@ if (!settings) resetSettings();
|
||||||
const boolFormat = v => v ? /*LANG*/"On" : /*LANG*/"Off";
|
const boolFormat = v => v ? /*LANG*/"On" : /*LANG*/"Off";
|
||||||
|
|
||||||
function showMainMenu() {
|
function showMainMenu() {
|
||||||
|
|
||||||
|
const mainmenu = {
|
||||||
|
'': { 'title': 'Settings' },
|
||||||
|
'< Back': ()=>load(),
|
||||||
|
/*LANG*/'Apps': ()=>showAppSettingsMenu(),
|
||||||
|
/*LANG*/'Bluetooth': ()=>showBLEMenu(),
|
||||||
|
/*LANG*/'System': ()=>showSystemMenu(),
|
||||||
|
/*LANG*/'Alerts': ()=>showAlertsMenu(),
|
||||||
|
/*LANG*/'Utils': ()=>showUtilMenu(),
|
||||||
|
/*LANG*/'Turn Off': ()=>{ if (Bangle.softOff) Bangle.softOff(); else Bangle.off() }
|
||||||
|
};
|
||||||
|
|
||||||
|
return E.showMenu(mainmenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showSystemMenu() {
|
||||||
|
|
||||||
|
const mainmenu = {
|
||||||
|
'': { 'title': 'System' },
|
||||||
|
'< Back': ()=>showMainMenu(),
|
||||||
|
/*LANG*/'Theme': ()=>showThemeMenu(),
|
||||||
|
/*LANG*/'LCD': ()=>showLCDMenu(),
|
||||||
|
/*LANG*/'Locale': ()=>showLocaleMenu(),
|
||||||
|
/*LANG*/'Select Clock': ()=>showClockMenu(),
|
||||||
|
/*LANG*/'Set Time': ()=>showSetTimeMenu()
|
||||||
|
};
|
||||||
|
|
||||||
|
return E.showMenu(mainmenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showAlertsMenu() {
|
||||||
var beepMenuItem;
|
var beepMenuItem;
|
||||||
if (BANGLEJS2) {
|
if (BANGLEJS2) {
|
||||||
beepMenuItem = {
|
beepMenuItem = {
|
||||||
|
@ -91,12 +122,9 @@ function showMainMenu() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const mainmenu = {
|
const mainmenu = {
|
||||||
'': { 'title': 'Settings' },
|
'': { 'title': 'Alerts' },
|
||||||
'< Back': ()=>load(),
|
'< Back': ()=>showMainMenu(),
|
||||||
/*LANG*/'App Settings': ()=>showAppSettingsMenu(),
|
|
||||||
/*LANG*/'BLE': ()=>showBLEMenu(),
|
|
||||||
/*LANG*/'Beep': beepMenuItem,
|
/*LANG*/'Beep': beepMenuItem,
|
||||||
/*LANG*/'Vibration': {
|
/*LANG*/'Vibration': {
|
||||||
value: settings.vibrate,
|
value: settings.vibrate,
|
||||||
|
@ -119,23 +147,18 @@ function showMainMenu() {
|
||||||
updateOptions();
|
updateOptions();
|
||||||
if ("qmsched" in WIDGETS) WIDGETS["qmsched"].draw();
|
if ("qmsched" in WIDGETS) WIDGETS["qmsched"].draw();
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
/*LANG*/'Locale': ()=>showLocaleMenu(),
|
|
||||||
/*LANG*/'Select Clock': ()=>showClockMenu(),
|
|
||||||
/*LANG*/'Set Time': ()=>showSetTimeMenu(),
|
|
||||||
/*LANG*/'LCD': ()=>showLCDMenu(),
|
|
||||||
/*LANG*/'Theme': ()=>showThemeMenu(),
|
|
||||||
/*LANG*/'Utils': ()=>showUtilMenu(),
|
|
||||||
/*LANG*/'Turn Off': ()=>{ if (Bangle.softOff) Bangle.softOff(); else Bangle.off() },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return E.showMenu(mainmenu);
|
return E.showMenu(mainmenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function showBLEMenu() {
|
function showBLEMenu() {
|
||||||
var hidV = [false, "kbmedia", "kb", "joy"];
|
var hidV = [false, "kbmedia", "kb", "joy"];
|
||||||
var hidN = ["Off", "Kbrd & Media", "Kbrd","Joystick"];
|
var hidN = ["Off", "Kbrd & Media", "Kbrd","Joystick"];
|
||||||
E.showMenu({
|
E.showMenu({
|
||||||
|
'': { 'title': 'Bluetooth' },
|
||||||
'< Back': ()=>showMainMenu(),
|
'< Back': ()=>showMainMenu(),
|
||||||
'Make Connectable': ()=>makeConnectable(),
|
'Make Connectable': ()=>makeConnectable(),
|
||||||
'BLE': {
|
'BLE': {
|
||||||
|
@ -190,7 +213,7 @@ function showThemeMenu() {
|
||||||
}
|
}
|
||||||
var m = E.showMenu({
|
var m = E.showMenu({
|
||||||
'':{title:'Theme'},
|
'':{title:'Theme'},
|
||||||
'< Back': ()=>showMainMenu(),
|
'< Back': ()=>showSystemMenu(),
|
||||||
'Dark BW': ()=>{
|
'Dark BW': ()=>{
|
||||||
upd({
|
upd({
|
||||||
fg:cl("#fff"), bg:cl("#000"),
|
fg:cl("#fff"), bg:cl("#000"),
|
||||||
|
@ -335,7 +358,7 @@ function showWhitelistMenu() {
|
||||||
function showLCDMenu() {
|
function showLCDMenu() {
|
||||||
const lcdMenu = {
|
const lcdMenu = {
|
||||||
'': { 'title': 'LCD' },
|
'': { 'title': 'LCD' },
|
||||||
'< Back': ()=>showMainMenu(),
|
'< Back': ()=>showSystemMenu(),
|
||||||
'LCD Brightness': {
|
'LCD Brightness': {
|
||||||
value: settings.brightness,
|
value: settings.brightness,
|
||||||
min: 0.1,
|
min: 0.1,
|
||||||
|
@ -447,7 +470,7 @@ function showLCDMenu() {
|
||||||
function showLocaleMenu() {
|
function showLocaleMenu() {
|
||||||
const localemenu = {
|
const localemenu = {
|
||||||
'': { 'title': 'Locale' },
|
'': { 'title': 'Locale' },
|
||||||
'< Back': ()=>showMainMenu(),
|
'< Back': ()=>showSystemMenu(),
|
||||||
'Time Zone': {
|
'Time Zone': {
|
||||||
value: settings.timezone,
|
value: settings.timezone,
|
||||||
min: -11,
|
min: -11,
|
||||||
|
@ -551,7 +574,7 @@ function showClockMenu() {
|
||||||
'': {
|
'': {
|
||||||
'title': 'Select Clock',
|
'title': 'Select Clock',
|
||||||
},
|
},
|
||||||
'< Back': ()=>showMainMenu(),
|
'< Back': ()=>showSystemMenu(),
|
||||||
};
|
};
|
||||||
clockApps.forEach((app, index) => {
|
clockApps.forEach((app, index) => {
|
||||||
var label = app.name;
|
var label = app.name;
|
||||||
|
@ -578,7 +601,7 @@ function showSetTimeMenu() {
|
||||||
'': { 'title': 'Set Time' },
|
'': { 'title': 'Set Time' },
|
||||||
'< Back': function () {
|
'< Back': function () {
|
||||||
setTime(d.getTime() / 1000);
|
setTime(d.getTime() / 1000);
|
||||||
showMainMenu();
|
showSystemMenu();
|
||||||
},
|
},
|
||||||
'Hour': {
|
'Hour': {
|
||||||
value: d.getHours(),
|
value: d.getHours(),
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
0.1: Initial release
|
||||||
|
0.2: Fixed launcher image
|
|
@ -1,3 +1,3 @@
|
||||||
Displays an image. I use this app to show my vaccination certificate.
|
Displays an image. I use this app to show my vaccination certificate.
|
||||||
The image is read from the file "showimage.user.img".
|
The image is read from the file "showimg.user.img".
|
||||||
Returns to watch face after 60s/button push.
|
Returns to watch face after 60s/button push.
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
E.toArrayBuffer(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAf////AHP/////AH//////AP/8AAAHAP4AAAAHAOAAMAAHAOAAeAAHAOAA+cAHAOAA/+AHAOAA/+AHAOAf/+AHAOA//+AHgOA///AHgOA///gDgOA/z/gDgOAfz/gDgOA///gDgOA///gDgOA//uADgOAf3+ADgOAP/+ADgOAD/8ADwOAB+4ADwOAA8AABwOAAAABBwOA8DgPxwOB/Dg/xwOB/jh/xwOB3zj5xwOB57nzxwOA4/njhwOA4/vHhwOA8f+PB4OAef+PB4OAef8eB4OAPP58A4OAHv/4A4OAH//wA4OAD//AA4OAA/8fn4PDgP///4P//////4P////9/wD///4AAA"))
|
require("heatshrink").decompress(atob("mEwwkBIf4Aah//BRQAMDowUNC5AARC4YKKL5gTC+B3TCpAyIC5oNBEA4XNJwS4GC55pHC8TEHC57QHC4wSEC5YpEC6YwEC5oEEC5x3DC6ZHbC7PwcYxfNAYYXPJA4XQDAwKEBYQXJIoReHC5gMFAAojBC5QUIC5Y5JMgYXIUQYJFPggXMAwICCBAYXMCAQJDDwQUCC5QOCUwQdEC5QqFDghNFC5wrEC5gQDPgoTCDYYXFMAgXaCQoXJEwZ4FLQbhFC4imDAAglFC5QAGBgYXKIoYWIC5YYFG4ZkDC4YjCYYwAJC4gASC6THFH5pqGAAY"))
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
0.01: Initial import.
|
0.01: Initial import.
|
||||||
0.07: Add swipe to change screens.
|
0.07: Add swipe to change screens.
|
||||||
|
1.06: Misc memory and screen optimisations.
|
||||||
|
1.10: ...
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
/*
|
/*
|
||||||
Speed and Altitude [speedalt2]
|
Speed and Altitude [speedalt2]
|
||||||
Mike Bennett mike[at]kereru.com
|
Mike Bennett mike[at]kereru.com
|
||||||
0.01 : Initial
|
1.10 : add inverted colours
|
||||||
0.06 : Add Posn screen
|
|
||||||
0.07 : Add swipe to change screens same as BTN3
|
|
||||||
*/
|
*/
|
||||||
var v = '1.05';
|
var v = '1.10';
|
||||||
|
|
||||||
/*kalmanjs, Wouter Bulten, MIT, https://github.com/wouterbulten/kalmanjs */
|
/*kalmanjs, Wouter Bulten, MIT, https://github.com/wouterbulten/kalmanjs */
|
||||||
var KalmanFilter = (function () {
|
var KalmanFilter = (function () {
|
||||||
|
@ -173,6 +171,15 @@ var KalmanFilter = (function () {
|
||||||
|
|
||||||
var buf = Graphics.createArrayBuffer(240,160,2,{msb:true});
|
var buf = Graphics.createArrayBuffer(240,160,2,{msb:true});
|
||||||
|
|
||||||
|
let LED = // LED as minimal and only definition (as instance / singleton)
|
||||||
|
{ isOn: false // status on / off, not needed if you don't need to ask for it
|
||||||
|
, set: function(v) { // turn on w/ no arg or truey, else off
|
||||||
|
g.setColor((this.isOn=(v===undefined||!!v))?1:0,0,0).fillCircle(40,10,10); }
|
||||||
|
, reset: function() { this.set(false); } // turn off
|
||||||
|
, write: function(v) { this.set(v); } // turn on w/ no arg or truey, else off
|
||||||
|
, toggle: function() { this.set( ! this.isOn); } // toggle the LED
|
||||||
|
}, LED1 = LED; // LED1 as 'synonym' for LED
|
||||||
|
|
||||||
// Load fonts
|
// Load fonts
|
||||||
//require("Font7x11Numeric7Seg").add(Graphics);
|
//require("Font7x11Numeric7Seg").add(Graphics);
|
||||||
|
|
||||||
|
@ -183,17 +190,16 @@ var canDraw = 1;
|
||||||
var time = ''; // Last time string displayed. Re displayed in background colour to remove before drawing new time.
|
var time = ''; // Last time string displayed. Re displayed in background colour to remove before drawing new time.
|
||||||
var tmrLP; // Timer for delay in switching to low power after screen turns off
|
var tmrLP; // Timer for delay in switching to low power after screen turns off
|
||||||
|
|
||||||
var max = {};
|
var maxSpd = 0;
|
||||||
max.spd = 0;
|
var maxAlt = 0;
|
||||||
max.alt = 0;
|
var maxN = 0; // counter. Only start comparing for max after a certain number of fixes to allow kalman filter to have smoohed the data.
|
||||||
max.n = 0; // counter. Only start comparing for max after a certain number of fixes to allow kalman filter to have smoohed the data.
|
|
||||||
|
|
||||||
var emulator = (process.env.BOARD=="EMSCRIPTEN")?1:0; // 1 = running in emulator. Supplies test values;
|
var emulator = (process.env.BOARD=="EMSCRIPTEN")?1:0; // 1 = running in emulator. Supplies test values;
|
||||||
|
|
||||||
var wp = {}; // Waypoint to use for distance from cur position.
|
var wp = {}; // Waypoint to use for distance from cur position.
|
||||||
|
|
||||||
function nxtWp(inc){
|
function nxtWp(){
|
||||||
cfg.wp+=inc;
|
cfg.wp++;
|
||||||
loadWp();
|
loadWp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +233,8 @@ function drawScrn(dat) {
|
||||||
if (!canDraw) return;
|
if (!canDraw) return;
|
||||||
|
|
||||||
buf.clear();
|
buf.clear();
|
||||||
|
buf.setBgColor(0);
|
||||||
|
|
||||||
var n;
|
var n;
|
||||||
n = dat.val.toString();
|
n = dat.val.toString();
|
||||||
|
|
||||||
|
@ -252,29 +259,21 @@ function drawScrn(dat) {
|
||||||
buf.setFontVector(35);
|
buf.setFontVector(35);
|
||||||
buf.drawString(dat.unit,5,164);
|
buf.drawString(dat.unit,5,164);
|
||||||
|
|
||||||
if ( dat.max ) drawMax(); // MAX display indicator
|
drawMax(dat.max); // MAX display indicator
|
||||||
if ( dat.wp ) drawWP(); // Waypoint name
|
drawWP(dat.wp); // Waypoint name
|
||||||
|
drawSats(dat.sats);
|
||||||
//Sats
|
|
||||||
if ( dat.sat ) {
|
|
||||||
if ( dat.age > 10 ) {
|
|
||||||
if ( dat.age > 90 ) dat.age = '>90';
|
|
||||||
drawSats('Age:'+dat.age);
|
|
||||||
}
|
|
||||||
else drawSats('Sats:'+dat.sats);
|
|
||||||
}
|
|
||||||
|
|
||||||
g.reset();
|
g.reset();
|
||||||
g.drawImage(img,0,40);
|
g.drawImage(img,0,40);
|
||||||
|
|
||||||
if ( pwrSav ) LED1.reset();
|
LED1.write(!pwrSav);
|
||||||
else LED1.set();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawPosn(dat) {
|
function drawPosn(dat) {
|
||||||
if (!canDraw) return;
|
if (!canDraw) return;
|
||||||
buf.clear();
|
buf.clear();
|
||||||
|
buf.setBgColor(0);
|
||||||
|
|
||||||
var x, y;
|
var x, y;
|
||||||
x=210;
|
x=210;
|
||||||
|
@ -293,20 +292,12 @@ function drawPosn(dat) {
|
||||||
buf.drawString(dat.ew,x,y+70);
|
buf.drawString(dat.ew,x,y+70);
|
||||||
|
|
||||||
|
|
||||||
//Sats
|
drawSats(dat.sats);
|
||||||
if ( dat.sat ) {
|
|
||||||
if ( dat.age > 10 ) {
|
|
||||||
if ( dat.age > 90 ) dat.age = '>90';
|
|
||||||
drawSats('Age:'+dat.age);
|
|
||||||
}
|
|
||||||
else drawSats('Sats:'+dat.sats);
|
|
||||||
}
|
|
||||||
|
|
||||||
g.reset();
|
g.reset();
|
||||||
g.drawImage(img,0,40);
|
g.drawImage(img,0,40);
|
||||||
|
|
||||||
if ( pwrSav ) LED1.reset();
|
LED1.write(!pwrSav);
|
||||||
else LED1.set();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,6 +305,8 @@ function drawClock() {
|
||||||
if (!canDraw) return;
|
if (!canDraw) return;
|
||||||
|
|
||||||
buf.clear();
|
buf.clear();
|
||||||
|
buf.setBgColor(0);
|
||||||
|
|
||||||
var x, y;
|
var x, y;
|
||||||
x=185;
|
x=185;
|
||||||
y=0;
|
y=0;
|
||||||
|
@ -329,19 +322,14 @@ function drawClock() {
|
||||||
g.reset();
|
g.reset();
|
||||||
g.drawImage(img,0,40);
|
g.drawImage(img,0,40);
|
||||||
|
|
||||||
if ( pwrSav ) LED1.reset();
|
LED1.write(!pwrSav);
|
||||||
else LED1.set();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawWP() {
|
function drawWP(wp) {
|
||||||
var nm = wp.name;
|
buf.setColor(3);
|
||||||
if ( nm == undefined || nm == 'NONE' || cfg.modeA ==1 ) nm = '';
|
|
||||||
buf.setColor(2);
|
|
||||||
|
|
||||||
buf.setFontAlign(0,1); //left, bottom
|
buf.setFontAlign(0,1); //left, bottom
|
||||||
buf.setFontVector(48);
|
buf.setFontVector(48);
|
||||||
buf.drawString(nm.substring(0,8),120,140);
|
buf.drawString(wp,120,140);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawSats(sats) {
|
function drawSats(sats) {
|
||||||
|
@ -351,16 +339,15 @@ function drawSats(sats) {
|
||||||
buf.drawString(sats,240,160);
|
buf.drawString(sats,240,160);
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawMax() {
|
function drawMax(max) {
|
||||||
buf.setFontVector(30);
|
buf.setFontVector(30);
|
||||||
buf.setColor(2);
|
buf.setColor(2);
|
||||||
buf.setFontAlign(0,1); //centre, bottom
|
buf.setFontAlign(0,1); //centre, bottom
|
||||||
buf.drawString('MAX',120,164);
|
buf.drawString(max,120,164);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onGPS(fix) {
|
function onGPS(fix) {
|
||||||
|
if ( emulator ) {
|
||||||
if ( emulator ) {
|
|
||||||
fix.fix = 1;
|
fix.fix = 1;
|
||||||
fix.speed = 10 + (Math.random()*5);
|
fix.speed = 10 + (Math.random()*5);
|
||||||
fix.alt = 354 + (Math.random()*50);
|
fix.alt = 354 + (Math.random()*50);
|
||||||
|
@ -382,10 +369,15 @@ function onGPS(fix) {
|
||||||
var ns = '';
|
var ns = '';
|
||||||
var ew = '';
|
var ew = '';
|
||||||
var lon = '---.--';
|
var lon = '---.--';
|
||||||
|
var sats = '---';
|
||||||
|
|
||||||
|
// Waypoint name
|
||||||
|
var wpName = wp.name;
|
||||||
|
if ( wpName == undefined || wpName == 'NONE' ) wpName = '';
|
||||||
|
wpName = wpName.substring(0,8);
|
||||||
|
|
||||||
if (fix.fix) lf = fix;
|
if (fix.fix) lf = fix;
|
||||||
|
|
||||||
if (lf.fix) {
|
if (lf.fix) {
|
||||||
|
|
||||||
// Smooth data
|
// Smooth data
|
||||||
|
@ -393,10 +385,9 @@ function onGPS(fix) {
|
||||||
if ( cfg.spdFilt ) lf.speed = spdFilter.filter(lf.speed);
|
if ( cfg.spdFilt ) lf.speed = spdFilter.filter(lf.speed);
|
||||||
if ( cfg.altFilt ) lf.alt = altFilter.filter(lf.alt);
|
if ( cfg.altFilt ) lf.alt = altFilter.filter(lf.alt);
|
||||||
lf.smoothed = 1;
|
lf.smoothed = 1;
|
||||||
if ( max.n <= 15 ) max.n++;
|
if ( maxN <= 15 ) maxN++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Speed
|
// Speed
|
||||||
if ( cfg.spd == 0 ) {
|
if ( cfg.spd == 0 ) {
|
||||||
m = require("locale").speed(lf.speed).match(/([0-9,\.]+)(.*)/); // regex splits numbers from units
|
m = require("locale").speed(lf.speed).match(/([0-9,\.]+)(.*)/); // regex splits numbers from units
|
||||||
|
@ -407,18 +398,19 @@ function onGPS(fix) {
|
||||||
|
|
||||||
if ( sp < 10 ) sp = sp.toFixed(1);
|
if ( sp < 10 ) sp = sp.toFixed(1);
|
||||||
else sp = Math.round(sp);
|
else sp = Math.round(sp);
|
||||||
|
if (isNaN(sp)) sp = '---';
|
||||||
|
|
||||||
if (parseFloat(sp) > parseFloat(max.spd) && max.n > 15 ) max.spd = sp;
|
if (parseFloat(sp) > parseFloat(maxSpd) && maxN > 15 ) maxSpd = sp;
|
||||||
|
|
||||||
// Altitude
|
// Altitude
|
||||||
al = lf.alt;
|
al = lf.alt;
|
||||||
al = Math.round(parseFloat(al)/parseFloat(cfg.alt));
|
al = Math.round(parseFloat(al)/parseFloat(cfg.alt));
|
||||||
|
if (parseFloat(al) > parseFloat(maxAlt) && maxN > 15 ) maxAlt = al;
|
||||||
if (parseFloat(al) > parseFloat(max.alt) && max.n > 15 ) max.alt = al;
|
if (isNaN(al)) al = '---';
|
||||||
|
|
||||||
// Distance to waypoint
|
// Distance to waypoint
|
||||||
di = distance(lf,wp);
|
di = distance(lf,wp);
|
||||||
if (isNaN(di)) di = 0;
|
if (isNaN(di)) di = '--------';
|
||||||
|
|
||||||
// Age of last fix (secs)
|
// Age of last fix (secs)
|
||||||
age = Math.max(0,Math.round(getTime())-(lf.time.getTime()/1000));
|
age = Math.max(0,Math.round(getTime())-(lf.time.getTime()/1000));
|
||||||
|
@ -431,6 +423,13 @@ function onGPS(fix) {
|
||||||
ew = 'E';
|
ew = 'E';
|
||||||
if ( lf.lon < 0 ) ew = 'W';
|
if ( lf.lon < 0 ) ew = 'W';
|
||||||
lon = Math.abs(lf.lon.toFixed(2));
|
lon = Math.abs(lf.lon.toFixed(2));
|
||||||
|
|
||||||
|
// Sats
|
||||||
|
if ( age > 10 ) {
|
||||||
|
sats = 'Age:'+Math.round(age);
|
||||||
|
if ( age > 90 ) sats = 'Age:>90';
|
||||||
|
}
|
||||||
|
else sats = 'Sats:'+lf.satellites;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,23 +437,21 @@ function onGPS(fix) {
|
||||||
// Speed
|
// Speed
|
||||||
if ( showMax )
|
if ( showMax )
|
||||||
drawScrn({
|
drawScrn({
|
||||||
val:max.spd,
|
val:maxSpd,
|
||||||
unit:cfg.spd_unit,
|
unit:cfg.spd_unit,
|
||||||
sats:lf.satellites,
|
sats:sats,
|
||||||
age:age,
|
age:age,
|
||||||
max:true,
|
max:'MAX',
|
||||||
wp:false,
|
wp:''
|
||||||
sat:true
|
|
||||||
}); // Speed maximums
|
}); // Speed maximums
|
||||||
else
|
else
|
||||||
drawScrn({
|
drawScrn({
|
||||||
val:sp,
|
val:sp,
|
||||||
unit:cfg.spd_unit,
|
unit:cfg.spd_unit,
|
||||||
sats:lf.satellites,
|
sats:sats,
|
||||||
age:age,
|
age:age,
|
||||||
max:false,
|
max:'SPD',
|
||||||
wp:false,
|
wp:''
|
||||||
sat:true
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,23 +459,21 @@ function onGPS(fix) {
|
||||||
// Alt
|
// Alt
|
||||||
if ( showMax )
|
if ( showMax )
|
||||||
drawScrn({
|
drawScrn({
|
||||||
val:max.alt,
|
val:maxAlt,
|
||||||
unit:cfg.alt_unit,
|
unit:cfg.alt_unit,
|
||||||
sats:lf.satellites,
|
sats:sats,
|
||||||
age:age,
|
age:age,
|
||||||
max:true,
|
max:'MAX',
|
||||||
wp:false,
|
wp:''
|
||||||
sat:true
|
|
||||||
}); // Alt maximums
|
}); // Alt maximums
|
||||||
else
|
else
|
||||||
drawScrn({
|
drawScrn({
|
||||||
val:al,
|
val:al,
|
||||||
unit:cfg.alt_unit,
|
unit:cfg.alt_unit,
|
||||||
sats:lf.satellites,
|
sats:sats,
|
||||||
age:age,
|
age:age,
|
||||||
max:false,
|
max:'ALT',
|
||||||
wp:false,
|
wp:''
|
||||||
sat:true
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,24 +482,22 @@ function onGPS(fix) {
|
||||||
drawScrn({
|
drawScrn({
|
||||||
val:di,
|
val:di,
|
||||||
unit:cfg.dist_unit,
|
unit:cfg.dist_unit,
|
||||||
sats:lf.satellites,
|
sats:sats,
|
||||||
age:age,
|
age:age,
|
||||||
max:false,
|
max:'DST',
|
||||||
wp:true,
|
wp:wpName
|
||||||
sat:true
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( cfg.modeA == 3 ) {
|
if ( cfg.modeA == 3 ) {
|
||||||
// Position
|
// Position
|
||||||
drawPosn({
|
drawPosn({
|
||||||
sats:lf.satellites,
|
sats:sats,
|
||||||
age:age,
|
age:age,
|
||||||
lat:lat,
|
lat:lat,
|
||||||
lon:lon,
|
lon:lon,
|
||||||
ns:ns,
|
ns:ns,
|
||||||
ew:ew,
|
ew:ew
|
||||||
sat:true
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,9 +527,9 @@ function nextFunc(dur) {
|
||||||
if ( cfg.modeA == 0 || cfg.modeA == 1 ) {
|
if ( cfg.modeA == 0 || cfg.modeA == 1 ) {
|
||||||
// Spd+Alt mode - Switch between fix and MAX
|
// Spd+Alt mode - Switch between fix and MAX
|
||||||
if ( dur < 2 ) showMax = !showMax; // Short press toggle fix/max display
|
if ( dur < 2 ) showMax = !showMax; // Short press toggle fix/max display
|
||||||
else { max.spd = 0; max.alt = 0; } // Long press resets max values.
|
else { maxSpd = 0; maxAlt = 0; } // Long press resets max values.
|
||||||
}
|
}
|
||||||
else if ( cfg.modeA == 2) nxtWp(1); // Dist mode - Select next waypoint
|
else if ( cfg.modeA == 2) nxtWp(); // Dist mode - Select next waypoint
|
||||||
onGPS(lf);
|
onGPS(lf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,7 +538,7 @@ function updateClock() {
|
||||||
if (!canDraw) return;
|
if (!canDraw) return;
|
||||||
if ( cfg.modeA != 4 ) return;
|
if ( cfg.modeA != 4 ) return;
|
||||||
drawClock();
|
drawClock();
|
||||||
if ( emulator ) {max.spd++;max.alt++;}
|
if ( emulator ) {maxSpd++;maxAlt++;}
|
||||||
}
|
}
|
||||||
|
|
||||||
function startDraw(){
|
function startDraw(){
|
||||||
|
@ -585,7 +578,6 @@ function setButtons(){
|
||||||
setWatch(function(e){
|
setWatch(function(e){
|
||||||
pwrSav=!pwrSav;
|
pwrSav=!pwrSav;
|
||||||
if ( pwrSav ) {
|
if ( pwrSav ) {
|
||||||
LED1.reset();
|
|
||||||
var s = require('Storage').readJSON('setting.json',1)||{};
|
var s = require('Storage').readJSON('setting.json',1)||{};
|
||||||
var t = s.timeout||10;
|
var t = s.timeout||10;
|
||||||
Bangle.setLCDTimeout(t);
|
Bangle.setLCDTimeout(t);
|
||||||
|
@ -593,8 +585,8 @@ function setButtons(){
|
||||||
else {
|
else {
|
||||||
Bangle.setLCDTimeout(0);
|
Bangle.setLCDTimeout(0);
|
||||||
// Bangle.setLCDPower(1);
|
// Bangle.setLCDPower(1);
|
||||||
LED1.set();
|
|
||||||
}
|
}
|
||||||
|
LED1.write(!pwrSav);
|
||||||
}, BTN2, {repeat:true,edge:"falling"});
|
}, BTN2, {repeat:true,edge:"falling"});
|
||||||
|
|
||||||
// BTN3 - next screen
|
// BTN3 - next screen
|
||||||
|
@ -690,7 +682,8 @@ var img = {
|
||||||
};
|
};
|
||||||
|
|
||||||
if ( cfg.colour == 1 ) img.palette = new Uint16Array([0,0xFFFF,0xFFF6,0xDFFF]);
|
if ( cfg.colour == 1 ) img.palette = new Uint16Array([0,0xFFFF,0xFFF6,0xDFFF]);
|
||||||
if ( cfg.colour == 2 ) img.palette = new Uint16Array([0,0xFF800,0xFAE0,0xF813]);
|
if ( cfg.colour == 2 ) img.palette = new Uint16Array([0,0xF800,0xFAE0,0xF813]);
|
||||||
|
if ( cfg.colour == 3 ) img.palette = new Uint16Array([0xFFFF,0x007F,0x0054,0x0054]);
|
||||||
|
|
||||||
var SCREENACCESS = {
|
var SCREENACCESS = {
|
||||||
withApp:true,
|
withApp:true,
|
||||||
|
|
|
@ -65,7 +65,8 @@
|
||||||
'< Back': function() { E.showMenu(appMenu); },
|
'< Back': function() { E.showMenu(appMenu); },
|
||||||
'Default' : function() { setColour(0); },
|
'Default' : function() { setColour(0); },
|
||||||
'Hi Contrast' : function() { setColour(1); },
|
'Hi Contrast' : function() { setColour(1); },
|
||||||
'Night' : function() { setColour(2); }
|
'Night' : function() { setColour(2); },
|
||||||
|
'Inverted' : function() { setColour(3); }
|
||||||
};
|
};
|
||||||
|
|
||||||
const kalMenu = {
|
const kalMenu = {
|
||||||
|
|
|
@ -31,3 +31,6 @@ Which one is which ?
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
require("heatshrink").decompress(atob("AH4A/ACXd7vQC6vUpoBBDaQXEDaQXIDZwXMAIQZHC4R6BAAIZJDAwXIDY4XHAAodJ7oXMDpQXSAAiRHhoWN7zFLDY/e9ve9zeMhvQCIIBFC5ARIC5oVNC5EOCpwABC4vuCZYXPCIwXOCJAAFC5gAJ8AXFCpwuHgDjCFqQXC6lN6gbFf5gXEAInd6AXVDYndhoXKBoIbMC5QZLC44AFDpIXNDpQXdhoYMAAbwIC6oZQbxhOKC5gbKC6BUGC6oA/AHgA=="))
|
require("heatshrink").decompress(atob("mEw4UA///sH8ov+8GyJf4AIgt8BZV9voNIBYQNIBYgNGBYwMEBYNVqoMEoALGBoYLDBQILCAQVQBYoOEBZIABBYUAgILGsBiEBodWy2gN4soywACBYcI1QJDBYoJFBYkCBQ2qBYUKBIoLHBAQLHBAYACBYwAEwALBgwKG1S/DC4wWCa4Y3Efa19mALKvrLDfY7XGBwjvVBYjuHfYgLLBg4LEAAMVBZQNEBZBPCBZQA+A"))
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
0.02: New App!
|
0.02: New App!
|
||||||
0.03: Improved messages and added Celsius sign
|
0.03: Improved messages and added Celsius sign
|
||||||
0.04: Make temperature value readable on smaller screens
|
0.04: Make temperature value readable on smaller screens
|
||||||
|
0.05: Use temperature from current locale
|
||||||
|
Update every 10s, average last 5 readings
|
||||||
|
Changes based on #1092
|
||||||
|
|
|
@ -1,13 +1,27 @@
|
||||||
|
// history of temperature readings
|
||||||
|
var history = [];
|
||||||
|
|
||||||
|
|
||||||
|
// When we get temperature...
|
||||||
function onTemperature(p) {
|
function onTemperature(p) {
|
||||||
g.reset(1).clearRect(0,24,g.getWidth(),g.getHeight());
|
var rect = Bangle.appRect;
|
||||||
|
g.reset(1).clearRect(rect.x, rect.y, rect.x2, rect.y2);
|
||||||
g.setFont("6x8",2).setFontAlign(0,0);
|
g.setFont("6x8",2).setFontAlign(0,0);
|
||||||
var x = g.getWidth()/2;
|
var x = (rect.x+rect.x2)/2;
|
||||||
var y = g.getHeight()/2 + 10;
|
var y = (rect.y+rect.y2)/2 + 10;
|
||||||
g.drawString("Temperature:", x, y - 45);
|
g.drawString("Temperature:", x, y - 45);
|
||||||
g.setFontVector(g.getWidth() > 200 ? 70 : 40).setFontAlign(0,0);
|
g.setFontVector(g.getWidth() > 200 ? 70 : 50).setFontAlign(0,0);
|
||||||
g.drawString(p.temperature.toFixed(1) + " °C", x, y);
|
|
||||||
|
// Average the last 5 temperature readings
|
||||||
|
while (history.length>4) history.shift();
|
||||||
|
history.push(p.temperature);
|
||||||
|
var avrTemp = E.sum(history) / history.length;
|
||||||
|
// Draw the temperature
|
||||||
|
var t = require('locale').temp(avrTemp).replace("'","°");
|
||||||
|
g.drawString(t, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gets the temperature in the most accurate way (pressure sensor or inbuilt thermistor)
|
||||||
function drawTemperature() {
|
function drawTemperature() {
|
||||||
if (Bangle.getPressure) {
|
if (Bangle.getPressure) {
|
||||||
Bangle.getPressure().then(onTemperature);
|
Bangle.getPressure().then(onTemperature);
|
||||||
|
@ -18,11 +32,10 @@ function drawTemperature() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
setInterval(function() {
|
setInterval(function() {
|
||||||
drawTemperature();
|
drawTemperature();
|
||||||
}, 20000);
|
}, 10000);
|
||||||
drawTemperature();
|
|
||||||
E.showMessage("Reading temperature...");
|
E.showMessage("Reading temperature...");
|
||||||
|
drawTemperature();
|
||||||
Bangle.loadWidgets();
|
Bangle.loadWidgets();
|
||||||
Bangle.drawWidgets();
|
Bangle.drawWidgets();
|
||||||
|
|
After Width: | Height: | Size: 2.4 KiB |
|
@ -293,9 +293,9 @@ Bangle.on('swipe', dir => {
|
||||||
else next();
|
else next();
|
||||||
});
|
});
|
||||||
|
|
||||||
// close launcher when lcd is off
|
// close launcher when screen is locked
|
||||||
Bangle.on('lcdPower', on => {
|
Bangle.on('lock', on => {
|
||||||
if(!on) return load();
|
if(on) return load();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (process.env.HWVERSION == 1) {
|
if (process.env.HWVERSION == 1) {
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
0.01: New watch face
|
||||||
|
0.02: Use Bangle.setUI for button/launcher handling
|
||||||
|
0.03: Bangle.js 2 support
|
|
@ -1,3 +0,0 @@
|
||||||
0.1: New watch face
|
|
||||||
0.2: Use Bangle.setUI for button/launcher handling
|
|
||||||
0.3: Bangle.js 2 support
|
|
|
@ -19,3 +19,4 @@
|
||||||
Stop goal drawing outside widget area
|
Stop goal drawing outside widget area
|
||||||
Fix issue with widget overwrite in large font mode
|
Fix issue with widget overwrite in large font mode
|
||||||
Memory usage enhancements
|
Memory usage enhancements
|
||||||
|
0.20: Fix issue where step count would randomly reset
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
E.on('kill', () => {
|
E.on('kill', () => {
|
||||||
if (!settings) { loadSettings() }
|
if (!settings) { loadSettings() }
|
||||||
let d = {
|
let d = {
|
||||||
lastUpdate : lastUpdate.toISOString(),
|
lastUpdate : lastUpdate.valueOf(),
|
||||||
stepsToday : stp_today,
|
stepsToday : stp_today,
|
||||||
settings : settings,
|
settings : settings,
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
|
var heatshrink = require("../core/lib/heatshrink");
|
||||||
var acorn;
|
var acorn;
|
||||||
try {
|
try {
|
||||||
acorn = require("acorn");
|
acorn = require("acorn");
|
||||||
|
@ -59,6 +60,7 @@ const STORAGE_KEYS = ['name', 'url', 'content', 'evaluate', 'noOverwite', 'suppo
|
||||||
const DATA_KEYS = ['name', 'wildcard', 'storageFile', 'url', 'content', 'evaluate'];
|
const DATA_KEYS = ['name', 'wildcard', 'storageFile', 'url', 'content', 'evaluate'];
|
||||||
const FORBIDDEN_FILE_NAME_CHARS = /[,;]/; // used as separators in appid.info
|
const FORBIDDEN_FILE_NAME_CHARS = /[,;]/; // used as separators in appid.info
|
||||||
const VALID_DUPLICATES = [ '.tfmodel', '.tfnames' ];
|
const VALID_DUPLICATES = [ '.tfmodel', '.tfnames' ];
|
||||||
|
const GRANDFATHERED_ICONS = ["s7clk", "snek", "astral", "alpinenav", "slomoclock", "arrow", "pebble", "rebble"];
|
||||||
|
|
||||||
function globToRegex(pattern) {
|
function globToRegex(pattern) {
|
||||||
const ESCAPE = '.*+-?^${}()|[]\\';
|
const ESCAPE = '.*+-?^${}()|[]\\';
|
||||||
|
@ -175,6 +177,23 @@ apps.forEach((app,appIdx) => {
|
||||||
for (const key in file) {
|
for (const key in file) {
|
||||||
if (!STORAGE_KEYS.includes(key)) ERROR(`App ${app.id} file ${file.name} has unknown key ${key}`);
|
if (!STORAGE_KEYS.includes(key)) ERROR(`App ${app.id} file ${file.name} has unknown key ${key}`);
|
||||||
}
|
}
|
||||||
|
// warn if JS icon is the wrong size
|
||||||
|
if (file.name == app.id+".img") {
|
||||||
|
let icon;
|
||||||
|
let match = fileContents.match(/E\.toArrayBuffer\(atob\(\"([^"]*)\"\)\)/);
|
||||||
|
if (match) icon = Buffer.from(match[1], 'base64');
|
||||||
|
else {
|
||||||
|
match = fileContents.match(/require\(\"heatshrink\"\)\.decompress\(\s*atob\(\s*\"([^"]*)\"\s*\)\s*\)/);
|
||||||
|
if (match) icon = heatshrink.decompress(Buffer.from(match[1], 'base64'));
|
||||||
|
else ERROR(`JS icon ${file.name} does not match the pattern 'require("heatshrink").decompress(atob("..."))'`);
|
||||||
|
}
|
||||||
|
if (match) {
|
||||||
|
if (icon[0] > 48 || icon[0] < 24 || icon[1] > 48 || icon[1] < 24) {
|
||||||
|
if (GRANDFATHERED_ICONS.includes(app.id)) WARN(`JS icon ${file.name} should be 48x48px (or slightly under) but is instead ${icon[0]}x${icon[1]}px`);
|
||||||
|
else ERROR(`JS icon ${file.name} should be 48x48px (or slightly under) but is instead ${icon[0]}x${icon[1]}px`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
let dataNames = [];
|
let dataNames = [];
|
||||||
(app.data||[]).forEach((data)=>{
|
(app.data||[]).forEach((data)=>{
|
||||||
|
|
|
@ -11,7 +11,7 @@ if (window.location.host=="banglejs.com") {
|
||||||
'This is not the official Bangle.js App Loader - you can try the <a href="https://banglejs.com/apps/">Official Version</a> here.';
|
'This is not the official Bangle.js App Loader - you can try the <a href="https://banglejs.com/apps/">Official Version</a> here.';
|
||||||
}
|
}
|
||||||
|
|
||||||
var RECOMMENDED_VERSION = "2v10";
|
var RECOMMENDED_VERSION = "2v11";
|
||||||
// could check http://www.espruino.com/json/BANGLEJS.json for this
|
// could check http://www.espruino.com/json/BANGLEJS.json for this
|
||||||
|
|
||||||
// We're only interested in Bangles
|
// We're only interested in Bangles
|
||||||
|
|