Merge branch 'espruino:master' into master

master
eleanor 2022-05-18 11:27:14 -05:00 committed by GitHub
commit e999660512
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 456 additions and 91 deletions

View File

@ -8,3 +8,4 @@
0.08: Use theme colors, Layout library 0.08: Use theme colors, Layout library
0.09: Fix time/date disappearing after fullscreen notification 0.09: Fix time/date disappearing after fullscreen notification
0.10: Use ClockFace library 0.10: Use ClockFace library
0.11: Use ClockFace.is12Hour

View File

@ -3,7 +3,6 @@
* A simple digital clock showing seconds as a bar * A simple digital clock showing seconds as a bar
**/ **/
// Check settings for what type our clock should be // Check settings for what type our clock should be
const is12Hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"];
let locale = require("locale"); let locale = require("locale");
{ // add some more info to locale { // add some more info to locale
let date = new Date(); let date = new Date();
@ -25,7 +24,7 @@ function renderBar(l) {
function timeText(date) { function timeText(date) {
if (!is12Hour) { if (!clock.is12Hour) {
return locale.time(date, true); return locale.time(date, true);
} }
const date12 = new Date(date.getTime()); const date12 = new Date(date.getTime());
@ -38,7 +37,7 @@ function timeText(date) {
return locale.time(date12, true); return locale.time(date12, true);
} }
function ampmText(date) { function ampmText(date) {
return (is12Hour && locale.hasMeridian)? locale.meridian(date) : ""; return (clock.is12Hour && locale.hasMeridian) ? locale.meridian(date) : "";
} }
function dateText(date) { function dateText(date) {
const dayName = locale.dow(date, true), const dayName = locale.dow(date, true),
@ -69,7 +68,7 @@ const ClockFace = require("ClockFace"),
}, {lazy: true}); }, {lazy: true});
// adjustments based on screen size and whether we display am/pm // adjustments based on screen size and whether we display am/pm
let thickness; // bar thickness, same as time font "pixel block" size let thickness; // bar thickness, same as time font "pixel block" size
if (is12Hour) { if (this.is12Hour) {
// Maximum font size = (<screen width> - <ampm: 2chars * (2*6)px>) / (5chars * 6px) // Maximum font size = (<screen width> - <ampm: 2chars * (2*6)px>) / (5chars * 6px)
thickness = Math.floor((Bangle.appRect.w-24)/(5*6)); thickness = Math.floor((Bangle.appRect.w-24)/(5*6));
} else { } else {

View File

@ -1,7 +1,7 @@
{ {
"id": "barclock", "id": "barclock",
"name": "Bar Clock", "name": "Bar Clock",
"version": "0.10", "version": "0.11",
"description": "A simple digital clock showing seconds as a bar", "description": "A simple digital clock showing seconds as a bar",
"icon": "clock-bar.png", "icon": "clock-bar.png",
"screenshots": [{"url":"screenshot.png"},{"url":"screenshot_pm.png"}], "screenshots": [{"url":"screenshot.png"},{"url":"screenshot_pm.png"}],

View File

@ -51,3 +51,4 @@
0.45: Fix 0.44 regression (auto-add semi-colon between each boot code chunk) 0.45: Fix 0.44 regression (auto-add semi-colon between each boot code chunk)
0.46: Fix no clock found error on Bangle.js 2 0.46: Fix no clock found error on Bangle.js 2
0.47: Add polyfill for setUI with an object as an argument (fix regression for 2v12 devices after Layout module changed) 0.47: Add polyfill for setUI with an object as an argument (fix regression for 2v12 devices after Layout module changed)
0.48: Workaround for BTHRM issues on Bangle.js 1 (write .boot files in chunks)

View File

@ -197,8 +197,18 @@ bootFiles.forEach(bootFile=>{
require('Storage').write('.boot0',"//"+bootFile+"\n",fileOffset); require('Storage').write('.boot0',"//"+bootFile+"\n",fileOffset);
fileOffset+=2+bootFile.length+1; fileOffset+=2+bootFile.length+1;
var bf = require('Storage').read(bootFile); var bf = require('Storage').read(bootFile);
require('Storage').write('.boot0',bf,fileOffset); // we can't just write 'bf' in one go because at least in 2v13 and earlier
fileOffset+=bf.length; // Espruino wants to read the whole file into RAM first, and on Bangle.js 1
// it can be too big (especially BTHRM).
var bflen = bf.length;
var bfoffset = 0;
while (bflen) {
var bfchunk = Math.min(bflen, 2048);
require('Storage').write('.boot0',bf.substr(bfoffset, bfchunk),fileOffset);
fileOffset+=bfchunk;
bfoffset+=bfchunk;
bflen-=bfchunk;
}
require('Storage').write('.boot0',";\n",fileOffset); require('Storage').write('.boot0',";\n",fileOffset);
fileOffset+=2; fileOffset+=2;
}); });

View File

@ -1,7 +1,7 @@
{ {
"id": "boot", "id": "boot",
"name": "Bootloader", "name": "Bootloader",
"version": "0.47", "version": "0.48",
"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
apps/f9lander/ChangeLog Normal file
View File

@ -0,0 +1 @@
0.01: New App!

33
apps/f9lander/README.md Normal file
View File

@ -0,0 +1,33 @@
# F9 Lander
Land a Falcon 9 booster on a drone ship.
## Game play
Attempt to land your Falcon 9 booster on a drone ship before running out of fuel.
A successful landing requires:
* setting down on the ship
* the booster has to be mostly vertical
* the landing speed cannot be too high
## Controls
The angle of the booster is controlled by tilting the watch side-to-side. The
throttle level is controlled by tilting the watch forward and back:
* screen horizontal (face up) means no throttle
* screen vertical corresponds to full throttle
The fuel burn rate is proportional to the throttle level.
## Creators
Liam Kl. B.
Marko Kl. B.
## Screenshots
![](f9lander_screenshot1.png)
![](f9lander_screenshot2.png)
![](f9lander_screenshot3.png)

View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEwwcA/4AD/P8yVJkgCCye27dt2wRE//kCIuSuwRIBwgCCpwRQpIRRnYRQkmdCIvPCJICBEZ4RG/IRP/15CJ/z5IRPz4RM/gQB/n+BxICCn/z/P/BxQCDz7mIAX4Cq31/CJ+ebpiYE/IR/CNP/5IROnn//4jP5DFQ5sJCKAjPk3oCMMk4QRQAX4Ckn7jBAA/5CK8nCJPJNHA"))

150
apps/f9lander/app.js Normal file
View File

@ -0,0 +1,150 @@
const falcon9 = Graphics.createImage(`
xxxxx
xxxxx xxxxx
x x
x x
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
xxxxx
xxxxxxxxx
xx xxxxx xx
xx xx`);
const droneShip = Graphics.createImage(`
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
`);
const droneX = Math.floor(Math.random()*(g.getWidth()-droneShip.width-40) + 20)
const cloudOffs = Math.floor(Math.random()*g.getWidth()/2);
const oceanHeight = g.getHeight()*0.1;
const targetY = g.getHeight()-oceanHeight-falcon9.height/2;
var booster = { x : g.getWidth()/4 + Math.random()*g.getWidth()/2,
y : 20,
vx : 0,
vy : 0,
mass : 100,
fuel : 100 };
var exploded = false;
var nExplosions = 0;
var landed = false;
const gravity = 4;
const dt = 0.1;
const fuelBurnRate = 20*(176/g.getHeight());
const maxV = 12;
function flameImageGen (throttle) {
var str = " xxx \n xxx \n";
str += "xxxxx\n".repeat(throttle);
str += " xxx \n x \n";
return Graphics.createImage(str);
}
function drawFalcon(x, y, throttle, angle) {
g.setColor(1, 1, 1).drawImage(falcon9, x, y, {rotate:angle});
if (throttle>0) {
var flameImg = flameImageGen(throttle);
var r = falcon9.height/2 + flameImg.height/2-1;
var xoffs = -Math.sin(angle)*r;
var yoffs = Math.cos(angle)*r;
if (Math.random()>0.7) g.setColor(1, 0.5, 0);
else g.setColor(1, 1, 0);
g.drawImage(flameImg, x+xoffs, y+yoffs, {rotate:angle});
}
}
function drawBG() {
g.setBgColor(0.2, 0.2, 1).clear();
g.setColor(0, 0, 1).fillRect(0, g.getHeight()-oceanHeight, g.getWidth()-1, g.getHeight()-1);
g.setColor(0.5, 0.5, 1).fillCircle(cloudOffs+34, 30, 15).fillCircle(cloudOffs+60, 35, 20).fillCircle(cloudOffs+75, 20, 10);
g.setColor(1, 1, 0).fillCircle(g.getWidth(), 0, 20);
g.setColor(1, 1, 1).drawImage(droneShip, droneX, g.getHeight()-oceanHeight-1);
}
function showFuel() {
g.setColor(0, 0, 0).setFont("4x6:2").setFontAlign(-1, -1, 0).drawString("Fuel: "+Math.abs(booster.fuel).toFixed(0), 4, 4);
}
function renderScreen(input) {
drawBG();
showFuel();
drawFalcon(booster.x, booster.y, Math.floor(input.throttle*12), input.angle);
}
function getInputs() {
var accel = Bangle.getAccel();
var a = Math.PI/2 + Math.atan2(accel.y, accel.x);
var t = (1+accel.z);
if (t > 1) t = 1;
if (t < 0) t = 0;
if (booster.fuel<=0) t = 0;
return {throttle: t, angle: a};
}
function epilogue(str) {
g.setFont("Vector", 24).setFontAlign(0, 0, 0).setColor(0, 0, 0).drawString(str, g.getWidth()/2, g.getHeight()/2).flip();
g.setFont("Vector", 16).drawString("<= again exit =>", g.getWidth()/2, g.getHeight()/2+20);
clearInterval(stepInterval);
Bangle.on("swipe", (d) => { if (d>0) load(); else load('f9lander.app.js'); });
}
function gameStep() {
if (exploded) {
if (nExplosions++ < 15) {
var r = Math.random()*25;
var x = Math.random()*30 - 15;
var y = Math.random()*30 - 15;
g.setColor(1, Math.random()*0.5+0.5, 0).fillCircle(booster.x+x, booster.y+y, r);
if (nExplosions==1) Bangle.buzz(600);
}
else epilogue("You crashed!");
}
else {
var input = getInputs();
if (booster.y >= targetY) {
// console.log(booster.x + " " + booster.y + " " + booster.vy + " " + droneX + " " + input.angle);
if (Math.abs(booster.x-droneX-droneShip.width/2)<droneShip.width/2 && Math.abs(input.angle)<Math.PI/8 && booster.vy<maxV) {
renderScreen({angle:0, throttle:0});
epilogue("You landed!");
}
else exploded = true;
}
else {
booster.x += booster.vx*dt;
booster.y += booster.vy*dt;
booster.vy += gravity*dt;
booster.fuel -= input.throttle*dt*fuelBurnRate;
booster.vy += -Math.cos(input.angle)*input.throttle*gravity*3*dt;
booster.vx += Math.sin(input.angle)*input.throttle*gravity*3*dt;
renderScreen(input);
}
}
}
var stepInterval;
Bangle.setLCDTimeout(0);
renderScreen({angle:0, throttle:0});
g.setFont("Vector", 24).setFontAlign(0, 0, 0).setColor(0, 0, 0).drawString("Swipe to start", g.getWidth()/2, g.getHeight()/2);
Bangle.on("swipe", () => {
stepInterval = setInterval(gameStep, Math.floor(1000*dt));
Bangle.removeListener("swipe");
});

BIN
apps/f9lander/f9lander.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 722 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -0,0 +1,15 @@
{ "id": "f9lander",
"name": "Falcon9 Lander",
"shortName":"F9lander",
"version":"0.01",
"description": "Land a rocket booster",
"icon": "f9lander.png",
"screenshots" : [ { "url":"f9lander_screenshot1.png" }, { "url":"f9lander_screenshot2.png" }, { "url":"f9lander_screenshot3.png" }],
"readme": "README.md",
"tags": "game",
"supports" : ["BANGLEJS", "BANGLEJS2"],
"storage": [
{"name":"f9lander.app.js","url":"app.js"},
{"name":"f9lander.img","url":"app-icon.js","evaluate":true}
]
}

View File

@ -13,3 +13,4 @@
0.12: Add setting for Daily Step Goal 0.12: Add setting for Daily Step Goal
0.13: Add support for internationalization 0.13: Add support for internationalization
0.14: Move settings 0.14: Move settings
0.15: Fix charts (fix #1366)

View File

@ -46,7 +46,7 @@ function menuHRM() {
function stepsPerHour() { function stepsPerHour() {
E.showMessage(/*LANG*/"Loading..."); E.showMessage(/*LANG*/"Loading...");
let data = new Uint16Array(24); var data = new Uint16Array(24);
require("health").readDay(new Date(), h=>data[h.hr]+=h.steps); require("health").readDay(new Date(), h=>data[h.hr]+=h.steps);
g.clear(1); g.clear(1);
Bangle.drawWidgets(); Bangle.drawWidgets();
@ -57,7 +57,7 @@ function stepsPerHour() {
function stepsPerDay() { function stepsPerDay() {
E.showMessage(/*LANG*/"Loading..."); E.showMessage(/*LANG*/"Loading...");
let data = new Uint16Array(31); var data = new Uint16Array(31);
require("health").readDailySummaries(new Date(), h=>data[h.day]+=h.steps); require("health").readDailySummaries(new Date(), h=>data[h.day]+=h.steps);
g.clear(1); g.clear(1);
Bangle.drawWidgets(); Bangle.drawWidgets();
@ -68,8 +68,8 @@ function stepsPerDay() {
function hrmPerHour() { function hrmPerHour() {
E.showMessage(/*LANG*/"Loading..."); E.showMessage(/*LANG*/"Loading...");
let data = new Uint16Array(24); var data = new Uint16Array(24);
let cnt = new Uint8Array(23); var cnt = new Uint8Array(23);
require("health").readDay(new Date(), h=>{ require("health").readDay(new Date(), h=>{
data[h.hr]+=h.bpm; data[h.hr]+=h.bpm;
if (h.bpm) cnt[h.hr]++; if (h.bpm) cnt[h.hr]++;
@ -84,8 +84,8 @@ function hrmPerHour() {
function hrmPerDay() { function hrmPerDay() {
E.showMessage(/*LANG*/"Loading..."); E.showMessage(/*LANG*/"Loading...");
let data = new Uint16Array(31); var data = new Uint16Array(31);
let cnt = new Uint8Array(31); var cnt = new Uint8Array(31);
require("health").readDailySummaries(new Date(), h=>{ require("health").readDailySummaries(new Date(), h=>{
data[h.day]+=h.bpm; data[h.day]+=h.bpm;
if (h.bpm) cnt[h.day]++; if (h.bpm) cnt[h.day]++;
@ -100,7 +100,7 @@ function hrmPerDay() {
function movementPerHour() { function movementPerHour() {
E.showMessage(/*LANG*/"Loading..."); E.showMessage(/*LANG*/"Loading...");
let data = new Uint16Array(24); var data = new Uint16Array(24);
require("health").readDay(new Date(), h=>data[h.hr]+=h.movement); require("health").readDay(new Date(), h=>data[h.hr]+=h.movement);
g.clear(1); g.clear(1);
Bangle.drawWidgets(); Bangle.drawWidgets();
@ -111,7 +111,7 @@ function movementPerHour() {
function movementPerDay() { function movementPerDay() {
E.showMessage(/*LANG*/"Loading..."); E.showMessage(/*LANG*/"Loading...");
let data = new Uint16Array(31); var data = new Uint16Array(31);
require("health").readDailySummaries(new Date(), h=>data[h.day]+=h.movement); require("health").readDailySummaries(new Date(), h=>data[h.day]+=h.movement);
g.clear(1); g.clear(1);
Bangle.drawWidgets(); Bangle.drawWidgets();
@ -183,7 +183,7 @@ function drawBarChart() {
} }
// draw a fake 0 height bar if chart_index is outside the bounds of the array // draw a fake 0 height bar if chart_index is outside the bounds of the array
if ((chart_index + bar - 1) >= 0 && (chart_index + bar - 1) < data_len) if ((chart_index + bar - 1) >= 0 && (chart_index + bar - 1) < data_len && chart_max_datum > 0)
bar_top = bar_bot - 100 * (chart_data[chart_index + bar - 1]) / chart_max_datum; bar_top = bar_bot - 100 * (chart_data[chart_index + bar - 1]) / chart_max_datum;
else else
bar_top = bar_bot; bar_top = bar_bot;

View File

@ -1,7 +1,7 @@
{ {
"id": "health", "id": "health",
"name": "Health Tracking", "name": "Health Tracking",
"version": "0.14", "version": "0.15",
"description": "Logs health data and provides an app to view it", "description": "Logs health data and provides an app to view it",
"icon": "app.png", "icon": "app.png",
"tags": "tool,system,health", "tags": "tool,system,health",

View File

@ -3,3 +3,4 @@
0.03: Added dependancy on Pedometer Widget 0.03: Added dependancy on Pedometer Widget
0.04: Fixed icon and png to 48x48 pixels 0.04: Fixed icon and png to 48x48 pixels
0.05: added charging icon 0.05: added charging icon
0.06: Add 12h support and autocycle control

View File

@ -2,7 +2,7 @@
"id": "rebble", "id": "rebble",
"name": "Rebble Clock", "name": "Rebble Clock",
"shortName": "Rebble", "shortName": "Rebble",
"version": "0.05", "version": "0.06",
"description": "A Pebble style clock, with configurable background, three sidebars including steps, day, date, sunrise, sunset, long live the rebellion", "description": "A Pebble style clock, with configurable background, three sidebars including steps, day, date, sunrise, sunset, long live the rebellion",
"readme": "README.md", "readme": "README.md",
"icon": "rebble.png", "icon": "rebble.png",

View File

@ -1,8 +1,10 @@
var SunCalc = require("https://raw.githubusercontent.com/mourner/suncalc/master/suncalc.js"); var SunCalc = require("https://raw.githubusercontent.com/mourner/suncalc/master/suncalc.js");
const SETTINGS_FILE = "rebble.json"; const SETTINGS_FILE = "rebble.json";
const LOCATION_FILE = "mylocation.json"; const LOCATION_FILE = "mylocation.json";
const GLOBAL_SETTINGS = "setting.json";
let settings; let settings;
let location; let location;
let is12Hour;
Graphics.prototype.setFontLECO1976Regular22 = function(scale) { Graphics.prototype.setFontLECO1976Regular22 = function(scale) {
// Actual height 22 (21 - 0) // Actual height 22 (21 - 0)
@ -33,12 +35,26 @@ function loadLocation() {
} }
function loadSettings() { function loadSettings() {
settings = require("Storage").readJSON(SETTINGS_FILE,1)|| {'bg': '#0f0', 'color': 'Green'}; settings = require("Storage").readJSON(SETTINGS_FILE,1)|| {'bg': '#0f0', 'color': 'Green', 'autoCycle': true};
is12Hour = (require("Storage").readJSON(GLOBAL_SETTINGS, 1) || {})["12hour"] || false;
}
function formatHours(hh) {
if (is12Hour) {
let hours = parseInt(hh,10);
if (hours == 0) {
hours = 12;
} else if (hours >= 12) {
if (hours>12) hours -= 12;
}
hh = (" "+hours).substr(-2);
}
return hh;
} }
function extractTime(d){ function extractTime(d){
var h = d.getHours(), m = d.getMinutes(); var h = d.getHours(), m = d.getMinutes();
return(("0"+h).substr(-2) + ":" + ("0"+m).substr(-2)); return(formatHours(("0"+h).substr(-2)) + ":" + ("0"+m).substr(-2));
} }
function updateSunRiseSunSet(lat, lon){ function updateSunRiseSunSet(lat, lon){
@ -81,6 +97,9 @@ function draw() {
let da = date.toString().split(" "); let da = date.toString().split(" ");
let hh = da[4].substr(0,2); let hh = da[4].substr(0,2);
let mm = da[4].substr(3,2); let mm = da[4].substr(3,2);
hh = formatHours(hh);
//const t = 6; //const t = 6;
if (drawCount % 60 == 0) if (drawCount % 60 == 0)
@ -260,7 +279,9 @@ function queueDraw() {
if (drawTimeout) clearTimeout(drawTimeout); if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = setTimeout(function() { drawTimeout = setTimeout(function() {
drawTimeout = undefined; drawTimeout = undefined;
if (!settings.autoCycle) {
nextSidebar(); nextSidebar();
}
draw(); draw();
}, 60000 - (Date.now() % 60000)); }, 60000 - (Date.now() % 60000));
} }

View File

@ -2,19 +2,19 @@
const SETTINGS_FILE = "rebble.json"; const SETTINGS_FILE = "rebble.json";
// initialize with default settings... // initialize with default settings...
let s = {'bg': '#0f0', 'color': 'Green'} let localSettings = {'bg': '#0f0', 'color': 'Green', 'autoCycle': 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')
let settings = storage.readJSON(SETTINGS_FILE, 1) || s; let settings = storage.readJSON(SETTINGS_FILE, 1) || localSettings;
const saved = settings || {} const saved = settings || {}
for (const key in saved) { for (const key in saved) {
s[key] = saved[key] localSettings[key] = saved[key]
} }
function save() { function save() {
settings = s settings = localSettings
storage.write(SETTINGS_FILE, settings) storage.write(SETTINGS_FILE, settings)
} }
@ -25,14 +25,22 @@
'': { 'title': 'Rebble Clock' }, '': { 'title': 'Rebble Clock' },
'< Back': back, '< Back': back,
'Colour': { 'Colour': {
value: 0 | color_options.indexOf(s.color), value: 0 | color_options.indexOf(localSettings.color),
min: 0, max: 5, min: 0, max: 5,
format: v => color_options[v], format: v => color_options[v],
onchange: v => { onchange: v => {
s.color = color_options[v]; localSettings.color = color_options[v];
s.bg = bg_code[v]; localSettings.bg = bg_code[v];
save(); save();
}, },
},
'Auto Cycle': {
value: "autoCycle" in localSettings ? localSettings.autoCycle : true,
format: () => (localSettings.autoCycle ? 'Yes' : 'No'),
onchange: () => {
localSettings.autoCycle = !localSettings.autoCycle;
save();
}
} }
}); });
}) })

View File

@ -2,3 +2,5 @@
0.02: Fix crash on start #1423 0.02: Fix crash on start #1423
0.03: Added power saving mode, move all read/write log actions into lib/module 0.03: Added power saving mode, move all read/write log actions into lib/module
0.04: Fix #1445, display loading info, add icons to display service states 0.04: Fix #1445, display loading info, add icons to display service states
0.05: Fix LOW_MEMORY,MEMORY error on to big log size
0.06: Reduced log size further to 750 entries

View File

@ -22,6 +22,7 @@ also provides a power saving mode using the built in movement calculation. The i
To minimize the log size only a changed state is logged. The logged timestamp is matching the beginning of its measurement period. To minimize the log size only a changed state is logged. The logged timestamp is matching the beginning of its measurement period.
When not on power saving mode a movement is detected nearly instantaneous and the detection of a no movement period is delayed by the minimal no movement duration. To match the beginning of the measurement period a cached timestamp (_sleeplog.firstnomodate_) is logged. When not on power saving mode a movement is detected nearly instantaneous and the detection of a no movement period is delayed by the minimal no movement duration. To match the beginning of the measurement period a cached timestamp (_sleeplog.firstnomodate_) is logged.
On power saving mode the measurement period is fixed to 10 minutes and all logged timestamps are also set back 10 minutes. On power saving mode the measurement period is fixed to 10 minutes and all logged timestamps are also set back 10 minutes.
To prevent a LOW_MEMORY,MEMORY error the log size is limited to 750 entries, older entries will be overwritten.
--- ---
### Control ### Control

View File

@ -98,6 +98,9 @@ exports = {
input = log; input = log;
} }
// check and if neccessary reduce logsize to prevent low mem
if (input.length > 750) input = input.slice(-750);
// simple check for log plausibility // simple check for log plausibility
if (input[0].length > 1 && input[0][0] * 1 > 9E11) { if (input[0].length > 1 && input[0][0] * 1 > 9E11) {
// write log to storage // write log to storage

View File

@ -2,7 +2,7 @@
"id":"sleeplog", "id":"sleeplog",
"name":"Sleep Log", "name":"Sleep Log",
"shortName": "SleepLog", "shortName": "SleepLog",
"version": "0.04", "version": "0.06",
"description": "Log and view your sleeping habits. This app derived from SleepPhaseAlarm and uses also the principe of Estimation of Stationary Sleep-segments (ESS). It also provides a power saving mode using the built in movement calculation.", "description": "Log and view your sleeping habits. This app derived from SleepPhaseAlarm and uses also the principe of Estimation of Stationary Sleep-segments (ESS). It also provides a power saving mode using the built in movement calculation.",
"icon": "app.png", "icon": "app.png",
"type": "app", "type": "app",

View File

@ -1 +1,2 @@
0.0.1: Initial implementation 0.0.1: Initial implementation
0.0.2: Fix app icon

View File

@ -1 +1 @@
atob("MDDBAP////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//gAAAAD//gAAAAD//gAAAAf//8AAAAf//8AAAAf//8AAAD/////gAD/////gAD/////gAf/////8Af/////8Af/////8D//////8D//////8D//////8D//////8D//////8D//////8D//////8D//////8D//////8D//////8D//////8D//////8f//////gf//////gf//////gD/////gAD/////gAD/////gAAf///8AAAf///8AAAf///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") atob("MDCI/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v////////////////////7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v////////////////////7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v////////////////////7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v///wAAAAAAAAAAAAAAAAAAAP////7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v///wAAAAAAAAAAAAAAAAAAAP////7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v///wAAAAAAAAAAAAAAAAAAAP////7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v///wAAAP///////////////////wAAAP////////////7+/v7+/v7+/v7+/v7+/v///wAAAP///////////////////wAAAP////////////7+/v7+/v7+/v7+/v7+/v///wAAAP///////////////////wAAAP////////////7+/v7+/v7+/v7+/v///wAAAP///////wAAAP///wAAAAAAAAAAAAAAAAAAAAAAAP////7+/v7+/v7+/v///wAAAP///////wAAAP///wAAAAAAAAAAAAAAAAAAAAAAAP////7+/v7+/v7+/v///wAAAP///////wAAAP///wAAAAAAAAAAAAAAAAAAAAAAAP////7+/v7+/v///wAAAP///////////////////wAAAP///////////////wAAAP////7+/v7+/v///wAAAP///////////////////wAAAP///////////////wAAAP////7+/v7+/v///wAAAP///////////////////wAAAP///////////////wAAAP////7+/v7+/v///wAAAP///wAAAP///////////wAAAAAAAAAAAAAAAAAAAAAAAP////7+/v7+/v///wAAAP///wAAAP///////////wAAAAAAAAAAAAAAAAAAAAAAAP////7+/v7+/v///wAAAP///wAAAP///////////wAAAAAAAAAAAAAAAAAAAAAAAP////7+/v7+/v///wAAAP///////////////////////wAAAP///////////wAAAP////7+/v7+/v///wAAAP///////////////////////wAAAP///////////wAAAP////7+/v7+/v///wAAAP///////////////////////wAAAP///////////wAAAP////7+/v7+/v///wAAAP///////////////////////wAAAAAAAAAAAAAAAAAAAP////7+/v7+/v///wAAAP///////////////////////wAAAAAAAAAAAAAAAAAAAP////7+/v7+/v///wAAAP///////////////////////wAAAAAAAAAAAAAAAAAAAP////7+/v///wAAAP///////////////////////////////////wAAAP////////7+/v7+/v///wAAAP///////////////////////////////////wAAAP////////7+/v7+/v///wAAAP///////////////////////////////////wAAAP////////7+/v7+/v7+/v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////7+/v7+/v7+/v7+/v7+/v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////7+/v7+/v7+/v7+/v7+/v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////7+/v7+/v7+/v7+/v7+/v7+/v////////////////////////////////////7+/v7+/v7+/v7+/v7+/v7+/v7+/v////////////////////////////////////7+/v7+/v7+/v7+/v7+/v7+/v7+/v////////////////////////////////////7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/g==")

View File

@ -2,12 +2,12 @@
"id": "tabanchi", "id": "tabanchi",
"name": "Tabanchi", "name": "Tabanchi",
"shortName": "Tabanchi", "shortName": "Tabanchi",
"version": "0.0.1", "version": "0.0.2",
"type": "app", "type": "app",
"description": "Tamagotchi WatchApp", "description": "Tamagotchi WatchApp",
"icon": "app.png", "icon": "app.png",
"allow_emulator": true, "allow_emulator": true,
"tags": "watch, pet", "tags": "clock, watch, virtual pet",
"supports": [ "supports": [
"BANGLEJS2" "BANGLEJS2"
], ],

View File

@ -1,2 +1,3 @@
0.01: Initial release 0.01: Initial release
0.02: Don't start drawing with white colour on white canvas 0.02: Don't start drawing with white colour on white canvas
0.03: Fix segmented line glitch when drawing, optimize screen lock detection

View File

@ -1,14 +1,13 @@
TinyDraw TinyDraw
======== ========
This is a simple drawing application to make sketches This is a simple drawing application to make sketches using different
using different brushes and colors for your BangleJS2 watch! brushes and colors for your BangleJS2 watch!
* Brush types: dot, brush, circle, square * Brush types: dot, brush, circle, square
It is my first BangleJS application, I plan It is my first BangleJS application, I plan to continue improving
to continue improving this app over time, but this app over time, but if you want to contribute or provide feedback
if you want to contribute or provide feedback
don't hesitate to contact me! don't hesitate to contact me!
--pancake --pancake

View File

@ -1,10 +1,10 @@
(function () { (function () {
var pen = 'circle'; let pen = 'circle';
var discard = null; let discard = null;
var kule = [0, 255, 255]; // R, G, B const kule = [0, 255, 255]; // R, G, B
var oldLock = false; let oldLock = false;
setInterval(() => { Bangle.on("lock", function() {
if (Bangle.isLocked()) { if (Bangle.isLocked()) {
if (oldLock) { if (oldLock) {
return; return;
@ -19,8 +19,7 @@
oldLock = false; oldLock = false;
drawUtil(); drawUtil();
} }
}, 1000); });
function nextColor () { function nextColor () {
kule[0] = Math.random(); kule[0] = Math.random();
kule[1] = Math.random(); kule[1] = Math.random();
@ -35,10 +34,33 @@
case 'square': pen = 'circle'; break; case 'square': pen = 'circle'; break;
default: pen = 'pixel'; break; default: pen = 'pixel'; break;
} }
console.log('set time');
drawUtil(); drawUtil();
discard = setTimeout(function () { console.log('timeout'); discard = null; }, 500); discard = setTimeout(function () { oldX = -1; oldY = -1; console.log('timeout'); discard = null; }, 500);
}
var oldX = -1;
var oldY = -1;
function drawBrushIcon () {
const w = g.getWidth();
switch (pen) {
case 'circle':
g.fillCircle(w - 10, 10, 5);
break;
case 'square':
g.fillRect(w - 5, 5, w - 15, 15);
break;
case 'pixel':
g.setPixel(10, 10);
g.fillCircle(w - 10, 10, 2);
break;
case 'crayon':
g.drawLine(w - 10, 5, w - 10, 15);
g.drawLine(w - 14, 6, w - 10, 12);
g.drawLine(w - 6, 6, w - 10, 12);
break;
}
} }
function drawUtil () { function drawUtil () {
@ -58,35 +80,32 @@
g.setColor('#fff'); g.setColor('#fff');
g.fillCircle(g.getWidth() - 10, 10, 8); g.fillCircle(g.getWidth() - 10, 10, 8);
g.setColor('#000'); g.setColor('#000');
drawBrushIcon();
}
var w = g.getWidth(); let tapTimer = null;
switch (pen) { let dragTimer = null;
case 'circle':
g.fillCircle(w - 10, 10, 5);
break;
case 'square':
g.fillRect(w - 5, 5, w - 15, 15);
break;
case 'pixel':
g.setPixel(10, 10);
g.fillCircle(w - 10, 10, 2);
break;
case 'crayon':
var tap = { x: 10, y: 15, dy: -5, dx: 5 };
g.drawLine(w - tap.x, tap.y, w - tap.x + tap.dx, tap.y + tap.dy);
g.drawLine(w - tap.x + 1, tap.y + 2, w - tap.x + tap.dx, tap.y + tap.dy - 2);
g.drawLine(w - tap.x + 2, tap.y + 2, w - tap.x + tap.dx, tap.y + tap.dy + 2);
break;
}
}
var tapTimer = null;
Bangle.on('drag', function (tap) { Bangle.on('drag', function (tap) {
let from = { x: tap.x, y: tap.y };
const to = { x: tap.x + tap.dx, y: tap.y + tap.dy };
if (oldX != -1) {
from = { x: oldX, y: oldY };
}
if (tap.b === 0) { if (tap.b === 0) {
if (tapTimer !== null) { if (tapTimer !== null) {
clearTimeout(tapTimer); clearTimeout(tapTimer);
tapTimer = null; tapTimer = null;
} }
} }
if (dragTimer != null) {
clearTimeout(dragTimer);
dragTimer = null;
}
dragTimer = setTimeout(function () {
oldX = -1;
oldY = -1;
}, 100);
// tap and hold the clear button // tap and hold the clear button
if (tap.x < 32 && tap.y < 32) { if (tap.x < 32 && tap.y < 32) {
if (tap.b === 1) { if (tap.b === 1) {
@ -110,6 +129,8 @@
tapTimer = setTimeout(function () { tapTimer = setTimeout(function () {
g.clear(); g.clear();
drawUtil(); drawUtil();
oldX = -1; oldY = -1;
tapTimer = null; tapTimer = null;
}, 800); }, 800);
} }
@ -127,28 +148,34 @@
drawUtil(); drawUtil();
return; return;
} }
oldX = to.x;
oldY = to.y;
g.setColor(kule[0], kule[1], kule[2]); g.setColor(kule[0], kule[1], kule[2]);
switch (pen) { switch (pen) {
case 'pixel': case 'pixel':
g.setPixel(tap.x, tap.y); g.drawLine(from.x, from.y, to.x, to.y);
g.drawLine(tap.x, tap.y, tap.x + tap.dx, tap.y + tap.dy);
break; break;
case 'crayon': case 'crayon':
g.drawLine(tap.x, tap.y, tap.x + tap.dx, tap.y + tap.dy); g.drawLine(from.x, from.y, to.x, to.y);
g.drawLine(tap.x + 1, tap.y + 2, tap.x + tap.dx, tap.y + tap.dy - 2); g.drawLine(from.x + 1, from.y + 2, to.x, to.y - 2);
g.drawLine(tap.x + 2, tap.y + 2, tap.x + tap.dx, tap.y + tap.dy + 2); g.drawLine(from.x + 2, from.y + 2, to.x, to.y + 2);
break; break;
case 'circle': case 'circle':
var XS = tap.dx / 10; var XS = (to.x - from.x) / 32;
var YS = tap.dy / 10; var YS = (to.y - from.y) / 32;
for (i = 0; i < 10; i++) { for (i = 0; i < 32; i++) {
g.fillCircle(tap.x + (i * XS), tap.y + (i * YS), 4, 4); g.fillCircle(from.x + (i * XS), from.y + (i * YS), 4, 4);
} }
break; break;
case 'square': case 'square':
g.fillRect(tap.x - 10, tap.y - 10, tap.x + 10, tap.y + 10); var XS = (to.x - from.x) / 32;
var YS = (to.y - from.y) / 32;
for (i = 0; i < 32; i++) {
const posX = from.x + (i * XS);
const posY = from.y + (i * YS);
g.fillRect(posX - 10, posY - 10, posX + 10, posY + 10);
}
break; break;
} }
drawUtil(); drawUtil();
@ -157,3 +184,4 @@
g.clear(); g.clear();
drawUtil(); drawUtil();
})(); })();

View File

@ -1,7 +1,7 @@
{ "id": "tinydraw", { "id": "tinydraw",
"name": "TinyDraw", "name": "TinyDraw",
"shortName":"TinyDraw", "shortName":"TinyDraw",
"version":"0.02", "version":"0.03",
"type": "app", "type": "app",
"description": "Draw stuff in your wrist", "description": "Draw stuff in your wrist",
"icon": "app.png", "icon": "app.png",

View File

@ -8,3 +8,4 @@
0.09: Vibrate on connection loss 0.09: Vibrate on connection loss
0.10: Bug fix 0.10: Bug fix
0.11: Avoid too many notifications. Change disconnected colour to red. 0.11: Avoid too many notifications. Change disconnected colour to red.
0.12: Prevent repeated execution of `draw()` from the current app.

View File

@ -1,7 +1,7 @@
{ {
"id": "widbt_notify", "id": "widbt_notify",
"name": "Bluetooth Widget with Notification", "name": "Bluetooth Widget with Notification",
"version": "0.11", "version": "0.12",
"description": "Show the current Bluetooth connection status in the top right of the clock and vibrate when disconnected.", "description": "Show the current Bluetooth connection status in the top right of the clock and vibrate when disconnected.",
"icon": "widget.png", "icon": "widget.png",
"type": "widget", "type": "widget",

View File

@ -28,7 +28,7 @@ WIDGETS.bluetooth_notify = {
disconnect: function() { disconnect: function() {
if(WIDGETS.bluetooth_notify.warningEnabled == 1){ if(WIDGETS.bluetooth_notify.warningEnabled == 1){
E.showMessage(/*LANG*/'Connection\nlost.', 'Bluetooth'); E.showMessage(/*LANG*/'Connection\nlost.', 'Bluetooth');
setInterval(()=>{WIDGETS.bluetooth_notify.redrawCurrentApp();}, 3000); // clear message - this will reload the widget, resetting 'warningEnabled'. setTimeout(()=>{WIDGETS.bluetooth_notify.redrawCurrentApp();}, 3000); // clear message - this will reload the widget, resetting 'warningEnabled'.
WIDGETS.bluetooth_notify.warningEnabled = 0; WIDGETS.bluetooth_notify.warningEnabled = 0;
setTimeout('WIDGETS.bluetooth_notify.warningEnabled = 1;', 30000); // don't buzz for the next 30 seconds. setTimeout('WIDGETS.bluetooth_notify.warningEnabled = 1;', 30000); // don't buzz for the next 30 seconds.

View File

@ -45,6 +45,7 @@
"Messages": "Messaggi", "Messages": "Messaggi",
"No Messages": "Nessun messaggio", "No Messages": "Nessun messaggio",
"Keep Msgs": "Tieni i messaggi", "Keep Msgs": "Tieni i messaggi",
"Mark all read": "Segna tutto come letto",
"Mark Unread": "Segna come non letto", "Mark Unread": "Segna come non letto",
"Vibrate": "Vibrazione", "Vibrate": "Vibrazione",
"Are you sure": "Sei sicuro/a", "Are you sure": "Sei sicuro/a",
@ -83,8 +84,8 @@
"Background": "Sfondo", "Background": "Sfondo",
"Foreground 2": "Primo piano 2", "Foreground 2": "Primo piano 2",
"Background 2": "Sfondo 2", "Background 2": "Sfondo 2",
"Highlight FG": "Selezione PP", "Highlight FG": "Primo piano selezione",
"Highlight BG": "Selezione Sf", "Highlight BG": "Sfondo selezione",
"Utilities": "Utilità", "Utilities": "Utilità",
"Storage": "Memoria", "Storage": "Memoria",
"Compact Storage": "Compatta memoria", "Compact Storage": "Compatta memoria",
@ -110,7 +111,7 @@
"Loading": "Caricamento", "Loading": "Caricamento",
"Launcher Settings": "Impostazioni Launcher", "Launcher Settings": "Impostazioni Launcher",
"Font": "Font", "Font": "Font",
"Show clocks": "Mostra orologi", "Show Clocks": "Mostra orologi",
"Log": "Log", "Log": "Log",
"Steps": "Passi", "Steps": "Passi",
"steps": "passi", "steps": "passi",
@ -151,19 +152,76 @@
"start&lap/reset, BTN1: EXIT": "start&lap/reset, BTN1: EXIT", "start&lap/reset, BTN1: EXIT": "start&lap/reset, BTN1: EXIT",
"back": "indietro", "back": "indietro",
"color": "colore", "color": "colore",
"BACK": "INDIETRO" "BACK": "INDIETRO",
"Select App": "Seleziona app",
"No Apps Found": "Nessuna app trovata",
"Edit Alarm": "Modifica sveglia",
"Auto Snooze": "Ripeti automaticamente",
"Delete Alarm": "Cancella sveglia",
"Repeat Alarm": "Ripeti sveglia",
"Once": "Una volta",
"Workdays": "Giorni lavorativi",
"Weekends": "Weekend",
"Every Day": "Ogni giorno",
"Custom": "Personalizza",
"Edit Timer": "Modifica timer",
"Delete Timer": "Cancella timer",
"Scheduler Settings": "Impostazioni schedulatore",
"Nothing to Enable": "Niente da attivare",
"Nothing to Disable": "Niente da disattivare",
"Enable All": "Attiva tutto",
"Disable All": "Disattiva tutto",
"Delete All": "Cancella tutto",
"Updating boot0": "Aggiornamento boot0 in corso",
"Reloading": "Ricaricamento in corso",
"Date & Time": "Data & ora",
"Small": "Piccolo",
"Medium": "Medio",
"Big": "Grande",
"Text size": "Dimensione testo",
"Find Phone": "Trova telefono",
"Movement": "Movimento",
"Heart Rate": "Frequenza cardiaca",
"Step Counting": "Conteggio passi",
"Daily Step Goal": "Obiettivo passi giornalieri",
"Fullscreen": "Schermo intero",
"Unlock Watch": "Sblocca orologio",
"Flash Icon": "Icona lampeggiante",
"Auto-Open Music": "Apri modalità musica automaticamente",
"Colour": "Colore",
"Notifications": "Notifiche",
"Scheduler": "Schedulatore",
"Stop": "Stop",
"Min Font": "Dimensione minima del font"
}, },
"//2": "App-specific overrides", "//2": "App-specific overrides",
"alarm": {
"//": "'Crea' instead of 'Nuovo' because 'Nuovo sveglia' would be weird (and wrong)",
"New": "Crea",
"Custom Days": "Personalizza i giorni",
"Advanced": "Altre funzionalità"
},
"health": {
"Health Tracking": "Monitoraggio salute",
"HRM Interval": "Intervallo monitoraggio cardiaco",
"3 min": "3 min",
"10 min": "10 min",
"Always": "Sempre"
},
"launch": { "launch": {
"Vector font size": "Dim. font vett.", "Vector Font Size": "Dim. font vett.",
"App Source\nNot found": "Codice app\nnon trovato" "App Source\nNot found": "Codice app\nnon trovato"
}, },
"messages": { "messages": {
"Unread timer": "Timer msg non letti" "Unread timer": "Timer messaggi non letti"
}, },
"run": { "run": {
"Record Run": "Registra corsa" "Record Run": "Registra corsa"
}, },
"sched": {
"Unlock at Buzz": "Sblocca quando vibra",
"s": "s"
},
"setting": { "setting": {
"Clock Style": "Formato ora", "Clock Style": "Formato ora",
"Compacting...\nTakes approx\n1 minute": "Compattamento in corso...\nCi vorrà circa un minuto", "Compacting...\nTakes approx\n1 minute": "Compattamento in corso...\nCi vorrà circa un minuto",

View File

@ -32,6 +32,8 @@ function ClockFace(options) {
if (dir>0 && options.down) options.down.apply(this); if (dir>0 && options.down) options.down.apply(this);
}; };
if (options.upDown) this._upDown = options.upDown; if (options.upDown) this._upDown = options.upDown;
this.is12Hour = !!(require("Storage").readJSON("setting.json", 1) || {})["12hour"];
} }
ClockFace.prototype.tick = function() { ClockFace.prototype.tick = function() {
@ -69,6 +71,7 @@ ClockFace.prototype.start = function() {
if (this._upDown) Bangle.setUI("clockupdown", d=>this._upDown.apply(this,[d])); if (this._upDown) Bangle.setUI("clockupdown", d=>this._upDown.apply(this,[d]));
else Bangle.setUI("clock"); else Bangle.setUI("clock");
delete this._last; delete this._last;
this.paused = false;
this.tick(); this.tick();
Bangle.on("lcdPower", on => { Bangle.on("lcdPower", on => {
@ -87,7 +90,7 @@ ClockFace.prototype.pause = function() {
ClockFace.prototype.resume = function() { ClockFace.prototype.resume = function() {
if (this._timeout) return; // not paused if (this._timeout) return; // not paused
delete this._last; delete this._last;
delete this.paused; this.paused = false;
if (this._resume) this._resume.apply(this); if (this._resume) this._resume.apply(this);
this.tick(true); this.tick(true);
}; };

View File

@ -59,6 +59,7 @@ var clock = new ClockFace({
draw: function(time, changed) { // at least draw or update is required draw: function(time, changed) { // at least draw or update is required
// (re)draw entire clockface, time is a Date object // (re)draw entire clockface, time is a Date object
// `changed` is the same format as for update() below, but always all true // `changed` is the same format as for update() below, but always all true
// You can use `this.is12Hour` to test if the 'Time Format' setting is set to "12h" or "24h"
}, },
// The difference between draw() and update() is that the screen is cleared // The difference between draw() and update() is that the screen is cleared
// before draw() is called, so it needs to always redraw the entire clock // before draw() is called, so it needs to always redraw the entire clock
@ -108,3 +109,28 @@ var clock = new ClockFace(function(time) {
clock.start(); clock.start();
``` ```
Properties
----------
The following properties are automatically set on the clock:
* `is12Hour`: `true` if the "Time Format" setting is set to "12h", `false` for "24h".
* `paused`: `true` while the clock is paused. (You don't need to check this inside your `draw()` code)
Inside the `draw()`/`update()` function you can access these using `this`:
```js
var ClockFace = require("ClockFace");
var clock = new ClockFace({
draw: function (time) {
if (this.is12Hour) // draw 12h time
else // use 24h format
}
});
clock.start();
Bangle.on('step', function(steps) {
if (clock.paused === false) // draw step count
});
```