diff --git a/CHANGELOG.md b/CHANGELOG.md index 9480f2ace..95e973e0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,3 +9,4 @@ Changed for individual apps are listed in `apps/appname/ChangeLog` * Fix issue removing an app that was just installed (fix #253) * Add `Favourite` functionality * Version number now clickable even when you're at the latest version (fix #291) +* Rewrite 'getInstalledApps' to minimize RAM usage diff --git a/apps.json b/apps.json index 95b299688..7449a233b 100644 --- a/apps.json +++ b/apps.json @@ -78,7 +78,7 @@ { "id": "welcome", "name": "Welcome", "icon": "app.png", - "version":"0.06", + "version":"0.07", "description": "Appears at first boot and explains how to use Bangle.js", "tags": "start,welcome", "allow_emulator":true, @@ -86,13 +86,14 @@ {"name":"welcome.boot.js","url":"boot.js"}, {"name":"welcome.app.js","url":"app.js"}, {"name":"welcome.settings.js","url":"settings.js"}, + {"name":"welcome.settings.json","url":"settings-default.json","evaluate":true}, {"name":"welcome.img","url":"app-icon.js","evaluate":true} ] }, { "id": "gbridge", "name": "Gadgetbridge", "icon": "app.png", - "version":"0.08", + "version":"0.09", "description": "The default notification handler for Gadgetbridge notifications from Android", "tags": "tool,system,android,widget", "type":"widget", @@ -119,7 +120,7 @@ { "id": "setting", "name": "Settings", "icon": "settings.png", - "version":"0.14", + "version":"0.15", "description": "A menu for setting up Bangle.js", "tags": "tool,system", "storage": [ @@ -279,7 +280,7 @@ { "id": "gpsrec", "name": "GPS Recorder", "icon": "app.png", - "version":"0.06", + "version":"0.07", "interface": "interface.html", "description": "Application that allows you to record a GPS track. Can run in background", "tags": "tool,outdoors,gps,widget", @@ -329,7 +330,7 @@ { "id": "widbat", "name": "Battery Level Widget", "icon": "widget.png", - "version":"0.04", + "version":"0.05", "description": "Show the current battery level and charging status in the top right of the clock", "tags": "widget,battery", "type":"widget", @@ -341,7 +342,7 @@ "name": "Battery Level Widget (with percentage)", "shortName": "Battery Widget", "icon": "widget.png", - "version":"0.08", + "version":"0.09", "description": "Show the current battery level and charging status in the top right of the clock, with charge percentage", "tags": "widget,battery", "type":"widget", @@ -354,7 +355,7 @@ { "id": "widbt", "name": "Bluetooth Widget", "icon": "widget.png", - "version":"0.03", + "version":"0.04", "description": "Show the current Bluetooth connection status in the top right of the clock", "tags": "widget,bluetooth", "type":"widget", @@ -362,6 +363,18 @@ {"name":"widbt.wid.js","url":"widget.js"} ] }, + { "id": "widram", + "name": "RAM Widget", + "shortName":"RAM Widget", + "icon": "widget.png", + "version":"0.01", + "description": "Display your Bangle's available RAM percentage in a widget", + "tags": "widget", + "type": "widget", + "storage": [ + {"name":"widram.wid.js","url":"widget.js"} + ] + }, { "id": "hrm", "name": "Heart Rate Monitor", "icon": "heartrate.png", @@ -504,13 +517,14 @@ "id": "ncstart", "name": "NCEU Startup", "icon": "start.png", - "version":"0.03", + "version":"0.04", "description": "NodeConfEU 2019 'First Start' Sequence", "tags": "start,welcome", "storage": [ {"name":"ncstart.app.js","url":"start.js"}, {"name":"ncstart.boot.js","url":"boot.js"}, {"name":"ncstart.settings.js","url":"settings.js"}, + {"name":"ncstart.settings.json","url":"settings-default.json","evaluate":true}, {"name":"ncstart.img","url":"start-icon.js","evaluate":true}, {"name":"nc-bangle.img","url":"start-bangle.js","evaluate":true}, {"name":"nc-nceu.img","url":"start-nceu.js","evaluate":true}, @@ -775,7 +789,7 @@ { "id": "widclk", "name": "Digital clock widget", "icon": "widget.png", - "version":"0.03", + "version":"0.04", "description": "A simple digital clock widget", "tags": "widget,clock", "type":"widget", @@ -1219,8 +1233,8 @@ "name": "Snake", "shortName":"Snake", "icon": "snake.png", - "version":"0.01", - "description": "The classic snake game. Eat apples and don't bite your tail:", + "version":"0.02", + "description": "The classic snake game. Eat apples and don't bite your tail.", "tags": "game,fun", "readme": "README.md", "storage": [ diff --git a/apps/gbridge/ChangeLog b/apps/gbridge/ChangeLog index d1f9c6a62..53f8a1b4c 100644 --- a/apps/gbridge/ChangeLog +++ b/apps/gbridge/ChangeLog @@ -7,3 +7,4 @@ 0.06: Gadgetbridge App 'Connected' state is no longer toggleable 0.07: Move configuration to settings menu 0.08: Don't turn on LCD at start of every song +0.09: Update Bluetooth connection state automatically diff --git a/apps/gbridge/widget.js b/apps/gbridge/widget.js index fa44757fc..03c622443 100644 --- a/apps/gbridge/widget.js +++ b/apps/gbridge/widget.js @@ -189,8 +189,8 @@ g.flip(); // turns screen on } - NRF.on("connected", changedConnectionState); - NRF.on("disconnected", changedConnectionState); + NRF.on("connect", changedConnectionState); + NRF.on("disconnect", changedConnectionState); WIDGETS["gbridgew"] = { area: "tl", width: 24, draw: draw }; diff --git a/apps/gpsrec/ChangeLog b/apps/gpsrec/ChangeLog index 9a47bdd9a..8f1c575a1 100644 --- a/apps/gpsrec/ChangeLog +++ b/apps/gpsrec/ChangeLog @@ -4,3 +4,4 @@ 0.04: Properly Fix GPS time display in gpsrec app 0.05: Tweaks for variable size widget system 0.06: Ensure widget update itself (fix #118) and change to using icons +0.07: Added @jeffmer's awesome track viewer diff --git a/apps/gpsrec/app.js b/apps/gpsrec/app.js index 58b4295a6..63f3840ff 100644 --- a/apps/gpsrec/app.js +++ b/apps/gpsrec/app.js @@ -70,27 +70,65 @@ function viewTracks() { return E.showMenu(menu); } +function getTrackInfo(fn) { + var filename = getFN(fn); + var minLat = 90; + var maxLat = -90; + var minLong = 180; + var maxLong = -180; + var starttime, duration=0; + var f = require("Storage").open(filename,"r"); + if (f===undefined) return; + var l = f.readLine(f); + var nl = 0, c, n; + if (l!==undefined) { + c = l.split(","); + starttime = parseInt(c[0]); + } + // pushed this loop together to try and bump loading speed a little + while(l!==undefined) { + ++nl;c=l.split(","); + n = parseFloat(c[1]);if(n>maxLat)maxLat=n;if(nmaxLong)maxLong=n;if(nylen ? 200/xlen : 200/ylen; + return { + fn : fn, + filename : filename, + time : new Date(starttime), + records : nl, + minLat : minLat, maxLat : maxLat, + minLong : minLong, maxLong : maxLong, + lfactor : lfactor, + scale : scale, + duration : Math.round(duration/1000) + }; +} + +function asTime(v){ + var mins = Math.floor(v/60); + var secs = v-mins*60; + return ""+mins.toString()+"m "+secs.toString()+"s"; +} + function viewTrack(n) { + E.showMessage("Loading...","GPS Track "+n); + var info = getTrackInfo(n); const menu = { '': { 'title': 'GPS Track '+n } }; - var trackCount = 0; - var trackTime; - var f = require("Storage").open(getFN(n),"r"); - var l = f.readLine(); - if (l!==undefined) { - var c = l.split(","); - trackTime = new Date(parseInt(c[0])); - } - while (l!==undefined) { - trackCount++; - // TODO: min/max/length of track? - l = f.readLine(); - } - if (trackTime) - menu[" "+trackTime.toISOString().substr(0,16).replace("T"," ")] = function(){}; - menu[trackCount+" records"] = function(){}; - // TODO: option to draw it? Just scan through, project using min/max + if (info.time) + menu[info.time.toISOString().substr(0,16).replace("T"," ")] = function(){}; + menu["Duration"] = { value : asTime(info.duration)}; + menu["Records"] = { value : ""+info.records }; + menu['Plot'] = function() { + plotTrack(info); + }; menu['Erase'] = function() { E.showPrompt("Delete Track?").then(function(v) { if (v) { @@ -107,4 +145,80 @@ function viewTrack(n) { return E.showMenu(menu); } +function plotTrack(info) { + function xcoord(long){ + return 30 + Math.round((long-info.minLong)*info.lfactor*info.scale); + } + + function ycoord(lat){ + return 210 - Math.round((lat - info.minLat)*info.scale); + } + + function radians(a) { + return a*Math.PI/180; + } + + function distance(lat1,long1,lat2,long2){ + var x = radians(long1-long2) * Math.cos(radians((lat1+lat2)/2)); + var y = radians(lat2-lat1); + return Math.sqrt(x*x + y*y) * 6371000; + } + + E.showMenu(); // remove menu + g.setColor(1,0.5,0.5); + g.setFont("Vector",16); + g.fillRect(9,80,11,120); + g.fillPoly([9,60,19,80,0,80]); + g.setColor(1,1,1); + g.drawString("N",2,40); + g.drawString("Track"+info.fn.toString()+" - Loading",10,220); + g.setColor(0,0,0); + g.fillRect(0,220,239,239); + g.setColor(1,1,1); + g.drawString(asTime(info.duration),10,220); + var f = require("Storage").open(info.filename,"r"); + if (f===undefined) return; + var l = f.readLine(f); + var ox=0; + var oy=0; + var olat,olong,dist=0; + var first = true; + var i=0; + while(l!==undefined) { + var c = l.split(","); + var lat = parseFloat(c[1]); + var long = parseFloat(c[2]); + var x = xcoord(long); + var y = ycoord(lat); + if (first) { + g.moveTo(x,y); + g.setColor(0,1,0); + g.fillCircle(x,y,5); + g.setColor(1,1,1); + first = false; + } else if (x!=ox || y!=oy) { + g.lineTo(x,y); + } + if (!first) { + var d = distance(olat,olong,lat,long); + if (!isNaN(d)) dist+=d; + } + olat = lat; + olong = long; + ox = x; + oy = y; + l = f.readLine(f); + } + g.setColor(1,0,0); + g.fillCircle(ox,oy,5); + g.setColor(1,1,1); + g.drawString(require("locale").distance(dist),120,220); + g.setFont("6x8",2); + g.setFontAlign(0,0,3); + g.drawString("Back",230,200); + setWatch(function() { + viewTrack(info.fn); + }, BTN3); +} + showMainMenu(); diff --git a/apps/ncstart/ChangeLog b/apps/ncstart/ChangeLog index 553f7388a..f4418827e 100644 --- a/apps/ncstart/ChangeLog +++ b/apps/ncstart/ChangeLog @@ -2,3 +2,6 @@ Renamed as nodeconf-specific 0.03: Move configuration into App/widget settings Move loader into welcome.boot.js +0.04: Run again when updated + Don't run again when settings app is updated (or absent) + Add "Run Now" option to settings diff --git a/apps/ncstart/boot.js b/apps/ncstart/boot.js index dbb70d213..e3f514f5b 100644 --- a/apps/ncstart/boot.js +++ b/apps/ncstart/boot.js @@ -1,9 +1,11 @@ (function() { - let s = require('Storage').readJSON('setting.json', 1) || {} + let s = require('Storage').readJSON('ncstart.settings.json', 1) + || require('Storage').readJSON('setting.json', 1) + || {welcomed: true} // do NOT run if global settings are also absent if (!s.welcomed && require('Storage').read('ncstart.app.js')) { setTimeout(() => { s.welcomed = true - require('Storage').write('setting.json', s) + require('Storage').write('ncstart.settings.json', s) load('ncstart.app.js') }) } diff --git a/apps/ncstart/settings-default.json b/apps/ncstart/settings-default.json new file mode 100644 index 000000000..d250efff5 --- /dev/null +++ b/apps/ncstart/settings-default.json @@ -0,0 +1,3 @@ +{ + "welcomed": false +} diff --git a/apps/ncstart/settings.js b/apps/ncstart/settings.js index 284262634..2b24095cf 100644 --- a/apps/ncstart/settings.js +++ b/apps/ncstart/settings.js @@ -1,16 +1,15 @@ // The welcome app is special, and gets to use global settings (function(back) { - let settings = require('Storage').readJSON('setting.json', 1) || {} + let settings = require('Storage').readJSON('ncstart.settings.json', 1) + || require('Storage').readJSON('setting.json', 1) || {} E.showMenu({ '': { 'title': 'NCEU Startup' }, - 'Run again': { + 'Run on Next Boot': { value: !settings.welcomed, - format: v => v ? 'Yes' : 'No', - onchange: v => { - settings.welcomed = v ? undefined : true - require('Storage').write('setting.json', settings) - }, + format: v => v ? 'OK' : 'No', + onchange: v => require('Storage').write('ncstart.settings.json', {welcomed: !v}), }, + 'Run Now': () => load('ncstart.app.js'), '< Back': back, }) }) diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index 6c4c19230..3d82be9c0 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -16,3 +16,4 @@ Make capitalization more consistent Move LCD Brightness menu into more general LCD menu 0.14: Reduce memory usage when running app settings page +0.15: Reduce memory usage when running default clock chooser (#294) diff --git a/apps/setting/settings.js b/apps/setting/settings.js index d0d6578dc..9e343a68e 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -296,10 +296,10 @@ function makeConnectable() { }); } function showClockMenu() { - var clockApps = require("Storage").list(/\.info$/).map(app => { - try { return require("Storage").readJSON(app); } - catch (e) { } - }).filter(app => app.type == "clock").sort((a, b) => a.sortorder - b.sortorder); + var clockApps = require("Storage").list(/\.info$/) + .map(app => {var a=storage.readJSON(app, 1);return (a&&a.type == "clock")?a:undefined}) + .filter(app => app) // filter out any undefined apps + .sort((a, b) => a.sortorder - b.sortorder); const clockMenu = { '': { 'title': 'Select Clock', diff --git a/apps/snake/ChangeLog b/apps/snake/ChangeLog index 2286a7f70..428718739 100644 --- a/apps/snake/ChangeLog +++ b/apps/snake/ChangeLog @@ -1 +1,2 @@ -0.01: New App! \ No newline at end of file +0.01: New App! +0.02: Performance and graphic improvements, game pause, beep and buzz \ No newline at end of file diff --git a/apps/snake/README.md b/apps/snake/README.md index 7860dbd88..483eae7a9 100644 --- a/apps/snake/README.md +++ b/apps/snake/README.md @@ -1,6 +1,6 @@ # Snake -![Screenshot](https://i.ibb.co/XzWrvPL/screenshot.png) +![Screenshot](https://i.imgur.com/bXQjxhB.png) The legentary classic game is now available on Bangle.js! Eat apples and don't bite your tail. @@ -11,3 +11,4 @@ Eat apples and don't bite your tail. - DOWN: BTN3 - LEFT: BTN4 - RIGHT: BTN5 +- PAUSE: BTN2 diff --git a/apps/snake/snake.js b/apps/snake/snake.js index 37b461596..4532e0113 100644 --- a/apps/snake/snake.js +++ b/apps/snake/snake.js @@ -1,37 +1,61 @@ +Bangle.setLCDMode("120x120"); + const H = g.getWidth(); const W = g.getHeight(); let running = true; let score = 0; let d; - -// game world -const gridSize = 40; +const gridSize = 20; const tileSize = 6; let nextX = 0; let nextY = 0; - -// snake const defaultTailSize = 3; let tailSize = defaultTailSize; const snakeTrail = []; -let snakeX = 10; -let snakeY = 10; +const snake = { x: 10, y: 10 }; +const apple = { x: Math.floor(Math.random() * gridSize), y: Math.floor(Math.random() * gridSize) }; -// apple -let appleX = Math.floor(Math.random() * gridSize); -let appleY = Math.floor(Math.random() * gridSize); +function drawBackground(){ + g.setColor("#000000"); + g.fillRect(0, 0, H, W); +} + +function drawApple(){ + g.setColor("#FF0000"); + g.fillCircle((apple.x * tileSize) + tileSize/2, (apple.y * tileSize) + tileSize/2, tileSize/2); +} + +function drawSnake(){ + g.setColor("#008000"); + for (let i = 0; i < snakeTrail.length; i++) { + g.fillRect(snakeTrail[i].x * tileSize, snakeTrail[i].y * tileSize, snakeTrail[i].x * tileSize + tileSize, snakeTrail[i].y * tileSize + tileSize); + + //snake bites it's tail + if (snakeTrail[i].x === snake.x && snakeTrail[i].y === snake.y && tailSize > defaultTailSize) { + Bangle.buzz(1000); + gameOver(); + } + } +} + +function drawScore(){ + g.setColor("#FFFFFF"); + g.setFont("6x8"); + g.setFontAlign(0, 0); + g.drawString("Score:" + score, W / 2, 10); +} function gameStart() { running = true; score = 0; } -function gameStop() { +function gameOver() { g.clear(); g.setColor("#FFFFFF"); - g.setFont("6x8", 2); - g.drawString("GAME OVER!", W / 2, H / 2 - 20); - g.drawString("Tap to Restart", W / 2, H / 2 + 20); + g.setFont("6x8"); + g.drawString("GAME OVER!", W / 2, H / 2 - 10); + g.drawString("Tap to Restart", W / 2, H / 2 + 10); running = false; tailSize = defaultTailSize; } @@ -41,66 +65,50 @@ function draw() { return; } + g.clear(); + // move snake in next pos - snakeX += nextX; - snakeY += nextY; + snake.x += nextX; + snake.y += nextY; - // snake over game world? - if (snakeX < 0) { - snakeX = gridSize - 1; + // snake over game world + if (snake.x < 0) { + snake.x = gridSize - 1; + } + if (snake.x > gridSize - 1) { + snake.x = 0; } - if (snakeX > gridSize - 1) { - snakeX = 0; + if (snake.y < 0) { + snake.y = gridSize - 1; + } + if (snake.y > gridSize - 1) { + snake.y = 0; } - if (snakeY < 0) { - snakeY = gridSize - 1; - } - if (snakeY > gridSize - 1) { - snakeY = 0; - } - - //snake bite apple? - if (snakeX === appleX && snakeY === appleY) { + //snake bite apple + if (snake.x === apple.x && snake.y === apple.y) { + Bangle.beep(20); tailSize++; score++; - appleX = Math.floor(Math.random() * gridSize); - appleY = Math.floor(Math.random() * gridSize); + apple.x = Math.floor(Math.random() * gridSize); + apple.y = Math.floor(Math.random() * gridSize); + drawApple(); } - //paint background - g.setColor("#000000"); - g.fillRect(0, 0, H, W); - - // paint snake - g.setColor("#008000"); - - for (let i = 0; i < snakeTrail.length; i++) { - g.fillRect(snakeTrail[i].x * tileSize, snakeTrail[i].y * tileSize, snakeTrail[i].x * tileSize + tileSize, snakeTrail[i].y * tileSize + tileSize); - - //snake bites it's tail? - if (snakeTrail[i].x === snakeX && snakeTrail[i].y === snakeY && tailSize > defaultTailSize) { - gameStop(); - } - } - - // paint apple - g.setColor("#FF0000"); - g.fillRect(appleX * tileSize, appleY * tileSize, appleX * tileSize + tileSize, appleY * tileSize + tileSize); - - // paint score - g.setColor("#FFFFFF"); - g.setFont("6x8"); - g.setFontAlign(0, 0); - g.drawString("Score:" + score, W / 2, 10); + drawBackground(); + drawApple(); + drawSnake(); + drawScore(); //set snake trail - snakeTrail.push({ x: snakeX, y: snakeY }); + snakeTrail.push({ x: snake.x, y: snake.y }); while (snakeTrail.length > tailSize) { snakeTrail.shift(); } + + g.flip(); } // input @@ -132,6 +140,9 @@ setWatch(() => {// Right d = 'r'; } }, BTN5, { repeat: true }); +setWatch(() => {// Pause + running = !running; +}, BTN2, { repeat: true }); Bangle.on('touch', button => { if (!running) { @@ -140,5 +151,5 @@ Bangle.on('touch', button => { }); // render X times per second -var x = 5; +const x = 5; setInterval(draw, 1000 / x); \ No newline at end of file diff --git a/apps/welcome/ChangeLog b/apps/welcome/ChangeLog index 89f3ab2c9..b8786af6a 100644 --- a/apps/welcome/ChangeLog +++ b/apps/welcome/ChangeLog @@ -4,3 +4,6 @@ 0.04: Fix regression after tweaks to Storage.readJSON 0.05: Move configuration into App/widget settings 0.06: Move loader into welcome.boot.js +0.07: Run again when updated + Don't run again when settings app is updated (or absent) + Add "Run Now" option to settings diff --git a/apps/welcome/app.js b/apps/welcome/app.js index 93a4234d8..a32a6e56f 100644 --- a/apps/welcome/app.js +++ b/apps/welcome/app.js @@ -288,6 +288,13 @@ setWatch(()=>{ }, BTN2, {repeat:true,edge:"rising"}); setWatch(()=>move(-1), BTN1, {repeat:true}); +(function migrateSettings(){ + let global_settings = require('Storage').readJSON('setting.json', 1) + if (global_settings) { + delete global_settings.welcomed + require('Storage').write('setting.json', global_settings) + } +})() Bangle.setLCDTimeout(0); Bangle.setLCDPower(1); diff --git a/apps/welcome/boot.js b/apps/welcome/boot.js index ecf98b555..bc5afcc66 100644 --- a/apps/welcome/boot.js +++ b/apps/welcome/boot.js @@ -1,9 +1,11 @@ (function() { - let s = require('Storage').readJSON('setting.json', 1) || {} + let s = require('Storage').readJSON('welcome.settings.json', 1) + || require('Storage').readJSON('setting.json', 1) + || {welcomed: true} // do NOT run if global settings are also absent if (!s.welcomed && require('Storage').read('welcome.app.js')) { setTimeout(() => { s.welcomed = true - require('Storage').write('setting.json', s) + require('Storage').write('welcome.settings.json', {welcomed: "yes"}) load('welcome.app.js') }) } diff --git a/apps/welcome/settings-default.json b/apps/welcome/settings-default.json new file mode 100644 index 000000000..d250efff5 --- /dev/null +++ b/apps/welcome/settings-default.json @@ -0,0 +1,3 @@ +{ + "welcomed": false +} diff --git a/apps/welcome/settings.js b/apps/welcome/settings.js index 2fbd585c6..b11921646 100644 --- a/apps/welcome/settings.js +++ b/apps/welcome/settings.js @@ -1,16 +1,15 @@ // The welcome app is special, and gets to use global settings (function(back) { - let settings = require('Storage').readJSON('setting.json', 1) || {} + let settings = require('Storage').readJSON('welcome.settings.json', 1) + || require('Storage').readJSON('setting.json', 1) || {} E.showMenu({ '': { 'title': 'Welcome App' }, - 'Run again': { + 'Run on Next Boot': { value: !settings.welcomed, - format: v => v ? 'Yes' : 'No', - onchange: v => { - settings.welcomed = v ? undefined : true - require('Storage').write('setting.json', settings) - }, + format: v => v ? 'OK' : 'No', + onchange: v => require('Storage').write('welcome.settings.json', {welcomed: !v}), }, + 'Run Now': () => load('welcome.app.js'), '< Back': back, }) }) diff --git a/apps/widbat/ChangeLog b/apps/widbat/ChangeLog index cd9993c02..b9d50ab8b 100644 --- a/apps/widbat/ChangeLog +++ b/apps/widbat/ChangeLog @@ -1,3 +1,4 @@ 0.02: Now refresh battery monitor every minute if LCD on 0.03: Tweaks for variable size widget system 0.04: Ensure redrawing works with variable size widget system +0.05: Fix regression stopping correct widget updates diff --git a/apps/widbat/widget.js b/apps/widbat/widget.js index 2f1f29802..dd6774d4c 100644 --- a/apps/widbat/widget.js +++ b/apps/widbat/widget.js @@ -30,7 +30,7 @@ Bangle.on('lcdPower', function(on) { WIDGETS["bat"].draw(); // refresh once a minute if LCD on if (!batteryInterval) - batteryInterval = setInterval(draw, 60000); + batteryInterval = setInterval(()=>WIDGETS["bat"].draw(), 60000); } else { if (batteryInterval) { clearInterval(batteryInterval); diff --git a/apps/widbatpc/ChangeLog b/apps/widbatpc/ChangeLog index 3627a86d3..129707320 100644 --- a/apps/widbatpc/ChangeLog +++ b/apps/widbatpc/ChangeLog @@ -5,3 +5,4 @@ 0.06: Show battery percentage as text 0.07: Add settings: percentage/color/charger icon 0.08: Draw percentage as inverted on monochrome battery +0.09: Fix regression stopping correct widget updates diff --git a/apps/widbatpc/widget.js b/apps/widbatpc/widget.js index 9f88b5c49..aca690ce0 100644 --- a/apps/widbatpc/widget.js +++ b/apps/widbatpc/widget.js @@ -110,7 +110,7 @@ Bangle.on('lcdPower', function(on) { WIDGETS["batpc"].draw(); // refresh once a minute if LCD on if (!batteryInterval) - batteryInterval = setInterval(draw, 60000); + batteryInterval = setInterval(()=>WIDGETS["batpc"].draw(), 60000); } else { if (batteryInterval) { clearInterval(batteryInterval); diff --git a/apps/widbt/ChangeLog b/apps/widbt/ChangeLog index c268d6df0..59dc603a9 100644 --- a/apps/widbt/ChangeLog +++ b/apps/widbt/ChangeLog @@ -1,2 +1,3 @@ 0.02: Tweaks for variable size widget system 0.03: Ensure redrawing works with variable size widget system +0.04: Fix automatic update of Bluetooth connection status diff --git a/apps/widbt/widget.js b/apps/widbt/widget.js index 8e96a395d..c3254c791 100644 --- a/apps/widbt/widget.js +++ b/apps/widbt/widget.js @@ -13,7 +13,7 @@ function changed() { WIDGETS["bluetooth"].draw(); g.flip();// turns screen on } -NRF.on('connected',changed); -NRF.on('disconnected',changed); +NRF.on('connect',changed); +NRF.on('disconnect',changed); WIDGETS["bluetooth"]={area:"tr",width:24,draw:draw}; })() diff --git a/apps/widclk/ChangeLog b/apps/widclk/ChangeLog index 5370129cc..6fda78a08 100644 --- a/apps/widclk/ChangeLog +++ b/apps/widclk/ChangeLog @@ -1,2 +1,3 @@ 0.02: Now refresh battery monitor every minute if LCD on 0.03: Ensure redrawing works with variable size widget system +0.04: Fix regression stopping correct widget updates diff --git a/apps/widclk/widget.js b/apps/widclk/widget.js index 1d5df36b2..ff22bb4d1 100644 --- a/apps/widclk/widget.js +++ b/apps/widclk/widget.js @@ -14,7 +14,7 @@ } } function startTimers(){ - intervalRef = setInterval(draw, 60*1000); + intervalRef = setInterval(()=>WIDGETS["wdclk"].draw(), 60*1000); WIDGETS["wdclk"].draw(); } Bangle.on('lcdPower', (on) => { @@ -23,5 +23,5 @@ }); WIDGETS["wdclk"]={area:"tr",width:width,draw:draw}; - if (Bangle.isLCDOn) intervalRef = setInterval(draw, 60*1000); + if (Bangle.isLCDOn) intervalRef = setInterval(()=>WIDGETS["wdclk"].draw(), 60*1000); })() diff --git a/apps/widram/ChangeLog b/apps/widram/ChangeLog new file mode 100644 index 000000000..4c21f3ace --- /dev/null +++ b/apps/widram/ChangeLog @@ -0,0 +1 @@ +0.01: New Widget! diff --git a/apps/widram/widget.js b/apps/widram/widget.js new file mode 100644 index 000000000..08710b726 --- /dev/null +++ b/apps/widram/widget.js @@ -0,0 +1,23 @@ +(() => { + function draw() { + g.reset(); + var m = process.memory(); + var pc = Math.round(m.usage*100/m.total); + g.drawImage(atob("BwgBqgP////AVQ=="), this.x+(24-7)/2, this.y+4); + g.setColor(pc>70 ? "#ff0000" : (pc>50 ? "#ffff00" : "#ffffff")); + g.setFont("6x8").setFontAlign(0,0).drawString(pc+"%", this.x+12, this.y+20, true/*solid*/); + } + var ramInterval; + Bangle.on('lcdPower', function(on) { + if (on) { + WIDGETS["ram"].draw(); + if (!ramInterval) ramInterval = setInterval(()=>WIDGETS["ram"].draw(), 10000); + } else { + if (ramInterval) { + clearInterval(ramInterval); + ramInterval = undefined; + } + } + }); + WIDGETS["ram"]={area:"tl",width: 24,draw:draw}; +})() diff --git a/apps/widram/widget.png b/apps/widram/widget.png new file mode 100644 index 000000000..c1cbf2e1a Binary files /dev/null and b/apps/widram/widget.png differ diff --git a/js/comms.js b/js/comms.js index 604ef19ed..1f840ada7 100644 --- a/js/comms.js +++ b/js/comms.js @@ -75,12 +75,21 @@ getInstalledApps : () => { Progress.hide({sticky:true}); return reject(""); } - Puck.eval('require("Storage").list(/\.info$/).map(f=>{var j=require("Storage").readJSON(f,1)||{};j.id=f.slice(0,-5);return j})', (appList,err) => { + Puck.write('\x10Bluetooth.print("[");require("Storage").list(/\.info$/).forEach(f=>{var j=require("Storage").readJSON(f,1)||{};j.id=f.slice(0,-5);Bluetooth.print(JSON.stringify(j)+",")});Bluetooth.println("0]")\n', (appList,err) => { Progress.hide({sticky:true}); + try { + appList = JSON.parse(appList); + // remove last element since we added a final '0' + // to make things easy on the Bangle.js side + appList = appList.slice(0,-1); + } catch (e) { + appList = null; + err = e.toString(); + } if (appList===null) return reject(err || ""); console.log("getInstalledApps", appList); resolve(appList); - }); + }, true /* callback on newline */); }); }); },