diff --git a/apps.json b/apps.json index 166f1e4f9..98e6a4df2 100644 --- a/apps.json +++ b/apps.json @@ -115,7 +115,7 @@ { "id": "setting", "name": "Settings", - "version": "0.31", + "version": "0.33", "description": "A menu for setting up Bangle.js", "icon": "settings.png", "tags": "tool,system", @@ -540,6 +540,21 @@ ], "data": [{"name":"trex.score","storageFile":true}] }, + { + "id": "cubescramble", + "name": "Cube Scramble", + "version":"0.01", + "description": "A random scramble generator for the 3x3 Rubik's cube", + "icon": "cube-scramble.png", + "tags": "", + "supports" : ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"cubescramble.app.js","url":"cube-scramble.js"}, + {"name":"cubescramble.img","url":"cube-scramble-icon.js","evaluate":true} + ] + }, { "id": "astroid", "name": "Asteroids!", @@ -4216,7 +4231,40 @@ ], "data": [{ "name": "qalarm.json" }] }, - { "id": "lcars", + { + "id": "emojuino", + "name": "Emojuino", + "shortName": "Emojuino", + "version": "0.01", + "description": "Emojis & Espruino: broadcast Unicode emojis via Bluetooth Low Energy.", + "icon": "emojuino.png", + "tags": "emoji", + "supports" : [ "BANGLEJS2" ], + "readme": "README.md", + "storage": [ + { "name": "emojuino.app.js", "url": "emojuino.js" }, + { "name": "emojuino.img", "url": "emojuino-icon.js", "evaluate": true } + ] + }, + { + "id": "cliclockJS2Enhanced", + "name": "Commandline-Clock JS2 Enhanced", + "shortName": "CLI-Clock JS2", + "version": "0.1", + "description": "Simple CLI-Styled Clock with enhancements. Modes that are hard to use and unneded are removed (BPM, battery info, memory ect) credit to hughbarney for the original code and design", + "icon": "app.png", + "screenshots": [{"url":"screengrab.png"}], + "type": "clock", + "tags": "clock,cli,command,bash,shell", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"cliclockJS2Enhanced.app.js","url":"app.js"}, + {"name":"cliclockJS2Enhanced.img","url":"app.icon.js","evaluate":true} + ] + }, + { + "id": "lcars", "name": "LCARS Clock", "shortName":"LCARS", "icon": "lcars.png", diff --git a/apps/boot/bootupdate.js b/apps/boot/bootupdate.js index 5cb6421a5..d642426c2 100644 --- a/apps/boot/bootupdate.js +++ b/apps/boot/bootupdate.js @@ -103,7 +103,7 @@ if (Bangle.swipeHandler) { Bangle.removeListener("swipe", Bangle.swipeHandler); delete Bangle.swipeHandler; } -if (Bangle.touchandler) { +if (Bangle.touchHandler) { Bangle.removeListener("touch", Bangle.touchHandler); delete Bangle.touchHandler; } diff --git a/apps/cliclockJS2Enhanced/app.icon.js b/apps/cliclockJS2Enhanced/app.icon.js new file mode 100644 index 000000000..b2974fe7a --- /dev/null +++ b/apps/cliclockJS2Enhanced/app.icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwkBiIA/AH4A/AH4A8gAAKC8gKUC7Rf/C/PM5gDBjnBC6EcC4PBDIIbCC5/BAIIXVA4YXXAoRHUC6R3EC6KnEMAbv/C6oAKC8YA/AH4A/AH4Ax")) \ No newline at end of file diff --git a/apps/cliclockJS2Enhanced/app.js b/apps/cliclockJS2Enhanced/app.js new file mode 100644 index 000000000..314e32375 --- /dev/null +++ b/apps/cliclockJS2Enhanced/app.js @@ -0,0 +1,216 @@ +var fontsize = g.getWidth()>200 ? 3 : 2; +var fontsizeTime = g.getWidth()>200 ? 4 : 4; + +var fontheight = 10*fontsize; +var fontheightTime = 10*fontsizeTime; +var locale = require("locale"); +var marginTop = 40; +var flag = false; + +var hrtOn = false; +var hrtStr = "Hrt: ??? bpm"; + +const NONE_MODE = "none"; +const ID_MODE = "id"; +const VER_MODE = "ver"; +const BATT_MODE = "batt"; +const MEM_MODE = "mem"; +const STEPS_MODE = "step"; +const HRT_MODE = "hrt"; +const NONE_FN_MODE = "no_fn"; +const HRT_FN_MODE = "fn_hrt"; + +let infoMode = NONE_MODE; +let functionMode = NONE_FN_MODE; + +let textCol = g.theme.dark ? "#0f0" : "#080"; + +function drawAll(){ + updateTime(); + updateRest(new Date()); +} + +function updateRest(now){ + writeLine(locale.dow(now),1); + writeLine(locale.date(now,1),2); + drawInfo(5); +} +function updateTime(){ + if (!Bangle.isLCDOn()) return; + let now = new Date(); + writeLine(locale.time(now,1),0); + writeLine(flag?" ":"_",3); + flag = !flag; + if(now.getMinutes() == 0) + updateRest(now); +} +function writeLineStart(line){ + if (line==0){ + g.drawString(">",0,marginTop+(line)*fontheight); + } else { + g.drawString(">",4,marginTop+(line-1)*fontheight + fontheightTime); + + } +} + +function writeLine(str,line){ + if (line == 0){ + var y = marginTop+line*fontheightTime; + g.setFont("6x8",fontsizeTime); + g.setColor(textCol).setFontAlign(-1,-1); + g.clearRect(0,y,((str.length+1)*40),y+fontheightTime-1); + writeLineStart(line); + g.drawString(str,25,y); + } else { + var y = marginTop+(line-1)*fontheight+fontheightTime; + g.setFont("6x8",fontsize); + g.setColor(textCol).setFontAlign(-1,-1); + g.clearRect(0,y,((str.length+1)*20),y+fontheight-1); + writeLineStart(line); + g.drawString(str,25,y); + } + +} + +function drawInfo(line) { + let val; + let str = ""; + let col = textCol; // green + + //console.log("drawInfo(), infoMode=" + infoMode + " funcMode=" + functionMode); + + switch(functionMode) { + case NONE_FN_MODE: + break; + case HRT_FN_MODE: + col = g.theme.dark ? "#0ff": "#088"; // cyan + str = "HRM: " + (hrtOn ? "ON" : "OFF"); + drawModeLine(line,str,col); + return; + } + + switch(infoMode) { + case NONE_MODE: + col = g.theme.bg; + str = ""; + break; + case HRT_MODE: + str = hrtStr; + break; + case STEPS_MODE: + str = "Steps: " + stepsWidget().getSteps(); + break; + case ID_MODE: + val = NRF.getAddress().split(":"); + str = "Id: " + val[4] + val[5]; + break; + case VER_MODE: + str = "Fw: " + process.env.VERSION; + break; + case MEM_MODE: + val = process.memory(); + str = "Memory: " + Math.round(val.usage*100/val.total) + "%"; + break; + case BATT_MODE: + default: + str = "Battery: " + E.getBattery() + "%"; + } + + drawModeLine(line,str,col); +} + +function drawModeLine(line, str, col) { + g.setColor(col); + var y = marginTop+line*fontheight; + g.fillRect(0, y, 239, y+fontheight-1); + g.setColor(g.theme.bg).setFontAlign(0, 0); + g.drawString(str, g.getWidth()/2, y+fontheight/2); +} + +function changeInfoMode() { + switch(functionMode) { + case NONE_FN_MODE: + break; + case HRT_FN_MODE: + hrtOn = !hrtOn; + Bangle.buzz(); + Bangle.setHRMPower(hrtOn ? 1 : 0); + if (hrtOn) infoMode = HRT_MODE; + return; + } + + switch(infoMode) { + case NONE_MODE: + if (stepsWidget() !== undefined) + infoMode = hrtOn ? HRT_MODE : STEPS_MODE; + else + infoMode = VER_MODE; + break; + case HRT_MODE: + if (stepsWidget() !== undefined) + infoMode = STEPS_MODE; + else + infoMode = VER_MODE; + break; + case STEPS_MODE: + infoMode = ID_MODE; + break; + case ID_MODE: + infoMode = VER_MODE; + break; + case VER_MODE: + infoMode = BATT_MODE; + break; + case BATT_MODE: + infoMode = MEM_MODE; + break; + case MEM_MODE: + default: + infoMode = NONE_MODE; + } +} + +function changeFunctionMode() { + //console.log("changeFunctionMode()"); + switch(functionMode) { + case NONE_FN_MODE: + functionMode = HRT_FN_MODE; + break; + case HRT_FN_MODE: + default: + functionMode = NONE_FN_MODE; + } + //console.log(functionMode); + +} + +function stepsWidget() { + if (WIDGETS.activepedom !== undefined) { + return WIDGETS.activepedom; + } else if (WIDGETS.wpedom !== undefined) { + return WIDGETS.wpedom; + } + return undefined; +} + +Bangle.on('HRM', function(hrm) { + if(hrm.confidence > 90){ + hrtStr = "Hrt: " + hrm.bpm + " bpm"; + } else { + hrtStr = "Hrt: ??? bpm"; + } +}); + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +drawAll(); +Bangle.on('lcdPower',function(on) { + if (on) drawAll(); +}); +var click = setInterval(updateTime, 1000); +// Show launcher when button pressed +Bangle.setUI("clockupdown", btn=>{ + if (btn<0) changeInfoMode(); + drawAll(); +}); diff --git a/apps/cliclockJS2Enhanced/app.js.png b/apps/cliclockJS2Enhanced/app.js.png new file mode 100644 index 000000000..6d74fcf71 Binary files /dev/null and b/apps/cliclockJS2Enhanced/app.js.png differ diff --git a/apps/cliclockJS2Enhanced/app.png b/apps/cliclockJS2Enhanced/app.png new file mode 100644 index 000000000..e70692034 Binary files /dev/null and b/apps/cliclockJS2Enhanced/app.png differ diff --git a/apps/cliclockJS2Enhanced/screengrab.png b/apps/cliclockJS2Enhanced/screengrab.png new file mode 100644 index 000000000..fd4556fb3 Binary files /dev/null and b/apps/cliclockJS2Enhanced/screengrab.png differ diff --git a/apps/cubescramble/ChangeLog b/apps/cubescramble/ChangeLog new file mode 100644 index 000000000..28f11c1c7 --- /dev/null +++ b/apps/cubescramble/ChangeLog @@ -0,0 +1 @@ +0.01: Initial Release diff --git a/apps/cubescramble/README.md b/apps/cubescramble/README.md new file mode 100644 index 000000000..779e32489 --- /dev/null +++ b/apps/cubescramble/README.md @@ -0,0 +1,18 @@ +# Cube Scramble + +A random scramble generator for the 3x3 Rubik's cube + +## Future features + +I'm keen to complete this project with + +* Add a timer +* Add the ability for times to be stored and exported + +## Requests + +Please reach out if you have feature requests or notice bugs. + +## Creator + +Made by [Nathan Lisgo](https://github.com/nlisgo) diff --git a/apps/cubescramble/cube-scramble-icon.js b/apps/cubescramble/cube-scramble-icon.js new file mode 100644 index 000000000..32ea10836 --- /dev/null +++ b/apps/cubescramble/cube-scramble-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("3YANB54AFgf/+ULCqOw/4ACC6EAxEAC4fwCp2YxGIwEPC4XxGBewqEICwIABGAUQRJWwp3u9xFBAAQUCr3u8gwHgAVBC4ugCwIKDC5nghGAgEODoIKEC44PBBgUAggFDBQZIHhAMB8j4CMgQHBgoDBoB5H3BuC5nM4AqDJAIABgnd7owF3GAhgWBAAJbD8oWBCoIABoAXLqBIBCoNmC4nQC4xGCJAQVBs93u9ghoYDJAmwwFwFwYWBCoIABuBeC7oLBGAmBu0MFgMFDIMHDAZIB6AhBiCoFBgIVBJAQXFAAMv//wI4kBKoJgDSIIVBuwVBgP/AAIXEJoNnuCRFg9gCoPwh4XHTwMHvxHDPQc///xC5PgC4PgCoPFLIQSC+QXEVAb9CunggpYCwMDC4/9C4bnBqFldQWIAAIXH+FNC4deJAMAC4IWCxECC4nybQQXDh3u8vQC4qiEHILxCC4ewF4PdJQIXDO4UwgEYC42wgEOC4NeoAXE+IsBhAFBC4u16EAC4PV8AWCwCpCCwIXDoBGD7rPB7vUC4UQCwRmDBoPQuwXE6ghCgAVEgsBC4fQu4XFD4MN7tE8oWD7oXEu4XE3YXCqHdovuoCgDI4WBC4VwC4YsB6HMgjBBYQKHCC4OKhnAC4K+DJAQXB4DxB9wfBC4cFBYN3tYWDAAO9C4PMC48ABQPAIogADqAMCpwXFhgKCIohJErgNBgoXDqHxC4QWIAAINCg1errmBh4XC4AWJAAIwBg9gonQgf/+QXBFxRJCC4N2OYP/C4VQCxZJCg61Bh4XB+cACxoABC4VvC4PxCx5JBC4k7C6AwCuf/+AWRAANnuX/RZhJIuBFSAAaLMA=")) diff --git a/apps/cubescramble/cube-scramble.js b/apps/cubescramble/cube-scramble.js new file mode 100644 index 000000000..c0b1d11c3 --- /dev/null +++ b/apps/cubescramble/cube-scramble.js @@ -0,0 +1,74 @@ + +// Scramble code from: https://raw.githubusercontent.com/bjcarlson42/blog-post-sample-code/master/Rubik's%20Cube%20JavaScript%20Scrambler/part_two.js +const makeScramble = () => { + const options = ["F", "F2", "F'", "R", "R2", "R'", "U", "U2", "U'", "B", "B2", "B'", "L", "L2", "L'", "D", "D2", "D'"]; + const numOptions = [0, 1, 2, 3, 4, 5]; // 0 = F, 1 = R, 2 = U, 3 = B, 4 = L, 5 = D + const scrambleMoves = []; + let bad = true; + + while (bad) { + let scramble = []; + for (let i = 0; i < 20; i++) { + scramble.push(numOptions[getRandomInt(6)]); + } + // check if moves directly next to each other involve the same letter + for (let i = 0; i < 20 - 1; i++) { + if (scramble[i] == scramble[i + 1]) { + bad = true; + break; + } else { + bad = false; + } + } + } + // switch numbers to letters + let move; + for (let i = 0; i < 20; i++) { + switch (scramble[i]) { + case 0: + move = options[getRandomInt(3)]; // 0,1,2 + scrambleMoves.push(move); + break; + case 1: + move = options[getRandomIntBetween(3, 6)]; // 3,4,5 + scrambleMoves.push(move); + break; + case 2: + move = options[getRandomIntBetween(6, 9)]; // 6,7,8 + scrambleMoves.push(move); + break; + case 3: + move = options[getRandomIntBetween(9, 12)]; // 9,10,11 + scrambleMoves.push(move); + break; + case 4: + move = options[getRandomIntBetween(12, 15)]; // 12,13,14 + scrambleMoves.push(move); + break; + case 5: + move = options[getRandomIntBetween(15, 18)]; // 15,16,17 + scrambleMoves.push(move); + break; + } + } + return scrambleMoves; +}; + +const getRandomInt = max => Math.floor(Math.random() * Math.floor(max)); // returns up to max - 1 + +const getRandomIntBetween = (min, max) => Math.floor(Math.random() * (max - min) + min); + +const presentScramble = () => { + g.clear(); + E.showMessage(makeScramble().join(" ")); +}; + +const init = () => { + presentScramble(); + + setWatch(() => { + presentScramble(); + }, BTN1, {repeat:true}); +}; + +init(); diff --git a/apps/cubescramble/cube-scramble.png b/apps/cubescramble/cube-scramble.png new file mode 100644 index 000000000..9d0a7c652 Binary files /dev/null and b/apps/cubescramble/cube-scramble.png differ diff --git a/apps/emojuino/ChangeLog b/apps/emojuino/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/emojuino/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/emojuino/README.md b/apps/emojuino/README.md new file mode 100644 index 000000000..568d06dfb --- /dev/null +++ b/apps/emojuino/README.md @@ -0,0 +1,28 @@ +# Emojuino + +Emojis & Espruino! + + +## Usage + +Select an emoji and then tap to transmit! The emoji will be recognised by [Pareto Anywhere](https://www.reelyactive.com/pareto/anywhere/) open source middleware and any other program which observes the [InteroperaBLE Identifier](https://reelyactive.github.io/interoperable-identifier/) open standard. + + +## Features + +Currently implements a tiny subset of possible [Unicode emojis](https://unicode.org/emoji/charts/full-emoji-list.html) which are advertised as an [InteroperaBLE Identifier](https://reelyactive.github.io/interoperable-identifier/) encapsulated as Eddystone UID. + + +## Controls + +Swipe left/right to select the emoji to broadcast. Tap the screen to initiate the broadcast. Emoji will flash while broadcasting, which lasts for 5 seconds. + + +## Requests + +[Contact reelyActive](https://www.reelyactive.com/contact/) for support/updates. + + +## Creator + +Developed by [jeffyactive](https://github.com/jeffyactive) of [reelyActive](https://www.reelyactive.com) diff --git a/apps/emojuino/emojuino-icon.js b/apps/emojuino/emojuino-icon.js new file mode 100644 index 000000000..d56749250 --- /dev/null +++ b/apps/emojuino/emojuino-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwkBiIAHkUoxGIwUiBxAAGiQVCAAeCkIWNCooADDBYWKDBYWEkc////+cyDBhxDCoQAD+YLDCw0YBQQVFAAYYCwIXFHQRDElGCJYgOCFw8vBwPyOgoJFGAg4BIoQWGDAhJCIwoLBHgYAGJQIjCIwguCnCRFRoeDGAZICAgOPFwaRGDAQfB/AwDBAYuCX44wDAgTrDBoIDBGYP/manBmYFBFYQPDwJeBD4iRGRoQ/FC4QqBEYIbERooTBCAeBNAIjBBQIDDAAggBG4IDDwQXBEQIDDUAgcCHASaBAYQTFMQpcFDYp+EEII9DAARRDFIIfDHIwXBVISlDC4YzD9wA0osFpwIF8lQqgWK8kAgEEBItABIIhGAAfgBoMABIoIChwX0jwED8oNBgoXFqAJBrwHD8IXEBwQNEEIYgFC4wAQ8MRC6sRC+BgULwIwHSINVpwuLC43kaAQABqgaHC4bZHAAkFqhGHGAovFAAYyDCwgwFL4IwGFxAwNFxIwG8lVCoSTEFw7bPCxAYNCxT0LIpIxMCpoyHFhI")) \ No newline at end of file diff --git a/apps/emojuino/emojuino.js b/apps/emojuino/emojuino.js new file mode 100644 index 000000000..3de92fa6c --- /dev/null +++ b/apps/emojuino/emojuino.js @@ -0,0 +1,145 @@ +/** + * Copyright reelyActive 2021 + * We believe in an open Internet of Things + */ + + +// Emojis are integer pairs with the form [ image, Unicode code point ] +// For code points see https://unicode.org/emoji/charts/emoji-list.html +const EMOJIS = [ + [ ':)', 0x1f642 ], // Slightly smiling + [ ':|', 0x1f610 ], // Neutral + [ ':(', 0x1f641 ], // Slightly frowning + [ '+1', 0x1f44d ], // Thumbs up + [ '-1', 0x1f44e ], // Thumbs down + [ '<3', 0x02764 ], // Heart +]; +const EMOJI_TRANSMISSION_MILLISECONDS = 5000; +const BLINK_PERIOD_MILLISECONDS = 500; +const TRANSMIT_BUZZ_MILLISECONDS = 200; +const CYCLE_BUZZ_MILLISECONDS = 50; + +// Non-user-configurable constants +const IMAGE_INDEX = 0; +const CODE_POINT_INDEX = 1; +const BTN_WATCH_OPTIONS = { repeat: true, debounce: 20, edge: "falling" }; +const UNICODE_CODE_POINT_ELIDED_UUID = [ 0x49, 0x6f, 0x49, 0x44, 0x55, + 0x54, 0x46, 0x2d, 0x33, 0x32 ]; + + +// Global variables +let emojiIndex = 0; +let isToggleOn = false; +let isTransmitting = false; +let lastDragX = 0; +let lastDragY = 0; + + +// Cycle through emojis +function cycleEmoji(isForward) { + if(isTransmitting) { return; } + + if(isForward) { + emojiIndex = (emojiIndex + 1) % EMOJIS.length; + } + else if(--emojiIndex < 0) { + emojiIndex = EMOJIS.length - 1; + } + + drawImage(EMOJIS[emojiIndex][IMAGE_INDEX]); + Bangle.buzz(CYCLE_BUZZ_MILLISECONDS); +} + + +// Handle a touch: transmit displayed emoji +function handleTouch(zone, event) { + if(isTransmitting) { return; } + + let emoji = EMOJIS[emojiIndex]; + transmitEmoji(emoji[IMAGE_INDEX], emoji[CODE_POINT_INDEX], + EMOJI_TRANSMISSION_MILLISECONDS); + Bangle.buzz(TRANSMIT_BUZZ_MILLISECONDS); +} + + +// Transmit the given code point for the given duration in milliseconds, +// blinking the image once per second. +function transmitEmoji(image, codePoint, duration) { + let instance = [ 0x00, 0x00, (codePoint >> 24) & 0xff, + (codePoint >> 16) & 0xff, (codePoint >> 8) & 0xff, + codePoint & 0xff ]; + + require('ble_eddystone_uid').advertise(UNICODE_CODE_POINT_ELIDED_UUID, + instance); + isTransmitting = true; + + let displayIntervalId = setInterval(toggleImage, BLINK_PERIOD_MILLISECONDS, + image); + + setTimeout(terminateEmoji, duration, displayIntervalId); +} + + +// Terminate the emoji transmission +function terminateEmoji(displayIntervalId) { + NRF.setAdvertising({ }); + isTransmitting = false; + clearInterval(displayIntervalId); + drawImage(EMOJIS[emojiIndex][IMAGE_INDEX]); +} + + +// Toggle the display between image/off +function toggleImage(image) { + if(isToggleOn) { + drawImage(EMOJIS[emojiIndex][IMAGE_INDEX]); + } + else { + g.clear(); + } + isToggleOn = !isToggleOn; +} + + +// Draw the given emoji +function drawImage(image) { + g.clear(); + g.drawString(image, g.getWidth() / 2, g.getHeight() / 2); + g.flip(); +} + + +// Handle a drag event +function handleDrag(event) { + let isFingerReleased = (event.b === 0); + + if(isFingerReleased) { + let isHorizontalDrag = (Math.abs(lastDragX) >= Math.abs(lastDragY)) && + (lastDragX !== 0); + + if(isHorizontalDrag) { + cycleEmoji(lastDragX > 0); + } + } + else { + lastDragX = event.dx; + lastDragY = event.dy; + } +} + + +// Special function to handle display switch on +Bangle.on('lcdPower', (on) => { + if(on) { + drawImage(EMOJIS[emojiIndex][IMAGE_INDEX]); + } +}); + + +// On start: display the first emoji and handle drag and touch events +g.clear(); +g.setFont('Vector', 80); +g.setFontAlign(0, 0); +drawImage(EMOJIS[emojiIndex][IMAGE_INDEX]); +Bangle.on('touch', handleTouch); +Bangle.on('drag', handleDrag); diff --git a/apps/emojuino/emojuino.png b/apps/emojuino/emojuino.png new file mode 100644 index 000000000..614cc025e Binary files /dev/null and b/apps/emojuino/emojuino.png differ diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index 0890cf510..faa50405f 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -34,3 +34,5 @@ 0.29: Add Customize to Theme menu 0.30: Move '< Back' to the top of menus 0.31: Remove Bangle 1 settings when running on Bangle 2 +0.32: Fix 'beep' menu on Bangle.js 2 +0.33: Really fix 'beep' menu on Bangle.js 2 this time diff --git a/apps/setting/settings.js b/apps/setting/settings.js index 0decb5313..fcf651b6f 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -38,7 +38,7 @@ function resetSettings() { quiet: 0, // quiet mode: 0: off, 1: priority only, 2: total silence timeout: 10, // Default LCD timeout in seconds vibrate: true, // Vibration enabled by default. App must support - beep: "vib", // Beep enabled by default. App must support + beep: BANGLEJS2?true:"vib", // Beep enabled by default. App must support timezone: 0, // Set the timezone for the device HID: false, // BLE HID mode, off by default clock: null, // a string for the default clock's name @@ -72,8 +72,37 @@ if (!('qmOptions' in settings)) settings.qmOptions = {}; // easier if this alway const boolFormat = v => v ? "On" : "Off"; function showMainMenu() { - var beepV = BANGLEJS2 ? [false,true] : [false, true, "vib"]; - var beepN = BANGLEJS2 ? ["Off","On"] : ["Off", "Piezo", "Vibrate"]; + var beepMenuItem; + if (BANGLEJS2) { + beepMenuItem = { + value: settings.beep!=false, + format: boolFormat, + onchange: v => { + settings.beep = v; + updateSettings(); + if (settings.beep) { + analogWrite(VIBRATE,0.1,{freq:2000}); + setTimeout(()=>VIBRATE.reset(),200); + } // beep with vibration moter + } + }; + } else { // Bangle.js 1 + var beepV = [false, true, "vib"]; + var beepN = ["Off", "Piezo", "Vibrate"]; + beepMenuItem = { + value: Math.max(0 | beepV.indexOf(settings.beep),0), + min: 0, max: beepV.length-1, + format: v => beepN[v], + onchange: v => { + settings.beep = beepV[v]; + if (v==1) { analogWrite(D18,0.5,{freq:2000});setTimeout(()=>D18.reset(),200); } // piezo on Bangle.js 1 + else if (v==2) { analogWrite(VIBRATE,0.1,{freq:2000});setTimeout(()=>VIBRATE.reset(),200); } // vibrate + updateSettings(); + } + }; + } + + const mainmenu = { '': { 'title': 'Settings' }, '< Back': ()=>load(), @@ -88,17 +117,7 @@ function showMainMenu() { updateSettings(); } }, - 'Beep': { - value: 0 | beepV.indexOf(settings.beep), - min: 0, max: 2, - format: v => beepN[v], - onchange: v => { - settings.beep = beepV[v]; - if (v==1) { analogWrite(D18,0.5,{freq:2000});setTimeout(()=>D18.reset(),200); } // piezo - else if (v==2) { analogWrite(D13,0.1,{freq:2000});setTimeout(()=>D13.reset(),200); } // vibrate - updateSettings(); - } - }, + 'Beep': beepMenuItem, 'Vibration': { value: settings.vibrate, format: boolFormat, @@ -146,7 +165,7 @@ function showBLEMenu() { } }, 'HID': { - value: 0 | hidV.indexOf(settings.HID), + value: Math.max(0,0 | hidV.indexOf(settings.HID)), min: 0, max: 3, format: v => hidN[v], onchange: v => {