Merge branch 'espruino:master' into master
|
|
@ -18,3 +18,4 @@
|
||||||
0.16: Correct date for all day events in negative timezones, improve locale display
|
0.16: Correct date for all day events in negative timezones, improve locale display
|
||||||
0.17: Fixed "Today" and "Tomorrow" labels displaying in non-current weeks
|
0.17: Fixed "Today" and "Tomorrow" labels displaying in non-current weeks
|
||||||
0.18: Correct date in clockinfo for all-day events in negative timezones
|
0.18: Correct date in clockinfo for all-day events in negative timezones
|
||||||
|
0.19: Change clockinfo title truncation to preserve images
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@
|
||||||
|
|
||||||
agenda.forEach((entry, i) => {
|
agenda.forEach((entry, i) => {
|
||||||
|
|
||||||
var title = entry.title.slice(0,12);
|
var title = g.setFont("6x8").wrapString(entry.title,100)[0];
|
||||||
// All day events are always in UTC and always start at 00:00:00, so we
|
// All day events are always in UTC and always start at 00:00:00, so we
|
||||||
// need to "undo" the timezone offsetting to make sure that the day is
|
// need to "undo" the timezone offsetting to make sure that the day is
|
||||||
// correct.
|
// correct.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "agenda",
|
"id": "agenda",
|
||||||
"name": "Agenda",
|
"name": "Agenda",
|
||||||
"version": "0.18",
|
"version": "0.19",
|
||||||
"description": "Simple agenda",
|
"description": "Simple agenda",
|
||||||
"icon": "agenda.png",
|
"icon": "agenda.png",
|
||||||
"screenshots": [{"url":"screenshot_agenda_overview.png"}, {"url":"screenshot_agenda_event1.png"}, {"url":"screenshot_agenda_event2.png"}],
|
"screenshots": [{"url":"screenshot_agenda_overview.png"}, {"url":"screenshot_agenda_event1.png"}, {"url":"screenshot_agenda_event2.png"}],
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,4 @@
|
||||||
0.02: Actually upload correct code
|
0.02: Actually upload correct code
|
||||||
0.03: Display sea-level pressure, too, and allow calibration
|
0.03: Display sea-level pressure, too, and allow calibration
|
||||||
0.04: Switch to using system code for pressure calibration
|
0.04: Switch to using system code for pressure calibration
|
||||||
|
0.05: Prompt before resetting calibration (stops long-press of button resetting calibration)
|
||||||
|
|
@ -7,6 +7,7 @@ var R = Bangle.appRect;
|
||||||
var y = R.y + R.h/2;
|
var y = R.y + R.h/2;
|
||||||
var MEDIANLENGTH = 20;
|
var MEDIANLENGTH = 20;
|
||||||
var avr = [];
|
var avr = [];
|
||||||
|
var updateDisplay = true;
|
||||||
|
|
||||||
function fmt(t) {
|
function fmt(t) {
|
||||||
if ((t > -100) && (t < 1000))
|
if ((t > -100) && (t < 1000))
|
||||||
|
|
@ -19,48 +20,57 @@ function fmt(t) {
|
||||||
Bangle.on('pressure', function(e) {
|
Bangle.on('pressure', function(e) {
|
||||||
while (avr.length>MEDIANLENGTH) avr.pop();
|
while (avr.length>MEDIANLENGTH) avr.pop();
|
||||||
avr.unshift(e.altitude);
|
avr.unshift(e.altitude);
|
||||||
let median = avr.slice().sort();
|
if (!updateDisplay) return;
|
||||||
|
let median = avr.slice().sort(), value;
|
||||||
g.reset().clearRect(0,y-30,g.getWidth()-10,R.h);
|
g.reset().clearRect(0,y-30,g.getWidth()-10,R.h);
|
||||||
if (median.length>10) {
|
if (median.length>10) {
|
||||||
var mid = median.length>>1;
|
var mid = median.length>>1;
|
||||||
var value = E.sum(median.slice(mid-4,mid+5)) / 9;
|
value = E.sum(median.slice(mid-4,mid+5)) / 9;
|
||||||
} else {
|
} else {
|
||||||
var value = median[median.length>>1];
|
value = median[median.length>>1];
|
||||||
}
|
}
|
||||||
t = fmt(value);
|
var t = fmt(value);
|
||||||
|
|
||||||
g.setFont("Vector",50).setFontAlign(0,0).drawString(t, g.getWidth()/2, y);
|
g.setFont("Vector",50).setFontAlign(0,0).drawString(t, g.getWidth()/2, y);
|
||||||
|
|
||||||
let o = Bangle.getOptions();
|
let o = Bangle.getOptions();
|
||||||
let sea = o.seaLevelPressure;
|
let sea = o.seaLevelPressure;
|
||||||
t = sea.toFixed(1) + " " + e.temperature.toFixed(1);
|
t = sea.toFixed(1) + " " + e.temperature.toFixed(1);
|
||||||
if (0) {
|
/*if (0) {
|
||||||
print("alt raw:", value.toFixed(1));
|
print("alt raw:", value.toFixed(1));
|
||||||
print("temperature:", e.temperature);
|
print("temperature:", e.temperature);
|
||||||
print("pressure:", e.pressure);
|
print("pressure:", e.pressure);
|
||||||
print("sea pressure:", sea);
|
print("sea pressure:", sea);
|
||||||
}
|
}*/
|
||||||
g.setFont("Vector",25).setFontAlign(-1,0).drawString(t, 10, R.y+R.h - 35);
|
g.setFont("Vector",25).setFontAlign(-1,0).drawString(t, 10, R.y+R.h - 35);
|
||||||
});
|
});
|
||||||
|
|
||||||
function setPressure(m, a) {
|
function setPressure(m, a) {
|
||||||
o = Bangle.getOptions();
|
var o = Bangle.getOptions();
|
||||||
print(o);
|
//print(o);
|
||||||
o.seaLevelPressure = o.seaLevelPressure * m + a;
|
o.seaLevelPressure = o.seaLevelPressure * m + a;
|
||||||
Bangle.setOptions(o);
|
Bangle.setOptions(o);
|
||||||
avr = [];
|
avr = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
print(g.getFonts());
|
function start() {
|
||||||
g.reset();
|
g.reset();
|
||||||
g.setFont("Vector:15");
|
g.setFont("Vector:15");
|
||||||
g.setFontAlign(0,0);
|
g.setFontAlign(0,0);
|
||||||
g.drawString(/*LANG*/"ALTITUDE (m)", g.getWidth()/2, y-40);
|
g.drawString(/*LANG*/"ALTITUDE (m)", g.getWidth()/2, y-40);
|
||||||
g.drawString(/*LANG*/"SEA L (hPa) TEMP (C)", g.getWidth()/2, y+62);
|
g.drawString(/*LANG*/"SEA L (hPa) TEMP (C)", g.getWidth()/2, y+62);
|
||||||
g.flip();
|
g.setFont("6x8").setFontAlign(0,0,3).drawString(/*LANG*/"STD", g.getWidth()-5, g.getHeight()/2);
|
||||||
g.setFont("6x8").setFontAlign(0,0,3).drawString(/*LANG*/"STD", g.getWidth()-5, g.getHeight()/2);
|
updateDisplay = true;
|
||||||
Bangle.setUI("updown", btn=> {
|
Bangle.setUI("updown", btn => {
|
||||||
if (!btn) setPressure(0, 1013.25);
|
if (!btn) {
|
||||||
if (btn<0) setPressure(1, 1);
|
updateDisplay = false;
|
||||||
if (btn>0) setPressure(1, -1);
|
E.showPrompt(/*LANG*/"Set calibration to default?",{title:/*LANG*/"Altitude"}).then(function(reset) {
|
||||||
});
|
start();
|
||||||
|
if (reset) setPressure(0, 1013.25);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (btn<0) setPressure(1, 1);
|
||||||
|
if (btn>0) setPressure(1, -1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
start();
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{ "id": "altimeter",
|
{ "id": "altimeter",
|
||||||
"name": "Altimeter",
|
"name": "Altimeter",
|
||||||
"version":"0.04",
|
"version":"0.05",
|
||||||
"description": "Simple altimeter that can display height changed using Bangle.js 2's built in pressure sensor.",
|
"description": "Simple altimeter that can display height changed using Bangle.js 2's built in pressure sensor.",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"tags": "tool,outdoors",
|
"tags": "tool,outdoors",
|
||||||
|
|
|
||||||
|
|
@ -75,4 +75,5 @@
|
||||||
0.64: Automatically create .widcache and .clkinfocache to speed up loads
|
0.64: Automatically create .widcache and .clkinfocache to speed up loads
|
||||||
Bangle.loadWidgets overwritten with fast version on success
|
Bangle.loadWidgets overwritten with fast version on success
|
||||||
Refuse to work on firmware <2v16 and remove old polyfills
|
Refuse to work on firmware <2v16 and remove old polyfills
|
||||||
0.65: Only display interpreter errors if log is nonzero
|
0.65: Only display interpreter errors if log is nonzero
|
||||||
|
0.66: Ensure __FILE__ is set even after a fresh boot (fix #3857)
|
||||||
|
|
@ -23,7 +23,8 @@ if (!_clkApp) {
|
||||||
require("Storage").writeJSON("setting.json", s);
|
require("Storage").writeJSON("setting.json", s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (s.clock) __FILE__=s.clock;
|
||||||
delete s;
|
delete s;
|
||||||
if (!_clkApp) _clkApp=`E.showMessage("No Clock Found");setWatch(()=>{Bangle.showLauncher();}, global.BTN2||BTN, {repeat:false,edge:"falling"});`;
|
if (!_clkApp) _clkApp=`E.showMessage("No Clock Found");setWatch(()=>{Bangle.showLauncher();}, global.BTN2||BTN, {repeat:false,edge:"falling"});`;
|
||||||
eval(_clkApp);
|
eval(_clkApp);
|
||||||
delete _clkApp;
|
delete _clkApp;
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "boot",
|
"id": "boot",
|
||||||
"name": "Bootloader",
|
"name": "Bootloader",
|
||||||
"version": "0.65",
|
"version": "0.66",
|
||||||
"description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings",
|
"description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings",
|
||||||
"icon": "bootloader.png",
|
"icon": "bootloader.png",
|
||||||
"type": "bootloader",
|
"type": "bootloader",
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
0.01: New App!
|
0.01: New App!
|
||||||
0.02: Bangle.js 2 compatibility
|
0.02: Bangle.js 2 compatibility
|
||||||
|
0.03: Add settings menu for showing time and battery percent with animation.
|
||||||
|
|
|
||||||
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
|
@ -1,8 +1,19 @@
|
||||||
|
|
||||||
|
var settings = Object.assign({
|
||||||
|
// default values
|
||||||
|
showBatPercent: true,
|
||||||
|
showTime: true,
|
||||||
|
|
||||||
|
|
||||||
|
}, require("Storage").readJSON("chargeAnimSettings.json", true) || {});
|
||||||
|
|
||||||
|
|
||||||
g.setBgColor(0, 0, 0);
|
g.setBgColor(0, 0, 0);
|
||||||
g.clear().flip();
|
g.clear().flip();
|
||||||
var imgbat = require("heatshrink").decompress(atob("nFYhBC/AH4A/AGUeACA22HEo3/G8YrTAC422HBQ2tHBI3/G/43/G/43/G/43/G/43/G/43/G+fTG+vSN+w326Q31GwI3/G9g2WG742CG/43rGwY3yGwg33RKo3bNzQ3bGwo3/G9A2GG942dG/43QGw43uGxA34IKw3VGyY3iG0I3pb8pBRG+wYPG8wYQG/42uG8oZSG/43bDKY3iDKg3cNzI3iRKo3gGyo3/G7A2WG7g2aG/43WGzA3dGzI3/G6fTGzRvcG/43/G/43/G/43/G/43/G/43/G/437HFw2IHFo2KAH4A/AH4Aa"));
|
var imgbat = require("heatshrink").decompress(atob("nFYhBC/AH4A/AGUeACA22HEo3/G8YrTAC422HBQ2tHBI3/G/43/G/43/G/43/G/43/G/43/G+fTG+vSN+w326Q31GwI3/G9g2WG742CG/43rGwY3yGwg33RKo3bNzQ3bGwo3/G9A2GG942dG/43QGw43uGxA34IKw3VGyY3iG0I3pb8pBRG+wYPG8wYQG/42uG8oZSG/43bDKY3iDKg3cNzI3iRKo3gGyo3/G7A2WG7g2aG/43WGzA3dGzI3/G6fTGzRvcG/43/G/43/G/43/G/43/G/43/G/437HFw2IHFo2KAH4A/AH4Aa"));
|
||||||
var imgbubble = require("heatshrink").decompress(atob("i0UhAebgoAFCaYXNBocjAAIWNCYoVHCw4UFIZwqELJQWFKZQVOChYVzABwVaCx7wKCqIWNCg4WMChIXJCZgAnA=="));
|
var imgbubble = require("heatshrink").decompress(atob("i0UhAebgoAFCaYXNBocjAAIWNCYoVHCw4UFIZwqELJQWFKZQVOChYVzABwVaCx7wKCqIWNCg4WMChIXJCZgAnA=="));
|
||||||
|
require("Font8x12").add(Graphics);
|
||||||
|
var batteryPercentStr="";
|
||||||
var W=g.getWidth(),H=g.getHeight();
|
var W=g.getWidth(),H=g.getHeight();
|
||||||
var b2v = (W != 240)?-1:1;
|
var b2v = (W != 240)?-1:1;
|
||||||
var b2rot = (W != 240)?Math.PI:0;
|
var b2rot = (W != 240)?Math.PI:0;
|
||||||
|
|
@ -12,11 +23,50 @@ for (var i=0;i<10;i++) {
|
||||||
bubbles.push({y:Math.random()*H,ly:0,x:(0.5+(i<5?i:i+8))*W/18,v:0.6+Math.random(),s:0.5+Math.random()});
|
bubbles.push({y:Math.random()*H,ly:0,x:(0.5+(i<5?i:i+8))*W/18,v:0.6+Math.random(),s:0.5+Math.random()});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g.setFont("Vector",22);
|
||||||
|
g.setFontAlign(0,0);
|
||||||
|
|
||||||
|
var clockStr="";
|
||||||
|
var x=g.getWidth()/2;
|
||||||
|
var cy=g.getHeight()-(g.getHeight()/7)
|
||||||
|
var by=g.getHeight()-(g.getHeight()/3.500)
|
||||||
|
|
||||||
|
|
||||||
|
function calculateTime(){
|
||||||
|
|
||||||
|
var d=new Date();
|
||||||
|
clockStr = require("locale").time(d, 1); // Hour and minute
|
||||||
|
var meridian=require("locale").meridian(d);
|
||||||
|
if(meridian!=""){
|
||||||
|
//Meridian active
|
||||||
|
clockStr=clockStr+" "+meridian;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
function calculate(){
|
||||||
|
if(settings.showTime==true){
|
||||||
|
calculateTime();
|
||||||
|
}
|
||||||
|
if(settings.showBatPercent==true){
|
||||||
|
batteryPercentStr=E.getBattery()+"%";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function anim() {
|
function anim() {
|
||||||
/* we don't use any kind of buffering here. Just draw one image
|
/* we don't use any kind of buffering here. Just draw one image
|
||||||
at a time (image contains a background) too, and there is minimal
|
at a time (image contains a background) too, and there is minimal
|
||||||
flicker. */
|
flicker. */
|
||||||
var mx = W/2.0, my = H/2.0;
|
var mx = W/2.0;
|
||||||
|
var my;
|
||||||
|
if(settings.showBatPercent){
|
||||||
|
var my = H/2.5;
|
||||||
|
}else{
|
||||||
|
var my = H/2.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bubbles.forEach(f=>{
|
bubbles.forEach(f=>{
|
||||||
f.y-=f.v * b2v;
|
f.y-=f.v * b2v;
|
||||||
if (f.y<-24)
|
if (f.y<-24)
|
||||||
|
|
@ -26,10 +76,25 @@ function anim() {
|
||||||
g.drawImage(imgbubble,f.y,f.x,{scale:f.s * b2scale, rotate:b2rot});
|
g.drawImage(imgbubble,f.y,f.x,{scale:f.s * b2scale, rotate:b2rot});
|
||||||
});
|
});
|
||||||
g.drawImage(imgbat, mx,my,{scale:b2scale, rotate:Math.sin(getTime()*2)*0.5-Math.PI/2 + b2rot});
|
g.drawImage(imgbat, mx,my,{scale:b2scale, rotate:Math.sin(getTime()*2)*0.5-Math.PI/2 + b2rot});
|
||||||
|
if(settings.showTime==true){
|
||||||
|
g.drawString(clockStr,x,cy);
|
||||||
|
}
|
||||||
|
if(settings.showBatPercent==true){
|
||||||
|
g.drawString(batteryPercentStr,x,by,true);
|
||||||
|
}
|
||||||
g.flip();
|
g.flip();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(settings.showBatPercent||settings.showTime){
|
||||||
|
//Eliminate unnesccesary need for calculation
|
||||||
|
calculate();
|
||||||
|
setInterval(calculate,20000);
|
||||||
}
|
}
|
||||||
|
|
||||||
setInterval(anim,20);
|
setInterval(anim,22);
|
||||||
|
|
||||||
|
|
||||||
Bangle.on("charging", isCharging => {
|
Bangle.on("charging", isCharging => {
|
||||||
if (!isCharging) load();
|
if (!isCharging) load();
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
|
@ -1,16 +1,21 @@
|
||||||
{
|
{
|
||||||
"id": "chargeanim",
|
"id": "chargeanim",
|
||||||
"name": "Charge Animation",
|
"name": "Charge Animation",
|
||||||
"version": "0.02",
|
"version": "0.03",
|
||||||
"description": "When charging, show a sideways charging animation and keep the screen on. When removed from the charger load the clock again.",
|
"description": "When charging, show a sideways charging animation and optionally, show time, or show battery percentage. When removed from the charger, clock loads again.",
|
||||||
"icon": "icon.png",
|
"icon": "icon.png",
|
||||||
"tags": "battery",
|
"tags": "battery",
|
||||||
"supports": ["BANGLEJS", "BANGLEJS2"],
|
"supports": ["BANGLEJS", "BANGLEJS2"],
|
||||||
"allow_emulator": true,
|
"allow_emulator": true,
|
||||||
"screenshots": [{"url":"bangle2-charge-animation-screenshot.png"},{"url":"bangle-charge-animation-screenshot.png"}],
|
"screenshots": [
|
||||||
|
{"url":"Screenshot1.png"},
|
||||||
|
{"url":"Screenshot2.png"},
|
||||||
|
{"url":"Screenshot3.png"}],
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"chargeanim.app.js","url":"app.js"},
|
{"name":"chargeanim.app.js","url":"app.js"},
|
||||||
{"name":"chargeanim.boot.js","url":"boot.js"},
|
{"name":"chargeanim.boot.js","url":"boot.js"},
|
||||||
|
{"name":"chargeanim.settings.js","url":"settings.js"},
|
||||||
{"name":"chargeanim.img","url":"app-icon.js","evaluate":true}
|
{"name":"chargeanim.img","url":"app-icon.js","evaluate":true}
|
||||||
]
|
],
|
||||||
|
"data": [{"name":"chargeAnimSettings.json"}]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
(function(back) {
|
||||||
|
var FILE = "chargeAnimSettings.json";
|
||||||
|
// Load settings
|
||||||
|
|
||||||
|
var settings = Object.assign({
|
||||||
|
// default values
|
||||||
|
showBatPercent: true,
|
||||||
|
showTime: true,
|
||||||
|
|
||||||
|
|
||||||
|
}, require('Storage').readJSON(FILE, true) || {});
|
||||||
|
|
||||||
|
function writeSettings() {
|
||||||
|
require('Storage').writeJSON(FILE, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show the menu
|
||||||
|
E.showMenu({
|
||||||
|
"" : { "title" : "Charge Animation" },
|
||||||
|
"< Back" : () => back(),
|
||||||
|
'Show Percent Charged': {
|
||||||
|
value: !!settings.showBatPercent, // !! converts undefined to false
|
||||||
|
onchange: v => {
|
||||||
|
settings.showBatPercent = v;
|
||||||
|
writeSettings();
|
||||||
|
}
|
||||||
|
// format: ... may be specified as a function which converts the value to a string
|
||||||
|
// if the value is a boolean, showMenu() will convert this automatically, which
|
||||||
|
// keeps settings menus consistent
|
||||||
|
},
|
||||||
|
'Show Time': {
|
||||||
|
value: !!settings.showTime, // !! converts undefined to false
|
||||||
|
onchange: v => {
|
||||||
|
settings.showTime = v;
|
||||||
|
writeSettings();
|
||||||
|
}
|
||||||
|
// format: ... may be specified as a function which converts the value to a string
|
||||||
|
// if the value is a boolean, showMenu() will convert this automatically, which
|
||||||
|
// keeps settings menus consistent
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
@ -15,3 +15,4 @@
|
||||||
0.14: Check for .clkinfocache and use that if exists (from boot 0.64)
|
0.14: Check for .clkinfocache and use that if exists (from boot 0.64)
|
||||||
0.15: Fix error when displaying a category with only one clockinfo (fix #3728)
|
0.15: Fix error when displaying a category with only one clockinfo (fix #3728)
|
||||||
0.16: Add BLE clkinfo entry
|
0.16: Add BLE clkinfo entry
|
||||||
|
0.17: Fix BLE icon alignment and border on some clocks
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ exports.load = function() {
|
||||||
get: function() {
|
get: function() {
|
||||||
return {
|
return {
|
||||||
text: this.isOn() ? "On" : "Off",
|
text: this.isOn() ? "On" : "Off",
|
||||||
img: atob("CxQBBgDgFgJgR4jZMawfAcA4D4NYybEYIwTAsBwDAA==")
|
img: atob("GBiBAAAAAAAAAAAYAAAcAAAWAAATAAARgAMRgAGTAADWAAB8AAA4AAA4AAB8AADWAAGTAAMRgAARgAATAAAWAAAcAAAYAAAAAAAAAA==")
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
run: function() {
|
run: function() {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{ "id": "clock_info",
|
{ "id": "clock_info",
|
||||||
"name": "Clock Info Module",
|
"name": "Clock Info Module",
|
||||||
"shortName": "Clock Info",
|
"shortName": "Clock Info",
|
||||||
"version":"0.16",
|
"version":"0.17",
|
||||||
"description": "A library used by clocks to provide extra information on the clock face (Altitude, BPM, etc)",
|
"description": "A library used by clocks to provide extra information on the clock face (Altitude, BPM, etc)",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,8 @@ Unless otherwise stated, this project is released under the MIT license.
|
||||||
Use of the patented method may be subject to licensing or permission.
|
Use of the patented method may be subject to licensing or permission.
|
||||||
For inquiries, contact the author.
|
For inquiries, contact the author.
|
||||||
|
|
||||||
|
Note: The patented method does not require licensing for non-commercial, research, educational, or personal use within the open-source community. Commercial or broad distribution beyond these uses may require permission or licensing. For such use cases, please contact the author.
|
||||||
|
|
||||||
### **Summary**
|
### **Summary**
|
||||||
|
|
||||||
The Circadian Rhythm Clock transforms the Bangle.js 2 into a **bio-aware, personalized circadian dashboard**, guiding users toward better alignment with their biological clock and modern life.
|
The Circadian Rhythm Clock transforms the Bangle.js 2 into a **bio-aware, personalized circadian dashboard**, guiding users toward better alignment with their biological clock and modern life.
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ const STATS_FONT_SIZE = 16;
|
||||||
function getSleepWindowStr() {
|
function getSleepWindowStr() {
|
||||||
let a = ("0"+S.sleepStart).substr(-2) + ":00";
|
let a = ("0"+S.sleepStart).substr(-2) + ":00";
|
||||||
let b = ("0"+S.sleepEnd).substr(-2) + ":00";
|
let b = ("0"+S.sleepEnd).substr(-2) + ":00";
|
||||||
return a + "–" + b;
|
return a + "-" + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
function stability(arr, key, hours) {
|
function stability(arr, key, hours) {
|
||||||
|
|
@ -518,7 +518,7 @@ function confirmResetAllData() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Menu logic: Sleep window, hydration, BT calibration, theme, notifications, bio ref, about — unchanged, use as before
|
// Menu logic: Sleep window, hydration, BT calibration, theme, notifications, bio ref, about - unchanged, use as before
|
||||||
|
|
||||||
function setSleepWindow() {
|
function setSleepWindow() {
|
||||||
let menu = { "": { title: "Select Start Hour" } };
|
let menu = { "": { title: "Select Start Hour" } };
|
||||||
|
|
@ -610,7 +610,7 @@ function calibrateBT() {
|
||||||
Bangle.setUI(uiOpts);
|
Bangle.setUI(uiOpts);
|
||||||
});
|
});
|
||||||
})(d);
|
})(d);
|
||||||
m["−" + d + "h"] = (() => () => {
|
m["-" + d + "h"] = (() => () => {
|
||||||
S.phaseOffset -= d;
|
S.phaseOffset -= d;
|
||||||
saveSettings();
|
saveSettings();
|
||||||
E.showAlert("Offset now: " + (S.phaseOffset>=0? "+"+S.phaseOffset : S.phaseOffset) + "h").then(() => {
|
E.showAlert("Offset now: " + (S.phaseOffset>=0? "+"+S.phaseOffset : S.phaseOffset) + "h").then(() => {
|
||||||
|
|
@ -711,7 +711,7 @@ function setBioTimeReference() {
|
||||||
E.showMenu(m);
|
E.showMenu(m);
|
||||||
|
|
||||||
function promptRefTime() {
|
function promptRefTime() {
|
||||||
E.showPrompt("Hour (0–23)?").then(h => {
|
E.showPrompt("Hour (0-23)?").then(h => {
|
||||||
if (h===undefined || h<0 || h>23) {
|
if (h===undefined || h<0 || h>23) {
|
||||||
E.showAlert("Invalid hour").then(() => {
|
E.showAlert("Invalid hour").then(() => {
|
||||||
drawClock();
|
drawClock();
|
||||||
|
|
@ -720,7 +720,7 @@ function setBioTimeReference() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
S.bioTimeRefHour = h;
|
S.bioTimeRefHour = h;
|
||||||
E.showPrompt("Minute (0–59)?").then(m => {
|
E.showPrompt("Minute (0-59)?").then(m => {
|
||||||
if (m===undefined || m<0 || m>59) {
|
if (m===undefined || m<0 || m>59) {
|
||||||
E.showAlert("Invalid minute").then(() => {
|
E.showAlert("Invalid minute").then(() => {
|
||||||
drawClock();
|
drawClock();
|
||||||
|
|
@ -743,7 +743,7 @@ function showAbout() {
|
||||||
E.showAlert(
|
E.showAlert(
|
||||||
"Circadian Wellness Clock v" + VERSION + "\n" +
|
"Circadian Wellness Clock v" + VERSION + "\n" +
|
||||||
"Displays your CRS and BioTime.\n" +
|
"Displays your CRS and BioTime.\n" +
|
||||||
"© 2025"
|
"Copyright 2025"
|
||||||
).then(()=>{
|
).then(()=>{
|
||||||
drawClock();
|
drawClock();
|
||||||
Bangle.setUI(uiOpts);
|
Bangle.setUI(uiOpts);
|
||||||
|
|
|
||||||
|
|
@ -16,4 +16,5 @@
|
||||||
0.15: Enable calendar and weather updates via custom notifications (via shortcuts app)
|
0.15: Enable calendar and weather updates via custom notifications (via shortcuts app)
|
||||||
0.16: Always request Current Time service from iOS
|
0.16: Always request Current Time service from iOS
|
||||||
0.17: Default to passing full UTF8 strings into messages app (which can now process them with an international font)
|
0.17: Default to passing full UTF8 strings into messages app (which can now process them with an international font)
|
||||||
0.18: Fix UTF8 conversion (check for `font` library, not `fonts`)
|
0.18: Fix UTF8 conversion (check for `font` library, not `fonts`)
|
||||||
|
0.19: Convert numeric weather values to int from BangleDumpWeather shortcut
|
||||||
|
|
@ -191,6 +191,11 @@ E.on('notify',msg=>{
|
||||||
wdir: d.wdir,
|
wdir: d.wdir,
|
||||||
loc: d.loc
|
loc: d.loc
|
||||||
}
|
}
|
||||||
|
// Convert string fields to numbers for iOS weather shortcut
|
||||||
|
const numFields = ['code', 'wdir', 'temp', 'hi', 'lo', 'hum', 'wind', 'uv', 'rain'];
|
||||||
|
numFields.forEach(field => {
|
||||||
|
if (weatherEvent[field] != null) weatherEvent[field] = +weatherEvent[field];
|
||||||
|
});
|
||||||
require("weather").update(weatherEvent);
|
require("weather").update(weatherEvent);
|
||||||
NRF.ancsAction(msg.uid, false);
|
NRF.ancsAction(msg.uid, false);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "ios",
|
"id": "ios",
|
||||||
"name": "iOS Integration",
|
"name": "iOS Integration",
|
||||||
"version": "0.18",
|
"version": "0.19",
|
||||||
"description": "Display notifications/music/etc from iOS devices",
|
"description": "Display notifications/music/etc from iOS devices",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"tags": "tool,system,ios,apple,messages,notifications",
|
"tags": "tool,system,ios,apple,messages,notifications",
|
||||||
|
|
|
||||||
|
|
@ -925,12 +925,6 @@ module.exports = {
|
||||||
"no-undef"
|
"no-undef"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"apps/fileman/fileman.app.js": {
|
|
||||||
"hash": "f378179e7dd3655ba7e9ce03e1f7fd5a2d1768ad7d9083b22e7d740405be842a",
|
|
||||||
"rules": [
|
|
||||||
"no-undef"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"apps/flappy/app.js": {
|
"apps/flappy/app.js": {
|
||||||
"hash": "e24b0c5e0469070e02dae00887bf50569c2c141a80c7c356b36987ddf68ce9cc",
|
"hash": "e24b0c5e0469070e02dae00887bf50569c2c141a80c7c356b36987ddf68ce9cc",
|
||||||
"rules": [
|
"rules": [
|
||||||
|
|
@ -1051,12 +1045,6 @@ module.exports = {
|
||||||
"no-undef"
|
"no-undef"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"apps/altimeter/app.js": {
|
|
||||||
"hash": "054ac328db51034aa339f1d10b4d264badd49438b95f08bc6fbfb90bd88c6ae0",
|
|
||||||
"rules": [
|
|
||||||
"no-undef"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"apps/alpinenav/app.js": {
|
"apps/alpinenav/app.js": {
|
||||||
"hash": "f8e59724d282f7c5c989adf64974a3728dc521aa8fbe047b7c37dae09213095a",
|
"hash": "f8e59724d282f7c5c989adf64974a3728dc521aa8fbe047b7c37dae09213095a",
|
||||||
"rules": [
|
"rules": [
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,5 @@
|
||||||
0.05: Add message icon for 'jira'
|
0.05: Add message icon for 'jira'
|
||||||
0.06: Add message icon for 'molly' and 'threema libre'
|
0.06: Add message icon for 'molly' and 'threema libre'
|
||||||
0.07: Minor code improvements
|
0.07: Minor code improvements
|
||||||
0.08: Add more icons including GMail, Google Messages, Google Agenda
|
0.08: Add more icons including GMail, Google Messages, Google Agenda
|
||||||
|
0.09: Add Bereal, Nextcloud, Thunderbird, Davx⁵, Kleinanzeigen, Element X
|
||||||
|
|
|
||||||
|
After Width: | Height: | Size: 184 B |
|
|
@ -102,6 +102,7 @@ exports.getColor = function(msg,options) {
|
||||||
*/""}
|
*/""}
|
||||||
"bibel": "#54342c",
|
"bibel": "#54342c",
|
||||||
"bring": "#455a64",
|
"bring": "#455a64",
|
||||||
|
"davx⁵": "#8bc34a",
|
||||||
"discord": "#5865f2", // https://discord.com/branding
|
"discord": "#5865f2", // https://discord.com/branding
|
||||||
"etar": "#36a18b",
|
"etar": "#36a18b",
|
||||||
"facebook": "#1877f2", // https://www.facebook.com/brand/resources/facebookapp/logo
|
"facebook": "#1877f2", // https://www.facebook.com/brand/resources/facebookapp/logo
|
||||||
|
|
@ -111,7 +112,8 @@ exports.getColor = function(msg,options) {
|
||||||
"google home": "#fbbc05",
|
"google home": "#fbbc05",
|
||||||
// "home assistant": "#41bdf5", // ha-blue is #41bdf5, but that's the background
|
// "home assistant": "#41bdf5", // ha-blue is #41bdf5, but that's the background
|
||||||
"instagram": "#ff0069", // https://about.instagram.com/brand/gradient
|
"instagram": "#ff0069", // https://about.instagram.com/brand/gradient
|
||||||
"jira": "#0052cc", //https://atlassian.design/resources/logo-library
|
"jira": "#0052cc", // https://atlassian.design/resources/logo-library
|
||||||
|
"kleinanzeigen": "#69bd2f", // https://themen.kleinanzeigen.de/medien/mediathek/kleinanzeigen-guideline-nutzung-logo/
|
||||||
"leboncoin": "#fa7321",
|
"leboncoin": "#fa7321",
|
||||||
"lieferando": "#ff8000",
|
"lieferando": "#ff8000",
|
||||||
"linkedin": "#0a66c2", // https://brand.linkedin.com/
|
"linkedin": "#0a66c2", // https://brand.linkedin.com/
|
||||||
|
|
@ -121,6 +123,7 @@ exports.getColor = function(msg,options) {
|
||||||
"mattermost": "#00f",
|
"mattermost": "#00f",
|
||||||
"n26": "#36a18b",
|
"n26": "#36a18b",
|
||||||
"nextbike": "#00f",
|
"nextbike": "#00f",
|
||||||
|
"nextcloud": "#0082c9", // https://nextcloud.com/brand/
|
||||||
"newpipe": "#f00",
|
"newpipe": "#f00",
|
||||||
"nina": "#e57004",
|
"nina": "#e57004",
|
||||||
"opentasks": "#409f8f",
|
"opentasks": "#409f8f",
|
||||||
|
|
@ -137,6 +140,7 @@ exports.getColor = function(msg,options) {
|
||||||
"teams": "#6264a7", // https://developer.microsoft.com/en-us/fluentui#/styles/web/colors/products
|
"teams": "#6264a7", // https://developer.microsoft.com/en-us/fluentui#/styles/web/colors/products
|
||||||
"telegram": "#0088cc",
|
"telegram": "#0088cc",
|
||||||
"telegram foss": "#0088cc",
|
"telegram foss": "#0088cc",
|
||||||
|
"thunderbird": "#1582e4",
|
||||||
"to do": "#3999e5",
|
"to do": "#3999e5",
|
||||||
"twitch": "#9146ff", // https://brand.twitch.tv/
|
"twitch": "#9146ff", // https://brand.twitch.tv/
|
||||||
"twitter": "#1d9bf0", // https://about.twitter.com/en/who-we-are/brand-toolkit
|
"twitter": "#1d9bf0", // https://about.twitter.com/en/who-we-are/brand-toolkit
|
||||||
|
|
|
||||||
|
|
@ -3,38 +3,41 @@
|
||||||
{ "app":"airbnb", "icon":"airbnb.png" },
|
{ "app":"airbnb", "icon":"airbnb.png" },
|
||||||
{ "app":"agenda", "icon":"agenda.png" },
|
{ "app":"agenda", "icon":"agenda.png" },
|
||||||
{ "app":"alarm", "icon":"alarm.png" },
|
{ "app":"alarm", "icon":"alarm.png" },
|
||||||
{ "app":"alarmclockreceiver", "icon":"alarm.png" },
|
{ "app":"alarmclockreceiver", "icon":"alarm.png" },
|
||||||
{ "app":"amazon shopping", "icon":"amazon.png" },
|
{ "app":"amazon shopping", "icon":"amazon.png" },
|
||||||
|
{ "app":"bereal.", "icon":"bereal.png" },
|
||||||
{ "app":"bibel", "icon":"bibel.png" },
|
{ "app":"bibel", "icon":"bibel.png" },
|
||||||
{ "app":"bitwarden", "icon":"security.png" },
|
{ "app":"bitwarden", "icon":"security.png" },
|
||||||
{ "app":"1password", "icon":"security.png" },
|
{ "app":"1password", "icon":"security.png" },
|
||||||
{ "app":"lastpass", "icon":"security.png" },
|
{ "app":"lastpass", "icon":"security.png" },
|
||||||
{ "app":"dashlane", "icon":"security.png" },
|
{ "app":"dashlane", "icon":"security.png" },
|
||||||
{ "app":"bring", "icon":"bring.png" },
|
{ "app":"bring", "icon":"bring.png" },
|
||||||
{ "app":"calendar", "icon":"etar.png" },
|
{ "app":"calendar", "icon":"etar.png" },
|
||||||
{ "app":"etar", "icon":"etar.png" },
|
{ "app":"etar", "icon":"etar.png" },
|
||||||
{ "app":"chat", "icon":"google chat.png" },
|
{ "app":"chat", "icon":"google chat.png" },
|
||||||
{ "app":"chrome", "icon":"chrome.png" },
|
{ "app":"chrome", "icon":"chrome.png" },
|
||||||
{ "app":"clock", "icon":"alarm.png" },
|
{ "app":"clock", "icon":"alarm.png" },
|
||||||
{ "app":"corona-warn", "icon":"coronavirus.png" },
|
{ "app":"corona-warn", "icon":"coronavirus.png" },
|
||||||
{ "app":"bmo", "icon":"bank.png" },
|
{ "app":"bmo", "icon":"bank.png" },
|
||||||
{ "app":"desjardins", "icon":"bank.png" },
|
{ "app":"desjardins", "icon":"bank.png" },
|
||||||
{ "app":"rbc mobile", "icon":"bank.png" },
|
{ "app":"rbc mobile", "icon":"bank.png" },
|
||||||
{ "app":"nbc", "icon":"bank.png" },
|
{ "app":"nbc", "icon":"bank.png" },
|
||||||
{ "app":"rabobank", "icon":"bank.png" },
|
{ "app":"rabobank", "icon":"bank.png" },
|
||||||
{ "app":"scotiabank", "icon":"bank.png" },
|
{ "app":"scotiabank", "icon":"bank.png" },
|
||||||
{ "app":"td (canada)", "icon":"bank.png" },
|
{ "app":"td (canada)", "icon":"bank.png" },
|
||||||
|
{ "app":"davx⁵", "icon":"sync.png" },
|
||||||
{ "app":"discord", "icon":"discord.png" },
|
{ "app":"discord", "icon":"discord.png" },
|
||||||
{ "app":"drive", "icon":"google drive.png" },
|
{ "app":"drive", "icon":"google drive.png" },
|
||||||
{ "app":"element", "icon":"matrix element.png" },
|
{ "app":"element", "icon":"matrix element.png" },
|
||||||
|
{ "app":"element x", "icon":"matrix element.png" },
|
||||||
{ "app":"facebook", "icon":"facebook.png" },
|
{ "app":"facebook", "icon":"facebook.png" },
|
||||||
{ "app":"messenger", "icon":"facebook messenger.png" },
|
{ "app":"messenger", "icon":"facebook messenger.png" },
|
||||||
{ "app":"firefox", "icon":"firefox.png" },
|
{ "app":"firefox", "icon":"firefox.png" },
|
||||||
{ "app":"firefox beta", "icon":"firefox.png" },
|
{ "app":"firefox beta", "icon":"firefox.png" },
|
||||||
{ "app":"firefox nightly", "icon":"firefox.png" },
|
{ "app":"firefox nightly", "icon":"firefox.png" },
|
||||||
{ "app":"f-droid", "icon":"security.png" },
|
{ "app":"f-droid", "icon":"security.png" },
|
||||||
{ "app":"neo store", "icon":"security.png" },
|
{ "app":"neo store", "icon":"security.png" },
|
||||||
{ "app":"aurora droid", "icon":"security.png" },
|
{ "app":"aurora droid", "icon":"security.png" },
|
||||||
{ "app":"github", "icon":"github.png" },
|
{ "app":"github", "icon":"github.png" },
|
||||||
{ "app":"gitlab", "icon":"gitlab.png" },
|
{ "app":"gitlab", "icon":"gitlab.png" },
|
||||||
{ "app":"gmail", "icon":"gmail.png" },
|
{ "app":"gmail", "icon":"gmail.png" },
|
||||||
|
|
@ -47,28 +50,30 @@
|
||||||
{ "app":"jira", "icon":"jira.png" },
|
{ "app":"jira", "icon":"jira.png" },
|
||||||
{ "app":"kalender", "icon":"kalender.png" },
|
{ "app":"kalender", "icon":"kalender.png" },
|
||||||
{ "app":"keep notes", "icon":"google keep.png" },
|
{ "app":"keep notes", "icon":"google keep.png" },
|
||||||
|
{ "app":"kleinanzeigen", "icon":"kleinanzeigen.png" },
|
||||||
{ "app":"leboncoin", "icon":"leboncoin.png" },
|
{ "app":"leboncoin", "icon":"leboncoin.png" },
|
||||||
{ "app":"lieferando", "icon":"lieferando.png" },
|
{ "app":"lieferando", "icon":"lieferando.png" },
|
||||||
{ "app":"linkedin", "icon":"linkedin.png" },
|
{ "app":"linkedin", "icon":"linkedin.png" },
|
||||||
{ "app":"maps", "icon":"map.png" },
|
{ "app":"maps", "icon":"map.png" },
|
||||||
{ "app":"organic maps", "icon":"map.png" },
|
{ "app":"organic maps", "icon":"map.png" },
|
||||||
{ "app":"osmand", "icon":"map.png" },
|
{ "app":"osmand", "icon":"map.png" },
|
||||||
{ "app":"mastodon", "icon":"mastodon.png" },
|
{ "app":"mastodon", "icon":"mastodon.png" },
|
||||||
{ "app":"fedilab", "icon":"mastodon.png" },
|
{ "app":"fedilab", "icon":"mastodon.png" },
|
||||||
{ "app":"tooot", "icon":"mastodon.png" },
|
{ "app":"tooot", "icon":"mastodon.png" },
|
||||||
{ "app":"tusky", "icon":"mastodon.png" },
|
{ "app":"tusky", "icon":"mastodon.png" },
|
||||||
{ "app":"mattermost", "icon":"mattermost.png" },
|
{ "app":"mattermost", "icon":"mattermost.png" },
|
||||||
{ "app":"messages", "icon":"messages.png" },
|
{ "app":"messages", "icon":"messages.png" },
|
||||||
{ "app":"n26", "icon":"n26.png" },
|
{ "app":"n26", "icon":"n26.png" },
|
||||||
{ "app":"netflix", "icon":"netflix.png" },
|
{ "app":"netflix", "icon":"netflix.png" },
|
||||||
{ "app":"news", "icon":"news.png" },
|
{ "app":"news", "icon":"news.png" },
|
||||||
{ "app":"cbc news", "icon":"news.png" },
|
{ "app":"cbc news", "icon":"news.png" },
|
||||||
{ "app":"rc info", "icon":"news.png" },
|
{ "app":"rc info", "icon":"news.png" },
|
||||||
{ "app":"reuters", "icon":"news.png" },
|
{ "app":"reuters", "icon":"news.png" },
|
||||||
{ "app":"ap news", "icon":"news.png" },
|
{ "app":"ap news", "icon":"news.png" },
|
||||||
{ "app":"la presse", "icon":"news.png" },
|
{ "app":"la presse", "icon":"news.png" },
|
||||||
{ "app":"nbc news", "icon":"news.png" },
|
{ "app":"nbc news", "icon":"news.png" },
|
||||||
{ "app":"nextbike", "icon":"nextbike.png" },
|
{ "app":"nextbike", "icon":"nextbike.png" },
|
||||||
|
{ "app":"nextcloud", "icon":"nextcloud.png" },
|
||||||
{ "app":"nina", "icon":"nina.png" },
|
{ "app":"nina", "icon":"nina.png" },
|
||||||
{ "app":"outlook mail", "icon":"outlook.png" },
|
{ "app":"outlook mail", "icon":"outlook.png" },
|
||||||
{ "app":"paypal", "icon":"paypal.png" },
|
{ "app":"paypal", "icon":"paypal.png" },
|
||||||
|
|
@ -78,11 +83,11 @@
|
||||||
{ "app":"post & dhl", "icon":"delivery.png" },
|
{ "app":"post & dhl", "icon":"delivery.png" },
|
||||||
{ "app":"proton mail", "icon":"protonmail.png" },
|
{ "app":"proton mail", "icon":"protonmail.png" },
|
||||||
{ "app":"reddit", "icon":"reddit.png" },
|
{ "app":"reddit", "icon":"reddit.png" },
|
||||||
{ "app":"sync pro", "icon":"reddit.png" },
|
{ "app":"sync pro", "icon":"reddit.png" },
|
||||||
{ "app":"sync dev", "icon":"reddit.png" },
|
{ "app":"sync dev", "icon":"reddit.png" },
|
||||||
{ "app":"boost", "icon":"reddit.png" },
|
{ "app":"boost", "icon":"reddit.png" },
|
||||||
{ "app":"infinity", "icon":"reddit.png" },
|
{ "app":"infinity", "icon":"reddit.png" },
|
||||||
{ "app":"slide", "icon":"reddit.png" },
|
{ "app":"slide", "icon":"reddit.png" },
|
||||||
{ "app":"signal", "icon":"signal.png" },
|
{ "app":"signal", "icon":"signal.png" },
|
||||||
{ "app":"molly", "icon":"signal.png" },
|
{ "app":"molly", "icon":"signal.png" },
|
||||||
{ "app":"skype", "icon":"skype.png" },
|
{ "app":"skype", "icon":"skype.png" },
|
||||||
|
|
@ -92,27 +97,28 @@
|
||||||
{ "app":"steam", "icon":"steam.png" },
|
{ "app":"steam", "icon":"steam.png" },
|
||||||
{ "app":"teams", "icon":"teams.png" },
|
{ "app":"teams", "icon":"teams.png" },
|
||||||
{ "app":"telegram", "icon":"telegram.png" },
|
{ "app":"telegram", "icon":"telegram.png" },
|
||||||
{ "app":"telegram foss", "icon":"telegram.png" },
|
{ "app":"telegram foss", "icon":"telegram.png" },
|
||||||
{ "app":"threema", "icon":"threema.png" },
|
{ "app":"threema", "icon":"threema.png" },
|
||||||
{ "app":"threema libre", "icon":"threema.png" },
|
{ "app":"threema libre", "icon":"threema.png" },
|
||||||
|
{ "app":"thunderbird", "icon":"mail.png" },
|
||||||
{ "app":"tiktok", "icon":"tiktok.png" },
|
{ "app":"tiktok", "icon":"tiktok.png" },
|
||||||
{ "app":"to do", "icon":"task.png" },
|
{ "app":"to do", "icon":"task.png" },
|
||||||
{ "app":"opentasks", "icon":"task.png" },
|
{ "app":"opentasks", "icon":"task.png" },
|
||||||
{ "app":"tasks", "icon":"task.png" },
|
{ "app":"tasks", "icon":"task.png" },
|
||||||
{ "app":"transit", "icon":"transit.png" },
|
{ "app":"transit", "icon":"transit.png" },
|
||||||
{ "app":"twitch", "icon":"twitch.png" },
|
{ "app":"twitch", "icon":"twitch.png" },
|
||||||
{ "app":"twitter", "icon":"twitter.png" },
|
{ "app":"twitter", "icon":"twitter.png" },
|
||||||
{ "app":"uber", "icon":"taxi.png" },
|
{ "app":"uber", "icon":"taxi.png" },
|
||||||
{ "app":"lyft", "icon":"taxi.png" },
|
{ "app":"lyft", "icon":"taxi.png" },
|
||||||
{ "app":"vlc", "icon":"vlc.png" },
|
{ "app":"vlc", "icon":"vlc.png" },
|
||||||
{ "app":"warnapp", "icon":"warnapp.png" },
|
{ "app":"warnapp", "icon":"warnapp.png" },
|
||||||
{ "app":"whatsapp", "icon":"whatsapp.png" },
|
{ "app":"whatsapp", "icon":"whatsapp.png" },
|
||||||
{ "app":"wordfeud", "icon":"wordfeud.png" },
|
{ "app":"wordfeud", "icon":"wordfeud.png" },
|
||||||
{ "app":"youtube", "icon":"youtube.png" },
|
{ "app":"youtube", "icon":"youtube.png" },
|
||||||
{ "app":"newpipe", "icon":"youtube.png" },
|
{ "app":"newpipe", "icon":"youtube.png" },
|
||||||
{ "app":"zoom", "icon":"videoconf.png" },
|
{ "app":"zoom", "icon":"videoconf.png" },
|
||||||
{ "app":"meet", "icon":"videoconf.png" },
|
{ "app":"meet", "icon":"videoconf.png" },
|
||||||
{ "app":"music", "icon":"music.png" },
|
{ "app":"music", "icon":"music.png" },
|
||||||
{ "app":"sms message", "icon":"default.png" },
|
{ "app":"sms message", "icon":"default.png" },
|
||||||
{ "app":"mail", "icon":"default.png" }
|
{ "app":"mail", "icon":"default.png" }
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
After Width: | Height: | Size: 248 B |
|
After Width: | Height: | Size: 195 B |
|
After Width: | Height: | Size: 448 B |
|
|
@ -4,7 +4,7 @@ exports.getImage = function(msg) {
|
||||||
if (msg.img) return atob(msg.img);
|
if (msg.img) return atob(msg.img);
|
||||||
let s = (("string"=== typeof msg) ? msg : (msg.src || "")).toLowerCase();
|
let s = (("string"=== typeof msg) ? msg : (msg.src || "")).toLowerCase();
|
||||||
if (msg.id=="music") s="music";
|
if (msg.id=="music") s="music";
|
||||||
let match = ",default|0,airbnb|1,agenda|2,alarm|3,alarmclockreceiver|3,amazon shopping|4,bibel|5,bitwarden|6,1password|6,lastpass|6,dashlane|6,bring|7,calendar|8,etar|8,chat|9,chrome|10,clock|3,corona-warn|11,bmo|12,desjardins|12,rbc mobile|12,nbc|12,rabobank|12,scotiabank|12,td (canada)|12,discord|13,drive|14,element|15,facebook|16,messenger|17,firefox|18,firefox beta|18,firefox nightly|18,f-droid|6,neo store|6,aurora droid|6,github|19,gitlab|20,gmail|21,gmx|22,google|23,google home|24,google play store|25,home assistant|26,instagram|27,jira|28,kalender|29,keep notes|30,leboncoin|31,lieferando|32,linkedin|33,maps|34,organic maps|34,osmand|34,mastodon|35,fedilab|35,tooot|35,tusky|35,mattermost|36,messages|37,n26|38,netflix|39,news|40,cbc news|40,rc info|40,reuters|40,ap news|40,la presse|40,nbc news|40,nextbike|41,nina|42,outlook mail|43,paypal|44,phone|45,plex|46,pocket|47,post & dhl|48,proton mail|49,reddit|50,sync pro|50,sync dev|50,boost|50,infinity|50,slide|50,signal|51,molly|51,skype|52,slack|53,snapchat|54,starbucks|55,steam|56,teams|57,telegram|58,telegram foss|58,threema|59,threema libre|59,tiktok|60,to do|61,opentasks|61,tasks|61,transit|62,twitch|63,twitter|64,uber|65,lyft|65,vlc|66,warnapp|67,whatsapp|68,wordfeud|69,youtube|70,newpipe|70,zoom|71,meet|71,music|72,sms message|0,mail|0,".match(new RegExp(`,${s}\\|(\\d+)`))
|
let match = ",default|0,airbnb|1,agenda|2,alarm|3,alarmclockreceiver|3,amazon shopping|4,bereal.|5,bibel|6,bitwarden|7,1password|7,lastpass|7,dashlane|7,bring|8,calendar|9,etar|9,chat|10,chrome|11,clock|3,corona-warn|12,bmo|13,desjardins|13,rbc mobile|13,nbc|13,rabobank|13,scotiabank|13,td (canada)|13,davx⁵|14,discord|15,drive|16,element|17,element x|17,facebook|18,messenger|19,firefox|20,firefox beta|20,firefox nightly|20,f-droid|7,neo store|7,aurora droid|7,github|21,gitlab|22,gmail|23,gmx|24,google|25,google home|26,google play store|27,home assistant|28,instagram|29,jira|30,kalender|31,keep notes|32,kleinanzeigen|33,leboncoin|34,lieferando|35,linkedin|36,maps|37,organic maps|37,osmand|37,mastodon|38,fedilab|38,tooot|38,tusky|38,mattermost|39,messages|40,n26|41,netflix|42,news|43,cbc news|43,rc info|43,reuters|43,ap news|43,la presse|43,nbc news|43,nextbike|44,nextcloud|45,nina|46,outlook mail|47,paypal|48,phone|49,plex|50,pocket|51,post & dhl|52,proton mail|53,reddit|54,sync pro|54,sync dev|54,boost|54,infinity|54,slide|54,signal|55,molly|55,skype|56,slack|57,snapchat|58,starbucks|59,steam|60,teams|61,telegram|62,telegram foss|62,threema|63,threema libre|63,thunderbird|64,tiktok|65,to do|66,opentasks|66,tasks|66,transit|67,twitch|68,twitter|69,uber|70,lyft|70,vlc|71,warnapp|72,whatsapp|73,wordfeud|74,youtube|75,newpipe|75,zoom|76,meet|76,music|77,sms message|0,mail|0,".match(new RegExp(`,${s}\\|(\\d+)`))
|
||||||
return require("Storage").read("messageicons.img", (match===null)?0:match[1]*76, 76);
|
return require("Storage").read("messageicons.img", (match===null)?0:match[1]*76, 76);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -24,6 +24,7 @@ exports.getColor = function(msg,options) {
|
||||||
"sms message": "#0ff",
|
"sms message": "#0ff",
|
||||||
"bibel": "#54342c",
|
"bibel": "#54342c",
|
||||||
"bring": "#455a64",
|
"bring": "#455a64",
|
||||||
|
"davx⁵": "#8bc34a",
|
||||||
"discord": "#5865f2", // https://discord.com/branding
|
"discord": "#5865f2", // https://discord.com/branding
|
||||||
"etar": "#36a18b",
|
"etar": "#36a18b",
|
||||||
"facebook": "#1877f2", // https://www.facebook.com/brand/resources/facebookapp/logo
|
"facebook": "#1877f2", // https://www.facebook.com/brand/resources/facebookapp/logo
|
||||||
|
|
@ -33,7 +34,8 @@ exports.getColor = function(msg,options) {
|
||||||
"google home": "#fbbc05",
|
"google home": "#fbbc05",
|
||||||
// "home assistant": "#41bdf5", // ha-blue is #41bdf5, but that's the background
|
// "home assistant": "#41bdf5", // ha-blue is #41bdf5, but that's the background
|
||||||
"instagram": "#ff0069", // https://about.instagram.com/brand/gradient
|
"instagram": "#ff0069", // https://about.instagram.com/brand/gradient
|
||||||
"jira": "#0052cc", //https://atlassian.design/resources/logo-library
|
"jira": "#0052cc", // https://atlassian.design/resources/logo-library
|
||||||
|
"kleinanzeigen": "#69bd2f", // https://themen.kleinanzeigen.de/medien/mediathek/kleinanzeigen-guideline-nutzung-logo/
|
||||||
"leboncoin": "#fa7321",
|
"leboncoin": "#fa7321",
|
||||||
"lieferando": "#ff8000",
|
"lieferando": "#ff8000",
|
||||||
"linkedin": "#0a66c2", // https://brand.linkedin.com/
|
"linkedin": "#0a66c2", // https://brand.linkedin.com/
|
||||||
|
|
@ -43,6 +45,7 @@ exports.getColor = function(msg,options) {
|
||||||
"mattermost": "#00f",
|
"mattermost": "#00f",
|
||||||
"n26": "#36a18b",
|
"n26": "#36a18b",
|
||||||
"nextbike": "#00f",
|
"nextbike": "#00f",
|
||||||
|
"nextcloud": "#0082c9", // https://nextcloud.com/brand/
|
||||||
"newpipe": "#f00",
|
"newpipe": "#f00",
|
||||||
"nina": "#e57004",
|
"nina": "#e57004",
|
||||||
"opentasks": "#409f8f",
|
"opentasks": "#409f8f",
|
||||||
|
|
@ -59,6 +62,7 @@ exports.getColor = function(msg,options) {
|
||||||
"teams": "#6264a7", // https://developer.microsoft.com/en-us/fluentui#/styles/web/colors/products
|
"teams": "#6264a7", // https://developer.microsoft.com/en-us/fluentui#/styles/web/colors/products
|
||||||
"telegram": "#0088cc",
|
"telegram": "#0088cc",
|
||||||
"telegram foss": "#0088cc",
|
"telegram foss": "#0088cc",
|
||||||
|
"thunderbird": "#1582e4",
|
||||||
"to do": "#3999e5",
|
"to do": "#3999e5",
|
||||||
"twitch": "#9146ff", // https://brand.twitch.tv/
|
"twitch": "#9146ff", // https://brand.twitch.tv/
|
||||||
"twitter": "#1d9bf0", // https://about.twitter.com/en/who-we-are/brand-toolkit
|
"twitter": "#1d9bf0", // https://about.twitter.com/en/who-we-are/brand-toolkit
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "messageicons",
|
"id": "messageicons",
|
||||||
"name": "Message Icons",
|
"name": "Message Icons",
|
||||||
"version": "0.08",
|
"version": "0.09",
|
||||||
"description": "Library containing a list of icons and colors for apps",
|
"description": "Library containing a list of icons and colors for apps",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
0.01: New App!
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
# Message Twist to Scroll
|
||||||
|
|
||||||
|
Temporarily activate scroll on twist function when a new message triggers the message app. This way it's possible to scroll through a message in the message scroller hands free.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
This is a bootloader app and only needs to be installed to add the functionality to the watch.
|
||||||
|
|
||||||
|
## Requests
|
||||||
|
|
||||||
|
Mention @thyttan in an issue on the espruino/BangleApps repository.
|
||||||
|
|
||||||
|
## Creator
|
||||||
|
|
||||||
|
thyttan
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |
|
|
@ -0,0 +1,63 @@
|
||||||
|
{
|
||||||
|
// twistThreshold How much acceleration to register a twist of the watch strap? Can be negative for opposite direction. default = 800
|
||||||
|
// twistMaxY Maximum acceleration in Y to trigger a twist (low Y means watch is facing the right way up). default = -800
|
||||||
|
// twistTimeout How little time (in ms) must a twist take from low->high acceleration? default = 1000
|
||||||
|
let onTwistEmitDrag = ()=>{
|
||||||
|
Bangle.setOptions({twistThreshold:2500, twistMaxY:-800, twistTimeout:400});
|
||||||
|
let isTwistDragging = false;
|
||||||
|
let twistHandler = ()=>{
|
||||||
|
if (!isTwistDragging) {
|
||||||
|
isTwistDragging = true;
|
||||||
|
Bangle.setLocked(false);
|
||||||
|
Bangle.setLCDPower(true);
|
||||||
|
let i = 25;
|
||||||
|
const int = setInterval(() => {
|
||||||
|
Bangle.emit("drag", {dy:-3, b:i===0?0:1})
|
||||||
|
i--;
|
||||||
|
if (i<0) {
|
||||||
|
clearInterval(int);
|
||||||
|
isTwistDragging = false;
|
||||||
|
}
|
||||||
|
}, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Bangle.on("twist", twistHandler);
|
||||||
|
// Give messagegui some extra time to add its remove function to
|
||||||
|
// Bangle.uiRemove, then attach msgtwscr remove logic.
|
||||||
|
setTimeout(
|
||||||
|
()=>{if (Bangle.uiRemove) {
|
||||||
|
let showMessageUIRemove = Bangle.uiRemove;
|
||||||
|
Bangle.uiRemove = function () {
|
||||||
|
Bangle.removeListener("twist", twistHandler)
|
||||||
|
showMessageUIRemove();
|
||||||
|
// Reset twist drag logic if we go to next message.
|
||||||
|
attachAfterTimeout();
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
800)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If doing regular loads, not Bangle.load, this is used:
|
||||||
|
if (global.__FILE__=="messagegui.new.js") {
|
||||||
|
onTwistEmitDrag();
|
||||||
|
}
|
||||||
|
|
||||||
|
let attachAfterTimeout = ()=>{
|
||||||
|
setTimeout(()=>{
|
||||||
|
if (global.__FILE__=="messagegui.new.js") {
|
||||||
|
onTwistEmitDrag();
|
||||||
|
}
|
||||||
|
},700)
|
||||||
|
// It feels like there's a more elegant solution than checking the filename
|
||||||
|
// after 700 milliseconds. But this at least seems to work w/o sometimes
|
||||||
|
// activating when it shouldn't.
|
||||||
|
// Maybe we could add events for when fast load and/or Bangle.uiRemove occurs?
|
||||||
|
// Then that could be used similarly to boot code and/or the `kill` event.
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Fastload Utils is installed this is used:
|
||||||
|
Bangle.on("message", (_, msg)=>{if (Bangle.CLOCK && msg.new) {
|
||||||
|
attachAfterTimeout();
|
||||||
|
}});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
{ "id": "msgtwscr",
|
||||||
|
"name": "Message Twist to Scroll",
|
||||||
|
"version":"0.01",
|
||||||
|
"description": "Temporarily activate scroll on twist function when a new message triggers the message app.",
|
||||||
|
"icon": "app.png",
|
||||||
|
"tags": "messages,tweak,scroll",
|
||||||
|
"type": "bootloader",
|
||||||
|
"supports" : ["BANGLEJS2"],
|
||||||
|
"readme": "README.md",
|
||||||
|
"storage": [
|
||||||
|
{"name":"msgtwscr.boot.js","url":"boot.js"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -6,4 +6,5 @@
|
||||||
0.06: Fix One Call API 3.0 not returning city names, which are required by the weather app
|
0.06: Fix One Call API 3.0 not returning city names, which are required by the weather app
|
||||||
0.07: Update weather after reconnecting bluetooth if update is due, refactor code
|
0.07: Update weather after reconnecting bluetooth if update is due, refactor code
|
||||||
0.08: Undo change to One Call API 3.0
|
0.08: Undo change to One Call API 3.0
|
||||||
0.09: Fix infinite loop when settings.updated is not defined
|
0.09: Fix infinite loop when settings.updated is not defined
|
||||||
|
0.10: Fix settings.updated being updated even when OWM call failed
|
||||||
|
|
@ -18,6 +18,13 @@
|
||||||
timeoutRef = setTimeout(loadIfDueAndReschedule, refreshMillis());
|
timeoutRef = setTimeout(loadIfDueAndReschedule, refreshMillis());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let onError = function(e) {
|
||||||
|
console.log("owmweather error:", e);
|
||||||
|
loading = false;
|
||||||
|
if (timeoutRef) clearTimeout(timeoutRef);
|
||||||
|
timeoutRef = setTimeout(loadIfDueAndReschedule, refreshMillis());
|
||||||
|
};
|
||||||
|
|
||||||
let loadIfDueAndReschedule = function () {
|
let loadIfDueAndReschedule = function () {
|
||||||
// also check if the weather.json file has been updated (e.g. force refresh)
|
// also check if the weather.json file has been updated (e.g. force refresh)
|
||||||
let weather = require("Storage").readJSON('weather.json') || {};
|
let weather = require("Storage").readJSON('weather.json') || {};
|
||||||
|
|
@ -30,7 +37,7 @@
|
||||||
if (!MillisUntilDue || MillisUntilDue <= 0) {
|
if (!MillisUntilDue || MillisUntilDue <= 0) {
|
||||||
if (!loading) {
|
if (!loading) {
|
||||||
loading = true;
|
loading = true;
|
||||||
require("owmweather").pull(onCompleted);
|
require("owmweather").pull(onCompleted, onError);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// called to early, reschedule
|
// called to early, reschedule
|
||||||
|
|
|
||||||
|
|
@ -27,13 +27,12 @@ function parseWeather(response) {
|
||||||
json.weather = weather;
|
json.weather = weather;
|
||||||
require("Storage").writeJSON('weather.json', json);
|
require("Storage").writeJSON('weather.json', json);
|
||||||
if (require("Storage").read("weather")!==undefined) require("weather").emit("update", json.weather);
|
if (require("Storage").read("weather")!==undefined) require("weather").emit("update", json.weather);
|
||||||
return undefined;
|
|
||||||
} else {
|
} else {
|
||||||
return /*LANG*/"Not OWM data";
|
throw /*LANG*/"Not OWM data";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.pull = function(completionCallback) {
|
exports.pull = function(completionCallback, errorCallback) {
|
||||||
let location = require("Storage").readJSON("mylocation.json", 1) || {
|
let location = require("Storage").readJSON("mylocation.json", 1) || {
|
||||||
"lat": 51.50,
|
"lat": 51.50,
|
||||||
"lon": 0.12,
|
"lon": 0.12,
|
||||||
|
|
@ -43,12 +42,12 @@ exports.pull = function(completionCallback) {
|
||||||
let uri = "https://api.openweathermap.org/data/2.5/weather?lat=" + location.lat.toFixed(2) + "&lon=" + location.lon.toFixed(2) + "&exclude=hourly,daily&appid=" + settings.apikey;
|
let uri = "https://api.openweathermap.org/data/2.5/weather?lat=" + location.lat.toFixed(2) + "&lon=" + location.lon.toFixed(2) + "&exclude=hourly,daily&appid=" + settings.apikey;
|
||||||
if (Bangle.http){
|
if (Bangle.http){
|
||||||
Bangle.http(uri, {timeout:10000}).then(event => {
|
Bangle.http(uri, {timeout:10000}).then(event => {
|
||||||
let result = parseWeather(event.resp);
|
parseWeather(event.resp);
|
||||||
if (completionCallback) completionCallback(result);
|
if (completionCallback) completionCallback();
|
||||||
}).catch((e)=>{
|
}).catch((e)=>{
|
||||||
if (completionCallback) completionCallback(e);
|
if (errorCallback) errorCallback(e);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (completionCallback) completionCallback(/*LANG*/"No http method found");
|
if (errorCallback) errorCallback(/*LANG*/"No http method found");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{ "id": "owmweather",
|
{ "id": "owmweather",
|
||||||
"name": "OpenWeatherMap weather provider",
|
"name": "OpenWeatherMap weather provider",
|
||||||
"shortName":"OWM Weather",
|
"shortName":"OWM Weather",
|
||||||
"version": "0.09",
|
"version": "0.10",
|
||||||
"description": "Pulls weather from OpenWeatherMap (OWM) API",
|
"description": "Pulls weather from OpenWeatherMap (OWM) API",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "bootloader",
|
"type": "bootloader",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
0.01: First release
|
0.01: First release
|
||||||
0.02: clock_info now uses app name to maintain settings specifically for this clock face
|
0.02: clock_info now uses app name to maintain settings specifically for this clock face
|
||||||
ensure clockinfo text is usppercase (font doesn't render lowercase)
|
ensure clockinfo text is uppercase (font doesn't render lowercase)
|
||||||
0.03: Use smaller font if clock_info test doesn't fit in area
|
0.03: Use smaller font if clock_info test doesn't fit in area
|
||||||
0.04: Ensure we only scale down clockinfo text if it really won't fit
|
0.04: Ensure we only scale down clockinfo text if it really won't fit
|
||||||
0.05: Minor code improvements
|
0.05: Minor code improvements
|
||||||
|
|
@ -10,4 +10,6 @@
|
||||||
0.09: Add date on the bottom
|
0.09: Add date on the bottom
|
||||||
0.10: Fix size of bottom bar after 0.09
|
0.10: Fix size of bottom bar after 0.09
|
||||||
Make date toggleable with settings
|
Make date toggleable with settings
|
||||||
Optional border around clockinfos (available from settings)
|
Optional border around clockinfos (available from settings)
|
||||||
|
0.11: Make the border on clockinfos the default
|
||||||
|
Fix clockinfos when too long (previously just output '...')
|
||||||
|
|
@ -20,7 +20,7 @@ Graphics.prototype.setFontLECO1976Regular14 = function() {
|
||||||
|
|
||||||
{
|
{
|
||||||
const SETTINGS_FILE = "pebblepp.json";
|
const SETTINGS_FILE = "pebblepp.json";
|
||||||
let settings = Object.assign({'theme':'System', 'showdate':true, 'clkinfoborder': false}, require("Storage").readJSON(SETTINGS_FILE,1)||{});
|
let settings = Object.assign({'theme':'System', 'showdate':true, 'clkinfoborder': true}, require("Storage").readJSON(SETTINGS_FILE,1)||{});
|
||||||
let background = require("clockbg");
|
let background = require("clockbg");
|
||||||
let theme;
|
let theme;
|
||||||
let drawTimeout;
|
let drawTimeout;
|
||||||
|
|
@ -102,7 +102,7 @@ let clockInfoDraw = (itm, info, options) => {
|
||||||
g.setFontLECO1976Regular14();
|
g.setFontLECO1976Regular14();
|
||||||
if (g.stringWidth(txt) > options.w) {// if still too big, split to 2 lines
|
if (g.stringWidth(txt) > options.w) {// if still too big, split to 2 lines
|
||||||
var l = g.wrapString(txt, options.w);
|
var l = g.wrapString(txt, options.w);
|
||||||
txt = l.slice(0,2).join("\n") + (l.length>2)?"...":"";
|
txt = l.slice(0,2).join("\n") + ((l.length>2)?"...":"");
|
||||||
}
|
}
|
||||||
y = options.y+options.h-12;
|
y = options.y+options.h-12;
|
||||||
if (settings.clkinfoborder) {
|
if (settings.clkinfoborder) {
|
||||||
|
|
@ -147,4 +147,4 @@ background.fillRect(Bangle.appRect); // start off with completely clear backgrou
|
||||||
g.setColor(theme.fg).fillRect(0, h2 - 6, w, h3 + 6);
|
g.setColor(theme.fg).fillRect(0, h2 - 6, w, h3 + 6);
|
||||||
|
|
||||||
draw();
|
draw();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "pebblepp",
|
"id": "pebblepp",
|
||||||
"name": "Pebble++ Clock",
|
"name": "Pebble++ Clock",
|
||||||
"shortName": "Pebble++",
|
"shortName": "Pebble++",
|
||||||
"version": "0.10",
|
"version": "0.11",
|
||||||
"description": "A Pebble style clock (based on the 'Pebble Clock' app) but with two configurable ClockInfo items at the top and custom backgrounds. Date/theme/borders be reconfigured using settings page.",
|
"description": "A Pebble style clock (based on the 'Pebble Clock' app) but with two configurable ClockInfo items at the top and custom backgrounds. Date/theme/borders be reconfigured using settings page.",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"screenshots": [{"url":"screenshot.png"},{"url":"screenshot2.png"}],
|
"screenshots": [{"url":"screenshot.png"},{"url":"screenshot2.png"}],
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
const SETTINGS_FILE = "pebblepp.json";
|
const SETTINGS_FILE = "pebblepp.json";
|
||||||
|
|
||||||
// Initialize with default settings...
|
// Initialize with default settings...
|
||||||
let settings = {'theme':'System', 'showdate':true, 'clkinfoborder':false}
|
let settings = {'theme':'System', 'showdate':true, 'clkinfoborder':true}
|
||||||
// ...and overwrite them with any saved values
|
// ...and overwrite them with any saved values
|
||||||
// This way saved values are preserved if a new version adds more settings
|
// This way saved values are preserved if a new version adds more settings
|
||||||
const storage = require('Storage');
|
const storage = require('Storage');
|
||||||
|
|
|
||||||
|
|
@ -7,3 +7,7 @@
|
||||||
0.13: Improve pattern rendering by HughB http://forum.espruino.com/profiles/167235/
|
0.13: Improve pattern rendering by HughB http://forum.espruino.com/profiles/167235/
|
||||||
0.14: Update setUI to work with new Bangle.js 2v13 menu style
|
0.14: Update setUI to work with new Bangle.js 2v13 menu style
|
||||||
0.15: Update to support clocks in custom setUI mode
|
0.15: Update to support clocks in custom setUI mode
|
||||||
|
0.16: Fix issue adding new patterns (fix #3858)
|
||||||
|
Display message if tapping manage when there are no patterns
|
||||||
|
Speed improvements
|
||||||
|
Add widgets to app (work around E.showMenu(back) bug with no widgets in Espruino 2v27)
|
||||||
|
|
@ -9,10 +9,10 @@ var showMainMenu = () => {
|
||||||
var mainmenu = {
|
var mainmenu = {
|
||||||
"": {
|
"": {
|
||||||
title: "Pattern Launcher",
|
title: "Pattern Launcher",
|
||||||
},
|
back: () => {
|
||||||
"< Back": () => {
|
log("showMainMenu cancel");
|
||||||
log("cancel");
|
load();
|
||||||
load();
|
}
|
||||||
},
|
},
|
||||||
"Add Pattern": () => {
|
"Add Pattern": () => {
|
||||||
log("creating pattern");
|
log("creating pattern");
|
||||||
|
|
@ -83,11 +83,11 @@ var showMainMenu = () => {
|
||||||
var settingsmenu = {
|
var settingsmenu = {
|
||||||
"": {
|
"": {
|
||||||
title: "Pattern Settings",
|
title: "Pattern Settings",
|
||||||
},
|
back: () => {
|
||||||
"< Back": () => {
|
log("settings cancel");
|
||||||
log("cancel");
|
showMainMenu();
|
||||||
load();
|
},
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (settings.lockDisabled) {
|
if (settings.lockDisabled) {
|
||||||
|
|
@ -116,12 +116,7 @@ var showMainMenu = () => {
|
||||||
|
|
||||||
var recognizeAndDrawPattern = () => {
|
var recognizeAndDrawPattern = () => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
E.showMenu();
|
|
||||||
g.clear();
|
|
||||||
drawCirclesWithPattern([]);
|
|
||||||
|
|
||||||
var pattern = [];
|
var pattern = [];
|
||||||
|
|
||||||
var isFinished = false;
|
var isFinished = false;
|
||||||
var finishHandler = () => {
|
var finishHandler = () => {
|
||||||
if (pattern.length === 0 || isFinished) {
|
if (pattern.length === 0 || isFinished) {
|
||||||
|
|
@ -129,15 +124,14 @@ var recognizeAndDrawPattern = () => {
|
||||||
}
|
}
|
||||||
log("Pattern is finished.");
|
log("Pattern is finished.");
|
||||||
isFinished = true;
|
isFinished = true;
|
||||||
Bangle.removeListener("drag", dragHandler);
|
g.clear();
|
||||||
Bangle.removeListener("tap", finishHandler);
|
require("widget_utils").show();
|
||||||
|
Bangle.setUI();
|
||||||
resolve(pattern.join(""));
|
resolve(pattern.join(""));
|
||||||
};
|
};
|
||||||
setWatch(() => finishHandler(), BTN);
|
|
||||||
// setTimeout(() => Bangle.on("tap", finishHandler), 250);
|
|
||||||
|
|
||||||
var positions = [];
|
var positions = [];
|
||||||
var getPattern = (positions) => {
|
var getPattern = (positions) => { "ram";/*faster*/
|
||||||
var circles = [
|
var circles = [
|
||||||
{ x: 25, y: 25, i: 0 },
|
{ x: 25, y: 25, i: 0 },
|
||||||
{ x: 87, y: 25, i: 1 },
|
{ x: 87, y: 25, i: 1 },
|
||||||
|
|
@ -151,18 +145,8 @@ var recognizeAndDrawPattern = () => {
|
||||||
];
|
];
|
||||||
return positions.reduce((pattern, p, i, arr) => {
|
return positions.reduce((pattern, p, i, arr) => {
|
||||||
var idx = circles.findIndex((c) => {
|
var idx = circles.findIndex((c) => {
|
||||||
var dx = p.x > c.x ? p.x - c.x : c.x - p.x;
|
var dx = p.x - c.x, dy = p.y - c.y;
|
||||||
if (dx > CIRCLE_RADIUS) {
|
return dx*dx + dy*dy <= CIRCLE_RADIUS_2;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var dy = p.y > c.y ? p.y - c.y : c.y - p.y;
|
|
||||||
if (dy > CIRCLE_RADIUS) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (dx + dy <= CIRCLE_RADIUS) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return dx * dx + dy * dy <= CIRCLE_RADIUS_2;
|
|
||||||
});
|
});
|
||||||
if (idx >= 0) {
|
if (idx >= 0) {
|
||||||
pattern += circles[idx].i;
|
pattern += circles[idx].i;
|
||||||
|
|
@ -183,7 +167,10 @@ var recognizeAndDrawPattern = () => {
|
||||||
positions = [];
|
positions = [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Bangle.on("drag", dragHandler);
|
require("widget_utils").hide();
|
||||||
|
g.clear();
|
||||||
|
drawCirclesWithPattern([]);
|
||||||
|
Bangle.setUI({mode:"custom", drag:dragHandler, btn :finishHandler});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -215,14 +202,14 @@ var getAppList = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
var getSelectedApp = () => {
|
var getSelectedApp = () => {
|
||||||
E.showMessage("Loading apps...");
|
E.showMessage(/*LANG*/"Loading apps...");
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
var selectAppMenu = {
|
var selectAppMenu = {
|
||||||
"": {
|
"": {
|
||||||
title: "Select App",
|
title: /*LANG*/"Select App",
|
||||||
},
|
},
|
||||||
"< Cancel": () => {
|
"< Cancel": () => {
|
||||||
log("cancel");
|
log("getSelectedApp cancel");
|
||||||
showMainMenu();
|
showMainMenu();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -286,6 +273,8 @@ var drawAppWithPattern = (i, r, storedPatterns) => {
|
||||||
|
|
||||||
var showScrollerContainingAppsWithPatterns = () => {
|
var showScrollerContainingAppsWithPatterns = () => {
|
||||||
var storedPatternsArray = getStoredPatternsArray();
|
var storedPatternsArray = getStoredPatternsArray();
|
||||||
|
if (!storedPatternsArray.length)
|
||||||
|
return E.showAlert(/*LANG*/"No Patterns",{title:/*LANG*/"Patterns"}).then(() => ({ pattern: "back", appName:"" }));
|
||||||
log("drawing scroller for stored patterns");
|
log("drawing scroller for stored patterns");
|
||||||
log(storedPatternsArray);
|
log(storedPatternsArray);
|
||||||
log(storedPatternsArray.length);
|
log(storedPatternsArray.length);
|
||||||
|
|
@ -485,4 +474,6 @@ var log = (message) => {
|
||||||
// run main function
|
// run main function
|
||||||
//////
|
//////
|
||||||
|
|
||||||
showMainMenu();
|
Bangle.loadWidgets();
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
showMainMenu();
|
||||||
|
|
@ -24,18 +24,8 @@
|
||||||
];
|
];
|
||||||
return positions.reduce((pattern, p, i, arr) => {
|
return positions.reduce((pattern, p, i, arr) => {
|
||||||
var idx = circles.findIndex((c) => {
|
var idx = circles.findIndex((c) => {
|
||||||
var dx = p.x > c.x ? p.x - c.x : c.x - p.x;
|
var dx = p.x - c.x, dy = p.y - c.y;
|
||||||
if (dx > CIRCLE_RADIUS) {
|
return dx*dx + dy*dy <= CIRCLE_RADIUS_2;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var dy = p.y > c.y ? p.y - c.y : c.y - p.y;
|
|
||||||
if (dy > CIRCLE_RADIUS) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (dx + dy <= CIRCLE_RADIUS) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return dx * dx + dy * dy <= CIRCLE_RADIUS_2;
|
|
||||||
});
|
});
|
||||||
if (idx >= 0) {
|
if (idx >= 0) {
|
||||||
pattern += circles[idx].i;
|
pattern += circles[idx].i;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "ptlaunch",
|
"id": "ptlaunch",
|
||||||
"name": "Pattern Launcher",
|
"name": "Pattern Launcher",
|
||||||
"shortName": "Pattern Launcher",
|
"shortName": "Pattern Launcher",
|
||||||
"version": "0.15",
|
"version": "0.16",
|
||||||
"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":"manage_patterns_light.png"}],
|
"screenshots": [{"url":"manage_patterns_light.png"}],
|
||||||
|
|
|
||||||
|
|
@ -55,4 +55,9 @@
|
||||||
0.43: Fix interaction on clocks without widgets
|
0.43: Fix interaction on clocks without widgets
|
||||||
0.44: List tracks in reverse chronological order.
|
0.44: List tracks in reverse chronological order.
|
||||||
0.45: Move recorder from widget into library
|
0.45: Move recorder from widget into library
|
||||||
Improve recorder ClockInfo icons
|
Improve recorder ClockInfo icons
|
||||||
|
0.46: Ensure altitude graph draws properly (or any graph using the last column of CSV data)
|
||||||
|
Lower accuracy of barometer data to ~1cm (saves about 15b/record)
|
||||||
|
0.47: Fix 'blip' on speed map on some recordings
|
||||||
|
Ensure Battery voltage is only stored to 0.01v
|
||||||
|
Add graphs for Steps+Battery
|
||||||
|
|
@ -197,6 +197,14 @@ function viewTrack(filename, info) {
|
||||||
menu[/*LANG*/'Plot HRM'] = function() {
|
menu[/*LANG*/'Plot HRM'] = function() {
|
||||||
plotGraph(info, "Heartrate");
|
plotGraph(info, "Heartrate");
|
||||||
};
|
};
|
||||||
|
if (info.fields.includes("Steps"))
|
||||||
|
menu[/*LANG*/'Plot Steps'] = function() {
|
||||||
|
plotGraph(info, "Steps");
|
||||||
|
};
|
||||||
|
if (info.fields.includes("Battery Percentage"))
|
||||||
|
menu[/*LANG*/'Plot Battery'] = function() {
|
||||||
|
plotGraph(info, "Battery");
|
||||||
|
};
|
||||||
// TODO: steps, heart rate?
|
// TODO: steps, heart rate?
|
||||||
menu[/*LANG*/'Erase'] = function() {
|
menu[/*LANG*/'Erase'] = function() {
|
||||||
E.showPrompt(/*LANG*/"Delete Track?").then(function(v) {
|
E.showPrompt(/*LANG*/"Delete Track?").then(function(v) {
|
||||||
|
|
@ -325,6 +333,7 @@ function plotGraph(info, style) { "ram"
|
||||||
var lt = 0; // last time
|
var lt = 0; // last time
|
||||||
//var tn = 0; // count for each time period
|
//var tn = 0; // count for each time period
|
||||||
var strt, dur = info.duration;
|
var strt, dur = info.duration;
|
||||||
|
if (dur<1) dur=1;
|
||||||
var f = require("Storage").open(filename,"r");
|
var f = require("Storage").open(filename,"r");
|
||||||
if (f===undefined) return;
|
if (f===undefined) return;
|
||||||
var l = f.readLine(f);
|
var l = f.readLine(f);
|
||||||
|
|
@ -333,14 +342,14 @@ function plotGraph(info, style) { "ram"
|
||||||
var factor = 1; // multiplier used for values when graphing
|
var factor = 1; // multiplier used for values when graphing
|
||||||
var timeIdx = info.fields.indexOf("Time");
|
var timeIdx = info.fields.indexOf("Time");
|
||||||
if (l!==undefined) {
|
if (l!==undefined) {
|
||||||
c = l.split(",");
|
c = l.trim().split(",");
|
||||||
strt = c[timeIdx];
|
strt = c[timeIdx];
|
||||||
}
|
}
|
||||||
if (style=="Heartrate") {
|
if (style=="Heartrate") {
|
||||||
title = /*LANG*/"Heartrate (bpm)";
|
title = /*LANG*/"Heartrate (bpm)";
|
||||||
var hrmIdx = info.fields.indexOf("Heartrate");
|
var hrmIdx = info.fields.indexOf("Heartrate");
|
||||||
while(l!==undefined) {
|
while(l!==undefined) {
|
||||||
c=l.split(",");l = f.readLine(f);
|
c=l.trim().split(",");l = f.readLine(f);
|
||||||
if (c[hrmIdx]=="") continue;
|
if (c[hrmIdx]=="") continue;
|
||||||
i = Math.round(80*(c[timeIdx] - strt)/dur);
|
i = Math.round(80*(c[timeIdx] - strt)/dur);
|
||||||
infn[i]+=+c[hrmIdx];
|
infn[i]+=+c[hrmIdx];
|
||||||
|
|
@ -351,45 +360,63 @@ function plotGraph(info, style) { "ram"
|
||||||
var altIdx = info.fields.indexOf("Barometer Altitude");
|
var altIdx = info.fields.indexOf("Barometer Altitude");
|
||||||
if (altIdx<0) altIdx = info.fields.indexOf("Altitude");
|
if (altIdx<0) altIdx = info.fields.indexOf("Altitude");
|
||||||
while(l!==undefined) {
|
while(l!==undefined) {
|
||||||
c=l.split(",");l = f.readLine(f);
|
c=l.trim().split(",");l = f.readLine(f);
|
||||||
if (c[altIdx]=="") continue;
|
if (c[altIdx]=="") continue;
|
||||||
i = Math.round(80*(c[timeIdx] - strt)/dur);
|
i = Math.round(80*(c[timeIdx] - strt)/dur);
|
||||||
infn[i]+=+c[altIdx];
|
infn[i]+=+c[altIdx];
|
||||||
infc[i]++;
|
infc[i]++;
|
||||||
}
|
}
|
||||||
|
} else if (style=="Steps") {
|
||||||
|
title = /*LANG*/"Steps/min";
|
||||||
|
var stpIdx = info.fields.indexOf("Steps");
|
||||||
|
var t,lt = c[timeIdx];
|
||||||
|
while(l!==undefined) {
|
||||||
|
c=l.trim().split(",");l = f.readLine(f);
|
||||||
|
if (c[stpIdx]=="") continue;
|
||||||
|
t = c[timeIdx];
|
||||||
|
i = Math.round(80*(t - strt)/dur);
|
||||||
|
infn[i]+=60*c[stpIdx];
|
||||||
|
infc[i]+=t-lt;
|
||||||
|
lt = t;
|
||||||
|
}
|
||||||
|
} else if (style=="Battery") {
|
||||||
|
title = /*LANG*/"Battery %";
|
||||||
|
var batIdx = info.fields.indexOf("Battery Percentage");
|
||||||
|
while(l!==undefined) {
|
||||||
|
c=l.trim().split(",");l = f.readLine(f);
|
||||||
|
if (c[batIdx]=="") continue;
|
||||||
|
i = Math.round(80*(c[timeIdx] - strt)/dur);
|
||||||
|
infn[i]+=+c[batIdx];
|
||||||
|
infc[i]++;
|
||||||
|
}
|
||||||
} else if (style=="Speed") {
|
} else if (style=="Speed") {
|
||||||
// use locate to work out units
|
// use locate to work out units
|
||||||
var localeStr = require("locale").speed(1,5); // get what 1kph equates to
|
var localeStr = require("locale").speed(1,5); // get what 1kph equates to
|
||||||
let units = localeStr.replace(/[0-9.]*/,"");
|
let units = localeStr.replace(/[0-9.]*/,"");
|
||||||
factor = parseFloat(localeStr)*3.6; // m/sec to whatever out units are
|
factor = parseFloat(localeStr)*3.6; // m/sec to whatever out units are
|
||||||
// title
|
|
||||||
title = /*LANG*/"Speed"+` (${units})`;
|
title = /*LANG*/"Speed"+` (${units})`;
|
||||||
var latIdx = info.fields.indexOf("Latitude");
|
var latIdx = info.fields.indexOf("Latitude");
|
||||||
var lonIdx = info.fields.indexOf("Longitude");
|
var lonIdx = info.fields.indexOf("Longitude");
|
||||||
// skip until we find our first data
|
// skip until we find our first data
|
||||||
while(l!==undefined && c[latIdx]=="") {
|
while(l!==undefined && c[latIdx]=="") {
|
||||||
c = l.split(",");
|
c = l.trim().split(",");
|
||||||
l = f.readLine(f);
|
l = f.readLine(f);
|
||||||
}
|
}
|
||||||
// now iterate
|
// now iterate
|
||||||
var p,lp = Bangle.project({lat:c[1],lon:c[2]});
|
var p,lp = Bangle.project({lat:c[latIdx],lon:c[lonIdx]});
|
||||||
var t,dx,dy,d,lt = c[timeIdx];
|
var t,dx,dy,d,lt = c[timeIdx];
|
||||||
while(l!==undefined) {
|
while(l!==undefined) {
|
||||||
c=l.split(",");
|
c=l.trim().split(",");
|
||||||
l = f.readLine(f);
|
l = f.readLine(f);
|
||||||
if (c[latIdx] == "") {
|
if (c[latIdx] == "") continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
t = c[timeIdx];
|
t = c[timeIdx];
|
||||||
i = Math.round(80*(t - strt)/dur);
|
i = Math.round(80*(t - strt)/dur);
|
||||||
p = Bangle.project({lat:c[latIdx],lon:c[lonIdx]});
|
p = Bangle.project({lat:c[latIdx],lon:c[lonIdx]});
|
||||||
dx = p.x-lp.x;
|
dx = p.x-lp.x;
|
||||||
dy = p.y-lp.y;
|
dy = p.y-lp.y;
|
||||||
d = Math.sqrt(dx*dx+dy*dy);
|
d = Math.sqrt(dx*dx+dy*dy);
|
||||||
if (t!=lt) {
|
infn[i]+=d; // speed
|
||||||
infn[i]+=d / (t-lt); // speed
|
infc[i]+=t-lt;
|
||||||
infc[i]++;
|
|
||||||
}
|
|
||||||
lp = p;
|
lp = p;
|
||||||
lt = t;
|
lt = t;
|
||||||
}
|
}
|
||||||
|
|
@ -405,6 +432,7 @@ function plotGraph(info, style) { "ram"
|
||||||
if (n>max) max=n;
|
if (n>max) max=n;
|
||||||
if (n<min) min=n;
|
if (n<min) min=n;
|
||||||
}
|
}
|
||||||
|
if (style=="Battery") {min=0;max=100;}
|
||||||
// work out a nice grid value
|
// work out a nice grid value
|
||||||
var heightDiff = max-min;
|
var heightDiff = max-min;
|
||||||
var grid = 1;
|
var grid = 1;
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ exports.getRecorders = function() {
|
||||||
name : "BAT",
|
name : "BAT",
|
||||||
fields : ["Battery Percentage", "Battery Voltage", "Charging"],
|
fields : ["Battery Percentage", "Battery Voltage", "Charging"],
|
||||||
getValues : () => {
|
getValues : () => {
|
||||||
return [E.getBattery(), NRF.getBattery(), Bangle.isCharging()];
|
return [E.getBattery(), NRF.getBattery().toFixed(2), Bangle.isCharging()];
|
||||||
},
|
},
|
||||||
start : () => {
|
start : () => {
|
||||||
},
|
},
|
||||||
|
|
@ -120,9 +120,9 @@ exports.getRecorders = function() {
|
||||||
recorders['baro'] = function() {
|
recorders['baro'] = function() {
|
||||||
var temp="",press="",alt="";
|
var temp="",press="",alt="";
|
||||||
function onPress(c) {
|
function onPress(c) {
|
||||||
temp=c.temperature;
|
temp=c.temperature.toFixed(1);
|
||||||
press=c.pressure;
|
press=c.pressure.toFixed(2);
|
||||||
alt=c.altitude;
|
alt=c.altitude.toFixed(2);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
name : "Baro",
|
name : "Baro",
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "recorder",
|
"id": "recorder",
|
||||||
"name": "Recorder",
|
"name": "Recorder",
|
||||||
"shortName": "Recorder",
|
"shortName": "Recorder",
|
||||||
"version": "0.45",
|
"version": "0.47",
|
||||||
"description": "Record GPS position, heart rate and more in the background, then download to your PC.",
|
"description": "Record GPS position, heart rate and more in the background, then download to your PC.",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"tags": "tool,outdoors,gps,widget,clkinfo",
|
"tags": "tool,outdoors,gps,widget,clkinfo",
|
||||||
|
|
|
||||||
|
|
@ -87,3 +87,4 @@ of 'Select Clock'
|
||||||
0.76: Add altitude calibration menu (and update README after menu changed)
|
0.76: Add altitude calibration menu (and update README after menu changed)
|
||||||
0.77: Save altitude calibration when user exits via reset
|
0.77: Save altitude calibration when user exits via reset
|
||||||
0.78: Fix menu scroll restore on BangleJS1
|
0.78: Fix menu scroll restore on BangleJS1
|
||||||
|
0.79: Ensure that tapping on pressure/altitude doesn't cause a menu to display temporarily
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "setting",
|
"id": "setting",
|
||||||
"name": "Settings",
|
"name": "Settings",
|
||||||
"version": "0.78",
|
"version": "0.79",
|
||||||
"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",
|
||||||
|
|
|
||||||
|
|
@ -1033,8 +1033,8 @@ function showTouchscreenCalibration() {
|
||||||
// Calibrate altitude - Bangle.js2 only
|
// Calibrate altitude - Bangle.js2 only
|
||||||
function showAltitude() {
|
function showAltitude() {
|
||||||
function onPressure(pressure) {
|
function onPressure(pressure) {
|
||||||
menuPressure.value = Math.round(pressure.pressure);
|
menuPressure.value = Math.round(pressure.pressure).toString(); // toString stops tapping on the item bringing up an adjustment menu
|
||||||
menuAltitude.value = Math.round(pressure.altitude);
|
menuAltitude.value = Math.round(pressure.altitude).toString();
|
||||||
m.draw();
|
m.draw();
|
||||||
}
|
}
|
||||||
function altitudeDone() {
|
function altitudeDone() {
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@
|
||||||
"name":"Sleep Log",
|
"name":"Sleep Log",
|
||||||
"shortName": "SleepLog",
|
"shortName": "SleepLog",
|
||||||
"version": "0.19",
|
"version": "0.19",
|
||||||
"description": "Log and view your sleeping habits. This app is using the built in movement calculation.",
|
"description": "Log and view your sleeping habits. This app uses built in movement calculations. View data from Bangle, or from the web app.",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "app",
|
"type": "app",
|
||||||
"tags": "tool,boot",
|
"tags": "tool,boot,health",
|
||||||
"supports": ["BANGLEJS2"],
|
"supports": ["BANGLEJS2"],
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"interface": "interface.html",
|
"interface": "interface.html",
|
||||||
|
|
|
||||||
2
core
|
|
@ -1 +1 @@
|
||||||
Subproject commit 7e7475ba3ab253099481a81e487aaacb9384f974
|
Subproject commit 0916756932699d626555171ce8e0a2989b151c89
|
||||||