From dc2013751ac8037a29bacceb7562ff3a33d51330 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Sat, 16 Nov 2019 22:36:43 +0000 Subject: [PATCH] Highlight default clock if none currently selected --- apps/settings.js | 4 ++-- firmware.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/settings.js b/apps/settings.js index b000518ed..6e186d9d8 100644 --- a/apps/settings.js +++ b/apps/settings.js @@ -187,9 +187,9 @@ function showClockMenu() { }, '< Back': showMainMenu, }; - clockApps.forEach(app => { + clockApps.forEach((app,index) => { var label = app.name; - if (settings.clock === app.src) { + if ((!settings.clock && index === 0) || (settings.clock === app.src)) { label = "* "+label; } clockMenu[label] = () => { 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