diff --git a/apps.json b/apps.json
index b1963974b..7fa521098 100644
--- a/apps.json
+++ b/apps.json
@@ -118,6 +118,24 @@
{"name":"welcome.json"}
]
},
+ { "id": "mywelcome",
+ "name": "Customised Welcome",
+ "shortName": "My Welcome",
+ "icon": "app.png",
+ "version":"0.10",
+ "description": "Appears at first boot and explains how to use Bangle.js. Like 'Welcome', but can be customised with a greeting",
+ "tags": "start,welcome",
+ "custom":"custom.html",
+ "storage": [
+ {"name":"mywelcome.boot.js","url":"boot.js"},
+ {"name":"mywelcome.app.js","url":"app.js"},
+ {"name":"mywelcome.settings.js","url":"settings.js"},
+ {"name":"mywelcome.img","url":"app-icon.js","evaluate":true}
+ ],
+ "data": [
+ {"name":"mywelcome.json"}
+ ]
+ },
{ "id": "gbridge",
"name": "Gadgetbridge",
"icon": "app.png",
@@ -1718,7 +1736,7 @@
"id": "simpletimer",
"name": "Timer",
"icon": "app.png",
- "version": "0.05",
+ "version": "0.07",
"description": "Simple timer, useful when playing board games or cooking",
"tags": "timer",
"readme": "README.md",
@@ -1940,8 +1958,8 @@
"name": "Vertical watch face",
"shortName":"Vertical Face",
"icon": "app.png",
- "version":"0.06",
- "description": "A simple vertical watch face with the date.",
+ "version":"0.07",
+ "description": "A simple vertical watch face with the date. Heart rate monitor is toggled with BTN1",
"tags": "clock",
"type":"clock",
"allow_emulator":true,
diff --git a/apps/mywelcome/ChangeLog b/apps/mywelcome/ChangeLog
new file mode 100644
index 000000000..15a286604
--- /dev/null
+++ b/apps/mywelcome/ChangeLog
@@ -0,0 +1,14 @@
+0.01: New App!
+0.02: Animate balloon intro
+0.03: BTN3 now won't restart when at the end
+0.04: Fix regression after tweaks to Storage.readJSON
+0.05: Move configuration into App/widget settings
+0.06: Move loader into welcome.boot.js
+0.07: Run again when updated
+ Don't run again when settings app is updated (or absent)
+ Add "Run Now" option to settings
+0.08: Don't overwrite existing settings on app update
+0.09: Allow welcome to run after a fresh install
+ More useful app menu
+ BTN2 now goes to menu on release
+0.10: Add birthday style
diff --git a/apps/mywelcome/app-icon.js b/apps/mywelcome/app-icon.js
new file mode 100644
index 000000000..5c1373e17
--- /dev/null
+++ b/apps/mywelcome/app-icon.js
@@ -0,0 +1 @@
+require("heatshrink").decompress(atob("mEwxH+AH4A/AH4AU5gAEFtoxnEwXN53WAAXO5oJB42Wy26AAIueFoPXFggAD4AwEGTQiB6otBFgwAD3QvFGC5dCFxiRGGClhrdbv67BXAIuLMBIwPsIABF4OpLwXOFxjBCF6gtBw2r1mHXoXWFxqQWFwOH62rL4IeB6xeOAAIvHGBYuC6+rR4QvCXpovXw3X1i/DR4QuPR5AvKFQOs6+GF4eod4IvPd5AvLwvWLwQvCv4fBR54vURwOHF4iQCX0yOCF4aQBX0QvHSAoAN3SOSd4WyF4yQPLyhgD1YvDMCJeIFxhgCF47BN4BeHFxpgDSAiRORpAuPMIYAFGBYuaF5aSHFwQvEFqQwOeggSBLa4xNF4X+4wAC/xeCFjIADrYwGBIIvlMQiPDBAOk0gDBz2XF8BlEF4eIxADFF8lcF9n+wIrFF05bHF9AsGF9wupGAYv/F8QupGAov/F/4wOF1gA/AH4Ap"))
diff --git a/apps/mywelcome/app.js b/apps/mywelcome/app.js
new file mode 100644
index 000000000..23cdd0d49
--- /dev/null
+++ b/apps/mywelcome/app.js
@@ -0,0 +1,298 @@
+// exec each function from seq one after the other
+function animate(seq,period) {
+ var i = setInterval(function() {
+ if (seq.length) {
+ var f = seq.shift();
+ if (f) f();
+ } else clearInterval(i);
+ },period);
+}
+
+// Fade in to FG color with angled lines
+function fade(col, callback) {
+ var n = 0;
+ function f() {
+ g.setColor(col);
+ for (var i=n;i<240;i+=10) {
+ g.drawLine(i,0,0,i).drawLine(i,240,240,i);
+ }
+ g.flip();
+ n++;
+ if (n<10) setTimeout(f,0);
+ else callback();
+ }
+ f();
+}
+
+
+var scenes = [
+ function() {
+ console.log("Start app");
+ g.clear(1);
+ eval(require("Storage").read("mywelcome.custom.js"));
+ },function() {
+ g.clear(1);
+ g.setFont("4x6",2);
+ var n=0;
+ var i = setInterval(function() {
+ n+=0.04;
+ g.setColor(n,n,n);
+ g.drawImage(Bangle.getLogo(),(240-222)/2,(240-100)/2);
+ if (n>=1) {
+ clearInterval(i);
+ setTimeout(()=>g.drawString("Open",34,144), 500);
+ setTimeout(()=>g.drawString("Hackable",34,156), 1000);
+ setTimeout(()=>g.drawString("Smart Watch",34,168), 1500);
+ }
+ },50);
+ },function() {
+ var img = require("heatshrink").decompress(atob("ptRxH+qYAfvl70mj5gAC0ekvd8FkAAdz3HJAYAH4+eJXWkJJYAF0hK2vfNJaIAB5t7S3fN5/V6wAD6vOTg9SumXy2W3QAB3eXul2JdnO63XAApPEVYvAJQIACJoRQDzBLoJQ3W5/NIwr4GJohMFAAROgJYvVJQiPGABZNN3bsdvYyESwnWJSIAC3RNM3V1JjZAES4nVJSYAB4xMNJrbkE56WD5xLVdB5NbFofNJbgABJh26qREPrFXrlbAAWjFgfWJgRLaTQhMLy5KNJINhsJLDrYrD5xLC6pLa5nGTR7oLq9bJQJMKTAXWJbbnR3RLJSoRMHv4pC5rkec6SaIrBLGw2r2XW1epcoqYeJiOXJYziEsOH2RBBw7lF56Yg5nGc6FScZOGJQPX2TmDFIfVTEBMSc4hLEw5KB6+rsJMH63X6pMf5hMQzBLCq5LD1ZLEJhTlfJiWXTA2GJYpMIcwPNc2O6TAuGRIPX1igDJg/PJmyYDcgXWwxMH1ApC53XcsHAJiVYcg2HJYZME0YpC5vWJkhLNJgLlDTAeFJhF/FQfVJkG6JiGXcomyJgOrJYhMErYqD53NJj7lRzBMDcoeGJhzoBJb3GJiN1qZBCJgWyJYpNF1LigAAXAJiNSJgzlGJgt/JkZLRy9TJgeHJhznFcuSZGw5MHJomjcuhLBqdcJiSaiTChMV1CYxy5LCqdXIAWy6+rJhCalTCN2JgdYH4WHJiGpTF7kDc43W2RMJTUZLQzBLFc4mr6+GJh2jTFmXJYyaEwuyc5Sag4xLZTQmG2WFJhxNaJYZMLJZSaEJoOHTR9/Ja+6JbdTqRNETRRNF1JLV4BLcAANYI5ToK1BLYJhWYJZwABq5NoJZ91JaAABdAZNS0ZLey9SJaRNYv5KM426JZmXuxKUJrKcL0lTzBLKzBKYJrVXvfGSol7EYWXJI27zF1JLQADq5NUrgYB4wAEEIV0comXI7wAFrCcPJgYWBTIIAETIN2JYmWuhMkdSdYCgOeJgueqRLFyzhfTi9bq4TC45MF49TuuXJlpONcogAC0hKB0gHDvZMEqRMpAANSq9crlbJAYADqwRDxGk0mIA4eCTQOeveXJdYAHqxNFdAeIAAQGCrOI0oHEAGVXTRJMGvgGCwRM7TAZMHwQGCvhM1rBMERIhMGAwdZJmtSqVTwNcwJEDJg19cvIADa4d9JhANDJnSLHJgrl6AAhFFAwpZDegjn7vhMGcvwABrJAFJgjl/TQpBBI4jl/AAN8TQhHDcv4ADcJBMDvpM+IYaeDAAhL+qd9SgycEJn7iEAA18Jf7nEcv4AIrJLIcv6aMcv4ADvhMHrJJ/AAbl/c6ZM/AAt9cv7nSIv7nLcv4AHrLl/TRpJBvgnjA=="));
+ g.reset();
+ g.setBgColor("#6633ff");
+ var y = 240, speed = 5;
+ function balloon(callback) {
+ y-=speed;
+ var x = (240-77)/2;
+ g.drawImage(img,x,y);
+ g.clearRect(x,y+81,x+77,y+81+speed);
+ if (y>60) setTimeout(balloon,0,callback);
+ else callback();
+ }
+ fade("#6633ff", function() {
+ balloon(function() {
+ g.setColor(-1);
+ g.setFont("6x8",3);
+ g.setFontAlign(0,0);
+ g.drawString("Welcome.",120,160);
+ });
+ });
+ setTimeout(function() {
+ var n=0;
+ var i = setInterval(function() {
+ n+=5;
+ g.scroll(0,-5);
+ if (n>170)
+ clearInterval(i);
+ },20);
+ },3500);
+
+ },function() {
+ g.reset();
+ g.setBgColor("#ffa800");g.clear();
+ g.setFont("6x8",2);
+ g.setFontAlign(0,0);
+ var x = 80, y = 35, h=35;
+ animate([
+ ()=>g.drawString("Your",x,y+=h),
+ ()=>g.drawString("Bangle.js",x,y+=h),
+ ()=>g.drawString("has",x,y+=h),
+ ()=>g.drawString("3 buttons",x,y+=h),
+ ()=>{g.setFont("Vector",36);g.drawString("1",200,40);},
+ ()=>g.drawString("2",200,120),
+ ()=>g.drawString("3",200,200)
+ ],200);
+ },
+ function() {
+ g.reset();
+ g.setBgColor("#00a8ff");g.clear();
+ g.setFontAlign(0,0);
+ g.setFont("Vector",48);
+ g.drawString("1",200,40);
+ g.setFontAlign(-1,-1);
+ g.setFont("6x8",2);
+ g.drawString("Move up\nin menus\n\nTurn Bangle.js on\nif it was off", 20,40);
+ },
+ function() {
+ g.reset();
+ g.setBgColor("#00a8ff");g.clear();
+ g.setFontAlign(0,0);
+ g.setFont("Vector",48);
+ g.drawString("2",200,120);
+ g.setFontAlign(-1,-1);
+ g.setFont("6x8",2);
+ g.drawString("Select menu\nitem\n\nLaunch app\nwhen watch\nis showing", 20,70);
+ },
+ function() {
+ g.reset();
+ g.setBgColor("#00a8ff");g.clear();
+ g.setFontAlign(0,0);
+ g.setFont("Vector",48);
+ g.drawString("3",200,200);
+ g.setFontAlign(-1,-1);
+ g.setFont("6x8",2);
+ g.drawString("Move down\nin menus\n\nLong press\nto exit app\nand go back\nto clock", 20,100);
+ },
+ function() {
+ g.reset();
+ g.setBgColor("#ff3300");g.clear();
+ g.setFontAlign(0,0);
+ g.setFont("Vector",48);
+ g.drawString("1",200,40);
+ g.drawString("2",200,120);
+ g.setFontAlign(-1,-1);
+ g.setFont("6x8",2);
+ g.drawString("If Bangle.js\never stops,\nhold buttons\n1 and 2 for\naround six\nseconds.\n\n\n\nBangle.js will\nthen reboot.", 20,20);
+ },
+ function() {
+ g.reset();
+ g.setBgColor("#00a8ff");g.clear();
+ g.setFont("6x8",2);
+ g.setFontAlign(0,0);
+ var x = 120, y = 10, h=21;
+ animate([
+ ()=>{g.drawString("Bangle.js has a",x,y+=h);
+ g.drawString("simple touchscreen",x,y+=h);},
+ 0,0,
+ ()=>{g.drawString("It'll detect touch",x,y+=h*2);
+ g.drawString("on left and right",x,y+=h);},
+ 0,0,
+ ()=>{g.drawString("Horizontal swipes",x,y+=h*2);
+ g.drawString("work too. Try now",x,y+=h);
+ g.drawString("to change page.",x,y+=h);}
+ ],300);
+ },
+ function() {
+ g.reset();
+ g.setBgColor("#339900");g.clear();
+ g.setFont("6x8",2);
+ g.setFontAlign(0,0);
+ var x = 120, y = 10, h=21;
+ animate([
+ ()=>{g.drawString("Bangle.js",x,y+=h);
+ g.drawString("comes with",x,y+=h);
+ g.drawString("a few simple",x,y+=h);
+ g.drawString("apps installed",x,y+=h);},
+ 0,0,
+ ()=>{g.drawString("To add more, visit",x,y+=h*2);
+ g.drawString("banglejs.com/apps",x,y+=h);
+ g.drawString("with a Bluetooth",x,y+=h);
+ g.drawString("capable device",x,y+=h);},
+ ],400);
+ },
+ function() {
+ g.reset();
+ g.setBgColor("#990066");g.clear();
+ g.setFont("6x8",2);
+ g.setFontAlign(0,0);
+ var x = 120, y = 10, h=21;
+ g.drawString("You can also make",x,y+=h);
+ g.drawString("your own apps!",x,y+=h);
+ y=160;
+ g.drawString("Check out",x,y+=h);
+ g.drawString("banglejs.com",x,y+=h);
+
+ var rx = 0, ry = 0;
+ var h = Graphics.createArrayBuffer(96,96,1,{msb:true});
+ // draw a cube
+ function draw() {
+ // rotate
+ rx += 0.1;
+ ry += 0.11;
+ var rcx=Math.cos(rx),
+ rsx=Math.sin(rx),
+ rcy=Math.cos(ry),
+ rsy=Math.sin(ry);
+ // Project 3D coordinates into 2D
+ function p(x,y,z) {
+ var t;
+ t = x*rcy + z*rsy;
+ z = z*rcy - x*rsy;
+ x=t;
+ t = y*rcx + z*rsx;
+ z = z*rcx - y*rsx;
+ y=t;
+ z += 4;
+ return [96*(0.5+x/z), 96*(0.5+y/z)];
+ }
+
+ var a;
+ // draw a series of lines to make up our cube
+ h.clear();
+ a = p(-1,-1,-1); h.moveTo(a[0],a[1]);
+ a = p(1,-1,-1); h.lineTo(a[0],a[1]);
+ a = p(1,1,-1); h.lineTo(a[0],a[1]);
+ a = p(-1,1,-1); h.lineTo(a[0],a[1]);
+ a = p(-1,-1,-1); h.lineTo(a[0],a[1]);
+ a = p(-1,-1,1); h.moveTo(a[0],a[1]);
+ a = p(1,-1,1); h.lineTo(a[0],a[1]);
+ a = p(1,1,1); h.lineTo(a[0],a[1]);
+ a = p(-1,1,1); h.lineTo(a[0],a[1]);
+ a = p(-1,-1,1); h.lineTo(a[0],a[1]);
+ a = p(-1,-1,-1); h.moveTo(a[0],a[1]);
+ a = p(-1,-1,1); h.lineTo(a[0],a[1]);
+ a = p(1,-1,-1); h.moveTo(a[0],a[1]);
+ a = p(1,-1,1); h.lineTo(a[0],a[1]);
+ a = p(1,1,-1); h.moveTo(a[0],a[1]);
+ a = p(1,1,1); h.lineTo(a[0],a[1]);
+ a = p(-1,1,-1); h.moveTo(a[0],a[1]);
+ a = p(-1,1,1); h.lineTo(a[0],a[1]);
+ g.drawImage({width:96,height:96,buffer:h.buffer},(240-96)/2,68);
+ }
+
+ setInterval(draw,50);
+ },
+ function() {
+ g.reset();
+ g.setBgColor("#660099");g.clear();
+ g.setFontAlign(0,0);
+ g.setFont("Vector",36);
+ g.drawString("2",200,120);
+ g.setFont("6x8",2);
+
+ var x = 90, y = 30, h=21;
+ animate([
+ ()=>g.drawString("That's it!",x,y+=h),
+ ()=>{g.drawString("Press",x,y+=h*3);
+ g.drawString("Button 2",x,y+=h);
+ g.drawString("to start",x,y+=h);
+ g.drawString("Bangle.js",x,y+=h);}
+ ],400);
+ }
+];
+
+var sceneNumber = 0;
+
+function move(dir) {
+ if (dir>0 && sceneNumber+1 == scenes.length) return; // at the end
+ sceneNumber = (sceneNumber+dir)%scenes.length;
+ if (sceneNumber<0) sceneNumber=0;
+ clearInterval();
+ Bangle.setLCDMode();
+ g.clear();
+ scenes[sceneNumber]();
+ if (sceneNumber>2) {
+ var l = scenes.length;
+ for (var i=0;i Style:
+
Line 1:
+Line 2:
+Line 3 (smaller):
+Line 4 (smaller):
+ + + +This is currently Christmas-themed, but more themes will be added in the future.
+ + + + + + diff --git a/apps/mywelcome/settings.js b/apps/mywelcome/settings.js new file mode 100644 index 000000000..cf7208d65 --- /dev/null +++ b/apps/mywelcome/settings.js @@ -0,0 +1,18 @@ +(function(back) { + let settings = require('Storage').readJSON('mywelcome.json', 1) + || require('Storage').readJSON('setting.json', 1) || {} + E.showMenu({ + '': { 'title': 'Welcome App' }, + 'Run next boot': { + value: !settings.welcomed, + format: v => v ? 'Yes' : 'No', + onchange: v => require('Storage').write('mywelcome.json', {welcomed: !v}), + }, + 'Run Now': () => load('mywelcome.app.js'), + 'Turn off & run next': () => { + require('Storage').write('mywelcome.json', {welcomed: false}); + Bangle.off(); + }, + '< Back': back, + }) +}) diff --git a/apps/simpletimer/ChangeLog b/apps/simpletimer/ChangeLog index e548d90fa..f1f3a1ec0 100644 --- a/apps/simpletimer/ChangeLog +++ b/apps/simpletimer/ChangeLog @@ -3,3 +3,5 @@ 0.03: BTN2 to open launcher 0.04: Remember last set time 0.05: Fix buzz that doesn't stop (fix #521) +0.06: Fix buzz error, remove '+' when timer running and add 'back' text (fix #577) +0.07: Fix buzz regression from 0.06 diff --git a/apps/simpletimer/app.js b/apps/simpletimer/app.js index 75c118980..e99761810 100644 --- a/apps/simpletimer/app.js +++ b/apps/simpletimer/app.js @@ -1,15 +1,19 @@ let counter = 0; let setValue = 0; -let counterInterval; +let counterInterval, alarmInterval, buzzInterval; let state; let saved = require("Storage").readJSON("simpletimer.json",true) || {}; const DEBOUNCE = 50; function buzzAndBeep() { + buzzInterval = -1; return Bangle.buzz(1000, 1) .then(() => Bangle.beep(200, 3000)) - .then(() => setTimeout(buzzAndBeep, 5000)); + .then(() => { + if (buzzInterval==-1) + buzzInterval = setTimeout(buzzAndBeep, 5000); + }); } function outOfTime() { @@ -19,7 +23,8 @@ function outOfTime() { g.drawString("Time UP!", 120, 50); counter = setValue; buzzAndBeep(); - setInterval(() => { + if (alarmInterval) clearInterval(alarmInterval); + alarmInterval = setInterval(() => { g.clearRect(0, 70, 220, 160); setTimeout(draw, 200); }, 400); @@ -55,8 +60,12 @@ function countDown() { } function clearIntervals() { - clearInterval(); + if (alarmInterval) clearInterval(alarmInterval); + if (counterInterval) clearInterval(counterInterval); + if (buzzInterval>0) clearTimeout(buzzInterval); + alarmInterval = undefined; counterInterval = undefined; + buzzInterval = undefined; } function set(delta) { @@ -93,16 +102,21 @@ const stateMap = { function changeState() { if (stateMap[state]) stateMap[state](); + drawLabels(); + draw(); } function drawLabels() { g.clear(); g.setFontAlign(-1, 0); g.setFont("6x8", 7); - g.drawString(`+ +`, 35, 180); + if (state != "started") // only when not runnung + g.drawString(`+ +`, 35, 180); g.setFontAlign(0, 0, 3); g.setFont("6x8", 1); - g.drawString(`reset (re)start`, 230, 120); + g.drawString("Reset (re)start", 230, 120); + if (state != "started") // only when not runnung + g.drawString("Back", 230, 120); } function resetTimer(value) { @@ -130,8 +144,7 @@ function addWatch() { { repeat: false, edge: "falling", - }, - ); + }); setWatch( () => { resetTimer(0); diff --git a/apps/verticalface/ChangeLog b/apps/verticalface/ChangeLog index 4ba4f7ec4..e26120599 100644 --- a/apps/verticalface/ChangeLog +++ b/apps/verticalface/ChangeLog @@ -1,3 +1,4 @@ 0.04: Fixed day being displayed 0.05: Stop hours being displayed wrong if moving from 2 digits to 1 (fix #516) 0.06: Tweak sizing to allow widgets at top, and add widgets (fix #567) +0.07: Added leading zero to hours and minutes diff --git a/apps/verticalface/app.js b/apps/verticalface/app.js index 8503265ca..f9138335f 100644 --- a/apps/verticalface/app.js +++ b/apps/verticalface/app.js @@ -6,6 +6,14 @@ let currentHRM = "CALC"; function drawTimeDate() { var d = new Date(); var h = d.getHours(), m = d.getMinutes(), day = d.getDate(), month = d.getMonth(), weekDay = d.getDay(); + + if (h < 10) { + h = "0" + h; + } + + if (m < 10) { + m = "0" + h; + } var daysOfWeek = ["SUN", "MON", "TUE","WED","THU","FRI","SAT"]; var hours = (" "+h).substr(-2);