diff --git a/apps.json b/apps.json index fd46de1d8..8b4e86d52 100644 --- a/apps.json +++ b/apps.json @@ -1590,7 +1590,7 @@ { "id": "widpedom", "name": "Pedometer widget", - "version": "0.19", + "version": "0.20", "description": "Daily pedometer widget", "icon": "widget.png", "type": "widget", @@ -3478,8 +3478,8 @@ { "id": "speedalt2", "name": "GPS Adventure Sports II", - "shortName": "GPS Adv Sport II", - "version": "0.07", + "shortName":"GPS Adv Sport II", + "version":"1.10", "description": "GPS speed, altitude and distance to waypoint display. Designed for easy viewing and use during outdoor activities such as para-gliding, hang-gliding, sailing, cycling etc.", "icon": "app.png", "type": "app", @@ -4209,7 +4209,7 @@ "id": "pastel", "name": "Pastel Clock", "shortName": "Pastel", - "version": "0.08", + "version": "0.09", "description": "A Configurable clock with custom fonts and background. Has a cyclic information line that includes, day, date, battery, sunrise and sunset times", "icon": "pastel.png", "dependencies": {"mylocation":"app", "widpedom":"app"}, @@ -4723,8 +4723,9 @@ "id": "pebble", "name": "Pebble Clock", "shortName": "Pebble", - "version": "0.04", + "version": "0.06", "description": "A pebble style clock to keep the rebellion going", + "dependencies": {"widpedom":"app"}, "readme": "README.md", "icon": "pebble.png", "screenshots": [{"url":"pebble_screenshot.png"}], @@ -4858,10 +4859,10 @@ "id": "ptlaunch", "name": "Pattern Launcher", "shortName": "Pattern Launcher", - "version": "0.10", + "version": "0.11", "description": "Directly launch apps from the clock screen with custom patterns.", "icon": "app.png", - "screenshots": [{"url":"main_menu_add.png"}, {"url":"add_pattern.png"}, {"url":"select_app.png"}, {"url":"main_menu_manage.png"}, {"url":"manage_patterns.png"}], + "screenshots": [{"url":"manage_patterns_light.png"}], "tags": "tools", "supports": ["BANGLEJS2"], "readme": "README.md", @@ -4876,11 +4877,11 @@ "id": "rebble", "name": "Rebble Clock", "shortName": "Rebble", - "version": "0.02", + "version": "0.03", "description": "A Pebble style clock, with configurable background, three sidebars including steps, day, date, sunrise, sunset, long live the rebellion", "readme": "README.md", "icon": "rebble.png", - "dependencies": {"mylocation":"app"}, + "dependencies": {"mylocation":"app", "widpedom":"app"}, "screenshots": [{"url":"screenshot_rebble.png"}], "type": "clock", "tags": "clock", @@ -4918,6 +4919,7 @@ "supports" : ["BANGLEJS", "BANGLEJS2"], "readme": "README.md", "storage": [ + {"name":"clicompleteclk.app.js","url":"app.js"}, {"name":"clicompleteclk.img","url":"app-icon.js","evaluate":true}, {"name":"clicompleteclk.settings.js","url":"settings.js"} ], @@ -4941,7 +4943,7 @@ { "id": "pooqround", "name": "pooq Round watch face", "shortName":"pooq Round", - "version":"0.00", + "version":"0.01", "description": "A 24 hour analogue watchface with high legibility and a novel style.", "icon": "app.png", "type": "clock", @@ -4977,14 +4979,52 @@ "id": "showimg", "name": "simple image viewer", "shortName":"showImage", - "version":"0.1", - "description": "Displays the image file in showimage.user.img. Returns to watch face after 60s or button push. I use it to display my vaccination certificate.", + "version":"0.2", + "description": "Displays the image in \"showimage.user.img\". The file has to be uploaded via the espruino IDE. Returns to watch face after 60s or button push. I use it to display my vaccination certificate.", "icon": "app.png", "tags": "tool", - "supports" : ["BANGLEJS2"], + "supports" : ["BANGLEJS2"], "storage": [ {"name":"showimg.app.js","url":"app.js"}, {"name":"showimg.img","url":"app-icon.js","evaluate":true} ] - } + }, + { + "id": "lapcounter", + "name": "Lap Counter", + "version": "0.01", + "description": "Click button to count laps. Shows count and total time snapshot (like a stopwatch, but laid back).", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], + "type": "app", + "tags": "tool,outdoors", + "readme":"README.md", + "supports": ["BANGLEJS", "BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"lapcounter.app.js","url":"app.js"}, + {"name":"lapcounter.img","url":"app-icon.js","evaluate":true} + ] + }, + { "id": "circlesclock", + "name": "Circles clock", + "shortName":"Circles clock", + "version":"0.01", + "description": "A clock with circles for different data at the bottom in a probably familiar style", + "icon": "app.png", + "dependencies": {"widpedom":"app"}, + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "allow_emulator":true, + "readme": "README.md", + "storage": [ + {"name":"circlesclock.app.js","url":"app.js"}, + {"name":"circlesclock.img","url":"app-icon.js","evaluate":true}, + {"name":"circlesclock.settings.js","url":"settings.js"} + ], + "data": [ + {"name":"circlesclock.json"} + ] + } ] diff --git a/apps/circlesclock/Changelog b/apps/circlesclock/Changelog new file mode 100644 index 000000000..af119ab59 --- /dev/null +++ b/apps/circlesclock/Changelog @@ -0,0 +1 @@ +0.01: New clock diff --git a/apps/circlesclock/README.md b/apps/circlesclock/README.md new file mode 100644 index 000000000..87edd5981 --- /dev/null +++ b/apps/circlesclock/README.md @@ -0,0 +1,19 @@ +# Circles clock + +A clock with circles for different data at the bottom in a probably familiar style + +It shows besides time, date and day of week the following information: + * Steps (requires [pedometer widget](https://banglejs.com/apps/#pedometer)) + * Heart rate (when screen is on and unlocked) + * Battery + +## Screenshot + +![Screenshot](screenshot.png) + +## TODO +* Show weather information + + +## Creator +Marco ([myxor](https://github.com/myxor)) diff --git a/apps/circlesclock/app-icon.js b/apps/circlesclock/app-icon.js new file mode 100644 index 000000000..ad727251a --- /dev/null +++ b/apps/circlesclock/app-icon.js @@ -0,0 +1 @@ + require("heatshrink").decompress(atob("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")) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js new file mode 100644 index 000000000..8474b7f4e --- /dev/null +++ b/apps/circlesclock/app.js @@ -0,0 +1,218 @@ +const locale = require("locale"); +const heatshrink = require("heatshrink"); + +var shoesIcon = heatshrink.decompress(atob("h0OwYJGgmAAgUBkgECgVJB4cSoAUDyEBkARDpADBhMAyQRBgVAkgmDhIUDAAuQAgY1DAAYA=")); +var heartIcon = heatshrink.decompress(atob("h0OwYOLkmQhMkgACByVJgESpIFBpEEBAIFBCgIFCCgsABwcAgQOCAAMSpAwDyBNM")); +var powerIcon = heatshrink.decompress(atob("h0OwYQNsAED7AEDmwEDtu2AgUbtuABwXbBIUN23AAoYOCgEDFIgODABI")); + +const SETTINGS_FILE = "circlesclock.json"; +let settings; + +function loadSettings() { + settings = require("Storage").readJSON(SETTINGS_FILE, 1) || { + 'maxHR': 200, + 'stepGoal': 10000 + }; +} + +const colorFg = '#fff'; +const colorBg = '#000'; +const colorGrey = '#808080'; + +let hrtValue; + +const h = g.getHeight(); +const w = g.getWidth(); +const hOffset = 30; +const h1 = Math.round(1 * h / 5 - hOffset); +const h2 = Math.round(3 * h / 5 - hOffset); +const h3 = Math.round(8 * h / 8 - hOffset); +const w1 = Math.round(w / 6); +const w2 = Math.round(3 * w / 6); +const w3 = Math.round(5 * w / 6); +const radiusOuter = 22; +const radiusInner = 16; + +function draw() { + g.reset(); + g.setColor(colorBg); + g.fillRect(0, 0, w, h); + + // time + g.setFont("Vector:50"); + g.setFontAlign(-1, -1); + g.setColor(colorFg); + g.drawString(locale.time(new Date(), 1), w / 10, h1 + 8); + + // date & dow + g.setFont("Vector:20"); + g.setFontAlign(-1, 0); + g.drawString(locale.date(new Date()), w / 10, h2); + g.drawString(locale.dow(new Date()), w / 10, h2 + 22); + + // Steps circle + drawSteps(); + + // Heart circle + drawHeartRate(); + + // Battery circle + drawBattery(); +} + + + +function drawSteps() { + const steps = getSteps(); + const blue = '#0000ff'; + g.setColor(colorGrey); + g.fillCircle(w1, h3, radiusOuter); + + const stepGoal = settings.stepGoal; + if (stepGoal > 0) { + let percent = steps / stepGoal; + if (stepGoal < steps) percent = 1; + drawGauge(w1, h3, percent, blue); + } + + g.setColor(colorBg); + g.fillCircle(w1, h3, radiusInner); + + g.fillPoly([w1, h3, w1 - 15, h3 + radiusOuter + 5, w1 + 15, h3 + radiusOuter + 5]); + + g.setFont("Vector:12"); + g.setFontAlign(0, 0); + g.setColor(colorFg); + g.drawString(shortValue(steps), w1 + 2, h3); + + g.drawImage(shoesIcon, w1 - 6, h3 + radiusOuter - 6); +} + +function drawHeartRate() { + const red = '#ff0000'; + g.setColor(colorGrey); + g.fillCircle(w2, h3, radiusOuter); + + if (hrtValue != undefined) { + const percent = hrtValue / settings.maxHR; + drawGauge(w2, h3, percent, red); + } + + g.setColor(colorBg); + g.fillCircle(w2, h3, radiusInner); + + g.fillPoly([w2, h3, w2 - 15, h3 + radiusOuter + 5, w2 + 15, h3 + radiusOuter + 5]); + + g.setFont("Vector:12"); + g.setFontAlign(0, 0); + g.setColor(colorFg); + g.drawString(hrtValue != undefined ? hrtValue : 0, w2, h3); + + g.drawImage(heartIcon, w2 - 6, h3 + radiusOuter - 6); +} + +function drawBattery() { + const battery = E.getBattery(); + const yellow = '#ffff00'; + g.setColor(colorGrey); + g.fillCircle(w3, h3, radiusOuter); + + if (battery > 0) { + const percent = battery / 100; + drawGauge(w3, h3, percent, yellow); + } + + g.setColor(colorBg); + g.fillCircle(w3, h3, radiusInner); + + g.fillPoly([w3, h3, w3 - 15, h3 + radiusOuter + 5, w3 + 15, h3 + radiusOuter + 5]); + + g.setFont("Vector:12"); + g.setFontAlign(0, 0); + g.setColor(colorFg); + g.drawString(battery + '%', w3, h3); + + g.drawImage(powerIcon, w3 - 6, h3 + radiusOuter - 6); +} + +function radians(a) { + return a * Math.PI / 180; +} + + +function drawGauge(cx, cy, percent, color) { + let offset = 30; + let end = 300; + var i = 0; + var r = radiusInner + 3; + + if (percent > 1) percent = 1; + + var startrot = -offset; + var endrot = startrot - ((end - offset) * percent); + + g.setColor(color); + + // draw gauge + for (i = startrot; i > endrot; i -= 4) { + x = cx + r * Math.sin(radians(i)); + y = cy + r * Math.cos(radians(i)); + g.fillCircle(x, y, 4); + } +} + +function shortValue(v) { + if (isNaN(v)) return '-'; + if (v <= 999) return v; + if (v >= 1000 && v < 10000) { + v = Math.floor(v / 100) * 100; + return (v / 1000).toFixed(1).replace(/\.0$/, '') + 'k'; + } + if (v >= 10000) { + v = Math.floor(v / 1000) * 1000; + return (v / 1000).toFixed(1).replace(/\.0$/, '') + 'k'; + } +} + +function getSteps() { + if (WIDGETS.wpedom !== undefined) { + return WIDGETS.wpedom.getSteps(); + } + return 0; +} + +Bangle.on('lock', function(isLocked) { + if (!isLocked) { + Bangle.setHRMPower(1, "watch"); + } else { + Bangle.setHRMPower(0, "watch"); + } + drawHeartRate(); + drawSteps(); +}); + +Bangle.on('HRM', function(hrm) { + //if(hrm.confidence > 90){ + hrtValue = hrm.bpm; + if (Bangle.isLCDOn()) + drawHeartRate(); + //} else { + // hrtValue = undefined; + //} +}); + +g.clear(); +Bangle.loadWidgets(); +/* + * we are not drawing the widgets as we are taking over the whole screen + * so we will blank out the draw() functions of each widget and change the + * area to the top bar doesn't get cleared. + */ +for (let wd of WIDGETS) { + wd.draw = () => {}; + wd.area = ""; +} +loadSettings(); +setInterval(draw, 60000); +draw(); +Bangle.setUI("clock"); diff --git a/apps/circlesclock/app.png b/apps/circlesclock/app.png new file mode 100644 index 000000000..94ff885fa Binary files /dev/null and b/apps/circlesclock/app.png differ diff --git a/apps/circlesclock/screenshot.png b/apps/circlesclock/screenshot.png new file mode 100644 index 000000000..94ff885fa Binary files /dev/null and b/apps/circlesclock/screenshot.png differ diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js new file mode 100644 index 000000000..2de278b47 --- /dev/null +++ b/apps/circlesclock/settings.js @@ -0,0 +1,33 @@ +(function(back) { + const SETTINGS_FILE = "circlesclock.json"; + const storage = require('Storage'); + let settings = storage.readJSON(SETTINGS_FILE, 1) || {}; + function save(key, value) { + settings[key] = value; + storage.write(SETTINGS_FILE, settings); + } + E.showMenu({ + '': { 'title': 'circlesclock' }, + 'max heartrate': { + value: "maxHR" in settings ? settings.maxHR : 200, + min: 20, + max : 250, + step: 10, + format: x => { + return x; + }, + onchange: x => save('maxHR', x), + }, + 'step goal': { + value: "stepGoal" in settings ? settings.stepGoal : 10000, + min: 2000, + max : 50000, + step: 2000, + format: x => { + return x; + }, + onchange: x => save('stepGoal', x), + }, + '< Back': back, + }); +}); diff --git a/apps/lapcounter/ChangeLog b/apps/lapcounter/ChangeLog new file mode 100644 index 000000000..9db0e26c5 --- /dev/null +++ b/apps/lapcounter/ChangeLog @@ -0,0 +1 @@ +0.01: first release diff --git a/apps/lapcounter/README.md b/apps/lapcounter/README.md new file mode 100644 index 000000000..8866955e4 --- /dev/null +++ b/apps/lapcounter/README.md @@ -0,0 +1,19 @@ +# Lap Counter + +Click button to count laps (e.g. in a swimming pool). +Also shows total duration snapshot (like a stopwatch, but laid back). + +![Screenshot](screenshot.png) + +## Usage + +* Click BTN1 to start counting. Counter becomes `0`, duration becomes `00:00.0` +* Each time you click BTN1, counter is incremented, and you see duration between first and last clicks. + +## Features + +Disables LCD timeout (so that you can be _sure_ what BTN1 would do). + +## Creator + +[Nimrod Kerrett](https://zzzen.com) diff --git a/apps/lapcounter/app-icon.js b/apps/lapcounter/app-icon.js new file mode 100644 index 000000000..a443b3a41 --- /dev/null +++ b/apps/lapcounter/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwkBiIA/AH4A/AAkQgEBAREAC6oABdZQXkI6wuKC5iPUFxoXIOpoX/C6QFCC6IsCC6ZEDC/4XcPooXOFgoXQIgwX/C7IUFC5wsIC5ouCC6hcJC5h1DF9YwBChCPOAH4A/AH4Ap")) diff --git a/apps/lapcounter/app.js b/apps/lapcounter/app.js new file mode 100644 index 000000000..215f6140a --- /dev/null +++ b/apps/lapcounter/app.js @@ -0,0 +1,53 @@ +const w = g.getWidth(); +const h = g.getHeight(); +const wid_h = 24; +let tStart; +let tNow; +let counter=-1; + +const icon = require("heatshrink").decompress(atob("mEwwkBiIA/AH4A/AAkQgEBAREAC6oABdZQXkI6wuKC5iPUFxoXIOpoX/C6QFCC6IsCC6ZEDC/4XcPooXOFgoXQIgwX/C7IUFC5wsIC5ouCC6hcJC5h1DF9YwBChCPOAH4A/AH4Ap")); + +function timeToText(t) { // Courtesy of stopwatch app + let hrs = Math.floor(t/3600000); + let mins = Math.floor(t/60000)%60; + let secs = Math.floor(t/1000)%60; + let tnth = Math.floor(t/100)%10; + let text; + + if (hrs === 0) + text = ("0"+mins).substr(-2) + ":" + ("0"+secs).substr(-2) + "." + tnth; + else + text = ("0"+hrs) + ":" + ("0"+mins).substr(-2) + ":" + ("0"+secs).substr(-2); + //log_debug(text); + return text; +} + +function doCounter() { + if (counter<0) { + tStart = Date.now(); + tNow = tStart; + } else { + tNow = Date.now(); + } + counter++; + let dT = tNow-tStart; + + g.clearRect(0,wid_h,w,h-wid_h); + g.setFontAlign(0,0); + g.setFont("Vector",72); + g.drawString(counter,w/2,h/2); + g.setFont("Vector",24); + g.drawString(timeToText(dT),w/2,h/2+50); +} + +setWatch(doCounter, BTN1, true); + +g.clear(true); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +Bangle.setLCDTimeout(0); +g.drawImage(icon,w/2-24,h/2-24); +g.setFontAlign(0,0); +require("Font8x12").add(Graphics); +g.setFont("8x12"); +g.drawString("Click button to count.", w/2, h/2+22); diff --git a/apps/lapcounter/app.png b/apps/lapcounter/app.png new file mode 100644 index 000000000..7d6ca8317 Binary files /dev/null and b/apps/lapcounter/app.png differ diff --git a/apps/lapcounter/screenshot.png b/apps/lapcounter/screenshot.png new file mode 100644 index 000000000..f3113d86e Binary files /dev/null and b/apps/lapcounter/screenshot.png differ diff --git a/apps/pastel/ChangeLog b/apps/pastel/ChangeLog index 2ede0e161..afeb305c5 100644 --- a/apps/pastel/ChangeLog +++ b/apps/pastel/ChangeLog @@ -6,3 +6,4 @@ 0.06: Converted fonts to font modules 0.07: Added info line that cycles on BTN1/BTN3 (or vitual buttons on a bangle 2) 0.08: Added dependancy on MyLocation +0.09: Added dependancy on Pedometer Widget diff --git a/apps/pebble/ChangeLog b/apps/pebble/ChangeLog index b3d37f841..d92be5e9c 100644 --- a/apps/pebble/ChangeLog +++ b/apps/pebble/ChangeLog @@ -3,3 +3,4 @@ 0.03: Changed time+calendar font to LECO1976Regular, changed to slanting boot 0.04: Fix widget hiding code (fix #1046) 0.05: Fix typo in settings - Purple +0.06: Added dependancy on Pedometer Widget diff --git a/apps/pooqround/ChangeLog b/apps/pooqround/ChangeLog index 12876f71a..8eb91cf97 100644 --- a/apps/pooqround/ChangeLog +++ b/apps/pooqround/ChangeLog @@ -1 +1,2 @@ 0.00: Initial check-in. +0.01: Add tap-to-decorate feature. Bugfixes. diff --git a/apps/pooqround/README.md b/apps/pooqround/README.md index 3c651ed67..d413fd88e 100644 --- a/apps/pooqround/README.md +++ b/apps/pooqround/README.md @@ -10,16 +10,18 @@ Either you'll like that, or you won't. ## Options -Because sometimes I don't want to burn what I'm cooking and others I'm lazy and just want to know if it's afternoon yet, -you can alter the number of ‘hands’ on the display. When the watch is unlocked, slide up to add dots representing the minute and second, -or down to remove the distraction. There's also a setting that displays the second hand, but only if the watch is perfectly face-to-the-sky, -in case you want the ability to check the _exact_ time, hands free, without the impact on battery life this usually entails. - Although we generally obey the system-wide theming, you can long press on the display for a menu of additional options specific to the face. We don't observe the system 12/24 setting, since it the design of the face is equally good in either interpretation. -By default, there is a backlight that comes on when you twist your wrist. This, of course, somewhat increases power draw and could be -annoying in an intentionally dark environment, so there is an option to disable it. +If you like an uncluttered display style, you can still bring up the day, date and minute hand transiently with a tap on the watchface (when unlocked). + +Similarly, because sometimes I don't want to burn what I'm cooking and others I'm lazy and just want to know if it's afternoon yet, +you can quickly alter the number of ‘hands’ on the display. When the watch is unlocked, slide up to add dots representing the minute and second, +or down to remove the distraction. There's also a setting that displays the second hand, but only if the watch is perfectly face-to-the-sky, +in case you want the ability to check the _exact_ time, hands free, without the impact on battery life this usually entails. + +In some versions of the Bangle.js firmware, the backlight doesn't come on automatically when you twist your wrist. There's currently a workaround +for this integrated into the watchface; you can disable it in the menu, if you prefer. ## Limitations diff --git a/apps/pooqround/app.js b/apps/pooqround/app.js index 29fae6ee6..22cf5ff79 100644 --- a/apps/pooqround/app.js +++ b/apps/pooqround/app.js @@ -83,7 +83,6 @@ class Options { Bangle.removeListener('drag', this.reactivator); this.emit('done'); } - g.clear(true); E.showMenu(m); } @@ -309,7 +308,7 @@ class Round { buffer: this.c.buffer, transparent: 0 }; this.options = new RoundOptions(); - this.timescales = [1000, 0, 60000, 900000]; + this.timescales = [1000, [1000, 60000], 60000, 900000]; this.state = {}; // Precomputed polygons for the border areas. this.tl = [0, 0, 58, 0, 0, 58]; @@ -323,13 +322,15 @@ class Round { this.r = this.xc - this.minR; } - reset() {this.state = {}; this.g.clear(true);} + reset(clear) {this.state = {}; clear && this.g.clear(true);} doIcons(which) { this.state[which] = null; this.render(new Date()); // Not quite right, I think. } + enhanceUntil(t) {this.enhance = t;} + pie(f, a0, a1, invert) { if (!invert) return this.pie(f, a1, a0 + 1, true); let t0 = Math.tan(a0 * 2 * Math.PI), t1 = Math.tan(a1 * 2 * Math.PI); @@ -369,17 +370,18 @@ class Round { const g = this.g; const b = this.b, bI = this.bI; const c = this.c, cI = this.cI; + const e = d < this.enhance; const state = this.state; const options = this.options; const cal = options.calendric; const res = options.resolution; - const dow = (cal == 1 || cal > 2) && d.getDay(); + const dow = (e || cal == 1 || cal > 2) && d.getDay(); const ts = res < 2 && d.getSeconds(); - const tm = res < 3 && d.getMinutes() + ts / 60; + const tm = (e || res < 3) && d.getMinutes() + ts / 60; const th = d.getHours() + d.getMinutes() / 60; - const dd = cal > 1 && d.getDate(); - const dm = cal > 3 && d.getMonth(); - const dy = cal > 4 && d.getFullYear(); + const dd = (e || cal > 1) && d.getDate(); + const dm = (e || cal > 3) && d.getMonth(); + const dy = (e || cal > 4) && d.getFullYear(); const xc = this.xc, yc = this.yc, r = this.r; const dlr = xc * 3/4, dlw = 8, dlhw = 4; @@ -475,7 +477,6 @@ class Clock { this.timescales = face.timescales; this.options = face.options; this.rates = {}; - this.faceUp = null; this.options.on('done', () => this.start()); @@ -485,7 +486,6 @@ class Clock { lock: () => {face.doIcons('locked'); this.active();}, faceUp: up => { this.conservative = !up; - this.faceUp = up; this.active(); }, twist: _ => this.options.autolight && Bangle.setLCDPower(true), @@ -504,9 +504,15 @@ class Clock { this.options.resolution++; this.rates.clock = this.timescales[this.options.resolution]; this.active(); - } else if (this.yX - this.yN < 20 && Date.now() - this.t0 > 500) { - this.stop(); - this.options.interact(); + } else if (this.yX - this.yN < 20) { + const now = new Date(); + if (now - this.t0 < 250) { + face.enhanceUntil(now + 30000); + face.render(now); + } else if (now - this.t0 > 500) { + this.stop(); + this.options.interact(); + } } this.t0 = null; } @@ -520,7 +526,7 @@ class Clock { redraw(rate) { const now = this.updated = new Date(); - if (this.refresh) this.face.reset(); + if (this.refresh) this.face.reset(true); this.refresh = false; rate = this.face.render(now, rate); if (rate !== this.rates.face) { @@ -535,7 +541,7 @@ class Clock { this.exception && clearTimeout(this.exception); this.interval && clearInterval(this.interval); this.timeout = this.exception = this.interval = this.rate = null; - this.face.reset(); // Cancel any ongoing background rendering + this.face.reset(false); // Cancel any ongoing background rendering return this; } diff --git a/apps/ptlaunch/ChangeLog b/apps/ptlaunch/ChangeLog index de38d715a..23031cff3 100644 --- a/apps/ptlaunch/ChangeLog +++ b/apps/ptlaunch/ChangeLog @@ -1,4 +1,5 @@ 0.01: Initial creation of the pattern launch app 0.02: Turn on lcd when launching an app if the lock screen was disabled in the settings 0.03: Make tap to confirm new pattern more reliable. Also allow for easier creation of single circle patterns. -0.10: Improve the management of existing patterns: Draw the linked pattern on the left hand side of the app name within a scroller, similar to the default launcher. Slighlty clean up the code to make it less horrible. \ No newline at end of file +0.10: Improve the management of existing patterns: Draw the linked pattern on the left hand side of the app name within a scroller, similar to the default launcher. Slighlty clean up the code to make it less horrible. +0.11: Respect theme colors. Fix: Do not pollute global space with internal variables ans functions in boot.js \ No newline at end of file diff --git a/apps/ptlaunch/README.md b/apps/ptlaunch/README.md index 8d61afece..7cc39e3d6 100644 --- a/apps/ptlaunch/README.md +++ b/apps/ptlaunch/README.md @@ -10,14 +10,21 @@ Then launch the linked apps directly from the clock screen by simply drawing the ## Add Pattern Screenshots -![](main_menu_add.png) -![](add_pattern.png) -![](select_app.png) +![](main_menu_add_light.png) +![](add_pattern_light.png) +![](select_app_light.png) + +![](main_menu_add_dark.png) +![](add_pattern_dark.png) +![](select_app_dark.png) ## Manage Pattern Screenshots -![](main_menu_manage.png) -![](manage_patterns.png) +![](main_menu_manage_light.png) +![](manage_patterns_light.png) + +![](main_menu_manage_dark.png) +![](manage_patterns_dark.png) ## Detailed Steps diff --git a/apps/ptlaunch/add_pattern.png b/apps/ptlaunch/add_pattern.png deleted file mode 100644 index c7cc38e82..000000000 Binary files a/apps/ptlaunch/add_pattern.png and /dev/null differ diff --git a/apps/ptlaunch/add_pattern_dark.png b/apps/ptlaunch/add_pattern_dark.png new file mode 100644 index 000000000..04dfdecd6 Binary files /dev/null and b/apps/ptlaunch/add_pattern_dark.png differ diff --git a/apps/ptlaunch/add_pattern_light.png b/apps/ptlaunch/add_pattern_light.png new file mode 100644 index 000000000..47549b43e Binary files /dev/null and b/apps/ptlaunch/add_pattern_light.png differ diff --git a/apps/ptlaunch/app.js b/apps/ptlaunch/app.js index b5a3bf610..062cc3c62 100644 --- a/apps/ptlaunch/app.js +++ b/apps/ptlaunch/app.js @@ -119,8 +119,7 @@ var recognizeAndDrawPattern = () => { return new Promise((resolve) => { E.showMenu(); g.clear(); - g.setColor(0, 0, 0); - CIRCLES.forEach((circle) => drawCircle(circle)); + drawCirclesWithPattern([]); var pattern = []; @@ -369,7 +368,6 @@ var drawAppWithPattern = (i, r, storedPatterns) => { offset: { x: 1, y: 3 + r.y }, }); - g.setColor(0, 0, 0); if (!storedPattern.wrappedAppName) { storedPattern.wrappedAppName = g .wrapString(app.name, g.getWidth() - 64) @@ -490,7 +488,7 @@ var drawCircle = (circle, drawBuffer, scale) => { log("drawing circle"); log({ x: x, y: y, r: r }); - drawBuffer.fillCircle(x, y, r); + drawBuffer.drawCircle(x, y, r); }; var cachedCirclesDrawings = {}; @@ -535,17 +533,15 @@ var drawCirclesWithPattern = (pattern, options) => { { msb: true } ); - drawBuffer.setColor(1); CIRCLES.forEach((circle) => drawCircle(circle, drawBuffer, scale)); - drawBuffer.setColor(0); drawBuffer.setFontAlign(0, 0); - drawBuffer.setFont("6x8", 4 * scale); + drawBuffer.setFont("Vector", 40 * scale); pattern.forEach((circleIndex, patternIndex) => { var circle = CIRCLES[circleIndex]; drawBuffer.drawString( patternIndex + 1, - circle.x * scale, + (circle.x + (scale === 1 ? 1 : 5)) * scale, circle.y * scale ); }); diff --git a/apps/ptlaunch/boot.js b/apps/ptlaunch/boot.js index a23607768..6fbd3ca41 100644 --- a/apps/ptlaunch/boot.js +++ b/apps/ptlaunch/boot.js @@ -1,167 +1,167 @@ -var DEBUG = true; -var log = (message) => { - if (DEBUG) { - console.log(JSON.stringify(message)); - } -}; - -var storedPatterns; -var positions = []; -var dragHandler = (position) => { - positions.push(position); - - debounce().then(() => { - log(positions.length); - - var CIRCLE_RADIUS = 25; - var CIRCLE_RADIUS_2 = CIRCLE_RADIUS * CIRCLE_RADIUS; - - var circles = [ - { x: 25, y: 25, i: 0 }, - { x: 87, y: 25, i: 1 }, - { x: 150, y: 25, i: 2 }, - { x: 25, y: 87, i: 3 }, - { x: 87, y: 87, i: 4 }, - { x: 150, y: 87, i: 5 }, - { x: 25, y: 150, i: 6 }, - { x: 87, y: 150, i: 7 }, - { x: 150, y: 150, i: 8 }, - ]; - var pattern = []; - - var step = Math.floor(positions.length / 100) + 1; - - var p, a, b, circle; - - for (var i = 0; i < positions.length; i += step) { - p = positions[i]; - - circle = circles[0]; - if (circle) { - a = p.x - circle.x; - b = p.y - circle.y; - if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { - pattern.push(circle.i); - circles.splice(0, 1); - } - } - - circle = circles[1]; - if (circle) { - a = p.x - circle.x; - b = p.y - circle.y; - if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { - pattern.push(circle.i); - circles.splice(1, 1); - } - } - - circle = circles[2]; - if (circle) { - a = p.x - circle.x; - b = p.y - circle.y; - if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { - pattern.push(circle.i); - circles.splice(2, 1); - } - } - - circle = circles[3]; - if (circle) { - a = p.x - circle.x; - b = p.y - circle.y; - if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { - pattern.push(circle.i); - circles.splice(3, 1); - } - } - - circle = circles[4]; - if (circle) { - a = p.x - circle.x; - b = p.y - circle.y; - if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { - pattern.push(circle.i); - circles.splice(4, 1); - } - } - - circle = circles[5]; - if (circle) { - a = p.x - circle.x; - b = p.y - circle.y; - if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { - pattern.push(circle.i); - circles.splice(5, 1); - } - } - - circle = circles[6]; - if (circle) { - a = p.x - circle.x; - b = p.y - circle.y; - if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { - pattern.push(circle.i); - circles.splice(6, 1); - } - } - circle = circles[7]; - if (circle) { - a = p.x - circle.x; - b = p.y - circle.y; - if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { - pattern.push(circle.i); - circles.splice(7, 1); - } - } - - circle = circles[8]; - if (circle) { - a = p.x - circle.x; - b = p.y - circle.y; - if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { - pattern.push(circle.i); - circles.splice(8, 1); - } - } - } - positions = []; - - pattern = pattern.join(""); - - if (pattern) { - if (storedPatterns[pattern]) { - var app = storedPatterns[pattern].app; - if (!!app && !!app.src) { - if (storedPatterns.settings) { - if (storedPatterns.settings.lockDisabled) { - Bangle.setLCDPower(true); - } - } - - Bangle.removeListener("drag", dragHandler); - load(app.src); - } - } - } - }); -}; - -var debounceTimeoutId; -var debounce = (delay) => { - if (debounceTimeoutId) { - clearTimeout(debounceTimeoutId); - } - - return new Promise((resolve) => { - debounceTimeoutId = setTimeout(() => { - debounceTimeoutId = undefined; - resolve(); - }, delay || 500); - }); -}; - (function () { + var DEBUG = false; + var log = (message) => { + if (DEBUG) { + console.log(JSON.stringify(message)); + } + }; + + var storedPatterns; + var positions = []; + var dragHandler = (position) => { + positions.push(position); + + debounce().then(() => { + log(positions.length); + + var CIRCLE_RADIUS = 25; + var CIRCLE_RADIUS_2 = CIRCLE_RADIUS * CIRCLE_RADIUS; + + var circles = [ + { x: 25, y: 25, i: 0 }, + { x: 87, y: 25, i: 1 }, + { x: 150, y: 25, i: 2 }, + { x: 25, y: 87, i: 3 }, + { x: 87, y: 87, i: 4 }, + { x: 150, y: 87, i: 5 }, + { x: 25, y: 150, i: 6 }, + { x: 87, y: 150, i: 7 }, + { x: 150, y: 150, i: 8 }, + ]; + var pattern = []; + + var step = Math.floor(positions.length / 100) + 1; + + var p, a, b, circle; + + for (var i = 0; i < positions.length; i += step) { + p = positions[i]; + + circle = circles[0]; + if (circle) { + a = p.x - circle.x; + b = p.y - circle.y; + if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { + pattern.push(circle.i); + circles.splice(0, 1); + } + } + + circle = circles[1]; + if (circle) { + a = p.x - circle.x; + b = p.y - circle.y; + if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { + pattern.push(circle.i); + circles.splice(1, 1); + } + } + + circle = circles[2]; + if (circle) { + a = p.x - circle.x; + b = p.y - circle.y; + if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { + pattern.push(circle.i); + circles.splice(2, 1); + } + } + + circle = circles[3]; + if (circle) { + a = p.x - circle.x; + b = p.y - circle.y; + if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { + pattern.push(circle.i); + circles.splice(3, 1); + } + } + + circle = circles[4]; + if (circle) { + a = p.x - circle.x; + b = p.y - circle.y; + if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { + pattern.push(circle.i); + circles.splice(4, 1); + } + } + + circle = circles[5]; + if (circle) { + a = p.x - circle.x; + b = p.y - circle.y; + if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { + pattern.push(circle.i); + circles.splice(5, 1); + } + } + + circle = circles[6]; + if (circle) { + a = p.x - circle.x; + b = p.y - circle.y; + if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { + pattern.push(circle.i); + circles.splice(6, 1); + } + } + circle = circles[7]; + if (circle) { + a = p.x - circle.x; + b = p.y - circle.y; + if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { + pattern.push(circle.i); + circles.splice(7, 1); + } + } + + circle = circles[8]; + if (circle) { + a = p.x - circle.x; + b = p.y - circle.y; + if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { + pattern.push(circle.i); + circles.splice(8, 1); + } + } + } + positions = []; + + pattern = pattern.join(""); + + if (pattern) { + if (storedPatterns[pattern]) { + var app = storedPatterns[pattern].app; + if (!!app && !!app.src) { + if (storedPatterns.settings) { + if (storedPatterns.settings.lockDisabled) { + Bangle.setLCDPower(true); + } + } + + Bangle.removeListener("drag", dragHandler); + load(app.src); + } + } + } + }); + }; + + var debounceTimeoutId; + var debounce = (delay) => { + if (debounceTimeoutId) { + clearTimeout(debounceTimeoutId); + } + + return new Promise((resolve) => { + debounceTimeoutId = setTimeout(() => { + debounceTimeoutId = undefined; + resolve(); + }, delay || 500); + }); + }; + var sui = Bangle.setUI; Bangle.setUI = function (mode, cb) { sui(mode, cb); diff --git a/apps/ptlaunch/main_menu_add_dark.png b/apps/ptlaunch/main_menu_add_dark.png new file mode 100644 index 000000000..4c1564eca Binary files /dev/null and b/apps/ptlaunch/main_menu_add_dark.png differ diff --git a/apps/ptlaunch/main_menu_add.png b/apps/ptlaunch/main_menu_add_light.png similarity index 100% rename from apps/ptlaunch/main_menu_add.png rename to apps/ptlaunch/main_menu_add_light.png diff --git a/apps/ptlaunch/main_menu_manage_dark.png b/apps/ptlaunch/main_menu_manage_dark.png new file mode 100644 index 000000000..e630db46d Binary files /dev/null and b/apps/ptlaunch/main_menu_manage_dark.png differ diff --git a/apps/ptlaunch/main_menu_manage.png b/apps/ptlaunch/main_menu_manage_light.png similarity index 100% rename from apps/ptlaunch/main_menu_manage.png rename to apps/ptlaunch/main_menu_manage_light.png diff --git a/apps/ptlaunch/manage_patterns.png b/apps/ptlaunch/manage_patterns.png deleted file mode 100644 index 82b10ad43..000000000 Binary files a/apps/ptlaunch/manage_patterns.png and /dev/null differ diff --git a/apps/ptlaunch/manage_patterns_dark.png b/apps/ptlaunch/manage_patterns_dark.png new file mode 100644 index 000000000..698a19222 Binary files /dev/null and b/apps/ptlaunch/manage_patterns_dark.png differ diff --git a/apps/ptlaunch/manage_patterns_light.png b/apps/ptlaunch/manage_patterns_light.png new file mode 100644 index 000000000..5e4b27131 Binary files /dev/null and b/apps/ptlaunch/manage_patterns_light.png differ diff --git a/apps/ptlaunch/select_app_dark.png b/apps/ptlaunch/select_app_dark.png new file mode 100644 index 000000000..422f2b5e2 Binary files /dev/null and b/apps/ptlaunch/select_app_dark.png differ diff --git a/apps/ptlaunch/select_app.png b/apps/ptlaunch/select_app_light.png similarity index 100% rename from apps/ptlaunch/select_app.png rename to apps/ptlaunch/select_app_light.png diff --git a/apps/rebble/ChangeLog b/apps/rebble/ChangeLog index 3e7094eab..16e65d4f9 100644 --- a/apps/rebble/ChangeLog +++ b/apps/rebble/ChangeLog @@ -1,2 +1,3 @@ 0.01: First release -0.02: Fix dependancies, fix type to Purple +0.02: Fix typo to Purple +0.03: Added dependancy on Pedometer Widget diff --git a/apps/showimg/ChangeLog b/apps/showimg/ChangeLog new file mode 100644 index 000000000..296bc78d0 --- /dev/null +++ b/apps/showimg/ChangeLog @@ -0,0 +1,2 @@ +0.1: Initial release +0.2: Fixed launcher image diff --git a/apps/showimg/app-icon.js b/apps/showimg/app-icon.js index 1c73a2f72..abb1eb434 100644 --- a/apps/showimg/app-icon.js +++ b/apps/showimg/app-icon.js @@ -1 +1 @@ -E.toArrayBuffer(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAf////AHP/////AH//////AP/8AAAHAP4AAAAHAOAAMAAHAOAAeAAHAOAA+cAHAOAA/+AHAOAA/+AHAOAf/+AHAOA//+AHgOA///AHgOA///gDgOA/z/gDgOAfz/gDgOA///gDgOA///gDgOA//uADgOAf3+ADgOAP/+ADgOAD/8ADwOAB+4ADwOAA8AABwOAAAABBwOA8DgPxwOB/Dg/xwOB/jh/xwOB3zj5xwOB57nzxwOA4/njhwOA4/vHhwOA8f+PB4OAef+PB4OAef8eB4OAPP58A4OAHv/4A4OAH//wA4OAD//AA4OAA/8fn4PDgP///4P//////4P////9/wD///4AAA")) +require("heatshrink").decompress(atob("mEwwkBIf4Aah//BRQAMDowUNC5AARC4YKKL5gTC+B3TCpAyIC5oNBEA4XNJwS4GC55pHC8TEHC57QHC4wSEC5YpEC6YwEC5oEEC5x3DC6ZHbC7PwcYxfNAYYXPJA4XQDAwKEBYQXJIoReHC5gMFAAojBC5QUIC5Y5JMgYXIUQYJFPggXMAwICCBAYXMCAQJDDwQUCC5QOCUwQdEC5QqFDghNFC5wrEC5gQDPgoTCDYYXFMAgXaCQoXJEwZ4FLQbhFC4imDAAglFC5QAGBgYXKIoYWIC5YYFG4ZkDC4YjCYYwAJC4gASC6THFH5pqGAAY")) diff --git a/apps/speedalt2/ChangeLog b/apps/speedalt2/ChangeLog index 91f01988e..bd338f8b2 100644 --- a/apps/speedalt2/ChangeLog +++ b/apps/speedalt2/ChangeLog @@ -1,2 +1,3 @@ 0.01: Initial import. 0.07: Add swipe to change screens. +1.06: Misc memory and screen optimisations. diff --git a/apps/speedalt2/app.js b/apps/speedalt2/app.js index 0db9629c7..fd53cf7c3 100644 --- a/apps/speedalt2/app.js +++ b/apps/speedalt2/app.js @@ -1,11 +1,9 @@ /* Speed and Altitude [speedalt2] Mike Bennett mike[at]kereru.com -0.01 : Initial -0.06 : Add Posn screen -0.07 : Add swipe to change screens same as BTN3 +1.10 : add inverted colours */ -var v = '1.05'; +var v = '1.10'; /*kalmanjs, Wouter Bulten, MIT, https://github.com/wouterbulten/kalmanjs */ var KalmanFilter = (function () { @@ -173,6 +171,15 @@ var KalmanFilter = (function () { var buf = Graphics.createArrayBuffer(240,160,2,{msb:true}); +let LED = // LED as minimal and only definition (as instance / singleton) +{ isOn: false // status on / off, not needed if you don't need to ask for it +, set: function(v) { // turn on w/ no arg or truey, else off + g.setColor((this.isOn=(v===undefined||!!v))?1:0,0,0).fillCircle(40,10,10); } +, reset: function() { this.set(false); } // turn off +, write: function(v) { this.set(v); } // turn on w/ no arg or truey, else off +, toggle: function() { this.set( ! this.isOn); } // toggle the LED +}, LED1 = LED; // LED1 as 'synonym' for LED + // Load fonts //require("Font7x11Numeric7Seg").add(Graphics); @@ -183,17 +190,16 @@ var canDraw = 1; var time = ''; // Last time string displayed. Re displayed in background colour to remove before drawing new time. var tmrLP; // Timer for delay in switching to low power after screen turns off -var max = {}; -max.spd = 0; -max.alt = 0; -max.n = 0; // counter. Only start comparing for max after a certain number of fixes to allow kalman filter to have smoohed the data. +var maxSpd = 0; +var maxAlt = 0; +var maxN = 0; // counter. Only start comparing for max after a certain number of fixes to allow kalman filter to have smoohed the data. var emulator = (process.env.BOARD=="EMSCRIPTEN")?1:0; // 1 = running in emulator. Supplies test values; var wp = {}; // Waypoint to use for distance from cur position. -function nxtWp(inc){ - cfg.wp+=inc; +function nxtWp(){ + cfg.wp++; loadWp(); } @@ -227,7 +233,8 @@ function drawScrn(dat) { if (!canDraw) return; buf.clear(); - + buf.setBgColor(0); + var n; n = dat.val.toString(); @@ -252,29 +259,21 @@ function drawScrn(dat) { buf.setFontVector(35); buf.drawString(dat.unit,5,164); - if ( dat.max ) drawMax(); // MAX display indicator - if ( dat.wp ) drawWP(); // Waypoint name - - //Sats - if ( dat.sat ) { - if ( dat.age > 10 ) { - if ( dat.age > 90 ) dat.age = '>90'; - drawSats('Age:'+dat.age); - } - else drawSats('Sats:'+dat.sats); - } - + drawMax(dat.max); // MAX display indicator + drawWP(dat.wp); // Waypoint name + drawSats(dat.sats); + g.reset(); g.drawImage(img,0,40); - if ( pwrSav ) LED1.reset(); - else LED1.set(); + LED1.write(!pwrSav); } function drawPosn(dat) { if (!canDraw) return; buf.clear(); + buf.setBgColor(0); var x, y; x=210; @@ -293,20 +292,12 @@ function drawPosn(dat) { buf.drawString(dat.ew,x,y+70); - //Sats - if ( dat.sat ) { - if ( dat.age > 10 ) { - if ( dat.age > 90 ) dat.age = '>90'; - drawSats('Age:'+dat.age); - } - else drawSats('Sats:'+dat.sats); - } + drawSats(dat.sats); g.reset(); g.drawImage(img,0,40); - if ( pwrSav ) LED1.reset(); - else LED1.set(); + LED1.write(!pwrSav); } @@ -314,6 +305,8 @@ function drawClock() { if (!canDraw) return; buf.clear(); + buf.setBgColor(0); + var x, y; x=185; y=0; @@ -329,19 +322,14 @@ function drawClock() { g.reset(); g.drawImage(img,0,40); - if ( pwrSav ) LED1.reset(); - else LED1.set(); + LED1.write(!pwrSav); } -function drawWP() { - var nm = wp.name; - if ( nm == undefined || nm == 'NONE' || cfg.modeA ==1 ) nm = ''; - buf.setColor(2); - +function drawWP(wp) { + buf.setColor(3); buf.setFontAlign(0,1); //left, bottom buf.setFontVector(48); - buf.drawString(nm.substring(0,8),120,140); - + buf.drawString(wp,120,140); } function drawSats(sats) { @@ -351,16 +339,15 @@ function drawSats(sats) { buf.drawString(sats,240,160); } -function drawMax() { +function drawMax(max) { buf.setFontVector(30); buf.setColor(2); buf.setFontAlign(0,1); //centre, bottom - buf.drawString('MAX',120,164); + buf.drawString(max,120,164); } function onGPS(fix) { - - if ( emulator ) { +if ( emulator ) { fix.fix = 1; fix.speed = 10 + (Math.random()*5); fix.alt = 354 + (Math.random()*50); @@ -382,10 +369,15 @@ function onGPS(fix) { var ns = ''; var ew = ''; var lon = '---.--'; + var sats = '---'; + // Waypoint name + var wpName = wp.name; + if ( wpName == undefined || wpName == 'NONE' ) wpName = ''; + wpName = wpName.substring(0,8); if (fix.fix) lf = fix; - + if (lf.fix) { // Smooth data @@ -393,10 +385,9 @@ function onGPS(fix) { if ( cfg.spdFilt ) lf.speed = spdFilter.filter(lf.speed); if ( cfg.altFilt ) lf.alt = altFilter.filter(lf.alt); lf.smoothed = 1; - if ( max.n <= 15 ) max.n++; + if ( maxN <= 15 ) maxN++; } - // Speed if ( cfg.spd == 0 ) { m = require("locale").speed(lf.speed).match(/([0-9,\.]+)(.*)/); // regex splits numbers from units @@ -407,18 +398,19 @@ function onGPS(fix) { if ( sp < 10 ) sp = sp.toFixed(1); else sp = Math.round(sp); + if (isNaN(sp)) sp = '---'; - if (parseFloat(sp) > parseFloat(max.spd) && max.n > 15 ) max.spd = sp; + if (parseFloat(sp) > parseFloat(maxSpd) && maxN > 15 ) maxSpd = sp; // Altitude al = lf.alt; al = Math.round(parseFloat(al)/parseFloat(cfg.alt)); - - if (parseFloat(al) > parseFloat(max.alt) && max.n > 15 ) max.alt = al; + if (parseFloat(al) > parseFloat(maxAlt) && maxN > 15 ) maxAlt = al; + if (isNaN(al)) al = '---'; // Distance to waypoint di = distance(lf,wp); - if (isNaN(di)) di = 0; + if (isNaN(di)) di = '--------'; // Age of last fix (secs) age = Math.max(0,Math.round(getTime())-(lf.time.getTime()/1000)); @@ -431,6 +423,13 @@ function onGPS(fix) { ew = 'E'; if ( lf.lon < 0 ) ew = 'W'; lon = Math.abs(lf.lon.toFixed(2)); + + // Sats + if ( age > 10 ) { + sats = 'Age:'+Math.round(age); + if ( age > 90 ) sats = 'Age:>90'; + } + else sats = 'Sats:'+lf.satellites; } @@ -438,23 +437,21 @@ function onGPS(fix) { // Speed if ( showMax ) drawScrn({ - val:max.spd, + val:maxSpd, unit:cfg.spd_unit, - sats:lf.satellites, + sats:sats, age:age, - max:true, - wp:false, - sat:true + max:'MAX', + wp:'' }); // Speed maximums else drawScrn({ val:sp, unit:cfg.spd_unit, - sats:lf.satellites, + sats:sats, age:age, - max:false, - wp:false, - sat:true + max:'SPD', + wp:'' }); } @@ -462,23 +459,21 @@ function onGPS(fix) { // Alt if ( showMax ) drawScrn({ - val:max.alt, + val:maxAlt, unit:cfg.alt_unit, - sats:lf.satellites, + sats:sats, age:age, - max:true, - wp:false, - sat:true + max:'MAX', + wp:'' }); // Alt maximums else drawScrn({ val:al, unit:cfg.alt_unit, - sats:lf.satellites, + sats:sats, age:age, - max:false, - wp:false, - sat:true + max:'ALT', + wp:'' }); } @@ -487,24 +482,22 @@ function onGPS(fix) { drawScrn({ val:di, unit:cfg.dist_unit, - sats:lf.satellites, + sats:sats, age:age, - max:false, - wp:true, - sat:true + max:'DST', + wp:wpName }); } if ( cfg.modeA == 3 ) { // Position - drawPosn({ - sats:lf.satellites, + drawPosn({ + sats:sats, age:age, lat:lat, lon:lon, ns:ns, - ew:ew, - sat:true + ew:ew }); } @@ -534,9 +527,9 @@ function nextFunc(dur) { if ( cfg.modeA == 0 || cfg.modeA == 1 ) { // Spd+Alt mode - Switch between fix and MAX if ( dur < 2 ) showMax = !showMax; // Short press toggle fix/max display - else { max.spd = 0; max.alt = 0; } // Long press resets max values. + else { maxSpd = 0; maxAlt = 0; } // Long press resets max values. } - else if ( cfg.modeA == 2) nxtWp(1); // Dist mode - Select next waypoint + else if ( cfg.modeA == 2) nxtWp(); // Dist mode - Select next waypoint onGPS(lf); } @@ -545,7 +538,7 @@ function updateClock() { if (!canDraw) return; if ( cfg.modeA != 4 ) return; drawClock(); - if ( emulator ) {max.spd++;max.alt++;} + if ( emulator ) {maxSpd++;maxAlt++;} } function startDraw(){ @@ -585,7 +578,6 @@ function setButtons(){ setWatch(function(e){ pwrSav=!pwrSav; if ( pwrSav ) { - LED1.reset(); var s = require('Storage').readJSON('setting.json',1)||{}; var t = s.timeout||10; Bangle.setLCDTimeout(t); @@ -593,8 +585,8 @@ function setButtons(){ else { Bangle.setLCDTimeout(0); // Bangle.setLCDPower(1); - LED1.set(); } + LED1.write(!pwrSav); }, BTN2, {repeat:true,edge:"falling"}); // BTN3 - next screen @@ -690,7 +682,8 @@ var img = { }; if ( cfg.colour == 1 ) img.palette = new Uint16Array([0,0xFFFF,0xFFF6,0xDFFF]); -if ( cfg.colour == 2 ) img.palette = new Uint16Array([0,0xFF800,0xFAE0,0xF813]); +if ( cfg.colour == 2 ) img.palette = new Uint16Array([0,0xF800,0xFAE0,0xF813]); +if ( cfg.colour == 3 ) img.palette = new Uint16Array([0xFFFF,0x007F,0x0054,0x0054]); var SCREENACCESS = { withApp:true, diff --git a/apps/speedalt2/settings.js b/apps/speedalt2/settings.js index 96174a89b..fe30d88df 100644 --- a/apps/speedalt2/settings.js +++ b/apps/speedalt2/settings.js @@ -65,7 +65,8 @@ '< Back': function() { E.showMenu(appMenu); }, 'Default' : function() { setColour(0); }, 'Hi Contrast' : function() { setColour(1); }, - 'Night' : function() { setColour(2); } + 'Night' : function() { setColour(2); }, + 'Inverted' : function() { setColour(3); } }; const kalMenu = { diff --git a/apps/stopwatch/README.md b/apps/stopwatch/README.md index 30a9306d1..ceeafaefc 100644 --- a/apps/stopwatch/README.md +++ b/apps/stopwatch/README.md @@ -31,3 +31,6 @@ Which one is which ? ![](A.jpg) ![](B.jpg) + + +Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) diff --git a/apps/widpedom/ChangeLog b/apps/widpedom/ChangeLog index 2f36c7647..c033ea505 100644 --- a/apps/widpedom/ChangeLog +++ b/apps/widpedom/ChangeLog @@ -19,3 +19,4 @@ Stop goal drawing outside widget area Fix issue with widget overwrite in large font mode Memory usage enhancements +0.20: Fix issue where step count would randomly reset diff --git a/apps/widpedom/widget.js b/apps/widpedom/widget.js index 3c861cf54..0ec0780c9 100644 --- a/apps/widpedom/widget.js +++ b/apps/widpedom/widget.js @@ -53,7 +53,7 @@ E.on('kill', () => { if (!settings) { loadSettings() } let d = { - lastUpdate : lastUpdate.toISOString(), + lastUpdate : lastUpdate.valueOf(), stepsToday : stp_today, settings : settings, }; diff --git a/core b/core index 2a8e872ec..b033af017 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 2a8e872ecb143a10e53273b4d3473164e104e1d3 +Subproject commit b033af017f6789a6a7777e6ef1428d94995a9b8b