Merge branch 'espruino:master' into dev

master
Andrew Gregory 2021-12-17 19:05:16 +08:00 committed by GitHub
commit 20a2df7a31
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 367 additions and 63 deletions

View File

@ -77,7 +77,7 @@
{
"id": "messages",
"name": "Messages",
"version": "0.13",
"version": "0.14",
"description": "App to display notifications from iOS and Gadgetbridge",
"icon": "app.png",
"type": "app",
@ -132,7 +132,7 @@
{
"id": "health",
"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)",
"icon": "app.png",
"tags": "tool,system,health",
@ -167,7 +167,7 @@
{
"id": "setting",
"name": "Settings",
"version": "0.37",
"version": "0.38",
"description": "A menu for setting up Bangle.js",
"icon": "settings.png",
"tags": "tool,system",
@ -554,7 +554,7 @@
{
"id": "impwclock",
"name": "Imprecise Word Clock",
"version": "0.03",
"version": "0.04",
"description": "Imprecise word clock for vacations, weekends, and those who never need accurate time.",
"icon": "clock-impword.png",
"type": "clock",
@ -4980,7 +4980,7 @@
"name": "simple image viewer",
"shortName":"showImage",
"version":"0.2",
"description": "Displays the image in \"showimage.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.",
"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",
"tags": "tool",
"supports" : ["BANGLEJS2"],
@ -5006,10 +5006,28 @@
{"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.01",
"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"},

View File

@ -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.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

View File

@ -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=="))

View File

@ -0,0 +1,2 @@
0.01: New clock
0.02: Fix icon & add battery warn functionality

View File

@ -1 +0,0 @@
0.01: New clock

View File

@ -5,7 +5,7 @@ A clock with circles for different data at the bottom in a probably familiar sty
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
* Battery (including charging and battery low)
## Screenshot
@ -14,6 +14,8 @@ It shows besides time, date and day of week the following information:
## TODO
* Show weather information
## Creator
Marco ([myxor](https://github.com/myxor))
## Icons
Icons taken from [materialdesignicons](https://materialdesignicons.com) under Apache License 2.0

View File

@ -1 +1 @@
require("heatshrink").decompress(atob("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"))
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=="))

View File

@ -1,9 +1,11 @@
const locale = require("locale");
const heatshrink = require("heatshrink");
var shoesIcon = heatshrink.decompress(atob("h0OwYJGgmAAgUBkgECgVJB4cSoAUDyEBkARDpADBhMAyQRBgVAkgmDhIUDAAuQAgY1DAAYA="));
var heartIcon = heatshrink.decompress(atob("h0OwYOLkmQhMkgACByVJgESpIFBpEEBAIFBCgIFCCgsABwcAgQOCAAMSpAwDyBNM"));
var powerIcon = heatshrink.decompress(atob("h0OwYQNsAED7AEDmwEDtu2AgUbtuABwXbBIUN23AAoYOCgEDFIgODABI"));
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;
@ -11,13 +13,16 @@ let settings;
function loadSettings() {
settings = require("Storage").readJSON(SETTINGS_FILE, 1) || {
'maxHR': 200,
'stepGoal': 10000
'stepGoal': 10000,
'batteryWarn': 30
};
}
const colorFg = '#fff';
const colorBg = '#000';
const colorGrey = '#808080';
const colorRed = '#ff0000';
const colorGreen = '#00ff00';
let hrtValue;
@ -89,13 +94,12 @@ function drawSteps() {
}
function drawHeartRate() {
const red = '#ff0000';
g.setColor(colorGrey);
g.fillCircle(w2, h3, radiusOuter);
if (hrtValue != undefined) {
const percent = hrtValue / settings.maxHR;
drawGauge(w2, h3, percent, red);
drawGauge(w2, h3, percent, colorRed);
}
g.setColor(colorBg);
@ -106,7 +110,7 @@ function drawHeartRate() {
g.setFont("Vector:12");
g.setFontAlign(0, 0);
g.setColor(colorFg);
g.drawString(hrtValue != undefined ? hrtValue : 0, w2, h3);
g.drawString(hrtValue != undefined ? hrtValue : "-", w2, h3);
g.drawImage(heartIcon, w2 - 6, h3 + radiusOuter - 6);
}
@ -129,10 +133,23 @@ function drawBattery() {
g.setFont("Vector:12");
g.setFontAlign(0, 0);
g.setColor(colorFg);
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(powerIcon, w3 - 6, h3 + radiusOuter - 6);
g.drawImage(icon, w3 - 6, h3 + radiusOuter - 6);
}
function radians(a) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -28,6 +28,16 @@
},
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,
});
});

View File

@ -1,2 +1,3 @@
0.01: New clock!
0.02: Load steps from Health Tracking app (if installed)
0.03: ...

View File

@ -1 +1 @@
0.1: New app
0.01: New app

View File

@ -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"))

View File

@ -4,4 +4,4 @@
0.04: reset to clock after 2 mins of inactivity
0.05: add Bangle 2 version
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

File diff suppressed because one or more lines are too long

View File

@ -7,3 +7,4 @@
0.06: Fix daily health summary for movement (a line got deleted!)
0.07: Added coloured 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)

View File

@ -27,7 +27,7 @@ Bangle.on("health", health => {
const DB_FILE_LEN = DB_HEADER_LEN + DB_RECORDS_PER_MONTH*DB_RECORD_LEN;
function getRecordFN(d) {
return "health-"+d.getFullYear()+"-"+d.getMonth()+".raw";
return "health-"+d.getFullYear()+"-"+(d.getMonth()+1)+".raw";
}
function getRecordIdx(d) {
return (DB_RECORDS_PER_DAY*(d.getDate()-1)) +

View File

@ -6,7 +6,7 @@ const DB_HEADER_LEN = 8;
const DB_FILE_LEN = DB_HEADER_LEN + DB_RECORDS_PER_MONTH*DB_RECORD_LEN;
function getRecordFN(d) {
return "health-"+d.getFullYear()+"-"+d.getMonth()+".raw";
return "health-"+d.getFullYear()+"-"+(d.getMonth()+1)+".raw";
}
function getRecordIdx(d) {
return (DB_RECORDS_PER_DAY*(d.getDate()-1)) +

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -154,7 +154,8 @@ var locales = {
month: "Januar,Februar,März,April,Mai,Juni,Juli,August,September,Oktober,November,Dezember",
abday: "So,Mo,Di,Mi,Do,Fr,Sa",
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": {
lang: "en_US",
@ -327,13 +328,15 @@ var locales = {
speed: "kmh",
distance: { 0: "m", 1: "km" },
temperature: "°C",
ampm: { 0: "", 1: "" },
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
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",
abday: "So,Mo,Di,Mi,Do,Fr,Sa",
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": {
lang: "en_IL",
@ -369,7 +372,8 @@ var locales = {
month: "enero,febrero,marzo,abril,mayo,junio,julio,agosto,septiembre,octubre,noviembre,diciembre",
abday: "dom,lun,mar,mié,jue,vie,sáb",
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": {
lang: "fr_BE",

View File

@ -20,3 +20,4 @@
0.13: Add /*LANG*/ comments for internationalisation
Add 'Delete All' option to message options
Now update correctly when 'require("messages").clearAll()' is called
0.14: Hide widget when all unread notifications are dismissed from phone

View File

@ -30,6 +30,10 @@ exports.pushMessage = function(event) {
require("Storage").writeJSON("messages.json",messages);
// if in app, process immediately
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
if (event.t!="add") {
return;

View File

@ -1 +1 @@
require("heatshrink").decompress(atob("MDABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"))
require("heatshrink").decompress(atob("mEwwIHEgPAAocP+AFDv4FDgf/Aoc/AocB/4FDh4FEv4FEAgIFIDgQFR+FwAoeAAof8gAFDLoIFC/wyBAoQ4CAoXgAoh0CAtybCAoJPBAoahDAoMHAoicBAoM54EfAoJqCAoQUBAoYUBAoYCBAoXgZAIFC4AFCCgOAYYI1CZIRHB/AFDcwmAAoj9Dj6mCdoQaBAAYWDgA"))

1
apps/pebbled/ChangeLog Normal file
View File

@ -0,0 +1 @@
0.1: first release

Binary file not shown.

22
apps/pebbled/README.md Normal file
View File

@ -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%
![](pebble_screenshot.png)
![](photo.jpg)
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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

129
apps/pebbled/pebbled.app.js Normal file
View File

@ -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");

View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEw4kB78A/4ACj/fn8Rz/Or987+M38hv8Rn++z9Cn8y/9rj9Tr+diIAHiAxDgIOICpYADCywyNCxQYMSxouVGBIWODBDgRC7hGQJAwWRGAguSC7JICCyYXYJAQXWLyhICC94LKu8Gqk1gGD+AjQ//C6Ei2HS0AXQ/U2gEquFVC6Pyk8AlssmwXK3oGF+fi2Et0v2C4ONoAPFhsiwBfFhU0lvS2wXBsVUC4vSkwHF90Etlso0L6CSBkowEFwNgM5sImQwEFw4AJGAguQGAsQ6UvxAAQ2UloMYkQAU0MZmUjmYAQmUi+MRSowAM4UmiMRSowALhiKBC4MQGCIuBgAXCGCAuCgIXBiLGCFyQXCGAJINsToBC4cQgGMI50AIwYwCACAWEGAQAOFwowRCwwwPFw4wPCxAYNCxRJLCxYxKCxwyGORI"))

BIN
apps/pebbled/pebbled.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -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();
}
}
});
});

BIN
apps/pebbled/photo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

View File

@ -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.
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
annoying in an intentionally dark environment, so there is an option to disable it.
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
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
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

View File

@ -40,3 +40,4 @@
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.37: Going into passkey menu now saves settings with passkey
0.38: Restructed menus as per forum discussion

View File

@ -61,6 +61,37 @@ if (!settings) resetSettings();
const boolFormat = v => v ? /*LANG*/"On" : /*LANG*/"Off";
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;
if (BANGLEJS2) {
beepMenuItem = {
@ -91,12 +122,9 @@ function showMainMenu() {
};
}
const mainmenu = {
'': { 'title': 'Settings' },
'< Back': ()=>load(),
/*LANG*/'App Settings': ()=>showAppSettingsMenu(),
/*LANG*/'BLE': ()=>showBLEMenu(),
'': { 'title': 'Alerts' },
'< Back': ()=>showMainMenu(),
/*LANG*/'Beep': beepMenuItem,
/*LANG*/'Vibration': {
value: settings.vibrate,
@ -119,23 +147,18 @@ function showMainMenu() {
updateOptions();
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);
}
function showBLEMenu() {
var hidV = [false, "kbmedia", "kb", "joy"];
var hidN = ["Off", "Kbrd & Media", "Kbrd","Joystick"];
E.showMenu({
'': { 'title': 'Bluetooth' },
'< Back': ()=>showMainMenu(),
'Make Connectable': ()=>makeConnectable(),
'BLE': {
@ -190,7 +213,7 @@ function showThemeMenu() {
}
var m = E.showMenu({
'':{title:'Theme'},
'< Back': ()=>showMainMenu(),
'< Back': ()=>showSystemMenu(),
'Dark BW': ()=>{
upd({
fg:cl("#fff"), bg:cl("#000"),
@ -335,7 +358,7 @@ function showWhitelistMenu() {
function showLCDMenu() {
const lcdMenu = {
'': { 'title': 'LCD' },
'< Back': ()=>showMainMenu(),
'< Back': ()=>showSystemMenu(),
'LCD Brightness': {
value: settings.brightness,
min: 0.1,
@ -447,7 +470,7 @@ function showLCDMenu() {
function showLocaleMenu() {
const localemenu = {
'': { 'title': 'Locale' },
'< Back': ()=>showMainMenu(),
'< Back': ()=>showSystemMenu(),
'Time Zone': {
value: settings.timezone,
min: -11,
@ -551,7 +574,7 @@ function showClockMenu() {
'': {
'title': 'Select Clock',
},
'< Back': ()=>showMainMenu(),
'< Back': ()=>showSystemMenu(),
};
clockApps.forEach((app, index) => {
var label = app.name;
@ -578,7 +601,7 @@ function showSetTimeMenu() {
'': { 'title': 'Set Time' },
'< Back': function () {
setTime(d.getTime() / 1000);
showMainMenu();
showSystemMenu();
},
'Hour': {
value: d.getHours(),

View File

@ -1,3 +1,3 @@
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.

View File

@ -1,3 +1,4 @@
0.01: Initial import.
0.07: Add swipe to change screens.
1.06: Misc memory and screen optimisations.
1.10: ...

View File

@ -1 +1 @@
require("heatshrink").decompress(atob("AH4A/ACXd7vQC6vUpoBBDaQXEDaQXIDZwXMAIQZHC4R6BAAIZJDAwXIDY4XHAAodJ7oXMDpQXSAAiRHhoWN7zFLDY/e9ve9zeMhvQCIIBFC5ARIC5oVNC5EOCpwABC4vuCZYXPCIwXOCJAAFC5gAJ8AXFCpwuHgDjCFqQXC6lN6gbFf5gXEAInd6AXVDYndhoXKBoIbMC5QZLC44AFDpIXNDpQXdhoYMAAbwIC6oZQbxhOKC5gbKC6BUGC6oA/AHgA=="))
require("heatshrink").decompress(atob("mEw4UA///sH8ov+8GyJf4AIgt8BZV9voNIBYQNIBYgNGBYwMEBYNVqoMEoALGBoYLDBQILCAQVQBYoOEBZIABBYUAgILGsBiEBodWy2gN4soywACBYcI1QJDBYoJFBYkCBQ2qBYUKBIoLHBAQLHBAYACBYwAEwALBgwKG1S/DC4wWCa4Y3Efa19mALKvrLDfY7XGBwjvVBYjuHfYgLLBg4LEAAMVBZQNEBZBPCBZQA+A"))

View File

@ -293,9 +293,9 @@ Bangle.on('swipe', dir => {
else next();
});
// close launcher when lcd is off
Bangle.on('lcdPower', on => {
if(!on) return load();
// close launcher when screen is locked
Bangle.on('lock', on => {
if(on) return load();
});
if (process.env.HWVERSION == 1) {

View File

@ -0,0 +1,3 @@
0.01: New watch face
0.02: Use Bangle.setUI for button/launcher handling
0.03: Bangle.js 2 support

View File

@ -1,3 +0,0 @@
0.1: New watch face
0.2: Use Bangle.setUI for button/launcher handling
0.3: Bangle.js 2 support

View File

@ -3,6 +3,7 @@
*/
var fs = require("fs");
var heatshrink = require("../core/lib/heatshrink");
var acorn;
try {
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 FORBIDDEN_FILE_NAME_CHARS = /[,;]/; // used as separators in appid.info
const VALID_DUPLICATES = [ '.tfmodel', '.tfnames' ];
const GRANDFATHERED_ICONS = ["hebrew_calendar", "fontclock", "slidingtext", "solarclock", "sweepclock", "matrixclock", "speedo", "s7clk", "mmonday", "bclock", "snek", "dane", "fclock", "digiclock", "astral", "alpinenav", "slomoclock", "tapelauncher", "arrow", "doztime", "swiperclocklaunch", "pebble", "rebble"];
function globToRegex(pattern) {
const ESCAPE = '.*+-?^${}()|[]\\';
@ -175,6 +177,23 @@ apps.forEach((app,appIdx) => {
for (const key in file) {
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[1] != 48) {
if (GRANDFATHERED_ICONS.includes(app.id)) WARN(`JS icon ${file.name} should be 48x48px but is instead ${icon[0]}x${icon[1]}px`);
else ERROR(`JS icon ${file.name} should be 48x48px but is instead ${icon[0]}x${icon[1]}px`);
}
}
}
});
let dataNames = [];
(app.data||[]).forEach((data)=>{

2
core

@ -1 +1 @@
Subproject commit b033af017f6789a6a7777e6ef1428d94995a9b8b
Subproject commit 2a8e872ecb143a10e53273b4d3473164e104e1d3