From fa090ff8da6108f9f1e879fe27ae985620dee26a Mon Sep 17 00:00:00 2001 From: Andrei Georgian CRISTINESCU Date: Thu, 14 Nov 2019 21:45:04 +0200 Subject: [PATCH 01/15] [app] promodoro --- apps.json | 13 ++ apps/apps.json | 519 ++++++++++++++++++++++++++++++++++++++++++++ apps/promodoro.js | 240 ++++++++++++++++++++ apps/promodoro.json | 5 + apps/promodoro.png | Bin 0 -> 2122 bytes 5 files changed, 777 insertions(+) create mode 100644 apps/apps.json create mode 100644 apps/promodoro.js create mode 100644 apps/promodoro.json create mode 100644 apps/promodoro.png diff --git a/apps.json b/apps.json index f2cb1a27a..978f28060 100644 --- a/apps.json +++ b/apps.json @@ -502,5 +502,18 @@ {"name": "-gpsinfo","url": "gps-info.js"}, {"name": "*gpsinfo","url": "gps-info-icon.js","evaluate": true} ] + }, + { + "id": "promodoro", + "name":"Promodoro", + "icon":"promodoro.png", + "description": "A simple promodoro timer.", + "tags": "promodoro", + "type": "app", + "storage": [ + {"name": "+promodoro","url": "promodoro.json"}, + {"name": "-promodoro","url": "promodoro.js"}, + {"name": "*promodoro","url": "promodoro.js","evaluate": true} + ] } ] diff --git a/apps/apps.json b/apps/apps.json new file mode 100644 index 000000000..978f28060 --- /dev/null +++ b/apps/apps.json @@ -0,0 +1,519 @@ +[ + { "id": "boot", + "name": "Bootloader", + "icon": "bootloader.png", + "description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings", + "tags": "tool,system", + "storage": [ + {"name":".bootcde","url":"bootloader.js"} + ], + "sortorder" : -10 + }, + { "id": "mclock", + "name": "Morphing Clock", + "icon": "clock-morphing.png", + "description": "7 segment clock that morphs between minutes and hours", + "tags": "clock", + "type":"clock", + "storage": [ + {"name":"+mclock","url":"clock-morphing.json"}, + {"name":"-mclock","url":"clock-morphing.js"}, + {"name":"*mclock","url":"clock-morphing-icon.js","evaluate":true} + ], + "sortorder" : -9 + }, + { "id": "setting", + "name": "Settings", + "icon": "settings.png", + "description": "A menu for setting up Bangle.js - by default this disables Bluetooth unless you enable 'BLE' AND 'Dev'", + "tags": "tool,system", + "storage": [ + {"name":"+setting","url":"settings.json"}, + {"name":"-setting","url":"settings.js"}, + {"name":"=setting","url":"settings-init.js"}, + {"name":"@setting","url":"settings-default.json","evaluate":true}, + {"name":"*setting","url":"settings-icon.js","evaluate":true} + ], + "sortorder" : -2 + }, + { "id": "wclock", + "name": "Word Clock", + "icon": "clock-word.png", + "description": "Display Time as Text", + "tags": "clock", + "type":"clock", + "storage": [ + {"name":"+wclock","url":"clock-word.json"}, + {"name":"-wclock","url":"clock-word.js"}, + {"name":"*wclock","url":"clock-word-icon.js","evaluate":true} + ] + }, + { "id": "aclock", + "name": "Analog Clock", + "icon": "clock-analog.png", + "description": "An Analog Clock", + "tags": "clock", + "type":"clock", + "storage": [ + {"name":"+aclock","url":"clock-analog.json"}, + {"name":"-aclock","url":"clock-analog.js"}, + {"name":"*aclock","url":"clock-analog-icon.js","evaluate":true} + ] + }, + { "id": "trex", + "name": "T-Rex", + "icon": "trex.png", + "description": "T-Rex game in the style of Chrome's offline game", + "tags": "game", + "storage": [ + {"name":"+trex","url":"trex.json"}, + {"name":"-trex","url":"trex.js"}, + {"name":"*trex","url":"trex-icon.js","evaluate":true} + ] + }, + { "id": "astroid", + "name": "Asteroids!", + "icon": "asteroids.png", + "description": "Retro asteroids game", + "tags": "game", + "storage": [ + {"name":"+astroid","url":"asteroids.json"}, + {"name":"-astroid","url":"asteroids.js"}, + {"name":"*astroid","url":"asteroids-icon.js","evaluate":true} + ] + }, + { "id": "clickms", + "name": "Click Master", + "icon": "click-master.png", + "description": "Get several friends to start the game, then compete to see who can press BTN1 the most!", + "tags": "game", + "storage": [ + {"name":"+clickms","url":"click-master.json"}, + {"name":"-clickms","url":"click-master.js"}, + {"name":"*clickms","url":"click-master-icon.js","evaluate":true} + ] + }, + { "id": "horsey", + "name": "Horse Race!", + "icon": "horse-race.png", + "description": "Get several friends to start the game, then compete to see who can press BTN1 the most!", + "tags": "game", + "storage": [ + {"name":"+horsey","url":"horse-race.json"}, + {"name":"-horsey","url":"horse-race.js"}, + {"name":"*horsey","url":"horse-race-icon.js","evaluate":true} + ] + }, + { "id": "compass", + "name": "Compass", + "icon": "compass.png", + "description": "Simple compass that points North", + "tags": "tool,outdoors", + "storage": [ + {"name":"+compass","url":"compass.json"}, + {"name":"-compass","url":"compass.js"}, + {"name":"*compass","url":"compass-icon.js","evaluate":true} + ] + }, + { "id": "gpstime", + "name": "GPS Time", + "icon": "gpstime.png", + "description": "Update the Bangle.js's clock based on the time from the GPS receiver", + "tags": "tool", + "storage": [ + {"name":"+gpstime","url":"gpstime.json"}, + {"name":"-gpstime","url":"gpstime.js"}, + {"name":"*gpstime","url":"gpstime-icon.js","evaluate":true} + ] + }, + { "id": "openloc", + "name": "Open Location / Plus Codes", + "icon": "openlocation.png", + "description": "Convert your current GPS location to a series of characters", + "tags": "tool,outdoors", + "storage": [ + {"name":"+openloc","url":"openlocation.json"}, + {"name":"-openloc","url":"openlocation.js","evaluate":true} + ] + }, + { "id": "speedo", + "name": "Speedo", + "icon": "speedo.png", + "description": "Show the current speed according to the GPS", + "tags": "tool,outdoors", + "storage": [ + {"name":"+speedo","url":"speedo.json"}, + {"name":"-speedo","url":"speedo.js"}, + {"name":"*speedo","url":"speedo-icon.js","evaluate":true} + ] + }, + { "id": "slevel", + "name": "Spirit Level", + "icon": "spiritlevel.png", + "description": "Show the current angle of the watch, so you can use it to make sure something is absolutely flat", + "tags": "tool", + "storage": [ + {"name":"+slevel","url":"spiritlevel.json"}, + {"name":"-slevel","url":"spiritlevel.js"}, + {"name":"*slevel","url":"spiritlevel-icon.js","evaluate":true} + ] + }, + { "id": "files", + "name": "App Manager", + "icon": "files.png", + "description": "Show currently installed apps, free space, and allow their deletion from the watch", + "tags": "tool,system", + "storage": [ + {"name":"+files","url":"files.json"}, + {"name":"-files","url":"files.js"}, + {"name":"*files","url":"files-icon.js","evaluate":true} + ] + }, + { "id": "sbat", + "name": "Battery Level Widget", + "icon": "widget-battery.png", + "description": "Show the current battery level and charging status in the top right of the clock", + "tags": "widget,battery", + "type":"widget", + "storage": [ + {"name":"+sbat","url":"widget-battery.json"}, + {"name":"=sbat","url":"widget-battery.js"} + ] + }, + { "id": "sbt", + "name": "Bluetooth Widget", + "icon": "widget-bluetooth.png", + "description": "Show the current Bluetooth connection status in the top right of the clock", + "tags": "widget,bluetooth", + "type":"widget", + "storage": [ + {"name":"+sbt","url":"widget-bluetooth.json"}, + {"name":"=sbt","url":"widget-bluetooth.js"} + ] + }, + { "id": "hrm", + "name": "Heart Rate Monitor", + "icon": "heartrate.png", + "description": "Measure your current heart rate", + "tags": "health", + "storage": [ + {"name":"+hrm","url":"heartrate.json"}, + {"name":"-hrm","url":"heartrate.js"}, + {"name":"*hrm","url":"heartrate-icon.js","evaluate":true} + ] + }, + { "id": "swatch", + "name": "Stopwatch", + "icon": "stopwatch.png", + "description": "Simple stopwatch with Lap Time recording", + "tags": "health", + "storage": [ + {"name":"+swatch","url":"stopwatch.json"}, + {"name":"-swatch","url":"stopwatch.js"}, + {"name":"*swatch","url":"stopwatch-icon.js","evaluate":true} + ] + }, + { "id": "hidmsic", + "name": "Bluetooth Music Controls", + "icon": "hid-music.png", + "description": "Enable HID in settings, pair with your phone, then use this app to control music from your watch!", + "tags": "bluetooth", + "storage": [ + {"name":"+hidmsic","url":"hid-music.json"}, + {"name":"-hidmsic","url":"hid-music.js"}, + {"name":"*hidmsic","url":"hid-music-icon.js","evaluate":true} + ] + }, + { "id": "hidkbd", + "name": "Bluetooth Keyboard", + "icon": "hid-keyboard.png", + "description": "Enable HID in settings, pair with your phone/PC, then use this app to control other apps", + "tags": "bluetooth", + "storage": [ + {"name":"+hidkbd","url":"hid-keyboard.json"}, + {"name":"-hidkbd","url":"hid-keyboard.min.js"}, + {"name":"*hidkbd","url":"hid-keyboard-icon.js","evaluate":true} + ] + }, + { "id": "hidbkbd", + "name": "Binary Bluetooth Keyboard", + "icon": "hid-binary-keyboard.png", + "description": "Enable HID in settings, pair with your phone/PC, then type messages using the onscreen keyboard by tapping repeatedly on the key you want", + "tags": "bluetooth", + "storage": [ + {"name":"+hidbkbd","url":"hid-binary-keyboard.json"}, + {"name":"-hidbkbd","url":"hid-binary-keyboard.js"}, + {"name":"*hidbkbd","url":"hid-binary-keyboard-icon.js","evaluate":true} + ] + }, + { "id": "animals", + "name": "Animals Game", + "icon": "animals.png", + "description": "Simple toddler's game - displays a different number of animals each time the screen is pressed", + "tags": "game", + "storage": [ + {"name":"+animals","url":"animals.json"}, + {"name":"-animals","url":"animals.js"}, + {"name":"*animals","url":"animals-icon.js","evaluate":true}, + {"name":"*snake","url":"animals-snake.js","evaluate":true}, + {"name":"*duck","url":"animals-duck.js","evaluate":true}, + {"name":"*swan","url":"animals-swan.js","evaluate":true}, + {"name":"*fox","url":"animals-fox.js","evaluate":true}, + {"name":"*camel","url":"animals-camel.js","evaluate":true}, + {"name":"*pig","url":"animals-pig.js","evaluate":true}, + {"name":"*sheep","url":"animals-sheep.js","evaluate":true}, + {"name":"*mouse","url":"animals-mouse.js","evaluate":true} + ], + "sortorder" : 1 + }, + { "id": "qrcode", + "name": "Custom QR Code", + "icon": "qrcode.png", + "description": "Use this to upload a customised QR code to Bangle.js", + "tags": "", + "custom": "qrcode.html", + "storage": [ + {"name":"-qrcode"}, + {"name":"+qrcode"}, + {"name":"=qrcode"} + ] + }, + { "id": "beer", + "name": "Beer Compass", + "icon": "beercompass.png", + "description": "Uploads all the pubs in an area onto your watch, so it can always point you at the nearest one", + "tags": "", + "custom": "beercompass.html", + "storage": [ + {"name":"-beer"}, + {"name":"+beer"}, + {"name":"=beer"} + ] + }, + { "id": "route", + "name": "Route Viewer", + "icon": "route.png", + "description": "Upload a KML file of a route, and have your watch display a map with how far around it you are", + "tags": "", + "custom": "route.html", + "storage": [ + {"name":"-route"}, + {"name":"+route"}, + {"name":"=route"} + ] + }, + + { + "id": "start", + "name": "NCEU Startup", + "icon": "start.png", + "description": "NodeConfEU 2019 Startup Sequence", + "tags": "start", + "storage": [ + {"name":"+start","url":"start.json"}, + {"name":"-start","url":"start.js"}, + {"name":"*start","url":"start-icon.js","evaluate":true}, + {"name":"*bangle","url":"start-bangle.js","evaluate":true}, + {"name":"*nceu","url":"start-nceu.js","evaluate":true}, + {"name":"*nfr","url":"start-nfr.js","evaluate":true}, + {"name":"*nodew","url":"start-nodew.js","evaluate":true}, + {"name":"*tf","url":"start-tf.js","evaluate":true} + ], + "sortorder" : -1 + }, + { "id": "funrun5", + "name": "NCEU 5K Fun Run", + "icon": "nceu-funrun.png", + "description": "Display a map of the NodeConf EU 2019 5K Fun Run route and your location on it", + "tags": "health", + "storage": [ + {"name":"+funrun5","url":"nceu-funrun.json"}, + {"name":"-funrun5","url":"nceu-funrun.js"}, + {"name":"*funrun5","url":"nceu-funrun-icon.js","evaluate":true} + ], + "sortorder" : -1 + }, + { "id": "nceuwid", + "name": "NCEU Logo Widget", + "icon": "nceu-widget.png", + "description": "Show the NodeConf EU logo in the top left", + "tags": "widget", + "type":"widget", + "storage": [ + {"name":"+nceuwid","url":"nceu-widget.json"}, + {"name":"=nceuwid","url":"nceu-widget.js"} + ], + "sortorder" : -1 + }, + { "id": "sclock", + "name": "Simple Clock", + "icon": "clock-simple.png", + "description": "Simple Digital Clock", + "tags": "sclock", + "type":"clock", + "storage": [ + {"name":"+sclock","url":"clock-simple.json"}, + {"name":"-sclock","url":"clock-simple.js"}, + {"name":"*sclock","url":"clock-simple-icon.js","evaluate":true} + ] + }, + { "id": "gesture", + "name": "Gesture Test", + "icon": "gesture.png", + "description": "BETA! Uploads a basic Tensorflow Gesture model, and then outputs each gesture as a message", + "tags": "gesture,ai", + "type":"app", + "storage": [ + {"name":"+gesture","url":"gesture.json"}, + {"name":"-gesture","url":"gesture.js"}, + {"name":".tfnames","url":"gesture-tfnames.js","evaluate":true}, + {"name":".tfmodel","url":"gesture-tfmodel.js","evaluate":true}, + {"name":"*gesture","url":"gesture-icon.js","evaluate":true} + ] + }, + { "id": "pparrot", + "name": "Party Parrot", + "icon": "party-parrot.png", + "description": "Party with a parrot on your wrist", + "tags": "party,parrot,lol", + "type":"app", + "storage": [ + {"name":"+pparrot","url":"party-parrot.json"}, + {"name":"-pparrot","url":"party-parrot.js"}, + {"name":"*pparrot","url":"party-parrot-icon.js","evaluate":true} + ] + }, + { "id": "hrings", + "name": "Hypno Rings", + "icon": "hypno-rings.png", + "description": "Experiment with trippy rings, press buttons for change", + "tags": "rings,hypnosis,psychadelic", + "type":"app", + "storage": [ + {"name":"+hrings","url":"hypno-rings.json"}, + {"name":"-hrings","url":"hypno-rings.js"}, + {"name":"*hrings","url":"hypno-rings-icon.js","evaluate":true} + ] + }, + { "id": "morse", + "name": "Morse Code", + "icon": "morse-code.png", + "description": "Learn morse code by hearing/seeing/feeling the code. Tap to toggle buzz!", + "tags": "morse,sound,visual,input", + "type":"app", + "storage": [ + {"name":"+morse","url":"morse-code.json"}, + {"name":"-morse","url":"morse-code.js"}, + {"name":"*morse","url":"morse-code-icon.js","evaluate":true} + ] + }, + { + "id": "blescan", + "name": "BLE Scanner", + "icon": "blescan.png", + "description": "Scan for advertising BLE devices", + "tags" : "bluetooth", + "storage" : [ + {"name":"+blescan","url":"blescan.json"}, + {"name":"-blescan","url":"blescan.js"}, + {"name":"*blescan","url":"blescan-icon.js", "evaluate":true} + ] + }, + { "id": "mmonday", + "name": "Manic Monday Tone", + "icon": "manic-monday-icon.png", + "description": "The Bangles make a comeback", + "tags": "sound", + "storage": [ + {"name":"+mmonday","url":"manic-monday.json"}, + {"name":"-mmonday","url":"manic-monday.js"}, + {"name":"*mmonday","url":"manic-monday-icon.js","evaluate":true} + ] + }, + { "id": "jbells", + "name": "Jingle Bells", + "icon": "jbells.png", + "description": "Play Jingle Bells", + "tags": "sound", + "type":"app", + "storage": [ + {"name":"+jbells","url":"jbells.json"}, + {"name":"-jbells","url":"jbells.js"}, + {"name":"*jbells","url":"jbells-icon.js","evaluate":true} + ] + }, + { "id": "scolor", + "name": "Show Color", + "icon": "show-color.png", + "description": "Display all available Colors and Names", + "tags": "tool", + "type":"app", + "storage": [ + {"name":"+scolor","url":"show-color.json"}, + {"name":"-scolor","url":"show-color.js"}, + {"name":"*scolor","url":"show-color-icon.js","evaluate":true} + ] + }, + { "id": "miclock", + "name": "Mixed Clock", + "icon": "clock-mixed.png", + "description": "A mix of analog and digital Clock", + "tags": "clock", + "type":"clock", + "storage": [ + {"name":"+miclock","url":"clock-mixed.json"}, + {"name":"-miclock","url":"clock-mixed.js"}, + {"name":"*miclock","url":"clock-mixed-icon.js","evaluate":true} + ] + }, + { "id": "bclock", + "name": "Binary Clock", + "icon": "clock-binary.png", + "description": "A simple binary clock watch face", + "tags": "clock", + "type":"clock", + "storage": [ + {"name":"+bclock","url":"clock-binary.json"}, + {"name":"-bclock","url":"clock-binary.js"}, + {"name":"*bclock","url":"clock-binary-icon.js","evaluate":true} + ] + }, + { "id": "clotris", + "name": "Clock-Tris", + "icon": "clock-tris.png", + "description": "A fully functional clone of a classic game of falling blocks", + "tags": "game", + "storage": [ + {"name":"+clotris","url":"clock-tris.json"}, + {"name":"-clotris","url":"clock-tris.js"}, + {"name":"*clotris","url":"clock-tris-icon.js","evaluate":true}, + {"name":".trishig","url":"clock-tris-high"} + ] + }, + { + "id": "gpsinfo", + "name": "GPS Info", + "icon": "gps-info.png", + "description": "An application that displays information about altitude, lat/lon, satellites and time", + "tags": "gps", + "type": "app", + "storage": [ + {"name": "+gpsinfo","url": "gps-info.json"}, + {"name": "-gpsinfo","url": "gps-info.js"}, + {"name": "*gpsinfo","url": "gps-info-icon.js","evaluate": true} + ] + }, + { + "id": "promodoro", + "name":"Promodoro", + "icon":"promodoro.png", + "description": "A simple promodoro timer.", + "tags": "promodoro", + "type": "app", + "storage": [ + {"name": "+promodoro","url": "promodoro.json"}, + {"name": "-promodoro","url": "promodoro.js"}, + {"name": "*promodoro","url": "promodoro.js","evaluate": true} + ] + } +] diff --git a/apps/promodoro.js b/apps/promodoro.js new file mode 100644 index 000000000..00e8916a2 --- /dev/null +++ b/apps/promodoro.js @@ -0,0 +1,240 @@ +const DEFAULT_TIME = 1500; // 25m +const TIME_BREAK = 300; +const STATES = { + INIT: 1, + STARTED: 2, + DONE: 3, + BREAK: 4 +}; +var counterInterval; + +class State { + constructor (state) { + this.state = state; + this.next = null; + } + + goNext () { + if (this.next) { + this.next.run(); + } + } + + setNext (next) { + this.next = next; + } + + setButtons () { + setWatch(() => { console.log('BTN1') }, BTN1, { repeat: true }); + setWatch(() => { console.log('BTN2') }, BTN2, { repeat: true }); + setWatch(() => { console.log('BTN3') }, BTN3, { repeat: true }); + } + clear () { + clearWatch(); + g.clear(); + g.setFontAlign(0, 0); + } + + draw () { + g.clear(); + } + + init () { } + + go (nextState) { + if (nextState) { + this.next = nextState; + } + + this.clear(); + this.init(); + this.setButtons(); + this.draw(); + } +} + +class InitState extends State { + constructor () { + super(STATES.INIT); + + this.timeCounter = DEFAULT_TIME; + } + + setButtons () { + setWatch(() => { + if (this.timeCounter + 300 > 3599) { + this.timeCounter = 3599; + } else { + this.timeCounter += 300; + } + + this.draw(); + + }, BTN1, { repeat: true }); + + setWatch(() => { + if (this.timeCounter - 300 > 0) { + this.timeCounter -= 300; + this.draw(); + } + }, BTN3, { repeat: true }); + + setWatch(() => { + const startedState = new StartedState(this.timeCounter); + + this.setNext(startedState); + this.next.go(); + }, BTN2, { repeat: true }); + } + + draw () { + g.clear(); + g.setFontAlign(0, 0); // center font + g.setFont("Vector", 50); // vector font, 80px + drawCounter(this.timeCounter); + } +} + +class StartedState extends State { + constructor (timeCounter) { + super(STATES.STARTED); + + this.timeCounter = timeCounter || DEFAULT_TIME; + } + + draw () { + drawCounter(this.timeCounter, 120, 120); + } + + init () { + function countDown () { + this.timeCounter--; + + // Out of time + if (this.timeCounter <= 0) { + clearInterval(counterInterval); + counterInterval = undefined; + this.next.go(); + return; + } + + this.draw(); + } + + const doneState = new DoneState(); + this.setNext(doneState); + counterInterval = setInterval(countDown.bind(this), 1000); + } +} + +class BreakState extends State { + constructor () { + super(STATES.BREAK); + } + + draw () { + g.setFontAlign(0, 0); + } + + init () { + const startedState = new StartedState(TIME_BREAK); + + this.setNext(startedState); + this.next.go(); + } +} +class DoneState extends State { + constructor () { + super(STATES.DONE); + } + + setButtons () { + setWatch(() => { + const initState = new InitState(); + clearTimeout(this.timeout); + initState.go(); + }, BTN1, { repeat: true }); + + setWatch(() => { + const breakState = new BreakState(); + clearTimeout(this.timeout); + breakState.go(); + }, BTN3, { repeat: true }); + + setWatch(() => { + }, BTN2, { repeat: true }); + } + + draw () { + g.clear(); + g.setFont("6x8", 2); + g.setFontAlign(0, 0, 3); + g.drawString("AGAIN", 230, 50); + g.drawString("BREAK", 230, 190); + g.setFont("Vector", 45); + g.setFontAlign(-1, -1); + + g.drawString('You \\nare \\na \\nhero!', 50, 40); + } + + init () { + + function buzz () { + Bangle.buzz(); + Bangle.beep(200, 4000) + .then(() => new Promise(resolve => setTimeout(resolve, 50))) + .then(() => Bangle.beep(200, 3000)) + .then(() => new Promise(resolve => setTimeout(resolve, 200))) + .then(() => Bangle.beep(200, 3000)) + .then(() => new Promise(resolve => setTimeout(resolve, 300))) + .then(() => { + Bangle.beep(200, 3000); + Bangle.buzz() + }); + } + + buzz(); + // again, 10 secs later + this.timeout = setTimeout(buzz.bind(this), 10000); + } +} + +function drawCounter (currentValue, x, y) { + if (currentValue < 0) { + return; + } + + x = x || 120; + y = y || 120; + + let minutes = 0; + let seconds = 0; + + if (currentValue >= 60) { + minutes = Math.floor(currentValue / 60); + seconds = currentValue % 60; + } else { + seconds = currentValue; + } + + let minutesString = '' + minutes; + let secondsString = '' + seconds; + + if (minutes < 10) { + minutesString = '0' + minutes; + } + + if (seconds < 10) { + secondsString = '0' + seconds; + } + + g.clear(); + g.drawString(minutesString + ':' + secondsString, x, y); +} + +function init () { + const initState = new InitState(); + initState.go(); +} + +init(); \ No newline at end of file diff --git a/apps/promodoro.json b/apps/promodoro.json new file mode 100644 index 000000000..03a0518ac --- /dev/null +++ b/apps/promodoro.json @@ -0,0 +1,5 @@ +{ + "name":"Promodoro","type":"app", + "icon":"*promodoro", + "src":"-promodoro" +} \ No newline at end of file diff --git a/apps/promodoro.png b/apps/promodoro.png new file mode 100644 index 0000000000000000000000000000000000000000..4ea72f270d5633755b90ede38c67cdc7e121e4c5 GIT binary patch literal 2122 zcmV-Q2(|Z#P)vh7l(-y(Eff0j)pz+4-E-b}m z^l1UU0sJkAf_|W6kOHNyIGvr_*sva<9~!I?Jkb@W=RYLoDrwjOgGsO==$POP?*AJ? zSCc6Ck74~?@$_KUUg&FvZ4|l$oLEWlunY$TCD7ZzgDoC!VDxiJA(A+Jtq2t^n77$H1Ng ztpSQwJ=k^Nu))U!-!rTvwB5Ja32X+Mq1>xv*ma?1pdWZDjMKW-$&wBvQB$WupU?w9 zFK{%B)8p>9U^DQr!3MA%P`fHo9R~uS18maZgis$YDz)Squsw{^_eP_jRZs}y^!ls0GZ8n#dH z^Dv&C9gUiH2t91@Tj0&EIK5Gq1D=PW!B4^ZgbI06{(jkDXIGq_NTQ$!+zsqv6mw|`o zg7=_i!6pRb9(?3y>1l7U;M-m`?1t|@Db$~vvm$VpVeLZi14p{zbP%jZ@Pe>I8F=5L z7kCBit4S2J)N}xs0S*~N`OwS>(*S4}a2{A|a0q9B%voSo@OL3!an)hi+dy1y0nLI< zz<#iONffk!t^)r6a&)omZ#U?mVcYUx%GkVTuNyo#e_>b(y6hIB?FCI4gu>net*aO+ z_dEsm3TQXbZ5V>nhMtgfcpK1S6=Kc^{lT#PUGemA5(OQ=m%%=7XajJkUrPWb;B!J} z!Z@vpz+(%5pK&v-=Yg*SyFn%3KEY83KAX{Og;-+F$pkEL;035xu43;2ju8I%e1*p{Kx30%;{fu|?QEU?W&o)OuZ<%HtroAJ{S) zHBlUmnhLmzx*?nP+=6WZwj25rKv$ezPom&u;39A@ZlTQp4fl|t$ z7sA#9?{vk}Q^2c96ubt6-gXNx0XiARX(@?7^hdlI8A_G`D+o;W#C$cLIC=B_G=Oao4_uF@$@C&Qog5K&^!sYRXOl; z^i4u*in!v_n-5Vw3g$xlUEtm%3SI!-4HwvTX7vNu0{p^Y3>c7Ggv^~BgTsE`^g3`B zYz7nn_W@r5HoLk3^C=|2)`0FRdZRs6b2nda1^WColtjU4;NON_6ABDIfvX4Wb1&Td7KEh zU=eoQupi?#Y6I?>x)-NMeY#+Ema3{`ad=C+2iy&Mb~FlBh4J(?p&tRC4ddxCzX9Cr zdRVS^S?nM!CY?iI5<=5loaB~kDJ*y?-)mWsqeSz<9ANPyo19{{_7HH!>iw-`23 ztbn!!n$%8kR;TVIH2D7f#8~_FrXC%bEXr*Ks>3qRiHfdy+R}P8e``Hoj?P2@m)^>Q z=kK+|a&udc-iWh}=^8G84QB?KcQH?|%tC#7cG*Xu1OF<3&Sf5Xugdq#*SuaSBK7H& z;5bv{C411A^+qI?ijNyRSpOe z!E-{FZ?!BWGy!&$IVTv^`!+90)U*xsODad|Rbn|4_2?@gCEPar#knUU3x1_Ecnxke?*w|O7WgF{$T@O9*mppEU@fBZwzZU=8L*tOCG;6XX9Y)r-z`L&ywqE?`h_kT z{6+3`y0eiS-e8eBf;;^lSqi+f(V+N`4^JERsL)!2wrrqfQmACuh)@h13*&TfsSbHr z7Dbb&33K0vzX4cTFmT@BoX|VKP#C8(jbiywY1*Giw*sADcN(k{ zx(Dbs_q^zhq=rp_62U)#L32kf6N1Tls8UP*2Ty*k3rtPI!T Date: Fri, 15 Nov 2019 11:15:17 +0200 Subject: [PATCH 02/15] remove apps.json from aps --- apps/apps.json | 519 ------------------------------------------------- 1 file changed, 519 deletions(-) delete mode 100644 apps/apps.json diff --git a/apps/apps.json b/apps/apps.json deleted file mode 100644 index 978f28060..000000000 --- a/apps/apps.json +++ /dev/null @@ -1,519 +0,0 @@ -[ - { "id": "boot", - "name": "Bootloader", - "icon": "bootloader.png", - "description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings", - "tags": "tool,system", - "storage": [ - {"name":".bootcde","url":"bootloader.js"} - ], - "sortorder" : -10 - }, - { "id": "mclock", - "name": "Morphing Clock", - "icon": "clock-morphing.png", - "description": "7 segment clock that morphs between minutes and hours", - "tags": "clock", - "type":"clock", - "storage": [ - {"name":"+mclock","url":"clock-morphing.json"}, - {"name":"-mclock","url":"clock-morphing.js"}, - {"name":"*mclock","url":"clock-morphing-icon.js","evaluate":true} - ], - "sortorder" : -9 - }, - { "id": "setting", - "name": "Settings", - "icon": "settings.png", - "description": "A menu for setting up Bangle.js - by default this disables Bluetooth unless you enable 'BLE' AND 'Dev'", - "tags": "tool,system", - "storage": [ - {"name":"+setting","url":"settings.json"}, - {"name":"-setting","url":"settings.js"}, - {"name":"=setting","url":"settings-init.js"}, - {"name":"@setting","url":"settings-default.json","evaluate":true}, - {"name":"*setting","url":"settings-icon.js","evaluate":true} - ], - "sortorder" : -2 - }, - { "id": "wclock", - "name": "Word Clock", - "icon": "clock-word.png", - "description": "Display Time as Text", - "tags": "clock", - "type":"clock", - "storage": [ - {"name":"+wclock","url":"clock-word.json"}, - {"name":"-wclock","url":"clock-word.js"}, - {"name":"*wclock","url":"clock-word-icon.js","evaluate":true} - ] - }, - { "id": "aclock", - "name": "Analog Clock", - "icon": "clock-analog.png", - "description": "An Analog Clock", - "tags": "clock", - "type":"clock", - "storage": [ - {"name":"+aclock","url":"clock-analog.json"}, - {"name":"-aclock","url":"clock-analog.js"}, - {"name":"*aclock","url":"clock-analog-icon.js","evaluate":true} - ] - }, - { "id": "trex", - "name": "T-Rex", - "icon": "trex.png", - "description": "T-Rex game in the style of Chrome's offline game", - "tags": "game", - "storage": [ - {"name":"+trex","url":"trex.json"}, - {"name":"-trex","url":"trex.js"}, - {"name":"*trex","url":"trex-icon.js","evaluate":true} - ] - }, - { "id": "astroid", - "name": "Asteroids!", - "icon": "asteroids.png", - "description": "Retro asteroids game", - "tags": "game", - "storage": [ - {"name":"+astroid","url":"asteroids.json"}, - {"name":"-astroid","url":"asteroids.js"}, - {"name":"*astroid","url":"asteroids-icon.js","evaluate":true} - ] - }, - { "id": "clickms", - "name": "Click Master", - "icon": "click-master.png", - "description": "Get several friends to start the game, then compete to see who can press BTN1 the most!", - "tags": "game", - "storage": [ - {"name":"+clickms","url":"click-master.json"}, - {"name":"-clickms","url":"click-master.js"}, - {"name":"*clickms","url":"click-master-icon.js","evaluate":true} - ] - }, - { "id": "horsey", - "name": "Horse Race!", - "icon": "horse-race.png", - "description": "Get several friends to start the game, then compete to see who can press BTN1 the most!", - "tags": "game", - "storage": [ - {"name":"+horsey","url":"horse-race.json"}, - {"name":"-horsey","url":"horse-race.js"}, - {"name":"*horsey","url":"horse-race-icon.js","evaluate":true} - ] - }, - { "id": "compass", - "name": "Compass", - "icon": "compass.png", - "description": "Simple compass that points North", - "tags": "tool,outdoors", - "storage": [ - {"name":"+compass","url":"compass.json"}, - {"name":"-compass","url":"compass.js"}, - {"name":"*compass","url":"compass-icon.js","evaluate":true} - ] - }, - { "id": "gpstime", - "name": "GPS Time", - "icon": "gpstime.png", - "description": "Update the Bangle.js's clock based on the time from the GPS receiver", - "tags": "tool", - "storage": [ - {"name":"+gpstime","url":"gpstime.json"}, - {"name":"-gpstime","url":"gpstime.js"}, - {"name":"*gpstime","url":"gpstime-icon.js","evaluate":true} - ] - }, - { "id": "openloc", - "name": "Open Location / Plus Codes", - "icon": "openlocation.png", - "description": "Convert your current GPS location to a series of characters", - "tags": "tool,outdoors", - "storage": [ - {"name":"+openloc","url":"openlocation.json"}, - {"name":"-openloc","url":"openlocation.js","evaluate":true} - ] - }, - { "id": "speedo", - "name": "Speedo", - "icon": "speedo.png", - "description": "Show the current speed according to the GPS", - "tags": "tool,outdoors", - "storage": [ - {"name":"+speedo","url":"speedo.json"}, - {"name":"-speedo","url":"speedo.js"}, - {"name":"*speedo","url":"speedo-icon.js","evaluate":true} - ] - }, - { "id": "slevel", - "name": "Spirit Level", - "icon": "spiritlevel.png", - "description": "Show the current angle of the watch, so you can use it to make sure something is absolutely flat", - "tags": "tool", - "storage": [ - {"name":"+slevel","url":"spiritlevel.json"}, - {"name":"-slevel","url":"spiritlevel.js"}, - {"name":"*slevel","url":"spiritlevel-icon.js","evaluate":true} - ] - }, - { "id": "files", - "name": "App Manager", - "icon": "files.png", - "description": "Show currently installed apps, free space, and allow their deletion from the watch", - "tags": "tool,system", - "storage": [ - {"name":"+files","url":"files.json"}, - {"name":"-files","url":"files.js"}, - {"name":"*files","url":"files-icon.js","evaluate":true} - ] - }, - { "id": "sbat", - "name": "Battery Level Widget", - "icon": "widget-battery.png", - "description": "Show the current battery level and charging status in the top right of the clock", - "tags": "widget,battery", - "type":"widget", - "storage": [ - {"name":"+sbat","url":"widget-battery.json"}, - {"name":"=sbat","url":"widget-battery.js"} - ] - }, - { "id": "sbt", - "name": "Bluetooth Widget", - "icon": "widget-bluetooth.png", - "description": "Show the current Bluetooth connection status in the top right of the clock", - "tags": "widget,bluetooth", - "type":"widget", - "storage": [ - {"name":"+sbt","url":"widget-bluetooth.json"}, - {"name":"=sbt","url":"widget-bluetooth.js"} - ] - }, - { "id": "hrm", - "name": "Heart Rate Monitor", - "icon": "heartrate.png", - "description": "Measure your current heart rate", - "tags": "health", - "storage": [ - {"name":"+hrm","url":"heartrate.json"}, - {"name":"-hrm","url":"heartrate.js"}, - {"name":"*hrm","url":"heartrate-icon.js","evaluate":true} - ] - }, - { "id": "swatch", - "name": "Stopwatch", - "icon": "stopwatch.png", - "description": "Simple stopwatch with Lap Time recording", - "tags": "health", - "storage": [ - {"name":"+swatch","url":"stopwatch.json"}, - {"name":"-swatch","url":"stopwatch.js"}, - {"name":"*swatch","url":"stopwatch-icon.js","evaluate":true} - ] - }, - { "id": "hidmsic", - "name": "Bluetooth Music Controls", - "icon": "hid-music.png", - "description": "Enable HID in settings, pair with your phone, then use this app to control music from your watch!", - "tags": "bluetooth", - "storage": [ - {"name":"+hidmsic","url":"hid-music.json"}, - {"name":"-hidmsic","url":"hid-music.js"}, - {"name":"*hidmsic","url":"hid-music-icon.js","evaluate":true} - ] - }, - { "id": "hidkbd", - "name": "Bluetooth Keyboard", - "icon": "hid-keyboard.png", - "description": "Enable HID in settings, pair with your phone/PC, then use this app to control other apps", - "tags": "bluetooth", - "storage": [ - {"name":"+hidkbd","url":"hid-keyboard.json"}, - {"name":"-hidkbd","url":"hid-keyboard.min.js"}, - {"name":"*hidkbd","url":"hid-keyboard-icon.js","evaluate":true} - ] - }, - { "id": "hidbkbd", - "name": "Binary Bluetooth Keyboard", - "icon": "hid-binary-keyboard.png", - "description": "Enable HID in settings, pair with your phone/PC, then type messages using the onscreen keyboard by tapping repeatedly on the key you want", - "tags": "bluetooth", - "storage": [ - {"name":"+hidbkbd","url":"hid-binary-keyboard.json"}, - {"name":"-hidbkbd","url":"hid-binary-keyboard.js"}, - {"name":"*hidbkbd","url":"hid-binary-keyboard-icon.js","evaluate":true} - ] - }, - { "id": "animals", - "name": "Animals Game", - "icon": "animals.png", - "description": "Simple toddler's game - displays a different number of animals each time the screen is pressed", - "tags": "game", - "storage": [ - {"name":"+animals","url":"animals.json"}, - {"name":"-animals","url":"animals.js"}, - {"name":"*animals","url":"animals-icon.js","evaluate":true}, - {"name":"*snake","url":"animals-snake.js","evaluate":true}, - {"name":"*duck","url":"animals-duck.js","evaluate":true}, - {"name":"*swan","url":"animals-swan.js","evaluate":true}, - {"name":"*fox","url":"animals-fox.js","evaluate":true}, - {"name":"*camel","url":"animals-camel.js","evaluate":true}, - {"name":"*pig","url":"animals-pig.js","evaluate":true}, - {"name":"*sheep","url":"animals-sheep.js","evaluate":true}, - {"name":"*mouse","url":"animals-mouse.js","evaluate":true} - ], - "sortorder" : 1 - }, - { "id": "qrcode", - "name": "Custom QR Code", - "icon": "qrcode.png", - "description": "Use this to upload a customised QR code to Bangle.js", - "tags": "", - "custom": "qrcode.html", - "storage": [ - {"name":"-qrcode"}, - {"name":"+qrcode"}, - {"name":"=qrcode"} - ] - }, - { "id": "beer", - "name": "Beer Compass", - "icon": "beercompass.png", - "description": "Uploads all the pubs in an area onto your watch, so it can always point you at the nearest one", - "tags": "", - "custom": "beercompass.html", - "storage": [ - {"name":"-beer"}, - {"name":"+beer"}, - {"name":"=beer"} - ] - }, - { "id": "route", - "name": "Route Viewer", - "icon": "route.png", - "description": "Upload a KML file of a route, and have your watch display a map with how far around it you are", - "tags": "", - "custom": "route.html", - "storage": [ - {"name":"-route"}, - {"name":"+route"}, - {"name":"=route"} - ] - }, - - { - "id": "start", - "name": "NCEU Startup", - "icon": "start.png", - "description": "NodeConfEU 2019 Startup Sequence", - "tags": "start", - "storage": [ - {"name":"+start","url":"start.json"}, - {"name":"-start","url":"start.js"}, - {"name":"*start","url":"start-icon.js","evaluate":true}, - {"name":"*bangle","url":"start-bangle.js","evaluate":true}, - {"name":"*nceu","url":"start-nceu.js","evaluate":true}, - {"name":"*nfr","url":"start-nfr.js","evaluate":true}, - {"name":"*nodew","url":"start-nodew.js","evaluate":true}, - {"name":"*tf","url":"start-tf.js","evaluate":true} - ], - "sortorder" : -1 - }, - { "id": "funrun5", - "name": "NCEU 5K Fun Run", - "icon": "nceu-funrun.png", - "description": "Display a map of the NodeConf EU 2019 5K Fun Run route and your location on it", - "tags": "health", - "storage": [ - {"name":"+funrun5","url":"nceu-funrun.json"}, - {"name":"-funrun5","url":"nceu-funrun.js"}, - {"name":"*funrun5","url":"nceu-funrun-icon.js","evaluate":true} - ], - "sortorder" : -1 - }, - { "id": "nceuwid", - "name": "NCEU Logo Widget", - "icon": "nceu-widget.png", - "description": "Show the NodeConf EU logo in the top left", - "tags": "widget", - "type":"widget", - "storage": [ - {"name":"+nceuwid","url":"nceu-widget.json"}, - {"name":"=nceuwid","url":"nceu-widget.js"} - ], - "sortorder" : -1 - }, - { "id": "sclock", - "name": "Simple Clock", - "icon": "clock-simple.png", - "description": "Simple Digital Clock", - "tags": "sclock", - "type":"clock", - "storage": [ - {"name":"+sclock","url":"clock-simple.json"}, - {"name":"-sclock","url":"clock-simple.js"}, - {"name":"*sclock","url":"clock-simple-icon.js","evaluate":true} - ] - }, - { "id": "gesture", - "name": "Gesture Test", - "icon": "gesture.png", - "description": "BETA! Uploads a basic Tensorflow Gesture model, and then outputs each gesture as a message", - "tags": "gesture,ai", - "type":"app", - "storage": [ - {"name":"+gesture","url":"gesture.json"}, - {"name":"-gesture","url":"gesture.js"}, - {"name":".tfnames","url":"gesture-tfnames.js","evaluate":true}, - {"name":".tfmodel","url":"gesture-tfmodel.js","evaluate":true}, - {"name":"*gesture","url":"gesture-icon.js","evaluate":true} - ] - }, - { "id": "pparrot", - "name": "Party Parrot", - "icon": "party-parrot.png", - "description": "Party with a parrot on your wrist", - "tags": "party,parrot,lol", - "type":"app", - "storage": [ - {"name":"+pparrot","url":"party-parrot.json"}, - {"name":"-pparrot","url":"party-parrot.js"}, - {"name":"*pparrot","url":"party-parrot-icon.js","evaluate":true} - ] - }, - { "id": "hrings", - "name": "Hypno Rings", - "icon": "hypno-rings.png", - "description": "Experiment with trippy rings, press buttons for change", - "tags": "rings,hypnosis,psychadelic", - "type":"app", - "storage": [ - {"name":"+hrings","url":"hypno-rings.json"}, - {"name":"-hrings","url":"hypno-rings.js"}, - {"name":"*hrings","url":"hypno-rings-icon.js","evaluate":true} - ] - }, - { "id": "morse", - "name": "Morse Code", - "icon": "morse-code.png", - "description": "Learn morse code by hearing/seeing/feeling the code. Tap to toggle buzz!", - "tags": "morse,sound,visual,input", - "type":"app", - "storage": [ - {"name":"+morse","url":"morse-code.json"}, - {"name":"-morse","url":"morse-code.js"}, - {"name":"*morse","url":"morse-code-icon.js","evaluate":true} - ] - }, - { - "id": "blescan", - "name": "BLE Scanner", - "icon": "blescan.png", - "description": "Scan for advertising BLE devices", - "tags" : "bluetooth", - "storage" : [ - {"name":"+blescan","url":"blescan.json"}, - {"name":"-blescan","url":"blescan.js"}, - {"name":"*blescan","url":"blescan-icon.js", "evaluate":true} - ] - }, - { "id": "mmonday", - "name": "Manic Monday Tone", - "icon": "manic-monday-icon.png", - "description": "The Bangles make a comeback", - "tags": "sound", - "storage": [ - {"name":"+mmonday","url":"manic-monday.json"}, - {"name":"-mmonday","url":"manic-monday.js"}, - {"name":"*mmonday","url":"manic-monday-icon.js","evaluate":true} - ] - }, - { "id": "jbells", - "name": "Jingle Bells", - "icon": "jbells.png", - "description": "Play Jingle Bells", - "tags": "sound", - "type":"app", - "storage": [ - {"name":"+jbells","url":"jbells.json"}, - {"name":"-jbells","url":"jbells.js"}, - {"name":"*jbells","url":"jbells-icon.js","evaluate":true} - ] - }, - { "id": "scolor", - "name": "Show Color", - "icon": "show-color.png", - "description": "Display all available Colors and Names", - "tags": "tool", - "type":"app", - "storage": [ - {"name":"+scolor","url":"show-color.json"}, - {"name":"-scolor","url":"show-color.js"}, - {"name":"*scolor","url":"show-color-icon.js","evaluate":true} - ] - }, - { "id": "miclock", - "name": "Mixed Clock", - "icon": "clock-mixed.png", - "description": "A mix of analog and digital Clock", - "tags": "clock", - "type":"clock", - "storage": [ - {"name":"+miclock","url":"clock-mixed.json"}, - {"name":"-miclock","url":"clock-mixed.js"}, - {"name":"*miclock","url":"clock-mixed-icon.js","evaluate":true} - ] - }, - { "id": "bclock", - "name": "Binary Clock", - "icon": "clock-binary.png", - "description": "A simple binary clock watch face", - "tags": "clock", - "type":"clock", - "storage": [ - {"name":"+bclock","url":"clock-binary.json"}, - {"name":"-bclock","url":"clock-binary.js"}, - {"name":"*bclock","url":"clock-binary-icon.js","evaluate":true} - ] - }, - { "id": "clotris", - "name": "Clock-Tris", - "icon": "clock-tris.png", - "description": "A fully functional clone of a classic game of falling blocks", - "tags": "game", - "storage": [ - {"name":"+clotris","url":"clock-tris.json"}, - {"name":"-clotris","url":"clock-tris.js"}, - {"name":"*clotris","url":"clock-tris-icon.js","evaluate":true}, - {"name":".trishig","url":"clock-tris-high"} - ] - }, - { - "id": "gpsinfo", - "name": "GPS Info", - "icon": "gps-info.png", - "description": "An application that displays information about altitude, lat/lon, satellites and time", - "tags": "gps", - "type": "app", - "storage": [ - {"name": "+gpsinfo","url": "gps-info.json"}, - {"name": "-gpsinfo","url": "gps-info.js"}, - {"name": "*gpsinfo","url": "gps-info-icon.js","evaluate": true} - ] - }, - { - "id": "promodoro", - "name":"Promodoro", - "icon":"promodoro.png", - "description": "A simple promodoro timer.", - "tags": "promodoro", - "type": "app", - "storage": [ - {"name": "+promodoro","url": "promodoro.json"}, - {"name": "-promodoro","url": "promodoro.js"}, - {"name": "*promodoro","url": "promodoro.js","evaluate": true} - ] - } -] From 4aa089777ffce3cdef4b702e890e26940aaaa488 Mon Sep 17 00:00:00 2001 From: Mark Becker Date: Fri, 15 Nov 2019 12:00:34 +0100 Subject: [PATCH 03/15] add missing -icon --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 79708bd76..242f80b8c 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ the *default* of `To RAM` "storage": [ {"name":"+7chname","url":"my-great-app.json"}, {"name":"-7chname","url":"my-great-app.js"}, - {"name":"*7chname","url":"my-great-app.js","evaluate":true} + {"name":"*7chname","url":"my-great-app-icon.js","evaluate":true} ], }, ``` From a26df19e874a1984fb20c2fccffa0dc42e8dfb05 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 15 Nov 2019 11:02:56 +0000 Subject: [PATCH 04/15] minor tweaks - add JS icon --- apps.json | 10 +++++----- apps/promodoro-icon.js | 1 + apps/promodoro.json | 6 +++--- 3 files changed, 9 insertions(+), 8 deletions(-) create mode 100644 apps/promodoro-icon.js diff --git a/apps.json b/apps.json index 978f28060..aae4fd940 100644 --- a/apps.json +++ b/apps.json @@ -504,16 +504,16 @@ ] }, { - "id": "promodoro", + "id": "promodo", "name":"Promodoro", "icon":"promodoro.png", "description": "A simple promodoro timer.", - "tags": "promodoro", + "tags": "promodoro,cooking,tools", "type": "app", "storage": [ - {"name": "+promodoro","url": "promodoro.json"}, - {"name": "-promodoro","url": "promodoro.js"}, - {"name": "*promodoro","url": "promodoro.js","evaluate": true} + {"name": "+promodo","url": "promodoro.json"}, + {"name": "-promodo","url": "promodoro.js"}, + {"name": "*promodo","url": "promodoro-icon.js","evaluate": true} ] } ] diff --git a/apps/promodoro-icon.js b/apps/promodoro-icon.js new file mode 100644 index 000000000..020df6f5c --- /dev/null +++ b/apps/promodoro-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwgQNhvQFCoXX7ooQFy0N7vdCYQDDIJ4YDC6QwC7oDBDwYcLN4QRDAApELEYYWGBQKEFCAoWKBIRaIBIIFEEA5iEEooUEDgYhEFxgDB6BfFGAgeFCAYXCBhAEJGYYrGMxQJDC4aIHHIjhGBQQXNE5L5DCIq3GIgiuHWQ7SHhoXKABRCBC6plDC6xVKJBgXVGIIWVAH5pTQK4X/cRAXvJCnQC7JIUCwQwTFwYwTCwgwSC4owQIwowQCw4wPCxAYNFxIYMCxgYJCpoZHBpI=")) diff --git a/apps/promodoro.json b/apps/promodoro.json index 03a0518ac..074f7c6ba 100644 --- a/apps/promodoro.json +++ b/apps/promodoro.json @@ -1,5 +1,5 @@ { "name":"Promodoro","type":"app", - "icon":"*promodoro", - "src":"-promodoro" -} \ No newline at end of file + "icon":"*promodo", + "src":"-promodo" +} From 7763fb5673f940037cb2ab0a0c3f2afb55bfc4fa Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Sat, 16 Nov 2019 21:22:26 +0000 Subject: [PATCH 05/15] Add Large Digit Clock to apps --- apps.json | 14 +++++- apps/clock-blob-icon.js | 1 + apps/clock-blob.js | 108 ++++++++++++++++++++++++++++++++++++++++ apps/clock-blob.json | 7 +++ apps/clock-blob.png | Bin 0 -> 817 bytes 5 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 apps/clock-blob-icon.js create mode 100644 apps/clock-blob.js create mode 100644 apps/clock-blob.json create mode 100644 apps/clock-blob.png diff --git a/apps.json b/apps.json index aae4fd940..09271c01a 100644 --- a/apps.json +++ b/apps.json @@ -514,6 +514,18 @@ {"name": "+promodo","url": "promodoro.json"}, {"name": "-promodo","url": "promodoro.js"}, {"name": "*promodo","url": "promodoro-icon.js","evaluate": true} - ] + ] +}, + { "id": "blobclk", + "name": "Large Digit Clock", + "icon": "clock-blob.png", + "description": "A clock with big digits", + "tags": "clock", + "type":"clock", + "storage": [ + {"name":"+blobclk","url":"clock-blob.json"}, + {"name":"-blobclk","url":"clock-blob.js"}, + {"name":"*blobclk","url":"clock-blob-icon.js","evaluate":true} + ] } ] diff --git a/apps/clock-blob-icon.js b/apps/clock-blob-icon.js new file mode 100644 index 000000000..860689824 --- /dev/null +++ b/apps/clock-blob-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwhC/AH4AUmYAOCw0DC58wFyowHC/4X/C9mIxAGKC5IPBCIoXWnAXOB4ODAQQXTGQQXCJoyPMC4ggDC6IVBC6JKFC6JZDC6SODCgQXQFwalCSAoXJXAgXSdo4XOCIi/CL54XvABwX/C/4XtgYWPmAXFGCAWGAH4A/ABgA=")) diff --git a/apps/clock-blob.js b/apps/clock-blob.js new file mode 100644 index 000000000..0bb8b8d2e --- /dev/null +++ b/apps/clock-blob.js @@ -0,0 +1,108 @@ +(function(){ + const buf = Graphics.createArrayBuffer(144,200,1,{msb:true}); + const NUMBERS = [ + [1,1,1,1,3,1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1],//0 + [0,1,1,1,3,0,0,1,1,1,0,0,1,1,1,0,0,1,1,1,0,0,1,1,1],//1 + [1,1,1,1,3,0,0,1,1,1,2,1,1,1,4,1,1,1,0,0,1,1,1,1,1],//2 + [1,1,1,1,3,0,0,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1],//3 + [1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,5,1,1,1,1,0,0,1,1,1],//4 + [1,1,1,1,1,1,1,1,0,0,5,1,1,1,3,0,0,1,1,1,1,1,1,1,1],//5 + [1,1,1,1,1,1,1,1,0,0,1,1,1,1,3,1,1,0,1,1,1,1,1,1,1],//6 + [1,1,1,1,3,0,0,1,1,1,0,2,1,1,1,0,1,1,1,0,0,1,1,1,0],//7 + [1,1,1,1,3,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1],//8 + [1,1,1,1,3,1,1,0,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1] //9 + ]; + let intervalRef = null; + let digits = [-1,-1,-1,-1,-1,-1]; + function flip() { + g.setColor(1,1,1); + g.drawImage({width:buf.getWidth(),height:buf.getHeight(),buffer:buf.buffer},55,26); + try { if (drawWidgets) { drawWidgets();} } catch(err) {} + } + function drawPixel(ox,oy,x,y,r,p) { + let x1 = ox+x*(r*2+1); + let y1 = oy+y*(r*2+1); + let xmid = x1+r; + let ymid = y1+r; + let x2 = xmid+r; + let y2 = ymid+r; + if (p > 0) { + if (p > 1) { + buf.setColor(0,0,0); + buf.fillRect(x1,y1,x2,y2); + } + buf.setColor(1,1,1); + } else { + buf.setColor(0,0,0); + } + if (p < 2) { + buf.fillRect(x1,y1,x2,y2); + } else if (p === 2) { + buf.fillPoly([xmid,y1,x2,y1,x2,y2,x1,y2,x1,ymid]); + } else if (p === 3) { + buf.fillPoly([x1,y1,xmid,y1,x2,ymid,x2,y2,x1,y2]); + } else if (p === 4) { + buf.fillPoly([x1,y1,x2,y1,x2,ymid,xmid,y2,x1,y2]); + } else if (p === 5) { + buf.fillPoly([x1,y1,x2,y1,x2,y2,xmid,y2,x1,ymid]); + } + } + function redraw() { + let time = new Date(); + let hours = time.getHours(); + let mins = time.getMinutes(); + let secs = time.getSeconds(); + + let newDigits = [Math.floor(hours/10),hours%10,Math.floor(mins/10),mins%10,Math.floor(secs/10),secs%10]; + + for (var p = 0;p<25;p++) { + var px = p%5; + var py = Math.floor(p/5); + if (digits[0] === -1 || NUMBERS[newDigits[0]][p] !== NUMBERS[digits[0]][p] ) { + drawPixel(0,20,px,py,6,NUMBERS[newDigits[0]][p]); + } + if (digits[1] === -1 || NUMBERS[newDigits[1]][p] !== NUMBERS[digits[1]][p] ) { + drawPixel(78,20,px,py,6,NUMBERS[newDigits[1]][p]); + } + if (digits[2] === -1 || NUMBERS[newDigits[2]][p] !== NUMBERS[digits[2]][p] ) { + drawPixel(0,92,px,py,6,NUMBERS[newDigits[2]][p]); + } + if (digits[3] === -1 || NUMBERS[newDigits[3]][p] !== NUMBERS[digits[3]][p] ) { + drawPixel(78,92,px,py,6,NUMBERS[newDigits[3]][p]); + } + if (digits[4] === -1 || NUMBERS[newDigits[4]][p] !== NUMBERS[digits[4]][p] ) { + drawPixel(69,164,px,py,3,NUMBERS[newDigits[4]][p]); + } + if (digits[5] === -1 || NUMBERS[newDigits[5]][p] !== NUMBERS[digits[5]][p] ) { + drawPixel(108,164,px,py,3,NUMBERS[newDigits[5]][p]); + } + } + digits = newDigits; + flip(); + } + function clearTimers() { + if(intervalRef) {clearInterval(intervalRef);} + } + function startTimers() { + g.clear(); + digits = [-1,-1,-1,-1,-1,-1]; + intervalRef = setInterval(redraw,1000); + redraw(); + } + startTimers(); + Bangle.on('lcdPower',function(on) { + if (on) { + g.clear(); + startTimers(); + try { if (drawWidgets) { drawWidgets();} } catch(err) {} + } else { + clearTimers(); + } + }); + Bangle.on('faceUp',function(up){ + if (up && !Bangle.isLCDOn()) { + clearTimers(); + Bangle.setLCDPower(true); + } + }); +})(); diff --git a/apps/clock-blob.json b/apps/clock-blob.json new file mode 100644 index 000000000..63b095a42 --- /dev/null +++ b/apps/clock-blob.json @@ -0,0 +1,7 @@ +{ + "name":"Large Digit Clock", + "type":"clock", + "icon":"*blobclk", + "src":"-blobclk", + "sortorder":-10 +} diff --git a/apps/clock-blob.png b/apps/clock-blob.png new file mode 100644 index 0000000000000000000000000000000000000000..738465d9d58a98ceab4432bf057fb195e74252f4 GIT binary patch literal 817 zcmV-11J3-3P)C^6G0fppWSW|Ol&F*O(f9+L4}L-Km=o=h*3=Rz{QV~ z2g9LvF8mV&4<1TlVq&5PJ!upqr6LD0Bqr7vT0V*f#R|dNFVdEFx8tF8%i5i7Gi3DC6`Tr@<2)~p0k{g_NPQ&9BthV_aMDPBTjLU~6V*Ub zydOYwP2^Px2Sla3&^6G`{ZNbZw1LIU8!8?E2yoQGi=(tS)c^`*vo9dP04=6vpx!mF zg^d=_GH@U;4H%7Sz-R>4frJ3Fi!sawWB3)%0sxNL8_?Hb$Au0%IE{P!c1FVRlMvFm zyxjKK-N~eb$p9gM#}~$jP+ZZzx|zo6W*Wh83hv9T)bW#_BMR|*fvJS%SL0>kcQdyV z$9yQE8cSwGc)vthrd5S$1>OZp;xBgEar0~otQHvW|_JSrWF{!cUt{omeS6( z@a4OB!XLp-vGxbMTM&G?#xlJEU60ZC%cZ(M;W(s-#nU3D7h(Vk+1G0YbTbg$&f&$! zE&2cXQ+7rC^`{83Vk!H2p^E`2PcS|cmXAiK&5CooHgGH@;%z|x>;pO&kO+at7e?S` zs&GM`!%$zVVn4j{*CzXb#w(@wYmQVJoE7tU;0?pSmXzCW_d0Ri38n`50im#G>g&6@7PM@rmWl@QY=u10*lIPmWSdpd>ciLNEIpD+y=jcLGW zvmLN#FFq!A9#@ACmW5kayJ(}Gk3{cVj)QeNodfad_z vzme3I1VEk%lHj^@l3O=meiIWDlPdTNBzOBJm;l>x00000NkvXXu0mjfr~ZC* literal 0 HcmV?d00001 From 59dc02648f3ca0cfedf4bcd8038befa127bff1fc Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Sat, 16 Nov 2019 21:29:40 +0000 Subject: [PATCH 06/15] Shorten clock title so it fits in menu --- apps/clock-blob.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/clock-blob.json b/apps/clock-blob.json index 63b095a42..b548acd80 100644 --- a/apps/clock-blob.json +++ b/apps/clock-blob.json @@ -1,5 +1,5 @@ { - "name":"Large Digit Clock", + "name":"Large Clock", "type":"clock", "icon":"*blobclk", "src":"-blobclk", From c89ad11d695d4d49c4707a346ae3e8a44c0b6b0b Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Sat, 16 Nov 2019 22:13:49 +0000 Subject: [PATCH 07/15] Add Select Clock option to settings app This adds an option to select the preferred clock to show on the main screen. The settings app menu lists all apps of type 'clock' with the current one marked with a *. It stores the src property of the selected clock as settings.clock. The bootloader app checks this property and tries to load that app. If the property is not set, or the app not found then it reverts to the current behaviour of using the first clock app it finds. --- apps/bootloader.js | 26 +++++++++++++++++++++----- apps/settings.js | 33 +++++++++++++++++++++++++++++++++ firmware.js | 12 ++++++------ 3 files changed, 60 insertions(+), 11 deletions(-) diff --git a/apps/bootloader.js b/apps/bootloader.js index 14b9ef440..6435ef39d 100644 --- a/apps/bootloader.js +++ b/apps/bootloader.js @@ -101,12 +101,28 @@ if (startapp) { function drawWidgets() { for (var w of WIDGETS) w.draw(); } - 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) eval(require("Storage").read(clockApps[0].src)); + var settings; + try { + settings = require("Storage").readJSON('@setting'); + } catch (e) { + settings = {} + } + 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); + } + } + if (clockApp) eval(clockApp); else E.showMessage("No Clock Found"); + delete clockApps; require("Storage").list().filter(a=>a[0]=='=').forEach(widget=>eval(require("Storage").read(widget))); setTimeout(drawWidgets,100); diff --git a/apps/settings.js b/apps/settings.js index ae14a53bc..b000518ed 100644 --- a/apps/settings.js +++ b/apps/settings.js @@ -27,6 +27,7 @@ function resetSettings() { HID : false, HIDGestures: false, debug: false, + clock: null }; setLCDTimeout(settings.timeout); updateSettings(); @@ -92,6 +93,7 @@ function showMainMenu() { } } }, + 'Select Clock': showClockMenu, 'Time Zone': { value: settings.timezone, min: -11, @@ -174,6 +176,37 @@ function makeConnectable() { showMainMenu(); }); } +function showClockMenu() { + 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); + const clockMenu = { + '': { + 'title': 'Select Clock', + }, + '< Back': showMainMenu, + }; + clockApps.forEach(app => { + var label = app.name; + if (settings.clock === app.src) { + label = "* "+label; + } + clockMenu[label] = () => { + if (settings.clock !== app.src) { + settings.clock = app.src; + updateSettings(); + showMainMenu(); + } + }; + }); + if (clockApps.length === 0) { + clockMenu["No Clocks Found"] = () => {}; + } + return Bangle.menu(clockMenu); +} + + function showSetTimeMenu() { d = new Date(); diff --git a/firmware.js b/firmware.js index 6a2995a24..4875b72c5 100644 --- a/firmware.js +++ b/firmware.js @@ -1,10 +1,10 @@ -require('Storage').write(".bootcde","E.setFlags({pretokenise:1});\nvar startapp;\ntry {\n startapp = require('Storage').readJSON('+start');\n} catch (e) {}\nif (startapp) {\n eval(require(\"Storage\").read(startapp.src));\n} else {\n delete startapp;\n setWatch(function displayMenu() {\n Bangle.setLCDMode(\"direct\");\n g.clear();\n clearInterval();\n clearWatch();\n Bangle.removeAllListeners();\n var s = require(\"Storage\");\n\n var apps = s.list().filter(a=>a[0]=='+').map(app=>{\n try { return s.readJSON(app); }\n catch (e) { return {name:\"DEAD: \"+app.substr(1)} }\n }).filter(app=>app.type==\"app\" || app.type==\"clock\" || !app.type);\n apps.sort((a,b)=>{\n var n=(0|a.sortorder)-(0|b.sortorder);\n if (n) return n; // do sortorder first\n if (a.nameb.name) return 1;\n return 0;\n });\n var selected = 0;\n var menuScroll = 0;\n var menuShowing = false;\n\n function drawMenu() {\n g.setFont(\"6x8\",2);\n g.setFontAlign(-1,0);\n var n = 3;\n if (selected>=n+menuScroll) menuScroll = 1+selected-n;\n if (selectedn+menuScroll) g.fillPoly([120,239,100,219,140,219]);\n else g.clearRect(100,219,140,239);\n for (var i=0;i0) {\n selected--;\n drawMenu();\n }\n }, BTN1, {repeat:true});\n setWatch(function() {\n if (selected+1WIDGETS[k].draw());\n }\n var clockApp = require(\"Storage\").list().filter(a=>a[0]=='+').map(app=>{\n try { return require(\"Storage\").readJSON(app); }\n catch (e) {}\n }).find(app=>app.type==\"clock\");\n if (clockApp) eval(require(\"Storage\").read(clockApp.src));\n else E.showMessage(\"No Clock Found\");\n delete clockApp;\n require(\"Storage\").list().filter(a=>a[0]=='=').forEach(widget=>eval(require(\"Storage\").read(widget)));\n setTimeout(drawWidgets,100);\n}\n"); +require('Storage').write(".bootcde","E.setFlags({pretokenise:1});\nvar startapp;\ntry {\n startapp = require('Storage').readJSON('+start');\n} catch (e) {}\nif (startapp) {\n eval(require(\"Storage\").read(startapp.src));\n} else {\n delete startapp;\n setWatch(function displayMenu() {\n Bangle.setLCDMode(\"direct\");\n g.clear();\n clearInterval();\n clearWatch();\n Bangle.removeAllListeners();\n var s = require(\"Storage\");\n\n var apps = s.list().filter(a=>a[0]=='+').map(app=>{\n try { return s.readJSON(app); }\n catch (e) { return {name:\"DEAD: \"+app.substr(1)} }\n }).filter(app=>app.type==\"app\" || app.type==\"clock\" || !app.type);\n apps.sort((a,b)=>{\n var n=(0|a.sortorder)-(0|b.sortorder);\n if (n) return n; // do sortorder first\n if (a.nameb.name) return 1;\n return 0;\n });\n var selected = 0;\n var menuScroll = 0;\n var menuShowing = false;\n\n function drawMenu() {\n g.setFont(\"6x8\",2);\n g.setFontAlign(-1,0);\n var n = 3;\n if (selected>=n+menuScroll) menuScroll = 1+selected-n;\n if (selectedn+menuScroll) g.fillPoly([120,239,100,219,140,219]);\n else g.clearRect(100,219,140,239);\n for (var i=0;i0) {\n selected--;\n drawMenu();\n }\n }, BTN1, {repeat:true});\n setWatch(function() {\n if (selected+1a[0]=='=').forEach(widget=>eval(require(\"Storage\").read(widget)));\n setTimeout(drawWidgets,100);\n } else {\n delete WIDGETS;\n delete WIDGETPOS;\n delete drawWidgets;\n }\n }, BTN2, {repeat:true,edge:\"falling\"});\n }, BTN2, {repeat:false,edge:\"falling\"}); // menu on middle button\n\n var WIDGETPOS={tl:32,tr:g.getWidth()-32,bl:32,br:g.getWidth()-32};\n var WIDGETS={};\n function drawWidgets() {\n for (var w of WIDGETS) w.draw();\n }\n var settings;\n try {\n settings = require(\"Storage\").readJSON('@setting');\n } catch (e) {\n settings = {}\n }\n var clockApp = settings.clock;\n if (clockApp) {\n clockApp = require(\"Storage\").read(clockApp)\n }\n if (!clockApp) {\n var clockApps = require(\"Storage\").list().filter(a=>a[0]=='+').map(app=>{\n try { return require(\"Storage\").readJSON(app); }\n catch (e) {}\n }).filter(app=>app.type==\"clock\").sort((a, b) => a.sortorder - b.sortorder);\n if (clockApps && clockApps.length > 0) {\n clockApp = require(\"Storage\").read(clockApps[0].src);\n }\n }\n if (clockApp) eval(clockApp);\n else E.showMessage(\"No Clock Found\");\n\n delete clockApps;\n require(\"Storage\").list().filter(a=>a[0]=='=').forEach(widget=>eval(require(\"Storage\").read(widget)));\n setTimeout(drawWidgets,100);\n}\n"); require('Storage').write("+mclock",{"name":"Morphing Clock","type":"clock","icon":"*mclock","src":"-mclock","sortorder":-10,"files":"+mclock,-mclock,*mclock"}); -require('Storage').write("-mclock","// Enable 'Set Current Time' in Settings -> Communications before sending\n(function(){ // make our own scope so this is GC'd when intervals are cleared\n// Offscreen buffer\nvar buf = Graphics.createArrayBuffer(240,86,1,{msb:true});\nfunction flip() {\n g.setColor(1,1,1);\n g.drawImage({width:buf.getWidth(),height:buf.getHeight(),buffer:buf.buffer},0,50);\n}\n// The last time that we displayed\nvar lastTime = \" \";\n// If animating, this is the interval's id\nvar animInterval;\n\n/* Get array of lines from digit d to d+1.\n n is the amount (0..1)\n maxFive is true is this digit only counts 0..5 */\nconst DIGITS = {\n\" \":n=>[],\n\"0\":n=>[\n[n,0,1,0],\n[1,0,1,1],\n[1,1,1,2],\n[n,2,1,2],\n[n,1,n,2],\n[n,0,n,1]],\n\"1\":n=>[\n[1-n,0,1,0],\n[1,0,1,1],\n[1-n,1,1,1],\n[1-n,1,1-n,2],\n[1-n,2,1,2]],\n\"2\":n=>[\n[0,0,1,0],\n[1,0,1,1],\n[0,1,1,1],\n[0,1+n,0,2],\n[1,2-n,1,2],\n[0,2,1,2]],\n\"3\":n=>[\n[0,0,1-n,0],\n[0,0,0,n],\n[1,0,1,1],\n[0,1,1,1],\n[1,1,1,2],\n[n,2,1,2]],\n\"4\":n=>[\n[0,0,0,1],\n[1,0,1-n,0],\n[1,0,1,1-n],\n[0,1,1,1],\n[1,1,1,2],\n[1-n,2,1,2]],\n\"5\": (n,maxFive)=>maxFive ? [ // 5 -> 0\n[0,0,0,1],\n[0,0,1,0],\n[n,1,1,1],\n[1,1,1,2],\n[0,2,1,2],\n[0,2,0,2],\n[1,1-n,1,1],\n[0,1,0,1+n]] : [ // 5 -> 6\n[0,0,0,1],\n[0,0,1,0],\n[0,1,1,1],\n[1,1,1,2],\n[0,2,1,2],\n[0,2-n,0,2]],\n\"6\":n=>[\n[0,0,0,1-n],\n[0,0,1,0],\n[n,1,1,1],\n[1,1-n,1,1],\n[1,1,1,2],\n[n,2,1,2],\n[0,1-n,0,2-2*n]],\n\"7\":n=>[\n[0,0,0,n],\n[0,0,1,0],\n[1,0,1,1],\n[1-n,1,1,1],\n[1,1,1,2],\n[1-n,2,1,2],\n[1-n,1,1-n,2]],\n\"8\":n=>[\n[0,0,0,1],\n[0,0,1,0],\n[1,0,1,1],\n[0,1,1,1],\n[1,1,1,2],\n[0,2,1,2],\n[0,1,0,2-n]],\n\"9\":n=>[\n[0,0,0,1],\n[0,0,1,0],\n[1,0,1,1],\n[0,1,1-n,1],\n[0,1,0,1+n],\n[1,1,1,2],\n[0,2,1,2]],\n\":\":n=>[\n[0.4,0.4,0.6,0.4],\n[0.6,0.4,0.6,0.6],\n[0.6,0.6,0.4,0.6],\n[0.4,0.4,0.4,0.6],\n[0.4,1.4,0.6,1.4],\n[0.6,1.4,0.6,1.6],\n[0.6,1.6,0.4,1.6],\n[0.4,1.4,0.4,1.6]]\n};\n\n/* Draw a transition between lastText and thisText.\n 'n' is the amount - 0..1 */\nfunction draw(lastText,thisText,n) {\n buf.clear();\n var x = 1; // x offset\n const p = 2; // padding around digits\n var y = p; // y offset\n const s = 34; // character size\n for (var i=0;i{\n if (c[0]!=c[2]) // horiz\n buf.fillRect(x+c[0]*s,y+c[1]*s-p,x+c[2]*s,y+c[3]*s+p);\n else if (c[1]!=c[3]) // vert\n buf.fillRect(x+c[0]*s-p,y+c[1]*s,x+c[2]*s+p,y+c[3]*s);\n });\n if (thisCh==\":\") x-=4;\n x+=s+p+7;\n }\n y += 2*s;\n var d = new Date();\n buf.setFont(\"6x8\");\n buf.setFontAlign(-1,-1);\n buf.drawString((\"0\"+d.getSeconds()).substr(-2), x, y-8);\n // date\n buf.setFontAlign(0,-1);\n var date = d.toString().substr(0,15);\n buf.drawString(date, buf.getWidth()/2, y+8);\n flip();\n}\n\n/* Show the current time, and animate if needed */\nfunction showTime() {\n if (!Bangle.isLCDOn()) return;\n if (animInterval) return; // in animation - quit\n var d = new Date();\n var t = (\" \"+d.getHours()).substr(-2)+\":\"+\n (\"0\"+d.getMinutes()).substr(-2);\n var l = lastTime;\n // same - don't animate\n if (t==l) {\n draw(t,l,0);\n return;\n }\n var n = 0;\n animInterval = setInterval(function() {\n n += 1/10;\n if (n>=1) {\n n=1;\n clearInterval(animInterval);\n animInterval=0;\n }\n draw(l,t,n);\n }, 20);\n lastTime = t;\n}\n\nBangle.on('lcdPower',function(on) {\n if (on) {\n showTime();\n drawWidgets();\n }\n});\n\ng.clear();\n// Update time once a second\nsetInterval(showTime, 1000);\nshowTime();\n})();\n"); +require('Storage').write("-mclock","(function(){ // make our own scope so this is GC'd when intervals are cleared\n// Offscreen buffer\nvar buf = Graphics.createArrayBuffer(240,86,1,{msb:true});\nfunction flip() {\n g.setColor(1,1,1);\n g.drawImage({width:buf.getWidth(),height:buf.getHeight(),buffer:buf.buffer},0,50);\n}\n// The last time that we displayed\nvar lastTime = \" \";\n// If animating, this is the interval's id\nvar animInterval;\n\n/* Get array of lines from digit d to d+1.\n n is the amount (0..1)\n maxFive is true is this digit only counts 0..5 */\nconst DIGITS = {\n\" \":n=>[],\n\"0\":n=>[\n[n,0,1,0],\n[1,0,1,1],\n[1,1,1,2],\n[n,2,1,2],\n[n,1,n,2],\n[n,0,n,1]],\n\"1\":n=>[\n[1-n,0,1,0],\n[1,0,1,1],\n[1-n,1,1,1],\n[1-n,1,1-n,2],\n[1-n,2,1,2]],\n\"2\":n=>[\n[0,0,1,0],\n[1,0,1,1],\n[0,1,1,1],\n[0,1+n,0,2],\n[1,2-n,1,2],\n[0,2,1,2]],\n\"3\":n=>[\n[0,0,1-n,0],\n[0,0,0,n],\n[1,0,1,1],\n[0,1,1,1],\n[1,1,1,2],\n[n,2,1,2]],\n\"4\":n=>[\n[0,0,0,1],\n[1,0,1-n,0],\n[1,0,1,1-n],\n[0,1,1,1],\n[1,1,1,2],\n[1-n,2,1,2]],\n\"5\": (n,maxFive)=>maxFive ? [ // 5 -> 0\n[0,0,0,1],\n[0,0,1,0],\n[n,1,1,1],\n[1,1,1,2],\n[0,2,1,2],\n[0,2,0,2],\n[1,1-n,1,1],\n[0,1,0,1+n]] : [ // 5 -> 6\n[0,0,0,1],\n[0,0,1,0],\n[0,1,1,1],\n[1,1,1,2],\n[0,2,1,2],\n[0,2-n,0,2]],\n\"6\":n=>[\n[0,0,0,1-n],\n[0,0,1,0],\n[n,1,1,1],\n[1,1-n,1,1],\n[1,1,1,2],\n[n,2,1,2],\n[0,1-n,0,2-2*n]],\n\"7\":n=>[\n[0,0,0,n],\n[0,0,1,0],\n[1,0,1,1],\n[1-n,1,1,1],\n[1,1,1,2],\n[1-n,2,1,2],\n[1-n,1,1-n,2]],\n\"8\":n=>[\n[0,0,0,1],\n[0,0,1,0],\n[1,0,1,1],\n[0,1,1,1],\n[1,1,1,2],\n[0,2,1,2],\n[0,1,0,2-n]],\n\"9\":n=>[\n[0,0,0,1],\n[0,0,1,0],\n[1,0,1,1],\n[0,1,1-n,1],\n[0,1,0,1+n],\n[1,1,1,2],\n[0,2,1,2]],\n\":\":n=>[\n[0.4,0.4,0.6,0.4],\n[0.6,0.4,0.6,0.6],\n[0.6,0.6,0.4,0.6],\n[0.4,0.4,0.4,0.6],\n[0.4,1.4,0.6,1.4],\n[0.6,1.4,0.6,1.6],\n[0.6,1.6,0.4,1.6],\n[0.4,1.4,0.4,1.6]]\n};\n\n/* Draw a transition between lastText and thisText.\n 'n' is the amount - 0..1 */\nfunction draw(lastText,thisText,n) {\n buf.clear();\n var x = 1; // x offset\n const p = 2; // padding around digits\n var y = p; // y offset\n const s = 34; // character size\n for (var i=0;i{\n if (c[0]!=c[2]) // horiz\n buf.fillRect(x+c[0]*s,y+c[1]*s-p,x+c[2]*s,y+c[3]*s+p);\n else if (c[1]!=c[3]) // vert\n buf.fillRect(x+c[0]*s-p,y+c[1]*s,x+c[2]*s+p,y+c[3]*s);\n });\n if (thisCh==\":\") x-=4;\n x+=s+p+7;\n }\n y += 2*s;\n var d = new Date();\n buf.setFont(\"6x8\");\n buf.setFontAlign(-1,-1);\n buf.drawString((\"0\"+d.getSeconds()).substr(-2), x, y-8);\n // date\n buf.setFontAlign(0,-1);\n var date = d.toString().substr(0,15);\n buf.drawString(date, buf.getWidth()/2, y+8);\n flip();\n}\n\n/* Show the current time, and animate if needed */\nfunction showTime() {\n if (!Bangle.isLCDOn()) return;\n if (animInterval) return; // in animation - quit\n var d = new Date();\n var t = (\" \"+d.getHours()).substr(-2)+\":\"+\n (\"0\"+d.getMinutes()).substr(-2);\n var l = lastTime;\n // same - don't animate\n if (t==l) {\n draw(t,l,0);\n return;\n }\n var n = 0;\n animInterval = setInterval(function() {\n n += 1/10;\n if (n>=1) {\n n=1;\n clearInterval(animInterval);\n animInterval=0;\n }\n draw(l,t,n);\n }, 20);\n lastTime = t;\n}\n\nBangle.on('lcdPower',function(on) {\n if (on) {\n showTime();\n drawWidgets();\n }\n});\n\ng.clear();\n// Update time once a second\nsetInterval(showTime, 1000);\nshowTime();\n})();\n"); require('Storage').write("*mclock",require("heatshrink").decompress(atob("mEwghC/AE8IxAAEwAWVDB4WIDBwWJAAIWPmf//8zDBpFDwYVBAAc4JJYWJDAoXKn4SC+EPAgXzC5JGCx4qDC4n//BIIEIRCEC4v/GBBdHC4xhCIw5dDC5BhCJAgXCRQoXGJAQXEUhAXHJAyNGC5KRCC7p2FC5B4CC5kggQXOBwvyBQMvSA4XL+EIwCoIC8ZHCgYXNO44LBBIiPPCAIwFC5DXGAAMwGAjvPGA4XIwYXHGALBDnAXFhCQHGAaOFwAXGPA4bFC4xIMIxIXDJBJGEC4xICSJCNEIwowEMJBdCFwwXEMJBdCC5BICDA4WDIw4wEAAMzCoMzBAgWIDAwAGCxRJEAAxFJDBgWNDBAWPAH4AYA=="))); require('Storage').write("+setting",{"name":"Settings","type":"app","icon":"*settings","src":"-settings","files":"+setting,-setting,=setting,@setting,*setting"}); -require('Storage').write("-setting","Bangle.setLCDPower(1);\nBangle.setLCDTimeout(0);\n\ng.clear();\nconst storage = require('Storage');\nlet settings;\n\nfunction debug(msg, arg) {\n if (settings.debug)\n console.log(msg, arg);\n}\n\nfunction updateSettings() {\n debug('updating settings', settings);\n //storage.erase('@setting'); // - not needed, just causes extra writes if settings were the same\n storage.write('@setting', settings);\n}\n\nfunction resetSettings() {\n settings = {\n ble: false,\n dev: false,\n timeout: 10,\n vibrate: true,\n beep: true,\n timezone: 0,\n HID : false,\n HIDGestures: false,\n debug: false,\n };\n setLCDTimeout(settings.timeout);\n updateSettings();\n}\n\ntry {\n settings = storage.readJSON('@setting');\n} catch (e) {}\nif (!settings) resetSettings();\n\nconst boolFormat = (v) => v ? \"On\" : \"Off\";\n\nfunction showMainMenu() {\n const mainmenu = {\n '': { 'title': 'Settings' },\n 'BLE': {\n value: settings.ble,\n format: boolFormat,\n onchange: () => {\n settings.ble = !settings.ble;\n updateSettings();\n }\n },\n 'Programmable': {\n value: settings.dev,\n format: boolFormat,\n onchange: () => {\n settings.dev = !settings.dev;\n updateSettings();\n }\n },\n 'LCD Timeout': {\n value: settings.timeout,\n min: 0,\n max: 60,\n step: 5,\n onchange: v => {\n settings.timeout = 0 | v;\n updateSettings();\n Bangle.setLCDTimeout(settings.timeout);\n }\n },\n 'Beep': {\n value: settings.beep,\n format: boolFormat,\n onchange: () => {\n settings.beep = !settings.beep;\n updateSettings();\n if (settings.beep) {\n Bangle.beep(1);\n }\n }\n },\n 'Vibration': {\n value: settings.vibrate,\n format: boolFormat,\n onchange: () => {\n settings.vibrate = !settings.vibrate;\n updateSettings();\n if (settings.vibrate) {\n VIBRATE.write(1);\n setTimeout(()=>VIBRATE.write(0), 10);\n }\n }\n },\n 'Time Zone': {\n value: settings.timezone,\n min: -11,\n max: 12,\n step: 1,\n onchange: v => {\n settings.timezone = 0 | v;\n updateSettings();\n }\n },\n 'HID': {\n value: settings.HID,\n format: boolFormat,\n onchange: () => {\n settings.HID = !settings.HID;\n updateSettings();\n }\n },\n 'HID Gestures': {\n value: settings.HIDGestures,\n format: boolFormat,\n onchange: () => {\n settings.HIDGestures = !settings.HIDGestures;\n updateSettings();\n }\n },\n 'Debug': {\n value: settings.debug,\n format: boolFormat,\n onchange: () => {\n settings.debug = !settings.debug;\n updateSettings();\n }\n },\n 'Set Time': showSetTimeMenu,\n 'Make Connectable': makeConnectable,\n 'Reset Settings': showResetMenu,\n 'Turn Off': Bangle.off,\n '< Back': load\n };\n return Bangle.menu(mainmenu);\n}\n\nfunction showResetMenu() {\n const resetmenu = {\n '': { 'title': 'Reset' },\n '< Back': showMainMenu,\n 'Reset Settings': () => {\n E.showPrompt('Reset Settings?').then((v) => {\n if (v) {\n E.showMessage('Resetting');\n resetSettings();\n }\n setTimeout(showMainMenu, 50);\n });\n },\n // this is include for debugging. remove for production\n /*'Erase': () => {\n storage.erase('=setting');\n storage.erase('-setting');\n storage.erase('@setting');\n storage.erase('*setting');\n storage.erase('+setting');\n E.reboot();\n }*/\n };\n return Bangle.menu(resetmenu);\n}\n\nfunction makeConnectable() {\n try { NRF.wake(); } catch(e) {}\n Bluetooth.setConsole(1);\n var name=\"Bangle.js \"+NRF.getAddress().substr(-5).replace(\":\",\"\");\n E.showPrompt(name+\"\\nStay Connectable?\",{title:\"Connectable\"}).then(r=>{\n if (settings.ble!=r) {\n settings.ble = r;\n updateSettings();\n }\n if (!r) try { NRF.sleep(); } catch(e) {}\n showMainMenu();\n });\n}\n\nfunction showSetTimeMenu() {\n d = new Date();\n const timemenu = {\n '': {\n 'title': 'Set Time',\n 'predraw': function() {\n d = new Date();\n timemenu.Hour.value = d.getHours();\n timemenu.Minute.value = d.getMinutes();\n timemenu.Second.value = d.getSeconds();\n timemenu.Date.value = d.getDate();\n timemenu.Month.value = d.getMonth() + 1;\n timemenu.Year.value = d.getFullYear();\n }\n },\n '< Back': showMainMenu,\n 'Hour': {\n value: d.getHours(),\n min: 0,\n max: 23,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setHours(v);\n setTime(d.getTime()/1000);\n }\n },\n 'Minute': {\n value: d.getMinutes(),\n min: 0,\n max: 59,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setMinutes(v);\n setTime(d.getTime()/1000);\n }\n },\n 'Second': {\n value: d.getSeconds(),\n min: 0,\n max: 59,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setSeconds(v);\n setTime(d.getTime()/1000);\n }\n },\n 'Date': {\n value: d.getDate(),\n min: 1,\n max: 31,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setDate(v);\n setTime(d.getTime()/1000);\n }\n },\n 'Month': {\n value: d.getMonth() + 1,\n min: 1,\n max: 12,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setMonth(v - 1);\n setTime(d.getTime()/1000);\n }\n },\n 'Year': {\n value: d.getFullYear(),\n min: d.getFullYear() - 10,\n max: d.getFullYear() + 10,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setFullYear(v);\n setTime(d.getTime()/1000);\n }\n }\n };\n return Bangle.menu(timemenu);\n}\n\nshowMainMenu();\n"); -require('Storage').write("=setting","Bangle.HID = E.toUint8Array(atob(\"BQEJBqEBhQIFBxngKecVACUBdQGVCIEClQF1CIEBlQV1AQUIGQEpBZEClQF1A5EBlQZ1CBUAJXMFBxkAKXOBAAkFFQAm/wB1CJUCsQLABQwJAaEBhQEVACUBdQGVAQm1gQIJtoECCbeBAgm4gQIJzYECCeKBAgnpgQIJ6oECwA==\"));\n\n(function() {\n var s = require('Storage').readJSON('@setting');\n var adv = { uart: true };\n if (s.ble) {\n if (s.dev)\n Bluetooth.setConsole(true);\n else\n Terminal.setConsole(true);\n if (s.HID) {\n adv.hid = Bangle.HID;\n } else\n delete Bangle.HID;\n }\n setTimeout(function() {\n NRF.setServices({}, adv);\n if (s.ble) NRF.wake();\n else NRF.sleep();\n },10);\n\n if (!s.vibrate) Bangle.buzz=()=>Promise.resolve();\n if (!s.beep) Bangle.beep=()=>Promise.resolve();\n Bangle.setLCDTimeout(s.timeout);\n if (!s.timeout) Bangle.setLCDPower(1);\n E.setTimeZone(s.timezone);\n})()\n"); +require('Storage').write("-setting","Bangle.setLCDPower(1);\nBangle.setLCDTimeout(0);\n\ng.clear();\nconst storage = require('Storage');\nlet settings;\n\nfunction debug(msg, arg) {\n if (settings.debug)\n console.log(msg, arg);\n}\n\nfunction updateSettings() {\n debug('updating settings', settings);\n //storage.erase('@setting'); // - not needed, just causes extra writes if settings were the same\n storage.write('@setting', settings);\n}\n\nfunction resetSettings() {\n settings = {\n ble: false,\n dev: false,\n timeout: 10,\n vibrate: true,\n beep: true,\n timezone: 0,\n HID : false,\n HIDGestures: false,\n debug: false,\n clock: null\n };\n setLCDTimeout(settings.timeout);\n updateSettings();\n}\n\ntry {\n settings = storage.readJSON('@setting');\n} catch (e) {}\nif (!settings) resetSettings();\n\nconst boolFormat = (v) => v ? \"On\" : \"Off\";\n\nfunction showMainMenu() {\n const mainmenu = {\n '': { 'title': 'Settings' },\n 'BLE': {\n value: settings.ble,\n format: boolFormat,\n onchange: () => {\n settings.ble = !settings.ble;\n updateSettings();\n }\n },\n 'Programmable': {\n value: settings.dev,\n format: boolFormat,\n onchange: () => {\n settings.dev = !settings.dev;\n updateSettings();\n }\n },\n 'LCD Timeout': {\n value: settings.timeout,\n min: 0,\n max: 60,\n step: 5,\n onchange: v => {\n settings.timeout = 0 | v;\n updateSettings();\n Bangle.setLCDTimeout(settings.timeout);\n }\n },\n 'Beep': {\n value: settings.beep,\n format: boolFormat,\n onchange: () => {\n settings.beep = !settings.beep;\n updateSettings();\n if (settings.beep) {\n Bangle.beep(1);\n }\n }\n },\n 'Vibration': {\n value: settings.vibrate,\n format: boolFormat,\n onchange: () => {\n settings.vibrate = !settings.vibrate;\n updateSettings();\n if (settings.vibrate) {\n VIBRATE.write(1);\n setTimeout(()=>VIBRATE.write(0), 10);\n }\n }\n },\n 'Select Clock': showClockMenu,\n 'Time Zone': {\n value: settings.timezone,\n min: -11,\n max: 12,\n step: 1,\n onchange: v => {\n settings.timezone = 0 | v;\n updateSettings();\n }\n },\n 'HID': {\n value: settings.HID,\n format: boolFormat,\n onchange: () => {\n settings.HID = !settings.HID;\n updateSettings();\n }\n },\n 'HID Gestures': {\n value: settings.HIDGestures,\n format: boolFormat,\n onchange: () => {\n settings.HIDGestures = !settings.HIDGestures;\n updateSettings();\n }\n },\n 'Debug': {\n value: settings.debug,\n format: boolFormat,\n onchange: () => {\n settings.debug = !settings.debug;\n updateSettings();\n }\n },\n 'Set Time': showSetTimeMenu,\n 'Make Connectable': makeConnectable,\n 'Reset Settings': showResetMenu,\n 'Turn Off': Bangle.off,\n '< Back': load\n };\n return Bangle.menu(mainmenu);\n}\n\nfunction showResetMenu() {\n const resetmenu = {\n '': { 'title': 'Reset' },\n '< Back': showMainMenu,\n 'Reset Settings': () => {\n E.showPrompt('Reset Settings?').then((v) => {\n if (v) {\n E.showMessage('Resetting');\n resetSettings();\n }\n setTimeout(showMainMenu, 50);\n });\n },\n // this is include for debugging. remove for production\n /*'Erase': () => {\n storage.erase('=setting');\n storage.erase('-setting');\n storage.erase('@setting');\n storage.erase('*setting');\n storage.erase('+setting');\n E.reboot();\n }*/\n };\n return Bangle.menu(resetmenu);\n}\n\nfunction makeConnectable() {\n try { NRF.wake(); } catch(e) {}\n Bluetooth.setConsole(1);\n var name=\"Bangle.js \"+NRF.getAddress().substr(-5).replace(\":\",\"\");\n E.showPrompt(name+\"\\nStay Connectable?\",{title:\"Connectable\"}).then(r=>{\n if (settings.ble!=r) {\n settings.ble = r;\n updateSettings();\n }\n if (!r) try { NRF.sleep(); } catch(e) {}\n showMainMenu();\n });\n}\nfunction showClockMenu() {\n var clockApps = require(\"Storage\").list().filter(a=>a[0]=='+').map(app=>{\n try { return require(\"Storage\").readJSON(app); }\n catch (e) {}\n }).filter(app=>app.type==\"clock\").sort((a, b) => a.sortorder - b.sortorder);\n const clockMenu = {\n '': {\n 'title': 'Select Clock',\n },\n '< Back': showMainMenu,\n };\n clockApps.forEach(app => {\n var label = app.name;\n if (settings.clock === app.src) {\n label = \"* \"+label;\n }\n clockMenu[label] = () => {\n if (settings.clock !== app.src) {\n settings.clock = app.src;\n updateSettings();\n showMainMenu();\n }\n };\n });\n if (clockApps.length === 0) {\n clockMenu[\"No Clocks Found\"] = () => {};\n }\n return Bangle.menu(clockMenu);\n}\n\n\n\nfunction showSetTimeMenu() {\n d = new Date();\n const timemenu = {\n '': {\n 'title': 'Set Time',\n 'predraw': function() {\n d = new Date();\n timemenu.Hour.value = d.getHours();\n timemenu.Minute.value = d.getMinutes();\n timemenu.Second.value = d.getSeconds();\n timemenu.Date.value = d.getDate();\n timemenu.Month.value = d.getMonth() + 1;\n timemenu.Year.value = d.getFullYear();\n }\n },\n '< Back': showMainMenu,\n 'Hour': {\n value: d.getHours(),\n min: 0,\n max: 23,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setHours(v);\n setTime(d.getTime()/1000);\n }\n },\n 'Minute': {\n value: d.getMinutes(),\n min: 0,\n max: 59,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setMinutes(v);\n setTime(d.getTime()/1000);\n }\n },\n 'Second': {\n value: d.getSeconds(),\n min: 0,\n max: 59,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setSeconds(v);\n setTime(d.getTime()/1000);\n }\n },\n 'Date': {\n value: d.getDate(),\n min: 1,\n max: 31,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setDate(v);\n setTime(d.getTime()/1000);\n }\n },\n 'Month': {\n value: d.getMonth() + 1,\n min: 1,\n max: 12,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setMonth(v - 1);\n setTime(d.getTime()/1000);\n }\n },\n 'Year': {\n value: d.getFullYear(),\n min: d.getFullYear() - 10,\n max: d.getFullYear() + 10,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setFullYear(v);\n setTime(d.getTime()/1000);\n }\n }\n };\n return Bangle.menu(timemenu);\n}\n\nshowMainMenu();\n"); +require('Storage').write("=setting","Bangle.HID = E.toUint8Array(atob(\"BQEJBqEBhQIFBxngKecVACUBdQGVCIEClQF1CIEBlQV1AQUIGQEpBZEClQF1A5EBlQZ1CBUAJXMFBxkAKXOBAAkFFQAm/wB1CJUCsQLABQwJAaEBhQEVACUBdQGVAQm1gQIJtoECCbeBAgm4gQIJzYECCeKBAgnpgQIJ6oECwA==\"));\n\n(function() {\n var s = require('Storage').readJSON('@setting');\n var adv = { uart: true };\n if (s.ble) {\n if (s.dev)\n Bluetooth.setConsole(true);\n else\n Terminal.setConsole(true);\n if (s.HID) {\n adv.hid = Bangle.HID;\n } else\n delete Bangle.HID;\n }\n NRF.setServices({}, adv);\n // we just reset, so BLE should be on\n try { // disable advertising if BLE should be off\n if (!s.ble) NRF.sleep();\n else NRF.wake();\n } catch(e) {}\n if (!s.vibrate) Bangle.buzz=Promise.resolve;\n if (!s.beep) Bangle.beep=Promise.resolve;\n Bangle.setLCDTimeout(s.timeout);\n if (!s.timeout) Bangle.setLCDPower(1);\n E.setTimeZone(s.timezone);\n})()\n"); require('Storage').write("@setting",{ ble: false, // Bluetooth disabled by default dev: false, // Espruino IDE disabled by default @@ -24,12 +24,12 @@ require('Storage').write("-gpstime","var img = require(\"heatshrink\").decompress(atob(\"mEwghC/AH8A1QWVhWq0AuVAAIuVAAIwT1WinQwTFwMzmQwTCYMjlUqGCIuBlWi0UzC6JdBIoMjC4UDmAuOkYXBPAWgmczLp2ilUiVAUDC4IwLFwIUBLoJ2BFwQwM1WjCgJ1DFwQwLFwJ1B0SQCkQWDGBQXBCgK9BDgKQBAAgwJOwUzRgIDBC54wCkZdGPBwACRgguDBIIwLFxEJBQIwLFxGaBYQwKFxQwLgAWGmQuBcAQwJC48ifYYwJgUidgsyC4L7DGBIXBdohnBCgL7BcYIXIGAqMCIoL7DL5IwERgIUBLoL7BO5QXBGAK7DkWiOxQXGFwOjFoUyFxZhDgBdCCgJ1CCxYxCgBABkcqOwIuNGAQXC0S9BLpgAFXoIwBmYuPAAYwCLp4wHFyYwDFyYwDFygwCCyoA/AFQA=\"));\n\nBangle.setLCDPower(1);\nBangle.setLCDTimeout(0);\n\ng.clear();\n\n\n\nvar fix;\nBangle.on('GPS',function(f) {\n fix = f;\n g.setFont(\"6x8\",2);\n g.setFontAlign(0,0);\n g.clearRect(90,30,239,90);\n if (fix.fix) {\n g.drawString(\"GPS\",170,40);\n g.drawString(\"Acquired\",170,60);\n } else {\n g.drawString(\"Waiting for\",170,40);\n g.drawString(\"GPS Fix\",170,60);\n }\n g.setFont(\"6x8\");\n g.drawString(fix.satellites+\" satellites\",170,80);\n \n g.clearRect(0,100,239,239);\n var t = fix.time.toString().split(\" \");/*\n [\n \"Sun\",\n \"Nov\",\n \"10\",\n \"2019\",\n \"15:55:35\",\n \"GMT+0100\"\n ]\n */\n //g.setFont(\"6x8\",2);\n //g.drawString(t[0],120,110); // day\n g.setFont(\"6x8\",3);\n g.drawString(t[1]+\" \"+t[2],120,135); // date\n g.setFont(\"6x8\",2);\n g.drawString(t[3],120,160); // year\n g.setFont(\"6x8\",3);\n g.drawString(t[4],120,185); // time\n // timezone\n var tz = (new Date()).getTimezoneOffset()/60;\n if (tz==0) tz=\"UTC\";\n else if (tz>0) tz=\"UTC+\"+tz;\n else tz=\"UTC\"+tz;\n g.setFont(\"6x8\",2);\n g.drawString(tz,120,210); // gmt\n g.setFontAlign(0,0,3);\n g.drawString(\"Set\",230,120);\n g.setFontAlign(0,0);\n});\n\nsetInterval(function() {\n g.drawImage(img,48,48,{scale:1.5,rotate:Math.sin(getTime()*2)/2});\n},100);\nsetWatch(function() {\n setTime(fix.time.getTime()/1000);\n}, BTN2, {repeat:true});\n\nBangle.setGPSPower(1)\n"); require('Storage').write("*gpstime",require("heatshrink").decompress(atob("mEwghC/AH8A1QWVhWq0AuVAAIuVAAIwT1WinQwTFwMzmQwTCYMjlUqGCIuBlWi0UzC6JdBIoMjC4UDmAuOkYXBPAWgmczLp2ilUiVAUDC4IwLFwIUBLoJ2BFwQwM1WjCgJ1DFwQwLFwJ1B0SQCkQWDGBQXBCgK9BDgKQBAAgwJOwUzRgIDBC54wCkZdGPBwACRgguDBIIwLFxEJBQIwLFxGaBYQwKFxQwLgAWGmQuBcAQwJC48ifYYwJgUidgsyC4L7DGBIXBdohnBCgL7BcYIXIGAqMCIoL7DL5IwERgIUBLoL7BO5QXBGAK7DkWiOxQXGFwOjFoUyFxZhDgBdCCgJ1CCxYxCgBABkcqOwIuNGAQXC0S9BLpgAFXoIwBmYuPAAYwCLp4wHFyYwDFyYwDFygwCCyoA/AFQA="))); require('Storage').write("+compass",{"name":"Compass","type":"app","icon":"*compass","src":"-compass","files":"+compass,-compass,*compass"}); -require('Storage').write("-compass","g.clear();\ng.setColor(0,0.5,1);\ng.fillCircle(120,130,80,80);\ng.setColor(0,0,0);\ng.fillCircle(120,130,70,70);\n\nfunction arrow(r,c) {\n r=r*Math.PI/180;\n var p = Math.PI/2;\n g.setColor(c);\n g.fillPoly([\n 120+60*Math.sin(r), 130-60*Math.cos(r),\n 120+10*Math.sin(r+p), 130-10*Math.cos(r+p),\n 120+10*Math.sin(r+-p), 130-10*Math.cos(r-p),\n ]);\n}\n\nvar oldHeading = 0;\nBangle.on('mag', function(m) {\n if (!Bangle.isLCDOn()) return;\n g.setFont(\"6x8\",3);\n g.setColor(0);\n g.fillRect(70,0,170,24);\n g.setColor(0xffff);\n g.setFontAlign(0,0);\n g.drawString((m.heading===undefined)?\"---\":Math.round(m.heading),120,12);\n g.setColor(0,0,0);\n arrow(oldHeading,0);\n arrow(oldHeading+180,0);\n arrow(m.heading,0xF800);\n arrow(m.heading+180,0x001F);\n oldHeading = m.heading;\n});\nBangle.setCompassPower(1);\n"); +require('Storage').write("-compass","g.clear();\ng.setColor(0,0.5,1);\ng.fillCircle(120,130,80,80);\ng.setColor(0,0,0);\ng.fillCircle(120,130,70,70);\n\nfunction arrow(r,c) {\n r=r*Math.PI/180;\n var p = Math.PI/2;\n g.setColor(c);\n g.fillPoly([\n 120+60*Math.sin(r), 130-60*Math.cos(r),\n 120+10*Math.sin(r+p), 130-10*Math.cos(r+p),\n 120+10*Math.sin(r+-p), 130-10*Math.cos(r-p),\n ]);\n}\n\nvar oldHeading = 0;\nBangle.on('mag', function(m) {\n if (!Bangle.isLCDOn()) return;\n g.setFont(\"6x8\",3);\n g.setColor(0);\n g.fillRect(70,0,170,24);\n g.setColor(0xffff);\n g.setFontAlign(0,0);\n g.drawString(isNaN(m.heading)?\"---\":Math.round(m.heading),120,12);\n g.setColor(0,0,0);\n arrow(oldHeading,0);\n arrow(oldHeading+180,0);\n arrow(m.heading,0xF800);\n arrow(m.heading+180,0x001F);\n oldHeading = m.heading;\n});\nBangle.setCompassPower(1);\n"); require('Storage').write("*compass",require("heatshrink").decompress(atob("mEwghC/AE8IxAAEwAWVDB4WIDBwWJAAIWOwcz///mc4DBhFDwYVBAAYYDJJAWJDAoXKCw//+YXJIwWPCQk/Aof4JBAuHC4v/GBBdHC4nzMIZGHCAIOBC4vz75hDJAgXCCgS9CC4fdAYQXGIwsyCAPyl//nvdVQoXFRofzkYXCCwJGBSIgXFQ4kymcykfdIwZgDC5XzkUyCwJGDC6FNCwPTC5i9FmQXCMgLZFC48zLgMilUv/vdkUjBII9BC6HSC55HD1WiklDNIgXIBok61QYBkSBFC5kqCwMjC6RGB1RcCR4gXIx4MC+Wqkfyl70BEQf4C4+DIwYqBC4XzGAc4C4sISAfz0QDCFgUzRwmAC4wQB+QTCC4f/AYJeCC4hIEPQi9FIwwXDbIzVHC4xICSIYXGRoRGFGAgqFXgouGC4iqDLo4XIJAQYHCwZGHGAgYBXQUzCwYuIDAwAHCxRJEAAxFJDBgWNDBAWPAH4AYA="))); require('Storage').write("+sbt",{"name":"bluetooth","type":"widget","src":"=sbt","files":"+sbt,=sbt"}); require('Storage').write("=sbt","(function(){\nvar img_bt = E.toArrayBuffer(atob(\"CxQBBgDgFgJgR4jZMawfAcA4D4NYybEYIwTAsBwDAA==\"));\nvar xpos = WIDGETPOS.tr-24;\nWIDGETPOS.tr-=24;\n\nfunction draw() {\n var x = xpos, y = 0;\n if (NRF.getSecurityStatus().connected)\n g.setColor(0,0.5,1);\n else\n g.setColor(0.3,0.3,0.3);\n g.drawImage(img_bt,10+x,2+y);\n g.setColor(1,1,1);\n}\nfunction changed() {\n draw();\n g.flip();\n}\nNRF.on('connected',changed);\nNRF.on('disconnected',changed);\nWIDGETS[\"bluetooth\"]={draw:draw};\n})()\n"); require('Storage').write("+sbat",{"name":"Battery Level","type":"widget","src":"=sbat","files":"+sbat,=sbat"}); -require('Storage').write("=sbat","(function(){\nvar img_charge = E.toArrayBuffer(atob(\"DhgBHOBzgc4HOP////////////////////3/4HgB4AeAHgB4AeAHgB4AeAHg\"));\nvar xpos = WIDGETPOS.tr-64;\nWIDGETPOS.tr-=68;\n\nfunction draw() {\n var s = 63;\n var x = xpos, y = 0;\n g.clearRect(x,y,x+s,y+23);\n if (Bangle.isCharging()) {\n g.drawImage(img_charge,x,y);\n x+=16;\n s-=16;\n }\n g.setColor(1,1,1);\n g.fillRect(x,y+2,x+s-4,y+21);\n g.clearRect(x+2,y+4,x+s-6,y+19);\n g.fillRect(x+s-3,y+10,x+s,y+14);\n g.fillRect(x+4,y+6,x+4+E.getBattery()*(s-12)/100,y+17);\n g.setColor(1,1,1);\n}\nBangle.on('charging',function(charging) { draw(); g.flip(); if(charging)Bangle.buzz(); });\nWIDGETS[\"battery\"]={draw:draw};\n})()\n"); +require('Storage').write("=sbat","(function(){\nvar img_charge = E.toArrayBuffer(atob(\"DhgBHOBzgc4HOP////////////////////3/4HgB4AeAHgB4AeAHgB4AeAHg\"));\nvar xpos = WIDGETPOS.tr-64;\nWIDGETPOS.tr-=68;\n\nfunction draw() {\n var s = 63;\n var x = xpos, y = 0;\n g.clearRect(x,y,x+s,y+23);\n g.setColor(1,1,1);\n if (Bangle.isCharging()) {\n g.drawImage(img_charge,x,y);\n x+=16;\n s-=16;\n }\n g.fillRect(x,y+2,x+s-4,y+21);\n g.clearRect(x+2,y+4,x+s-6,y+19);\n g.fillRect(x+s-3,y+10,x+s,y+14);\n g.fillRect(x+4,y+6,x+4+E.getBattery()*(s-12)/100,y+17);\n g.setColor(1,1,1);\n}\nBangle.on('charging',function(charging) { draw(); g.flip(); if(charging)Bangle.buzz(); });\nWIDGETS[\"battery\"]={draw:draw};\n})()\n"); require('Storage').write("+funrun5",{"name":"5K Fun Run","type":"app","icon":"*funrun5","src":"-funrun5","sortorder":-1,"files":"+funrun5,-funrun5,*funrun5"}); require('Storage').write("-funrun5","var coordScale = 0.6068;\r\nvar coords = new Int32Array([-807016,6918514,-807057,6918544,-807135,6918582,-807238,6918630,-807289,6918646,-807308,6918663,-807376,6918755,-807413,6918852,-807454,6919002,-807482,6919080,-807509,6919158,-807523,6919221,-807538,6919256,-807578,6919336,-807628,6919447,-807634,6919485,-807640,6919505,-807671,6919531,-807703,6919558,-807760,6919613,-807752,6919623,-807772,6919643,-807802,6919665,-807807,6919670,-807811,6919685,-807919,6919656,-807919,6919645,-807890,6919584,-807858,6919533,-807897,6919503,-807951,6919463,-807929,6919430,-807916,6919412,-807907,6919382,-807901,6919347,-807893,6919322,-807878,6919292,-807858,6919274,-807890,6919232,-807909,6919217,-807938,6919206,-807988,6919180,-807940,6919127,-807921,6919100,-807908,6919072,-807903,6919039,-807899,6919006,-807911,6918947,-807907,6918936,-807898,6918905,-807881,6918911,-807874,6918843,-807870,6918821,-807854,6918775,-807811,6918684,-807768,6918593,-807767,6918593,-807729,6918516,-807726,6918505,-807726,6918498,-807739,6918481,-807718,6918465,-807697,6918443,-807616,6918355,-807518,6918263,-807459,6918191,-807492,6918162,-807494,6918147,-807499,6918142,-807500,6918142,-807622,6918041,-807558,6917962,-807520,6917901,-807475,6917933,-807402,6917995,-807381,6918024,-807361,6918068,-807323,6918028,-807262,6918061,-807263,6918061,-807159,6918116,-807148,6918056,-807028,6918063,-807030,6918063,-806979,6918068,-806892,6918090,-806760,6918115,-806628,6918140,-806556,6918162,-806545,6918175,-806531,6918173,-806477,6918169,-806424,6918180,-806425,6918180,-806367,6918195,-806339,6918197,-806309,6918191,-806282,6918182,-806248,6918160,-806225,6918136,-806204,6918107,-806190,6918076,-806169,6917968,-806167,6917953,-806157,6917925,-806140,6917896,-806087,6917839,-806071,6917824,-805969,6917904,-805867,6917983,-805765,6918063,-805659,6918096,-805677,6918131,-805676,6918131,-805717,6918212,-805757,6918294,-805798,6918397,-805827,6918459,-805877,6918557,-805930,6918608,-805965,6918619,-806037,6918646,-806149,6918676,-806196,6918685,-806324,6918703,-806480,6918735,-806528,6918738,-806644,6918712,-806792,6918667,-806846,6918659,-806914,6918654,-806945,6918661,-806971,6918676,-806993,6918689,-806992,6918692,-807065,6918753,-807086,6918786,-807094,6918788,-807102,6918795,-807104,6918793,-807107,6918799,-807102,6918802,-807112,6918812,-807106,6918815,-807115,6918826,-807120,6918823,-807132,6918841,-807141,6918850,-807151,6918841,-807170,6918832,-807193,6918813,-807222,6918775,-807246,6918718,-807250,6918694,-807264,6918637,-807238,6918630,-807148,6918587,-807057,6918544,-806948,6918463]);\r\n\r\nvar min = {\"x\":-807988,\"y\":6917824};\r\nvar max = {\"x\":-805659,\"y\":6919685};\r\nvar gcoords = new Uint8Array(coords.length);\r\nvar coordDistance = new Uint16Array(coords.length/2);\r\n\r\nvar PT_DISTANCE = 30; // distance to a point before we consider it complete\r\n\r\nfunction toScr(p) {\r\n return {\r\n x : 10 + (p.x-min.x)*100/(max.x-min.x),\r\n y : 230 - (p.y-min.y)*100/(max.y-min.y)\r\n };\r\n}\r\n\r\nvar last;\r\nvar totalDistance = 0;\r\nfor (var i=0;i { diff --git a/firmware.js b/firmware.js index 4875b72c5..9bf18ab09 100644 --- a/firmware.js +++ b/firmware.js @@ -3,7 +3,7 @@ require('Storage').write("-mclock","(function(){ // make our own scope so this is GC'd when intervals are cleared\n// Offscreen buffer\nvar buf = Graphics.createArrayBuffer(240,86,1,{msb:true});\nfunction flip() {\n g.setColor(1,1,1);\n g.drawImage({width:buf.getWidth(),height:buf.getHeight(),buffer:buf.buffer},0,50);\n}\n// The last time that we displayed\nvar lastTime = \" \";\n// If animating, this is the interval's id\nvar animInterval;\n\n/* Get array of lines from digit d to d+1.\n n is the amount (0..1)\n maxFive is true is this digit only counts 0..5 */\nconst DIGITS = {\n\" \":n=>[],\n\"0\":n=>[\n[n,0,1,0],\n[1,0,1,1],\n[1,1,1,2],\n[n,2,1,2],\n[n,1,n,2],\n[n,0,n,1]],\n\"1\":n=>[\n[1-n,0,1,0],\n[1,0,1,1],\n[1-n,1,1,1],\n[1-n,1,1-n,2],\n[1-n,2,1,2]],\n\"2\":n=>[\n[0,0,1,0],\n[1,0,1,1],\n[0,1,1,1],\n[0,1+n,0,2],\n[1,2-n,1,2],\n[0,2,1,2]],\n\"3\":n=>[\n[0,0,1-n,0],\n[0,0,0,n],\n[1,0,1,1],\n[0,1,1,1],\n[1,1,1,2],\n[n,2,1,2]],\n\"4\":n=>[\n[0,0,0,1],\n[1,0,1-n,0],\n[1,0,1,1-n],\n[0,1,1,1],\n[1,1,1,2],\n[1-n,2,1,2]],\n\"5\": (n,maxFive)=>maxFive ? [ // 5 -> 0\n[0,0,0,1],\n[0,0,1,0],\n[n,1,1,1],\n[1,1,1,2],\n[0,2,1,2],\n[0,2,0,2],\n[1,1-n,1,1],\n[0,1,0,1+n]] : [ // 5 -> 6\n[0,0,0,1],\n[0,0,1,0],\n[0,1,1,1],\n[1,1,1,2],\n[0,2,1,2],\n[0,2-n,0,2]],\n\"6\":n=>[\n[0,0,0,1-n],\n[0,0,1,0],\n[n,1,1,1],\n[1,1-n,1,1],\n[1,1,1,2],\n[n,2,1,2],\n[0,1-n,0,2-2*n]],\n\"7\":n=>[\n[0,0,0,n],\n[0,0,1,0],\n[1,0,1,1],\n[1-n,1,1,1],\n[1,1,1,2],\n[1-n,2,1,2],\n[1-n,1,1-n,2]],\n\"8\":n=>[\n[0,0,0,1],\n[0,0,1,0],\n[1,0,1,1],\n[0,1,1,1],\n[1,1,1,2],\n[0,2,1,2],\n[0,1,0,2-n]],\n\"9\":n=>[\n[0,0,0,1],\n[0,0,1,0],\n[1,0,1,1],\n[0,1,1-n,1],\n[0,1,0,1+n],\n[1,1,1,2],\n[0,2,1,2]],\n\":\":n=>[\n[0.4,0.4,0.6,0.4],\n[0.6,0.4,0.6,0.6],\n[0.6,0.6,0.4,0.6],\n[0.4,0.4,0.4,0.6],\n[0.4,1.4,0.6,1.4],\n[0.6,1.4,0.6,1.6],\n[0.6,1.6,0.4,1.6],\n[0.4,1.4,0.4,1.6]]\n};\n\n/* Draw a transition between lastText and thisText.\n 'n' is the amount - 0..1 */\nfunction draw(lastText,thisText,n) {\n buf.clear();\n var x = 1; // x offset\n const p = 2; // padding around digits\n var y = p; // y offset\n const s = 34; // character size\n for (var i=0;i{\n if (c[0]!=c[2]) // horiz\n buf.fillRect(x+c[0]*s,y+c[1]*s-p,x+c[2]*s,y+c[3]*s+p);\n else if (c[1]!=c[3]) // vert\n buf.fillRect(x+c[0]*s-p,y+c[1]*s,x+c[2]*s+p,y+c[3]*s);\n });\n if (thisCh==\":\") x-=4;\n x+=s+p+7;\n }\n y += 2*s;\n var d = new Date();\n buf.setFont(\"6x8\");\n buf.setFontAlign(-1,-1);\n buf.drawString((\"0\"+d.getSeconds()).substr(-2), x, y-8);\n // date\n buf.setFontAlign(0,-1);\n var date = d.toString().substr(0,15);\n buf.drawString(date, buf.getWidth()/2, y+8);\n flip();\n}\n\n/* Show the current time, and animate if needed */\nfunction showTime() {\n if (!Bangle.isLCDOn()) return;\n if (animInterval) return; // in animation - quit\n var d = new Date();\n var t = (\" \"+d.getHours()).substr(-2)+\":\"+\n (\"0\"+d.getMinutes()).substr(-2);\n var l = lastTime;\n // same - don't animate\n if (t==l) {\n draw(t,l,0);\n return;\n }\n var n = 0;\n animInterval = setInterval(function() {\n n += 1/10;\n if (n>=1) {\n n=1;\n clearInterval(animInterval);\n animInterval=0;\n }\n draw(l,t,n);\n }, 20);\n lastTime = t;\n}\n\nBangle.on('lcdPower',function(on) {\n if (on) {\n showTime();\n drawWidgets();\n }\n});\n\ng.clear();\n// Update time once a second\nsetInterval(showTime, 1000);\nshowTime();\n})();\n"); require('Storage').write("*mclock",require("heatshrink").decompress(atob("mEwghC/AE8IxAAEwAWVDB4WIDBwWJAAIWPmf//8zDBpFDwYVBAAc4JJYWJDAoXKn4SC+EPAgXzC5JGCx4qDC4n//BIIEIRCEC4v/GBBdHC4xhCIw5dDC5BhCJAgXCRQoXGJAQXEUhAXHJAyNGC5KRCC7p2FC5B4CC5kggQXOBwvyBQMvSA4XL+EIwCoIC8ZHCgYXNO44LBBIiPPCAIwFC5DXGAAMwGAjvPGA4XIwYXHGALBDnAXFhCQHGAaOFwAXGPA4bFC4xIMIxIXDJBJGEC4xICSJCNEIwowEMJBdCFwwXEMJBdCC5BICDA4WDIw4wEAAMzCoMzBAgWIDAwAGCxRJEAAxFJDBgWNDBAWPAH4AYA=="))); require('Storage').write("+setting",{"name":"Settings","type":"app","icon":"*settings","src":"-settings","files":"+setting,-setting,=setting,@setting,*setting"}); -require('Storage').write("-setting","Bangle.setLCDPower(1);\nBangle.setLCDTimeout(0);\n\ng.clear();\nconst storage = require('Storage');\nlet settings;\n\nfunction debug(msg, arg) {\n if (settings.debug)\n console.log(msg, arg);\n}\n\nfunction updateSettings() {\n debug('updating settings', settings);\n //storage.erase('@setting'); // - not needed, just causes extra writes if settings were the same\n storage.write('@setting', settings);\n}\n\nfunction resetSettings() {\n settings = {\n ble: false,\n dev: false,\n timeout: 10,\n vibrate: true,\n beep: true,\n timezone: 0,\n HID : false,\n HIDGestures: false,\n debug: false,\n clock: null\n };\n setLCDTimeout(settings.timeout);\n updateSettings();\n}\n\ntry {\n settings = storage.readJSON('@setting');\n} catch (e) {}\nif (!settings) resetSettings();\n\nconst boolFormat = (v) => v ? \"On\" : \"Off\";\n\nfunction showMainMenu() {\n const mainmenu = {\n '': { 'title': 'Settings' },\n 'BLE': {\n value: settings.ble,\n format: boolFormat,\n onchange: () => {\n settings.ble = !settings.ble;\n updateSettings();\n }\n },\n 'Programmable': {\n value: settings.dev,\n format: boolFormat,\n onchange: () => {\n settings.dev = !settings.dev;\n updateSettings();\n }\n },\n 'LCD Timeout': {\n value: settings.timeout,\n min: 0,\n max: 60,\n step: 5,\n onchange: v => {\n settings.timeout = 0 | v;\n updateSettings();\n Bangle.setLCDTimeout(settings.timeout);\n }\n },\n 'Beep': {\n value: settings.beep,\n format: boolFormat,\n onchange: () => {\n settings.beep = !settings.beep;\n updateSettings();\n if (settings.beep) {\n Bangle.beep(1);\n }\n }\n },\n 'Vibration': {\n value: settings.vibrate,\n format: boolFormat,\n onchange: () => {\n settings.vibrate = !settings.vibrate;\n updateSettings();\n if (settings.vibrate) {\n VIBRATE.write(1);\n setTimeout(()=>VIBRATE.write(0), 10);\n }\n }\n },\n 'Select Clock': showClockMenu,\n 'Time Zone': {\n value: settings.timezone,\n min: -11,\n max: 12,\n step: 1,\n onchange: v => {\n settings.timezone = 0 | v;\n updateSettings();\n }\n },\n 'HID': {\n value: settings.HID,\n format: boolFormat,\n onchange: () => {\n settings.HID = !settings.HID;\n updateSettings();\n }\n },\n 'HID Gestures': {\n value: settings.HIDGestures,\n format: boolFormat,\n onchange: () => {\n settings.HIDGestures = !settings.HIDGestures;\n updateSettings();\n }\n },\n 'Debug': {\n value: settings.debug,\n format: boolFormat,\n onchange: () => {\n settings.debug = !settings.debug;\n updateSettings();\n }\n },\n 'Set Time': showSetTimeMenu,\n 'Make Connectable': makeConnectable,\n 'Reset Settings': showResetMenu,\n 'Turn Off': Bangle.off,\n '< Back': load\n };\n return Bangle.menu(mainmenu);\n}\n\nfunction showResetMenu() {\n const resetmenu = {\n '': { 'title': 'Reset' },\n '< Back': showMainMenu,\n 'Reset Settings': () => {\n E.showPrompt('Reset Settings?').then((v) => {\n if (v) {\n E.showMessage('Resetting');\n resetSettings();\n }\n setTimeout(showMainMenu, 50);\n });\n },\n // this is include for debugging. remove for production\n /*'Erase': () => {\n storage.erase('=setting');\n storage.erase('-setting');\n storage.erase('@setting');\n storage.erase('*setting');\n storage.erase('+setting');\n E.reboot();\n }*/\n };\n return Bangle.menu(resetmenu);\n}\n\nfunction makeConnectable() {\n try { NRF.wake(); } catch(e) {}\n Bluetooth.setConsole(1);\n var name=\"Bangle.js \"+NRF.getAddress().substr(-5).replace(\":\",\"\");\n E.showPrompt(name+\"\\nStay Connectable?\",{title:\"Connectable\"}).then(r=>{\n if (settings.ble!=r) {\n settings.ble = r;\n updateSettings();\n }\n if (!r) try { NRF.sleep(); } catch(e) {}\n showMainMenu();\n });\n}\nfunction showClockMenu() {\n var clockApps = require(\"Storage\").list().filter(a=>a[0]=='+').map(app=>{\n try { return require(\"Storage\").readJSON(app); }\n catch (e) {}\n }).filter(app=>app.type==\"clock\").sort((a, b) => a.sortorder - b.sortorder);\n const clockMenu = {\n '': {\n 'title': 'Select Clock',\n },\n '< Back': showMainMenu,\n };\n clockApps.forEach(app => {\n var label = app.name;\n if (settings.clock === app.src) {\n label = \"* \"+label;\n }\n clockMenu[label] = () => {\n if (settings.clock !== app.src) {\n settings.clock = app.src;\n updateSettings();\n showMainMenu();\n }\n };\n });\n if (clockApps.length === 0) {\n clockMenu[\"No Clocks Found\"] = () => {};\n }\n return Bangle.menu(clockMenu);\n}\n\n\n\nfunction showSetTimeMenu() {\n d = new Date();\n const timemenu = {\n '': {\n 'title': 'Set Time',\n 'predraw': function() {\n d = new Date();\n timemenu.Hour.value = d.getHours();\n timemenu.Minute.value = d.getMinutes();\n timemenu.Second.value = d.getSeconds();\n timemenu.Date.value = d.getDate();\n timemenu.Month.value = d.getMonth() + 1;\n timemenu.Year.value = d.getFullYear();\n }\n },\n '< Back': showMainMenu,\n 'Hour': {\n value: d.getHours(),\n min: 0,\n max: 23,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setHours(v);\n setTime(d.getTime()/1000);\n }\n },\n 'Minute': {\n value: d.getMinutes(),\n min: 0,\n max: 59,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setMinutes(v);\n setTime(d.getTime()/1000);\n }\n },\n 'Second': {\n value: d.getSeconds(),\n min: 0,\n max: 59,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setSeconds(v);\n setTime(d.getTime()/1000);\n }\n },\n 'Date': {\n value: d.getDate(),\n min: 1,\n max: 31,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setDate(v);\n setTime(d.getTime()/1000);\n }\n },\n 'Month': {\n value: d.getMonth() + 1,\n min: 1,\n max: 12,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setMonth(v - 1);\n setTime(d.getTime()/1000);\n }\n },\n 'Year': {\n value: d.getFullYear(),\n min: d.getFullYear() - 10,\n max: d.getFullYear() + 10,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setFullYear(v);\n setTime(d.getTime()/1000);\n }\n }\n };\n return Bangle.menu(timemenu);\n}\n\nshowMainMenu();\n"); +require('Storage').write("-setting","Bangle.setLCDPower(1);\nBangle.setLCDTimeout(0);\n\ng.clear();\nconst storage = require('Storage');\nlet settings;\n\nfunction debug(msg, arg) {\n if (settings.debug)\n console.log(msg, arg);\n}\n\nfunction updateSettings() {\n debug('updating settings', settings);\n //storage.erase('@setting'); // - not needed, just causes extra writes if settings were the same\n storage.write('@setting', settings);\n}\n\nfunction resetSettings() {\n settings = {\n ble: false,\n dev: false,\n timeout: 10,\n vibrate: true,\n beep: true,\n timezone: 0,\n HID : false,\n HIDGestures: false,\n debug: false,\n clock: null\n };\n setLCDTimeout(settings.timeout);\n updateSettings();\n}\n\ntry {\n settings = storage.readJSON('@setting');\n} catch (e) {}\nif (!settings) resetSettings();\n\nconst boolFormat = (v) => v ? \"On\" : \"Off\";\n\nfunction showMainMenu() {\n const mainmenu = {\n '': { 'title': 'Settings' },\n 'BLE': {\n value: settings.ble,\n format: boolFormat,\n onchange: () => {\n settings.ble = !settings.ble;\n updateSettings();\n }\n },\n 'Programmable': {\n value: settings.dev,\n format: boolFormat,\n onchange: () => {\n settings.dev = !settings.dev;\n updateSettings();\n }\n },\n 'LCD Timeout': {\n value: settings.timeout,\n min: 0,\n max: 60,\n step: 5,\n onchange: v => {\n settings.timeout = 0 | v;\n updateSettings();\n Bangle.setLCDTimeout(settings.timeout);\n }\n },\n 'Beep': {\n value: settings.beep,\n format: boolFormat,\n onchange: () => {\n settings.beep = !settings.beep;\n updateSettings();\n if (settings.beep) {\n Bangle.beep(1);\n }\n }\n },\n 'Vibration': {\n value: settings.vibrate,\n format: boolFormat,\n onchange: () => {\n settings.vibrate = !settings.vibrate;\n updateSettings();\n if (settings.vibrate) {\n VIBRATE.write(1);\n setTimeout(()=>VIBRATE.write(0), 10);\n }\n }\n },\n 'Select Clock': showClockMenu,\n 'Time Zone': {\n value: settings.timezone,\n min: -11,\n max: 12,\n step: 1,\n onchange: v => {\n settings.timezone = 0 | v;\n updateSettings();\n }\n },\n 'HID': {\n value: settings.HID,\n format: boolFormat,\n onchange: () => {\n settings.HID = !settings.HID;\n updateSettings();\n }\n },\n 'HID Gestures': {\n value: settings.HIDGestures,\n format: boolFormat,\n onchange: () => {\n settings.HIDGestures = !settings.HIDGestures;\n updateSettings();\n }\n },\n 'Debug': {\n value: settings.debug,\n format: boolFormat,\n onchange: () => {\n settings.debug = !settings.debug;\n updateSettings();\n }\n },\n 'Set Time': showSetTimeMenu,\n 'Make Connectable': makeConnectable,\n 'Reset Settings': showResetMenu,\n 'Turn Off': Bangle.off,\n '< Back': load\n };\n return Bangle.menu(mainmenu);\n}\n\nfunction showResetMenu() {\n const resetmenu = {\n '': { 'title': 'Reset' },\n '< Back': showMainMenu,\n 'Reset Settings': () => {\n E.showPrompt('Reset Settings?').then((v) => {\n if (v) {\n E.showMessage('Resetting');\n resetSettings();\n }\n setTimeout(showMainMenu, 50);\n });\n },\n // this is include for debugging. remove for production\n /*'Erase': () => {\n storage.erase('=setting');\n storage.erase('-setting');\n storage.erase('@setting');\n storage.erase('*setting');\n storage.erase('+setting');\n E.reboot();\n }*/\n };\n return Bangle.menu(resetmenu);\n}\n\nfunction makeConnectable() {\n try { NRF.wake(); } catch(e) {}\n Bluetooth.setConsole(1);\n var name=\"Bangle.js \"+NRF.getAddress().substr(-5).replace(\":\",\"\");\n E.showPrompt(name+\"\\nStay Connectable?\",{title:\"Connectable\"}).then(r=>{\n if (settings.ble!=r) {\n settings.ble = r;\n updateSettings();\n }\n if (!r) try { NRF.sleep(); } catch(e) {}\n showMainMenu();\n });\n}\nfunction showClockMenu() {\n var clockApps = require(\"Storage\").list().filter(a=>a[0]=='+').map(app=>{\n try { return require(\"Storage\").readJSON(app); }\n catch (e) {}\n }).filter(app=>app.type==\"clock\").sort((a, b) => a.sortorder - b.sortorder);\n const clockMenu = {\n '': {\n 'title': 'Select Clock',\n },\n '< Back': showMainMenu,\n };\n clockApps.forEach((app,index) => {\n var label = app.name;\n if ((!settings.clock && index === 0) || (settings.clock === app.src)) {\n label = \"* \"+label;\n }\n clockMenu[label] = () => {\n if (settings.clock !== app.src) {\n settings.clock = app.src;\n updateSettings();\n showMainMenu();\n }\n };\n });\n if (clockApps.length === 0) {\n clockMenu[\"No Clocks Found\"] = () => {};\n }\n return Bangle.menu(clockMenu);\n}\n\n\n\nfunction showSetTimeMenu() {\n d = new Date();\n const timemenu = {\n '': {\n 'title': 'Set Time',\n 'predraw': function() {\n d = new Date();\n timemenu.Hour.value = d.getHours();\n timemenu.Minute.value = d.getMinutes();\n timemenu.Second.value = d.getSeconds();\n timemenu.Date.value = d.getDate();\n timemenu.Month.value = d.getMonth() + 1;\n timemenu.Year.value = d.getFullYear();\n }\n },\n '< Back': showMainMenu,\n 'Hour': {\n value: d.getHours(),\n min: 0,\n max: 23,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setHours(v);\n setTime(d.getTime()/1000);\n }\n },\n 'Minute': {\n value: d.getMinutes(),\n min: 0,\n max: 59,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setMinutes(v);\n setTime(d.getTime()/1000);\n }\n },\n 'Second': {\n value: d.getSeconds(),\n min: 0,\n max: 59,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setSeconds(v);\n setTime(d.getTime()/1000);\n }\n },\n 'Date': {\n value: d.getDate(),\n min: 1,\n max: 31,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setDate(v);\n setTime(d.getTime()/1000);\n }\n },\n 'Month': {\n value: d.getMonth() + 1,\n min: 1,\n max: 12,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setMonth(v - 1);\n setTime(d.getTime()/1000);\n }\n },\n 'Year': {\n value: d.getFullYear(),\n min: d.getFullYear() - 10,\n max: d.getFullYear() + 10,\n step: 1,\n onchange: v => {\n d = new Date();\n d.setFullYear(v);\n setTime(d.getTime()/1000);\n }\n }\n };\n return Bangle.menu(timemenu);\n}\n\nshowMainMenu();\n"); require('Storage').write("=setting","Bangle.HID = E.toUint8Array(atob(\"BQEJBqEBhQIFBxngKecVACUBdQGVCIEClQF1CIEBlQV1AQUIGQEpBZEClQF1A5EBlQZ1CBUAJXMFBxkAKXOBAAkFFQAm/wB1CJUCsQLABQwJAaEBhQEVACUBdQGVAQm1gQIJtoECCbeBAgm4gQIJzYECCeKBAgnpgQIJ6oECwA==\"));\n\n(function() {\n var s = require('Storage').readJSON('@setting');\n var adv = { uart: true };\n if (s.ble) {\n if (s.dev)\n Bluetooth.setConsole(true);\n else\n Terminal.setConsole(true);\n if (s.HID) {\n adv.hid = Bangle.HID;\n } else\n delete Bangle.HID;\n }\n NRF.setServices({}, adv);\n // we just reset, so BLE should be on\n try { // disable advertising if BLE should be off\n if (!s.ble) NRF.sleep();\n else NRF.wake();\n } catch(e) {}\n if (!s.vibrate) Bangle.buzz=Promise.resolve;\n if (!s.beep) Bangle.beep=Promise.resolve;\n Bangle.setLCDTimeout(s.timeout);\n if (!s.timeout) Bangle.setLCDPower(1);\n E.setTimeZone(s.timezone);\n})()\n"); require('Storage').write("@setting",{ ble: false, // Bluetooth disabled by default From da1d4d768c5843fda804a553153373d7f725e496 Mon Sep 17 00:00:00 2001 From: ra100 Date: Sun, 17 Nov 2019 23:26:12 +0100 Subject: [PATCH 09/15] =?UTF-8?q?=F0=9F=9A=9A=20Move=20apps=20to=20subfold?= =?UTF-8?q?ers=20#46?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/{ => aclock}/clock-analog-icon.js | 0 apps/{ => aclock}/clock-analog.js | 0 apps/{ => aclock}/clock-analog.json | 0 apps/{ => aclock}/clock-analog.png | Bin apps/{ => animals}/animals-camel.js | 0 apps/{ => animals}/animals-duck.js | 0 apps/{ => animals}/animals-fox.js | 0 apps/{ => animals}/animals-icon.js | 0 apps/{ => animals}/animals-mouse.js | 0 apps/{ => animals}/animals-pig.js | 0 apps/{ => animals}/animals-sheep.js | 0 apps/{ => animals}/animals-snake.js | 0 apps/{ => animals}/animals-swan.js | 0 apps/{ => animals}/animals.js | 0 apps/{ => animals}/animals.json | 0 apps/{ => animals}/animals.png | Bin apps/{ => astroid}/asteroids-icon.js | 0 apps/{ => astroid}/asteroids.js | 0 apps/{ => astroid}/asteroids.json | 0 apps/{ => astroid}/asteroids.png | Bin apps/{ => bclock}/clock-binary-icon.js | 0 apps/{ => bclock}/clock-binary.js | 0 apps/{ => bclock}/clock-binary.json | 0 apps/{ => bclock}/clock-binary.png | Bin apps/{ => beer}/beercompass.html | 0 apps/{ => beer}/beercompass.png | Bin apps/{ => blescan}/blescan-icon.js | 0 apps/{ => blescan}/blescan.js | 0 apps/{ => blescan}/blescan.json | 0 apps/{ => blescan}/blescan.png | Bin apps/{ => blobclk}/clock-blob-icon.js | 0 apps/{ => blobclk}/clock-blob.js | 0 apps/{ => blobclk}/clock-blob.json | 0 apps/{ => blobclk}/clock-blob.png | Bin apps/{ => boot}/bootloader.js | 0 apps/{ => boot}/bootloader.png | Bin apps/{ => clickms}/click-master-icon.js | 0 apps/{ => clickms}/click-master.js | 0 apps/{ => clickms}/click-master.json | 0 apps/{ => clickms}/click-master.png | Bin apps/{ => clotris}/clock-tris-high | 0 apps/{ => clotris}/clock-tris-icon.js | 0 apps/{ => clotris}/clock-tris.js | 0 apps/{ => clotris}/clock-tris.json | 0 apps/{ => clotris}/clock-tris.png | Bin apps/{ => compass}/compass-icon.js | 0 apps/{ => compass}/compass.js | 0 apps/{ => compass}/compass.json | 0 apps/{ => compass}/compass.png | Bin apps/{ => files}/files-icon.js | 0 apps/{ => files}/files.js | 0 apps/{ => files}/files.json | 0 apps/{ => files}/files.png | Bin apps/{ => funrun5}/nceu-funrun-icon.js | 0 apps/{ => funrun5}/nceu-funrun.js | 0 apps/{ => funrun5}/nceu-funrun.json | 0 apps/{ => funrun5}/nceu-funrun.png | Bin apps/{ => gesture}/gesture-icon.js | 0 apps/{ => gesture}/gesture-tfmodel.js | 0 apps/{ => gesture}/gesture-tfnames.js | 0 apps/{ => gesture}/gesture.js | 0 apps/{ => gesture}/gesture.json | 0 apps/{ => gesture}/gesture.png | Bin apps/{ => gpsinfo}/gps-info-icon.js | 0 apps/{ => gpsinfo}/gps-info.js | 0 apps/{ => gpsinfo}/gps-info.json | 0 apps/{ => gpsinfo}/gps-info.png | Bin apps/{ => gpstime}/gpstime-icon.js | 0 apps/{ => gpstime}/gpstime.js | 0 apps/{ => gpstime}/gpstime.json | 0 apps/{ => gpstime}/gpstime.png | Bin apps/{ => hidbkbd}/hid-binary-keyboard-icon.js | 0 apps/{ => hidbkbd}/hid-binary-keyboard.js | 0 apps/{ => hidbkbd}/hid-binary-keyboard.json | 0 apps/{ => hidbkbd}/hid-binary-keyboard.png | Bin apps/{ => hidkbd}/hid-keyboard-icon.js | 0 apps/{ => hidkbd}/hid-keyboard.js | 0 apps/{ => hidkbd}/hid-keyboard.json | 0 apps/{ => hidkbd}/hid-keyboard.min.js | 0 apps/{ => hidkbd}/hid-keyboard.png | Bin apps/{ => hidmsic}/hid-music-icon.js | 0 apps/{ => hidmsic}/hid-music.js | 0 apps/{ => hidmsic}/hid-music.json | 0 apps/{ => hidmsic}/hid-music.png | Bin apps/{ => horsey}/horse-race-icon.js | 0 apps/{ => horsey}/horse-race.js | 0 apps/{ => horsey}/horse-race.json | 0 apps/{ => horsey}/horse-race.png | Bin apps/{ => hrings}/hypno-rings-icon.js | 0 apps/{ => hrings}/hypno-rings.js | 0 apps/{ => hrings}/hypno-rings.json | 0 apps/{ => hrings}/hypno-rings.png | Bin apps/{ => hrm}/heartrate-icon.js | 0 apps/{ => hrm}/heartrate.js | 0 apps/{ => hrm}/heartrate.json | 0 apps/{ => hrm}/heartrate.png | Bin apps/{ => jbells}/jbells-icon.js | 0 apps/{ => jbells}/jbells.js | 0 apps/{ => jbells}/jbells.json | 0 apps/{ => jbells}/jbells.png | Bin apps/{ => mclock}/clock-morphing-icon.js | 0 apps/{ => mclock}/clock-morphing.js | 0 apps/{ => mclock}/clock-morphing.json | 0 apps/{ => mclock}/clock-morphing.png | Bin apps/{ => miclock}/clock-mixed-icon.js | 0 apps/{ => miclock}/clock-mixed.js | 0 apps/{ => miclock}/clock-mixed.json | 0 apps/{ => miclock}/clock-mixed.png | Bin apps/{ => mmonday}/manic-monday-icon.js | 0 apps/{ => mmonday}/manic-monday-icon.png | Bin apps/{ => mmonday}/manic-monday.js | 0 apps/{ => mmonday}/manic-monday.json | 0 apps/{ => morse}/morse-code-icon.js | 0 apps/{ => morse}/morse-code.js | 0 apps/{ => morse}/morse-code.json | 0 apps/{ => morse}/morse-code.png | Bin apps/{ => nceuwid}/nceu-widget.js | 0 apps/{ => nceuwid}/nceu-widget.json | 0 apps/{ => nceuwid}/nceu-widget.png | Bin apps/{ => openloc}/openlocation-icon.js | 0 apps/{ => openloc}/openlocation.js | 0 apps/{ => openloc}/openlocation.json | 0 apps/{ => openloc}/openlocation.png | Bin apps/{ => pparrot}/party-parrot-icon.js | 0 apps/{ => pparrot}/party-parrot.js | 0 apps/{ => pparrot}/party-parrot.json | 0 apps/{ => pparrot}/party-parrot.png | Bin apps/{ => promodo}/promodoro-icon.js | 0 apps/{ => promodo}/promodoro.js | 0 apps/{ => promodo}/promodoro.json | 0 apps/{ => promodo}/promodoro.png | Bin apps/{ => qrcode}/qrcode.html | 0 apps/{ => qrcode}/qrcode.png | Bin apps/{ => route}/route.html | 0 apps/{ => route}/route.png | Bin apps/{ => sbat}/widget-battery.js | 0 apps/{ => sbat}/widget-battery.json | 0 apps/{ => sbat}/widget-battery.png | Bin apps/{ => sbt}/widget-bluetooth.js | 0 apps/{ => sbt}/widget-bluetooth.json | 0 apps/{ => sbt}/widget-bluetooth.png | Bin apps/{ => sclock}/clock-simple-icon.js | 0 apps/{ => sclock}/clock-simple.js | 0 apps/{ => sclock}/clock-simple.json | 0 apps/{ => sclock}/clock-simple.png | Bin apps/{ => scolor}/show-color-icon.js | 0 apps/{ => scolor}/show-color.js | 0 apps/{ => scolor}/show-color.json | 0 apps/{ => scolor}/show-color.png | Bin apps/{ => setting}/settings-default.json | 0 apps/{ => setting}/settings-icon.js | 0 apps/{ => setting}/settings-init.js | 0 apps/{ => setting}/settings.js | 0 apps/{ => setting}/settings.json | 0 apps/{ => setting}/settings.png | Bin apps/{ => slevel}/spiritlevel-icon.js | 0 apps/{ => slevel}/spiritlevel.js | 0 apps/{ => slevel}/spiritlevel.json | 0 apps/{ => slevel}/spiritlevel.png | Bin apps/{ => speedo}/speedo-icon.js | 0 apps/{ => speedo}/speedo.js | 0 apps/{ => speedo}/speedo.json | 0 apps/{ => speedo}/speedo.png | Bin apps/{ => start}/start-bangle.js | 0 apps/{ => start}/start-icon.js | 0 apps/{ => start}/start-nceu.js | 0 apps/{ => start}/start-nfr.js | 0 apps/{ => start}/start-nodew.js | 0 apps/{ => start}/start-tf.js | 0 apps/{ => start}/start.js | 0 apps/{ => start}/start.json | 0 apps/{ => start}/start.png | Bin apps/{ => swatch}/stopwatch-icon.js | 0 apps/{ => swatch}/stopwatch.js | 0 apps/{ => swatch}/stopwatch.json | 0 apps/{ => swatch}/stopwatch.png | Bin apps/{ => trex}/trex-icon.js | 0 apps/{ => trex}/trex.js | 0 apps/{ => trex}/trex.json | 0 apps/{ => trex}/trex.png | Bin apps/{ => wclock}/clock-word-icon.js | 0 apps/{ => wclock}/clock-word.js | 0 apps/{ => wclock}/clock-word.json | 0 apps/{ => wclock}/clock-word.png | Bin 184 files changed, 0 insertions(+), 0 deletions(-) rename apps/{ => aclock}/clock-analog-icon.js (100%) rename apps/{ => aclock}/clock-analog.js (100%) rename apps/{ => aclock}/clock-analog.json (100%) rename apps/{ => aclock}/clock-analog.png (100%) rename apps/{ => animals}/animals-camel.js (100%) rename apps/{ => animals}/animals-duck.js (100%) rename apps/{ => animals}/animals-fox.js (100%) rename apps/{ => animals}/animals-icon.js (100%) rename apps/{ => animals}/animals-mouse.js (100%) rename apps/{ => animals}/animals-pig.js (100%) rename apps/{ => animals}/animals-sheep.js (100%) rename apps/{ => animals}/animals-snake.js (100%) rename apps/{ => animals}/animals-swan.js (100%) rename apps/{ => animals}/animals.js (100%) rename apps/{ => animals}/animals.json (100%) rename apps/{ => animals}/animals.png (100%) rename apps/{ => astroid}/asteroids-icon.js (100%) rename apps/{ => astroid}/asteroids.js (100%) rename apps/{ => astroid}/asteroids.json (100%) rename apps/{ => astroid}/asteroids.png (100%) rename apps/{ => bclock}/clock-binary-icon.js (100%) rename apps/{ => bclock}/clock-binary.js (100%) rename apps/{ => bclock}/clock-binary.json (100%) rename apps/{ => bclock}/clock-binary.png (100%) rename apps/{ => beer}/beercompass.html (100%) rename apps/{ => beer}/beercompass.png (100%) rename apps/{ => blescan}/blescan-icon.js (100%) rename apps/{ => blescan}/blescan.js (100%) rename apps/{ => blescan}/blescan.json (100%) rename apps/{ => blescan}/blescan.png (100%) rename apps/{ => blobclk}/clock-blob-icon.js (100%) rename apps/{ => blobclk}/clock-blob.js (100%) rename apps/{ => blobclk}/clock-blob.json (100%) rename apps/{ => blobclk}/clock-blob.png (100%) rename apps/{ => boot}/bootloader.js (100%) rename apps/{ => boot}/bootloader.png (100%) rename apps/{ => clickms}/click-master-icon.js (100%) rename apps/{ => clickms}/click-master.js (100%) rename apps/{ => clickms}/click-master.json (100%) rename apps/{ => clickms}/click-master.png (100%) rename apps/{ => clotris}/clock-tris-high (100%) rename apps/{ => clotris}/clock-tris-icon.js (100%) rename apps/{ => clotris}/clock-tris.js (100%) rename apps/{ => clotris}/clock-tris.json (100%) rename apps/{ => clotris}/clock-tris.png (100%) rename apps/{ => compass}/compass-icon.js (100%) rename apps/{ => compass}/compass.js (100%) rename apps/{ => compass}/compass.json (100%) rename apps/{ => compass}/compass.png (100%) rename apps/{ => files}/files-icon.js (100%) rename apps/{ => files}/files.js (100%) rename apps/{ => files}/files.json (100%) rename apps/{ => files}/files.png (100%) rename apps/{ => funrun5}/nceu-funrun-icon.js (100%) rename apps/{ => funrun5}/nceu-funrun.js (100%) rename apps/{ => funrun5}/nceu-funrun.json (100%) rename apps/{ => funrun5}/nceu-funrun.png (100%) rename apps/{ => gesture}/gesture-icon.js (100%) rename apps/{ => gesture}/gesture-tfmodel.js (100%) rename apps/{ => gesture}/gesture-tfnames.js (100%) rename apps/{ => gesture}/gesture.js (100%) rename apps/{ => gesture}/gesture.json (100%) rename apps/{ => gesture}/gesture.png (100%) rename apps/{ => gpsinfo}/gps-info-icon.js (100%) rename apps/{ => gpsinfo}/gps-info.js (100%) rename apps/{ => gpsinfo}/gps-info.json (100%) rename apps/{ => gpsinfo}/gps-info.png (100%) rename apps/{ => gpstime}/gpstime-icon.js (100%) rename apps/{ => gpstime}/gpstime.js (100%) rename apps/{ => gpstime}/gpstime.json (100%) rename apps/{ => gpstime}/gpstime.png (100%) rename apps/{ => hidbkbd}/hid-binary-keyboard-icon.js (100%) rename apps/{ => hidbkbd}/hid-binary-keyboard.js (100%) rename apps/{ => hidbkbd}/hid-binary-keyboard.json (100%) rename apps/{ => hidbkbd}/hid-binary-keyboard.png (100%) rename apps/{ => hidkbd}/hid-keyboard-icon.js (100%) rename apps/{ => hidkbd}/hid-keyboard.js (100%) rename apps/{ => hidkbd}/hid-keyboard.json (100%) rename apps/{ => hidkbd}/hid-keyboard.min.js (100%) rename apps/{ => hidkbd}/hid-keyboard.png (100%) rename apps/{ => hidmsic}/hid-music-icon.js (100%) rename apps/{ => hidmsic}/hid-music.js (100%) rename apps/{ => hidmsic}/hid-music.json (100%) rename apps/{ => hidmsic}/hid-music.png (100%) rename apps/{ => horsey}/horse-race-icon.js (100%) rename apps/{ => horsey}/horse-race.js (100%) rename apps/{ => horsey}/horse-race.json (100%) rename apps/{ => horsey}/horse-race.png (100%) rename apps/{ => hrings}/hypno-rings-icon.js (100%) rename apps/{ => hrings}/hypno-rings.js (100%) rename apps/{ => hrings}/hypno-rings.json (100%) rename apps/{ => hrings}/hypno-rings.png (100%) rename apps/{ => hrm}/heartrate-icon.js (100%) rename apps/{ => hrm}/heartrate.js (100%) rename apps/{ => hrm}/heartrate.json (100%) rename apps/{ => hrm}/heartrate.png (100%) rename apps/{ => jbells}/jbells-icon.js (100%) rename apps/{ => jbells}/jbells.js (100%) rename apps/{ => jbells}/jbells.json (100%) rename apps/{ => jbells}/jbells.png (100%) rename apps/{ => mclock}/clock-morphing-icon.js (100%) rename apps/{ => mclock}/clock-morphing.js (100%) rename apps/{ => mclock}/clock-morphing.json (100%) rename apps/{ => mclock}/clock-morphing.png (100%) rename apps/{ => miclock}/clock-mixed-icon.js (100%) rename apps/{ => miclock}/clock-mixed.js (100%) rename apps/{ => miclock}/clock-mixed.json (100%) rename apps/{ => miclock}/clock-mixed.png (100%) rename apps/{ => mmonday}/manic-monday-icon.js (100%) rename apps/{ => mmonday}/manic-monday-icon.png (100%) rename apps/{ => mmonday}/manic-monday.js (100%) rename apps/{ => mmonday}/manic-monday.json (100%) rename apps/{ => morse}/morse-code-icon.js (100%) rename apps/{ => morse}/morse-code.js (100%) rename apps/{ => morse}/morse-code.json (100%) rename apps/{ => morse}/morse-code.png (100%) rename apps/{ => nceuwid}/nceu-widget.js (100%) rename apps/{ => nceuwid}/nceu-widget.json (100%) rename apps/{ => nceuwid}/nceu-widget.png (100%) rename apps/{ => openloc}/openlocation-icon.js (100%) rename apps/{ => openloc}/openlocation.js (100%) rename apps/{ => openloc}/openlocation.json (100%) rename apps/{ => openloc}/openlocation.png (100%) rename apps/{ => pparrot}/party-parrot-icon.js (100%) rename apps/{ => pparrot}/party-parrot.js (100%) rename apps/{ => pparrot}/party-parrot.json (100%) rename apps/{ => pparrot}/party-parrot.png (100%) rename apps/{ => promodo}/promodoro-icon.js (100%) rename apps/{ => promodo}/promodoro.js (100%) rename apps/{ => promodo}/promodoro.json (100%) rename apps/{ => promodo}/promodoro.png (100%) rename apps/{ => qrcode}/qrcode.html (100%) rename apps/{ => qrcode}/qrcode.png (100%) rename apps/{ => route}/route.html (100%) rename apps/{ => route}/route.png (100%) rename apps/{ => sbat}/widget-battery.js (100%) rename apps/{ => sbat}/widget-battery.json (100%) rename apps/{ => sbat}/widget-battery.png (100%) rename apps/{ => sbt}/widget-bluetooth.js (100%) rename apps/{ => sbt}/widget-bluetooth.json (100%) rename apps/{ => sbt}/widget-bluetooth.png (100%) rename apps/{ => sclock}/clock-simple-icon.js (100%) rename apps/{ => sclock}/clock-simple.js (100%) rename apps/{ => sclock}/clock-simple.json (100%) rename apps/{ => sclock}/clock-simple.png (100%) rename apps/{ => scolor}/show-color-icon.js (100%) rename apps/{ => scolor}/show-color.js (100%) rename apps/{ => scolor}/show-color.json (100%) rename apps/{ => scolor}/show-color.png (100%) rename apps/{ => setting}/settings-default.json (100%) rename apps/{ => setting}/settings-icon.js (100%) rename apps/{ => setting}/settings-init.js (100%) rename apps/{ => setting}/settings.js (100%) rename apps/{ => setting}/settings.json (100%) rename apps/{ => setting}/settings.png (100%) rename apps/{ => slevel}/spiritlevel-icon.js (100%) rename apps/{ => slevel}/spiritlevel.js (100%) rename apps/{ => slevel}/spiritlevel.json (100%) rename apps/{ => slevel}/spiritlevel.png (100%) rename apps/{ => speedo}/speedo-icon.js (100%) rename apps/{ => speedo}/speedo.js (100%) rename apps/{ => speedo}/speedo.json (100%) rename apps/{ => speedo}/speedo.png (100%) rename apps/{ => start}/start-bangle.js (100%) rename apps/{ => start}/start-icon.js (100%) rename apps/{ => start}/start-nceu.js (100%) rename apps/{ => start}/start-nfr.js (100%) rename apps/{ => start}/start-nodew.js (100%) rename apps/{ => start}/start-tf.js (100%) rename apps/{ => start}/start.js (100%) rename apps/{ => start}/start.json (100%) rename apps/{ => start}/start.png (100%) rename apps/{ => swatch}/stopwatch-icon.js (100%) rename apps/{ => swatch}/stopwatch.js (100%) rename apps/{ => swatch}/stopwatch.json (100%) rename apps/{ => swatch}/stopwatch.png (100%) rename apps/{ => trex}/trex-icon.js (100%) rename apps/{ => trex}/trex.js (100%) rename apps/{ => trex}/trex.json (100%) rename apps/{ => trex}/trex.png (100%) rename apps/{ => wclock}/clock-word-icon.js (100%) rename apps/{ => wclock}/clock-word.js (100%) rename apps/{ => wclock}/clock-word.json (100%) rename apps/{ => wclock}/clock-word.png (100%) diff --git a/apps/clock-analog-icon.js b/apps/aclock/clock-analog-icon.js similarity index 100% rename from apps/clock-analog-icon.js rename to apps/aclock/clock-analog-icon.js diff --git a/apps/clock-analog.js b/apps/aclock/clock-analog.js similarity index 100% rename from apps/clock-analog.js rename to apps/aclock/clock-analog.js diff --git a/apps/clock-analog.json b/apps/aclock/clock-analog.json similarity index 100% rename from apps/clock-analog.json rename to apps/aclock/clock-analog.json diff --git a/apps/clock-analog.png b/apps/aclock/clock-analog.png similarity index 100% rename from apps/clock-analog.png rename to apps/aclock/clock-analog.png diff --git a/apps/animals-camel.js b/apps/animals/animals-camel.js similarity index 100% rename from apps/animals-camel.js rename to apps/animals/animals-camel.js diff --git a/apps/animals-duck.js b/apps/animals/animals-duck.js similarity index 100% rename from apps/animals-duck.js rename to apps/animals/animals-duck.js diff --git a/apps/animals-fox.js b/apps/animals/animals-fox.js similarity index 100% rename from apps/animals-fox.js rename to apps/animals/animals-fox.js diff --git a/apps/animals-icon.js b/apps/animals/animals-icon.js similarity index 100% rename from apps/animals-icon.js rename to apps/animals/animals-icon.js diff --git a/apps/animals-mouse.js b/apps/animals/animals-mouse.js similarity index 100% rename from apps/animals-mouse.js rename to apps/animals/animals-mouse.js diff --git a/apps/animals-pig.js b/apps/animals/animals-pig.js similarity index 100% rename from apps/animals-pig.js rename to apps/animals/animals-pig.js diff --git a/apps/animals-sheep.js b/apps/animals/animals-sheep.js similarity index 100% rename from apps/animals-sheep.js rename to apps/animals/animals-sheep.js diff --git a/apps/animals-snake.js b/apps/animals/animals-snake.js similarity index 100% rename from apps/animals-snake.js rename to apps/animals/animals-snake.js diff --git a/apps/animals-swan.js b/apps/animals/animals-swan.js similarity index 100% rename from apps/animals-swan.js rename to apps/animals/animals-swan.js diff --git a/apps/animals.js b/apps/animals/animals.js similarity index 100% rename from apps/animals.js rename to apps/animals/animals.js diff --git a/apps/animals.json b/apps/animals/animals.json similarity index 100% rename from apps/animals.json rename to apps/animals/animals.json diff --git a/apps/animals.png b/apps/animals/animals.png similarity index 100% rename from apps/animals.png rename to apps/animals/animals.png diff --git a/apps/asteroids-icon.js b/apps/astroid/asteroids-icon.js similarity index 100% rename from apps/asteroids-icon.js rename to apps/astroid/asteroids-icon.js diff --git a/apps/asteroids.js b/apps/astroid/asteroids.js similarity index 100% rename from apps/asteroids.js rename to apps/astroid/asteroids.js diff --git a/apps/asteroids.json b/apps/astroid/asteroids.json similarity index 100% rename from apps/asteroids.json rename to apps/astroid/asteroids.json diff --git a/apps/asteroids.png b/apps/astroid/asteroids.png similarity index 100% rename from apps/asteroids.png rename to apps/astroid/asteroids.png diff --git a/apps/clock-binary-icon.js b/apps/bclock/clock-binary-icon.js similarity index 100% rename from apps/clock-binary-icon.js rename to apps/bclock/clock-binary-icon.js diff --git a/apps/clock-binary.js b/apps/bclock/clock-binary.js similarity index 100% rename from apps/clock-binary.js rename to apps/bclock/clock-binary.js diff --git a/apps/clock-binary.json b/apps/bclock/clock-binary.json similarity index 100% rename from apps/clock-binary.json rename to apps/bclock/clock-binary.json diff --git a/apps/clock-binary.png b/apps/bclock/clock-binary.png similarity index 100% rename from apps/clock-binary.png rename to apps/bclock/clock-binary.png diff --git a/apps/beercompass.html b/apps/beer/beercompass.html similarity index 100% rename from apps/beercompass.html rename to apps/beer/beercompass.html diff --git a/apps/beercompass.png b/apps/beer/beercompass.png similarity index 100% rename from apps/beercompass.png rename to apps/beer/beercompass.png diff --git a/apps/blescan-icon.js b/apps/blescan/blescan-icon.js similarity index 100% rename from apps/blescan-icon.js rename to apps/blescan/blescan-icon.js diff --git a/apps/blescan.js b/apps/blescan/blescan.js similarity index 100% rename from apps/blescan.js rename to apps/blescan/blescan.js diff --git a/apps/blescan.json b/apps/blescan/blescan.json similarity index 100% rename from apps/blescan.json rename to apps/blescan/blescan.json diff --git a/apps/blescan.png b/apps/blescan/blescan.png similarity index 100% rename from apps/blescan.png rename to apps/blescan/blescan.png diff --git a/apps/clock-blob-icon.js b/apps/blobclk/clock-blob-icon.js similarity index 100% rename from apps/clock-blob-icon.js rename to apps/blobclk/clock-blob-icon.js diff --git a/apps/clock-blob.js b/apps/blobclk/clock-blob.js similarity index 100% rename from apps/clock-blob.js rename to apps/blobclk/clock-blob.js diff --git a/apps/clock-blob.json b/apps/blobclk/clock-blob.json similarity index 100% rename from apps/clock-blob.json rename to apps/blobclk/clock-blob.json diff --git a/apps/clock-blob.png b/apps/blobclk/clock-blob.png similarity index 100% rename from apps/clock-blob.png rename to apps/blobclk/clock-blob.png diff --git a/apps/bootloader.js b/apps/boot/bootloader.js similarity index 100% rename from apps/bootloader.js rename to apps/boot/bootloader.js diff --git a/apps/bootloader.png b/apps/boot/bootloader.png similarity index 100% rename from apps/bootloader.png rename to apps/boot/bootloader.png diff --git a/apps/click-master-icon.js b/apps/clickms/click-master-icon.js similarity index 100% rename from apps/click-master-icon.js rename to apps/clickms/click-master-icon.js diff --git a/apps/click-master.js b/apps/clickms/click-master.js similarity index 100% rename from apps/click-master.js rename to apps/clickms/click-master.js diff --git a/apps/click-master.json b/apps/clickms/click-master.json similarity index 100% rename from apps/click-master.json rename to apps/clickms/click-master.json diff --git a/apps/click-master.png b/apps/clickms/click-master.png similarity index 100% rename from apps/click-master.png rename to apps/clickms/click-master.png diff --git a/apps/clock-tris-high b/apps/clotris/clock-tris-high similarity index 100% rename from apps/clock-tris-high rename to apps/clotris/clock-tris-high diff --git a/apps/clock-tris-icon.js b/apps/clotris/clock-tris-icon.js similarity index 100% rename from apps/clock-tris-icon.js rename to apps/clotris/clock-tris-icon.js diff --git a/apps/clock-tris.js b/apps/clotris/clock-tris.js similarity index 100% rename from apps/clock-tris.js rename to apps/clotris/clock-tris.js diff --git a/apps/clock-tris.json b/apps/clotris/clock-tris.json similarity index 100% rename from apps/clock-tris.json rename to apps/clotris/clock-tris.json diff --git a/apps/clock-tris.png b/apps/clotris/clock-tris.png similarity index 100% rename from apps/clock-tris.png rename to apps/clotris/clock-tris.png diff --git a/apps/compass-icon.js b/apps/compass/compass-icon.js similarity index 100% rename from apps/compass-icon.js rename to apps/compass/compass-icon.js diff --git a/apps/compass.js b/apps/compass/compass.js similarity index 100% rename from apps/compass.js rename to apps/compass/compass.js diff --git a/apps/compass.json b/apps/compass/compass.json similarity index 100% rename from apps/compass.json rename to apps/compass/compass.json diff --git a/apps/compass.png b/apps/compass/compass.png similarity index 100% rename from apps/compass.png rename to apps/compass/compass.png diff --git a/apps/files-icon.js b/apps/files/files-icon.js similarity index 100% rename from apps/files-icon.js rename to apps/files/files-icon.js diff --git a/apps/files.js b/apps/files/files.js similarity index 100% rename from apps/files.js rename to apps/files/files.js diff --git a/apps/files.json b/apps/files/files.json similarity index 100% rename from apps/files.json rename to apps/files/files.json diff --git a/apps/files.png b/apps/files/files.png similarity index 100% rename from apps/files.png rename to apps/files/files.png diff --git a/apps/nceu-funrun-icon.js b/apps/funrun5/nceu-funrun-icon.js similarity index 100% rename from apps/nceu-funrun-icon.js rename to apps/funrun5/nceu-funrun-icon.js diff --git a/apps/nceu-funrun.js b/apps/funrun5/nceu-funrun.js similarity index 100% rename from apps/nceu-funrun.js rename to apps/funrun5/nceu-funrun.js diff --git a/apps/nceu-funrun.json b/apps/funrun5/nceu-funrun.json similarity index 100% rename from apps/nceu-funrun.json rename to apps/funrun5/nceu-funrun.json diff --git a/apps/nceu-funrun.png b/apps/funrun5/nceu-funrun.png similarity index 100% rename from apps/nceu-funrun.png rename to apps/funrun5/nceu-funrun.png diff --git a/apps/gesture-icon.js b/apps/gesture/gesture-icon.js similarity index 100% rename from apps/gesture-icon.js rename to apps/gesture/gesture-icon.js diff --git a/apps/gesture-tfmodel.js b/apps/gesture/gesture-tfmodel.js similarity index 100% rename from apps/gesture-tfmodel.js rename to apps/gesture/gesture-tfmodel.js diff --git a/apps/gesture-tfnames.js b/apps/gesture/gesture-tfnames.js similarity index 100% rename from apps/gesture-tfnames.js rename to apps/gesture/gesture-tfnames.js diff --git a/apps/gesture.js b/apps/gesture/gesture.js similarity index 100% rename from apps/gesture.js rename to apps/gesture/gesture.js diff --git a/apps/gesture.json b/apps/gesture/gesture.json similarity index 100% rename from apps/gesture.json rename to apps/gesture/gesture.json diff --git a/apps/gesture.png b/apps/gesture/gesture.png similarity index 100% rename from apps/gesture.png rename to apps/gesture/gesture.png diff --git a/apps/gps-info-icon.js b/apps/gpsinfo/gps-info-icon.js similarity index 100% rename from apps/gps-info-icon.js rename to apps/gpsinfo/gps-info-icon.js diff --git a/apps/gps-info.js b/apps/gpsinfo/gps-info.js similarity index 100% rename from apps/gps-info.js rename to apps/gpsinfo/gps-info.js diff --git a/apps/gps-info.json b/apps/gpsinfo/gps-info.json similarity index 100% rename from apps/gps-info.json rename to apps/gpsinfo/gps-info.json diff --git a/apps/gps-info.png b/apps/gpsinfo/gps-info.png similarity index 100% rename from apps/gps-info.png rename to apps/gpsinfo/gps-info.png diff --git a/apps/gpstime-icon.js b/apps/gpstime/gpstime-icon.js similarity index 100% rename from apps/gpstime-icon.js rename to apps/gpstime/gpstime-icon.js diff --git a/apps/gpstime.js b/apps/gpstime/gpstime.js similarity index 100% rename from apps/gpstime.js rename to apps/gpstime/gpstime.js diff --git a/apps/gpstime.json b/apps/gpstime/gpstime.json similarity index 100% rename from apps/gpstime.json rename to apps/gpstime/gpstime.json diff --git a/apps/gpstime.png b/apps/gpstime/gpstime.png similarity index 100% rename from apps/gpstime.png rename to apps/gpstime/gpstime.png diff --git a/apps/hid-binary-keyboard-icon.js b/apps/hidbkbd/hid-binary-keyboard-icon.js similarity index 100% rename from apps/hid-binary-keyboard-icon.js rename to apps/hidbkbd/hid-binary-keyboard-icon.js diff --git a/apps/hid-binary-keyboard.js b/apps/hidbkbd/hid-binary-keyboard.js similarity index 100% rename from apps/hid-binary-keyboard.js rename to apps/hidbkbd/hid-binary-keyboard.js diff --git a/apps/hid-binary-keyboard.json b/apps/hidbkbd/hid-binary-keyboard.json similarity index 100% rename from apps/hid-binary-keyboard.json rename to apps/hidbkbd/hid-binary-keyboard.json diff --git a/apps/hid-binary-keyboard.png b/apps/hidbkbd/hid-binary-keyboard.png similarity index 100% rename from apps/hid-binary-keyboard.png rename to apps/hidbkbd/hid-binary-keyboard.png diff --git a/apps/hid-keyboard-icon.js b/apps/hidkbd/hid-keyboard-icon.js similarity index 100% rename from apps/hid-keyboard-icon.js rename to apps/hidkbd/hid-keyboard-icon.js diff --git a/apps/hid-keyboard.js b/apps/hidkbd/hid-keyboard.js similarity index 100% rename from apps/hid-keyboard.js rename to apps/hidkbd/hid-keyboard.js diff --git a/apps/hid-keyboard.json b/apps/hidkbd/hid-keyboard.json similarity index 100% rename from apps/hid-keyboard.json rename to apps/hidkbd/hid-keyboard.json diff --git a/apps/hid-keyboard.min.js b/apps/hidkbd/hid-keyboard.min.js similarity index 100% rename from apps/hid-keyboard.min.js rename to apps/hidkbd/hid-keyboard.min.js diff --git a/apps/hid-keyboard.png b/apps/hidkbd/hid-keyboard.png similarity index 100% rename from apps/hid-keyboard.png rename to apps/hidkbd/hid-keyboard.png diff --git a/apps/hid-music-icon.js b/apps/hidmsic/hid-music-icon.js similarity index 100% rename from apps/hid-music-icon.js rename to apps/hidmsic/hid-music-icon.js diff --git a/apps/hid-music.js b/apps/hidmsic/hid-music.js similarity index 100% rename from apps/hid-music.js rename to apps/hidmsic/hid-music.js diff --git a/apps/hid-music.json b/apps/hidmsic/hid-music.json similarity index 100% rename from apps/hid-music.json rename to apps/hidmsic/hid-music.json diff --git a/apps/hid-music.png b/apps/hidmsic/hid-music.png similarity index 100% rename from apps/hid-music.png rename to apps/hidmsic/hid-music.png diff --git a/apps/horse-race-icon.js b/apps/horsey/horse-race-icon.js similarity index 100% rename from apps/horse-race-icon.js rename to apps/horsey/horse-race-icon.js diff --git a/apps/horse-race.js b/apps/horsey/horse-race.js similarity index 100% rename from apps/horse-race.js rename to apps/horsey/horse-race.js diff --git a/apps/horse-race.json b/apps/horsey/horse-race.json similarity index 100% rename from apps/horse-race.json rename to apps/horsey/horse-race.json diff --git a/apps/horse-race.png b/apps/horsey/horse-race.png similarity index 100% rename from apps/horse-race.png rename to apps/horsey/horse-race.png diff --git a/apps/hypno-rings-icon.js b/apps/hrings/hypno-rings-icon.js similarity index 100% rename from apps/hypno-rings-icon.js rename to apps/hrings/hypno-rings-icon.js diff --git a/apps/hypno-rings.js b/apps/hrings/hypno-rings.js similarity index 100% rename from apps/hypno-rings.js rename to apps/hrings/hypno-rings.js diff --git a/apps/hypno-rings.json b/apps/hrings/hypno-rings.json similarity index 100% rename from apps/hypno-rings.json rename to apps/hrings/hypno-rings.json diff --git a/apps/hypno-rings.png b/apps/hrings/hypno-rings.png similarity index 100% rename from apps/hypno-rings.png rename to apps/hrings/hypno-rings.png diff --git a/apps/heartrate-icon.js b/apps/hrm/heartrate-icon.js similarity index 100% rename from apps/heartrate-icon.js rename to apps/hrm/heartrate-icon.js diff --git a/apps/heartrate.js b/apps/hrm/heartrate.js similarity index 100% rename from apps/heartrate.js rename to apps/hrm/heartrate.js diff --git a/apps/heartrate.json b/apps/hrm/heartrate.json similarity index 100% rename from apps/heartrate.json rename to apps/hrm/heartrate.json diff --git a/apps/heartrate.png b/apps/hrm/heartrate.png similarity index 100% rename from apps/heartrate.png rename to apps/hrm/heartrate.png diff --git a/apps/jbells-icon.js b/apps/jbells/jbells-icon.js similarity index 100% rename from apps/jbells-icon.js rename to apps/jbells/jbells-icon.js diff --git a/apps/jbells.js b/apps/jbells/jbells.js similarity index 100% rename from apps/jbells.js rename to apps/jbells/jbells.js diff --git a/apps/jbells.json b/apps/jbells/jbells.json similarity index 100% rename from apps/jbells.json rename to apps/jbells/jbells.json diff --git a/apps/jbells.png b/apps/jbells/jbells.png similarity index 100% rename from apps/jbells.png rename to apps/jbells/jbells.png diff --git a/apps/clock-morphing-icon.js b/apps/mclock/clock-morphing-icon.js similarity index 100% rename from apps/clock-morphing-icon.js rename to apps/mclock/clock-morphing-icon.js diff --git a/apps/clock-morphing.js b/apps/mclock/clock-morphing.js similarity index 100% rename from apps/clock-morphing.js rename to apps/mclock/clock-morphing.js diff --git a/apps/clock-morphing.json b/apps/mclock/clock-morphing.json similarity index 100% rename from apps/clock-morphing.json rename to apps/mclock/clock-morphing.json diff --git a/apps/clock-morphing.png b/apps/mclock/clock-morphing.png similarity index 100% rename from apps/clock-morphing.png rename to apps/mclock/clock-morphing.png diff --git a/apps/clock-mixed-icon.js b/apps/miclock/clock-mixed-icon.js similarity index 100% rename from apps/clock-mixed-icon.js rename to apps/miclock/clock-mixed-icon.js diff --git a/apps/clock-mixed.js b/apps/miclock/clock-mixed.js similarity index 100% rename from apps/clock-mixed.js rename to apps/miclock/clock-mixed.js diff --git a/apps/clock-mixed.json b/apps/miclock/clock-mixed.json similarity index 100% rename from apps/clock-mixed.json rename to apps/miclock/clock-mixed.json diff --git a/apps/clock-mixed.png b/apps/miclock/clock-mixed.png similarity index 100% rename from apps/clock-mixed.png rename to apps/miclock/clock-mixed.png diff --git a/apps/manic-monday-icon.js b/apps/mmonday/manic-monday-icon.js similarity index 100% rename from apps/manic-monday-icon.js rename to apps/mmonday/manic-monday-icon.js diff --git a/apps/manic-monday-icon.png b/apps/mmonday/manic-monday-icon.png similarity index 100% rename from apps/manic-monday-icon.png rename to apps/mmonday/manic-monday-icon.png diff --git a/apps/manic-monday.js b/apps/mmonday/manic-monday.js similarity index 100% rename from apps/manic-monday.js rename to apps/mmonday/manic-monday.js diff --git a/apps/manic-monday.json b/apps/mmonday/manic-monday.json similarity index 100% rename from apps/manic-monday.json rename to apps/mmonday/manic-monday.json diff --git a/apps/morse-code-icon.js b/apps/morse/morse-code-icon.js similarity index 100% rename from apps/morse-code-icon.js rename to apps/morse/morse-code-icon.js diff --git a/apps/morse-code.js b/apps/morse/morse-code.js similarity index 100% rename from apps/morse-code.js rename to apps/morse/morse-code.js diff --git a/apps/morse-code.json b/apps/morse/morse-code.json similarity index 100% rename from apps/morse-code.json rename to apps/morse/morse-code.json diff --git a/apps/morse-code.png b/apps/morse/morse-code.png similarity index 100% rename from apps/morse-code.png rename to apps/morse/morse-code.png diff --git a/apps/nceu-widget.js b/apps/nceuwid/nceu-widget.js similarity index 100% rename from apps/nceu-widget.js rename to apps/nceuwid/nceu-widget.js diff --git a/apps/nceu-widget.json b/apps/nceuwid/nceu-widget.json similarity index 100% rename from apps/nceu-widget.json rename to apps/nceuwid/nceu-widget.json diff --git a/apps/nceu-widget.png b/apps/nceuwid/nceu-widget.png similarity index 100% rename from apps/nceu-widget.png rename to apps/nceuwid/nceu-widget.png diff --git a/apps/openlocation-icon.js b/apps/openloc/openlocation-icon.js similarity index 100% rename from apps/openlocation-icon.js rename to apps/openloc/openlocation-icon.js diff --git a/apps/openlocation.js b/apps/openloc/openlocation.js similarity index 100% rename from apps/openlocation.js rename to apps/openloc/openlocation.js diff --git a/apps/openlocation.json b/apps/openloc/openlocation.json similarity index 100% rename from apps/openlocation.json rename to apps/openloc/openlocation.json diff --git a/apps/openlocation.png b/apps/openloc/openlocation.png similarity index 100% rename from apps/openlocation.png rename to apps/openloc/openlocation.png diff --git a/apps/party-parrot-icon.js b/apps/pparrot/party-parrot-icon.js similarity index 100% rename from apps/party-parrot-icon.js rename to apps/pparrot/party-parrot-icon.js diff --git a/apps/party-parrot.js b/apps/pparrot/party-parrot.js similarity index 100% rename from apps/party-parrot.js rename to apps/pparrot/party-parrot.js diff --git a/apps/party-parrot.json b/apps/pparrot/party-parrot.json similarity index 100% rename from apps/party-parrot.json rename to apps/pparrot/party-parrot.json diff --git a/apps/party-parrot.png b/apps/pparrot/party-parrot.png similarity index 100% rename from apps/party-parrot.png rename to apps/pparrot/party-parrot.png diff --git a/apps/promodoro-icon.js b/apps/promodo/promodoro-icon.js similarity index 100% rename from apps/promodoro-icon.js rename to apps/promodo/promodoro-icon.js diff --git a/apps/promodoro.js b/apps/promodo/promodoro.js similarity index 100% rename from apps/promodoro.js rename to apps/promodo/promodoro.js diff --git a/apps/promodoro.json b/apps/promodo/promodoro.json similarity index 100% rename from apps/promodoro.json rename to apps/promodo/promodoro.json diff --git a/apps/promodoro.png b/apps/promodo/promodoro.png similarity index 100% rename from apps/promodoro.png rename to apps/promodo/promodoro.png diff --git a/apps/qrcode.html b/apps/qrcode/qrcode.html similarity index 100% rename from apps/qrcode.html rename to apps/qrcode/qrcode.html diff --git a/apps/qrcode.png b/apps/qrcode/qrcode.png similarity index 100% rename from apps/qrcode.png rename to apps/qrcode/qrcode.png diff --git a/apps/route.html b/apps/route/route.html similarity index 100% rename from apps/route.html rename to apps/route/route.html diff --git a/apps/route.png b/apps/route/route.png similarity index 100% rename from apps/route.png rename to apps/route/route.png diff --git a/apps/widget-battery.js b/apps/sbat/widget-battery.js similarity index 100% rename from apps/widget-battery.js rename to apps/sbat/widget-battery.js diff --git a/apps/widget-battery.json b/apps/sbat/widget-battery.json similarity index 100% rename from apps/widget-battery.json rename to apps/sbat/widget-battery.json diff --git a/apps/widget-battery.png b/apps/sbat/widget-battery.png similarity index 100% rename from apps/widget-battery.png rename to apps/sbat/widget-battery.png diff --git a/apps/widget-bluetooth.js b/apps/sbt/widget-bluetooth.js similarity index 100% rename from apps/widget-bluetooth.js rename to apps/sbt/widget-bluetooth.js diff --git a/apps/widget-bluetooth.json b/apps/sbt/widget-bluetooth.json similarity index 100% rename from apps/widget-bluetooth.json rename to apps/sbt/widget-bluetooth.json diff --git a/apps/widget-bluetooth.png b/apps/sbt/widget-bluetooth.png similarity index 100% rename from apps/widget-bluetooth.png rename to apps/sbt/widget-bluetooth.png diff --git a/apps/clock-simple-icon.js b/apps/sclock/clock-simple-icon.js similarity index 100% rename from apps/clock-simple-icon.js rename to apps/sclock/clock-simple-icon.js diff --git a/apps/clock-simple.js b/apps/sclock/clock-simple.js similarity index 100% rename from apps/clock-simple.js rename to apps/sclock/clock-simple.js diff --git a/apps/clock-simple.json b/apps/sclock/clock-simple.json similarity index 100% rename from apps/clock-simple.json rename to apps/sclock/clock-simple.json diff --git a/apps/clock-simple.png b/apps/sclock/clock-simple.png similarity index 100% rename from apps/clock-simple.png rename to apps/sclock/clock-simple.png diff --git a/apps/show-color-icon.js b/apps/scolor/show-color-icon.js similarity index 100% rename from apps/show-color-icon.js rename to apps/scolor/show-color-icon.js diff --git a/apps/show-color.js b/apps/scolor/show-color.js similarity index 100% rename from apps/show-color.js rename to apps/scolor/show-color.js diff --git a/apps/show-color.json b/apps/scolor/show-color.json similarity index 100% rename from apps/show-color.json rename to apps/scolor/show-color.json diff --git a/apps/show-color.png b/apps/scolor/show-color.png similarity index 100% rename from apps/show-color.png rename to apps/scolor/show-color.png diff --git a/apps/settings-default.json b/apps/setting/settings-default.json similarity index 100% rename from apps/settings-default.json rename to apps/setting/settings-default.json diff --git a/apps/settings-icon.js b/apps/setting/settings-icon.js similarity index 100% rename from apps/settings-icon.js rename to apps/setting/settings-icon.js diff --git a/apps/settings-init.js b/apps/setting/settings-init.js similarity index 100% rename from apps/settings-init.js rename to apps/setting/settings-init.js diff --git a/apps/settings.js b/apps/setting/settings.js similarity index 100% rename from apps/settings.js rename to apps/setting/settings.js diff --git a/apps/settings.json b/apps/setting/settings.json similarity index 100% rename from apps/settings.json rename to apps/setting/settings.json diff --git a/apps/settings.png b/apps/setting/settings.png similarity index 100% rename from apps/settings.png rename to apps/setting/settings.png diff --git a/apps/spiritlevel-icon.js b/apps/slevel/spiritlevel-icon.js similarity index 100% rename from apps/spiritlevel-icon.js rename to apps/slevel/spiritlevel-icon.js diff --git a/apps/spiritlevel.js b/apps/slevel/spiritlevel.js similarity index 100% rename from apps/spiritlevel.js rename to apps/slevel/spiritlevel.js diff --git a/apps/spiritlevel.json b/apps/slevel/spiritlevel.json similarity index 100% rename from apps/spiritlevel.json rename to apps/slevel/spiritlevel.json diff --git a/apps/spiritlevel.png b/apps/slevel/spiritlevel.png similarity index 100% rename from apps/spiritlevel.png rename to apps/slevel/spiritlevel.png diff --git a/apps/speedo-icon.js b/apps/speedo/speedo-icon.js similarity index 100% rename from apps/speedo-icon.js rename to apps/speedo/speedo-icon.js diff --git a/apps/speedo.js b/apps/speedo/speedo.js similarity index 100% rename from apps/speedo.js rename to apps/speedo/speedo.js diff --git a/apps/speedo.json b/apps/speedo/speedo.json similarity index 100% rename from apps/speedo.json rename to apps/speedo/speedo.json diff --git a/apps/speedo.png b/apps/speedo/speedo.png similarity index 100% rename from apps/speedo.png rename to apps/speedo/speedo.png diff --git a/apps/start-bangle.js b/apps/start/start-bangle.js similarity index 100% rename from apps/start-bangle.js rename to apps/start/start-bangle.js diff --git a/apps/start-icon.js b/apps/start/start-icon.js similarity index 100% rename from apps/start-icon.js rename to apps/start/start-icon.js diff --git a/apps/start-nceu.js b/apps/start/start-nceu.js similarity index 100% rename from apps/start-nceu.js rename to apps/start/start-nceu.js diff --git a/apps/start-nfr.js b/apps/start/start-nfr.js similarity index 100% rename from apps/start-nfr.js rename to apps/start/start-nfr.js diff --git a/apps/start-nodew.js b/apps/start/start-nodew.js similarity index 100% rename from apps/start-nodew.js rename to apps/start/start-nodew.js diff --git a/apps/start-tf.js b/apps/start/start-tf.js similarity index 100% rename from apps/start-tf.js rename to apps/start/start-tf.js diff --git a/apps/start.js b/apps/start/start.js similarity index 100% rename from apps/start.js rename to apps/start/start.js diff --git a/apps/start.json b/apps/start/start.json similarity index 100% rename from apps/start.json rename to apps/start/start.json diff --git a/apps/start.png b/apps/start/start.png similarity index 100% rename from apps/start.png rename to apps/start/start.png diff --git a/apps/stopwatch-icon.js b/apps/swatch/stopwatch-icon.js similarity index 100% rename from apps/stopwatch-icon.js rename to apps/swatch/stopwatch-icon.js diff --git a/apps/stopwatch.js b/apps/swatch/stopwatch.js similarity index 100% rename from apps/stopwatch.js rename to apps/swatch/stopwatch.js diff --git a/apps/stopwatch.json b/apps/swatch/stopwatch.json similarity index 100% rename from apps/stopwatch.json rename to apps/swatch/stopwatch.json diff --git a/apps/stopwatch.png b/apps/swatch/stopwatch.png similarity index 100% rename from apps/stopwatch.png rename to apps/swatch/stopwatch.png diff --git a/apps/trex-icon.js b/apps/trex/trex-icon.js similarity index 100% rename from apps/trex-icon.js rename to apps/trex/trex-icon.js diff --git a/apps/trex.js b/apps/trex/trex.js similarity index 100% rename from apps/trex.js rename to apps/trex/trex.js diff --git a/apps/trex.json b/apps/trex/trex.json similarity index 100% rename from apps/trex.json rename to apps/trex/trex.json diff --git a/apps/trex.png b/apps/trex/trex.png similarity index 100% rename from apps/trex.png rename to apps/trex/trex.png diff --git a/apps/clock-word-icon.js b/apps/wclock/clock-word-icon.js similarity index 100% rename from apps/clock-word-icon.js rename to apps/wclock/clock-word-icon.js diff --git a/apps/clock-word.js b/apps/wclock/clock-word.js similarity index 100% rename from apps/clock-word.js rename to apps/wclock/clock-word.js diff --git a/apps/clock-word.json b/apps/wclock/clock-word.json similarity index 100% rename from apps/clock-word.json rename to apps/wclock/clock-word.json diff --git a/apps/clock-word.png b/apps/wclock/clock-word.png similarity index 100% rename from apps/clock-word.png rename to apps/wclock/clock-word.png From dc0e3823b50f8435fcd5807cc4c5e2c48a0f16b3 Mon Sep 17 00:00:00 2001 From: ra100 Date: Sun, 17 Nov 2019 23:39:31 +0100 Subject: [PATCH 10/15] =?UTF-8?q?=F0=9F=90=9B=20Fix=20filepaths=20after=20?= =?UTF-8?q?moving=20to=20subfolders=20#46?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- appinfo.js | 2 +- index.js | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/appinfo.js b/appinfo.js index 5efcfde50..6fa4aa474 100644 --- a/appinfo.js +++ b/appinfo.js @@ -10,7 +10,7 @@ var AppInfo = { if (storageFile.content) return Promise.resolve(storageFile); else if (storageFile.url) - return fileGetter("apps/"+storageFile.url).then(content => { + return fileGetter(`apps/${app.id}/${storageFile.url}`).then(content => { return { name : storageFile.name, content : content, diff --git a/index.js b/index.js index 5d3b7834e..7653a077b 100644 --- a/index.js +++ b/index.js @@ -73,7 +73,7 @@ function handleCustomApp(app) {