From 860da909bf29cf57675e05a518c0767bf2c54343 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 13 Feb 2020 08:18:32 +0000 Subject: [PATCH] Added welcome app (fix #96) When installing default apps, update time --- apps.json | 16 ++- apps/boot/ChangeLog | 1 + apps/boot/bootloader.js | 41 +++--- apps/setting/ChangeLog | 1 + apps/setting/settings.js | 9 ++ apps/welcome/ChangeLog | 1 + apps/welcome/app-icon.js | 1 + apps/welcome/app.js | 266 +++++++++++++++++++++++++++++++++++++++ apps/welcome/app.json | 5 + apps/welcome/app.png | Bin 0 -> 1939 bytes defaultapps.json | 2 +- index.js | 2 + 12 files changed, 322 insertions(+), 23 deletions(-) create mode 100644 apps/welcome/ChangeLog create mode 100644 apps/welcome/app-icon.js create mode 100644 apps/welcome/app.js create mode 100644 apps/welcome/app.json create mode 100644 apps/welcome/app.png diff --git a/apps.json b/apps.json index 2a990e817..4dced39cf 100644 --- a/apps.json +++ b/apps.json @@ -2,7 +2,7 @@ { "id": "boot", "name": "Bootloader", "icon": "bootloader.png", - "version":"0.04", + "version":"0.05", "description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings", "tags": "tool,system", "storage": [ @@ -36,6 +36,18 @@ {"name":"*about","url":"app-icon.js","evaluate":true} ] }, + { "id": "welcome", + "name": "Welcome", + "icon": "app.png", + "version":"0.01", + "description": "Appears at first boot and explains how to use Bangle.js", + "tags": "", + "storage": [ + {"name":"+welcome","url":"app.json"}, + {"name":"-welcome","url":"app.js"}, + {"name":"*welcome","url":"app-icon.js","evaluate":true} + ] + }, { "id": "gbridge", "name": "Gadgetbridge", "icon": "app.png", @@ -67,7 +79,7 @@ { "id": "setting", "name": "Settings", "icon": "settings.png", - "version":"0.02", + "version":"0.03", "description": "A menu for setting up Bangle.js", "tags": "tool,system", "storage": [ diff --git a/apps/boot/ChangeLog b/apps/boot/ChangeLog index bfbbfd5cc..aebf43427 100644 --- a/apps/boot/ChangeLog +++ b/apps/boot/ChangeLog @@ -1,3 +1,4 @@ 0.02: Attempt to reset state of the interpreter better before loading an app 0.03: Fix issue switching clockfaces via menu 0.04: Add alarm functionality +0.05: Add Welcome screen on boot diff --git a/apps/boot/bootloader.js b/apps/boot/bootloader.js index e73e9c955..fc21ee60c 100644 --- a/apps/boot/bootloader.js +++ b/apps/boot/bootloader.js @@ -1,22 +1,23 @@ // This runs after a 'fresh' boot -var settings; -try { - settings = require("Storage").readJSON('@setting'); -} catch (e) { - settings = {} +var settings={}; +try { settings = require("Storage").readJSON('@setting'); } catch (e) {} +if (!settings.welcomed && require("Storage").read("-welcome")!==undefined) { + setTimeout(()=>load("-welcome")); +} else { + // load clock if specified + var clockApp = settings.clock; + if (clockApp) clockApp = require("Storage").read(clockApp) + if (!clockApp) { + var clockApps = require("Storage").list().filter(a=>a[0]=='+').map(app=>{ + try { return require("Storage").readJSON(app); } + catch (e) {} + }).filter(app=>app.type=="clock").sort((a, b) => a.sortorder - b.sortorder); + if (clockApps && clockApps.length > 0) + clockApp = require("Storage").read(clockApps[0].src); + delete clockApps; + } + if (clockApp) eval(clockApp); + else E.showMessage("No Clock Found"); + delete clockApp; } -// load clock if specified -var clockApp = settings.clock; -if (clockApp) clockApp = require("Storage").read(clockApp) -if (!clockApp) { - var clockApps = require("Storage").list().filter(a=>a[0]=='+').map(app=>{ - try { return require("Storage").readJSON(app); } - catch (e) {} - }).filter(app=>app.type=="clock").sort((a, b) => a.sortorder - b.sortorder); - if (clockApps && clockApps.length > 0) - clockApp = require("Storage").read(clockApps[0].src); - delete clockApps; -} -if (clockApp) eval(clockApp); -else E.showMessage("No Clock Found"); -delete clockApp; +delete settings; diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index bc5ccebb3..21d81d42c 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -1 +1,2 @@ 0.02: Add support for 30-minute timezones. +0.03: Add support for Welcome app diff --git a/apps/setting/settings.js b/apps/setting/settings.js index 9c7a490fb..e1f85f86a 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -21,6 +21,7 @@ function resetSettings() { clock: null, "12hour" : false, distance : "kilometer" // or "mile" + // welcomed : undefined/true (whether welcome app should show) }; Bangle.setLCDTimeout(settings.timeout); updateSettings(); @@ -87,6 +88,14 @@ function showMainMenu() { } } }, + 'Welcome App': { + value: !settings.welcomed, + format: boolFormat, + onchange: v => { + settings.welcomed = v?undefined:true; + updateSettings(); + } + }, 'Locale': showLocaleMenu, 'Select Clock': showClockMenu, 'HID': { diff --git a/apps/welcome/ChangeLog b/apps/welcome/ChangeLog new file mode 100644 index 000000000..efbc53fb0 --- /dev/null +++ b/apps/welcome/ChangeLog @@ -0,0 +1 @@ +0.00: New App! diff --git a/apps/welcome/app-icon.js b/apps/welcome/app-icon.js new file mode 100644 index 000000000..5c1373e17 --- /dev/null +++ b/apps/welcome/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/welcome/app.js b/apps/welcome/app.js new file mode 100644 index 000000000..0b7c76a0e --- /dev/null +++ b/apps/welcome/app.js @@ -0,0 +1,266 @@ +function animate(seq,period) { + var i = setInterval(function() { + if (seq.length) { + var f = seq.shift(); + if (f) f(); + } else clearInterval(i); + },period); +} + +var scenes = [ + 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() { + g.reset(); + g.setBgColor("#6633ff");g.clear(); + g.setFont("6x8",3); + g.setFontAlign(0,0); + g.drawString("Welcome.",120,160); + g.drawImage(require("heatshrink").decompress(atob("ptRxH+AEXMAAwrjJEhQ/JSRO7JaZN2Hg/N5/V6wAD6vOJxG6ywAB3QAEJdvO63XAApPE5oTE4BLCJo5PkJRnW5/NIwoFFJopMHJ0I0F6pKER4wALJtoyESwnWJSIAC3RNqS5PVJSYAB4xMNJrYvE56WD5xLVdCBNaFofNJbgABJhxNSsNhrYAC1IsD6xMCJbSaEJhZNOJIJLFrYrD5xLC6pLa5nGTThLDJhKYC6xLbc6JNKJQhMFv4pC5rkec7hLGw2r2XW1epcoqYeJiJNHJQuH2RBBw7lF56Yg5nGc6yVFJQPX2TmDFIfVTEBMXraWEJQPX1dhJg/W6/VJj/MJiBNEJYerJYhMKcr5MWTAeGJYpMIcwPNc2JMCS4eGRIPX1gIDJg/PJnTkC62GJg+oFIXO67lg4BMWcgeHJYZME0YpC5vWJkhLNJgKYHwpMIv4qD6pMg3RMSrZCC2RMB1ZLEJglbFQfO5pMfcqKZEcoeGJhzoBJb3GJiP+Jg2yJYpNF1LigAAXAJjLlGJgt/JkblTJgeHJhznFcuSZGw5MHJomjcuxMUTURLUJiuoTGpMDsOy6+rJhCalJapNEw5MQ1KYvJYv+rbnC62yJhKajTC6aE1fXwxMO0aY0JgmF2TnKTUHGJbJNEw2ywpMOJrRLDJhhLKJgZNBw6aPv5LX3RLbAANbJoaaKJoupJavAJbqbFABboF1BLYJhZLPTQhNlJZ5KQTSRNG0ZLzJrF/JZu6JZpKVJrKcM/xMEJUBNaDIJJGAARJlJrQYB4wAEJYgAEJD5OVJYpM2TiRLIJoRLtJyBLDJhJNGJlJOMcooAB0hJB0gHEJmBPHJIQADB4eI0mkxAHEy+Wz2eJl4AEJhYACA4mlA4pM4JoZMGAwZM2JotcTJRM/rbeFJhJL2AAWHrmBJn4AJHo4HFcvaSQJfxM/JiJGHcv6TMJf5M/c6gFEJn6aHJf5M/dDRM/JiRK/Jn5NZJP5M/JjBI/JphH/Jn5NYIv5M/Jn5NlIf5MJE8wA==")),(240-77)/2,60); + 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) { + sceneNumber = (sceneNumber+dir)%scenes.length; + if (sceneNumber<0) sceneNumber=0; + clearInterval(); + scenes[sceneNumber](); + if (sceneNumber>1) { + var l = scenes.length; + for (var i=0;imove(1), BTN3, {repeat:true}); +setWatch(()=>{ + // If we're on the last page + if (sceneNumber == scenes.length-1) { + try { + var settings = require("Storage").readJSON('@setting'); + settings.welcomed = true; + require("Storage").write('@setting',settings); + } catch (e) {} + load(); + } +}, BTN2, {repeat:true,edge:"rising"}); +setWatch(()=>move(-1), BTN1, {repeat:true}); + + + +Bangle.setLCDTimeout(0); +Bangle.setLCDPower(1); +move(0); diff --git a/apps/welcome/app.json b/apps/welcome/app.json new file mode 100644 index 000000000..584f9fc40 --- /dev/null +++ b/apps/welcome/app.json @@ -0,0 +1,5 @@ +{ + "name":"Welcome", + "icon":"*welcome", + "src":"-welcome" +} diff --git a/apps/welcome/app.png b/apps/welcome/app.png new file mode 100644 index 0000000000000000000000000000000000000000..ebbf254bd7c3546e8337c97648a7eb56747c81ac GIT binary patch literal 1939 zcmV;E2WP)^Vse?M*ABwfS z8MZ{CGrE{9Te8V!(51`XGM!;roJ%xW2E^g2NO{qXsim}(VOBaof>d5Dolx3xFQxb1 z-nZxMkEd_+KDRC9c8eL`e{OQldCvKM@9+H1@Ao`#6F2ey4asCOZNf#^U4iltNGVVP zD9{Fa2%!dFY=)EdIoSdkU1+ff<1#70}x@Hu6Kz{*xG?E@iS0CV6Z_UXTXX+c`#EfepLM z7bkj*!-~A7=*pg+Sbi*K%7RHf4giWO!Qq3`KOGl&fb97ejd1$m`W-Ff7CVP?6!NP@ z*#dZSJOwP6bwBxEm_^gcdS*L+X9eY#LFhPi?iv?)0Qct&s7(@2rVYtLc?9_Na7Wq| z*s!a7VL$mhO77$FB^z-&y=>gMfp-sY$1lBBpl3RC?8G{+#s}vNi$-#!6vBPB&)OMR zSFd&$bZt`bEWGtWzIxkQ4xXu@;q+gK#Us}SYaD|6$H%;%Ti;I9kp;}PGuy7fJm2Nj z3iFC{=TP>!hdI^J%>L8W066-F^;LCQ!M&eAbbP(vkK`q5{1_wcNTtxuZ2ySr8h}N& zRszc2md$8ii@03Y-n|s>8yCR?kc`--87pEZEdlP41PEPrX4^*;%A5{2vnS8zR7W$x z$ly8R&9b`gL{GM5xU>zNlg7h)0KF}J0vsa*DW~nsDFU8oDs=&cd09m`4HsuS|8}Go}cbc4m$MYKWCB5WaYg-fnm1w~?N@s{QIvQxc8y;|@aI_lzb}w~BisS# zemenx-!nLkY_L)4u$>fXwvAaIiTBWc+v}7`&~p6!uCs3uaov50-F-3g3k#a`wiTU zvP%9=C|wR)0Y87>{T;xe;}`am?ajxK)a*r5vJpf0+j$=?(bQEM4dHi_T)m(OP>_0! z1_+^4NFyyH<*{D@K^5csiY97XHdE-Io)Y4AJ18jdq6!;N6w__G$4oxaYSOXO>ixVd z+ws{6d|mcaH(IW=leb~(nby14&Nh=~ygVGcVjJW0xrjs(bVp2%hH_X~(1Taf-^c)x z7fdd^7$=di#^z*S%ALL$;a+Lr=xF3e6aY{@cU@z0T5E~G9qD5HeiuEVI9(y3DL9Gw z1yOPg`+ITpuxVa+DK3e)^{?OJ2V;=^WrSx4^Q0WKKXvUe>I+R(Rh1DhZFp7C$I`_l zlS*4#H@%Sr4uO?(LjPWs*V=<2)&jK*IPU`jS>z$Ju_P`2WvTIvXn zmH3zi^y9hR%brk`mjK)IQWZKoBLssHEiBBw=l9z94dC&#M}GJIl*eYU7cZ~QEIAx*jx#4V*6tXFt75D0`S3i z9}Y}9+K^{NLmzuXR~F6skih>$z;LX3{!6Pxw0a<^>ZsE89`|RJp-`2xV9n22`K4{uPal12c#LV76{gFJ8nP!- zaw36avkT_Uy!ZAWT)neo#k6g;jWdVG2vqd_X5^b_KQbcVPgUo7pa0hDpH9h{^Jkwc z-!McT8S3Bl{(_CIEp)Rdry0B}FR$L8xE8Y*}X}Yi3ly zimxsC2XF#(_RiV^WkXzj?IRg&AIPu(06{kcC_FmEycEFvEC@)5a|@6}ST)4#1`by) zyX#!0>t$TP%4Lh%RHy~~L+v8eWV#kifB-A0ZW?Y&s`=Rw5cL>u!8JF_b1TZrj!Z7V#$X$n89sf7V!{MeE?v?nqF**mb8fyw8z-vHP29u{ Z;y>o9o!*JS4-fzV002ovPDHLkV1gG+pke?3 literal 0 HcmV?d00001 diff --git a/defaultapps.json b/defaultapps.json index 6f6c4aa00..02a8a2392 100644 --- a/defaultapps.json +++ b/defaultapps.json @@ -1 +1 @@ -["boot","launch","mclock","setting","alarm","sbat","sbt"] +["boot","launch","mclock","setting","alarm","sbat","sbt","welcome"] diff --git a/index.js b/index.js index 931e47777..ad1c1aff8 100644 --- a/index.js +++ b/index.js @@ -541,6 +541,8 @@ document.getElementById("installdefault").addEventListener("click",event=>{ } upload(); }); + }).then(()=>{ + return Comms.setTime(); }).then(()=>{ showToast("Default apps successfully installed!","success"); return getInstalledApps();