Merge branch 'master' into master

master
Gordon Williams 2021-11-29 10:54:23 +00:00 committed by GitHub
commit 3e1c90e485
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 632 additions and 23 deletions

View File

@ -170,7 +170,7 @@
{
"id": "locale",
"name": "Languages",
"version": "0.09",
"version": "0.10",
"description": "Translations for different countries",
"icon": "locale.png",
"type": "locale",
@ -448,6 +448,27 @@
{"name":"matrixclock.img","url":"matrixclock-icon.js","evaluate":true}
]
},
{
"id": "mandlebrotclock",
"name": "Mandlebrot Clock",
"version": "0.01",
"description": "A mandlebrot set themed clock cool",
"icon": "mandlebrotclock.png",
"screenshots": [{ "url": "screenshot_mandlebrotclock.png" }],
"type": "clock",
"tags": "clock",
"supports": ["BANGLEJS2"],
"readme": "README.md",
"allow_emulator": true,
"storage": [
{ "name": "mandlebrotclock.app.js", "url": "mandlebrotclock.js" },
{
"name": "mandlebrotclock.img",
"url": "mandlebrotclock-icon.js",
"evaluate": true
}
]
},
{
"id": "imgclock",
"name": "Image background clock",
@ -664,7 +685,7 @@
{
"id": "gpsrec",
"name": "GPS Recorder",
"version": "0.25",
"version": "0.26",
"description": "Application that allows you to record a GPS track. Can run in background",
"icon": "app.png",
"tags": "tool,outdoors,gps,widget",
@ -683,7 +704,7 @@
"id": "recorder",
"name": "Recorder (BETA)",
"shortName": "Recorder",
"version": "0.03",
"version": "0.04",
"description": "Record GPS position, heart rate and more in the background, then download to your PC.",
"icon": "app.png",
"tags": "tool,outdoors,gps,widget",
@ -3893,8 +3914,8 @@
{
"id": "thermom",
"name": "Thermometer",
"version": "0.02",
"description": "Displays the current temperature, updated every 20 seconds",
"version": "0.03",
"description": "Displays the current temperature in degree Celsius, updated every 20 seconds",
"icon": "app.png",
"tags": "tool",
"supports": ["BANGLEJS"],
@ -4085,7 +4106,7 @@
"id": "pastel",
"name": "Pastel Clock",
"shortName": "Pastel",
"version": "0.06",
"version": "0.07",
"description": "A Configurable clock with custom fonts and background",
"icon": "pastel.png",
"screenshots": [{"url":"screenshot_pastel.png"}],
@ -4378,7 +4399,7 @@
"shortName":"BinWatch",
"icon": "app.png",
"screenshots": [{"url":"screenshot.png"}],
"version":"0.03",
"version":"0.04",
"supports": ["BANGLEJS2"],
"readme": "README.md",
"allow_emulator":true,
@ -4473,5 +4494,37 @@
{"name":"a_clock_timer.app.js","url":"app.js"},
{"name":"a_clock_timer.img","url":"app-icon.js","evaluate":true}
]
},
{
"id":"intervalTimer",
"name":"Interval Timer",
"shortName":"Interval Timer",
"icon": "app.png",
"version":"0.01",
"description": "Interval Timer for workouts, HIIT, or whatever else.",
"tags": "timer, interval, hiit, workout",
"readme":"README.md",
"supports":["BANGLEJS2"],
"storage": [
{"name":"intervalTimer.app.js","url":"app.js"},
{"name":"intervalTimer.img","url":"app-icon.js","evaluate":true}
]
},
{ "id": "93dub",
"name": "93 Dub",
"shortName":"93 Dub",
"icon": "93dub.png",
"screenshots": [{"url":"screenshot.png"}],
"version":"0.03",
"description": "Fan recreation of orviwan's 91 Dub app for the Pebble smartwatch. Uses assets from his 91-Dub-v2.0 repo",
"tags": "clock",
"type": "clock",
"supports":["BANGLEJS2"],
"readme": "README.md",
"allow_emulator": true,
"storage": [
{"name":"93dub.app.js","url":"app.js"},
{"name":"93dub.img","url":"app-icon.js","evaluate":true}
]
}
]

BIN
apps/93dub/93dub.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 B

3
apps/93dub/ChangeLog Normal file
View File

@ -0,0 +1,3 @@
0.01: Initial version for upload
0.02: DiscoMinotaur's adjustments (removed battery and adjusted spacing)
0.03: Code style cleanup

11
apps/93dub/README.md Normal file
View File

@ -0,0 +1,11 @@
# 93 Dub
![](screenshot.png)
Uses many portions from Espruino documentation, example watchfaces, and the waveclk app. It also sourced from Jon Barlow's 91 Dub v2.0 source code and resources and adapted for Bangle.js 2's screen. Time, date and the battery display works. It is not pixel perfect to the original.
Contributors:
Leer10
Orviwan (original watchface and assets)
Gordon Williams (Bangle.js, watchapps for reference code and documentation)
DiscoMinotaur (adjustments)

1
apps/93dub/app-icon.js Normal file
View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEwwkBG2XwAgcPC6P/h//AAIDBA4Pwh/w+AGBAgIDBC4oVDAAITBCAIIBAYIBBAgIvHh4YCFgQPBAoIvCCwoAWIQYAQGLgAWI6bQVdQiiDOyAX/C/7+IAIYvSh4RBAYIXLAwJAHC6ZFCF5yn/C7wDBBAJ3EVAKBDC5QLBYAoLFC5nwCgoXlL44vSL653sL4QXBL6DvXC9YCBACIXCZ4YAQFaYAgPAhqCa4SDFLoZpICYIXDQKLyCDIQXVAAKI0AAYA=="))

137
apps/93dub/app.js Normal file
View File

@ -0,0 +1,137 @@
// get 12 hour status, code from barclock
const is12Hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"];
// define background
var imgBg = require("heatshrink").decompress(atob("2GwgJC/AH4A/AH4A/AH4A/AH4A/ACcGAhAV/Cp3gvdug+Gj0AgeABYMBAQMIggVEg/w/9/h/Gn8As3ACpk559zznmseAs0B13nq/Rie+uodCIIUZw9hzFmv+AgcCmco7MRilow1ACpN8gFhwMilFRCoMowgVEIIVhIINhwFg4GiCpfw/dhx/mn4uBCoXRhWktAVFTIVhw9mj8YseDkUnqPEoeuugVEAAlgSgICBACAVC8AUQCQQVSAEsD/4ASeYgA/ACkHNiK5Cj4VR/AVBng+RCQVwCqMOAQPhIKOHgEB44VR8YVBx4VR+eAgOfCqPxwEDCqX5CoKvS/PAgc/YqQVU/gV/Cv4V/Cv4V/Cv4V/Cv4V/Cv4V/Cv4V/Cv4V/Cv4V/Cv4V/Cv4V/Cv4V/Cv4V/Cv4V/CsMfCqP4CoOfCqP54EBx4VR+OAgPPCqPzwEA44VR4cAgHhCqMHCoNwAQIAPjwCBngVRvgCBV6XwCoMHCqPAHyIA/AEigEf4IAOkAEDoAPJWAtA+PHv+Al6uPCofAGAgALoHz51/8AVT+IVS+4VPpMR73woH27n/8Eh8+ZmadIqsoyGICofAkMUktJFZAVBzgVBv34YgMhi8RkIVJnGQIIN8/H34FB8kJiIVIkVEyGQkF8/Pj4GBkhBKCoOexEQvHx8fBgMXzMxTJkICoXCVx8AggDGABsD/4AB/AVQAH4APA"));
// define fonts
// reg number first char 48 28 by 41
var fontNum = atob("AAAAAAAAAAAAAA//8D//g//8P/+I//8//44//w//j4//A/+P4/8A/4/4AAAAD/4AAAAP/wAAAAf/gAAAA//AAAAB/+AAAAD/8AAAAH/4AAAAP/wAAAAf/gAAAA//AAAAB/+AAAAD/8AAAAH/wAAAAH/H/gH/H8f/gf/Hx//h//HH//n//Ef/+H//B//4H//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/wB/4AP/4H/4A//4f/4D//5//4P//h//4//+B//4AAAAAAAAAAAAAAAAAf/+AAAB//4gAAD//jgAAD/+PgABj/4/gAHj/j/gAfgAP/gA/AA//AB+AB/+AD8AD/8AH4AH/4APwAP/wAfgAf/gA/AA//AB+AB/+AD8AD/8AH4AH/4APwAP/wAfgAf/AA/AAf8f88AAfx/8wAAfH/8AAAcf/8AAAR//4AAAH//gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAA4AAAAAD4AAYAAP4AD8AA/4AH4AD/4APwAP/wAfgAf/gA/AA//AB+AB/+AD8AD/8AH4AH/4APwAP/wAfgAf/gA/AA//AB+AB/+AD8AD/8AH4AH/wAHgAH/H/GH/H8f/gf/Hx//h//HH//n//Ef/+H//B//4H//AAAAAAAAAAAAAAP//AAAAP//AAAAP//AAAAP/8AAAAP/2AAAAP/eAAAAAB+AAAAAD8AAAAAH4AAAAAPwAAAAAfgAAAAA/AAAAAB+AAAAAD8AAAAAH4AAAAAPwAAAAAfgAAAAA/AAAAAB+AAAAAD8AAAB/7x/4AH/7H/4Af/4f/4B//5//4H//h//4f/+B//4AAAAAAAAAAAAAD//wAAAD//wAAAj//gAADj/+AAAPj/5gAA/j/ngAD/gAfgAP/gA/AA//AB+AB/+AD8AD/8AH4AH/4APwAP/wAfgAf/gA/AA//AB+AB/+AD8AD/8AH4AH/4APwAP/wAfgAf/AA/AAf8AA8f8fwAAx/8fAAAH/8cAAAf/8QAAA//8AAAA//8AAAAAAAAAAAAAA//8D//g//8P/+I//8//44//0//j4//Y/+P4/94/4/4AH4AD/4APwAP/wAfgAf/gA/AA//AB+AB/+AD8AD/8AH4AH/4APwAP/wAfgAf/gA/AA//AB+AB/+AD8AD/8AH4AH/wAPwAH/AAPH/H8AAMf/HwAAB//HAAAH//EAAAH//AAAAH//AAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAGAAAAAAOAAAAAAeAAAAAA+AAAAAB+AAAAAD8AAAAAH4AAAAAPwAAAAAfgAAAAA/AAAAAB+AAAAAD8AAAAAH4AAAAAPwAAAAAfgAAAAA/AAAAAB8AAAAADx/4B/4HH/4H/4Mf/4f/4R//5//4H//h//4f/+B//4AAAAAAAAAAAAAD//wP/+D//w//4j//z//jj//T/+Pj/9j/4/j/3j/j/gAfgAP/gA/AA//AB+AB/+AD8AD/8AH4AH/4APwAP/wAfgAf/gA/AA//AB+AB/+AD8AD/8AH4AH/4APwAP/wAfgAf/AA/AAf8f+8f8fx/+x/8fH/+H/8cf/+f/8R//4f/8H//gf/8AAAAAAAAAAAAAA//8AAAA//8AAAI//8AAA4//0AAD4//YAAP4/94AA/4AH4AD/4APwAP/wAfgAf/gA/AA//AB+AB/+AD8AD/8AH4AH/4APwAP/wAfgAf/gA/AA//AB+AB/+AD8AD/8AH4AH/wAPwAH/H/vH/H8f/sf/Hx//h//HH//n//Ef/+H//B//4H//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
// tiny font for percentage first char 48 6 by 8
var fontTiny = atob("AH6BgYF+ACFB/wEBAGGDhYlxAEKBkZFuAAx0hP8EAPqRkZGOAH6RkZFOAICHmKDAAG6RkZFuAHKJiYl+AAAAAAAAAAAAAAAA");
// date font first char 48 12 by 15
var fontDate = atob("AAAAAfv149wAeADwAeADwAeADvHr9+AAAAAAAAAAAAAAAAAAAAAAAAAPHn9/AAAAAAP0A9wweGDwweGDwweGDvAL8AAAAAAAAAAAgwOGDwweGDwweGDvHp98AAAAA/gB6AAwAGAAwAGAAwAGAPHj9/AAAAAfgF6BwweGDwweGDwweGDgHoB+AAAAAfv169wweGDwweGDwweGDgHoB+AAAAAAAAAAgAGAAwAGAAwAGAAvHh9/AAAAAfv169wweGDwweGDwweGDvHr9+AAAAAfgF6BwweGDwweGDwweGDvHr9+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
// define days of the week images
var imgMon = E.toArrayBuffer(atob("Ig8BgHwfD5AvB8HD8z8wMPzPzMQzM/M/DMz8z8c7f7f7z////3Oz+3+PzPzPw/M/M/D8z8z8PzPzPw/vB8/n/8H3/A=="));
var imgTue = E.toArrayBuffer(atob("Ig8BwDv9wDAOfmgf/5+Z///n5n/5+fmf/n5+Z//fv9oH////Af37/b/+fn5n/5+fmf/n5+Z/+fn5n/5/g+gfn+D8AA=="));
var imgWed = E.toArrayBuffer(atob("Ig8Bf7gHgM/NA9Az8z/z8PzP/Pw/M/8/D8z/z8c7QPf7z+A//3O3/3+MzP/PwzM/8/D8z/z8PzP/PxAtA9A4B4B4DA=="));
var imgThu = E.toArrayBuffer(atob("Ig8BgHf7f6Ac/M/P/z8z8//PzPzz8/M/PPz8z8+/QLf7/+A///v3+3+8/PzPzz8/M/PPz8z88/PzPzz8/vB/P3/8HA=="));
var imgFri = E.toArrayBuffer(atob("Ig8B/wDwP7+geg/P5/5+c/n/n5z+f+fnP5/5+c/oHoF7/AfAf/7/7/+/n/k/z+f+R/P5/5j8/n/nHz+/++PP7//8+A=="));
var imgSat = E.toArrayBuffer(atob("Ig8B4DwDwDgOgXAJ/5+f/n/n5/+f+fn55/5+fnoHoF/fAfAf//+b/f3/5n5+f/mfn5/+Z+fn//n5+eAef358B7//nA=="));
var imgSun = E.toArrayBuffer(atob("Ig8BwHf7D7Ac/MHD/z8wMP/PzMQ/8/M/D/z8z8QPf7f6A/////83+3+/zPzPz/M/M/P8z8z8//PzPwA/B8/oD8H3/A=="));
// define icons
var imgSep = E.toArrayBuffer(atob("BhsBAAAAAA///////////////AAAAAAA"));
var imgPercent = E.toArrayBuffer(atob("BwcBuq7ffbqugA=="));
var img24hr = E.toArrayBuffer(atob("EwgBj7vO53na73tcDtu9uDev7vA93g=="));
var imgPM = E.toArrayBuffer(atob("EwgB+HOfdnPu1X3ar4dV9+q+/bfftg=="));
//vars
var separator = true;
var is24hr = !is12Hour;
var leadingZero = true;
//the following 2 sections are used from waveclk to schedule minutely updates
// timeout used to update every minute
var drawTimeout;
// schedule a draw for the next minute
function queueDraw() {
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = setTimeout(function() {
drawTimeout = undefined;
draw();
}, 60000 - (Date.now() % 60000));
}
function drawBackground() {
g.setBgColor(0,0,0);
g.setColor(1,1,1);
g.clear();
g.drawImage(imgBg,0,0);
g.reset();
}
function draw(){
drawBackground();
var date = new Date();
var h = date.getHours(), m = date.getMinutes();
var d = date.getDate(), w = date.getDay();
g.reset();
g.setBgColor(0,0,0);
g.setColor(1,1,1);
//draw 24 hr indicator and 12 hr specific behavior
if (is24hr){
g.drawImage(img24hr,32, 65);
if (leadingZero){
h = ("0"+h).substr(-2);
}
} else if (h > 12) {
g.drawImage(imgPM,40, 70);
h = h - 12;
if (leadingZero){
h = ("0"+h).substr(-2);
} else {
h = " " + h;
}
}
//draw separator
if (separator){
g.drawImage(imgSep, 85,98);}
//draw day of week
var imgW = null;
if (w == 0) {imgW = imgSun;}
if (w == 1) {imgW = imgMon;}
if (w == 2) {imgW = imgTue;}
if (w == 3) {imgW = imgWed;}
if (w == 4) {imgW = imgThr;}
if (w == 5) {imgW = imgFri;}
if (w == 6) {imgW = imgSat;}
g.drawImage(imgW, 85, 63);
// draw nums
// draw time
g.setColor(0,0,0);
g.setBgColor(1,1,1);
g.setFontCustom(fontNum, 48, 28, 41);
if (h<10) {
if (leadingZero) {
h = ("0"+h).substr(-2);
} else {
h = " " + h;
}
}
g.drawString(h, 25, 90, true);
g.drawString(("0"+m).substr(-2), 92, 90, true);
// draw date
g.setFontCustom(fontDate, 48, 12, 15);
g.drawString(("0"+d).substr(-2), 123,63, true);
// widget redraw
Bangle.drawWidgets();
queueDraw();
}
draw();
//the following section is also from waveclk
Bangle.on('lcdPower',on=>{
if (on) {
draw(); // draw immediately, queue redraw
} else { // stop draw timer
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = undefined;
}
});
Bangle.setUI("clock");
Bangle.loadWidgets();
Bangle.drawWidgets();

BIN
apps/93dub/screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -27,3 +27,4 @@
0.23: Fix issue where tracks wouldn't record when running from OpenStMap if a period hadn't been set up first
0.24: Better support for Bangle.js 2, avoid widget area for Graphs, smooth graphs more
0.25: Fix issue where if Bangle.js 2 got a GPS fix but no reported time, errors could be caused by the widget (fix #935)
0.26: Multiple bugfixes

View File

@ -249,10 +249,10 @@ function plotTrack(info) {
g.fillCircle(ox,oy,5);
if (info.qOSTM) g.setColor(0, 0, 0);
else g.setColor(1,1,1);
g.drawString(require("locale").distance(dist),120,220);
g.drawString(require("locale").distance(dist),g.getWidth() / 2, g.getHeight() - 20);
g.setFont("6x8",2);
g.setFontAlign(0,0,3);
g.drawString("Back",230,200);
g.drawString("Back",g.getWidth() - 10, g.getHeight() - 40);
setWatch(function() {
viewTrack(info.fn, info);
}, global.BTN3||BTN1);
@ -330,13 +330,13 @@ function plotGraph(info, style) {
height: g.getHeight()-(24+8),
axes : true,
gridy : grid,
gridx : 50,
gridx : infn.length / 3,
title: title,
xlabel : x=>Math.round(x*dur/(60*infn.length))+" min" // minutes
});
g.setFont("6x8",2);
g.setFontAlign(0,0,3);
g.drawString("Back",230,200);
g.drawString("Back",g.getWidth() - 10, g.getHeight() - 40);
setWatch(function() {
viewTrack(info.fn, info);
}, global.BTN3||BTN1);

View File

@ -0,0 +1 @@
0.01: First Release

View File

@ -0,0 +1,34 @@
# Interval Timer
An interval timer for workouts and whatever else!
## Usage
First set the active time (i.e. the number of seconds to perform exercises).
![Set Active Time](images/set-active.png)
Next set the rest time (i.e. number of seconds to rest between exercises).
![Set Rest Time](images/set-rest.png)
Finally choose the number of sets to perform.
![Set Number Sets](images/set-sets.png)
Active time will be shown in red, rest time in green. The watch will buzz whenever active or rest time gets to 0.
![Timer (active)](images/timer1.png)
![Timer (rest)](images/timer2.png)
You can press the physical button during timer countdown to pause the timer.
![Paused](images/pause.png)
View after all sets are completed. Press menu to change settings or restart to start timer again with the same settings.
![Completed view](images/done.png)
## Creator
James Gough

View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEwwg96hWq1WgDCgXWxGZzOICqQABC4QABCyIXFDBsICIeJyfznAFBwAWPC4Of///mYYMCwgXBl4XB/4xCFxwABn4XCDAQwICw2ICwf/+YwJxGDHoQXHGARGIn/4C5QwBJAwQDC5QLCIw6GEC5BIGIwQLBJAgXGJAwXEJAgXPHgoXIEYIXFLwRIFC484C4h2DJAoIFPA+Ix4MGAAJoDHYgXKf4QXUJAYJGC5p5CF6hIBO44XNABIXGEw4AIU4rXFC5jvFc5AAHxAXGQwwAHQAIXcPCB2FC4RgOB4IXFJBxGHJB5GHJAYwKFwIXIJAIwKFwJGHGAYYICwIuIGAeImYWFmYJBFxIYEwZjC+YtCCxZJDAA4WMDBIWODIwVRAH4AXA=="))

306
apps/intervalTimer/app.js Normal file
View File

@ -0,0 +1,306 @@
/**
Interval Timer
An app for the Bangle.js watch
*/
var Layout = require("Layout");
// Globals
var timerMode; // 'active' || 'rest'
var numSets = 1;
var activeTime = 20;
var restTime = 10;
var counter;
var setsRemaining;
var counterInterval;
var outOfTimeTimeout;
var timerIsPaused;
var timerLayout;
/** Called to initialize the timer layout */
function initTimerLayout() {
timerLayout = new Layout( {
type:"v", c: [
{type:"txt", font:"40%", pad: 10, label:"00:00", id:"time" },
{type:"txt", font:"6x8:2", label:"0", id:"set" }
]
}, {btns: [
{label: "Stop", cb: l => {
if (timerIsPaused){
timerIsPaused = false;
resumeTimer();
}
else{
timerIsPaused = true;
pauseTimer();
}
}
}
]
});
}
/** Pauses the timer by clearing the counterInterval */
function pauseTimer() {
if (counterInterval){
clearTimeout(counterInterval);
counterInterval = undefined;
}
// update layout to display "Paused"
timerLayout.clear(timerLayout.time);
timerLayout.time.label = "||";
timerLayout.clear(timerLayout.set);
timerLayout.set.label = "Paused";
timerLayout.render();
}
/** Reumes the timer by setting the counterInterval again */
function resumeTimer() {
if (!counterInterval){
counterInterval = setInterval(countDown, 1000);
}
// display the timer values again.
timerLayout.clear(timerLayout.time);
timerLayout.time.label = counter;
timerLayout.clear(timerLayout.set);
timerLayout.set.label = `Sets: ${setsRemaining}`;
timerLayout.render();
}
/** Display 'Done' view, called when all sets are completed */
function outOfTime() {
var stopLayout = new Layout( {
type:"v", c: [
{type:"txt", font:"30%", label:"Done!", id:"time" },
]
}, {btns: [
// menu button allows user to modify times and sets
{label:"Menu", cb: l=> {
if (outOfTimeTimeout){
clearTimeout(outOfTimeTimeout);
outOfTimeTimeout = undefined;
}
//stopLayout.remove();
setup();
}
},
// restart button runs timer again with the same settings
{label:"Restart", cb: l=> {
if (outOfTimeTimeout){
clearTimeout(outOfTimeTimeout);
outOfTimeTimeout = undefined;
}
//stopLayout.remove();
timerMode = 'active';
startTimer();
}
}
]});
if (counterInterval) return;
setsRemaining = numSets;
g.clear();
stopLayout.render();
Bangle.buzz(500);
Bangle.beep(200, 4000)
.then(() => new Promise(resolve => setTimeout(resolve,200)))
.then(() => Bangle.beep(200, 3000));
}
/** Function called by the counterInterval at each second.
Updates the timer display values.
*/
function countDown() {
// Out of time
if (counter<=0) {
if(timerMode === 'active'){
timerMode = 'rest';
startTimer();
return;
}
else{
--setsRemaining;
if (setsRemaining === 0){
clearInterval(counterInterval);
counterInterval = undefined;
//setWatch(startTimer, (process.env.HWVERSION==2) ? BTN1 : BTN2);
outOfTime();
return;
}
timerMode = 'active';
startTimer();
return;
}
}
timerLayout.clear(timerLayout.time);
timerLayout.time.label = counter;
timerLayout.render();
counter--;
}
/** Start the interval timer. */
function startTimer() {
timerIsPaused = false;
g.clear();
if(timerMode === 'active'){
counter = activeTime;
timerLayout.time.col = '#f00';
}
else{
counter = restTime;
timerLayout.time.col = '#0f0';
}
timerLayout.clear(timerLayout.set);
timerLayout.set.label = `Sets: ${setsRemaining}`;
timerLayout.render();
Bangle.buzz();
countDown();
if (!counterInterval){
counterInterval = setInterval(countDown, 1000);
}
}
/** Menu step in which user sets the number of sets to be performed. */
function setNumSets(){
g.clear();
var menuLayout = new Layout( {
type:"v", c: [
{type:"txt", font:"6x8:2", label:"Number Sets", id:"title" },
{type:"txt", font:"30%", pad: 20, label: numSets, id:"value" },
{type:"btn", font:"6x8:2", label:"Back", cb: l => {
setRestTime();
}
}
]
}, {btns: [
{label:"+", cb: l=> {
incrementNumSets();
}},
{label:"Go", cb: l=> {
setsRemaining = numSets;
initTimerLayout();
startTimer();
}},
{label:"-", cb: l=>{
decrementNumSets();
}}
]});
menuLayout.render();
const incrementNumSets = () => {
++numSets;
menuLayout.clear(menuLayout.numSets);
menuLayout.value.label = numSets;
menuLayout.render();
};
const decrementNumSets = () => {
if(numSets === 1){
return;
}
--numSets;
menuLayout.clear(menuLayout.numSets);
menuLayout.value.label = numSets;
menuLayout.render();
};
}
/** Menu step in which user sets the number of seconds of rest time for each set. */
function setRestTime(){
g.clear();
var menuLayout = new Layout( {
type:"v", c: [
{type:"txt", font:"6x8:2", label:"Rest Time", id:"title" },
{type:"txt", font:"30%", pad: 20, label: restTime, id:"value" },
{type:"btn", font:"6x8:2", label:"Back", cb: l => {
setActiveTime();
}
}
]
}, {btns: [
{label:"+", cb: l=> {
incrementRestTime();
}},
{label:"OK", cb: l=>setNumSets()},
{label:"-", cb: l=>{
decrementRestTime();
}}
]});
menuLayout.render();
const incrementRestTime = () => {
restTime += 5;
menuLayout.clear(menuLayout.restTime);
menuLayout.value.label = restTime;
menuLayout.render();
};
const decrementRestTime = () => {
if(restTime === 0){
return;
}
restTime -= 5;
menuLayout.clear(menuLayout.restTime);
menuLayout.value.label = restTime;
menuLayout.render();
};
}
/** Menu step in which user sets the number of seconds of active time for each set. */
function setActiveTime(){
g.clear();
var menuLayout = new Layout( {
type:"v", c: [
{type:"txt", font:"6x8:2", label:"Active Time", id:"title" },
{type:"txt", font:"30%", pad: 20, label: activeTime, id:"value" }
]
}, {btns: [
{font:"20%", label:"+", fillx:1, cb: l=> {
incrementActiveTime();
}},
{label:"OK", cb: l => setRestTime()},
{type:"btn", font:"20%", label:"-", fillx:1, cb: l=> {
decrementActiveTime();
}
}
]});
menuLayout.render();
const incrementActiveTime = () => {
activeTime += 5;
menuLayout.clear(menuLayout.activeTime);
menuLayout.value.label = activeTime;
menuLayout.render();
};
const decrementActiveTime = () => {
if(activeTime === 0){
return;
}
activeTime -= 5;
menuLayout.clear(menuLayout.activeTime);
menuLayout.value.label = activeTime;
menuLayout.render();
};
}
/** Start the setup menu, walks through setting active time, rest time, and number of sets. */
function setup(){
if (timerLayout){
// remove timerLayout, otherwise it's pause button callback will still be registered
timerLayout.remove(timerLayout);
timerLayout = undefined;
}
Bangle.setUI(); // remove all existing input handlers
timerMode = 'active';
setActiveTime();
}
// this keeps the watch LCD lit up
Bangle.setLCDPower(1);
setup();

BIN
apps/intervalTimer/app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -9,3 +9,4 @@
0.07: Improve handling of non-ASCII characters (fix #469)
0.08: Added Mavigation units and en_NAV
0.09: Added New Zealand en_NZ
0.10: Apply 12hour setting to time

View File

@ -146,7 +146,7 @@ exports = { name : "en_GB", currencySym:"£",
"%-m": "d.getMonth()+1",
"%d": "('0'+d.getDate()).slice(-2)",
"%-d": "d.getDate()",
"%HH": "('0'+d.getHours()).slice(-2)",
"%HH": "('0'+getHours(d)).slice(-2)",
"%MM": "('0'+d.getMinutes()).slice(-2)",
"%SS": "('0'+d.getSeconds()).slice(-2)",
"%A": "day.split(',')[d.getDay()]",
@ -178,6 +178,13 @@ var month = ${js(locale.month + ',' + locale.abmonth)};
function round(n) {
return n < 10 ? Math.round(n * 10) / 10 : Math.round(n);
}
var is12;
function getHours(d) {
var h = d.getHours();
if (is12===undefined) is12 = (require('Storage').readJSON('setting.json',1)||{})["12hour"];
if (!is12) return h;
return (h%12==0) ? 12 : h%12;
}
exports = {
name: ${js(locale.lang)},
currencySym: ${js(locale.currency_symbol)},

View File

@ -0,0 +1,2 @@
0.01: Initial Release

View File

@ -0,0 +1,9 @@
# Mandlebrot Clock
A simple clock themed on the mandlebrot set.
Written by [James Milner](https://www.github.com/jameslmilner)
![](app.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEwxH+vdvwMzq8CrGCwVewNRluCxAHBAAOsxAAB1gAD1oBB2fWAAPO1mBGZIvCrECq4bBglYmglBGgIxBFQItDFQQsC2es6/XF4OrwOsqwvIt4vBxFdgder0uwUoLQRXE1oqB1nQ1nW2RbCA4PW6HP52rF5d7KoKNBmcDIYIzBrBaB1vPFAOz2RVB1ml54qB1fQFwQvB5+kwSQJWIQoExAFBRYaBB0pVCQYRiB0wDC1erFoPO5ul02sF5QnBAAYFBwbkF0ul1eIAQOqOwLlBIwL7BGIOkAANvxErF49dF4dYGoJfBLoIwD6AfBEgJbBwIEBqwGBqw4BU4Osvd1uteSBDiEFIKLDdQey6ytBEQNWAQOBwMyKYcrAAILBWIRgIEofQ1mJAoS6B2ez665B5+rLQMrq1WWBAACHwJNBCA5WCbgPQ1pYBFYOl6CMB6vP0prB1l6kguLAAWBJgKPHRIOz03Q6+z2QsBVgOrdgOlvaKBLhhiG6AUGJoJOB6GmMgPPcQLHCdAgtRSYgHFrDKBXYWBLQOk0qlBcgNWBYJdSAAcCC4qOBAILzE62l0mCIYVWvQuVAAMsAokzR4WJ1us2fW6K/BMwMrgErAQIAcq+sGAOtF4Os1vXF4I5B1mlFzSQELwU0xGtAIOzF4LCBBgOrLbYwDwUuwVeYIiRB6ukwLBDF7QwCwVYKgJgBGAOt6PW54vB1i7cq2rVoNYFQJfCMAXW62rM4QWDGoPXMwNWAgIMDAw2B67XDlezwUAgYsCwWJLwK9B1YnBwLSEAwIeCBgXXBoQGDHgMr64vEDIOIwNXSAJfBF4RgB1elfQK+GqweCGIIvBCgJUCF4QHBF4rqBRIS/BxKOC1qPB54wBF4pSDE4IjCcAQ6BGYIPCNYYYCl1SKYI0BMwIvBDoIvBPgR1EDgdWKAINDFwIECFoIABbItRulYMYhfCF4Y8BCoYbBAANWEYJfCZALuCIgi/GveeRoIuBXgOt1uy6HV5+kF4olBAAIeBGIIDCAAILCRQYMCNgWs0uqEQOs2fQ6+y63R0vJ1d7q+IUwgAXNoOl5xeBGAOrdYPW6A5BHQWteAovXwWq569BVoWl0ur0g8BVAMrq2lU4gAVq2m1gvC1gwBSAOrLgSiECgIvZq+CKwPWL4IvBXoPQ0uBXQxiBLzCHCW4ItBxGt2fXMAN71iJGYK8r1jqBF4PXL4QvB62r1a+BF4yXBFytWxGB0us6/XdoWzF4TKBwKPGH4IwULgIoB55eB2YGCXoPQ5xeBq+BvUkOolXGAMBXaOCruCwXQ2es1ovC0vP0ulKoOmwWsSgI2BwV70rKBHQIuORgWkwWl2QvBAAXX1YJBwOrAQOAvYxBHoN65HOBQIIBqyeGFgZEBwJ2BKgIqC1ogC2XW0osB1fQ62k5+qMgJoBC4PQfgLYBEYIABNoNWljjCHgNeBgWr63W2QvBxOJBIWr54uCYgL0BLAIsCBIIKB1T+BVwN8WAJcBNQIABIgQGB1fX2RdBXoOJFQWzSIOz1uzAoIwBFgXX2ZHBOIRDCWAOBRgQtC53P1OB0wlBMgQuBdwQAF1oxBEwI7B1p0CBgIIBAAPP0mBcgNWBYOkBYbfB6wtCxCaFGYQKBAoQvBOQIACHoey2ey6D2D0uC0yIBLIILB0pJBEIU6wU0FQbEBF4hnFA4ZlBNoRhCGAJYBHYSKD1eyEYJfBrxfCAwNeAILVBwZZExIABGATNCGARvBCoIMBFwJzDAIderFYwWJsgyBCoI1BAYIABF4QeBL4IvDOIIvDL4PPBYIuCKQQRBEAWsrE0AocQAQJpBGgRNCIQIECCQQzD6Gr0qMBbwYADJ4ZUBl1YBAVelwpBNIQDBFIImCl2CagIVBAATkC5/WFwhLFFoMtwM0E4MtltevggBgcDwITCrEzxEulz5CDgNkMIer6GyLogsCwWmI4MzrFXGAMEA=="))

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -1,2 +1,2 @@
0.02: Ported to Banglejs2.
0.01: New App!
0.02: Ported to Banglejs2.

View File

@ -2,3 +2,4 @@
0.02: Use 'recorder.log..' rather than 'record.log..'
Fix interface.html
0.03: Fix theme and maps/graphing if no GPS
0.04: Multiple bugfixes

View File

@ -304,10 +304,10 @@ function plotTrack(info) {
g.fillCircle(ox,oy,5);
if (info.qOSTM) g.setColor("#000");
else g.setColor(g.theme.fg);
g.drawString(require("locale").distance(dist),120,220);
g.drawString(require("locale").distance(dist),g.getWidth() / 2, g.getHeight() - 20);
g.setFont("6x8",2);
g.setFontAlign(0,0,3);
g.drawString("Back",230,200);
g.drawString("Back",g.getWidth() - 10, g.getHeight() - 40);
setWatch(function() {
viewTrack(info.fn, info);
}, global.BTN3||BTN1);
@ -360,6 +360,10 @@ function plotGraph(info, style) {
var t,dx,dy,d,lt = c[timeIdx];
while(l!==undefined) {
++nl;c=l.split(",");
l = f.readLine(f);
if (c[latIdx] == "") {
continue;
}
t = c[timeIdx];
i = Math.round(80*(t - strt)/dur);
p = Bangle.project({lat:c[latIdx],lon:c[lonIdx]});
@ -372,7 +376,6 @@ function plotGraph(info, style) {
}
lp = p;
lt = t;
l = f.readLine(f);
}
} else throw new Error("Unknown type "+style);
var min=100000,max=-100000;
@ -396,13 +399,15 @@ function plotGraph(info, style) {
height: g.getHeight()-(24+8),
axes : true,
gridy : grid,
gridx : 50,
gridx : infn.length / 3,
title: title,
miny: min,
maxy: max,
xlabel : x=>Math.round(x*dur/(60*infn.length))+" min" // minutes
});
g.setFont("6x8",2);
g.setFontAlign(0,0,3);
g.drawString("Back",230,200);
g.drawString("Back",g.getWidth() - 10, g.getHeight() - 40);
setWatch(function() {
viewTrack(info.filename, info);
}, global.BTN3||BTN1);

View File

@ -1 +1,2 @@
0.02: New App!
0.03: Improved messages and added Celsius sign

View File

@ -3,9 +3,9 @@ function onTemperature(p) {
g.setFont("6x8",2).setFontAlign(0,0);
var x = g.getWidth()/2;
var y = g.getHeight()/2 + 10;
g.drawString("Temperature", x, y - 45);
g.drawString("Temperature:", x, y - 45);
g.setFontVector(70).setFontAlign(0,0);
g.drawString(p.temperature.toFixed(1), x, y);
g.drawString(p.temperature.toFixed(1) + " °C", x, y);
}
function drawTemperature() {
@ -23,6 +23,6 @@ setInterval(function() {
drawTemperature();
}, 20000);
drawTemperature();
E.showMessage("Loading...");
E.showMessage("Reading temperature...");
Bangle.loadWidgets();
Bangle.drawWidgets();
Bangle.drawWidgets();

View File

@ -7,7 +7,7 @@ Usage:
// read a single app setting
value = require('Settings').get(appid, key, default);
// omit key to read all app settings
value = require('Settings').get();
value = require('Settings').get(appid);
// write a single app setting
require('Settings').set(appid, key, value)
// omit key and pass an object as values to overwrite all settings